summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAlex Waterman <alexw@nvidia.com>2013-11-13 11:58:32 -0800
committerHiroshi Doyu <hdoyu@nvidia.com>2014-03-11 22:49:34 -0700
commitfdec8f268bc9968e054955123fd7dad7128d5c8a (patch)
treed217ac1ebcfac2ff226082e947da7c4e68b93f21 /drivers
parentb36bd3ecf8ebb3c6a748f8cdc7fe5c80bfbcb616 (diff)
video: tegra: nvmap: implement new cache operation
Provide the ability to flush a list of handles. This code will optimize the cache flush to be full inner/outer flushes if the total size of the passed list of handles exceeds the inner cache maintenance threshold. Bug 1373180 Change-Id: I357b5d5d1a9697aa6487ad6ef6723448a368a45b Signed-off-by: Alex Waterman <alexw@nvidia.com> Signed-off-by: Sri Krishna chowdary <schowdary@nvidia.com> Reviewed-on: http://git-master/r/330638 Reviewed-by: Hiroshi Doyu <hdoyu@nvidia.com> Tested-by: Hiroshi Doyu <hdoyu@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/tegra/nvmap/nvmap_dmabuf.c6
-rw-r--r--drivers/video/tegra/nvmap/nvmap_ioctl.c74
-rw-r--r--drivers/video/tegra/nvmap/nvmap_mm.c38
-rw-r--r--drivers/video/tegra/nvmap/nvmap_priv.h8
4 files changed, 87 insertions, 39 deletions
diff --git a/drivers/video/tegra/nvmap/nvmap_dmabuf.c b/drivers/video/tegra/nvmap/nvmap_dmabuf.c
index 370a6c702b26..46f4f63ca45a 100644
--- a/drivers/video/tegra/nvmap/nvmap_dmabuf.c
+++ b/drivers/video/tegra/nvmap/nvmap_dmabuf.c
@@ -458,8 +458,8 @@ static int nvmap_dmabuf_begin_cpu_access(struct dma_buf *dmabuf,
struct nvmap_handle_info *info = dmabuf->priv;
trace_nvmap_dmabuf_begin_cpu_access(dmabuf, start, len);
- return __nvmap_cache_maint(NULL, info->handle, start, start + len,
- NVMAP_CACHE_OP_INV, 1);
+ return __nvmap_do_cache_maint(NULL, info->handle, start, start + len,
+ NVMAP_CACHE_OP_INV, 1);
}
static void nvmap_dmabuf_end_cpu_access(struct dma_buf *dmabuf,
@@ -469,7 +469,7 @@ static void nvmap_dmabuf_end_cpu_access(struct dma_buf *dmabuf,
struct nvmap_handle_info *info = dmabuf->priv;
trace_nvmap_dmabuf_end_cpu_access(dmabuf, start, len);
- __nvmap_cache_maint(NULL, info->handle, start, start + len,
+ __nvmap_do_cache_maint(NULL, info->handle, start, start + len,
NVMAP_CACHE_OP_WB_INV, 1);
}
diff --git a/drivers/video/tegra/nvmap/nvmap_ioctl.c b/drivers/video/tegra/nvmap/nvmap_ioctl.c
index b449d40051fe..5a89be557860 100644
--- a/drivers/video/tegra/nvmap/nvmap_ioctl.c
+++ b/drivers/video/tegra/nvmap/nvmap_ioctl.c
@@ -646,13 +646,9 @@ int nvmap_ioctl_rw_handle(struct file *filp, int is_read, void __user *arg,
return err;
}
-int nvmap_ioctl_cache_maint(struct file *filp, void __user *arg, bool is32)
+static int __nvmap_cache_maint(struct nvmap_client *client,
+ struct nvmap_cache_op *op)
{
- struct nvmap_client *client = filp->private_data;
- struct nvmap_cache_op op;
-#ifdef CONFIG_COMPAT
- struct nvmap_cache_op_32 op32;
-#endif
struct vm_area_struct *vma;
struct nvmap_vma_priv *vpriv;
struct nvmap_handle *handle;
@@ -660,31 +656,18 @@ int nvmap_ioctl_cache_maint(struct file *filp, void __user *arg, bool is32)
unsigned long end;
int err = 0;
-#ifdef CONFIG_COMPAT
- if (is32) {
- if (copy_from_user(&op32, arg, sizeof(op32)))
- return -EFAULT;
- op.addr = op32.addr;
- op.handle = op32.handle;
- op.len = op32.len;
- op.op = op32.op;
- } else
-#endif
- if (copy_from_user(&op, arg, sizeof(op)))
- return -EFAULT;
-
- handle = unmarshal_user_handle(op.handle);
- if (!handle || !op.addr || op.op < NVMAP_CACHE_OP_WB ||
- op.op > NVMAP_CACHE_OP_WB_INV)
+ handle = unmarshal_user_handle(op->handle);
+ if (!handle || !op->addr || op->op < NVMAP_CACHE_OP_WB ||
+ op->op > NVMAP_CACHE_OP_WB_INV)
return -EINVAL;
down_read(&current->mm->mmap_sem);
- vma = find_vma(current->active_mm, op.addr);
+ vma = find_vma(current->active_mm, (unsigned long)op->addr);
if (!vma || !is_nvmap_vma(vma) ||
- (ulong)op.addr < vma->vm_start ||
- (ulong)op.addr >= vma->vm_end ||
- op.len > vma->vm_end - (ulong)op.addr) {
+ (ulong)op->addr < vma->vm_start ||
+ (ulong)op->addr >= vma->vm_end ||
+ op->len > vma->vm_end - (ulong)op->addr) {
err = -EADDRNOTAVAIL;
goto out;
}
@@ -696,16 +679,41 @@ int nvmap_ioctl_cache_maint(struct file *filp, void __user *arg, bool is32)
goto out;
}
- start = op.addr - vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT);
- end = start + op.len;
+ start = (unsigned long)op->addr - vma->vm_start +
+ (vma->vm_pgoff << PAGE_SHIFT);
+ end = start + op->len;
- err = __nvmap_cache_maint(client, vpriv->handle, start, end, op.op,
- CACHE_MAINT_ALLOW_DEFERRED);
+ err = __nvmap_do_cache_maint(client, vpriv->handle, start, end, op->op,
+ CACHE_MAINT_ALLOW_DEFERRED);
out:
up_read(&current->mm->mmap_sem);
return err;
}
+int nvmap_ioctl_cache_maint(struct file *filp, void __user *arg, bool is32)
+{
+ struct nvmap_client *client = filp->private_data;
+ struct nvmap_cache_op op;
+#ifdef CONFIG_COMPAT
+ struct nvmap_cache_op_32 op32;
+#endif
+
+#ifdef CONFIG_COMPAT
+ if (is32) {
+ if (copy_from_user(&op32, arg, sizeof(op32)))
+ return -EFAULT;
+ op.addr = op32.addr;
+ op.handle = op32.handle;
+ op.len = op32.len;
+ op.op = op32.op;
+ } else
+#endif
+ if (copy_from_user(&op, arg, sizeof(op)))
+ return -EFAULT;
+
+ return __nvmap_cache_maint(client, &op);
+}
+
int nvmap_ioctl_free(struct file *filp, unsigned long arg)
{
struct nvmap_client *client = filp->private_data;
@@ -938,7 +946,7 @@ out:
return err;
}
-int __nvmap_cache_maint(struct nvmap_client *client,
+int __nvmap_do_cache_maint(struct nvmap_client *client,
struct nvmap_handle *h,
unsigned long start, unsigned long end,
unsigned int op, unsigned int allow_deferred)
@@ -1048,7 +1056,7 @@ static ssize_t rw_handle(struct nvmap_client *client, struct nvmap_handle *h,
break;
}
if (is_read)
- __nvmap_cache_maint(client, h, h_offs,
+ __nvmap_do_cache_maint(client, h, h_offs,
h_offs + elem_size, NVMAP_CACHE_OP_INV,
CACHE_MAINT_IMMEDIATE);
@@ -1059,7 +1067,7 @@ static ssize_t rw_handle(struct nvmap_client *client, struct nvmap_handle *h,
break;
if (!is_read)
- __nvmap_cache_maint(client, h, h_offs,
+ __nvmap_do_cache_maint(client, h, h_offs,
h_offs + elem_size, NVMAP_CACHE_OP_WB_INV,
CACHE_MAINT_IMMEDIATE);
diff --git a/drivers/video/tegra/nvmap/nvmap_mm.c b/drivers/video/tegra/nvmap/nvmap_mm.c
index 2af163279fc7..fd29f8b551a9 100644
--- a/drivers/video/tegra/nvmap/nvmap_mm.c
+++ b/drivers/video/tegra/nvmap/nvmap_mm.c
@@ -83,3 +83,41 @@ void nvmap_flush_cache(struct page **pages, int numpages)
#endif
}
}
+
+/*
+ * Flush the list of passed handles. This will optimze the flush if it can.
+ * In the case that all the handles together are larger than the inner cache
+ * maint threshold it is possible to just do an entire inner cache flush.
+ */
+int nvmap_flush_cache_list(struct nvmap_handle **handles, int nr)
+{
+ int i, err = 0;
+ u64 total = 0;
+
+ for (i = 0; i < nr; i++)
+ total += handles[i]->size;
+
+ /* Full flush in the case the passed list is bigger than our
+ * threshold. */
+ if (total >= cache_maint_inner_threshold) {
+ inner_flush_cache_all();
+ outer_flush_all();
+ nvmap_stats_inc(NS_CFLUSH_RQ, total);
+ nvmap_stats_inc(NS_CFLUSH_DONE, cache_maint_inner_threshold);
+ trace_nvmap_cache_flush(total,
+ nvmap_stats_read(NS_ALLOC),
+ nvmap_stats_read(NS_CFLUSH_RQ),
+ nvmap_stats_read(NS_CFLUSH_DONE));
+ } else {
+ for (i = 0; i < nr; i++) {
+ err = __nvmap_do_cache_maint(handles[i]->owner,
+ handles[i], 0,
+ handles[i]->size,
+ NVMAP_CACHE_OP_WB_INV, 0);
+ if (err)
+ break;
+ }
+ }
+
+ return err;
+}
diff --git a/drivers/video/tegra/nvmap/nvmap_priv.h b/drivers/video/tegra/nvmap/nvmap_priv.h
index 13be4a1aa1f0..22e2df786442 100644
--- a/drivers/video/tegra/nvmap/nvmap_priv.h
+++ b/drivers/video/tegra/nvmap/nvmap_priv.h
@@ -410,6 +410,8 @@ void inner_flush_cache_all(void);
void inner_clean_cache_all(void);
void nvmap_flush_cache(struct page **pages, int numpages);
+int nvmap_flush_cache_list(struct nvmap_handle **handles, int nr);
+
/* Internal API to support dmabuf */
struct dma_buf *__nvmap_dmabuf_export(struct nvmap_client *client,
struct nvmap_handle *handle);
@@ -426,9 +428,9 @@ void __nvmap_munmap(struct nvmap_handle *h, void *addr);
int __nvmap_map(struct nvmap_handle *h, struct vm_area_struct *vma);
int __nvmap_get_handle_param(struct nvmap_client *client,
struct nvmap_handle *h, u32 param, u64 *result);
-int __nvmap_cache_maint(struct nvmap_client *client, struct nvmap_handle *h,
- unsigned long start, unsigned long end,
- unsigned int op, unsigned int allow_deferred);
+int __nvmap_do_cache_maint(struct nvmap_client *client, struct nvmap_handle *h,
+ unsigned long start, unsigned long end,
+ unsigned int op, unsigned int allow_deferred);
struct nvmap_client *__nvmap_create_client(struct nvmap_device *dev,
const char *name);
struct dma_buf *__nvmap_dmabuf_export_from_ref(struct nvmap_handle_ref *ref);