[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel] [UNIKRAFT PATCH v4 6/7] plat/xen: Add Xenbus device probing
Extend the Xenbus bus driver with support for probing Xenbus devices. Signed-off-by: Costin Lupu <costin.lupu@xxxxxxxxx> --- plat/xen/include/xenbus/client.h | 12 ++++ plat/xen/include/xenbus/xenbus.h | 17 ++++- plat/xen/xenbus/client.c | 12 ++++ plat/xen/xenbus/exportsyms.uk | 1 + plat/xen/xenbus/xenbus.c | 131 ++++++++++++++++++++++++++++++++++++++- 5 files changed, 171 insertions(+), 2 deletions(-) diff --git a/plat/xen/include/xenbus/client.h b/plat/xen/include/xenbus/client.h index f3540b7..8b7e8c1 100644 --- a/plat/xen/include/xenbus/client.h +++ b/plat/xen/include/xenbus/client.h @@ -86,4 +86,16 @@ int xenbus_watch_wait_event(struct xenbus_watch *watch); */ int xenbus_watch_notify_event(struct xenbus_watch *watch); +/* + * Driver states + */ + +/* + * Returns the driver state found at the given Xenstore path. + * + * @param path Xenstore path + * @return The Xenbus driver state + */ +XenbusState xenbus_read_driver_state(const char *path); + #endif /* __XENBUS_CLIENT_H__ */ diff --git a/plat/xen/include/xenbus/xenbus.h b/plat/xen/include/xenbus/xenbus.h index 230dcd4..3d3b540 100644 --- a/plat/xen/include/xenbus/xenbus.h +++ b/plat/xen/include/xenbus/xenbus.h @@ -110,7 +110,22 @@ UK_TAILQ_HEAD(xenbus_watch_list, struct xenbus_watch); */ struct xenbus_device { - + /**< in use by Xenbus handler */ + UK_TAILQ_ENTRY(struct xenbus_device) next; + /**< Device state */ + XenbusState state; + /**< Device type */ + enum xenbus_dev_type devtype; + /**< Xenstore path of the device */ + char *nodename; + /**< Xenstore path of the device peer (e.g. backend for frontend) */ + char *otherend; + /**< Domain id of the other end */ + domid_t otherend_id; + /**< Watch for monitoring changes on other end */ + struct xenbus_watch *otherend_watch; + /**< Xenbus driver */ + struct xenbus_driver *drv; }; UK_TAILQ_HEAD(xenbus_device_list, struct xenbus_device); diff --git a/plat/xen/xenbus/client.c b/plat/xen/xenbus/client.c index 3dbca0f..274e6e7 100644 --- a/plat/xen/xenbus/client.c +++ b/plat/xen/xenbus/client.c @@ -44,6 +44,7 @@ #include <string.h> #include <uk/errptr.h> #include <uk/wait.h> +#include <xenbus/xs.h> #include <xenbus/client.h> @@ -130,3 +131,14 @@ int xenbus_watch_notify_event(struct xenbus_watch *watch) return 0; } + +XenbusState xenbus_read_driver_state(const char *path) +{ + char state_path[strlen(path) + sizeof("/state")]; + XenbusState state = XenbusStateUnknown; + + sprintf(state_path, "%s/state", path); + xs_read_integer(XBT_NIL, state_path, (int *) &state); + + return state; +} diff --git a/plat/xen/xenbus/exportsyms.uk b/plat/xen/xenbus/exportsyms.uk index a424fd9..d57a2a5 100644 --- a/plat/xen/xenbus/exportsyms.uk +++ b/plat/xen/xenbus/exportsyms.uk @@ -27,3 +27,4 @@ xenbus_state_to_str xenbus_devtype_to_str xenbus_str_to_devtype xenbus_watch_wait_event +xenbus_read_driver_state diff --git a/plat/xen/xenbus/xenbus.c b/plat/xen/xenbus/xenbus.c index a20546b..28f0cfd 100644 --- a/plat/xen/xenbus/xenbus.c +++ b/plat/xen/xenbus/xenbus.c @@ -43,8 +43,12 @@ #include <uk/errptr.h> #include <uk/assert.h> #include <xenbus/xenbus.h> +#include <xenbus/xs.h> +#include <xenbus/client.h> #include "xs_comms.h" +#define XS_DEV_PATH "device" + static struct xenbus_handler xbh; @@ -67,13 +71,138 @@ void uk_xb_free(void *ptr) uk_free(xbh.a, ptr); } + +static struct xenbus_driver *xenbus_find_driver(xenbus_dev_type_t devtype) +{ + struct xenbus_driver *drv; + const xenbus_dev_type_t *pdevtype; + + UK_TAILQ_FOREACH(drv, &xbh.drv_list, next) { + for (pdevtype = drv->device_types; + *pdevtype != xenbus_dev_none; pdevtype++) { + if (*pdevtype == devtype) + return drv; + } + } + + return NULL; /* no driver found */ +} + +static int xenbus_probe_device(struct xenbus_driver *drv, + xenbus_dev_type_t type, const char *name) +{ + int err; + struct xenbus_device *dev; + char *nodename = NULL; + XenbusState state; + + /* device/type/name */ + err = asprintf(&nodename, "%s/%s/%s", + XS_DEV_PATH, xenbus_devtype_to_str(type), name); + if (err < 0) + goto out; + + state = xenbus_read_driver_state(nodename); + if (state != XenbusStateInitialising) + return 0; + + uk_printd(DLVL_INFO, "Xenbus device: %s\n", nodename); + + dev = uk_xb_calloc(1, sizeof(*dev) + strlen(nodename) + 1); + if (!dev) { + uk_printd(DLVL_ERR, "Failed to initialize: Out of memory!\n"); + err = -ENOMEM; + goto out; + } + + dev->state = XenbusStateInitialising; + dev->devtype = type; + dev->nodename = (char *) (dev + 1); + strcpy(dev->nodename, nodename); + + err = drv->add_dev(dev); + if (err) { + uk_printd(DLVL_ERR, "Failed to add device.\n"); + uk_xb_free(dev); + } + +out: + if (nodename) + free(nodename); + + return err; +} + +static int xenbus_probe_device_type(const char *devtype_str) +{ + struct xenbus_driver *drv; + xenbus_dev_type_t devtype; + char dirname[sizeof(XS_DEV_PATH) + strlen(devtype_str)]; + char **devices = NULL; + int err = 0; + + devtype = xenbus_str_to_devtype(devtype_str); + if (!devtype) { + uk_printd(DLVL_WARN, + "Unsupported device type: %s\n", devtype_str); + goto out; + } + + drv = xenbus_find_driver(devtype); + if (!drv) { + uk_printd(DLVL_WARN, + "No driver for device type: %s\n", devtype_str); + goto out; + } + + sprintf(dirname, "%s/%s", XS_DEV_PATH, devtype_str); + + /* Get device list */ + devices = xs_ls(XBT_NIL, dirname); + if (PTRISERR(devices)) { + err = PTR2ERR(devices); + uk_printd(DLVL_ERR, + "Error reading %s devices: %d\n", devtype_str, err); + goto out; + } + + for (int i = 0; devices[i] != NULL; i++) { + /* Probe only if no prior error */ + if (err == 0) + err = xenbus_probe_device(drv, devtype, devices[i]); + } + +out: + if (!PTRISERR(devices)) + free(devices); + + return err; +} + static int xenbus_probe(void) { + char **devtypes; int err = 0; uk_printd(DLVL_INFO, "Probe Xenbus\n"); - /* TODO */ + /* Get device types list */ + devtypes = xs_ls(XBT_NIL, XS_DEV_PATH); + if (PTRISERR(devtypes)) { + err = PTR2ERR(devtypes); + uk_printd(DLVL_ERR, "Error reading device types: %d\n", err); + goto out; + } + + for (int i = 0; devtypes[i] != NULL; i++) { + /* Probe only if no previous error */ + if (err == 0) + err = xenbus_probe_device_type(devtypes[i]); + } + +out: + if (!PTRISERR(devtypes)) + free(devtypes); return err; } -- 2.11.0 _______________________________________________ Minios-devel mailing list Minios-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/minios-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |