OSDN Git Service

iommu/iommu-debug: Add file for profiling the fast DMA APIs
authorMitchel Humpherys <mitchelh@codeaurora.org>
Thu, 8 Oct 2015 22:08:01 +0000 (15:08 -0700)
committerJeevan Shriram <jshriram@codeaurora.org>
Sat, 21 May 2016 02:24:01 +0000 (19:24 -0700)
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>
drivers/iommu/iommu-debug.c

index 1ecbedd..c949730 100644 (file)
@@ -25,6 +25,9 @@
 #include <soc/qcom/secure_buffer.h>
 #include <linux/qcom_iommu.h>
 #include <linux/module.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)
 {
@@ -799,6 +802,131 @@ static const struct file_operations iommu_debug_profiling_fast_fops = {
        .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",
+       };
+       struct dma_attrs coherent_attrs;
+       struct dma_attrs *extra_attrs[] = {
+               NULL,
+               &coherent_attrs,
+       };
+
+       init_dma_attrs(&coherent_attrs);
+       dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &coherent_attrs);
+
+       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)
 {
@@ -1198,6 +1326,13 @@ static int snarf_iommu_devices(struct device *dev, const char *name)
                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",
+                      name);
+               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",