aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/msi.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2006-10-04 05:16:57 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-04 10:55:29 -0400
commit277bc33bc2479707e88b0b2ae6fe56e8e4aabe81 (patch)
tree2b7ca3715612d656ed6eab51d7a9504a80cfec4f /drivers/pci/msi.c
parent1f80025e624bb14fefadfef7e80fbfb9740d4714 (diff)
[PATCH] msi: only use a single irq_chip for msi interrupts
The logic works like this. Since we no longer track the state logic by hand in msi.c startup and shutdown are no longer needed. By updating msi_set_mask_bit to work on msi devices that do not implement a mask bit we can always call the mask/unmask functions. What we really have are mask and unmask so we use them to implement the .mask and .unmask functions instead of .enable and .disable. By switching to the handle_edge_irq handler we only need an ack function that moves the irq if necessary. Which removes the old end and ack functions and their peculiar logic of sometimes disabling an irq. This removes the reliance on pre genirq irq handling methods. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Tony Luck <tony.luck@intel.com> Cc: Andi Kleen <ak@suse.de> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Greg KH <greg@kroah.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
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