video: tegra: host: Map cmdbuf using nvmap_kmap
Terje Bergstrom [Wed, 17 Oct 2012 08:53:47 +0000 (11:53 +0300)]
Use nvmap_kmap() instead of nvmap_mmap() to map individual pages from cmdbuf.

Bug 1158533

Change-Id: I76320d1373b0177debec76fe171f0b0c02fe35cd
Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-on: http://git-master/r/145504
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Ken Adams <kadams@nvidia.com>
Reviewed-by: Juha Tukkinen <jtukkinen@nvidia.com>

drivers/video/tegra/host/chip_support.h
drivers/video/tegra/host/dmabuf.c
drivers/video/tegra/host/dmabuf.h
drivers/video/tegra/host/nvhost_job.c
drivers/video/tegra/host/nvhost_memmgr.c
drivers/video/tegra/host/nvmap.c
drivers/video/tegra/host/nvmap.h

index 5b8f48e..e6ec905 100644 (file)
@@ -150,6 +150,8 @@ struct nvhost_mem_ops {
        void (*unpin)(struct mem_mgr *, struct mem_handle *, struct sg_table *);
        void *(*mmap)(struct mem_handle *);
        void (*munmap)(struct mem_handle *, void *);
+       void *(*kmap)(struct mem_handle *, unsigned int);
+       void (*kunmap)(struct mem_handle *, unsigned int, void *);
 };
 
 struct nvhost_actmon_ops {
index 68554b0..e275557 100644 (file)
@@ -69,6 +69,17 @@ void nvhost_dmabuf_munmap(struct mem_handle *handle, void *addr)
        dma_buf_vunmap(to_dmabuf(handle), addr);
 }
 
+void *nvhost_dmabuf_kmap(struct mem_handle *handle, unsigned int pagenum)
+{
+       return dma_buf_kmap(to_dmabuf(handle), pagenum);
+}
+
+void nvhost_dmabuf_kunmap(struct mem_handle *handle, unsigned int pagenum,
+               void *addr)
+{
+       dma_buf_kunmap(to_dmabuf(handle), pagenum, addr);
+}
+
 struct mem_handle *nvhost_dmabuf_get(u32 id, struct nvhost_device *dev)
 {
        struct mem_handle *h;
index 0beb1d6..15e297d 100644 (file)
@@ -37,6 +37,9 @@ struct sg_table *nvhost_dmabuf_pin(struct mem_handle *handle);
 void nvhost_dmabuf_unpin(struct mem_handle *handle, struct sg_table *sgt);
 void *nvhost_dmabuf_mmap(struct mem_handle *handle);
 void nvhost_dmabuf_munmap(struct mem_handle *handle, void *addr);
+void *nvhost_dmabuf_kmap(struct mem_handle *handle, unsigned int pagenum);
+void nvhost_dmabuf_kunmap(struct mem_handle *handle, unsigned int pagenum,
+               void *addr);
 int nvhost_dmabuf_get(u32 id, struct nvhost_device *dev);
 
 #endif
index f065594..8211838 100644 (file)
@@ -169,12 +169,15 @@ void nvhost_job_add_gather(struct nvhost_job *job,
        job->num_gathers += 1;
 }
 
-static int do_relocs(struct nvhost_job *job, u32 cmdbuf_mem, void *cmdbuf_addr)
+static int do_relocs(struct nvhost_job *job,
+               u32 cmdbuf_mem, struct mem_handle *h)
 {
        struct sg_table *target_sgt = NULL;
        int i;
        u32 mem_id = 0;
        struct mem_handle *target_ref = NULL;
+       int last_page = -1;
+       void *cmdbuf_page_addr = NULL;
 
        /* pin & patch the relocs for one gather */
        for (i = 0; i < job->num_relocs; i++) {
@@ -203,16 +206,33 @@ static int do_relocs(struct nvhost_job *job, u32 cmdbuf_mem, void *cmdbuf_addr)
                        job->unpins[job->num_unpins++].h = target_ref;
                }
 
+               if (last_page != reloc->cmdbuf_offset >> PAGE_SHIFT) {
+                       if (cmdbuf_page_addr)
+                               mem_op().kunmap(h, last_page, cmdbuf_page_addr);
+
+                       cmdbuf_page_addr = mem_op().kmap(h,
+                                       reloc->cmdbuf_offset >> PAGE_SHIFT);
+                       last_page = reloc->cmdbuf_offset >> PAGE_SHIFT;
+
+                       if (unlikely(!cmdbuf_page_addr)) {
+                               pr_err("Couldn't map cmdbuf for relocation\n");
+                               return -ENOMEM;
+                       }
+               }
+
                __raw_writel(
                        (sg_dma_address(target_sgt->sgl) +
                                reloc->target_offset) >> shift->shift,
-                       (cmdbuf_addr + reloc->cmdbuf_offset));
-
+                       (cmdbuf_page_addr +
+                               (reloc->cmdbuf_offset & ~PAGE_MASK)));
                /* Different gathers might have same mem_id. This ensures we
                 * perform reloc only once per gather memid. */
                reloc->cmdbuf_mem = 0;
        }
 
