]> 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 d9b651c0118618bb2f45d1f5ae6e06b5194acfbc..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
@@ -923,6 +984,8 @@ static int device_change_notifier(struct notifier_block *nb,
        struct protection_domain *domain;
        struct dma_ops_domain *dma_domain;
        struct amd_iommu *iommu;
+       int order = amd_iommu_aperture_order;
+       unsigned long flags;
 
        if (devid > amd_iommu_last_bdf)
                goto out;
@@ -954,6 +1017,21 @@ static int device_change_notifier(struct notifier_block *nb,
                if (!domain)
                        goto out;
                detach_device(domain, devid);
+               break;
+       case BUS_NOTIFY_ADD_DEVICE:
+               /* allocate a protection domain if a device is added */
+               dma_domain = find_protection_domain(devid);
+               if (dma_domain)
+                       goto out;
+               dma_domain = dma_ops_domain_alloc(iommu, order);
+               if (!dma_domain)
+                       goto out;
+               dma_domain->target_dev = devid;
+
+               spin_lock_irqsave(&iommu_pd_list_lock, flags);
+               list_add_tail(&dma_domain->list, &iommu_pd_list);
+               spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
+
                break;
        default:
                goto out;
@@ -1057,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)
@@ -1148,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;
 
@@ -1164,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;
@@ -1200,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) {
@@ -1221,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;
 
@@ -1260,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 */
@@ -1312,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;
 
@@ -1374,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;
@@ -1408,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;
 
@@ -1464,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;
 
@@ -1518,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;
@@ -1527,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];
@@ -1574,6 +1672,7 @@ int __init amd_iommu_init_dma_ops(void)
                iommu->default_dom = dma_ops_domain_alloc(iommu, order);
                if (iommu->default_dom == NULL)
                        return -ENOMEM;
+               iommu->default_dom->domain.flags |= PD_DEFAULT_MASK;
                ret = iommu_init_unity_mappings(iommu);
                if (ret)
                        goto free_domains;
@@ -1597,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:
@@ -1625,8 +1724,6 @@ free_domains:
  *
  *****************************************************************************/
 
-#ifdef CONFIG_IOMMU_API
-
 static void cleanup_domain(struct protection_domain *domain)
 {
        unsigned long flags;
@@ -1837,4 +1934,3 @@ static struct iommu_ops amd_iommu_ops = {
        .iova_to_phys = amd_iommu_iova_to_phys,
 };
 
-#endif