diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/host/Kconfig | 1 | ||||
-rw-r--r-- | drivers/pci/host/pcie-altera.c | 23 | ||||
-rw-r--r-- | drivers/pci/host/pcie-designware.c | 1 | ||||
-rw-r--r-- | drivers/pci/host/pcie-hisi.c | 8 | ||||
-rw-r--r-- | drivers/pci/msi.c | 8 | ||||
-rw-r--r-- | drivers/pci/pci-acpi.c | 44 | ||||
-rw-r--r-- | drivers/pci/pci-driver.c | 16 | ||||
-rw-r--r-- | drivers/pci/pci-sysfs.c | 5 | ||||
-rw-r--r-- | drivers/pci/pci.c | 4 | ||||
-rw-r--r-- | drivers/pci/pci.h | 4 | ||||
-rw-r--r-- | drivers/pci/probe.c | 2 | ||||
-rw-r--r-- | drivers/pci/quirks.c | 4 |
12 files changed, 97 insertions, 23 deletions
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index 6d181ba09ccd..75a605426538 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig @@ -5,6 +5,7 @@ config PCI_DRA7XX bool "TI DRA7xx PCIe controller" select PCIE_DW depends on OF && HAS_IOMEM && TI_PIPE3 + depends on BROKEN help Enables support for the PCIe controller in the DRA7xx SoC. There are two instances of PCIe controller in DRA7xx. This controller can diff --git a/drivers/pci/host/pcie-altera.c b/drivers/pci/host/pcie-altera.c index e5dda38bdde5..99da549d5d06 100644 --- a/drivers/pci/host/pcie-altera.c +++ b/drivers/pci/host/pcie-altera.c @@ -55,8 +55,10 @@ #define TLP_CFG_DW2(bus, devfn, offset) \ (((bus) << 24) | ((devfn) << 16) | (offset)) #define TLP_REQ_ID(bus, devfn) (((bus) << 8) | (devfn)) +#define TLP_COMP_STATUS(s) (((s) >> 12) & 7) #define TLP_HDR_SIZE 3 #define TLP_LOOP 500 +#define RP_DEVFN 0 #define INTX_NUM 4 @@ -166,34 +168,41 @@ static bool altera_pcie_valid_config(struct altera_pcie *pcie, static int tlp_read_packet(struct altera_pcie *pcie, u32 *value) { - u8 loop; + int i; bool sop = 0; u32 ctrl; u32 reg0, reg1; + u32 comp_status = 1; /* * Minimum 2 loops to read TLP headers and 1 loop to read data * payload. */ - for (loop = 0; loop < TLP_LOOP; loop++) { + for (i = 0; i < TLP_LOOP; i++) { ctrl = cra_readl(pcie, RP_RXCPL_STATUS); if ((ctrl & RP_RXCPL_SOP) || (ctrl & RP_RXCPL_EOP) || sop) { reg0 = cra_readl(pcie, RP_RXCPL_REG0); reg1 = cra_readl(pcie, RP_RXCPL_REG1); - if (ctrl & RP_RXCPL_SOP) + if (ctrl & RP_RXCPL_SOP) { sop = true; + comp_status = TLP_COMP_STATUS(reg1); + } if (ctrl & RP_RXCPL_EOP) { + if (comp_status) + return PCIBIOS_DEVICE_NOT_FOUND; + if (value) *value = reg0; + return PCIBIOS_SUCCESSFUL; } } udelay(5); } - return -ENOENT; + return PCIBIOS_DEVICE_NOT_FOUND; } static void tlp_write_packet(struct altera_pcie *pcie, u32 *headers, @@ -233,7 +242,7 @@ static int tlp_cfg_dword_read(struct altera_pcie *pcie, u8 bus, u32 devfn, else headers[0] = TLP_CFG_DW0(TLP_FMTTYPE_CFGRD1); - headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, devfn), + headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, RP_DEVFN), TLP_READ_TAG, byte_en); headers[2] = TLP_CFG_DW2(bus, devfn, where); @@ -253,7 +262,7 @@ static int tlp_cfg_dword_write(struct altera_pcie *pcie, u8 bus, u32 devfn, else headers[0] = TLP_CFG_DW0(TLP_FMTTYPE_CFGWR1); - headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, devfn), + headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, RP_DEVFN), TLP_WRITE_TAG, byte_en); headers[2] = TLP_CFG_DW2(bus, devfn, where); @@ -458,7 +467,7 @@ static int altera_pcie_init_irq_domain(struct altera_pcie *pcie) struct device_node *node = dev->of_node; /* Setup INTx */ - pcie->irq_domain = irq_domain_add_linear(node, INTX_NUM, + pcie->irq_domain = irq_domain_add_linear(node, INTX_NUM + 1, &intx_domain_ops, pcie); if (!pcie->irq_domain) { dev_err(dev, "Failed to get a INTx IRQ domain\n"); diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index e28bc0bd3a7d..21716827847a 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -440,7 +440,6 @@ int dw_pcie_host_init(struct pcie_port *pp) ret, pp->io); continue; } - pp->io_base = pp->io->start; break; case IORESOURCE_MEM: pp->mem = win->res; diff --git a/drivers/pci/host/pcie-hisi.c b/drivers/pci/host/pcie-hisi.c index 4bad6954019b..3e98d4edae2d 100644 --- a/drivers/pci/host/pcie-hisi.c +++ b/drivers/pci/host/pcie-hisi.c @@ -72,7 +72,9 @@ static int hisi_pcie_cfg_read(struct pcie_port *pp, int where, int size, *val = *(u8 __force *) walker; else if (size == 2) *val = *(u16 __force *) walker; - else if (size != 4) + else if (size == 4) + *val = reg_val; + else return PCIBIOS_BAD_REGISTER_NUMBER; return PCIBIOS_SUCCESSFUL; @@ -138,7 +140,7 @@ static struct pcie_host_ops hisi_pcie_host_ops = { .link_up = hisi_pcie_link_up, }; -static int __init hisi_add_pcie_port(struct pcie_port *pp, +static int hisi_add_pcie_port(struct pcie_port *pp, struct platform_device *pdev) { int ret; @@ -166,7 +168,7 @@ static int __init hisi_add_pcie_port(struct pcie_port *pp, return 0; } -static int __init hisi_pcie_probe(struct platform_device *pdev) +static int hisi_pcie_probe(struct platform_device *pdev) { struct hisi_pcie *hisi_pcie; struct pcie_port *pp; diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index b64d26719906..a080f4496fe2 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -54,7 +54,7 @@ static int pci_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) struct irq_domain *domain; domain = pci_msi_get_domain(dev); - if (domain) + if (domain && irq_domain_is_hierarchy(domain)) return pci_msi_domain_alloc_irqs(domain, dev, nvec, type); return arch_setup_msi_irqs(dev, nvec, type); @@ -65,7 +65,7 @@ static void pci_msi_teardown_msi_irqs(struct pci_dev *dev) struct irq_domain *domain; domain = pci_msi_get_domain(dev); - if (domain) + if (domain && irq_domain_is_hierarchy(domain)) pci_msi_domain_free_irqs(domain, dev); else arch_teardown_msi_irqs(dev); @@ -257,6 +257,7 @@ void pci_msi_mask_irq(struct irq_data *data) { msi_set_mask_bit(data, 1); } +EXPORT_SYMBOL_GPL(pci_msi_mask_irq); /** * pci_msi_unmask_irq - Generic irq chip callback to unmask PCI/MSI interrupts @@ -266,6 +267,7 @@ void pci_msi_unmask_irq(struct irq_data *data) { msi_set_mask_bit(data, 0); } +EXPORT_SYMBOL_GPL(pci_msi_unmask_irq); void default_restore_msi_irqs(struct pci_dev *dev) { @@ -1122,6 +1124,7 @@ struct pci_dev *msi_desc_to_pci_dev(struct msi_desc *desc) { return to_pci_dev(desc->dev); } +EXPORT_SYMBOL(msi_desc_to_pci_dev); void *msi_desc_to_pci_sysdata(struct msi_desc *desc) { @@ -1281,6 +1284,7 @@ struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode, domain->bus_token = DOMAIN_BUS_PCI_MSI; return domain; } +EXPORT_SYMBOL_GPL(pci_msi_create_irq_domain); /** * pci_msi_domain_alloc_irqs - Allocate interrupts for @dev in @domain diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index a32ba753e413..9a033e8ee9a4 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -9,7 +9,9 @@ #include <linux/delay.h> #include <linux/init.h> +#include <linux/irqdomain.h> #include <linux/pci.h> +#include <linux/msi.h> #include <linux/pci_hotplug.h> #include <linux/module.h> #include <linux/pci-aspm.h> @@ -529,7 +531,7 @@ static bool acpi_pci_need_resume(struct pci_dev *dev) return !!adev->power.flags.dsw_present; } -static struct pci_platform_pm_ops acpi_pci_platform_pm = { +static const struct pci_platform_pm_ops acpi_pci_platform_pm = { .is_manageable = acpi_pci_power_manageable, .set_state = acpi_pci_set_power_state, .choose_state = acpi_pci_choose_state, @@ -689,6 +691,46 @@ static struct acpi_bus_type acpi_pci_bus = { .cleanup = pci_acpi_cleanup, }; + +static struct fwnode_handle *(*pci_msi_get_fwnode_cb)(struct device *dev); + +/** + * pci_msi_register_fwnode_provider - Register callback to retrieve fwnode + * @fn: Callback matching a device to a fwnode that identifies a PCI + * MSI domain. + * + * This should be called by irqchip driver, which is the parent of + * the MSI domain to provide callback interface to query fwnode. + */ +void +pci_msi_register_fwnode_provider(struct fwnode_handle *(*fn)(struct device *)) +{ + pci_msi_get_fwnode_cb = fn; +} + +/** + * pci_host_bridge_acpi_msi_domain - Retrieve MSI domain of a PCI host bridge + * @bus: The PCI host bridge bus. + * + * This function uses the callback function registered by + * pci_msi_register_fwnode_provider() to retrieve the irq_domain with + * type DOMAIN_BUS_PCI_MSI of the specified host bridge bus. + * This returns NULL on error or when the domain is not found. + */ +struct irq_domain *pci_host_bridge_acpi_msi_domain(struct pci_bus *bus) +{ + struct fwnode_handle *fwnode; + + if (!pci_msi_get_fwnode_cb) + return NULL; + + fwnode = pci_msi_get_fwnode_cb(&bus->dev); + if (!fwnode) + return NULL; + + return irq_find_matching_fwnode(fwnode, DOMAIN_BUS_PCI_MSI); +} + static int __init acpi_pci_init(void) { int ret; diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 4446fcb5effd..d7ffd66814bb 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -1146,9 +1146,21 @@ static int pci_pm_runtime_suspend(struct device *dev) pci_dev->state_saved = false; pci_dev->no_d3cold = false; error = pm->runtime_suspend(dev); - suspend_report_result(pm->runtime_suspend, error); - if (error) + if (error) { + /* + * -EBUSY and -EAGAIN is used to request the runtime PM core + * to schedule a new suspend, so log the event only with debug + * log level. + */ + if (error == -EBUSY || error == -EAGAIN) + dev_dbg(dev, "can't suspend now (%pf returned %d)\n", + pm->runtime_suspend, error); + else + dev_err(dev, "can't suspend (%pf returned %d)\n", + pm->runtime_suspend, error); + return error; + } if (!pci_dev->d3cold_allowed) pci_dev->no_d3cold = true; diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 4ba61db43a6b..95d9e7bd933b 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -216,7 +216,10 @@ static ssize_t numa_node_store(struct device *dev, if (ret) return ret; - if (node >= MAX_NUMNODES || !node_online(node)) + if ((node < 0 && node != NUMA_NO_NODE) || node >= MAX_NUMNODES) + return -EINVAL; + + if (node != NUMA_NO_NODE && !node_online(node)) return -EINVAL; add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 49e3715477d1..602eb4223510 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -527,9 +527,9 @@ static void pci_restore_bars(struct pci_dev *dev) pci_update_resource(dev, i); } -static struct pci_platform_pm_ops *pci_platform_pm; +static const struct pci_platform_pm_ops *pci_platform_pm; -int pci_set_platform_pm(struct pci_platform_pm_ops *ops) +int pci_set_platform_pm(const struct pci_platform_pm_ops *ops) { if (!ops->is_manageable || !ops->set_state || !ops->choose_state || !ops->sleep_wake) diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 44d9859057b4..9a1660f592ef 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -68,7 +68,7 @@ struct pci_platform_pm_ops { bool (*need_resume)(struct pci_dev *dev); }; -int pci_set_platform_pm(struct pci_platform_pm_ops *ops); +int pci_set_platform_pm(const struct pci_platform_pm_ops *ops); void pci_update_current_state(struct pci_dev *dev, pci_power_t state); void pci_power_up(struct pci_dev *dev); void pci_disable_enabled_device(struct pci_dev *dev); @@ -335,6 +335,4 @@ static inline int pci_dev_specific_reset(struct pci_dev *dev, int probe) } #endif -struct pci_host_bridge *pci_find_host_bridge(struct pci_bus *bus); - #endif /* DRIVERS_PCI_H */ diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 32b9f1b88266..6d7ab9bb0d5a 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -672,6 +672,8 @@ static struct irq_domain *pci_host_bridge_msi_domain(struct pci_bus *bus) * should be called from here. */ d = pci_host_bridge_of_msi_domain(bus); + if (!d) + d = pci_host_bridge_acpi_msi_domain(bus); return d; } diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 13ac34ddec19..0575a1e026b4 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3417,7 +3417,9 @@ static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe) return 0; } -#include "../gpu/drm/i915/i915_reg.h" +#define SOUTH_CHICKEN2 0xc2004 +#define PCH_PP_STATUS 0xc7200 +#define PCH_PP_CONTROL 0xc7204 #define MSG_CTL 0x45010 #define NSDE_PWR_STATE 0xd0100 #define IGD_OPERATION_TIMEOUT 10000 /* set timeout 10 seconds */ |