]> Git Repo - linux.git/commitdiff
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <[email protected]>
Sun, 10 Jun 2018 16:44:53 +0000 (09:44 -0700)
committerLinus Torvalds <[email protected]>
Sun, 10 Jun 2018 16:44:53 +0000 (09:44 -0700)
Pull x86 updates and fixes from Thomas Gleixner:

 - Fix the (late) fallout from the vector management rework causing
   hlist corruption and irq descriptor reference leaks caused by a
   missing sanity check.

   The straight forward fix triggered another long standing issue to
   surface. The pre rework code hid the issue due to being way slower,
   but now the chance that user space sees an EBUSY error return when
   updating irq affinities is way higher, though quite a bunch of
   userspace tools do not handle it properly despite the fact that EBUSY
   could be returned for at least 10 years.

   It turned out that the EBUSY return can be avoided completely by
   utilizing the existing delayed affinity update mechanism for irq
   remapped scenarios as well. That's a bit more error handling in the
   kernel, but avoids fruitless fingerpointing discussions with tool
   developers.

 - Decouple PHYSICAL_MASK from AMD SME as its going to be required for
   the upcoming Intel memory encryption support as well.

 - Handle legacy device ACPI detection properly for newer platforms

 - Fix the wrong argument ordering in the vector allocation tracepoint

 - Simplify the IDT setup code for the APIC=n case

 - Use the proper string helpers in the MTRR code

 - Remove a stale unused VDSO source file

 - Convert the microcode update lock to a raw spinlock as its used in
   atomic context.

* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/intel_rdt: Enable CMT and MBM on new Skylake stepping
  x86/apic/vector: Print APIC control bits in debugfs
  genirq/affinity: Defer affinity setting if irq chip is busy
  x86/platform/uv: Use apic_ack_irq()
  x86/ioapic: Use apic_ack_irq()
  irq_remapping: Use apic_ack_irq()
  x86/apic: Provide apic_ack_irq()
  genirq/migration: Avoid out of line call if pending is not set
  genirq/generic_pending: Do not lose pending affinity update
  x86/apic/vector: Prevent hlist corruption and leaks
  x86/vector: Fix the args of vector_alloc tracepoint
  x86/idt: Simplify the idt_setup_apic_and_irq_gates()
  x86/platform/uv: Remove extra parentheses
  x86/mm: Decouple dynamic __PHYSICAL_MASK from AMD SME
  x86: Mark native_set_p4d() as __always_inline
  x86/microcode: Make the late update update_lock a raw lock for RT
  x86/mtrr: Convert to use strncpy_from_user() helper
  x86/mtrr: Convert to use match_string() helper
  x86/vdso: Remove unused file
  x86/i8237: Register device based on FADT legacy boot flag

1  2 
arch/x86/Kconfig
arch/x86/include/asm/pgtable_64.h
arch/x86/include/asm/x86_init.h
arch/x86/kernel/cpu/intel_rdt.c
arch/x86/mm/pgtable.c
drivers/iommu/amd_iommu.c
include/linux/irq.h
kernel/irq/manage.c

diff --combined arch/x86/Kconfig
index f182a4e8e5bd24cb58bf0ce8a659adb5aa0c8d81,43a8fc4762965268be346919a7d8ae31ff914efd..0527060b27103dadf768ac519193bbd07f1f6af4
@@@ -1,8 -1,8 +1,8 @@@
  # SPDX-License-Identifier: GPL-2.0
  # Select 32 or 64 bit
  config 64BIT
 -      bool "64-bit kernel" if ARCH = "x86"
 -      default ARCH != "i386"
 +      bool "64-bit kernel" if "$(ARCH)" = "x86"
 +      default "$(ARCH)" != "i386"
        ---help---
          Say yes to build a 64-bit kernel - formerly known as x86_64
          Say no to build a 32-bit kernel - formerly known as i386
@@@ -28,8 -28,6 +28,8 @@@ config X86_6
        select ARCH_USE_CMPXCHG_LOCKREF
        select HAVE_ARCH_SOFT_DIRTY
        select MODULES_USE_ELF_RELA
 +      select NEED_DMA_MAP_STATE
 +      select SWIOTLB
        select X86_DEV_DMA_OPS
        select ARCH_HAS_SYSCALL_WRAPPER
  
