[PATCH 08/11] drm/ttm: introduce callback for ttm_tt populate & unpopulate
Alex Deucher
alexdeucher at gmail.com
Mon Nov 7 12:17:54 PST 2011
On Mon, Nov 7, 2011 at 12:35 PM, Rob Clark <robdclark at gmail.com> wrote:
> On Thu, Nov 3, 2011 at 6:39 PM, <j.glisse at gmail.com> wrote:
>> From: Jerome Glisse <jglisse at redhat.com>
>>
>> Move the page allocation and freeing to driver callback and
>> provide ttm code helper function for those.
>
> btw, having page allocation/freeing in driver callback would solve one
> issue that I've been struggling with on ARM.. (well actually, two..
> but one that might not apply to some x86 drivers)
>
> 1) for buffers mapped uncached/writecombine to userspace, I need a
> page that is removed from kernel linear map. ARM requires that all
> virtual mappings of a page have the same cache attributes. With GEM
> shmem backed buffers, I can't control page allocation. The TTM DMA
> pool stuff looks also interesting in this regard, since I can avoid
> the need to do cache invalidate operations if I know the previous use
> of a page was not for a cached buffer.
>
> 2) well, in some cases we need pages allocated in low 32bits..
> although this applies to some x86 drivers too, and there is a proposal
> of how to handle this issue.
>
> Previously, since omapdrm is a UMA driver, I'd not looked too closely
> at TTM.. but maybe I need to revisit. Is there any good example of a
> UMA driver using TTM? (Or even some documentation.. although I'm
> happy with a good example.)
Radeon IGP chipsets and APUs are UMA. Programming-wise, they still
have the concept of vram, but rather than having dedicated vram, they
utilize a chunk of contiguous system memory stolen from the top of
system memory by the bios at boot time. In addition to "vram" they
have a gart mechanism that lets you map cached or uncached system
pages into the GPU's address space.
Alex
>
> Just starting to look at the ttm code.. can you map back from 'struct
> ttm_tt' to the GEM object? I'm wondering how the populate callback
> can know the cache attributes that the buffer is created with..
> (maybe a dumb question, I'm a newbie when it comes to the TTM code..)
>
> BR,
> -R
>
>> Most intrusive change, is the fact that we now only fully
>> populate an object this simplify some of code designed around
>> the page fault design.
>>
>> Signed-off-by: Jerome Glisse <jglisse at redhat.com>
>> ---
>> drivers/gpu/drm/nouveau/nouveau_bo.c | 3 +
>> drivers/gpu/drm/radeon/radeon_ttm.c | 2 +
>> drivers/gpu/drm/ttm/ttm_bo_util.c | 31 ++++++-----
>> drivers/gpu/drm/ttm/ttm_bo_vm.c | 13 ++--
>> drivers/gpu/drm/ttm/ttm_page_alloc.c | 42 ++++++++++++++
>> drivers/gpu/drm/ttm/ttm_tt.c | 97 +++----------------------------
>> drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c | 3 +
>> include/drm/ttm/ttm_bo_driver.h | 41 ++++++++------
>> include/drm/ttm/ttm_page_alloc.h | 18 ++++++
>> 9 files changed, 125 insertions(+), 125 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
>> index b060fa4..7e5ca3f 100644
>> --- a/drivers/gpu/drm/nouveau/nouveau_bo.c
>> +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
>> @@ -28,6 +28,7 @@
>> */
>>
>> #include "drmP.h"
>> +#include "ttm/ttm_page_alloc.h"
>>
>> #include "nouveau_drm.h"
>> #include "nouveau_drv.h"
>> @@ -1050,6 +1051,8 @@ nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence)
>>
>> struct ttm_bo_driver nouveau_bo_driver = {
>> .ttm_tt_create = &nouveau_ttm_tt_create,
>> + .ttm_tt_populate = &ttm_page_alloc_ttm_tt_populate,
>> + .ttm_tt_unpopulate = &ttm_page_alloc_ttm_tt_unpopulate,
>> .invalidate_caches = nouveau_bo_invalidate_caches,
>> .init_mem_type = nouveau_bo_init_mem_type,
>> .evict_flags = nouveau_bo_evict_flags,
>> diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
>> index 53ff62b..490afce 100644
>> --- a/drivers/gpu/drm/radeon/radeon_ttm.c
>> +++ b/drivers/gpu/drm/radeon/radeon_ttm.c
>> @@ -584,6 +584,8 @@ struct ttm_tt *radeon_ttm_tt_create(struct ttm_bo_device *bdev,
>>
>> static struct ttm_bo_driver radeon_bo_driver = {
>> .ttm_tt_create = &radeon_ttm_tt_create,
>> + .ttm_tt_populate = &ttm_page_alloc_ttm_tt_populate,
>> + .ttm_tt_unpopulate = &ttm_page_alloc_ttm_tt_unpopulate,
>> .invalidate_caches = &radeon_invalidate_caches,
>> .init_mem_type = &radeon_init_mem_type,
>> .evict_flags = &radeon_evict_flags,
>> diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
>> index 082fcae..60f204d 100644
>> --- a/drivers/gpu/drm/ttm/ttm_bo_util.c
>> +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
>> @@ -244,7 +244,7 @@ static int ttm_copy_io_ttm_page(struct ttm_tt *ttm, void *src,
>> unsigned long page,
>> pgprot_t prot)
>> {
>> - struct page *d = ttm_tt_get_page(ttm, page);
>> + struct page *d = ttm->pages[page];
>> void *dst;
>>
>> if (!d)
>> @@ -281,7 +281,7 @@ static int ttm_copy_ttm_io_page(struct ttm_tt *ttm, void *dst,
>> unsigned long page,
>> pgprot_t prot)
>> {
>> - struct page *s = ttm_tt_get_page(ttm, page);
>> + struct page *s = ttm->pages[page];
>> void *src;
>>
>> if (!s)
>> @@ -342,6 +342,12 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
>> if (old_iomap == NULL && ttm == NULL)
>> goto out2;
>>
>> + if (ttm->state == tt_unpopulated) {
>> + ret = ttm->bdev->driver->ttm_tt_populate(ttm);
>> + if (ret)
>> + goto out1;
>> + }
>> +
>> add = 0;
>> dir = 1;
>>
>> @@ -502,10 +508,16 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo,
>> {
>> struct ttm_mem_reg *mem = &bo->mem; pgprot_t prot;
>> struct ttm_tt *ttm = bo->ttm;
>> - struct page *d;
>> - int i;
>> + int ret;
>>
>> BUG_ON(!ttm);
>> +
>> + if (ttm->state == tt_unpopulated) {
>> + ret = ttm->bdev->driver->ttm_tt_populate(ttm);
>> + if (ret)
>> + return ret;
>> + }
>> +
>> if (num_pages == 1 && (mem->placement & TTM_PL_FLAG_CACHED)) {
>> /*
>> * We're mapping a single page, and the desired
>> @@ -513,18 +525,9 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo,
>> */
>>
>> map->bo_kmap_type = ttm_bo_map_kmap;
>> - map->page = ttm_tt_get_page(ttm, start_page);
>> + map->page = ttm->pages[start_page];
>> map->virtual = kmap(map->page);
>> } else {
>> - /*
>> - * Populate the part we're mapping;
>> - */
>> - for (i = start_page; i < start_page + num_pages; ++i) {
>> - d = ttm_tt_get_page(ttm, i);
>> - if (!d)
>> - return -ENOMEM;
>> - }
>> -
>> /*
>> * We need to use vmap to get the desired page protection
>> * or to make the buffer object look contiguous.
>> diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c
>> index 221b924..bc1d751 100644
>> --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c
>> +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c
>> @@ -174,18 +174,19 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
>> vma->vm_page_prot = (bo->mem.placement & TTM_PL_FLAG_CACHED) ?
>> vm_get_page_prot(vma->vm_flags) :
>> ttm_io_prot(bo->mem.placement, vma->vm_page_prot);
>> - }
>>
>> - /*
>> - * Speculatively prefault a number of pages. Only error on
>> - * first page.
>> - */
>> + /* Allocate all page at once, most common usage */
>> + if (ttm->bdev->driver->ttm_tt_populate(ttm)) {
>> + retval = VM_FAULT_OOM;
>> + goto out_io_unlock;
>> + }
>> + }
>>
>> for (i = 0; i < TTM_BO_VM_NUM_PREFAULT; ++i) {
>> if (bo->mem.bus.is_iomem)
>> pfn = ((bo->mem.bus.base + bo->mem.bus.offset) >> PAGE_SHIFT) + page_offset;
>> else {
>> - page = ttm_tt_get_page(ttm, page_offset);
>> + page = ttm->pages[page_offset];
>> if (unlikely(!page && i == 0)) {
>> retval = VM_FAULT_OOM;
>> goto out_io_unlock;
>> diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c
>> index c4f18b9..5b5b1e0 100644
>> --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
>> +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
>> @@ -852,6 +852,48 @@ void ttm_page_alloc_fini(void)
>> _manager = NULL;
>> }
>>
>> +int ttm_page_alloc_ttm_tt_populate(struct ttm_tt *ttm)
>> +{
>> + struct ttm_mem_global *mem_glob = ttm->glob->mem_glob;
>> + int ret;
>> +
>> + if (ttm->state != tt_unpopulated)
>> + return 0;
>> +
>> + if (unlikely(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)) {
>> + ret = ttm_tt_swapin(ttm);
>> + if (unlikely(ret != 0))
>> + return ret;
>> + }
>> +
>> + ret = ttm_get_pages(ttm->pages, ttm->num_pages, ttm->page_flags,
>> + ttm->caching_state, ttm->dma_address);
>> + if (ret != 0)
>> + return -ENOMEM;
>> + ret = ttm_mem_global_alloc_pages(mem_glob, ttm->pages,
>> + ttm->num_pages, false, false);
>> + if (unlikely(ret != 0)) {
>> + ttm_put_pages(ttm->pages, ttm->num_pages, ttm->page_flags,
>> + ttm->caching_state, ttm->dma_address);
>> + return -ENOMEM;
>> + }
>> +
>> + ttm->state = tt_unbound;
>> + return 0;
>> +}
>> +EXPORT_SYMBOL(ttm_page_alloc_ttm_tt_populate);
>> +
>> +void ttm_page_alloc_ttm_tt_unpopulate(struct ttm_tt *ttm)
>> +{
>> + struct ttm_mem_global *glob = ttm->glob->mem_glob;
>> +
>> + ttm_mem_global_free_pages(glob, ttm->pages, ttm->num_pages);
>> + ttm_put_pages(ttm->pages, ttm->num_pages, ttm->page_flags,
>> + ttm->caching_state, ttm->dma_address);
>> + ttm->state = tt_unpopulated;
>> +}
>> +EXPORT_SYMBOL(ttm_page_alloc_ttm_tt_unpopulate);
>> +
>> int ttm_page_alloc_debugfs(struct seq_file *m, void *data)
>> {
>> struct ttm_page_pool *p;
>> diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
>> index b55e132..07e86c4 100644
>> --- a/drivers/gpu/drm/ttm/ttm_tt.c
>> +++ b/drivers/gpu/drm/ttm/ttm_tt.c
>> @@ -42,8 +42,6 @@
>> #include "ttm/ttm_placement.h"
>> #include "ttm/ttm_page_alloc.h"
>>
>> -static int ttm_tt_swapin(struct ttm_tt *ttm);
>> -
>> /**
>> * Allocates storage for pointers to the pages that back the ttm.
>> */
>> @@ -62,75 +60,6 @@ static void ttm_tt_free_page_directory(struct ttm_tt *ttm)
>> ttm->dma_address = NULL;
>> }
>>
>> -static struct page *__ttm_tt_get_page(struct ttm_tt *ttm, int index)
>> -{
>> - struct page *p;
>> - struct ttm_mem_global *mem_glob = ttm->glob->mem_glob;
>> - int ret;
>> -
>> - if (NULL == (p = ttm->pages[index])) {
>> -
>> - ret = ttm_get_pages(&ttm->pages[index], 1, ttm->page_flags,
>> - ttm->caching_state,
>> - &ttm->dma_address[index]);
>> - if (ret != 0)
>> - return NULL;
>> -
>> - ret = ttm_mem_global_alloc_pages(mem_glob, &ttm->pages[index],
>> - 1, false, false);
>> - if (unlikely(ret != 0))
>> - goto out_err;
>> - }
>> - return p;
>> -out_err:
>> - ttm_put_pages(&ttm->pages[index], 1, ttm->page_flags,
>> - ttm->caching_state, &ttm->dma_address[index]);
>> - return NULL;
>> -}
>> -
>> -struct page *ttm_tt_get_page(struct ttm_tt *ttm, int index)
>> -{
>> - int ret;
>> -
>> - if (unlikely(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)) {
>> - ret = ttm_tt_swapin(ttm);
>> - if (unlikely(ret != 0))
>> - return NULL;
>> - }
>> - return __ttm_tt_get_page(ttm, index);
>> -}
>> -
>> -int ttm_tt_populate(struct ttm_tt *ttm)
>> -{
>> - struct ttm_mem_global *mem_glob = ttm->glob->mem_glob;
>> - int ret;
>> -
>> - if (ttm->state != tt_unpopulated)
>> - return 0;
>> -
>> - if (unlikely(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)) {
>> - ret = ttm_tt_swapin(ttm);
>> - if (unlikely(ret != 0))
>> - return ret;
>> - }
>> -
>> - ret = ttm_get_pages(ttm->pages, ttm->num_pages, ttm->page_flags,
>> - ttm->caching_state, ttm->dma_address);
>> - if (ret != 0)
>> - return -ENOMEM;
>> - ret = ttm_mem_global_alloc_pages(mem_glob, ttm->pages,
>> - ttm->num_pages, false, false);
>> - if (unlikely(ret != 0)) {
>> - ttm_put_pages(ttm->pages, ttm->num_pages, ttm->page_flags,
>> - ttm->caching_state, ttm->dma_address);
>> - return -ENOMEM;
>> - }
>> -
>> - ttm->state = tt_unbound;
>> - return 0;
>> -}
>> -EXPORT_SYMBOL(ttm_tt_populate);
>> -
>> #ifdef CONFIG_X86
>> static inline int ttm_tt_set_page_caching(struct page *p,
>> enum ttm_caching_state c_old,
>> @@ -232,23 +161,13 @@ int ttm_tt_set_placement_caching(struct ttm_tt *ttm, uint32_t placement)
>> }
>> EXPORT_SYMBOL(ttm_tt_set_placement_caching);
>>
>> -static void ttm_tt_free_alloced_pages(struct ttm_tt *ttm)
>> -{
>> - struct ttm_mem_global *glob = ttm->glob->mem_glob;
>> -
>> - ttm_mem_global_free_pages(glob, ttm->pages, ttm->num_pages);
>> - ttm_put_pages(ttm->pages, ttm->num_pages, ttm->page_flags,
>> - ttm->caching_state, ttm->dma_address);
>> - ttm->state = tt_unpopulated;
>> -}
>> -
>> void ttm_tt_destroy(struct ttm_tt *ttm)
>> {
>> if (unlikely(ttm == NULL))
>> return;
>>
>> if (likely(ttm->pages != NULL)) {
>> - ttm_tt_free_alloced_pages(ttm);
>> + ttm->bdev->driver->ttm_tt_unpopulate(ttm);
>> ttm_tt_free_page_directory(ttm);
>> }
>>
>> @@ -303,7 +222,7 @@ int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem)
>> if (ttm->state == tt_bound)
>> return 0;
>>
>> - ret = ttm_tt_populate(ttm);
>> + ret = ttm->bdev->driver->ttm_tt_populate(ttm);
>> if (ret)
>> return ret;
>>
>> @@ -317,7 +236,7 @@ int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem)
>> }
>> EXPORT_SYMBOL(ttm_tt_bind);
>>
>> -static int ttm_tt_swapin(struct ttm_tt *ttm)
>> +int ttm_tt_swapin(struct ttm_tt *ttm)
>> {
>> struct address_space *swap_space;
>> struct file *swap_storage;
>> @@ -331,6 +250,10 @@ static int ttm_tt_swapin(struct ttm_tt *ttm)
>> swap_storage = ttm->swap_storage;
>> BUG_ON(swap_storage == NULL);
>>
>> + ret = ttm->bdev->driver->ttm_tt_populate(ttm);
>> + if (ret)
>> + return ret;
>> +
>> swap_space = swap_storage->f_path.dentry->d_inode->i_mapping;
>>
>> for (i = 0; i < ttm->num_pages; ++i) {
>> @@ -339,7 +262,7 @@ static int ttm_tt_swapin(struct ttm_tt *ttm)
>> ret = PTR_ERR(from_page);
>> goto out_err;
>> }
>> - to_page = __ttm_tt_get_page(ttm, i);
>> + to_page = ttm->pages[i];
>> if (unlikely(to_page == NULL))
>> goto out_err;
>>
>> @@ -360,7 +283,7 @@ static int ttm_tt_swapin(struct ttm_tt *ttm)
>>
>> return 0;
>> out_err:
>> - ttm_tt_free_alloced_pages(ttm);
>> + ttm->bdev->driver->ttm_tt_unpopulate(ttm);
>> return ret;
>> }
>>
>> @@ -412,7 +335,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
>> page_cache_release(to_page);
>> }
>>
>> - ttm_tt_free_alloced_pages(ttm);
>> + ttm->bdev->driver->ttm_tt_unpopulate(ttm);
>> ttm->swap_storage = swap_storage;
>> ttm->page_flags |= TTM_PAGE_FLAG_SWAPPED;
>> if (persistent_swap_storage)
>> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
>> index cc72435..383993b 100644
>> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
>> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
>> @@ -28,6 +28,7 @@
>> #include "vmwgfx_drv.h"
>> #include "ttm/ttm_bo_driver.h"
>> #include "ttm/ttm_placement.h"
>> +#include "ttm/ttm_page_alloc.h"
>>
>> static uint32_t vram_placement_flags = TTM_PL_FLAG_VRAM |
>> TTM_PL_FLAG_CACHED;
>> @@ -334,6 +335,8 @@ static int vmw_sync_obj_wait(void *sync_obj, void *sync_arg,
>>
>> struct ttm_bo_driver vmw_bo_driver = {
>> .ttm_tt_create = &vmw_ttm_tt_create,
>> + .ttm_tt_populate = &ttm_page_alloc_ttm_tt_populate,
>> + .ttm_tt_unpopulate = &ttm_page_alloc_ttm_tt_unpopulate,
>> .invalidate_caches = vmw_invalidate_caches,
>> .init_mem_type = vmw_init_mem_type,
>> .evict_flags = vmw_evict_flags,
>> diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
>> index 6b8c5cd..ae06e42 100644
>> --- a/include/drm/ttm/ttm_bo_driver.h
>> +++ b/include/drm/ttm/ttm_bo_driver.h
>> @@ -319,6 +319,26 @@ struct ttm_bo_driver {
>> struct page *dummy_read_page);
>>
>> /**
>> + * ttm_tt_populate
>> + *
>> + * @ttm: The struct ttm_tt to contain the backing pages.
>> + *
>> + * Allocate all backing pages
>> + * Returns:
>> + * -ENOMEM: Out of memory.
>> + */
>> + int (*ttm_tt_populate)(struct ttm_tt *ttm);
>> +
>> + /**
>> + * ttm_tt_unpopulate
>> + *
>> + * @ttm: The struct ttm_tt to contain the backing pages.
>> + *
>> + * Free all backing page
>> + */
>> + void (*ttm_tt_unpopulate)(struct ttm_tt *ttm);
>> +
>> + /**
>> * struct ttm_bo_driver member invalidate_caches
>> *
>> * @bdev: the buffer object device.
>> @@ -585,15 +605,6 @@ extern int ttm_tt_init(struct ttm_tt *ttm, struct ttm_bo_device *bdev,
>> extern int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem);
>>
>> /**
>> - * ttm_tt_populate:
>> - *
>> - * @ttm: The struct ttm_tt to contain the backing pages.
>> - *
>> - * Add backing pages to all of @ttm
>> - */
>> -extern int ttm_tt_populate(struct ttm_tt *ttm);
>> -
>> -/**
>> * ttm_ttm_destroy:
>> *
>> * @ttm: The struct ttm_tt.
>> @@ -612,19 +623,13 @@ extern void ttm_tt_destroy(struct ttm_tt *ttm);
>> extern void ttm_tt_unbind(struct ttm_tt *ttm);
>>
>> /**
>> - * ttm_ttm_destroy:
>> + * ttm_tt_swapin:
>> *
>> * @ttm: The struct ttm_tt.
>> - * @index: Index of the desired page.
>> *
>> - * Return a pointer to the struct page backing @ttm at page
>> - * index @index. If the page is unpopulated, one will be allocated to
>> - * populate that index.
>> - *
>> - * Returns:
>> - * NULL on OOM.
>> + * Swap in a previously swap out ttm_tt.
>> */
>> -extern struct page *ttm_tt_get_page(struct ttm_tt *ttm, int index);
>> +extern int ttm_tt_swapin(struct ttm_tt *ttm);
>>
>> /**
>> * ttm_tt_cache_flush:
>> diff --git a/include/drm/ttm/ttm_page_alloc.h b/include/drm/ttm/ttm_page_alloc.h
>> index fffb3bd..18a2d6b 100644
>> --- a/include/drm/ttm/ttm_page_alloc.h
>> +++ b/include/drm/ttm/ttm_page_alloc.h
>> @@ -67,6 +67,24 @@ int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages);
>> void ttm_page_alloc_fini(void);
>>
>> /**
>> + * ttm_page_alloc_ttm_tt_populate:
>> + *
>> + * @ttm: The struct ttm_tt to contain the backing pages.
>> + *
>> + * Add backing pages to all of @ttm
>> + */
>> +extern int ttm_page_alloc_ttm_tt_populate(struct ttm_tt *ttm);
>> +
>> +/**
>> + * ttm_page_alloc_ttm_tt_unpopulate:
>> + *
>> + * @ttm: The struct ttm_tt which to free backing pages.
>> + *
>> + * Free all pages of @ttm
>> + */
>> +extern void ttm_page_alloc_ttm_tt_unpopulate(struct ttm_tt *ttm);
>> +
>> +/**
>> * Output the state of pools to debugfs file
>> */
>> extern int ttm_page_alloc_debugfs(struct seq_file *m, void *data);
>> --
>> 1.7.7.1
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel at lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>
More information about the dri-devel
mailing list