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 | } | ||
