video: tegra: host: Support physical addresses
Terje Bergstrom [Thu, 29 Aug 2013 09:17:28 +0000 (12:17 +0300)]
Support physical addresses in nvhost_memmgr interface. This is needed
to support carveout memories.

Change-Id: Iaa6c5a33fde20db9d3c4f2cf0778371cce07da2d
Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-on: http://git-master/r/270080
Reviewed-by: Juha Tukkinen <jtukkinen@nvidia.com>
Tested-by: Juha Tukkinen <jtukkinen@nvidia.com>

12 files changed:
drivers/video/tegra/host/gr3d/gr3d.c
drivers/video/tegra/host/gr3d/gr3d_t114.c
drivers/video/tegra/host/gr3d/gr3d_t20.c
drivers/video/tegra/host/gr3d/gr3d_t30.c
drivers/video/tegra/host/host1x/host1x_cdma.c
drivers/video/tegra/host/msenc/msenc.c
drivers/video/tegra/host/nvhost_memmgr.c
drivers/video/tegra/host/nvhost_memmgr.h
drivers/video/tegra/host/nvmap.c
drivers/video/tegra/host/tsec/tsec.c
drivers/video/tegra/host/user_hwctx.c
drivers/video/tegra/host/vic03/vic03.c

index e1a7ce1..1b68743 100644 (file)
@@ -111,7 +111,7 @@ struct host1x_hwctx *nvhost_3dctx_alloc_common(struct host1x_hwctx_handler *p,
                        &ch->dev->dev);
        if (IS_ERR(ctx->restore_sgt))
                goto fail_pin;
-       ctx->restore_phys = sg_dma_address(ctx->restore_sgt->sgl);
+       ctx->restore_phys = nvhost_memmgr_dma_addr(ctx->restore_sgt);
 
        kref_init(&ctx->hwctx.ref);
        ctx->hwctx.h = &p->h;
