@@ -109,6 +109,19 @@ static struct aer_error *__find_aer_error_by_dev(struct pci_dev *dev)
return __find_aer_error((u16)domain, dev->bus->number, dev->devfn);
}
+static bool pci_is_upstream_bus(struct pci_bus *bus, struct pci_bus *up_bus)
+{
+ struct pci_bus *pbus = bus->parent;
+
+ while (pbus) {
+ if (pbus == up_bus)
+ return true;
+ pbus = pbus->parent;
+ }
+
+ return false;
+}
+
/* inject_lock must be held before calling */
static struct pci_ops *__find_pci_bus_ops(struct pci_bus *bus)
{
@@ -118,6 +131,13 @@ static struct pci_ops *__find_pci_bus_ops(struct pci_bus *bus)
if (bus_ops->bus == bus)
return bus_ops->ops;
}
+
+ /* can't find bus_ops, fall back to get bus_ops of upstream bus */
+ list_for_each_entry(bus_ops, &pci_bus_ops_list, list) {
+ if (pci_is_upstream_bus(bus, bus_ops->bus))
+ return bus_ops->ops;
+ }
+
return NULL;
}
@@ -208,6 +228,7 @@ static int pci_read_aer(struct pci_bus *bus, unsigned int devfn, int where,
}
out:
ops = __find_pci_bus_ops(bus);
+ BUG_ON(!ops);
spin_unlock_irqrestore(&inject_lock, flags);
return ops->read(bus, devfn, where, size, val);
}
@@ -243,6 +264,7 @@ int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where, int size,
}
out:
ops = __find_pci_bus_ops(bus);
+ BUG_ON(!ops);
spin_unlock_irqrestore(&inject_lock, flags);
return ops->write(bus, devfn, where, size, val);
}
@@ -506,6 +528,7 @@ static struct miscdevice aer_inject_device = {
.fops = &aer_inject_fops,
};
+
static int __init aer_inject_init(void)
{
return misc_register(&aer_inject_device);