summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2014-04-07 23:49:35 (GMT)
committerScott Wood <scottwood@freescale.com>2014-04-07 23:49:35 (GMT)
commit62b8c978ee6b8d135d9e7953221de58000dba986 (patch)
tree683b04b2e627f6710c22c151b23c8cc9a165315e /drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
parent78fd82238d0e5716578c326404184a27ba67fd6e (diff)
downloadlinux-fsl-qoriq-62b8c978ee6b8d135d9e7953221de58000dba986.tar.xz
Rewind v3.13-rc3+ (78fd82238d0e5716) to v3.12
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c381
1 files changed, 17 insertions, 364 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
index 0489c61..96dc84d 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
@@ -141,374 +141,35 @@ struct ttm_placement vmw_srf_placement = {
};
struct vmw_ttm_tt {
- struct ttm_dma_tt dma_ttm;
+ struct ttm_tt ttm;
struct vmw_private *dev_priv;
int gmr_id;
- struct sg_table sgt;
- struct vmw_sg_table vsgt;
- uint64_t sg_alloc_size;
- bool mapped;
};
-const size_t vmw_tt_size = sizeof(struct vmw_ttm_tt);
-
-/**
- * Helper functions to advance a struct vmw_piter iterator.
- *
- * @viter: Pointer to the iterator.
- *
- * These functions return false if past the end of the list,
- * true otherwise. Functions are selected depending on the current
- * DMA mapping mode.
- */
-static bool __vmw_piter_non_sg_next(struct vmw_piter *viter)
-{
- return ++(viter->i) < viter->num_pages;
-}
-
-static bool __vmw_piter_sg_next(struct vmw_piter *viter)
-{
- return __sg_page_iter_next(&viter->iter);
-}
-
-
-/**
- * Helper functions to return a pointer to the current page.
- *
- * @viter: Pointer to the iterator
- *
- * These functions return a pointer to the page currently
- * pointed to by @viter. Functions are selected depending on the
- * current mapping mode.
- */
-static struct page *__vmw_piter_non_sg_page(struct vmw_piter *viter)
-{
- return viter->pages[viter->i];
-}
-
-static struct page *__vmw_piter_sg_page(struct vmw_piter *viter)
-{
- return sg_page_iter_page(&viter->iter);
-}
-
-
-/**
- * Helper functions to return the DMA address of the current page.
- *
- * @viter: Pointer to the iterator
- *
- * These functions return the DMA address of the page currently
- * pointed to by @viter. Functions are selected depending on the
- * current mapping mode.
- */
-static dma_addr_t __vmw_piter_phys_addr(struct vmw_piter *viter)
-{
- return page_to_phys(viter->pages[viter->i]);
-}
-
-static dma_addr_t __vmw_piter_dma_addr(struct vmw_piter *viter)
-{
- return viter->addrs[viter->i];
-}
-
-static dma_addr_t __vmw_piter_sg_addr(struct vmw_piter *viter)
-{
- return sg_page_iter_dma_address(&viter->iter);
-}
-
-
-/**
- * vmw_piter_start - Initialize a struct vmw_piter.
- *
- * @viter: Pointer to the iterator to initialize
- * @vsgt: Pointer to a struct vmw_sg_table to initialize from
- *
- * Note that we're following the convention of __sg_page_iter_start, so that
- * the iterator doesn't point to a valid page after initialization; it has
- * to be advanced one step first.
- */
-void vmw_piter_start(struct vmw_piter *viter, const struct vmw_sg_table *vsgt,
- unsigned long p_offset)
-{
- viter->i = p_offset - 1;
- viter->num_pages = vsgt->num_pages;
- switch (vsgt->mode) {
- case vmw_dma_phys:
- viter->next = &__vmw_piter_non_sg_next;
- viter->dma_address = &__vmw_piter_phys_addr;
- viter->page = &__vmw_piter_non_sg_page;
- viter->pages = vsgt->pages;
- break;
- case vmw_dma_alloc_coherent:
- viter->next = &__vmw_piter_non_sg_next;
- viter->dma_address = &__vmw_piter_dma_addr;
- viter->page = &__vmw_piter_non_sg_page;
- viter->addrs = vsgt->addrs;
- break;
- case vmw_dma_map_populate:
- case vmw_dma_map_bind:
- viter->next = &__vmw_piter_sg_next;
- viter->dma_address = &__vmw_piter_sg_addr;
- viter->page = &__vmw_piter_sg_page;
- __sg_page_iter_start(&viter->iter, vsgt->sgt->sgl,
- vsgt->sgt->orig_nents, p_offset);
- break;
- default:
- BUG();
- }
-}
-
-/**
- * vmw_ttm_unmap_from_dma - unmap device addresses previsouly mapped for
- * TTM pages
- *
- * @vmw_tt: Pointer to a struct vmw_ttm_backend
- *
- * Used to free dma mappings previously mapped by vmw_ttm_map_for_dma.
- */
-static void vmw_ttm_unmap_from_dma(struct vmw_ttm_tt *vmw_tt)
-{
- struct device *dev = vmw_tt->dev_priv->dev->dev;
-
- dma_unmap_sg(dev, vmw_tt->sgt.sgl, vmw_tt->sgt.nents,
- DMA_BIDIRECTIONAL);
- vmw_tt->sgt.nents = vmw_tt->sgt.orig_nents;
-}
-
-/**
- * vmw_ttm_map_for_dma - map TTM pages to get device addresses
- *
- * @vmw_tt: Pointer to a struct vmw_ttm_backend
- *
- * This function is used to get device addresses from the kernel DMA layer.
- * However, it's violating the DMA API in that when this operation has been
- * performed, it's illegal for the CPU to write to the pages without first
- * unmapping the DMA mappings, or calling dma_sync_sg_for_cpu(). It is
- * therefore only legal to call this function if we know that the function
- * dma_sync_sg_for_cpu() is a NOP, and dma_sync_sg_for_device() is at most
- * a CPU write buffer flush.
- */
-static int vmw_ttm_map_for_dma(struct vmw_ttm_tt *vmw_tt)
-{
- struct device *dev = vmw_tt->dev_priv->dev->dev;
- int ret;
-
- ret = dma_map_sg(dev, vmw_tt->sgt.sgl, vmw_tt->sgt.orig_nents,
- DMA_BIDIRECTIONAL);
- if (unlikely(ret == 0))
- return -ENOMEM;
-
- vmw_tt->sgt.nents = ret;
-
- return 0;
-}
-
-/**
- * vmw_ttm_map_dma - Make sure TTM pages are visible to the device
- *
- * @vmw_tt: Pointer to a struct vmw_ttm_tt
- *
- * Select the correct function for and make sure the TTM pages are
- * visible to the device. Allocate storage for the device mappings.
- * If a mapping has already been performed, indicated by the storage
- * pointer being non NULL, the function returns success.
- */
-static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt)
-{
- struct vmw_private *dev_priv = vmw_tt->dev_priv;
- struct ttm_mem_global *glob = vmw_mem_glob(dev_priv);
- struct vmw_sg_table *vsgt = &vmw_tt->vsgt;
- struct vmw_piter iter;
- dma_addr_t old;
- int ret = 0;
- static size_t sgl_size;
- static size_t sgt_size;
-
- if (vmw_tt->mapped)
- return 0;
-
- vsgt->mode = dev_priv->map_mode;
- vsgt->pages = vmw_tt->dma_ttm.ttm.pages;
- vsgt->num_pages = vmw_tt->dma_ttm.ttm.num_pages;
- vsgt->addrs = vmw_tt->dma_ttm.dma_address;
- vsgt->sgt = &vmw_tt->sgt;
-
- switch (dev_priv->map_mode) {
- case vmw_dma_map_bind:
- case vmw_dma_map_populate:
- if (unlikely(!sgl_size)) {
- sgl_size = ttm_round_pot(sizeof(struct scatterlist));
- sgt_size = ttm_round_pot(sizeof(struct sg_table));
- }
- vmw_tt->sg_alloc_size = sgt_size + sgl_size * vsgt->num_pages;
- ret = ttm_mem_global_alloc(glob, vmw_tt->sg_alloc_size, false,
- true);
- if (unlikely(ret != 0))
- return ret;
-
- ret = sg_alloc_table_from_pages(&vmw_tt->sgt, vsgt->pages,
- vsgt->num_pages, 0,
- (unsigned long)
- vsgt->num_pages << PAGE_SHIFT,
- GFP_KERNEL);
- if (unlikely(ret != 0))
- goto out_sg_alloc_fail;
-
- if (vsgt->num_pages > vmw_tt->sgt.nents) {
- uint64_t over_alloc =
- sgl_size * (vsgt->num_pages -
- vmw_tt->sgt.nents);
-
- ttm_mem_global_free(glob, over_alloc);
- vmw_tt->sg_alloc_size -= over_alloc;
- }
-
- ret = vmw_ttm_map_for_dma(vmw_tt);
- if (unlikely(ret != 0))
- goto out_map_fail;
-
- break;
- default:
- break;
- }
-
- old = ~((dma_addr_t) 0);
- vmw_tt->vsgt.num_regions = 0;
- for (vmw_piter_start(&iter, vsgt, 0); vmw_piter_next(&iter);) {
- dma_addr_t cur = vmw_piter_dma_addr(&iter);
-
- if (cur != old + PAGE_SIZE)
- vmw_tt->vsgt.num_regions++;
- old = cur;
- }
-
- vmw_tt->mapped = true;
- return 0;
-
-out_map_fail:
- sg_free_table(vmw_tt->vsgt.sgt);
- vmw_tt->vsgt.sgt = NULL;
-out_sg_alloc_fail:
- ttm_mem_global_free(glob, vmw_tt->sg_alloc_size);
- return ret;
-}
-
-/**
- * vmw_ttm_unmap_dma - Tear down any TTM page device mappings
- *
- * @vmw_tt: Pointer to a struct vmw_ttm_tt
- *
- * Tear down any previously set up device DMA mappings and free
- * any storage space allocated for them. If there are no mappings set up,
- * this function is a NOP.
- */
-static void vmw_ttm_unmap_dma(struct vmw_ttm_tt *vmw_tt)
-{
- struct vmw_private *dev_priv = vmw_tt->dev_priv;
-
- if (!vmw_tt->vsgt.sgt)
- return;
-
- switch (dev_priv->map_mode) {
- case vmw_dma_map_bind:
- case vmw_dma_map_populate:
- vmw_ttm_unmap_from_dma(vmw_tt);
- sg_free_table(vmw_tt->vsgt.sgt);
- vmw_tt->vsgt.sgt = NULL;
- ttm_mem_global_free(vmw_mem_glob(dev_priv),
- vmw_tt->sg_alloc_size);
- break;
- default:
- break;
- }
- vmw_tt->mapped = false;
-}
-
static int vmw_ttm_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem)
{
- struct vmw_ttm_tt *vmw_be =
- container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm);
- int ret;
-
- ret = vmw_ttm_map_dma(vmw_be);
- if (unlikely(ret != 0))
- return ret;
+ 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->vsgt,
+ return vmw_gmr_bind(vmw_be->dev_priv, ttm->pages,
ttm->num_pages, vmw_be->gmr_id);
}
static int vmw_ttm_unbind(struct ttm_tt *ttm)
{
- struct vmw_ttm_tt *vmw_be =
- container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm);
+ 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);
-
- if (vmw_be->dev_priv->map_mode == vmw_dma_map_bind)
- vmw_ttm_unmap_dma(vmw_be);
-
return 0;
}
static void vmw_ttm_destroy(struct ttm_tt *ttm)
{
- struct vmw_ttm_tt *vmw_be =
- container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm);
-
- vmw_ttm_unmap_dma(vmw_be);
- if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent)
- ttm_dma_tt_fini(&vmw_be->dma_ttm);
- else
- ttm_tt_fini(ttm);
- kfree(vmw_be);
-}
+ struct vmw_ttm_tt *vmw_be = container_of(ttm, struct vmw_ttm_tt, ttm);
-static int vmw_ttm_populate(struct ttm_tt *ttm)
-{
- struct vmw_ttm_tt *vmw_tt =
- container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm);
- struct vmw_private *dev_priv = vmw_tt->dev_priv;
- struct ttm_mem_global *glob = vmw_mem_glob(dev_priv);
- int ret;
-
- if (ttm->state != tt_unpopulated)
- return 0;
-
- if (dev_priv->map_mode == vmw_dma_alloc_coherent) {
- size_t size =
- ttm_round_pot(ttm->num_pages * sizeof(dma_addr_t));
- ret = ttm_mem_global_alloc(glob, size, false, true);
- if (unlikely(ret != 0))
- return ret;
-
- ret = ttm_dma_populate(&vmw_tt->dma_ttm, dev_priv->dev->dev);
- if (unlikely(ret != 0))
- ttm_mem_global_free(glob, size);
- } else
- ret = ttm_pool_populate(ttm);
-
- return ret;
-}
-
-static void vmw_ttm_unpopulate(struct ttm_tt *ttm)
-{
- struct vmw_ttm_tt *vmw_tt = container_of(ttm, struct vmw_ttm_tt,
- dma_ttm.ttm);
- struct vmw_private *dev_priv = vmw_tt->dev_priv;
- struct ttm_mem_global *glob = vmw_mem_glob(dev_priv);
-
- vmw_ttm_unmap_dma(vmw_tt);
- if (dev_priv->map_mode == vmw_dma_alloc_coherent) {
- size_t size =
- ttm_round_pot(ttm->num_pages * sizeof(dma_addr_t));
-
- ttm_dma_unpopulate(&vmw_tt->dma_ttm, dev_priv->dev->dev);
- ttm_mem_global_free(glob, size);
- } else
- ttm_pool_unpopulate(ttm);
+ ttm_tt_fini(ttm);
+ kfree(vmw_be);
}
static struct ttm_backend_func vmw_ttm_func = {
@@ -522,28 +183,20 @@ struct ttm_tt *vmw_ttm_tt_create(struct ttm_bo_device *bdev,
struct page *dummy_read_page)
{
struct vmw_ttm_tt *vmw_be;
- int ret;
- vmw_be = kzalloc(sizeof(*vmw_be), GFP_KERNEL);
+ vmw_be = kmalloc(sizeof(*vmw_be), GFP_KERNEL);
if (!vmw_be)
return NULL;
- vmw_be->dma_ttm.ttm.func = &vmw_ttm_func;
+ vmw_be->ttm.func = &vmw_ttm_func;
vmw_be->dev_priv = container_of(bdev, struct vmw_private, bdev);
- if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent)
- ret = ttm_dma_tt_init(&vmw_be->dma_ttm, bdev, size, page_flags,
- dummy_read_page);
- else
- ret = ttm_tt_init(&vmw_be->dma_ttm.ttm, bdev, size, page_flags,
- dummy_read_page);
- if (unlikely(ret != 0))
- goto out_no_init;
-
- return &vmw_be->dma_ttm.ttm;
-out_no_init:
- kfree(vmw_be);
- return NULL;
+ if (ttm_tt_init(&vmw_be->ttm, bdev, size, page_flags, dummy_read_page)) {
+ kfree(vmw_be);
+ return NULL;
+ }
+
+ return &vmw_be->ttm;
}
int vmw_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags)
@@ -679,8 +332,8 @@ static int vmw_sync_obj_wait(void *sync_obj, bool lazy, bool interruptible)
struct ttm_bo_driver vmw_bo_driver = {
.ttm_tt_create = &vmw_ttm_tt_create,
- .ttm_tt_populate = &vmw_ttm_populate,
- .ttm_tt_unpopulate = &vmw_ttm_unpopulate,
+ .ttm_tt_populate = &ttm_pool_populate,
+ .ttm_tt_unpopulate = &ttm_pool_unpopulate,
.invalidate_caches = vmw_invalidate_caches,
.init_mem_type = vmw_init_mem_type,
.evict_flags = vmw_evict_flags,