Merge tag 'iommu-updates-v3.8' of git://git.kernel.org/pub/scm/linux/kernel/git/joro...
Linus Torvalds [Thu, 20 Dec 2012 18:07:25 +0000 (10:07 -0800)]
Pull IOMMU updates from Joerg Roedel:
 "A few new features this merge-window.  The most important one is
  probably, that dma-debug now warns if a dma-handle is not checked with
  dma_mapping_error by the device driver.  This requires minor changes
  to some architectures which make use of dma-debug.  Most of these
  changes have the respective Acks by the Arch-Maintainers.

  Besides that there are updates to the AMD IOMMU driver for refactor
  the IOMMU-Groups support and to make sure it does not trigger a
  hardware erratum.

  The OMAP changes (for which I pulled in a branch from Tony Lindgren's
  tree) have a conflict in linux-next with the arm-soc tree.  The
  conflict is in the file arch/arm/mach-omap2/clock44xx_data.c which is
  deleted in the arm-soc tree.  It is safe to delete the file too so
  solve the conflict.  Similar changes are done in the arm-soc tree in
  the common clock framework migration.  A missing hunk from the patch
  in the IOMMU tree will be submitted as a seperate patch when the
  merge-window is closed."

* tag 'iommu-updates-v3.8' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: (29 commits)
  ARM: dma-mapping: support debug_dma_mapping_error
  ARM: OMAP4: hwmod data: ipu and dsp to use parent clocks instead of leaf clocks
  iommu/omap: Adapt to runtime pm
  iommu/omap: Migrate to hwmod framework
  iommu/omap: Keep mmu enabled when requested
  iommu/omap: Remove redundant clock handling on ISR
  iommu/amd: Remove obsolete comment
  iommu/amd: Don't use 512GB pages
  iommu/tegra: smmu: Move bus_set_iommu after probe for multi arch
  iommu/tegra: gart: Move bus_set_iommu after probe for multi arch
  iommu/tegra: smmu: Remove unnecessary PTC/TLB flush all
  tile: dma_debug: add debug_dma_mapping_error support
  sh: dma_debug: add debug_dma_mapping_error support
  powerpc: dma_debug: add debug_dma_mapping_error support
  mips: dma_debug: add debug_dma_mapping_error support
  microblaze: dma-mapping: support debug_dma_mapping_error
  ia64: dma_debug: add debug_dma_mapping_error support
  c6x: dma_debug: add debug_dma_mapping_error support
  ARM64: dma_debug: add debug_dma_mapping_error support
  intel-iommu: Prevent devices with RMRRs from being placed into SI Domain
  ...

1  2 
arch/arm/include/asm/dma-mapping.h
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
drivers/iommu/intel-iommu.c
drivers/iommu/tegra-smmu.c

@@@ -91,6 -91,7 +91,7 @@@ static inline dma_addr_t virt_to_dma(st
   */
  static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
  {
+       debug_dma_mapping_error(dev, dma_addr);
        return dma_addr == DMA_ERROR_CODE;
  }
  
@@@ -111,8 -112,6 +112,8 @@@ static inline void dma_free_noncoherent
  
  extern int dma_supported(struct device *dev, u64 mask);
  
 +extern int arm_dma_set_mask(struct device *dev, u64 dma_mask);
 +
  /**
   * arm_dma_alloc - allocate consistent memory for DMA
   * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
@@@ -213,6 -212,13 +214,6 @@@ static inline void dma_free_writecombin
  extern void __init init_dma_coherent_pool_size(unsigned long size);
  
  /*
 - * This can be called during boot to increase the size of the consistent
 - * DMA region above it's default value of 2MB. It must be called before the
 - * memory allocator is initialised, i.e. before any core_initcall.
 - */
 -static inline void init_consistent_dma_size(unsigned long size) { }
 -
 -/*
   * For SA-1111, IXP425, and ADI systems  the dma-mapping functions are "magic"
   * and utilize bounce buffers as needed to work around limited DMA windows.
   *
  #include <asm/mach-types.h>
  #include <asm/mach/map.h>
  
 +#include <linux/omap-dma.h>
 +
  #include "iomap.h"
 -#include <plat/dma.h>
 -#include <plat/omap_hwmod.h>
 -#include <plat/omap_device.h>
 +#include "omap_hwmod.h"
 +#include "omap_device.h"
  #include "omap4-keypad.h"
  
  #include "soc.h"
@@@ -36,7 -35,6 +36,7 @@@
  #include "mux.h"
  #include "control.h"
  #include "devices.h"
 +#include "dma.h"
  
  #define L3_MODULES_MAX_LEN 12
  #define L3_MODULES 3
@@@ -203,16 -201,6 +203,16 @@@ static struct resource omap3isp_resourc
                .flags          = IORESOURCE_MEM,
        },
        {
 +              .start          = OMAP343X_CTRL_BASE + OMAP343X_CONTROL_CSIRXFE,
 +              .end            = OMAP343X_CTRL_BASE + OMAP343X_CONTROL_CSIRXFE + 3,
 +              .flags          = IORESOURCE_MEM,
 +      },
 +      {
 +              .start          = OMAP343X_CTRL_BASE + OMAP3630_CONTROL_CAMERA_PHY_CTRL,
 +              .end            = OMAP343X_CTRL_BASE + OMAP3630_CONTROL_CAMERA_PHY_CTRL + 3,
 +              .flags          = IORESOURCE_MEM,
 +      },
 +      {
                .start          = 24 + OMAP_INTC_START,
                .flags          = IORESOURCE_IRQ,
        }
@@@ -226,7 -214,7 +226,7 @@@ static struct platform_device omap3isp_
  };
  
  static struct omap_iommu_arch_data omap3_isp_iommu = {
-       .name = "isp",
+       .name = "mmu_isp",
  };
  
  int omap3_init_camera(struct isp_platform_data *pdata)
@@@ -735,3 -723,29 +735,3 @@@ static int __init omap2_init_devices(vo
        return 0;
  }
  arch_initcall(omap2_init_devices);
 -
 -#if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
 -static int __init omap_init_wdt(void)
 -{
 -      int id = -1;
 -      struct platform_device *pdev;
 -      struct omap_hwmod *oh;
 -      char *oh_name = "wd_timer2";
 -      char *dev_name = "omap_wdt";
 -
 -      if (!cpu_class_is_omap2() || of_have_populated_dt())
 -              return 0;
 -
 -      oh = omap_hwmod_lookup(oh_name);
 -      if (!oh) {
 -              pr_err("Could not look up wd_timer%d hwmod\n", id);
 -              return -EINVAL;
 -      }
 -
 -      pdev = omap_device_build(dev_name, id, oh, NULL, 0, NULL, 0, 0);
 -      WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s.\n",
 -                              dev_name, oh->name);
 -      return 0;
 -}
 -subsys_initcall(omap_init_wdt);
 -#endif
  #include <linux/platform_data/gpio-omap.h>
  #include <linux/power/smartreflex.h>
  #include <linux/platform_data/omap_ocp2scp.h>
 +#include <linux/i2c-omap.h>
  
 -#include <plat/omap_hwmod.h>
 -#include <plat/i2c.h>
 -#include <plat/dma.h>
 +#include <linux/omap-dma.h>
 +
 +#include <linux/platform_data/omap_ocp2scp.h>
  #include <linux/platform_data/spi-omap2-mcspi.h>
  #include <linux/platform_data/asoc-ti-mcbsp.h>
  #include <linux/platform_data/iommu-omap.h>
 -#include <plat/mmc.h>
  #include <plat/dmtimer.h>
 -#include <plat/common.h>
  
 +#include "omap_hwmod.h"
  #include "omap_hwmod_common_data.h"
  #include "cm1_44xx.h"
  #include "cm2_44xx.h"
  #include "prm44xx.h"
  #include "prm-regbits-44xx.h"
 +#include "i2c.h"
 +#include "mmc.h"
  #include "wd_timer.h"
  
  /* Base offset for all OMAP4 interrupts external to MPUSS */
@@@ -653,7 -651,7 +653,7 @@@ static struct omap_hwmod omap44xx_dsp_h
        .mpu_irqs       = omap44xx_dsp_irqs,
        .rst_lines      = omap44xx_dsp_resets,
        .rst_lines_cnt  = ARRAY_SIZE(omap44xx_dsp_resets),
-       .main_clk       = "dsp_fck",
+       .main_clk       = "dpll_iva_m4x2_ck",
        .prcm = {
                .omap4 = {
                        .clkctrl_offs = OMAP4_CM_TESLA_TESLA_CLKCTRL_OFFSET,
@@@ -1529,7 -1527,8 +1529,7 @@@ static struct omap_hwmod_class omap44xx
  };
  
  static struct omap_i2c_dev_attr i2c_dev_attr = {
 -      .flags  = OMAP_I2C_FLAG_BUS_SHIFT_NONE |
 -                      OMAP_I2C_FLAG_RESET_REGS_POSTIDLE,
 +      .flags  = OMAP_I2C_FLAG_BUS_SHIFT_NONE,
  };
  
  /* i2c1 */
@@@ -1679,7 -1678,7 +1679,7 @@@ static struct omap_hwmod omap44xx_ipu_h
        .mpu_irqs       = omap44xx_ipu_irqs,
        .rst_lines      = omap44xx_ipu_resets,
        .rst_lines_cnt  = ARRAY_SIZE(omap44xx_ipu_resets),
-       .main_clk       = "ipu_fck",
+       .main_clk       = "ducati_clk_mux_ck",
        .prcm = {
                .omap4 = {
                        .clkctrl_offs = OMAP4_CM_DUCATI_DUCATI_CLKCTRL_OFFSET,
@@@ -3103,7 -3102,6 +3103,7 @@@ static struct omap_hwmod_class_sysconfi
                           SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
                           SYSS_HAS_RESET_STATUS),
        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
 +      .clockact       = CLOCKACT_TEST_ICLK,
        .sysc_fields    = &omap_hwmod_sysc_type1,
  };
  
@@@ -3157,7 -3155,6 +3157,7 @@@ static struct omap_hwmod omap44xx_timer
        .name           = "timer1",
        .class          = &omap44xx_timer_1ms_hwmod_class,
        .clkdm_name     = "l4_wkup_clkdm",
 +      .flags          = HWMOD_SET_DEFAULT_CLOCKACT,
        .mpu_irqs       = omap44xx_timer1_irqs,
        .main_clk       = "timer1_fck",
        .prcm = {
@@@ -3180,7 -3177,6 +3180,7 @@@ static struct omap_hwmod omap44xx_timer
        .name           = "timer2",
        .class          = &omap44xx_timer_1ms_hwmod_class,
        .clkdm_name     = "l4_per_clkdm",
 +      .flags          = HWMOD_SET_DEFAULT_CLOCKACT,
        .mpu_irqs       = omap44xx_timer2_irqs,
        .main_clk       = "timer2_fck",
        .prcm = {
@@@ -3355,7 -3351,6 +3355,7 @@@ static struct omap_hwmod omap44xx_timer
        .name           = "timer10",
        .class          = &omap44xx_timer_1ms_hwmod_class,
        .clkdm_name     = "l4_per_clkdm",
 +      .flags          = HWMOD_SET_DEFAULT_CLOCKACT,
        .mpu_irqs       = omap44xx_timer10_irqs,
        .main_clk       = "timer10_fck",
        .prcm = {
@@@ -1827,17 -1827,10 +1827,17 @@@ static int __domain_mapping(struct dmar
                        if (!pte)
                                return -ENOMEM;
                        /* It is large page*/
 -                      if (largepage_lvl > 1)
 +                      if (largepage_lvl > 1) {
                                pteval |= DMA_PTE_LARGE_PAGE;
 -                      else
 +                              /* Ensure that old small page tables are removed to make room
 +                                 for superpage, if they exist. */
 +                              dma_pte_clear_range(domain, iov_pfn,
 +                                                  iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1);
 +                              dma_pte_free_pagetable(domain, iov_pfn,
 +                                                     iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1);
 +                      } else {
                                pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE;
 +                      }
  
                }
                /* We don't need lock here, nobody else
@@@ -2327,8 -2320,39 +2327,39 @@@ static int domain_add_dev_info(struct d
        return 0;
  }
  
+ static bool device_has_rmrr(struct pci_dev *dev)
+ {
+       struct dmar_rmrr_unit *rmrr;
+       int i;
+       for_each_rmrr_units(rmrr) {
+               for (i = 0; i < rmrr->devices_cnt; i++) {
+                       /*
+                        * Return TRUE if this RMRR contains the device that
+                        * is passed in.
+                        */
+                       if (rmrr->devices[i] == dev)
+                               return true;
+               }
+       }
+       return false;
+ }
  static int iommu_should_identity_map(struct pci_dev *pdev, int startup)
  {
+       /*
+        * We want to prevent any device associated with an RMRR from
+        * getting placed into the SI Domain. This is done because
+        * problems exist when devices are moved in and out of domains
+        * and their respective RMRR info is lost. We exempt USB devices
+        * from this process due to their usage of RMRRs that are known
+        * to not be needed after BIOS hand-off to OS.
+        */
+       if (device_has_rmrr(pdev) &&
+           (pdev->class >> 8) != PCI_CLASS_SERIAL_USB)
+               return 0;
        if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
                return 1;
  
  #include <linux/of_iommu.h>
  #include <linux/debugfs.h>
  #include <linux/seq_file.h>
 +#include <linux/tegra-ahb.h>
  
  #include <asm/page.h>
  #include <asm/cacheflush.h>
  
 -#include <mach/iomap.h>
 -#include <mach/tegra-ahb.h>
 -
  enum smmu_hwgrp {
        HWGRP_AFI,
        HWGRP_AVPC,
@@@ -694,10 -696,8 +694,8 @@@ static void __smmu_iommu_unmap(struct s
        *pte = _PTE_VACANT(iova);
        FLUSH_CPU_DCACHE(pte, page, sizeof(*pte));
        flush_ptc_and_tlb(as->smmu, as, iova, pte, page, 0);
-       if (!--(*count)) {
+       if (!--(*count))
                free_ptbl(as, iova);
-               smmu_flush_regs(as->smmu, 0);
-       }
  }
  
  static void __smmu_iommu_map_pfn(struct smmu_as *as, dma_addr_t iova,
@@@ -1232,6 -1232,7 +1230,7 @@@ static int tegra_smmu_probe(struct plat
  
        smmu_debugfs_create(smmu);
        smmu_handle = smmu;
+       bus_set_iommu(&platform_bus_type, &smmu_iommu_ops);
        return 0;
  }
  
@@@ -1276,7 -1277,6 +1275,6 @@@ static struct platform_driver tegra_smm
  
  static int __devinit tegra_smmu_init(void)
  {
-       bus_set_iommu(&platform_bus_type, &smmu_iommu_ops);
        return platform_driver_register(&tegra_smmu_driver);
  }