aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/io_apic.h2
-rw-r--r--arch/x86/kernel/apic/io_apic.c156
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);
172extern int setup_ioapic_entry(int apic, int irq, 172extern 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);
176extern void ioapic_write_entry(int apic, int pin, 176extern 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
394static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx) 396static __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
402static 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
400static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) 408static 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
1478int setup_ioapic_entry(int apic_id, int irq, 1486int 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
2314static void ir_irq_migration(struct work_struct *work);
2315
2316static 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 */
2337static void 2346static void
2338migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask) 2347migrate_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
2383static 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
2408unmask:
2409 unmask_IO_APIC_irq_desc(desc);
2410
2411 return ret;
2412}
2413
2414static 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 */
2440static void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc, 2386static 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}
2452static void set_ir_ioapic_affinity_irq(unsigned int irq, 2391static 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
2479static 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
2497static void
2498eoi_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
2540static void ack_x2apic_level(unsigned int irq) 2512static 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
2545static void ack_x2apic_edge(unsigned int irq) 2519static void ack_x2apic_edge(unsigned int irq)