summaryrefslogtreecommitdiff
path: root/drivers/pci/msi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-02-23 11:53:22 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-23 11:53:22 -0800
commit60e8d3e11645a1b9c4197d9786df3894332c1685 (patch)
tree00f2d71dfc8c9e6cf9fc1033eca3f169249a838e /drivers/pci/msi.c
parent190c3ee06a0f0660839785b7ad8a830e832d9481 (diff)
parentc4d052ce970ea98e9e1cc72461ba3b7a25397657 (diff)
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.c122
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;