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 <benh@kernel.crashing.org> Signed-off-by: Dave Airlie <airlied@linux.ie>
This commit is contained in:
committed by
Dave Airlie
parent
f77d390c97
commit
41c2e75e60
@@ -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)
|
||||
{
|
||||
|
Reference in New Issue
Block a user