Commit 3f4a739c authored by Yinghai Lu's avatar Yinghai Lu Committed by Ingo Molnar

x86: find nr_irqs_gsi with mp_ioapic_routing

Impact: find right nr_irqs_gsi on some systems.

One test-system has gap between gsi's:

[    0.000000] ACPI: IOAPIC (id[0x04] address[0xfec00000] gsi_base[0])
[    0.000000] IOAPIC[0]: apic_id 4, version 0, address 0xfec00000, GSI 0-23
[    0.000000] ACPI: IOAPIC (id[0x05] address[0xfeafd000] gsi_base[48])
[    0.000000] IOAPIC[1]: apic_id 5, version 0, address 0xfeafd000, GSI 48-54
[    0.000000] ACPI: IOAPIC (id[0x06] address[0xfeafc000] gsi_base[56])
[    0.000000] IOAPIC[2]: apic_id 6, version 0, address 0xfeafc000, GSI 56-62
...
[    0.000000] nr_irqs_gsi: 38

So nr_irqs_gsi is not right. some irq for MSI will overwrite with io_apic.

need to get that with acpi_probe_gsi when acpi io_apic is used
Signed-off-by: default avatarYinghai Lu <yinghai@kernel.org>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent e736ad54
...@@ -60,6 +60,7 @@ extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, ...@@ -60,6 +60,7 @@ extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
u32 gsi); u32 gsi);
extern void mp_config_acpi_legacy_irqs(void); extern void mp_config_acpi_legacy_irqs(void);
extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low); extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low);
extern int acpi_probe_gsi(void);
#ifdef CONFIG_X86_IO_APIC #ifdef CONFIG_X86_IO_APIC
extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin, extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
u32 gsi, int triggering, int polarity); u32 gsi, int triggering, int polarity);
...@@ -71,6 +72,11 @@ mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin, ...@@ -71,6 +72,11 @@ mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
return 0; return 0;
} }
#endif #endif
#else /* !CONFIG_ACPI: */
static inline int acpi_probe_gsi(void)
{
return 0;
}
#endif /* CONFIG_ACPI */ #endif /* CONFIG_ACPI */
#define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_APICS) #define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_APICS)
......
...@@ -973,6 +973,29 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) ...@@ -973,6 +973,29 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
nr_ioapics++; nr_ioapics++;
} }
int __init acpi_probe_gsi(void)
{
int idx;
int gsi;
int max_gsi = 0;
if (acpi_disabled)
return 0;
if (!acpi_ioapic)
return 0;
max_gsi = 0;
for (idx = 0; idx < nr_ioapics; idx++) {
gsi = mp_ioapic_routing[idx].gsi_end;
if (gsi > max_gsi)
max_gsi = gsi;
}
return max_gsi + 1;
}
static void assign_to_mp_irq(struct mp_config_intsrc *m, static void assign_to_mp_irq(struct mp_config_intsrc *m,
struct mp_config_intsrc *mp_irq) struct mp_config_intsrc *mp_irq)
{ {
......
...@@ -3841,14 +3841,24 @@ int __init io_apic_get_redir_entries (int ioapic) ...@@ -3841,14 +3841,24 @@ int __init io_apic_get_redir_entries (int ioapic)
void __init probe_nr_irqs_gsi(void) void __init probe_nr_irqs_gsi(void)
{ {
int idx;
int nr = 0; int nr = 0;
for (idx = 0; idx < nr_ioapics; idx++) nr = acpi_probe_gsi();
nr += io_apic_get_redir_entries(idx) + 1; if (nr > nr_irqs_gsi) {
if (nr > nr_irqs_gsi)
nr_irqs_gsi = nr; nr_irqs_gsi = nr;
} else {
/* for acpi=off or acpi is not compiled in */
int idx;
nr = 0;
for (idx = 0; idx < nr_ioapics; idx++)
nr += io_apic_get_redir_entries(idx) + 1;
if (nr > nr_irqs_gsi)
nr_irqs_gsi = nr;
}
printk(KERN_DEBUG "nr_irqs_gsi: %d\n", nr_irqs_gsi);
} }
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
......
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