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.h | |
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.h')
-rw-r--r-- | drivers/pci/msi.h | 133 |
1 files changed, 71 insertions, 62 deletions
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index 4ac52d441e47..56951c39d3a3 100644 --- a/drivers/pci/msi.h +++ b/drivers/pci/msi.h | |||
@@ -6,6 +6,68 @@ | |||
6 | #ifndef MSI_H | 6 | #ifndef MSI_H |
7 | #define MSI_H | 7 | #define MSI_H |
8 | 8 | ||
9 | /* | ||
10 | * MSI operation vector. Used by the msi core code (drivers/pci/msi.c) | ||
11 | * to abstract platform-specific tasks relating to MSI address generation | ||
12 | * and resource management. | ||
13 | */ | ||
14 | struct msi_ops { | ||
15 | /** | ||
16 | * setup - generate an MSI bus address and data for a given vector | ||
17 | * @pdev: PCI device context (in) | ||
18 | * @vector: vector allocated by the msi core (in) | ||
19 | * @addr_hi: upper 32 bits of PCI bus MSI address (out) | ||
20 | * @addr_lo: lower 32 bits of PCI bus MSI address (out) | ||
21 | * @data: MSI data payload (out) | ||
22 | * | ||
23 | * Description: The setup op is used to generate a PCI bus addres and | ||
24 | * data which the msi core will program into the card MSI capability | ||
25 | * registers. The setup routine is responsible for picking an initial | ||
26 | * cpu to target the MSI at. The setup routine is responsible for | ||
27 | * examining pdev to determine the MSI capabilities of the card and | ||
28 | * generating a suitable address/data. The setup routine is | ||
29 | * responsible for allocating and tracking any system resources it | ||
30 | * needs to route the MSI to the cpu it picks, and for associating | ||
31 | * those resources with the passed in vector. | ||
32 | * | ||
33 | * Returns 0 if the MSI address/data was successfully setup. | ||
34 | **/ | ||
35 | |||
36 | int (*setup) (struct pci_dev *pdev, unsigned int vector, | ||
37 | u32 *addr_hi, u32 *addr_lo, u32 *data); | ||
38 | |||
39 | /** | ||
40 | * teardown - release resources allocated by setup | ||
41 | * @vector: vector context for resources (in) | ||
42 | * | ||
43 | * Description: The teardown op is used to release any resources | ||
44 | * that were allocated in the setup routine associated with the passed | ||
45 | * in vector. | ||
46 | **/ | ||
47 | |||
48 | void (*teardown) (unsigned int vector); | ||
49 | |||
50 | /** | ||
51 | * target - retarget an MSI at a different cpu | ||
52 | * @vector: vector context for resources (in) | ||
53 | * @cpu: new cpu to direct vector at (in) | ||
54 | * @addr_hi: new value of PCI bus upper 32 bits (in/out) | ||
55 | * @addr_lo: new value of PCI bus lower 32 bits (in/out) | ||
56 | * | ||
57 | * Description: The target op is used to redirect an MSI vector | ||
58 | * at a different cpu. addr_hi/addr_lo coming in are the existing | ||
59 | * values that the MSI core has programmed into the card. The | ||
60 | * target code is responsible for freeing any resources (if any) | ||
61 | * associated with the old address, and generating a new PCI bus | ||
62 | * addr_hi/addr_lo that will redirect the vector at the indicated cpu. | ||
63 | **/ | ||
64 | |||
65 | void (*target) (unsigned int vector, unsigned int cpu, | ||
66 | u32 *addr_hi, u32 *addr_lo); | ||
67 | }; | ||
68 | |||
69 | extern int msi_register(struct msi_ops *ops); | ||
70 | |||
9 | #include <asm/msi.h> | 71 | #include <asm/msi.h> |
10 | 72 | ||
11 | /* | 73 | /* |
@@ -63,67 +125,6 @@ extern int pci_vector_resources(int last, int nr_released); | |||
63 | #define msix_mask(address) (address | PCI_MSIX_FLAGS_BITMASK) | 125 | #define msix_mask(address) (address | PCI_MSIX_FLAGS_BITMASK) |
64 | #define msix_is_pending(address) (address & PCI_MSIX_FLAGS_PENDMASK) | 126 | #define msix_is_pending(address) (address & PCI_MSIX_FLAGS_PENDMASK) |
65 | 127 | ||
66 | /* | ||
67 | * MSI Defined Data Structures | ||
68 | */ | ||
69 | #define MSI_ADDRESS_HEADER 0xfee | ||
70 | #define MSI_ADDRESS_HEADER_SHIFT 12 | ||
71 | #define MSI_ADDRESS_HEADER_MASK 0xfff000 | ||
72 | #define MSI_ADDRESS_DEST_ID_MASK 0xfff0000f | ||
73 | #define MSI_TARGET_CPU_MASK 0xff | ||
74 | #define MSI_DELIVERY_MODE 0 | ||
75 | #define MSI_LEVEL_MODE 1 /* Edge always assert */ | ||
76 | #define MSI_TRIGGER_MODE 0 /* MSI is edge sensitive */ | ||
77 | #define MSI_PHYSICAL_MODE 0 | ||
78 | #define MSI_LOGICAL_MODE 1 | ||
79 | #define MSI_REDIRECTION_HINT_MODE 0 | ||
80 | |||
81 | struct msg_data { | ||
82 | #if defined(__LITTLE_ENDIAN_BITFIELD) | ||
83 | __u32 vector : 8; | ||
84 | __u32 delivery_mode : 3; /* 000b: FIXED | 001b: lowest prior */ | ||
85 | __u32 reserved_1 : 3; | ||
86 | __u32 level : 1; /* 0: deassert | 1: assert */ | ||
87 | __u32 trigger : 1; /* 0: edge | 1: level */ | ||
88 | __u32 reserved_2 : 16; | ||
89 | #elif defined(__BIG_ENDIAN_BITFIELD) | ||
90 | __u32 reserved_2 : 16; | ||
91 | __u32 trigger : 1; /* 0: edge | 1: level */ | ||
92 | __u32 level : 1; /* 0: deassert | 1: assert */ | ||
93 | __u32 reserved_1 : 3; | ||
94 | __u32 delivery_mode : 3; /* 000b: FIXED | 001b: lowest prior */ | ||
95 | __u32 vector : 8; | ||
96 | #else | ||
97 | #error "Bitfield endianness not defined! Check your byteorder.h" | ||
98 | #endif | ||
99 | } __attribute__ ((packed)); | ||
100 | |||
101 | struct msg_address { | ||
102 | union { | ||
103 | struct { | ||
104 | #if defined(__LITTLE_ENDIAN_BITFIELD) | ||
105 | __u32 reserved_1 : 2; | ||
106 | __u32 dest_mode : 1; /*0:physic | 1:logic */ | ||
107 | __u32 redirection_hint: 1; /*0: dedicated CPU | ||
108 | 1: lowest priority */ | ||
109 | __u32 reserved_2 : 4; | ||
110 | __u32 dest_id : 24; /* Destination ID */ | ||
111 | #elif defined(__BIG_ENDIAN_BITFIELD) | ||
112 | __u32 dest_id : 24; /* Destination ID */ | ||
113 | __u32 reserved_2 : 4; | ||
114 | __u32 redirection_hint: 1; /*0: dedicated CPU | ||
115 | 1: lowest priority */ | ||
116 | __u32 dest_mode : 1; /*0:physic | 1:logic */ | ||
117 | __u32 reserved_1 : 2; | ||
118 | #else | ||
119 | #error "Bitfield endianness not defined! Check your byteorder.h" | ||
120 | #endif | ||
121 | }u; | ||
122 | __u32 value; | ||
123 | }lo_address; | ||
124 | __u32 hi_address; | ||
125 | } __attribute__ ((packed)); | ||
126 | |||
127 | struct msi_desc { | 128 | struct msi_desc { |
128 | struct { | 129 | struct { |
129 | __u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */ | 130 | __u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */ |
@@ -132,7 +133,7 @@ struct msi_desc { | |||
132 | __u8 reserved: 1; /* reserved */ | 133 | __u8 reserved: 1; /* reserved */ |
133 | __u8 entry_nr; /* specific enabled entry */ | 134 | __u8 entry_nr; /* specific enabled entry */ |
134 | __u8 default_vector; /* default pre-assigned vector */ | 135 | __u8 default_vector; /* default pre-assigned vector */ |
135 | __u8 current_cpu; /* current destination cpu */ | 136 | __u8 unused; /* formerly unused destination cpu*/ |
136 | }msi_attrib; | 137 | }msi_attrib; |
137 | 138 | ||
138 | struct { | 139 | struct { |
@@ -142,6 +143,14 @@ struct msi_desc { | |||
142 | 143 | ||
143 | void __iomem *mask_base; | 144 | void __iomem *mask_base; |
144 | struct pci_dev *dev; | 145 | struct pci_dev *dev; |
146 | |||
147 | #ifdef CONFIG_PM | ||
148 | /* PM save area for MSIX address/data */ | ||
149 | |||
150 | u32 address_hi_save; | ||
151 | u32 address_lo_save; | ||
152 | u32 data_save; | ||
153 | #endif | ||
145 | }; | 154 | }; |
146 | 155 | ||
147 | #endif /* MSI_H */ | 156 | #endif /* MSI_H */ |