diff options
Diffstat (limited to 'drivers/pci/pcie/portdrv_core.c')
-rw-r--r-- | drivers/pci/pcie/portdrv_core.c | 34 |
1 files changed, 18 insertions, 16 deletions
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index 75915b30ad19..d03a7a39b2d8 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -200,10 +200,13 @@ static int init_service_irqs(struct pci_dev *dev, int *irqs, int mask) { int i, irq = -1; - /* We have to use INTx if MSI cannot be used for PCIe PME or pciehp. */ + /* + * If MSI cannot be used for PCIe PME or hotplug, we have to use + * INTx or other interrupts, e.g. system shared interrupt. + */ if (((mask & PCIE_PORT_SERVICE_PME) && pcie_pme_no_msi()) || ((mask & PCIE_PORT_SERVICE_HP) && pciehp_no_msi())) { - if (dev->pin) + if (dev->irq) irq = dev->irq; goto no_msi; } @@ -212,8 +215,12 @@ static int init_service_irqs(struct pci_dev *dev, int *irqs, int mask) if (!pcie_port_enable_msix(dev, irqs, mask)) return 0; - /* We're not going to use MSI-X, so try MSI and fall back to INTx */ - if (!pci_enable_msi(dev) || dev->pin) + /* + * We're not going to use MSI-X, so try MSI and fall back to INTx. + * If neither MSI/MSI-X nor INTx available, try other interrupt. On + * some platforms, root port doesn't support MSI/MSI-X/INTx in RC mode. + */ + if (!pci_enable_msi(dev) || dev->irq) irq = dev->irq; no_msi: @@ -246,8 +253,7 @@ static void cleanup_service_irqs(struct pci_dev *dev) */ static int get_port_device_capability(struct pci_dev *dev) { - int services = 0, pos; - u16 reg16; + int services = 0; u32 reg32; int cap_mask = 0; int err; @@ -265,11 +271,9 @@ static int get_port_device_capability(struct pci_dev *dev) return 0; } - pos = pci_pcie_cap(dev); - pci_read_config_word(dev, pos + PCI_EXP_FLAGS, ®16); /* Hot-Plug Capable */ - if ((cap_mask & PCIE_PORT_SERVICE_HP) && (reg16 & PCI_EXP_FLAGS_SLOT)) { - pci_read_config_dword(dev, pos + PCI_EXP_SLTCAP, ®32); + if (cap_mask & PCIE_PORT_SERVICE_HP) { + pcie_capability_read_dword(dev, PCI_EXP_SLTCAP, ®32); if (reg32 & PCI_EXP_SLTCAP_HPC) { services |= PCIE_PORT_SERVICE_HP; /* @@ -277,10 +281,8 @@ static int get_port_device_capability(struct pci_dev *dev) * enabled by the BIOS and the hot-plug service driver * is not loaded. */ - pos += PCI_EXP_SLTCTL; - pci_read_config_word(dev, pos, ®16); - reg16 &= ~(PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE); - pci_write_config_word(dev, pos, reg16); + pcie_capability_clear_word(dev, PCI_EXP_SLTCTL, + PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE); } } /* AER capable */ @@ -298,7 +300,7 @@ static int get_port_device_capability(struct pci_dev *dev) services |= PCIE_PORT_SERVICE_VC; /* Root ports are capable of generating PME too */ if ((cap_mask & PCIE_PORT_SERVICE_PME) - && dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) { + && pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) { services |= PCIE_PORT_SERVICE_PME; /* * Disable PME interrupt on this port in case it's been enabled @@ -336,7 +338,7 @@ static int pcie_device_init(struct pci_dev *pdev, int service, int irq) device->release = release_pcie_device; /* callback to free pcie dev */ dev_set_name(device, "%s:pcie%02x", pci_name(pdev), - get_descriptor_id(pdev->pcie_type, service)); + get_descriptor_id(pci_pcie_type(pdev), service)); device->parent = &pdev->dev; device_enable_async_suspend(device); |