index dd6c627..8469bed 100644 (file)
@@ -443,7 +443,7 @@ struct nvhost_hwctx_handler *nvhost_gr3d_t114_ctxhandler_init(
        p->save_sgt = nvhost_memmgr_pin(memmgr, p->save_buf, &ch->dev->dev);
        if (IS_ERR(p->save_sgt))
                goto fail_pin;
-       p->save_phys = sg_dma_address(p->save_sgt->sgl);
+       p->save_phys = nvhost_memmgr_dma_addr(p->save_sgt);
 
        setup_save(p, save_ptr);
 
index 7c37cbc..1ef3735 100644 (file)
@@ -388,7 +388,7 @@ struct nvhost_hwctx_handler *nvhost_gr3d_t20_ctxhandler_init(
        p->save_sgt = nvhost_memmgr_pin(memmgr, p->save_buf, &ch->dev->dev);
        if (IS_ERR(p->save_sgt))
                goto fail_pin;
-       p->save_phys = sg_dma_address(p->save_sgt->sgl);
+       p->save_phys = nvhost_memmgr_dma_addr(p->save_sgt);
 
        setup_save(p, save_ptr);
 
index 66ff175..c26d80e 100644 (file)
@@ -426,7 +426,7 @@ struct nvhost_hwctx_handler *nvhost_gr3d_t30_ctxhandler_init(
        p->save_sgt = nvhost_memmgr_pin(memmgr, p->save_buf, &ch->dev->dev);
        if (IS_ERR(p->save_sgt))
                goto fail_pin;
-       p->save_phys = sg_dma_address(p->save_sgt->sgl);
+       p->save_phys = nvhost_memmgr_dma_addr(p->save_sgt);
 
        setup_save(p, save_ptr);
 
@@ -516,7 +516,7 @@ int nvhost_gr3d_t30_read_reg(
                goto done;
        }
        /* Set address of target memory slot to the stream */
-       opcodes[3] = sg_dma_address(mem_sgt->sgl);
+       opcodes[3] = nvhost_memmgr_dma_addr(mem_sgt);
 
        read_waiter = nvhost_intr_alloc_waiter();
        if (!read_waiter) {
index 38e9e97..c71277e 100644 (file)
@@ -98,7 +98,7 @@ static int push_buffer_init(struct push_buffer *pb)
                pb->sgt = 0;
                goto fail;
        }
-       pb->phys = sg_dma_address(pb->sgt->sgl);
+       pb->phys = nvhost_memmgr_dma_addr(pb->sgt);
 
        /* memory for storing nvmap client and handles for each opcode pair */
        pb->client_handle = kzalloc(NVHOST_GATHER_QUEUE_SIZE *
index e0917b3..4c7456a 100644 (file)
@@ -153,7 +153,7 @@ int msenc_boot(struct platform_device *dev)
 
        nvhost_device_writel(dev, msenc_dmactl_r(), 0);
        nvhost_device_writel(dev, msenc_dmatrfbase_r(),
-               (sg_dma_address(m->pa->sgl) + m->os.bin_data_offset) >> 8);
+               (nvhost_memmgr_dma_addr(m->pa) + m->os.bin_data_offset) >> 8);
 
        for (offset = 0; offset < m->os.data_size; offset += 256)
                msenc_dma_pa_to_internal_256b(dev,
index 1e0d316..ff77748 100644 (file)
@@ -331,7 +331,7 @@ int nvhost_memmgr_pin_array_ids(struct mem_mgr *mgr,
                if (IS_ERR(sgt))
                        return PTR_ERR(sgt);
 
-               phys_addr[ids[i].index] = sg_dma_address(sgt->sgl);
+               phys_addr[ids[i].index] = nvhost_memmgr_dma_addr(sgt);
                unpin_data[pin_count].h = h;
                unpin_data[pin_count++].mem = sgt;
 
index e5d8c52..22e0838 100644 (file)
@@ -21,6 +21,9 @@
 #ifndef _NVHOST_MEM_MGR_H_
 #define _NVHOST_MEM_MGR_H_
 
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+
 struct nvhost_chip_support;
 struct mem_mgr;
 struct mem_handle;
@@ -109,4 +112,16 @@ void nvhost_memmgr_smmu_unmap(struct sg_table *sgt, size_t size,
                           struct device *dev);
 #endif
 
+/*
+ * Return IOVA for buffers allocated from IOVMM heap and have IOVA assigned.
+ * Otherwise assume the buffer was allocated from carveout and return physical
+ * address.
+ */
+static inline dma_addr_t nvhost_memmgr_dma_addr(struct sg_table *sgt)
+{
+       return sg_dma_address(sgt->sgl) && sg_dma_address(sgt->sgl) != DMA_ERROR_CODE ?
+               sg_dma_address(sgt->sgl) :
+               sg_phys(sgt->sgl);
+}
+
 #endif
index b05c0a7..b482775 100644 (file)
@@ -146,7 +146,7 @@ struct sg_table *nvhost_nvmap_pin(struct mem_mgr *mgr,
        /* create the per-as part of the priv if needed */
        as_priv = priv->as[asid];
        if (!as_priv) {
-               u64 size = 0, addr = 0;
+               u64 size = 0, addr = 0, heap = 0;
 
                ret = nvmap_get_handle_param(nvmap, ref,
                                NVMAP_HANDLE_PARAM_SIZE, &size);
@@ -162,6 +162,13 @@ struct sg_table *nvhost_nvmap_pin(struct mem_mgr *mgr,
                        return ERR_PTR(ret);
                }
 
+               ret = nvmap_get_handle_param(nvmap, ref,
+                               NVMAP_HANDLE_PARAM_HEAP, &heap);
+               if (ret) {
+                       mutex_unlock(&priv->lock);
+                       return ERR_PTR(ret);
+               }
+
                as_priv = kzalloc(sizeof(*as_priv), GFP_KERNEL);
                if (!as_priv) {
                        mutex_unlock(&priv->lock);
@@ -182,17 +189,24 @@ struct sg_table *nvhost_nvmap_pin(struct mem_mgr *mgr,
                if (asid == tegra_smmu_get_asid(NULL) && !IS_ERR_VALUE(addr))
                        as_priv->flags |= BIT(FLAG_NVMAP_MAPPED);
 
+               if (heap & NVMAP_HEAP_CARVEOUT_MASK)
+                       as_priv->flags |= BIT(FLAG_CARVEOUT);
+
                priv->as[asid] = as_priv;
        }
 
        sgt = as_priv->sgt;
 
-       if (as_priv->flags & BIT(FLAG_NVMAP_MAPPED) &&
+       if (as_priv->flags & BIT(FLAG_CARVEOUT))
+               ;
+       else if (as_priv->flags & BIT(FLAG_NVMAP_MAPPED) &&
                        sg_dma_address(sgt->sgl) == 0) {
                dma_addr_t addr = 0;
                int err = nvmap_pin(as_priv->client, ref, &addr);
-               if (err)
+               if (err) {
+                       mutex_unlock(&priv->lock);
                        return ERR_PTR(err);
+               }
 
                sg_dma_address(sgt->sgl) = addr;
        } else if (as_priv->pin_count == 0 &&
index 02f28c3..80d4380 100644 (file)
@@ -261,7 +261,7 @@ int tsec_boot(struct platform_device *dev)
 
        nvhost_device_writel(dev, tsec_dmactl_r(), 0);
        nvhost_device_writel(dev, tsec_dmatrfbase_r(),
-               (sg_dma_address(m->pa->sgl) + m->os.bin_data_offset) >> 8);
+               (nvhost_memmgr_dma_addr(m->pa) + m->os.bin_data_offset) >> 8);
 
        for (offset = 0; offset < m->os.data_size; offset += 256)
                tsec_dma_pa_to_internal_256b(dev,
index f7f370f..c771737 100644 (file)
@@ -35,7 +35,7 @@ static void user_hwctx_save_push(struct nvhost_hwctx *nctx,
                        ctx->save_buf,
                        ctx->save_offset,
                        nvhost_opcode_gather(ctx->save_size),
-                       sg_dma_address(ctx->save_sgt->sgl));
+                       nvhost_memmgr_dma_addr(ctx->save_sgt));
 }
 
 static void user_hwctx_restore_push(struct nvhost_hwctx *nctx,
@@ -47,7 +47,7 @@ static void user_hwctx_restore_push(struct nvhost_hwctx *nctx,
                        ctx->restore,
                        ctx->restore_offset,
                        nvhost_opcode_gather(ctx->restore_size),
-                       sg_dma_address(ctx->restore_sgt->sgl));
+                       nvhost_memmgr_dma_addr(ctx->restore_sgt));
 }
 
 static void user_hwctx_free(struct kref *ref)
@@ -136,7 +136,7 @@ int user_hwctx_set_save(struct user_hwctx *ctx,
        if (!page_addr)
                return -ENOMEM;
 
-       __raw_writel(sg_dma_address(ctx->restore_sgt->sgl) + offset,
+       __raw_writel(nvhost_memmgr_dma_addr(ctx->restore_sgt) + offset,
                        page_addr + (reloc->cmdbuf_offset & ~PAGE_MASK));
        nvhost_memmgr_kunmap(ctx->save_buf,
                        reloc->cmdbuf_offset >> PAGE_SHIFT,
index 9ed95d4..2e92290 100644 (file)
@@ -248,7 +248,7 @@ static int vic03_read_ucode(struct platform_device *dev)
                err = PTR_ERR(v->ucode.sgt);
                goto clean_up;
        }
-       v->ucode.pa = sg_dma_address(v->ucode.sgt->sgl);
+       v->ucode.pa = nvhost_memmgr_dma_addr(v->ucode.sgt);
 
        v->ucode.va = nvhost_memmgr_mmap(v->ucode.mem_r);
        if (!v->ucode.va) {
@@ -492,7 +492,7 @@ static struct nvhost_hwctx *vic03_alloc_hwctx(struct nvhost_hwctx_handler *h,
                        ctx->restore, &ch->dev->dev);
        if (IS_ERR(ctx->restore_sgt))
                goto fail_pin;
-       ctx->restore_phys = sg_dma_address(ctx->restore_sgt->sgl);
+       ctx->restore_phys = nvhost_memmgr_dma_addr(ctx->restore_sgt);
 
        ctx->restore_size = nvhost_vic03_restore_size;
        ctx->hwctx.restore_incrs = 1;