On 03/12/2014 14:40, Michael S. Tsirkin wrote: > On Wed, Dec 03, 2014 at 12:29:43PM +0000, Stefano Stabellini wrote: >> The second patch is already Acked. >> You just need a review on this one to move forward, right? >> >> Andreas, Michael? > > Looks like a generic qdev thing, nothing to do with me. > >> On Wed, 3 Dec 2014, Paul Durrant wrote: >>> The Xen ioreq-server API, introduced in Xen 4.5, requires that PCI device >>> models explicitly register with Xen for config space accesses. This patch >>> adds a listener interface into qdev-core which can be used by the Xen >>> interface code to monitor for arrival and departure of PCI devices. >>> >>> Signed-off-by: Paul Durrant <paul.durr...@citrix.com> >>> Cc: Michael S. Tsirkin <m...@redhat.com> >>> Cc: Andreas Faerber" <afaer...@suse.de> >>> Cc: Paolo Bonzini <pbonz...@redhat.com> >>> Cc: Peter Crosthwaite <peter.crosthwa...@xilinx.com> >>> Cc: Igor Mammedov <imamm...@redhat.com> >>> Cc: Markus Armbruster <arm...@redhat.com> >>> Cc: Thomas Huth <th...@linux.vnet.ibm.com> >>> Cc: Christian Borntraeger <borntrae...@de.ibm.com> >>> --- >>> hw/core/qdev.c | 54 >>> +++++++++++++++++++++++++++++++++++++++++++++++ >>> include/hw/qdev-core.h | 10 +++++++++ >>> include/qemu/typedefs.h | 1 + >>> 3 files changed, 65 insertions(+) >>> >>> diff --git a/hw/core/qdev.c b/hw/core/qdev.c >>> index fcb1638..4a9c1f6 100644 >>> --- a/hw/core/qdev.c >>> +++ b/hw/core/qdev.c >>> @@ -175,6 +175,56 @@ int qdev_init(DeviceState *dev) >>> return 0; >>> } >>> >>> +static QTAILQ_HEAD(qdev_listeners, DeviceListener) qdev_listeners >>> + = QTAILQ_HEAD_INITIALIZER(qdev_listeners); >>> + >>> +enum ListenerDirection { Forward, Reverse }; >>> + >>> +#define QDEV_LISTENER_CALL(_callback, _direction, _args...) \ >>> + do { \ >>> + DeviceListener *_listener; \ >>> + \ >>> + switch (_direction) { \ >>> + case Forward: \ >>> + QTAILQ_FOREACH(_listener, &qdev_listeners, link) { \ >>> + if (_listener->_callback) { \ >>> + _listener->_callback(_listener, ##_args); \ >>> + } \ >>> + } \ >>> + break; \ >>> + case Reverse: \ >>> + QTAILQ_FOREACH_REVERSE(_listener, &qdev_listeners, \ >>> + qdev_listeners, link) { \ >>> + if (_listener->_callback) { \ >>> + _listener->_callback(_listener, ##_args); \ >>> + } \ >>> + } \ >>> + break; \ >>> + default: \ >>> + abort(); \ >>> + } \ >>> + } while (0) >>> + >>> +static int qdev_listener_add(DeviceState *dev, void *opaque) >>> +{ >>> + QDEV_LISTENER_CALL(realize, Forward, dev); >>> + >>> + return 0; >>> +} >>> + >>> +void qdev_listener_register(DeviceListener *listener) >>> +{ >>> + QTAILQ_INSERT_TAIL(&qdev_listeners, listener, link); >>> + >>> + qbus_walk_children(sysbus_get_default(), NULL, NULL, qdev_listener_add, >>> + NULL, NULL); >>> +} >>> + >>> +void qdev_listener_unregister(DeviceListener *listener) >>> +{ >>> + QTAILQ_REMOVE(&qdev_listeners, listener, link); >>> +} >>> + >>> static void device_realize(DeviceState *dev, Error **errp) >>> { >>> DeviceClass *dc = DEVICE_GET_CLASS(dev); >>> @@ -186,12 +236,16 @@ static void device_realize(DeviceState *dev, Error >>> **errp) >>> return; >>> } >>> } >>> + >>> + QDEV_LISTENER_CALL(realize, Forward, dev); >>> } >>> >>> static void device_unrealize(DeviceState *dev, Error **errp) >>> { >>> DeviceClass *dc = DEVICE_GET_CLASS(dev); >>> >>> + QDEV_LISTENER_CALL(unrealize, Reverse, dev);
These need to be in device_set_realized. device_realize and device_unrealize are just for backwards-compatibility to devices that still use init/exit. Also, this has to be call to be _after_ unrealization, i.e. after setting dev->pending_deleted_event in device_set_realize. Paolo >>> if (dc->exit) { >>> int rc = dc->exit(dev); >>> if (rc < 0) { >>> diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h >>> index 178fee2..f2dc267 100644 >>> --- a/include/hw/qdev-core.h >>> +++ b/include/hw/qdev-core.h >>> @@ -167,6 +167,12 @@ struct DeviceState { >>> int alias_required_for_version; >>> }; >>> >>> +struct DeviceListener { >>> + void (*realize)(DeviceListener *listener, DeviceState *dev); >>> + void (*unrealize)(DeviceListener *listener, DeviceState *dev); >>> + QTAILQ_ENTRY(DeviceListener) link; >>> +}; >>> + >>> #define TYPE_BUS "bus" >>> #define BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_BUS) >>> #define BUS_CLASS(klass) OBJECT_CLASS_CHECK(BusClass, (klass), TYPE_BUS) >>> @@ -368,4 +374,8 @@ static inline void qbus_set_hotplug_handler(BusState >>> *bus, DeviceState *handler, >>> QDEV_HOTPLUG_HANDLER_PROPERTY, errp); >>> bus->allow_hotplug = 1; >>> } >>> + >>> +void qdev_listener_register(DeviceListener *listener); >>> +void qdev_listener_unregister(DeviceListener *listener); >>> + >>> #endif >>> diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h >>> index 04df51b..e32bca2 100644 >>> --- a/include/qemu/typedefs.h >>> +++ b/include/qemu/typedefs.h >>> @@ -20,6 +20,7 @@ typedef struct Property Property; >>> typedef struct PropertyInfo PropertyInfo; >>> typedef struct CompatProperty CompatProperty; >>> typedef struct DeviceState DeviceState; >>> +typedef struct DeviceListener DeviceListener; >>> typedef struct BusState BusState; >>> typedef struct BusClass BusClass; >>> >>> -- >>> 1.7.10.4 >>> >>>