From 700bf80ca9fadf2c1404c220addebd92d9ad799d Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 22 Aug 2006 09:47:33 +0200 Subject: Bring in stripped TTM functionality. --- linux-core/drm_vm.c | 299 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 279 insertions(+), 20 deletions(-) (limited to 'linux-core/drm_vm.c') diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index cf3bc3cf..9f48f297 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -34,12 +34,42 @@ */ #include "drmP.h" + #if defined(__ia64__) #include #endif static void drm_vm_open(struct vm_area_struct *vma); static void drm_vm_close(struct vm_area_struct *vma); +static void drm_vm_ttm_close(struct vm_area_struct *vma); +static int drm_vm_ttm_open(struct vm_area_struct *vma); +static void drm_vm_ttm_open_wrapper(struct vm_area_struct *vma); + + +pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma) +{ + pgprot_t tmp = drm_prot_map(vma->vm_flags); + +#if defined(__i386__) || defined(__x86_64__) + if (boot_cpu_data.x86 > 3 && map_type != _DRM_AGP) { + pgprot_val(tmp) |= _PAGE_PCD; + pgprot_val(tmp) &= ~_PAGE_PWT; + } +#elif defined(__powerpc__) + pgprot_val(tmp) |= _PAGE_NO_CACHE; + if (map->type == _DRM_REGISTERS) + pgprot_val(tmp) |= _PAGE_GUARDED; +#endif +#if defined(__ia64__) + if (efi_range_is_wc(vma->vm_start, vma->vm_end - + vma->vm_start)) + tmp = pgprot_writecombine(tmp); + else + tmp = pgprot_noncached(tmp); +#endif + return tmp; +} + /** * \c nopage method for AGP virtual memory. @@ -129,6 +159,131 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, } #endif /* __OS_HAS_AGP */ + +static int drm_ttm_remap_bound_pfn(struct vm_area_struct *vma, + unsigned long address, + unsigned long size) +{ + unsigned long + page_offset = (address - vma->vm_start) >> PAGE_SHIFT; + unsigned long + num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; + drm_ttm_vma_list_t *entry = (drm_ttm_vma_list_t *) + vma->vm_private_data; + drm_map_t *map = entry->map; + drm_ttm_t *ttm = (drm_ttm_t *) map->offset; + unsigned long i, cur_pfn; + unsigned long start = 0; + unsigned long end = 0; + unsigned long last_pfn = 0; + unsigned long start_pfn = 0; + int bound_sequence = FALSE; + int ret = 0; + uint32_t cur_flags; + + for (i=page_offset; ipage_flags[i]; + + if (!bound_sequence && (cur_flags & DRM_TTM_PAGE_UNCACHED)) { + + start = i; + end = i; + last_pfn = (cur_flags & DRM_TTM_MASK_PFN) >> PAGE_SHIFT; + start_pfn = last_pfn; + bound_sequence = TRUE; + + } else if (bound_sequence) { + + cur_pfn = (cur_flags & DRM_TTM_MASK_PFN) >> PAGE_SHIFT; + + if ( !(cur_flags & DRM_TTM_PAGE_UNCACHED) || + (cur_pfn != last_pfn + 1)) { + + ret = io_remap_pfn_range(vma, + vma->vm_start + (start << PAGE_SHIFT), + (ttm->aperture_base >> PAGE_SHIFT) + + start_pfn, + (end - start + 1) << PAGE_SHIFT, + drm_io_prot(_DRM_AGP, vma)); + + if (ret) + break; + + bound_sequence = (cur_flags & DRM_TTM_PAGE_UNCACHED); + if (!bound_sequence) + continue; + + start = i; + end = i; + last_pfn = cur_pfn; + start_pfn = last_pfn; + + } else { + + end++; + last_pfn = cur_pfn; + + } + } + } + + if (!ret && bound_sequence) { + ret = io_remap_pfn_range(vma, + vma->vm_start + (start << PAGE_SHIFT), + (ttm->aperture_base >> PAGE_SHIFT) + + start_pfn, + (end - start + 1) << PAGE_SHIFT, + drm_io_prot(_DRM_AGP, vma)); + } + + if (ret) { + DRM_ERROR("Map returned %c\n", ret); + } + return ret; +} + +static __inline__ struct page *drm_do_vm_ttm_nopage(struct vm_area_struct *vma, + unsigned long address) +{ + drm_ttm_vma_list_t *entry = (drm_ttm_vma_list_t *) + vma->vm_private_data; + drm_map_t *map; + unsigned long page_offset; + struct page *page; + drm_ttm_t *ttm; + pgprot_t default_prot; + uint32_t page_flags; + + if (address > vma->vm_end) + return NOPAGE_SIGBUS; /* Disallow mremap */ + if (!entry) + return NOPAGE_OOM; /* Nothing allocated */ + + map = (drm_map_t *) entry->map; + ttm = (drm_ttm_t *) map->offset; + page_offset = (address - vma->vm_start) >> PAGE_SHIFT; + page = ttm->pages[page_offset]; + + page_flags = ttm->page_flags[page_offset]; + + if (!page) { + page = ttm->pages[page_offset] = + alloc_page(GFP_KERNEL); + SetPageReserved(page); + } + if (!page) + return NOPAGE_OOM; + + get_page(page); + + default_prot = drm_prot_map(vma->vm_flags); + + BUG_ON(page_flags & DRM_TTM_PAGE_UNCACHED); + vma->vm_page_prot = default_prot; + + return page; +} + /** * \c nopage method for shared virtual memory. * @@ -243,6 +398,9 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) dmah.size = map->size; __drm_pci_free(dev, &dmah); break; + case _DRM_TTM: + BUG_ON(1); + break; } drm_free(map, sizeof(*map), DRM_MEM_MAPS); } @@ -358,6 +516,15 @@ static struct page *drm_vm_sg_nopage(struct vm_area_struct *vma, return drm_do_vm_sg_nopage(vma, address); } +static struct page *drm_vm_ttm_nopage(struct vm_area_struct *vma, + unsigned long address, int *type) +{ + if (type) + *type = VM_FAULT_MINOR; + return drm_do_vm_ttm_nopage(vma, address); +} + + #else /* LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,0) */ static struct page *drm_vm_nopage(struct vm_area_struct *vma, @@ -384,6 +551,13 @@ static struct page *drm_vm_sg_nopage(struct vm_area_struct *vma, return drm_do_vm_sg_nopage(vma, address); } +static struct page *drm_vm_ttm_nopage(struct vm_area_struct *vma, + unsigned long address, int unused) +{ + return drm_do_vm_ttm_nopage(vma, address); +} + + #endif /** AGP virtual memory operations */ @@ -414,6 +588,12 @@ static struct vm_operations_struct drm_vm_sg_ops = { .close = drm_vm_close, }; +static struct vm_operations_struct drm_vm_ttm_ops = { + .nopage = drm_vm_ttm_nopage, + .open = drm_vm_ttm_open_wrapper, + .close = drm_vm_ttm_close, +}; + /** * \c open method for shared virtual memory. * @@ -443,6 +623,46 @@ static void drm_vm_open(struct vm_area_struct *vma) } } +static int drm_vm_ttm_open(struct vm_area_struct *vma) { + + drm_ttm_vma_list_t *entry, *tmp_vma = + (drm_ttm_vma_list_t *) vma->vm_private_data; + drm_map_t *map; + drm_ttm_t *ttm; + drm_file_t *priv = vma->vm_file->private_data; + drm_device_t *dev = priv->head->dev; + int ret = 0; + + drm_vm_open(vma); + mutex_lock(&dev->struct_mutex); + entry = drm_calloc(1, sizeof(*entry), DRM_MEM_VMAS); + if (entry) { + *entry = *tmp_vma; + map = (drm_map_t *) entry->map; + ttm = (drm_ttm_t *) map->offset; + /* ret = drm_ttm_add_mm_to_list(ttm, vma->vm_mm); */ + if (!ret) { + atomic_inc(&ttm->vma_count); + INIT_LIST_HEAD(&entry->head); + entry->vma = vma; + entry->orig_protection = vma->vm_page_prot; + list_add_tail(&entry->head, &ttm->vma_list->head); + vma->vm_private_data = (void *) entry; + DRM_DEBUG("Added VMA to ttm at 0x%016lx\n", + (unsigned long) ttm); + } + } else { + ret = -ENOMEM; + } + mutex_unlock(&dev->struct_mutex); + return ret; +} + +static void drm_vm_ttm_open_wrapper(struct vm_area_struct *vma) +{ + drm_vm_ttm_open(vma); +} + /** * \c close method for all virtual memory types. * @@ -476,6 +696,47 @@ static void drm_vm_close(struct vm_area_struct *vma) mutex_unlock(&dev->struct_mutex); } + +static void drm_vm_ttm_close(struct vm_area_struct *vma) +{ + drm_ttm_vma_list_t *ttm_vma = + (drm_ttm_vma_list_t *) vma->vm_private_data; + drm_map_t *map; + drm_ttm_t *ttm; + int found_maps; + struct list_head *list; + drm_device_t *dev; + + drm_vm_close(vma); + if (ttm_vma) { + map = (drm_map_t *) ttm_vma->map; + ttm = (drm_ttm_t *) map->offset; + dev = ttm->dev; + mutex_lock(&dev->struct_mutex); + list_del(&ttm_vma->head); + /* drm_ttm_delete_mm(ttm, vma->vm_mm); */ + drm_free(ttm_vma, sizeof(*ttm_vma), DRM_MEM_VMAS); + atomic_dec(&ttm->vma_count); + found_maps = 0; + list = NULL; +#if 0 /* Reimplement with vma_count */ + list_for_each(list, &ttm->owner->ttms) { + r_list = list_entry(list, drm_map_list_t, head); + if (r_list->map == map) + found_maps++; + } + if (!found_maps) { + if (drm_destroy_ttm(ttm) != -EBUSY) { + drm_free(map, sizeof(*map), DRM_MEM_MAPS); + } + } +#endif + mutex_unlock(&dev->struct_mutex); + } + return; +} + + /** * mmap DMA memory. * @@ -620,27 +881,9 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) /* fall through to _DRM_FRAME_BUFFER... */ case _DRM_FRAME_BUFFER: case _DRM_REGISTERS: -#if defined(__i386__) || defined(__x86_64__) - if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) { - pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; - pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT; - } -#elif defined(__powerpc__) - pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; - if (map->type == _DRM_REGISTERS) - pgprot_val(vma->vm_page_prot) |= _PAGE_GUARDED; -#endif - vma->vm_flags |= VM_IO; /* not in core dump */ -#if defined(__ia64__) - if (efi_range_is_wc(vma->vm_start, vma->vm_end - - vma->vm_start)) - vma->vm_page_prot = - pgprot_writecombine(vma->vm_page_prot); - else - vma->vm_page_prot = - pgprot_noncached(vma->vm_page_prot); -#endif offset = dev->driver->get_reg_ofs(dev); + vma->vm_flags |= VM_IO; /* not in core dump */ + vma->vm_page_prot = drm_io_prot(map->type, vma); #ifdef __sparc__ if (io_remap_pfn_range(vma, vma->vm_start, (map->offset + offset) >>PAGE_SHIFT, @@ -687,6 +930,22 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) vma->vm_flags |= VM_RESERVED; #endif break; + case _DRM_TTM: { + drm_ttm_vma_list_t tmp_vma; + tmp_vma.orig_protection = vma->vm_page_prot; + tmp_vma.map = map; + vma->vm_ops = &drm_vm_ttm_ops; + vma->vm_private_data = (void *) &tmp_vma; + vma->vm_file = filp; + vma->vm_flags |= VM_RESERVED | VM_IO; + if (drm_ttm_remap_bound_pfn(vma, + vma->vm_start, + vma->vm_end - vma->vm_start)) + return -EAGAIN; + if (drm_vm_ttm_open(vma)) + return -EAGAIN; + return 0; + } default: return -EINVAL; /* This should never happen. */ } -- cgit v1.2.3 From e201511a0fbeb177a9ecd7f77d177fc88c1616fb Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 22 Aug 2006 11:57:08 +0200 Subject: More ttm cleanups. --- linux-core/drm_vm.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) (limited to 'linux-core/drm_vm.c') diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index 9f48f297..85b39490 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -640,7 +640,7 @@ static int drm_vm_ttm_open(struct vm_area_struct *vma) { *entry = *tmp_vma; map = (drm_map_t *) entry->map; ttm = (drm_ttm_t *) map->offset; - /* ret = drm_ttm_add_mm_to_list(ttm, vma->vm_mm); */ + ret = drm_ttm_add_mm_to_list(ttm, vma->vm_mm); if (!ret) { atomic_inc(&ttm->vma_count); INIT_LIST_HEAD(&entry->head); @@ -706,6 +706,7 @@ static void drm_vm_ttm_close(struct vm_area_struct *vma) int found_maps; struct list_head *list; drm_device_t *dev; + int ret; drm_vm_close(vma); if (ttm_vma) { @@ -713,24 +714,15 @@ static void drm_vm_ttm_close(struct vm_area_struct *vma) ttm = (drm_ttm_t *) map->offset; dev = ttm->dev; mutex_lock(&dev->struct_mutex); - list_del(&ttm_vma->head); - /* drm_ttm_delete_mm(ttm, vma->vm_mm); */ + drm_ttm_delete_mm(ttm, vma->vm_mm); drm_free(ttm_vma, sizeof(*ttm_vma), DRM_MEM_VMAS); - atomic_dec(&ttm->vma_count); - found_maps = 0; - list = NULL; -#if 0 /* Reimplement with vma_count */ - list_for_each(list, &ttm->owner->ttms) { - r_list = list_entry(list, drm_map_list_t, head); - if (r_list->map == map) - found_maps++; - } - if (!found_maps) { - if (drm_destroy_ttm(ttm) != -EBUSY) { - drm_free(map, sizeof(*map), DRM_MEM_MAPS); + if (atomic_dec_and_test(&ttm->vma_count)) { + if (ttm->destroy) { + ret = drm_destroy_ttm(ttm); + BUG_ON(ret); + drm_free(map, sizeof(*map), DRM_MEM_TTM); } } -#endif mutex_unlock(&dev->struct_mutex); } return; -- cgit v1.2.3 From 4c03030b12bae28dad50d69bd271de632c43ff13 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 25 Aug 2006 18:05:35 +0200 Subject: Checkpoint commit Buffer object code. --- linux-core/drm_vm.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'linux-core/drm_vm.c') diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index 85b39490..9c2fbe08 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -703,8 +703,6 @@ static void drm_vm_ttm_close(struct vm_area_struct *vma) (drm_ttm_vma_list_t *) vma->vm_private_data; drm_map_t *map; drm_ttm_t *ttm; - int found_maps; - struct list_head *list; drm_device_t *dev; int ret; -- cgit v1.2.3 From 1d3cf107d20cb11ad07667622785ef8341ab9c2a Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 25 Aug 2006 18:14:22 +0200 Subject: Module protection map access is moving into mainline kernels. Update drm_compat accordingly. (Reported by Dave Airlie) --- linux-core/drm_vm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_vm.c') diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index 9c2fbe08..b5003c97 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -48,7 +48,7 @@ static void drm_vm_ttm_open_wrapper(struct vm_area_struct *vma); pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma) { - pgprot_t tmp = drm_prot_map(vma->vm_flags); + pgprot_t tmp = vm_get_page_prot(vma->vm_flags); #if defined(__i386__) || defined(__x86_64__) if (boot_cpu_data.x86 > 3 && map_type != _DRM_AGP) { @@ -276,7 +276,7 @@ static __inline__ struct page *drm_do_vm_ttm_nopage(struct vm_area_struct *vma, get_page(page); - default_prot = drm_prot_map(vma->vm_flags); + default_prot = vm_get_page_prot(vma->vm_flags); BUG_ON(page_flags & DRM_TTM_PAGE_UNCACHED); vma->vm_page_prot = default_prot; -- cgit v1.2.3 From 14a835be616183e733a2d6a7dcc697b8a6f46caf Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 30 Aug 2006 15:08:40 +0200 Subject: Buffer object mapping and mapping synchronization for multiple clients. --- linux-core/drm_vm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux-core/drm_vm.c') diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index 7163341d..69391058 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -713,6 +713,7 @@ static void drm_vm_ttm_close(struct vm_area_struct *vma) dev = ttm->dev; mutex_lock(&dev->struct_mutex); drm_ttm_delete_mm(ttm, vma->vm_mm); + list_del(&ttm_vma->head); drm_free(ttm_vma, sizeof(*ttm_vma), DRM_MEM_VMAS); if (atomic_dec_and_test(&ttm->vma_count)) { if (ttm->destroy) { -- cgit v1.2.3 From 191e284709ee792a32124e96e43d5876406b93dc Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 12 Sep 2006 12:01:00 +0200 Subject: More bugfixes. Disable the i915 IRQ turnoff for now since it seems to be causing problems. --- linux-core/drm_vm.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_vm.c') diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index 69391058..e7b808cc 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -253,6 +253,7 @@ static __inline__ struct page *drm_do_vm_ttm_nopage(struct vm_area_struct *vma, drm_ttm_t *ttm; pgprot_t default_prot; uint32_t page_flags; + drm_buffer_manager_t *bm; if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */ @@ -261,12 +262,18 @@ static __inline__ struct page *drm_do_vm_ttm_nopage(struct vm_area_struct *vma, map = (drm_map_t *) entry->map; ttm = (drm_ttm_t *) map->offset; + bm = &ttm->dev->bm; page_offset = (address - vma->vm_start) >> PAGE_SHIFT; page = ttm->pages[page_offset]; page_flags = ttm->page_flags[page_offset]; if (!page) { + if (bm->cur_pages >= bm->max_pages) { + DRM_ERROR("Maximum locked page count exceeded\n"); + return NOPAGE_OOM; + } + ++bm->cur_pages; page = ttm->pages[page_offset] = alloc_page(GFP_KERNEL); SetPageReserved(page); @@ -274,8 +281,6 @@ static __inline__ struct page *drm_do_vm_ttm_nopage(struct vm_area_struct *vma, if (!page) return NOPAGE_OOM; - get_page(page); - default_prot = vm_get_page_prot(vma->vm_flags); BUG_ON(page_flags & DRM_TTM_PAGE_UNCACHED); -- cgit v1.2.3 From 682c6ed0293771b093452597540118f47fda1adf Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 14 Sep 2006 12:17:38 +0200 Subject: Remove the use of reserved pages, and use locked pages instead. Update compatibility for latest linux versions. --- linux-core/drm_vm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_vm.c') diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index e7b808cc..aed0e04f 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -276,16 +276,17 @@ static __inline__ struct page *drm_do_vm_ttm_nopage(struct vm_area_struct *vma, ++bm->cur_pages; page = ttm->pages[page_offset] = alloc_page(GFP_KERNEL); - SetPageReserved(page); } if (!page) return NOPAGE_OOM; + SetPageLocked(page); + get_page(page); + default_prot = vm_get_page_prot(vma->vm_flags); BUG_ON(page_flags & DRM_TTM_PAGE_UNCACHED); vma->vm_page_prot = default_prot; - return page; } -- cgit v1.2.3 From 235f6fc650e9974211843b9196a903963dae0211 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 27 Sep 2006 09:27:31 +0200 Subject: Adapt to architecture-specific hooks for gatt pages. --- linux-core/drm_vm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'linux-core/drm_vm.c') diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index aed0e04f..76d7fb4e 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -274,8 +274,7 @@ static __inline__ struct page *drm_do_vm_ttm_nopage(struct vm_area_struct *vma, return NOPAGE_OOM; } ++bm->cur_pages; - page = ttm->pages[page_offset] = - alloc_page(GFP_KERNEL); + page = ttm->pages[page_offset] = drm_alloc_gatt_pages(0); } if (!page) return NOPAGE_OOM; -- cgit v1.2.3 From d85b99435f0ea7a17b3b7be31b53c00632c07177 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 2 Oct 2006 13:49:43 +0200 Subject: Allow for 44 bit user-tokens (or drm_file offsets) --- linux-core/drm_vm.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'linux-core/drm_vm.c') diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index 76d7fb4e..4755684e 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -100,7 +100,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, if (!dev->agp || !dev->agp->cant_use_aperture) goto vm_nopage_error; - if (drm_ht_find_item(&dev->map_hash, VM_OFFSET(vma), &hash)) + if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash)) goto vm_nopage_error; r_list = drm_hash_entry(hash, drm_map_list_t, hash); @@ -753,8 +753,8 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) lock_kernel(); dev = priv->head->dev; dma = dev->dma; - DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", - vma->vm_start, vma->vm_end, VM_OFFSET(vma)); + DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n", + vma->vm_start, vma->vm_end, vma->vm_pgoff); /* Length must match exact page count */ if (!dma || (length >> PAGE_SHIFT) != dma->page_count) { @@ -813,8 +813,8 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) unsigned long offset = 0; drm_hash_item_t *hash; - DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", - vma->vm_start, vma->vm_end, VM_OFFSET(vma)); + DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n", + vma->vm_start, vma->vm_end, vma->vm_pgoff); if (!priv->authenticated) return -EACCES; @@ -823,7 +823,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) * the AGP mapped at physical address 0 * --BenH. */ - if (!VM_OFFSET(vma) + if (!vma->vm_pgoff #if __OS_HAS_AGP && (!dev->agp || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE) @@ -831,7 +831,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) ) return drm_mmap_dma(filp, vma); - if (drm_ht_find_item(&dev->map_hash, VM_OFFSET(vma), &hash)) { + if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff , &hash)) { DRM_ERROR("Could not find map\n"); return -EINVAL; } -- cgit v1.2.3 From c58574c60505a699e19e1ed59e1b441be2594e53 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 10 Oct 2006 10:37:26 +0200 Subject: Use a nopage-based approach to fault in pfns. --- linux-core/drm_vm.c | 48 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) (limited to 'linux-core/drm_vm.c') diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index 4755684e..5fbbaadd 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -237,7 +237,7 @@ static int drm_ttm_remap_bound_pfn(struct vm_area_struct *vma, } if (ret) { - DRM_ERROR("Map returned %c\n", ret); + DRM_ERROR("Map returned %c\n", ret); } return ret; } @@ -254,6 +254,7 @@ static __inline__ struct page *drm_do_vm_ttm_nopage(struct vm_area_struct *vma, pgprot_t default_prot; uint32_t page_flags; drm_buffer_manager_t *bm; + drm_device_t *dev; if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */ @@ -262,7 +263,11 @@ static __inline__ struct page *drm_do_vm_ttm_nopage(struct vm_area_struct *vma, map = (drm_map_t *) entry->map; ttm = (drm_ttm_t *) map->offset; - bm = &ttm->dev->bm; + + dev = ttm->dev; + mutex_lock(&dev->struct_mutex); + + bm = &dev->bm; page_offset = (address - vma->vm_start) >> PAGE_SHIFT; page = ttm->pages[page_offset]; @@ -270,22 +275,43 @@ static __inline__ struct page *drm_do_vm_ttm_nopage(struct vm_area_struct *vma, if (!page) { if (bm->cur_pages >= bm->max_pages) { - DRM_ERROR("Maximum locked page count exceeded\n"); - return NOPAGE_OOM; + DRM_ERROR("Maximum locked page count exceeded\n"); + page = NOPAGE_OOM; + goto out; } ++bm->cur_pages; page = ttm->pages[page_offset] = drm_alloc_gatt_pages(0); + if (page) { + SetPageLocked(page); + } else { + page = NOPAGE_OOM; + } } - if (!page) - return NOPAGE_OOM; - SetPageLocked(page); - get_page(page); + if (page_flags & DRM_TTM_PAGE_UNCACHED) { - default_prot = vm_get_page_prot(vma->vm_flags); + /* + * This makes sure we don't race with another + * drm_ttm_remap_bound_pfn(); + */ - BUG_ON(page_flags & DRM_TTM_PAGE_UNCACHED); + if (!drm_pte_is_clear(vma, address)) { + page = NOPAGE_RETRY; + goto out1; + } + + drm_ttm_remap_bound_pfn(vma, address, PAGE_SIZE); + page = NOPAGE_RETRY; + goto out1; + } + get_page(page); + + out1: + default_prot = vm_get_page_prot(vma->vm_flags); vma->vm_page_prot = default_prot; + + out: + mutex_unlock(&dev->struct_mutex); return page; } @@ -645,7 +671,6 @@ static int drm_vm_ttm_open(struct vm_area_struct *vma) { *entry = *tmp_vma; map = (drm_map_t *) entry->map; ttm = (drm_ttm_t *) map->offset; - ret = drm_ttm_add_mm_to_list(ttm, vma->vm_mm); if (!ret) { atomic_inc(&ttm->vma_count); INIT_LIST_HEAD(&entry->head); @@ -717,7 +742,6 @@ static void drm_vm_ttm_close(struct vm_area_struct *vma) ttm = (drm_ttm_t *) map->offset; dev = ttm->dev; mutex_lock(&dev->struct_mutex); - drm_ttm_delete_mm(ttm, vma->vm_mm); list_del(&ttm_vma->head); drm_free(ttm_vma, sizeof(*ttm_vma), DRM_MEM_VMAS); if (atomic_dec_and_test(&ttm->vma_count)) { -- cgit v1.2.3 From f2db76e2f206d2017f710eaddc4b33add4498898 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 11 Oct 2006 13:40:35 +0200 Subject: Big update: Adapt for new functions in the 2.6.19 kernel. Remove the ability to have multiple regions in one TTM. This simplifies a lot of code. Remove the ability to access TTMs from user space. We don't need it anymore without ttm regions. Don't change caching policy for evicted buffers. Instead change it only when the buffer is accessed by the CPU (on the first page fault). This tremendously speeds up eviction rates. Current code is safe for kernels <= 2.6.14. Should also be OK with 2.6.19 and above. --- linux-core/drm_vm.c | 255 ++++++++++++++++++---------------------------------- 1 file changed, 85 insertions(+), 170 deletions(-) (limited to 'linux-core/drm_vm.c') diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index 5fbbaadd..45951156 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -159,120 +159,48 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, } #endif /* __OS_HAS_AGP */ - -static int drm_ttm_remap_bound_pfn(struct vm_area_struct *vma, - unsigned long address, - unsigned long size) -{ - unsigned long - page_offset = (address - vma->vm_start) >> PAGE_SHIFT; - unsigned long - num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; - drm_ttm_vma_list_t *entry = (drm_ttm_vma_list_t *) - vma->vm_private_data; - drm_map_t *map = entry->map; - drm_ttm_t *ttm = (drm_ttm_t *) map->offset; - unsigned long i, cur_pfn; - unsigned long start = 0; - unsigned long end = 0; - unsigned long last_pfn = 0; - unsigned long start_pfn = 0; - int bound_sequence = FALSE; - int ret = 0; - uint32_t cur_flags; - - for (i=page_offset; ipage_flags[i]; - - if (!bound_sequence && (cur_flags & DRM_TTM_PAGE_UNCACHED)) { - - start = i; - end = i; - last_pfn = (cur_flags & DRM_TTM_MASK_PFN) >> PAGE_SHIFT; - start_pfn = last_pfn; - bound_sequence = TRUE; - - } else if (bound_sequence) { - - cur_pfn = (cur_flags & DRM_TTM_MASK_PFN) >> PAGE_SHIFT; - - if ( !(cur_flags & DRM_TTM_PAGE_UNCACHED) || - (cur_pfn != last_pfn + 1)) { - - ret = io_remap_pfn_range(vma, - vma->vm_start + (start << PAGE_SHIFT), - (ttm->aperture_base >> PAGE_SHIFT) - + start_pfn, - (end - start + 1) << PAGE_SHIFT, - drm_io_prot(_DRM_AGP, vma)); - - if (ret) - break; - - bound_sequence = (cur_flags & DRM_TTM_PAGE_UNCACHED); - if (!bound_sequence) - continue; - - start = i; - end = i; - last_pfn = cur_pfn; - start_pfn = last_pfn; - - } else { - - end++; - last_pfn = cur_pfn; - - } - } - } - - if (!ret && bound_sequence) { - ret = io_remap_pfn_range(vma, - vma->vm_start + (start << PAGE_SHIFT), - (ttm->aperture_base >> PAGE_SHIFT) - + start_pfn, - (end - start + 1) << PAGE_SHIFT, - drm_io_prot(_DRM_AGP, vma)); - } - - if (ret) { - DRM_ERROR("Map returned %c\n", ret); - } - return ret; -} - -static __inline__ struct page *drm_do_vm_ttm_nopage(struct vm_area_struct *vma, - unsigned long address) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)) +static +#endif +struct page *drm_vm_ttm_fault(struct vm_area_struct *vma, + struct fault_data *data) { - drm_ttm_vma_list_t *entry = (drm_ttm_vma_list_t *) - vma->vm_private_data; - drm_map_t *map; + unsigned long address = data->address; + drm_local_map_t *map = (drm_local_map_t *) vma->vm_private_data; unsigned long page_offset; struct page *page; drm_ttm_t *ttm; - pgprot_t default_prot; - uint32_t page_flags; drm_buffer_manager_t *bm; drm_device_t *dev; + unsigned long pfn; + int err; + pgprot_t pgprot; - if (address > vma->vm_end) - return NOPAGE_SIGBUS; /* Disallow mremap */ - if (!entry) - return NOPAGE_OOM; /* Nothing allocated */ + if (!map) { + data->type = VM_FAULT_OOM; + return NULL; + } + + if (address > vma->vm_end) { + data->type = VM_FAULT_SIGBUS; + return NULL; + } - map = (drm_map_t *) entry->map; ttm = (drm_ttm_t *) map->offset; dev = ttm->dev; + + /* + * Perhaps retry here? + */ + mutex_lock(&dev->struct_mutex); + drm_fixup_ttm_caching(ttm); bm = &dev->bm; page_offset = (address - vma->vm_start) >> PAGE_SHIFT; page = ttm->pages[page_offset]; - page_flags = ttm->page_flags[page_offset]; - if (!page) { if (bm->cur_pages >= bm->max_pages) { DRM_ERROR("Maximum locked page count exceeded\n"); @@ -281,40 +209,65 @@ static __inline__ struct page *drm_do_vm_ttm_nopage(struct vm_area_struct *vma, } ++bm->cur_pages; page = ttm->pages[page_offset] = drm_alloc_gatt_pages(0); - if (page) { - SetPageLocked(page); - } else { - page = NOPAGE_OOM; + if (!page) { + data->type = VM_FAULT_OOM; + goto out; } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) + SetPageLocked(page); +#else + SetPageReserved(page); +#endif } - if (page_flags & DRM_TTM_PAGE_UNCACHED) { + if (ttm->page_flags & DRM_TTM_PAGE_UNCACHED) { /* - * This makes sure we don't race with another - * drm_ttm_remap_bound_pfn(); + * FIXME: Check can't map aperture flag. */ - if (!drm_pte_is_clear(vma, address)) { - page = NOPAGE_RETRY; - goto out1; - } - - drm_ttm_remap_bound_pfn(vma, address, PAGE_SIZE); - page = NOPAGE_RETRY; - goto out1; + pfn = ttm->aper_offset + page_offset + + (ttm->be->aperture_base >> PAGE_SHIFT); + pgprot = drm_io_prot(ttm->be->drm_map_type, vma); + } else { + pfn = page_to_pfn(page); + pgprot = vma->vm_page_prot; } - get_page(page); - out1: - default_prot = vm_get_page_prot(vma->vm_flags); - vma->vm_page_prot = default_prot; + err = vm_insert_pfn(vma, address, pfn, pgprot); + if (!err && (ttm->page_flags & DRM_TTM_PAGE_UNCACHED) && + ttm->num_pages > 1) { + + /* + * FIXME: Check can't map aperture flag. + */ + + /* + * Since we're not racing with anybody else, + * we might as well populate the whole object space. + * Note that we're touching vma->vm_flags with this + * operation, but we are not changing them, so we should be + * OK. + */ + + BUG_ON(ttm->state == ttm_unpopulated); + err = io_remap_pfn_range(vma, address + PAGE_SIZE, pfn+1, + (ttm->num_pages - 1) * PAGE_SIZE, + pgprot); + } + + + if (!err || err == -EBUSY) + data->type = VM_FAULT_MINOR; + else + data->type = VM_FAULT_OOM; out: mutex_unlock(&dev->struct_mutex); - return page; + return NULL; } + /** * \c nopage method for shared virtual memory. * @@ -547,14 +500,6 @@ static struct page *drm_vm_sg_nopage(struct vm_area_struct *vma, return drm_do_vm_sg_nopage(vma, address); } -static struct page *drm_vm_ttm_nopage(struct vm_area_struct *vma, - unsigned long address, int *type) -{ - if (type) - *type = VM_FAULT_MINOR; - return drm_do_vm_ttm_nopage(vma, address); -} - #else /* LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,0) */ @@ -582,13 +527,6 @@ static struct page *drm_vm_sg_nopage(struct vm_area_struct *vma, return drm_do_vm_sg_nopage(vma, address); } -static struct page *drm_vm_ttm_nopage(struct vm_area_struct *vma, - unsigned long address, int unused) -{ - return drm_do_vm_ttm_nopage(vma, address); -} - - #endif /** AGP virtual memory operations */ @@ -619,11 +557,19 @@ static struct vm_operations_struct drm_vm_sg_ops = { .close = drm_vm_close, }; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) static struct vm_operations_struct drm_vm_ttm_ops = { .nopage = drm_vm_ttm_nopage, .open = drm_vm_ttm_open_wrapper, .close = drm_vm_ttm_close, }; +#else +static struct vm_operations_struct drm_vm_ttm_ops = { + .fault = drm_vm_ttm_fault, + .open = drm_vm_ttm_open_wrapper, + .close = drm_vm_ttm_close, +}; +#endif /** * \c open method for shared virtual memory. @@ -656,36 +602,17 @@ static void drm_vm_open(struct vm_area_struct *vma) static int drm_vm_ttm_open(struct vm_area_struct *vma) { - drm_ttm_vma_list_t *entry, *tmp_vma = - (drm_ttm_vma_list_t *) vma->vm_private_data; - drm_map_t *map; + drm_local_map_t *map = (drm_local_map_t *)vma->vm_private_data; drm_ttm_t *ttm; drm_file_t *priv = vma->vm_file->private_data; drm_device_t *dev = priv->head->dev; - int ret = 0; drm_vm_open(vma); mutex_lock(&dev->struct_mutex); - entry = drm_calloc(1, sizeof(*entry), DRM_MEM_VMAS); - if (entry) { - *entry = *tmp_vma; - map = (drm_map_t *) entry->map; - ttm = (drm_ttm_t *) map->offset; - if (!ret) { - atomic_inc(&ttm->vma_count); - INIT_LIST_HEAD(&entry->head); - entry->vma = vma; - entry->orig_protection = vma->vm_page_prot; - list_add_tail(&entry->head, &ttm->vma_list->head); - vma->vm_private_data = (void *) entry; - DRM_DEBUG("Added VMA to ttm at 0x%016lx\n", - (unsigned long) ttm); - } - } else { - ret = -ENOMEM; - } + ttm = (drm_ttm_t *) map->offset; + atomic_inc(&ttm->vma_count); mutex_unlock(&dev->struct_mutex); - return ret; + return 0; } static void drm_vm_ttm_open_wrapper(struct vm_area_struct *vma) @@ -729,21 +656,16 @@ static void drm_vm_close(struct vm_area_struct *vma) static void drm_vm_ttm_close(struct vm_area_struct *vma) { - drm_ttm_vma_list_t *ttm_vma = - (drm_ttm_vma_list_t *) vma->vm_private_data; - drm_map_t *map; + drm_local_map_t *map = (drm_local_map_t *) vma->vm_private_data; drm_ttm_t *ttm; drm_device_t *dev; int ret; drm_vm_close(vma); - if (ttm_vma) { - map = (drm_map_t *) ttm_vma->map; + if (map) { ttm = (drm_ttm_t *) map->offset; dev = ttm->dev; mutex_lock(&dev->struct_mutex); - list_del(&ttm_vma->head); - drm_free(ttm_vma, sizeof(*ttm_vma), DRM_MEM_VMAS); if (atomic_dec_and_test(&ttm->vma_count)) { if (ttm->destroy) { ret = drm_destroy_ttm(ttm); @@ -951,17 +873,10 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) #endif break; case _DRM_TTM: { - drm_ttm_vma_list_t tmp_vma; - tmp_vma.orig_protection = vma->vm_page_prot; - tmp_vma.map = map; vma->vm_ops = &drm_vm_ttm_ops; - vma->vm_private_data = (void *) &tmp_vma; + vma->vm_private_data = (void *) map; vma->vm_file = filp; vma->vm_flags |= VM_RESERVED | VM_IO; - if (drm_ttm_remap_bound_pfn(vma, - vma->vm_start, - vma->vm_end - vma->vm_start)) - return -EAGAIN; if (drm_vm_ttm_open(vma)) return -EAGAIN; return 0; -- cgit v1.2.3 From 30703893674b3da5b862dee2acd6efca13424398 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 11 Oct 2006 22:21:01 +0200 Subject: Compatibility code for 2.6.15-2.6.18. It is ugly but a little comfort is that it will go away in the mainstream kernel. Some bugfixes, mainly in error paths. --- linux-core/drm_vm.c | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) (limited to 'linux-core/drm_vm.c') diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index 45951156..091b43f7 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -204,15 +204,15 @@ struct page *drm_vm_ttm_fault(struct vm_area_struct *vma, if (!page) { if (bm->cur_pages >= bm->max_pages) { DRM_ERROR("Maximum locked page count exceeded\n"); - page = NOPAGE_OOM; + data->type = VM_FAULT_OOM; goto out; } - ++bm->cur_pages; page = ttm->pages[page_offset] = drm_alloc_gatt_pages(0); if (!page) { data->type = VM_FAULT_OOM; goto out; } + ++bm->cur_pages; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) SetPageLocked(page); #else @@ -236,28 +236,6 @@ struct page *drm_vm_ttm_fault(struct vm_area_struct *vma, err = vm_insert_pfn(vma, address, pfn, pgprot); - if (!err && (ttm->page_flags & DRM_TTM_PAGE_UNCACHED) && - ttm->num_pages > 1) { - - /* - * FIXME: Check can't map aperture flag. - */ - - /* - * Since we're not racing with anybody else, - * we might as well populate the whole object space. - * Note that we're touching vma->vm_flags with this - * operation, but we are not changing them, so we should be - * OK. - */ - - BUG_ON(ttm->state == ttm_unpopulated); - err = io_remap_pfn_range(vma, address + PAGE_SIZE, pfn+1, - (ttm->num_pages - 1) * PAGE_SIZE, - pgprot); - } - - if (!err || err == -EBUSY) data->type = VM_FAULT_MINOR; else @@ -611,6 +589,9 @@ static int drm_vm_ttm_open(struct vm_area_struct *vma) { mutex_lock(&dev->struct_mutex); ttm = (drm_ttm_t *) map->offset; atomic_inc(&ttm->vma_count); +#ifdef DRM_ODD_MM_COMPAT + drm_ttm_add_vma(ttm, vma); +#endif mutex_unlock(&dev->struct_mutex); return 0; } @@ -666,6 +647,9 @@ static void drm_vm_ttm_close(struct vm_area_struct *vma) ttm = (drm_ttm_t *) map->offset; dev = ttm->dev; mutex_lock(&dev->struct_mutex); +#ifdef DRM_ODD_MM_COMPAT + drm_ttm_delete_vma(ttm, vma); +#endif if (atomic_dec_and_test(&ttm->vma_count)) { if (ttm->destroy) { ret = drm_destroy_ttm(ttm); @@ -877,6 +861,11 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) vma->vm_private_data = (void *) map; vma->vm_file = filp; vma->vm_flags |= VM_RESERVED | VM_IO; +#ifdef DRM_ODD_MM_COMPAT + mutex_lock(&dev->struct_mutex); + drm_ttm_map_bound(vma); + mutex_unlock(&dev->struct_mutex); +#endif if (drm_vm_ttm_open(vma)) return -EAGAIN; return 0; -- cgit v1.2.3 From d515936ea7f98f6aaa9217699796beadef9d664b Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 17 Oct 2006 19:40:57 +0200 Subject: Add memory usage accounting to avoid DOS problems. --- linux-core/drm_vm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux-core/drm_vm.c') diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index 091b43f7..1654236d 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -202,13 +202,13 @@ struct page *drm_vm_ttm_fault(struct vm_area_struct *vma, page = ttm->pages[page_offset]; if (!page) { - if (bm->cur_pages >= bm->max_pages) { - DRM_ERROR("Maximum locked page count exceeded\n"); + if (drm_alloc_memctl(PAGE_SIZE)) { data->type = VM_FAULT_OOM; goto out; } page = ttm->pages[page_offset] = drm_alloc_gatt_pages(0); if (!page) { + drm_free_memctl(PAGE_SIZE); data->type = VM_FAULT_OOM; goto out; } @@ -654,7 +654,7 @@ static void drm_vm_ttm_close(struct vm_area_struct *vma) if (ttm->destroy) { ret = drm_destroy_ttm(ttm); BUG_ON(ret); - drm_free(map, sizeof(*map), DRM_MEM_TTM); + drm_ctl_free(map, sizeof(*map), DRM_MEM_TTM); } } mutex_unlock(&dev->struct_mutex); -- cgit v1.2.3 From f22f89e6b3c970a29197d3a53c170fb7d0340cbe Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 17 Oct 2006 19:52:34 +0200 Subject: Add vma list memory usage to memory accounting. Use byte unit for /proc printout of memory usage for small sizes to be able to detect memory allocation bugs more easily. --- linux-core/drm_vm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux-core/drm_vm.c') diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index 1654236d..aa112751 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -315,7 +315,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) } else { dev->vmalist = pt->next; } - drm_free(pt, sizeof(*pt), DRM_MEM_VMAS); + drm_ctl_free(pt, sizeof(*pt), DRM_MEM_VMAS); } else { prev = pt; } @@ -567,7 +567,7 @@ static void drm_vm_open(struct vm_area_struct *vma) vma->vm_start, vma->vm_end - vma->vm_start); atomic_inc(&dev->vma_count); - vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS); + vma_entry = drm_ctl_alloc(sizeof(*vma_entry), DRM_MEM_VMAS); if (vma_entry) { mutex_lock(&dev->struct_mutex); vma_entry->vma = vma; @@ -627,7 +627,7 @@ static void drm_vm_close(struct vm_area_struct *vma) } else { dev->vmalist = pt->next; } - drm_free(pt, sizeof(*pt), DRM_MEM_VMAS); + drm_ctl_free(pt, sizeof(*pt), DRM_MEM_VMAS); break; } } -- cgit v1.2.3