diff options
author | Chris Johnson <cwj@nvidia.com> | 2011-04-30 14:24:44 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:45:05 -0800 |
commit | f8de8910119769d354bf1a89cef1a0a0c624b486 (patch) | |
tree | b2b7417cd0905ef1d2b9bf2fdf86636319ea7033 /drivers/video/tegra/nvmap | |
parent | 41ca4ada73f986e7a8622ba458c1ac3915598c30 (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.c | 49 |
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; +} |