summaryrefslogtreecommitdiff
path: root/drivers/video/tegra/nvmap/nvmap_handle.c
diff options
context:
space:
mode:
authorRebecca Schultz Zavin <rebecca@android.com>2010-10-27 20:52:19 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:36:35 -0800
commit67f79a61b1f528981476b3f9e08e55cd85337958 (patch)
tree4052ee0d814563aedecf4e3ff92dc522fac99231 /drivers/video/tegra/nvmap/nvmap_handle.c
parentf1a0750d6acc558dfb688d179e5cd9add2819334 (diff)
video: tegra: nvmap: Fix handle ref counting
In the current implementation handles hold references to a client and clients hold references to their handles. As a result when a process terminates it's handles can't be cleaned up and we leak memory. Instead only hold references to handles from clients. Change-Id: Iba699e740a043deaf0a78b13b4ea01544675078f Signed-off-by: Rebecca Schultz Zavin <rebecca@android.com>
Diffstat (limited to 'drivers/video/tegra/nvmap/nvmap_handle.c')
-rw-r--r--drivers/video/tegra/nvmap/nvmap_handle.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/drivers/video/tegra/nvmap/nvmap_handle.c b/drivers/video/tegra/nvmap/nvmap_handle.c
index be130b4be757..09502bff4883 100644
--- a/drivers/video/tegra/nvmap/nvmap_handle.c
+++ b/drivers/video/tegra/nvmap/nvmap_handle.c
@@ -71,19 +71,21 @@ static inline void altfree(void *ptr, size_t len)
void _nvmap_handle_free(struct nvmap_handle *h)
{
- struct nvmap_client *client = h->owner;
+ struct nvmap_device *dev = h->dev;
unsigned int i, nr_page;
- if (nvmap_handle_remove(client->dev, h) != 0)
+ if (nvmap_handle_remove(dev, h) != 0)
return;
if (!h->alloc)
goto out;
if (!h->heap_pgalloc) {
- nvmap_carveout_commit_subtract(client,
+ mutex_lock(&h->lock);
+ nvmap_carveout_commit_subtract(h->owner,
nvmap_heap_to_arg(nvmap_block_to_heap(h->carveout)),
h->size);
+ mutex_unlock(&h->lock);
nvmap_heap_free(h->carveout);
goto out;
}
@@ -93,7 +95,8 @@ void _nvmap_handle_free(struct nvmap_handle *h)
BUG_ON(h->size & ~PAGE_MASK);
BUG_ON(!h->pgalloc.pages);
- nvmap_mru_remove(client->share, h);
+ nvmap_mru_remove(nvmap_get_share_from_dev(dev), h);
+
if (h->pgalloc.area)
tegra_iovmm_free_vm(h->pgalloc.area);
@@ -104,7 +107,6 @@ void _nvmap_handle_free(struct nvmap_handle *h)
out:
kfree(h);
- nvmap_client_put(client);
}
extern void __flush_dcache_page(struct address_space *, struct page *);
@@ -423,10 +425,12 @@ struct nvmap_handle_ref *nvmap_create_handle(struct nvmap_client *client,
atomic_set(&h->ref, 1);
atomic_set(&h->pin, 0);
- h->owner = nvmap_client_get(client);
+ h->owner = client;
+ h->dev = client->dev;
BUG_ON(!h->owner);
h->size = h->orig_size = size;
h->flags = NVMAP_HANDLE_WRITE_COMBINE;
+ mutex_init(&h->lock);
nvmap_handle_add(client->dev, h);