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