| From be4cfe50a3e531de950da56180c5b7a6f38ce154 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 22 Jun 2021 17:26:30 +0200 |
| Subject: PCI: iproc: Support multi-MSI only on uniprocessor kernel |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Sandor Bodo-Merle <sbodomerle@gmail.com> |
| |
| [ Upstream commit 2dc0a201d0f59e6818ef443609f0850a32910844 ] |
| |
| The interrupt affinity scheme used by this driver is incompatible with |
| multi-MSI as it implies moving the doorbell address to that of another MSI |
| group. This isn't possible for multi-MSI, as all the MSIs must have the |
| same doorbell address. As such it is restricted to systems with a single |
| CPU. |
| |
| Link: https://lore.kernel.org/r/20210622152630.40842-2-sbodomerle@gmail.com |
| Fixes: fc54bae28818 ("PCI: iproc: Allow allocation of multiple MSIs") |
| Reported-by: Marc Zyngier <maz@kernel.org> |
| Signed-off-by: Sandor Bodo-Merle <sbodomerle@gmail.com> |
| Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> |
| Acked-by: Marc Zyngier <maz@kernel.org> |
| Acked-by: Pali Rohár <pali@kernel.org> |
| Acked-by: Ray Jui <ray.jui@broadcom.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/pci/controller/pcie-iproc-msi.c | 8 +++++++- |
| 1 file changed, 7 insertions(+), 1 deletion(-) |
| |
| diff --git a/drivers/pci/controller/pcie-iproc-msi.c b/drivers/pci/controller/pcie-iproc-msi.c |
| index 557d93dcb3bc..81b4effeb130 100644 |
| --- a/drivers/pci/controller/pcie-iproc-msi.c |
| +++ b/drivers/pci/controller/pcie-iproc-msi.c |
| @@ -171,7 +171,7 @@ static struct irq_chip iproc_msi_irq_chip = { |
| |
| static struct msi_domain_info iproc_msi_domain_info = { |
| .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | |
| - MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX, |
| + MSI_FLAG_PCI_MSIX, |
| .chip = &iproc_msi_irq_chip, |
| }; |
| |
| @@ -250,6 +250,9 @@ static int iproc_msi_irq_domain_alloc(struct irq_domain *domain, |
| struct iproc_msi *msi = domain->host_data; |
| int hwirq, i; |
| |
| + if (msi->nr_cpus > 1 && nr_irqs > 1) |
| + return -EINVAL; |
| + |
| mutex_lock(&msi->bitmap_lock); |
| |
| /* |
| @@ -540,6 +543,9 @@ int iproc_msi_init(struct iproc_pcie *pcie, struct device_node *node) |
| mutex_init(&msi->bitmap_lock); |
| msi->nr_cpus = num_possible_cpus(); |
| |
| + if (msi->nr_cpus == 1) |
| + iproc_msi_domain_info.flags |= MSI_FLAG_MULTI_PCI_MSI; |
| + |
| msi->nr_irqs = of_irq_count(node); |
| if (!msi->nr_irqs) { |
| dev_err(pcie->dev, "found no MSI GIC interrupt\n"); |
| -- |
| 2.30.2 |
| |