diff options
Diffstat (limited to 'drivers/video/tegra/nvmap/nvmap_ioctl.c')
-rw-r--r-- | drivers/video/tegra/nvmap/nvmap_ioctl.c | 58 |
1 files changed, 45 insertions, 13 deletions
diff --git a/drivers/video/tegra/nvmap/nvmap_ioctl.c b/drivers/video/tegra/nvmap/nvmap_ioctl.c index 44f00d2951a0..da974b2c6846 100644 --- a/drivers/video/tegra/nvmap/nvmap_ioctl.c +++ b/drivers/video/tegra/nvmap/nvmap_ioctl.c @@ -3,7 +3,7 @@ * * User-space interface to nvmap * - * Copyright (c) 2011, NVIDIA Corporation. + * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -65,10 +65,10 @@ int nvmap_ioctl_pinop(struct file *filp, bool is_pin, void __user *arg) return -EINVAL; if (op.count > 1) { - size_t bytes = op.count * sizeof(unsigned long *); + size_t bytes = op.count * sizeof(*refs); /* kcalloc below will catch overflow. */ if (op.count > ARRAY_SIZE(on_stack)) - refs = kmalloc(op.count * sizeof(*refs), GFP_KERNEL); + refs = kcalloc(op.count, sizeof(*refs), GFP_KERNEL); else refs = on_stack; @@ -175,6 +175,9 @@ int nvmap_ioctl_alloc(struct file *filp, void __user *arg) /* user-space handles are aligned to page boundaries, to prevent * data leakage. */ op.align = max_t(size_t, op.align, PAGE_SIZE); +#if defined(CONFIG_NVMAP_FORCE_ZEROED_USER_PAGES) + op.flags |= NVMAP_HANDLE_ZEROED_PAGES; +#endif return nvmap_alloc_handle_id(client, op.handle, op.heap_mask, op.align, op.flags); @@ -236,6 +239,11 @@ int nvmap_map_into_caller_ptr(struct file *filp, void __user *arg) if (!h) return -EPERM; + if(!h->alloc) { + nvmap_handle_put(h); + return -EFAULT; + } + trace_nvmap_map_into_caller_ptr(client, h, op.offset, op.length, op.flags); down_read(¤t->mm->mmap_sem); @@ -251,7 +259,7 @@ int nvmap_map_into_caller_ptr(struct file *filp, void __user *arg) goto out; } - if ((op.offset + op.length) > h->size) { + if (op.offset > h->size || (op.offset + op.length) > h->size) { err = -EADDRNOTAVAIL; goto out; } @@ -542,14 +550,32 @@ static void heap_page_cache_maint(struct nvmap_client *client, } } +static bool fast_cache_maint_outer(unsigned long start, + unsigned long end, unsigned int op) +{ + bool result = false; +#if defined(CONFIG_NVMAP_OUTER_CACHE_MAINT_BY_SET_WAYS) + if (end - start >= FLUSH_CLEAN_BY_SET_WAY_THRESHOLD_OUTER) { + if (op == NVMAP_CACHE_OP_WB_INV) { + outer_flush_all(); + result = true; + } + if (op == NVMAP_CACHE_OP_WB) { + outer_clean_all(); + result = true; + } + } +#endif + return result; +} + static bool fast_cache_maint(struct nvmap_client *client, struct nvmap_handle *h, unsigned long start, unsigned long end, unsigned int op) { int ret = false; - #if defined(CONFIG_NVMAP_CACHE_MAINT_BY_SET_WAYS) if ((op == NVMAP_CACHE_OP_INV) || - ((end - start) < FLUSH_CLEAN_BY_SET_WAY_THRESHOLD)) + ((end - start) < FLUSH_CLEAN_BY_SET_WAY_THRESHOLD_INNER)) goto out; if (op == NVMAP_CACHE_OP_WB_INV) @@ -557,13 +583,19 @@ static bool fast_cache_maint(struct nvmap_client *client, struct nvmap_handle *h else if (op == NVMAP_CACHE_OP_WB) inner_clean_cache_all(); - if (h->heap_pgalloc && (h->flags != NVMAP_HANDLE_INNER_CACHEABLE)) { - heap_page_cache_maint(client, h, start, end, op, - false, true, NULL, 0, 0); - } else if (h->flags != NVMAP_HANDLE_INNER_CACHEABLE) { - start += h->carveout->base; - end += h->carveout->base; - outer_cache_maint(op, start, end - start); + /* outer maintenance */ + if (h->flags != NVMAP_HANDLE_INNER_CACHEABLE ) { + if(!fast_cache_maint_outer(start, end, op)) + { + if (h->heap_pgalloc) { + heap_page_cache_maint(client, h, start, + end, op, false, true, NULL, 0, 0); + } else { + start += h->carveout->base; + end += h->carveout->base; + outer_cache_maint(op, start, end - start); + } + } } ret = true; out: |