iommu/iommu-debug: Add file for profiling the fast DMA APIs
The fast DMA API implementation that was recently needs to be profiled.
Add a new debugfs file (similar to the original "profiling" file) to do
this.
CRs-Fixed: 997751
Change-Id: I1236d9b6aaeab9d34b39e7f5d7b285691d1779da
Signed-off-by: Mitchel Humpherys <mitchelh@codeaurora.org>
Signed-off-by: Patrick Daly <pdaly@codeaurora.org>
diff --git a/drivers/iommu/iommu-debug.c b/drivers/iommu/iommu-debug.c
index 79dd817..5b79fe2 100644
--- a/drivers/iommu/iommu-debug.c
+++ b/drivers/iommu/iommu-debug.c
@@ -24,6 +24,9 @@
#include <linux/uaccess.h>
#include <linux/dma-contiguous.h>
#include <soc/qcom/secure_buffer.h>
+#include <linux/dma-mapping.h>
+#include <asm/cacheflush.h>
+#include <asm/dma-iommu.h>
static const char *iommu_debug_attr_to_string(enum iommu_attr attr)
{
@@ -772,6 +775,127 @@
.release = single_release,
};
+static int iommu_debug_profiling_fast_dma_api_show(struct seq_file *s,
+ void *ignored)
+{
+ int i, experiment;
+ struct iommu_debug_device *ddev = s->private;
+ struct device *dev = ddev->dev;
+ u64 map_elapsed_ns[10], unmap_elapsed_ns[10];
+ struct dma_iommu_mapping *mapping;
+ dma_addr_t dma_addr;
+ void *virt;
+ int fast = 1;
+ const char * const extra_labels[] = {
+ "not coherent",
+ "coherent",
+ };
+ unsigned long extra_attrs[] = {
+ 0,
+ DMA_ATTR_SKIP_CPU_SYNC,
+ };
+
+ virt = kmalloc(1518, GFP_KERNEL);
+ if (!virt)
+ goto out;
+
+ mapping = arm_iommu_create_mapping(&platform_bus_type, 0, SZ_1G * 4ULL);
+ if (!mapping) {
+ seq_puts(s, "fast_smmu_create_mapping failed\n");
+ goto out_kfree;
+ }
+
+ if (iommu_domain_set_attr(mapping->domain, DOMAIN_ATTR_FAST, &fast)) {
+ seq_puts(s, "iommu_domain_set_attr failed\n");
+ goto out_release_mapping;
+ }
+
+ if (arm_iommu_attach_device(dev, mapping)) {
+ seq_puts(s, "fast_smmu_attach_device failed\n");
+ goto out_release_mapping;
+ }
+
+ if (iommu_enable_config_clocks(mapping->domain)) {
+ seq_puts(s, "Couldn't enable clocks\n");
+ goto out_detach;
+ }
+ for (experiment = 0; experiment < 2; ++experiment) {
+ u64 map_avg = 0, unmap_avg = 0;
+
+ for (i = 0; i < 10; ++i) {
+ struct timespec tbefore, tafter, diff;
+ u64 ns;
+
+ getnstimeofday(&tbefore);
+ dma_addr = dma_map_single_attrs(
+ dev, virt, SZ_4K, DMA_TO_DEVICE,
+ extra_attrs[experiment]);
+ getnstimeofday(&tafter);
+ diff = timespec_sub(tafter, tbefore);
+ ns = timespec_to_ns(&diff);
+ if (dma_mapping_error(dev, dma_addr)) {
+ seq_puts(s, "dma_map_single failed\n");
+ goto out_disable_config_clocks;
+ }
+ map_elapsed_ns[i] = ns;
+
+ getnstimeofday(&tbefore);
+ dma_unmap_single_attrs(
+ dev, dma_addr, SZ_4K, DMA_TO_DEVICE,
+ extra_attrs[experiment]);
+ getnstimeofday(&tafter);
+ diff = timespec_sub(tafter, tbefore);
+ ns = timespec_to_ns(&diff);
+ unmap_elapsed_ns[i] = ns;
+ }
+
+ seq_printf(s, "%13s %24s (ns): [", extra_labels[experiment],
+ "dma_map_single_attrs");
+ for (i = 0; i < 10; ++i) {
+ map_avg += map_elapsed_ns[i];
+ seq_printf(s, "%5llu%s", map_elapsed_ns[i],
+ i < 9 ? ", " : "");
+ }
+ map_avg /= 10;
+ seq_printf(s, "] (avg: %llu)\n", map_avg);
+
+ seq_printf(s, "%13s %24s (ns): [", extra_labels[experiment],
+ "dma_unmap_single_attrs");
+ for (i = 0; i < 10; ++i) {
+ unmap_avg += unmap_elapsed_ns[i];
+ seq_printf(s, "%5llu%s", unmap_elapsed_ns[i],
+ i < 9 ? ", " : "");
+ }
+ unmap_avg /= 10;
+ seq_printf(s, "] (avg: %llu)\n", unmap_avg);
+ }
+
+out_disable_config_clocks:
+ iommu_disable_config_clocks(mapping->domain);
+out_detach:
+ arm_iommu_detach_device(dev);
+out_release_mapping:
+ arm_iommu_release_mapping(mapping);
+out_kfree:
+ kfree(virt);
+out:
+ return 0;
+}
+
+static int iommu_debug_profiling_fast_dma_api_open(struct inode *inode,
+ struct file *file)
+{
+ return single_open(file, iommu_debug_profiling_fast_dma_api_show,
+ inode->i_private);
+}
+
+static const struct file_operations iommu_debug_profiling_fast_dma_api_fops = {
+ .open = iommu_debug_profiling_fast_dma_api_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
static int iommu_debug_attach_do_attach(struct iommu_debug_device *ddev,
int val, bool is_secure)
{
@@ -1157,6 +1281,13 @@
goto err_rmdir;
}
+ if (!debugfs_create_file("profiling_fast_dma_api", S_IRUSR, dir, ddev,
+ &iommu_debug_profiling_fast_dma_api_fops)) {
+ pr_err("Couldn't create iommu/devices/%s/profiling_fast_dma_api debugfs file\n",
+ dev_name(dev));
+ goto err_rmdir;
+ }
+
if (!debugfs_create_file("attach", S_IRUSR, dir, ddev,
&iommu_debug_attach_fops)) {
pr_err("Couldn't create iommu/devices/%s/attach debugfs file\n",