Re: [patch 1/3] drm: nopage
From: Dave Airlie
Date: Tue Jan 08 2008 - 17:25:33 EST
> Dave, this patch is against 2.6.24-rc6-mm1. You said git-drm had rewritten this area,
> but the patch didn't have any rejects and seems to run fine here (although I'm not
> exactly sure how to exercise drm too well).
Hi Nick,
there should be a new nopage method added though which you need to
convert..
Dave.
>
> Anyway, please apply.
>
> --
>
> drm: nopage
>
> Convert drm from nopage to fault.
> Remove redundant vma range checks.
>
> Signed-off-by: Nick Piggin <npiggin@xxxxxxx>
> Cc: airlied@xxxxxxxx
> Cc: linux-kernel@xxxxxxxxxxxxxxx
> ---
> drivers/char/drm/drm_vm.c | 131 +++++++++++++++++++++-------------------------
> 1 file changed, 61 insertions(+), 70 deletions(-)
>
> Index: linux-2.6/drivers/char/drm/drm_vm.c
> ===================================================================
> --- linux-2.6.orig/drivers/char/drm/drm_vm.c
> +++ linux-2.6/drivers/char/drm/drm_vm.c
> @@ -70,7 +70,7 @@ static pgprot_t drm_io_prot(uint32_t map
> }
>
> /**
> - * \c nopage method for AGP virtual memory.
> + * \c fault method for AGP virtual memory.
> *
> * \param vma virtual memory area.
> * \param address access address.
> @@ -80,8 +80,8 @@ static pgprot_t drm_io_prot(uint32_t map
> * 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 __inline__ 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->head->dev;
> @@ -93,19 +93,24 @@ static __inline__ struct page *drm_do_vm
> * 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;
> @@ -127,7 +132,7 @@ static __inline__ struct page *drm_do_vm
> }
>
> if (!agpmem)
> - goto vm_nopage_error;
> + goto vm_fault_error;
>
> /*
> * Get the page, inc the use count, and return it
> @@ -135,27 +140,28 @@ static __inline__ struct page *drm_do_vm
> offset = (baddr - agpmem->bound) >> PAGE_SHIFT;
> page = virt_to_page(__va(agpmem->memory->memory[offset]));
> get_page(page);
> + vmf->page = page;
>
> DRM_DEBUG
> ("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n",
> baddr, __va(agpmem->memory->memory[offset]), offset,
> page_count(page));
>
> - 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 __inline__ 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 */
>
> /**
> - * \c nopage method for shared virtual memory.
> + * \c fault method for shared virtual memory.
> *
> * \param vma virtual memory area.
> * \param address access address.
> @@ -164,28 +170,27 @@ static __inline__ struct page *drm_do_vm
> * 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 __inline__ 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("shm_nopage 0x%lx\n", address);
> - return page;
> + DRM_DEBUG("shm_fault 0x%lx\n", offset);
> + return 0;
> }
>
> /**
> @@ -270,7 +275,7 @@ static void drm_vm_shm_close(struct vm_a
> }
>
> /**
> - * \c nopage method for DMA virtual memory.
> + * \c fault method for DMA virtual memory.
> *
> * \param vma virtual memory area.
> * \param address access address.
> @@ -278,8 +283,8 @@ static void drm_vm_shm_close(struct vm_a
> *
> * 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 __inline__ 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->head->dev;
> @@ -289,24 +294,23 @@ static __inline__ struct page *drm_do_vm
> 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("dma_nopage 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.
> @@ -314,8 +318,8 @@ static __inline__ struct page *drm_do_vm
> *
> * 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 __inline__ 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;
> @@ -327,77 +331,64 @@ static __inline__ struct page *drm_do_vm
> struct page *page;
>
> 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;
> + return 0;
> }
>
> -static struct page *drm_vm_nopage(struct vm_area_struct *vma,
> - unsigned long address, int *type)
> +static int drm_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
> {
> - if (type)
> - *type = VM_FAULT_MINOR;
> - return drm_do_vm_nopage(vma, address);
> + return drm_do_vm_fault(vma, vmf);
> }
>
> -static struct page *drm_vm_shm_nopage(struct vm_area_struct *vma,
> - unsigned long address, int *type)
> +static int drm_vm_shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
> {
> - if (type)
> - *type = VM_FAULT_MINOR;
> - return drm_do_vm_shm_nopage(vma, address);
> + return drm_do_vm_shm_fault(vma, vmf);
> }
>
> -static struct page *drm_vm_dma_nopage(struct vm_area_struct *vma,
> - unsigned long address, int *type)
> +static int drm_vm_dma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
> {
> - if (type)
> - *type = VM_FAULT_MINOR;
> - return drm_do_vm_dma_nopage(vma, address);
> + return drm_do_vm_dma_fault(vma, vmf);
> }
>
> -static struct page *drm_vm_sg_nopage(struct vm_area_struct *vma,
> - unsigned long address, int *type)
> +static int drm_vm_sg_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
> {
> - if (type)
> - *type = VM_FAULT_MINOR;
> - return drm_do_vm_sg_nopage(vma, address);
> + return drm_do_vm_sg_fault(vma, vmf);
> }
>
> /** AGP virtual memory operations */
> static struct vm_operations_struct drm_vm_ops = {
> - .nopage = drm_vm_nopage,
> + .fault = drm_vm_fault,
> .open = drm_vm_open,
> .close = drm_vm_close,
> };
>
> /** Shared virtual memory operations */
> static struct vm_operations_struct drm_vm_shm_ops = {
> - .nopage = drm_vm_shm_nopage,
> + .fault = drm_vm_shm_fault,
> .open = drm_vm_open,
> .close = drm_vm_shm_close,
> };
>
> /** DMA virtual memory operations */
> static struct vm_operations_struct drm_vm_dma_ops = {
> - .nopage = drm_vm_dma_nopage,
> + .fault = drm_vm_dma_fault,
> .open = drm_vm_open,
> .close = drm_vm_close,
> };
>
> /** Scatter-gather virtual memory operations */
> static struct vm_operations_struct drm_vm_sg_ops = {
> - .nopage = drm_vm_sg_nopage,
> + .fault = drm_vm_sg_fault,
> .open = drm_vm_open,
> .close = drm_vm_close,
> };
> @@ -610,7 +601,7 @@ static int drm_mmap_locked(struct file *
> /*
> * On some platforms we can't talk to bus dma address from the CPU, so for
> * memory of type DRM_AGP, we'll deal with sorting out the real physical
> - * pages and mappings in nopage()
> + * pages and mappings in fault()
> */
> #if defined(__powerpc__)
> pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
> @@ -640,7 +631,7 @@ static int drm_mmap_locked(struct file *
> break;
> case _DRM_CONSISTENT:
> /* Consistent memory is really like shared memory. But
> - * it's allocated in a different way, so avoid nopage */
> + * it's allocated in a different way, so avoid fault */
> if (remap_pfn_range(vma, vma->vm_start,
> page_to_pfn(virt_to_page(map->handle)),
> vma->vm_end - vma->vm_start, vma->vm_page_prot))
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/