+       if (cmdbuf_page_addr)
+               mem_op().kunmap(h, last_page, cmdbuf_page_addr);
+
        return 0;
 }
 
@@ -222,7 +242,7 @@ static int do_relocs(struct nvhost_job *job, u32 cmdbuf_mem, void *cmdbuf_addr)
  * avoid a wrap condition in the HW).
  */
 static int do_waitchks(struct nvhost_job *job, struct nvhost_syncpt *sp,
-               u32 patch_mem, void *patch_addr)
+               u32 patch_mem, struct mem_handle *h)
 {
        int i;
 
@@ -239,6 +259,8 @@ static int do_waitchks(struct nvhost_job *job, struct nvhost_syncpt *sp,
                                nvhost_syncpt_read(sp, wait->syncpt_id));
                if (nvhost_syncpt_is_expired(sp,
                                        wait->syncpt_id, wait->thresh)) {
+                       void *patch_addr = NULL;
+
                        /*
                         * NULL an already satisfied WAIT_SYNCPT host method,
                         * by patching its args in the command stream. The
@@ -255,8 +277,18 @@ static int do_waitchks(struct nvhost_job *job, struct nvhost_syncpt *sp,
                            nvhost_syncpt_read_min(sp, wait->syncpt_id));
 
                        /* patch the wait */
-                       nvhost_syncpt_patch_wait(sp,
-                                       (patch_addr + wait->offset));
+                       patch_addr = mem_op().kmap(h,
+                                       wait->offset >> PAGE_SHIFT);
+                       if (patch_addr) {
+                               nvhost_syncpt_patch_wait(sp,
+                                       (patch_addr +
+                                        (wait->offset & ~PAGE_MASK)));
+                               mem_op().kunmap(h,
+                                               wait->offset >> PAGE_SHIFT,
+                                               patch_addr);
+                       } else {
+                               pr_err("Couldn't map cmdbuf for wait check\n");
+                       }
                }
 
                wait->mem = 0;
@@ -268,7 +300,6 @@ int nvhost_job_pin(struct nvhost_job *job, struct nvhost_syncpt *sp)
 {
        int err = 0, i = 0, j = 0;
        struct sg_table *gather_sgt = NULL;
-       void *gather_addr = NULL;
        unsigned long waitchk_mask = job->waitchk_mask;
 
        /* get current syncpt values for waitchk */
@@ -309,17 +340,10 @@ int nvhost_job_pin(struct nvhost_job *job, struct nvhost_syncpt *sp)
                        job->unpins[job->num_unpins].mem = g->mem_sgt;
                        job->unpins[job->num_unpins++].h = g->ref;
 
-                       gather_addr = mem_op().mmap(g->ref);
-                       if (!gather_addr) {
-                               err = -ENOMEM;
-                               break;
-                       }
-
-                       err = do_relocs(job, g->mem_id, gather_addr);
+                       err = do_relocs(job, g->mem_id, g->ref);
                        if (!err)
                                err = do_waitchks(job, sp,
-                                               g->mem_id, gather_addr);
-                       mem_op().munmap(g->ref, gather_addr);
+                                               g->mem_id, g->ref);
 
                        if (err)
                                break;
index 861cd8c..6192917 100644 (file)
@@ -215,6 +215,43 @@ void nvhost_memmgr_munmap(struct mem_handle *handle, void *addr)
        }
 }
 
