aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/msi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/msi.c')
-rw-r--r--drivers/pci/msi.c115
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
189static unsigned int startup_msi_irq_wo_maskbit(unsigned int irq) 189static void ack_msi_irq(unsigned int irq)
190{
191 return 0; /* never anything pending */
192}
193
194static 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
201static void shutdown_msi_irq(unsigned int irq)
202{
203}
204
205static 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
211static 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
218static 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 */
226static 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 */
242static 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 */
258static struct hw_interrupt_type msi_irq_wo_maskbit_type = { 199static 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
333static int create_msi_irq(struct hw_interrupt_type *handler) 271static 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