aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/msi-apic.c
diff options
context:
space:
mode:
authorMark Maule <maule@sgi.com>2006-04-10 22:17:48 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-06-21 14:59:58 -0400
commitfd58e55fcf5568e51da2ed54d7acd049c3fdb184 (patch)
tree2cf41864d66b8db39f637549d4652c7664256155 /drivers/pci/msi-apic.c
parentc34b4c734482dda750deb6089521f7c891b48736 (diff)
[PATCH] PCI: msi abstractions and support for altix
Abstract portions of the MSI core for platforms that do not use standard APIC interrupt controllers. This is implemented through a new arch-specific msi setup routine, and a set of msi ops which can be set on a per platform basis. Signed-off-by: Mark Maule <maule@sgi.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci/msi-apic.c')
-rw-r--r--drivers/pci/msi-apic.c100
1 files changed, 100 insertions, 0 deletions
diff --git a/drivers/pci/msi-apic.c b/drivers/pci/msi-apic.c
new file mode 100644
index 000000000000..0eb5fe9003a2
--- /dev/null
+++ b/drivers/pci/msi-apic.c
@@ -0,0 +1,100 @@
1/*
2 * MSI hooks for standard x86 apic
3 */
4
5#include <linux/pci.h>
6#include <linux/irq.h>
7
8#include "msi.h"
9
10/*
11 * Shifts for APIC-based data
12 */
13
14#define MSI_DATA_VECTOR_SHIFT 0
15#define MSI_DATA_VECTOR(v) (((u8)v) << MSI_DATA_VECTOR_SHIFT)
16
17#define MSI_DATA_DELIVERY_SHIFT 8
18#define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_SHIFT)
19#define MSI_DATA_DELIVERY_LOWPRI (1 << MSI_DATA_DELIVERY_SHIFT)
20
21#define MSI_DATA_LEVEL_SHIFT 14
22#define MSI_DATA_LEVEL_DEASSERT (0 << MSI_DATA_LEVEL_SHIFT)
23#define MSI_DATA_LEVEL_ASSERT (1 << MSI_DATA_LEVEL_SHIFT)
24
25#define MSI_DATA_TRIGGER_SHIFT 15
26#define MSI_DATA_TRIGGER_EDGE (0 << MSI_DATA_TRIGGER_SHIFT)
27#define MSI_DATA_TRIGGER_LEVEL (1 << MSI_DATA_TRIGGER_SHIFT)
28
29/*
30 * Shift/mask fields for APIC-based bus address
31 */
32
33#define MSI_ADDR_HEADER 0xfee00000
34
35#define MSI_ADDR_DESTID_MASK 0xfff0000f
36#define MSI_ADDR_DESTID_CPU(cpu) ((cpu) << MSI_TARGET_CPU_SHIFT)
37
38#define MSI_ADDR_DESTMODE_SHIFT 2
39#define MSI_ADDR_DESTMODE_PHYS (0 << MSI_ADDR_DESTMODE_SHIFT)
40#define MSI_ADDR_DESTMODE_LOGIC (1 << MSI_ADDR_DESTMODE_SHIFT)
41
42#define MSI_ADDR_REDIRECTION_SHIFT 3
43#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT)
44#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT)
45
46
47static void
48msi_target_apic(unsigned int vector,
49 unsigned int dest_cpu,
50 u32 *address_hi, /* in/out */
51 u32 *address_lo) /* in/out */
52{
53 u32 addr = *address_lo;
54
55 addr &= MSI_ADDR_DESTID_MASK;
56 addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(dest_cpu));
57
58 *address_lo = addr;
59}
60
61static int
62msi_setup_apic(struct pci_dev *pdev, /* unused in generic */
63 unsigned int vector,
64 u32 *address_hi,
65 u32 *address_lo,
66 u32 *data)
67{
68 unsigned long dest_phys_id;
69
70 dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map));
71
72 *address_hi = 0;
73 *address_lo = MSI_ADDR_HEADER |
74 MSI_ADDR_DESTMODE_PHYS |
75 MSI_ADDR_REDIRECTION_CPU |
76 MSI_ADDR_DESTID_CPU(dest_phys_id);
77
78 *data = MSI_DATA_TRIGGER_EDGE |
79 MSI_DATA_LEVEL_ASSERT |
80 MSI_DATA_DELIVERY_FIXED |
81 MSI_DATA_VECTOR(vector);
82
83 return 0;
84}
85
86static void
87msi_teardown_apic(unsigned int vector)
88{
89 return; /* no-op */
90}
91
92/*
93 * Generic ops used on most IA archs/platforms. Set with msi_register()
94 */
95
96struct msi_ops msi_apic_ops = {
97 .setup = msi_setup_apic,
98 .teardown = msi_teardown_apic,
99 .target = msi_target_apic,
100};