@@@ -60,10 -58,8 +60,10 @@@ config X8
        select ARCH_HAS_KCOV                    if X86_64
        select ARCH_HAS_MEMBARRIER_SYNC_CORE
        select ARCH_HAS_PMEM_API                if X86_64
 +      select ARCH_HAS_PTE_SPECIAL
        select ARCH_HAS_REFCOUNT
        select ARCH_HAS_UACCESS_FLUSHCACHE      if X86_64
 +      select ARCH_HAS_UACCESS_MCSAFE          if X86_64
        select ARCH_HAS_SET_MEMORY
        select ARCH_HAS_SG_CHAIN
        select ARCH_HAS_STRICT_KERNEL_RWX
        select HAVE_C_RECORDMCOUNT
        select HAVE_DEBUG_KMEMLEAK
        select HAVE_DEBUG_STACKOVERFLOW
 -      select HAVE_DMA_API_DEBUG
        select HAVE_DMA_CONTIGUOUS
        select HAVE_DYNAMIC_FTRACE
        select HAVE_DYNAMIC_FTRACE_WITH_REGS
 -      select HAVE_EBPF_JIT                    if X86_64
 +      select HAVE_EBPF_JIT
        select HAVE_EFFICIENT_UNALIGNED_ACCESS
        select HAVE_EXIT_THREAD
        select HAVE_FENTRY                      if X86_64 || DYNAMIC_FTRACE
        select HAVE_UNSTABLE_SCHED_CLOCK
        select HAVE_USER_RETURN_NOTIFIER
        select IRQ_FORCED_THREADING
 +      select NEED_SG_DMA_LENGTH
        select PCI_LOCKLESS_CONFIG
        select PERF_EVENTS
        select RTC_LIB
@@@ -240,6 -236,13 +240,6 @@@ config ARCH_MMAP_RND_COMPAT_BITS_MA
  config SBUS
        bool
  
 -config NEED_DMA_MAP_STATE
 -      def_bool y
 -      depends on X86_64 || INTEL_IOMMU || DMA_API_DEBUG || SWIOTLB
 -
 -config NEED_SG_DMA_LENGTH
 -      def_bool y
 -
  config GENERIC_ISA_DMA
        def_bool y
        depends on ISA_DMA_API
@@@ -334,6 -337,9 +334,9 @@@ config ARCH_SUPPORTS_UPROBE
  config FIX_EARLYCON_MEM
        def_bool y
  
+ config DYNAMIC_PHYSICAL_MASK
+       bool
  config PGTABLE_LEVELS
        int
        default 5 if X86_5LEVEL
@@@ -872,7 -878,6 +875,7 @@@ config DM
  
  config GART_IOMMU
        bool "Old AMD GART IOMMU support"
 +      select IOMMU_HELPER
        select SWIOTLB
        depends on X86_64 && PCI && AMD_NB
        ---help---
  
  config CALGARY_IOMMU
        bool "IBM Calgary IOMMU support"
 +      select IOMMU_HELPER
        select SWIOTLB
        depends on X86_64 && PCI
        ---help---
@@@ -922,6 -926,20 +925,6 @@@ config CALGARY_IOMMU_ENABLED_BY_DEFAUL
          Calgary anyway, pass 'iommu=calgary' on the kernel command line.
          If unsure, say Y.
  
 -# need this always selected by IOMMU for the VIA workaround
 -config SWIOTLB
 -      def_bool y if X86_64
 -      ---help---
 -        Support for software bounce buffers used on x86-64 systems
 -        which don't have a hardware IOMMU. Using this PCI devices
 -        which can only access 32-bits of memory can be used on systems
 -        with more than 3 GB of memory.
 -        If unsure, say Y.
 -
 -config IOMMU_HELPER
 -      def_bool y
 -      depends on CALGARY_IOMMU || GART_IOMMU || SWIOTLB || AMD_IOMMU
 -
  config MAXSMP
        bool "Enable Maximum number of SMP Processors and NUMA Nodes"
        depends on X86_64 && SMP && DEBUG_KERNEL
@@@ -1443,7 -1461,6 +1446,7 @@@ config HIGHME
  config X86_PAE
        bool "PAE (Physical Address Extension) Support"
        depends on X86_32 && !HIGHMEM4G
 +      select PHYS_ADDR_T_64BIT
        select SWIOTLB
        ---help---
          PAE is required for NX support, and furthermore enables
@@@ -1471,6 -1488,14 +1474,6 @@@ config X86_5LEVE
  
          Say N if unsure.
  
 -config ARCH_PHYS_ADDR_T_64BIT
 -      def_bool y
 -      depends on X86_64 || X86_PAE
 -
 -config ARCH_DMA_ADDR_T_64BIT
 -      def_bool y
 -      depends on X86_64 || HIGHMEM64G
 -
  config X86_DIRECT_GBPAGES
        def_bool y
        depends on X86_64 && !DEBUG_PAGEALLOC
@@@ -1486,6 -1511,7 +1489,7 @@@ config ARCH_HAS_MEM_ENCRYP
  config AMD_MEM_ENCRYPT
        bool "AMD Secure Memory Encryption (SME) support"
        depends on X86_64 && CPU_SUP_AMD
+       select DYNAMIC_PHYSICAL_MASK
        ---help---
          Say yes to enable support for the encryption of system memory.
          This requires an AMD processor that supports Secure Memory
index 3c5385f9a88fc1e78729647566d819abbd210b42,c750112cb416dfdfb06d65ee1d0f696ac298ca02..0fdcd21dadbd6422bf40f5cbb2361c08c5fafc14
@@@ -216,11 -216,11 +216,11 @@@ static inline pgd_t pti_set_user_pgd(pg
  }
  #endif
  
- static inline void native_set_p4d(p4d_t *p4dp, p4d_t p4d)
+ static __always_inline void native_set_p4d(p4d_t *p4dp, p4d_t p4d)
  {
        pgd_t pgd;
  
 -      if (pgtable_l5_enabled || !IS_ENABLED(CONFIG_PAGE_TABLE_ISOLATION)) {
 +      if (pgtable_l5_enabled() || !IS_ENABLED(CONFIG_PAGE_TABLE_ISOLATION)) {
                *p4dp = p4d;
                return;
        }
        *p4dp = native_make_p4d(native_pgd_val(pgd));
  }
  
- static inline void native_p4d_clear(p4d_t *p4d)
+ static __always_inline void native_p4d_clear(p4d_t *p4d)
  {
        native_set_p4d(p4d, native_make_p4d(0));
  }
index 2d27236c16a38e824aebd9538ad70e014f490742,db98e3ab3295266cb98c354afaae2a2fc494427c..b85a7c54c6a13b51f27b26f13a2dd52f148547a7
@@@ -170,7 -170,7 +170,7 @@@ struct x86_cpuinit_ops 
        void (*fixup_cpu_id)(struct cpuinfo_x86 *c, int node);
  };
  
 -struct timespec;
 +struct timespec64;
  
  /**
   * struct x86_legacy_devices - legacy x86 devices
@@@ -264,8 -264,8 +264,8 @@@ struct x86_hyper_runtime 
  struct x86_platform_ops {
        unsigned long (*calibrate_cpu)(void);
        unsigned long (*calibrate_tsc)(void);
 -      void (*get_wallclock)(struct timespec *ts);
 -      int (*set_wallclock)(const struct timespec *ts);
 +      void (*get_wallclock)(struct timespec64 *ts);
 +      int (*set_wallclock)(const struct timespec64 *ts);
        void (*iommu_shutdown)(void);
        bool (*is_untracked_pat_range)(u64 start, u64 end);
        void (*nmi_init)(void);
@@@ -301,5 -301,6 +301,6 @@@ extern struct x86_apic_ops x86_apic_ops
  extern void x86_early_init_platform_quirks(void);
  extern void x86_init_noop(void);
  extern void x86_init_uint_noop(unsigned int unused);
+ extern bool x86_pnpbios_disabled(void);
  
  #endif
index 24bfa63e86cf8cd3ca790ef46a9518d282dab009,316a8875bd9061207a22eb9de0658a03249a131d..ec4754f81cbdcdf4971cafe73698500360da3934
@@@ -33,8 -33,8 +33,8 @@@
  #include <asm/intel_rdt_sched.h>
  #include "intel_rdt.h"
  
 -#define MAX_MBA_BW    100u
  #define MBA_IS_LINEAR 0x4
 +#define MBA_MAX_MBPS  U32_MAX
  
  /* Mutex to protect rdtgroup access. */
  DEFINE_MUTEX(rdtgroup_mutex);
@@@ -178,7 -178,7 +178,7 @@@ struct rdt_resource rdt_resources_all[
                .msr_update             = mba_wrmsr,
                .cache_level            = 3,
                .parse_ctrlval          = parse_bw,
 -              .format_str             = "%d=%*d",
 +              .format_str             = "%d=%*u",
                .fflags                 = RFTYPE_RES_MB,
        },
  };
