Skip to content

Commit

Permalink
PCI/MSI: Fix MSI IRQ domains for VFs on virtual buses
Browse files Browse the repository at this point in the history
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: 44aa0c6 ("PCI/MSI: Add hooks to populate the msi_domain field")
Tested-by: Joerg Roedel <joro@8bytes.org>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Signed-off-by: Bjorn Helgaas <helgaas@kernel.org>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
  • Loading branch information
Alex Williamson authored and Bjorn Helgaas committed Sep 24, 2015
1 parent b838b39 commit 38ea72b
Showing 1 changed file with 11 additions and 6 deletions.
17 changes: 11 additions & 6 deletions drivers/pci/probe.c
Original file line number Diff line number Diff line change
@@ -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);
}

0 comments on commit 38ea72b

Please sign in to comment.