]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/iommu/amd_iommu.c
Merge tag 'linux-kselftest-5.5-rc1-fixes2' of git://git.kernel.org/pub/scm/linux...
[linux.git] / drivers / iommu / amd_iommu.c
index 12e5039a7a256f507795610f75d19805595bc7d9..bd25674ee4dbab8392b00b744693b5e63b756262 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-direct.h>
+#include <linux/dma-iommu.h>
 #include <linux/iommu-helper.h>
 #include <linux/iommu.h>
 #include <linux/delay.h>
@@ -88,8 +89,6 @@ const struct iommu_ops amd_iommu_ops;
 static ATOMIC_NOTIFIER_HEAD(ppr_notifier);
 int amd_iommu_max_glx_val = -1;
 
-static const struct dma_map_ops amd_iommu_dma_ops;
-
 /*
  * general struct to manage commands send to an IOMMU
  */
@@ -102,21 +101,6 @@ struct kmem_cache *amd_iommu_irq_cache;
 static void update_domain(struct protection_domain *domain);
 static int protection_domain_init(struct protection_domain *domain);
 static void detach_device(struct device *dev);
-static void iova_domain_flush_tlb(struct iova_domain *iovad);
-
-/*
- * Data container for a dma_ops specific protection domain
- */
-struct dma_ops_domain {
-       /* generic protection domain information */
-       struct protection_domain domain;
-
-       /* IOVA RB-Tree */
-       struct iova_domain iovad;
-};
-
-static struct iova_domain reserved_iova_ranges;
-static struct lock_class_key reserved_rbtree_key;
 
 /****************************************************************************
  *
@@ -167,12 +151,6 @@ static struct protection_domain *to_pdomain(struct iommu_domain *dom)
        return container_of(dom, struct protection_domain, domain);
 }
 
-static struct dma_ops_domain* to_dma_ops_domain(struct protection_domain *domain)
-{
-       BUG_ON(domain->flags != PD_DMA_OPS_MASK);
-       return container_of(domain, struct dma_ops_domain, domain);
-}
-
 static struct iommu_dev_data *alloc_dev_data(u16 devid)
 {
        struct iommu_dev_data *dev_data;
@@ -206,71 +184,61 @@ static struct iommu_dev_data *search_dev_data(u16 devid)
        return NULL;
 }
 
-static int __last_alias(struct pci_dev *pdev, u16 alias, void *data)
-{
-       *(u16 *)data = alias;
-       return 0;
-}
-
-static u16 get_alias(struct device *dev)
+static int clone_alias(struct pci_dev *pdev, u16 alias, void *data)
 {
-       struct pci_dev *pdev = to_pci_dev(dev);
-       u16 devid, ivrs_alias, pci_alias;
-
-       /* The callers make sure that get_device_id() does not fail here */
-       devid = get_device_id(dev);
+       u16 devid = pci_dev_id(pdev);
 
-       /* For ACPI HID devices, we simply return the devid as such */
-       if (!dev_is_pci(dev))
-               return devid;
+       if (devid == alias)
+               return 0;
 
-       ivrs_alias = amd_iommu_alias_table[devid];
+       amd_iommu_rlookup_table[alias] =
+               amd_iommu_rlookup_table[devid];
+       memcpy(amd_iommu_dev_table[alias].data,
+              amd_iommu_dev_table[devid].data,
+              sizeof(amd_iommu_dev_table[alias].data));
 
-       pci_for_each_dma_alias(pdev, __last_alias, &pci_alias);
+       return 0;
+}
 
-       if (ivrs_alias == pci_alias)
-               return ivrs_alias;
+static void clone_aliases(struct pci_dev *pdev)
+{
+       if (!pdev)
+               return;
 
        /*
-        * DMA alias showdown
-        *
-        * The IVRS is fairly reliable in telling us about aliases, but it
-        * can't know about every screwy device.  If we don't have an IVRS
-        * reported alias, use the PCI reported alias.  In that case we may
-        * still need to initialize the rlookup and dev_table entries if the
-        * alias is to a non-existent device.
+        * The IVRS alias stored in the alias table may not be
+        * part of the PCI DMA aliases if it's bus differs
+        * from the original device.
         */
-       if (ivrs_alias == devid) {
-               if (!amd_iommu_rlookup_table[pci_alias]) {
-                       amd_iommu_rlookup_table[pci_alias] =
-                               amd_iommu_rlookup_table[devid];
-                       memcpy(amd_iommu_dev_table[pci_alias].data,
-                              amd_iommu_dev_table[devid].data,
-                              sizeof(amd_iommu_dev_table[pci_alias].data));
-               }
+       clone_alias(pdev, amd_iommu_alias_table[pci_dev_id(pdev)], NULL);
 
-               return pci_alias;
-       }
+       pci_for_each_dma_alias(pdev, clone_alias, NULL);
+}
 
-       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), pdev->vendor, pdev->device,
-               PCI_BUS_NUM(pci_alias), PCI_SLOT(pci_alias),
-               PCI_FUNC(pci_alias));
+static struct pci_dev *setup_aliases(struct device *dev)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       u16 ivrs_alias;
+
+       /* For ACPI HID devices, there are no aliases */
+       if (!dev_is_pci(dev))
+               return NULL;
 
        /*
-        * If we don't have a PCI DMA alias and the IVRS alias is on the same
-        * bus, then the IVRS table may know about a quirk that we don't.
+        * Add the IVRS alias to the pci aliases if it is on the same
+        * bus. The IVRS table may know about a quirk that we don't.
         */
-       if (pci_alias == devid &&
+       ivrs_alias = amd_iommu_alias_table[pci_dev_id(pdev)];
+       if (ivrs_alias != pci_dev_id(pdev) &&
            PCI_BUS_NUM(ivrs_alias) == pdev->bus->number) {
                pci_add_dma_alias(pdev, ivrs_alias & 0xff);
                pci_info(pdev, "Added PCI DMA alias %02x.%d\n",
                        PCI_SLOT(ivrs_alias), PCI_FUNC(ivrs_alias));
        }
 
-       return ivrs_alias;
+       clone_aliases(pdev);
+
+       return pdev;
 }
 
 static struct iommu_dev_data *find_dev_data(u16 devid)
@@ -408,7 +376,7 @@ static int iommu_init_device(struct device *dev)
        if (!dev_data)
                return -ENOMEM;
 
-       dev_data->alias = get_alias(dev);
+       dev_data->pdev = setup_aliases(dev);
 
        /*
         * By default we use passthrough mode for IOMMUv2 capable device.
@@ -433,20 +401,16 @@ static int iommu_init_device(struct device *dev)
 
 static void iommu_ignore_device(struct device *dev)
 {
-       u16 alias;
        int devid;
 
        devid = get_device_id(dev);
        if (devid < 0)
                return;
 
-       alias = get_alias(dev);
-
+       amd_iommu_rlookup_table[devid] = NULL;
        memset(&amd_iommu_dev_table[devid], 0, sizeof(struct dev_table_entry));
-       memset(&amd_iommu_dev_table[alias], 0, sizeof(struct dev_table_entry));
 
-       amd_iommu_rlookup_table[devid] = NULL;
-       amd_iommu_rlookup_table[alias] = NULL;
+       setup_aliases(dev);
 }
 
 static void iommu_uninit_device(struct device *dev)
@@ -620,8 +584,7 @@ static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
                        pasid, address, flags);
                break;
        case EVENT_TYPE_INV_PPR_REQ:
-               pasid = ((event[0] >> 16) & 0xFFFF)
-                       | ((event[1] << 6) & 0xF0000);
+               pasid = PPR_PASID(*((u64 *)__evt));
                tag = event[1] & 0x03FF;
                dev_err(dev, "Event logged [INVALID_PPR_REQUEST device=%02x:%02x.%x pasid=0x%05x address=0x%llx flags=0x%04x tag=0x%03x]\n",
                        PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
@@ -856,17 +819,18 @@ static void copy_cmd_to_buffer(struct amd_iommu *iommu,
                               struct iommu_cmd *cmd)
 {
        u8 *target;
-
-       target = iommu->cmd_buf + iommu->cmd_buf_tail;
-
-       iommu->cmd_buf_tail += sizeof(*cmd);
-       iommu->cmd_buf_tail %= CMD_BUFFER_SIZE;
+       u32 tail;
 
        /* Copy command to buffer */
+       tail = iommu->cmd_buf_tail;
+       target = iommu->cmd_buf + tail;
        memcpy(target, cmd, sizeof(*cmd));
 
+       tail = (tail + sizeof(*cmd)) % CMD_BUFFER_SIZE;
+       iommu->cmd_buf_tail = tail;
+
        /* Tell the IOMMU about it */
