Commit 0342e162 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Fix and Reenable MSI Support on x86_64

From: long <tlnguyen@snoqualmie.dp.intel.com>

MSI support for x86_64 is currently disabled in the kernel 2.6.x.  Below is
the patch, which provides a fix and reenable it.

In addition, the patch provides a info message during kernel boot if
configuring vector-base indexing.

Cc: Andi Kleen <ak@muc.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 8c05319f
...@@ -1411,11 +1411,16 @@ void __init print_IO_APIC(void) ...@@ -1411,11 +1411,16 @@ void __init print_IO_APIC(void)
); );
} }
} }
if (use_pci_vector())
printk(KERN_INFO "Using vector-based indexing\n");
printk(KERN_DEBUG "IRQ to pin mappings:\n"); printk(KERN_DEBUG "IRQ to pin mappings:\n");
for (i = 0; i < NR_IRQS; i++) { for (i = 0; i < NR_IRQS; i++) {
struct irq_pin_list *entry = irq_2_pin + i; struct irq_pin_list *entry = irq_2_pin + i;
if (entry->pin < 0) if (entry->pin < 0)
continue; continue;
if (use_pci_vector() && !platform_legacy_irq(i))
printk(KERN_DEBUG "IRQ%d ", IO_APIC_VECTOR(i));
else
printk(KERN_DEBUG "IRQ%d ", i); printk(KERN_DEBUG "IRQ%d ", i);
for (;;) { for (;;) {
printk("-> %d:%d", entry->apic, entry->pin); printk("-> %d:%d", entry->apic, entry->pin);
......
...@@ -47,6 +47,12 @@ ...@@ -47,6 +47,12 @@
BI(x,8) BI(x,9) BI(x,a) BI(x,b) \ BI(x,8) BI(x,9) BI(x,a) BI(x,b) \
BI(x,c) BI(x,d) BI(x,e) BI(x,f) BI(x,c) BI(x,d) BI(x,e) BI(x,f)
#define BUILD_14_IRQS(x) \
BI(x,0) BI(x,1) BI(x,2) BI(x,3) \
BI(x,4) BI(x,5) BI(x,6) BI(x,7) \
BI(x,8) BI(x,9) BI(x,a) BI(x,b) \
BI(x,c) BI(x,d)
/* /*
* ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts: * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
* (these are usually mapped to vectors 0x20-0x2f) * (these are usually mapped to vectors 0x20-0x2f)
...@@ -68,9 +74,15 @@ BUILD_16_IRQS(0x0) ...@@ -68,9 +74,15 @@ BUILD_16_IRQS(0x0)
BUILD_16_IRQS(0x4) BUILD_16_IRQS(0x5) BUILD_16_IRQS(0x6) BUILD_16_IRQS(0x7) BUILD_16_IRQS(0x4) BUILD_16_IRQS(0x5) BUILD_16_IRQS(0x6) BUILD_16_IRQS(0x7)
BUILD_16_IRQS(0x8) BUILD_16_IRQS(0x9) BUILD_16_IRQS(0xa) BUILD_16_IRQS(0xb) BUILD_16_IRQS(0x8) BUILD_16_IRQS(0x9) BUILD_16_IRQS(0xa) BUILD_16_IRQS(0xb)
BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd) BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd)
#ifdef CONFIG_PCI_USE_VECTOR
BUILD_14_IRQS(0xe)
#endif
#endif #endif
#undef BUILD_16_IRQS #undef BUILD_16_IRQS
#undef BUILD_14_IRQS
#undef BI #undef BI
...@@ -83,6 +95,12 @@ BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd) ...@@ -83,6 +95,12 @@ BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd)
IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \ IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \
IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f) IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f)
#define IRQLIST_14(x) \
IRQ(x,0), IRQ(x,1), IRQ(x,2), IRQ(x,3), \
IRQ(x,4), IRQ(x,5), IRQ(x,6), IRQ(x,7), \
IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \
IRQ(x,c), IRQ(x,d)
void (*interrupt[NR_IRQS])(void) = { void (*interrupt[NR_IRQS])(void) = {
IRQLIST_16(0x0), IRQLIST_16(0x0),
...@@ -91,11 +109,17 @@ void (*interrupt[NR_IRQS])(void) = { ...@@ -91,11 +109,17 @@ void (*interrupt[NR_IRQS])(void) = {
IRQLIST_16(0x4), IRQLIST_16(0x5), IRQLIST_16(0x6), IRQLIST_16(0x7), IRQLIST_16(0x4), IRQLIST_16(0x5), IRQLIST_16(0x6), IRQLIST_16(0x7),
IRQLIST_16(0x8), IRQLIST_16(0x9), IRQLIST_16(0xa), IRQLIST_16(0xb), IRQLIST_16(0x8), IRQLIST_16(0x9), IRQLIST_16(0xa), IRQLIST_16(0xb),
IRQLIST_16(0xc), IRQLIST_16(0xd) IRQLIST_16(0xc), IRQLIST_16(0xd)
#ifdef CONFIG_PCI_USE_VECTOR
, IRQLIST_14(0xe)
#endif
#endif #endif
}; };
#undef IRQ #undef IRQ
#undef IRQLIST_16 #undef IRQLIST_16
#undef IRQLIST_14
/* /*
* This is the 'legacy' 8259A Programmable Interrupt Controller, * This is the 'legacy' 8259A Programmable Interrupt Controller,
......
...@@ -67,8 +67,8 @@ static struct irq_pin_list { ...@@ -67,8 +67,8 @@ static struct irq_pin_list {
short apic, pin, next; short apic, pin, next;
} irq_2_pin[PIN_MAP_SIZE]; } irq_2_pin[PIN_MAP_SIZE];
int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1};
#ifdef CONFIG_PCI_USE_VECTOR #ifdef CONFIG_PCI_USE_VECTOR
int vector_irq[NR_IRQS] = { [0 ... NR_IRQS -1] = -1};
#define vector_to_irq(vector) \ #define vector_to_irq(vector) \
(platform_legacy_irq(vector) ? vector : vector_irq[vector]) (platform_legacy_irq(vector) ? vector : vector_irq[vector])
#else #else
...@@ -656,10 +656,14 @@ static inline int IO_APIC_irq_trigger(int irq) ...@@ -656,10 +656,14 @@ static inline int IO_APIC_irq_trigger(int irq)
/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */ /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 }; u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 };
#ifndef CONFIG_PCI_USE_VECTOR #ifdef CONFIG_PCI_USE_VECTOR
int assign_irq_vector(int irq)
#else
int __init assign_irq_vector(int irq) int __init assign_irq_vector(int irq)
#endif
{ {
static int current_vector = FIRST_DEVICE_VECTOR, offset = 0; static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
BUG_ON(irq >= NR_IRQ_VECTORS); BUG_ON(irq >= NR_IRQ_VECTORS);
if (IO_APIC_VECTOR(irq) > 0) if (IO_APIC_VECTOR(irq) > 0)
return IO_APIC_VECTOR(irq); return IO_APIC_VECTOR(irq);
...@@ -668,18 +672,19 @@ int __init assign_irq_vector(int irq) ...@@ -668,18 +672,19 @@ int __init assign_irq_vector(int irq)
if (current_vector == IA32_SYSCALL_VECTOR) if (current_vector == IA32_SYSCALL_VECTOR)
goto next; goto next;
if (current_vector > FIRST_SYSTEM_VECTOR) { if (current_vector >= FIRST_SYSTEM_VECTOR) {
offset++; offset++;
if (!(offset%8))
return -ENOSPC;
current_vector = FIRST_DEVICE_VECTOR + offset; current_vector = FIRST_DEVICE_VECTOR + offset;
} }
if (current_vector == FIRST_SYSTEM_VECTOR) vector_irq[current_vector] = irq;
panic("ran out of interrupt sources!"); if (irq != AUTO_ASSIGN)
IO_APIC_VECTOR(irq) = current_vector; IO_APIC_VECTOR(irq) = current_vector;
return current_vector; return current_vector;
} }
#endif
extern void (*interrupt[NR_IRQS])(void); extern void (*interrupt[NR_IRQS])(void);
static struct hw_interrupt_type ioapic_level_type; static struct hw_interrupt_type ioapic_level_type;
...@@ -925,11 +930,16 @@ void __init print_IO_APIC(void) ...@@ -925,11 +930,16 @@ void __init print_IO_APIC(void)
); );
} }
} }
if (use_pci_vector())
printk(KERN_INFO "Using vector-based indexing\n");
printk(KERN_DEBUG "IRQ to pin mappings:\n"); printk(KERN_DEBUG "IRQ to pin mappings:\n");
for (i = 0; i < NR_IRQS; i++) { for (i = 0; i < NR_IRQS; i++) {
struct irq_pin_list *entry = irq_2_pin + i; struct irq_pin_list *entry = irq_2_pin + i;
if (entry->pin < 0) if (entry->pin < 0)
continue; continue;
if (use_pci_vector() && !platform_legacy_irq(i))
printk(KERN_DEBUG "IRQ%d ", IO_APIC_VECTOR(i));
else
printk(KERN_DEBUG "IRQ%d ", i); printk(KERN_DEBUG "IRQ%d ", i);
for (;;) { for (;;) {
printk("-> %d:%d", entry->apic, entry->pin); printk("-> %d:%d", entry->apic, entry->pin);
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# #
config PCI_USE_VECTOR config PCI_USE_VECTOR
bool "Vector-based interrupt indexing (MSI)" bool "Vector-based interrupt indexing (MSI)"
depends on (X86_LOCAL_APIC && X86_IO_APIC && !X86_64) || IA64 depends on (X86_LOCAL_APIC && X86_IO_APIC) || IA64
default n default n
help help
This replaces the current existing IRQ-based index interrupt scheme This replaces the current existing IRQ-based index interrupt scheme
......
...@@ -78,6 +78,7 @@ struct hw_interrupt_type; ...@@ -78,6 +78,7 @@ struct hw_interrupt_type;
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
extern u8 irq_vector[NR_IRQ_VECTORS]; extern u8 irq_vector[NR_IRQ_VECTORS];
#define IO_APIC_VECTOR(irq) (irq_vector[irq]) #define IO_APIC_VECTOR(irq) (irq_vector[irq])
#define AUTO_ASSIGN -1
/* /*
* Various low-level irq details needed by irq.c, process.c, * Various low-level irq details needed by irq.c, process.c,
......
...@@ -11,11 +11,6 @@ ...@@ -11,11 +11,6 @@
#define LAST_DEVICE_VECTOR 232 #define LAST_DEVICE_VECTOR 232
#define MSI_DEST_MODE MSI_LOGICAL_MODE #define MSI_DEST_MODE MSI_LOGICAL_MODE
#define MSI_TARGET_CPU_SHIFT 12 #define MSI_TARGET_CPU_SHIFT 12
#ifdef CONFIG_SMP
#define MSI_TARGET_CPU logical_smp_processor_id()
#else
#define MSI_TARGET_CPU TARGET_CPUS #define MSI_TARGET_CPU TARGET_CPUS
#endif
#endif /* ASM_MSI_H */ #endif /* ASM_MSI_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment