From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
To: j.glisse@gmail.com
Cc: thellstrom@vmware.com, Jerome Glisse <jglisse@redhat.com>,
dri-devel@lists.freedesktop.org
Subject: Re: [PATCH 07/11] drm/ttm: merge ttm_backend and ttm_tt
Date: Mon, 7 Nov 2011 09:39:01 -0500 [thread overview]
Message-ID: <20111107143901.GA10823@phenom.dumpdata.com> (raw)
In-Reply-To: <1320363555-28438-8-git-send-email-j.glisse@gmail.com>
On Thu, Nov 03, 2011 at 07:39:11PM -0400, j.glisse@gmail.com wrote:
> From: Jerome Glisse <jglisse@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@oracle.com>
>
> Signed-off-by: Jerome Glisse <jglisse@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(>t->ttm, bdev, size, page_flags, dummy_read_page)) {
> + return NULL;
> + }
> + return >t->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 >t->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
next prev parent reply other threads:[~2011-11-07 14:39 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-11-03 23:39 ttm: merge ttm_backend & ttm_tt, introduce ttm dma allocator j.glisse
2011-11-03 23:39 ` [PATCH 01/11] drm/ttm: remove userspace backed ttm object support j.glisse
2011-11-03 23:39 ` [PATCH 02/11] drm/ttm: remove split btw highmen and lowmem page j.glisse
2011-11-03 23:39 ` [PATCH 03/11] drm/ttm: remove unused backend flags field j.glisse
2011-11-03 23:39 ` [PATCH 04/11] drm/ttm: use ttm put pages function to properly restore cache attribute j.glisse
2011-11-03 23:39 ` [PATCH 05/11] drm/ttm: convert page allocation to use page ptr array instead of list V3 j.glisse
2011-11-03 23:39 ` [PATCH 06/11] drm/ttm: test for dma_address array allocation failure j.glisse
2011-11-03 23:39 ` [PATCH 07/11] drm/ttm: merge ttm_backend and ttm_tt j.glisse
2011-11-07 14:39 ` Konrad Rzeszutek Wilk [this message]
2011-11-03 23:39 ` [PATCH 08/11] drm/ttm: introduce callback for ttm_tt populate & unpopulate j.glisse
2011-11-07 14:40 ` Konrad Rzeszutek Wilk
2011-11-07 17:35 ` Rob Clark
2011-11-07 19:39 ` Jerome Glisse
2011-11-07 20:17 ` Alex Deucher
2011-11-03 23:39 ` [PATCH 09/11] ttm: Provide DMA aware TTM page pool code j.glisse
2011-11-03 23:39 ` [PATCH 10/11] swiotlb: Expose swiotlb_nr_tlb function to modules j.glisse
2011-11-03 23:39 ` [PATCH 11/11] drm/radeon/kms: Enable the TTM DMA pool if swiotlb is on j.glisse
2011-11-07 17:50 ` ttm: merge ttm_backend & ttm_tt, introduce ttm dma allocator Konrad Rzeszutek Wilk
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20111107143901.GA10823@phenom.dumpdata.com \
--to=konrad.wilk@oracle.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=j.glisse@gmail.com \
--cc=jglisse@redhat.com \
--cc=thellstrom@vmware.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.