diff options
author | Chris Johnson <cwj@nvidia.com> | 2011-04-30 14:24:44 -0700 |
---|---|---|
committer | Niket Sirsi <nsirsi@nvidia.com> | 2011-05-16 15:15:20 -0700 |
commit | 6d8d2c454e835f7cfe34371e07dac173f3153452 (patch) | |
tree | c80564468037653f45c29d607e52e8c472ae8367 /drivers/video/tegra/nvmap/nvmap.c | |
parent | 0edac603fc410d7b6686b27e545586b42feb7a80 (diff) |
nvrm: move stale wait checking into the kerneltegra-11.2.6
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
Note: reset the author in this commit to fix a email addr problem
and since from the latest/last cherry pick there was a reworking
of the code to be compatible with different user space versions
it also seemed reasonable.
(cherry picked from commit 4069d8e67665624ad3dceb628e572980dd57acd0)
(cherry picked from commit 6e4336408588e348804a62e53386acc9abc06823)
(cherry picked from commit 87a9efe751716ca741caac72b9061fdfdcec540a)
Change-Id: I9c6076da2384f373d5f402bee4406b09b4ebc4ff
Reviewed-on: http://git-master/r/23159
Reviewed-on: http://git-master/r/30281
Tested-by: Chris Johnson <cwj@nvidia.com>
Reviewed-by: Ken Adams <kadams@nvidia.com>
Reviewed-by: Prajakta Gudadhe <pgudadhe@nvidia.com>
Diffstat (limited to 'drivers/video/tegra/nvmap/nvmap.c')
-rw-r--r-- | drivers/video/tegra/nvmap/nvmap.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/drivers/video/tegra/nvmap/nvmap.c b/drivers/video/tegra/nvmap/nvmap.c index 00b9a5adb49f..e8d795006082 100644 --- a/drivers/video/tegra/nvmap/nvmap.c +++ b/drivers/video/tegra/nvmap/nvmap.c @@ -730,3 +730,53 @@ 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_wait(struct nvmap_client *client, + struct nvmap_handle *patch, + u32 patch_offset, u32 patch_value) +{ + unsigned long phys; + unsigned int pfn, last_pfn = 0; + void *addr; + pte_t **pte; + + 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); + + /* write PTE, so addr points to cmdbuf PFN */ + if (pfn != last_pfn) { + pgprot_t prot = nvmap_pgprot(patch, pgprot_kernel); + unsigned long kaddr = (unsigned long)addr; + set_pte_at(&init_mm, kaddr, *pte, pfn_pte(pfn, prot)); + flush_tlb_kernel_page(kaddr); + last_pfn = pfn; + } + + /* write patch_value to addr + page offset */ + __raw_writel(patch_value, addr + (phys & ~PAGE_MASK)); + + nvmap_free_pte(client->dev, pte); + wmb(); + return 0; +} |