Merge tag 'iommu-updates-v4.13' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 12 Jul 2017 17:00:04 +0000 (10:00 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 12 Jul 2017 17:00:04 +0000 (10:00 -0700)
Pull IOMMU updates from Joerg Roedel:
 "This update comes with:

   - Support for lockless operation in the ARM io-pgtable code.

     This is an important step to solve the scalability problems in the
     common dma-iommu code for ARM

   - Some Errata workarounds for ARM SMMU implemenations

   - Rewrite of the deferred IO/TLB flush code in the AMD IOMMU driver.

     The code suffered from very high flush rates, with the new
     implementation the flush rate is down to ~1% of what it was before

   - Support for amd_iommu=off when booting with kexec.

     The problem here was that the IOMMU driver bailed out early without
     disabling the iommu hardware, if it was enabled in the old kernel

   - The Rockchip IOMMU driver is now available on ARM64

   - Align the return value of the iommu_ops->device_group call-backs to
     not miss error values

   - Preempt-disable optimizations in the Intel VT-d and common IOVA
     code to help Linux-RT

   - Various other small cleanups and fixes"

* tag 'iommu-updates-v4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: (60 commits)
  iommu/vt-d: Constify intel_dma_ops
  iommu: Warn once when device_group callback returns NULL
  iommu/omap: Return ERR_PTR in device_group call-back
  iommu: Return ERR_PTR() values from device_group call-backs
  iommu/s390: Use iommu_group_get_for_dev() in s390_iommu_add_device()
  iommu/vt-d: Don't disable preemption while accessing deferred_flush()
  iommu/iova: Don't disable preempt around this_cpu_ptr()
  iommu/arm-smmu-v3: Add workaround for Cavium ThunderX2 erratum #126
  iommu/arm-smmu-v3: Enable ACPI based HiSilicon CMD_PREFETCH quirk(erratum 161010701)
  iommu/arm-smmu-v3: Add workaround for Cavium ThunderX2 erratum #74
  ACPI/IORT: Fixup SMMUv3 resource size for Cavium ThunderX2 SMMUv3 model
  iommu/arm-smmu-v3, acpi: Add temporary Cavium SMMU-V3 IORT model number definitions
  iommu/io-pgtable-arm: Use dma_wmb() instead of wmb() when publishing table
  iommu/io-pgtable: depend on !GENERIC_ATOMIC64 when using COMPILE_TEST with LPAE
  iommu/arm-smmu-v3: Remove io-pgtable spinlock
  iommu/arm-smmu: Remove io-pgtable spinlock
  iommu/io-pgtable-arm-v7s: Support lockless operation
  iommu/io-pgtable-arm: Support lockless operation
  iommu/io-pgtable: Introduce explicit coherency
  iommu/io-pgtable-arm-v7s: Refactor split_blk_unmap
  ...

1  2 
Documentation/arm64/silicon-errata.txt
drivers/acpi/arm64/iort.c
drivers/iommu/amd_iommu.c
drivers/iommu/dma-iommu.c
drivers/iommu/intel-iommu.c
drivers/iommu/intel_irq_remapping.c

@@@ -61,12 -61,14 +61,15 @@@ stable kernels
  | Cavium         | ThunderX ITS    | #23144          | CAVIUM_ERRATUM_23144        |
  | Cavium         | ThunderX GICv3  | #23154          | CAVIUM_ERRATUM_23154        |
  | Cavium         | ThunderX Core   | #27456          | CAVIUM_ERRATUM_27456        |
- | Cavium         | ThunderX SMMUv2 | #27704          | N/A                         |
 +| Cavium         | ThunderX Core   | #30115          | CAVIUM_ERRATUM_30115        |
+ | Cavium         | ThunderX SMMUv2 | #27704          | N/A                         |
+ | Cavium         | ThunderX2 SMMUv3| #74             | N/A                         |
+ | Cavium         | ThunderX2 SMMUv3| #126            | N/A                         |
  |                |                 |                 |                             |
  | Freescale/NXP  | LS2080A/LS1043A | A-008585        | FSL_ERRATUM_A008585         |
  |                |                 |                 |                             |
  | Hisilicon      | Hip0{5,6,7}     | #161010101      | HISILICON_ERRATUM_161010101 |
+ | Hisilicon      | Hip0{6,7}       | #161010701      | N/A                         |
  |                |                 |                 |                             |
  | Qualcomm Tech. | Falkor v1       | E1003           | QCOM_FALKOR_ERRATUM_1003    |
  | Qualcomm Tech. | Falkor v1       | E1009           | QCOM_FALKOR_ERRATUM_1009    |
  #define IORT_IOMMU_TYPE               ((1 << ACPI_IORT_NODE_SMMU) |   \
                                (1 << ACPI_IORT_NODE_SMMU_V3))
  
+ /* Until ACPICA headers cover IORT rev. C */
+ #ifndef ACPI_IORT_SMMU_V3_CAVIUM_CN99XX
+ #define ACPI_IORT_SMMU_V3_CAVIUM_CN99XX               0x2
+ #endif
  struct iort_its_msi_chip {
        struct list_head        list;
        struct fwnode_handle    *fw_node;
@@@ -234,6 -239,21 +239,6 @@@ static struct acpi_iort_node *iort_scan
        return NULL;
  }
  
 -static acpi_status
 -iort_match_type_callback(struct acpi_iort_node *node, void *context)
 -{
 -      return AE_OK;
 -}
 -
 -bool iort_node_match(u8 type)
 -{
 -      struct acpi_iort_node *node;
 -
 -      node = iort_scan_node(type, iort_match_type_callback, NULL);
 -
 -      return node != NULL;
 -}
 -
  static acpi_status iort_match_node_callback(struct acpi_iort_node *node,
                                            void *context)
  {
@@@ -819,6 -839,36 +824,36 @@@ static int __init arm_smmu_v3_count_res
        return num_res;
  }
  
+ static bool arm_smmu_v3_is_combined_irq(struct acpi_iort_smmu_v3 *smmu)
+ {
+       /*
+        * Cavium ThunderX2 implementation doesn't not support unique
+        * irq line. Use single irq line for all the SMMUv3 interrupts.
+        */
+       if (smmu->model != ACPI_IORT_SMMU_V3_CAVIUM_CN99XX)
+               return false;
+       /*
+        * ThunderX2 doesn't support MSIs from the SMMU, so we're checking
+        * SPI numbers here.
+        */
+       return smmu->event_gsiv == smmu->pri_gsiv &&
+              smmu->event_gsiv == smmu->gerr_gsiv &&
+              smmu->event_gsiv == smmu->sync_gsiv;
+ }
+ static unsigned long arm_smmu_v3_resource_size(struct acpi_iort_smmu_v3 *smmu)
+ {
+       /*
+        * Override the size, for Cavium ThunderX2 implementation
+        * which doesn't support the page 1 SMMU register space.
+        */
+       if (smmu->model == ACPI_IORT_SMMU_V3_CAVIUM_CN99XX)
+               return SZ_64K;
+       return SZ_128K;
+ }
  static void __init arm_smmu_v3_init_resources(struct resource *res,
                                              struct acpi_iort_node *node)
  {
        smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
  
        res[num_res].start = smmu->base_address;
-       res[num_res].end = smmu->base_address + SZ_128K - 1;
+       res[num_res].end = smmu->base_address +
+                               arm_smmu_v3_resource_size(smmu) - 1;
        res[num_res].flags = IORESOURCE_MEM;
  
        num_res++;
+       if (arm_smmu_v3_is_combined_irq(smmu)) {
+               if (smmu->event_gsiv)
+                       acpi_iort_register_irq(smmu->event_gsiv, "combined",
+                                              ACPI_EDGE_SENSITIVE,
+                                              &res[num_res++]);
+       } else {
  
-       if (smmu->event_gsiv)
-               acpi_iort_register_irq(smmu->event_gsiv, "eventq",
-                                      ACPI_EDGE_SENSITIVE,
-                                      &res[num_res++]);
-       if (smmu->pri_gsiv)
-               acpi_iort_register_irq(smmu->pri_gsiv, "priq",
-                                      ACPI_EDGE_SENSITIVE,
-                                      &res[num_res++]);
-       if (smmu->gerr_gsiv)
-               acpi_iort_register_irq(smmu->gerr_gsiv, "gerror",
-                                      ACPI_EDGE_SENSITIVE,
-                                      &res[num_res++]);
-       if (smmu->sync_gsiv)
-               acpi_iort_register_irq(smmu->sync_gsiv, "cmdq-sync",
-                                      ACPI_EDGE_SENSITIVE,
-                                      &res[num_res++]);
+               if (smmu->event_gsiv)
+                       acpi_iort_register_irq(smmu->event_gsiv, "eventq",
+                                              ACPI_EDGE_SENSITIVE,
+                                              &res[num_res++]);
+               if (smmu->pri_gsiv)
+                       acpi_iort_register_irq(smmu->pri_gsiv, "priq",
+                                              ACPI_EDGE_SENSITIVE,
+                                              &res[num_res++]);
+               if (smmu->gerr_gsiv)
+                       acpi_iort_register_irq(smmu->gerr_gsiv, "gerror",
+                                              ACPI_EDGE_SENSITIVE,
+                                              &res[num_res++]);
+               if (smmu->sync_gsiv)
+                       acpi_iort_register_irq(smmu->sync_gsiv, "cmdq-sync",
+                                              ACPI_EDGE_SENSITIVE,
+                                              &res[num_res++]);
+       }
  }
  
  static bool __init arm_smmu_v3_is_coherent(struct acpi_iort_node *node)
@@@ -54,8 -54,6 +54,8 @@@
  #include "amd_iommu_types.h"
  #include "irq_remapping.h"
  
 +#define AMD_IOMMU_MAPPING_ERROR       0
 +
  #define CMD_SET_TYPE(cmd, t) ((cmd)->data[1] |= ((t) << 28))
  
  #define LOOP_TIMEOUT  100000
@@@ -91,25 -89,6 +91,6 @@@ LIST_HEAD(ioapic_map)
  LIST_HEAD(hpet_map);
  LIST_HEAD(acpihid_map);
  
- #define FLUSH_QUEUE_SIZE 256
- struct flush_queue_entry {
-       unsigned long iova_pfn;
-       unsigned long pages;
-       struct dma_ops_domain *dma_dom;
- };
- struct flush_queue {
-       spinlock_t lock;
-       unsigned next;
-       struct flush_queue_entry *entries;
- };
- static DEFINE_PER_CPU(struct flush_queue, flush_queue);
- static atomic_t queue_timer_on;
- static struct timer_list queue_timer;
  /*
   * Domain for untranslated devices - only allocated
   * if iommu=pt passed on kernel cmd line.
@@@ -140,6 -119,8 +121,8 @@@ struct iommu_dev_data 
                                             PPR completions */
        u32 errata;                       /* Bitmap for errata to apply */
        bool use_vapic;                   /* Enable device to use vapic mode */
+       struct ratelimit_state rs;        /* Ratelimit IOPF messages */
  };
  
  /*
@@@ -155,6 -136,20 +138,20 @@@ static void update_domain(struct protec
  static int protection_domain_init(struct protection_domain *domain);
  static void detach_device(struct device *dev);
  
+ #define FLUSH_QUEUE_SIZE 256
+ struct flush_queue_entry {
+       unsigned long iova_pfn;
+       unsigned long pages;
+       u64 counter; /* Flush counter when this entry was added to the queue */
+ };
+ struct flush_queue {
+       struct flush_queue_entry *entries;
+       unsigned head, tail;
+       spinlock_t lock;
+ };
  /*
   * Data container for a dma_ops specific protection domain
   */
@@@ -164,6 -159,36 +161,36 @@@ struct dma_ops_domain 
  
        /* IOVA RB-Tree */
        struct iova_domain iovad;
+       struct flush_queue __percpu *flush_queue;
+       /*
+        * We need two counter here to be race-free wrt. IOTLB flushing and
+        * adding entries to the flush queue.
+        *
+        * The flush_start_cnt is incremented _before_ the IOTLB flush starts.
+        * New entries added to the flush ring-buffer get their 'counter' value
+        * from here. This way we can make sure that entries added to the queue
+        * (or other per-cpu queues of the same domain) while the TLB is about
+        * to be flushed are not considered to be flushed already.
+        */
+       atomic64_t flush_start_cnt;
+       /*
+        * The flush_finish_cnt is incremented when an IOTLB flush is complete.
+        * This value is always smaller than flush_start_cnt. The queue_add
+        * function frees all IOVAs that have a counter value smaller than
+        * flush_finish_cnt. This makes sure that we only free IOVAs that are
+        * flushed out of the IOTLB of the domain.
+        */
+       atomic64_t flush_finish_cnt;
+       /*
+        * Timer to make sure we don't keep IOVAs around unflushed
+        * for too long
+        */
+       struct timer_list flush_timer;
+       atomic_t flush_timer_on;
  };
  
  static struct iova_domain reserved_iova_ranges;
@@@ -255,6 -280,8 +282,8 @@@ static struct iommu_dev_data *alloc_dev
        list_add_tail(&dev_data->dev_data_list, &dev_data_list);
        spin_unlock_irqrestore(&dev_data_list_lock, flags);
  
+       ratelimit_default_init(&dev_data->rs);
        return dev_data;
  }
  
@@@ -553,6 -580,29 +582,29 @@@ static void dump_command(unsigned long 
                pr_err("AMD-Vi: CMD[%d]: %08x\n", i, cmd->data[i]);
  }
  
+ static void amd_iommu_report_page_fault(u16 devid, u16 domain_id,
+                                       u64 address, int flags)
+ {
+       struct iommu_dev_data *dev_data = NULL;
+       struct pci_dev *pdev;
+       pdev = pci_get_bus_and_slot(PCI_BUS_NUM(devid), devid & 0xff);
+       if (pdev)
+               dev_data = get_dev_data(&pdev->dev);
+       if (dev_data && __ratelimit(&dev_data->rs)) {
+               dev_err(&pdev->dev, "AMD-Vi: Event logged [IO_PAGE_FAULT domain=0x%04x address=0x%016llx flags=0x%04x]\n",
+                       domain_id, address, flags);
+       } else if (printk_ratelimit()) {
+               pr_err("AMD-Vi: Event logged [IO_PAGE_FAULT device=%02x:%02x.%x domain=0x%04x address=0x%016llx flags=0x%04x]\n",
+                       PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+                       domain_id, address, flags);
+       }
+       if (pdev)
+               pci_dev_put(pdev);
+ }
  static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
  {
        int type, devid, domid, flags;
@@@ -577,7 -627,12 +629,12 @@@ retry
                goto retry;
        }
  
-       printk(KERN_ERR "AMD-Vi: Event logged [");
+       if (type == EVENT_TYPE_IO_FAULT) {
+               amd_iommu_report_page_fault(devid, domid, address, flags);
+               return;
+       } else {
+               printk(KERN_ERR "AMD-Vi: Event logged [");
+       }
  
        switch (type) {
        case EVENT_TYPE_ILL_DEV:
                       address, flags);
                dump_dte_entry(devid);
                break;
-       case EVENT_TYPE_IO_FAULT:
-               printk("IO_PAGE_FAULT device=%02x:%02x.%x "
-                      "domain=0x%04x address=0x%016llx flags=0x%04x]\n",
-                      PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
-                      domid, address, flags);
-               break;
        case EVENT_TYPE_DEV_TAB_ERR:
                printk("DEV_TAB_HARDWARE_ERROR device=%02x:%02x.%x "
                       "address=0x%016llx flags=0x%04x]\n",
@@@ -850,19 -899,20 +901,20 @@@ static int wait_on_sem(volatile u64 *se
  }
  
  static void copy_cmd_to_buffer(struct amd_iommu *iommu,
-                              struct iommu_cmd *cmd,
-                              u32 tail)
+                              struct iommu_cmd *cmd)
  {
        u8 *target;
  
-       target = iommu->cmd_buf + tail;
-       tail   = (tail + sizeof(*cmd)) % CMD_BUFFER_SIZE;
+       target = iommu->cmd_buf + iommu->cmd_buf_tail;
+       iommu->cmd_buf_tail += sizeof(*cmd);
+       iommu->cmd_buf_tail %= CMD_BUFFER_SIZE;
  
        /* Copy command to buffer */
        memcpy(target, cmd, sizeof(*cmd));
  
        /* Tell the IOMMU about it */
-       writel(tail, iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
+       writel(iommu->cmd_buf_tail, iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
  }
  
  static void build_completion_wait(struct iommu_cmd *cmd, u64 address)
@@@ -1020,33 -1070,34 +1072,34 @@@ static int __iommu_queue_command_sync(s
                                      struct iommu_cmd *cmd,
                                      bool sync)
  {
-       u32 left, tail, head, next_tail;
+       unsigned int count = 0;
+       u32 left, next_tail;
  
+       next_tail = (iommu->cmd_buf_tail + sizeof(*cmd)) % CMD_BUFFER_SIZE;
  again:
-       head      = readl(iommu->mmio_base + MMIO_CMD_HEAD_OFFSET);
-       tail      = readl(iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
-       next_tail = (tail + sizeof(*cmd)) % CMD_BUFFER_SIZE;
-       left      = (head - next_tail) % CMD_BUFFER_SIZE;
+       left      = (iommu->cmd_buf_head - next_tail) % CMD_BUFFER_SIZE;
  
        if (left <= 0x20) {
-               struct iommu_cmd sync_cmd;
-               int ret;
-               iommu->cmd_sem = 0;
+               /* Skip udelay() the first time around */
+               if (count++) {
+                       if (count == LOOP_TIMEOUT) {
+                               pr_err("AMD-Vi: Command buffer timeout\n");
+                               return -EIO;
+                       }
  
-               build_completion_wait(&sync_cmd, (u64)&iommu->cmd_sem);
-               copy_cmd_to_buffer(iommu, &sync_cmd, tail);
+                       udelay(1);
+               }
  
-               if ((ret = wait_on_sem(&iommu->cmd_sem)) != 0)
-                       return ret;
+               /* Update head and recheck remaining space */
+               iommu->cmd_buf_head = readl(iommu->mmio_base +
+                                           MMIO_CMD_HEAD_OFFSET);
  
                goto again;
        }
  
-       copy_cmd_to_buffer(iommu, cmd, tail);
+       copy_cmd_to_buffer(iommu, cmd);
  
-       /* We need to sync now to make sure all commands are processed */
+       /* Do we need to make sure all commands are processed? */
        iommu->need_sync = sync;
  
        return 0;
@@@ -1735,6 -1786,180 +1788,180 @@@ static void free_gcr3_table(struct prot
        free_page((unsigned long)domain->gcr3_tbl);
  }
  
+ static void dma_ops_domain_free_flush_queue(struct dma_ops_domain *dom)
+ {
+       int cpu;
+       for_each_possible_cpu(cpu) {
+               struct flush_queue *queue;
+               queue = per_cpu_ptr(dom->flush_queue, cpu);
+               kfree(queue->entries);
+       }
+       free_percpu(dom->flush_queue);
+       dom->flush_queue = NULL;
+ }
+ static int dma_ops_domain_alloc_flush_queue(struct dma_ops_domain *dom)
+ {
+       int cpu;
+       atomic64_set(&dom->flush_start_cnt,  0);
+       atomic64_set(&dom->flush_finish_cnt, 0);
+       dom->flush_queue = alloc_percpu(struct flush_queue);
+       if (!dom->flush_queue)
+               return -ENOMEM;
+       /* First make sure everything is cleared */
+       for_each_possible_cpu(cpu) {
+               struct flush_queue *queue;
+               queue = per_cpu_ptr(dom->flush_queue, cpu);
+               queue->head    = 0;
+               queue->tail    = 0;
+               queue->entries = NULL;
+       }
+       /* Now start doing the allocation */
+       for_each_possible_cpu(cpu) {
+               struct flush_queue *queue;
+               queue = per_cpu_ptr(dom->flush_queue, cpu);
+               queue->entries = kzalloc(FLUSH_QUEUE_SIZE * sizeof(*queue->entries),
+                                        GFP_KERNEL);
+               if (!queue->entries) {
+                       dma_ops_domain_free_flush_queue(dom);
+                       return -ENOMEM;
+               }
+               spin_lock_init(&queue->lock);
+       }
+       return 0;
+ }
+ static void dma_ops_domain_flush_tlb(struct dma_ops_domain *dom)
+ {
+       atomic64_inc(&dom->flush_start_cnt);
+       domain_flush_tlb(&dom->domain);
+       domain_flush_complete(&dom->domain);
+       atomic64_inc(&dom->flush_finish_cnt);
+ }
+ static inline bool queue_ring_full(struct flush_queue *queue)
+ {
+       assert_spin_locked(&queue->lock);
+       return (((queue->tail + 1) % FLUSH_QUEUE_SIZE) == queue->head);
+ }
+ #define queue_ring_for_each(i, q) \
+       for (i = (q)->head; i != (q)->tail; i = (i + 1) % FLUSH_QUEUE_SIZE)
+ static inline unsigned queue_ring_add(struct flush_queue *queue)
+ {
+       unsigned idx = queue->tail;
+       assert_spin_locked(&queue->lock);
+       queue->tail = (idx + 1) % FLUSH_QUEUE_SIZE;
+       return idx;
+ }
+ static inline void queue_ring_remove_head(struct flush_queue *queue)
+ {
+       assert_spin_locked(&queue->lock);
+       queue->head = (queue->head + 1) % FLUSH_QUEUE_SIZE;
+ }
+ static void queue_ring_free_flushed(struct dma_ops_domain *dom,
+                                   struct flush_queue *queue)
+ {
+       u64 counter = atomic64_read(&dom->flush_finish_cnt);
+       int idx;
+       queue_ring_for_each(idx, queue) {
+               /*
+                * This assumes that counter values in the ring-buffer are
+                * monotonously rising.
+                */
+               if (queue->entries[idx].counter >= counter)
+                       break;
+               free_iova_fast(&dom->iovad,
+                              queue->entries[idx].iova_pfn,
+                              queue->entries[idx].pages);
+               queue_ring_remove_head(queue);
+       }
+ }
+ static void queue_add(struct dma_ops_domain *dom,
+                     unsigned long address, unsigned long pages)
+ {
+       struct flush_queue *queue;
+       unsigned long flags;
+       int idx;
+       pages     = __roundup_pow_of_two(pages);
+       address >>= PAGE_SHIFT;
+       queue = get_cpu_ptr(dom->flush_queue);
+       spin_lock_irqsave(&queue->lock, flags);
+       /*
+        * First remove the enries from the ring-buffer that are already
+        * flushed to make the below queue_ring_full() check less likely
+        */
+       queue_ring_free_flushed(dom, queue);
+       /*
+        * When ring-queue is full, flush the entries from the IOTLB so
+        * that we can free all entries with queue_ring_free_flushed()
+        * below.
+        */
+       if (queue_ring_full(queue)) {
+               dma_ops_domain_flush_tlb(dom);
+               queue_ring_free_flushed(dom, queue);
+       }
+       idx = queue_ring_add(queue);
+       queue->entries[idx].iova_pfn = address;
+       queue->entries[idx].pages    = pages;
+       queue->entries[idx].counter  = atomic64_read(&dom->flush_start_cnt);
+       spin_unlock_irqrestore(&queue->lock, flags);
+       if (atomic_cmpxchg(&dom->flush_timer_on, 0, 1) == 0)
+               mod_timer(&dom->flush_timer, jiffies + msecs_to_jiffies(10));
+       put_cpu_ptr(dom->flush_queue);
+ }
+ static void queue_flush_timeout(unsigned long data)
+ {
+       struct dma_ops_domain *dom = (struct dma_ops_domain *)data;
+       int cpu;
+       atomic_set(&dom->flush_timer_on, 0);
+       dma_ops_domain_flush_tlb(dom);
+       for_each_possible_cpu(cpu) {
+               struct flush_queue *queue;
+               unsigned long flags;
+               queue = per_cpu_ptr(dom->flush_queue, cpu);
+               spin_lock_irqsave(&queue->lock, flags);
+               queue_ring_free_flushed(dom, queue);
+               spin_unlock_irqrestore(&queue->lock, flags);
+       }
+ }
  /*
   * Free a domain, only used if something went wrong in the
   * allocation path and we need to free an already allocated page table
@@@ -1746,6 -1971,11 +1973,11 @@@ static void dma_ops_domain_free(struct 
  
        del_domain_from_list(&dom->domain);
  
+       if (timer_pending(&dom->flush_timer))
+               del_timer(&dom->flush_timer);
+       dma_ops_domain_free_flush_queue(dom);
        put_iova_domain(&dom->iovad);
  
        free_pagetable(&dom->domain);
@@@ -1784,6 -2014,14 +2016,14 @@@ static struct dma_ops_domain *dma_ops_d
        /* Initialize reserved ranges */
        copy_reserved_iova(&reserved_iova_ranges, &dma_dom->iovad);
  
+       if (dma_ops_domain_alloc_flush_queue(dma_dom))
+               goto free_dma_dom;
+       setup_timer(&dma_dom->flush_timer, queue_flush_timeout,
+                   (unsigned long)dma_dom);
+       atomic_set(&dma_dom->flush_timer_on, 0);
        add_domain_to_list(&dma_dom->domain);
  
        return dma_dom;
@@@ -1846,7 -2084,8 +2086,8 @@@ static void set_dte_entry(u16 devid, st
                flags    |= tmp;
        }
  
-       flags &= ~(0xffffUL);
+       flags &= ~(DTE_FLAG_SA | 0xffffULL);
        flags |= domain->id;
  
        amd_iommu_dev_table[devid].data[1]  = flags;
@@@ -2227,92 -2466,6 +2468,6 @@@ static struct iommu_group *amd_iommu_de
   *
   *****************************************************************************/
  
- static void __queue_flush(struct flush_queue *queue)
- {
-       struct protection_domain *domain;
-       unsigned long flags;
-       int idx;
-       /* First flush TLB of all known domains */
-       spin_lock_irqsave(&amd_iommu_pd_lock, flags);
-       list_for_each_entry(domain, &amd_iommu_pd_list, list)
-               domain_flush_tlb(domain);
-       spin_unlock_irqrestore(&amd_iommu_pd_lock, flags);
-       /* Wait until flushes have completed */
-       domain_flush_complete(NULL);
-       for (idx = 0; idx < queue->next; ++idx) {
-               struct flush_queue_entry *entry;
-               entry = queue->entries + idx;
-               free_iova_fast(&entry->dma_dom->iovad,
-                               entry->iova_pfn,
-                               entry->pages);
-               /* Not really necessary, just to make sure we catch any bugs */
-               entry->dma_dom = NULL;
-       }
-       queue->next = 0;
- }
- static void queue_flush_all(void)
- {
-       int cpu;
-       for_each_possible_cpu(cpu) {
-               struct flush_queue *queue;
-               unsigned long flags;
-               queue = per_cpu_ptr(&flush_queue, cpu);
-               spin_lock_irqsave(&queue->lock, flags);
-               if (queue->next > 0)
-                       __queue_flush(queue);
-               spin_unlock_irqrestore(&queue->lock, flags);
-       }
- }
- static void queue_flush_timeout(unsigned long unsused)
- {
-       atomic_set(&queue_timer_on, 0);
-       queue_flush_all();
- }
- static void queue_add(struct dma_ops_domain *dma_dom,
-                     unsigned long address, unsigned long pages)
- {
-       struct flush_queue_entry *entry;
-       struct flush_queue *queue;
-       unsigned long flags;
-       int idx;
-       pages     = __roundup_pow_of_two(pages);
-       address >>= PAGE_SHIFT;
-       queue = get_cpu_ptr(&flush_queue);
-       spin_lock_irqsave(&queue->lock, flags);
-       if (queue->next == FLUSH_QUEUE_SIZE)
-               __queue_flush(queue);
-       idx   = queue->next++;
-       entry = queue->entries + idx;
-       entry->iova_pfn = address;
-       entry->pages    = pages;
-       entry->dma_dom  = dma_dom;
-       spin_unlock_irqrestore(&queue->lock, flags);
-       if (atomic_cmpxchg(&queue_timer_on, 0, 1) == 0)
-               mod_timer(&queue_timer, jiffies + msecs_to_jiffies(10));
-       put_cpu_ptr(&flush_queue);
- }
  /*
   * In the dma_ops path we only have the struct device. This function
   * finds the corresponding IOMMU, the protection domain and the
@@@ -2396,7 -2549,7 +2551,7 @@@ static dma_addr_t __map_single(struct d
        paddr &= PAGE_MASK;
  
        address = dma_ops_alloc_iova(dev, dma_dom, pages, dma_mask);
 -      if (address == DMA_ERROR_CODE)
 +      if (address == AMD_IOMMU_MAPPING_ERROR)
                goto out;
  
        prot = dir2prot(direction);
@@@ -2433,7 -2586,7 +2588,7 @@@ out_unmap
  
        dma_ops_free_iova(dma_dom, address, pages);
  
 -      return DMA_ERROR_CODE;
 +      return AMD_IOMMU_MAPPING_ERROR;
  }
  
  /*
@@@ -2485,7 -2638,7 +2640,7 @@@ static dma_addr_t map_page(struct devic
        if (PTR_ERR(domain) == -EINVAL)
                return (dma_addr_t)paddr;
        else if (IS_ERR(domain))
 -              return DMA_ERROR_CODE;
 +              return AMD_IOMMU_MAPPING_ERROR;
  
        dma_mask = *dev->dma_mask;
        dma_dom = to_dma_ops_domain(domain);
@@@ -2562,7 -2715,7 +2717,7 @@@ static int map_sg(struct device *dev, s
        npages = sg_num_pages(dev, sglist, nelems);
  
        address = dma_ops_alloc_iova(dev, dma_dom, npages, dma_mask);
 -      if (address == DMA_ERROR_CODE)
 +      if (address == AMD_IOMMU_MAPPING_ERROR)
                goto out_err;
  
        prot = dir2prot(direction);
@@@ -2685,7 -2838,7 +2840,7 @@@ static void *alloc_coherent(struct devi
        *dma_addr = __map_single(dev, dma_dom, page_to_phys(page),
                                 size, DMA_BIDIRECTIONAL, dma_mask);
  
 -      if (*dma_addr == DMA_ERROR_CODE)
 +      if (*dma_addr == AMD_IOMMU_MAPPING_ERROR)
                goto out_free;
  
        return page_address(page);
@@@ -2731,16 -2884,9 +2886,16 @@@ free_mem
   */
  static int amd_iommu_dma_supported(struct device *dev, u64 mask)
  {
 +      if (!x86_dma_supported(dev, mask))
 +              return 0;
        return check_device(dev);
  }
  
 +static int amd_iommu_mapping_error(struct device *dev, dma_addr_t dma_addr)
 +{
 +      return dma_addr == AMD_IOMMU_MAPPING_ERROR;
 +}
 +
  static const struct dma_map_ops amd_iommu_dma_ops = {
        .alloc          = alloc_coherent,
        .free           = free_coherent,
        .map_sg         = map_sg,
        .unmap_sg       = unmap_sg,
        .dma_supported  = amd_iommu_dma_supported,
 +      .mapping_error  = amd_iommu_mapping_error,
  };
  
  static int init_reserved_iova_ranges(void)
  
  int __init amd_iommu_init_api(void)
  {
-       int ret, cpu, err = 0;
+       int ret, err = 0;
  
        ret = iova_cache_get();
        if (ret)
        if (ret)
                return ret;
  
-       for_each_possible_cpu(cpu) {
-               struct flush_queue *queue = per_cpu_ptr(&flush_queue, cpu);
-               queue->entries = kzalloc(FLUSH_QUEUE_SIZE *
-                                        sizeof(*queue->entries),
-                                        GFP_KERNEL);
-               if (!queue->entries)
-                       goto out_put_iova;
-               spin_lock_init(&queue->lock);
-       }
        err = bus_set_iommu(&pci_bus_type, &amd_iommu_ops);
        if (err)
                return err;
        err = bus_set_iommu(&platform_bus_type, &amd_iommu_ops);
        if (err)
                return err;
-       return 0;
- out_put_iova:
-       for_each_possible_cpu(cpu) {
-               struct flush_queue *queue = per_cpu_ptr(&flush_queue, cpu);
-               kfree(queue->entries);
-       }
  
-       return -ENOMEM;
+       return 0;
  }
  
  int __init amd_iommu_init_dma_ops(void)
  {
-       setup_timer(&queue_timer, queue_flush_timeout, 0);
-       atomic_set(&queue_timer_on, 0);
        swiotlb        = iommu_pass_through ? 1 : 0;
        iommu_detected = 1;
  
@@@ -3012,12 -3134,6 +3144,6 @@@ static void amd_iommu_domain_free(struc
  
        switch (dom->type) {
        case IOMMU_DOMAIN_DMA:
-               /*
-                * First make sure the domain is no longer referenced from the
-                * flush queue
-                */
-               queue_flush_all();
                /* Now release the domain */
                dma_dom = to_dma_ops_domain(domain);
                dma_ops_domain_free(dma_dom);
@@@ -4281,7 -4397,7 +4407,7 @@@ static void irq_remapping_deactivate(st
                                            irte_info->index);
  }
  
- static struct irq_domain_ops amd_ir_domain_ops = {
+ static const struct irq_domain_ops amd_ir_domain_ops = {
        .alloc = irq_remapping_alloc,
        .free = irq_remapping_free,
        .activate = irq_remapping_activate,
@@@ -4394,29 -4510,21 +4520,29 @@@ static void ir_compose_msi_msg(struct i
  }
  
  static struct irq_chip amd_ir_chip = {
 -      .irq_ack = ir_ack_apic_edge,
 -      .irq_set_affinity = amd_ir_set_affinity,
 -      .irq_set_vcpu_affinity = amd_ir_set_vcpu_affinity,
 -      .irq_compose_msi_msg = ir_compose_msi_msg,
 +      .name                   = "AMD-IR",
 +      .irq_ack                = ir_ack_apic_edge,
 +      .irq_set_affinity       = amd_ir_set_affinity,
 +      .irq_set_vcpu_affinity  = amd_ir_set_vcpu_affinity,
 +      .irq_compose_msi_msg    = ir_compose_msi_msg,
  };
  
  int amd_iommu_create_irq_domain(struct amd_iommu *iommu)
  {
 -      iommu->ir_domain = irq_domain_add_tree(NULL, &amd_ir_domain_ops, iommu);
 +      struct fwnode_handle *fn;
 +
 +      fn = irq_domain_alloc_named_id_fwnode("AMD-IR", iommu->index);
 +      if (!fn)
 +              return -ENOMEM;
 +      iommu->ir_domain = irq_domain_create_tree(fn, &amd_ir_domain_ops, iommu);
 +      irq_domain_free_fwnode(fn);
        if (!iommu->ir_domain)
                return -ENOMEM;
  
        iommu->ir_domain->parent = arch_get_ir_parent_domain();
 -      iommu->msi_domain = arch_create_msi_irq_domain(iommu->ir_domain);
 -
 +      iommu->msi_domain = arch_create_remap_msi_irq_domain(iommu->ir_domain,
 +                                                           "AMD-IR-MSI",
 +                                                           iommu->index);
        return 0;
  }
  
@@@ -31,8 -31,6 +31,8 @@@
  #include <linux/scatterlist.h>
  #include <linux/vmalloc.h>
  
 +#define IOMMU_MAPPING_ERROR   0
 +
  struct iommu_dma_msi_page {
        struct list_head        list;
        dma_addr_t              iova;
@@@ -316,7 -314,7 +316,7 @@@ int iommu_dma_init_domain(struct iommu_
                 * If we have devices with different DMA masks, move the free
                 * area cache limit down for the benefit of the smaller one.
                 */
-               iovad->dma_32bit_pfn = min(end_pfn, iovad->dma_32bit_pfn);
+               iovad->dma_32bit_pfn = min(end_pfn + 1, iovad->dma_32bit_pfn);
  
                return 0;
        }
@@@ -502,7 -500,7 +502,7 @@@ void iommu_dma_free(struct device *dev
  {
        __iommu_dma_unmap(iommu_get_domain_for_dev(dev), *handle, size);
        __iommu_dma_free_pages(pages, PAGE_ALIGN(size) >> PAGE_SHIFT);
 -      *handle = DMA_ERROR_CODE;
 +      *handle = IOMMU_MAPPING_ERROR;
  }
  
  /**
@@@ -535,7 -533,7 +535,7 @@@ struct page **iommu_dma_alloc(struct de
        dma_addr_t iova;
        unsigned int count, min_size, alloc_sizes = domain->pgsize_bitmap;
  
 -      *handle = DMA_ERROR_CODE;
 +      *handle = IOMMU_MAPPING_ERROR;
  
        min_size = alloc_sizes & -alloc_sizes;
        if (min_size < PAGE_SIZE) {
@@@ -629,11 -627,11 +629,11 @@@ static dma_addr_t __iommu_dma_map(struc
  
        iova = iommu_dma_alloc_iova(domain, size, dma_get_mask(dev), dev);
        if (!iova)
 -              return DMA_ERROR_CODE;
 +              return IOMMU_MAPPING_ERROR;
  
        if (iommu_map(domain, iova, phys - iova_off, size, prot)) {
                iommu_dma_free_iova(cookie, iova, size);
 -              return DMA_ERROR_CODE;
 +              return IOMMU_MAPPING_ERROR;
        }
        return iova + iova_off;
  }
@@@ -673,7 -671,7 +673,7 @@@ static int __finalise_sg(struct device 
  
                s->offset += s_iova_off;
                s->length = s_length;
 -              sg_dma_address(s) = DMA_ERROR_CODE;
 +              sg_dma_address(s) = IOMMU_MAPPING_ERROR;
                sg_dma_len(s) = 0;
  
                /*
@@@ -716,11 -714,11 +716,11 @@@ static void __invalidate_sg(struct scat
        int i;
  
        for_each_sg(sg, s, nents, i) {
 -              if (sg_dma_address(s) != DMA_ERROR_CODE)
 +              if (sg_dma_address(s) != IOMMU_MAPPING_ERROR)
                        s->offset += sg_dma_address(s);
                if (sg_dma_len(s))
                        s->length = sg_dma_len(s);
 -              sg_dma_address(s) = DMA_ERROR_CODE;
 +              sg_dma_address(s) = IOMMU_MAPPING_ERROR;
                sg_dma_len(s) = 0;
        }
  }
@@@ -838,7 -836,7 +838,7 @@@ void iommu_dma_unmap_resource(struct de
  
  int iommu_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
  {
 -      return dma_addr == DMA_ERROR_CODE;
 +      return dma_addr == IOMMU_MAPPING_ERROR;
  }
  
  static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device *dev,
@@@ -481,7 -481,7 +481,7 @@@ struct deferred_flush_data 
        struct deferred_flush_table *tables;
  };
  
- DEFINE_PER_CPU(struct deferred_flush_data, deferred_flush);
static DEFINE_PER_CPU(struct deferred_flush_data, deferred_flush);
  
  /* bitmap for indexing intel_iommus */
  static int g_num_of_iommus;
@@@ -2390,7 -2390,7 +2390,7 @@@ static struct dmar_domain *find_domain(
  
        /* No lock here, assumes no domain exit in normal case */
        info = dev->archdata.iommu;
-       if (info)
+       if (likely(info))
                return info->domain;
        return NULL;
  }
@@@ -3478,7 -3478,7 +3478,7 @@@ static unsigned long intel_alloc_iova(s
        return iova_pfn;
  }
  
- static struct dmar_domain *__get_valid_domain_for_dev(struct device *dev)
+ static struct dmar_domain *get_valid_domain_for_dev(struct device *dev)
  {
        struct dmar_domain *domain, *tmp;
        struct dmar_rmrr_unit *rmrr;
@@@ -3525,18 -3525,6 +3525,6 @@@ out
        return domain;
  }
  
- static inline struct dmar_domain *get_valid_domain_for_dev(struct device *dev)
- {
-       struct device_domain_info *info;
-       /* No lock here, assumes no domain exit in normal case */
-       info = dev->archdata.iommu;
-       if (likely(info))
-               return info->domain;
-       return __get_valid_domain_for_dev(dev);
- }
  /* Check if the dev needs to go through non-identity map and unmap process.*/
  static int iommu_no_mapping(struct device *dev)
  {
@@@ -3725,10 -3713,8 +3713,8 @@@ static void add_unmap(struct dmar_domai
        struct intel_iommu *iommu;
        struct deferred_flush_entry *entry;
        struct deferred_flush_data *flush_data;
-       unsigned int cpuid;
  
-       cpuid = get_cpu();
-       flush_data = per_cpu_ptr(&deferred_flush, cpuid);
+       flush_data = raw_cpu_ptr(&deferred_flush);
  
        /* Flush all CPUs' entries to avoid deferring too much.  If
         * this becomes a bottleneck, can just flush us, and rely on
        }
        flush_data->size++;
        spin_unlock_irqrestore(&flush_data->lock, flags);
-       put_cpu();
  }
  
  static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size)
@@@ -3973,7 -3957,7 +3957,7 @@@ static int intel_mapping_error(struct d
        return !dma_addr;
  }
  
- struct dma_map_ops intel_dma_ops = {
const struct dma_map_ops intel_dma_ops = {
        .alloc = intel_alloc_coherent,
        .free = intel_free_coherent,
        .map_sg = intel_map_sg,
        .map_page = intel_map_page,
        .unmap_page = intel_unmap_page,
        .mapping_error = intel_mapping_error,
 +#ifdef CONFIG_X86
 +      .dma_supported = x86_dma_supported,
 +#endif
  };
  
  static inline int iommu_domain_cache_init(void)
@@@ -4318,7 -4299,7 +4302,7 @@@ int dmar_parse_one_atsr(struct acpi_dma
        struct acpi_dmar_atsr *atsr;
        struct dmar_atsr_unit *atsru;
  
 -      if (system_state != SYSTEM_BOOTING && !intel_iommu_enabled)
 +      if (system_state >= SYSTEM_RUNNING && !intel_iommu_enabled)
                return 0;
  
        atsr = container_of(hdr, struct acpi_dmar_atsr, header);
@@@ -4568,7 -4549,7 +4552,7 @@@ int dmar_iommu_notify_scope_dev(struct 
        struct acpi_dmar_atsr *atsr;
        struct acpi_dmar_reserved_memory *rmrr;
  
 -      if (!intel_iommu_enabled && system_state != SYSTEM_BOOTING)
 +      if (!intel_iommu_enabled && system_state >= SYSTEM_RUNNING)
                return 0;
  
        list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
@@@ -76,7 -76,7 +76,7 @@@ static struct hpet_scope ir_hpet[MAX_HP
   * the dmar_global_lock.
   */
  static DEFINE_RAW_SPINLOCK(irq_2_ir_lock);
- static struct irq_domain_ops intel_ir_domain_ops;
+ static const struct irq_domain_ops intel_ir_domain_ops;
  
  static void iommu_disable_irq_remapping(struct intel_iommu *iommu);
  static int __init parse_ioapics_under_ir(void);
@@@ -500,9 -500,8 +500,9 @@@ static void iommu_enable_irq_remapping(
  static int intel_setup_irq_remapping(struct intel_iommu *iommu)
  {
        struct ir_table *ir_table;
 -      struct page *pages;
 +      struct fwnode_handle *fn;
        unsigned long *bitmap;
 +      struct page *pages;
  
        if (iommu->ir_table)
                return 0;
                goto out_free_pages;
        }
  
 -      iommu->ir_domain = irq_domain_add_hierarchy(arch_get_ir_parent_domain(),
 -                                                  0, INTR_REMAP_TABLE_ENTRIES,
 -                                                  NULL, &intel_ir_domain_ops,
 -                                                  iommu);
 +      fn = irq_domain_alloc_named_id_fwnode("INTEL-IR", iommu->seq_id);
 +      if (!fn)
 +              goto out_free_bitmap;
 +
 +      iommu->ir_domain =
 +              irq_domain_create_hierarchy(arch_get_ir_parent_domain(),
 +                                          0, INTR_REMAP_TABLE_ENTRIES,
 +                                          fn, &intel_ir_domain_ops,
 +                                          iommu);
 +      irq_domain_free_fwnode(fn);
        if (!iommu->ir_domain) {
                pr_err("IR%d: failed to allocate irqdomain\n", iommu->seq_id);
                goto out_free_bitmap;
        }
 -      iommu->ir_msi_domain = arch_create_msi_irq_domain(iommu->ir_domain);
 +      iommu->ir_msi_domain =
 +              arch_create_remap_msi_irq_domain(iommu->ir_domain,
 +                                               "INTEL-IR-MSI",
 +                                               iommu->seq_id);
  
        ir_table->base = page_address(pages);
        ir_table->bitmap = bitmap;
@@@ -1215,11 -1205,10 +1215,11 @@@ static int intel_ir_set_vcpu_affinity(s
  }
  
  static struct irq_chip intel_ir_chip = {
 -      .irq_ack = ir_ack_apic_edge,
 -      .irq_set_affinity = intel_ir_set_affinity,
 -      .irq_compose_msi_msg = intel_ir_compose_msi_msg,
 -      .irq_set_vcpu_affinity = intel_ir_set_vcpu_affinity,
 +      .name                   = "INTEL-IR",
 +      .irq_ack                = ir_ack_apic_edge,
 +      .irq_set_affinity       = intel_ir_set_affinity,
 +      .irq_compose_msi_msg    = intel_ir_compose_msi_msg,
 +      .irq_set_vcpu_affinity  = intel_ir_set_vcpu_affinity,
  };
  
  static void intel_irq_remapping_prepare_irte(struct intel_ir_data *data,
@@@ -1407,7 -1396,7 +1407,7 @@@ static void intel_irq_remapping_deactiv
        modify_irte(&data->irq_2_iommu, &entry);
  }
  
- static struct irq_domain_ops intel_ir_domain_ops = {
+ static const struct irq_domain_ops intel_ir_domain_ops = {
        .alloc = intel_irq_remapping_alloc,
        .free = intel_irq_remapping_free,
        .activate = intel_irq_remapping_activate,