diff options
Diffstat (limited to 'drivers/pci/msi.c')
-rw-r--r-- | drivers/pci/msi.c | 115 |
1 files changed, 24 insertions, 91 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index e3ba3963988c..fc7dd2a239dd 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -53,21 +53,20 @@ static void msi_set_mask_bit(unsigned int irq, int flag) | |||
53 | struct msi_desc *entry; | 53 | struct msi_desc *entry; |
54 | 54 | ||
55 | entry = msi_desc[irq]; | 55 | entry = msi_desc[irq]; |
56 | if (!entry || !entry->dev || !entry->mask_base) | 56 | BUG_ON(!entry || !entry->dev); |
57 | return; | ||
58 | switch (entry->msi_attrib.type) { | 57 | switch (entry->msi_attrib.type) { |
59 | case PCI_CAP_ID_MSI: | 58 | case PCI_CAP_ID_MSI: |
60 | { | 59 | if (entry->msi_attrib.maskbit) { |
61 | int pos; | 60 | int pos; |
62 | u32 mask_bits; | 61 | u32 mask_bits; |
63 | 62 | ||
64 | pos = (long)entry->mask_base; | 63 | pos = (long)entry->mask_base; |
65 | pci_read_config_dword(entry->dev, pos, &mask_bits); | 64 | pci_read_config_dword(entry->dev, pos, &mask_bits); |
66 | mask_bits &= ~(1); | 65 | mask_bits &= ~(1); |
67 | mask_bits |= flag; | 66 | mask_bits |= flag; |
68 | pci_write_config_dword(entry->dev, pos, mask_bits); | 67 | pci_write_config_dword(entry->dev, pos, mask_bits); |
68 | } | ||
69 | break; | 69 | break; |
70 | } | ||
71 | case PCI_CAP_ID_MSIX: | 70 | case PCI_CAP_ID_MSIX: |
72 | { | 71 | { |
73 | int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + | 72 | int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + |
@@ -76,6 +75,7 @@ static void msi_set_mask_bit(unsigned int irq, int flag) | |||
76 | break; | 75 | break; |
77 | } | 76 | } |
78 | default: | 77 | default: |
78 | BUG(); | ||
79 | break; | 79 | break; |
80 | } | 80 | } |
81 | } | 81 | } |
@@ -186,83 +186,21 @@ static void unmask_MSI_irq(unsigned int irq) | |||
186 | msi_set_mask_bit(irq, 0); | 186 | msi_set_mask_bit(irq, 0); |
187 | } | 187 | } |
188 | 188 | ||
189 | static unsigned int startup_msi_irq_wo_maskbit(unsigned int irq) | 189 | static void ack_msi_irq(unsigned int irq) |
190 | { | ||
191 | return 0; /* never anything pending */ | ||
192 | } | ||
193 | |||
194 | static unsigned int startup_msi_irq_w_maskbit(unsigned int irq) | ||
195 | { | ||
196 | startup_msi_irq_wo_maskbit(irq); | ||
197 | unmask_MSI_irq(irq); | ||
198 | return 0; /* never anything pending */ | ||
199 | } | ||
200 | |||
201 | static void shutdown_msi_irq(unsigned int irq) | ||
202 | { | ||
203 | } | ||
204 | |||
205 | static void end_msi_irq_wo_maskbit(unsigned int irq) | ||
206 | { | 190 | { |
207 | move_native_irq(irq); | 191 | move_native_irq(irq); |
208 | ack_APIC_irq(); | 192 | ack_APIC_irq(); |
209 | } | 193 | } |
210 | 194 | ||
211 | static void end_msi_irq_w_maskbit(unsigned int irq) | ||
212 | { | ||
213 | move_native_irq(irq); | ||
214 | unmask_MSI_irq(irq); | ||
215 | ack_APIC_irq(); | ||
216 | } | ||
217 | |||
218 | static void do_nothing(unsigned int irq) | ||
219 | { | ||
220 | } | ||
221 | |||
222 | /* | ||
223 | * Interrupt Type for MSI-X PCI/PCI-X/PCI-Express Devices, | ||
224 | * which implement the MSI-X Capability Structure. | ||
225 | */ | ||
226 | static struct hw_interrupt_type msix_irq_type = { | ||
227 | .typename = "PCI-MSI-X", | ||
228 | .startup = startup_msi_irq_w_maskbit, | ||
229 | .shutdown = shutdown_msi_irq, | ||
230 | .enable = unmask_MSI_irq, | ||
231 | .disable = mask_MSI_irq, | ||
232 | .ack = mask_MSI_irq, | ||
233 | .end = end_msi_irq_w_maskbit, | ||
234 | .set_affinity = set_msi_affinity | ||
235 | }; | ||
236 | |||
237 | /* | ||
238 | * Interrupt Type for MSI PCI/PCI-X/PCI-Express Devices, | ||
239 | * which implement the MSI Capability Structure with | ||
240 | * Mask-and-Pending Bits. | ||
241 | */ | ||
242 | static struct hw_interrupt_type msi_irq_w_maskbit_type = { | ||
243 | .typename = "PCI-MSI", | ||
244 | .startup = startup_msi_irq_w_maskbit, | ||
245 | .shutdown = shutdown_msi_irq, | ||
246 | .enable = unmask_MSI_irq, | ||
247 | .disable = mask_MSI_irq, | ||
248 | .ack = mask_MSI_irq, | ||
249 | .end = end_msi_irq_w_maskbit, | ||
250 | .set_affinity = set_msi_affinity | ||
251 | }; | ||
252 | |||
253 | /* | 195 | /* |
254 | * Interrupt Type for MSI PCI/PCI-X/PCI-Express Devices, | 196 | * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices, |
255 | * which implement the MSI Capability Structure without | 197 | * which implement the MSI or MSI-X Capability Structure. |
256 | * Mask-and-Pending Bits. | ||
257 | */ | 198 | */ |
258 | static struct hw_interrupt_type msi_irq_wo_maskbit_type = { | 199 | static struct irq_chip msi_chip = { |
259 | .typename = "PCI-MSI", | 200 | .name = "PCI-MSI", |
260 | .startup = startup_msi_irq_wo_maskbit, | 201 | .unmask = unmask_MSI_irq, |
261 | .shutdown = shutdown_msi_irq, | 202 | .mask = mask_MSI_irq, |
262 | .enable = do_nothing, | 203 | .ack = ack_msi_irq, |
263 | .disable = do_nothing, | ||
264 | .ack = do_nothing, | ||
265 | .end = end_msi_irq_wo_maskbit, | ||
266 | .set_affinity = set_msi_affinity | 204 | .set_affinity = set_msi_affinity |
267 | }; | 205 | }; |
268 | 206 | ||
@@ -330,7 +268,7 @@ static void attach_msi_entry(struct msi_desc *entry, int irq) | |||
330 | spin_unlock_irqrestore(&msi_lock, flags); | 268 | spin_unlock_irqrestore(&msi_lock, flags); |
331 | } | 269 | } |
332 | 270 | ||
333 | static int create_msi_irq(struct hw_interrupt_type *handler) | 271 | static int create_msi_irq(struct irq_chip *chip) |
334 | { | 272 | { |
335 | struct msi_desc *entry; | 273 | struct msi_desc *entry; |
336 | int irq; | 274 | int irq; |
@@ -345,7 +283,7 @@ static int create_msi_irq(struct hw_interrupt_type *handler) | |||
345 | return -EBUSY; | 283 | return -EBUSY; |
346 | } | 284 | } |
347 | 285 | ||
348 | set_irq_chip(irq, handler); | 286 | set_irq_chip_and_handler(irq, chip, handle_edge_irq); |
349 | set_irq_data(irq, entry); | 287 | set_irq_data(irq, entry); |
350 | 288 | ||
351 | return irq; | 289 | return irq; |
@@ -634,16 +572,11 @@ static int msi_capability_init(struct pci_dev *dev) | |||
634 | struct msi_desc *entry; | 572 | struct msi_desc *entry; |
635 | int pos, irq; | 573 | int pos, irq; |
636 | u16 control; | 574 | u16 control; |
637 | struct hw_interrupt_type *handler; | ||
638 | 575 | ||
639 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); | 576 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); |
640 | pci_read_config_word(dev, msi_control_reg(pos), &control); | 577 | pci_read_config_word(dev, msi_control_reg(pos), &control); |
641 | /* MSI Entry Initialization */ | 578 | /* MSI Entry Initialization */ |
642 | handler = &msi_irq_wo_maskbit_type; | 579 | irq = create_msi_irq(&msi_chip); |
643 | if (is_mask_bit_support(control)) | ||
644 | handler = &msi_irq_w_maskbit_type; | ||
645 | |||
646 | irq = create_msi_irq(handler); | ||
647 | if (irq < 0) | 580 | if (irq < 0) |
648 | return irq; | 581 | return irq; |
649 | 582 | ||
@@ -715,7 +648,7 @@ static int msix_capability_init(struct pci_dev *dev, | |||
715 | 648 | ||
716 | /* MSI-X Table Initialization */ | 649 | /* MSI-X Table Initialization */ |
717 | for (i = 0; i < nvec; i++) { | 650 | for (i = 0; i < nvec; i++) { |
718 | irq = create_msi_irq(&msix_irq_type); | 651 | irq = create_msi_irq(&msi_chip); |
719 | if (irq < 0) | 652 | if (irq < 0) |
720 | break; | 653 | break; |
721 | 654 | ||