diff options
author | Mark Maule <maule@sgi.com> | 2006-04-10 22:17:48 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-06-21 14:59:58 -0400 |
commit | fd58e55fcf5568e51da2ed54d7acd049c3fdb184 (patch) | |
tree | 2cf41864d66b8db39f637549d4652c7664256155 /drivers/pci/msi-apic.c | |
parent | c34b4c734482dda750deb6089521f7c891b48736 (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.c | 100 |
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 | |||
47 | static void | ||
48 | msi_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 | |||
61 | static int | ||
62 | msi_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 | |||
86 | static void | ||
87 | msi_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 | |||
96 | struct msi_ops msi_apic_ops = { | ||
97 | .setup = msi_setup_apic, | ||
98 | .teardown = msi_teardown_apic, | ||
99 | .target = msi_target_apic, | ||
100 | }; | ||