Merge tag 'iommu-updates-v4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/joro...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 20 May 2016 00:07:04 +0000 (17:07 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 20 May 2016 00:07:04 +0000 (17:07 -0700)
Pull IOMMU updates from Joerg Roedel:
 "The updates include:

   - rate limiting for the VT-d fault handler

   - remove statistics code from the AMD IOMMU driver.  It is unused and
     should be replaced by something more generic if needed

   - per-domain pagesize-bitmaps in IOMMU core code to support systems
     with different types of IOMMUs

   - support for ACPI devices in the AMD IOMMU driver

   - 4GB mode support for Mediatek IOMMU driver

   - ARM-SMMU updates from Will Deacon:
      - support for 64k pages with SMMUv1 implementations (e.g MMU-401)
      - remove open-coded 64-bit MMIO accessors
      - initial support for 16-bit VMIDs, as supported by some ThunderX
        SMMU implementations
      - a couple of errata workarounds for silicon in the field

   - various fixes here and there"

* tag 'iommu-updates-v4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: (44 commits)
  iommu/arm-smmu: Use per-domain page sizes.
  iommu/amd: Remove statistics code
  iommu/dma: Finish optimising higher-order allocations
  iommu: Allow selecting page sizes per domain
  iommu: of: enforce const-ness of struct iommu_ops
  iommu: remove unused priv field from struct iommu_ops
  iommu/dma: Implement scatterlist segment merging
  iommu/arm-smmu: Clear cache lock bit of ACR
  iommu/arm-smmu: Support SMMUv1 64KB supplement
  iommu/arm-smmu: Decouple context format from kernel config
  iommu/arm-smmu: Tidy up 64-bit/atomic I/O accesses
  io-64-nonatomic: Add relaxed accessor variants
  iommu/arm-smmu: Work around MMU-500 prefetch errata
  iommu/arm-smmu: Convert ThunderX workaround to new method
  iommu/arm-smmu: Differentiate specific implementations
  iommu/arm-smmu: Workaround for ThunderX erratum #27704
  iommu/arm-smmu: Add support for 16 bit VMID
  iommu/amd: Move get_device_id() and friends to beginning of file
  iommu/amd: Don't use IS_ERR_VALUE to check integer values
  iommu/amd: Signedness bug in acpihid_device_group()
  ...

1  2 
Documentation/kernel-parameters.txt
arch/arm64/mm/dma-mapping.c
drivers/iommu/amd_iommu.c
drivers/iommu/iommu.c

@@@ -131,7 -131,6 +131,7 @@@ parameter is applicable
                        More X86-64 boot options can be found in
                        Documentation/x86/x86_64/boot-options.txt .
        X86     Either 32-bit or 64-bit x86 (same as X86-32+X86-64)
 +      X86_UV  SGI UV support is enabled.
        XEN     Xen support is enabled
  
  In addition, the following text indicates that the option:
@@@ -168,18 -167,16 +168,18 @@@ bytes respectively. Such letter suffixe
  
        acpi=           [HW,ACPI,X86,ARM64]
                        Advanced Configuration and Power Interface
 -                      Format: { force | off | strict | noirq | rsdt |
 +                      Format: { force | on | off | strict | noirq | rsdt |
                                  copy_dsdt }
                        force -- enable ACPI if default was off
 +                      on -- enable ACPI but allow fallback to DT [arm64]
                        off -- disable ACPI if default was on
                        noirq -- do not use ACPI for IRQ routing
                        strict -- Be less tolerant of platforms that are not
                                strictly ACPI specification compliant.
                        rsdt -- prefer RSDT over (default) XSDT
                        copy_dsdt -- copy DSDT to memory
 -                      For ARM64, ONLY "acpi=off" or "acpi=force" are available
 +                      For ARM64, ONLY "acpi=off", "acpi=on" or "acpi=force"
 +                      are available
  
                        See also Documentation/power/runtime_pm.txt, pci=noacpi
  
                        acpi_osi=!*             # remove all strings
                        acpi_osi=!              # disable all built-in OS vendor
                                                  strings
 +                      acpi_osi=!!             # enable all built-in OS vendor
 +                                                strings
                        acpi_osi=               # disable all strings
  
                        'acpi_osi=!' can be used in combination with single or
                        Format: <int> (must be >=0)
                        Default: 64
  
 +      bau=            [X86_UV] Enable the BAU on SGI UV.  The default
 +                      behavior is to disable the BAU (i.e. bau=0).
 +                      Format: { "0" | "1" }
 +                      0 - Disable the BAU.
 +                      1 - Enable the BAU.
 +                      unset - Disable the BAU.
 +
        baycom_epp=     [HW,AX25]
                        Format: <io>,<mode>
  
                        It will be ignored when crashkernel=X,high is not used
                        or memory reserved is below 4G.
  
 +      cryptomgr.notests
 +                        [KNL] Disable crypto self-tests
 +
        cs89x0_dma=     [HW,NET]
                        Format: <dma>
  
                hwp_only
                        Only load intel_pstate on systems which support
                        hardware P state control (HWP) if available.
 +              support_acpi_ppc
 +                      Enforce ACPI _PPC performance limits. If the Fixed ACPI
 +                      Description Table, specifies preferred power management
 +                      profile as "Enterprise Server" or "Performance Server",
 +                      then this feature is turned on by default.
  
        intremap=       [X86-64, Intel-IOMMU]
                        on      enable Interrupt Remapping (default)
                        PCI device 00:14.0 write the parameter as:
                                ivrs_hpet[0]=00:14.0
  
+       ivrs_acpihid    [HW,X86_64]
+                       Provide an override to the ACPI-HID:UID<->DEVICE-ID
+                       mapping provided in the IVRS ACPI table. For
+                       example, to map UART-HID:UID AMD0020:0 to
+                       PCI device 00:14.5 write the parameter as:
+                               ivrs_acpihid[00:14.5]=AMD0020:0
        js=             [HW,JOY] Analog joystick
                        See Documentation/input/joystick.txt.
  
  
        nohugeiomap     [KNL,x86] Disable kernel huge I/O mappings.
  
 +      nosmt           [KNL,S390] Disable symmetric multithreading (SMT).
 +                      Equivalent to smt=1.
 +
        noxsave         [BUGS=X86] Disables x86 extended register state save
                        and restore using xsave. The kernel will fallback to
                        enabling legacy floating-point and sse state.
                        Lazy RCU callbacks are those which RCU can
                        prove do nothing more than free memory.
  
 +      rcuperf.gp_exp= [KNL]
 +                      Measure performance of expedited synchronous
 +                      grace-period primitives.
 +
 +      rcuperf.holdoff= [KNL]
 +                      Set test-start holdoff period.  The purpose of
 +                      this parameter is to delay the start of the
 +                      test until boot completes in order to avoid
 +                      interference.
 +
 +      rcuperf.nreaders= [KNL]
 +                      Set number of RCU readers.  The value -1 selects
 +                      N, where N is the number of CPUs.  A value
 +                      "n" less than -1 selects N-n+1, where N is again
 +                      the number of CPUs.  For example, -2 selects N
 +                      (the number of CPUs), -3 selects N+1, and so on.
 +                      A value of "n" less than or equal to -N selects
 +                      a single reader.
 +
 +      rcuperf.nwriters= [KNL]
 +                      Set number of RCU writers.  The values operate
 +                      the same as for rcuperf.nreaders.
 +                      N, where N is the number of CPUs
 +
 +      rcuperf.perf_runnable= [BOOT]
 +                      Start rcuperf running at boot time.
 +
 +      rcuperf.shutdown= [KNL]
 +                      Shut the system down after performance tests
 +                      complete.  This is useful for hands-off automated
 +                      testing.
 +
 +      rcuperf.perf_type= [KNL]
 +                      Specify the RCU implementation to test.
 +
 +      rcuperf.verbose= [KNL]
 +                      Enable additional printk() statements.
 +
        rcutorture.cbflood_inter_holdoff= [KNL]
                        Set holdoff time (jiffies) between successive
                        callback-flood tests.
                                1: Fast pin select (default)
                                2: ATC IRMode
  
 +      smt             [KNL,S390] Set the maximum number of threads (logical
 +                      CPUs) to use per physical CPU on systems capable of
 +                      symmetric multithreading (SMT). Will be capped to the
 +                      actual hardware limit.
 +                      Format: <integer>
 +                      Default: -1 (no limit)
 +
        softlockup_panic=
                        [KNL] Should the soft-lockup detector generate panics.
                        Format: <integer>
@@@ -562,8 -562,8 +562,8 @@@ static void *__iommu_alloc_attrs(struc
                struct page **pages;
                pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL, coherent);
  
-               pages = iommu_dma_alloc(dev, iosize, gfp, ioprot, handle,
-                                       flush_page);
+               pages = iommu_dma_alloc(dev, iosize, gfp, attrs, ioprot,
+                                       handle, flush_page);
                if (!pages)
                        return NULL;
  
@@@ -804,24 -804,57 +804,24 @@@ struct iommu_dma_notifier_data 
  static LIST_HEAD(iommu_dma_masters);
  static DEFINE_MUTEX(iommu_dma_notifier_lock);
  
 -/*
 - * Temporarily "borrow" a domain feature flag to to tell if we had to resort
 - * to creating our own domain here, in case we need to clean it up again.
 - */
 -#define __IOMMU_DOMAIN_FAKE_DEFAULT           (1U << 31)
 -
  static bool do_iommu_attach(struct device *dev, const struct iommu_ops *ops,
                           u64 dma_base, u64 size)
  {
        struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
  
        /*
 -       * Best case: The device is either part of a group which was
 -       * already attached to a domain in a previous call, or it's
 -       * been put in a default DMA domain by the IOMMU core.
 +       * If the IOMMU driver has the DMA domain support that we require,
 +       * then the IOMMU core will have already configured a group for this
 +       * device, and allocated the default domain for that group.
         */
 -      if (!domain) {
 -              /*
 -               * Urgh. The IOMMU core isn't going to do default domains
 -               * for non-PCI devices anyway, until it has some means of
 -               * abstracting the entirely implementation-specific
 -               * sideband data/SoC topology/unicorn dust that may or
 -               * may not differentiate upstream masters.
 -               * So until then, HORRIBLE HACKS!
 -               */
 -              domain = ops->domain_alloc(IOMMU_DOMAIN_DMA);
 -              if (!domain)
 -                      goto out_no_domain;
 -
 -              domain->ops = ops;
 -              domain->type = IOMMU_DOMAIN_DMA | __IOMMU_DOMAIN_FAKE_DEFAULT;
 -
 -              if (iommu_attach_device(domain, dev))
 -                      goto out_put_domain;
 +      if (!domain || iommu_dma_init_domain(domain, dma_base, size)) {
 +              pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n",
 +                      dev_name(dev));
 +              return false;
        }
  
 -      if (iommu_dma_init_domain(domain, dma_base, size))
 -              goto out_detach;
 -
        dev->archdata.dma_ops = &iommu_dma_ops;
        return true;
 -
 -out_detach:
 -      iommu_detach_device(domain, dev);
 -out_put_domain:
 -      if (domain->type & __IOMMU_DOMAIN_FAKE_DEFAULT)
 -              iommu_domain_free(domain);
 -out_no_domain:
 -      pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n",
 -              dev_name(dev));
 -      return false;
  }
  
  static void queue_iommu_attach(struct device *dev, const struct iommu_ops *ops,
@@@ -900,10 -933,6 +900,10 @@@ static int __init __iommu_dma_init(void
                ret = register_iommu_dma_ops_notifier(&platform_bus_type);
        if (!ret)
                ret = register_iommu_dma_ops_notifier(&amba_bustype);
 +#ifdef CONFIG_PCI
 +      if (!ret)
 +              ret = register_iommu_dma_ops_notifier(&pci_bus_type);
 +#endif
  
        /* handle devices queued before this arch_initcall */
        if (!ret)
@@@ -938,8 -967,11 +938,8 @@@ void arch_teardown_dma_ops(struct devic
  {
        struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
  
 -      if (domain) {
 +      if (WARN_ON(domain))
                iommu_detach_device(domain, dev);
 -              if (domain->type & __IOMMU_DOMAIN_FAKE_DEFAULT)
 -                      iommu_domain_free(domain);
 -      }
  
        dev->archdata.dma_ops = NULL;
  }
  #else
  
  static void __iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
-                                 struct iommu_ops *iommu)
+                                 const struct iommu_ops *iommu)
  { }
  
  #endif  /* CONFIG_IOMMU_DMA */
  
  void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
-                       struct iommu_ops *iommu, bool coherent)
+                       const struct iommu_ops *iommu, bool coherent)
  {
        if (!dev->archdata.dma_ops)
                dev->archdata.dma_ops = &swiotlb_dma_ops;
@@@ -19,6 -19,8 +19,8 @@@
  
  #include <linux/ratelimit.h>
  #include <linux/pci.h>
+ #include <linux/acpi.h>
+ #include <linux/amba/bus.h>
  #include <linux/pci-ats.h>
  #include <linux/bitmap.h>
  #include <linux/slab.h>
@@@ -72,6 -74,7 +74,7 @@@ static DEFINE_SPINLOCK(dev_data_list_lo
  
  LIST_HEAD(ioapic_map);
  LIST_HEAD(hpet_map);
+ LIST_HEAD(acpihid_map);
  
  /*
   * Domain for untranslated devices - only allocated
@@@ -162,18 -165,65 +165,65 @@@ struct dma_ops_domain 
   *
   ****************************************************************************/
  
- static struct protection_domain *to_pdomain(struct iommu_domain *dom)
+ static inline int match_hid_uid(struct device *dev,
+                               struct acpihid_map_entry *entry)
  {
-       return container_of(dom, struct protection_domain, domain);
+       const char *hid, *uid;
+       hid = acpi_device_hid(ACPI_COMPANION(dev));
+       uid = acpi_device_uid(ACPI_COMPANION(dev));
+       if (!hid || !(*hid))
+               return -ENODEV;
+       if (!uid || !(*uid))
+               return strcmp(hid, entry->hid);
+       if (!(*entry->uid))
+               return strcmp(hid, entry->hid);
+       return (strcmp(hid, entry->hid) || strcmp(uid, entry->uid));
  }
  
- static inline u16 get_device_id(struct device *dev)
+ static inline u16 get_pci_device_id(struct device *dev)
  {
        struct pci_dev *pdev = to_pci_dev(dev);
  
        return PCI_DEVID(pdev->bus->number, pdev->devfn);
  }
  
+ static inline int get_acpihid_device_id(struct device *dev,
+                                       struct acpihid_map_entry **entry)
+ {
+       struct acpihid_map_entry *p;
+       list_for_each_entry(p, &acpihid_map, list) {
+               if (!match_hid_uid(dev, p)) {
+                       if (entry)
+                               *entry = p;
+                       return p->devid;
+               }
+       }
+       return -EINVAL;
+ }
+ static inline int get_device_id(struct device *dev)
+ {
+       int devid;
+       if (dev_is_pci(dev))
+               devid = get_pci_device_id(dev);
+       else
+               devid = get_acpihid_device_id(dev, NULL);
+       return devid;
+ }
+ static struct protection_domain *to_pdomain(struct iommu_domain *dom)
+ {
+       return container_of(dom, struct protection_domain, domain);
+ }
  static struct iommu_dev_data *alloc_dev_data(u16 devid)
  {
        struct iommu_dev_data *dev_data;
@@@ -222,6 -272,7 +272,7 @@@ static u16 get_alias(struct device *dev
        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);
        ivrs_alias = amd_iommu_alias_table[devid];
        pci_for_each_dma_alias(pdev, __last_alias, &pci_alias);
         */
        if (pci_alias == devid &&
            PCI_BUS_NUM(ivrs_alias) == pdev->bus->number) {
 -              pdev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN;
 -              pdev->dma_alias_devfn = ivrs_alias & 0xff;
 +              pci_add_dma_alias(pdev, ivrs_alias & 0xff);
                pr_info("AMD-Vi: Added PCI DMA alias %02x.%d for %s\n",
                        PCI_SLOT(ivrs_alias), PCI_FUNC(ivrs_alias),
                        dev_name(dev));
@@@ -289,6 -341,29 +340,29 @@@ static struct iommu_dev_data *get_dev_d
        return dev->archdata.iommu;
  }
  
+ /*
+ * Find or create an IOMMU group for a acpihid device.
+ */
+ static struct iommu_group *acpihid_device_group(struct device *dev)
+ {
+       struct acpihid_map_entry *p, *entry = NULL;
+       int devid;
+       devid = get_acpihid_device_id(dev, &entry);
+       if (devid < 0)
+               return ERR_PTR(devid);
+       list_for_each_entry(p, &acpihid_map, list) {
+               if ((devid == p->devid) && p->group)
+                       entry->group = p->group;
+       }
+       if (!entry->group)
+               entry->group = generic_device_group(dev);
+       return entry->group;
+ }
  static bool pci_iommuv2_capable(struct pci_dev *pdev)
  {
        static const int caps[] = {
@@@ -340,9 -415,11 +414,11 @@@ static void init_unity_mappings_for_dev
                                           struct dma_ops_domain *dma_dom)
  {
        struct unity_map_entry *e;
-       u16 devid;
+       int devid;
  
        devid = get_device_id(dev);
+       if (devid < 0)
+               return;
  
        list_for_each_entry(e, &amd_iommu_unity_map, list) {
                if (!(devid >= e->devid_start && devid <= e->devid_end))
   */
  static bool check_device(struct device *dev)
  {
-       u16 devid;
+       int devid;
  
        if (!dev || !dev->dma_mask)
                return false;
  
-       /* No PCI device */
-       if (!dev_is_pci(dev))
-               return false;
        devid = get_device_id(dev);
+       if (devid < 0)
+               return false;
  
        /* Out of our scope? */
        if (devid > amd_iommu_last_bdf)
@@@ -401,22 -476,26 +475,26 @@@ out
  
  static int iommu_init_device(struct device *dev)
  {
-       struct pci_dev *pdev = to_pci_dev(dev);
        struct iommu_dev_data *dev_data;
+       int devid;
  
        if (dev->archdata.iommu)
                return 0;
  
-       dev_data = find_dev_data(get_device_id(dev));
+       devid = get_device_id(dev);
+       if (devid < 0)
+               return devid;
+       dev_data = find_dev_data(devid);
        if (!dev_data)
                return -ENOMEM;
  
        dev_data->alias = get_alias(dev);
  
-       if (pci_iommuv2_capable(pdev)) {
+       if (dev_is_pci(dev) && pci_iommuv2_capable(to_pci_dev(dev))) {
                struct amd_iommu *iommu;
  
-               iommu              = amd_iommu_rlookup_table[dev_data->devid];
+               iommu = amd_iommu_rlookup_table[dev_data->devid];
                dev_data->iommu_v2 = iommu->is_iommu_v2;
        }
  
  
  static void iommu_ignore_device(struct device *dev)
  {
-       u16 devid, alias;
+       u16 alias;
+       int devid;
  
        devid = get_device_id(dev);
+       if (devid < 0)
+               return;
        alias = get_alias(dev);
  
        memset(&amd_iommu_dev_table[devid], 0, sizeof(struct dev_table_entry));
  
  static void iommu_uninit_device(struct device *dev)
  {
-       struct iommu_dev_data *dev_data = search_dev_data(get_device_id(dev));
+       int devid;
+       struct iommu_dev_data *dev_data;
  
+       devid = get_device_id(dev);
+       if (devid < 0)
+               return;
+       dev_data = search_dev_data(devid);
        if (!dev_data)
                return;
  
         */
  }
  
- #ifdef CONFIG_AMD_IOMMU_STATS
- /*
-  * Initialization code for statistics collection
-  */
- DECLARE_STATS_COUNTER(compl_wait);
- DECLARE_STATS_COUNTER(cnt_map_single);
- DECLARE_STATS_COUNTER(cnt_unmap_single);
- DECLARE_STATS_COUNTER(cnt_map_sg);
- DECLARE_STATS_COUNTER(cnt_unmap_sg);
- DECLARE_STATS_COUNTER(cnt_alloc_coherent);
- DECLARE_STATS_COUNTER(cnt_free_coherent);
- DECLARE_STATS_COUNTER(cross_page);
- DECLARE_STATS_COUNTER(domain_flush_single);
- DECLARE_STATS_COUNTER(domain_flush_all);
- DECLARE_STATS_COUNTER(alloced_io_mem);
- DECLARE_STATS_COUNTER(total_map_requests);
- DECLARE_STATS_COUNTER(complete_ppr);
- DECLARE_STATS_COUNTER(invalidate_iotlb);
- DECLARE_STATS_COUNTER(invalidate_iotlb_all);
- DECLARE_STATS_COUNTER(pri_requests);
- static struct dentry *stats_dir;
- static struct dentry *de_fflush;
- static void amd_iommu_stats_add(struct __iommu_counter *cnt)
- {
-       if (stats_dir == NULL)
-               return;
-       cnt->dent = debugfs_create_u64(cnt->name, 0444, stats_dir,
-                                      &cnt->value);
- }
- static void amd_iommu_stats_init(void)
- {
-       stats_dir = debugfs_create_dir("amd-iommu", NULL);
-       if (stats_dir == NULL)
-               return;
-       de_fflush  = debugfs_create_bool("fullflush", 0444, stats_dir,
-                                        &amd_iommu_unmap_flush);
-       amd_iommu_stats_add(&compl_wait);
-       amd_iommu_stats_add(&cnt_map_single);
-       amd_iommu_stats_add(&cnt_unmap_single);
-       amd_iommu_stats_add(&cnt_map_sg);
-       amd_iommu_stats_add(&cnt_unmap_sg);
-       amd_iommu_stats_add(&cnt_alloc_coherent);
-       amd_iommu_stats_add(&cnt_free_coherent);
-       amd_iommu_stats_add(&cross_page);
-       amd_iommu_stats_add(&domain_flush_single);
-       amd_iommu_stats_add(&domain_flush_all);
-       amd_iommu_stats_add(&alloced_io_mem);
-       amd_iommu_stats_add(&total_map_requests);
-       amd_iommu_stats_add(&complete_ppr);
-       amd_iommu_stats_add(&invalidate_iotlb);
-       amd_iommu_stats_add(&invalidate_iotlb_all);
-       amd_iommu_stats_add(&pri_requests);
- }
- #endif
  /****************************************************************************
   *
   * Interrupt handling functions
@@@ -652,8 -677,6 +676,6 @@@ static void iommu_handle_ppr_entry(stru
  {
        struct amd_iommu_fault fault;
  
-       INC_STATS_COUNTER(pri_requests);
        if (PPR_REQ_TYPE(raw[0]) != PPR_REQ_FAULT) {
                pr_err_ratelimited("AMD-Vi: Unknown PPR request received\n");
                return;
@@@ -2283,13 -2306,17 +2305,17 @@@ static bool pci_pri_tlp_required(struc
  static int attach_device(struct device *dev,
                         struct protection_domain *domain)
  {
-       struct pci_dev *pdev = to_pci_dev(dev);
+       struct pci_dev *pdev;
        struct iommu_dev_data *dev_data;
        unsigned long flags;
        int ret;
  
        dev_data = get_dev_data(dev);
  
+       if (!dev_is_pci(dev))
+               goto skip_ats_check;
+       pdev = to_pci_dev(dev);
        if (domain->flags & PD_IOMMUV2_MASK) {
                if (!dev_data->passthrough)
                        return -EINVAL;
                dev_data->ats.qdep    = pci_ats_queue_depth(pdev);
        }
  
+ skip_ats_check:
        write_lock_irqsave(&amd_iommu_devtable_lock, flags);
        ret = __attach_device(dev_data, domain);
        write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
@@@ -2364,6 -2392,9 +2391,9 @@@ static void detach_device(struct devic
        __detach_device(dev_data);
        write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
  
+       if (!dev_is_pci(dev))
+               return;
        if (domain->flags & PD_IOMMUV2_MASK && dev_data->iommu_v2)
                pdev_iommuv2_disable(to_pci_dev(dev));
        else if (dev_data->ats.enabled)
@@@ -2377,13 -2408,15 +2407,15 @@@ static int amd_iommu_add_device(struct 
        struct iommu_dev_data *dev_data;
        struct iommu_domain *domain;
        struct amd_iommu *iommu;
-       u16 devid;
-       int ret;
+       int ret, devid;
  
        if (!check_device(dev) || get_dev_data(dev))
                return 0;
  
        devid = get_device_id(dev);
+       if (devid < 0)
+               return devid;
        iommu = amd_iommu_rlookup_table[devid];
  
        ret = iommu_init_device(dev);
  static void amd_iommu_remove_device(struct device *dev)
  {
        struct amd_iommu *iommu;
-       u16 devid;
+       int devid;
  
        if (!check_device(dev))
                return;
  
        devid = get_device_id(dev);
+       if (devid < 0)
+               return;
        iommu = amd_iommu_rlookup_table[devid];
  
        iommu_uninit_device(dev);
        iommu_completion_wait(iommu);
  }
  
+ static struct iommu_group *amd_iommu_device_group(struct device *dev)
+ {
+       if (dev_is_pci(dev))
+               return pci_device_group(dev);
+       return acpihid_device_group(dev);
+ }
  /*****************************************************************************
   *
   * The next functions belong to the dma_ops mapping/unmapping code.
@@@ -2597,11 -2641,6 +2640,6 @@@ static dma_addr_t __map_single(struct d
        pages = iommu_num_pages(paddr, size, PAGE_SIZE);
        paddr &= PAGE_MASK;
  
-       INC_STATS_COUNTER(total_map_requests);
-       if (pages > 1)
-               INC_STATS_COUNTER(cross_page);
        if (align)
                align_mask = (1UL << get_order(size)) - 1;
  
        }
        address += offset;
  
-       ADD_STATS_COUNTER(alloced_io_mem, size);
        if (unlikely(amd_iommu_np_cache)) {
                domain_flush_pages(&dma_dom->domain, address, size);
                domain_flush_complete(&dma_dom->domain);
@@@ -2671,8 -2708,6 +2707,6 @@@ static void __unmap_single(struct dma_o
                start += PAGE_SIZE;
        }
  
-       SUB_STATS_COUNTER(alloced_io_mem, size);
        dma_ops_free_addresses(dma_dom, dma_addr, pages);
  }
  
@@@ -2688,8 -2723,6 +2722,6 @@@ static dma_addr_t map_page(struct devic
        struct protection_domain *domain;
        u64 dma_mask;
  
-       INC_STATS_COUNTER(cnt_map_single);
        domain = get_domain(dev);
        if (PTR_ERR(domain) == -EINVAL)
                return (dma_addr_t)paddr;
@@@ -2710,8 -2743,6 +2742,6 @@@ static void unmap_page(struct device *d
  {
        struct protection_domain *domain;
  
-       INC_STATS_COUNTER(cnt_unmap_single);
        domain = get_domain(dev);
        if (IS_ERR(domain))
                return;
@@@ -2734,8 -2765,6 +2764,6 @@@ static int map_sg(struct device *dev, s
        int mapped_elems = 0;
        u64 dma_mask;
  
-       INC_STATS_COUNTER(cnt_map_sg);
        domain = get_domain(dev);
        if (IS_ERR(domain))
                return 0;
@@@ -2781,8 -2810,6 +2809,6 @@@ static void unmap_sg(struct device *dev
        struct scatterlist *s;
        int i;
  
-       INC_STATS_COUNTER(cnt_unmap_sg);
        domain = get_domain(dev);
        if (IS_ERR(domain))
                return;
@@@ -2805,8 -2832,6 +2831,6 @@@ static void *alloc_coherent(struct devi
        struct protection_domain *domain;
        struct page *page;
  
-       INC_STATS_COUNTER(cnt_alloc_coherent);
        domain = get_domain(dev);
        if (PTR_ERR(domain) == -EINVAL) {
                page = alloc_pages(flag, get_order(size));
@@@ -2860,8 -2885,6 +2884,6 @@@ static void free_coherent(struct devic
        struct protection_domain *domain;
        struct page *page;
  
-       INC_STATS_COUNTER(cnt_free_coherent);
        page = virt_to_page(virt_addr);
        size = PAGE_ALIGN(size);
  
@@@ -2926,7 -2949,17 +2948,17 @@@ static struct dma_map_ops amd_iommu_dma
  
  int __init amd_iommu_init_api(void)
  {
-       return bus_set_iommu(&pci_bus_type, &amd_iommu_ops);
+       int err = 0;
+       err = bus_set_iommu(&pci_bus_type, &amd_iommu_ops);
+       if (err)
+               return err;
+ #ifdef CONFIG_ARM_AMBA
+       err = bus_set_iommu(&amba_bustype, &amd_iommu_ops);
+       if (err)
+               return err;
+ #endif
+       return 0;
  }
  
  int __init amd_iommu_init_dma_ops(void)
        if (!swiotlb)
                dma_ops = &nommu_dma_ops;
  
-       amd_iommu_stats_init();
        if (amd_iommu_unmap_flush)
                pr_info("AMD-Vi: IO/TLB flush on unmap enabled\n");
        else
@@@ -3098,12 -3129,14 +3128,14 @@@ static void amd_iommu_detach_device(str
  {
        struct iommu_dev_data *dev_data = dev->archdata.iommu;
        struct amd_iommu *iommu;
-       u16 devid;
+       int devid;
  
        if (!check_device(dev))
                return;
  
        devid = get_device_id(dev);
+       if (devid < 0)
+               return;
  
        if (dev_data->domain != NULL)
                detach_device(dev);
@@@ -3221,9 -3254,11 +3253,11 @@@ static void amd_iommu_get_dm_regions(st
                                     struct list_head *head)
  {
        struct unity_map_entry *entry;
-       u16 devid;
+       int devid;
  
        devid = get_device_id(dev);
+       if (devid < 0)
+               return;
  
        list_for_each_entry(entry, &amd_iommu_unity_map, list) {
                struct iommu_dm_region *region;
@@@ -3270,7 -3305,7 +3304,7 @@@ static const struct iommu_ops amd_iommu
        .iova_to_phys = amd_iommu_iova_to_phys,
        .add_device = amd_iommu_add_device,
        .remove_device = amd_iommu_remove_device,
-       .device_group = pci_device_group,
+       .device_group = amd_iommu_device_group,
        .get_dm_regions = amd_iommu_get_dm_regions,
        .put_dm_regions = amd_iommu_put_dm_regions,
        .pgsize_bitmap  = AMD_IOMMU_PGSIZES,
@@@ -3431,8 -3466,6 +3465,6 @@@ out
  static int __amd_iommu_flush_page(struct protection_domain *domain, int pasid,
                                  u64 address)
  {
-       INC_STATS_COUNTER(invalidate_iotlb);
        return __flush_pasid(domain, pasid, address, false);
  }
  
@@@ -3453,8 -3486,6 +3485,6 @@@ EXPORT_SYMBOL(amd_iommu_flush_page)
  
  static int __amd_iommu_flush_tlb(struct protection_domain *domain, int pasid)
  {
-       INC_STATS_COUNTER(invalidate_iotlb_all);
        return __flush_pasid(domain, pasid, CMD_INV_IOMMU_ALL_PAGES_ADDRESS,
                             true);
  }
@@@ -3574,8 -3605,6 +3604,6 @@@ int amd_iommu_complete_ppr(struct pci_d
        struct amd_iommu *iommu;
        struct iommu_cmd cmd;
  
-       INC_STATS_COUNTER(complete_ppr);
        dev_data = get_dev_data(&pdev->dev);
        iommu    = amd_iommu_rlookup_table[dev_data->devid];
  
@@@ -3925,6 -3954,9 +3953,9 @@@ static struct irq_domain *get_irq_domai
        case X86_IRQ_ALLOC_TYPE_MSI:
        case X86_IRQ_ALLOC_TYPE_MSIX:
                devid = get_device_id(&info->msi_dev->dev);
+               if (devid < 0)
+                       return NULL;
                iommu = amd_iommu_rlookup_table[devid];
                if (iommu)
                        return iommu->msi_domain;
diff --combined drivers/iommu/iommu.c
@@@ -337,9 -337,9 +337,9 @@@ static int iommu_group_create_direct_ma
        if (!domain || domain->type != IOMMU_DOMAIN_DMA)
                return 0;
  
-       BUG_ON(!domain->ops->pgsize_bitmap);
+       BUG_ON(!domain->pgsize_bitmap);
  
-       pg_size = 1UL << __ffs(domain->ops->pgsize_bitmap);
+       pg_size = 1UL << __ffs(domain->pgsize_bitmap);
        INIT_LIST_HEAD(&mappings);
  
        iommu_get_dm_regions(dev, &mappings);
@@@ -660,8 -660,8 +660,8 @@@ static struct iommu_group *get_pci_func
  }
  
  /*
 - * Look for aliases to or from the given device for exisiting groups.  The
 - * dma_alias_devfn only supports aliases on the same bus, therefore the search
 + * Look for aliases to or from the given device for existing groups. DMA
 + * aliases are only supported on the same bus, therefore the search
   * space is quite small (especially since we're really only looking at pcie
   * device, and therefore only expect multiple slots on the root complex or
   * downstream switch ports).  It's conceivable though that a pair of
@@@ -686,7 -686,11 +686,7 @@@ static struct iommu_group *get_pci_alia
                        continue;
  
                /* We alias them or they alias us */
 -              if (((pdev->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVFN) &&
 -                   pdev->dma_alias_devfn == tmp->devfn) ||
 -                  ((tmp->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVFN) &&
 -                   tmp->dma_alias_devfn == pdev->devfn)) {
 -
 +              if (pci_devs_are_dma_aliases(pdev, tmp)) {
                        group = get_pci_alias_group(tmp, devfns);
                        if (group) {
                                pci_dev_put(tmp);
@@@ -1069,6 -1073,8 +1069,8 @@@ static struct iommu_domain *__iommu_dom
  
        domain->ops  = bus->iommu_ops;
        domain->type = type;
+       /* Assume all sizes by default; the driver may override this later */
+       domain->pgsize_bitmap  = bus->iommu_ops->pgsize_bitmap;
  
        return domain;
  }
@@@ -1293,7 -1299,7 +1295,7 @@@ static size_t iommu_pgsize(struct iommu
        pgsize = (1UL << (pgsize_idx + 1)) - 1;
  
        /* throw away page sizes not supported by the hardware */
-       pgsize &= domain->ops->pgsize_bitmap;
+       pgsize &= domain->pgsize_bitmap;
  
        /* make sure we're still sane */
        BUG_ON(!pgsize);
@@@ -1315,14 -1321,14 +1317,14 @@@ int iommu_map(struct iommu_domain *doma
        int ret = 0;
  
        if (unlikely(domain->ops->map == NULL ||
-                    domain->ops->pgsize_bitmap == 0UL))
+                    domain->pgsize_bitmap == 0UL))
                return -ENODEV;
  
        if (unlikely(!(domain->type & __IOMMU_DOMAIN_PAGING)))
                return -EINVAL;
  
        /* find out the minimum page size supported */
-       min_pagesz = 1 << __ffs(domain->ops->pgsize_bitmap);
+       min_pagesz = 1 << __ffs(domain->pgsize_bitmap);
  
        /*
         * both the virtual address and the physical one, as well as
@@@ -1369,14 -1375,14 +1371,14 @@@ size_t iommu_unmap(struct iommu_domain 
        unsigned long orig_iova = iova;
  
        if (unlikely(domain->ops->unmap == NULL ||
-                    domain->ops->pgsize_bitmap == 0UL))
+                    domain->pgsize_bitmap == 0UL))
                return -ENODEV;
  
        if (unlikely(!(domain->type & __IOMMU_DOMAIN_PAGING)))
                return -EINVAL;
  
        /* find out the minimum page size supported */
-       min_pagesz = 1 << __ffs(domain->ops->pgsize_bitmap);
+       min_pagesz = 1 << __ffs(domain->pgsize_bitmap);
  
        /*
         * The virtual address, as well as the size of the mapping, must be
@@@ -1422,10 -1428,10 +1424,10 @@@ size_t default_iommu_map_sg(struct iomm
        unsigned int i, min_pagesz;
        int ret;
  
-       if (unlikely(domain->ops->pgsize_bitmap == 0UL))
+       if (unlikely(domain->pgsize_bitmap == 0UL))
                return 0;
  
-       min_pagesz = 1 << __ffs(domain->ops->pgsize_bitmap);
+       min_pagesz = 1 << __ffs(domain->pgsize_bitmap);
  
        for_each_sg(sg, s, nents, i) {
                phys_addr_t phys = page_to_phys(sg_page(s)) + s->offset;
@@@ -1506,7 -1512,7 +1508,7 @@@ int iommu_domain_get_attr(struct iommu_
                break;
        case DOMAIN_ATTR_PAGING:
                paging  = data;
-               *paging = (domain->ops->pgsize_bitmap != 0UL);
+               *paging = (domain->pgsize_bitmap != 0UL);
                break;
        case DOMAIN_ATTR_WINDOWS:
                count = data;