All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] irqchip/gic-v3-its: Fix MSI alias accounting
@ 2017-05-31 17:52 Robin Murphy
  2017-05-31 18:29 ` Marc Zyngier
  0 siblings, 1 reply; 2+ messages in thread
From: Robin Murphy @ 2017-05-31 17:52 UTC (permalink / raw)
  To: tglx, jason, marc.zyngier; +Cc: linux-kernel

The call to pci_for_each_dma_alias() in the ITS PCI code has aroused
suspicion in the past, and upon closer inspection does turn out to be
completely backwards. Rather than iterating through each RID alias of
the given device, what we actually want to be doing here is iterating
through all the *other* devices which may also alias the same RID, in
order to size the table for the worst case.

Do the right thing by ignoring the initial DMA aliases themselves and
just using that walk to detect an aliasing bridge, then walking back
down the bus topology as necessary to actually count everything else.

Our alias handling still isn't perfect, since we don't account for the
cases of certain bridges only taking ownership of transactions under
particular circumstances, but without completely reworking the ITS code
to cope with the notion of multiple DevIDs per device, it'll have to do.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
 drivers/irqchip/irq-gic-v3-its-pci-msi.c | 35 ++++++++++++++++----------------
 1 file changed, 17 insertions(+), 18 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
index aee1c60d7ab5..77931214d954 100644
--- a/drivers/irqchip/irq-gic-v3-its-pci-msi.c
+++ b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
@@ -41,27 +41,22 @@ static struct irq_chip its_msi_irq_chip = {
 	.irq_write_msi_msg	= pci_msi_domain_write_msg,
 };
 
-struct its_pci_alias {
-	struct pci_dev	*pdev;
-	u32		count;
-};
-
-static int its_pci_msi_vec_count(struct pci_dev *pdev)
+static int its_pci_msi_vec_count(struct pci_dev *pdev, void *data)
 {
-	int msi, msix;
+	int msi, msix, *count = data;
 
 	msi = max(pci_msi_vec_count(pdev), 0);
 	msix = max(pci_msix_vec_count(pdev), 0);
+	*count += max(msi, msix);
 
-	return max(msi, msix);
+	return 0;
 }
 
 static int its_get_pci_alias(struct pci_dev *pdev, u16 alias, void *data)
 {
-	struct its_pci_alias *dev_alias = data;
+	struct pci_dev **alias_dev = data;
 
-	if (pdev != dev_alias->pdev)
-		dev_alias->count += its_pci_msi_vec_count(pdev);
+	*alias_dev = pdev;
 
 	return 0;
 }
@@ -69,9 +64,9 @@ static int its_get_pci_alias(struct pci_dev *pdev, u16 alias, void *data)
 static int its_pci_msi_prepare(struct irq_domain *domain, struct device *dev,
 			       int nvec, msi_alloc_info_t *info)
 {
-	struct pci_dev *pdev;
-	struct its_pci_alias dev_alias;
+	struct pci_dev *pdev, *alias_dev;
 	struct msi_domain_info *msi_info;
+	int alias_count = 0;
 
 	if (!dev_is_pci(dev))
 		return -EINVAL;
@@ -79,16 +74,20 @@ static int its_pci_msi_prepare(struct irq_domain *domain, struct device *dev,
 	msi_info = msi_get_domain_info(domain->parent);
 
 	pdev = to_pci_dev(dev);
-	dev_alias.pdev = pdev;
-	dev_alias.count = nvec;
-
-	pci_for_each_dma_alias(pdev, its_get_pci_alias, &dev_alias);
+	/*
+	 * If pdev is downstream of any aliasing bridges, take an upper
+	 * bound of how many other vectors could map to the same DevID.
+	 */
+	pci_for_each_dma_alias(pdev, its_get_pci_alias, &alias_dev);
+	if (alias_dev != pdev && alias_dev->subordinate)
+		pci_walk_bus(alias_dev->subordinate, its_pci_msi_vec_count,
+			     &alias_count);
 
 	/* ITS specific DeviceID, as the core ITS ignores dev. */
 	info->scratchpad[0].ul = pci_msi_domain_get_msi_rid(domain, pdev);
 
 	return msi_info->ops->msi_prepare(domain->parent,
-					  dev, dev_alias.count, info);
+					  dev, max(nvec, alias_count), info);
 }
 
 static struct msi_domain_ops its_pci_msi_ops = {
-- 
2.12.2.dirty

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] irqchip/gic-v3-its: Fix MSI alias accounting
  2017-05-31 17:52 [PATCH] irqchip/gic-v3-its: Fix MSI alias accounting Robin Murphy
@ 2017-05-31 18:29 ` Marc Zyngier
  0 siblings, 0 replies; 2+ messages in thread
From: Marc Zyngier @ 2017-05-31 18:29 UTC (permalink / raw)
  To: Robin Murphy, tglx, jason; +Cc: linux-kernel

On 31/05/17 18:52, Robin Murphy wrote:
> The call to pci_for_each_dma_alias() in the ITS PCI code has aroused
> suspicion in the past, and upon closer inspection does turn out to be
> completely backwards. Rather than iterating through each RID alias of
> the given device, what we actually want to be doing here is iterating
> through all the *other* devices which may also alias the same RID, in
> order to size the table for the worst case.
> 
> Do the right thing by ignoring the initial DMA aliases themselves and
> just using that walk to detect an aliasing bridge, then walking back
> down the bus topology as necessary to actually count everything else.
> 
> Our alias handling still isn't perfect, since we don't account for the
> cases of certain bridges only taking ownership of transactions under
> particular circumstances, but without completely reworking the ITS code
> to cope with the notion of multiple DevIDs per device, it'll have to do.
> 
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>

Ah, that's pretty neat.

Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>

I'll queue this for 4.13.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2017-05-31 18:29 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-31 17:52 [PATCH] irqchip/gic-v3-its: Fix MSI alias accounting Robin Murphy
2017-05-31 18:29 ` Marc Zyngier

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.