summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/iovmm-smmu.c
diff options
context:
space:
mode:
authorHiro Sugawara <hsugawara@nvidia.com>2011-08-25 17:00:12 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:49:01 -0800
commit153aee1d24b26fd84896755033d1101cbfbd9505 (patch)
tree3a70268eba03a61812fedf822786edbc07c36181 /arch/arm/mach-tegra/iovmm-smmu.c
parente7c51e695a5818e6126413bead3282c24586831b (diff)
arm: tegra: smmu: Add a sysfs entry for enabling page map signature
For debugging and sanity checking, IOVA and PA are returned in each mapped page if PID matches what is set by the sysfs entry. Reviewed-on: http://git-master/r/49716 (cherry picked from commit 53e7058b8c021ad868beba6d522afd61f8b9315c) Change-Id: Ia289eeb743370366fe37b54678a7c1a657163491 Reviewed-on: http://git-master/r/54515 Tested-by: Hiro Sugawara <hsugawara@nvidia.com> Reviewed-by: Dan Willemsen <dwillemsen@nvidia.com> Rebase-Id: R1ba0ffd93f76001fe7b68a61c3fa0d8f44787e64
Diffstat (limited to 'arch/arm/mach-tegra/iovmm-smmu.c')
-rw-r--r--arch/arm/mach-tegra/iovmm-smmu.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/arch/arm/mach-tegra/iovmm-smmu.c b/arch/arm/mach-tegra/iovmm-smmu.c
index 021906b99bfb..ceb9a5ad803e 100644
--- a/arch/arm/mach-tegra/iovmm-smmu.c
+++ b/arch/arm/mach-tegra/iovmm-smmu.c
@@ -30,6 +30,7 @@
#include <linux/pagemap.h>
#include <linux/sysfs.h>
#include <linux/device.h>
+#include <linux/sched.h>
#include <asm/io.h>
#include <asm/cacheflush.h>
#include <asm/page.h>
@@ -329,6 +330,7 @@ struct smmu_device {
unsigned long lowest_asid; /* Variables for hardware testing */
unsigned long debug_asid;
unsigned long verbose;
+ unsigned long signature_pid; /* For debugging aid */
};
#define VA_PAGE_TO_PA(va, page) \
@@ -583,6 +585,21 @@ static smmu_pte_t *locate_pte(struct smmu_as *as,
return &ptbl[ptn % SMMU_PTBL_COUNT];
}
+static void put_signature(struct smmu_as *as,
+ unsigned long addr, unsigned long pfn)
+{
+ if (as->smmu->signature_pid == current->pid) {
+ struct page *page = pfn_to_page(pfn);
+ unsigned long *vaddr = kmap(page);
+ if (vaddr) {
+ vaddr[0] = addr;
+ vaddr[1] = pfn << PAGE_SHIFT;
+ FLUSH_CPU_DCACHE(vaddr, page, sizeof(vaddr[0]) * 2);
+ kunmap(page);
+ }
+ }
+}
+
static int smmu_map(struct tegra_iovmm_domain *domain,
struct tegra_iovmm_area *iovma)
{
@@ -624,6 +641,7 @@ static int smmu_map(struct tegra_iovmm_domain *domain,
flush_ptc_and_tlb(as->smmu, as, addr, pte, ptpage, 0);
kunmap(ptpage);
up(&as->sem);
+ put_signature(as, addr, pfn);
addr += SMMU_PAGE_SIZE;
}
return 0;
@@ -719,6 +737,7 @@ static void smmu_map_pfn(struct tegra_iovmm_domain *domain,
FLUSH_CPU_DCACHE(pte, ptpage, sizeof *pte);
flush_ptc_and_tlb(smmu, as, addr, pte, ptpage, 0);
kunmap(ptpage);
+ put_signature(as, addr, pfn);
}
up(&as->sem);
}
@@ -1211,11 +1230,10 @@ static ssize_t _sysfs_show_##name(struct device *d, \
return rv; \
}
-#ifdef CONFIG_TEGRA_SMMU_SYSFS
static void (*_sysfs_null_callback)(struct smmu_device *, unsigned long *) =
NULL;
-#define _SYSFS_SET_VALUE(name, field, base, ceil, callback) \
+#define _SYSFS_SET_VALUE_DO(name, field, base, ceil, callback) \
static ssize_t _sysfs_set_##name(struct device *d, \
struct device_attribute *da, const char *buf, size_t count) \
{ \
@@ -1229,6 +1247,8 @@ static ssize_t _sysfs_set_##name(struct device *d, \
} \
return count; \
}
+#ifdef CONFIG_TEGRA_SMMU_SYSFS
+#define _SYSFS_SET_VALUE _SYSFS_SET_VALUE_DO
#else
#define _SYSFS_SET_VALUE(name, field, base, ceil, callback) \
static ssize_t _sysfs_set_##name(struct device *d, \
@@ -1246,6 +1266,9 @@ _SYSFS_SET_VALUE(debug_asid, debug_asid, 10,
MC_SMMU_NUM_ASIDS, _sysfs_null_callback)
_SYSFS_SHOW_VALUE(verbose, verbose, "%lu")
_SYSFS_SET_VALUE(verbose, verbose, 10, 3, _sysfs_null_callback)
+_SYSFS_SHOW_VALUE(signature_pid, signature_pid, "%lu")
+_SYSFS_SET_VALUE_DO(signature_pid, signature_pid, 10, PID_MAX_LIMIT+1,
+ _sysfs_null_callback)
#ifdef CONFIG_TEGRA_SMMU_SYSFS
static void _sysfs_mask_attr(struct smmu_device *smmu, unsigned long *field)
@@ -1291,6 +1314,8 @@ static struct device_attribute _attr_values[] = {
_sysfs_show_debug_asid, _sysfs_set_debug_asid),
__ATTR(verbose, S_IRUGO|S_IWUSR,
_sysfs_show_verbose, _sysfs_set_verbose),
+ __ATTR(signature_pid, S_IRUGO|S_IWUSR,
+ _sysfs_show_signature_pid, _sysfs_set_signature_pid),
__ATTR(pdir_attr, S_IRUGO|S_IWUSR,
_sysfs_show_pdir_attr, _sysfs_set_pdir_attr),