@@ -1840,6 +1840,40 @@ PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn)
return bus->devices[devfn];
}
+static void pci_functions_validate(PCIBus *bus, PCIDevice *d, Error **errp)
+{
+ PCIDevice *br = pci_bridge_get_device(bus);
+ PCIDeviceClass *pc;
+ PCIDevice *dev;
+ int devfn;
+ int limit = d->devfn + PCI_FUNC_MAX;
+ Error *local_err = NULL;
+
+ if (br &&
+ pci_bus_is_express(bus) &&
+ pcie_cap_is_arifwd_enabled(br)) {
+ limit = 255;
+ }
+
+ for (devfn = d->devfn; devfn < limit; devfn++) {
+ dev = pci_find_device(bus, pci_bus_num(bus), devfn);
+ if (!dev) {
+ continue;
+ }
+
+ pc = PCI_DEVICE_GET_CLASS(dev);
+ if (!pc->is_valid_func) {
+ continue;
+ }
+
+ pc->is_valid_func(d, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+ }
+}
+
static void pci_qdev_realize(DeviceState *qdev, Error **errp)
{
PCIDevice *pci_dev = (PCIDevice *)qdev;
@@ -1882,6 +1916,21 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp)
pci_qdev_unrealize(DEVICE(pci_dev), NULL);
return;
}
+
+ /*
+ * If the function number is 0, indicate the closure of the slot.
+ * then we get the chance to check all functions on same device
+ * if valid.
+ */
+ if (DEVICE(pci_dev)->hotplugged &&
+ pci_get_function_0(pci_dev) == pci_dev) {
+ pci_functions_validate(bus, pci_dev, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ pci_qdev_unrealize(DEVICE(pci_dev), NULL);
+ return;
+ }
+ }
}
static void pci_default_realize(PCIDevice *dev, Error **errp)
@@ -190,6 +190,7 @@ typedef struct PCIDeviceClass {
void (*realize)(PCIDevice *dev, Error **errp);
int (*init)(PCIDevice *dev);/* TODO convert to realize() and remove */
+ void (*is_valid_func)(PCIDevice *dev, Error **errp);
PCIUnregisterFunc *exit;
PCIConfigReadFunc *config_read;
PCIConfigWriteFunc *config_write;