aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm/drm_vm.c
diff options
context:
space:
mode:
authorThomas Hellstrom <thomas@tungstengraphics.com>2006-08-07 08:36:47 -0400
committerDave Airlie <airlied@linux.ie>2006-09-21 15:32:31 -0400
commit8d153f7107ff2c5d6e32053ae377c961187ab6b9 (patch)
treec90cdf1bf8e04237e840b37033fc0f57b74ab292 /drivers/char/drm/drm_vm.c
parent8669cbc5e651bf4effa20e8c244a5a7d67da6fe9 (diff)
drm: update user token hashing and map handles
Keep hashed user tokens, with the following changes: 32-bit physical device addresses are mapped directly to user-tokens. No duplicate maps are allowed, and the addresses are assumed to be outside of the range 0x10000000 through 0x30000000. The user-token is identical to the 32-bit physical start-address of the map. 64-bit physical device addressed are mapped to user-tokens in the range 0x10000000 to 0x30000000 with page-size increments. The user_token should not be interpreted as an address. Other map types, like upcoming TTM maps are mapped to user-tokens in the range 0x10000000 to 0x30000000 with page-size increments. The user_token should not be interpreted as an address. Implement hashed map lookups. Signed-off-by: Dave Airlie <airlied@linux.ie>
Diffstat (limited to 'drivers/char/drm/drm_vm.c')
-rw-r--r--drivers/char/drm/drm_vm.c37
1 files changed, 11 insertions, 26 deletions
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
index afb4f0a44b81..b40ae438f531 100644
--- a/drivers/char/drm/drm_vm.c
+++ b/drivers/char/drm/drm_vm.c
@@ -59,7 +59,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
59 drm_device_t *dev = priv->head->dev; 59 drm_device_t *dev = priv->head->dev;
60 drm_map_t *map = NULL; 60 drm_map_t *map = NULL;
61 drm_map_list_t *r_list; 61 drm_map_list_t *r_list;
62 struct list_head *list; 62 drm_hash_item_t *hash;
63 63
64 /* 64 /*
65 * Find the right map 65 * Find the right map
@@ -70,14 +70,11 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
70 if (!dev->agp || !dev->agp->cant_use_aperture) 70 if (!dev->agp || !dev->agp->cant_use_aperture)
71 goto vm_nopage_error; 71 goto vm_nopage_error;
72 72
73 list_for_each(list, &dev->maplist->head) { 73 if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff << PAGE_SHIFT, &hash))
74 r_list = list_entry(list, drm_map_list_t, head); 74 goto vm_nopage_error;
75 map = r_list->map; 75
76 if (!map) 76 r_list = drm_hash_entry(hash, drm_map_list_t, hash);
77 continue; 77 map = r_list->map;
78 if (r_list->user_token == (vma->vm_pgoff << PAGE_SHIFT))
79 break;
80 }
81 78
82 if (map && map->type == _DRM_AGP) { 79 if (map && map->type == _DRM_AGP) {
83 unsigned long offset = address - vma->vm_start; 80 unsigned long offset = address - vma->vm_start;
@@ -521,9 +518,8 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
521 drm_file_t *priv = filp->private_data; 518 drm_file_t *priv = filp->private_data;
522 drm_device_t *dev = priv->head->dev; 519 drm_device_t *dev = priv->head->dev;
523 drm_map_t *map = NULL; 520 drm_map_t *map = NULL;
524 drm_map_list_t *r_list;
525 unsigned long offset = 0; 521 unsigned long offset = 0;
526 struct list_head *list; 522 drm_hash_item_t *hash;
527 523
528 DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", 524 DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
529 vma->vm_start, vma->vm_end, vma->vm_pgoff << PAGE_SHIFT); 525 vma->vm_start, vma->vm_end, vma->vm_pgoff << PAGE_SHIFT);
@@ -543,23 +539,12 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
543 ) 539 )
544 return drm_mmap_dma(filp, vma); 540 return drm_mmap_dma(filp, vma);
545 541
546 /* A sequential search of a linked list is 542 if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff << PAGE_SHIFT, &hash)) {
547 fine here because: 1) there will only be 543 DRM_ERROR("Could not find map\n");
548 about 5-10 entries in the list and, 2) a 544 return -EINVAL;
549 DRI client only has to do this mapping
550 once, so it doesn't have to be optimized
551 for performance, even if the list was a
552 bit longer. */
553 list_for_each(list, &dev->maplist->head) {
554
555 r_list = list_entry(list, drm_map_list_t, head);
556 map = r_list->map;
557 if (!map)
558 continue;
559 if (r_list->user_token == vma->vm_pgoff << PAGE_SHIFT)
560 break;
561 } 545 }
562 546
547 map = drm_hash_entry(hash, drm_map_list_t, hash)->map;
563 if (!map || ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) 548 if (!map || ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
564 return -EPERM; 549 return -EPERM;
565 550