diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-02-02 00:55:47 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2009-03-13 00:23:57 -0400 |
commit | 41c2e75e60200a860a74b7c84a6375c105e7437f (patch) | |
tree | 18e97662d6859eead4de816e121d001b34a7352a /drivers/gpu/drm/drm_bufs.c | |
parent | f77d390c9779c496aa5b99ec832996fb76bb1d13 (diff) |
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>
Diffstat (limited to 'drivers/gpu/drm/drm_bufs.c')
-rw-r--r-- | drivers/gpu/drm/drm_bufs.c | 37 |
1 files changed, 28 insertions, 9 deletions
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, | |||
54 | { | 54 | { |
55 | struct drm_map_list *entry; | 55 | struct drm_map_list *entry; |
56 | list_for_each_entry(entry, &dev->maplist, head) { | 56 | list_for_each_entry(entry, &dev->maplist, head) { |
57 | if (entry->map && (entry->master == dev->primary->master) && (map->type == entry->map->type) && | 57 | /* |
58 | ((entry->map->offset == map->offset) || | 58 | * Because the kernel-userspace ABI is fixed at a 32-bit offset |
59 | ((map->type == _DRM_SHM) && (map->flags&_DRM_CONTAINS_LOCK)))) { | 59 | * while PCI resources may live above that, we ignore the map |
60 | * offset for maps of type _DRM_FRAMEBUFFER or _DRM_REGISTERS. | ||
61 | * It is assumed that each driver will have only one resource of | ||
62 | * each type. | ||
63 | */ | ||
64 | if (!entry->map || | ||
65 | map->type != entry->map->type || | ||
66 | entry->master != dev->primary->master) | ||
67 | continue; | ||
68 | switch (map->type) { | ||
69 | case _DRM_SHM: | ||
70 | if (map->flags != _DRM_CONTAINS_LOCK) | ||
71 | break; | ||
72 | case _DRM_REGISTERS: | ||
73 | case _DRM_FRAME_BUFFER: | ||
60 | return entry; | 74 | return entry; |
75 | default: /* Make gcc happy */ | ||
76 | ; | ||
61 | } | 77 | } |
78 | if (entry->map->offset == map->offset) | ||
79 | return entry; | ||
62 | } | 80 | } |
63 | 81 | ||
64 | return NULL; | 82 | return NULL; |
@@ -96,7 +114,7 @@ static int drm_map_handle(struct drm_device *dev, struct drm_hash_item *hash, | |||
96 | * type. Adds the map to the map list drm_device::maplist. Adds MTRR's where | 114 | * type. Adds the map to the map list drm_device::maplist. Adds MTRR's where |
97 | * applicable and if supported by the kernel. | 115 | * applicable and if supported by the kernel. |
98 | */ | 116 | */ |
99 | static int drm_addmap_core(struct drm_device * dev, unsigned int offset, | 117 | static int drm_addmap_core(struct drm_device * dev, resource_size_t offset, |
100 | unsigned int size, enum drm_map_type type, | 118 | unsigned int size, enum drm_map_type type, |
101 | enum drm_map_flags flags, | 119 | enum drm_map_flags flags, |
102 | struct drm_map_list ** maplist) | 120 | struct drm_map_list ** maplist) |
@@ -124,9 +142,9 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset, | |||
124 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | 142 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); |
125 | return -EINVAL; | 143 | return -EINVAL; |
126 | } | 144 | } |
127 | DRM_DEBUG("offset = 0x%08lx, size = 0x%08lx, type = %d\n", | 145 | DRM_DEBUG("offset = 0x%08llx, size = 0x%08lx, type = %d\n", |
128 | map->offset, map->size, map->type); | 146 | (unsigned long long)map->offset, map->size, map->type); |
129 | if ((map->offset & (~PAGE_MASK)) || (map->size & (~PAGE_MASK))) { | 147 | if ((map->offset & (~(resource_size_t)PAGE_MASK)) || (map->size & (~PAGE_MASK))) { |
130 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | 148 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); |
131 | return -EINVAL; | 149 | return -EINVAL; |
132 | } | 150 | } |
@@ -254,7 +272,8 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset, | |||
254 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | 272 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); |
255 | return -EPERM; | 273 | return -EPERM; |
256 | } | 274 | } |
257 | DRM_DEBUG("AGP offset = 0x%08lx, size = 0x%08lx\n", map->offset, map->size); | 275 | DRM_DEBUG("AGP offset = 0x%08llx, size = 0x%08lx\n", |
276 | (unsigned long long)map->offset, map->size); | ||
258 | 277 | ||
259 | break; | 278 | break; |
260 | case _DRM_GEM: | 279 | case _DRM_GEM: |
@@ -322,7 +341,7 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset, | |||
322 | return 0; | 341 | return 0; |
323 | } | 342 | } |
324 | 343 | ||
325 | int drm_addmap(struct drm_device * dev, unsigned int offset, | 344 | int drm_addmap(struct drm_device * dev, resource_size_t offset, |
326 | unsigned int size, enum drm_map_type type, | 345 | unsigned int size, enum drm_map_type type, |
327 | enum drm_map_flags flags, struct drm_local_map ** map_ptr) | 346 | enum drm_map_flags flags, struct drm_local_map ** map_ptr) |
328 | { | 347 | { |