aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLucas Stach <l.stach@pengutronix.de>2015-09-18 14:58:35 -0400
committerBjorn Helgaas <bhelgaas@google.com>2015-09-18 14:58:35 -0400
commit79707374090411c5fa9dbcde862e59306bf8f765 (patch)
tree27fa887d0045afa25b0e4d4ae6fb3f3d4936a923
parentea643e1a33576216de589cf525dbb40267fde5a9 (diff)
PCI: designware: Implement multivector MSI IRQ setup
Implement multivector MSI IRQ setup. This allows to set up and use multiple MSI IRQs per device. [bhelgaas: changelog, use -EINVAL instead of -ENOSYS] Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Pratyush Anand <pratyush.anand@gmail.com>
-rw-r--r--drivers/pci/host/pcie-designware.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index ea5b285baea6..66d789aefa0d 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -286,6 +286,9 @@ static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
286 } 286 }
287 287
288 *pos = pos0; 288 *pos = pos0;
289 desc->nvec_used = no_irqs;
290 desc->msi_attrib.multiple = order_base_2(no_irqs);
291
289 return irq; 292 return irq;
290 293
291no_valid_irq: 294no_valid_irq:
@@ -329,6 +332,33 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
329 return 0; 332 return 0;
330} 333}
331 334
335static int dw_msi_setup_irqs(struct msi_controller *chip, struct pci_dev *pdev,
336 int nvec, int type)
337{
338#ifdef CONFIG_PCI_MSI
339 int irq, pos;
340 struct msi_desc *desc;
341 struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
342
343 /* MSI-X interrupts are not supported */
344 if (type == PCI_CAP_ID_MSIX)
345 return -EINVAL;
346
347 WARN_ON(!list_is_singular(&pdev->dev.msi_list));
348 desc = list_entry(pdev->dev.msi_list.next, struct msi_desc, list);
349
350 irq = assign_irq(nvec, desc, &pos);
351 if (irq < 0)
352 return irq;
353
354 dw_msi_setup_msg(pp, irq, pos);
355
356 return 0;
357#else
358 return -EINVAL;
359#endif
360}
361
332static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq) 362static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
333{ 363{
334 struct irq_data *data = irq_get_irq_data(irq); 364 struct irq_data *data = irq_get_irq_data(irq);
@@ -340,6 +370,7 @@ static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
340 370
341static struct msi_controller dw_pcie_msi_chip = { 371static struct msi_controller dw_pcie_msi_chip = {
342 .setup_irq = dw_msi_setup_irq, 372 .setup_irq = dw_msi_setup_irq,
373 .setup_irqs = dw_msi_setup_irqs,
343 .teardown_irq = dw_msi_teardown_irq, 374 .teardown_irq = dw_msi_teardown_irq,
344}; 375};
345 376