diff options
-rw-r--r-- | arch/x86/include/asm/io_apic.h | 2 | ||||
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 156 |
2 files changed, 66 insertions, 92 deletions
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index 59cb4a1317b7..ffcd08f96e47 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h | |||
@@ -172,7 +172,7 @@ extern void probe_nr_irqs_gsi(void); | |||
172 | extern int setup_ioapic_entry(int apic, int irq, | 172 | extern int setup_ioapic_entry(int apic, int irq, |
173 | struct IO_APIC_route_entry *entry, | 173 | struct IO_APIC_route_entry *entry, |
174 | unsigned int destination, int trigger, | 174 | unsigned int destination, int trigger, |
175 | int polarity, int vector); | 175 | int polarity, int vector, int pin); |
176 | extern void ioapic_write_entry(int apic, int pin, | 176 | extern void ioapic_write_entry(int apic, int pin, |
177 | struct IO_APIC_route_entry e); | 177 | struct IO_APIC_route_entry e); |
178 | #else /* !CONFIG_X86_IO_APIC */ | 178 | #else /* !CONFIG_X86_IO_APIC */ |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 4d975d0e3588..e074eac5bd35 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -389,6 +389,8 @@ struct io_apic { | |||
389 | unsigned int index; | 389 | unsigned int index; |
390 | unsigned int unused[3]; | 390 | unsigned int unused[3]; |
391 | unsigned int data; | 391 | unsigned int data; |
392 | unsigned int unused2[11]; | ||
393 | unsigned int eoi; | ||
392 | }; | 394 | }; |
393 | 395 | ||
394 | static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx) | 396 | static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx) |
@@ -397,6 +399,12 @@ static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx) | |||
397 | + (mp_ioapics[idx].apicaddr & ~PAGE_MASK); | 399 | + (mp_ioapics[idx].apicaddr & ~PAGE_MASK); |
398 | } | 400 | } |
399 | 401 | ||
402 | static inline void io_apic_eoi(unsigned int apic, unsigned int vector) | ||
403 | { | ||
404 | struct io_apic __iomem *io_apic = io_apic_base(apic); | ||
405 | writel(vector, &io_apic->eoi); | ||
406 | } | ||
407 | |||
400 | static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) | 408 | static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) |
401 | { | 409 | { |
402 | struct io_apic __iomem *io_apic = io_apic_base(apic); | 410 | struct io_apic __iomem *io_apic = io_apic_base(apic); |
@@ -1478,7 +1486,7 @@ static void ioapic_register_intr(int irq, struct irq_desc *desc, unsigned long t | |||
1478 | int setup_ioapic_entry(int apic_id, int irq, | 1486 | int setup_ioapic_entry(int apic_id, int irq, |
1479 | struct IO_APIC_route_entry *entry, | 1487 | struct IO_APIC_route_entry *entry, |
1480 | unsigned int destination, int trigger, | 1488 | unsigned int destination, int trigger, |
1481 | int polarity, int vector) | 1489 | int polarity, int vector, int pin) |
1482 | { | 1490 | { |
1483 | /* | 1491 | /* |
1484 | * add it to the IO-APIC irq-routing table: | 1492 | * add it to the IO-APIC irq-routing table: |
@@ -1504,7 +1512,14 @@ int setup_ioapic_entry(int apic_id, int irq, | |||
1504 | 1512 | ||
1505 | irte.present = 1; | 1513 | irte.present = 1; |
1506 | irte.dst_mode = apic->irq_dest_mode; | 1514 | irte.dst_mode = apic->irq_dest_mode; |
1507 | irte.trigger_mode = trigger; | 1515 | /* |
1516 | * Trigger mode in the IRTE will always be edge, and the | ||
1517 | * actual level or edge trigger will be setup in the IO-APIC | ||
1518 | * RTE. This will help simplify level triggered irq migration. | ||
1519 | * For more details, see the comments above explainig IO-APIC | ||
1520 | * irq migration in the presence of interrupt-remapping. | ||
1521 | */ | ||
1522 | irte.trigger_mode = 0; | ||
1508 | irte.dlvry_mode = apic->irq_delivery_mode; | 1523 | irte.dlvry_mode = apic->irq_delivery_mode; |
1509 | irte.vector = vector; | 1524 | irte.vector = vector; |
1510 | irte.dest_id = IRTE_DEST(destination); | 1525 | irte.dest_id = IRTE_DEST(destination); |
@@ -1515,18 +1530,23 @@ int setup_ioapic_entry(int apic_id, int irq, | |||
1515 | ir_entry->zero = 0; | 1530 | ir_entry->zero = 0; |
1516 | ir_entry->format = 1; | 1531 | ir_entry->format = 1; |
1517 | ir_entry->index = (index & 0x7fff); | 1532 | ir_entry->index = (index & 0x7fff); |
1533 | /* | ||
1534 | * IO-APIC RTE will be configured with virtual vector. | ||
1535 | * irq handler will do the explicit EOI to the io-apic. | ||
1536 | */ | ||
1537 | ir_entry->vector = pin; | ||
1518 | } else | 1538 | } else |
1519 | #endif | 1539 | #endif |
1520 | { | 1540 | { |
1521 | entry->delivery_mode = apic->irq_delivery_mode; | 1541 | entry->delivery_mode = apic->irq_delivery_mode; |
1522 | entry->dest_mode = apic->irq_dest_mode; | 1542 | entry->dest_mode = apic->irq_dest_mode; |
1523 | entry->dest = destination; | 1543 | entry->dest = destination; |
1544 | entry->vector = vector; | ||
1524 | } | 1545 | } |
1525 | 1546 | ||
1526 | entry->mask = 0; /* enable IRQ */ | 1547 | entry->mask = 0; /* enable IRQ */ |
1527 | entry->trigger = trigger; | 1548 | entry->trigger = trigger; |
1528 | entry->polarity = polarity; | 1549 | entry->polarity = polarity; |
1529 | entry->vector = vector; | ||
1530 | 1550 | ||
1531 | /* Mask level triggered irqs. | 1551 | /* Mask level triggered irqs. |
1532 | * Use IRQ_DELAYED_DISABLE for edge triggered irqs. | 1552 | * Use IRQ_DELAYED_DISABLE for edge triggered irqs. |
@@ -1561,7 +1581,7 @@ static void setup_IO_APIC_irq(int apic_id, int pin, unsigned int irq, struct irq | |||
1561 | 1581 | ||
1562 | 1582 | ||
1563 | if (setup_ioapic_entry(mp_ioapics[apic_id].apicid, irq, &entry, | 1583 | if (setup_ioapic_entry(mp_ioapics[apic_id].apicid, irq, &entry, |
1564 | dest, trigger, polarity, cfg->vector)) { | 1584 | dest, trigger, polarity, cfg->vector, pin)) { |
1565 | printk("Failed to setup ioapic entry for ioapic %d, pin %d\n", | 1585 | printk("Failed to setup ioapic entry for ioapic %d, pin %d\n", |
1566 | mp_ioapics[apic_id].apicid, pin); | 1586 | mp_ioapics[apic_id].apicid, pin); |
1567 | __clear_irq_vector(irq, cfg); | 1587 | __clear_irq_vector(irq, cfg); |
@@ -2311,37 +2331,24 @@ static int ioapic_retrigger_irq(unsigned int irq) | |||
2311 | #ifdef CONFIG_SMP | 2331 | #ifdef CONFIG_SMP |
2312 | 2332 | ||
2313 | #ifdef CONFIG_INTR_REMAP | 2333 | #ifdef CONFIG_INTR_REMAP |
2314 | static void ir_irq_migration(struct work_struct *work); | ||
2315 | |||
2316 | static DECLARE_DELAYED_WORK(ir_migration_work, ir_irq_migration); | ||
2317 | 2334 | ||
2318 | /* | 2335 | /* |
2319 | * Migrate the IO-APIC irq in the presence of intr-remapping. | 2336 | * Migrate the IO-APIC irq in the presence of intr-remapping. |
2320 | * | 2337 | * |
2321 | * For edge triggered, irq migration is a simple atomic update(of vector | 2338 | * For both level and edge triggered, irq migration is a simple atomic |
2322 | * and cpu destination) of IRTE and flush the hardware cache. | 2339 | * update(of vector and cpu destination) of IRTE and flush the hardware cache. |
2323 | * | ||
2324 | * For level triggered, we need to modify the io-apic RTE aswell with the update | ||
2325 | * vector information, along with modifying IRTE with vector and destination. | ||
2326 | * So irq migration for level triggered is little bit more complex compared to | ||
2327 | * edge triggered migration. But the good news is, we use the same algorithm | ||
2328 | * for level triggered migration as we have today, only difference being, | ||
2329 | * we now initiate the irq migration from process context instead of the | ||
2330 | * interrupt context. | ||
2331 | * | 2340 | * |
2332 | * In future, when we do a directed EOI (combined with cpu EOI broadcast | 2341 | * For level triggered, we eliminate the io-apic RTE modification (with the |
2333 | * suppression) to the IO-APIC, level triggered irq migration will also be | 2342 | * updated vector information), by using a virtual vector (io-apic pin number). |
2334 | * as simple as edge triggered migration and we can do the irq migration | 2343 | * Real vector that is used for interrupting cpu will be coming from |
2335 | * with a simple atomic update to IO-APIC RTE. | 2344 | * the interrupt-remapping table entry. |
2336 | */ | 2345 | */ |
2337 | static void | 2346 | static void |
2338 | migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask) | 2347 | migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask) |
2339 | { | 2348 | { |
2340 | struct irq_cfg *cfg; | 2349 | struct irq_cfg *cfg; |
2341 | struct irte irte; | 2350 | struct irte irte; |
2342 | int modify_ioapic_rte; | ||
2343 | unsigned int dest; | 2351 | unsigned int dest; |
2344 | unsigned long flags; | ||
2345 | unsigned int irq; | 2352 | unsigned int irq; |
2346 | 2353 | ||
2347 | if (!cpumask_intersects(mask, cpu_online_mask)) | 2354 | if (!cpumask_intersects(mask, cpu_online_mask)) |
@@ -2359,13 +2366,6 @@ migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask) | |||
2359 | 2366 | ||
2360 | dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask); | 2367 | dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask); |
2361 | 2368 | ||
2362 | modify_ioapic_rte = desc->status & IRQ_LEVEL; | ||
2363 | if (modify_ioapic_rte) { | ||
2364 | spin_lock_irqsave(&ioapic_lock, flags); | ||
2365 | __target_IO_APIC_irq(irq, dest, cfg); | ||
2366 | spin_unlock_irqrestore(&ioapic_lock, flags); | ||
2367 | } | ||
2368 | |||
2369 | irte.vector = cfg->vector; | 2369 | irte.vector = cfg->vector; |
2370 | irte.dest_id = IRTE_DEST(dest); | 2370 | irte.dest_id = IRTE_DEST(dest); |
2371 | 2371 | ||
@@ -2380,73 +2380,12 @@ migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask) | |||
2380 | cpumask_copy(desc->affinity, mask); | 2380 | cpumask_copy(desc->affinity, mask); |
2381 | } | 2381 | } |
2382 | 2382 | ||
2383 | static int migrate_irq_remapped_level_desc(struct irq_desc *desc) | ||
2384 | { | ||
2385 | int ret = -1; | ||
2386 | struct irq_cfg *cfg = desc->chip_data; | ||
2387 | |||
2388 | mask_IO_APIC_irq_desc(desc); | ||
2389 | |||
2390 | if (io_apic_level_ack_pending(cfg)) { | ||
2391 | /* | ||
2392 | * Interrupt in progress. Migrating irq now will change the | ||
2393 | * vector information in the IO-APIC RTE and that will confuse | ||
2394 | * the EOI broadcast performed by cpu. | ||
2395 | * So, delay the irq migration to the next instance. | ||
2396 | */ | ||
2397 | schedule_delayed_work(&ir_migration_work, 1); | ||
2398 | goto unmask; | ||
2399 | } | ||
2400 | |||
2401 | /* everthing is clear. we have right of way */ | ||
2402 | migrate_ioapic_irq_desc(desc, desc->pending_mask); | ||
2403 | |||
2404 | ret = 0; | ||
2405 | desc->status &= ~IRQ_MOVE_PENDING; | ||
2406 | cpumask_clear(desc->pending_mask); | ||
2407 | |||
2408 | unmask: | ||
2409 | unmask_IO_APIC_irq_desc(desc); | ||
2410 | |||
2411 | return ret; | ||
2412 | } | ||
2413 | |||
2414 | static void ir_irq_migration(struct work_struct *work) | ||
2415 | { | ||
2416 | unsigned int irq; | ||
2417 | struct irq_desc *desc; | ||
2418 | |||
2419 | for_each_irq_desc(irq, desc) { | ||
2420 | if (desc->status & IRQ_MOVE_PENDING) { | ||
2421 | unsigned long flags; | ||
2422 | |||
2423 | spin_lock_irqsave(&desc->lock, flags); | ||
2424 | if (!desc->chip->set_affinity || | ||
2425 | !(desc->status & IRQ_MOVE_PENDING)) { | ||
2426 | desc->status &= ~IRQ_MOVE_PENDING; | ||
2427 | spin_unlock_irqrestore(&desc->lock, flags); | ||
2428 | continue; | ||
2429 | } | ||
2430 | |||
2431 | desc->chip->set_affinity(irq, desc->pending_mask); | ||
2432 | spin_unlock_irqrestore(&desc->lock, flags); | ||
2433 | } | ||
2434 | } | ||
2435 | } | ||
2436 | |||
2437 | /* | 2383 | /* |
2438 | * Migrates the IRQ destination in the process context. | 2384 | * Migrates the IRQ destination in the process context. |
2439 | */ | 2385 | */ |
2440 | static void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc, | 2386 | static void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc, |
2441 | const struct cpumask *mask) | 2387 | const struct cpumask *mask) |
2442 | { | 2388 | { |
2443 | if (desc->status & IRQ_LEVEL) { | ||
2444 | desc->status |= IRQ_MOVE_PENDING; | ||
2445 | cpumask_copy(desc->pending_mask, mask); | ||
2446 | migrate_irq_remapped_level_desc(desc); | ||
2447 | return; | ||
2448 | } | ||
2449 | |||
2450 | migrate_ioapic_irq_desc(desc, mask); | 2389 | migrate_ioapic_irq_desc(desc, mask); |
2451 | } | 2390 | } |
2452 | static void set_ir_ioapic_affinity_irq(unsigned int irq, | 2391 | static void set_ir_ioapic_affinity_irq(unsigned int irq, |
@@ -2537,9 +2476,44 @@ static inline void irq_complete_move(struct irq_desc **descp) {} | |||
2537 | #endif | 2476 | #endif |
2538 | 2477 | ||
2539 | #ifdef CONFIG_INTR_REMAP | 2478 | #ifdef CONFIG_INTR_REMAP |
2479 | static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg) | ||
2480 | { | ||
2481 | int apic, pin; | ||
2482 | struct irq_pin_list *entry; | ||
2483 | |||
2484 | entry = cfg->irq_2_pin; | ||
2485 | for (;;) { | ||
2486 | |||
2487 | if (!entry) | ||
2488 | break; | ||
2489 | |||
2490 | apic = entry->apic; | ||
2491 | pin = entry->pin; | ||
2492 | io_apic_eoi(apic, pin); | ||
2493 | entry = entry->next; | ||
2494 | } | ||
2495 | } | ||
2496 | |||
2497 | static void | ||
2498 | eoi_ioapic_irq(struct irq_desc *desc) | ||
2499 | { | ||
2500 | struct irq_cfg *cfg; | ||
2501 | unsigned long flags; | ||
2502 | unsigned int irq; | ||
2503 | |||
2504 | irq = desc->irq; | ||
2505 | cfg = desc->chip_data; | ||
2506 | |||
2507 | spin_lock_irqsave(&ioapic_lock, flags); | ||
2508 | __eoi_ioapic_irq(irq, cfg); | ||
2509 | spin_unlock_irqrestore(&ioapic_lock, flags); | ||
2510 | } | ||
2511 | |||
2540 | static void ack_x2apic_level(unsigned int irq) | 2512 | static void ack_x2apic_level(unsigned int irq) |
2541 | { | 2513 | { |
2514 | struct irq_desc *desc = irq_to_desc(irq); | ||
2542 | ack_x2APIC_irq(); | 2515 | ack_x2APIC_irq(); |
2516 | eoi_ioapic_irq(desc); | ||
2543 | } | 2517 | } |
2544 | 2518 | ||
2545 | static void ack_x2apic_edge(unsigned int irq) | 2519 | static void ack_x2apic_edge(unsigned int irq) |