summaryrefslogtreecommitdiff
path: root/drivers/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/tegra/nvmap/nvmap_dev.c56
-rw-r--r--drivers/video/tegra/nvmap/nvmap_handle.c2
-rw-r--r--drivers/video/tegra/nvmap/nvmap_ioctl.c33
-rw-r--r--drivers/video/tegra/nvmap/nvmap_mm.c2
-rw-r--r--drivers/video/tegra/nvmap/nvmap_priv.h2
5 files changed, 41 insertions, 54 deletions
diff --git a/drivers/video/tegra/nvmap/nvmap_dev.c b/drivers/video/tegra/nvmap/nvmap_dev.c
index 4b2e9f3641f2..6ae8e7190855 100644
--- a/drivers/video/tegra/nvmap/nvmap_dev.c
+++ b/drivers/video/tegra/nvmap/nvmap_dev.c
@@ -542,21 +542,10 @@ int __nvmap_map(struct nvmap_handle *h, struct vm_area_struct *vma)
static int nvmap_map(struct file *filp, struct vm_area_struct *vma)
{
- struct nvmap_vma_priv *priv;
-
- /* after NVMAP_IOC_MMAP, the handle that is mapped by this VMA
- * will be stored in vm_private_data and faulted in. until the
- * ioctl is made, the VMA is mapped no-access */
- vma->vm_private_data = NULL;
-
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
+ BUG_ON(vma->vm_private_data != NULL);
vma->vm_flags |= (VM_SHARED | VM_DONTEXPAND |
VM_DONTDUMP | VM_DONTCOPY);
vma->vm_ops = &nvmap_vma_ops;
- vma->vm_private_data = priv;
return 0;
}
@@ -689,61 +678,60 @@ void nvmap_vma_open(struct vm_area_struct *vma)
{
struct nvmap_vma_priv *priv;
struct nvmap_handle *h;
- struct nvmap_vma_list *vma_list;
+ struct nvmap_vma_list *vma_list, *tmp;
priv = vma->vm_private_data;
BUG_ON(!priv);
BUG_ON(!priv->handle);
+ atomic_inc(&priv->count);
h = priv->handle;
- if (h->heap_pgalloc) {
- vma_list = kmalloc(sizeof(*vma_list), GFP_KERNEL);
- if (!vma_list) {
- WARN(1, "vma not tracked");
- goto finish;
- }
- vma_list->vma = vma;
- INIT_LIST_HEAD(&vma_list->list);
+
+ vma_list = kmalloc(sizeof(*vma_list), GFP_KERNEL);
+ if (vma_list) {
mutex_lock(&h->lock);
- list_add(&vma_list->list, &h->pgalloc.vmas);
+ list_for_each_entry(tmp, &h->vmas, list)
+ BUG_ON(tmp->vma == vma);
+
+ vma_list->vma = vma;
+ list_add(&vma_list->list, &h->vmas);
mutex_unlock(&h->lock);
+ } else {
+ WARN(1, "vma not tracked");
}
-
-finish:
- atomic_inc(&priv->count);
}
static void nvmap_vma_close(struct vm_area_struct *vma)
{
struct nvmap_vma_priv *priv = vma->vm_private_data;
- struct nvmap_vma_list *vma_list, *tmp;
+ struct nvmap_vma_list *vma_list;
struct nvmap_handle *h;
+ bool vma_found = false;
if (!priv)
- goto finish;
+ return;
- if (!priv->handle || !priv->handle->heap_pgalloc)
- goto try_to_free_priv;
+ BUG_ON(!priv->handle);
h = priv->handle;
mutex_lock(&h->lock);
- list_for_each_entry_safe(vma_list, tmp, &h->pgalloc.vmas, list) {
+ list_for_each_entry(vma_list, &h->vmas, list) {
if (vma_list->vma != vma)
continue;
list_del(&vma_list->list);
kfree(vma_list);
+ vma_found = true;
break;
}
+ BUG_ON(!vma_found);
mutex_unlock(&h->lock);
-try_to_free_priv:
- if (!atomic_dec_return(&priv->count)) {
+ if (__atomic_add_unless(&priv->count, -1, 0) == 1) {
if (priv->handle)
nvmap_handle_put(priv->handle);
+ vma->vm_private_data = NULL;
kfree(priv);
}
-finish:
- vma->vm_private_data = NULL;
}
static int nvmap_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
diff --git a/drivers/video/tegra/nvmap/nvmap_handle.c b/drivers/video/tegra/nvmap/nvmap_handle.c
index cdbf6ee65fad..0959a98d5bf4 100644
--- a/drivers/video/tegra/nvmap/nvmap_handle.c
+++ b/drivers/video/tegra/nvmap/nvmap_handle.c
@@ -229,7 +229,6 @@ static int handle_page_alloc(struct nvmap_client *client,
h->size = size;
h->pgalloc.pages = pages;
h->pgalloc.contig = contiguous;
- INIT_LIST_HEAD(&h->pgalloc.vmas);
atomic_set(&h->pgalloc.ndirty, 0);
return 0;
@@ -510,6 +509,7 @@ struct nvmap_handle_ref *nvmap_create_handle(struct nvmap_client *client,
h->size = h->orig_size = size;
h->flags = NVMAP_HANDLE_WRITE_COMBINE;
mutex_init(&h->lock);
+ INIT_LIST_HEAD(&h->vmas);
/*
* This takes out 1 ref on the dambuf. This corresponds to the
diff --git a/drivers/video/tegra/nvmap/nvmap_ioctl.c b/drivers/video/tegra/nvmap/nvmap_ioctl.c
index a3d39f509633..d9853e179f85 100644
--- a/drivers/video/tegra/nvmap/nvmap_ioctl.c
+++ b/drivers/video/tegra/nvmap/nvmap_ioctl.c
@@ -425,7 +425,7 @@ int nvmap_map_into_caller_ptr(struct file *filp, void __user *arg, bool is32)
#ifdef CONFIG_COMPAT
struct nvmap_map_caller_32 op32;
#endif
- struct nvmap_vma_priv *vpriv;
+ struct nvmap_vma_priv *priv;
struct vm_area_struct *vma;
struct nvmap_handle *h = NULL;
int err = 0;
@@ -464,7 +464,7 @@ int nvmap_map_into_caller_ptr(struct file *filp, void __user *arg, bool is32)
down_read(&current->mm->mmap_sem);
vma = find_vma(current->mm, op.addr);
- if (!vma || !vma->vm_private_data) {
+ if (!vma) {
err = -ENOMEM;
goto out;
}
@@ -479,9 +479,6 @@ int nvmap_map_into_caller_ptr(struct file *filp, void __user *arg, bool is32)
goto out;
}
- vpriv = vma->vm_private_data;
- BUG_ON(!vpriv);
-
/* the VMA must exactly match the requested mapping operation, and the
* VMA that is targetted must have been created by this driver
*/
@@ -492,22 +489,24 @@ int nvmap_map_into_caller_ptr(struct file *filp, void __user *arg, bool is32)
}
/* verify that each mmap() system call creates a unique VMA */
-
- if (vpriv->handle && (h == vpriv->handle)) {
+ if (vma->vm_private_data)
goto out;
- } else if (vpriv->handle) {
- err = -EADDRNOTAVAIL;
- goto out;
- }
if (!h->heap_pgalloc && (h->carveout->base & ~PAGE_MASK)) {
err = -EFAULT;
goto out;
}
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ err = -ENOMEM;
+ goto out;
+ }
+
vma->vm_flags |= (h->heap_pgalloc ? 0 : VM_PFNMAP);
- vpriv->handle = h;
- vpriv->offs = op.offset;
+ priv->handle = h;
+ priv->offs = op.offset;
+ vma->vm_private_data = priv;
vma->vm_page_prot = nvmap_pgprot(h, vma->vm_page_prot);
nvmap_vma_open(vma);
@@ -640,7 +639,7 @@ static int __nvmap_cache_maint(struct nvmap_client *client,
struct nvmap_cache_op *op)
{
struct vm_area_struct *vma;
- struct nvmap_vma_priv *vpriv;
+ struct nvmap_vma_priv *priv;
struct nvmap_handle *handle;
unsigned long start;
unsigned long end;
@@ -662,9 +661,9 @@ static int __nvmap_cache_maint(struct nvmap_client *client,
goto out;
}
- vpriv = (struct nvmap_vma_priv *)vma->vm_private_data;
+ priv = (struct nvmap_vma_priv *)vma->vm_private_data;
- if (vpriv->handle != handle) {
+ if (priv->handle != handle) {
err = -EFAULT;
goto out;
}
@@ -673,7 +672,7 @@ static int __nvmap_cache_maint(struct nvmap_client *client,
(vma->vm_pgoff << PAGE_SHIFT);
end = start + op->len;
- err = __nvmap_do_cache_maint(client, vpriv->handle, start, end, op->op,
+ err = __nvmap_do_cache_maint(client, priv->handle, start, end, op->op,
false);
out:
up_read(&current->mm->mmap_sem);
diff --git a/drivers/video/tegra/nvmap/nvmap_mm.c b/drivers/video/tegra/nvmap/nvmap_mm.c
index 16265859ecd2..942394c23f78 100644
--- a/drivers/video/tegra/nvmap/nvmap_mm.c
+++ b/drivers/video/tegra/nvmap/nvmap_mm.c
@@ -190,7 +190,7 @@ void nvmap_zap_handle(struct nvmap_handle *handle, u32 offset, u32 size)
size = PAGE_ALIGN((offset & ~PAGE_MASK) + size);
mutex_lock(&handle->lock);
- vmas = &handle->pgalloc.vmas;
+ vmas = &handle->vmas;
list_for_each_entry(vma_list, vmas, list) {
struct nvmap_vma_priv *priv;
u32 vm_size = size;
diff --git a/drivers/video/tegra/nvmap/nvmap_priv.h b/drivers/video/tegra/nvmap/nvmap_priv.h
index 79a957881689..7489263c8c62 100644
--- a/drivers/video/tegra/nvmap/nvmap_priv.h
+++ b/drivers/video/tegra/nvmap/nvmap_priv.h
@@ -105,7 +105,6 @@ struct nvmap_vma_list {
struct nvmap_pgalloc {
struct page **pages;
bool contig; /* contiguous system memory */
- struct list_head vmas;
atomic_t ndirty; /* count number of dirty pages */
};
@@ -135,6 +134,7 @@ struct nvmap_handle {
bool alloc; /* handle has memory allocated */
u32 userflags; /* flags passed from userspace */
void *vaddr; /* mapping used inside kernel */
+ struct list_head vmas; /* list of all user vma's */
struct mutex lock;
void *nvhost_priv; /* nvhost private data */
void (*nvhost_priv_delete)(void *priv);