12de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell#define DPRINTK(fmt, args...) \ 22de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell pr_debug("xenbus_probe (%s:%d) " fmt ".\n", \ 32de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell __func__, __LINE__, ##args) 42de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 52de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell#include <linux/kernel.h> 62de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell#include <linux/err.h> 72de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell#include <linux/string.h> 82de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell#include <linux/ctype.h> 92de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell#include <linux/fcntl.h> 102de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell#include <linux/mm.h> 112de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell#include <linux/proc_fs.h> 122de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell#include <linux/notifier.h> 132de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell#include <linux/kthread.h> 142de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell#include <linux/mutex.h> 152de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell#include <linux/io.h> 1672ee5112a0007c958dc57f4a1469c4bbd2cf4d11Paul Gortmaker#include <linux/module.h> 172de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 182de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell#include <asm/page.h> 192de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell#include <asm/pgtable.h> 202de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell#include <asm/xen/hypervisor.h> 212de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell#include <xen/xenbus.h> 222de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell#include <xen/events.h> 232de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell#include <xen/page.h> 242de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 252de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell#include <xen/platform_pci.h> 262de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 272de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell#include "xenbus_comms.h" 282de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell#include "xenbus_probe.h" 292de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 302de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 312de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell/* device/<type>/<id> => <type>-<id> */ 322de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbellstatic int frontend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename) 332de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell{ 342de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell nodename = strchr(nodename, '/'); 352de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell if (!nodename || strlen(nodename + 1) >= XEN_BUS_ID_SIZE) { 362de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell printk(KERN_WARNING "XENBUS: bad frontend %s\n", nodename); 372de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell return -EINVAL; 382de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell } 392de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 402de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell strlcpy(bus_id, nodename + 1, XEN_BUS_ID_SIZE); 412de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell if (!strchr(bus_id, '/')) { 422de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell printk(KERN_WARNING "XENBUS: bus_id %s no slash\n", bus_id); 432de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell return -EINVAL; 442de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell } 452de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell *strchr(bus_id, '/') = '-'; 462de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell return 0; 472de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell} 482de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 492de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell/* device/<typename>/<name> */ 506bac7f9f9e8e549c18ec4b77c499a45a1fae61b9Ian Campbellstatic int xenbus_probe_frontend(struct xen_bus_type *bus, const char *type, 516bac7f9f9e8e549c18ec4b77c499a45a1fae61b9Ian Campbell const char *name) 522de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell{ 532de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell char *nodename; 542de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell int err; 552de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 5642c46e6ba5461fcab289bf4a1b7160f94c10aa28Stefano Stabellini /* ignore console/0 */ 5742c46e6ba5461fcab289bf4a1b7160f94c10aa28Stefano Stabellini if (!strncmp(type, "console", 7) && !strncmp(name, "0", 1)) { 5842c46e6ba5461fcab289bf4a1b7160f94c10aa28Stefano Stabellini DPRINTK("Ignoring buggy device entry console/0"); 5942c46e6ba5461fcab289bf4a1b7160f94c10aa28Stefano Stabellini return 0; 6042c46e6ba5461fcab289bf4a1b7160f94c10aa28Stefano Stabellini } 6142c46e6ba5461fcab289bf4a1b7160f94c10aa28Stefano Stabellini 622de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell nodename = kasprintf(GFP_KERNEL, "%s/%s/%s", bus->root, type, name); 632de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell if (!nodename) 642de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell return -ENOMEM; 652de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 662de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell DPRINTK("%s", nodename); 672de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 682de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell err = xenbus_probe_node(bus, type, nodename); 692de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell kfree(nodename); 702de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell return err; 712de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell} 722de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 736bac7f9f9e8e549c18ec4b77c499a45a1fae61b9Ian Campbellstatic int xenbus_uevent_frontend(struct device *_dev, 746bac7f9f9e8e549c18ec4b77c499a45a1fae61b9Ian Campbell struct kobj_uevent_env *env) 75df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell{ 76df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell struct xenbus_device *dev = to_xenbus_device(_dev); 77df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell 78df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell if (add_uevent_var(env, "MODALIAS=xen:%s", dev->devicetype)) 79df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell return -ENOMEM; 80df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell 81df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell return 0; 82df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell} 83df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell 84df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell 852de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbellstatic void backend_changed(struct xenbus_watch *watch, 862de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell const char **vec, unsigned int len) 872de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell{ 882de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell xenbus_otherend_changed(watch, vec, len, 1); 892de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell} 902de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 91c7853aea57d8e850b0979e7bdcbcabdcbbdd9e37Kazuhiro SUZUKIstatic const struct dev_pm_ops xenbus_pm_ops = { 92b3e96c0c756211e805c6941d4a6e5f6e1995cb6bShriram Rajagopalan .suspend = xenbus_dev_suspend, 93b3e96c0c756211e805c6941d4a6e5f6e1995cb6bShriram Rajagopalan .resume = xenbus_dev_resume, 94b3e96c0c756211e805c6941d4a6e5f6e1995cb6bShriram Rajagopalan .freeze = xenbus_dev_suspend, 95b3e96c0c756211e805c6941d4a6e5f6e1995cb6bShriram Rajagopalan .thaw = xenbus_dev_cancel, 96b3e96c0c756211e805c6941d4a6e5f6e1995cb6bShriram Rajagopalan .restore = xenbus_dev_resume, 97c7853aea57d8e850b0979e7bdcbcabdcbbdd9e37Kazuhiro SUZUKI}; 98c7853aea57d8e850b0979e7bdcbcabdcbbdd9e37Kazuhiro SUZUKI 992de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbellstatic struct xen_bus_type xenbus_frontend = { 1002de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell .root = "device", 1016bac7f9f9e8e549c18ec4b77c499a45a1fae61b9Ian Campbell .levels = 2, /* device/type/<id> */ 1022de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell .get_bus_id = frontend_bus_id, 1032de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell .probe = xenbus_probe_frontend, 1042de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell .otherend_changed = backend_changed, 1052de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell .bus = { 1066bac7f9f9e8e549c18ec4b77c499a45a1fae61b9Ian Campbell .name = "xen", 1076bac7f9f9e8e549c18ec4b77c499a45a1fae61b9Ian Campbell .match = xenbus_match, 1086bac7f9f9e8e549c18ec4b77c499a45a1fae61b9Ian Campbell .uevent = xenbus_uevent_frontend, 1096bac7f9f9e8e549c18ec4b77c499a45a1fae61b9Ian Campbell .probe = xenbus_dev_probe, 1106bac7f9f9e8e549c18ec4b77c499a45a1fae61b9Ian Campbell .remove = xenbus_dev_remove, 1116bac7f9f9e8e549c18ec4b77c499a45a1fae61b9Ian Campbell .shutdown = xenbus_dev_shutdown, 112cc85e93342c030f8ba07f572afa159ec4518231fBastian Blank .dev_attrs = xenbus_dev_attrs, 1136bac7f9f9e8e549c18ec4b77c499a45a1fae61b9Ian Campbell 114c7853aea57d8e850b0979e7bdcbcabdcbbdd9e37Kazuhiro SUZUKI .pm = &xenbus_pm_ops, 1152de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell }, 1162de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell}; 1172de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 1182de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbellstatic void frontend_changed(struct xenbus_watch *watch, 1192de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell const char **vec, unsigned int len) 1202de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell{ 1212de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell DPRINTK(""); 1222de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 1232de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell xenbus_dev_changed(vec[XS_WATCH_PATH], &xenbus_frontend); 1242de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell} 1252de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 1262de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 1272de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell/* We watch for devices appearing and vanishing. */ 1282de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbellstatic struct xenbus_watch fe_watch = { 1292de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell .node = "device", 1302de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell .callback = frontend_changed, 1312de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell}; 1322de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 1332de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbellstatic int read_backend_details(struct xenbus_device *xendev) 1342de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell{ 1352de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell return xenbus_read_otherend_details(xendev, "backend-id", "backend"); 1362de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell} 1372de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 1383066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilkstatic int is_device_connecting(struct device *dev, void *data, bool ignore_nonessential) 1392de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell{ 1402de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell struct xenbus_device *xendev = to_xenbus_device(dev); 1412de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell struct device_driver *drv = data; 1422de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell struct xenbus_driver *xendrv; 1432de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 1442de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell /* 1452de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell * A device with no driver will never connect. We care only about 1462de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell * devices which should currently be in the process of connecting. 1472de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell */ 1482de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell if (!dev->driver) 1492de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell return 0; 1502de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 1512de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell /* Is this search limited to a particular driver? */ 1522de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell if (drv && (dev->driver != drv)) 1532de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell return 0; 1542de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 1553066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk if (ignore_nonessential) { 1563066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk /* With older QEMU, for PVonHVM guests the guest config files 1573066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk * could contain: vfb = [ 'vnc=1, vnclisten=0.0.0.0'] 1583066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk * which is nonsensical as there is no PV FB (there can be 1593066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk * a PVKB) running as HVM guest. */ 1603066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk 1613066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk if ((strncmp(xendev->nodename, "device/vkbd", 11) == 0)) 1623066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk return 0; 1633066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk 1643066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk if ((strncmp(xendev->nodename, "device/vfb", 10) == 0)) 1653066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk return 0; 1663066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk } 1672de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell xendrv = to_xenbus_driver(dev->driver); 1682de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell return (xendev->state < XenbusStateConnected || 1692de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell (xendev->state == XenbusStateConnected && 1702de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell xendrv->is_ready && !xendrv->is_ready(xendev))); 1712de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell} 1723066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilkstatic int essential_device_connecting(struct device *dev, void *data) 1733066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk{ 1743066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk return is_device_connecting(dev, data, true /* ignore PV[KBB+FB] */); 1753066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk} 1763066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilkstatic int non_essential_device_connecting(struct device *dev, void *data) 1773066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk{ 1783066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk return is_device_connecting(dev, data, false); 1793066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk} 1802de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 1813066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilkstatic int exists_essential_connecting_device(struct device_driver *drv) 1822de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell{ 1832de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv, 1843066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk essential_device_connecting); 1853066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk} 1863066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilkstatic int exists_non_essential_connecting_device(struct device_driver *drv) 1873066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk{ 1883066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv, 1893066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk non_essential_device_connecting); 1902de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell} 1912de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 1922de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbellstatic int print_device_status(struct device *dev, void *data) 1932de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell{ 1942de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell struct xenbus_device *xendev = to_xenbus_device(dev); 1952de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell struct device_driver *drv = data; 1962de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 1972de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell /* Is this operation limited to a particular driver? */ 1982de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell if (drv && (dev->driver != drv)) 1992de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell return 0; 2002de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 2012de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell if (!dev->driver) { 2022de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell /* Information only: is this too noisy? */ 2032de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell printk(KERN_INFO "XENBUS: Device with no driver: %s\n", 2042de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell xendev->nodename); 2052de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell } else if (xendev->state < XenbusStateConnected) { 2062de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell enum xenbus_state rstate = XenbusStateUnknown; 2072de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell if (xendev->otherend) 2082de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell rstate = xenbus_read_driver_state(xendev->otherend); 2092de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell printk(KERN_WARNING "XENBUS: Timeout connecting " 2102de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell "to device: %s (local state %d, remote state %d)\n", 2112de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell xendev->nodename, xendev->state, rstate); 2122de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell } 2132de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 2142de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell return 0; 2152de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell} 2162de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 2172de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell/* We only wait for device setup after most initcalls have run. */ 2182de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbellstatic int ready_to_wait_for_devices; 2192de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 2203066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilkstatic bool wait_loop(unsigned long start, unsigned int max_delay, 2213066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk unsigned int *seconds_waited) 2223066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk{ 2233066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk if (time_after(jiffies, start + (*seconds_waited+5)*HZ)) { 2243066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk if (!*seconds_waited) 2253066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk printk(KERN_WARNING "XENBUS: Waiting for " 2263066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk "devices to initialise: "); 2273066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk *seconds_waited += 5; 2283066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk printk("%us...", max_delay - *seconds_waited); 2293066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk if (*seconds_waited == max_delay) 2303066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk return true; 2313066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk } 2323066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk 2333066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk schedule_timeout_interruptible(HZ/10); 2343066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk 2353066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk return false; 2363066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk} 2372de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell/* 2382de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell * On a 5-minute timeout, wait for all devices currently configured. We need 2392de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell * to do this to guarantee that the filesystems and / or network devices 2402de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell * needed for boot are available, before we can allow the boot to proceed. 2412de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell * 2422de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell * This needs to be on a late_initcall, to happen after the frontend device 2432de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell * drivers have been initialised, but before the root fs is mounted. 2442de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell * 2452de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell * A possible improvement here would be to have the tools add a per-device 2462de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell * flag to the store entry, indicating whether it is needed at boot time. 2472de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell * This would allow people who knew what they were doing to accelerate their 2482de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell * boot slightly, but of course needs tools or manual intervention to set up 2492de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell * those flags correctly. 2502de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell */ 2512de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbellstatic void wait_for_devices(struct xenbus_driver *xendrv) 2522de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell{ 2532de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell unsigned long start = jiffies; 2542de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell struct device_driver *drv = xendrv ? &xendrv->driver : NULL; 2552de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell unsigned int seconds_waited = 0; 2562de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 2572de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell if (!ready_to_wait_for_devices || !xen_domain()) 2582de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell return; 2592de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 2603066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk while (exists_non_essential_connecting_device(drv)) 2613066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk if (wait_loop(start, 30, &seconds_waited)) 2623066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk break; 2633066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk 2643066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk /* Skips PVKB and PVFB check.*/ 2653066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk while (exists_essential_connecting_device(drv)) 2663066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk if (wait_loop(start, 270, &seconds_waited)) 2673066616ce23aad5719c23a0f21f32676402cb44bKonrad Rzeszutek Wilk break; 2682de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 2692de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell if (seconds_waited) 2702de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell printk("\n"); 2712de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 2722de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell bus_for_each_dev(&xenbus_frontend.bus, NULL, drv, 2732de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell print_device_status); 2742de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell} 2752de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 27673db144b58a32fc39733db6a7e1fe582072ad26aJan Beulichint xenbus_register_frontend(struct xenbus_driver *drv) 2772de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell{ 2782de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell int ret; 2792de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 2802de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell drv->read_otherend_details = read_backend_details; 2812de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 28273db144b58a32fc39733db6a7e1fe582072ad26aJan Beulich ret = xenbus_register_driver_common(drv, &xenbus_frontend); 2832de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell if (ret) 2842de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell return ret; 2852de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 2862de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell /* If this driver is loaded as a module wait for devices to attach. */ 2872de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell wait_for_devices(drv); 2882de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 2892de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell return 0; 2902de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell} 29173db144b58a32fc39733db6a7e1fe582072ad26aJan BeulichEXPORT_SYMBOL_GPL(xenbus_register_frontend); 2922de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 293116df6f004af81925dcaa90d4a3b76da6b009427Olaf Heringstatic DECLARE_WAIT_QUEUE_HEAD(backend_state_wq); 294116df6f004af81925dcaa90d4a3b76da6b009427Olaf Heringstatic int backend_state; 295116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering 296116df6f004af81925dcaa90d4a3b76da6b009427Olaf Heringstatic void xenbus_reset_backend_state_changed(struct xenbus_watch *w, 297116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering const char **v, unsigned int l) 298116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering{ 299116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering xenbus_scanf(XBT_NIL, v[XS_WATCH_PATH], "", "%i", &backend_state); 300116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering printk(KERN_DEBUG "XENBUS: backend %s %s\n", 301116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering v[XS_WATCH_PATH], xenbus_strstate(backend_state)); 302116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering wake_up(&backend_state_wq); 303116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering} 304116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering 305116df6f004af81925dcaa90d4a3b76da6b009427Olaf Heringstatic void xenbus_reset_wait_for_backend(char *be, int expected) 306116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering{ 307116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering long timeout; 308116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering timeout = wait_event_interruptible_timeout(backend_state_wq, 309116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering backend_state == expected, 5 * HZ); 310116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering if (timeout <= 0) 311116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering printk(KERN_INFO "XENBUS: backend %s timed out.\n", be); 312116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering} 313116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering 314116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering/* 315116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering * Reset frontend if it is in Connected or Closed state. 316116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering * Wait for backend to catch up. 317116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering * State Connected happens during kdump, Closed after kexec. 318116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering */ 319116df6f004af81925dcaa90d4a3b76da6b009427Olaf Heringstatic void xenbus_reset_frontend(char *fe, char *be, int be_state) 320116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering{ 321116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering struct xenbus_watch be_watch; 322116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering 323116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering printk(KERN_DEBUG "XENBUS: backend %s %s\n", 324116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering be, xenbus_strstate(be_state)); 325116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering 326116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering memset(&be_watch, 0, sizeof(be_watch)); 327116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering be_watch.node = kasprintf(GFP_NOIO | __GFP_HIGH, "%s/state", be); 328116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering if (!be_watch.node) 329116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering return; 330116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering 331116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering be_watch.callback = xenbus_reset_backend_state_changed; 332116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering backend_state = XenbusStateUnknown; 333116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering 334116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering printk(KERN_INFO "XENBUS: triggering reconnect on %s\n", be); 335116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering register_xenbus_watch(&be_watch); 336116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering 337116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering /* fall through to forward backend to state XenbusStateInitialising */ 338116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering switch (be_state) { 339116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering case XenbusStateConnected: 340116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering xenbus_printf(XBT_NIL, fe, "state", "%d", XenbusStateClosing); 341116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering xenbus_reset_wait_for_backend(be, XenbusStateClosing); 342116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering 343116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering case XenbusStateClosing: 344116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering xenbus_printf(XBT_NIL, fe, "state", "%d", XenbusStateClosed); 345116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering xenbus_reset_wait_for_backend(be, XenbusStateClosed); 346116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering 347116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering case XenbusStateClosed: 348116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering xenbus_printf(XBT_NIL, fe, "state", "%d", XenbusStateInitialising); 349116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering xenbus_reset_wait_for_backend(be, XenbusStateInitWait); 350116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering } 351116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering 352116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering unregister_xenbus_watch(&be_watch); 353116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering printk(KERN_INFO "XENBUS: reconnect done on %s\n", be); 354116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering kfree(be_watch.node); 355116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering} 356116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering 357116df6f004af81925dcaa90d4a3b76da6b009427Olaf Heringstatic void xenbus_check_frontend(char *class, char *dev) 358116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering{ 359116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering int be_state, fe_state, err; 360116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering char *backend, *frontend; 361116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering 362116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering frontend = kasprintf(GFP_NOIO | __GFP_HIGH, "device/%s/%s", class, dev); 363116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering if (!frontend) 364116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering return; 365116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering 366116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering err = xenbus_scanf(XBT_NIL, frontend, "state", "%i", &fe_state); 367116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering if (err != 1) 368116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering goto out; 369116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering 370116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering switch (fe_state) { 371116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering case XenbusStateConnected: 372116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering case XenbusStateClosed: 373116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering printk(KERN_DEBUG "XENBUS: frontend %s %s\n", 374116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering frontend, xenbus_strstate(fe_state)); 375116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering backend = xenbus_read(XBT_NIL, frontend, "backend", NULL); 376116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering if (!backend || IS_ERR(backend)) 377116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering goto out; 378116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering err = xenbus_scanf(XBT_NIL, backend, "state", "%i", &be_state); 379116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering if (err == 1) 380116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering xenbus_reset_frontend(frontend, backend, be_state); 381116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering kfree(backend); 382116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering break; 383116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering default: 384116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering break; 385116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering } 386116df6f004af81925dcaa90d4a3b76da6b009427Olaf Heringout: 387116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering kfree(frontend); 388116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering} 389116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering 390116df6f004af81925dcaa90d4a3b76da6b009427Olaf Heringstatic void xenbus_reset_state(void) 391116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering{ 392116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering char **devclass, **dev; 393116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering int devclass_n, dev_n; 394116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering int i, j; 395116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering 396116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering devclass = xenbus_directory(XBT_NIL, "device", "", &devclass_n); 397116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering if (IS_ERR(devclass)) 398116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering return; 399116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering 400116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering for (i = 0; i < devclass_n; i++) { 401116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering dev = xenbus_directory(XBT_NIL, "device", devclass[i], &dev_n); 402116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering if (IS_ERR(dev)) 403116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering continue; 404116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering for (j = 0; j < dev_n; j++) 405116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering xenbus_check_frontend(devclass[i], dev[j]); 406116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering kfree(dev); 407116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering } 408116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering kfree(devclass); 409116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering} 410116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering 411df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbellstatic int frontend_probe_and_watch(struct notifier_block *notifier, 412df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell unsigned long event, 413df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell void *data) 414df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell{ 415116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering /* reset devices in Connected or Closed state */ 416116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering if (xen_hvm_domain()) 417116df6f004af81925dcaa90d4a3b76da6b009427Olaf Hering xenbus_reset_state(); 418df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell /* Enumerate devices in xenstore and watch for changes. */ 419df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell xenbus_probe_devices(&xenbus_frontend); 420df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell register_xenbus_watch(&fe_watch); 4210ff4fdf065101504cd84ac36924fcdad6641a4f7Jeremy Fitzhardinge 422df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell return NOTIFY_DONE; 423df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell} 424df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell 425df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell 4262de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbellstatic int __init xenbus_probe_frontend_init(void) 4272de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell{ 428df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell static struct notifier_block xenstore_notifier = { 429df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell .notifier_call = frontend_probe_and_watch 430df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell }; 4312de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell int err; 4322de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 4332de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell DPRINTK(""); 4342de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 4352de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell /* Register ourselves with the kernel bus subsystem */ 4362de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell err = bus_register(&xenbus_frontend.bus); 4370ff4fdf065101504cd84ac36924fcdad6641a4f7Jeremy Fitzhardinge if (err) 4382de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell return err; 4392de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 440df660251eb534649f90f9dcfe1da1cef4ea48a3eIan Campbell register_xenstore_notifier(&xenstore_notifier); 4412de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 4422de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell return 0; 4432de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell} 444806f5463d2598ea23a7a688c47c2774846fe7f2fJeremy Fitzhardingesubsys_initcall(xenbus_probe_frontend_init); 4452de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 4462de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell#ifndef MODULE 4472de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbellstatic int __init boot_wait_for_devices(void) 4482de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell{ 4492de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell if (xen_hvm_domain() && !xen_platform_pci_unplug) 4502de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell return -ENODEV; 4512de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 4522de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell ready_to_wait_for_devices = 1; 4532de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell wait_for_devices(NULL); 4542de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell return 0; 4552de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell} 4562de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell 4572de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbelllate_initcall(boot_wait_for_devices); 4582de06cc1f18d638cc7ab1169f61a8599045c2d4fIan Campbell#endif 4591b31a143450ea9b5e6168f3b21a02c4a6a63ad01Jeremy Fitzhardinge 4601b31a143450ea9b5e6168f3b21a02c4a6a63ad01Jeremy FitzhardingeMODULE_LICENSE("GPL"); 461