diff options
author | Eric Anholt <eric@anholt.net> | 2008-05-30 14:42:08 -0700 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2008-05-30 14:42:08 -0700 |
commit | 461bfa3da6f85b85c21cd84f81bb4eefa5481418 (patch) | |
tree | 33e91c8cd024f67922670f9ed6565ceda1e4f3b5 /linux-core/drm_vm.c | |
parent | 50bce2bc625deb439dd61f504496dddd0cd4f572 (diff) | |
parent | 6e8a2cff66ac0d6afaf9bb233bc81449c2014078 (diff) |
Merge commit 'origin/master' into drm-gem
Conflicts:
linux-core/Makefile.kernel
shared-core/i915_drv.h
shared-core/nouveau_state.c
Diffstat (limited to 'linux-core/drm_vm.c')
-rw-r--r-- | linux-core/drm_vm.c | 143 |
1 files changed, 62 insertions, 81 deletions
diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index cabfb8f4..6618c0ae 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -81,8 +81,9 @@ static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma) return tmp; } +#ifndef DRM_VM_NOPAGE /** - * \c nopage method for AGP virtual memory. + * \c fault method for AGP virtual memory. * * \param vma virtual memory area. * \param address access address. @@ -92,8 +93,7 @@ static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma) * map, get the page, increment the use count and return it. */ #if __OS_HAS_AGP -static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, - unsigned long address) +static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct drm_file *priv = vma->vm_file->private_data; struct drm_device *dev = priv->minor->dev; @@ -105,19 +105,24 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, * Find the right map */ if (!drm_core_has_AGP(dev)) - goto vm_nopage_error; + goto vm_fault_error; if (!dev->agp || !dev->agp->cant_use_aperture) - goto vm_nopage_error; + goto vm_fault_error; if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash)) - goto vm_nopage_error; + goto vm_fault_error; r_list = drm_hash_entry(hash, struct drm_map_list, hash); map = r_list->map; if (map && map->type == _DRM_AGP) { - unsigned long offset = address - vma->vm_start; + /* + * Using vm_pgoff as a selector forces us to use this unusual + * addressing scheme. + */ + unsigned long offset = (unsigned long)vmf->virtual_address - + vma->vm_start; unsigned long baddr = map->offset + offset; struct drm_agp_mem *agpmem; struct page *page; @@ -139,7 +144,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, } if (!agpmem) - goto vm_nopage_error; + goto vm_fault_error; /* * Get the page, inc the use count, and return it @@ -147,25 +152,21 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, offset = (baddr - agpmem->bound) >> PAGE_SHIFT; page = virt_to_page(__va(agpmem->memory->memory[offset])); get_page(page); + vmf->page = page; -#if 0 - /* page_count() not defined everywhere */ DRM_DEBUG ("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n", baddr, __va(agpmem->memory->memory[offset]), offset, page_count(page)); -#endif - - return page; + return 0; } - vm_nopage_error: - return NOPAGE_SIGBUS; /* Disallow mremap */ +vm_fault_error: + return VM_FAULT_SIGBUS; /* Disallow mremap */ } #else /* __OS_HAS_AGP */ -static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, - unsigned long address) +static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { - return NOPAGE_SIGBUS; + return VM_FAULT_SIGBUS; } #endif /* __OS_HAS_AGP */ @@ -179,29 +180,28 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, * Get the mapping, find the real physical page to map, get the page, and * return it. */ -static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma, - unsigned long address) +static int drm_do_vm_shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct drm_map *map = (struct drm_map *) vma->vm_private_data; unsigned long offset; unsigned long i; struct page *page; - if (address > vma->vm_end) - return NOPAGE_SIGBUS; /* Disallow mremap */ if (!map) - return NOPAGE_SIGBUS; /* Nothing allocated */ + return VM_FAULT_SIGBUS; /* Nothing allocated */ - offset = address - vma->vm_start; + offset = (unsigned long)vmf->virtual_address - vma->vm_start; i = (unsigned long)map->handle + offset; page = vmalloc_to_page((void *)i); if (!page) - return NOPAGE_SIGBUS; + return VM_FAULT_SIGBUS; get_page(page); + vmf->page = page; - DRM_DEBUG("0x%lx\n", address); - return page; + DRM_DEBUG("shm_fault 0x%lx\n", offset); + return 0; } +#endif /** * \c close method for shared virtual memory. @@ -283,8 +283,9 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) mutex_unlock(&dev->struct_mutex); } +#ifndef DRM_VM_NOPAGE /** - * \c nopage method for DMA virtual memory. + * \c fault method for DMA virtual memory. * * \param vma virtual memory area. * \param address access address. @@ -292,8 +293,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) * * Determine the page number from the page offset and get it from drm_device_dma::pagelist. */ -static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma, - unsigned long address) +static int drm_do_vm_dma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct drm_file *priv = vma->vm_file->private_data; struct drm_device *dev = priv->minor->dev; @@ -303,24 +303,23 @@ static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma, struct page *page; if (!dma) - return NOPAGE_SIGBUS; /* Error */ - if (address > vma->vm_end) - return NOPAGE_SIGBUS; /* Disallow mremap */ + return VM_FAULT_SIGBUS; /* Error */ if (!dma->pagelist) - return NOPAGE_SIGBUS; /* Nothing allocated */ + return VM_FAULT_SIGBUS; /* Nothing allocated */ - offset = address - vma->vm_start; /* vm_[pg]off[set] should be 0 */ - page_nr = offset >> PAGE_SHIFT; + offset = (unsigned long)vmf->virtual_address - vma->vm_start; /* vm_[pg]off[set] should be 0 */ + page_nr = offset >> PAGE_SHIFT; /* page_nr could just be vmf->pgoff */ page = virt_to_page((dma->pagelist[page_nr] + (offset & (~PAGE_MASK)))); get_page(page); + vmf->page = page; - DRM_DEBUG("0x%lx (page %lu)\n", address, page_nr); - return page; + DRM_DEBUG("dma_fault 0x%lx (page %lu)\n", offset, page_nr); + return 0; } /** - * \c nopage method for scatter-gather virtual memory. + * \c fault method for scatter-gather virtual memory. * * \param vma virtual memory area. * \param address access address. @@ -328,8 +327,7 @@ static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma, * * Determine the map offset from the page offset and get it from drm_sg_mem::pagelist. */ -static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma, - unsigned long address) +static int drm_do_vm_sg_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct drm_map *map = (struct drm_map *) vma->vm_private_data; struct drm_file *priv = vma->vm_file->private_data; @@ -340,80 +338,62 @@ static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma, unsigned long page_offset; struct page *page; - DRM_DEBUG("\n"); if (!entry) - return NOPAGE_SIGBUS; /* Error */ - if (address > vma->vm_end) - return NOPAGE_SIGBUS; /* Disallow mremap */ + return VM_FAULT_SIGBUS; /* Error */ if (!entry->pagelist) - return NOPAGE_SIGBUS; /* Nothing allocated */ + return VM_FAULT_SIGBUS; /* Nothing allocated */ - offset = address - vma->vm_start; + offset = (unsigned long)vmf->virtual_address - vma->vm_start; map_offset = map->offset - (unsigned long)dev->sg->virtual; page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT); page = entry->pagelist[page_offset]; get_page(page); + vmf->page = page; - return page; -} - -static struct page *drm_vm_nopage(struct vm_area_struct *vma, - unsigned long address, int *type) -{ - if (type) - *type = VM_FAULT_MINOR; - return drm_do_vm_nopage(vma, address); -} - -static struct page *drm_vm_shm_nopage(struct vm_area_struct *vma, - unsigned long address, int *type) -{ - if (type) - *type = VM_FAULT_MINOR; - return drm_do_vm_shm_nopage(vma, address); -} - -static struct page *drm_vm_dma_nopage(struct vm_area_struct *vma, - unsigned long address, int *type) -{ - if (type) - *type = VM_FAULT_MINOR; - return drm_do_vm_dma_nopage(vma, address); -} - -static struct page *drm_vm_sg_nopage(struct vm_area_struct *vma, - unsigned long address, int *type) -{ - if (type) - *type = VM_FAULT_MINOR; - return drm_do_vm_sg_nopage(vma, address); + return 0; } - +#endif /** AGP virtual memory operations */ static struct vm_operations_struct drm_vm_ops = { +#ifdef DRM_VM_NOPAGE .nopage = drm_vm_nopage, +#else + .fault = drm_do_vm_fault, +#endif .open = drm_vm_open, .close = drm_vm_close, }; /** Shared virtual memory operations */ static struct vm_operations_struct drm_vm_shm_ops = { +#ifdef DRM_VM_NOPAGE .nopage = drm_vm_shm_nopage, +#else + .fault = drm_do_vm_shm_fault, +#endif .open = drm_vm_open, .close = drm_vm_shm_close, }; /** DMA virtual memory operations */ static struct vm_operations_struct drm_vm_dma_ops = { +#ifdef DRM_VM_NOPAGE .nopage = drm_vm_dma_nopage, +#else + .fault = drm_do_vm_dma_fault, +#endif .open = drm_vm_open, .close = drm_vm_close, }; /** Scatter-gather virtual memory operations */ static struct vm_operations_struct drm_vm_sg_ops = { +#ifdef DRM_VM_NOPAGE .nopage = drm_vm_sg_nopage, +#else + .fault = drm_do_vm_sg_fault, +#endif .open = drm_vm_open, .close = drm_vm_close, }; @@ -751,6 +731,7 @@ static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma, err = drm_bo_wait(bo, 0, 1, 0, 1); if (err) { ret = (err != -EAGAIN) ? NOPFN_SIGBUS : NOPFN_REFAULT; + bo->priv_flags &= ~_DRM_BO_FLAG_UNLOCKED; goto out_unlock; } |