summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/iovmm-smmu.c
diff options
context:
space:
mode:
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),