-       writel(iommu->cmd_buf_tail, iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
+       writel(tail, iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
 }
 
 static void build_completion_wait(struct iommu_cmd *cmd, u64 address)
@@ -1216,6 +1180,13 @@ static int device_flush_iotlb(struct iommu_dev_data *dev_data,
        return iommu_queue_command(iommu, &cmd);
 }
 
+static int device_flush_dte_alias(struct pci_dev *pdev, u16 alias, void *data)
+{
+       struct amd_iommu *iommu = data;
+
+       return iommu_flush_dte(iommu, alias);
+}
+
 /*
  * Command send function for invalidating a device table entry
  */
@@ -1226,14 +1197,22 @@ static int device_flush_dte(struct iommu_dev_data *dev_data)
        int ret;
 
        iommu = amd_iommu_rlookup_table[dev_data->devid];
-       alias = dev_data->alias;
 
-       ret = iommu_flush_dte(iommu, dev_data->devid);
-       if (!ret && alias != dev_data->devid)
-               ret = iommu_flush_dte(iommu, alias);
+       if (dev_data->pdev)
+               ret = pci_for_each_dma_alias(dev_data->pdev,
+                                            device_flush_dte_alias, iommu);
+       else
+               ret = iommu_flush_dte(iommu, dev_data->devid);
        if (ret)
                return ret;
 
+       alias = amd_iommu_alias_table[dev_data->devid];
+       if (alias != dev_data->devid) {
+               ret = iommu_flush_dte(iommu, alias);
+               if (ret)
+                       return ret;
+       }
+
        if (dev_data->ats.enabled)
                ret = device_flush_iotlb(dev_data, 0, ~0UL);
 
@@ -1282,12 +1261,6 @@ static void domain_flush_pages(struct protection_domain *domain,
        __domain_flush_pages(domain, address, size, 0);
 }
 
-/* Flush the whole IO/TLB for a given protection domain */
-static void domain_flush_tlb(struct protection_domain *domain)
-{
-       __domain_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 0);
-}
-
 /* Flush the whole IO/TLB for a given protection domain - including PDE */
 static void domain_flush_tlb_pde(struct protection_domain *domain)
 {
@@ -1733,43 +1706,6 @@ static unsigned long iommu_unmap_page(struct protection_domain *dom,
        return unmapped;
 }
 
-/****************************************************************************
- *
- * The next functions belong to the address allocator for the dma_ops
- * interface functions.
- *
- ****************************************************************************/
-
-
-static unsigned long dma_ops_alloc_iova(struct device *dev,
-                                       struct dma_ops_domain *dma_dom,
-                                       unsigned int pages, u64 dma_mask)
-{
-       unsigned long pfn = 0;
-
-       pages = __roundup_pow_of_two(pages);
-
-       if (dma_mask > DMA_BIT_MASK(32))
-               pfn = alloc_iova_fast(&dma_dom->iovad, pages,
-                                     IOVA_PFN(DMA_BIT_MASK(32)), false);
-
-       if (!pfn)
-               pfn = alloc_iova_fast(&dma_dom->iovad, pages,
-                                     IOVA_PFN(dma_mask), true);
-
-       return (pfn << PAGE_SHIFT);
-}
-
-static void dma_ops_free_iova(struct dma_ops_domain *dma_dom,
-                             unsigned long address,
-                             unsigned int pages)
-{
-       pages = __roundup_pow_of_two(pages);
-       address >>= PAGE_SHIFT;
-
-       free_iova_fast(&dma_dom->iovad, address, pages);
-}
-
 /****************************************************************************
  *
  * The next functions belong to the domain allocation. A domain is
@@ -1846,42 +1782,23 @@ static void free_gcr3_table(struct protection_domain *domain)
        free_page((unsigned long)domain->gcr3_tbl);
 }
 
-static void dma_ops_domain_flush_tlb(struct dma_ops_domain *dom)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&dom->domain.lock, flags);
-       domain_flush_tlb(&dom->domain);
-       domain_flush_complete(&dom->domain);
-       spin_unlock_irqrestore(&dom->domain.lock, flags);
-}
-
-static void iova_domain_flush_tlb(struct iova_domain *iovad)
-{
-       struct dma_ops_domain *dom;
-
-       dom = container_of(iovad, struct dma_ops_domain, iovad);
-
-       dma_ops_domain_flush_tlb(dom);
-}
-
 /*
  * Free a domain, only used if something went wrong in the
  * allocation path and we need to free an already allocated page table
  */
-static void dma_ops_domain_free(struct dma_ops_domain *dom)
+static void dma_ops_domain_free(struct protection_domain *domain)
 {
-       if (!dom)
+       if (!domain)
                return;
 
-       put_iova_domain(&dom->iovad);
+       iommu_put_dma_cookie(&domain->domain);
 
-       free_pagetable(&dom->domain);
+       free_pagetable(domain);
 
-       if (dom->domain.id)
-               domain_id_free(dom->domain.id);
+       if (domain->id)
+               domain_id_free(domain->id);
 
-       kfree(dom);
+       kfree(domain);
 }
 
 /*
@@ -1889,35 +1806,30 @@ static void dma_ops_domain_free(struct dma_ops_domain *dom)
  * It also initializes the page table and the address allocator data
  * structures required for the dma_ops interface
  */
-static struct dma_ops_domain *dma_ops_domain_alloc(void)
+static struct protection_domain *dma_ops_domain_alloc(void)
 {
-       struct dma_ops_domain *dma_dom;
+       struct protection_domain *domain;
 
-       dma_dom = kzalloc(sizeof(struct dma_ops_domain), GFP_KERNEL);
-       if (!dma_dom)
+       domain = kzalloc(sizeof(struct protection_domain), GFP_KERNEL);
+       if (!domain)
                return NULL;
 
-       if (protection_domain_init(&dma_dom->domain))
-               goto free_dma_dom;
-
-       dma_dom->domain.mode = PAGE_MODE_3_LEVEL;
-       dma_dom->domain.pt_root = (void *)get_zeroed_page(GFP_KERNEL);
-       dma_dom->domain.flags = PD_DMA_OPS_MASK;
-       if (!dma_dom->domain.pt_root)
-               goto free_dma_dom;
-
-       init_iova_domain(&dma_dom->iovad, PAGE_SIZE, IOVA_START_PFN);
+       if (protection_domain_init(domain))
+               goto free_domain;
 
-       if (init_iova_flush_queue(&dma_dom->iovad, iova_domain_flush_tlb, NULL))
-               goto free_dma_dom;
+       domain->mode = PAGE_MODE_3_LEVEL;
+       domain->pt_root = (void *)get_zeroed_page(GFP_KERNEL);
+       domain->flags = PD_DMA_OPS_MASK;
+       if (!domain->pt_root)
+               goto free_domain;
 
-       /* Initialize reserved ranges */
-       copy_reserved_iova(&reserved_iova_ranges, &dma_dom->iovad);
+       if (iommu_get_dma_cookie(&domain->domain) == -ENOMEM)
+               goto free_domain;
 
-       return dma_dom;
+       return domain;
 
-free_dma_dom:
-       dma_ops_domain_free(dma_dom);
+free_domain:
+       dma_ops_domain_free(domain);
 
        return NULL;
 }
@@ -2015,11 +1927,9 @@ static void do_attach(struct iommu_dev_data *dev_data,
                      struct protection_domain *domain)
 {
        struct amd_iommu *iommu;
-       u16 alias;
        bool ats;
 
        iommu = amd_iommu_rlookup_table[dev_data->devid];
-       alias = dev_data->alias;
        ats   = dev_data->ats.enabled;
 
        /* Update data structures */
@@ -2032,8 +1942,7 @@ static void do_attach(struct iommu_dev_data *dev_data,
 
        /* Update device table */
        set_dte_entry(dev_data->devid, domain, ats, dev_data->iommu_v2);
-       if (alias != dev_data->devid)
-               set_dte_entry(alias, domain, ats, dev_data->iommu_v2);
+       clone_aliases(dev_data->pdev);
 
        device_flush_dte(dev_data);
 }
@@ -2042,17 +1951,14 @@ 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;
 
        /* Update data structures */
        dev_data->domain = NULL;
        list_del(&dev_data->list);
        clear_dte_entry(dev_data->devid);
-       if (alias != dev_data->devid)
-               clear_dte_entry(alias);
+       clone_aliases(dev_data->pdev);
 
        /* Flush the DTE entry */
        device_flush_dte(dev_data);
@@ -2285,8 +2191,8 @@ static int amd_iommu_add_device(struct device *dev)
        domain = iommu_get_domain_for_dev(dev);
        if (domain->type == IOMMU_DOMAIN_IDENTITY)
                dev_data->passthrough = true;
-       else
-               dev->dma_ops = &amd_iommu_dma_ops;
+       else if (domain->type == IOMMU_DOMAIN_DMA)
+               iommu_setup_dma_ops(dev, IOVA_START_PFN << PAGE_SHIFT, 0);
 
 out:
        iommu_completion_wait(iommu);
@@ -2320,43 +2226,32 @@ static struct iommu_group *amd_iommu_device_group(struct device *dev)
        return acpihid_device_group(dev);
 }
 
+static int amd_iommu_domain_get_attr(struct iommu_domain *domain,
+               enum iommu_attr attr, void *data)
+{
+       switch (domain->type) {
+       case IOMMU_DOMAIN_UNMANAGED:
+               return -ENODEV;
+       case IOMMU_DOMAIN_DMA:
+               switch (attr) {
+               case DOMAIN_ATTR_DMA_USE_FLUSH_QUEUE:
+                       *(int *)data = !amd_iommu_unmap_flush;
+                       return 0;
+               default:
+                       return -ENODEV;
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+}
+
 /*****************************************************************************
  *
  * The next functions belong to the dma_ops mapping/unmapping code.
  *
  *****************************************************************************/
 
-/*
- * In the dma_ops path we only have the struct device. This function
- * finds the corresponding IOMMU, the protection domain and the
- * requestor id for a given device.
- * If the device is not yet associated with a domain this is also done
- * in this function.
- */
-static struct protection_domain *get_domain(struct device *dev)
-{
-       struct protection_domain *domain;
-       struct iommu_domain *io_domain;
-
-       if (!check_device(dev))
-               return ERR_PTR(-EINVAL);
-
-       domain = get_dev_data(dev)->domain;
-       if (domain == NULL && get_dev_data(dev)->defer_attach) {
-               get_dev_data(dev)->defer_attach = false;
-               io_domain = iommu_get_domain_for_dev(dev);
-               domain = to_pdomain(io_domain);
-               attach_device(dev, domain);
-       }
-       if (domain == NULL)
-               return ERR_PTR(-EBUSY);
-
-       if (!dma_ops_domain(domain))
-               return ERR_PTR(-EBUSY);
-
-       return domain;
-}
-
 static void update_device_table(struct protection_domain *domain)
 {
        struct iommu_dev_data *dev_data;
@@ -2364,13 +2259,7 @@ static void update_device_table(struct protection_domain *domain)
        list_for_each_entry(dev_data, &domain->dev_list, list) {
                set_dte_entry(dev_data->devid, domain, dev_data->ats.enabled,
                              dev_data->iommu_v2);
-
-               if (dev_data->devid == dev_data->alias)
-                       continue;
-
-               /* There is an alias, update device table entry for it */
-               set_dte_entry(dev_data->alias, domain, dev_data->ats.enabled,
-                             dev_data->iommu_v2);
+               clone_aliases(dev_data->pdev);
        }
 }
 
@@ -2382,458 +2271,6 @@ static void update_domain(struct protection_domain *domain)
        domain_flush_tlb_pde(domain);
 }
 
-static int dir2prot(enum dma_data_direction direction)
-{
-       if (direction == DMA_TO_DEVICE)
-               return IOMMU_PROT_IR;
-       else if (direction == DMA_FROM_DEVICE)
-               return IOMMU_PROT_IW;
-       else if (direction == DMA_BIDIRECTIONAL)
-               return IOMMU_PROT_IW | IOMMU_PROT_IR;
-       else
-               return 0;
-}
-
-/*
- * This function contains common code for mapping of a physically
- * contiguous memory region into DMA address space. It is used by all
- * mapping functions provided with this IOMMU driver.
- * Must be called with the domain lock held.
- */
-static dma_addr_t __map_single(struct device *dev,
-                              struct dma_ops_domain *dma_dom,
-                              phys_addr_t paddr,
-                              size_t size,
-                              enum dma_data_direction direction,
-                              u64 dma_mask)
-{
-       dma_addr_t offset = paddr & ~PAGE_MASK;
-       dma_addr_t address, start, ret;
-       unsigned long flags;
-       unsigned int pages;
-       int prot = 0;
-       int i;
-
-       pages = iommu_num_pages(paddr, size, PAGE_SIZE);
-       paddr &= PAGE_MASK;
-
-       address = dma_ops_alloc_iova(dev, dma_dom, pages, dma_mask);
-       if (!address)
-               goto out;
-
-       prot = dir2prot(direction);
-
-       start = address;
-       for (i = 0; i < pages; ++i) {
-               ret = iommu_map_page(&dma_dom->domain, start, paddr,
-                                    PAGE_SIZE, prot, GFP_ATOMIC);
-               if (ret)
-                       goto out_unmap;
-
-               paddr += PAGE_SIZE;
-               start += PAGE_SIZE;
-       }
-       address += offset;
-
-       domain_flush_np_cache(&dma_dom->domain, address, size);
-
-out:
-       return address;
-
-out_unmap:
-
-       for (--i; i >= 0; --i) {
-               start -= PAGE_SIZE;
-               iommu_unmap_page(&dma_dom->domain, start, PAGE_SIZE);
-       }
-
-       spin_lock_irqsave(&dma_dom->domain.lock, flags);
-       domain_flush_tlb(&dma_dom->domain);
-       domain_flush_complete(&dma_dom->domain);
-       spin_unlock_irqrestore(&dma_dom->domain.lock, flags);
-
-       dma_ops_free_iova(dma_dom, address, pages);
-
-       return DMA_MAPPING_ERROR;
-}
-
-/*
- * Does the reverse of the __map_single function. Must be called with
- * the domain lock held too
- */
-static void __unmap_single(struct dma_ops_domain *dma_dom,
-                          dma_addr_t dma_addr,
-                          size_t size,
-                          int dir)
-{
-       dma_addr_t i, start;
-       unsigned int pages;
-
-       pages = iommu_num_pages(dma_addr, size, PAGE_SIZE);
-       dma_addr &= PAGE_MASK;
-       start = dma_addr;
-
-       for (i = 0; i < pages; ++i) {
-               iommu_unmap_page(&dma_dom->domain, start, PAGE_SIZE);
-               start += PAGE_SIZE;
-       }
-
-       if (amd_iommu_unmap_flush) {
-               unsigned long flags;
-
-               spin_lock_irqsave(&dma_dom->domain.lock, flags);
-               domain_flush_tlb(&dma_dom->domain);
-               domain_flush_complete(&dma_dom->domain);
-               spin_unlock_irqrestore(&dma_dom->domain.lock, flags);
-               dma_ops_free_iova(dma_dom, dma_addr, pages);
-       } else {
-               pages = __roundup_pow_of_two(pages);
-               queue_iova(&dma_dom->iovad, dma_addr >> PAGE_SHIFT, pages, 0);
-       }
-}
-
-/*
- * The exported map_single function for dma_ops.
- */
-static dma_addr_t map_page(struct device *dev, struct page *page,
-                          unsigned long offset, size_t size,
-                          enum dma_data_direction dir,
-                          unsigned long attrs)
-{
-       phys_addr_t paddr = page_to_phys(page) + offset;
-       struct protection_domain *domain;
-       struct dma_ops_domain *dma_dom;
-       u64 dma_mask;
-
-       domain = get_domain(dev);
-       if (PTR_ERR(domain) == -EINVAL)
-               return (dma_addr_t)paddr;
-       else if (IS_ERR(domain))
-               return DMA_MAPPING_ERROR;
-
-       dma_mask = *dev->dma_mask;
-       dma_dom = to_dma_ops_domain(domain);
-
-       return __map_single(dev, dma_dom, paddr, size, dir, dma_mask);
-}
-
-/*
- * The exported unmap_single function for dma_ops.
- */
-static void unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
-                      enum dma_data_direction dir, unsigned long attrs)
-{
-       struct protection_domain *domain;
-       struct dma_ops_domain *dma_dom;
-
-       domain = get_domain(dev);
-       if (IS_ERR(domain))
-               return;
-
-       dma_dom = to_dma_ops_domain(domain);
-
-       __unmap_single(dma_dom, dma_addr, size, dir);
-}
-
-static int sg_num_pages(struct device *dev,
-                       struct scatterlist *sglist,
-                       int nelems)
-{
-       unsigned long mask, boundary_size;
-       struct scatterlist *s;
-       int i, npages = 0;
-
-       mask          = dma_get_seg_boundary(dev);
-       boundary_size = mask + 1 ? ALIGN(mask + 1, PAGE_SIZE) >> PAGE_SHIFT :
-                                  1UL << (BITS_PER_LONG - PAGE_SHIFT);
-
-       for_each_sg(sglist, s, nelems, i) {
-               int p, n;
-
-               s->dma_address = npages << PAGE_SHIFT;
-               p = npages % boundary_size;
-               n = iommu_num_pages(sg_phys(s), s->length, PAGE_SIZE);
-               if (p + n > boundary_size)
-                       npages += boundary_size - p;
-               npages += n;
-       }
-
-       return npages;
-}
-
-/*
- * The exported map_sg function for dma_ops (handles scatter-gather
- * lists).
- */
-static int map_sg(struct device *dev, struct scatterlist *sglist,
-                 int nelems, enum dma_data_direction direction,
-                 unsigned long attrs)
-{
-       int mapped_pages = 0, npages = 0, prot = 0, i;
-       struct protection_domain *domain;
-       struct dma_ops_domain *dma_dom;
-       struct scatterlist *s;
-       unsigned long address;
-       u64 dma_mask;
-       int ret;
-
-       domain = get_domain(dev);
-       if (IS_ERR(domain))
-               return 0;
-
-       dma_dom  = to_dma_ops_domain(domain);
-       dma_mask = *dev->dma_mask;
-
-       npages = sg_num_pages(dev, sglist, nelems);
-
-       address = dma_ops_alloc_iova(dev, dma_dom, npages, dma_mask);
-       if (!address)
-               goto out_err;
-
-       prot = dir2prot(direction);
-
-       /* Map all sg entries */
-       for_each_sg(sglist, s, nelems, i) {
-               int j, pages = iommu_num_pages(sg_phys(s), s->length, PAGE_SIZE);
-
-               for (j = 0; j < pages; ++j) {
-                       unsigned long bus_addr, phys_addr;
-
-                       bus_addr  = address + s->dma_address + (j << PAGE_SHIFT);
-                       phys_addr = (sg_phys(s) & PAGE_MASK) + (j << PAGE_SHIFT);
-                       ret = iommu_map_page(domain, bus_addr, phys_addr,
-                                            PAGE_SIZE, prot,
-                                            GFP_ATOMIC | __GFP_NOWARN);
-                       if (ret)
-                               goto out_unmap;
-
-                       mapped_pages += 1;
-               }
-       }
-
-       /* Everything is mapped - write the right values into s->dma_address */
-       for_each_sg(sglist, s, nelems, i) {
-               /*
-                * Add in the remaining piece of the scatter-gather offset that
-                * was masked out when we were determining the physical address
-                * via (sg_phys(s) & PAGE_MASK) earlier.
-                */
-               s->dma_address += address + (s->offset & ~PAGE_MASK);
-               s->dma_length   = s->length;
-       }
-
-       if (s)
-               domain_flush_np_cache(domain, s->dma_address, s->dma_length);
-
-       return nelems;
-
-out_unmap:
-       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);
-
-               for (j = 0; j < pages; ++j) {
-                       unsigned long bus_addr;
-
-                       bus_addr  = address + s->dma_address + (j << PAGE_SHIFT);
-                       iommu_unmap_page(domain, bus_addr, PAGE_SIZE);
-
-                       if (--mapped_pages == 0)
-                               goto out_free_iova;
-               }
-       }
-
-out_free_iova:
-       free_iova_fast(&dma_dom->iovad, address >> PAGE_SHIFT, npages);
-
-out_err:
-       return 0;
-}
-
-/*
- * The exported map_sg function for dma_ops (handles scatter-gather
- * lists).
- */
-static void unmap_sg(struct device *dev, struct scatterlist *sglist,
-                    int nelems, enum dma_data_direction dir,
-                    unsigned long attrs)
-{
-       struct protection_domain *domain;
-       struct dma_ops_domain *dma_dom;
-       unsigned long startaddr;
-       int npages;
-
-       domain = get_domain(dev);
-       if (IS_ERR(domain))
-               return;
-
-       startaddr = sg_dma_address(sglist) & PAGE_MASK;
-       dma_dom   = to_dma_ops_domain(domain);
-       npages    = sg_num_pages(dev, sglist, nelems);
-
-       __unmap_single(dma_dom, startaddr, npages << PAGE_SHIFT, dir);
-}
-
-/*
- * The exported alloc_coherent function for dma_ops.
- */
-static void *alloc_coherent(struct device *dev, size_t size,
-                           dma_addr_t *dma_addr, gfp_t flag,
-                           unsigned long attrs)
-{
-       u64 dma_mask = dev->coherent_dma_mask;
-       struct protection_domain *domain;
-       struct dma_ops_domain *dma_dom;
-       struct page *page;
-
-       domain = get_domain(dev);
-       if (PTR_ERR(domain) == -EINVAL) {
-               page = alloc_pages(flag, get_order(size));
-               *dma_addr = page_to_phys(page);
-               return page_address(page);
-       } else if (IS_ERR(domain))
-               return NULL;
-
-       dma_dom   = to_dma_ops_domain(domain);
-       size      = PAGE_ALIGN(size);
-       dma_mask  = dev->coherent_dma_mask;
-       flag     &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
-       flag     |= __GFP_ZERO;
-
-       page = alloc_pages(flag | __GFP_NOWARN,  get_order(size));
-       if (!page) {
-               if (!gfpflags_allow_blocking(flag))
-                       return NULL;
-
-               page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT,
-                                       get_order(size), flag & __GFP_NOWARN);
-               if (!page)
-                       return NULL;
-       }
-
-       if (!dma_mask)
-               dma_mask = *dev->dma_mask;
-
-       *dma_addr = __map_single(dev, dma_dom, page_to_phys(page),
-                                size, DMA_BIDIRECTIONAL, dma_mask);
-
-       if (*dma_addr == DMA_MAPPING_ERROR)
-               goto out_free;
-
-       return page_address(page);
-
-out_free:
-
-       if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
-               __free_pages(page, get_order(size));
-
-       return NULL;
-}
-
-/*
- * The exported free_coherent function for dma_ops.
- */
-static void free_coherent(struct device *dev, size_t size,
-                         void *virt_addr, dma_addr_t dma_addr,
-                         unsigned long attrs)
-{
-       struct protection_domain *domain;
-       struct dma_ops_domain *dma_dom;
-       struct page *page;
-
-       page = virt_to_page(virt_addr);
-       size = PAGE_ALIGN(size);
-
-       domain = get_domain(dev);
-       if (IS_ERR(domain))
-               goto free_mem;
-
-       dma_dom = to_dma_ops_domain(domain);
-
-       __unmap_single(dma_dom, dma_addr, size, DMA_BIDIRECTIONAL);
-
-free_mem:
-       if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
-               __free_pages(page, get_order(size));
-}
-
-/*
- * This function is called by the DMA layer to find out if we can handle a
- * particular device. It is part of the dma_ops.
- */
-static int amd_iommu_dma_supported(struct device *dev, u64 mask)
-{
-       if (!dma_direct_supported(dev, mask))
-               return 0;
-       return check_device(dev);
-}
-
-static const struct dma_map_ops amd_iommu_dma_ops = {
-       .alloc          = alloc_coherent,
-       .free           = free_coherent,
-       .map_page       = map_page,
-       .unmap_page     = unmap_page,
-       .map_sg         = map_sg,
-       .unmap_sg       = unmap_sg,
-       .dma_supported  = amd_iommu_dma_supported,
-       .mmap           = dma_common_mmap,
-       .get_sgtable    = dma_common_get_sgtable,
-};
-
-static int init_reserved_iova_ranges(void)
-{
-       struct pci_dev *pdev = NULL;
-       struct iova *val;
-
-       init_iova_domain(&reserved_iova_ranges, PAGE_SIZE, IOVA_START_PFN);
-
-       lockdep_set_class(&reserved_iova_ranges.iova_rbtree_lock,
-                         &reserved_rbtree_key);
-
-       /* MSI memory range */
-       val = reserve_iova(&reserved_iova_ranges,
-                          IOVA_PFN(MSI_RANGE_START), IOVA_PFN(MSI_RANGE_END));
-       if (!val) {
-               pr_err("Reserving MSI range failed\n");
-               return -ENOMEM;
-       }
-
-       /* HT memory range */
-       val = reserve_iova(&reserved_iova_ranges,
-                          IOVA_PFN(HT_RANGE_START), IOVA_PFN(HT_RANGE_END));
-       if (!val) {
-               pr_err("Reserving HT range failed\n");
-               return -ENOMEM;
-       }
-
-       /*
-        * Memory used for PCI resources
-        * FIXME: Check whether we can reserve the PCI-hole completly
-        */
-       for_each_pci_dev(pdev) {
-               int i;
-
-               for (i = 0; i < PCI_NUM_RESOURCES; ++i) {
-                       struct resource *r = &pdev->resource[i];
-
-                       if (!(r->flags & IORESOURCE_MEM))
-                               continue;
-
-                       val = reserve_iova(&reserved_iova_ranges,
-                                          IOVA_PFN(r->start),
-                                          IOVA_PFN(r->end));
-                       if (!val) {
-                               pci_err(pdev, "Reserve pci-resource range %pR failed\n", r);
-                               return -ENOMEM;
-                       }
-               }
-       }
-
-       return 0;
-}
-
 int __init amd_iommu_init_api(void)
 {
        int ret, err = 0;
@@ -2842,10 +2279,6 @@ int __init amd_iommu_init_api(void)
        if (ret)
                return ret;
 
-       ret = init_reserved_iova_ranges();
-       if (ret)
-               return ret;
-
        err = bus_set_iommu(&pci_bus_type, &amd_iommu_ops);
        if (err)
                return err;
@@ -2916,7 +2349,6 @@ static void protection_domain_free(struct protection_domain *domain)
 static int protection_domain_init(struct protection_domain *domain)
 {
        spin_lock_init(&domain->lock);
-       mutex_init(&domain->api_lock);
        domain->id = domain_id_alloc();
        if (!domain->id)
                return -ENOMEM;
@@ -2947,7 +2379,6 @@ static struct protection_domain *protection_domain_alloc(void)
 static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
 {
        struct protection_domain *pdomain;
-       struct dma_ops_domain *dma_domain;
 
        switch (type) {
        case IOMMU_DOMAIN_UNMANAGED:
@@ -2968,12 +2399,11 @@ static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
 
                break;
        case IOMMU_DOMAIN_DMA:
-               dma_domain = dma_ops_domain_alloc();
-               if (!dma_domain) {
+               pdomain = dma_ops_domain_alloc();
+               if (!pdomain) {
                        pr_err("Failed to allocate\n");
                        return NULL;
                }
-               pdomain = &dma_domain->domain;
                break;
        case IOMMU_DOMAIN_IDENTITY:
                pdomain = protection_domain_alloc();
@@ -2992,7 +2422,6 @@ static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
 static void amd_iommu_domain_free(struct iommu_domain *dom)
 {
        struct protection_domain *domain;
-       struct dma_ops_domain *dma_dom;
 
        domain = to_pdomain(dom);
 
@@ -3007,8 +2436,7 @@ static void amd_iommu_domain_free(struct iommu_domain *dom)
        switch (dom->type) {
        case IOMMU_DOMAIN_DMA:
                /* Now release the domain */
-               dma_dom = to_dma_ops_domain(domain);
-               dma_ops_domain_free(dma_dom);
+               dma_ops_domain_free(domain);
                break;
        default:
                if (domain->mode != PAGE_MODE_NONE)
@@ -3064,6 +2492,7 @@ static int amd_iommu_attach_device(struct iommu_domain *dom,
                return -EINVAL;
 
        dev_data = dev->archdata.iommu;
+       dev_data->defer_attach = false;
 
        iommu = amd_iommu_rlookup_table[dev_data->devid];
        if (!iommu)
@@ -3089,7 +2518,8 @@ static int amd_iommu_attach_device(struct iommu_domain *dom,
 }
 
 static int amd_iommu_map(struct iommu_domain *dom, unsigned long iova,
-                        phys_addr_t paddr, size_t page_size, int iommu_prot)
+                        phys_addr_t paddr, size_t page_size, int iommu_prot,
+                        gfp_t gfp)
 {
        struct protection_domain *domain = to_pdomain(dom);
        int prot = 0;
@@ -3103,9 +2533,7 @@ static int amd_iommu_map(struct iommu_domain *dom, unsigned long iova,
        if (iommu_prot & IOMMU_WRITE)
                prot |= IOMMU_PROT_IW;
 
-       mutex_lock(&domain->api_lock);
-       ret = iommu_map_page(domain, iova, paddr, page_size, prot, GFP_KERNEL);
-       mutex_unlock(&domain->api_lock);
+       ret = iommu_map_page(domain, iova, paddr, page_size, prot, gfp);
 
        domain_flush_np_cache(domain, iova, page_size);
 
@@ -3117,16 +2545,11 @@ static size_t amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova,
                              struct iommu_iotlb_gather *gather)
 {
        struct protection_domain *domain = to_pdomain(dom);
-       size_t unmap_size;
 
        if (domain->mode == PAGE_MODE_NONE)
                return 0;
 
-       mutex_lock(&domain->api_lock);
-       unmap_size = iommu_unmap_page(domain, iova, page_size);
-       mutex_unlock(&domain->api_lock);
-
-       return unmap_size;
+       return iommu_unmap_page(domain, iova, page_size);
 }
 
 static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom,
@@ -3227,19 +2650,6 @@ static void amd_iommu_put_resv_regions(struct device *dev,
                kfree(entry);
 }
 
-static void amd_iommu_apply_resv_region(struct device *dev,
-                                     struct iommu_domain *domain,
-                                     struct iommu_resv_region *region)
-{
-       struct dma_ops_domain *dma_dom = to_dma_ops_domain(to_pdomain(domain));
-       unsigned long start, end;
-
-       start = IOVA_PFN(region->start);
-       end   = IOVA_PFN(region->start + region->length - 1);
-
-       WARN_ON_ONCE(reserve_iova(&dma_dom->iovad, start, end) == NULL);
-}
-
 static bool amd_iommu_is_attach_deferred(struct iommu_domain *domain,
                                         struct device *dev)
 {
@@ -3276,9 +2686,9 @@ const struct iommu_ops amd_iommu_ops = {
        .add_device = amd_iommu_add_device,
        .remove_device = amd_iommu_remove_device,
        .device_group = amd_iommu_device_group,
+       .domain_get_attr = amd_iommu_domain_get_attr,
        .get_resv_regions = amd_iommu_get_resv_regions,
        .put_resv_regions = amd_iommu_put_resv_regions,
-       .apply_resv_region = amd_iommu_apply_resv_region,
        .is_attach_deferred = amd_iommu_is_attach_deferred,
        .pgsize_bitmap  = AMD_IOMMU_PGSIZES,
        .flush_iotlb_all = amd_iommu_flush_iotlb_all,
@@ -3590,9 +3000,23 @@ EXPORT_SYMBOL(amd_iommu_complete_ppr);
 struct iommu_domain *amd_iommu_get_v2_domain(struct pci_dev *pdev)
 {
        struct protection_domain *pdomain;
+       struct iommu_domain *io_domain;
+       struct device *dev = &pdev->dev;
+
+       if (!check_device(dev))
+               return NULL;
 
-       pdomain = get_domain(&pdev->dev);
-       if (IS_ERR(pdomain))
+       pdomain = get_dev_data(dev)->domain;
+       if (pdomain == NULL && get_dev_data(dev)->defer_attach) {
+               get_dev_data(dev)->defer_attach = false;
+               io_domain = iommu_get_domain_for_dev(dev);
+               pdomain = to_pdomain(io_domain);
+               attach_device(dev, pdomain);
+       }
+       if (pdomain == NULL)
+               return NULL;
+
+       if (!dma_ops_domain(pdomain))
                return NULL;
 
        /* Only return IOMMUv2 domains */
@@ -3732,7 +3156,20 @@ static void set_remap_table_entry(struct amd_iommu *iommu, u16 devid,
        iommu_flush_dte(iommu, devid);
 }
 
-static struct irq_remap_table *alloc_irq_table(u16 devid)
+static int set_remap_table_entry_alias(struct pci_dev *pdev, u16 alias,
+                                      void *data)
+{
+       struct irq_remap_table *table = data;
+
+       irq_lookup_table[alias] = table;
+       set_dte_irq_entry(alias, table);
+
+       iommu_flush_dte(amd_iommu_rlookup_table[alias], alias);
+
+       return 0;
+}
+
+static struct irq_remap_table *alloc_irq_table(u16 devid, struct pci_dev *pdev)
 {
        struct irq_remap_table *table = NULL;
        struct irq_remap_table *new_table = NULL;
@@ -3778,7 +3215,12 @@ static struct irq_remap_table *alloc_irq_table(u16 devid)
        table = new_table;
        new_table = NULL;
 
-       set_remap_table_entry(iommu, devid, table);
+       if (pdev)
+               pci_for_each_dma_alias(pdev, set_remap_table_entry_alias,
+                                      table);
+       else
+               set_remap_table_entry(iommu, devid, table);
+
        if (devid != alias)
                set_remap_table_entry(iommu, alias, table);
 
@@ -3795,7 +3237,8 @@ static struct irq_remap_table *alloc_irq_table(u16 devid)
        return table;
 }
 
-static int alloc_irq_index(u16 devid, int count, bool align)
+static int alloc_irq_index(u16 devid, int count, bool align,
+                          struct pci_dev *pdev)
 {
        struct irq_remap_table *table;
        int index, c, alignment = 1;
@@ -3805,7 +3248,7 @@ static int alloc_irq_index(u16 devid, int count, bool align)
        if (!iommu)
                return -ENODEV;
 
-       table = alloc_irq_table(devid);
+       table = alloc_irq_table(devid, pdev);
        if (!table)
                return -ENODEV;
 
@@ -4238,7 +3681,7 @@ static int irq_remapping_alloc(struct irq_domain *domain, unsigned int virq,
                struct irq_remap_table *table;
                struct amd_iommu *iommu;
 
-               table = alloc_irq_table(devid);
+               table = alloc_irq_table(devid, NULL);
                if (table) {
                        if (!table->min_index) {
                                /*
@@ -4255,11 +3698,15 @@ static int irq_remapping_alloc(struct irq_domain *domain, unsigned int virq,
                } else {
                        index = -ENOMEM;
                }
-       } else {
+       } else if (info->type == X86_IRQ_ALLOC_TYPE_MSI ||
+                  info->type == X86_IRQ_ALLOC_TYPE_MSIX) {
                bool align = (info->type == X86_IRQ_ALLOC_TYPE_MSI);
 
-               index = alloc_irq_index(devid, nr_irqs, align);
+               index = alloc_irq_index(devid, nr_irqs, align, info->msi_dev);
+       } else {
+               index = alloc_irq_index(devid, nr_irqs, false, NULL);
        }
+
        if (index < 0) {
                pr_warn("Failed to allocate IRTE\n");
                ret = index;