[PATCH 07/11] drm/ttm: merge ttm_backend and ttm_tt

Konrad Rzeszutek Wilk konrad.wilk at oracle.com
Mon Nov 7 06:39:01 PST 2011


On Thu, Nov 03, 2011 at 07:39:11PM -0400, j.glisse at gmail.com wrote:
> From: Jerome Glisse <jglisse at redhat.com>
> 
> ttm_backend will exist only and only with a ttm_tt, and ttm_tt
> will be of interesting use only when bind to a backend. Thus to
> avoid code & data duplication btw the two merge them.

Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk at oracle.com>
> 
> Signed-off-by: Jerome Glisse <jglisse at redhat.com>
> ---
>  drivers/gpu/drm/nouveau/nouveau_bo.c    |   14 ++-
>  drivers/gpu/drm/nouveau/nouveau_drv.h   |    5 +-
>  drivers/gpu/drm/nouveau/nouveau_sgdma.c |  188 ++++++++++++--------------
>  drivers/gpu/drm/radeon/radeon_ttm.c     |  222 ++++++++++++-------------------
>  drivers/gpu/drm/ttm/ttm_agp_backend.c   |   88 +++++--------
>  drivers/gpu/drm/ttm/ttm_bo.c            |    9 +-
>  drivers/gpu/drm/ttm/ttm_tt.c            |   59 ++-------
>  drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c  |   66 +++------
>  include/drm/ttm/ttm_bo_driver.h         |  104 ++++++---------
>  9 files changed, 295 insertions(+), 460 deletions(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
> index 7226f41..b060fa4 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_bo.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
> @@ -343,8 +343,10 @@ nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val)
>  		*mem = val;
>  }
>  
> -static struct ttm_backend *
> -nouveau_bo_create_ttm_backend_entry(struct ttm_bo_device *bdev)
> +static struct ttm_tt *
> +nouveau_ttm_tt_create(struct ttm_bo_device *bdev,
> +		      unsigned long size, uint32_t page_flags,
> +		      struct page *dummy_read_page)
>  {
>  	struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev);
>  	struct drm_device *dev = dev_priv->dev;
> @@ -352,11 +354,13 @@ nouveau_bo_create_ttm_backend_entry(struct ttm_bo_device *bdev)
>  	switch (dev_priv->gart_info.type) {
>  #if __OS_HAS_AGP
>  	case NOUVEAU_GART_AGP:
> -		return ttm_agp_backend_init(bdev, dev->agp->bridge);
> +		return ttm_agp_tt_create(bdev, dev->agp->bridge,
> +					 size, page_flags, dummy_read_page);
>  #endif
>  	case NOUVEAU_GART_PDMA:
>  	case NOUVEAU_GART_HW:
> -		return nouveau_sgdma_init_ttm(dev);
> +		return nouveau_sgdma_create_ttm(bdev, size, page_flags,
> +						dummy_read_page);
>  	default:
>  		NV_ERROR(dev, "Unknown GART type %d\n",
>  			 dev_priv->gart_info.type);
> @@ -1045,7 +1049,7 @@ nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence)
>  }
>  
>  struct ttm_bo_driver nouveau_bo_driver = {
> -	.create_ttm_backend_entry = nouveau_bo_create_ttm_backend_entry,
> +	.ttm_tt_create = &nouveau_ttm_tt_create,
>  	.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/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
> index 29837da..0c53e39 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_drv.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
> @@ -1000,7 +1000,10 @@ extern int nouveau_sgdma_init(struct drm_device *);
>  extern void nouveau_sgdma_takedown(struct drm_device *);
>  extern uint32_t nouveau_sgdma_get_physical(struct drm_device *,
>  					   uint32_t offset);
> -extern struct ttm_backend *nouveau_sgdma_init_ttm(struct drm_device *);
> +extern struct ttm_tt *nouveau_sgdma_create_ttm(struct ttm_bo_device *bdev,
> +					       unsigned long size,
> +					       uint32_t page_flags,
> +					       struct page *dummy_read_page);
>  
>  /* nouveau_debugfs.c */
>  #if defined(CONFIG_DRM_NOUVEAU_DEBUG)
> diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
> index b75258a..bc2ab90 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
> @@ -8,44 +8,23 @@
>  #define NV_CTXDMA_PAGE_MASK  (NV_CTXDMA_PAGE_SIZE - 1)
>  
>  struct nouveau_sgdma_be {
> -	struct ttm_backend backend;
> +	struct ttm_tt ttm;
>  	struct drm_device *dev;
> -
> -	dma_addr_t *pages;
> -	unsigned nr_pages;
> -	bool unmap_pages;
> -
>  	u64 offset;
> -	bool bound;
>  };
>  
>  static int
> -nouveau_sgdma_populate(struct ttm_backend *be, unsigned long num_pages,
> -		       struct page **pages, struct page *dummy_read_page,
> -		       dma_addr_t *dma_addrs)
> +nouveau_sgdma_dma_map(struct ttm_tt *ttm)
>  {
> -	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
> +	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
>  	struct drm_device *dev = nvbe->dev;
>  	int i;
>  
> -	NV_DEBUG(nvbe->dev, "num_pages = %ld\n", num_pages);
> -
> -	nvbe->pages = dma_addrs;
> -	nvbe->nr_pages = num_pages;
> -	nvbe->unmap_pages = true;
> -
> -	/* this code path isn't called and is incorrect anyways */
> -	if (0) { /* dma_addrs[0] != DMA_ERROR_CODE) { */
> -		nvbe->unmap_pages = false;
> -		return 0;
> -	}
> -
> -	for (i = 0; i < num_pages; i++) {
> -		nvbe->pages[i] = pci_map_page(dev->pdev, pages[i], 0,
> -					      PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
> -		if (pci_dma_mapping_error(dev->pdev, nvbe->pages[i])) {
> -			nvbe->nr_pages = --i;
> -			be->func->clear(be);
> +	for (i = 0; i < ttm->num_pages; i++) {
> +		ttm->dma_address[i] = pci_map_page(dev->pdev, ttm->pages[i],
> +						   0, PAGE_SIZE,
> +						   PCI_DMA_BIDIRECTIONAL);
> +		if (pci_dma_mapping_error(dev->pdev, ttm->dma_address[i])) {
>  			return -EFAULT;
>  		}
>  	}
> @@ -54,53 +33,52 @@ nouveau_sgdma_populate(struct ttm_backend *be, unsigned long num_pages,
>  }
>  
>  static void
> -nouveau_sgdma_clear(struct ttm_backend *be)
> +nouveau_sgdma_dma_unmap(struct ttm_tt *ttm)
>  {
> -	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
> +	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
>  	struct drm_device *dev = nvbe->dev;
> +	int i;
>  
> -	if (nvbe->bound)
> -		be->func->unbind(be);
> -
> -	if (nvbe->unmap_pages) {
> -		while (nvbe->nr_pages--) {
> -			pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages],
> +	for (i = 0; i < ttm->num_pages; i++) {
> +		if (ttm->dma_address[i]) {
> +			pci_unmap_page(dev->pdev, ttm->dma_address[i],
>  				       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
>  		}
> +		ttm->dma_address[i] = 0;
>  	}
>  }
>  
>  static void
> -nouveau_sgdma_destroy(struct ttm_backend *be)
> +nouveau_sgdma_destroy(struct ttm_tt *ttm)
>  {
> -	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
> +	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
>  
> -	if (be) {
> +	if (ttm) {
>  		NV_DEBUG(nvbe->dev, "\n");
> -
> -		if (nvbe) {
> -			if (nvbe->pages)
> -				be->func->clear(be);
> -			kfree(nvbe);
> -		}
> +		kfree(nvbe);
>  	}
>  }
>  
>  static int
> -nv04_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
> +nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem)
>  {
> -	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
> +	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
>  	struct drm_device *dev = nvbe->dev;
>  	struct drm_nouveau_private *dev_priv = dev->dev_private;
>  	struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma;
>  	unsigned i, j, pte;
> +	int r;
>  
>  	NV_DEBUG(dev, "pg=0x%lx\n", mem->start);
> +	r = nouveau_sgdma_dma_map(ttm);
> +	if (r) {
> +		return r;
> +	}
>  
>  	nvbe->offset = mem->start << PAGE_SHIFT;
>  	pte = (nvbe->offset >> NV_CTXDMA_PAGE_SHIFT) + 2;
> -	for (i = 0; i < nvbe->nr_pages; i++) {
> -		dma_addr_t dma_offset = nvbe->pages[i];
> +	for (i = 0; i < ttm->num_pages; i++) {
> +		dma_addr_t dma_offset = ttm->dma_address[i];
>  		uint32_t offset_l = lower_32_bits(dma_offset);
>  
>  		for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++, pte++) {
> @@ -109,14 +87,13 @@ nv04_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
>  		}
>  	}
>  
> -	nvbe->bound = true;
>  	return 0;
>  }
>  
>  static int
> -nv04_sgdma_unbind(struct ttm_backend *be)
> +nv04_sgdma_unbind(struct ttm_tt *ttm)
>  {
> -	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
> +	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
>  	struct drm_device *dev = nvbe->dev;
>  	struct drm_nouveau_private *dev_priv = dev->dev_private;
>  	struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma;
> @@ -124,22 +101,20 @@ nv04_sgdma_unbind(struct ttm_backend *be)
>  
>  	NV_DEBUG(dev, "\n");
>  
> -	if (!nvbe->bound)
> +	if (ttm->state != tt_bound)
>  		return 0;
>  
>  	pte = (nvbe->offset >> NV_CTXDMA_PAGE_SHIFT) + 2;
> -	for (i = 0; i < nvbe->nr_pages; i++) {
> +	for (i = 0; i < ttm->num_pages; i++) {
>  		for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++, pte++)
>  			nv_wo32(gpuobj, (pte * 4) + 0, 0x00000000);
>  	}
>  
> -	nvbe->bound = false;
> +	nouveau_sgdma_dma_unmap(ttm);
>  	return 0;
>  }
>  
>  static struct ttm_backend_func nv04_sgdma_backend = {
> -	.populate		= nouveau_sgdma_populate,
> -	.clear			= nouveau_sgdma_clear,
>  	.bind			= nv04_sgdma_bind,
>  	.unbind			= nv04_sgdma_unbind,
>  	.destroy		= nouveau_sgdma_destroy
> @@ -158,16 +133,21 @@ nv41_sgdma_flush(struct nouveau_sgdma_be *nvbe)
>  }
>  
>  static int
> -nv41_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
> +nv41_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem)
>  {
> -	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
> +	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
>  	struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private;
>  	struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma;
> -	dma_addr_t *list = nvbe->pages;
> +	dma_addr_t *list = ttm->dma_address;
>  	u32 pte = mem->start << 2;
> -	u32 cnt = nvbe->nr_pages;
> +	u32 cnt = ttm->num_pages;
> +	int r;
>  
>  	nvbe->offset = mem->start << PAGE_SHIFT;
> +	r = nouveau_sgdma_dma_map(ttm);
> +	if (r) {
> +		return r;
> +	}
>  
>  	while (cnt--) {
>  		nv_wo32(pgt, pte, (*list++ >> 7) | 1);
> @@ -175,18 +155,17 @@ nv41_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
>  	}
>  
>  	nv41_sgdma_flush(nvbe);
> -	nvbe->bound = true;
>  	return 0;
>  }
>  
>  static int
> -nv41_sgdma_unbind(struct ttm_backend *be)
> +nv41_sgdma_unbind(struct ttm_tt *ttm)
>  {
> -	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
> +	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
>  	struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private;
>  	struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma;
>  	u32 pte = (nvbe->offset >> 12) << 2;
> -	u32 cnt = nvbe->nr_pages;
> +	u32 cnt = ttm->num_pages;
>  
>  	while (cnt--) {
>  		nv_wo32(pgt, pte, 0x00000000);
> @@ -194,24 +173,23 @@ nv41_sgdma_unbind(struct ttm_backend *be)
>  	}
>  
>  	nv41_sgdma_flush(nvbe);
> -	nvbe->bound = false;
> +	nouveau_sgdma_dma_unmap(ttm);
>  	return 0;
>  }
>  
>  static struct ttm_backend_func nv41_sgdma_backend = {
> -	.populate		= nouveau_sgdma_populate,
> -	.clear			= nouveau_sgdma_clear,
>  	.bind			= nv41_sgdma_bind,
>  	.unbind			= nv41_sgdma_unbind,
>  	.destroy		= nouveau_sgdma_destroy
>  };
>  
>  static void
> -nv44_sgdma_flush(struct nouveau_sgdma_be *nvbe)
> +nv44_sgdma_flush(struct ttm_tt *ttm)
>  {
> +	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
>  	struct drm_device *dev = nvbe->dev;
>  
> -	nv_wr32(dev, 0x100814, (nvbe->nr_pages - 1) << 12);
> +	nv_wr32(dev, 0x100814, (ttm->num_pages - 1) << 12);
>  	nv_wr32(dev, 0x100808, nvbe->offset | 0x20);
>  	if (!nv_wait(dev, 0x100808, 0x00000001, 0x00000001))
>  		NV_ERROR(dev, "gart flush timeout: 0x%08x\n",
> @@ -270,17 +248,21 @@ nv44_sgdma_fill(struct nouveau_gpuobj *pgt, dma_addr_t *list, u32 base, u32 cnt)
>  }
>  
>  static int
> -nv44_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
> +nv44_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem)
>  {
> -	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
> +	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
>  	struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private;
>  	struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma;
> -	dma_addr_t *list = nvbe->pages;
> +	dma_addr_t *list = ttm->dma_address;
>  	u32 pte = mem->start << 2, tmp[4];
> -	u32 cnt = nvbe->nr_pages;
> -	int i;
> +	u32 cnt = ttm->num_pages;
> +	int i, r;
>  
>  	nvbe->offset = mem->start << PAGE_SHIFT;
> +	r = nouveau_sgdma_dma_map(ttm);
> +	if (r) {
> +		return r;
> +	}
>  
>  	if (pte & 0x0000000c) {
>  		u32  max = 4 - ((pte >> 2) & 0x3);
> @@ -305,19 +287,18 @@ nv44_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
>  	if (cnt)
>  		nv44_sgdma_fill(pgt, list, pte, cnt);
>  
> -	nv44_sgdma_flush(nvbe);
> -	nvbe->bound = true;
> +	nv44_sgdma_flush(ttm);
>  	return 0;
>  }
>  
>  static int
> -nv44_sgdma_unbind(struct ttm_backend *be)
> +nv44_sgdma_unbind(struct ttm_tt *ttm)
>  {
> -	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
> +	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
>  	struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private;
>  	struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma;
>  	u32 pte = (nvbe->offset >> 12) << 2;
> -	u32 cnt = nvbe->nr_pages;
> +	u32 cnt = ttm->num_pages;
>  
>  	if (pte & 0x0000000c) {
>  		u32  max = 4 - ((pte >> 2) & 0x3);
> @@ -339,55 +320,53 @@ nv44_sgdma_unbind(struct ttm_backend *be)
>  	if (cnt)
>  		nv44_sgdma_fill(pgt, NULL, pte, cnt);
>  
> -	nv44_sgdma_flush(nvbe);
> -	nvbe->bound = false;
> +	nv44_sgdma_flush(ttm);
> +	nouveau_sgdma_dma_unmap(ttm);
>  	return 0;
>  }
>  
>  static struct ttm_backend_func nv44_sgdma_backend = {
> -	.populate		= nouveau_sgdma_populate,
> -	.clear			= nouveau_sgdma_clear,
>  	.bind			= nv44_sgdma_bind,
>  	.unbind			= nv44_sgdma_unbind,
>  	.destroy		= nouveau_sgdma_destroy
>  };
>  
>  static int
> -nv50_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
> +nv50_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem)
>  {
> -	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
>  	struct nouveau_mem *node = mem->mm_node;
> +	int r;
> +
>  	/* noop: bound in move_notify() */
> -	node->pages = nvbe->pages;
> -	nvbe->pages = (dma_addr_t *)node;
> -	nvbe->bound = true;
> +	r = nouveau_sgdma_dma_map(ttm);
> +	if (r) {
> +		return r;
> +	}
> +	node->pages = ttm->dma_address;
>  	return 0;
>  }
>  
>  static int
> -nv50_sgdma_unbind(struct ttm_backend *be)
> +nv50_sgdma_unbind(struct ttm_tt *ttm)
>  {
> -	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
> -	struct nouveau_mem *node = (struct nouveau_mem *)nvbe->pages;
>  	/* noop: unbound in move_notify() */
> -	nvbe->pages = node->pages;
> -	node->pages = NULL;
> -	nvbe->bound = false;
> +	nouveau_sgdma_dma_unmap(ttm);
>  	return 0;
>  }
>  
>  static struct ttm_backend_func nv50_sgdma_backend = {
> -	.populate		= nouveau_sgdma_populate,
> -	.clear			= nouveau_sgdma_clear,
>  	.bind			= nv50_sgdma_bind,
>  	.unbind			= nv50_sgdma_unbind,
>  	.destroy		= nouveau_sgdma_destroy
>  };
>  
> -struct ttm_backend *
> -nouveau_sgdma_init_ttm(struct drm_device *dev)
> +struct ttm_tt *
> +nouveau_sgdma_create_ttm(struct ttm_bo_device *bdev,
> +			 unsigned long size, uint32_t page_flags,
> +			 struct page *dummy_read_page)
>  {
> -	struct drm_nouveau_private *dev_priv = dev->dev_private;
> +	struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev);
> +	struct drm_device *dev = dev_priv->dev;
>  	struct nouveau_sgdma_be *nvbe;
>  
>  	nvbe = kzalloc(sizeof(*nvbe), GFP_KERNEL);
> @@ -395,9 +374,12 @@ nouveau_sgdma_init_ttm(struct drm_device *dev)
>  		return NULL;
>  
>  	nvbe->dev = dev;
> +	nvbe->ttm.func = dev_priv->gart_info.func;
>  
> -	nvbe->backend.func = dev_priv->gart_info.func;
> -	return &nvbe->backend;
> +	if (ttm_tt_init(&nvbe->ttm, bdev, size, page_flags, dummy_read_page)) {
> +		return NULL;
> +	}
> +	return &nvbe->ttm;
>  }
>  
>  int
> diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
> index 97c76ae..53ff62b 100644
> --- a/drivers/gpu/drm/radeon/radeon_ttm.c
> +++ b/drivers/gpu/drm/radeon/radeon_ttm.c
> @@ -114,24 +114,6 @@ static void radeon_ttm_global_fini(struct radeon_device *rdev)
>  	}
>  }
>  
> -struct ttm_backend *radeon_ttm_backend_create(struct radeon_device *rdev);
> -
> -static struct ttm_backend*
> -radeon_create_ttm_backend_entry(struct ttm_bo_device *bdev)
> -{
> -	struct radeon_device *rdev;
> -
> -	rdev = radeon_get_rdev(bdev);
> -#if __OS_HAS_AGP
> -	if (rdev->flags & RADEON_IS_AGP) {
> -		return ttm_agp_backend_init(bdev, rdev->ddev->agp->bridge);
> -	} else
> -#endif
> -	{
> -		return radeon_ttm_backend_create(rdev);
> -	}
> -}
> -
>  static int radeon_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags)
>  {
>  	return 0;
> @@ -515,8 +497,93 @@ static bool radeon_sync_obj_signaled(void *sync_obj, void *sync_arg)
>  	return radeon_fence_signaled((struct radeon_fence *)sync_obj);
>  }
>  
> +/*
> + * TTM backend functions.
> + */
> +struct radeon_ttm_tt {
> +	struct ttm_tt			ttm;
> +	struct radeon_device		*rdev;
> +	u64				offset;
> +};
> +
> +static int radeon_ttm_backend_bind(struct ttm_tt *ttm,
> +				   struct ttm_mem_reg *bo_mem)
> +{
> +	struct radeon_ttm_tt *gtt;
> +	int r;
> +
> +	gtt = container_of(ttm, struct radeon_ttm_tt, ttm);
> +	gtt->offset = (unsigned long)(bo_mem->start << PAGE_SHIFT);
> +	if (!ttm->num_pages) {
> +		WARN(1, "nothing to bind %lu pages for mreg %p back %p!\n",
> +		     ttm->num_pages, bo_mem, ttm);
> +	}
> +	r = radeon_gart_bind(gtt->rdev, gtt->offset,
> +			     ttm->num_pages, ttm->pages, ttm->dma_address);
> +	if (r) {
> +		DRM_ERROR("failed to bind %lu pages at 0x%08X\n",
> +			  ttm->num_pages, (unsigned)gtt->offset);
> +		return r;
> +	}
> +	return 0;
> +}
> +
> +static int radeon_ttm_backend_unbind(struct ttm_tt *ttm)
> +{
> +	struct radeon_ttm_tt *gtt;
> +
> +	gtt = container_of(ttm, struct radeon_ttm_tt, ttm);
> +	radeon_gart_unbind(gtt->rdev, gtt->offset, ttm->num_pages);
> +	return 0;
> +}
> +
> +static void radeon_ttm_backend_destroy(struct ttm_tt *ttm)
> +{
> +	struct radeon_ttm_tt *gtt;
> +
> +	gtt = container_of(ttm, struct radeon_ttm_tt, ttm);
> +	if (ttm->state == tt_bound) {
> +		radeon_ttm_backend_unbind(ttm);
> +	}
> +	kfree(gtt);
> +}
> +
> +static struct ttm_backend_func radeon_backend_func = {
> +	.bind = &radeon_ttm_backend_bind,
> +	.unbind = &radeon_ttm_backend_unbind,
> +	.destroy = &radeon_ttm_backend_destroy,
> +};
> +
> +struct ttm_tt *radeon_ttm_tt_create(struct ttm_bo_device *bdev,
> +				    unsigned long size, uint32_t page_flags,
> +				    struct page *dummy_read_page)
> +{
> +	struct radeon_device *rdev;
> +	struct radeon_ttm_tt *gtt;
> +
> +	rdev = radeon_get_rdev(bdev);
> +#if __OS_HAS_AGP
> +	if (rdev->flags & RADEON_IS_AGP) {
> +		return ttm_agp_tt_create(bdev, rdev->ddev->agp->bridge,
> +					 size, page_flags, dummy_read_page);
> +	}
> +#endif
> +
> +	gtt = kzalloc(sizeof(struct radeon_ttm_tt), GFP_KERNEL);
> +	if (gtt == NULL) {
> +		return NULL;
> +	}
> +	gtt->ttm.func = &radeon_backend_func;
> +	gtt->rdev = rdev;
> +	if (ttm_tt_init(&gtt->ttm, bdev, size, page_flags, dummy_read_page)) {
> +		return NULL;
> +	}
> +	return &gtt->ttm;
> +}
> +
> +
>  static struct ttm_bo_driver radeon_bo_driver = {
> -	.create_ttm_backend_entry = &radeon_create_ttm_backend_entry,
> +	.ttm_tt_create = &radeon_ttm_tt_create,
>  	.invalidate_caches = &radeon_invalidate_caches,
>  	.init_mem_type = &radeon_init_mem_type,
>  	.evict_flags = &radeon_evict_flags,
> @@ -680,123 +747,6 @@ int radeon_mmap(struct file *filp, struct vm_area_struct *vma)
>  }
>  
>  
> -/*
> - * TTM backend functions.
> - */
> -struct radeon_ttm_backend {
> -	struct ttm_backend		backend;
> -	struct radeon_device		*rdev;
> -	unsigned long			num_pages;
> -	struct page			**pages;
> -	struct page			*dummy_read_page;
> -	dma_addr_t			*dma_addrs;
> -	bool				populated;
> -	bool				bound;
> -	unsigned			offset;
> -};
> -
> -static int radeon_ttm_backend_populate(struct ttm_backend *backend,
> -				       unsigned long num_pages,
> -				       struct page **pages,
> -				       struct page *dummy_read_page,
> -				       dma_addr_t *dma_addrs)
> -{
> -	struct radeon_ttm_backend *gtt;
> -
> -	gtt = container_of(backend, struct radeon_ttm_backend, backend);
> -	gtt->pages = pages;
> -	gtt->dma_addrs = dma_addrs;
> -	gtt->num_pages = num_pages;
> -	gtt->dummy_read_page = dummy_read_page;
> -	gtt->populated = true;
> -	return 0;
> -}
> -
> -static void radeon_ttm_backend_clear(struct ttm_backend *backend)
> -{
> -	struct radeon_ttm_backend *gtt;
> -
> -	gtt = container_of(backend, struct radeon_ttm_backend, backend);
> -	gtt->pages = NULL;
> -	gtt->dma_addrs = NULL;
> -	gtt->num_pages = 0;
> -	gtt->dummy_read_page = NULL;
> -	gtt->populated = false;
> -	gtt->bound = false;
> -}
> -
> -
> -static int radeon_ttm_backend_bind(struct ttm_backend *backend,
> -				   struct ttm_mem_reg *bo_mem)
> -{
> -	struct radeon_ttm_backend *gtt;
> -	int r;
> -
> -	gtt = container_of(backend, struct radeon_ttm_backend, backend);
> -	gtt->offset = bo_mem->start << PAGE_SHIFT;
> -	if (!gtt->num_pages) {
> -		WARN(1, "nothing to bind %lu pages for mreg %p back %p!\n",
> -		     gtt->num_pages, bo_mem, backend);
> -	}
> -	r = radeon_gart_bind(gtt->rdev, gtt->offset,
> -			     gtt->num_pages, gtt->pages, gtt->dma_addrs);
> -	if (r) {
> -		DRM_ERROR("failed to bind %lu pages at 0x%08X\n",
> -			  gtt->num_pages, gtt->offset);
> -		return r;
> -	}
> -	gtt->bound = true;
> -	return 0;
> -}
> -
> -static int radeon_ttm_backend_unbind(struct ttm_backend *backend)
> -{
> -	struct radeon_ttm_backend *gtt;
> -
> -	gtt = container_of(backend, struct radeon_ttm_backend, backend);
> -	radeon_gart_unbind(gtt->rdev, gtt->offset, gtt->num_pages);
> -	gtt->bound = false;
> -	return 0;
> -}
> -
> -static void radeon_ttm_backend_destroy(struct ttm_backend *backend)
> -{
> -	struct radeon_ttm_backend *gtt;
> -
> -	gtt = container_of(backend, struct radeon_ttm_backend, backend);
> -	if (gtt->bound) {
> -		radeon_ttm_backend_unbind(backend);
> -	}
> -	kfree(gtt);
> -}
> -
> -static struct ttm_backend_func radeon_backend_func = {
> -	.populate = &radeon_ttm_backend_populate,
> -	.clear = &radeon_ttm_backend_clear,
> -	.bind = &radeon_ttm_backend_bind,
> -	.unbind = &radeon_ttm_backend_unbind,
> -	.destroy = &radeon_ttm_backend_destroy,
> -};
> -
> -struct ttm_backend *radeon_ttm_backend_create(struct radeon_device *rdev)
> -{
> -	struct radeon_ttm_backend *gtt;
> -
> -	gtt = kzalloc(sizeof(struct radeon_ttm_backend), GFP_KERNEL);
> -	if (gtt == NULL) {
> -		return NULL;
> -	}
> -	gtt->backend.bdev = &rdev->mman.bdev;
> -	gtt->backend.func = &radeon_backend_func;
> -	gtt->rdev = rdev;
> -	gtt->pages = NULL;
> -	gtt->num_pages = 0;
> -	gtt->dummy_read_page = NULL;
> -	gtt->populated = false;
> -	gtt->bound = false;
> -	return &gtt->backend;
> -}
> -
>  #define RADEON_DEBUGFS_MEM_TYPES 2
>  
>  #if defined(CONFIG_DEBUG_FS)
> diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c b/drivers/gpu/drm/ttm/ttm_agp_backend.c
> index 1c4a72f..14ebd36 100644
> --- a/drivers/gpu/drm/ttm/ttm_agp_backend.c
> +++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c
> @@ -40,45 +40,33 @@
>  #include <asm/agp.h>
>  
>  struct ttm_agp_backend {
> -	struct ttm_backend backend;
> +	struct ttm_tt ttm;
>  	struct agp_memory *mem;
>  	struct agp_bridge_data *bridge;
>  };
>  
> -static int ttm_agp_populate(struct ttm_backend *backend,
> -			    unsigned long num_pages, struct page **pages,
> -			    struct page *dummy_read_page,
> -			    dma_addr_t *dma_addrs)
> +static int ttm_agp_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem)
>  {
> -	struct ttm_agp_backend *agp_be =
> -	    container_of(backend, struct ttm_agp_backend, backend);
> -	struct page **cur_page, **last_page = pages + num_pages;
> +	struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm);
> +	struct drm_mm_node *node = bo_mem->mm_node;
>  	struct agp_memory *mem;
> +	int ret, cached = (bo_mem->placement & TTM_PL_FLAG_CACHED);
> +	unsigned i;
>  
> -	mem = agp_allocate_memory(agp_be->bridge, num_pages, AGP_USER_MEMORY);
> +	mem = agp_allocate_memory(agp_be->bridge, ttm->num_pages, AGP_USER_MEMORY);
>  	if (unlikely(mem == NULL))
>  		return -ENOMEM;
>  
>  	mem->page_count = 0;
> -	for (cur_page = pages; cur_page < last_page; ++cur_page) {
> -		struct page *page = *cur_page;
> +	for (i = 0; i < ttm->num_pages; i++) {
> +		struct page *page = ttm->pages[i];
> +
>  		if (!page)
> -			page = dummy_read_page;
> +			page = ttm->dummy_read_page;
>  
>  		mem->pages[mem->page_count++] = page;
>  	}
>  	agp_be->mem = mem;
> -	return 0;
> -}
> -
> -static int ttm_agp_bind(struct ttm_backend *backend, struct ttm_mem_reg *bo_mem)
> -{
> -	struct ttm_agp_backend *agp_be =
> -	    container_of(backend, struct ttm_agp_backend, backend);
> -	struct drm_mm_node *node = bo_mem->mm_node;
> -	struct agp_memory *mem = agp_be->mem;
> -	int cached = (bo_mem->placement & TTM_PL_FLAG_CACHED);
> -	int ret;
>  
>  	mem->is_flushed = 1;
>  	mem->type = (cached) ? AGP_USER_CACHED_MEMORY : AGP_USER_MEMORY;
> @@ -90,50 +78,38 @@ static int ttm_agp_bind(struct ttm_backend *backend, struct ttm_mem_reg *bo_mem)
>  	return ret;
>  }
>  
> -static int ttm_agp_unbind(struct ttm_backend *backend)
> +static int ttm_agp_unbind(struct ttm_tt *ttm)
>  {
> -	struct ttm_agp_backend *agp_be =
> -	    container_of(backend, struct ttm_agp_backend, backend);
> -
> -	if (agp_be->mem->is_bound)
> -		return agp_unbind_memory(agp_be->mem);
> -	else
> -		return 0;
> -}
> +	struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm);
>  
> -static void ttm_agp_clear(struct ttm_backend *backend)
> -{
> -	struct ttm_agp_backend *agp_be =
> -	    container_of(backend, struct ttm_agp_backend, backend);
> -	struct agp_memory *mem = agp_be->mem;
> -
> -	if (mem) {
> -		ttm_agp_unbind(backend);
> -		agp_free_memory(mem);
> +	if (agp_be->mem) {
> +		if (agp_be->mem->is_bound)
> +			return agp_unbind_memory(agp_be->mem);
> +		agp_free_memory(agp_be->mem);
> +		agp_be->mem = NULL;
>  	}
> -	agp_be->mem = NULL;
> +	return 0;
>  }
>  
> -static void ttm_agp_destroy(struct ttm_backend *backend)
> +static void ttm_agp_destroy(struct ttm_tt *ttm)
>  {
> -	struct ttm_agp_backend *agp_be =
> -	    container_of(backend, struct ttm_agp_backend, backend);
> +	struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm);
>  
>  	if (agp_be->mem)
> -		ttm_agp_clear(backend);
> +		ttm_agp_unbind(ttm);
>  	kfree(agp_be);
>  }
>  
>  static struct ttm_backend_func ttm_agp_func = {
> -	.populate = ttm_agp_populate,
> -	.clear = ttm_agp_clear,
>  	.bind = ttm_agp_bind,
>  	.unbind = ttm_agp_unbind,
>  	.destroy = ttm_agp_destroy,
>  };
>  
> -struct ttm_backend *ttm_agp_backend_init(struct ttm_bo_device *bdev,
> -					 struct agp_bridge_data *bridge)
> +struct ttm_tt *ttm_agp_tt_create(struct ttm_bo_device *bdev,
> +				 struct agp_bridge_data *bridge,
> +				 unsigned long size, uint32_t page_flags,
> +				 struct page *dummy_read_page)
>  {
>  	struct ttm_agp_backend *agp_be;
>  
> @@ -143,10 +119,14 @@ struct ttm_backend *ttm_agp_backend_init(struct ttm_bo_device *bdev,
>  
>  	agp_be->mem = NULL;
>  	agp_be->bridge = bridge;
> -	agp_be->backend.func = &ttm_agp_func;
> -	agp_be->backend.bdev = bdev;
> -	return &agp_be->backend;
> +	agp_be->ttm.func = &ttm_agp_func;
> +
> +	if (ttm_tt_init(&agp_be->ttm, bdev, size, page_flags, dummy_read_page)) {
> +		return NULL;
> +	}
> +
> +	return &agp_be->ttm;
>  }
> -EXPORT_SYMBOL(ttm_agp_backend_init);
> +EXPORT_SYMBOL(ttm_agp_tt_create);
>  
>  #endif
> diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
> index 4bde335..cb73527 100644
> --- a/drivers/gpu/drm/ttm/ttm_bo.c
> +++ b/drivers/gpu/drm/ttm/ttm_bo.c
> @@ -337,8 +337,8 @@ static int ttm_bo_add_ttm(struct ttm_buffer_object *bo, bool zero_alloc)
>  		if (zero_alloc)
>  			page_flags |= TTM_PAGE_FLAG_ZERO_ALLOC;
>  	case ttm_bo_type_kernel:
> -		bo->ttm = ttm_tt_create(bdev, bo->num_pages << PAGE_SHIFT,
> -					page_flags, glob->dummy_read_page);
> +		bo->ttm = bdev->driver->ttm_tt_create(bdev, bo->num_pages << PAGE_SHIFT,
> +						      page_flags, glob->dummy_read_page);
>  		if (unlikely(bo->ttm == NULL))
>  			ret = -ENOMEM;
>  		break;
> @@ -1437,10 +1437,7 @@ int ttm_bo_global_init(struct drm_global_reference *ref)
>  		goto out_no_shrink;
>  	}
>  
> -	glob->ttm_bo_extra_size =
> -		ttm_round_pot(sizeof(struct ttm_tt)) +
> -		ttm_round_pot(sizeof(struct ttm_backend));
> -
> +	glob->ttm_bo_extra_size = ttm_round_pot(sizeof(struct ttm_tt));
>  	glob->ttm_bo_size = glob->ttm_bo_extra_size +
>  		ttm_round_pot(sizeof(struct ttm_buffer_object));
>  
> diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
> index 58ea7dc..b55e132 100644
> --- a/drivers/gpu/drm/ttm/ttm_tt.c
> +++ b/drivers/gpu/drm/ttm/ttm_tt.c
> @@ -103,7 +103,6 @@ struct page *ttm_tt_get_page(struct ttm_tt *ttm, int index)
>  int ttm_tt_populate(struct ttm_tt *ttm)
>  {
>  	struct ttm_mem_global *mem_glob = ttm->glob->mem_glob;
> -	struct ttm_backend *be;
>  	int ret;
>  
>  	if (ttm->state != tt_unpopulated)
> @@ -115,8 +114,6 @@ int ttm_tt_populate(struct ttm_tt *ttm)
>  			return ret;
>  	}
>  
> -	be = ttm->be;
> -
>  	ret = ttm_get_pages(ttm->pages, ttm->num_pages, ttm->page_flags,
>  			    ttm->caching_state, ttm->dma_address);
>  	if (ret != 0)
> @@ -129,8 +126,6 @@ int ttm_tt_populate(struct ttm_tt *ttm)
>  		return -ENOMEM;
>  	}
>  
> -	be->func->populate(be, ttm->num_pages, ttm->pages,
> -			   ttm->dummy_read_page, ttm->dma_address);
>  	ttm->state = tt_unbound;
>  	return 0;
>  }
> @@ -239,12 +234,8 @@ EXPORT_SYMBOL(ttm_tt_set_placement_caching);
>  
>  static void ttm_tt_free_alloced_pages(struct ttm_tt *ttm)
>  {
> -	struct ttm_backend *be = ttm->be;
>  	struct ttm_mem_global *glob = ttm->glob->mem_glob;
>  
> -	if (be)
> -		be->func->clear(be);
> -
>  	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);
> @@ -253,20 +244,11 @@ static void ttm_tt_free_alloced_pages(struct ttm_tt *ttm)
>  
>  void ttm_tt_destroy(struct ttm_tt *ttm)
>  {
> -	struct ttm_backend *be;
> -
>  	if (unlikely(ttm == NULL))
>  		return;
>  
> -	be = ttm->be;
> -	if (likely(be != NULL)) {
> -		be->func->destroy(be);
> -		ttm->be = NULL;
> -	}
> -
>  	if (likely(ttm->pages != NULL)) {
>  		ttm_tt_free_alloced_pages(ttm);
> -
>  		ttm_tt_free_page_directory(ttm);
>  	}
>  
> @@ -274,52 +256,38 @@ void ttm_tt_destroy(struct ttm_tt *ttm)
>  	    ttm->swap_storage)
>  		fput(ttm->swap_storage);
>  
> -	kfree(ttm);
> +	ttm->swap_storage = NULL;
> +	ttm->func->destroy(ttm);
>  }
>  
> -struct ttm_tt *ttm_tt_create(struct ttm_bo_device *bdev, unsigned long size,
> -			     uint32_t page_flags, struct page *dummy_read_page)
> +int ttm_tt_init(struct ttm_tt *ttm, struct ttm_bo_device *bdev,
> +		unsigned long size, uint32_t page_flags,
> +		struct page *dummy_read_page)
>  {
> -	struct ttm_bo_driver *bo_driver = bdev->driver;
> -	struct ttm_tt *ttm;
> -
> -	if (!bo_driver)
> -		return NULL;
> -
> -	ttm = kzalloc(sizeof(*ttm), GFP_KERNEL);
> -	if (!ttm)
> -		return NULL;
> -
> +	ttm->bdev = bdev;
>  	ttm->glob = bdev->glob;
>  	ttm->num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
>  	ttm->caching_state = tt_cached;
>  	ttm->page_flags = page_flags;
> -
>  	ttm->dummy_read_page = dummy_read_page;
> +	ttm->state = tt_unpopulated;
>  
>  	ttm_tt_alloc_page_directory(ttm);
>  	if (!ttm->pages || !ttm->dma_address) {
>  		ttm_tt_destroy(ttm);
>  		printk(KERN_ERR TTM_PFX "Failed allocating page table\n");
> -		return NULL;
> -	}
> -	ttm->be = bo_driver->create_ttm_backend_entry(bdev);
> -	if (!ttm->be) {
> -		ttm_tt_destroy(ttm);
> -		printk(KERN_ERR TTM_PFX "Failed creating ttm backend entry\n");
> -		return NULL;
> +		return -ENOMEM;
>  	}
> -	ttm->state = tt_unpopulated;
> -	return ttm;
> +	return 0;
>  }
> +EXPORT_SYMBOL(ttm_tt_init);
>  
>  void ttm_tt_unbind(struct ttm_tt *ttm)
>  {
>  	int ret;
> -	struct ttm_backend *be = ttm->be;
>  
>  	if (ttm->state == tt_bound) {
> -		ret = be->func->unbind(be);
> +		ret = ttm->func->unbind(ttm);
>  		BUG_ON(ret);
>  		ttm->state = tt_unbound;
>  	}
> @@ -328,7 +296,6 @@ void ttm_tt_unbind(struct ttm_tt *ttm)
>  int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem)
>  {
>  	int ret = 0;
> -	struct ttm_backend *be;
>  
>  	if (!ttm)
>  		return -EINVAL;
> @@ -336,13 +303,11 @@ int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem)
>  	if (ttm->state == tt_bound)
>  		return 0;
>  
> -	be = ttm->be;
> -
>  	ret = ttm_tt_populate(ttm);
>  	if (ret)
>  		return ret;
>  
> -	ret = be->func->bind(be, bo_mem);
> +	ret = ttm->func->bind(ttm, bo_mem);
>  	if (unlikely(ret != 0))
>  		return ret;
>  
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
> index 5a72ed9..cc72435 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
> @@ -139,85 +139,61 @@ struct ttm_placement vmw_srf_placement = {
>  	.busy_placement = gmr_vram_placement_flags
>  };
>  
> -struct vmw_ttm_backend {
> -	struct ttm_backend backend;
> -	struct page **pages;
> -	unsigned long num_pages;
> +struct vmw_ttm_tt {
> +	struct ttm_tt ttm;
>  	struct vmw_private *dev_priv;
>  	int gmr_id;
>  };
>  
> -static int vmw_ttm_populate(struct ttm_backend *backend,
> -			    unsigned long num_pages, struct page **pages,
> -			    struct page *dummy_read_page,
> -			    dma_addr_t *dma_addrs)
> +static int vmw_ttm_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem)
>  {
> -	struct vmw_ttm_backend *vmw_be =
> -	    container_of(backend, struct vmw_ttm_backend, backend);
> -
> -	vmw_be->pages = pages;
> -	vmw_be->num_pages = num_pages;
> -
> -	return 0;
> -}
> -
> -static int vmw_ttm_bind(struct ttm_backend *backend, struct ttm_mem_reg *bo_mem)
> -{
> -	struct vmw_ttm_backend *vmw_be =
> -	    container_of(backend, struct vmw_ttm_backend, backend);
> +	struct vmw_ttm_tt *vmw_be = container_of(ttm, struct vmw_ttm_tt, ttm);
>  
>  	vmw_be->gmr_id = bo_mem->start;
>  
> -	return vmw_gmr_bind(vmw_be->dev_priv, vmw_be->pages,
> -			    vmw_be->num_pages, vmw_be->gmr_id);
> +	return vmw_gmr_bind(vmw_be->dev_priv, ttm->pages,
> +			    ttm->num_pages, vmw_be->gmr_id);
>  }
>  
> -static int vmw_ttm_unbind(struct ttm_backend *backend)
> +static int vmw_ttm_unbind(struct ttm_tt *ttm)
>  {
> -	struct vmw_ttm_backend *vmw_be =
> -	    container_of(backend, struct vmw_ttm_backend, backend);
> +	struct vmw_ttm_tt *vmw_be = container_of(ttm, struct vmw_ttm_tt, ttm);
>  
>  	vmw_gmr_unbind(vmw_be->dev_priv, vmw_be->gmr_id);
>  	return 0;
>  }
>  
> -static void vmw_ttm_clear(struct ttm_backend *backend)
> +static void vmw_ttm_destroy(struct ttm_tt *ttm)
>  {
> -	struct vmw_ttm_backend *vmw_be =
> -		container_of(backend, struct vmw_ttm_backend, backend);
> -
> -	vmw_be->pages = NULL;
> -	vmw_be->num_pages = 0;
> -}
> -
> -static void vmw_ttm_destroy(struct ttm_backend *backend)
> -{
> -	struct vmw_ttm_backend *vmw_be =
> -	    container_of(backend, struct vmw_ttm_backend, backend);
> +	struct vmw_ttm_tt *vmw_be = container_of(ttm, struct vmw_ttm_tt, ttm);
>  
>  	kfree(vmw_be);
>  }
>  
>  static struct ttm_backend_func vmw_ttm_func = {
> -	.populate = vmw_ttm_populate,
> -	.clear = vmw_ttm_clear,
>  	.bind = vmw_ttm_bind,
>  	.unbind = vmw_ttm_unbind,
>  	.destroy = vmw_ttm_destroy,
>  };
>  
> -struct ttm_backend *vmw_ttm_backend_init(struct ttm_bo_device *bdev)
> +struct ttm_tt *vmw_ttm_tt_create(struct ttm_bo_device *bdev,
> +				 unsigned long size, uint32_t page_flags,
> +				 struct page *dummy_read_page)
>  {
> -	struct vmw_ttm_backend *vmw_be;
> +	struct vmw_ttm_tt *vmw_be;
>  
>  	vmw_be = kmalloc(sizeof(*vmw_be), GFP_KERNEL);
>  	if (!vmw_be)
>  		return NULL;
>  
> -	vmw_be->backend.func = &vmw_ttm_func;
> +	vmw_be->ttm.func = &vmw_ttm_func;
>  	vmw_be->dev_priv = container_of(bdev, struct vmw_private, bdev);
>  
> -	return &vmw_be->backend;
> +	if (ttm_tt_init(&vmw_be->ttm, bdev, size, page_flags, dummy_read_page)) {
> +		return NULL;
> +	}
> +
> +	return &vmw_be->ttm;
>  }
>  
>  int vmw_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags)
> @@ -357,7 +333,7 @@ static int vmw_sync_obj_wait(void *sync_obj, void *sync_arg,
>  }
>  
>  struct ttm_bo_driver vmw_bo_driver = {
> -	.create_ttm_backend_entry = vmw_ttm_backend_init,
> +	.ttm_tt_create = &vmw_ttm_tt_create,
>  	.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 6d17140..6b8c5cd 100644
> --- a/include/drm/ttm/ttm_bo_driver.h
> +++ b/include/drm/ttm/ttm_bo_driver.h
> @@ -43,36 +43,9 @@ struct ttm_backend;
>  
>  struct ttm_backend_func {
>  	/**
> -	 * struct ttm_backend_func member populate
> -	 *
> -	 * @backend: Pointer to a struct ttm_backend.
> -	 * @num_pages: Number of pages to populate.
> -	 * @pages: Array of pointers to ttm pages.
> -	 * @dummy_read_page: Page to be used instead of NULL pages in the
> -	 * array @pages.
> -	 * @dma_addrs: Array of DMA (bus) address of the ttm pages.
> -	 *
> -	 * Populate the backend with ttm pages. Depending on the backend,
> -	 * it may or may not copy the @pages array.
> -	 */
> -	int (*populate) (struct ttm_backend *backend,
> -			 unsigned long num_pages, struct page **pages,
> -			 struct page *dummy_read_page,
> -			 dma_addr_t *dma_addrs);
> -	/**
> -	 * struct ttm_backend_func member clear
> -	 *
> -	 * @backend: Pointer to a struct ttm_backend.
> -	 *
> -	 * This is an "unpopulate" function. Release all resources
> -	 * allocated with populate.
> -	 */
> -	void (*clear) (struct ttm_backend *backend);
> -
> -	/**
>  	 * struct ttm_backend_func member bind
>  	 *
> -	 * @backend: Pointer to a struct ttm_backend.
> +	 * @ttm: Pointer to a struct ttm_tt.
>  	 * @bo_mem: Pointer to a struct ttm_mem_reg describing the
>  	 * memory type and location for binding.
>  	 *
> @@ -80,40 +53,27 @@ struct ttm_backend_func {
>  	 * indicated by @bo_mem. This function should be able to handle
>  	 * differences between aperture and system page sizes.
>  	 */
> -	int (*bind) (struct ttm_backend *backend, struct ttm_mem_reg *bo_mem);
> +	int (*bind) (struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem);
>  
>  	/**
>  	 * struct ttm_backend_func member unbind
>  	 *
> -	 * @backend: Pointer to a struct ttm_backend.
> +	 * @ttm: Pointer to a struct ttm_tt.
>  	 *
>  	 * Unbind previously bound backend pages. This function should be
>  	 * able to handle differences between aperture and system page sizes.
>  	 */
> -	int (*unbind) (struct ttm_backend *backend);
> +	int (*unbind) (struct ttm_tt *ttm);
>  
>  	/**
>  	 * struct ttm_backend_func member destroy
>  	 *
> -	 * @backend: Pointer to a struct ttm_backend.
> +	 * @ttm: Pointer to a struct ttm_tt.
>  	 *
> -	 * Destroy the backend.
> +	 * Destroy the backend. This will be call back from ttm_tt_destroy so
> +	 * don't call ttm_tt_destroy from the callback or infinite loop.
>  	 */
> -	void (*destroy) (struct ttm_backend *backend);
> -};
> -
> -/**
> - * struct ttm_backend
> - *
> - * @bdev: Pointer to a struct ttm_bo_device.
> - * @func: Pointer to a struct ttm_backend_func that describes
> - * the backend methods.
> - *
> - */
> -
> -struct ttm_backend {
> -	struct ttm_bo_device *bdev;
> -	struct ttm_backend_func *func;
> +	void (*destroy) (struct ttm_tt *ttm);
>  };
>  
>  #define TTM_PAGE_FLAG_WRITE           (1 << 3)
> @@ -131,6 +91,9 @@ enum ttm_caching_state {
>  /**
>   * struct ttm_tt
>   *
> + * @bdev: Pointer to a struct ttm_bo_device.
> + * @func: Pointer to a struct ttm_backend_func that describes
> + * the backend methods.
>   * @dummy_read_page: Page to map where the ttm_tt page array contains a NULL
>   * pointer.
>   * @pages: Array of pages backing the data.
> @@ -148,6 +111,8 @@ enum ttm_caching_state {
>   */
>  
>  struct ttm_tt {
> +	struct ttm_bo_device *bdev;
> +	struct ttm_backend_func *func;
>  	struct page *dummy_read_page;
>  	struct page **pages;
>  	uint32_t page_flags;
> @@ -336,15 +301,22 @@ struct ttm_mem_type_manager {
>  
>  struct ttm_bo_driver {
>  	/**
> -	 * struct ttm_bo_driver member create_ttm_backend_entry
> +	 * ttm_tt_create
>  	 *
> -	 * @bdev: The buffer object device.
> +	 * @bdev: pointer to a struct ttm_bo_device:
> +	 * @size: Size of the data needed backing.
> +	 * @page_flags: Page flags as identified by TTM_PAGE_FLAG_XX flags.
> +	 * @dummy_read_page: See struct ttm_bo_device.
>  	 *
> -	 * Create a driver specific struct ttm_backend.
> +	 * Create a struct ttm_tt to back data with system memory pages.
> +	 * No pages are actually allocated.
> +	 * Returns:
> +	 * NULL: Out of memory.
>  	 */
> -
> -	struct ttm_backend *(*create_ttm_backend_entry)
> -	 (struct ttm_bo_device *bdev);
> +	struct ttm_tt *(*ttm_tt_create)(struct ttm_bo_device *bdev,
> +					unsigned long size,
> +					uint32_t page_flags,
> +					struct page *dummy_read_page);
>  
>  	/**
>  	 * struct ttm_bo_driver member invalidate_caches
> @@ -585,8 +557,9 @@ ttm_flag_masked(uint32_t *old, uint32_t new, uint32_t mask)
>  }
>  
>  /**
> - * ttm_tt_create
> + * ttm_tt_init
>   *
> + * @ttm: The struct ttm_tt.
>   * @bdev: pointer to a struct ttm_bo_device:
>   * @size: Size of the data needed backing.
>   * @page_flags: Page flags as identified by TTM_PAGE_FLAG_XX flags.
> @@ -597,10 +570,9 @@ ttm_flag_masked(uint32_t *old, uint32_t new, uint32_t mask)
>   * Returns:
>   * NULL: Out of memory.
>   */
> -extern struct ttm_tt *ttm_tt_create(struct ttm_bo_device *bdev,
> -				    unsigned long size,
> -				    uint32_t page_flags,
> -				    struct page *dummy_read_page);
> +extern int ttm_tt_init(struct ttm_tt *ttm, struct ttm_bo_device *bdev,
> +			unsigned long size, uint32_t page_flags,
> +			struct page *dummy_read_page);
>  
>  /**
>   * ttm_ttm_bind:
> @@ -626,7 +598,7 @@ extern int ttm_tt_populate(struct ttm_tt *ttm);
>   *
>   * @ttm: The struct ttm_tt.
>   *
> - * Unbind, unpopulate and destroy a struct ttm_tt.
> + * Unbind, unpopulate and destroy common struct ttm_tt.
>   */
>  extern void ttm_tt_destroy(struct ttm_tt *ttm);
>  
> @@ -1013,17 +985,23 @@ extern const struct ttm_mem_type_manager_func ttm_bo_manager_func;
>  #include <linux/agp_backend.h>
>  
>  /**
> - * ttm_agp_backend_init
> + * ttm_agp_tt_create
>   *
>   * @bdev: Pointer to a struct ttm_bo_device.
>   * @bridge: The agp bridge this device is sitting on.
> + * @size: Size of the data needed backing.
> + * @page_flags: Page flags as identified by TTM_PAGE_FLAG_XX flags.
> + * @dummy_read_page: See struct ttm_bo_device.
> + *
>   *
>   * Create a TTM backend that uses the indicated AGP bridge as an aperture
>   * for TT memory. This function uses the linux agpgart interface to
>   * bind and unbind memory backing a ttm_tt.
>   */
> -extern struct ttm_backend *ttm_agp_backend_init(struct ttm_bo_device *bdev,
> -						struct agp_bridge_data *bridge);
> +extern struct ttm_tt *ttm_agp_tt_create(struct ttm_bo_device *bdev,
> +					struct agp_bridge_data *bridge,
> +					unsigned long size, uint32_t page_flags,
> +					struct page *dummy_read_page);
>  #endif
>  
>  #endif
> -- 
> 1.7.7.1


More information about the dri-devel mailing list