diff options
author | Jiang Liu <jiang.liu@linux.intel.com> | 2015-04-13 02:11:59 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2015-04-24 09:36:51 -0400 |
commit | d32932d02e1869be838cea3ace42467c360db377 (patch) | |
tree | 2cc299d5550cc3e2f160bb37f5e381369884b494 /arch/x86/kernel/apic/io_apic.c | |
parent | 96ed44b2d5e0e9d6e5b135e84ea5c8cd763ce861 (diff) |
x86/irq: Convert IOAPIC to use hierarchical irqdomain interfaces
Convert IOAPIC driver to support and use hierarchical irqdomain
interfaces. It's a little big, but would break bisecting if we split
it into multiple patches.
Fold in a patch from Andy Shevchenko <andriy.shevchenko@linux.intel.com>
to make it bisectable.
http://lkml.org/lkml/2014/12/10/622
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Tested-by: Joerg Roedel <jroedel@suse.de>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Sander Eikelenboom <linux@eikelenboom.it>
Cc: David Vrabel <david.vrabel@citrix.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: sfi-devel@simplefirmware.org
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dimitri Sivanich <sivanich@sgi.com>
Cc: Len Brown <len.brown@intel.com>
Cc: Pavel Machek <pavel@ucw.cz>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <robh@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: David Cohen <david.a.cohen@linux.intel.com>
Link: http://lkml.kernel.org/r/1428905519-23704-38-git-send-email-jiang.liu@linux.intel.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/kernel/apic/io_apic.c')
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 308 |
1 files changed, 211 insertions, 97 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index c8f786b5b91c..ba50f8d6f6b0 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -142,6 +142,11 @@ u32 mp_pin_to_gsi(int ioapic, int pin) | |||
142 | return mp_ioapic_gsi_routing(ioapic)->gsi_base + pin; | 142 | return mp_ioapic_gsi_routing(ioapic)->gsi_base + pin; |
143 | } | 143 | } |
144 | 144 | ||
145 | static inline bool mp_is_legacy_irq(int irq) | ||
146 | { | ||
147 | return irq >= 0 && irq < nr_legacy_irqs(); | ||
148 | } | ||
149 | |||
145 | /* | 150 | /* |
146 | * Initialize all legacy IRQs and all pins on the first IOAPIC | 151 | * Initialize all legacy IRQs and all pins on the first IOAPIC |
147 | * if we have legacy interrupt controller. Kernel boot option "pirq=" | 152 | * if we have legacy interrupt controller. Kernel boot option "pirq=" |
@@ -152,7 +157,7 @@ static inline int mp_init_irq_at_boot(int ioapic, int irq) | |||
152 | if (!nr_legacy_irqs()) | 157 | if (!nr_legacy_irqs()) |
153 | return 0; | 158 | return 0; |
154 | 159 | ||
155 | return ioapic == 0 || (irq >= 0 && irq < nr_legacy_irqs()); | 160 | return ioapic == 0 || mp_is_legacy_irq(irq); |
156 | } | 161 | } |
157 | 162 | ||
158 | static inline struct mp_pin_info *mp_pin_info(int ioapic_idx, int pin) | 163 | static inline struct mp_pin_info *mp_pin_info(int ioapic_idx, int pin) |
@@ -231,7 +236,7 @@ struct irq_pin_list { | |||
231 | 236 | ||
232 | static struct irq_pin_list *alloc_irq_pin_list(int node) | 237 | static struct irq_pin_list *alloc_irq_pin_list(int node) |
233 | { | 238 | { |
234 | return kzalloc_node(sizeof(struct irq_pin_list), GFP_KERNEL, node); | 239 | return kzalloc_node(sizeof(struct irq_pin_list), GFP_ATOMIC, node); |
235 | } | 240 | } |
236 | 241 | ||
237 | static void alloc_ioapic_saved_registers(int idx) | 242 | static void alloc_ioapic_saved_registers(int idx) |
@@ -560,6 +565,17 @@ void native_eoi_ioapic_pin(int apic, int pin, int vector) | |||
560 | } | 565 | } |
561 | } | 566 | } |
562 | 567 | ||
568 | void eoi_ioapic_pin(int vector, struct irq_cfg *cfg) | ||
569 | { | ||
570 | unsigned long flags; | ||
571 | struct irq_pin_list *entry; | ||
572 | |||
573 | raw_spin_lock_irqsave(&ioapic_lock, flags); | ||
574 | for_each_irq_pin(entry, cfg->irq_2_pin) | ||
575 | native_eoi_ioapic_pin(entry->apic, entry->pin, vector); | ||
576 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); | ||
577 | } | ||
578 | |||
563 | void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg) | 579 | void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg) |
564 | { | 580 | { |
565 | struct irq_pin_list *entry; | 581 | struct irq_pin_list *entry; |
@@ -603,9 +619,8 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin) | |||
603 | entry.trigger = IOAPIC_LEVEL; | 619 | entry.trigger = IOAPIC_LEVEL; |
604 | ioapic_write_entry(apic, pin, entry); | 620 | ioapic_write_entry(apic, pin, entry); |
605 | } | 621 | } |
606 | |||
607 | raw_spin_lock_irqsave(&ioapic_lock, flags); | 622 | raw_spin_lock_irqsave(&ioapic_lock, flags); |
608 | x86_io_apic_ops.eoi_ioapic_pin(apic, pin, entry.vector); | 623 | native_eoi_ioapic_pin(apic, pin, entry.vector); |
609 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); | 624 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
610 | } | 625 | } |
611 | 626 | ||
@@ -1023,95 +1038,121 @@ static bool mp_check_pin_attr(int irq, struct irq_alloc_info *info) | |||
1023 | data->polarity == info->ioapic_polarity; | 1038 | data->polarity == info->ioapic_polarity; |
1024 | } | 1039 | } |
1025 | 1040 | ||
1026 | static int alloc_irq_from_domain(struct irq_domain *domain, u32 gsi, int pin, | 1041 | static int alloc_irq_from_domain(struct irq_domain *domain, int ioapic, u32 gsi, |
1027 | struct irq_alloc_info *info) | 1042 | struct irq_alloc_info *info) |
1028 | { | 1043 | { |
1044 | bool legacy = false; | ||
1029 | int irq = -1; | 1045 | int irq = -1; |
1030 | int ioapic = mp_irqdomain_ioapic_idx(domain); | ||
1031 | int type = ioapics[ioapic].irqdomain_cfg.type; | 1046 | int type = ioapics[ioapic].irqdomain_cfg.type; |
1032 | 1047 | ||
1033 | switch (type) { | 1048 | switch (type) { |
1034 | case IOAPIC_DOMAIN_LEGACY: | 1049 | case IOAPIC_DOMAIN_LEGACY: |
1035 | /* | 1050 | /* |
1036 | * Dynamically allocate IRQ number for non-ISA IRQs in the first 16 | 1051 | * Dynamically allocate IRQ number for non-ISA IRQs in the first |
1037 | * GSIs on some weird platforms. | 1052 | * 16 GSIs on some weird platforms. |
1038 | */ | 1053 | */ |
1039 | if (gsi < nr_legacy_irqs()) | 1054 | if (!ioapic_initialized || gsi >= nr_legacy_irqs()) |
1040 | irq = irq_create_mapping(domain, pin); | ||
1041 | else if (irq_create_strict_mappings(domain, gsi, pin, 1) == 0) | ||
1042 | irq = gsi; | 1055 | irq = gsi; |
1056 | legacy = mp_is_legacy_irq(irq); | ||
1043 | break; | 1057 | break; |
1044 | case IOAPIC_DOMAIN_STRICT: | 1058 | case IOAPIC_DOMAIN_STRICT: |
1045 | if (irq_create_strict_mappings(domain, gsi, pin, 1) == 0) | 1059 | irq = gsi; |
1046 | irq = gsi; | ||
1047 | break; | 1060 | break; |
1048 | case IOAPIC_DOMAIN_DYNAMIC: | 1061 | case IOAPIC_DOMAIN_DYNAMIC: |
1049 | irq = irq_create_mapping(domain, pin); | ||
1050 | break; | 1062 | break; |
1051 | default: | 1063 | default: |
1052 | WARN(1, "ioapic: unknown irqdomain type %d\n", type); | 1064 | WARN(1, "ioapic: unknown irqdomain type %d\n", type); |
1053 | break; | 1065 | return -1; |
1066 | } | ||
1067 | |||
1068 | return __irq_domain_alloc_irqs(domain, irq, 1, | ||
1069 | ioapic_alloc_attr_node(info), | ||
1070 | info, legacy); | ||
1071 | } | ||
1072 | |||
1073 | /* | ||
1074 | * Need special handling for ISA IRQs because there may be multiple IOAPIC pins | ||
1075 | * sharing the same ISA IRQ number and irqdomain only supports 1:1 mapping | ||
1076 | * between IOAPIC pin and IRQ number. A typical IOAPIC has 24 pins, pin 0-15 are | ||
1077 | * used for legacy IRQs and pin 16-23 are used for PCI IRQs (PIRQ A-H). | ||
1078 | * When ACPI is disabled, only legacy IRQ numbers (IRQ0-15) are available, and | ||
1079 | * some BIOSes may use MP Interrupt Source records to override IRQ numbers for | ||
1080 | * PIRQs instead of reprogramming the interrupt routing logic. Thus there may be | ||
1081 | * multiple pins sharing the same legacy IRQ number when ACPI is disabled. | ||
1082 | */ | ||
1083 | static int alloc_isa_irq_from_domain(struct irq_domain *domain, | ||
1084 | int irq, int ioapic, int pin, | ||
1085 | struct irq_alloc_info *info) | ||
1086 | { | ||
1087 | struct mp_chip_data *data; | ||
1088 | struct irq_data *irq_data = irq_get_irq_data(irq); | ||
1089 | int node = ioapic_alloc_attr_node(info); | ||
1090 | |||
1091 | /* | ||
1092 | * Legacy ISA IRQ has already been allocated, just add pin to | ||
1093 | * the pin list assoicated with this IRQ and program the IOAPIC | ||
1094 | * entry. The IOAPIC entry | ||
1095 | */ | ||
1096 | if (irq_data && irq_data->parent_data) { | ||
1097 | struct irq_cfg *cfg = irqd_cfg(irq_data); | ||
1098 | |||
1099 | if (!mp_check_pin_attr(irq, info)) | ||
1100 | return -EBUSY; | ||
1101 | if (__add_pin_to_irq_node(cfg, node, ioapic, info->ioapic_pin)) | ||
1102 | return -ENOMEM; | ||
1103 | } else { | ||
1104 | irq = __irq_domain_alloc_irqs(domain, irq, 1, node, info, true); | ||
1105 | if (irq >= 0) { | ||
1106 | irq_data = irq_domain_get_irq_data(domain, irq); | ||
1107 | data = irq_data->chip_data; | ||
1108 | data->isa_irq = true; | ||
1109 | } | ||
1054 | } | 1110 | } |
1055 | 1111 | ||
1056 | return irq > 0 ? irq : -1; | 1112 | return irq; |
1057 | } | 1113 | } |
1058 | 1114 | ||
1059 | static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin, | 1115 | static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin, |
1060 | unsigned int flags, struct irq_alloc_info *info) | 1116 | unsigned int flags, struct irq_alloc_info *info) |
1061 | { | 1117 | { |
1062 | int irq; | 1118 | int irq; |
1119 | bool legacy = false; | ||
1120 | struct irq_alloc_info tmp; | ||
1121 | struct mp_chip_data *data; | ||
1063 | struct irq_domain *domain = mp_ioapic_irqdomain(ioapic); | 1122 | struct irq_domain *domain = mp_ioapic_irqdomain(ioapic); |
1064 | struct mp_pin_info *pinfo = mp_pin_info(ioapic, pin); | ||
1065 | 1123 | ||
1066 | if (!domain) | 1124 | if (!domain) |
1067 | return -1; | 1125 | return -ENOSYS; |
1068 | 1126 | ||
1069 | mutex_lock(&ioapic_mutex); | ||
1070 | |||
1071 | /* | ||
1072 | * Don't use irqdomain to manage ISA IRQs because there may be | ||
1073 | * multiple IOAPIC pins sharing the same ISA IRQ number and | ||
1074 | * irqdomain only supports 1:1 mapping between IOAPIC pin and | ||
1075 | * IRQ number. A typical IOAPIC has 24 pins, pin 0-15 are used | ||
1076 | * for legacy IRQs and pin 16-23 are used for PCI IRQs (PIRQ A-H). | ||
1077 | * When ACPI is disabled, only legacy IRQ numbers (IRQ0-15) are | ||
1078 | * available, and some BIOSes may use MP Interrupt Source records | ||
1079 | * to override IRQ numbers for PIRQs instead of reprogramming | ||
1080 | * the interrupt routing logic. Thus there may be multiple pins | ||
1081 | * sharing the same legacy IRQ number when ACPI is disabled. | ||
1082 | */ | ||
1083 | if (idx >= 0 && test_bit(mp_irqs[idx].srcbus, mp_bus_not_pci)) { | 1127 | if (idx >= 0 && test_bit(mp_irqs[idx].srcbus, mp_bus_not_pci)) { |
1084 | irq = mp_irqs[idx].srcbusirq; | 1128 | irq = mp_irqs[idx].srcbusirq; |
1085 | if (flags & IOAPIC_MAP_ALLOC) { | 1129 | legacy = mp_is_legacy_irq(irq); |
1086 | if (pinfo->count == 0 && | 1130 | } |
1087 | mp_irqdomain_map(domain, irq, pin) != 0) | ||
1088 | irq = -1; | ||
1089 | 1131 | ||
1090 | /* special handling for timer IRQ0 */ | 1132 | mutex_lock(&ioapic_mutex); |
1133 | if (!(flags & IOAPIC_MAP_ALLOC)) { | ||
1134 | if (!legacy) { | ||
1135 | irq = irq_find_mapping(domain, pin); | ||
1091 | if (irq == 0) | 1136 | if (irq == 0) |
1092 | pinfo->count++; | 1137 | irq = -ENOENT; |
1093 | } | 1138 | } |
1094 | } else { | 1139 | } else { |
1095 | irq = irq_find_mapping(domain, pin); | 1140 | ioapic_copy_alloc_attr(&tmp, info, gsi, ioapic, pin); |
1096 | if (irq <= 0 && (flags & IOAPIC_MAP_ALLOC)) | 1141 | if (legacy) |
1097 | irq = alloc_irq_from_domain(domain, gsi, pin, info); | 1142 | irq = alloc_isa_irq_from_domain(domain, irq, |
1098 | } | 1143 | ioapic, pin, &tmp); |
1099 | 1144 | else if ((irq = irq_find_mapping(domain, pin)) == 0) | |
1100 | if (flags & IOAPIC_MAP_ALLOC) { | 1145 | irq = alloc_irq_from_domain(domain, ioapic, gsi, &tmp); |
1101 | /* special handling for legacy IRQs */ | 1146 | else if (!mp_check_pin_attr(irq, &tmp)) |
1102 | if (irq < nr_legacy_irqs() && pinfo->count == 1 && | 1147 | irq = -EBUSY; |
1103 | mp_irqdomain_map(domain, irq, pin) != 0) | 1148 | if (irq >= 0) { |
1104 | irq = -1; | 1149 | data = irq_get_chip_data(irq); |
1105 | 1150 | data->count++; | |
1106 | if (irq > 0) | 1151 | } |
1107 | pinfo->count++; | ||
1108 | else if (pinfo->count == 0) | ||
1109 | pinfo->set = 0; | ||
1110 | } | 1152 | } |
1111 | |||
1112 | mutex_unlock(&ioapic_mutex); | 1153 | mutex_unlock(&ioapic_mutex); |
1113 | 1154 | ||
1114 | return irq > 0 ? irq : -1; | 1155 | return irq; |
1115 | } | 1156 | } |
1116 | 1157 | ||
1117 | static int pin_2_irq(int idx, int ioapic, int pin, unsigned int flags) | 1158 | static int pin_2_irq(int idx, int ioapic, int pin, unsigned int flags) |
@@ -1166,26 +1207,19 @@ int mp_map_gsi_to_irq(u32 gsi, unsigned int flags, | |||
1166 | 1207 | ||
1167 | void mp_unmap_irq(int irq) | 1208 | void mp_unmap_irq(int irq) |
1168 | { | 1209 | { |
1169 | struct irq_data *data = irq_get_irq_data(irq); | 1210 | struct irq_data *irq_data = irq_get_irq_data(irq); |
1170 | struct mp_pin_info *info; | 1211 | struct mp_chip_data *data; |
1171 | int ioapic, pin; | ||
1172 | 1212 | ||
1173 | if (!data || !data->domain) | 1213 | if (!irq_data || !irq_data->domain) |
1174 | return; | 1214 | return; |
1175 | 1215 | ||
1176 | ioapic = (int)(long)data->domain->host_data; | 1216 | data = irq_data->chip_data; |
1177 | pin = (int)data->hwirq; | 1217 | if (!data || data->isa_irq) |
1178 | info = mp_pin_info(ioapic, pin); | 1218 | return; |
1179 | 1219 | ||
1180 | mutex_lock(&ioapic_mutex); | 1220 | mutex_lock(&ioapic_mutex); |
1181 | if (--info->count == 0) { | 1221 | if (--data->count == 0) |
1182 | info->set = 0; | 1222 | irq_domain_free_irqs(irq, 1); |
1183 | if (irq < nr_legacy_irqs() && | ||
1184 | ioapics[ioapic].irqdomain_cfg.type == IOAPIC_DOMAIN_LEGACY) | ||
1185 | mp_irqdomain_unmap(data->domain, irq); | ||
1186 | else | ||
1187 | irq_dispose_mapping(irq); | ||
1188 | } | ||
1189 | mutex_unlock(&ioapic_mutex); | 1223 | mutex_unlock(&ioapic_mutex); |
1190 | } | 1224 | } |
1191 | 1225 | ||
@@ -1252,7 +1286,7 @@ out: | |||
1252 | } | 1286 | } |
1253 | EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector); | 1287 | EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector); |
1254 | 1288 | ||
1255 | static struct irq_chip ioapic_chip; | 1289 | static struct irq_chip ioapic_chip, ioapic_ir_chip; |
1256 | 1290 | ||
1257 | #ifdef CONFIG_X86_32 | 1291 | #ifdef CONFIG_X86_32 |
1258 | static inline int IO_APIC_irq_trigger(int irq) | 1292 | static inline int IO_APIC_irq_trigger(int irq) |
@@ -1595,7 +1629,7 @@ void __init print_IO_APICs(void) | |||
1595 | struct irq_pin_list *entry; | 1629 | struct irq_pin_list *entry; |
1596 | 1630 | ||
1597 | chip = irq_get_chip(irq); | 1631 | chip = irq_get_chip(irq); |
1598 | if (chip != &ioapic_chip) | 1632 | if (chip != &ioapic_chip && chip != &ioapic_ir_chip) |
1599 | continue; | 1633 | continue; |
1600 | 1634 | ||
1601 | cfg = irq_cfg(irq); | 1635 | cfg = irq_cfg(irq); |
@@ -2057,12 +2091,12 @@ static inline void ioapic_irqd_unmask(struct irq_data *data, | |||
2057 | } | 2091 | } |
2058 | #endif | 2092 | #endif |
2059 | 2093 | ||
2060 | static void ack_ioapic_level(struct irq_data *data) | 2094 | static void ioapic_ack_level(struct irq_data *data) |
2061 | { | 2095 | { |
2062 | struct irq_cfg *cfg = irqd_cfg(data); | 2096 | struct irq_cfg *cfg = irqd_cfg(data); |
2063 | int i, irq = data->irq; | ||
2064 | unsigned long v; | 2097 | unsigned long v; |
2065 | bool masked; | 2098 | bool masked; |
2099 | int i; | ||
2066 | 2100 | ||
2067 | irq_complete_move(cfg); | 2101 | irq_complete_move(cfg); |
2068 | masked = ioapic_irqd_mask(data, cfg); | 2102 | masked = ioapic_irqd_mask(data, cfg); |
@@ -2117,22 +2151,70 @@ static void ack_ioapic_level(struct irq_data *data) | |||
2117 | */ | 2151 | */ |
2118 | if (!(v & (1 << (i & 0x1f)))) { | 2152 | if (!(v & (1 << (i & 0x1f)))) { |
2119 | atomic_inc(&irq_mis_count); | 2153 | atomic_inc(&irq_mis_count); |
2120 | 2154 | eoi_ioapic_pin(cfg->vector, cfg); | |
2121 | eoi_ioapic_irq(irq, cfg); | ||
2122 | } | 2155 | } |
2123 | 2156 | ||
2124 | ioapic_irqd_unmask(data, cfg, masked); | 2157 | ioapic_irqd_unmask(data, cfg, masked); |
2125 | } | 2158 | } |
2126 | 2159 | ||
2160 | static void ioapic_ir_ack_level(struct irq_data *irq_data) | ||
2161 | { | ||
2162 | struct mp_chip_data *data = irq_data->chip_data; | ||
2163 | |||
2164 | /* | ||
2165 | * Intr-remapping uses pin number as the virtual vector | ||
2166 | * in the RTE. Actual vector is programmed in | ||
2167 | * intr-remapping table entry. Hence for the io-apic | ||
2168 | * EOI we use the pin number. | ||
2169 | */ | ||
2170 | ack_APIC_irq(); | ||
2171 | eoi_ioapic_pin(data->entry.vector, irqd_cfg(irq_data)); | ||
2172 | } | ||
2173 | |||
2174 | static int ioapic_set_affinity(struct irq_data *irq_data, | ||
2175 | const struct cpumask *mask, bool force) | ||
2176 | { | ||
2177 | struct irq_data *parent = irq_data->parent_data; | ||
2178 | struct mp_chip_data *data = irq_data->chip_data; | ||
2179 | unsigned int dest, irq = irq_data->irq; | ||
2180 | struct irq_cfg *cfg; | ||
2181 | unsigned long flags; | ||
2182 | int ret; | ||
2183 | |||
2184 | ret = parent->chip->irq_set_affinity(parent, mask, force); | ||
2185 | raw_spin_lock_irqsave(&ioapic_lock, flags); | ||
2186 | if (ret >= 0 && ret != IRQ_SET_MASK_OK_DONE) { | ||
2187 | cfg = irqd_cfg(irq_data); | ||
2188 | data->entry.dest = cfg->dest_apicid; | ||
2189 | data->entry.vector = cfg->vector; | ||
2190 | /* Only the high 8 bits are valid. */ | ||
2191 | dest = SET_APIC_LOGICAL_ID(cfg->dest_apicid); | ||
2192 | __target_IO_APIC_irq(irq, dest, cfg); | ||
2193 | } | ||
2194 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); | ||
2195 | |||
2196 | return ret; | ||
2197 | } | ||
2198 | |||
2127 | static struct irq_chip ioapic_chip __read_mostly = { | 2199 | static struct irq_chip ioapic_chip __read_mostly = { |
2128 | .name = "IO-APIC", | 2200 | .name = "IO-APIC", |
2129 | .irq_startup = startup_ioapic_irq, | 2201 | .irq_startup = startup_ioapic_irq, |
2130 | .irq_mask = mask_ioapic_irq, | 2202 | .irq_mask = mask_ioapic_irq, |
2131 | .irq_unmask = unmask_ioapic_irq, | 2203 | .irq_unmask = unmask_ioapic_irq, |
2132 | .irq_ack = apic_ack_edge, | 2204 | .irq_ack = irq_chip_ack_parent, |
2133 | .irq_eoi = ack_ioapic_level, | 2205 | .irq_eoi = ioapic_ack_level, |
2134 | .irq_set_affinity = native_ioapic_set_affinity, | 2206 | .irq_set_affinity = ioapic_set_affinity, |
2135 | .irq_retrigger = apic_retrigger_irq, | 2207 | .flags = IRQCHIP_SKIP_SET_WAKE, |
2208 | }; | ||
2209 | |||
2210 | static struct irq_chip ioapic_ir_chip __read_mostly = { | ||
2211 | .name = "IR-IO-APIC", | ||
2212 | .irq_startup = startup_ioapic_irq, | ||
2213 | .irq_mask = mask_ioapic_irq, | ||
2214 | .irq_unmask = unmask_ioapic_irq, | ||
2215 | .irq_ack = irq_chip_ack_parent, | ||
2216 | .irq_eoi = ioapic_ir_ack_level, | ||
2217 | .irq_set_affinity = ioapic_set_affinity, | ||
2136 | .flags = IRQCHIP_SKIP_SET_WAKE, | 2218 | .flags = IRQCHIP_SKIP_SET_WAKE, |
2137 | }; | 2219 | }; |
2138 | 2220 | ||
@@ -2265,6 +2347,24 @@ static int __init disable_timer_pin_setup(char *arg) | |||
2265 | } | 2347 | } |
2266 | early_param("disable_timer_pin_1", disable_timer_pin_setup); | 2348 | early_param("disable_timer_pin_1", disable_timer_pin_setup); |
2267 | 2349 | ||
2350 | static int mp_alloc_timer_irq(int ioapic, int pin) | ||
2351 | { | ||
2352 | int irq = -1; | ||
2353 | struct irq_alloc_info info; | ||
2354 | struct irq_domain *domain = mp_ioapic_irqdomain(ioapic); | ||
2355 | |||
2356 | if (domain) { | ||
2357 | ioapic_set_alloc_attr(&info, NUMA_NO_NODE, 0, 0); | ||
2358 | info.ioapic_id = mpc_ioapic_id(ioapic); | ||
2359 | info.ioapic_pin = pin; | ||
2360 | mutex_lock(&ioapic_mutex); | ||
2361 | irq = alloc_isa_irq_from_domain(domain, 0, ioapic, pin, &info); | ||
2362 | mutex_unlock(&ioapic_mutex); | ||
2363 | } | ||
2364 | |||
2365 | return irq; | ||
2366 | } | ||
2367 | |||
2268 | /* | 2368 | /* |
2269 | * This code may look a bit paranoid, but it's supposed to cooperate with | 2369 | * This code may look a bit paranoid, but it's supposed to cooperate with |
2270 | * a wide range of boards and BIOS bugs. Fortunately only the timer IRQ | 2370 | * a wide range of boards and BIOS bugs. Fortunately only the timer IRQ |
@@ -2287,7 +2387,6 @@ static inline void __init check_timer(void) | |||
2287 | * get/set the timer IRQ vector: | 2387 | * get/set the timer IRQ vector: |
2288 | */ | 2388 | */ |
2289 | legacy_pic->mask(0); | 2389 | legacy_pic->mask(0); |
2290 | assign_irq_vector(0, cfg, apic->target_cpus()); | ||
2291 | 2390 | ||
2292 | /* | 2391 | /* |
2293 | * As IRQ0 is to be enabled in the 8259A, the virtual | 2392 | * As IRQ0 is to be enabled in the 8259A, the virtual |
@@ -2328,15 +2427,12 @@ static inline void __init check_timer(void) | |||
2328 | } | 2427 | } |
2329 | 2428 | ||
2330 | if (pin1 != -1) { | 2429 | if (pin1 != -1) { |
2331 | /* | 2430 | /* Ok, does IRQ0 through the IOAPIC work? */ |
2332 | * Ok, does IRQ0 through the IOAPIC work? | ||
2333 | */ | ||
2334 | if (no_pin1) { | 2431 | if (no_pin1) { |
2335 | add_pin_to_irq_node(cfg, node, apic1, pin1); | 2432 | mp_alloc_timer_irq(apic1, pin1); |
2336 | setup_timer_IRQ0_pin(apic1, pin1, cfg->vector); | ||
2337 | } else { | 2433 | } else { |
2338 | /* for edge trigger, setup_ioapic_irq already | 2434 | /* |
2339 | * leave it unmasked. | 2435 | * for edge trigger, it's already unmasked, |
2340 | * so only need to unmask if it is level-trigger | 2436 | * so only need to unmask if it is level-trigger |
2341 | * do we really have level trigger timer? | 2437 | * do we really have level trigger timer? |
2342 | */ | 2438 | */ |
@@ -2345,6 +2441,7 @@ static inline void __init check_timer(void) | |||
2345 | if (idx != -1 && irq_trigger(idx)) | 2441 | if (idx != -1 && irq_trigger(idx)) |
2346 | unmask_ioapic(cfg); | 2442 | unmask_ioapic(cfg); |
2347 | } | 2443 | } |
2444 | irq_domain_activate_irq(irq_get_irq_data(0)); | ||
2348 | if (timer_irq_works()) { | 2445 | if (timer_irq_works()) { |
2349 | if (disable_timer_pin_1 > 0) | 2446 | if (disable_timer_pin_1 > 0) |
2350 | clear_IO_APIC_pin(0, pin1); | 2447 | clear_IO_APIC_pin(0, pin1); |
@@ -2365,7 +2462,7 @@ static inline void __init check_timer(void) | |||
2365 | * legacy devices should be connected to IO APIC #0 | 2462 | * legacy devices should be connected to IO APIC #0 |
2366 | */ | 2463 | */ |
2367 | replace_pin_at_irq_node(cfg, node, apic1, pin1, apic2, pin2); | 2464 | replace_pin_at_irq_node(cfg, node, apic1, pin1, apic2, pin2); |
2368 | setup_timer_IRQ0_pin(apic2, pin2, cfg->vector); | 2465 | irq_domain_activate_irq(irq_get_irq_data(0)); |
2369 | legacy_pic->unmask(0); | 2466 | legacy_pic->unmask(0); |
2370 | if (timer_irq_works()) { | 2467 | if (timer_irq_works()) { |
2371 | apic_printk(APIC_QUIET, KERN_INFO "....... works.\n"); | 2468 | apic_printk(APIC_QUIET, KERN_INFO "....... works.\n"); |
@@ -2443,6 +2540,8 @@ out: | |||
2443 | static int mp_irqdomain_create(int ioapic) | 2540 | static int mp_irqdomain_create(int ioapic) |
2444 | { | 2541 | { |
2445 | size_t size; | 2542 | size_t size; |
2543 | struct irq_alloc_info info; | ||
2544 | struct irq_domain *parent; | ||
2446 | int hwirqs = mp_ioapic_pin_count(ioapic); | 2545 | int hwirqs = mp_ioapic_pin_count(ioapic); |
2447 | struct ioapic *ip = &ioapics[ioapic]; | 2546 | struct ioapic *ip = &ioapics[ioapic]; |
2448 | struct ioapic_domain_cfg *cfg = &ip->irqdomain_cfg; | 2547 | struct ioapic_domain_cfg *cfg = &ip->irqdomain_cfg; |
@@ -2456,9 +2555,18 @@ static int mp_irqdomain_create(int ioapic) | |||
2456 | if (cfg->type == IOAPIC_DOMAIN_INVALID) | 2555 | if (cfg->type == IOAPIC_DOMAIN_INVALID) |
2457 | return 0; | 2556 | return 0; |
2458 | 2557 | ||
2558 | init_irq_alloc_info(&info, NULL); | ||
2559 | info.type = X86_IRQ_ALLOC_TYPE_IOAPIC; | ||
2560 | info.ioapic_id = mpc_ioapic_id(ioapic); | ||
2561 | parent = irq_remapping_get_ir_irq_domain(&info); | ||
2562 | if (!parent) | ||
2563 | parent = x86_vector_domain; | ||
2564 | |||
2459 | ip->irqdomain = irq_domain_add_linear(cfg->dev, hwirqs, cfg->ops, | 2565 | ip->irqdomain = irq_domain_add_linear(cfg->dev, hwirqs, cfg->ops, |
2460 | (void *)(long)ioapic); | 2566 | (void *)(long)ioapic); |
2461 | if(!ip->irqdomain) { | 2567 | if (ip->irqdomain) { |
2568 | ip->irqdomain->parent = parent; | ||
2569 | } else { | ||
2462 | kfree(ip->pin_info); | 2570 | kfree(ip->pin_info); |
2463 | ip->pin_info = NULL; | 2571 | ip->pin_info = NULL; |
2464 | return -ENOMEM; | 2572 | return -ENOMEM; |
@@ -3072,7 +3180,6 @@ int mp_unregister_ioapic(u32 gsi_base) | |||
3072 | { | 3180 | { |
3073 | int ioapic, pin; | 3181 | int ioapic, pin; |
3074 | int found = 0; | 3182 | int found = 0; |
3075 | struct mp_pin_info *pin_info; | ||
3076 | 3183 | ||
3077 | for_each_ioapic(ioapic) | 3184 | for_each_ioapic(ioapic) |
3078 | if (ioapics[ioapic].gsi_config.gsi_base == gsi_base) { | 3185 | if (ioapics[ioapic].gsi_config.gsi_base == gsi_base) { |
@@ -3085,11 +3192,17 @@ int mp_unregister_ioapic(u32 gsi_base) | |||
3085 | } | 3192 | } |
3086 | 3193 | ||
3087 | for_each_pin(ioapic, pin) { | 3194 | for_each_pin(ioapic, pin) { |
3088 | pin_info = mp_pin_info(ioapic, pin); | 3195 | u32 gsi = mp_pin_to_gsi(ioapic, pin); |
3089 | if (pin_info->count) { | 3196 | int irq = mp_map_gsi_to_irq(gsi, 0, NULL); |
3090 | pr_warn("pin%d on IOAPIC%d is still in use.\n", | 3197 | struct mp_chip_data *data; |
3091 | pin, ioapic); | 3198 | |
3092 | return -EBUSY; | 3199 | if (irq >= 0) { |
3200 | data = irq_get_chip_data(irq); | ||
3201 | if (data && data->count) { | ||
3202 | pr_warn("pin%d on IOAPIC%d is still in use.\n", | ||
3203 | pin, ioapic); | ||
3204 | return -EBUSY; | ||
3205 | } | ||
3093 | } | 3206 | } |
3094 | } | 3207 | } |
3095 | 3208 | ||
@@ -3241,7 +3354,8 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq, | |||
3241 | } | 3354 | } |
3242 | 3355 | ||
3243 | irq_data->hwirq = info->ioapic_pin; | 3356 | irq_data->hwirq = info->ioapic_pin; |
3244 | irq_data->chip = &ioapic_chip; | 3357 | irq_data->chip = (domain->parent == x86_vector_domain) ? |
3358 | &ioapic_chip : &ioapic_ir_chip; | ||
3245 | irq_data->chip_data = data; | 3359 | irq_data->chip_data = data; |
3246 | mp_irqdomain_get_attr(mp_pin_to_gsi(ioapic, pin), data, info); | 3360 | mp_irqdomain_get_attr(mp_pin_to_gsi(ioapic, pin), data, info); |
3247 | 3361 | ||