aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/apic/Makefile1
-rw-r--r--arch/x86/kernel/apic/htirq.c107
-rw-r--r--arch/x86/kernel/apic/io_apic.c92
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
8obj-$(CONFIG_X86_IO_APIC) += io_apic.o 8obj-$(CONFIG_X86_IO_APIC) += io_apic.o
9obj-$(CONFIG_PCI_MSI) += msi.o 9obj-$(CONFIG_PCI_MSI) += msi.o
10obj-$(CONFIG_HT_IRQ) += htirq.o
10obj-$(CONFIG_SMP) += ipi.o 11obj-$(CONFIG_SMP) += ipi.o
11 12
12ifeq ($(CONFIG_X86_64),y) 13ifeq ($(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 */
24static 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
39static int
40ht_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
54static 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
64int 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
2451device_initcall(ioapic_init_ops); 2449device_initcall(ioapic_init_ops);
2452 2450
2453/*
2454 * Hypertransport interrupt support
2455 */
2456#ifdef CONFIG_HT_IRQ
2457
2458static 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
2472static int
2473ht_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
2487static 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
2497int 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
2543static int 2451static int
2544io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr) 2452io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
2545{ 2453{