From 41c2e75e60200a860a74b7c84a6375c105e7437f Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 2 Feb 2009 16:55:47 +1100 Subject: 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: Benjamin Herrenschmidt Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_bufs.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/drm_bufs.c') diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index 1b8dbd5961bc..cddea1a2472c 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c @@ -54,11 +54,29 @@ static struct drm_map_list *drm_find_matching_map(struct drm_device *dev, { struct drm_map_list *entry; 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) || - ((map->type == _DRM_SHM) && (map->flags&_DRM_CONTAINS_LOCK)))) { + /* + * Because the kernel-userspace ABI is fixed at a 32-bit offset + * 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; + default: /* Make gcc happy */ + ; } + if (entry->map->offset == map->offset) + return entry; } return NULL; @@ -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 * 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, enum drm_map_flags flags, struct drm_map_list ** maplist) @@ -124,9 +142,9 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset, drm_free(map, sizeof(*map), DRM_MEM_MAPS); return -EINVAL; } - DRM_DEBUG("offset = 0x%08lx, size = 0x%08lx, type = %d\n", - map->offset, map->size, map->type); - if ((map->offset & (~PAGE_MASK)) || (map->size & (~PAGE_MASK))) { + DRM_DEBUG("offset = 0x%08llx, size = 0x%08lx, type = %d\n", + (unsigned long long)map->offset, map->size, map->type); + if ((map->offset & (~(resource_size_t)PAGE_MASK)) || (map->size & (~PAGE_MASK))) { drm_free(map, sizeof(*map), DRM_MEM_MAPS); return -EINVAL; } @@ -254,7 +272,8 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset, drm_free(map, sizeof(*map), DRM_MEM_MAPS); 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; case _DRM_GEM: @@ -322,7 +341,7 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset, 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, enum drm_map_flags flags, struct drm_local_map ** map_ptr) { -- cgit v1.2.3