On Wed, Apr 05, 2017 at 02:41:42PM +0200, Cédric Le Goater wrote: > From: Benjamin Herrenschmidt <[email protected]> > > This allows a bus class to tell whether a given bus has room for > any new device. max_dev isn't sufficient as the rules can depend > on some arguments or can differ between instances of a bus. This > will be used by PCI in subsequent patches > > Signed-off-by: Benjamin Herrenschmidt <[email protected]> > [clg: updated for qemu-2.9 ] > Signed-off-by: Cédric Le Goater <[email protected]> > --- > include/hw/qdev-core.h | 1 + > qdev-monitor.c | 14 +++++++++----- > 2 files changed, 10 insertions(+), 5 deletions(-) > > diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h > index b44b47676576..867662ba5352 100644 > --- a/include/hw/qdev-core.h > +++ b/include/hw/qdev-core.h > @@ -201,6 +201,7 @@ struct BusClass { > */ > char *(*get_fw_dev_path)(DeviceState *dev); > void (*reset)(BusState *bus); > + bool (*can_add_device)(BusState *bus, QemuOpts *opts); > BusRealize realize; > BusUnrealize unrealize; > > diff --git a/qdev-monitor.c b/qdev-monitor.c > index 5f2fcdfc4551..c6eca929c473 100644 > --- a/qdev-monitor.c > +++ b/qdev-monitor.c > @@ -415,7 +415,7 @@ static inline bool qbus_is_full(BusState *bus) > * Return the bus if found, else %NULL. > */ > static BusState *qbus_find_recursive(BusState *bus, const char *name, > - const char *bus_typename) > + const char *bus_typename, QemuOpts > *opts) > { > BusChild *kid; > BusState *pick, *child, *ret; > @@ -429,7 +429,10 @@ static BusState *qbus_find_recursive(BusState *bus, > const char *name, > } > > if (match && !qbus_is_full(bus)) { > - return bus; /* root matches and isn't full */ > + BusClass *bc = BUS_GET_CLASS(bus); > + if (!bc->can_add_device || bc->can_add_device(bus, opts)) { > + return bus; /* root matches and isn't full */
Seems like qbus_is_full() should be changed to use the can_add_device
hook, rather than changing the caller here. Essentially the current
max_devs implementation would become the fallback if the bus doesn't
define a bus specific test.
> + }
> }
>
> pick = match ? bus : NULL;
> @@ -437,7 +440,7 @@ static BusState *qbus_find_recursive(BusState *bus, const
> char *name,
> QTAILQ_FOREACH(kid, &bus->children, sibling) {
> DeviceState *dev = kid->child;
> QLIST_FOREACH(child, &dev->child_bus, sibling) {
> - ret = qbus_find_recursive(child, name, bus_typename);
> + ret = qbus_find_recursive(child, name, bus_typename, opts);
> if (ret && !qbus_is_full(ret)) {
> return ret; /* a descendant matches and isn't full */
> }
> @@ -467,7 +470,7 @@ static BusState *qbus_find(const char *path, Error **errp)
> assert(!path[0]);
> elem[0] = len = 0;
> }
> - bus = qbus_find_recursive(sysbus_get_default(), elem, NULL);
> + bus = qbus_find_recursive(sysbus_get_default(), elem, NULL, NULL);
> if (!bus) {
> error_setg(errp, "Bus '%s' not found", elem);
> return NULL;
> @@ -591,7 +594,8 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp)
> return NULL;
> }
> } else if (dc->bus_type != NULL) {
> - bus = qbus_find_recursive(sysbus_get_default(), NULL, dc->bus_type);
> + bus = qbus_find_recursive(sysbus_get_default(), NULL, dc->bus_type,
> + opts);
> if (!bus || qbus_is_full(bus)) {
> error_setg(errp, "No '%s' bus found for device '%s'",
> dc->bus_type, driver);
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
signature.asc
Description: PGP signature