@@@ -230,14 -230,6 +230,14 @@@ static inline void cache_alloc_hsw_prob
        rdt_alloc_capable = true;
  }
  
 +bool is_mba_sc(struct rdt_resource *r)
 +{
 +      if (!r)
 +              return rdt_resources_all[RDT_RESOURCE_MBA].membw.mba_sc;
 +
 +      return r->membw.mba_sc;
 +}
 +
  /*
   * rdt_get_mb_table() - get a mapping of bandwidth(b/w) percentage values
   * exposed to user interface and the h/w understandable delay values.
@@@ -349,7 -341,7 +349,7 @@@ static int get_cache_id(int cpu, int le
   * that can be written to QOS_MSRs.
   * There are currently no SKUs which support non linear delay values.
   */
 -static u32 delay_bw_map(unsigned long bw, struct rdt_resource *r)
 +u32 delay_bw_map(unsigned long bw, struct rdt_resource *r)
  {
        if (r->membw.delay_linear)
                return MAX_MBA_BW - bw;
@@@ -439,40 -431,25 +439,40 @@@ struct rdt_domain *rdt_find_domain(stru
        return NULL;
  }
  
 +void setup_default_ctrlval(struct rdt_resource *r, u32 *dc, u32 *dm)
 +{
 +      int i;
 +
 +      /*
 +       * Initialize the Control MSRs to having no control.
 +       * For Cache Allocation: Set all bits in cbm
 +       * For Memory Allocation: Set b/w requested to 100%
 +       * and the bandwidth in MBps to U32_MAX
 +       */
 +      for (i = 0; i < r->num_closid; i++, dc++, dm++) {
 +              *dc = r->default_ctrl;
 +              *dm = MBA_MAX_MBPS;
 +      }
 +}
 +
  static int domain_setup_ctrlval(struct rdt_resource *r, struct rdt_domain *d)
  {
        struct msr_param m;
 -      u32 *dc;
 -      int i;
 +      u32 *dc, *dm;
  
        dc = kmalloc_array(r->num_closid, sizeof(*d->ctrl_val), GFP_KERNEL);
        if (!dc)
                return -ENOMEM;
  
 -      d->ctrl_val = dc;
 +      dm = kmalloc_array(r->num_closid, sizeof(*d->mbps_val), GFP_KERNEL);
 +      if (!dm) {
 +              kfree(dc);
 +              return -ENOMEM;
 +      }
  
 -      /*
 -       * Initialize the Control MSRs to having no control.
 -       * For Cache Allocation: Set all bits in cbm
 -       * For Memory Allocation: Set b/w requested to 100
 -       */
 -      for (i = 0; i < r->num_closid; i++, dc++)
 -              *dc = r->default_ctrl;
 +      d->ctrl_val = dc;
 +      d->mbps_val = dm;
 +      setup_default_ctrlval(r, dc, dm);
  
        m.low = 0;
        m.high = r->num_closid;
@@@ -611,7 -588,6 +611,7 @@@ static void domain_remove_cpu(int cpu, 
                }
  
                kfree(d->ctrl_val);
 +              kfree(d->mbps_val);
                kfree(d->rmid_busy_llc);
                kfree(d->mbm_total);
                kfree(d->mbm_local);
@@@ -845,6 -821,8 +845,8 @@@ static __init void rdt_quirks(void
        case INTEL_FAM6_SKYLAKE_X:
                if (boot_cpu_data.x86_stepping <= 4)
                        set_rdt_options("!cmt,!mbmtotal,!mbmlocal,!l3cat");
+               else
+                       set_rdt_options("!l3cat");
        }
  }
  
diff --combined arch/x86/mm/pgtable.c
index 938dbcd46b97b2827400e2f71813f50bb26622d4,3ca59cf7a7f9406090e68366e8944c85ed506ff5..47b5951e592bec3edcea33e662c2965ec80e3572
@@@ -8,6 -8,11 +8,11 @@@
  #include <asm/fixmap.h>
  #include <asm/mtrr.h>
  
+ #ifdef CONFIG_DYNAMIC_PHYSICAL_MASK
+ phys_addr_t physical_mask __ro_after_init = (1ULL << __PHYSICAL_MASK_SHIFT) - 1;
+ EXPORT_SYMBOL(physical_mask);
+ #endif
  #define PGALLOC_GFP (GFP_KERNEL_ACCOUNT | __GFP_ZERO)
  
  #ifdef CONFIG_HIGHPTE
@@@ -114,12 -119,13 +119,12 @@@ static inline void pgd_list_del(pgd_t *
  
  static void pgd_set_mm(pgd_t *pgd, struct mm_struct *mm)
  {
 -      BUILD_BUG_ON(sizeof(virt_to_page(pgd)->index) < sizeof(mm));
 -      virt_to_page(pgd)->index = (pgoff_t)mm;
 +      virt_to_page(pgd)->pt_mm = mm;
  }
  
  struct mm_struct *pgd_page_get_mm(struct page *page)
  {
 -      return (struct mm_struct *)page->index;
 +      return page->pt_mm;
  }
  
  static void pgd_ctor(struct mm_struct *mm, pgd_t *pgd)
index 1912e9106fbe0a9f9d7180ed82d24da9345c0abc,b0b30a568db71180ad03a129f54ca14d9338528f..0cea80be288889ea55ce63e8554cd062097e2a32
@@@ -354,9 -354,6 +354,9 @@@ static bool pci_iommuv2_capable(struct 
        };
        int i, pos;
  
 +      if (pci_ats_disabled())
 +              return false;
 +
        for (i = 0; i < 3; ++i) {
                pos = pci_find_ext_capability(pdev, caps[i]);
                if (pos == 0)
@@@ -547,7 -544,7 +547,7 @@@ static void amd_iommu_report_page_fault
  static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
  {
        struct device *dev = iommu->iommu.dev;
 -      int type, devid, domid, flags;
 +      int type, devid, pasid, flags, tag;
        volatile u32 *event = __evt;
        int count = 0;
        u64 address;
  retry:
        type    = (event[1] >> EVENT_TYPE_SHIFT)  & EVENT_TYPE_MASK;
        devid   = (event[0] >> EVENT_DEVID_SHIFT) & EVENT_DEVID_MASK;
 -      domid   = (event[1] >> EVENT_DOMID_SHIFT) & EVENT_DOMID_MASK;
 +      pasid   = PPR_PASID(*(u64 *)&event[0]);
        flags   = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK;
        address = (u64)(((u64)event[3]) << 32) | event[2];
  
        }
  
        if (type == EVENT_TYPE_IO_FAULT) {
 -              amd_iommu_report_page_fault(devid, domid, address, flags);
 +              amd_iommu_report_page_fault(devid, pasid, address, flags);
                return;
        } else {
                dev_err(dev, "AMD-Vi: Event logged [");
  
        switch (type) {
        case EVENT_TYPE_ILL_DEV:
 -              dev_err(dev, "ILLEGAL_DEV_TABLE_ENTRY device=%02x:%02x.%x "
 -                      "address=0x%016llx flags=0x%04x]\n",
 +              dev_err(dev, "ILLEGAL_DEV_TABLE_ENTRY device=%02x:%02x.%x pasid=0x%05x address=0x%016llx flags=0x%04x]\n",
                        PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
 -                      address, flags);
 +                      pasid, address, flags);
                dump_dte_entry(devid);
                break;
        case EVENT_TYPE_DEV_TAB_ERR:
                        address, flags);
                break;
        case EVENT_TYPE_PAGE_TAB_ERR:
 -              dev_err(dev, "PAGE_TAB_HARDWARE_ERROR device=%02x:%02x.%x "
 -                      "domain=0x%04x address=0x%016llx flags=0x%04x]\n",
 +              dev_err(dev, "PAGE_TAB_HARDWARE_ERROR 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);
 +                      pasid, address, flags);
                break;
        case EVENT_TYPE_ILL_CMD:
                dev_err(dev, "ILLEGAL_COMMAND_ERROR address=0x%016llx]\n", address);
                dump_command(address);
                break;
        case EVENT_TYPE_CMD_HARD_ERR:
 -              dev_err(dev, "COMMAND_HARDWARE_ERROR address=0x%016llx "
 -                      "flags=0x%04x]\n", address, flags);
 +              dev_err(dev, "COMMAND_HARDWARE_ERROR address=0x%016llx flags=0x%04x]\n",
 +                      address, flags);
                break;
        case EVENT_TYPE_IOTLB_INV_TO:
 -              dev_err(dev, "IOTLB_INV_TIMEOUT device=%02x:%02x.%x "
 -                      "address=0x%016llx]\n",
 +              dev_err(dev, "IOTLB_INV_TIMEOUT device=%02x:%02x.%x address=0x%016llx]\n",
                        PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
                        address);
                break;
        case EVENT_TYPE_INV_DEV_REQ:
 -              dev_err(dev, "INVALID_DEVICE_REQUEST device=%02x:%02x.%x "
 -                      "address=0x%016llx flags=0x%04x]\n",
 +              dev_err(dev, "INVALID_DEVICE_REQUEST device=%02x:%02x.%x pasid=0x%05x address=0x%016llx flags=0x%04x]\n",
                        PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
 -                      address, flags);
 +                      pasid, address, flags);
 +              break;
 +      case EVENT_TYPE_INV_PPR_REQ:
 +              pasid = ((event[0] >> 16) & 0xFFFF)
 +                      | ((event[1] << 6) & 0xF0000);
 +              tag = event[1] & 0x03FF;
 +              dev_err(dev, "INVALID_PPR_REQUEST device=%02x:%02x.%x pasid=0x%05x address=0x%016llx flags=0x%04x]\n",
 +                      PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
 +                      pasid, address, flags);
                break;
        default:
 -              dev_err(dev, KERN_ERR "UNKNOWN event[0]=0x%08x event[1]=0x%08x "
 -                      "event[2]=0x%08x event[3]=0x%08x\n",
 +              dev_err(dev, "UNKNOWN event[0]=0x%08x event[1]=0x%08x event[2]=0x%08x event[3]=0x%08x\n",
                        event[0], event[1], event[2], event[3]);
        }
  
@@@ -1917,6 -1911,15 +1917,6 @@@ static void do_detach(struct iommu_dev_
        struct amd_iommu *iommu;
        u16 alias;
  
 -      /*
 -       * First check if the device is still attached. It might already
 -       * be detached from its domain because the generic
 -       * iommu_detach_group code detached it and we try again here in
 -       * our alias handling.
 -       */
 -      if (!dev_data->domain)
 -              return;
 -
        iommu = amd_iommu_rlookup_table[dev_data->devid];
        alias = dev_data->alias;
  
  }
  
  /*
 - * If a device is not yet associated with a domain, this function does
 - * assigns it visible for the hardware
 + * If a device is not yet associated with a domain, this function makes the
 + * device visible in the domain
   */
  static int __attach_device(struct iommu_dev_data *dev_data,
                           struct protection_domain *domain)
@@@ -2058,8 -2061,8 +2058,8 @@@ static bool pci_pri_tlp_required(struc
  }
  
  /*
 - * If a device is not yet associated with a domain, this function
 - * assigns it visible for the hardware
 + * If a device is not yet associated with a domain, this function makes the
 + * device visible in the domain
   */
  static int attach_device(struct device *dev,
                         struct protection_domain *domain)
@@@ -2121,6 -2124,9 +2121,6 @@@ static void __detach_device(struct iomm
         */
        WARN_ON(!irqs_disabled());
  
 -      if (WARN_ON(!dev_data->domain))
 -              return;
 -
        domain = dev_data->domain;
  
        spin_lock(&domain->lock);
@@@ -2142,15 -2148,6 +2142,15 @@@ static void detach_device(struct devic
        dev_data = get_dev_data(dev);
        domain   = dev_data->domain;
  
 +      /*
 +       * First check if the device is still attached. It might already
 +       * be detached from its domain because the generic
 +       * iommu_detach_group code detached it and we try again here in
 +       * our alias handling.
 +       */
 +      if (WARN_ON(!dev_data->domain))
 +              return;
 +
        /* lock device table */
        spin_lock_irqsave(&amd_iommu_devtable_lock, flags);
        __detach_device(dev_data);
@@@ -2796,7 -2793,6 +2796,7 @@@ static void cleanup_domain(struct prote
        while (!list_empty(&domain->dev_list)) {
                entry = list_first_entry(&domain->dev_list,
                                         struct iommu_dev_data, list);
 +              BUG_ON(!entry->domain);
                __detach_device(entry);
        }
  
@@@ -3527,11 -3523,9 +3527,11 @@@ int amd_iommu_device_info(struct pci_de
  
        memset(info, 0, sizeof(*info));
  
 -      pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS);
 -      if (pos)
 -              info->flags |= AMD_IOMMU_DEVICE_FLAG_ATS_SUP;
 +      if (!pci_ats_disabled()) {
 +              pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS);
 +              if (pos)
 +                      info->flags |= AMD_IOMMU_DEVICE_FLAG_ATS_SUP;
 +      }
  
        pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI);
        if (pos)
@@@ -4385,7 -4379,7 +4385,7 @@@ static void ir_compose_msi_msg(struct i
  
  static struct irq_chip amd_ir_chip = {
        .name                   = "AMD-IR",
-       .irq_ack                = ir_ack_apic_edge,
+       .irq_ack                = apic_ack_irq,
        .irq_set_affinity       = amd_ir_set_affinity,
        .irq_set_vcpu_affinity  = amd_ir_set_vcpu_affinity,
        .irq_compose_msi_msg    = ir_compose_msi_msg,
diff --combined include/linux/irq.h
index b2067083aa9436ea3bc9f3a62bd6d1ae980627f7,4e66378f290b5767cdd2516fea5c6ae79cf901ce..4bd2f34947f4a7647a485fe2e8092c1fd055f630
@@@ -512,7 -512,6 +512,7 @@@ enum 
        IRQCHIP_SKIP_SET_WAKE           = (1 <<  4),
        IRQCHIP_ONESHOT_SAFE            = (1 <<  5),
        IRQCHIP_EOI_THREADED            = (1 <<  6),
 +      IRQCHIP_SUPPORTS_LEVEL_MSI      = (1 <<  7),
  };
  
  #include <linux/irqdesc.h>
@@@ -552,7 -551,12 +552,12 @@@ extern int irq_affinity_online_cpu(unsi
  #endif
  
  #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_PENDING_IRQ)
- void irq_move_irq(struct irq_data *data);
+ void __irq_move_irq(struct irq_data *data);
+ static inline void irq_move_irq(struct irq_data *data)
+ {
+       if (unlikely(irqd_is_setaffinity_pending(data)))
+               __irq_move_irq(data);
+ }
  void irq_move_masked_irq(struct irq_data *data);
  void irq_force_complete_move(struct irq_desc *desc);
  #else
diff --combined kernel/irq/manage.c
index 4c2ef8084e326a00699a4af4e978aba9e5c803b6,facfecfc543cee6cdc39f9379e9ad1f3a8da73be..daeabd791d5896a366d7ba7b386dde76bfbc0a73
@@@ -24,7 -24,6 +24,7 @@@
  
  #ifdef CONFIG_IRQ_FORCED_THREADING
  __read_mostly bool force_irqthreads;
 +EXPORT_SYMBOL_GPL(force_irqthreads);
  
  static int __init setup_forced_irqthreads(char *arg)
  {
@@@ -205,6 -204,39 +205,39 @@@ int irq_do_set_affinity(struct irq_dat
        return ret;
  }
  
+ #ifdef CONFIG_GENERIC_PENDING_IRQ
+ static inline int irq_set_affinity_pending(struct irq_data *data,
+                                          const struct cpumask *dest)
+ {
+       struct irq_desc *desc = irq_data_to_desc(data);
+       irqd_set_move_pending(data);
+       irq_copy_pending(desc, dest);
+       return 0;
+ }
+ #else
+ static inline int irq_set_affinity_pending(struct irq_data *data,
+                                          const struct cpumask *dest)
+ {
+       return -EBUSY;
+ }
+ #endif
+ static int irq_try_set_affinity(struct irq_data *data,
+                               const struct cpumask *dest, bool force)
+ {
+       int ret = irq_do_set_affinity(data, dest, force);
+       /*
+        * In case that the underlying vector management is busy and the
+        * architecture supports the generic pending mechanism then utilize
+        * this to avoid returning an error to user space.
+        */
+       if (ret == -EBUSY && !force)
+               ret = irq_set_affinity_pending(data, dest);
+       return ret;
+ }
  int irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask,
                            bool force)
  {
        if (!chip || !chip->irq_set_affinity)
                return -EINVAL;
  
-       if (irq_can_move_pcntxt(data)) {
-               ret = irq_do_set_affinity(data, mask, force);
+       if (irq_can_move_pcntxt(data) && !irqd_is_setaffinity_pending(data)) {
+               ret = irq_try_set_affinity(data, mask, force);
        } else {
                irqd_set_move_pending(data);
                irq_copy_pending(desc, mask);
This page took 0.11071 seconds and 4 git commands to generate.