]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'iommu/next'
authorThierry Reding <treding@nvidia.com>
Thu, 24 Oct 2013 12:37:05 +0000 (14:37 +0200)
committerThierry Reding <treding@nvidia.com>
Thu, 24 Oct 2013 12:37:05 +0000 (14:37 +0200)
drivers/iommu/Makefile
drivers/iommu/intel_irq_remapping.c
drivers/iommu/iommu-traces.c [new file with mode: 0644]
drivers/iommu/iommu.c
drivers/iommu/tegra-gart.c
drivers/iommu/tegra-smmu.c
include/linux/iommu.h
include/trace/events/iommu.h [new file with mode: 0644]

index 14c1f474cf1188008316e7e480c7e3c6d22f04f5..5d58bf16e9e3c15d013c3cb071019be5403223df 100644 (file)
@@ -1,4 +1,5 @@
 obj-$(CONFIG_IOMMU_API) += iommu.o
+obj-$(CONFIG_IOMMU_API) += iommu-traces.o
 obj-$(CONFIG_OF_IOMMU) += of_iommu.o
 obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
 obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
index f71673dbb23da174cfd8045b0782ce38cc4b4f3a..b97d70b1abe0c7778524123f35e5bb6f6cb2d7b1 100644 (file)
@@ -525,12 +525,13 @@ static int __init intel_irq_remapping_supported(void)
        if (disable_irq_remap)
                return 0;
        if (irq_remap_broken) {
-               WARN_TAINT(1, TAINT_FIRMWARE_WORKAROUND,
-                          "This system BIOS has enabled interrupt remapping\n"
-                          "on a chipset that contains an erratum making that\n"
-                          "feature unstable.  To maintain system stability\n"
-                          "interrupt remapping is being disabled.  Please\n"
-                          "contact your BIOS vendor for an update\n");
+               printk(KERN_WARNING
+                       "This system BIOS has enabled interrupt remapping\n"
+                       "on a chipset that contains an erratum making that\n"
+                       "feature unstable.  To maintain system stability\n"
+                       "interrupt remapping is being disabled.  Please\n"
+                       "contact your BIOS vendor for an update\n");
+               add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
                disable_irq_remap = 1;
                return 0;
        }
diff --git a/drivers/iommu/iommu-traces.c b/drivers/iommu/iommu-traces.c
new file mode 100644 (file)
index 0000000..bf3b317
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * iommu trace points
+ *
+ * Copyright (C) 2013 Shuah Khan <shuah.kh@samsung.com>
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/types.h>
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/iommu.h>
+
+/* iommu_group_event */
+EXPORT_TRACEPOINT_SYMBOL_GPL(add_device_to_group);
+EXPORT_TRACEPOINT_SYMBOL_GPL(remove_device_from_group);
+
+/* iommu_device_event */
+EXPORT_TRACEPOINT_SYMBOL_GPL(attach_device_to_domain);
+EXPORT_TRACEPOINT_SYMBOL_GPL(detach_device_from_domain);
+
+/* iommu_map_unmap */
+EXPORT_TRACEPOINT_SYMBOL_GPL(map);
+EXPORT_TRACEPOINT_SYMBOL_GPL(unmap);
+
+/* iommu_error */
+EXPORT_TRACEPOINT_SYMBOL_GPL(io_page_fault);
index fbe9ca734f8fe3839a30dcf805b159faad3cc225..e5555fcfe703b702088873a0dd648eaf19d1676e 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/idr.h>
 #include <linux/notifier.h>
 #include <linux/err.h>
+#include <trace/events/iommu.h>
 
 static struct kset *iommu_group_kset;
 static struct ida iommu_group_ida;
@@ -363,6 +364,8 @@ rename:
        /* Notify any listeners about change to group. */
        blocking_notifier_call_chain(&group->notifier,
                                     IOMMU_GROUP_NOTIFY_ADD_DEVICE, dev);
+
+       trace_add_device_to_group(group->id, dev);
        return 0;
 }
 EXPORT_SYMBOL_GPL(iommu_group_add_device);
