diff options
-rw-r--r-- | arch/x86/kernel/apic/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/kernel/apic/htirq.c | 107 | ||||
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 92 |
3 files changed, 108 insertions, 92 deletions
diff --git a/arch/x86/kernel/apic/Makefile b/arch/x86/kernel/apic/Makefile index aac300750f0e..8bb12ddc5db8 100644 --- a/arch/x86/kernel/apic/Makefile +++ b/arch/x86/kernel/apic/Makefile | |||
@@ -7,6 +7,7 @@ obj-y += hw_nmi.o | |||
7 | 7 | ||
8 | obj-$(CONFIG_X86_IO_APIC) += io_apic.o | 8 | obj-$(CONFIG_X86_IO_APIC) += io_apic.o |
9 | obj-$(CONFIG_PCI_MSI) += msi.o | 9 | obj-$(CONFIG_PCI_MSI) += msi.o |
10 | obj-$(CONFIG_HT_IRQ) += htirq.o | ||
10 | obj-$(CONFIG_SMP) += ipi.o | 11 | obj-$(CONFIG_SMP) += ipi.o |
11 | 12 | ||
12 | ifeq ($(CONFIG_X86_64),y) | 13 | ifeq ($(CONFIG_X86_64),y) |
diff --git a/arch/x86/kernel/apic/htirq.c b/arch/x86/kernel/apic/htirq.c new file mode 100644 index 000000000000..a4980c5091f0 --- /dev/null +++ b/arch/x86/kernel/apic/htirq.c | |||
@@ -0,0 +1,107 @@ | |||
1 | /* | ||
2 | * Support Hypertransport IRQ | ||
3 | * | ||
4 | * Copyright (C) 1997, 1998, 1999, 2000, 2009 Ingo Molnar, Hajnalka Szabo | ||
5 | * Moved from arch/x86/kernel/apic/io_apic.c. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | #include <linux/mm.h> | ||
12 | #include <linux/interrupt.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/pci.h> | ||
16 | #include <linux/htirq.h> | ||
17 | #include <asm/hw_irq.h> | ||
18 | #include <asm/apic.h> | ||
19 | #include <asm/hypertransport.h> | ||
20 | |||
21 | /* | ||
22 | * Hypertransport interrupt support | ||
23 | */ | ||
24 | static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector) | ||
25 | { | ||
26 | struct ht_irq_msg msg; | ||
27 | |||
28 | fetch_ht_irq_msg(irq, &msg); | ||
29 | |||
30 | msg.address_lo &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK); | ||
31 | msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK); | ||
32 | |||
33 | msg.address_lo |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest); | ||
34 | msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest); | ||
35 | |||
36 | write_ht_irq_msg(irq, &msg); | ||
37 | } | ||
38 | |||
39 | static int | ||
40 | ht_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) | ||
41 | { | ||
42 | struct irq_cfg *cfg = data->chip_data; | ||
43 | unsigned int dest; | ||
44 | int ret; | ||
45 | |||
46 | ret = apic_set_affinity(data, mask, &dest); | ||
47 | if (ret) | ||
48 | return ret; | ||
49 | |||
50 | target_ht_irq(data->irq, dest, cfg->vector); | ||
51 | return IRQ_SET_MASK_OK_NOCOPY; | ||
52 | } | ||
53 | |||
54 | static struct irq_chip ht_irq_chip = { | ||
55 | .name = "PCI-HT", | ||
56 | .irq_mask = mask_ht_irq, | ||
57 | .irq_unmask = unmask_ht_irq, | ||
58 | .irq_ack = apic_ack_edge, | ||
59 | .irq_set_affinity = ht_set_affinity, | ||
60 | .irq_retrigger = apic_retrigger_irq, | ||
61 | .flags = IRQCHIP_SKIP_SET_WAKE, | ||
62 | }; | ||
63 | |||
64 | int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) | ||
65 | { | ||
66 | struct irq_cfg *cfg; | ||
67 | struct ht_irq_msg msg; | ||
68 | unsigned dest; | ||
69 | int err; | ||
70 | |||
71 | if (disable_apic) | ||
72 | return -ENXIO; | ||
73 | |||
74 | cfg = irq_cfg(irq); | ||
75 | err = assign_irq_vector(irq, cfg, apic->target_cpus()); | ||
76 | if (err) | ||
77 | return err; | ||
78 | |||
79 | err = apic->cpu_mask_to_apicid_and(cfg->domain, | ||
80 | apic->target_cpus(), &dest); | ||
81 | if (err) | ||
82 | return err; | ||
83 | |||
84 | msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest); | ||
85 | |||
86 | msg.address_lo = | ||
87 | HT_IRQ_LOW_BASE | | ||
88 | HT_IRQ_LOW_DEST_ID(dest) | | ||
89 | HT_IRQ_LOW_VECTOR(cfg->vector) | | ||
90 | ((apic->irq_dest_mode == 0) ? | ||
91 | HT_IRQ_LOW_DM_PHYSICAL : | ||
92 | HT_IRQ_LOW_DM_LOGICAL) | | ||
93 | HT_IRQ_LOW_RQEOI_EDGE | | ||
94 | ((apic->irq_delivery_mode != dest_LowestPrio) ? | ||
95 | HT_IRQ_LOW_MT_FIXED : | ||
96 | HT_IRQ_LOW_MT_ARBITRATED) | | ||
97 | HT_IRQ_LOW_IRQ_MASKED; | ||
98 | |||
99 | write_ht_irq_msg(irq, &msg); | ||
100 | |||
101 | irq_set_chip_and_handler_name(irq, &ht_irq_chip, | ||
102 | handle_edge_irq, "edge"); | ||
103 | |||
104 | dev_dbg(&dev->dev, "irq %d for HT\n", irq); | ||
105 | |||
106 | return 0; | ||
107 | } | ||
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 653fe211e4ca..b1acb68e19c7 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <linux/syscore_ops.h> | 33 | #include <linux/syscore_ops.h> |
34 | #include <linux/irqdomain.h> | 34 | #include <linux/irqdomain.h> |
35 | #include <linux/htirq.h> | ||
36 | #include <linux/freezer.h> | 35 | #include <linux/freezer.h> |
37 | #include <linux/kthread.h> | 36 | #include <linux/kthread.h> |
38 | #include <linux/jiffies.h> /* time_after() */ | 37 | #include <linux/jiffies.h> /* time_after() */ |
@@ -49,7 +48,6 @@ | |||
49 | #include <asm/dma.h> | 48 | #include <asm/dma.h> |
50 | #include <asm/timer.h> | 49 | #include <asm/timer.h> |
51 | #include <asm/i8259.h> | 50 | #include <asm/i8259.h> |
52 | #include <asm/hypertransport.h> | ||
53 | #include <asm/setup.h> | 51 | #include <asm/setup.h> |
54 | #include <asm/irq_remapping.h> | 52 | #include <asm/irq_remapping.h> |
55 | #include <asm/hw_irq.h> | 53 | #include <asm/hw_irq.h> |
@@ -2450,96 +2448,6 @@ static int __init ioapic_init_ops(void) | |||
2450 | 2448 | ||
2451 | device_initcall(ioapic_init_ops); | 2449 | device_initcall(ioapic_init_ops); |
2452 | 2450 | ||
2453 | /* | ||
2454 | * Hypertransport interrupt support | ||
2455 | */ | ||
2456 | #ifdef CONFIG_HT_IRQ | ||
2457 | |||
2458 | static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector) | ||
2459 | { | ||
2460 | struct ht_irq_msg msg; | ||
2461 | fetch_ht_irq_msg(irq, &msg); | ||
2462 | |||
2463 | msg.address_lo &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK); | ||
2464 | msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK); | ||
2465 | |||
2466 | msg.address_lo |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest); | ||
2467 | msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest); | ||
2468 | |||
2469 | write_ht_irq_msg(irq, &msg); | ||
2470 | } | ||
2471 | |||
2472 | static int | ||
2473 | ht_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) | ||
2474 | { | ||
2475 | struct irq_cfg *cfg = data->chip_data; | ||
2476 | unsigned int dest; | ||
2477 | int ret; | ||
2478 | |||
2479 | ret = apic_set_affinity(data, mask, &dest); | ||
2480 | if (ret) | ||
2481 | return ret; | ||
2482 | |||
2483 | target_ht_irq(data->irq, dest, cfg->vector); | ||
2484 | return IRQ_SET_MASK_OK_NOCOPY; | ||
2485 | } | ||
2486 | |||
2487 | static struct irq_chip ht_irq_chip = { | ||
2488 | .name = "PCI-HT", | ||
2489 | .irq_mask = mask_ht_irq, | ||
2490 | .irq_unmask = unmask_ht_irq, | ||
2491 | .irq_ack = apic_ack_edge, | ||
2492 | .irq_set_affinity = ht_set_affinity, | ||
2493 | .irq_retrigger = apic_retrigger_irq, | ||
2494 | .flags = IRQCHIP_SKIP_SET_WAKE, | ||
2495 | }; | ||
2496 | |||
2497 | int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) | ||
2498 | { | ||
2499 | struct irq_cfg *cfg; | ||
2500 | struct ht_irq_msg msg; | ||
2501 | unsigned dest; | ||
2502 | int err; | ||
2503 | |||
2504 | if (disable_apic) | ||
2505 | return -ENXIO; | ||
2506 | |||
2507 | cfg = irq_cfg(irq); | ||
2508 | err = assign_irq_vector(irq, cfg, apic->target_cpus()); | ||
2509 | if (err) | ||
2510 | return err; | ||
2511 | |||
2512 | err = apic->cpu_mask_to_apicid_and(cfg->domain, | ||
2513 | apic->target_cpus(), &dest); | ||
2514 | if (err) | ||
2515 | return err; | ||
2516 | |||
2517 | msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest); | ||
2518 | |||
2519 | msg.address_lo = | ||
2520 | HT_IRQ_LOW_BASE | | ||
2521 | HT_IRQ_LOW_DEST_ID(dest) | | ||
2522 | HT_IRQ_LOW_VECTOR(cfg->vector) | | ||
2523 | ((apic->irq_dest_mode == 0) ? | ||
2524 | HT_IRQ_LOW_DM_PHYSICAL : | ||
2525 | HT_IRQ_LOW_DM_LOGICAL) | | ||
2526 | HT_IRQ_LOW_RQEOI_EDGE | | ||
2527 | ((apic->irq_delivery_mode != dest_LowestPrio) ? | ||
2528 | HT_IRQ_LOW_MT_FIXED : | ||
2529 | HT_IRQ_LOW_MT_ARBITRATED) | | ||
2530 | HT_IRQ_LOW_IRQ_MASKED; | ||
2531 | |||
2532 | write_ht_irq_msg(irq, &msg); | ||
2533 | |||
2534 | irq_set_chip_and_handler_name(irq, &ht_irq_chip, | ||
2535 | handle_edge_irq, "edge"); | ||
2536 | |||
2537 | dev_printk(KERN_DEBUG, &dev->dev, "irq %d for HT\n", irq); | ||
2538 | |||
2539 | return 0; | ||
2540 | } | ||
2541 | #endif /* CONFIG_HT_IRQ */ | ||
2542 | |||
2543 | static int | 2451 | static int |
2544 | io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr) | 2452 | io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr) |
2545 | { | 2453 | { |