From 2de06cc1f18d638cc7ab1169f61a8599045c2d4f Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Mon, 9 Feb 2009 12:05:51 -0800 Subject: xen: separate out frontend xenbus Impact: refactor Make a distinct frontend xenbus, in preparation for adding a backend xenbus. Signed-off-by: Ian Campbell Signed-off-by: Jeremy Fitzhardinge [corresponds to 2fd433a4188f in git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git with adjustments to reflect changes in the code which is moved] Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/Kconfig | 3 + drivers/xen/xenbus/Makefile | 2 + drivers/xen/xenbus/xenbus_probe.c | 361 ++++++----------------------- drivers/xen/xenbus/xenbus_probe.h | 30 +-- drivers/xen/xenbus/xenbus_probe_frontend.c | 275 ++++++++++++++++++++++ 5 files changed, 366 insertions(+), 305 deletions(-) create mode 100644 drivers/xen/xenbus/xenbus_probe_frontend.c (limited to 'drivers/xen') diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index 6e6180ccd726..10b6bef2e217 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig @@ -62,6 +62,9 @@ config XEN_SYS_HYPERVISOR virtual environment, /sys/hypervisor will still be present, but will have no xen contents. +config XEN_XENBUS_FRONTEND + tristate + config XEN_PLATFORM_PCI tristate "xen platform pci device driver" depends on XEN_PVHVM diff --git a/drivers/xen/xenbus/Makefile b/drivers/xen/xenbus/Makefile index 5571f5b84223..33e8cf8149b3 100644 --- a/drivers/xen/xenbus/Makefile +++ b/drivers/xen/xenbus/Makefile @@ -5,3 +5,5 @@ xenbus-objs += xenbus_client.o xenbus-objs += xenbus_comms.o xenbus-objs += xenbus_xs.o xenbus-objs += xenbus_probe.o + +obj-$(CONFIG_XEN_XENBUS_FRONTEND) += xenbus_probe_frontend.o diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index deb9c4ba3a93..d46205868b88 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -56,7 +56,6 @@ #include #include -#include #include #include "xenbus_comms.h" @@ -73,15 +72,6 @@ static unsigned long xen_store_mfn; static BLOCKING_NOTIFIER_HEAD(xenstore_chain); -static void wait_for_devices(struct xenbus_driver *xendrv); - -static int xenbus_probe_frontend(const char *type, const char *name); - -static void xenbus_dev_shutdown(struct device *_dev); - -static int xenbus_dev_suspend(struct device *dev, pm_message_t state); -static int xenbus_dev_resume(struct device *dev); - /* If something in array of ids matches this device, return it. */ static const struct xenbus_device_id * match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev) @@ -102,8 +92,10 @@ int xenbus_match(struct device *_dev, struct device_driver *_drv) return match_device(drv->ids, to_xenbus_device(_dev)) != NULL; } +EXPORT_SYMBOL_GPL(xenbus_match); + -static int xenbus_uevent(struct device *_dev, struct kobj_uevent_env *env) +int xenbus_uevent(struct device *_dev, struct kobj_uevent_env *env) { struct xenbus_device *dev = to_xenbus_device(_dev); @@ -112,25 +104,7 @@ static int xenbus_uevent(struct device *_dev, struct kobj_uevent_env *env) return 0; } - -/* device// => - */ -static int frontend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename) -{ - nodename = strchr(nodename, '/'); - if (!nodename || strlen(nodename + 1) >= XEN_BUS_ID_SIZE) { - printk(KERN_WARNING "XENBUS: bad frontend %s\n", nodename); - return -EINVAL; - } - - strlcpy(bus_id, nodename + 1, XEN_BUS_ID_SIZE); - if (!strchr(bus_id, '/')) { - printk(KERN_WARNING "XENBUS: bus_id %s no slash\n", bus_id); - return -EINVAL; - } - *strchr(bus_id, '/') = '-'; - return 0; -} - +EXPORT_SYMBOL_GPL(xenbus_uevent); static void free_otherend_details(struct xenbus_device *dev) { @@ -149,7 +123,28 @@ static void free_otherend_watch(struct xenbus_device *dev) } -int read_otherend_details(struct xenbus_device *xendev, +static int talk_to_otherend(struct xenbus_device *dev) +{ + struct xenbus_driver *drv = to_xenbus_driver(dev->dev.driver); + + free_otherend_watch(dev); + free_otherend_details(dev); + + return drv->read_otherend_details(dev); +} + + + +static int watch_otherend(struct xenbus_device *dev) +{ + struct xen_bus_type *bus = container_of(dev->dev.bus, struct xen_bus_type, bus); + + return xenbus_watch_pathfmt(dev, &dev->otherend_watch, bus->otherend_changed, + "%s/%s", dev->otherend, "state"); +} + + +int xenbus_read_otherend_details(struct xenbus_device *xendev, char *id_node, char *path_node) { int err = xenbus_gather(XBT_NIL, xendev->nodename, @@ -174,39 +169,11 @@ int read_otherend_details(struct xenbus_device *xendev, return 0; } +EXPORT_SYMBOL_GPL(xenbus_read_otherend_details); - -static int read_backend_details(struct xenbus_device *xendev) -{ - return read_otherend_details(xendev, "backend-id", "backend"); -} - -static struct device_attribute xenbus_dev_attrs[] = { - __ATTR_NULL -}; - -/* Bus type for frontend drivers. */ -static struct xen_bus_type xenbus_frontend = { - .root = "device", - .levels = 2, /* device/type/ */ - .get_bus_id = frontend_bus_id, - .probe = xenbus_probe_frontend, - .bus = { - .name = "xen", - .match = xenbus_match, - .uevent = xenbus_uevent, - .probe = xenbus_dev_probe, - .remove = xenbus_dev_remove, - .shutdown = xenbus_dev_shutdown, - .dev_attrs = xenbus_dev_attrs, - - .suspend = xenbus_dev_suspend, - .resume = xenbus_dev_resume, - }, -}; - -static void otherend_changed(struct xenbus_watch *watch, - const char **vec, unsigned int len) +void xenbus_otherend_changed(struct xenbus_watch *watch, + const char **vec, unsigned int len, + int ignore_on_shutdown) { struct xenbus_device *dev = container_of(watch, struct xenbus_device, otherend_watch); @@ -234,11 +201,7 @@ static void otherend_changed(struct xenbus_watch *watch, * work that can fail e.g., when the rootfs is gone. */ if (system_state > SYSTEM_RUNNING) { - struct xen_bus_type *bus = bus; - bus = container_of(dev->dev.bus, struct xen_bus_type, bus); - /* If we're frontend, drive the state machine to Closed. */ - /* This should cause the backend to release our resources. */ - if ((bus == &xenbus_frontend) && (state == XenbusStateClosing)) + if (ignore_on_shutdown && (state == XenbusStateClosing)) xenbus_frontend_closed(dev); return; } @@ -246,25 +209,7 @@ static void otherend_changed(struct xenbus_watch *watch, if (drv->otherend_changed) drv->otherend_changed(dev, state); } - - -static int talk_to_otherend(struct xenbus_device *dev) -{ - struct xenbus_driver *drv = to_xenbus_driver(dev->dev.driver); - - free_otherend_watch(dev); - free_otherend_details(dev); - - return drv->read_otherend_details(dev); -} - - -static int watch_otherend(struct xenbus_device *dev) -{ - return xenbus_watch_pathfmt(dev, &dev->otherend_watch, otherend_changed, - "%s/%s", dev->otherend, "state"); -} - +EXPORT_SYMBOL_GPL(xenbus_otherend_changed); int xenbus_dev_probe(struct device *_dev) { @@ -310,6 +255,7 @@ fail: xenbus_switch_state(dev, XenbusStateClosed); return -ENODEV; } +EXPORT_SYMBOL_GPL(xenbus_dev_probe); int xenbus_dev_remove(struct device *_dev) { @@ -327,8 +273,9 @@ int xenbus_dev_remove(struct device *_dev) xenbus_switch_state(dev, XenbusStateClosed); return 0; } +EXPORT_SYMBOL_GPL(xenbus_dev_remove); -static void xenbus_dev_shutdown(struct device *_dev) +void xenbus_dev_shutdown(struct device *_dev) { struct xenbus_device *dev = to_xenbus_device(_dev); unsigned long timeout = 5*HZ; @@ -349,6 +296,7 @@ static void xenbus_dev_shutdown(struct device *_dev) out: put_device(&dev->dev); } +EXPORT_SYMBOL_GPL(xenbus_dev_shutdown); int xenbus_register_driver_common(struct xenbus_driver *drv, struct xen_bus_type *bus, @@ -362,25 +310,7 @@ int xenbus_register_driver_common(struct xenbus_driver *drv, return driver_register(&drv->driver); } - -int __xenbus_register_frontend(struct xenbus_driver *drv, - struct module *owner, const char *mod_name) -{ - int ret; - - drv->read_otherend_details = read_backend_details; - - ret = xenbus_register_driver_common(drv, &xenbus_frontend, - owner, mod_name); - if (ret) - return ret; - - /* If this driver is loaded as a module wait for devices to attach. */ - wait_for_devices(drv); - - return 0; -} -EXPORT_SYMBOL_GPL(__xenbus_register_frontend); +EXPORT_SYMBOL_GPL(xenbus_register_driver_common); void xenbus_unregister_driver(struct xenbus_driver *drv) { @@ -551,24 +481,7 @@ fail: kfree(xendev); return err; } - -/* device// */ -static int xenbus_probe_frontend(const char *type, const char *name) -{ - char *nodename; - int err; - - nodename = kasprintf(GFP_KERNEL, "%s/%s/%s", - xenbus_frontend.root, type, name); - if (!nodename) - return -ENOMEM; - - DPRINTK("%s", nodename); - - err = xenbus_probe_node(&xenbus_frontend, type, nodename); - kfree(nodename); - return err; -} +EXPORT_SYMBOL_GPL(xenbus_probe_node); static int xenbus_probe_device_type(struct xen_bus_type *bus, const char *type) { @@ -577,15 +490,23 @@ static int xenbus_probe_device_type(struct xen_bus_type *bus, const char *type) unsigned int dir_n = 0; int i; + printk(KERN_CRIT "%s type %s\n", __func__, type); + dir = xenbus_directory(XBT_NIL, bus->root, type, &dir_n); - if (IS_ERR(dir)) + if (IS_ERR(dir)) { + printk(KERN_CRIT "%s failed xenbus_directory\n", __func__); return PTR_ERR(dir); + } for (i = 0; i < dir_n; i++) { - err = bus->probe(type, dir[i]); - if (err) + printk(KERN_CRIT "%s %d/%d %s\n", __func__, i+1,dir_n, dir[i]); + err = bus->probe(bus, type, dir[i]); + if (err) { + printk(KERN_CRIT "%s failed\n", __func__); break; + } } + printk("%s done\n", __func__); kfree(dir); return err; } @@ -596,18 +517,27 @@ int xenbus_probe_devices(struct xen_bus_type *bus) char **dir; unsigned int i, dir_n; + printk(KERN_CRIT "%s %s\n", __func__, bus->root); + dir = xenbus_directory(XBT_NIL, bus->root, "", &dir_n); - if (IS_ERR(dir)) + if (IS_ERR(dir)) { + printk(KERN_CRIT "%s failed xenbus_directory\n", __func__); return PTR_ERR(dir); + } for (i = 0; i < dir_n; i++) { + printk(KERN_CRIT "%s %d/%d %s\n", __func__, i+1,dir_n, dir[i]); err = xenbus_probe_device_type(bus, dir[i]); - if (err) + if (err) { + printk(KERN_CRIT "%s failed\n", __func__); break; + } } + printk("%s done\n", __func__); kfree(dir); return err; } +EXPORT_SYMBOL_GPL(xenbus_probe_devices); static unsigned int char_count(const char *str, char c) { @@ -670,32 +600,17 @@ void xenbus_dev_changed(const char *node, struct xen_bus_type *bus) } EXPORT_SYMBOL_GPL(xenbus_dev_changed); -static void frontend_changed(struct xenbus_watch *watch, - const char **vec, unsigned int len) -{ - DPRINTK(""); - - xenbus_dev_changed(vec[XS_WATCH_PATH], &xenbus_frontend); -} - -/* We watch for devices appearing and vanishing. */ -static struct xenbus_watch fe_watch = { - .node = "device", - .callback = frontend_changed, -}; - -static int xenbus_dev_suspend(struct device *dev, pm_message_t state) +int xenbus_dev_suspend(struct device *dev, pm_message_t state) { int err = 0; struct xenbus_driver *drv; - struct xenbus_device *xdev; + struct xenbus_device *xdev = container_of(dev, struct xenbus_device, dev); - DPRINTK(""); + DPRINTK("%s", xdev->nodename); if (dev->driver == NULL) return 0; drv = to_xenbus_driver(dev->driver); - xdev = container_of(dev, struct xenbus_device, dev); if (drv->suspend) err = drv->suspend(xdev, state); if (err) @@ -703,21 +618,19 @@ static int xenbus_dev_suspend(struct device *dev, pm_message_t state) "xenbus: suspend %s failed: %i\n", dev_name(dev), err); return 0; } +EXPORT_SYMBOL_GPL(xenbus_dev_suspend); -static int xenbus_dev_resume(struct device *dev) +int xenbus_dev_resume(struct device *dev) { int err; struct xenbus_driver *drv; - struct xenbus_device *xdev; + struct xenbus_device *xdev = container_of(dev, struct xenbus_device, dev); - DPRINTK(""); + DPRINTK("%s", xdev->nodename); if (dev->driver == NULL) return 0; - drv = to_xenbus_driver(dev->driver); - xdev = container_of(dev, struct xenbus_device, dev); - err = talk_to_otherend(xdev); if (err) { printk(KERN_WARNING @@ -748,6 +661,7 @@ static int xenbus_dev_resume(struct device *dev) return 0; } +EXPORT_SYMBOL_GPL(xenbus_dev_resume); /* A flag to determine if xenstored is 'ready' (i.e. has started) */ int xenstored_ready = 0; @@ -776,11 +690,6 @@ void xenbus_probe(struct work_struct *unused) { xenstored_ready = 1; - /* Enumerate devices in xenstore and watch for changes. */ - xenbus_probe_devices(&xenbus_frontend); - register_xenbus_watch(&fe_watch); - xenbus_backend_probe_and_watch(); - /* Notify others that xenstore is up */ blocking_notifier_call_chain(&xenstore_chain, 0, NULL); } @@ -811,15 +720,6 @@ static int __init xenbus_init(void) if (!xen_domain()) goto out_error; - /* Register ourselves with the kernel bus subsystem */ - err = bus_register(&xenbus_frontend.bus); - if (err) - goto out_error; - - err = xenbus_backend_bus_register(); - if (err) - goto out_unreg_front; - /* * Domain0 doesn't have a store_evtchn or store_mfn yet. */ @@ -874,7 +774,7 @@ static int __init xenbus_init(void) if (err) { printk(KERN_WARNING "XENBUS: Error initializing xenstore comms: %i\n", err); - goto out_unreg_back; + goto out_error; } #ifdef CONFIG_XEN_COMPAT_XENFS @@ -885,135 +785,16 @@ static int __init xenbus_init(void) proc_mkdir("xen", NULL); #endif + printk(KERN_CRIT "%s ok\n", __func__); return 0; - out_unreg_back: - xenbus_backend_bus_unregister(); - - out_unreg_front: - bus_unregister(&xenbus_frontend.bus); - out_error: if (page != 0) free_page(page); + return err; } postcore_initcall(xenbus_init); MODULE_LICENSE("GPL"); - -static int is_device_connecting(struct device *dev, void *data) -{ - struct xenbus_device *xendev = to_xenbus_device(dev); - struct device_driver *drv = data; - struct xenbus_driver *xendrv; - - /* - * A device with no driver will never connect. We care only about - * devices which should currently be in the process of connecting. - */ - if (!dev->driver) - return 0; - - /* Is this search limited to a particular driver? */ - if (drv && (dev->driver != drv)) - return 0; - - xendrv = to_xenbus_driver(dev->driver); - return (xendev->state < XenbusStateConnected || - (xendev->state == XenbusStateConnected && - xendrv->is_ready && !xendrv->is_ready(xendev))); -} - -static int exists_connecting_device(struct device_driver *drv) -{ - return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv, - is_device_connecting); -} - -static int print_device_status(struct device *dev, void *data) -{ - struct xenbus_device *xendev = to_xenbus_device(dev); - struct device_driver *drv = data; - - /* Is this operation limited to a particular driver? */ - if (drv && (dev->driver != drv)) - return 0; - - if (!dev->driver) { - /* Information only: is this too noisy? */ - printk(KERN_INFO "XENBUS: Device with no driver: %s\n", - xendev->nodename); - } else if (xendev->state < XenbusStateConnected) { - enum xenbus_state rstate = XenbusStateUnknown; - if (xendev->otherend) - rstate = xenbus_read_driver_state(xendev->otherend); - printk(KERN_WARNING "XENBUS: Timeout connecting " - "to device: %s (local state %d, remote state %d)\n", - xendev->nodename, xendev->state, rstate); - } - - return 0; -} - -/* We only wait for device setup after most initcalls have run. */ -static int ready_to_wait_for_devices; - -/* - * On a 5-minute timeout, wait for all devices currently configured. We need - * to do this to guarantee that the filesystems and / or network devices - * needed for boot are available, before we can allow the boot to proceed. - * - * This needs to be on a late_initcall, to happen after the frontend device - * drivers have been initialised, but before the root fs is mounted. - * - * A possible improvement here would be to have the tools add a per-device - * flag to the store entry, indicating whether it is needed at boot time. - * This would allow people who knew what they were doing to accelerate their - * boot slightly, but of course needs tools or manual intervention to set up - * those flags correctly. - */ -static void wait_for_devices(struct xenbus_driver *xendrv) -{ - unsigned long start = jiffies; - struct device_driver *drv = xendrv ? &xendrv->driver : NULL; - unsigned int seconds_waited = 0; - - if (!ready_to_wait_for_devices || !xen_domain()) - return; - - while (exists_connecting_device(drv)) { - if (time_after(jiffies, start + (seconds_waited+5)*HZ)) { - if (!seconds_waited) - printk(KERN_WARNING "XENBUS: Waiting for " - "devices to initialise: "); - seconds_waited += 5; - printk("%us...", 300 - seconds_waited); - if (seconds_waited == 300) - break; - } - - schedule_timeout_interruptible(HZ/10); - } - - if (seconds_waited) - printk("\n"); - - bus_for_each_dev(&xenbus_frontend.bus, NULL, drv, - print_device_status); -} - -#ifndef MODULE -static int __init boot_wait_for_devices(void) -{ - if (xen_hvm_domain() && !xen_platform_pci_unplug) - return -ENODEV; - - ready_to_wait_for_devices = 1; - wait_for_devices(NULL); - return 0; -} - -late_initcall(boot_wait_for_devices); -#endif diff --git a/drivers/xen/xenbus/xenbus_probe.h b/drivers/xen/xenbus/xenbus_probe.h index 6c5e3185a6a2..be390cef329f 100644 --- a/drivers/xen/xenbus/xenbus_probe.h +++ b/drivers/xen/xenbus/xenbus_probe.h @@ -36,26 +36,13 @@ #define XEN_BUS_ID_SIZE 20 -#ifdef CONFIG_XEN_BACKEND -extern void xenbus_backend_suspend(int (*fn)(struct device *, void *)); -extern void xenbus_backend_resume(int (*fn)(struct device *, void *)); -extern void xenbus_backend_probe_and_watch(void); -extern int xenbus_backend_bus_register(void); -extern void xenbus_backend_bus_unregister(void); -#else -static inline void xenbus_backend_suspend(int (*fn)(struct device *, void *)) {} -static inline void xenbus_backend_resume(int (*fn)(struct device *, void *)) {} -static inline void xenbus_backend_probe_and_watch(void) {} -static inline int xenbus_backend_bus_register(void) { return 0; } -static inline void xenbus_backend_bus_unregister(void) {} -#endif - struct xen_bus_type { char *root; unsigned int levels; int (*get_bus_id)(char bus_id[XEN_BUS_ID_SIZE], const char *nodename); - int (*probe)(const char *type, const char *dir); + int (*probe)(struct xen_bus_type *bus, const char *type, const char *dir); + void (*otherend_changed)(struct xenbus_watch *watch, const char **vec, unsigned int len); struct bus_type bus; }; @@ -73,4 +60,17 @@ extern int xenbus_probe_devices(struct xen_bus_type *bus); extern void xenbus_dev_changed(const char *node, struct xen_bus_type *bus); +extern int xenbus_uevent(struct device *_dev, struct kobj_uevent_env *env); +extern void xenbus_dev_shutdown(struct device *_dev); + +extern int xenbus_dev_suspend(struct device *dev, pm_message_t state); +extern int xenbus_dev_resume(struct device *dev); + +extern void xenbus_otherend_changed(struct xenbus_watch *watch, + const char **vec, unsigned int len, + int ignore_on_shutdown); + +extern int xenbus_read_otherend_details(struct xenbus_device *xendev, + char *id_node, char *path_node); + #endif diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c new file mode 100644 index 000000000000..04c4f0123521 --- /dev/null +++ b/drivers/xen/xenbus/xenbus_probe_frontend.c @@ -0,0 +1,275 @@ +#define DPRINTK(fmt, args...) \ + pr_debug("xenbus_probe (%s:%d) " fmt ".\n", \ + __func__, __LINE__, ##args) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "xenbus_comms.h" +#include "xenbus_probe.h" + + +/* device// => - */ +static int frontend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename) +{ + nodename = strchr(nodename, '/'); + if (!nodename || strlen(nodename + 1) >= XEN_BUS_ID_SIZE) { + printk(KERN_WARNING "XENBUS: bad frontend %s\n", nodename); + return -EINVAL; + } + + strlcpy(bus_id, nodename + 1, XEN_BUS_ID_SIZE); + if (!strchr(bus_id, '/')) { + printk(KERN_WARNING "XENBUS: bus_id %s no slash\n", bus_id); + return -EINVAL; + } + *strchr(bus_id, '/') = '-'; + return 0; +} + +/* device// */ +static int xenbus_probe_frontend(struct xen_bus_type *bus, const char *type, const char *name) +{ + char *nodename; + int err; + + nodename = kasprintf(GFP_KERNEL, "%s/%s/%s", bus->root, type, name); + if (!nodename) + return -ENOMEM; + + DPRINTK("%s", nodename); + + err = xenbus_probe_node(bus, type, nodename); + kfree(nodename); + return err; +} + +static void backend_changed(struct xenbus_watch *watch, + const char **vec, unsigned int len) +{ + xenbus_otherend_changed(watch, vec, len, 1); +} + +static struct device_attribute xenbus_frontend_dev_attrs[] = { + __ATTR_NULL +}; + +static struct xen_bus_type xenbus_frontend = { + .root = "device", + .levels = 2, /* device/type/ */ + .get_bus_id = frontend_bus_id, + .probe = xenbus_probe_frontend, + .otherend_changed = backend_changed, + .bus = { + .name = "xen", + .match = xenbus_match, + .uevent = xenbus_uevent, + .probe = xenbus_dev_probe, + .remove = xenbus_dev_remove, + .shutdown = xenbus_dev_shutdown, + .dev_attrs= xenbus_frontend_dev_attrs, + + .suspend = xenbus_dev_suspend, + .resume = xenbus_dev_resume, + }, +}; + +static void frontend_changed(struct xenbus_watch *watch, + const char **vec, unsigned int len) +{ + DPRINTK(""); + + xenbus_dev_changed(vec[XS_WATCH_PATH], &xenbus_frontend); +} + + +/* We watch for devices appearing and vanishing. */ +static struct xenbus_watch fe_watch = { + .node = "device", + .callback = frontend_changed, +}; + +static int read_backend_details(struct xenbus_device *xendev) +{ + return xenbus_read_otherend_details(xendev, "backend-id", "backend"); +} + +static int is_device_connecting(struct device *dev, void *data) +{ + struct xenbus_device *xendev = to_xenbus_device(dev); + struct device_driver *drv = data; + struct xenbus_driver *xendrv; + + /* + * A device with no driver will never connect. We care only about + * devices which should currently be in the process of connecting. + */ + if (!dev->driver) + return 0; + + /* Is this search limited to a particular driver? */ + if (drv && (dev->driver != drv)) + return 0; + + xendrv = to_xenbus_driver(dev->driver); + return (xendev->state < XenbusStateConnected || + (xendev->state == XenbusStateConnected && + xendrv->is_ready && !xendrv->is_ready(xendev))); +} + +static int exists_connecting_device(struct device_driver *drv) +{ + return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv, + is_device_connecting); +} + +static int print_device_status(struct device *dev, void *data) +{ + struct xenbus_device *xendev = to_xenbus_device(dev); + struct device_driver *drv = data; + + /* Is this operation limited to a particular driver? */ + if (drv && (dev->driver != drv)) + return 0; + + if (!dev->driver) { + /* Information only: is this too noisy? */ + printk(KERN_INFO "XENBUS: Device with no driver: %s\n", + xendev->nodename); + } else if (xendev->state < XenbusStateConnected) { + enum xenbus_state rstate = XenbusStateUnknown; + if (xendev->otherend) + rstate = xenbus_read_driver_state(xendev->otherend); + printk(KERN_WARNING "XENBUS: Timeout connecting " + "to device: %s (local state %d, remote state %d)\n", + xendev->nodename, xendev->state, rstate); + } + + return 0; +} + +/* We only wait for device setup after most initcalls have run. */ +static int ready_to_wait_for_devices; + +/* + * On a 5-minute timeout, wait for all devices currently configured. We need + * to do this to guarantee that the filesystems and / or network devices + * needed for boot are available, before we can allow the boot to proceed. + * + * This needs to be on a late_initcall, to happen after the frontend device + * drivers have been initialised, but before the root fs is mounted. + * + * A possible improvement here would be to have the tools add a per-device + * flag to the store entry, indicating whether it is needed at boot time. + * This would allow people who knew what they were doing to accelerate their + * boot slightly, but of course needs tools or manual intervention to set up + * those flags correctly. + */ +static void wait_for_devices(struct xenbus_driver *xendrv) +{ + unsigned long start = jiffies; + struct device_driver *drv = xendrv ? &xendrv->driver : NULL; + unsigned int seconds_waited = 0; + + if (!ready_to_wait_for_devices || !xen_domain()) + return; + + while (exists_connecting_device(drv)) { + if (time_after(jiffies, start + (seconds_waited+5)*HZ)) { + if (!seconds_waited) + printk(KERN_WARNING "XENBUS: Waiting for " + "devices to initialise: "); + seconds_waited += 5; + printk("%us...", 300 - seconds_waited); + if (seconds_waited == 300) + break; + } + + schedule_timeout_interruptible(HZ/10); + } + + if (seconds_waited) + printk("\n"); + + bus_for_each_dev(&xenbus_frontend.bus, NULL, drv, + print_device_status); +} + +int __xenbus_register_frontend(struct xenbus_driver *drv, + struct module *owner, const char *mod_name) +{ + int ret; + + drv->read_otherend_details = read_backend_details; + + ret = xenbus_register_driver_common(drv, &xenbus_frontend, + owner, mod_name); + if (ret) + return ret; + + /* If this driver is loaded as a module wait for devices to attach. */ + wait_for_devices(drv); + + return 0; +} +EXPORT_SYMBOL_GPL(__xenbus_register_frontend); + +static int __init xenbus_probe_frontend_init(void) +{ + int err; + + DPRINTK(""); + + /* Register ourselves with the kernel bus subsystem */ + err = bus_register(&xenbus_frontend.bus); + if (err) { + printk(KERN_CRIT "%s didn't register bus!\n", __func__); + return err; + } + printk(KERN_CRIT "%s bus registered ok\n", __func__); + + if (!xen_initial_domain()) { + /* Enumerate devices in xenstore and watch for changes. */ + xenbus_probe_devices(&xenbus_frontend); + printk(KERN_CRIT "%s devices probed ok\n", __func__); + register_xenbus_watch(&fe_watch); + printk(KERN_CRIT "%s watch add ok ok\n", __func__); + printk(KERN_CRIT "%s all done\n", __func__); + } + + return 0; +} + +module_init(xenbus_probe_frontend_init); + +#ifndef MODULE +static int __init boot_wait_for_devices(void) +{ + if (xen_hvm_domain() && !xen_platform_pci_unplug) + return -ENODEV; + + ready_to_wait_for_devices = 1; + wait_for_devices(NULL); + return 0; +} + +late_initcall(boot_wait_for_devices); +#endif -- cgit v1.2.3 From df660251eb534649f90f9dcfe1da1cef4ea48a3e Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Mon, 9 Feb 2009 12:05:51 -0800 Subject: xen: add backend driver support Impact: backend device support Add the basic machinery to support backend drivers. Signed-off-by: Ian Campbell Signed-off-by: Jeremy Fitzhardinge [corresponds to 79727b851bac in git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git] Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/Kconfig | 8 + drivers/xen/xenbus/Makefile | 3 + drivers/xen/xenbus/xenbus_comms.c | 1 + drivers/xen/xenbus/xenbus_probe.c | 13 +- drivers/xen/xenbus/xenbus_probe.h | 1 - drivers/xen/xenbus/xenbus_probe_backend.c | 300 +++++++++++++++++++++++++++++ drivers/xen/xenbus/xenbus_probe_frontend.c | 39 +++- 7 files changed, 344 insertions(+), 21 deletions(-) create mode 100644 drivers/xen/xenbus/xenbus_probe_backend.c (limited to 'drivers/xen') diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index 10b6bef2e217..84bf17bbb1cd 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig @@ -29,6 +29,14 @@ config XEN_DEV_EVTCHN firing. If in doubt, say yes. +config XEN_BACKEND + tristate "Backend driver support" + depends on XEN_DOM0 + default y + help + Support for backend device drivers that provide I/O services + to other virtual machines. + config XENFS tristate "Xen filesystem" default y diff --git a/drivers/xen/xenbus/Makefile b/drivers/xen/xenbus/Makefile index 33e8cf8149b3..8dca685358b4 100644 --- a/drivers/xen/xenbus/Makefile +++ b/drivers/xen/xenbus/Makefile @@ -6,4 +6,7 @@ xenbus-objs += xenbus_comms.o xenbus-objs += xenbus_xs.o xenbus-objs += xenbus_probe.o +xenbus-be-objs-$(CONFIG_XEN_BACKEND) += xenbus_probe_backend.o +xenbus-objs += $(xenbus-be-objs-y) + obj-$(CONFIG_XEN_XENBUS_FRONTEND) += xenbus_probe_frontend.o diff --git a/drivers/xen/xenbus/xenbus_comms.c b/drivers/xen/xenbus/xenbus_comms.c index 090c61ee8fd0..700dc7714838 100644 --- a/drivers/xen/xenbus/xenbus_comms.c +++ b/drivers/xen/xenbus/xenbus_comms.c @@ -49,6 +49,7 @@ static DECLARE_WAIT_QUEUE_HEAD(xb_waitq); static irqreturn_t wake_waiting(int irq, void *unused) { if (unlikely(xenstored_ready == 0)) { + printk(KERN_CRIT "xenbus_probe wake_waiting\n"); xenstored_ready = 1; schedule_work(&probe_work); } diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index d46205868b88..b09eb17ba007 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -95,17 +95,6 @@ int xenbus_match(struct device *_dev, struct device_driver *_drv) EXPORT_SYMBOL_GPL(xenbus_match); -int xenbus_uevent(struct device *_dev, struct kobj_uevent_env *env) -{ - struct xenbus_device *dev = to_xenbus_device(_dev); - - if (add_uevent_var(env, "MODALIAS=xen:%s", dev->devicetype)) - return -ENOMEM; - - return 0; -} -EXPORT_SYMBOL_GPL(xenbus_uevent); - static void free_otherend_details(struct xenbus_device *dev) { kfree(dev->otherend); @@ -690,6 +679,8 @@ void xenbus_probe(struct work_struct *unused) { xenstored_ready = 1; + printk(KERN_CRIT "xenbus_probe wake_waiting\n"); + /* Notify others that xenstore is up */ blocking_notifier_call_chain(&xenstore_chain, 0, NULL); } diff --git a/drivers/xen/xenbus/xenbus_probe.h b/drivers/xen/xenbus/xenbus_probe.h index be390cef329f..0e5fc4c63eb2 100644 --- a/drivers/xen/xenbus/xenbus_probe.h +++ b/drivers/xen/xenbus/xenbus_probe.h @@ -60,7 +60,6 @@ extern int xenbus_probe_devices(struct xen_bus_type *bus); extern void xenbus_dev_changed(const char *node, struct xen_bus_type *bus); -extern int xenbus_uevent(struct device *_dev, struct kobj_uevent_env *env); extern void xenbus_dev_shutdown(struct device *_dev); extern int xenbus_dev_suspend(struct device *dev, pm_message_t state); diff --git a/drivers/xen/xenbus/xenbus_probe_backend.c b/drivers/xen/xenbus/xenbus_probe_backend.c new file mode 100644 index 000000000000..7459ccee3c8b --- /dev/null +++ b/drivers/xen/xenbus/xenbus_probe_backend.c @@ -0,0 +1,300 @@ +/****************************************************************************** + * Talks to Xen Store to figure out what devices we have (backend half). + * + * Copyright (C) 2005 Rusty Russell, IBM Corporation + * Copyright (C) 2005 Mike Wray, Hewlett-Packard + * Copyright (C) 2005, 2006 XenSource Ltd + * Copyright (C) 2007 Solarflare Communications, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#define DPRINTK(fmt, args...) \ + pr_debug("xenbus_probe (%s:%d) " fmt ".\n", \ + __func__, __LINE__, ##args) + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "xenbus_comms.h" +#include "xenbus_probe.h" + +/* backend/// => -- */ +static int backend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename) +{ + int domid, err; + const char *devid, *type, *frontend; + unsigned int typelen; + + type = strchr(nodename, '/'); + if (!type) + return -EINVAL; + type++; + typelen = strcspn(type, "/"); + if (!typelen || type[typelen] != '/') + return -EINVAL; + + devid = strrchr(nodename, '/') + 1; + + err = xenbus_gather(XBT_NIL, nodename, "frontend-id", "%i", &domid, + "frontend", NULL, &frontend, + NULL); + if (err) + return err; + if (strlen(frontend) == 0) + err = -ERANGE; + if (!err && !xenbus_exists(XBT_NIL, frontend, "")) + err = -ENOENT; + kfree(frontend); + + if (err) + return err; + + if (snprintf(bus_id, XEN_BUS_ID_SIZE, + "%.*s-%i-%s", typelen, type, domid, devid) >= XEN_BUS_ID_SIZE) + return -ENOSPC; + return 0; +} + +static int xenbus_uevent_backend(struct device *dev, + struct kobj_uevent_env *env) +{ + struct xenbus_device *xdev; + struct xenbus_driver *drv; + struct xen_bus_type *bus; + + DPRINTK(""); + + if (dev == NULL) + return -ENODEV; + + xdev = to_xenbus_device(dev); + bus = container_of(xdev->dev.bus, struct xen_bus_type, bus); + if (xdev == NULL) + return -ENODEV; + + /* stuff we want to pass to /sbin/hotplug */ + if (add_uevent_var(env, "XENBUS_TYPE=%s", xdev->devicetype)) + return -ENOMEM; + + if (add_uevent_var(env, "XENBUS_PATH=%s", xdev->nodename)) + return -ENOMEM; + + if (add_uevent_var(env, "XENBUS_BASE_PATH=%s", bus->root)) + return -ENOMEM; + + if (dev->driver) { + drv = to_xenbus_driver(dev->driver); + if (drv && drv->uevent) + return drv->uevent(xdev, env); + } + + return 0; +} + +/* backend/// */ +static int xenbus_probe_backend_unit(struct xen_bus_type *bus, + const char *dir, + const char *type, + const char *name) +{ + char *nodename; + int err; + + nodename = kasprintf(GFP_KERNEL, "%s/%s", dir, name); + if (!nodename) + return -ENOMEM; + + DPRINTK("%s\n", nodename); + + err = xenbus_probe_node(bus, type, nodename); + kfree(nodename); + return err; +} + +/* backend// */ +static int xenbus_probe_backend(struct xen_bus_type *bus, const char *type, const char *domid) +{ + char *nodename; + int err = 0; + char **dir; + unsigned int i, dir_n = 0; + + DPRINTK(""); + + nodename = kasprintf(GFP_KERNEL, "%s/%s/%s", bus->root, type, domid); + if (!nodename) + return -ENOMEM; + + dir = xenbus_directory(XBT_NIL, nodename, "", &dir_n); + if (IS_ERR(dir)) { + kfree(nodename); + return PTR_ERR(dir); + } + + for (i = 0; i < dir_n; i++) { + err = xenbus_probe_backend_unit(bus, nodename, type, dir[i]); + if (err) + break; + } + kfree(dir); + kfree(nodename); + return err; +} + +static void frontend_changed(struct xenbus_watch *watch, + const char **vec, unsigned int len) +{ + xenbus_otherend_changed(watch, vec, len, 0); +} + +static struct device_attribute xenbus_backend_dev_attrs[] = { + __ATTR_NULL +}; + +static struct xen_bus_type xenbus_backend = { + .root = "backend", + .levels = 3, /* backend/type// */ + .get_bus_id = backend_bus_id, + .probe = xenbus_probe_backend, + .otherend_changed = frontend_changed, + .bus = { + .name = "xen-backend", + .match = xenbus_match, + .uevent = xenbus_uevent_backend, + .probe = xenbus_dev_probe, + .remove = xenbus_dev_remove, + .shutdown = xenbus_dev_shutdown, + .dev_attrs = xenbus_backend_dev_attrs, + }, +}; + +static void backend_changed(struct xenbus_watch *watch, + const char **vec, unsigned int len) +{ + DPRINTK(""); + + xenbus_dev_changed(vec[XS_WATCH_PATH], &xenbus_backend); +} + +static struct xenbus_watch be_watch = { + .node = "backend", + .callback = backend_changed, +}; + +static int read_frontend_details(struct xenbus_device *xendev) +{ + return xenbus_read_otherend_details(xendev, "frontend-id", "frontend"); +} + +//void xenbus_backend_suspend(int (*fn)(struct device *, void *)) +//{ +// DPRINTK(""); +// bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, fn); +//} + +//void xenbus_backend_resume(int (*fn)(struct device *, void *)) +//{ +// DPRINTK(""); +// bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, fn); +//} + +//int xenbus_for_each_backend(void *arg, int (*fn)(struct device *, void *)) +//{ +// return bus_for_each_dev(&xenbus_backend.bus, NULL, arg, fn); +//} +//EXPORT_SYMBOL_GPL(xenbus_for_each_backend); + +int xenbus_dev_is_online(struct xenbus_device *dev) +{ + int rc, val; + + rc = xenbus_scanf(XBT_NIL, dev->nodename, "online", "%d", &val); + if (rc != 1) + val = 0; /* no online node present */ + + return val; +} +EXPORT_SYMBOL_GPL(xenbus_dev_is_online); + +int __xenbus_register_backend(struct xenbus_driver *drv, + struct module *owner, const char *mod_name) +{ + drv->read_otherend_details = read_frontend_details; + + return xenbus_register_driver_common(drv, &xenbus_backend, + owner, mod_name); +} +EXPORT_SYMBOL_GPL(__xenbus_register_backend); + +static int backend_probe_and_watch(struct notifier_block *notifier, + unsigned long event, + void *data) +{ + /* Enumerate devices in xenstore and watch for changes. */ + xenbus_probe_devices(&xenbus_backend); + printk(KERN_CRIT "%s devices probed ok\n", __func__); + register_xenbus_watch(&be_watch); + printk(KERN_CRIT "%s watch add ok ok\n", __func__); + printk(KERN_CRIT "%s all done\n", __func__); + return NOTIFY_DONE; +} + +static int __init xenbus_probe_backend_init(void) +{ + static struct notifier_block xenstore_notifier = { + .notifier_call = backend_probe_and_watch + }; + int err; + + DPRINTK(""); + + /* Register ourselves with the kernel bus subsystem */ + err = bus_register(&xenbus_backend.bus); + if (err) { + printk(KERN_CRIT "%s didn't register bus!\n", __func__); + return err; + } + printk(KERN_CRIT "%s bus registered ok\n", __func__); + + register_xenstore_notifier(&xenstore_notifier); + + return 0; +} + +module_init(xenbus_probe_backend_init); diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c index 04c4f0123521..dd31d5a43b40 100644 --- a/drivers/xen/xenbus/xenbus_probe_frontend.c +++ b/drivers/xen/xenbus/xenbus_probe_frontend.c @@ -62,6 +62,17 @@ static int xenbus_probe_frontend(struct xen_bus_type *bus, const char *type, con return err; } +static int xenbus_uevent_frontend(struct device *_dev, struct kobj_uevent_env *env) +{ + struct xenbus_device *dev = to_xenbus_device(_dev); + + if (add_uevent_var(env, "MODALIAS=xen:%s", dev->devicetype)) + return -ENOMEM; + + return 0; +} + + static void backend_changed(struct xenbus_watch *watch, const char **vec, unsigned int len) { @@ -81,7 +92,7 @@ static struct xen_bus_type xenbus_frontend = { .bus = { .name = "xen", .match = xenbus_match, - .uevent = xenbus_uevent, + .uevent = xenbus_uevent_frontend, .probe = xenbus_dev_probe, .remove = xenbus_dev_remove, .shutdown = xenbus_dev_shutdown, @@ -232,8 +243,25 @@ int __xenbus_register_frontend(struct xenbus_driver *drv, } EXPORT_SYMBOL_GPL(__xenbus_register_frontend); +static int frontend_probe_and_watch(struct notifier_block *notifier, + unsigned long event, + void *data) +{ + /* Enumerate devices in xenstore and watch for changes. */ + xenbus_probe_devices(&xenbus_frontend); + printk(KERN_CRIT "%s devices probed ok\n", __func__); + register_xenbus_watch(&fe_watch); + printk(KERN_CRIT "%s watch add ok ok\n", __func__); + printk(KERN_CRIT "%s all done\n", __func__); + return NOTIFY_DONE; +} + + static int __init xenbus_probe_frontend_init(void) { + static struct notifier_block xenstore_notifier = { + .notifier_call = frontend_probe_and_watch + }; int err; DPRINTK(""); @@ -246,14 +274,7 @@ static int __init xenbus_probe_frontend_init(void) } printk(KERN_CRIT "%s bus registered ok\n", __func__); - if (!xen_initial_domain()) { - /* Enumerate devices in xenstore and watch for changes. */ - xenbus_probe_devices(&xenbus_frontend); - printk(KERN_CRIT "%s devices probed ok\n", __func__); - register_xenbus_watch(&fe_watch); - printk(KERN_CRIT "%s watch add ok ok\n", __func__); - printk(KERN_CRIT "%s all done\n", __func__); - } + register_xenstore_notifier(&xenstore_notifier); return 0; } -- cgit v1.2.3 From 74c2ee98385fe2653d6a817f6f74c18eec4c2424 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 9 Feb 2009 16:37:23 -0800 Subject: xen: remove xen/evtchn.h Impact: cleanup It's a usermode header for users of /dev/xen/evtchn. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ian Campbell [corresponds to b60e48cec12f in git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git] Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/xenbus/xenbus_probe_backend.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/xen') diff --git a/drivers/xen/xenbus/xenbus_probe_backend.c b/drivers/xen/xenbus/xenbus_probe_backend.c index 7459ccee3c8b..3bd38123e69a 100644 --- a/drivers/xen/xenbus/xenbus_probe_backend.c +++ b/drivers/xen/xenbus/xenbus_probe_backend.c @@ -48,7 +48,6 @@ #include #include #include -#include #include #include "xenbus_comms.h" -- cgit v1.2.3 From 806f5463d2598ea23a7a688c47c2774846fe7f2f Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 4 Mar 2009 22:31:45 -0800 Subject: xenbus/frontend: register bus earlier Impact: bugfix Make sure the frontend bus is registered early, before any drivers want to attach. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ian Campbell [corresponds to 1d5df318f87f in git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git] Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/xenbus/xenbus_probe_frontend.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/xen') diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c index dd31d5a43b40..ccd201f47927 100644 --- a/drivers/xen/xenbus/xenbus_probe_frontend.c +++ b/drivers/xen/xenbus/xenbus_probe_frontend.c @@ -278,8 +278,7 @@ static int __init xenbus_probe_frontend_init(void) return 0; } - -module_init(xenbus_probe_frontend_init); +subsys_initcall(xenbus_probe_frontend_init); #ifndef MODULE static int __init boot_wait_for_devices(void) -- cgit v1.2.3 From c3676e8462009d84dce89a454956460de3bfdca7 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 4 Mar 2009 22:32:16 -0800 Subject: xen/xenbus: make sure backend bus is registered earlier Impact: bugfix Need to register it before any drivers want to attach. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ian Campbell [corresponds to a7a9c3a942c6 in git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git] Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/xenbus/xenbus_probe_backend.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/xen') diff --git a/drivers/xen/xenbus/xenbus_probe_backend.c b/drivers/xen/xenbus/xenbus_probe_backend.c index 3bd38123e69a..a3cc5351fe29 100644 --- a/drivers/xen/xenbus/xenbus_probe_backend.c +++ b/drivers/xen/xenbus/xenbus_probe_backend.c @@ -295,5 +295,4 @@ static int __init xenbus_probe_backend_init(void) return 0; } - -module_init(xenbus_probe_backend_init); +subsys_initcall(xenbus_probe_backend_init); -- cgit v1.2.3 From 1b31a143450ea9b5e6168f3b21a02c4a6a63ad01 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Fri, 27 Mar 2009 16:29:44 -0700 Subject: xen/xenbus: make frontend bus GPL Make sure frontend xenbus has a GPL module license, so it can access all the xenbus symbols exported GPL only. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ian Campbell [corresponds to 525cbc8adcb5 in git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git] Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/xenbus/xenbus_probe_frontend.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/xen') diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c index ccd201f47927..3a4236524768 100644 --- a/drivers/xen/xenbus/xenbus_probe_frontend.c +++ b/drivers/xen/xenbus/xenbus_probe_frontend.c @@ -293,3 +293,5 @@ static int __init boot_wait_for_devices(void) late_initcall(boot_wait_for_devices); #endif + +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 7432e4bd0bcec9f18d9c94de8925b8a59d3edf94 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 29 Oct 2009 14:19:42 -0700 Subject: xen/xenbus: clean up error handling Don't report errors when booting on non-Xen, because its just confusing. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ian Campbell [corresponds to 8aa08376d6aa in git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git] Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/xenbus/xenbus_probe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/xen') diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index b09eb17ba007..96bd1ef61ebe 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -242,7 +242,7 @@ int xenbus_dev_probe(struct device *_dev) fail: xenbus_dev_error(dev, err, "xenbus_dev_probe on %s", dev->nodename); xenbus_switch_state(dev, XenbusStateClosed); - return -ENODEV; + return err; } EXPORT_SYMBOL_GPL(xenbus_dev_probe); @@ -709,7 +709,7 @@ static int __init xenbus_init(void) err = -ENODEV; if (!xen_domain()) - goto out_error; + return err; /* * Domain0 doesn't have a store_evtchn or store_mfn yet. -- cgit v1.2.3 From a16448e071ca80e599ea4f780242f40a0a213b07 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 29 Mar 2010 14:37:44 -0700 Subject: xen/xenbus: cleanup debug noise in xenbus_comms.c Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ian Campbell [corresponds to 6796c12281dc in git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git] Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/xenbus/xenbus_comms.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/xen') diff --git a/drivers/xen/xenbus/xenbus_comms.c b/drivers/xen/xenbus/xenbus_comms.c index 700dc7714838..090c61ee8fd0 100644 --- a/drivers/xen/xenbus/xenbus_comms.c +++ b/drivers/xen/xenbus/xenbus_comms.c @@ -49,7 +49,6 @@ static DECLARE_WAIT_QUEUE_HEAD(xb_waitq); static irqreturn_t wake_waiting(int irq, void *unused) { if (unlikely(xenstored_ready == 0)) { - printk(KERN_CRIT "xenbus_probe wake_waiting\n"); xenstored_ready = 1; schedule_work(&probe_work); } -- cgit v1.2.3 From a39bda27b35266beae945f48e0b6ab58d06a17d5 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 29 Mar 2010 14:38:12 -0700 Subject: xen/xenbus: clean up noise in xenbus_probe.c Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ian Campbell [corresponds to 01aded30aaef in git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git] Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/xenbus/xenbus_probe.c | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) (limited to 'drivers/xen') diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index 96bd1ef61ebe..811923451218 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -479,23 +479,16 @@ static int xenbus_probe_device_type(struct xen_bus_type *bus, const char *type) unsigned int dir_n = 0; int i; - printk(KERN_CRIT "%s type %s\n", __func__, type); - dir = xenbus_directory(XBT_NIL, bus->root, type, &dir_n); - if (IS_ERR(dir)) { - printk(KERN_CRIT "%s failed xenbus_directory\n", __func__); + if (IS_ERR(dir)) return PTR_ERR(dir); - } for (i = 0; i < dir_n; i++) { - printk(KERN_CRIT "%s %d/%d %s\n", __func__, i+1,dir_n, dir[i]); err = bus->probe(bus, type, dir[i]); - if (err) { - printk(KERN_CRIT "%s failed\n", __func__); + if (err) break; - } } - printk("%s done\n", __func__); + kfree(dir); return err; } @@ -506,23 +499,16 @@ int xenbus_probe_devices(struct xen_bus_type *bus) char **dir; unsigned int i, dir_n; - printk(KERN_CRIT "%s %s\n", __func__, bus->root); - dir = xenbus_directory(XBT_NIL, bus->root, "", &dir_n); - if (IS_ERR(dir)) { - printk(KERN_CRIT "%s failed xenbus_directory\n", __func__); + if (IS_ERR(dir)) return PTR_ERR(dir); - } for (i = 0; i < dir_n; i++) { - printk(KERN_CRIT "%s %d/%d %s\n", __func__, i+1,dir_n, dir[i]); err = xenbus_probe_device_type(bus, dir[i]); - if (err) { - printk(KERN_CRIT "%s failed\n", __func__); + if (err) break; - } } - printk("%s done\n", __func__); + kfree(dir); return err; } @@ -679,8 +665,6 @@ void xenbus_probe(struct work_struct *unused) { xenstored_ready = 1; - printk(KERN_CRIT "xenbus_probe wake_waiting\n"); - /* Notify others that xenstore is up */ blocking_notifier_call_chain(&xenstore_chain, 0, NULL); } @@ -776,7 +760,6 @@ static int __init xenbus_init(void) proc_mkdir("xen", NULL); #endif - printk(KERN_CRIT "%s ok\n", __func__); return 0; out_error: -- cgit v1.2.3 From b5d33d088f45bb62fdaaf1755da05aa5524a3a8f Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 29 Mar 2010 14:38:35 -0700 Subject: xen/xenbus: clean up noise in xenbus_probe_backend.c Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ian Campbell [corresponds to 98b833aaf81e in git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git] Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/xenbus/xenbus_probe_backend.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/xen') diff --git a/drivers/xen/xenbus/xenbus_probe_backend.c b/drivers/xen/xenbus/xenbus_probe_backend.c index a3cc5351fe29..9b9dd36bb1c4 100644 --- a/drivers/xen/xenbus/xenbus_probe_backend.c +++ b/drivers/xen/xenbus/xenbus_probe_backend.c @@ -267,10 +267,8 @@ static int backend_probe_and_watch(struct notifier_block *notifier, { /* Enumerate devices in xenstore and watch for changes. */ xenbus_probe_devices(&xenbus_backend); - printk(KERN_CRIT "%s devices probed ok\n", __func__); register_xenbus_watch(&be_watch); - printk(KERN_CRIT "%s watch add ok ok\n", __func__); - printk(KERN_CRIT "%s all done\n", __func__); + return NOTIFY_DONE; } @@ -285,11 +283,8 @@ static int __init xenbus_probe_backend_init(void) /* Register ourselves with the kernel bus subsystem */ err = bus_register(&xenbus_backend.bus); - if (err) { - printk(KERN_CRIT "%s didn't register bus!\n", __func__); + if (err) return err; - } - printk(KERN_CRIT "%s bus registered ok\n", __func__); register_xenstore_notifier(&xenstore_notifier); -- cgit v1.2.3 From 0ff4fdf065101504cd84ac36924fcdad6641a4f7 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 29 Mar 2010 14:38:54 -0700 Subject: xen/xenbus: clean up noise in xenbus_probe_frontend.c Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ian Campbell [corresponds to 616ff7a06a3f in git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git] Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/xenbus/xenbus_probe_frontend.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/xen') diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c index 3a4236524768..60c311ab3190 100644 --- a/drivers/xen/xenbus/xenbus_probe_frontend.c +++ b/drivers/xen/xenbus/xenbus_probe_frontend.c @@ -249,10 +249,8 @@ static int frontend_probe_and_watch(struct notifier_block *notifier, { /* Enumerate devices in xenstore and watch for changes. */ xenbus_probe_devices(&xenbus_frontend); - printk(KERN_CRIT "%s devices probed ok\n", __func__); register_xenbus_watch(&fe_watch); - printk(KERN_CRIT "%s watch add ok ok\n", __func__); - printk(KERN_CRIT "%s all done\n", __func__); + return NOTIFY_DONE; } @@ -268,11 +266,8 @@ static int __init xenbus_probe_frontend_init(void) /* Register ourselves with the kernel bus subsystem */ err = bus_register(&xenbus_frontend.bus); - if (err) { - printk(KERN_CRIT "%s didn't register bus!\n", __func__); + if (err) return err; - } - printk(KERN_CRIT "%s bus registered ok\n", __func__); register_xenstore_notifier(&xenstore_notifier); -- cgit v1.2.3 From 6bac7f9f9e8e549c18ec4b77c499a45a1fae61b9 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 10 Dec 2010 14:39:15 +0000 Subject: xen/xenbus: fixup checkpatch issues in xenbus_probe* Signed-off-by: Ian Campbell Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/Kconfig | 2 +- drivers/xen/xenbus/xenbus_probe.c | 12 ++++++--- drivers/xen/xenbus/xenbus_probe.h | 6 +++-- drivers/xen/xenbus/xenbus_probe_backend.c | 41 +++++++++--------------------- drivers/xen/xenbus/xenbus_probe_frontend.c | 28 ++++++++++---------- 5 files changed, 40 insertions(+), 49 deletions(-) (limited to 'drivers/xen') diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index 84bf17bbb1cd..554ed573c028 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig @@ -72,7 +72,7 @@ config XEN_SYS_HYPERVISOR config XEN_XENBUS_FRONTEND tristate - + config XEN_PLATFORM_PCI tristate "xen platform pci device driver" depends on XEN_PVHVM diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index 811923451218..baa65e7fbbc7 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -126,9 +126,11 @@ static int talk_to_otherend(struct xenbus_device *dev) static int watch_otherend(struct xenbus_device *dev) { - struct xen_bus_type *bus = container_of(dev->dev.bus, struct xen_bus_type, bus); + struct xen_bus_type *bus = + container_of(dev->dev.bus, struct xen_bus_type, bus); - return xenbus_watch_pathfmt(dev, &dev->otherend_watch, bus->otherend_changed, + return xenbus_watch_pathfmt(dev, &dev->otherend_watch, + bus->otherend_changed, "%s/%s", dev->otherend, "state"); } @@ -579,7 +581,8 @@ int xenbus_dev_suspend(struct device *dev, pm_message_t state) { int err = 0; struct xenbus_driver *drv; - struct xenbus_device *xdev = container_of(dev, struct xenbus_device, dev); + struct xenbus_device *xdev + = container_of(dev, struct xenbus_device, dev); DPRINTK("%s", xdev->nodename); @@ -599,7 +602,8 @@ int xenbus_dev_resume(struct device *dev) { int err; struct xenbus_driver *drv; - struct xenbus_device *xdev = container_of(dev, struct xenbus_device, dev); + struct xenbus_device *xdev + = container_of(dev, struct xenbus_device, dev); DPRINTK("%s", xdev->nodename); diff --git a/drivers/xen/xenbus/xenbus_probe.h b/drivers/xen/xenbus/xenbus_probe.h index 0e5fc4c63eb2..24665812316a 100644 --- a/drivers/xen/xenbus/xenbus_probe.h +++ b/drivers/xen/xenbus/xenbus_probe.h @@ -41,8 +41,10 @@ struct xen_bus_type char *root; unsigned int levels; int (*get_bus_id)(char bus_id[XEN_BUS_ID_SIZE], const char *nodename); - int (*probe)(struct xen_bus_type *bus, const char *type, const char *dir); - void (*otherend_changed)(struct xenbus_watch *watch, const char **vec, unsigned int len); + int (*probe)(struct xen_bus_type *bus, const char *type, + const char *dir); + void (*otherend_changed)(struct xenbus_watch *watch, const char **vec, + unsigned int len); struct bus_type bus; }; diff --git a/drivers/xen/xenbus/xenbus_probe_backend.c b/drivers/xen/xenbus/xenbus_probe_backend.c index 9b9dd36bb1c4..6cf467bf63ec 100644 --- a/drivers/xen/xenbus/xenbus_probe_backend.c +++ b/drivers/xen/xenbus/xenbus_probe_backend.c @@ -84,8 +84,8 @@ static int backend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename) if (err) return err; - if (snprintf(bus_id, XEN_BUS_ID_SIZE, - "%.*s-%i-%s", typelen, type, domid, devid) >= XEN_BUS_ID_SIZE) + if (snprintf(bus_id, XEN_BUS_ID_SIZE, "%.*s-%i-%s", + typelen, type, domid, devid) >= XEN_BUS_ID_SIZE) return -ENOSPC; return 0; } @@ -147,7 +147,8 @@ static int xenbus_probe_backend_unit(struct xen_bus_type *bus, } /* backend// */ -static int xenbus_probe_backend(struct xen_bus_type *bus, const char *type, const char *domid) +static int xenbus_probe_backend(struct xen_bus_type *bus, const char *type, + const char *domid) { char *nodename; int err = 0; @@ -188,18 +189,18 @@ static struct device_attribute xenbus_backend_dev_attrs[] = { static struct xen_bus_type xenbus_backend = { .root = "backend", - .levels = 3, /* backend/type// */ + .levels = 3, /* backend/type// */ .get_bus_id = backend_bus_id, .probe = xenbus_probe_backend, .otherend_changed = frontend_changed, .bus = { - .name = "xen-backend", - .match = xenbus_match, - .uevent = xenbus_uevent_backend, - .probe = xenbus_dev_probe, - .remove = xenbus_dev_remove, - .shutdown = xenbus_dev_shutdown, - .dev_attrs = xenbus_backend_dev_attrs, + .name = "xen-backend", + .match = xenbus_match, + .uevent = xenbus_uevent_backend, + .probe = xenbus_dev_probe, + .remove = xenbus_dev_remove, + .shutdown = xenbus_dev_shutdown, + .dev_attrs = xenbus_backend_dev_attrs, }, }; @@ -221,24 +222,6 @@ static int read_frontend_details(struct xenbus_device *xendev) return xenbus_read_otherend_details(xendev, "frontend-id", "frontend"); } -//void xenbus_backend_suspend(int (*fn)(struct device *, void *)) -//{ -// DPRINTK(""); -// bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, fn); -//} - -//void xenbus_backend_resume(int (*fn)(struct device *, void *)) -//{ -// DPRINTK(""); -// bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, fn); -//} - -//int xenbus_for_each_backend(void *arg, int (*fn)(struct device *, void *)) -//{ -// return bus_for_each_dev(&xenbus_backend.bus, NULL, arg, fn); -//} -//EXPORT_SYMBOL_GPL(xenbus_for_each_backend); - int xenbus_dev_is_online(struct xenbus_device *dev) { int rc, val; diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c index 60c311ab3190..5bcc2d6cf129 100644 --- a/drivers/xen/xenbus/xenbus_probe_frontend.c +++ b/drivers/xen/xenbus/xenbus_probe_frontend.c @@ -46,7 +46,8 @@ static int frontend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename) } /* device// */ -static int xenbus_probe_frontend(struct xen_bus_type *bus, const char *type, const char *name) +static int xenbus_probe_frontend(struct xen_bus_type *bus, const char *type, + const char *name) { char *nodename; int err; @@ -62,7 +63,8 @@ static int xenbus_probe_frontend(struct xen_bus_type *bus, const char *type, con return err; } -static int xenbus_uevent_frontend(struct device *_dev, struct kobj_uevent_env *env) +static int xenbus_uevent_frontend(struct device *_dev, + struct kobj_uevent_env *env) { struct xenbus_device *dev = to_xenbus_device(_dev); @@ -85,21 +87,21 @@ static struct device_attribute xenbus_frontend_dev_attrs[] = { static struct xen_bus_type xenbus_frontend = { .root = "device", - .levels = 2, /* device/type/ */ + .levels = 2, /* device/type/ */ .get_bus_id = frontend_bus_id, .probe = xenbus_probe_frontend, .otherend_changed = backend_changed, .bus = { - .name = "xen", - .match = xenbus_match, - .uevent = xenbus_uevent_frontend, - .probe = xenbus_dev_probe, - .remove = xenbus_dev_remove, - .shutdown = xenbus_dev_shutdown, - .dev_attrs= xenbus_frontend_dev_attrs, - - .suspend = xenbus_dev_suspend, - .resume = xenbus_dev_resume, + .name = "xen", + .match = xenbus_match, + .uevent = xenbus_uevent_frontend, + .probe = xenbus_dev_probe, + .remove = xenbus_dev_remove, + .shutdown = xenbus_dev_shutdown, + .dev_attrs = xenbus_frontend_dev_attrs, + + .suspend = xenbus_dev_suspend, + .resume = xenbus_dev_resume, }, }; -- cgit v1.2.3 From 329620a878cf89184b28500d37fa33cc870a3357 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Sat, 21 Mar 2009 23:29:34 -0700 Subject: xen/xenbus: making backend support modular is too complex Impact: build fix Making the xenbus backend support a separate module is needlessly complex and causes build failures. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/xen') diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index 554ed573c028..5a48ce996dea 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig @@ -30,7 +30,7 @@ config XEN_DEV_EVTCHN If in doubt, say yes. config XEN_BACKEND - tristate "Backend driver support" + bool "Backend driver support" depends on XEN_DOM0 default y help -- cgit v1.2.3