Commit 41c2e75e authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Dave Airlie

drm: Make drm_local_map use a resource_size_t offset

This changes drm_local_map to use a resource_size for its "offset"
member instead of an unsigned long, thus allowing 32-bit machines
with a >32-bit physical address space to be able to store there
their register or framebuffer addresses when those are above 4G,
such as when using a PCI video card on a recent AMCC 440 SoC.

This patch isn't as "trivial" as it sounds: A few functions needed
to have some unsigned long/int changed to resource_size_t and a few
printk's had to be adjusted.

But also, because userspace isn't capable of passing such offsets,
I had to modify drm_find_matching_map() to ignore the offset passed
in for maps of type _DRM_FRAMEBUFFER or _DRM_REGISTERS.

If we ever support multiple _DRM_FRAMEBUFFER or _DRM_REGISTERS maps
for a given device, we might have to change that trick, but I don't
think that happens on any current driver.
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
parent f77d390c
...@@ -54,11 +54,29 @@ static struct drm_map_list *drm_find_matching_map(struct drm_device *dev, ...@@ -54,11 +54,29 @@ static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,
{ {
struct drm_map_list *entry; struct drm_map_list *entry;
list_for_each_entry(entry, &dev->maplist, head) { list_for_each_entry(entry, &dev->maplist, head) {
if (entry->map && (entry->master == dev->primary->master) && (map->type == entry->map->type) && /*
((entry->map->offset == map->offset) || * Because the kernel-userspace ABI is fixed at a 32-bit offset
((map->type == _DRM_SHM) && (map->flags&_DRM_CONTAINS_LOCK)))) { * while PCI resources may live above that, we ignore the map
* offset for maps of type _DRM_FRAMEBUFFER or _DRM_REGISTERS.
* It is assumed that each driver will have only one resource of
* each type.
*/
if (!entry->map ||
map->type != entry->map->type ||
entry->master != dev->primary->master)
continue;
switch (map->type) {
case _DRM_SHM:
if (map->flags != _DRM_CONTAINS_LOCK)
break;
case _DRM_REGISTERS:
case _DRM_FRAME_BUFFER:
return entry; return entry;
default: /* Make gcc happy */
;
} }
if (entry->map->offset == map->offset)
return entry;
} }
return NULL; return NULL;
...@@ -96,7 +114,7 @@ static int drm_map_handle(struct drm_device *dev, struct drm_hash_item *hash, ...@@ -96,7 +114,7 @@ static int drm_map_handle(struct drm_device *dev, struct drm_hash_item *hash,
* type. Adds the map to the map list drm_device::maplist. Adds MTRR's where * type. Adds the map to the map list drm_device::maplist. Adds MTRR's where
* applicable and if supported by the kernel. * applicable and if supported by the kernel.
*/ */
static int drm_addmap_core(struct drm_device * dev, unsigned int offset, static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
unsigned int size, enum drm_map_type type, unsigned int size, enum drm_map_type type,
enum drm_map_flags flags, enum drm_map_flags flags,
struct drm_map_list ** maplist) struct drm_map_list ** maplist)
...@@ -124,9 +142,9 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset, ...@@ -124,9 +142,9 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset,
drm_free(map, sizeof(*map), DRM_MEM_MAPS); drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -EINVAL; return -EINVAL;
} }
DRM_DEBUG("offset = 0x%08lx, size = 0x%08lx, type = %d\n", DRM_DEBUG("offset = 0x%08llx, size = 0x%08lx, type = %d\n",
map->offset, map->size, map->type); (unsigned long long)map->offset, map->size, map->type);
if ((map->offset & (~PAGE_MASK)) || (map->size & (~PAGE_MASK))) { if ((map->offset & (~(resource_size_t)PAGE_MASK)) || (map->size & (~PAGE_MASK))) {
drm_free(map, sizeof(*map), DRM_MEM_MAPS); drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -EINVAL; return -EINVAL;
} }
...@@ -254,7 +272,8 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset, ...@@ -254,7 +272,8 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset,
drm_free(map, sizeof(*map), DRM_MEM_MAPS); drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -EPERM; return -EPERM;
} }
DRM_DEBUG("AGP offset = 0x%08lx, size = 0x%08lx\n", map->offset, map->size); DRM_DEBUG("AGP offset = 0x%08llx, size = 0x%08lx\n",
(unsigned long long)map->offset, map->size);
break; break;
case _DRM_GEM: case _DRM_GEM:
...@@ -322,7 +341,7 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset, ...@@ -322,7 +341,7 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset,
return 0; return 0;
} }
int drm_addmap(struct drm_device * dev, unsigned int offset, int drm_addmap(struct drm_device * dev, resource_size_t offset,
unsigned int size, enum drm_map_type type, unsigned int size, enum drm_map_type type,
enum drm_map_flags flags, struct drm_local_map ** map_ptr) enum drm_map_flags flags, struct drm_local_map ** map_ptr)
{ {
......
...@@ -276,9 +276,9 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request, ...@@ -276,9 +276,9 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
type = "??"; type = "??";
else else
type = types[map->type]; type = types[map->type];
DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ", DRM_PROC_PRINT("%4d 0x%08llx 0x%08lx %4.4s 0x%02x 0x%08lx ",
i, i,
map->offset, (unsigned long long)map->offset,
map->size, type, map->flags, map->size, type, map->flags,
(unsigned long) r_list->user_token); (unsigned long) r_list->user_token);
if (map->mtrr < 0) { if (map->mtrr < 0) {
......
...@@ -115,9 +115,9 @@ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -115,9 +115,9 @@ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
* Using vm_pgoff as a selector forces us to use this unusual * Using vm_pgoff as a selector forces us to use this unusual
* addressing scheme. * addressing scheme.
*/ */
unsigned long offset = (unsigned long)vmf->virtual_address - resource_size_t offset = (unsigned long)vmf->virtual_address -
vma->vm_start; vma->vm_start;
unsigned long baddr = map->offset + offset; resource_size_t baddr = map->offset + offset;
struct drm_agp_mem *agpmem; struct drm_agp_mem *agpmem;
struct page *page; struct page *page;
...@@ -149,8 +149,10 @@ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -149,8 +149,10 @@ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
vmf->page = page; vmf->page = page;
DRM_DEBUG DRM_DEBUG
("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n", ("baddr = 0x%llx page = 0x%p, offset = 0x%llx, count=%d\n",
baddr, __va(agpmem->memory->memory[offset]), offset, (unsigned long long)baddr,
__va(agpmem->memory->memory[offset]),
(unsigned long long)offset,
page_count(page)); page_count(page));
return 0; return 0;
} }
...@@ -512,14 +514,14 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) ...@@ -512,14 +514,14 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
return 0; return 0;
} }
unsigned long drm_core_get_map_ofs(struct drm_local_map * map) resource_size_t drm_core_get_map_ofs(struct drm_local_map * map)
{ {
return map->offset; return map->offset;
} }
EXPORT_SYMBOL(drm_core_get_map_ofs); EXPORT_SYMBOL(drm_core_get_map_ofs);
unsigned long drm_core_get_reg_ofs(struct drm_device *dev) resource_size_t drm_core_get_reg_ofs(struct drm_device *dev)
{ {
#ifdef __alpha__ #ifdef __alpha__
return dev->hose->dense_mem_base - dev->hose->mem_space->start; return dev->hose->dense_mem_base - dev->hose->mem_space->start;
...@@ -548,7 +550,7 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) ...@@ -548,7 +550,7 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
struct drm_file *priv = filp->private_data; struct drm_file *priv = filp->private_data;
struct drm_device *dev = priv->minor->dev; struct drm_device *dev = priv->minor->dev;
struct drm_local_map *map = NULL; struct drm_local_map *map = NULL;
unsigned long offset = 0; resource_size_t offset = 0;
struct drm_hash_item *hash; struct drm_hash_item *hash;
DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n", DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
...@@ -623,9 +625,9 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) ...@@ -623,9 +625,9 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
vma->vm_page_prot)) vma->vm_page_prot))
return -EAGAIN; return -EAGAIN;
DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx," DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx,"
" offset = 0x%lx\n", " offset = 0x%llx\n",
map->type, map->type,
vma->vm_start, vma->vm_end, map->offset + offset); vma->vm_start, vma->vm_end, (unsigned long long)(map->offset + offset));
vma->vm_ops = &drm_vm_ops; vma->vm_ops = &drm_vm_ops;
break; break;
case _DRM_CONSISTENT: case _DRM_CONSISTENT:
......
...@@ -148,8 +148,8 @@ void mga_do_dma_flush(drm_mga_private_t * dev_priv) ...@@ -148,8 +148,8 @@ void mga_do_dma_flush(drm_mga_private_t * dev_priv)
primary->space = head - tail; primary->space = head - tail;
} }
DRM_DEBUG(" head = 0x%06lx\n", head - dev_priv->primary->offset); DRM_DEBUG(" head = 0x%06lx\n", (unsigned long)(head - dev_priv->primary->offset));
DRM_DEBUG(" tail = 0x%06lx\n", tail - dev_priv->primary->offset); DRM_DEBUG(" tail = 0x%06lx\n", (unsigned long)(tail - dev_priv->primary->offset));
DRM_DEBUG(" space = 0x%06x\n", primary->space); DRM_DEBUG(" space = 0x%06x\n", primary->space);
mga_flush_write_combine(); mga_flush_write_combine();
...@@ -187,7 +187,7 @@ void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv) ...@@ -187,7 +187,7 @@ void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv)
primary->space = head - dev_priv->primary->offset; primary->space = head - dev_priv->primary->offset;
} }
DRM_DEBUG(" head = 0x%06lx\n", head - dev_priv->primary->offset); DRM_DEBUG(" head = 0x%06lx\n", (unsigned long)(head - dev_priv->primary->offset));
DRM_DEBUG(" tail = 0x%06x\n", primary->tail); DRM_DEBUG(" tail = 0x%06x\n", primary->tail);
DRM_DEBUG(" wrap = %d\n", primary->last_wrap); DRM_DEBUG(" wrap = %d\n", primary->last_wrap);
DRM_DEBUG(" space = 0x%06x\n", primary->space); DRM_DEBUG(" space = 0x%06x\n", primary->space);
...@@ -239,7 +239,7 @@ static void mga_freelist_print(struct drm_device * dev) ...@@ -239,7 +239,7 @@ static void mga_freelist_print(struct drm_device * dev)
for (entry = dev_priv->head->next; entry; entry = entry->next) { for (entry = dev_priv->head->next; entry; entry = entry->next) {
DRM_INFO(" %p idx=%2d age=0x%x 0x%06lx\n", DRM_INFO(" %p idx=%2d age=0x%x 0x%06lx\n",
entry, entry->buf->idx, entry->age.head, entry, entry->buf->idx, entry->age.head,
entry->age.head - dev_priv->primary->offset); (unsigned long)(entry->age.head - dev_priv->primary->offset));
} }
DRM_INFO("\n"); DRM_INFO("\n");
} }
...@@ -340,10 +340,10 @@ static struct drm_buf *mga_freelist_get(struct drm_device * dev) ...@@ -340,10 +340,10 @@ static struct drm_buf *mga_freelist_get(struct drm_device * dev)
DRM_DEBUG(" tail=0x%06lx %d\n", DRM_DEBUG(" tail=0x%06lx %d\n",
tail->age.head ? tail->age.head ?
tail->age.head - dev_priv->primary->offset : 0, (unsigned long)(tail->age.head - dev_priv->primary->offset) : 0,
tail->age.wrap); tail->age.wrap);
DRM_DEBUG(" head=0x%06lx %d\n", DRM_DEBUG(" head=0x%06lx %d\n",
head - dev_priv->primary->offset, wrap); (unsigned long)(head - dev_priv->primary->offset), wrap);
if (TEST_AGE(&tail->age, head, wrap)) { if (TEST_AGE(&tail->age, head, wrap)) {
prev = dev_priv->tail->prev; prev = dev_priv->tail->prev;
...@@ -366,8 +366,9 @@ int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf) ...@@ -366,8 +366,9 @@ int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf)
drm_mga_freelist_t *head, *entry, *prev; drm_mga_freelist_t *head, *entry, *prev;
DRM_DEBUG("age=0x%06lx wrap=%d\n", DRM_DEBUG("age=0x%06lx wrap=%d\n",
buf_priv->list_entry->age.head - (unsigned long)(buf_priv->list_entry->age.head -
dev_priv->primary->offset, buf_priv->list_entry->age.wrap); dev_priv->primary->offset),
buf_priv->list_entry->age.wrap);
entry = buf_priv->list_entry; entry = buf_priv->list_entry;
head = dev_priv->head; head = dev_priv->head;
......
...@@ -317,8 +317,8 @@ do { \ ...@@ -317,8 +317,8 @@ do { \
DRM_INFO( "\n" ); \ DRM_INFO( "\n" ); \
DRM_INFO( " tail=0x%06x head=0x%06lx\n", \ DRM_INFO( " tail=0x%06x head=0x%06lx\n", \
dev_priv->prim.tail, \ dev_priv->prim.tail, \
MGA_READ( MGA_PRIMADDRESS ) - \ (unsigned long)(MGA_READ(MGA_PRIMADDRESS) - \
dev_priv->primary->offset ); \ dev_priv->primary->offset)); \
} \ } \
if ( !test_bit( 0, &dev_priv->prim.wrapped ) ) { \ if ( !test_bit( 0, &dev_priv->prim.wrapped ) ) { \
if ( dev_priv->prim.space < \ if ( dev_priv->prim.space < \
......
...@@ -525,11 +525,12 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init) ...@@ -525,11 +525,12 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
} else } else
#endif #endif
{ {
dev_priv->cce_ring->handle = (void *)dev_priv->cce_ring->offset; dev_priv->cce_ring->handle =
(void *)(unsigned long)dev_priv->cce_ring->offset;
dev_priv->ring_rptr->handle = dev_priv->ring_rptr->handle =
(void *)dev_priv->ring_rptr->offset; (void *)(unsigned long)dev_priv->ring_rptr->offset;
dev->agp_buffer_map->handle = dev->agp_buffer_map->handle =
(void *)dev->agp_buffer_map->offset; (void *)(unsigned long)dev->agp_buffer_map->offset;
} }
#if __OS_HAS_AGP #if __OS_HAS_AGP
......
...@@ -1062,11 +1062,12 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, ...@@ -1062,11 +1062,12 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
} else } else
#endif #endif
{ {
dev_priv->cp_ring->handle = (void *)dev_priv->cp_ring->offset; dev_priv->cp_ring->handle =
(void *)(unsigned long)dev_priv->cp_ring->offset;
dev_priv->ring_rptr->handle = dev_priv->ring_rptr->handle =
(void *)dev_priv->ring_rptr->offset; (void *)(unsigned long)dev_priv->ring_rptr->offset;
dev->agp_buffer_map->handle = dev->agp_buffer_map->handle =
(void *)dev->agp_buffer_map->offset; (void *)(unsigned long)dev->agp_buffer_map->offset;
DRM_DEBUG("dev_priv->cp_ring->handle %p\n", DRM_DEBUG("dev_priv->cp_ring->handle %p\n",
dev_priv->cp_ring->handle); dev_priv->cp_ring->handle);
...@@ -1177,7 +1178,7 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, ...@@ -1177,7 +1178,7 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
/* if we have an offset set from userspace */ /* if we have an offset set from userspace */
if (dev_priv->pcigart_offset_set) { if (dev_priv->pcigart_offset_set) {
dev_priv->gart_info.bus_addr = dev_priv->gart_info.bus_addr =
dev_priv->pcigart_offset + dev_priv->fb_location; (resource_size_t)dev_priv->pcigart_offset + dev_priv->fb_location;
dev_priv->gart_info.mapping.offset = dev_priv->gart_info.mapping.offset =
dev_priv->pcigart_offset + dev_priv->fb_aper_offset; dev_priv->pcigart_offset + dev_priv->fb_aper_offset;
dev_priv->gart_info.mapping.size = dev_priv->gart_info.mapping.size =
......
...@@ -526,7 +526,7 @@ struct drm_mm { ...@@ -526,7 +526,7 @@ struct drm_mm {
* Kernel side of a mapping * Kernel side of a mapping
*/ */
struct drm_local_map { struct drm_local_map {
unsigned long offset; /**< Requested physical address (0 for SAREA)*/ resource_size_t offset; /**< Requested physical address (0 for SAREA)*/
unsigned long size; /**< Requested physical size (bytes) */ unsigned long size; /**< Requested physical size (bytes) */
enum drm_map_type type; /**< Type of memory to map */ enum drm_map_type type; /**< Type of memory to map */
enum drm_map_flags flags; /**< Flags */ enum drm_map_flags flags; /**< Flags */
...@@ -760,8 +760,8 @@ struct drm_driver { ...@@ -760,8 +760,8 @@ struct drm_driver {
struct drm_file *file_priv); struct drm_file *file_priv);
void (*reclaim_buffers_idlelocked) (struct drm_device *dev, void (*reclaim_buffers_idlelocked) (struct drm_device *dev,
struct drm_file *file_priv); struct drm_file *file_priv);
unsigned long (*get_map_ofs) (struct drm_local_map * map); resource_size_t (*get_map_ofs) (struct drm_local_map * map);
unsigned long (*get_reg_ofs) (struct drm_device *dev); resource_size_t (*get_reg_ofs) (struct drm_device *dev);
void (*set_version) (struct drm_device *dev, void (*set_version) (struct drm_device *dev,
struct drm_set_version *sv); struct drm_set_version *sv);
...@@ -1062,8 +1062,8 @@ extern int drm_release(struct inode *inode, struct file *filp); ...@@ -1062,8 +1062,8 @@ extern int drm_release(struct inode *inode, struct file *filp);
extern int drm_mmap(struct file *filp, struct vm_area_struct *vma); extern int drm_mmap(struct file *filp, struct vm_area_struct *vma);
extern int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma); extern int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma);
extern void drm_vm_open_locked(struct vm_area_struct *vma); extern void drm_vm_open_locked(struct vm_area_struct *vma);
extern unsigned long drm_core_get_map_ofs(struct drm_local_map * map); extern resource_size_t drm_core_get_map_ofs(struct drm_local_map * map);
extern unsigned long drm_core_get_reg_ofs(struct drm_device *dev); extern resource_size_t drm_core_get_reg_ofs(struct drm_device *dev);
extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait); extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
/* Memory management support (drm_memory.h) */ /* Memory management support (drm_memory.h) */
...@@ -1166,7 +1166,7 @@ extern int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv ...@@ -1166,7 +1166,7 @@ extern int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv
/* Buffer management support (drm_bufs.h) */ /* Buffer management support (drm_bufs.h) */
extern int drm_addbufs_agp(struct drm_device *dev, struct drm_buf_desc * request); extern int drm_addbufs_agp(struct drm_device *dev, struct drm_buf_desc * request);
extern int drm_addbufs_pci(struct drm_device *dev, struct drm_buf_desc * request); extern int drm_addbufs_pci(struct drm_device *dev, struct drm_buf_desc * request);
extern int drm_addmap(struct drm_device *dev, unsigned int offset, extern int drm_addmap(struct drm_device *dev, resource_size_t offset,
unsigned int size, enum drm_map_type type, unsigned int size, enum drm_map_type type,
enum drm_map_flags flags, struct drm_local_map **map_ptr); enum drm_map_flags flags, struct drm_local_map **map_ptr);
extern int drm_addmap_ioctl(struct drm_device *dev, void *data, extern int drm_addmap_ioctl(struct drm_device *dev, void *data,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment