Merge branch 'x86-iommu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 21 Oct 2010 21:23:48 +0000 (14:23 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 21 Oct 2010 21:23:48 +0000 (14:23 -0700)
* 'x86-iommu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  x86, iommu: Update header comments with appropriate naming
  ia64, iommu: Add a dummy iommu_table.h file in IA64.
  x86, iommu: Fix IOMMU_INIT alignment rules
  x86, doc: Adding comments about .iommu_table and its neighbors.
  x86, iommu: Utilize the IOMMU_INIT macros functionality.
  x86, VT-d: Make Intel VT-d IOMMU use IOMMU_INIT_* macros.
  x86, GART/AMD-VI: Make AMD GART and IOMMU use IOMMU_INIT_* macros.
  x86, calgary: Make Calgary IOMMU use IOMMU_INIT_* macros.
  x86, xen-swiotlb: Make Xen-SWIOTLB use IOMMU_INIT_* macros.
  x86, swiotlb: Make SWIOTLB use IOMMU_INIT_* macros.
  x86, swiotlb: Simplify SWIOTLB pci_swiotlb_detect routine.
  x86, iommu: Add proper dependency sort routine (and sanity check).
  x86, iommu: Make all IOMMU's detection routines return a value.
  x86, iommu: Add IOMMU_INIT macros, .iommu_table section, and iommu_table_entry structure

1  2 
arch/x86/include/asm/amd_iommu.h
arch/x86/include/asm/gart.h
arch/x86/kernel/Makefile
arch/x86/kernel/amd_iommu_init.c
arch/x86/kernel/aperture_64.c
arch/x86/kernel/pci-gart_64.c
drivers/pci/dmar.c
include/linux/dmar.h

index f16a2caca1e0346ce62b47b1d7e0c866c8ddcfcf,2798142cdb49e978f407a05e5c9c0abf134eaa73..a6863a2dec1f6883b6be0b3fd68ca7f6d8982d83
@@@ -1,5 -1,5 +1,5 @@@
  /*
 - * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.
 + * Copyright (C) 2007-2010 Advanced Micro Devices, Inc.
   * Author: Joerg Roedel <joerg.roedel@amd.com>
   *         Leo Duran <leo.duran@amd.com>
   *
  
  #ifdef CONFIG_AMD_IOMMU
  
- extern void amd_iommu_detect(void);
+ extern int amd_iommu_detect(void);
  
  #else
  
- static inline void amd_iommu_detect(void) { }
+ static inline int amd_iommu_detect(void) { return -ENODEV; }
  
  #endif
  
index bf357f9b25f0a69ac70b3fd73ea943437fc43e9b,d7d1d4c438a422785b3001f0ea99d7d0a15cac9a..43085bfc99c30f963b929a9c7afdcff932ad9236
@@@ -17,7 -17,6 +17,7 @@@ extern int fix_aperture
  #define GARTEN                (1<<0)
  #define DISGARTCPU    (1<<4)
  #define DISGARTIO     (1<<5)
 +#define DISTLBWALKPRB (1<<6)
  
  /* GART cache control register bits. */
  #define INVGART               (1<<0)
@@@ -28,6 -27,7 +28,6 @@@
  #define AMD64_GARTAPERTUREBASE        0x94
  #define AMD64_GARTTABLEBASE   0x98
  #define AMD64_GARTCACHECTL    0x9c
 -#define AMD64_GARTEN          (1<<0)
  
  #ifdef CONFIG_GART_IOMMU
  extern int gart_iommu_aperture;
@@@ -37,7 -37,7 +37,7 @@@ extern int gart_iommu_aperture_disabled
  extern void early_gart_iommu_check(void);
  extern int gart_iommu_init(void);
  extern void __init gart_parse_options(char *);
- extern void gart_iommu_hole_init(void);
+ extern int gart_iommu_hole_init(void);
  
  #else
  #define gart_iommu_aperture            0
@@@ -50,26 -50,14 +50,27 @@@ static inline void early_gart_iommu_che
  static inline void gart_parse_options(char *options)
  {
  }
- static inline void gart_iommu_hole_init(void)
+ static inline int gart_iommu_hole_init(void)
  {
+       return -ENODEV;
  }
  #endif
  
  extern int agp_amd64_init(void);
  
 +static inline void gart_set_size_and_enable(struct pci_dev *dev, u32 order)
 +{
 +      u32 ctl;
 +
 +      /*
 +       * Don't enable translation but enable GART IO and CPU accesses.
 +       * Also, set DISTLBWALKPRB since GART tables memory is UC.
 +       */
 +      ctl = DISTLBWALKPRB | order << 1;
 +
 +      pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, ctl);
 +}
 +
  static inline void enable_gart_translation(struct pci_dev *dev, u64 addr)
  {
        u32 tmp, ctl;
diff --combined arch/x86/kernel/Makefile
index 80a93dc99076c3732a620b2f51a5560369ff3cb0,6817546595ef8acb46220d1b00835da3b0d668cb..2c833d8c41418c0583ee2da48231918dd1a6c176
@@@ -11,8 -11,6 +11,8 @@@ ifdef CONFIG_FUNCTION_TRACE
  CFLAGS_REMOVE_tsc.o = -pg
  CFLAGS_REMOVE_rtc.o = -pg
  CFLAGS_REMOVE_paravirt-spinlocks.o = -pg
 +CFLAGS_REMOVE_pvclock.o = -pg
 +CFLAGS_REMOVE_kvmclock.o = -pg
  CFLAGS_REMOVE_ftrace.o = -pg
  CFLAGS_REMOVE_early_printk.o = -pg
  endif
@@@ -34,8 -32,7 +34,8 @@@ GCOV_PROFILE_paravirt.o               := 
  obj-y                 := process_$(BITS).o signal.o entry_$(BITS).o
  obj-y                 += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
  obj-y                 += time.o ioport.o ldt.o dumpstack.o
 -obj-y                 += setup.o x86_init.o i8259.o irqinit.o
 +obj-y                 += setup.o x86_init.o i8259.o irqinit.o jump_label.o
 +obj-$(CONFIG_IRQ_WORK)  += irq_work.o
  obj-$(CONFIG_X86_VISWS)       += visws_quirks.o
  obj-$(CONFIG_X86_32)  += probe_roms_32.o
  obj-$(CONFIG_X86_32)  += sys_i386_32.o i386_ksyms_32.o
@@@ -45,6 -42,7 +45,7 @@@ obj-y                 += bootflag.o e820.
  obj-y                 += pci-dma.o quirks.o i8237.o topology.o kdebugfs.o
  obj-y                 += alternative.o i8253.o pci-nommu.o hw_breakpoint.o
  obj-y                 += tsc.o io_delay.o rtc.o
+ obj-y                 += pci-iommu_table.o
  
  obj-$(CONFIG_X86_TRAMPOLINE)  += trampoline.o
  obj-y                         += process.o
@@@ -86,15 -84,15 +87,15 @@@ obj-$(CONFIG_DOUBLEFAULT)  += doublefau
  obj-$(CONFIG_KGDB)            += kgdb.o
  obj-$(CONFIG_VM86)            += vm86_32.o
  obj-$(CONFIG_EARLY_PRINTK)    += early_printk.o
 +obj-$(CONFIG_EARLY_PRINTK_MRST)       += early_printk_mrst.o
  
  obj-$(CONFIG_HPET_TIMER)      += hpet.o
  obj-$(CONFIG_APB_TIMER)               += apb_timer.o
  
 -obj-$(CONFIG_K8_NB)           += k8.o
 +obj-$(CONFIG_AMD_NB)          += amd_nb.o
  obj-$(CONFIG_DEBUG_RODATA_TEST)       += test_rodata.o
  obj-$(CONFIG_DEBUG_NX_TEST)   += test_nx.o
  
 -obj-$(CONFIG_VMI)             += vmi_32.o vmiclock_32.o
  obj-$(CONFIG_KVM_GUEST)               += kvm.o
  obj-$(CONFIG_KVM_CLOCK)               += kvmclock.o
  obj-$(CONFIG_PARAVIRT)                += paravirt.o paravirt_patch_$(BITS).o
@@@ -107,7 -105,6 +108,7 @@@ obj-$(CONFIG_SCx200)               += scx200.
  scx200-y                      += scx200_32.o
  
  obj-$(CONFIG_OLPC)            += olpc.o
 +obj-$(CONFIG_OLPC_XO1)                += olpc-xo1.o
  obj-$(CONFIG_OLPC_OPENFIRMWARE)       += olpc_ofw.o
  obj-$(CONFIG_X86_MRST)                += mrst.o
  
@@@ -124,6 -121,7 +125,6 @@@ obj-$(CONFIG_SWIOTLB)                      += pci-swiotlb.
  # 64 bit specific files
  ifeq ($(CONFIG_X86_64),y)
        obj-$(CONFIG_X86_UV)            += tlb_uv.o bios_uv.o uv_irq.o uv_sysfs.o uv_time.o
 -      obj-$(CONFIG_X86_PM_TIMER)      += pmtimer_64.o
        obj-$(CONFIG_AUDIT)             += audit_64.o
  
        obj-$(CONFIG_GART_IOMMU)        += pci-gart_64.o aperture_64.o
index 3cb482e123de75f9044e0f843d23fb4348e513a7,26a5e4385210184d83bb46d1f911b2ec9ef87ab7..6e11c8134158e62837deab38e350037e462730f9
@@@ -1,5 -1,5 +1,5 @@@
  /*
 - * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.
 + * Copyright (C) 2007-2010 Advanced Micro Devices, Inc.
   * Author: Joerg Roedel <joerg.roedel@amd.com>
   *         Leo Duran <leo.duran@amd.com>
   *
@@@ -31,7 -31,7 +31,7 @@@
  #include <asm/iommu.h>
  #include <asm/gart.h>
  #include <asm/x86_init.h>
+ #include <asm/iommu_table.h>
  /*
   * definitions for the ACPI scanning code
   */
@@@ -194,39 -194,6 +194,39 @@@ static inline unsigned long tbl_size(in
        return 1UL << shift;
  }
  
 +/* Access to l1 and l2 indexed register spaces */
 +
 +static u32 iommu_read_l1(struct amd_iommu *iommu, u16 l1, u8 address)
 +{
 +      u32 val;
 +
 +      pci_write_config_dword(iommu->dev, 0xf8, (address | l1 << 16));
 +      pci_read_config_dword(iommu->dev, 0xfc, &val);
 +      return val;
 +}
 +
 +static void iommu_write_l1(struct amd_iommu *iommu, u16 l1, u8 address, u32 val)
 +{
 +      pci_write_config_dword(iommu->dev, 0xf8, (address | l1 << 16 | 1 << 31));
 +      pci_write_config_dword(iommu->dev, 0xfc, val);
 +      pci_write_config_dword(iommu->dev, 0xf8, (address | l1 << 16));
 +}
 +
 +static u32 iommu_read_l2(struct amd_iommu *iommu, u8 address)
 +{
 +      u32 val;
 +
 +      pci_write_config_dword(iommu->dev, 0xf0, address);
 +      pci_read_config_dword(iommu->dev, 0xf4, &val);
 +      return val;
 +}
 +
 +static void iommu_write_l2(struct amd_iommu *iommu, u8 address, u32 val)
 +{
 +      pci_write_config_dword(iommu->dev, 0xf0, (address | 1 << 8));
 +      pci_write_config_dword(iommu->dev, 0xf4, val);
 +}
 +
  /****************************************************************************
   *
   * AMD IOMMU MMIO register space handling functions
@@@ -652,7 -619,6 +652,7 @@@ static void __init init_iommu_from_pci(
  {
        int cap_ptr = iommu->cap_ptr;
        u32 range, misc;
 +      int i, j;
  
        pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET,
                              &iommu->cap);
        iommu->last_device = calc_devid(MMIO_GET_BUS(range),
                                        MMIO_GET_LD(range));
        iommu->evt_msi_num = MMIO_MSI_NUM(misc);
 +
 +      if (!is_rd890_iommu(iommu->dev))
 +              return;
 +
 +      /*
 +       * Some rd890 systems may not be fully reconfigured by the BIOS, so
 +       * it's necessary for us to store this information so it can be
 +       * reprogrammed on resume
 +       */
 +
 +      pci_read_config_dword(iommu->dev, iommu->cap_ptr + 4,
 +                            &iommu->stored_addr_lo);
 +      pci_read_config_dword(iommu->dev, iommu->cap_ptr + 8,
 +                            &iommu->stored_addr_hi);
 +
 +      /* Low bit locks writes to configuration space */
 +      iommu->stored_addr_lo &= ~1;
 +
 +      for (i = 0; i < 6; i++)
 +              for (j = 0; j < 0x12; j++)
 +                      iommu->stored_l1[i][j] = iommu_read_l1(iommu, i, j);
 +
 +      for (i = 0; i < 0x83; i++)
 +              iommu->stored_l2[i] = iommu_read_l2(iommu, i);
  }
  
  /*
@@@ -707,9 -649,29 +707,9 @@@ static void __init init_iommu_from_acpi
        struct ivhd_entry *e;
  
        /*
 -       * First set the recommended feature enable bits from ACPI
 -       * into the IOMMU control registers
 -       */
 -      h->flags & IVHD_FLAG_HT_TUN_EN_MASK ?
 -              iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) :
 -              iommu_feature_disable(iommu, CONTROL_HT_TUN_EN);
 -
 -      h->flags & IVHD_FLAG_PASSPW_EN_MASK ?
 -              iommu_feature_enable(iommu, CONTROL_PASSPW_EN) :
 -              iommu_feature_disable(iommu, CONTROL_PASSPW_EN);
 -
 -      h->flags & IVHD_FLAG_RESPASSPW_EN_MASK ?
 -              iommu_feature_enable(iommu, CONTROL_RESPASSPW_EN) :
 -              iommu_feature_disable(iommu, CONTROL_RESPASSPW_EN);
 -
 -      h->flags & IVHD_FLAG_ISOC_EN_MASK ?
 -              iommu_feature_enable(iommu, CONTROL_ISOC_EN) :
 -              iommu_feature_disable(iommu, CONTROL_ISOC_EN);
 -
 -      /*
 -       * make IOMMU memory accesses cache coherent
 +       * First save the recommended feature enable bits from ACPI
         */
 -      iommu_feature_enable(iommu, CONTROL_COHERENT_EN);
 +      iommu->acpi_flags = h->flags;
  
        /*
         * Done. Now parse the device entries
@@@ -1154,79 -1116,6 +1154,79 @@@ static void init_device_table(void
        }
  }
  
 +static void iommu_init_flags(struct amd_iommu *iommu)
 +{
 +      iommu->acpi_flags & IVHD_FLAG_HT_TUN_EN_MASK ?
 +              iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) :
 +              iommu_feature_disable(iommu, CONTROL_HT_TUN_EN);
 +
 +      iommu->acpi_flags & IVHD_FLAG_PASSPW_EN_MASK ?
 +              iommu_feature_enable(iommu, CONTROL_PASSPW_EN) :
 +              iommu_feature_disable(iommu, CONTROL_PASSPW_EN);
 +
 +      iommu->acpi_flags & IVHD_FLAG_RESPASSPW_EN_MASK ?
 +              iommu_feature_enable(iommu, CONTROL_RESPASSPW_EN) :
 +              iommu_feature_disable(iommu, CONTROL_RESPASSPW_EN);
 +
 +      iommu->acpi_flags & IVHD_FLAG_ISOC_EN_MASK ?
 +              iommu_feature_enable(iommu, CONTROL_ISOC_EN) :
 +              iommu_feature_disable(iommu, CONTROL_ISOC_EN);
 +
 +      /*
 +       * make IOMMU memory accesses cache coherent
 +       */
 +      iommu_feature_enable(iommu, CONTROL_COHERENT_EN);
 +}
 +
 +static void iommu_apply_resume_quirks(struct amd_iommu *iommu)
 +{
 +      int i, j;
 +      u32 ioc_feature_control;
 +      struct pci_dev *pdev = NULL;
 +
 +      /* RD890 BIOSes may not have completely reconfigured the iommu */
 +      if (!is_rd890_iommu(iommu->dev))
 +              return;
 +
 +      /*
 +       * First, we need to ensure that the iommu is enabled. This is
 +       * controlled by a register in the northbridge
 +       */
 +      pdev = pci_get_bus_and_slot(iommu->dev->bus->number, PCI_DEVFN(0, 0));
 +
 +      if (!pdev)
 +              return;
 +
 +      /* Select Northbridge indirect register 0x75 and enable writing */
 +      pci_write_config_dword(pdev, 0x60, 0x75 | (1 << 7));
 +      pci_read_config_dword(pdev, 0x64, &ioc_feature_control);
 +
 +      /* Enable the iommu */
 +      if (!(ioc_feature_control & 0x1))
 +              pci_write_config_dword(pdev, 0x64, ioc_feature_control | 1);
 +
 +      pci_dev_put(pdev);
 +
 +      /* Restore the iommu BAR */
 +      pci_write_config_dword(iommu->dev, iommu->cap_ptr + 4,
 +                             iommu->stored_addr_lo);
 +      pci_write_config_dword(iommu->dev, iommu->cap_ptr + 8,
 +                             iommu->stored_addr_hi);
 +
 +      /* Restore the l1 indirect regs for each of the 6 l1s */
 +      for (i = 0; i < 6; i++)
 +              for (j = 0; j < 0x12; j++)
 +                      iommu_write_l1(iommu, i, j, iommu->stored_l1[i][j]);
 +
 +      /* Restore the l2 indirect regs */
 +      for (i = 0; i < 0x83; i++)
 +              iommu_write_l2(iommu, i, iommu->stored_l2[i]);
 +
 +      /* Lock PCI setup registers */
 +      pci_write_config_dword(iommu->dev, iommu->cap_ptr + 4,
 +                             iommu->stored_addr_lo | 1);
 +}
 +
  /*
   * This function finally enables all IOMMUs found in the system after
   * they have been initialized
@@@ -1237,7 -1126,6 +1237,7 @@@ static void enable_iommus(void
  
        for_each_iommu(iommu) {
                iommu_disable(iommu);
 +              iommu_init_flags(iommu);
                iommu_set_device_table(iommu);
                iommu_enable_command_buffer(iommu);
                iommu_enable_event_buffer(iommu);
@@@ -1262,11 -1150,6 +1262,11 @@@ static void disable_iommus(void
  
  static int amd_iommu_resume(struct sys_device *dev)
  {
 +      struct amd_iommu *iommu;
 +
 +      for_each_iommu(iommu)
 +              iommu_apply_resume_quirks(iommu);
 +
        /* re-load the hardware */
        enable_iommus();
  
@@@ -1499,13 -1382,13 +1499,13 @@@ static int __init early_amd_iommu_detec
        return 0;
  }
  
void __init amd_iommu_detect(void)
int __init amd_iommu_detect(void)
  {
        if (no_iommu || (iommu_detected && !gart_iommu_aperture))
-               return;
+               return -ENODEV;
  
        if (amd_iommu_disabled)
-               return;
+               return -ENODEV;
  
        if (acpi_table_parse("IVRS", early_amd_iommu_detect) == 0) {
                iommu_detected = 1;
  
                /* Make sure ACS will be enabled */
                pci_request_acs();
+               return 1;
        }
+       return -ENODEV;
  }
  
  /****************************************************************************
@@@ -1545,3 -1430,8 +1547,8 @@@ static int __init parse_amd_iommu_optio
  
  __setup("amd_iommu_dump", parse_amd_iommu_dump);
  __setup("amd_iommu=", parse_amd_iommu_options);
+ IOMMU_INIT_FINISH(amd_iommu_detect,
+                 gart_iommu_hole_init,
+                 0,
+                 0);
index 377f5db3b8b4092d4926000703c3433231fe86e0,afa0dab3302f4f776bf681b4ace1f63de678f2f4..b3a16e8f0703d47f50a354223bfe8c6e9382126e
@@@ -27,7 -27,7 +27,7 @@@
  #include <asm/gart.h>
  #include <asm/pci-direct.h>
  #include <asm/dma.h>
 -#include <asm/k8.h>
 +#include <asm/amd_nb.h>
  #include <asm/x86_init.h>
  
  int gart_iommu_aperture;
@@@ -307,7 -307,7 +307,7 @@@ void __init early_gart_iommu_check(void
                                continue;
  
                        ctl = read_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL);
 -                      aper_enabled = ctl & AMD64_GARTEN;
 +                      aper_enabled = ctl & GARTEN;
                        aper_order = (ctl >> 1) & 7;
                        aper_size = (32 * 1024 * 1024) << aper_order;
                        aper_base = read_pci_config(bus, slot, 3, AMD64_GARTAPERTUREBASE) & 0x7fff;
                                continue;
  
                        ctl = read_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL);
 -                      ctl &= ~AMD64_GARTEN;
 +                      ctl &= ~GARTEN;
                        write_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL, ctl);
                }
        }
  
  static int __initdata printed_gart_size_msg;
  
void __init gart_iommu_hole_init(void)
int __init gart_iommu_hole_init(void)
  {
        u32 agp_aper_base = 0, agp_aper_order = 0;
        u32 aper_size, aper_alloc = 0, aper_order = 0, last_aper_order = 0;
  
        if (gart_iommu_aperture_disabled || !fix_aperture ||
            !early_pci_allowed())
-               return;
+               return -ENODEV;
  
        printk(KERN_INFO  "Checking aperture...\n");
  
@@@ -463,8 -463,9 +463,9 @@@ out
                        unsigned long n = (32 * 1024 * 1024) << last_aper_order;
  
                        insert_aperture_resource((u32)last_aper_base, n);
+                       return 1;
                }
-               return;
+               return 0;
        }
  
        if (!fallback_aper_force) {
                        panic("Not enough memory for aperture");
                }
        } else {
-               return;
+               return 0;
        }
  
        /* Fix up the north bridges */
        for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) {
 -              int bus;
 -              int dev_base, dev_limit;
 +              int bus, dev_base, dev_limit;
 +
 +              /*
 +               * Don't enable translation yet but enable GART IO and CPU
 +               * accesses and set DISTLBWALKPRB since GART table memory is UC.
 +               */
 +              u32 ctl = DISTLBWALKPRB | aper_order << 1;
  
                bus = bus_dev_ranges[i].bus;
                dev_base = bus_dev_ranges[i].dev_base;
                        if (!early_is_k8_nb(read_pci_config(bus, slot, 3, 0x00)))
                                continue;
  
 -                      /* Don't enable translation yet. That is done later.
 -                         Assume this BIOS didn't initialise the GART so
 -                         just overwrite all previous bits */
 -                      write_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL, aper_order << 1);
 +                      write_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL, ctl);
                        write_pci_config(bus, slot, 3, AMD64_GARTAPERTUREBASE, aper_alloc >> 25);
                }
        }
  
        set_up_gart_resume(aper_order, aper_alloc);
+       return 1;
  }
index c562207b1b3da8c6abcf1d85416e4c22f078a1be,de9734b100a416a59c2b2eb875b5035f0d555ff9..ba0f0ca9f280bb0473470fdb71a3fa04faec00f0
@@@ -39,8 -39,9 +39,9 @@@
  #include <asm/cacheflush.h>
  #include <asm/swiotlb.h>
  #include <asm/dma.h>
 -#include <asm/k8.h>
 +#include <asm/amd_nb.h>
  #include <asm/x86_init.h>
+ #include <asm/iommu_table.h>
  
  static unsigned long iommu_bus_base;  /* GART remapping area (physical) */
  static unsigned long iommu_size;      /* size of remapping area bytes */
@@@ -560,11 -561,8 +561,11 @@@ static void enable_gart_translations(vo
  {
        int i;
  
 -      for (i = 0; i < num_k8_northbridges; i++) {
 -              struct pci_dev *dev = k8_northbridges[i];
 +      if (!k8_northbridges.gart_supported)
 +              return;
 +
 +      for (i = 0; i < k8_northbridges.num; i++) {
 +              struct pci_dev *dev = k8_northbridges.nb_misc[i];
  
                enable_gart_translation(dev, __pa(agp_gatt_table));
        }
@@@ -595,19 -593,16 +596,19 @@@ static void gart_fixup_northbridges(str
        if (!fix_up_north_bridges)
                return;
  
 +      if (!k8_northbridges.gart_supported)
 +              return;
 +
        pr_info("PCI-DMA: Restoring GART aperture settings\n");
  
 -      for (i = 0; i < num_k8_northbridges; i++) {
 -              struct pci_dev *dev = k8_northbridges[i];
 +      for (i = 0; i < k8_northbridges.num; i++) {
 +              struct pci_dev *dev = k8_northbridges.nb_misc[i];
  
                /*
                 * Don't enable translations just yet.  That is the next
                 * step.  Restore the pre-suspend aperture settings.
                 */
 -              pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, aperture_order << 1);
 +              gart_set_size_and_enable(dev, aperture_order);
                pci_write_config_dword(dev, AMD64_GARTAPERTUREBASE, aperture_alloc >> 25);
        }
  }
@@@ -655,8 -650,8 +656,8 @@@ static __init int init_k8_gatt(struct a
  
        aper_size = aper_base = info->aper_size = 0;
        dev = NULL;
 -      for (i = 0; i < num_k8_northbridges; i++) {
 -              dev = k8_northbridges[i];
 +      for (i = 0; i < k8_northbridges.num; i++) {
 +              dev = k8_northbridges.nb_misc[i];
                new_aper_base = read_aperture(dev, &new_aper_size);
                if (!new_aper_base)
                        goto nommu;
@@@ -724,13 -719,10 +725,13 @@@ static void gart_iommu_shutdown(void
        if (!no_agp)
                return;
  
 -      for (i = 0; i < num_k8_northbridges; i++) {
 +      if (!k8_northbridges.gart_supported)
 +              return;
 +
 +      for (i = 0; i < k8_northbridges.num; i++) {
                u32 ctl;
  
 -              dev = k8_northbridges[i];
 +              dev = k8_northbridges.nb_misc[i];
                pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &ctl);
  
                ctl &= ~GARTEN;
@@@ -748,7 -740,7 +749,7 @@@ int __init gart_iommu_init(void
        unsigned long scratch;
        long i;
  
 -      if (num_k8_northbridges == 0)
 +      if (!k8_northbridges.gart_supported)
                return 0;
  
  #ifndef CONFIG_AGP_AMD64
@@@ -905,3 -897,4 +906,4 @@@ void __init gart_parse_options(char *p
                }
        }
  }
+ IOMMU_INIT_POST(gart_iommu_hole_init);
diff --combined drivers/pci/dmar.c
index 3de3a436a432c1719b5d02f4c40c0ff59e6f3449,4ef56a0920a75f189abb306bab34ba5f7844803f..0157708d474da57ad0532a3bb8bbbd90f0204aeb
@@@ -36,6 -36,7 +36,7 @@@
  #include <linux/tboot.h>
  #include <linux/dmi.h>
  #include <linux/slab.h>
+ #include <asm/iommu_table.h>
  
  #define PREFIX "DMAR: "
  
@@@ -687,7 -688,7 +688,7 @@@ failed
        return 0;
  }
  
void __init detect_intel_iommu(void)
int __init detect_intel_iommu(void)
  {
        int ret;
  
        }
        early_acpi_os_unmap_memory(dmar_tbl, dmar_tbl_size);
        dmar_tbl = NULL;
+       return ret ? 1 : -ENODEV;
  }
  
  
@@@ -1221,9 -1224,9 +1224,9 @@@ const char *dmar_get_fault_reason(u8 fa
        }
  }
  
 -void dmar_msi_unmask(unsigned int irq)
 +void dmar_msi_unmask(struct irq_data *data)
  {
 -      struct intel_iommu *iommu = get_irq_data(irq);
 +      struct intel_iommu *iommu = irq_data_get_irq_data(data);
        unsigned long flag;
  
        /* unmask it */
        spin_unlock_irqrestore(&iommu->register_lock, flag);
  }
  
 -void dmar_msi_mask(unsigned int irq)
 +void dmar_msi_mask(struct irq_data *data)
  {
        unsigned long flag;
 -      struct intel_iommu *iommu = get_irq_data(irq);
 +      struct intel_iommu *iommu = irq_data_get_irq_data(data);
  
        /* mask it */
        spin_lock_irqsave(&iommu->register_lock, flag);
@@@ -1455,3 -1458,4 +1458,4 @@@ int __init dmar_ir_support(void
                return 0;
        return dmar->flags & 0x1;
  }
+ IOMMU_INIT_POST(detect_intel_iommu);
diff --combined include/linux/dmar.h
index 51651b76d40f9ab545be13fa0a53dc1a1b212f6c,a206020415112fb1b4ae12f494d9a8dddab0d02f..a7d9dc21391d276e94c7a008107d31a0c56d8dc6
@@@ -57,15 -57,15 +57,15 @@@ extern int dmar_table_init(void)
  extern int dmar_dev_scope_init(void);
  
  /* Intel IOMMU detection */
- extern void detect_intel_iommu(void);
+ extern int detect_intel_iommu(void);
  extern int enable_drhd_fault_handling(void);
  
  extern int parse_ioapics_under_ir(void);
  extern int alloc_iommu(struct dmar_drhd_unit *);
  #else
- static inline void detect_intel_iommu(void)
+ static inline int detect_intel_iommu(void)
  {
-       return;
+       return -ENODEV;
  }
  
  static inline int dmar_table_init(void)
@@@ -106,7 -106,6 +106,7 @@@ struct irte 
                __u64 high;
        };
  };
 +
  #ifdef CONFIG_INTR_REMAP
  extern int intr_remapping_enabled;
  extern int intr_remapping_supported(void);
@@@ -120,8 -119,11 +120,8 @@@ extern int alloc_irte(struct intel_iomm
  extern int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index,
                        u16 sub_handle);
  extern int map_irq_to_irte_handle(int irq, u16 *sub_handle);
 -extern int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index);
 -extern int flush_irte(int irq);
  extern int free_irte(int irq);
  
 -extern int irq_remapped(int irq);
  extern struct intel_iommu *map_dev_to_ir(struct pci_dev *dev);
  extern struct intel_iommu *map_ioapic_to_ir(int apic);
  extern struct intel_iommu *map_hpet_to_ir(u8 id);
@@@ -175,6 -177,7 +175,6 @@@ static inline int set_msi_sid(struct ir
        return 0;
  }
  
 -#define irq_remapped(irq)             (0)
  #define enable_intr_remapping(mode)   (-1)
  #define disable_intr_remapping()      (0)
  #define reenable_intr_remapping(mode) (0)
  /* Can't use the common MSI interrupt functions
   * since DMAR is not a pci device
   */
 -extern void dmar_msi_unmask(unsigned int irq);
 -extern void dmar_msi_mask(unsigned int irq);
 +struct irq_data;
 +extern void dmar_msi_unmask(struct irq_data *data);
 +extern void dmar_msi_mask(struct irq_data *data);
  extern void dmar_msi_read(int irq, struct msi_msg *msg);
  extern void dmar_msi_write(int irq, struct msi_msg *msg);
  extern int dmar_set_interrupt(struct intel_iommu *iommu);