diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/pci/msi-altix.c | 81 | ||||
-rw-r--r-- | drivers/pci/msi-apic.c | 86 | ||||
-rw-r--r-- | drivers/pci/msi.c | 150 | ||||
-rw-r--r-- | drivers/pci/msi.h | 27 |
4 files changed, 145 insertions, 199 deletions
diff --git a/drivers/pci/msi-altix.c b/drivers/pci/msi-altix.c index 7aedc2ac8c28..6ffd1f850d41 100644 --- a/drivers/pci/msi-altix.c +++ b/drivers/pci/msi-altix.c | |||
@@ -7,8 +7,10 @@ | |||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/types.h> | 9 | #include <linux/types.h> |
10 | #include <linux/irq.h> | ||
10 | #include <linux/pci.h> | 11 | #include <linux/pci.h> |
11 | #include <linux/cpumask.h> | 12 | #include <linux/cpumask.h> |
13 | #include <linux/msi.h> | ||
12 | 14 | ||
13 | #include <asm/sn/addrs.h> | 15 | #include <asm/sn/addrs.h> |
14 | #include <asm/sn/intr.h> | 16 | #include <asm/sn/intr.h> |
@@ -16,17 +18,16 @@ | |||
16 | #include <asm/sn/pcidev.h> | 18 | #include <asm/sn/pcidev.h> |
17 | #include <asm/sn/nodepda.h> | 19 | #include <asm/sn/nodepda.h> |
18 | 20 | ||
19 | #include "msi.h" | ||
20 | |||
21 | struct sn_msi_info { | 21 | struct sn_msi_info { |
22 | u64 pci_addr; | 22 | u64 pci_addr; |
23 | struct sn_irq_info *sn_irq_info; | 23 | struct sn_irq_info *sn_irq_info; |
24 | }; | 24 | }; |
25 | 25 | ||
26 | static struct sn_msi_info *sn_msi_info; | 26 | static struct sn_msi_info sn_msi_info[NR_IRQS]; |
27 | |||
28 | static struct irq_chip sn_msi_chip; | ||
27 | 29 | ||
28 | static void | 30 | void sn_teardown_msi_irq(unsigned int irq) |
29 | sn_msi_teardown(unsigned int irq) | ||
30 | { | 31 | { |
31 | nasid_t nasid; | 32 | nasid_t nasid; |
32 | int widget; | 33 | int widget; |
@@ -61,9 +62,10 @@ sn_msi_teardown(unsigned int irq) | |||
61 | return; | 62 | return; |
62 | } | 63 | } |
63 | 64 | ||
64 | int | 65 | int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) |
65 | sn_msi_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg) | ||
66 | { | 66 | { |
67 | struct msi_msg msg; | ||
68 | struct msi_desc *entry; | ||
67 | int widget; | 69 | int widget; |
68 | int status; | 70 | int status; |
69 | nasid_t nasid; | 71 | nasid_t nasid; |
@@ -72,6 +74,10 @@ sn_msi_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg) | |||
72 | struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev); | 74 | struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev); |
73 | struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); | 75 | struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); |
74 | 76 | ||
77 | entry = get_irq_data(irq); | ||
78 | if (!entry->msi_attrib.is_64) | ||
79 | return -EINVAL; | ||
80 | |||
75 | if (bussoft == NULL) | 81 | if (bussoft == NULL) |
76 | return -EINVAL; | 82 | return -EINVAL; |
77 | 83 | ||
@@ -121,25 +127,29 @@ sn_msi_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg) | |||
121 | sn_msi_info[irq].sn_irq_info = sn_irq_info; | 127 | sn_msi_info[irq].sn_irq_info = sn_irq_info; |
122 | sn_msi_info[irq].pci_addr = bus_addr; | 128 | sn_msi_info[irq].pci_addr = bus_addr; |
123 | 129 | ||
124 | msg->address_hi = (u32)(bus_addr >> 32); | 130 | msg.address_hi = (u32)(bus_addr >> 32); |
125 | msg->address_lo = (u32)(bus_addr & 0x00000000ffffffff); | 131 | msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff); |
126 | 132 | ||
127 | /* | 133 | /* |
128 | * In the SN platform, bit 16 is a "send vector" bit which | 134 | * In the SN platform, bit 16 is a "send vector" bit which |
129 | * must be present in order to move the vector through the system. | 135 | * must be present in order to move the vector through the system. |
130 | */ | 136 | */ |
131 | msg->data = 0x100 + irq; | 137 | msg.data = 0x100 + irq; |
132 | 138 | ||
133 | #ifdef CONFIG_SMP | 139 | #ifdef CONFIG_SMP |
134 | set_irq_affinity_info(irq, sn_irq_info->irq_cpuid, 0); | 140 | set_irq_affinity_info(irq, sn_irq_info->irq_cpuid, 0); |
135 | #endif | 141 | #endif |
136 | 142 | ||
143 | write_msi_msg(irq, &msg); | ||
144 | set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq); | ||
145 | |||
137 | return 0; | 146 | return 0; |
138 | } | 147 | } |
139 | 148 | ||
140 | static void | 149 | #ifdef CONFIG_SMP |
141 | sn_msi_target(unsigned int irq, cpumask_t cpu_mask, struct msi_msg *msg) | 150 | static void sn_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask) |
142 | { | 151 | { |
152 | struct msi_msg msg; | ||
143 | int slice; | 153 | int slice; |
144 | nasid_t nasid; | 154 | nasid_t nasid; |
145 | u64 bus_addr; | 155 | u64 bus_addr; |
@@ -159,11 +169,12 @@ sn_msi_target(unsigned int irq, cpumask_t cpu_mask, struct msi_msg *msg) | |||
159 | * Release XIO resources for the old MSI PCI address | 169 | * Release XIO resources for the old MSI PCI address |
160 | */ | 170 | */ |
161 | 171 | ||
172 | read_msi_msg(irq, &msg); | ||
162 | sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; | 173 | sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; |
163 | pdev = sn_pdev->pdi_linux_pcidev; | 174 | pdev = sn_pdev->pdi_linux_pcidev; |
164 | provider = SN_PCIDEV_BUSPROVIDER(pdev); | 175 | provider = SN_PCIDEV_BUSPROVIDER(pdev); |
165 | 176 | ||
166 | bus_addr = (u64)(msg->address_hi) << 32 | (u64)(msg->address_lo); | 177 | bus_addr = (u64)(msg.address_hi) << 32 | (u64)(msg.address_lo); |
167 | (*provider->dma_unmap)(pdev, bus_addr, PCI_DMA_FROMDEVICE); | 178 | (*provider->dma_unmap)(pdev, bus_addr, PCI_DMA_FROMDEVICE); |
168 | sn_msi_info[irq].pci_addr = 0; | 179 | sn_msi_info[irq].pci_addr = 0; |
169 | 180 | ||
@@ -185,27 +196,35 @@ sn_msi_target(unsigned int irq, cpumask_t cpu_mask, struct msi_msg *msg) | |||
185 | SN_DMA_MSI|SN_DMA_ADDR_XIO); | 196 | SN_DMA_MSI|SN_DMA_ADDR_XIO); |
186 | 197 | ||
187 | sn_msi_info[irq].pci_addr = bus_addr; | 198 | sn_msi_info[irq].pci_addr = bus_addr; |
188 | msg->address_hi = (u32)(bus_addr >> 32); | 199 | msg.address_hi = (u32)(bus_addr >> 32); |
189 | msg->address_lo = (u32)(bus_addr & 0x00000000ffffffff); | 200 | msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff); |
201 | |||
202 | write_msi_msg(irq, &msg); | ||
203 | set_native_irq_info(irq, cpu_mask); | ||
190 | } | 204 | } |
205 | #endif /* CONFIG_SMP */ | ||
191 | 206 | ||
192 | struct msi_ops sn_msi_ops = { | 207 | static void sn_ack_msi_irq(unsigned int irq) |
193 | .needs_64bit_address = 1, | 208 | { |
194 | .setup = sn_msi_setup, | 209 | move_native_irq(irq); |
195 | .teardown = sn_msi_teardown, | 210 | ia64_eoi(); |
196 | #ifdef CONFIG_SMP | 211 | } |
197 | .target = sn_msi_target, | ||
198 | #endif | ||
199 | }; | ||
200 | 212 | ||
201 | int | 213 | static int sn_msi_retrigger_irq(unsigned int irq) |
202 | sn_msi_init(void) | ||
203 | { | 214 | { |
204 | sn_msi_info = | 215 | unsigned int vector = irq; |
205 | kzalloc(sizeof(struct sn_msi_info) * NR_IRQS, GFP_KERNEL); | 216 | ia64_resend_irq(vector); |
206 | if (! sn_msi_info) | ||
207 | return -ENOMEM; | ||
208 | 217 | ||
209 | msi_register(&sn_msi_ops); | 218 | return 1; |
210 | return 0; | ||
211 | } | 219 | } |
220 | |||
221 | static struct irq_chip sn_msi_chip = { | ||
222 | .name = "PCI-MSI", | ||
223 | .mask = mask_msi_irq, | ||
224 | .unmask = unmask_msi_irq, | ||
225 | .ack = sn_ack_msi_irq, | ||
226 | #ifdef CONFIG_SMP | ||
227 | .set_affinity = sn_set_msi_irq_affinity, | ||
228 | #endif | ||
229 | .retrigger = sn_msi_retrigger_irq, | ||
230 | }; | ||
diff --git a/drivers/pci/msi-apic.c b/drivers/pci/msi-apic.c index afc0ed13aa89..822e59a1b822 100644 --- a/drivers/pci/msi-apic.c +++ b/drivers/pci/msi-apic.c | |||
@@ -4,10 +4,9 @@ | |||
4 | 4 | ||
5 | #include <linux/pci.h> | 5 | #include <linux/pci.h> |
6 | #include <linux/irq.h> | 6 | #include <linux/irq.h> |
7 | #include <linux/msi.h> | ||
7 | #include <asm/smp.h> | 8 | #include <asm/smp.h> |
8 | 9 | ||
9 | #include "msi.h" | ||
10 | |||
11 | /* | 10 | /* |
12 | * Shifts for APIC-based data | 11 | * Shifts for APIC-based data |
13 | */ | 12 | */ |
@@ -31,6 +30,7 @@ | |||
31 | * Shift/mask fields for APIC-based bus address | 30 | * Shift/mask fields for APIC-based bus address |
32 | */ | 31 | */ |
33 | 32 | ||
33 | #define MSI_TARGET_CPU_SHIFT 4 | ||
34 | #define MSI_ADDR_HEADER 0xfee00000 | 34 | #define MSI_ADDR_HEADER 0xfee00000 |
35 | 35 | ||
36 | #define MSI_ADDR_DESTID_MASK 0xfff0000f | 36 | #define MSI_ADDR_DESTID_MASK 0xfff0000f |
@@ -44,58 +44,100 @@ | |||
44 | #define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT) | 44 | #define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT) |
45 | #define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT) | 45 | #define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT) |
46 | 46 | ||
47 | static struct irq_chip ia64_msi_chip; | ||
47 | 48 | ||
48 | static void | 49 | #ifdef CONFIG_SMP |
49 | msi_target_apic(unsigned int irq, cpumask_t cpu_mask, struct msi_msg *msg) | 50 | static void ia64_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask) |
50 | { | 51 | { |
51 | u32 addr = msg->address_lo; | 52 | struct msi_msg msg; |
53 | u32 addr; | ||
54 | |||
55 | read_msi_msg(irq, &msg); | ||
52 | 56 | ||
57 | addr = msg.address_lo; | ||
53 | addr &= MSI_ADDR_DESTID_MASK; | 58 | addr &= MSI_ADDR_DESTID_MASK; |
54 | addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(first_cpu(cpu_mask))); | 59 | addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(first_cpu(cpu_mask))); |
60 | msg.address_lo = addr; | ||
55 | 61 | ||
56 | msg->address_lo = addr; | 62 | write_msi_msg(irq, &msg); |
63 | set_native_irq_info(irq, cpu_mask); | ||
57 | } | 64 | } |
65 | #endif /* CONFIG_SMP */ | ||
58 | 66 | ||
59 | static int | 67 | int ia64_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) |
60 | msi_setup_apic(struct pci_dev *pdev, /* unused in generic */ | ||
61 | unsigned int irq, | ||
62 | struct msi_msg *msg) | ||
63 | { | 68 | { |
69 | struct msi_msg msg; | ||
64 | unsigned long dest_phys_id; | 70 | unsigned long dest_phys_id; |
65 | unsigned int vector; | 71 | unsigned int vector; |
66 | 72 | ||
67 | dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map)); | 73 | dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map)); |
68 | vector = irq; | 74 | vector = irq; |
69 | 75 | ||
70 | msg->address_hi = 0; | 76 | msg.address_hi = 0; |
71 | msg->address_lo = | 77 | msg.address_lo = |
72 | MSI_ADDR_HEADER | | 78 | MSI_ADDR_HEADER | |
73 | MSI_ADDR_DESTMODE_PHYS | | 79 | MSI_ADDR_DESTMODE_PHYS | |
74 | MSI_ADDR_REDIRECTION_CPU | | 80 | MSI_ADDR_REDIRECTION_CPU | |
75 | MSI_ADDR_DESTID_CPU(dest_phys_id); | 81 | MSI_ADDR_DESTID_CPU(dest_phys_id); |
76 | 82 | ||
77 | msg->data = | 83 | msg.data = |
78 | MSI_DATA_TRIGGER_EDGE | | 84 | MSI_DATA_TRIGGER_EDGE | |
79 | MSI_DATA_LEVEL_ASSERT | | 85 | MSI_DATA_LEVEL_ASSERT | |
80 | MSI_DATA_DELIVERY_FIXED | | 86 | MSI_DATA_DELIVERY_FIXED | |
81 | MSI_DATA_VECTOR(vector); | 87 | MSI_DATA_VECTOR(vector); |
82 | 88 | ||
89 | write_msi_msg(irq, &msg); | ||
90 | set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq); | ||
91 | |||
83 | return 0; | 92 | return 0; |
84 | } | 93 | } |
85 | 94 | ||
86 | static void | 95 | void ia64_teardown_msi_irq(unsigned int irq) |
87 | msi_teardown_apic(unsigned int irq) | ||
88 | { | 96 | { |
89 | return; /* no-op */ | 97 | return; /* no-op */ |
90 | } | 98 | } |
91 | 99 | ||
100 | static void ia64_ack_msi_irq(unsigned int irq) | ||
101 | { | ||
102 | move_native_irq(irq); | ||
103 | ia64_eoi(); | ||
104 | } | ||
105 | |||
106 | static int ia64_msi_retrigger_irq(unsigned int irq) | ||
107 | { | ||
108 | unsigned int vector = irq; | ||
109 | ia64_resend_irq(vector); | ||
110 | |||
111 | return 1; | ||
112 | } | ||
113 | |||
92 | /* | 114 | /* |
93 | * Generic ops used on most IA archs/platforms. Set with msi_register() | 115 | * Generic ops used on most IA64 platforms. |
94 | */ | 116 | */ |
95 | 117 | static struct irq_chip ia64_msi_chip = { | |
96 | struct msi_ops msi_apic_ops = { | 118 | .name = "PCI-MSI", |
97 | .needs_64bit_address = 0, | 119 | .mask = mask_msi_irq, |
98 | .setup = msi_setup_apic, | 120 | .unmask = unmask_msi_irq, |
99 | .teardown = msi_teardown_apic, | 121 | .ack = ia64_ack_msi_irq, |
100 | .target = msi_target_apic, | 122 | #ifdef CONFIG_SMP |
123 | .set_affinity = ia64_set_msi_irq_affinity, | ||
124 | #endif | ||
125 | .retrigger = ia64_msi_retrigger_irq, | ||
101 | }; | 126 | }; |
127 | |||
128 | |||
129 | int arch_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) | ||
130 | { | ||
131 | if (platform_setup_msi_irq) | ||
132 | return platform_setup_msi_irq(irq, pdev); | ||
133 | |||
134 | return ia64_setup_msi_irq(irq, pdev); | ||
135 | } | ||
136 | |||
137 | void arch_teardown_msi_irq(unsigned int irq) | ||
138 | { | ||
139 | if (platform_teardown_msi_irq) | ||
140 | return platform_teardown_msi_irq(irq); | ||
141 | |||
142 | return ia64_teardown_msi_irq(irq); | ||
143 | } | ||
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index fc7dd2a239dd..f9fdc54473c4 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/smp_lock.h> | 15 | #include <linux/smp_lock.h> |
16 | #include <linux/pci.h> | 16 | #include <linux/pci.h> |
17 | #include <linux/proc_fs.h> | 17 | #include <linux/proc_fs.h> |
18 | #include <linux/msi.h> | ||
18 | 19 | ||
19 | #include <asm/errno.h> | 20 | #include <asm/errno.h> |
20 | #include <asm/io.h> | 21 | #include <asm/io.h> |
@@ -29,15 +30,6 @@ static kmem_cache_t* msi_cachep; | |||
29 | 30 | ||
30 | static int pci_msi_enable = 1; | 31 | static int pci_msi_enable = 1; |
31 | 32 | ||
32 | static struct msi_ops *msi_ops; | ||
33 | |||
34 | int | ||
35 | msi_register(struct msi_ops *ops) | ||
36 | { | ||
37 | msi_ops = ops; | ||
38 | return 0; | ||
39 | } | ||
40 | |||
41 | static int msi_cache_init(void) | 33 | static int msi_cache_init(void) |
42 | { | 34 | { |
43 | msi_cachep = kmem_cache_create("msi_cache", sizeof(struct msi_desc), | 35 | msi_cachep = kmem_cache_create("msi_cache", sizeof(struct msi_desc), |
@@ -80,8 +72,9 @@ static void msi_set_mask_bit(unsigned int irq, int flag) | |||
80 | } | 72 | } |
81 | } | 73 | } |
82 | 74 | ||
83 | static void read_msi_msg(struct msi_desc *entry, struct msi_msg *msg) | 75 | void read_msi_msg(unsigned int irq, struct msi_msg *msg) |
84 | { | 76 | { |
77 | struct msi_desc *entry = get_irq_data(irq); | ||
85 | switch(entry->msi_attrib.type) { | 78 | switch(entry->msi_attrib.type) { |
86 | case PCI_CAP_ID_MSI: | 79 | case PCI_CAP_ID_MSI: |
87 | { | 80 | { |
@@ -118,8 +111,9 @@ static void read_msi_msg(struct msi_desc *entry, struct msi_msg *msg) | |||
118 | } | 111 | } |
119 | } | 112 | } |
120 | 113 | ||
121 | static void write_msi_msg(struct msi_desc *entry, struct msi_msg *msg) | 114 | void write_msi_msg(unsigned int irq, struct msi_msg *msg) |
122 | { | 115 | { |
116 | struct msi_desc *entry = get_irq_data(irq); | ||
123 | switch (entry->msi_attrib.type) { | 117 | switch (entry->msi_attrib.type) { |
124 | case PCI_CAP_ID_MSI: | 118 | case PCI_CAP_ID_MSI: |
125 | { | 119 | { |
@@ -157,53 +151,16 @@ static void write_msi_msg(struct msi_desc *entry, struct msi_msg *msg) | |||
157 | } | 151 | } |
158 | } | 152 | } |
159 | 153 | ||
160 | #ifdef CONFIG_SMP | 154 | void mask_msi_irq(unsigned int irq) |
161 | static void set_msi_affinity(unsigned int irq, cpumask_t cpu_mask) | ||
162 | { | ||
163 | struct msi_desc *entry; | ||
164 | struct msi_msg msg; | ||
165 | |||
166 | entry = msi_desc[irq]; | ||
167 | if (!entry || !entry->dev) | ||
168 | return; | ||
169 | |||
170 | read_msi_msg(entry, &msg); | ||
171 | msi_ops->target(irq, cpu_mask, &msg); | ||
172 | write_msi_msg(entry, &msg); | ||
173 | set_native_irq_info(irq, cpu_mask); | ||
174 | } | ||
175 | #else | ||
176 | #define set_msi_affinity NULL | ||
177 | #endif /* CONFIG_SMP */ | ||
178 | |||
179 | static void mask_MSI_irq(unsigned int irq) | ||
180 | { | 155 | { |
181 | msi_set_mask_bit(irq, 1); | 156 | msi_set_mask_bit(irq, 1); |
182 | } | 157 | } |
183 | 158 | ||
184 | static void unmask_MSI_irq(unsigned int irq) | 159 | void unmask_msi_irq(unsigned int irq) |
185 | { | 160 | { |
186 | msi_set_mask_bit(irq, 0); | 161 | msi_set_mask_bit(irq, 0); |
187 | } | 162 | } |
188 | 163 | ||
189 | static void ack_msi_irq(unsigned int irq) | ||
190 | { | ||
191 | move_native_irq(irq); | ||
192 | ack_APIC_irq(); | ||
193 | } | ||
194 | |||
195 | /* | ||
196 | * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices, | ||
197 | * which implement the MSI or MSI-X Capability Structure. | ||
198 | */ | ||
199 | static struct irq_chip msi_chip = { | ||
200 | .name = "PCI-MSI", | ||
201 | .unmask = unmask_MSI_irq, | ||
202 | .mask = mask_MSI_irq, | ||
203 | .ack = ack_msi_irq, | ||
204 | .set_affinity = set_msi_affinity | ||
205 | }; | ||
206 | |||
207 | static int msi_free_irq(struct pci_dev* dev, int irq); | 164 | static int msi_free_irq(struct pci_dev* dev, int irq); |
208 | static int msi_init(void) | 165 | static int msi_init(void) |
209 | { | 166 | { |
@@ -219,22 +176,6 @@ static int msi_init(void) | |||
219 | return status; | 176 | return status; |
220 | } | 177 | } |
221 | 178 | ||
222 | status = msi_arch_init(); | ||
223 | if (status < 0) { | ||
224 | pci_msi_enable = 0; | ||
225 | printk(KERN_WARNING | ||
226 | "PCI: MSI arch init failed. MSI disabled.\n"); | ||
227 | return status; | ||
228 | } | ||
229 | |||
230 | if (! msi_ops) { | ||
231 | pci_msi_enable = 0; | ||
232 | printk(KERN_WARNING | ||
233 | "PCI: MSI ops not registered. MSI disabled.\n"); | ||
234 | status = -EINVAL; | ||
235 | return status; | ||
236 | } | ||
237 | |||
238 | status = msi_cache_init(); | 179 | status = msi_cache_init(); |
239 | if (status < 0) { | 180 | if (status < 0) { |
240 | pci_msi_enable = 0; | 181 | pci_msi_enable = 0; |
@@ -268,7 +209,7 @@ static void attach_msi_entry(struct msi_desc *entry, int irq) | |||
268 | spin_unlock_irqrestore(&msi_lock, flags); | 209 | spin_unlock_irqrestore(&msi_lock, flags); |
269 | } | 210 | } |
270 | 211 | ||
271 | static int create_msi_irq(struct irq_chip *chip) | 212 | static int create_msi_irq(void) |
272 | { | 213 | { |
273 | struct msi_desc *entry; | 214 | struct msi_desc *entry; |
274 | int irq; | 215 | int irq; |
@@ -283,7 +224,6 @@ static int create_msi_irq(struct irq_chip *chip) | |||
283 | return -EBUSY; | 224 | return -EBUSY; |
284 | } | 225 | } |
285 | 226 | ||
286 | set_irq_chip_and_handler(irq, chip, handle_edge_irq); | ||
287 | set_irq_data(irq, entry); | 227 | set_irq_data(irq, entry); |
288 | 228 | ||
289 | return irq; | 229 | return irq; |
@@ -473,7 +413,7 @@ int pci_save_msix_state(struct pci_dev *dev) | |||
473 | struct msi_desc *entry; | 413 | struct msi_desc *entry; |
474 | 414 | ||
475 | entry = msi_desc[irq]; | 415 | entry = msi_desc[irq]; |
476 | read_msi_msg(entry, &entry->msg_save); | 416 | read_msi_msg(irq, &entry->msg_save); |
477 | 417 | ||
478 | tail = msi_desc[irq]->link.tail; | 418 | tail = msi_desc[irq]->link.tail; |
479 | irq = tail; | 419 | irq = tail; |
@@ -512,7 +452,7 @@ void pci_restore_msix_state(struct pci_dev *dev) | |||
512 | irq = head = dev->irq; | 452 | irq = head = dev->irq; |
513 | while (head != tail) { | 453 | while (head != tail) { |
514 | entry = msi_desc[irq]; | 454 | entry = msi_desc[irq]; |
515 | write_msi_msg(entry, &entry->msg_save); | 455 | write_msi_msg(irq, &entry->msg_save); |
516 | 456 | ||
517 | tail = msi_desc[irq]->link.tail; | 457 | tail = msi_desc[irq]->link.tail; |
518 | irq = tail; | 458 | irq = tail; |
@@ -524,39 +464,6 @@ void pci_restore_msix_state(struct pci_dev *dev) | |||
524 | } | 464 | } |
525 | #endif | 465 | #endif |
526 | 466 | ||
527 | static int msi_register_init(struct pci_dev *dev, struct msi_desc *entry) | ||
528 | { | ||
529 | int status; | ||
530 | struct msi_msg msg; | ||
531 | int pos; | ||
532 | u16 control; | ||
533 | |||
534 | pos = entry->msi_attrib.pos; | ||
535 | pci_read_config_word(dev, msi_control_reg(pos), &control); | ||
536 | |||
537 | /* Configure MSI capability structure */ | ||
538 | status = msi_ops->setup(dev, dev->irq, &msg); | ||
539 | if (status < 0) | ||
540 | return status; | ||
541 | |||
542 | write_msi_msg(entry, &msg); | ||
543 | if (entry->msi_attrib.maskbit) { | ||
544 | unsigned int maskbits, temp; | ||
545 | /* All MSIs are unmasked by default, Mask them all */ | ||
546 | pci_read_config_dword(dev, | ||
547 | msi_mask_bits_reg(pos, is_64bit_address(control)), | ||
548 | &maskbits); | ||
549 | temp = (1 << multi_msi_capable(control)); | ||
550 | temp = ((temp - 1) & ~temp); | ||
551 | maskbits |= temp; | ||
552 | pci_write_config_dword(dev, | ||
553 | msi_mask_bits_reg(pos, is_64bit_address(control)), | ||
554 | maskbits); | ||
555 | } | ||
556 | |||
557 | return 0; | ||
558 | } | ||
559 | |||
560 | /** | 467 | /** |
561 | * msi_capability_init - configure device's MSI capability structure | 468 | * msi_capability_init - configure device's MSI capability structure |
562 | * @dev: pointer to the pci_dev data structure of MSI device function | 469 | * @dev: pointer to the pci_dev data structure of MSI device function |
@@ -576,7 +483,7 @@ static int msi_capability_init(struct pci_dev *dev) | |||
576 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); | 483 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); |
577 | pci_read_config_word(dev, msi_control_reg(pos), &control); | 484 | pci_read_config_word(dev, msi_control_reg(pos), &control); |
578 | /* MSI Entry Initialization */ | 485 | /* MSI Entry Initialization */ |
579 | irq = create_msi_irq(&msi_chip); | 486 | irq = create_msi_irq(); |
580 | if (irq < 0) | 487 | if (irq < 0) |
581 | return irq; | 488 | return irq; |
582 | 489 | ||
@@ -589,16 +496,27 @@ static int msi_capability_init(struct pci_dev *dev) | |||
589 | entry->msi_attrib.maskbit = is_mask_bit_support(control); | 496 | entry->msi_attrib.maskbit = is_mask_bit_support(control); |
590 | entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */ | 497 | entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */ |
591 | entry->msi_attrib.pos = pos; | 498 | entry->msi_attrib.pos = pos; |
592 | dev->irq = irq; | ||
593 | entry->dev = dev; | ||
594 | if (is_mask_bit_support(control)) { | 499 | if (is_mask_bit_support(control)) { |
595 | entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos, | 500 | entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos, |
596 | is_64bit_address(control)); | 501 | is_64bit_address(control)); |
597 | } | 502 | } |
503 | entry->dev = dev; | ||
504 | if (entry->msi_attrib.maskbit) { | ||
505 | unsigned int maskbits, temp; | ||
506 | /* All MSIs are unmasked by default, Mask them all */ | ||
507 | pci_read_config_dword(dev, | ||
508 | msi_mask_bits_reg(pos, is_64bit_address(control)), | ||
509 | &maskbits); | ||
510 | temp = (1 << multi_msi_capable(control)); | ||
511 | temp = ((temp - 1) & ~temp); | ||
512 | maskbits |= temp; | ||
513 | pci_write_config_dword(dev, | ||
514 | msi_mask_bits_reg(pos, is_64bit_address(control)), | ||
515 | maskbits); | ||
516 | } | ||
598 | /* Configure MSI capability structure */ | 517 | /* Configure MSI capability structure */ |
599 | status = msi_register_init(dev, entry); | 518 | status = arch_setup_msi_irq(irq, dev); |
600 | if (status != 0) { | 519 | if (status < 0) { |
601 | dev->irq = entry->msi_attrib.default_irq; | ||
602 | destroy_msi_irq(irq); | 520 | destroy_msi_irq(irq); |
603 | return status; | 521 | return status; |
604 | } | 522 | } |
@@ -607,6 +525,7 @@ static int msi_capability_init(struct pci_dev *dev) | |||
607 | /* Set MSI enabled bits */ | 525 | /* Set MSI enabled bits */ |
608 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); | 526 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); |
609 | 527 | ||
528 | dev->irq = irq; | ||
610 | return 0; | 529 | return 0; |
611 | } | 530 | } |
612 | 531 | ||
@@ -624,7 +543,6 @@ static int msix_capability_init(struct pci_dev *dev, | |||
624 | struct msix_entry *entries, int nvec) | 543 | struct msix_entry *entries, int nvec) |
625 | { | 544 | { |
626 | struct msi_desc *head = NULL, *tail = NULL, *entry = NULL; | 545 | struct msi_desc *head = NULL, *tail = NULL, *entry = NULL; |
627 | struct msi_msg msg; | ||
628 | int status; | 546 | int status; |
629 | int irq, pos, i, j, nr_entries, temp = 0; | 547 | int irq, pos, i, j, nr_entries, temp = 0; |
630 | unsigned long phys_addr; | 548 | unsigned long phys_addr; |
@@ -648,7 +566,7 @@ static int msix_capability_init(struct pci_dev *dev, | |||
648 | 566 | ||
649 | /* MSI-X Table Initialization */ | 567 | /* MSI-X Table Initialization */ |
650 | for (i = 0; i < nvec; i++) { | 568 | for (i = 0; i < nvec; i++) { |
651 | irq = create_msi_irq(&msi_chip); | 569 | irq = create_msi_irq(); |
652 | if (irq < 0) | 570 | if (irq < 0) |
653 | break; | 571 | break; |
654 | 572 | ||
@@ -676,13 +594,12 @@ static int msix_capability_init(struct pci_dev *dev, | |||
676 | temp = irq; | 594 | temp = irq; |
677 | tail = entry; | 595 | tail = entry; |
678 | /* Configure MSI-X capability structure */ | 596 | /* Configure MSI-X capability structure */ |
679 | status = msi_ops->setup(dev, irq, &msg); | 597 | status = arch_setup_msi_irq(irq, dev); |
680 | if (status < 0) { | 598 | if (status < 0) { |
681 | destroy_msi_irq(irq); | 599 | destroy_msi_irq(irq); |
682 | break; | 600 | break; |
683 | } | 601 | } |
684 | 602 | ||
685 | write_msi_msg(entry, &msg); | ||
686 | attach_msi_entry(entry, irq); | 603 | attach_msi_entry(entry, irq); |
687 | } | 604 | } |
688 | if (i != nvec) { | 605 | if (i != nvec) { |
@@ -746,7 +663,6 @@ int pci_msi_supported(struct pci_dev * dev) | |||
746 | int pci_enable_msi(struct pci_dev* dev) | 663 | int pci_enable_msi(struct pci_dev* dev) |
747 | { | 664 | { |
748 | int pos, temp, status; | 665 | int pos, temp, status; |
749 | u16 control; | ||
750 | 666 | ||
751 | if (pci_msi_supported(dev) < 0) | 667 | if (pci_msi_supported(dev) < 0) |
752 | return -EINVAL; | 668 | return -EINVAL; |
@@ -761,10 +677,6 @@ int pci_enable_msi(struct pci_dev* dev) | |||
761 | if (!pos) | 677 | if (!pos) |
762 | return -EINVAL; | 678 | return -EINVAL; |
763 | 679 | ||
764 | pci_read_config_word(dev, msi_control_reg(pos), &control); | ||
765 | if (!is_64bit_address(control) && msi_ops->needs_64bit_address) | ||
766 | return -EINVAL; | ||
767 | |||
768 | WARN_ON(!msi_lookup_irq(dev, PCI_CAP_ID_MSI)); | 680 | WARN_ON(!msi_lookup_irq(dev, PCI_CAP_ID_MSI)); |
769 | 681 | ||
770 | /* Check whether driver already requested for MSI-X irqs */ | 682 | /* Check whether driver already requested for MSI-X irqs */ |
@@ -831,7 +743,7 @@ static int msi_free_irq(struct pci_dev* dev, int irq) | |||
831 | void __iomem *base; | 743 | void __iomem *base; |
832 | unsigned long flags; | 744 | unsigned long flags; |
833 | 745 | ||
834 | msi_ops->teardown(irq); | 746 | arch_teardown_msi_irq(irq); |
835 | 747 | ||
836 | spin_lock_irqsave(&msi_lock, flags); | 748 | spin_lock_irqsave(&msi_lock, flags); |
837 | entry = msi_desc[irq]; | 749 | entry = msi_desc[irq]; |
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index 77823bfed5c1..f0cca1772f9c 100644 --- a/drivers/pci/msi.h +++ b/drivers/pci/msi.h | |||
@@ -6,8 +6,6 @@ | |||
6 | #ifndef MSI_H | 6 | #ifndef MSI_H |
7 | #define MSI_H | 7 | #define MSI_H |
8 | 8 | ||
9 | #include <asm/msi.h> | ||
10 | |||
11 | /* | 9 | /* |
12 | * MSI-X Address Register | 10 | * MSI-X Address Register |
13 | */ | 11 | */ |
@@ -49,29 +47,4 @@ | |||
49 | #define msix_mask(address) (address | PCI_MSIX_FLAGS_BITMASK) | 47 | #define msix_mask(address) (address | PCI_MSIX_FLAGS_BITMASK) |
50 | #define msix_is_pending(address) (address & PCI_MSIX_FLAGS_PENDMASK) | 48 | #define msix_is_pending(address) (address & PCI_MSIX_FLAGS_PENDMASK) |
51 | 49 | ||
52 | struct msi_desc { | ||
53 | struct { | ||
54 | __u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */ | ||
55 | __u8 maskbit : 1; /* mask-pending bit supported ? */ | ||
56 | __u8 unused : 1; | ||
57 | __u8 is_64 : 1; /* Address size: 0=32bit 1=64bit */ | ||
58 | __u8 pos; /* Location of the msi capability */ | ||
59 | __u16 entry_nr; /* specific enabled entry */ | ||
60 | unsigned default_irq; /* default pre-assigned irq */ | ||
61 | }msi_attrib; | ||
62 | |||
63 | struct { | ||
64 | __u16 head; | ||
65 | __u16 tail; | ||
66 | }link; | ||
67 | |||
68 | void __iomem *mask_base; | ||
69 | struct pci_dev *dev; | ||
70 | |||
71 | #ifdef CONFIG_PM | ||
72 | /* PM save area for MSIX address/data */ | ||
73 | struct msi_msg msg_save; | ||
74 | #endif | ||
75 | }; | ||
76 | |||
77 | #endif /* MSI_H */ | 50 | #endif /* MSI_H */ |