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

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
......@@ -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);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment