Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 38ea72bd authored by Alex Williamson's avatar Alex Williamson Committed by Bjorn Helgaas
Browse files

PCI/MSI: Fix MSI IRQ domains for VFs on virtual buses



SR-IOV creates a virtual bus where bus->self is NULL.  When we add VFs and
scan for an MSI domain, pci_set_bus_msi_domain() dereferences bus->self,
which causes a kernel NULL pointer dereference oops.

Scan up to the parent bus until we find a real bridge where we can get the
MSI domain.

[bhelgaas: changelog]
Fixes: 44aa0c65 ("PCI/MSI: Add hooks to populate the msi_domain field")
Tested-by: default avatarJoerg Roedel <joro@8bytes.org>
Signed-off-by: default avatarAlex Williamson <alex.williamson@redhat.com>
Signed-off-by: default avatarBjorn Helgaas <helgaas@kernel.org>
Acked-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
parent b838b39e
Loading
Loading
Loading
Loading
+11 −6
Original line number Diff line number Diff line
@@ -676,15 +676,20 @@ static struct irq_domain *pci_host_bridge_msi_domain(struct pci_bus *bus)
static void pci_set_bus_msi_domain(struct pci_bus *bus)
{
	struct irq_domain *d;
	struct pci_bus *b;

	/*
	 * Either bus is the root, and we must obtain it from the
	 * firmware, or we inherit it from the bridge device.
	 * The bus can be a root bus, a subordinate bus, or a virtual bus
	 * created by an SR-IOV device.  Walk up to the first bridge device
	 * found or derive the domain from the host bridge.
	 */
	if (pci_is_root_bus(bus))
		d = pci_host_bridge_msi_domain(bus);
	else
		d = dev_get_msi_domain(&bus->self->dev);
	for (b = bus, d = NULL; !d && !pci_is_root_bus(b); b = b->parent) {
		if (b->self)
			d = dev_get_msi_domain(&b->self->dev);
	}

	if (!d)
		d = pci_host_bridge_msi_domain(b);

	dev_set_msi_domain(&bus->dev, d);
}