diff options
author | vdumpa <vdumpa@nvidia.com> | 2011-05-15 19:31:15 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:45:04 -0800 |
commit | 546fb49a3cf459dc5de4c015987390ed221412eb (patch) | |
tree | 3982b86ca987b201fe9fb22c7fbab759024387f6 /drivers/video/tegra/nvmap | |
parent | 91985ba2716065d11974e6140b1febf4f93f0f55 (diff) |
video: tegra: nvmap: Add support to allocate specific IOVM
Original-Change-Id: I95cdf71e74947d4394e0cfd272a29c47562d4059
Reviewed-on: http://git-master/r/31648
Reviewed-by: Niket Sirsi <nsirsi@nvidia.com>
Tested-by: Niket Sirsi <nsirsi@nvidia.com>
Rebase-Id: Rb8c6f92bdfd0bf124a878800a793828fa61c0043
Diffstat (limited to 'drivers/video/tegra/nvmap')
-rw-r--r-- | drivers/video/tegra/nvmap/nvmap.c | 47 | ||||
-rw-r--r-- | drivers/video/tegra/nvmap/nvmap.h | 6 | ||||
-rw-r--r-- | drivers/video/tegra/nvmap/nvmap_handle.c | 3 | ||||
-rw-r--r-- | drivers/video/tegra/nvmap/nvmap_mru.c | 9 |
4 files changed, 62 insertions, 3 deletions
diff --git a/drivers/video/tegra/nvmap/nvmap.c b/drivers/video/tegra/nvmap/nvmap.c index 09627145ec82..06ce0767e3ee 100644 --- a/drivers/video/tegra/nvmap/nvmap.c +++ b/drivers/video/tegra/nvmap/nvmap.c @@ -725,6 +725,53 @@ struct nvmap_handle_ref *nvmap_alloc(struct nvmap_client *client, size_t size, return r; } +/* allocates memory with specifed iovm_start address. */ +struct nvmap_handle_ref *nvmap_alloc_iovm(struct nvmap_client *client, + size_t size, size_t align, unsigned int flags, unsigned int iovm_start) +{ + int err; + struct nvmap_handle *h; + struct nvmap_handle_ref *r; + const unsigned int default_heap = NVMAP_HEAP_IOVMM; + + /* size need to be more than one page. + * otherwise heap preference would change to system heap. + */ + if (size <= PAGE_SIZE) + size = PAGE_SIZE << 1; + r = nvmap_create_handle(client, size); + if (IS_ERR_OR_NULL(r)) + return r; + + h = r->handle; + h->pgalloc.iovm_addr = iovm_start; + err = nvmap_alloc_handle_id(client, nvmap_ref_to_id(r), + default_heap, align, flags); + if (err) + goto fail; + + err = mutex_lock_interruptible(&client->share->pin_lock); + if (WARN_ON(err)) + goto fail; + err = pin_locked(client, h); + mutex_unlock(&client->share->pin_lock); + if (err) + goto fail; + return r; + +fail: + nvmap_free_handle_id(client, nvmap_ref_to_id(r)); + return ERR_PTR(err); +} + +void nvmap_free_iovm(struct nvmap_client *client, struct nvmap_handle_ref *r) +{ + unsigned long ref_id = nvmap_ref_to_id(r); + + nvmap_unpin_ids(client, 1, &ref_id); + nvmap_free_handle_id(client, ref_id); +} + void nvmap_free(struct nvmap_client *client, struct nvmap_handle_ref *r) { nvmap_free_handle_id(client, nvmap_ref_to_id(r)); diff --git a/drivers/video/tegra/nvmap/nvmap.h b/drivers/video/tegra/nvmap/nvmap.h index 713e6f4e2926..8f5c477b793c 100644 --- a/drivers/video/tegra/nvmap/nvmap.h +++ b/drivers/video/tegra/nvmap/nvmap.h @@ -61,6 +61,7 @@ struct nvmap_pgalloc { struct list_head mru_list; /* MRU entry for IOVMM reclamation */ bool contig; /* contiguous system memory */ bool dirty; /* area is invalid and needs mapping */ + u32 iovm_addr; /* is non-zero, if client need specific iova mapping */ }; struct nvmap_handle { @@ -239,4 +240,9 @@ static inline pgprot_t nvmap_pgprot(struct nvmap_handle *h, pgprot_t prot) int is_nvmap_vma(struct vm_area_struct *vma); +struct nvmap_handle_ref *nvmap_alloc_iovm(struct nvmap_client *client, + size_t size, size_t align, unsigned int flags, unsigned int iova_start); + +void nvmap_free_iovm(struct nvmap_client *client, struct nvmap_handle_ref *r); + #endif diff --git a/drivers/video/tegra/nvmap/nvmap_handle.c b/drivers/video/tegra/nvmap/nvmap_handle.c index de47aa7a5e58..0c77e8a23035 100644 --- a/drivers/video/tegra/nvmap/nvmap_handle.c +++ b/drivers/video/tegra/nvmap/nvmap_handle.c @@ -194,7 +194,8 @@ static int handle_page_alloc(struct nvmap_client *client, #ifndef CONFIG_NVMAP_RECLAIM_UNPINNED_VM h->pgalloc.area = tegra_iovmm_create_vm(client->share->iovmm, - NULL, size, h->align, prot); + NULL, size, h->align, prot, + h->pgalloc.iovm_addr); if (!h->pgalloc.area) goto fail; diff --git a/drivers/video/tegra/nvmap/nvmap_mru.c b/drivers/video/tegra/nvmap/nvmap_mru.c index d525fbed74d2..02e8f1402a1d 100644 --- a/drivers/video/tegra/nvmap/nvmap_mru.c +++ b/drivers/video/tegra/nvmap/nvmap_mru.c @@ -116,12 +116,16 @@ struct tegra_iovmm_area *nvmap_handle_iovmm(struct nvmap_client *c, } vm = tegra_iovmm_create_vm(c->share->iovmm, NULL, - h->size, h->align, prot); + h->size, h->align, prot, + h->pgalloc.iovm_addr); if (vm) { INIT_LIST_HEAD(&h->pgalloc.mru_list); return vm; } + /* if client is looking for specific iovm address, return from here. */ + if ((vm == NULL) && (h->pgalloc.iovm_addr != 0)) + return NULL; /* attempt to re-use the most recently unpinned IOVMM area in the * same size bin as the current handle. If that fails, iteratively * evict handles (starting from the current bin) until an allocation @@ -160,7 +164,8 @@ struct tegra_iovmm_area *nvmap_handle_iovmm(struct nvmap_client *c, tegra_iovmm_free_vm(evict->pgalloc.area); evict->pgalloc.area = NULL; vm = tegra_iovmm_create_vm(c->share->iovmm, - NULL, h->size, h->align, prot); + NULL, h->size, h->align, + prot, h->pgalloc.iovm_addr); nvmap_mru_lock(c->share); } } |