]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/x86/kernel/amd_iommu.c
AMD IOMMU: remove now unnecessary #ifdefs
[linux-2.6-omap-h63xx.git] / arch / x86 / kernel / amd_iommu.c
index f2260609eadc5e81d0cc4572cdcb75e50404df37..5113c080f0c442093db228b759946766f59afb06 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/pci.h>
 #include <linux/gfp.h>
 #include <linux/bitops.h>
+#include <linux/debugfs.h>
 #include <linux/scatterlist.h>
 #include <linux/iommu-helper.h>
 #ifdef CONFIG_IOMMU_API
@@ -57,6 +58,66 @@ static int dma_ops_unity_map(struct dma_ops_domain *dma_dom,
 static struct dma_ops_domain *find_protection_domain(u16 devid);
 
 
+#ifdef CONFIG_AMD_IOMMU_STATS
+
+/*
+ * Initialization code for statistics collection
+ */
+
+DECLARE_STATS_COUNTER(compl_wait);
+DECLARE_STATS_COUNTER(cnt_map_single);
+DECLARE_STATS_COUNTER(cnt_unmap_single);
+DECLARE_STATS_COUNTER(cnt_map_sg);
+DECLARE_STATS_COUNTER(cnt_unmap_sg);
+DECLARE_STATS_COUNTER(cnt_alloc_coherent);
+DECLARE_STATS_COUNTER(cnt_free_coherent);
+DECLARE_STATS_COUNTER(cross_page);
+DECLARE_STATS_COUNTER(domain_flush_single);
+DECLARE_STATS_COUNTER(domain_flush_all);
+DECLARE_STATS_COUNTER(alloced_io_mem);
+DECLARE_STATS_COUNTER(total_map_requests);
+
+static struct dentry *stats_dir;
+static struct dentry *de_isolate;
+static struct dentry *de_fflush;
+
+static void amd_iommu_stats_add(struct __iommu_counter *cnt)
+{
+       if (stats_dir == NULL)
+               return;
+
+       cnt->dent = debugfs_create_u64(cnt->name, 0444, stats_dir,
+                                      &cnt->value);
+}
+
+static void amd_iommu_stats_init(void)
+{
+       stats_dir = debugfs_create_dir("amd-iommu", NULL);
+       if (stats_dir == NULL)
+               return;
+
+       de_isolate = debugfs_create_bool("isolation", 0444, stats_dir,
+                                        (u32 *)&amd_iommu_isolate);
+
+       de_fflush  = debugfs_create_bool("fullflush", 0444, stats_dir,
+                                        (u32 *)&amd_iommu_unmap_flush);
+
+       amd_iommu_stats_add(&compl_wait);
+       amd_iommu_stats_add(&cnt_map_single);
+       amd_iommu_stats_add(&cnt_unmap_single);
+       amd_iommu_stats_add(&cnt_map_sg);
+       amd_iommu_stats_add(&cnt_unmap_sg);
+       amd_iommu_stats_add(&cnt_alloc_coherent);
+       amd_iommu_stats_add(&cnt_free_coherent);
+       amd_iommu_stats_add(&cross_page);
+       amd_iommu_stats_add(&domain_flush_single);
+       amd_iommu_stats_add(&domain_flush_all);
+       amd_iommu_stats_add(&alloced_io_mem);
+       amd_iommu_stats_add(&total_map_requests);
+}
+
+#endif
+
 /* returns !0 if the IOMMU is caching non-present entries in its TLB */
 static int iommu_has_npcache(struct amd_iommu *iommu)
 {
@@ -198,7 +259,7 @@ static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
        spin_lock_irqsave(&iommu->lock, flags);
        ret = __iommu_queue_command(iommu, cmd);
        if (!ret)
-               iommu->need_sync = 1;
+               iommu->need_sync = true;
        spin_unlock_irqrestore(&iommu->lock, flags);
 
        return ret;
@@ -214,6 +275,8 @@ static void __iommu_wait_for_completion(struct amd_iommu *iommu)
        unsigned status = 0;
        unsigned long i = 0;
 
+       INC_STATS_COUNTER(compl_wait);
+
        while (!ready && (i < EXIT_LOOP_COUNT)) {
                ++i;
                /* wait for the bit to become one */
@@ -263,7 +326,7 @@ static int iommu_completion_wait(struct amd_iommu *iommu)
 
        ret = __iommu_completion_wait(iommu);
 
-       iommu->need_sync = 0;
+       iommu->need_sync = false;
 
        if (ret)
                goto out;
@@ -358,10 +421,11 @@ static void iommu_flush_tlb(struct amd_iommu *iommu, u16 domid)
 {
        u64 address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS;
 
+       INC_STATS_COUNTER(domain_flush_single);
+
        iommu_queue_inv_iommu_pages(iommu, address, domid, 0, 1);
 }
 
-#ifdef CONFIG_IOMMU_API
 /*
  * This function is used to flush the IO/TLB for a given protection domain
  * on every IOMMU in the system
@@ -372,6 +436,8 @@ static void iommu_flush_domain(u16 domid)
        struct amd_iommu *iommu;
        struct iommu_cmd cmd;
 
+       INC_STATS_COUNTER(domain_flush_all);
+
        __iommu_build_inv_iommu_pages(&cmd, CMD_INV_IOMMU_ALL_PAGES_ADDRESS,
                                      domid, 1, 1);
 
@@ -383,7 +449,6 @@ static void iommu_flush_domain(u16 domid)
                spin_unlock_irqrestore(&iommu->lock, flags);
        }
 }
-#endif
 
 /****************************************************************************
  *
@@ -449,7 +514,6 @@ static int iommu_map_page(struct protection_domain *dom,
        return 0;
 }
 
-#ifdef CONFIG_IOMMU_API
 static void iommu_unmap_page(struct protection_domain *dom,
                             unsigned long bus_addr)
 {
@@ -471,7 +535,6 @@ static void iommu_unmap_page(struct protection_domain *dom,
 
        *pte = 0;
 }
-#endif
 
 /*
  * This function checks if a specific unity mapping entry is needed for
@@ -656,7 +719,6 @@ static u16 domain_id_alloc(void)
        return id;
 }
 
-#ifdef CONFIG_IOMMU_API
 static void domain_id_free(int id)
 {
        unsigned long flags;
@@ -666,7 +728,6 @@ static void domain_id_free(int id)
                __clear_bit(id, amd_iommu_pd_alloc_bitmap);
        write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
 }
-#endif
 
 /*
  * Used to reserve address ranges in the aperture (e.g. for exclusion
@@ -1074,8 +1135,7 @@ static int get_device_resources(struct device *dev,
                *domain = &dma_dom->domain;
                attach_device(*iommu, *domain, *bdf);
                printk(KERN_INFO "AMD IOMMU: Using protection domain %d for "
-                               "device ", (*domain)->id);
-               print_devid(_bdf, 1);
+                               "device %s\n", (*domain)->id, dev_name(dev));
        }
 
        if (domain_for_device(_bdf) == NULL)
@@ -1165,6 +1225,11 @@ static dma_addr_t __map_single(struct device *dev,
        pages = iommu_num_pages(paddr, size, PAGE_SIZE);
        paddr &= PAGE_MASK;
 
+       INC_STATS_COUNTER(total_map_requests);
+
+       if (pages > 1)
+               INC_STATS_COUNTER(cross_page);
+
        if (align)
                align_mask = (1UL << get_order(size)) - 1;
 
@@ -1181,6 +1246,8 @@ static dma_addr_t __map_single(struct device *dev,
        }
        address += offset;
 
+       ADD_STATS_COUNTER(alloced_io_mem, size);
+
        if (unlikely(dma_dom->need_flush && !amd_iommu_unmap_flush)) {
                iommu_flush_tlb(iommu, dma_dom->domain.id);
                dma_dom->need_flush = false;
@@ -1217,6 +1284,8 @@ static void __unmap_single(struct amd_iommu *iommu,
                start += PAGE_SIZE;
        }
 
+       SUB_STATS_COUNTER(alloced_io_mem, size);
+
        dma_ops_free_addresses(dma_dom, dma_addr, pages);
 
        if (amd_iommu_unmap_flush || dma_dom->need_flush) {
@@ -1238,6 +1307,8 @@ static dma_addr_t map_single(struct device *dev, phys_addr_t paddr,
        dma_addr_t addr;
        u64 dma_mask;
 
+       INC_STATS_COUNTER(cnt_map_single);
+
        if (!check_device(dev))
                return bad_dma_address;
 
@@ -1277,6 +1348,8 @@ static void unmap_single(struct device *dev, dma_addr_t dma_addr,
        struct protection_domain *domain;
        u16 devid;
 
+       INC_STATS_COUNTER(cnt_unmap_single);
+
        if (!check_device(dev) ||
            !get_device_resources(dev, &iommu, &domain, &devid))
                /* device not handled by any AMD IOMMU */
@@ -1329,6 +1402,8 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
        int mapped_elems = 0;
        u64 dma_mask;
 
+       INC_STATS_COUNTER(cnt_map_sg);
+
        if (!check_device(dev))
                return 0;
 
@@ -1391,6 +1466,8 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist,
        u16 devid;
        int i;
 
+       INC_STATS_COUNTER(cnt_unmap_sg);
+
        if (!check_device(dev) ||
            !get_device_resources(dev, &iommu, &domain, &devid))
                return;
@@ -1425,6 +1502,8 @@ static void *alloc_coherent(struct device *dev, size_t size,
        phys_addr_t paddr;
        u64 dma_mask = dev->coherent_dma_mask;
 
+       INC_STATS_COUNTER(cnt_alloc_coherent);
+
        if (!check_device(dev))
                return NULL;
 
@@ -1481,6 +1560,8 @@ static void free_coherent(struct device *dev, size_t size,
        struct protection_domain *domain;
        u16 devid;
 
+       INC_STATS_COUNTER(cnt_free_coherent);
+
        if (!check_device(dev))
                return;
 
@@ -1535,7 +1616,7 @@ static int amd_iommu_dma_supported(struct device *dev, u64 mask)
  * we don't need to preallocate the protection domains anymore.
  * For now we have to.
  */
-void prealloc_protection_domains(void)
+static void prealloc_protection_domains(void)
 {
        struct pci_dev *dev = NULL;
        struct dma_ops_domain *dma_dom;
@@ -1544,7 +1625,7 @@ void prealloc_protection_domains(void)
        u16 devid;
 
        while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-               devid = (dev->bus->number << 8) | dev->devfn;
+               devid = calc_devid(dev->bus->number, dev->devfn);
                if (devid > amd_iommu_last_bdf)
                        continue;
                devid = amd_iommu_alias_table[devid];
@@ -1615,12 +1696,12 @@ int __init amd_iommu_init_dma_ops(void)
        /* Make the driver finally visible to the drivers */
        dma_ops = &amd_iommu_dma_ops;
 
-#ifdef CONFIG_IOMMU_API
        register_iommu(&amd_iommu_ops);
-#endif
 
        bus_register_notifier(&pci_bus_type, &device_nb);
 
+       amd_iommu_stats_init();
+
        return 0;
 
 free_domains:
@@ -1643,8 +1724,6 @@ free_domains:
  *
  *****************************************************************************/
 
-#ifdef CONFIG_IOMMU_API
-
 static void cleanup_domain(struct protection_domain *domain)
 {
        unsigned long flags;
@@ -1855,4 +1934,3 @@ static struct iommu_ops amd_iommu_ops = {
        .iova_to_phys = amd_iommu_iova_to_phys,
 };
 
-#endif