Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] PCI: Change MSI to use physical delivery mode always

MSI hardcoded delivery mode to use logical delivery mode. Recently
x86_64 moved to use physical mode addressing to support physflat mode.
With this mode enabled noticed that my eth with MSI werent working.

msi_address_init() was hardcoded to use logical mode for i386 and x86_64.
So when we switch to use physical mode, things stopped working.

Since anyway we dont use lowest priority delivery with MSI, its always
directed to just a single CPU. Its safe and simpler to use
physical mode always, even when we use logical delivery mode for IPI's
or other ioapic RTE's.

Signed-off-by: Ashok Raj <ashok.raj@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Ashok Raj and committed by
Greg Kroah-Hartman
b4033c17 48b19148

+26 -22
+12 -8
drivers/pci/msi.c
··· 23 23 #include "pci.h" 24 24 #include "msi.h" 25 25 26 + #define MSI_TARGET_CPU first_cpu(cpu_online_map) 27 + 26 28 static DEFINE_SPINLOCK(msi_lock); 27 29 static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL }; 28 30 static kmem_cache_t* msi_cachep; ··· 94 92 struct msi_desc *entry; 95 93 struct msg_address address; 96 94 unsigned int irq = vector; 95 + unsigned int dest_cpu = first_cpu(cpu_mask); 97 96 98 97 entry = (struct msi_desc *)msi_desc[vector]; 99 98 if (!entry || !entry->dev) ··· 111 108 pci_read_config_dword(entry->dev, msi_lower_address_reg(pos), 112 109 &address.lo_address.value); 113 110 address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK; 114 - address.lo_address.value |= (cpu_mask_to_apicid(cpu_mask) << 115 - MSI_TARGET_CPU_SHIFT); 116 - entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask); 111 + address.lo_address.value |= (cpu_physical_id(dest_cpu) << 112 + MSI_TARGET_CPU_SHIFT); 113 + entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu); 117 114 pci_write_config_dword(entry->dev, msi_lower_address_reg(pos), 118 115 address.lo_address.value); 119 116 set_native_irq_info(irq, cpu_mask); ··· 126 123 127 124 address.lo_address.value = readl(entry->mask_base + offset); 128 125 address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK; 129 - address.lo_address.value |= (cpu_mask_to_apicid(cpu_mask) << 130 - MSI_TARGET_CPU_SHIFT); 131 - entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask); 126 + address.lo_address.value |= (cpu_physical_id(dest_cpu) << 127 + MSI_TARGET_CPU_SHIFT); 128 + entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu); 132 129 writel(address.lo_address.value, entry->mask_base + offset); 133 130 set_native_irq_info(irq, cpu_mask); 134 131 break; ··· 262 259 static void msi_address_init(struct msg_address *msi_address) 263 260 { 264 261 unsigned int dest_id; 262 + unsigned long dest_phys_id = cpu_physical_id(MSI_TARGET_CPU); 265 263 266 264 memset(msi_address, 0, sizeof(struct msg_address)); 267 265 msi_address->hi_address = (u32)0; 268 266 dest_id = (MSI_ADDRESS_HEADER << MSI_ADDRESS_HEADER_SHIFT); 269 - msi_address->lo_address.u.dest_mode = MSI_DEST_MODE; 267 + msi_address->lo_address.u.dest_mode = MSI_PHYSICAL_MODE; 270 268 msi_address->lo_address.u.redirection_hint = MSI_REDIRECTION_HINT_MODE; 271 269 msi_address->lo_address.u.dest_id = dest_id; 272 - msi_address->lo_address.value |= (MSI_TARGET_CPU << MSI_TARGET_CPU_SHIFT); 270 + msi_address->lo_address.value |= (dest_phys_id << MSI_TARGET_CPU_SHIFT); 273 271 } 274 272 275 273 static int msi_free_vector(struct pci_dev* dev, int vector, int reassign);
+1 -8
include/asm-i386/msi.h
··· 10 10 #include <mach_apic.h> 11 11 12 12 #define LAST_DEVICE_VECTOR 232 13 - #define MSI_DEST_MODE MSI_LOGICAL_MODE 14 - #define MSI_TARGET_CPU_SHIFT 12 15 - 16 - #ifdef CONFIG_SMP 17 - #define MSI_TARGET_CPU logical_smp_processor_id() 18 - #else 19 - #define MSI_TARGET_CPU cpu_to_logical_apicid(first_cpu(cpu_online_map)) 20 - #endif 13 + #define MSI_TARGET_CPU_SHIFT 12 21 14 22 15 #endif /* ASM_MSI_H */
+6
include/asm-i386/smp.h
··· 45 45 #define MAX_APICID 256 46 46 extern u8 x86_cpu_to_apicid[]; 47 47 48 + #define cpu_physical_id(cpu) x86_cpu_to_apicid[cpu] 49 + 48 50 #ifdef CONFIG_HOTPLUG_CPU 49 51 extern void cpu_exit_clear(void); 50 52 extern void cpu_uninit(void); ··· 93 91 extern int __cpu_disable(void); 94 92 extern void __cpu_die(unsigned int cpu); 95 93 #endif /* !__ASSEMBLY__ */ 94 + 95 + #else /* CONFIG_SMP */ 96 + 97 + #define cpu_physical_id(cpu) boot_cpu_physical_apicid 96 98 97 99 #define NO_PROC_ID 0xFF /* No processor magic marker */ 98 100
-3
include/asm-ia64/msi.h
··· 12 12 static inline void set_intr_gate (int nr, void *func) {} 13 13 #define IO_APIC_VECTOR(irq) (irq) 14 14 #define ack_APIC_irq ia64_eoi 15 - #define cpu_mask_to_apicid(mask) cpu_physical_id(first_cpu(mask)) 16 - #define MSI_DEST_MODE MSI_PHYSICAL_MODE 17 - #define MSI_TARGET_CPU ((ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff) 18 15 #define MSI_TARGET_CPU_SHIFT 4 19 16 20 17 #endif /* ASM_MSI_H */
+1 -3
include/asm-x86_64/msi.h
··· 11 11 #include <asm/smp.h> 12 12 13 13 #define LAST_DEVICE_VECTOR 232 14 - #define MSI_DEST_MODE MSI_LOGICAL_MODE 15 - #define MSI_TARGET_CPU_SHIFT 12 16 - #define MSI_TARGET_CPU logical_smp_processor_id() 14 + #define MSI_TARGET_CPU_SHIFT 12 17 15 18 16 #endif /* ASM_MSI_H */
+6
include/asm-x86_64/smp.h
··· 135 135 } 136 136 #endif 137 137 138 + #ifdef CONFIG_SMP 139 + #define cpu_physical_id(cpu) x86_cpu_to_apicid[cpu] 140 + #else 141 + #define cpu_physical_id(cpu) boot_cpu_id 142 + #endif 143 + 138 144 #endif 139 145