@@ -399,6 +402,8 @@ void iommu_group_remove_device(struct device *dev)
        sysfs_remove_link(group->devices_kobj, device->name);
        sysfs_remove_link(&dev->kobj, "iommu_group");
 
+       trace_remove_device_from_group(group->id, dev);
+
        kfree(device->name);
        kfree(device);
        dev->iommu_group = NULL;
@@ -680,10 +685,14 @@ EXPORT_SYMBOL_GPL(iommu_domain_free);
 
 int iommu_attach_device(struct iommu_domain *domain, struct device *dev)
 {
+       int ret;
        if (unlikely(domain->ops->attach_dev == NULL))
                return -ENODEV;
 
-       return domain->ops->attach_dev(domain, dev);
+       ret = domain->ops->attach_dev(domain, dev);
+       if (!ret)
+               trace_attach_device_to_domain(dev);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(iommu_attach_device);
 
@@ -693,6 +702,7 @@ void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
                return;
 
        domain->ops->detach_dev(domain, dev);
+       trace_detach_device_from_domain(dev);
 }
 EXPORT_SYMBOL_GPL(iommu_detach_device);
 
@@ -807,17 +817,17 @@ int iommu_map(struct iommu_domain *domain, unsigned long iova,
         * size of the smallest page supported by the hardware
         */
        if (!IS_ALIGNED(iova | paddr | size, min_pagesz)) {
-               pr_err("unaligned: iova 0x%lx pa 0x%pa size 0x%zx min_pagesz 0x%x\n",
+               pr_err("unaligned: iova 0x%lx pa %pa size 0x%zx min_pagesz 0x%x\n",
                       iova, &paddr, size, min_pagesz);
                return -EINVAL;
        }
 
-       pr_debug("map: iova 0x%lx pa 0x%pa size 0x%zx\n", iova, &paddr, size);
+       pr_debug("map: iova 0x%lx pa %pa size 0x%zx\n", iova, &paddr, size);
 
        while (size) {
                size_t pgsize = iommu_pgsize(domain, iova | paddr, size);
 
-               pr_debug("mapping: iova 0x%lx pa 0x%pa pgsize 0x%zx\n",
+               pr_debug("mapping: iova 0x%lx pa %pa pgsize 0x%zx\n",
                         iova, &paddr, pgsize);
 
                ret = domain->ops->map(domain, iova, paddr, pgsize, prot);
@@ -832,6 +842,8 @@ int iommu_map(struct iommu_domain *domain, unsigned long iova,
        /* unroll mapping in case something went wrong */
        if (ret)
                iommu_unmap(domain, orig_iova, orig_size - size);
+       else
+               trace_map(iova, paddr, size);
 
        return ret;
 }
@@ -880,6 +892,7 @@ size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size)
                unmapped += unmapped_page;
        }
 
+       trace_unmap(iova, 0, size);
        return unmapped;
 }
 EXPORT_SYMBOL_GPL(iommu_unmap);
index 108c0e9c24d97bfba39f701de0c14323ad5e3569..f75483a3a2ef8f5d348bcdafd30f8b7e7b2c09d4 100644 (file)
@@ -252,7 +252,7 @@ static int gart_iommu_map(struct iommu_domain *domain, unsigned long iova,
        spin_lock_irqsave(&gart->pte_lock, flags);
        pfn = __phys_to_pfn(pa);
        if (!pfn_valid(pfn)) {
-               dev_err(gart->dev, "Invalid page: %08x\n", pa);
+               dev_err(gart->dev, "Invalid page: %pa\n", &pa);
                spin_unlock_irqrestore(&gart->pte_lock, flags);
                return -EINVAL;
        }
@@ -295,8 +295,8 @@ static phys_addr_t gart_iommu_iova_to_phys(struct iommu_domain *domain,
 
        pa = (pte & GART_PAGE_MASK);
        if (!pfn_valid(__phys_to_pfn(pa))) {
-               dev_err(gart->dev, "No entry for %08llx:%08x\n",
-                        (unsigned long long)iova, pa);
+               dev_err(gart->dev, "No entry for %08llx:%pa\n",
+                        (unsigned long long)iova, &pa);
                gart_dump_table(gart);
                return -EINVAL;
        }
@@ -351,7 +351,6 @@ static int tegra_gart_probe(struct platform_device *pdev)
        struct gart_device *gart;
        struct resource *res, *res_remap;
        void __iomem *gart_regs;
-       int err;
        struct device *dev = &pdev->dev;
 
        if (gart_handle)
@@ -376,8 +375,7 @@ static int tegra_gart_probe(struct platform_device *pdev)
        gart_regs = devm_ioremap(dev, res->start, resource_size(res));
        if (!gart_regs) {
                dev_err(dev, "failed to remap GART registers\n");
-               err = -ENXIO;
-               goto fail;
+               return -ENXIO;
        }
 
        gart->dev = &pdev->dev;
@@ -391,8 +389,7 @@ static int tegra_gart_probe(struct platform_device *pdev)
        gart->savedata = vmalloc(sizeof(u32) * gart->page_count);
        if (!gart->savedata) {
                dev_err(dev, "failed to allocate context save area\n");
-               err = -ENOMEM;
-               goto fail;
+               return -ENOMEM;
        }
 
        platform_set_drvdata(pdev, gart);
@@ -401,27 +398,15 @@ static int tegra_gart_probe(struct platform_device *pdev)
        gart_handle = gart;
        bus_set_iommu(&platform_bus_type, &gart_iommu_ops);
        return 0;
-
-fail:
-       if (gart_regs)
-               devm_iounmap(dev, gart_regs);
-       if (gart && gart->savedata)
-               vfree(gart->savedata);
-       devm_kfree(dev, gart);
-       return err;
 }
 
 static int tegra_gart_remove(struct platform_device *pdev)
 {
        struct gart_device *gart = platform_get_drvdata(pdev);
-       struct device *dev = gart->dev;
 
        writel(0, gart->regs + GART_CONFIG);
        if (gart->savedata)
                vfree(gart->savedata);
-       if (gart->regs)
-               devm_iounmap(dev, gart->regs);
-       devm_kfree(dev, gart);
        gart_handle = NULL;
        return 0;
 }
index e0665603afd9379f0dfc37dc31ee60113a82ca12..34374b3bc13bfbf3b5021686c1ba7e741661113c 100644 (file)
@@ -731,7 +731,7 @@ static int smmu_iommu_map(struct iommu_domain *domain, unsigned long iova,
        unsigned long pfn = __phys_to_pfn(pa);
        unsigned long flags;
 
-       dev_dbg(as->smmu->dev, "[%d] %08lx:%08x\n", as->asid, iova, pa);
+       dev_dbg(as->smmu->dev, "[%d] %08lx:%pa\n", as->asid, iova, &pa);
 
        if (!pfn_valid(pfn))
                return -ENOMEM;
index 7ea319e95b4771ecb9dc4be7d04ad24a8e628d86..a444c790fa7235e2bc7247313804a5062d0a4db8 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/types.h>
+#include <trace/events/iommu.h>
 
 #define IOMMU_READ     (1)
 #define IOMMU_WRITE    (2)
@@ -227,6 +228,7 @@ static inline int report_iommu_fault(struct iommu_domain *domain,
                ret = domain->handler(domain, dev, iova, flags,
                                                domain->handler_token);
 
+       trace_io_page_fault(dev, iova, flags);
        return ret;
 }
 
diff --git a/include/trace/events/iommu.h b/include/trace/events/iommu.h
new file mode 100644 (file)
index 0000000..a8f5c32
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * iommu trace points
+ *
+ * Copyright (C) 2013 Shuah Khan <shuah.kh@samsung.com>
+ *
+ */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM iommu
+
+#if !defined(_TRACE_IOMMU_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_IOMMU_H
+
+#include <linux/tracepoint.h>
+#include <linux/pci.h>
+
+struct device;
+
+DECLARE_EVENT_CLASS(iommu_group_event,
+
+       TP_PROTO(int group_id, struct device *dev),
+
+       TP_ARGS(group_id, dev),
+
+       TP_STRUCT__entry(
+               __field(int, gid)
+               __string(device, dev_name(dev))
+       ),
+
+       TP_fast_assign(
+               __entry->gid = group_id;
+               __assign_str(device, dev_name(dev));
+       ),
+
+       TP_printk("IOMMU: groupID=%d device=%s",
+                       __entry->gid, __get_str(device)
+       )
+);
+
+DEFINE_EVENT(iommu_group_event, add_device_to_group,
+
+       TP_PROTO(int group_id, struct device *dev),
+
+       TP_ARGS(group_id, dev)
+
+);
+
+DEFINE_EVENT(iommu_group_event, remove_device_from_group,
+
+       TP_PROTO(int group_id, struct device *dev),
+
+       TP_ARGS(group_id, dev)
+);
+
+DECLARE_EVENT_CLASS(iommu_device_event,
+
+       TP_PROTO(struct device *dev),
+
+       TP_ARGS(dev),
+
+       TP_STRUCT__entry(
+               __string(device, dev_name(dev))
+       ),
+
+       TP_fast_assign(
+               __assign_str(device, dev_name(dev));
+       ),
+
+       TP_printk("IOMMU: device=%s", __get_str(device)
+       )
+);
+
+DEFINE_EVENT(iommu_device_event, attach_device_to_domain,
+
+       TP_PROTO(struct device *dev),
+
+       TP_ARGS(dev)
+);
+
+DEFINE_EVENT(iommu_device_event, detach_device_from_domain,
+
+       TP_PROTO(struct device *dev),
+
+       TP_ARGS(dev)
+);
+
+DECLARE_EVENT_CLASS(iommu_map_unmap,
+
+       TP_PROTO(unsigned long iova, phys_addr_t paddr, size_t size),
+
+       TP_ARGS(iova, paddr, size),
+
+       TP_STRUCT__entry(
+               __field(u64, iova)
+               __field(u64, paddr)
+               __field(int, size)
+       ),
+
+       TP_fast_assign(
+               __entry->iova = iova;
+               __entry->paddr = paddr;
+               __entry->size = size;
+       ),
+
+       TP_printk("IOMMU: iova=0x%016llx paddr=0x%016llx size=0x%x",
+                       __entry->iova, __entry->paddr, __entry->size
+       )
+);
+
+DEFINE_EVENT(iommu_map_unmap, map,
+
+       TP_PROTO(unsigned long iova, phys_addr_t paddr, size_t size),
+
+       TP_ARGS(iova, paddr, size)
+);
+
+DEFINE_EVENT_PRINT(iommu_map_unmap, unmap,
+
+       TP_PROTO(unsigned long iova, phys_addr_t paddr, size_t size),
+
+       TP_ARGS(iova, paddr, size),
+
+       TP_printk("IOMMU: iova=0x%016llx size=0x%x",
+                       __entry->iova, __entry->size
+       )
+);
+
+DECLARE_EVENT_CLASS(iommu_error,
+
+       TP_PROTO(struct device *dev, unsigned long iova, int flags),
+
+       TP_ARGS(dev, iova, flags),
+
+       TP_STRUCT__entry(
+               __string(device, dev_name(dev))
+               __string(driver, dev_driver_string(dev))
+               __field(u64, iova)
+               __field(int, flags)
+       ),
+
+       TP_fast_assign(
+               __assign_str(device, dev_name(dev));
+               __assign_str(driver, dev_driver_string(dev));
+               __entry->iova = iova;
+               __entry->flags = flags;
+       ),
+
+       TP_printk("IOMMU:%s %s iova=0x%016llx flags=0x%04x",
+                       __get_str(driver), __get_str(device),
+                       __entry->iova, __entry->flags
+       )
+);
+
+DEFINE_EVENT(iommu_error, io_page_fault,
+
+       TP_PROTO(struct device *dev, unsigned long iova, int flags),
+
+       TP_ARGS(dev, iova, flags)
+);
+#endif /* _TRACE_IOMMU_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>