diff options
-rw-r--r-- | arch/x86/include/asm/io_apic.h | 13 | ||||
-rw-r--r-- | arch/x86/kernel/acpi/boot.c | 102 | ||||
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 103 |
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 | 153 | extern u8 io_apic_unique_id(u8 id); |
154 | extern int io_apic_get_unique_id(int ioapic, int apic_id); | 154 | extern int io_apic_get_unique_id(int ioapic, int apic_id); |
155 | extern int io_apic_get_version(int ioapic); | 155 | extern int io_apic_get_version(int ioapic); |
156 | extern int io_apic_get_redir_entries(int ioapic); | 156 | extern int io_apic_get_redir_entries(int ioapic); |
157 | #endif /* CONFIG_ACPI */ | ||
158 | 157 | ||
159 | struct io_apic_irq_attr; | 158 | struct io_apic_irq_attr; |
160 | extern int io_apic_set_pci_routing(struct device *dev, int irq, | 159 | extern 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); |
178 | extern void ioapic_write_entry(int apic, int pin, | 177 | extern void ioapic_write_entry(int apic, int pin, |
179 | struct IO_APIC_route_entry e); | 178 | struct IO_APIC_route_entry e); |
179 | |||
180 | struct mp_ioapic_gsi{ | ||
181 | int gsi_base; | ||
182 | int gsi_end; | ||
183 | }; | ||
184 | extern struct mp_ioapic_gsi mp_gsi_routing[]; | ||
185 | int mp_find_ioapic(int gsi); | ||
186 | int mp_find_ioapic_pin(int ioapic, int gsi); | ||
187 | void __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 |
182 | static const int timer_through_8259 = 0; | 191 | static 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) | |||
833 | extern int es7000_plat; | 833 | extern int es7000_plat; |
834 | #endif | 834 | #endif |
835 | 835 | ||
836 | static struct { | ||
837 | int gsi_base; | ||
838 | int gsi_end; | ||
839 | } mp_ioapic_routing[MAX_IO_APICS]; | ||
840 | |||
841 | int 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 | |||
856 | int 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 | |||
866 | static 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 | |||
888 | static 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 | |||
903 | void __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 | |||
936 | int __init acpi_probe_gsi(void) | 836 | int __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]; | |||
85 | struct mpc_ioapic mp_ioapics[MAX_IO_APICS]; | 85 | struct mpc_ioapic mp_ioapics[MAX_IO_APICS]; |
86 | int nr_ioapics; | 86 | int nr_ioapics; |
87 | 87 | ||
88 | /* IO APIC gsi routing info */ | ||
89 | struct mp_ioapic_gsi mp_gsi_routing[MAX_IO_APICS]; | ||
90 | |||
88 | /* MP IRQ source entries */ | 91 | /* MP IRQ source entries */ |
89 | struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES]; | 92 | struct 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 | /* -------------------------------------------------------------------------- | 3947 | u8 __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 |
3951 | int __init io_apic_get_unique_id(int ioapic, int apic_id) | 3971 | int __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 | |||
4223 | int 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 | |||
4238 | int 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 | |||
4248 | static 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 | |||
4263 | void __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 | } | ||