summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorvdumpa <vdumpa@nvidia.com>2011-05-15 19:31:15 -0700
committerNiket Sirsi <nsirsi@nvidia.com>2011-06-06 18:34:10 -0700
commite0ec2660057b8e0f986fb0e3859bcf59b358ef41 (patch)
tree8f9f4a59367d093edbb325c60653e4dd42c3d3ed /drivers
parent03a0ac091432484b8d677d4260254ba8e7d2afe3 (diff)
video: tegra: nvmap: Add support to allocate specific IOVM
Change-Id: I95cdf71e74947d4394e0cfd272a29c47562d4059 Reviewed-on: http://git-master/r/31648 Reviewed-by: Niket Sirsi <nsirsi@nvidia.com> Tested-by: Niket Sirsi <nsirsi@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/tegra/nvmap/nvmap.c47
-rw-r--r--drivers/video/tegra/nvmap/nvmap.h6
-rw-r--r--drivers/video/tegra/nvmap/nvmap_handle.c3
-rw-r--r--drivers/video/tegra/nvmap/nvmap_mru.c9
4 files changed, 62 insertions, 3 deletions
diff --git a/drivers/video/tegra/nvmap/nvmap.c b/drivers/video/tegra/nvmap/nvmap.c
index 4061d8283e08..6a1cc425c6ff 100644
--- a/drivers/video/tegra/nvmap/nvmap.c
+++ b/drivers/video/tegra/nvmap/nvmap.c
@@ -726,6 +726,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);
}
}