aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm/drm_vm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/drm/drm_vm.c')
-rw-r--r--drivers/char/drm/drm_vm.c45
1 files changed, 15 insertions, 30 deletions
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
index ffd0800ed601..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 == VM_OFFSET(vma))
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;
@@ -467,7 +464,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
467 dev = priv->head->dev; 464 dev = priv->head->dev;
468 dma = dev->dma; 465 dma = dev->dma;
469 DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", 466 DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
470 vma->vm_start, vma->vm_end, VM_OFFSET(vma)); 467 vma->vm_start, vma->vm_end, vma->vm_pgoff << PAGE_SHIFT);
471 468
472 /* Length must match exact page count */ 469 /* Length must match exact page count */
473 if (!dma || (length >> PAGE_SHIFT) != dma->page_count) { 470 if (!dma || (length >> PAGE_SHIFT) != dma->page_count) {
@@ -521,12 +518,11 @@ 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, VM_OFFSET(vma)); 525 vma->vm_start, vma->vm_end, vma->vm_pgoff << PAGE_SHIFT);
530 526
531 if (!priv->authenticated) 527 if (!priv->authenticated)
532 return -EACCES; 528 return -EACCES;
@@ -535,7 +531,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
535 * the AGP mapped at physical address 0 531 * the AGP mapped at physical address 0
536 * --BenH. 532 * --BenH.
537 */ 533 */
538 if (!VM_OFFSET(vma) 534 if (!(vma->vm_pgoff << PAGE_SHIFT)
539#if __OS_HAS_AGP 535#if __OS_HAS_AGP
540 && (!dev->agp 536 && (!dev->agp
541 || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE) 537 || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE)
@@ -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 == VM_OFFSET(vma))
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
@@ -620,7 +605,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
620 offset = dev->driver->get_reg_ofs(dev); 605 offset = dev->driver->get_reg_ofs(dev);
621#ifdef __sparc__ 606#ifdef __sparc__
622 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 607 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
623 if (io_remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start, 608 if (io_remap_pfn_range(vma, vma->vm_start,
624 (map->offset + offset) >> PAGE_SHIFT, 609 (map->offset + offset) >> PAGE_SHIFT,
625 vma->vm_end - vma->vm_start, 610 vma->vm_end - vma->vm_start,
626 vma->vm_page_prot)) 611 vma->vm_page_prot))