aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/mpparse.c
diff options
context:
space:
mode:
authorAlexey Starikovskiy <astarikovskiy@suse.de>2008-05-14 11:02:57 -0400
committerThomas Gleixner <tglx@linutronix.de>2008-05-25 04:55:12 -0400
commit11113f84c72bd832dc4e76122e613b0e623e2346 (patch)
treea2c8f05d35cb41f6b14eae3908278af08902a31b /arch/x86/kernel/mpparse.c
parent32c5061265caf201d6a2c0d02181e2b68769c22c (diff)
x86: complete move ACPI from mpparse.c
Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/mpparse.c')
-rw-r--r--arch/x86/kernel/mpparse.c299
1 files changed, 1 insertions, 298 deletions
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index ff1342325efc..d05b70c329c4 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -1,5 +1,5 @@
1/* 1/*
22 * Intel Multiprocessor Specification 1.1 and 1.4 2 * Intel Multiprocessor Specification 1.1 and 1.4
3 * compliant MP-table parsing routines. 3 * compliant MP-table parsing routines.
4 * 4 *
5 * (c) 1995 Alan Cox, Building #3 <alan@redhat.com> 5 * (c) 1995 Alan Cox, Building #3 <alan@redhat.com>
@@ -788,300 +788,3 @@ void __init find_smp_config(void)
788{ 788{
789 __find_smp_config(1); 789 __find_smp_config(1);
790} 790}
791
792/* --------------------------------------------------------------------------
793 ACPI-based MP Configuration
794 -------------------------------------------------------------------------- */
795
796#ifdef CONFIG_ACPI
797
798#ifdef CONFIG_X86_IO_APIC
799
800#if defined(CONFIG_X86_ES7000) || defined(CONFIG_X86_GENERICARCH)
801extern int es7000_plat;
802#endif
803
804#define MP_ISA_BUS 0
805
806static struct mp_ioapic_routing mp_ioapic_routing[MAX_IO_APICS];
807
808static int mp_find_ioapic(int gsi)
809{
810 int i = 0;
811
812 /* Find the IOAPIC that manages this GSI. */
813 for (i = 0; i < nr_ioapics; i++) {
814 if ((gsi >= mp_ioapic_routing[i].gsi_base)
815 && (gsi <= mp_ioapic_routing[i].gsi_end))
816 return i;
817 }
818
819 printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
820 return -1;
821}
822
823static u8 __init uniq_ioapic_id(u8 id)
824{
825#ifdef CONFIG_X86_32
826 if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
827 !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
828 return io_apic_get_unique_id(nr_ioapics, id);
829 else
830 return id;
831#else
832 int i;
833 DECLARE_BITMAP(used, 256);
834 bitmap_zero(used, 256);
835 for (i = 0; i < nr_ioapics; i++) {
836 struct mpc_config_ioapic *ia = &mp_ioapics[i];
837 __set_bit(ia->mpc_apicid, used);
838 }
839 if (!test_bit(id, used))
840 return id;
841 return find_first_zero_bit(used, 256);
842#endif
843}
844
845void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
846{
847 int idx = 0;
848
849 if (bad_ioapic(address))
850 return;
851
852 idx = nr_ioapics;
853
854 mp_ioapics[idx].mpc_type = MP_IOAPIC;
855 mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE;
856 mp_ioapics[idx].mpc_apicaddr = address;
857
858 set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
859 mp_ioapics[idx].mpc_apicid = uniq_ioapic_id(id);
860#ifdef CONFIG_X86_32
861 mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
862#else
863 mp_ioapics[idx].mpc_apicver = 0;
864#endif
865 /*
866 * Build basic GSI lookup table to facilitate gsi->io_apic lookups
867 * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
868 */
869 mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid;
870 mp_ioapic_routing[idx].gsi_base = gsi_base;
871 mp_ioapic_routing[idx].gsi_end = gsi_base +
872 io_apic_get_redir_entries(idx);
873
874 printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
875 "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid,
876 mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
877 mp_ioapic_routing[idx].gsi_base, mp_ioapic_routing[idx].gsi_end);
878
879 nr_ioapics++;
880}
881
882void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
883{
884 struct mpc_config_intsrc intsrc;
885 int ioapic = -1;
886 int pin = -1;
887
888 /*
889 * Convert 'gsi' to 'ioapic.pin'.
890 */
891 ioapic = mp_find_ioapic(gsi);
892 if (ioapic < 0)
893 return;
894 pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
895
896 /*
897 * TBD: This check is for faulty timer entries, where the override
898 * erroneously sets the trigger to level, resulting in a HUGE
899 * increase of timer interrupts!
900 */
901 if ((bus_irq == 0) && (trigger == 3))
902 trigger = 1;
903
904 intsrc.mpc_type = MP_INTSRC;
905 intsrc.mpc_irqtype = mp_INT;
906 intsrc.mpc_irqflag = (trigger << 2) | polarity;
907 intsrc.mpc_srcbus = MP_ISA_BUS;
908 intsrc.mpc_srcbusirq = bus_irq; /* IRQ */
909 intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; /* APIC ID */
910 intsrc.mpc_dstirq = pin; /* INTIN# */
911
912 MP_intsrc_info(&intsrc);
913}
914
915void __init mp_config_acpi_legacy_irqs(void)
916{
917 struct mpc_config_intsrc intsrc;
918 int i = 0;
919 int ioapic = -1;
920
921#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
922 /*
923 * Fabricate the legacy ISA bus (bus #31).
924 */
925 mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA;
926#endif
927 set_bit(MP_ISA_BUS, mp_bus_not_pci);
928 Dprintk("Bus #%d is ISA\n", MP_ISA_BUS);
929
930#if defined(CONFIG_X86_ES7000) || defined(CONFIG_X86_GENERICARCH)
931 /*
932 * Older generations of ES7000 have no legacy identity mappings
933 */
934 if (es7000_plat == 1)
935 return;
936#endif
937
938 /*
939 * Locate the IOAPIC that manages the ISA IRQs (0-15).
940 */
941 ioapic = mp_find_ioapic(0);
942 if (ioapic < 0)
943 return;
944
945 intsrc.mpc_type = MP_INTSRC;
946 intsrc.mpc_irqflag = 0; /* Conforming */
947 intsrc.mpc_srcbus = MP_ISA_BUS;
948#ifdef CONFIG_X86_IO_APIC
949 intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;
950#endif
951 /*
952 * Use the default configuration for the IRQs 0-15. Unless
953 * overridden by (MADT) interrupt source override entries.
954 */
955 for (i = 0; i < 16; i++) {
956 int idx;
957
958 for (idx = 0; idx < mp_irq_entries; idx++) {
959 struct mpc_config_intsrc *irq = mp_irqs + idx;
960
961 /* Do we already have a mapping for this ISA IRQ? */
962 if (irq->mpc_srcbus == MP_ISA_BUS
963 && irq->mpc_srcbusirq == i)
964 break;
965
966 /* Do we already have a mapping for this IOAPIC pin */
967 if ((irq->mpc_dstapic == intsrc.mpc_dstapic) &&
968 (irq->mpc_dstirq == i))
969 break;
970 }
971
972 if (idx != mp_irq_entries) {
973 printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i);
974 continue; /* IRQ already used */
975 }
976
977 intsrc.mpc_irqtype = mp_INT;
978 intsrc.mpc_srcbusirq = i; /* Identity mapped */
979 intsrc.mpc_dstirq = i;
980
981 MP_intsrc_info(&intsrc);
982 }
983}
984
985int mp_register_gsi(u32 gsi, int triggering, int polarity)
986{
987 int ioapic;
988 int ioapic_pin;
989#ifdef CONFIG_X86_32
990#define MAX_GSI_NUM 4096
991#define IRQ_COMPRESSION_START 64
992
993 static int pci_irq = IRQ_COMPRESSION_START;
994 /*
995 * Mapping between Global System Interrupts, which
996 * represent all possible interrupts, and IRQs
997 * assigned to actual devices.
998 */
999 static int gsi_to_irq[MAX_GSI_NUM];
1000#else
1001
1002 if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
1003 return gsi;
1004#endif
1005
1006 /* Don't set up the ACPI SCI because it's already set up */
1007 if (acpi_gbl_FADT.sci_interrupt == gsi)
1008 return gsi;
1009
1010 ioapic = mp_find_ioapic(gsi);
1011 if (ioapic < 0) {
1012 printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
1013 return gsi;
1014 }
1015
1016 ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
1017
1018#ifdef CONFIG_X86_32
1019 if (ioapic_renumber_irq)
1020 gsi = ioapic_renumber_irq(ioapic, gsi);
1021#endif
1022
1023 /*
1024 * Avoid pin reprogramming. PRTs typically include entries
1025 * with redundant pin->gsi mappings (but unique PCI devices);
1026 * we only program the IOAPIC on the first.
1027 */
1028 if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
1029 printk(KERN_ERR "Invalid reference to IOAPIC pin "
1030 "%d-%d\n", mp_ioapic_routing[ioapic].apic_id,
1031 ioapic_pin);
1032 return gsi;
1033 }
1034 if (test_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed)) {
1035 Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
1036 mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
1037#ifdef CONFIG_X86_32
1038 return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]);
1039#else
1040 return gsi;
1041#endif
1042 }
1043
1044 set_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed);
1045#ifdef CONFIG_X86_32
1046 /*
1047 * For GSI >= 64, use IRQ compression
1048 */
1049 if ((gsi >= IRQ_COMPRESSION_START)
1050 && (triggering == ACPI_LEVEL_SENSITIVE)) {
1051 /*
1052 * For PCI devices assign IRQs in order, avoiding gaps
1053 * due to unused I/O APIC pins.
1054 */
1055 int irq = gsi;
1056 if (gsi < MAX_GSI_NUM) {
1057 /*
1058 * Retain the VIA chipset work-around (gsi > 15), but
1059 * avoid a problem where the 8254 timer (IRQ0) is setup
1060 * via an override (so it's not on pin 0 of the ioapic),
1061 * and at the same time, the pin 0 interrupt is a PCI
1062 * type. The gsi > 15 test could cause these two pins
1063 * to be shared as IRQ0, and they are not shareable.
1064 * So test for this condition, and if necessary, avoid
1065 * the pin collision.
1066 */
1067 gsi = pci_irq++;
1068 /*
1069 * Don't assign IRQ used by ACPI SCI
1070 */
1071 if (gsi == acpi_gbl_FADT.sci_interrupt)
1072 gsi = pci_irq++;
1073 gsi_to_irq[irq] = gsi;
1074 } else {
1075 printk(KERN_ERR "GSI %u is too high\n", gsi);
1076 return gsi;
1077 }
1078 }
1079#endif
1080 io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
1081 triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
1082 polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
1083 return gsi;
1084}
1085
1086#endif /* CONFIG_X86_IO_APIC */
1087#endif /* CONFIG_ACPI */