|
@@ -286,6 +286,9 @@ static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
|
|
}
|
|
}
|
|
|
|
|
|
*pos = pos0;
|
|
*pos = pos0;
|
|
|
|
+ desc->nvec_used = no_irqs;
|
|
|
|
+ desc->msi_attrib.multiple = order_base_2(no_irqs);
|
|
|
|
+
|
|
return irq;
|
|
return irq;
|
|
|
|
|
|
no_valid_irq:
|
|
no_valid_irq:
|
|
@@ -329,6 +332,33 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int dw_msi_setup_irqs(struct msi_controller *chip, struct pci_dev *pdev,
|
|
|
|
+ int nvec, int type)
|
|
|
|
+{
|
|
|
|
+#ifdef CONFIG_PCI_MSI
|
|
|
|
+ int irq, pos;
|
|
|
|
+ struct msi_desc *desc;
|
|
|
|
+ struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
|
|
|
|
+
|
|
|
|
+ /* MSI-X interrupts are not supported */
|
|
|
|
+ if (type == PCI_CAP_ID_MSIX)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ WARN_ON(!list_is_singular(&pdev->dev.msi_list));
|
|
|
|
+ desc = list_entry(pdev->dev.msi_list.next, struct msi_desc, list);
|
|
|
|
+
|
|
|
|
+ irq = assign_irq(nvec, desc, &pos);
|
|
|
|
+ if (irq < 0)
|
|
|
|
+ return irq;
|
|
|
|
+
|
|
|
|
+ dw_msi_setup_msg(pp, irq, pos);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+#else
|
|
|
|
+ return -EINVAL;
|
|
|
|
+#endif
|
|
|
|
+}
|
|
|
|
+
|
|
static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
|
|
static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
|
|
{
|
|
{
|
|
struct irq_data *data = irq_get_irq_data(irq);
|
|
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)
|
|
|
|
|
|
static struct msi_controller dw_pcie_msi_chip = {
|
|
static struct msi_controller dw_pcie_msi_chip = {
|
|
.setup_irq = dw_msi_setup_irq,
|
|
.setup_irq = dw_msi_setup_irq,
|
|
|
|
+ .setup_irqs = dw_msi_setup_irqs,
|
|
.teardown_irq = dw_msi_teardown_irq,
|
|
.teardown_irq = dw_msi_teardown_irq,
|
|
};
|
|
};
|
|
|
|
|