diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-23 20:53:22 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-23 20:53:22 +0100 |
commit | 60e8d3e11645a1b9c4197d9786df3894332c1685 (patch) | |
tree | 00f2d71dfc8c9e6cf9fc1033eca3f169249a838e /drivers/pci/msi.c | |
parent | Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net (diff) | |
parent | Merge branch 'pci/virtualization' into next (diff) | |
download | linux-60e8d3e11645a1b9c4197d9786df3894332c1685.tar.xz linux-60e8d3e11645a1b9c4197d9786df3894332c1685.zip |
Merge tag 'pci-v4.11-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI updates from Bjorn Helgaas:
- add ASPM L1 substate support
- enable PCIe Extended Tags when supported
- configure PCIe MPS settings on iProc, Versatile, X-Gene, and Xilinx
- increase VPD access timeout
- add ACS quirks for Intel Union Point, Qualcomm QDF2400 and QDF2432
- use new pci_irq_alloc_vectors() in more drivers
- fix MSI affinity memory leak
- remove unused MSI interfaces and update documentation
- remove unused AER .link_reset() callback
- avoid pci_lock / p->pi_lock deadlock seen with perf
- serialize sysfs enable/disable num_vfs operations
- move DesignWare IP from drivers/pci/host/ to drivers/pci/dwc/ and
refactor so we can support both hosts and endpoints
- add DT ECAM-like support for HiSilicon Hip06/Hip07 controllers
- add Rockchip system power management support
- add Thunder-X cn81xx and cn83xx support
- add Exynos 5440 PCIe PHY support
* tag 'pci-v4.11-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (93 commits)
PCI: dwc: Remove dependency of designware on CONFIG_PCI
PCI: dwc: Add CONFIG_PCIE_DW_HOST to enable PCI dwc host
PCI: dwc: Split pcie-designware.c into host and core files
PCI: dwc: designware: Fix style errors in pcie-designware.c
PCI: dwc: designware: Parse "num-lanes" property in dw_pcie_setup_rc()
PCI: dwc: all: Split struct pcie_port into host-only and core structures
PCI: dwc: designware: Get device pointer at the start of dw_pcie_host_init()
PCI: dwc: all: Rename cfg_read/cfg_write to read/write
PCI: dwc: all: Use platform_set_drvdata() to save private data
PCI: dwc: designware: Move register defines to designware header file
PCI: dwc: Use PTR_ERR_OR_ZERO to simplify code
PCI: dra7xx: Group PHY API invocations
PCI: dra7xx: Enable MSI and legacy interrupts simultaneously
PCI: dra7xx: Add support to force RC to work in GEN1 mode
PCI: dra7xx: Simplify probe code with devm_gpiod_get_optional()
PCI: Move DesignWare IP support to new drivers/pci/dwc/ directory
PCI: exynos: Support the PHY generic framework
Documentation: binding: Modify the exynos5440 PCIe binding
phy: phy-exynos-pcie: Add support for Exynos PCIe PHY
Documentation: samsung-phy: Add exynos-pcie-phy binding
...
Diffstat (limited to 'drivers/pci/msi.c')
-rw-r--r-- | drivers/pci/msi.c | 122 |
1 files changed, 22 insertions, 100 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 7f73bacf13ed..980eaf588281 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -32,32 +32,13 @@ int pci_msi_ignore_mask; #define msix_table_size(flags) ((flags & PCI_MSIX_FLAGS_QSIZE) + 1) #ifdef CONFIG_PCI_MSI_IRQ_DOMAIN -static struct irq_domain *pci_msi_default_domain; -static DEFINE_MUTEX(pci_msi_domain_lock); - -struct irq_domain * __weak arch_get_pci_msi_domain(struct pci_dev *dev) -{ - return pci_msi_default_domain; -} - -static struct irq_domain *pci_msi_get_domain(struct pci_dev *dev) -{ - struct irq_domain *domain; - - domain = dev_get_msi_domain(&dev->dev); - if (domain) - return domain; - - return arch_get_pci_msi_domain(dev); -} - 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); + domain = dev_get_msi_domain(&dev->dev); if (domain && irq_domain_is_hierarchy(domain)) - return pci_msi_domain_alloc_irqs(domain, dev, nvec, type); + return msi_domain_alloc_irqs(domain, &dev->dev, nvec); return arch_setup_msi_irqs(dev, nvec, type); } @@ -66,9 +47,9 @@ static void pci_msi_teardown_msi_irqs(struct pci_dev *dev) { struct irq_domain *domain; - domain = pci_msi_get_domain(dev); + domain = dev_get_msi_domain(&dev->dev); if (domain && irq_domain_is_hierarchy(domain)) - pci_msi_domain_free_irqs(domain, dev); + msi_domain_free_irqs(domain, &dev->dev); else arch_teardown_msi_irqs(dev); } @@ -379,7 +360,7 @@ static void free_msi_irqs(struct pci_dev *dev) } list_del(&entry->list); - kfree(entry); + free_msi_entry(entry); } if (dev->msi_irq_groups) { @@ -610,7 +591,7 @@ static int msi_verify_entries(struct pci_dev *dev) * msi_capability_init - configure device's MSI capability structure * @dev: pointer to the pci_dev data structure of MSI device function * @nvec: number of interrupts to allocate - * @affinity: flag to indicate cpu irq affinity mask should be set + * @affd: description of automatic irq affinity assignments (may be %NULL) * * Setup the MSI capability structure of the device with the requested * number of interrupts. A return value of zero indicates the successful @@ -731,7 +712,7 @@ static int msix_setup_entries(struct pci_dev *dev, void __iomem *base, ret = 0; out: kfree(masks); - return 0; + return ret; } static void msix_program_entries(struct pci_dev *dev, @@ -1084,7 +1065,7 @@ static int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec, if (nvec < 0) return nvec; if (nvec < minvec) - return -EINVAL; + return -ENOSPC; if (nvec > maxvec) nvec = maxvec; @@ -1109,23 +1090,15 @@ static int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec, } } -/** - * pci_enable_msi_range - configure device's MSI capability structure - * @dev: device to configure - * @minvec: minimal number of interrupts to configure - * @maxvec: maximum number of interrupts to configure - * - * This function tries to allocate a maximum possible number of interrupts in a - * range between @minvec and @maxvec. It returns a negative errno if an error - * occurs. If it succeeds, it returns the actual number of interrupts allocated - * and updates the @dev's irq member to the lowest new interrupt number; - * the other interrupt numbers allocated to this device are consecutive. - **/ -int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec) +/* deprecated, don't use */ +int pci_enable_msi(struct pci_dev *dev) { - return __pci_enable_msi_range(dev, minvec, maxvec, NULL); + int rc = __pci_enable_msi_range(dev, 1, 1, NULL); + if (rc < 0) + return rc; + return 0; } -EXPORT_SYMBOL(pci_enable_msi_range); +EXPORT_SYMBOL(pci_enable_msi); static int __pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, int minvec, @@ -1235,9 +1208,11 @@ int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs, } /* use legacy irq if allowed */ - if ((flags & PCI_IRQ_LEGACY) && min_vecs == 1) { - pci_intx(dev, 1); - return 1; + if (flags & PCI_IRQ_LEGACY) { + if (min_vecs == 1 && dev->irq) { + pci_intx(dev, 1); + return 1; + } } return vecs; @@ -1391,7 +1366,7 @@ int pci_msi_domain_check_cap(struct irq_domain *domain, { struct msi_desc *desc = first_pci_msi_entry(to_pci_dev(dev)); - /* Special handling to support pci_enable_msi_range() */ + /* Special handling to support __pci_enable_msi_range() */ if (pci_msi_desc_is_multi_msi(desc) && !(info->flags & MSI_FLAG_MULTI_PCI_MSI)) return 1; @@ -1404,7 +1379,7 @@ int pci_msi_domain_check_cap(struct irq_domain *domain, static int pci_msi_domain_handle_error(struct irq_domain *domain, struct msi_desc *desc, int error) { - /* Special handling to support pci_enable_msi_range() */ + /* Special handling to support __pci_enable_msi_range() */ if (pci_msi_desc_is_multi_msi(desc) && error == -ENOSPC) return 1; @@ -1491,59 +1466,6 @@ struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode, } EXPORT_SYMBOL_GPL(pci_msi_create_irq_domain); -/** - * pci_msi_domain_alloc_irqs - Allocate interrupts for @dev in @domain - * @domain: The interrupt domain to allocate from - * @dev: The device for which to allocate - * @nvec: The number of interrupts to allocate - * @type: Unused to allow simpler migration from the arch_XXX interfaces - * - * Returns: - * A virtual interrupt number or an error code in case of failure - */ -int pci_msi_domain_alloc_irqs(struct irq_domain *domain, struct pci_dev *dev, - int nvec, int type) -{ - return msi_domain_alloc_irqs(domain, &dev->dev, nvec); -} - -/** - * pci_msi_domain_free_irqs - Free interrupts for @dev in @domain - * @domain: The interrupt domain - * @dev: The device for which to free interrupts - */ -void pci_msi_domain_free_irqs(struct irq_domain *domain, struct pci_dev *dev) -{ - msi_domain_free_irqs(domain, &dev->dev); -} - -/** - * pci_msi_create_default_irq_domain - Create a default MSI interrupt domain - * @fwnode: Optional fwnode of the interrupt controller - * @info: MSI domain info - * @parent: Parent irq domain - * - * Returns: A domain pointer or NULL in case of failure. If successful - * the default PCI/MSI irqdomain pointer is updated. - */ -struct irq_domain *pci_msi_create_default_irq_domain(struct fwnode_handle *fwnode, - struct msi_domain_info *info, struct irq_domain *parent) -{ - struct irq_domain *domain; - - mutex_lock(&pci_msi_domain_lock); - if (pci_msi_default_domain) { - pr_err("PCI: default irq domain for PCI MSI has already been created.\n"); - domain = NULL; - } else { - domain = pci_msi_create_irq_domain(fwnode, info, parent); - pci_msi_default_domain = domain; - } - mutex_unlock(&pci_msi_domain_lock); - - return domain; -} - static int get_msi_id_cb(struct pci_dev *pdev, u16 alias, void *data) { u32 *pa = data; |