diff options
author | Rebecca Schultz Zavin <rebecca@android.com> | 2010-10-27 20:52:19 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:36:35 -0800 |
commit | 67f79a61b1f528981476b3f9e08e55cd85337958 (patch) | |
tree | 4052ee0d814563aedecf4e3ff92dc522fac99231 /drivers/video/tegra/nvmap/nvmap_handle.c | |
parent | f1a0750d6acc558dfb688d179e5cd9add2819334 (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.c | 16 |
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); |