mirror of https://github.com/proxmox/mirror_qemu
hw/pci: switch to a generic hotplug handling for PCIDevice
make qdev_unplug()/device_set_realized() to call hotplug handler's plug/unplug methods if available and remove not needed anymore hot(un)plug handling from PCIDevice. In case if hotplug handler is not available, revert to the legacy hotplug method for compatibility with not yet converted buses. Signed-off-by: Igor Mammedov <imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>master
parent
a66e657e18
commit
5e95494380
|
@ -213,7 +213,6 @@ void qdev_unplug(DeviceState *dev, Error **errp)
|
||||||
error_set(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
|
error_set(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert(dc->unplug != NULL);
|
|
||||||
|
|
||||||
if (!dc->hotpluggable) {
|
if (!dc->hotpluggable) {
|
||||||
error_set(errp, QERR_DEVICE_NO_HOTPLUG,
|
error_set(errp, QERR_DEVICE_NO_HOTPLUG,
|
||||||
|
@ -223,9 +222,13 @@ void qdev_unplug(DeviceState *dev, Error **errp)
|
||||||
|
|
||||||
qdev_hot_removed = true;
|
qdev_hot_removed = true;
|
||||||
|
|
||||||
if (dc->unplug(dev) < 0) {
|
if (dev->parent_bus && dev->parent_bus->hotplug_handler) {
|
||||||
|
hotplug_handler_unplug(dev->parent_bus->hotplug_handler, dev, errp);
|
||||||
|
} else {
|
||||||
|
assert(dc->unplug != NULL);
|
||||||
|
if (dc->unplug(dev) < 0) { /* legacy handler */
|
||||||
error_set(errp, QERR_UNDEFINED_ERROR);
|
error_set(errp, QERR_UNDEFINED_ERROR);
|
||||||
return;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -720,6 +723,12 @@ static void device_set_realized(Object *obj, bool value, Error **err)
|
||||||
dc->realize(dev, &local_err);
|
dc->realize(dev, &local_err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dev->parent_bus && dev->parent_bus->hotplug_handler &&
|
||||||
|
local_err == NULL) {
|
||||||
|
hotplug_handler_plug(dev->parent_bus->hotplug_handler,
|
||||||
|
dev, &local_err);
|
||||||
|
}
|
||||||
|
|
||||||
if (qdev_get_vmsd(dev) && local_err == NULL) {
|
if (qdev_get_vmsd(dev) && local_err == NULL) {
|
||||||
vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
|
vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
|
||||||
dev->instance_id_alias,
|
dev->instance_id_alias,
|
||||||
|
|
29
hw/pci/pci.c
29
hw/pci/pci.c
|
@ -35,6 +35,7 @@
|
||||||
#include "hw/pci/msi.h"
|
#include "hw/pci/msi.h"
|
||||||
#include "hw/pci/msix.h"
|
#include "hw/pci/msix.h"
|
||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
|
#include "hw/hotplug.h"
|
||||||
|
|
||||||
//#define DEBUG_PCI
|
//#define DEBUG_PCI
|
||||||
#ifdef DEBUG_PCI
|
#ifdef DEBUG_PCI
|
||||||
|
@ -346,13 +347,6 @@ void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
|
||||||
bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0]));
|
bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *qdev)
|
|
||||||
{
|
|
||||||
bus->qbus.allow_hotplug = 1;
|
|
||||||
bus->hotplug = hotplug;
|
|
||||||
bus->hotplug_qdev = qdev;
|
|
||||||
}
|
|
||||||
|
|
||||||
PCIBus *pci_register_bus(DeviceState *parent, const char *name,
|
PCIBus *pci_register_bus(DeviceState *parent, const char *name,
|
||||||
pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
|
pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
|
||||||
void *irq_opaque,
|
void *irq_opaque,
|
||||||
|
@ -1778,29 +1772,9 @@ static int pci_qdev_init(DeviceState *qdev)
|
||||||
}
|
}
|
||||||
pci_add_option_rom(pci_dev, is_default_rom);
|
pci_add_option_rom(pci_dev, is_default_rom);
|
||||||
|
|
||||||
if (bus->hotplug) {
|
|
||||||
/* Let buses differentiate between hotplug and when device is
|
|
||||||
* enabled during qemu machine creation. */
|
|
||||||
rc = bus->hotplug(bus->hotplug_qdev, pci_dev,
|
|
||||||
qdev->hotplugged ? PCI_HOTPLUG_ENABLED:
|
|
||||||
PCI_COLDPLUG_ENABLED);
|
|
||||||
if (rc != 0) {
|
|
||||||
int r = pci_unregister_device(&pci_dev->qdev);
|
|
||||||
assert(!r);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pci_unplug_device(DeviceState *qdev)
|
|
||||||
{
|
|
||||||
PCIDevice *dev = PCI_DEVICE(qdev);
|
|
||||||
|
|
||||||
return dev->bus->hotplug(dev->bus->hotplug_qdev, dev,
|
|
||||||
PCI_HOTPLUG_DISABLED);
|
|
||||||
}
|
|
||||||
|
|
||||||
PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction,
|
PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction,
|
||||||
const char *name)
|
const char *name)
|
||||||
{
|
{
|
||||||
|
@ -2271,7 +2245,6 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *k = DEVICE_CLASS(klass);
|
DeviceClass *k = DEVICE_CLASS(klass);
|
||||||
k->init = pci_qdev_init;
|
k->init = pci_qdev_init;
|
||||||
k->unplug = pci_unplug_device;
|
|
||||||
k->exit = pci_unregister_device;
|
k->exit = pci_unregister_device;
|
||||||
k->bus_type = TYPE_PCI_BUS;
|
k->bus_type = TYPE_PCI_BUS;
|
||||||
k->props = pci_props;
|
k->props = pci_props;
|
||||||
|
|
|
@ -327,15 +327,6 @@ typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level);
|
||||||
typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
|
typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
|
||||||
typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin);
|
typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin);
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
PCI_HOTPLUG_DISABLED,
|
|
||||||
PCI_HOTPLUG_ENABLED,
|
|
||||||
PCI_COLDPLUG_ENABLED,
|
|
||||||
} PCIHotplugState;
|
|
||||||
|
|
||||||
typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev,
|
|
||||||
PCIHotplugState state);
|
|
||||||
|
|
||||||
#define TYPE_PCI_BUS "PCI"
|
#define TYPE_PCI_BUS "PCI"
|
||||||
#define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS)
|
#define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS)
|
||||||
#define TYPE_PCIE_BUS "PCIE"
|
#define TYPE_PCIE_BUS "PCIE"
|
||||||
|
@ -354,7 +345,6 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name,
|
||||||
void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
|
void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
|
||||||
void *irq_opaque, int nirq);
|
void *irq_opaque, int nirq);
|
||||||
int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
|
int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
|
||||||
void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
|
|
||||||
/* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */
|
/* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */
|
||||||
int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin);
|
int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin);
|
||||||
PCIBus *pci_register_bus(DeviceState *parent, const char *name,
|
PCIBus *pci_register_bus(DeviceState *parent, const char *name,
|
||||||
|
|
|
@ -16,8 +16,6 @@ struct PCIBus {
|
||||||
pci_set_irq_fn set_irq;
|
pci_set_irq_fn set_irq;
|
||||||
pci_map_irq_fn map_irq;
|
pci_map_irq_fn map_irq;
|
||||||
pci_route_irq_fn route_intx_to_irq;
|
pci_route_irq_fn route_intx_to_irq;
|
||||||
pci_hotplug_fn hotplug;
|
|
||||||
DeviceState *hotplug_qdev;
|
|
||||||
void *irq_opaque;
|
void *irq_opaque;
|
||||||
PCIDevice *devices[PCI_SLOT_MAX * PCI_FUNC_MAX];
|
PCIDevice *devices[PCI_SLOT_MAX * PCI_FUNC_MAX];
|
||||||
PCIDevice *parent_dev;
|
PCIDevice *parent_dev;
|
||||||
|
|
|
@ -163,7 +163,7 @@ tests/test-xbzrle$(EXESUF): tests/test-xbzrle.o xbzrle.o page_cache.o libqemuuti
|
||||||
tests/test-cutils$(EXESUF): tests/test-cutils.o util/cutils.o
|
tests/test-cutils$(EXESUF): tests/test-cutils.o util/cutils.o
|
||||||
tests/test-int128$(EXESUF): tests/test-int128.o
|
tests/test-int128$(EXESUF): tests/test-int128.o
|
||||||
tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \
|
tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \
|
||||||
hw/core/qdev.o hw/core/qdev-properties.o \
|
hw/core/qdev.o hw/core/qdev-properties.o hw/core/hotplug.o\
|
||||||
hw/core/irq.o \
|
hw/core/irq.o \
|
||||||
$(qom-core-obj) \
|
$(qom-core-obj) \
|
||||||
$(test-qapi-obj-y) \
|
$(test-qapi-obj-y) \
|
||||||
|
|
Loading…
Reference in New Issue