Commit 249e2a38 authored by Ganesan Ramalingam's avatar Ganesan Ramalingam Committed by Ralf Baechle

MIPS: Netlogic: MSI enable fix for XLS

MSI interrupts do not work on XLS after commit a776c491
( "PCI: msi: Disable msi interrupts when we initialize a pci device" )
because the change disables MSI interrupts on the XLS PCIe bridges
during the PCI enumeration.

Fix this by enabling MSI interrupts on the bridge in the
arch_setup_msi_irq() function. A new function xls_get_pcie_link()
has been introduced to get the PCI device corresponding to the
top level PCIe bridge on which MSI has to be enabled.

Also, update get_irq_vector() to use the new xls_get_pcie_link()
function and PCI_SLOT() macro for determining the IRQ of PCI devices.
Signed-off-by: 's avatarGanesan Ramalingam <>
Signed-off-by: 's avatarJayachandran C <>
Patchwork: 's avatarRalf Baechle <>
parent ea8e867d
......@@ -41,6 +41,7 @@
#include <linux/irq.h>
#include <linux/irqdesc.h>
#include <linux/console.h>
#include <linux/pci_regs.h>
#include <asm/io.h>
......@@ -156,35 +157,55 @@ struct pci_controller nlm_pci_controller = {
.io_offset = 0x00000000UL,
* The top level PCIe links on the XLS PCIe controller appear as
* bridges. Given a device, this function finds which link it is
* on.
static struct pci_dev *xls_get_pcie_link(const struct pci_dev *dev)
struct pci_bus *bus, *p;
/* Find the bridge on bus 0 */
bus = dev->bus;
for (p = bus->parent; p && p->number != 0; p = p->parent)
bus = p;
return p ? bus->self : NULL;
static int get_irq_vector(const struct pci_dev *dev)
struct pci_dev *lnk;
if (!nlm_chip_is_xls())
return PIC_PCIX_IRQ; /* for XLR just one IRQ*/
return PIC_PCIX_IRQ; /* for XLR just one IRQ */
* For XLS PCIe, there is an IRQ per Link, find out which
* link the device is on to assign interrupts
if (dev->bus->self == NULL)
lnk = xls_get_pcie_link(dev);
if (lnk == NULL)
return 0;
switch (dev->bus->self->devfn) {
case 0x0:
switch (PCI_SLOT(lnk->devfn)) {
case 0:
case 0x8:
case 1:
case 0x10:
case 2:
if (nlm_chip_is_xls_b())
case 0x18:
case 3:
if (nlm_chip_is_xls_b())
WARN(1, "Unexpected devfn %d\n", dev->bus->self->devfn);
WARN(1, "Unexpected devfn %d\n", lnk->devfn);
return 0;
......@@ -202,7 +223,27 @@ void arch_teardown_msi_irq(unsigned int irq)
int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
struct msi_msg msg;
struct pci_dev *lnk;
int irq, ret;
u16 val;
/* MSI not supported on XLR */
if (!nlm_chip_is_xls())
return 1;
* Enable MSI on the XLS PCIe controller bridge which was disabled
* at enumeration, the bridge MSI capability is at 0x50
lnk = xls_get_pcie_link(dev);
if (lnk == NULL)
return 1;
pci_read_config_word(lnk, 0x50 + PCI_MSI_FLAGS, &val);
if ((val & PCI_MSI_FLAGS_ENABLE) == 0) {
pci_write_config_word(lnk, 0x50 + PCI_MSI_FLAGS, val);
irq = get_irq_vector(dev);
if (irq <= 0)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment