aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/io_apic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/io_apic.c')
-rw-r--r--arch/x86/kernel/io_apic.c199
1 files changed, 74 insertions, 125 deletions
diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c
index e03bc0f87eef..6f80dc2f137e 100644
--- a/arch/x86/kernel/io_apic.c
+++ b/arch/x86/kernel/io_apic.c
@@ -107,7 +107,6 @@ static int __init parse_noapic(char *str)
107} 107}
108early_param("noapic", parse_noapic); 108early_param("noapic", parse_noapic);
109 109
110struct irq_cfg;
111struct irq_pin_list; 110struct irq_pin_list;
112struct irq_cfg { 111struct irq_cfg {
113 unsigned int irq; 112 unsigned int irq;
@@ -120,7 +119,7 @@ struct irq_cfg {
120}; 119};
121 120
122/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */ 121/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
123static struct irq_cfg irq_cfg_legacy[] __initdata = { 122static struct irq_cfg irq_cfgx[NR_IRQS] = {
124 [0] = { .irq = 0, .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR, }, 123 [0] = { .irq = 0, .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR, },
125 [1] = { .irq = 1, .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR, }, 124 [1] = { .irq = 1, .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR, },
126 [2] = { .irq = 2, .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR, }, 125 [2] = { .irq = 2, .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR, },
@@ -139,49 +138,27 @@ static struct irq_cfg irq_cfg_legacy[] __initdata = {
139 [15] = { .irq = 15, .domain = CPU_MASK_ALL, .vector = IRQ15_VECTOR, }, 138 [15] = { .irq = 15, .domain = CPU_MASK_ALL, .vector = IRQ15_VECTOR, },
140}; 139};
141 140
142static struct irq_cfg irq_cfg_init = { .irq = -1U, };
143
144static void init_one_irq_cfg(struct irq_cfg *cfg)
145{
146 memcpy(cfg, &irq_cfg_init, sizeof(struct irq_cfg));
147}
148
149static struct irq_cfg *irq_cfgx;
150
151static void __init init_work(void *data)
152{
153 struct dyn_array *da = data;
154 struct irq_cfg *cfg;
155 int legacy_count;
156 int i;
157
158 cfg = *da->name;
159
160 memcpy(cfg, irq_cfg_legacy, sizeof(irq_cfg_legacy));
161
162 legacy_count = ARRAY_SIZE(irq_cfg_legacy);
163 for (i = legacy_count; i < *da->nr; i++)
164 init_one_irq_cfg(&cfg[i]);
165}
166
167#define for_each_irq_cfg(irq, cfg) \ 141#define for_each_irq_cfg(irq, cfg) \
168 for (irq = 0, cfg = &irq_cfgx[irq]; irq < nr_irqs; irq++, cfg = &irq_cfgx[irq]) 142 for (irq = 0, cfg = irq_cfgx; irq < nr_irqs; irq++, cfg++)
169 143
170DEFINE_DYN_ARRAY(irq_cfgx, sizeof(struct irq_cfg), nr_irqs, PAGE_SIZE, init_work); 144static struct irq_cfg *irq_cfg(unsigned int irq)
171
172struct irq_cfg *irq_cfg(unsigned int irq)
173{ 145{
174 if (irq < nr_irqs) 146 return irq < nr_irqs ? irq_cfgx + irq : NULL;
175 return &irq_cfgx[irq];
176
177 return NULL;
178} 147}
179struct irq_cfg *irq_cfg_alloc(unsigned int irq) 148
149static struct irq_cfg *irq_cfg_alloc(unsigned int irq)
180{ 150{
181 return irq_cfg(irq); 151 return irq_cfg(irq);
182} 152}
183 153
184/* 154/*
155 * Rough estimation of how many shared IRQs there are, can be changed
156 * anytime.
157 */
158#define MAX_PLUS_SHARED_IRQS NR_IRQS
159#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
160
161/*
185 * This is performance-critical, we want to do it O(1) 162 * This is performance-critical, we want to do it O(1)
186 * 163 *
187 * the indexing order of this array favors 1:1 mappings 164 * the indexing order of this array favors 1:1 mappings
@@ -193,59 +170,29 @@ struct irq_pin_list {
193 struct irq_pin_list *next; 170 struct irq_pin_list *next;
194}; 171};
195 172
196static struct irq_pin_list *irq_2_pin_head; 173static struct irq_pin_list irq_2_pin_head[PIN_MAP_SIZE];
197/* fill one page ? */
198static int nr_irq_2_pin = 0x100;
199static struct irq_pin_list *irq_2_pin_ptr; 174static struct irq_pin_list *irq_2_pin_ptr;
200static void __init irq_2_pin_init_work(void *data) 175
176static void __init irq_2_pin_init(void)
201{ 177{
202 struct dyn_array *da = data; 178 struct irq_pin_list *pin = irq_2_pin_head;
203 struct irq_pin_list *pin;
204 int i; 179 int i;
205 180
206 pin = *da->name; 181 for (i = 1; i < PIN_MAP_SIZE; i++)
207
208 for (i = 1; i < *da->nr; i++)
209 pin[i-1].next = &pin[i]; 182 pin[i-1].next = &pin[i];
210 183
211 irq_2_pin_ptr = &pin[0]; 184 irq_2_pin_ptr = &pin[0];
212} 185}
213DEFINE_DYN_ARRAY(irq_2_pin_head, sizeof(struct irq_pin_list), nr_irq_2_pin, PAGE_SIZE, irq_2_pin_init_work);
214 186
215static struct irq_pin_list *get_one_free_irq_2_pin(void) 187static struct irq_pin_list *get_one_free_irq_2_pin(void)
216{ 188{
217 struct irq_pin_list *pin; 189 struct irq_pin_list *pin = irq_2_pin_ptr;
218 int i;
219
220 pin = irq_2_pin_ptr;
221
222 if (pin) {
223 irq_2_pin_ptr = pin->next;
224 pin->next = NULL;
225 return pin;
226 }
227
228 /*
229 * we run out of pre-allocate ones, allocate more
230 */
231 printk(KERN_DEBUG "try to get more irq_2_pin %d\n", nr_irq_2_pin);
232
233 if (after_bootmem)
234 pin = kzalloc(sizeof(struct irq_pin_list)*nr_irq_2_pin,
235 GFP_ATOMIC);
236 else
237 pin = __alloc_bootmem_nopanic(sizeof(struct irq_pin_list) *
238 nr_irq_2_pin, PAGE_SIZE, 0);
239 190
240 if (!pin) 191 if (!pin)
241 panic("can not get more irq_2_pin\n"); 192 panic("can not get more irq_2_pin\n");
242 193
243 for (i = 1; i < nr_irq_2_pin; i++)
244 pin[i-1].next = &pin[i];
245
246 irq_2_pin_ptr = pin->next; 194 irq_2_pin_ptr = pin->next;
247 pin->next = NULL; 195 pin->next = NULL;
248
249 return pin; 196 return pin;
250} 197}
251 198
@@ -284,8 +231,9 @@ static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned i
284static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value) 231static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
285{ 232{
286 struct io_apic __iomem *io_apic = io_apic_base(apic); 233 struct io_apic __iomem *io_apic = io_apic_base(apic);
287 if (sis_apic_bug) 234
288 writel(reg, &io_apic->index); 235 if (sis_apic_bug)
236 writel(reg, &io_apic->index);
289 writel(value, &io_apic->data); 237 writel(value, &io_apic->data);
290} 238}
291 239
@@ -1044,11 +992,11 @@ static int pin_2_irq(int idx, int apic, int pin)
1044 while (i < apic) 992 while (i < apic)
1045 irq += nr_ioapic_registers[i++]; 993 irq += nr_ioapic_registers[i++];
1046 irq += pin; 994 irq += pin;
1047 /* 995 /*
1048 * For MPS mode, so far only needed by ES7000 platform 996 * For MPS mode, so far only needed by ES7000 platform
1049 */ 997 */
1050 if (ioapic_renumber_irq) 998 if (ioapic_renumber_irq)
1051 irq = ioapic_renumber_irq(apic, irq); 999 irq = ioapic_renumber_irq(apic, irq);
1052 } 1000 }
1053 1001
1054#ifdef CONFIG_X86_32 1002#ifdef CONFIG_X86_32
@@ -1232,19 +1180,19 @@ static struct irq_chip ir_ioapic_chip;
1232#ifdef CONFIG_X86_32 1180#ifdef CONFIG_X86_32
1233static inline int IO_APIC_irq_trigger(int irq) 1181static inline int IO_APIC_irq_trigger(int irq)
1234{ 1182{
1235 int apic, idx, pin; 1183 int apic, idx, pin;
1236 1184
1237 for (apic = 0; apic < nr_ioapics; apic++) { 1185 for (apic = 0; apic < nr_ioapics; apic++) {
1238 for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { 1186 for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
1239 idx = find_irq_entry(apic, pin, mp_INT); 1187 idx = find_irq_entry(apic, pin, mp_INT);
1240 if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin))) 1188 if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
1241 return irq_trigger(idx); 1189 return irq_trigger(idx);
1242 } 1190 }
1243 } 1191 }
1244 /* 1192 /*
1245 * nonexistent IRQs are edge default 1193 * nonexistent IRQs are edge default
1246 */ 1194 */
1247 return 0; 1195 return 0;
1248} 1196}
1249#else 1197#else
1250static inline int IO_APIC_irq_trigger(int irq) 1198static inline int IO_APIC_irq_trigger(int irq)
@@ -1509,8 +1457,8 @@ __apicdebuginit(void) print_IO_APIC(void)
1509 reg_01.raw = io_apic_read(apic, 1); 1457 reg_01.raw = io_apic_read(apic, 1);
1510 if (reg_01.bits.version >= 0x10) 1458 if (reg_01.bits.version >= 0x10)
1511 reg_02.raw = io_apic_read(apic, 2); 1459 reg_02.raw = io_apic_read(apic, 2);
1512 if (reg_01.bits.version >= 0x20) 1460 if (reg_01.bits.version >= 0x20)
1513 reg_03.raw = io_apic_read(apic, 3); 1461 reg_03.raw = io_apic_read(apic, 3);
1514 spin_unlock_irqrestore(&ioapic_lock, flags); 1462 spin_unlock_irqrestore(&ioapic_lock, flags);
1515 1463
1516 printk("\n"); 1464 printk("\n");
@@ -2089,9 +2037,9 @@ static int ioapic_retrigger_irq(unsigned int irq)
2089#else 2037#else
2090static int ioapic_retrigger_irq(unsigned int irq) 2038static int ioapic_retrigger_irq(unsigned int irq)
2091{ 2039{
2092 send_IPI_self(irq_cfg(irq)->vector); 2040 send_IPI_self(irq_cfg(irq)->vector);
2093 2041
2094 return 1; 2042 return 1;
2095} 2043}
2096#endif 2044#endif
2097 2045
@@ -2189,7 +2137,7 @@ static int migrate_irq_remapped_level(int irq)
2189 2137
2190 if (io_apic_level_ack_pending(irq)) { 2138 if (io_apic_level_ack_pending(irq)) {
2191 /* 2139 /*
2192 * Interrupt in progress. Migrating irq now will change the 2140 * Interrupt in progress. Migrating irq now will change the
2193 * vector information in the IO-APIC RTE and that will confuse 2141 * vector information in the IO-APIC RTE and that will confuse
2194 * the EOI broadcast performed by cpu. 2142 * the EOI broadcast performed by cpu.
2195 * So, delay the irq migration to the next instance. 2143 * So, delay the irq migration to the next instance.
@@ -2426,28 +2374,28 @@ static void ack_apic_level(unsigned int irq)
2426} 2374}
2427 2375
2428static struct irq_chip ioapic_chip __read_mostly = { 2376static struct irq_chip ioapic_chip __read_mostly = {
2429 .name = "IO-APIC", 2377 .name = "IO-APIC",
2430 .startup = startup_ioapic_irq, 2378 .startup = startup_ioapic_irq,
2431 .mask = mask_IO_APIC_irq, 2379 .mask = mask_IO_APIC_irq,
2432 .unmask = unmask_IO_APIC_irq, 2380 .unmask = unmask_IO_APIC_irq,
2433 .ack = ack_apic_edge, 2381 .ack = ack_apic_edge,
2434 .eoi = ack_apic_level, 2382 .eoi = ack_apic_level,
2435#ifdef CONFIG_SMP 2383#ifdef CONFIG_SMP
2436 .set_affinity = set_ioapic_affinity_irq, 2384 .set_affinity = set_ioapic_affinity_irq,
2437#endif 2385#endif
2438 .retrigger = ioapic_retrigger_irq, 2386 .retrigger = ioapic_retrigger_irq,
2439}; 2387};
2440 2388
2441#ifdef CONFIG_INTR_REMAP 2389#ifdef CONFIG_INTR_REMAP
2442static struct irq_chip ir_ioapic_chip __read_mostly = { 2390static struct irq_chip ir_ioapic_chip __read_mostly = {
2443 .name = "IR-IO-APIC", 2391 .name = "IR-IO-APIC",
2444 .startup = startup_ioapic_irq, 2392 .startup = startup_ioapic_irq,
2445 .mask = mask_IO_APIC_irq, 2393 .mask = mask_IO_APIC_irq,
2446 .unmask = unmask_IO_APIC_irq, 2394 .unmask = unmask_IO_APIC_irq,
2447 .ack = ack_x2apic_edge, 2395 .ack = ack_x2apic_edge,
2448 .eoi = ack_x2apic_level, 2396 .eoi = ack_x2apic_level,
2449#ifdef CONFIG_SMP 2397#ifdef CONFIG_SMP
2450 .set_affinity = set_ir_ioapic_affinity_irq, 2398 .set_affinity = set_ir_ioapic_affinity_irq,
2451#endif 2399#endif
2452 .retrigger = ioapic_retrigger_irq, 2400 .retrigger = ioapic_retrigger_irq,
2453}; 2401};
@@ -2636,8 +2584,8 @@ static inline void __init check_timer(void)
2636 2584
2637 local_irq_save(flags); 2585 local_irq_save(flags);
2638 2586
2639 ver = apic_read(APIC_LVR); 2587 ver = apic_read(APIC_LVR);
2640 ver = GET_APIC_VERSION(ver); 2588 ver = GET_APIC_VERSION(ver);
2641 2589
2642 /* 2590 /*
2643 * get/set the timer IRQ vector: 2591 * get/set the timer IRQ vector:
@@ -2822,12 +2770,12 @@ void __init setup_IO_APIC(void)
2822 io_apic_irqs = ~PIC_IRQS; 2770 io_apic_irqs = ~PIC_IRQS;
2823 2771
2824 apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n"); 2772 apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
2825 /* 2773 /*
2826 * Set up IO-APIC IRQ routing. 2774 * Set up IO-APIC IRQ routing.
2827 */ 2775 */
2828#ifdef CONFIG_X86_32 2776#ifdef CONFIG_X86_32
2829 if (!acpi_ioapic) 2777 if (!acpi_ioapic)
2830 setup_ioapic_ids_from_mpc(); 2778 setup_ioapic_ids_from_mpc();
2831#endif 2779#endif
2832 sync_Arb_IDs(); 2780 sync_Arb_IDs();
2833 setup_IO_APIC_irqs(); 2781 setup_IO_APIC_irqs();
@@ -2842,9 +2790,9 @@ void __init setup_IO_APIC(void)
2842 2790
2843static int __init io_apic_bug_finalize(void) 2791static int __init io_apic_bug_finalize(void)
2844{ 2792{
2845 if (sis_apic_bug == -1) 2793 if (sis_apic_bug == -1)
2846 sis_apic_bug = 0; 2794 sis_apic_bug = 0;
2847 return 0; 2795 return 0;
2848} 2796}
2849 2797
2850late_initcall(io_apic_bug_finalize); 2798late_initcall(io_apic_bug_finalize);
@@ -3199,7 +3147,7 @@ static int msi_alloc_irte(struct pci_dev *dev, int irq, int nvec)
3199 if (index < 0) { 3147 if (index < 0) {
3200 printk(KERN_ERR 3148 printk(KERN_ERR
3201 "Unable to allocate %d IRTE for PCI %s\n", nvec, 3149 "Unable to allocate %d IRTE for PCI %s\n", nvec,
3202 pci_name(dev)); 3150 pci_name(dev));
3203 return -ENOSPC; 3151 return -ENOSPC;
3204 } 3152 }
3205 return index; 3153 return index;
@@ -3885,23 +3833,24 @@ static struct resource * __init ioapic_setup_resources(void)
3885void __init ioapic_init_mappings(void) 3833void __init ioapic_init_mappings(void)
3886{ 3834{
3887 unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; 3835 unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
3888 int i;
3889 struct resource *ioapic_res; 3836 struct resource *ioapic_res;
3837 int i;
3890 3838
3839 irq_2_pin_init();
3891 ioapic_res = ioapic_setup_resources(); 3840 ioapic_res = ioapic_setup_resources();
3892 for (i = 0; i < nr_ioapics; i++) { 3841 for (i = 0; i < nr_ioapics; i++) {
3893 if (smp_found_config) { 3842 if (smp_found_config) {
3894 ioapic_phys = mp_ioapics[i].mp_apicaddr; 3843 ioapic_phys = mp_ioapics[i].mp_apicaddr;
3895#ifdef CONFIG_X86_32 3844#ifdef CONFIG_X86_32
3896 if (!ioapic_phys) { 3845 if (!ioapic_phys) {
3897 printk(KERN_ERR 3846 printk(KERN_ERR
3898 "WARNING: bogus zero IO-APIC " 3847 "WARNING: bogus zero IO-APIC "
3899 "address found in MPTABLE, " 3848 "address found in MPTABLE, "
3900 "disabling IO/APIC support!\n"); 3849 "disabling IO/APIC support!\n");
3901 smp_found_config = 0; 3850 smp_found_config = 0;
3902 skip_ioapic_setup = 1; 3851 skip_ioapic_setup = 1;
3903 goto fake_ioapic_page; 3852 goto fake_ioapic_page;
3904 } 3853 }
3905#endif 3854#endif
3906 } else { 3855 } else {
3907#ifdef CONFIG_X86_32 3856#ifdef CONFIG_X86_32