x86/apic changes for v3.9
Subsystems (11)
Linus,
Please pull the latest x86-apic-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86-apic-for-linus
HEAD: af8d102f999a41c0189bd2cce488bac2ee88c29b x86/intel/irq_remapping: Clean up x2apic opt-out security warning mess
Main changes:
* Multiple MSI support added to the APIC, PCI and AHCI code - acked by all relevant maintainers, by Alexander Gordeev.
The advantage is that multiple AHCI ports can have multiple MSI irqs assigned, and can thus spread to multiple CPUs.
[ Drivers can make use of this new facility via the
pci_enable_msi_block_auto() method. ]
* x86 IOAPIC code from interrupt remapping cleanups from Joerg Roedel:
These patches move all interrupt remapping specific checks out of the x86 core code and replaces the respective call-sites with function pointers. As a result the interrupt remapping code is better abstraced from x86 core interrupt handling code.
* Various smaller improvements, fixes and cleanups.
out-of-topic modifications in x86-apic-for-linus:
-------------------------------------------------
drivers/ata/ahci.c # 5ca72c4: AHCI: Support multiple MSIs
drivers/ata/ahci.h # 5ca72c4: AHCI: Support multiple MSIs
drivers/ata/libahci.c # 5ca72c4: AHCI: Support multiple MSIs
drivers/iommu/amd_iommu.c # 9b1b0e4: x86, io-apic: Move CONFIG_IRQ_REM
drivers/iommu/dmar.c # 078e1ee: x86, irq: Move irq_remapping_enab
drivers/iommu/intel-iommu.c # 078e1ee: x86, irq: Move irq_remapping_enab
drivers/iommu/intel_irq_remapping.c# af8d102: x86/intel/irq_remapping: Clean up
# 9b1b0e4: x86, io-apic: Move CONFIG_IRQ_REM
# afcc8a4: x86, io_apic: Introduce x86_io_ap
drivers/iommu/irq_remapping.c # a1bb20c: x86, irq: Move irq_remapped out o
# da16532: x86, io_apic: Introduce eoi_ioapi
# 7601384: x86, msi: Introduce x86_msi.compo
# 2976fd8: x86, irq: Introduce setup_remappe
# 11b4a1c: x86, irq: Move irq_remapped() che
# 9b1b0e4: x86, io-apic: Move CONFIG_IRQ_REM
# 6a9f5de: x86, io_apic: Move irq_remapping_
# a6a25dd: x86, io_apic: Convert setup_ioapi
# 373dd7a: x86, io_apic: Introduce set_affin
# 5afba62: x86, msi: Use IRQ remapping speci
# 71054d8: x86, hpet: Introduce x86_msi_ops.
# 1c4248c: x86, io_apic: Introduce x86_io_ap
# 70733e0: x86, apic: Move irq_remapping_ena
drivers/iommu/irq_remapping.h # 078e1ee: x86, irq: Move irq_remapping_enab
drivers/pci/msi.c # 08261d8: PCI/MSI: Enable multiple MSIs wit
include/linux/irq.h # 5afba62: x86, msi: Use IRQ remapping speci
# 51906e7: x86/MSI: Support multiple MSIs ininclude/linux/pci.h # 08261d8: PCI/MSI: Enable multiple MSIs witkernel/irq/chip.c # 51906e7: x86/MSI: Support multiple MSIs in
Thanks,
Ingo
------------------>
Alexander Gordeev (3):
x86/MSI: Support multiple MSIs in presense of IRQ remapping PCI/MSI: Enable multiple MSIs with pci_enable_msi_block_auto()
AHCI: Support multiple MSIs
Alok N Kataria (2):
x86/apic: Allow x2apic without IR on VMware platform x86, kvm: Fix intialization warnings in kvm.c
Andy Lutomirski (1):
x86/intel/irq_remapping: Clean up x2apic opt-out security warning mess
Dave Jones (1):
x86/apic: Remove noisy zero-mask warning from default_send_IPI_mask_logical()
Joerg Roedel (19):
x86, apic: Move irq_remapping_enabled checks into IRQ-remapping code x86, apic: Mask IO-APIC and PIC unconditionally on LAPIC resume x86, io_apic: Introduce x86_io_apic_ops.disable()
x86, io_apic: Introduce x86_io_apic_ops.print_entries for debugging x86, hpet: Introduce x86_msi_ops.setup_hpet_msi
x86, msi: Use IRQ remapping specific setup_msi_irqs routine x86, io_apic: Introduce set_affinity function pointer
x86, io_apic: Convert setup_ioapic_entry to function pointer x86, io_apic: Move irq_remapping_enabled checks out of check_timer() x86, io_apic: Remove irq_remapping_enabled check in setup_timer_IRQ0_pin x86, irq: Move irq_remapping_enabled declaration to iommu code x86, irq: Add data structure to keep AMD specific irq remapping information x86, io-apic: Move CONFIG_IRQ_REMAP code out of x86 core
x86, io-apic: Remove !irq_remapped() check from __target_IO_APIC_irq() x86, irq: Move irq_remapped() check into free_remapped_irq x86, irq: Introduce setup_remapped_irq()
x86, msi: Introduce x86_msi.compose_msi_msg call-back
x86, io_apic: Introduce eoi_ioapic_pin call-back
x86, irq: Move irq_remapped out of x86 core code
Documentation/PCI/MSI-HOWTO.txt | 37 ++- arch/x86/include/asm/hpet.h | 5 +- arch/x86/include/asm/hw_irq.h | 13 +- arch/x86/include/asm/hypervisor.h | 13 +- arch/x86/include/asm/io_apic.h | 28 +++ arch/x86/include/asm/irq_remapping.h | 40 ++- arch/x86/include/asm/kvm_para.h | 8 +- arch/x86/include/asm/pci.h | 3 + arch/x86/include/asm/x86_init.h | 27 ++- arch/x86/kernel/apic/apic.c | 28 +-- arch/x86/kernel/apic/io_apic.c | 457 +++++++++++++++-------------------- arch/x86/kernel/apic/ipi.c | 2 +- arch/x86/kernel/cpu/hypervisor.c | 7 + arch/x86/kernel/cpu/vmware.c | 13 + arch/x86/kernel/hpet.c | 2 +- arch/x86/kernel/kvm.c | 1 + arch/x86/kernel/x86_init.c | 24 +- arch/x86/xen/enlighten.c | 1 + drivers/ata/ahci.c | 93 ++++++- drivers/ata/ahci.h | 6 + drivers/ata/libahci.c | 118 ++++++++- drivers/iommu/amd_iommu.c | 8 +- drivers/iommu/dmar.c | 2 + drivers/iommu/intel-iommu.c | 2 + drivers/iommu/intel_irq_remapping.c | 48 +++- drivers/iommu/irq_remapping.c | 231 +++++++++++++++++- drivers/iommu/irq_remapping.h | 1 + drivers/pci/msi.c | 26 ++ include/linux/irq.h | 8 + include/linux/pci.h | 7 + kernel/irq/chip.c | 30 ++- 31 files changed, 918 insertions(+), 371 deletions(-)
Documentation/PCI/MSI-HOWTO.txt +32 -5
@@ -127,15 +127,42 @@ on the number of vectors that can be allocated; pci_enable_msi_block() returns as soon as it finds any constraint that doesn't allow the call to succeed. -4.2.3 pci_disable_msi +4.2.3 pci_enable_msi_block_auto + +int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *count) + +This variation on pci_enable_msi() call allows a device driver to request +the maximum possible number of MSIs. The MSI specification only allows +interrupts to be allocated in powers of two, up to a maximum of 2^5 (32). + +If this function returns a positive number, it indicates that it has +succeeded and the returned value is the number of allocated interrupts. In +this case, the function enables MSI on this device and updates dev->irq to +be the lowest of the new interrupts assigned to it. The other interrupts +assigned to the device are in the range dev->irq to dev->irq + returned +value - 1. + +If this function returns a negative number, it indicates an error and +the driver should not attempt to request any more MSI interrupts for +this device. + +If the device driver needs to know the number of interrupts the device +supports it can pass the pointer count where that number is stored. The +device driver must decide what action to take if pci_enable_msi_block_auto() +succeeds, but returns a value less than the number of interrupts supported. +If the device driver does not need to know the number of interrupts +supported, it can set the pointer count to NULL. + +4.2.4 pci_disable_msi void pci_disable_msi(struct pci_dev *dev) This function should be used to undo the effect of pci_enable_msi() or -pci_enable_msi_block(). Calling it restores dev->irq to the pin-based -interrupt number and frees the previously allocated message signaled -interrupt(s). The interrupt may subsequently be assigned to another -device, so drivers should not cache the value of dev->irq. +pci_enable_msi_block() or pci_enable_msi_block_auto(). Calling it restores +dev->irq to the pin-based interrupt number and frees the previously +allocated message signaled interrupt(s). The interrupt may subsequently be +assigned to another device, so drivers should not cache the value of +dev->irq. Before calling this function, a device driver must always call free_irq() on any interrupt for which it previously called request_irq().
arch/x86/include/asm/hpet.h +3 -2
@@ -80,9 +80,9 @@ extern void hpet_msi_write(struct hpet_dev *hdev, struct msi_msg *msg);extern void hpet_msi_read (struct hpet_dev *hdev,struct msi_msg *msg);#ifdef CONFIG_PCI_MSI -extern int arch_setup_hpet_msi (unsigned int irq,unsigned int id); +extern int default_setup_hpet_msi (unsigned int irq,unsigned int id);#else -static inline int arch_setup_hpet_msi (unsigned int irq,unsigned int id) +static inline int default_setup_hpet_msi (unsigned int irq,unsigned int id) {return -EINVAL ; }
@@ -111,6 +111,7 @@ extern void hpet_unregister_irq_handler(rtc_irq_handler handler);static inline int hpet_enable (void ) {return 0 ; }static inline int is_hpet_enabled (void ) {return 0 ; }#define hpet_readl (a) 0 +#define default_setup_hpet_msi NULL#endif #endif /* _ASM_X86_HPET_H */
arch/x86/include/asm/hw_irq.h +12 -1
@@ -101,6 +101,7 @@ static inline void set_io_apic_irq_attr(struct io_apic_irq_attr *irq_attr, irq_attr->polarity = polarity; } +/* Intel specific interrupt remapping information */ struct irq_2_iommu {struct intel_iommu *iommu;u16 irte_index;
@@ -108,6 +109,12 @@ struct irq_2_iommu {u8 irte_mask; }; +/* AMD specific interrupt remapping information */ +struct irq_2_irte { +u16 devid;/* Device ID for IRTE table */ +u16 index;/* Index into IRTE table*/ +}; +/* * This is performance-critical, we want to do it O(1) *
@@ -120,7 +127,11 @@ struct irq_cfg {u8 vector; u8 move_in_progress : 1;#ifdef CONFIG_IRQ_REMAP -struct irq_2_iommu irq_2_iommu; + u8 remapped : 1; +union { +struct irq_2_iommu irq_2_iommu; +struct irq_2_irte irq_2_irte; + };#endif };
arch/x86/include/asm/hypervisor.h +4 -9
@@ -25,6 +25,7 @@extern void init_hypervisor (struct cpuinfo_x86 *c);extern void init_hypervisor_platform (void ); +extern bool hypervisor_x2apic_available (void );/* * x86 hypervisor information
@@ -41,6 +42,9 @@ struct hypervisor_x86 {/* Platform setup (run once per boot) */ void (*init_platform)(void ); + +/* X2APIC detection (run once per boot) */ +bool (*x2apic_available)(void ); };extern const struct hypervisor_x86 *x86_hyper;
@@ -51,13 +55,4 @@ extern const struct hypervisor_x86 x86_hyper_ms_hyperv;extern const struct hypervisor_x86 x86_hyper_xen_hvm;extern const struct hypervisor_x86 x86_hyper_kvm; -static inline bool hypervisor_x2apic_available (void ) -{ -if (kvm_para_available ()) -return true; -if (xen_x2apic_para_available ()) -return true; -return false; -} -#endif
arch/x86/include/asm/io_apic.h +28 -0
@@ -144,11 +144,24 @@ extern int timer_through_8259; (mp_irq_entries && !skip_ioapic_setup && io_apic_irqs)struct io_apic_irq_attr ; +struct irq_cfg ;extern int io_apic_set_pci_routing (struct device *dev,int irq,struct io_apic_irq_attr *irq_attr);void setup_IO_APIC_irq_extra (u32 gsi);extern void ioapic_insert_resources (void ); +extern int native_setup_ioapic_entry (int ,struct IO_APIC_route_entry *, +unsigned int ,int , +struct io_apic_irq_attr *); +extern int native_setup_ioapic_entry (int ,struct IO_APIC_route_entry *, +unsigned int ,int , +struct io_apic_irq_attr *); +extern void eoi_ioapic_irq (unsigned int irq,struct irq_cfg *cfg); + +extern void native_compose_msi_msg (struct pci_dev *pdev, +unsigned int irq,unsigned int dest, +struct msi_msg *msg,u8 hpet_id); +extern void native_eoi_ioapic_pin (int apic,int pin,int vector);int io_apic_setup_irq_pin_once (unsigned int irq,int node,struct io_apic_irq_attr *attr);extern int save_ioapic_entries (void );
@@ -179,6 +192,12 @@ extern void __init native_io_apic_init_mappings(void);extern unsigned int native_io_apic_read (unsigned int apic,unsigned int reg);extern void native_io_apic_write (unsigned int apic,unsigned int reg,unsigned int val);extern void native_io_apic_modify (unsigned int apic,unsigned int reg,unsigned int val); +extern void native_disable_io_apic (void ); +extern void native_io_apic_print_entries (unsigned int apic,unsigned int nr_entries); +extern void intel_ir_io_apic_print_entries (unsigned int apic,unsigned int nr_entries); +extern int native_ioapic_set_affinity (struct irq_data *, +const struct cpumask *, +bool );static inline unsigned int io_apic_read (unsigned int apic,unsigned int reg) {
@@ -193,6 +212,9 @@ static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned { x86_io_apic_ops.modify (apic, reg, value); } + +extern void io_apic_eoi (unsigned int apic,unsigned int vector); +#else /* !CONFIG_X86_IO_APIC */ #define io_apic_assign_pci_irqs 0
@@ -223,6 +245,12 @@ static inline void disable_ioapic_support(void) { }#define native_io_apic_read NULL#define native_io_apic_write NULL#define native_io_apic_modify NULL +#define native_disable_io_apic NULL +#define native_io_apic_print_entries NULL +#define native_ioapic_set_affinity NULL +#define native_setup_ioapic_entry NULL +#define native_compose_msi_msg NULL +#define native_eoi_ioapic_pin NULL#endif #endif /* _ASM_X86_IO_APIC_H */
arch/x86/include/asm/irq_remapping.h +18 -22
@@ -26,8 +26,6 @@#ifdef CONFIG_IRQ_REMAP -extern int irq_remapping_enabled; -extern void setup_irq_remapping_ops (void );extern int irq_remapping_supported (void );extern int irq_remapping_prepare (void );
@@ -40,21 +38,19 @@ extern int setup_ioapic_remapped_entry(int irq,unsigned int destination, int vector, struct io_apic_irq_attr *attr); -extern int set_remapped_irq_affinity (struct irq_data *data, -const struct cpumask *mask, -bool force);extern void free_remapped_irq (int irq);extern void compose_remapped_msi_msg (struct pci_dev *pdev,unsigned int irq,unsigned int dest,struct msi_msg *msg,u8 hpet_id); -extern int msi_alloc_remapped_irq (struct pci_dev *pdev,int irq,int nvec); -extern int msi_setup_remapped_irq (struct pci_dev *pdev,unsigned int irq, -int index,int sub_handle);extern int setup_hpet_msi_remapped (unsigned int irq,unsigned int id); +extern void panic_if_irq_remap (const char *msg); +extern bool setup_remapped_irq (int irq, +struct irq_cfg *cfg, +struct irq_chip *chip); -#else /* CONFIG_IRQ_REMAP */ +void irq_remap_modify_chip_defaults (struct irq_chip *chip); -#define irq_remapping_enabled 0 +#else /* CONFIG_IRQ_REMAP */ static inline void setup_irq_remapping_ops (void ) { }static inline int irq_remapping_supported (void ) {return 0 ; }
@@ -71,30 +67,30 @@ static inline int setup_ioapic_remapped_entry(int irq, {return -ENODEV ; } -static inline int set_remapped_irq_affinity (struct irq_data *data, -const struct cpumask *mask, -bool force) -{ -return 0 ; -}static inline void free_remapped_irq (int irq) { }static inline void compose_remapped_msi_msg (struct pci_dev *pdev,unsigned int irq,unsigned int dest,struct msi_msg *msg,u8 hpet_id) { } -static inline int msi_alloc_remapped_irq (struct pci_dev *pdev,int irq,int nvec) +static inline int setup_hpet_msi_remapped (unsigned int irq,unsigned int id) {return -ENODEV ; } -static inline int msi_setup_remapped_irq (struct pci_dev *pdev,unsigned int irq, -int index,int sub_handle) + +static inline void panic_if_irq_remap (const char *msg) +{ +} + +static inline void irq_remap_modify_chip_defaults (struct irq_chip *chip) { -return -ENODEV ; } -static inline int setup_hpet_msi_remapped (unsigned int irq,unsigned int id) + +static inline bool setup_remapped_irq (int irq, +struct irq_cfg *cfg, +struct irq_chip *chip) { -return -ENODEV ; +return false; }#endif /* CONFIG_IRQ_REMAP */
arch/x86/include/asm/kvm_para.h +4 -4
@@ -85,13 +85,13 @@ static inline long kvm_hypercall4(unsigned int nr, unsigned long p1,return ret; } -static inline int kvm_para_available (void ) +static inline bool kvm_para_available (void ) {unsigned int eax, ebx, ecx, edx;char signature[13 ];if (boot_cpu_data.cpuid_level <0 ) -return 0 ;/* So we don't blow up on old processors */ +return false;/* So we don't blow up on old processors */ if (cpu_has_hypervisor) {cpuid (KVM_CPUID_SIGNATURE , &eax, &ebx, &ecx, &edx);
@@ -101,10 +101,10 @@ static inline int kvm_para_available(void) signature[12 ] =0 ;if (strcmp (signature,"KVMKVMKVM" ) ==0 ) -return 1 ; +return true; } -return 0 ; +return false; }static inline unsigned int kvm_arch_para_features (void )
arch/x86/include/asm/pci.h +3 -0
@@ -121,9 +121,12 @@ static inline void x86_restore_msi_irqs(struct pci_dev *dev, int irq)#define arch_teardown_msi_irq x86_teardown_msi_irq#define arch_restore_msi_irqs x86_restore_msi_irqs/* implemented in arch/x86/kernel/apic/io_apic. */ +struct msi_desc ;int native_setup_msi_irqs (struct pci_dev *dev,int nvec,int type);void native_teardown_msi_irq (unsigned int irq);void native_restore_msi_irqs (struct pci_dev *dev,int irq); +int setup_msi_irq (struct pci_dev *dev,struct msi_desc *msidesc, +unsigned int irq_base,unsigned int irq_offset);/* default to the implementation in drivers/lib/msi.c */ #define HAVE_DEFAULT_MSI_TEARDOWN_IRQS #define HAVE_DEFAULT_MSI_RESTORE_IRQS
arch/x86/include/asm/x86_init.h +23 -4
@@ -181,19 +181,38 @@ struct x86_platform_ops { };struct pci_dev ; +struct msi_msg ;struct x86_msi_ops {int (*setup_msi_irqs)(struct pci_dev *dev,int nvec,int type); +void (*compose_msi_msg)(struct pci_dev *dev,unsigned int irq, +unsigned int dest,struct msi_msg *msg, +u8 hpet_id);void (*teardown_msi_irq)(unsigned int irq);void (*teardown_msi_irqs)(struct pci_dev *dev);void (*restore_msi_irqs)(struct pci_dev *dev,int irq); +int (*setup_hpet_msi)(unsigned int irq,unsigned int id); }; +struct IO_APIC_route_entry ; +struct io_apic_irq_attr ; +struct irq_data ; +struct cpumask ; +struct x86_io_apic_ops { -void (*init) (void ); -unsigned int (*read) (unsigned int apic,unsigned int reg); -void (*write) (unsigned int apic,unsigned int reg,unsigned int value); -void (*modify)(unsigned int apic,unsigned int reg,unsigned int value); +void (*init) (void ); +unsigned int (*read) (unsigned int apic,unsigned int reg); +void (*write) (unsigned int apic,unsigned int reg,unsigned int value); +void (*modify) (unsigned int apic,unsigned int reg,unsigned int value); +void (*disable)(void ); +void (*print_entries)(unsigned int apic,unsigned int nr_entries); +int (*set_affinity)(struct irq_data *data, +const struct cpumask *mask, +bool force); +int (*setup_entry)(int irq,struct IO_APIC_route_entry *entry, +unsigned int destination,int vector, +struct io_apic_irq_attr *attr); +void (*eoi_ioapic_pin)(int apic,int pin,int vector); };extern struct x86_init_ops x86_init;
arch/x86/kernel/apic/apic.c +12 -16
@@ -1477,8 +1477,7 @@ void __init bsp_end_local_APIC_setup(void)* Now that local APIC setup is completed for BP, configure the fault * handling for interrupt remapping. */ -if (irq_remapping_enabled) -irq_remap_enable_fault_handling (); +irq_remap_enable_fault_handling (); }
@@ -2251,8 +2250,7 @@ static int lapic_suspend(void)local_irq_save (flags);disable_local_APIC (); -if (irq_remapping_enabled) -irq_remapping_disable (); +irq_remapping_disable ();local_irq_restore (flags);return 0 ;
@@ -2268,16 +2266,15 @@ static void lapic_resume(void)return ;local_irq_save (flags); -if (irq_remapping_enabled) { -/* -* IO-APIC and PIC have their own resume routines. -* We just mask them here to make sure the interrupt -* subsystem is completely quiet while we enable x2apic -* and interrupt-remapping. -*/ -mask_ioapic_entries (); - legacy_pic->mask_all (); - } + +/* +* IO-APIC and PIC have their own resume routines. +* We just mask them here to make sure the interrupt +* subsystem is completely quiet while we enable x2apic +* and interrupt-remapping. +*/ +mask_ioapic_entries (); + legacy_pic->mask_all ();if (x2apic_mode)enable_x2apic ();
@@ -2320,8 +2317,7 @@ static void lapic_resume(void)apic_write (APIC_ESR ,0 );apic_read (APIC_ESR ); -if (irq_remapping_enabled) -irq_remapping_reenable (x2apic_mode); +irq_remapping_reenable (x2apic_mode);local_irq_restore (flags); }
arch/x86/kernel/apic/io_apic.c +199 -258
703 lines not on this page · raw message
arch/x86/kernel/apic/ipi.c +1 -1
@@ -106,7 +106,7 @@ void default_send_IPI_mask_logical(const struct cpumask *cpumask, int vector)unsigned long mask =cpumask_bits (cpumask)[0 ];unsigned long flags; -if (WARN_ONCE (!mask,"empty IPI mask" )) +if (!mask)return ;local_irq_save (flags);
arch/x86/kernel/cpu/hypervisor.c +7 -0
@@ -79,3 +79,10 @@ void __init init_hypervisor_platform(void)if (x86_hyper->init_platform) x86_hyper->init_platform (); } + +bool __init hypervisor_x2apic_available (void ) +{ +return x86_hyper && + x86_hyper->x2apic_available && + x86_hyper->x2apic_available (); +}
arch/x86/kernel/cpu/vmware.c +13 -0
@@ -33,6 +33,9 @@#define VMWARE_PORT_CMD_GETVERSION 10#define VMWARE_PORT_CMD_GETHZ 45 +#define VMWARE_PORT_CMD_GETVCPU_INFO 68 +#define VMWARE_PORT_CMD_LEGACY_X2APIC 3 +#define VMWARE_PORT_CMD_VCPU_RESERVED 31#define VMWARE_PORT (cmd, eax, ebx, ecx, edx) \ __asm__("inl (%%dx)" : \
@@ -125,10 +128,20 @@ static void __cpuinit vmware_set_cpu_features(struct cpuinfo_x86 *c)set_cpu_cap (c,X86_FEATURE_TSC_RELIABLE ); } +/* Checks if hypervisor supports x2apic without VT-D interrupt remapping. */ +static bool __init vmware_legacy_x2apic_available (void ) +{ +uint32_t eax, ebx, ecx, edx; +VMWARE_PORT (GETVCPU_INFO , eax, ebx, ecx, edx); +return (eax & (1 <<VMWARE_PORT_CMD_VCPU_RESERVED )) ==0 && + (eax & (1 <<VMWARE_PORT_CMD_LEGACY_X2APIC )) !=0 ; +} +const __refconst struct hypervisor_x86 x86_hyper_vmware = { .name ="VMware" , .detect = vmware_platform, .set_cpu_features = vmware_set_cpu_features, .init_platform = vmware_platform_setup, + .x2apic_available = vmware_legacy_x2apic_available, };EXPORT_SYMBOL (x86_hyper_vmware);
arch/x86/kernel/hpet.c +1 -1
@@ -478,7 +478,7 @@ static int hpet_msi_next_event(unsigned long delta,static int hpet_setup_msi_irq (unsigned int irq) { -if (arch_setup_hpet_msi (irq, hpet_blockid)) { +if (x86_msi.setup_hpet_msi (irq, hpet_blockid)) {destroy_irq (irq);return -EINVAL ; }
arch/x86/kernel/kvm.c +1 -0
@@ -505,6 +505,7 @@ static bool __init kvm_detect(void)const struct hypervisor_x86 x86_hyper_kvm__refconst = { .name ="KVM" , .detect = kvm_detect, + .x2apic_available = kvm_para_available, };EXPORT_SYMBOL_GPL (x86_hyper_kvm);
arch/x86/kernel/x86_init.c +16 -8
@@ -19,6 +19,7 @@#include <asm/time.h> #include <asm/irq.h> #include <asm/io_apic.h> +#include <asm/hpet.h> #include <asm/pat.h> #include <asm/tsc.h> #include <asm/iommu.h>
@@ -111,15 +112,22 @@ struct x86_platform_ops x86_platform = {EXPORT_SYMBOL_GPL (x86_platform);struct x86_msi_ops x86_msi = { - .setup_msi_irqs = native_setup_msi_irqs, - .teardown_msi_irq = native_teardown_msi_irq, - .teardown_msi_irqs = default_teardown_msi_irqs, - .restore_msi_irqs = default_restore_msi_irqs, + .setup_msi_irqs = native_setup_msi_irqs, + .compose_msi_msg = native_compose_msi_msg, + .teardown_msi_irq = native_teardown_msi_irq, + .teardown_msi_irqs = default_teardown_msi_irqs, + .restore_msi_irqs = default_restore_msi_irqs, + .setup_hpet_msi = default_setup_hpet_msi, };struct x86_io_apic_ops x86_io_apic_ops = { - .init = native_io_apic_init_mappings, - .read = native_io_apic_read, - .write = native_io_apic_write, - .modify = native_io_apic_modify, + .init = native_io_apic_init_mappings, + .read = native_io_apic_read, + .write = native_io_apic_write, + .modify = native_io_apic_modify, + .disable = native_disable_io_apic, + .print_entries = native_io_apic_print_entries, + .set_affinity = native_ioapic_set_affinity, + .setup_entry = native_setup_ioapic_entry, + .eoi_ioapic_pin = native_eoi_ioapic_pin, };
arch/x86/xen/enlighten.c +1 -0
@@ -1668,6 +1668,7 @@ const struct hypervisor_x86 x86_hyper_xen_hvm __refconst = { .name = "Xen HVM", .detect = xen_hvm_platform, .init_platform = xen_hvm_guest_init, + .x2apic_available = xen_x2apic_para_available, };EXPORT_SYMBOL (x86_hyper_xen_hvm);#endif
drivers/ata/ahci.c +89 -4
119 lines not on this page · raw message
drivers/ata/ahci.h +6 -0
@@ -231,6 +231,7 @@ enum {AHCI_HFLAG_DELAY_ENGINE = (1 <<15 ),/* do not start engine on port start (wait until error-handling stage) */ + AHCI_HFLAG_MULTI_MSI = (1 << 16), /* multiple PCI MSIs *//* ap->flags bits */
@@ -297,6 +298,8 @@ struct ahci_port_priv { unsigned int ncq_saw_d2h:1; unsigned int ncq_saw_dmas:1; unsigned int ncq_saw_sdb:1; +u32 intr_status;/* interrupts to handle */ +spinlock_t lock;/* protects parent ata_port */ u32 intr_mask;/* interrupts to enable */ bool fbs_supported;/* set iff FBS is supported */ bool fbs_enabled;/* set iff FBS is enabled */
@@ -359,7 +362,10 @@ void ahci_set_em_messages(struct ahci_host_priv *hpriv, struct ata_port_info *pi);int ahci_reset_em (struct ata_host *host);irqreturn_t ahci_interrupt (int irq,void *dev_instance); +irqreturn_t ahci_hw_interrupt (int irq,void *dev_instance); +irqreturn_t ahci_thread_fn (int irq,void *dev_instance);void ahci_print_info (struct ata_host *host,const char *scc_s); +int ahci_host_activate (struct ata_host *host,int irq,unsigned int n_msis);static inline void __iomem *__ahci_port_base (struct ata_host *host,unsigned int port_no)
drivers/ata/libahci.c +112 -6
143 lines not on this page · raw message
drivers/iommu/amd_iommu.c +4 -4
@@ -4017,10 +4017,10 @@ static int alloc_irq_index(struct irq_cfg *cfg, u16 devid, int count) index -= count -1 ; + cfg->remapped =1 ; irte_info = &cfg->irq_2_iommu; irte_info->sub_handle = devid; irte_info->irte_index = index; - irte_info->iommu = (void *)cfg; goto out; }
@@ -4127,9 +4127,9 @@ static int setup_ioapic_entry(int irq, struct IO_APIC_route_entry *entry, index = attr->ioapic_pin;/* Setup IRQ remapping info */ + cfg->remapped =1 ; irte_info->sub_handle = devid; irte_info->irte_index = index; - irte_info->iommu = (void *)cfg;/* Setup IRTE for IOMMU */ irte.val =0 ;
@@ -4288,9 +4288,9 @@ static int msi_setup_irq(struct pci_dev *pdev, unsigned int irq, devid =get_device_id (&pdev->dev); irte_info = &cfg->irq_2_iommu; + cfg->remapped =1 ; irte_info->sub_handle = devid; irte_info->irte_index = index + offset; - irte_info->iommu = (void *)cfg;return 0 ; }
@@ -4314,9 +4314,9 @@ static int setup_hpet_msi(unsigned int irq, unsigned int id)if (index <0 )return index; + cfg->remapped =1 ; irte_info->sub_handle = devid; irte_info->irte_index = index; - irte_info->iommu = (void *)cfg;return 0 ; }
drivers/iommu/dmar.c +2 -0
@@ -41,6 +41,8 @@#include <asm/irq_remapping.h> #include <asm/iommu_table.h> +#include "irq_remapping.h" +/* No locks are needed as DMA remapping hardware unit * list is constructed at boot time and hotplug of * these units are not supported by the architecture.
drivers/iommu/intel-iommu.c +2 -0
@@ -46,6 +46,8 @@#include <asm/cacheflush.h> #include <asm/iommu.h> +#include "irq_remapping.h" +#define ROOT_SIZE VTD_PAGE_SIZE#define CONTEXT_SIZE VTD_PAGE_SIZE
drivers/iommu/intel_irq_remapping.c +40 -8
121 lines not on this page · raw message
drivers/iommu/irq_remapping.c +221 -10
300 lines not on this page · raw message
drivers/iommu/irq_remapping.h +1 -0
@@ -34,6 +34,7 @@ struct msi_msg;extern int disable_irq_remap;extern int disable_sourceid_checking;extern int no_x2apic_optout; +extern int irq_remapping_enabled;struct irq_remap_ops {/* Check whether Interrupt Remapping is supported */
drivers/pci/msi.c +26 -0
@@ -845,6 +845,32 @@ int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec) }EXPORT_SYMBOL (pci_enable_msi_block); +int pci_enable_msi_block_auto (struct pci_dev *dev,unsigned int *maxvec) +{ +int ret, pos, nvec; +u16 msgctl; + + pos =pci_find_capability (dev,PCI_CAP_ID_MSI ); +if (!pos) +return -EINVAL ; + +pci_read_config_word (dev, pos +PCI_MSI_FLAGS , &msgctl); + ret =1 << ((msgctl &PCI_MSI_FLAGS_QMASK ) >>1 ); + +if (maxvec) + *maxvec = ret; + +do { + nvec = ret; + ret =pci_enable_msi_block (dev, nvec); + }while (ret >0 ); + +if (ret <0 ) +return ret; +return nvec; +} +EXPORT_SYMBOL (pci_enable_msi_block_auto); +void pci_msi_shutdown (struct pci_dev *dev) {struct msi_desc *desc;
include/linux/irq.h +8 -0
@@ -509,8 +509,11 @@ static inline void irq_set_percpu_devid_flags(unsigned int irq)/* Handle dynamic irq creation and destruction */ extern unsigned int create_irq_nr (unsigned int irq_want,int node); +extern unsigned int __create_irqs (unsigned int from,unsigned int count, +int node);extern int create_irq (void );extern void destroy_irq (unsigned int irq); +extern void destroy_irqs (unsigned int irq,unsigned int count);/* * Dynamic irq helper functions. Obsolete. Use irq_alloc_desc* and
@@ -528,6 +531,8 @@ extern int irq_set_handler_data(unsigned int irq, void *data);extern int irq_set_chip_data (unsigned int irq,void *data);extern int irq_set_irq_type (unsigned int irq,unsigned int type);extern int irq_set_msi_desc (unsigned int irq,struct msi_desc *entry); +extern int irq_set_msi_desc_off (unsigned int irq_base,unsigned int irq_offset, +struct msi_desc *entry);extern struct irq_data *irq_get_irq_data (unsigned int irq);static inline struct irq_chip *irq_get_chip (unsigned int irq)
@@ -590,6 +595,9 @@ int __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,#define irq_alloc_desc_from (from, node) \ irq_alloc_descs(-1, from, 1, node) +#define irq_alloc_descs_from (from, cnt, node) \ + irq_alloc_descs(-1, from, cnt, node) +void irq_free_descs (unsigned int irq,unsigned int cnt);int irq_reserve_irqs (unsigned int from,unsigned int cnt);
include/linux/pci.h +7 -0
@@ -1101,6 +1101,12 @@ static inline int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec)return -1 ; } +static inline int +pci_enable_msi_block_auto (struct pci_dev *dev,unsigned int *maxvec) +{ +return -1 ; +} +static inline void pci_msi_shutdown (struct pci_dev *dev) { }static inline void pci_disable_msi (struct pci_dev *dev)
@@ -1132,6 +1138,7 @@ static inline int pci_msi_enabled(void) }#else extern int pci_enable_msi_block (struct pci_dev *dev,unsigned int nvec); +extern int pci_enable_msi_block_auto (struct pci_dev *dev,unsigned int *maxvec);extern void pci_msi_shutdown (struct pci_dev *dev);extern void pci_disable_msi (struct pci_dev *dev);extern int pci_msix_table_size (struct pci_dev *dev);
kernel/irq/chip.c +22 -8
@@ -90,27 +90,41 @@ int irq_set_handler_data(unsigned int irq, void *data)EXPORT_SYMBOL (irq_set_handler_data);/** -* irq_set_msi_desc - set MSI descriptor data for an irq -* @irq: Interrupt number -* @entry: Pointer to MSI descriptor data +* irq_set_msi_desc_off - set MSI descriptor data for an irq at offset +* @irq_base: Interrupt number base +* @irq_offset: Interrupt number offset +* @entry: Pointer to MSI descriptor data * -* Set the MSI descriptor entry for an irq +* Set the MSI descriptor entry for an irq at offset */ -int irq_set_msi_desc (unsigned int irq,struct msi_desc *entry) +int irq_set_msi_desc_off (unsigned int irq_base,unsigned int irq_offset, +struct msi_desc *entry) {unsigned long flags; -struct irq_desc *desc =irq_get_desc_lock (irq, &flags,IRQ_GET_DESC_CHECK_GLOBAL ); +struct irq_desc *desc =irq_get_desc_lock (irq_base + irq_offset, &flags,IRQ_GET_DESC_CHECK_GLOBAL );if (!desc)return -EINVAL ; desc->irq_data.msi_desc = entry; -if (entry) - entry->irq = irq; +if (entry && !irq_offset) + entry->irq = irq_base;irq_put_desc_unlock (desc, flags);return 0 ; }/** +* irq_set_msi_desc - set MSI descriptor data for an irq +* @irq: Interrupt number +* @entry: Pointer to MSI descriptor data +* +* Set the MSI descriptor entry for an irq +*/ +int irq_set_msi_desc (unsigned int irq,struct msi_desc *entry) +{ +return irq_set_msi_desc_off (irq,0 , entry); +} + +/** * irq_set_chip_data - set irq chip data for an irq * @irq: Interrupt number * @data: Pointer to chip specific data