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.c142
1 files changed, 141 insertions, 1 deletions
diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c
index 60bb8b19f4cd..6bd51ce3ce32 100644
--- a/arch/x86/kernel/io_apic.c
+++ b/arch/x86/kernel/io_apic.c
@@ -141,6 +141,9 @@ struct irq_cfg {
141 unsigned move_cleanup_count; 141 unsigned move_cleanup_count;
142 u8 vector; 142 u8 vector;
143 u8 move_in_progress : 1; 143 u8 move_in_progress : 1;
144#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
145 u8 move_desc_pending : 1;
146#endif
144}; 147};
145 148
146/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */ 149/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
@@ -241,6 +244,121 @@ void arch_init_chip_data(struct irq_desc *desc, int cpu)
241 } 244 }
242} 245}
243 246
247#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
248
249static void
250init_copy_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg, int cpu)
251{
252 struct irq_pin_list *old_entry, *head, *tail, *entry;
253
254 cfg->irq_2_pin = NULL;
255 old_entry = old_cfg->irq_2_pin;
256 if (!old_entry)
257 return;
258
259 entry = get_one_free_irq_2_pin(cpu);
260 if (!entry)
261 return;
262
263 entry->apic = old_entry->apic;
264 entry->pin = old_entry->pin;
265 head = entry;
266 tail = entry;
267 old_entry = old_entry->next;
268 while (old_entry) {
269 entry = get_one_free_irq_2_pin(cpu);
270 if (!entry) {
271 entry = head;
272 while (entry) {
273 head = entry->next;
274 kfree(entry);
275 entry = head;
276 }
277 /* still use the old one */
278 return;
279 }
280 entry->apic = old_entry->apic;
281 entry->pin = old_entry->pin;
282 tail->next = entry;
283 tail = entry;
284 old_entry = old_entry->next;
285 }
286
287 tail->next = NULL;
288 cfg->irq_2_pin = head;
289}
290
291static void free_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg)
292{
293 struct irq_pin_list *entry, *next;
294
295 if (old_cfg->irq_2_pin == cfg->irq_2_pin)
296 return;
297
298 entry = old_cfg->irq_2_pin;
299
300 while (entry) {
301 next = entry->next;
302 kfree(entry);
303 entry = next;
304 }
305 old_cfg->irq_2_pin = NULL;
306}
307
308void arch_init_copy_chip_data(struct irq_desc *old_desc,
309 struct irq_desc *desc, int cpu)
310{
311 struct irq_cfg *cfg;
312 struct irq_cfg *old_cfg;
313
314 cfg = get_one_free_irq_cfg(cpu);
315
316 if (!cfg)
317 return;
318
319 desc->chip_data = cfg;
320
321 old_cfg = old_desc->chip_data;
322
323 memcpy(cfg, old_cfg, sizeof(struct irq_cfg));
324
325 init_copy_irq_2_pin(old_cfg, cfg, cpu);
326}
327
328static void free_irq_cfg(struct irq_cfg *old_cfg)
329{
330 kfree(old_cfg);
331}
332
333void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc)
334{
335 struct irq_cfg *old_cfg, *cfg;
336
337 old_cfg = old_desc->chip_data;
338 cfg = desc->chip_data;
339
340 if (old_cfg == cfg)
341 return;
342
343 if (old_cfg) {
344 free_irq_2_pin(old_cfg, cfg);
345 free_irq_cfg(old_cfg);
346 old_desc->chip_data = NULL;
347 }
348}
349
350static void set_extra_move_desc(struct irq_desc *desc, cpumask_t mask)
351{
352 struct irq_cfg *cfg = desc->chip_data;
353
354 if (!cfg->move_in_progress) {
355 /* it means that domain is not changed */
356 if (!cpus_intersects(desc->affinity, mask))
357 cfg->move_desc_pending = 1;
358 }
359}
360#endif
361
244#else 362#else
245static struct irq_cfg *irq_cfg(unsigned int irq) 363static struct irq_cfg *irq_cfg(unsigned int irq)
246{ 364{
@@ -249,10 +367,12 @@ static struct irq_cfg *irq_cfg(unsigned int irq)
249 367
250#endif 368#endif
251 369
370#ifndef CONFIG_NUMA_MIGRATE_IRQ_DESC
252static inline void 371static inline void
253set_extra_move_desc(struct irq_desc *desc, const struct cpumask *mask) 372set_extra_move_desc(struct irq_desc *desc, const struct cpumask *mask)
254{ 373{
255} 374}
375#endif
256 376
257struct io_apic { 377struct io_apic {
258 unsigned int index; 378 unsigned int index;
@@ -2397,11 +2517,31 @@ static void irq_complete_move(struct irq_desc **descp)
2397 struct irq_cfg *cfg = desc->chip_data; 2517 struct irq_cfg *cfg = desc->chip_data;
2398 unsigned vector, me; 2518 unsigned vector, me;
2399 2519
2400 if (likely(!cfg->move_in_progress)) 2520 if (likely(!cfg->move_in_progress)) {
2521#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
2522 if (likely(!cfg->move_desc_pending))
2523 return;
2524
2525 /* domain is not change, but affinity is changed */
2526 me = smp_processor_id();
2527 if (cpu_isset(me, desc->affinity)) {
2528 *descp = desc = move_irq_desc(desc, me);
2529 /* get the new one */
2530 cfg = desc->chip_data;
2531 cfg->move_desc_pending = 0;
2532 }
2533#endif
2401 return; 2534 return;
2535 }
2402 2536
2403 vector = ~get_irq_regs()->orig_ax; 2537 vector = ~get_irq_regs()->orig_ax;
2404 me = smp_processor_id(); 2538 me = smp_processor_id();
2539#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
2540 *descp = desc = move_irq_desc(desc, me);
2541 /* get the new one */
2542 cfg = desc->chip_data;
2543#endif
2544
2405 if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) 2545 if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain))
2406 send_cleanup_vector(cfg); 2546 send_cleanup_vector(cfg);
2407} 2547}