aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/io_apic.h13
-rw-r--r--arch/x86/kernel/acpi/boot.c102
-rw-r--r--arch/x86/kernel/apic/io_apic.c103
3 files changed, 109 insertions, 109 deletions
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 330ee807f89e..85232d32fcb8 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -150,11 +150,10 @@ extern int timer_through_8259;
150#define io_apic_assign_pci_irqs \ 150#define io_apic_assign_pci_irqs \
151 (mp_irq_entries && !skip_ioapic_setup && io_apic_irqs) 151 (mp_irq_entries && !skip_ioapic_setup && io_apic_irqs)
152 152
153#ifdef CONFIG_ACPI 153extern u8 io_apic_unique_id(u8 id);
154extern int io_apic_get_unique_id(int ioapic, int apic_id); 154extern int io_apic_get_unique_id(int ioapic, int apic_id);
155extern int io_apic_get_version(int ioapic); 155extern int io_apic_get_version(int ioapic);
156extern int io_apic_get_redir_entries(int ioapic); 156extern int io_apic_get_redir_entries(int ioapic);
157#endif /* CONFIG_ACPI */
158 157
159struct io_apic_irq_attr; 158struct io_apic_irq_attr;
160extern int io_apic_set_pci_routing(struct device *dev, int irq, 159extern int io_apic_set_pci_routing(struct device *dev, int irq,
@@ -177,6 +176,16 @@ extern int setup_ioapic_entry(int apic, int irq,
177 int polarity, int vector, int pin); 176 int polarity, int vector, int pin);
178extern void ioapic_write_entry(int apic, int pin, 177extern void ioapic_write_entry(int apic, int pin,
179 struct IO_APIC_route_entry e); 178 struct IO_APIC_route_entry e);
179
180struct mp_ioapic_gsi{
181 int gsi_base;
182 int gsi_end;
183};
184extern struct mp_ioapic_gsi mp_gsi_routing[];
185int mp_find_ioapic(int gsi);
186int mp_find_ioapic_pin(int ioapic, int gsi);
187void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
188
180#else /* !CONFIG_X86_IO_APIC */ 189#else /* !CONFIG_X86_IO_APIC */
181#define io_apic_assign_pci_irqs 0 190#define io_apic_assign_pci_irqs 0
182static const int timer_through_8259 = 0; 191static const int timer_through_8259 = 0;
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 6b8ca3a0285d..7e62d1eb8e30 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -833,106 +833,6 @@ static int __init acpi_parse_madt_lapic_entries(void)
833extern int es7000_plat; 833extern int es7000_plat;
834#endif 834#endif
835 835
836static struct {
837 int gsi_base;
838 int gsi_end;
839} mp_ioapic_routing[MAX_IO_APICS];
840
841int mp_find_ioapic(int gsi)
842{
843 int i = 0;
844
845 /* Find the IOAPIC that manages this GSI. */
846 for (i = 0; i < nr_ioapics; i++) {
847 if ((gsi >= mp_ioapic_routing[i].gsi_base)
848 && (gsi <= mp_ioapic_routing[i].gsi_end))
849 return i;
850 }
851
852 printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
853 return -1;
854}
855
856int mp_find_ioapic_pin(int ioapic, int gsi)
857{
858 if (WARN_ON(ioapic == -1))
859 return -1;
860 if (WARN_ON(gsi > mp_ioapic_routing[ioapic].gsi_end))
861 return -1;
862
863 return gsi - mp_ioapic_routing[ioapic].gsi_base;
864}
865
866static u8 __init uniq_ioapic_id(u8 id)
867{
868#ifdef CONFIG_X86_32
869 if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
870 !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
871 return io_apic_get_unique_id(nr_ioapics, id);
872 else
873 return id;
874#else
875 int i;
876 DECLARE_BITMAP(used, 256);
877 bitmap_zero(used, 256);
878 for (i = 0; i < nr_ioapics; i++) {
879 struct mpc_ioapic *ia = &mp_ioapics[i];
880 __set_bit(ia->apicid, used);
881 }
882 if (!test_bit(id, used))
883 return id;
884 return find_first_zero_bit(used, 256);
885#endif
886}
887
888static int bad_ioapic(unsigned long address)
889{
890 if (nr_ioapics >= MAX_IO_APICS) {
891 printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
892 "(found %d)\n", MAX_IO_APICS, nr_ioapics);
893 panic("Recompile kernel with bigger MAX_IO_APICS!\n");
894 }
895 if (!address) {
896 printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
897 " found in table, skipping!\n");
898 return 1;
899 }
900 return 0;
901}
902
903void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
904{
905 int idx = 0;
906
907 if (bad_ioapic(address))
908 return;
909
910 idx = nr_ioapics;
911
912 mp_ioapics[idx].type = MP_IOAPIC;
913 mp_ioapics[idx].flags = MPC_APIC_USABLE;
914 mp_ioapics[idx].apicaddr = address;
915
916 set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
917 mp_ioapics[idx].apicid = uniq_ioapic_id(id);
918 mp_ioapics[idx].apicver = io_apic_get_version(idx);
919
920 /*
921 * Build basic GSI lookup table to facilitate gsi->io_apic lookups
922 * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
923 */
924 mp_ioapic_routing[idx].gsi_base = gsi_base;
925 mp_ioapic_routing[idx].gsi_end = gsi_base +
926 io_apic_get_redir_entries(idx);
927
928 printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
929 "GSI %d-%d\n", idx, mp_ioapics[idx].apicid,
930 mp_ioapics[idx].apicver, mp_ioapics[idx].apicaddr,
931 mp_ioapic_routing[idx].gsi_base, mp_ioapic_routing[idx].gsi_end);
932
933 nr_ioapics++;
934}
935
936int __init acpi_probe_gsi(void) 836int __init acpi_probe_gsi(void)
937{ 837{
938 int idx; 838 int idx;
@@ -947,7 +847,7 @@ int __init acpi_probe_gsi(void)
947 847
948 max_gsi = 0; 848 max_gsi = 0;
949 for (idx = 0; idx < nr_ioapics; idx++) { 849 for (idx = 0; idx < nr_ioapics; idx++) {
950 gsi = mp_ioapic_routing[idx].gsi_end; 850 gsi = mp_gsi_routing[idx].gsi_end;
951 851
952 if (gsi > max_gsi) 852 if (gsi > max_gsi)
953 max_gsi = gsi; 853 max_gsi = gsi;
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index d2ed6c5ddc80..a8c0232b3893 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -85,6 +85,9 @@ int nr_ioapic_registers[MAX_IO_APICS];
85struct mpc_ioapic mp_ioapics[MAX_IO_APICS]; 85struct mpc_ioapic mp_ioapics[MAX_IO_APICS];
86int nr_ioapics; 86int nr_ioapics;
87 87
88/* IO APIC gsi routing info */
89struct mp_ioapic_gsi mp_gsi_routing[MAX_IO_APICS];
90
88/* MP IRQ source entries */ 91/* MP IRQ source entries */
89struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES]; 92struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];
90 93
@@ -3941,11 +3944,28 @@ int io_apic_set_pci_routing(struct device *dev, int irq,
3941 return __io_apic_set_pci_routing(dev, irq, irq_attr); 3944 return __io_apic_set_pci_routing(dev, irq, irq_attr);
3942} 3945}
3943 3946
3944/* -------------------------------------------------------------------------- 3947u8 __init io_apic_unique_id(u8 id)
3945 ACPI-based IOAPIC Configuration 3948{
3946 -------------------------------------------------------------------------- */ 3949#ifdef CONFIG_X86_32
3950 if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
3951 !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
3952 return io_apic_get_unique_id(nr_ioapics, id);
3953 else
3954 return id;
3955#else
3956 int i;
3957 DECLARE_BITMAP(used, 256);
3947 3958
3948#ifdef CONFIG_ACPI 3959 bitmap_zero(used, 256);
3960 for (i = 0; i < nr_ioapics; i++) {
3961 struct mpc_ioapic *ia = &mp_ioapics[i];
3962 __set_bit(ia->apicid, used);
3963 }
3964 if (!test_bit(id, used))
3965 return id;
3966 return find_first_zero_bit(used, 256);
3967#endif
3968}
3949 3969
3950#ifdef CONFIG_X86_32 3970#ifdef CONFIG_X86_32
3951int __init io_apic_get_unique_id(int ioapic, int apic_id) 3971int __init io_apic_get_unique_id(int ioapic, int apic_id)
@@ -4054,8 +4074,6 @@ int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
4054 return 0; 4074 return 0;
4055} 4075}
4056 4076
4057#endif /* CONFIG_ACPI */
4058
4059/* 4077/*
4060 * This function currently is only a helper for the i386 smp boot process where 4078 * This function currently is only a helper for the i386 smp boot process where
4061 * we need to reprogram the ioredtbls to cater for the cpus which have come online 4079 * we need to reprogram the ioredtbls to cater for the cpus which have come online
@@ -4201,3 +4219,76 @@ void __init ioapic_insert_resources(void)
4201 r++; 4219 r++;
4202 } 4220 }
4203} 4221}
4222
4223int mp_find_ioapic(int gsi)
4224{
4225 int i = 0;
4226
4227 /* Find the IOAPIC that manages this GSI. */
4228 for (i = 0; i < nr_ioapics; i++) {
4229 if ((gsi >= mp_gsi_routing[i].gsi_base)
4230 && (gsi <= mp_gsi_routing[i].gsi_end))
4231 return i;
4232 }
4233
4234 printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
4235 return -1;
4236}
4237
4238int mp_find_ioapic_pin(int ioapic, int gsi)
4239{
4240 if (WARN_ON(ioapic == -1))
4241 return -1;
4242 if (WARN_ON(gsi > mp_gsi_routing[ioapic].gsi_end))
4243 return -1;
4244
4245 return gsi - mp_gsi_routing[ioapic].gsi_base;
4246}
4247
4248static int bad_ioapic(unsigned long address)
4249{
4250 if (nr_ioapics >= MAX_IO_APICS) {
4251 printk(KERN_WARNING "WARING: Max # of I/O APICs (%d) exceeded "
4252 "(found %d), skipping\n", MAX_IO_APICS, nr_ioapics);
4253 return 1;
4254 }
4255 if (!address) {
4256 printk(KERN_WARNING "WARNING: Bogus (zero) I/O APIC address"
4257 " found in table, skipping!\n");
4258 return 1;
4259 }
4260 return 0;
4261}
4262
4263void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
4264{
4265 int idx = 0;
4266
4267 if (bad_ioapic(address))
4268 return;
4269
4270 idx = nr_ioapics;
4271
4272 mp_ioapics[idx].type = MP_IOAPIC;
4273 mp_ioapics[idx].flags = MPC_APIC_USABLE;
4274 mp_ioapics[idx].apicaddr = address;
4275
4276 set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
4277 mp_ioapics[idx].apicid = io_apic_unique_id(id);
4278 mp_ioapics[idx].apicver = io_apic_get_version(idx);
4279
4280 /*
4281 * Build basic GSI lookup table to facilitate gsi->io_apic lookups
4282 * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
4283 */
4284 mp_gsi_routing[idx].gsi_base = gsi_base;
4285 mp_gsi_routing[idx].gsi_end = gsi_base +
4286 io_apic_get_redir_entries(idx);
4287
4288 printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
4289 "GSI %d-%d\n", idx, mp_ioapics[idx].apicid,
4290 mp_ioapics[idx].apicver, mp_ioapics[idx].apicaddr,
4291 mp_gsi_routing[idx].gsi_base, mp_gsi_routing[idx].gsi_end);
4292
4293 nr_ioapics++;
4294}