> -----Original Message----- > From: Paolo Bonzini [mailto:pbonz...@redhat.com] > Sent: 03 December 2014 13:56 > To: Michael S. Tsirkin; Stefano Stabellini > Cc: Paul Durrant; qemu-devel@nongnu.org; Peter Crosthwaite; Thomas > Huth; Markus Armbruster; Christian Borntraeger; Igor Mammedov; Andreas > Faerber > Subject: Re: [Qemu-devel] [PATCH v4 REPOST 1/2] Add device listener > interface > > > > 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. >
Ok. Thanks. I'll move the calls. Paul > 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 > >>> > >>>