+void *nvhost_memmgr_kmap(struct mem_handle *handle, unsigned int pagenum)
+{
+       switch (nvhost_memmgr_type((u32)handle)) {
+#ifdef CONFIG_TEGRA_GRHOST_USE_NVMAP
+       case mem_mgr_type_nvmap:
+               return nvhost_nvmap_kmap(handle, pagenum);
+               break;
+#endif
+#ifdef CONFIG_TEGRA_GRHOST_USE_DMABUF
+       case mem_mgr_type_dmabuf:
+               return nvhost_dmabuf_kmap(handle, pagenum);
+               break;
+#endif
+       default:
+               return 0;
+               break;
+       }
+}
+
+void nvhost_memmgr_kunmap(struct mem_handle *handle, unsigned int pagenum,
+               void *addr)
+{
+       switch (nvhost_memmgr_type((u32)handle)) {
+#ifdef CONFIG_TEGRA_GRHOST_USE_NVMAP
+       case mem_mgr_type_nvmap:
+               nvhost_nvmap_kunmap(handle, pagenum, addr);
+               break;
+#endif
+#ifdef CONFIG_TEGRA_GRHOST_USE_DMABUF
+       case mem_mgr_type_dmabuf:
+               nvhost_dmabuf_kunmap(handle, pagenum, addr);
+               break;
+#endif
+       default:
+               break;
+       }
+}
 static const struct nvhost_mem_ops mem_ops = {
        .alloc_mgr = nvhost_memmgr_alloc_mgr,
        .put_mgr = nvhost_memmgr_put_mgr,
@@ -227,6 +264,8 @@ static const struct nvhost_mem_ops mem_ops = {
        .unpin = nvhost_memmgr_unpin,
        .mmap = nvhost_memmgr_mmap,
        .munmap = nvhost_memmgr_munmap,
+       .kmap = nvhost_memmgr_kmap,
+       .kunmap = nvhost_memmgr_kunmap,
 };
 
 int nvhost_memmgr_init(struct nvhost_chip_support *chip)
index 44fc3ed..9b00147 100644 (file)
@@ -106,6 +106,17 @@ void nvhost_nvmap_munmap(struct mem_handle *handle, void *addr)
        nvmap_munmap((struct nvmap_handle_ref *)handle, addr);
 }
 
+void *nvhost_nvmap_kmap(struct mem_handle *handle, unsigned int pagenum)
+{
+       return nvmap_kmap((struct nvmap_handle_ref *)handle, pagenum);
+}
+
+void nvhost_nvmap_kunmap(struct mem_handle *handle, unsigned int pagenum,
+               void *addr)
+{
+       nvmap_kunmap((struct nvmap_handle_ref *)handle, pagenum, addr);
+}
+
 struct mem_handle *nvhost_nvmap_get(struct mem_mgr *mgr,
                u32 id, struct nvhost_device *dev)
 {
index 1bf1882..31b1554 100644 (file)
@@ -40,6 +40,9 @@ void nvhost_nvmap_unpin(struct mem_mgr *mgr,
                struct mem_handle *handle, struct sg_table *sgt);
 void *nvhost_nvmap_mmap(struct mem_handle *handle);
 void nvhost_nvmap_munmap(struct mem_handle *handle, void *addr);
+void *nvhost_nvmap_kmap(struct mem_handle *handle, unsigned int pagenum);
+void nvhost_nvmap_kunmap(struct mem_handle *handle, unsigned int pagenum,
+               void *addr);
 struct mem_handle *nvhost_nvmap_get(struct mem_mgr *mgr,
                u32 id, struct nvhost_device *dev);