diff options
| -rw-r--r-- | arch/x86/include/asm/irq_remapping.h | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/early-quirks.c | 20 | ||||
| -rw-r--r-- | drivers/iommu/intel_irq_remapping.c | 10 | ||||
| -rw-r--r-- | drivers/iommu/irq_remapping.c | 6 | ||||
| -rw-r--r-- | drivers/iommu/irq_remapping.h | 2 | 
5 files changed, 40 insertions, 0 deletions
diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h index 95fd3527f63..aca6aa2088b 100644 --- a/arch/x86/include/asm/irq_remapping.h +++ b/arch/x86/include/asm/irq_remapping.h @@ -28,6 +28,7 @@  extern void setup_irq_remapping_ops(void);  extern int irq_remapping_supported(void); +extern void set_irq_remapping_broken(void);  extern int irq_remapping_prepare(void);  extern int irq_remapping_enable(void);  extern void irq_remapping_disable(void); @@ -54,6 +55,7 @@ void irq_remap_modify_chip_defaults(struct irq_chip *chip);  static inline void setup_irq_remapping_ops(void) { }  static inline int irq_remapping_supported(void) { return 0; } +static inline void set_irq_remapping_broken(void) { }  static inline int irq_remapping_prepare(void) { return -ENODEV; }  static inline int irq_remapping_enable(void) { return -ENODEV; }  static inline void irq_remapping_disable(void) { } diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index 3755ef49439..94ab6b90dd3 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -18,6 +18,7 @@  #include <asm/apic.h>  #include <asm/iommu.h>  #include <asm/gart.h> +#include <asm/irq_remapping.h>  static void __init fix_hypertransport_config(int num, int slot, int func)  { @@ -192,6 +193,21 @@ static void __init ati_bugs_contd(int num, int slot, int func)  }  #endif +static void __init intel_remapping_check(int num, int slot, int func) +{ +	u8 revision; + +	revision = read_pci_config_byte(num, slot, func, PCI_REVISION_ID); + +	/* +	 * Revision 0x13 of this chipset supports irq remapping +	 * but has an erratum that breaks its behavior, flag it as such +	 */ +	if (revision == 0x13) +		set_irq_remapping_broken(); + +} +  #define QFLAG_APPLY_ONCE 	0x1  #define QFLAG_APPLIED		0x2  #define QFLAG_DONE		(QFLAG_APPLY_ONCE|QFLAG_APPLIED) @@ -221,6 +237,10 @@ static struct chipset early_qrk[] __initdata = {  	  PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs },  	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS,  	  PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs_contd }, +	{ PCI_VENDOR_ID_INTEL, 0x3403, PCI_CLASS_BRIDGE_HOST, +	  PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check }, +	{ PCI_VENDOR_ID_INTEL, 0x3406, PCI_CLASS_BRIDGE_HOST, +	  PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check },  	{}  }; diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index f3b8f23b5d8..5b19b2d6ec2 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -524,6 +524,16 @@ static int __init intel_irq_remapping_supported(void)  	if (disable_irq_remap)  		return 0; +	if (irq_remap_broken) { +		WARN_TAINT(1, TAINT_FIRMWARE_WORKAROUND, +			   "This system BIOS has enabled interrupt remapping\n" +			   "on a chipset that contains an erratum making that\n" +			   "feature unstable.  To maintain system stability\n" +			   "interrupt remapping is being disabled.  Please\n" +			   "contact your BIOS vendor for an update\n"); +		disable_irq_remap = 1; +		return 0; +	}  	if (!dmar_ir_support())  		return 0; diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index d56f8c17c5f..3c11043bdee 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c @@ -19,6 +19,7 @@  int irq_remapping_enabled;  int disable_irq_remap; +int irq_remap_broken;  int disable_sourceid_checking;  int no_x2apic_optout; @@ -211,6 +212,11 @@ void __init setup_irq_remapping_ops(void)  #endif  } +void set_irq_remapping_broken(void) +{ +	irq_remap_broken = 1; +} +  int irq_remapping_supported(void)  {  	if (disable_irq_remap) diff --git a/drivers/iommu/irq_remapping.h b/drivers/iommu/irq_remapping.h index ecb63767040..90c4dae5a46 100644 --- a/drivers/iommu/irq_remapping.h +++ b/drivers/iommu/irq_remapping.h @@ -32,6 +32,7 @@ struct pci_dev;  struct msi_msg;  extern int disable_irq_remap; +extern int irq_remap_broken;  extern int disable_sourceid_checking;  extern int no_x2apic_optout;  extern int irq_remapping_enabled; @@ -89,6 +90,7 @@ extern struct irq_remap_ops amd_iommu_irq_ops;  #define irq_remapping_enabled 0  #define disable_irq_remap     1 +#define irq_remap_broken      0  #endif /* CONFIG_IRQ_REMAP */  |