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: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
Yinghai Lu 2009-02-08 16:18:03 -08:00 коммит произвёл Ingo Molnar
Родитель f72dccace7
Коммит cc6c50066e
3 изменённых файлов: 44 добавлений и 5 удалений

Просмотреть файл

@ -73,6 +73,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);
@ -84,6 +85,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)

Просмотреть файл

@ -961,6 +961,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 mpc_intsrc *m, static void assign_to_mp_irq(struct mpc_intsrc *m,
struct mpc_intsrc *mp_irq) struct mpc_intsrc *mp_irq)
{ {

Просмотреть файл

@ -3824,14 +3824,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);
} }
#ifdef CONFIG_SPARSE_IRQ #ifdef CONFIG_SPARSE_IRQ