OSDN Git Service

Merge branches 'iommu/fixes', 'arm/msm', 'arm/tegra', 'arm/mediatek', 'x86/vt-d'...
[uclinux-h8/linux.git] / drivers / iommu / amd_iommu.c
index 87ba23a..6b0760d 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #define pr_fmt(fmt)     "AMD-Vi: " fmt
+#define dev_fmt(fmt)    pr_fmt(fmt)
 
 #include <linux/ratelimit.h>
 #include <linux/pci.h>
@@ -279,10 +280,10 @@ static u16 get_alias(struct device *dev)
                return pci_alias;
        }
 
-       pr_info("Using IVRS reported alias %02x:%02x.%d "
-               "for device %s[%04x:%04x], kernel reported alias "
+       pci_info(pdev, "Using IVRS reported alias %02x:%02x.%d "
+               "for device [%04x:%04x], kernel reported alias "
                "%02x:%02x.%d\n", PCI_BUS_NUM(ivrs_alias), PCI_SLOT(ivrs_alias),
-               PCI_FUNC(ivrs_alias), dev_name(dev), pdev->vendor, pdev->device,
+               PCI_FUNC(ivrs_alias), pdev->vendor, pdev->device,
                PCI_BUS_NUM(pci_alias), PCI_SLOT(pci_alias),
                PCI_FUNC(pci_alias));
 
@@ -293,9 +294,8 @@ static u16 get_alias(struct device *dev)
        if (pci_alias == devid &&
            PCI_BUS_NUM(ivrs_alias) == pdev->bus->number) {
                pci_add_dma_alias(pdev, ivrs_alias & 0xff);
-               pr_info("Added PCI DMA alias %02x.%d for %s\n",
-                       PCI_SLOT(ivrs_alias), PCI_FUNC(ivrs_alias),
-                       dev_name(dev));
+               pci_info(pdev, "Added PCI DMA alias %02x.%d\n",
+                       PCI_SLOT(ivrs_alias), PCI_FUNC(ivrs_alias));
        }
 
        return ivrs_alias;
@@ -545,7 +545,7 @@ static void amd_iommu_report_page_fault(u16 devid, u16 domain_id,
                dev_data = get_dev_data(&pdev->dev);
 
        if (dev_data && __ratelimit(&dev_data->rs)) {
-               dev_err(&pdev->dev, "Event logged [IO_PAGE_FAULT domain=0x%04x address=0x%llx flags=0x%04x]\n",
+               pci_err(pdev, "Event logged [IO_PAGE_FAULT domain=0x%04x address=0x%llx flags=0x%04x]\n",
                        domain_id, address, flags);
        } else if (printk_ratelimit()) {
                pr_err("Event logged [IO_PAGE_FAULT device=%02x:%02x.%x domain=0x%04x address=0x%llx flags=0x%04x]\n",
@@ -1991,16 +1991,13 @@ static void do_attach(struct iommu_dev_data *dev_data,
 
 static void do_detach(struct iommu_dev_data *dev_data)
 {
+       struct protection_domain *domain = dev_data->domain;
        struct amd_iommu *iommu;
        u16 alias;
 
        iommu = amd_iommu_rlookup_table[dev_data->devid];
        alias = dev_data->alias;
 
-       /* decrease reference counters */
-       dev_data->domain->dev_iommu[iommu->index] -= 1;
-       dev_data->domain->dev_cnt                 -= 1;
-
        /* Update data structures */
        dev_data->domain = NULL;
        list_del(&dev_data->list);
@@ -2010,6 +2007,16 @@ static void do_detach(struct iommu_dev_data *dev_data)
 
        /* Flush the DTE entry */
        device_flush_dte(dev_data);
+
+       /* Flush IOTLB */
+       domain_flush_tlb_pde(domain);
+
+       /* Wait for the flushes to finish */
+       domain_flush_complete(domain);
+
+       /* decrease reference counters - needs to happen after the flushes */
+       domain->dev_iommu[iommu->index] -= 1;
+       domain->dev_cnt                 -= 1;
 }
 
 /*
@@ -2251,8 +2258,7 @@ static int amd_iommu_add_device(struct device *dev)
        ret = iommu_init_device(dev);
        if (ret) {
                if (ret != -ENOTSUPP)
-                       pr_err("Failed to initialize device %s - trying to proceed anyway\n",
-                               dev_name(dev));
+                       dev_err(dev, "Failed to initialize - trying to proceed anyway\n");
 
                iommu_ignore_device(dev);
                dev->dma_ops = NULL;
@@ -2562,6 +2568,7 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
        struct scatterlist *s;
        unsigned long address;
        u64 dma_mask;
+       int ret;
 
        domain = get_domain(dev);
        if (IS_ERR(domain))
@@ -2584,7 +2591,6 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
 
                for (j = 0; j < pages; ++j) {
                        unsigned long bus_addr, phys_addr;
-                       int ret;
 
                        bus_addr  = address + s->dma_address + (j << PAGE_SHIFT);
                        phys_addr = (sg_phys(s) & PAGE_MASK) + (j << PAGE_SHIFT);
@@ -2605,8 +2611,8 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
        return nelems;
 
 out_unmap:
-       pr_err("%s: IOMMU mapping error in map_sg (io-pages: %d)\n",
-              dev_name(dev), npages);
+       dev_err(dev, "IOMMU mapping error in map_sg (io-pages: %d reason: %d)\n",
+               npages, ret);
 
        for_each_sg(sglist, s, nelems, i) {
                int j, pages = iommu_num_pages(sg_phys(s), s->length, PAGE_SIZE);
@@ -2617,13 +2623,13 @@ out_unmap:
                        bus_addr  = address + s->dma_address + (j << PAGE_SHIFT);
                        iommu_unmap_page(domain, bus_addr, PAGE_SIZE);
 
-                       if (--mapped_pages)
+                       if (--mapped_pages == 0)
                                goto out_free_iova;
                }
        }
 
 out_free_iova:
-       free_iova_fast(&dma_dom->iovad, address, npages);
+       free_iova_fast(&dma_dom->iovad, address >> PAGE_SHIFT, npages);
 
 out_err:
        return 0;
@@ -2800,7 +2806,7 @@ static int init_reserved_iova_ranges(void)
                                           IOVA_PFN(r->start),
                                           IOVA_PFN(r->end));
                        if (!val) {
-                               pr_err("Reserve pci-resource range failed\n");
+                               pci_err(pdev, "Reserve pci-resource range %pR failed\n", r);
                                return -ENOMEM;
                        }
                }
@@ -3170,8 +3176,7 @@ static void amd_iommu_get_resv_regions(struct device *dev,
                                                 length, prot,
                                                 IOMMU_RESV_DIRECT);
                if (!region) {
-                       pr_err("Out of memory allocating dm-regions for %s\n",
-                               dev_name(dev));
+                       dev_err(dev, "Out of memory allocating dm-regions\n");
                        return;
                }
                list_add_tail(&region->list, head);