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: 44aa0c657e
("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>
This commit is contained in:
Родитель
b838b39e93
Коммит
38ea72bdb6
|
@ -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);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче