summaryrefslogtreecommitdiff
path: root/drivers/video/tegra/nvmap
diff options
context:
space:
mode:
authorChris Johnson <cwj@nvidia.com>2011-04-30 14:24:44 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:45:05 -0800
commitf8de8910119769d354bf1a89cef1a0a0c624b486 (patch)
treeb2b7417cd0905ef1d2b9bf2fdf86636319ea7033 /drivers/video/tegra/nvmap
parent41ca4ada73f986e7a8622ba458c1ac3915598c30 (diff)
nvrm: move stale wait checking into the kernel
The kernel now receives wait tracking data (similar to gathers and relocs) and compares the current syncpt with the threshold value. If it's old, it gets a kernel mapping and rewrites the method data to use a kernel reserved syncpt that is always 0 (so trivially pops when seen by the HW). Bug 519650 Bug 785525 Bug 803452 The waitchk implementation is also backward compatible with older user space code that didn't supply waitchk data as part of the submit. (cherry picked from commit 4069d8e67665624ad3dceb628e572980dd57acd0) (cherry picked from commit 6e4336408588e348804a62e53386acc9abc06823) (cherry picked from commit 87a9efe751716ca741caac72b9061fdfdcec540a) (cherry picked from commit 6d8d2c454e835f7cfe34371e07dac173f3153452) Original-Change-Id: I1bf4c940fefb6e251aa8c396e92631fa3cbe32df Reviewed-on: http://git-master/r/23159 Reviewed-on: http://git-master/r/30281 Reviewed-on: http://git-master/r/32669 Reviewed-by: Niket Sirsi <nsirsi@nvidia.com> Tested-by: Niket Sirsi <nsirsi@nvidia.com> Rebase-Id: Rbad4942a103de7d64d8a6a11d4a973740c56fa8e
Diffstat (limited to 'drivers/video/tegra/nvmap')
-rw-r--r--drivers/video/tegra/nvmap/nvmap.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/drivers/video/tegra/nvmap/nvmap.c b/drivers/video/tegra/nvmap/nvmap.c
index 06ce0767e3ee..dcd1672fcc2e 100644
--- a/drivers/video/tegra/nvmap/nvmap.c
+++ b/drivers/video/tegra/nvmap/nvmap.c
@@ -776,3 +776,52 @@ void nvmap_free(struct nvmap_client *client, struct nvmap_handle_ref *r)
{
nvmap_free_handle_id(client, nvmap_ref_to_id(r));
}
+
+/*
+ * create a mapping to the user's buffer and write it
+ * (uses similar logic from nvmap_reloc_pin_array to map the cmdbuf)
+ */
+int nvmap_patch_word(struct nvmap_client *client,
+ struct nvmap_handle *patch,
+ u32 patch_offset, u32 patch_value)
+{
+ phys_addr_t phys;
+ unsigned long kaddr;
+ unsigned int pfn;
+ void *addr;
+ pte_t **pte;
+ pgprot_t prot;
+
+ if (patch_offset >= patch->size) {
+ nvmap_warn(client, "read/write outside of handle\n");
+ return -EFAULT;
+ }
+
+ pte = nvmap_alloc_pte(client->dev, &addr);
+ if (IS_ERR(pte))
+ return PTR_ERR(pte);
+
+ /* derive physaddr of cmdbuf WAIT to patch */
+ if (patch->heap_pgalloc) {
+ unsigned int page = patch_offset >> PAGE_SHIFT;
+ phys = page_to_phys(patch->pgalloc.pages[page]);
+ phys += (patch_offset & ~PAGE_MASK);
+ } else {
+ phys = patch->carveout->base + patch_offset;
+ }
+
+ pfn = __phys_to_pfn(phys);
+ prot = nvmap_pgprot(patch, pgprot_kernel);
+ kaddr = (unsigned long)addr;
+
+ /* write PTE, so addr points to cmdbuf PFN */
+ set_pte_at(&init_mm, kaddr, *pte, pfn_pte(pfn, prot));
+ flush_tlb_kernel_page(kaddr);
+
+ /* write patch_value to addr + page offset */
+ __raw_writel(patch_value, addr + (phys & ~PAGE_MASK));
+
+ nvmap_free_pte(client->dev, pte);
+ wmb();
+ return 0;
+}