Message ID | 1480246353-10297-8-git-send-email-caoj.fnst@cn.fujitsu.com |
---|---|
State | New |
Headers | show |
On Sun, Nov 27, 2016 at 07:32:30PM +0800, Cao jin wrote: > From: Chen Fan <chen.fan.fnst@cn.fujitsu.com> > > PCI hotplug requires that function 0 is added last to close the > slot. Since vfio-pci supporting AER, we require that the VM bus > contains the same set of devices as the host bus to support AER, > we can perform an AER validation test whenever the function 0 is > hot-added into VM. > > Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com> > Signed-off-by: Dou Liyang <douly.fnst@cn.fujitsu.com> > Signed-off-by: Cao jin <caoj.fnst@cn.fujitsu.com> I'm fine with this interface. Reviewed-by: Michael S. Tsirkin <mst@redhat.com> > --- > hw/pci/pci.c | 29 +++++++++++++++++++++++++++++ > include/hw/pci/pci.h | 1 + > 2 files changed, 30 insertions(+) > > diff --git a/hw/pci/pci.c b/hw/pci/pci.c > index 24fae16..26eaf4c 100644 > --- a/hw/pci/pci.c > +++ b/hw/pci/pci.c > @@ -1942,6 +1942,20 @@ PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn) > return bus->devices[devfn]; > } > > +static void pci_function_is_valid(PCIBus *bus, PCIDevice *d, void *opaque) > +{ > + PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(d); > + Error **errp = opaque; > + > + if (*errp) { > + return; > + } > + > + if (pc->is_valid_func) { > + pc->is_valid_func(d, errp); > + } > +} > + > static void pci_qdev_realize(DeviceState *qdev, Error **errp) > { > PCIDevice *pci_dev = (PCIDevice *)qdev; > @@ -1984,6 +1998,21 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp) > pci_qdev_unrealize(DEVICE(pci_dev), NULL); > return; > } > + > + /* > + * Hot-added function number 0 indicates the closure of the slot, it is > + * time to check whether all functions under the same bus is valid. > + */ > + if (DEVICE(pci_dev)->hotplugged && > + pci_get_function_0(pci_dev) == pci_dev) { > + pci_for_each_device(bus, pci_bus_num(bus), > + pci_function_is_valid, &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) > diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h > index 772692f..678f305 100644 > --- a/include/hw/pci/pci.h > +++ b/include/hw/pci/pci.h > @@ -205,6 +205,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; > -- > 1.8.3.1 > >
diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 24fae16..26eaf4c 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -1942,6 +1942,20 @@ PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn) return bus->devices[devfn]; } +static void pci_function_is_valid(PCIBus *bus, PCIDevice *d, void *opaque) +{ + PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(d); + Error **errp = opaque; + + if (*errp) { + return; + } + + if (pc->is_valid_func) { + pc->is_valid_func(d, errp); + } +} + static void pci_qdev_realize(DeviceState *qdev, Error **errp) { PCIDevice *pci_dev = (PCIDevice *)qdev; @@ -1984,6 +1998,21 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp) pci_qdev_unrealize(DEVICE(pci_dev), NULL); return; } + + /* + * Hot-added function number 0 indicates the closure of the slot, it is + * time to check whether all functions under the same bus is valid. + */ + if (DEVICE(pci_dev)->hotplugged && + pci_get_function_0(pci_dev) == pci_dev) { + pci_for_each_device(bus, pci_bus_num(bus), + pci_function_is_valid, &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) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 772692f..678f305 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -205,6 +205,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;