xref: /OK3568_Linux_fs/kernel/drivers/xen/xenbus/xenbus_probe_frontend.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun #define DPRINTK(fmt, ...)				\
5*4882a593Smuzhiyun 	pr_debug("(%s:%d) " fmt "\n",			\
6*4882a593Smuzhiyun 		 __func__, __LINE__, ##__VA_ARGS__)
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/kernel.h>
9*4882a593Smuzhiyun #include <linux/err.h>
10*4882a593Smuzhiyun #include <linux/string.h>
11*4882a593Smuzhiyun #include <linux/ctype.h>
12*4882a593Smuzhiyun #include <linux/fcntl.h>
13*4882a593Smuzhiyun #include <linux/mm.h>
14*4882a593Smuzhiyun #include <linux/proc_fs.h>
15*4882a593Smuzhiyun #include <linux/notifier.h>
16*4882a593Smuzhiyun #include <linux/kthread.h>
17*4882a593Smuzhiyun #include <linux/mutex.h>
18*4882a593Smuzhiyun #include <linux/io.h>
19*4882a593Smuzhiyun #include <linux/module.h>
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #include <asm/page.h>
22*4882a593Smuzhiyun #include <asm/xen/hypervisor.h>
23*4882a593Smuzhiyun #include <xen/xenbus.h>
24*4882a593Smuzhiyun #include <xen/events.h>
25*4882a593Smuzhiyun #include <xen/page.h>
26*4882a593Smuzhiyun #include <xen/xen.h>
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #include <xen/platform_pci.h>
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #include "xenbus.h"
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun /* device/<type>/<id> => <type>-<id> */
frontend_bus_id(char bus_id[XEN_BUS_ID_SIZE],const char * nodename)35*4882a593Smuzhiyun static int frontend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename)
36*4882a593Smuzhiyun {
37*4882a593Smuzhiyun 	nodename = strchr(nodename, '/');
38*4882a593Smuzhiyun 	if (!nodename || strlen(nodename + 1) >= XEN_BUS_ID_SIZE) {
39*4882a593Smuzhiyun 		pr_warn("bad frontend %s\n", nodename);
40*4882a593Smuzhiyun 		return -EINVAL;
41*4882a593Smuzhiyun 	}
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun 	strlcpy(bus_id, nodename + 1, XEN_BUS_ID_SIZE);
44*4882a593Smuzhiyun 	if (!strchr(bus_id, '/')) {
45*4882a593Smuzhiyun 		pr_warn("bus_id %s no slash\n", bus_id);
46*4882a593Smuzhiyun 		return -EINVAL;
47*4882a593Smuzhiyun 	}
48*4882a593Smuzhiyun 	*strchr(bus_id, '/') = '-';
49*4882a593Smuzhiyun 	return 0;
50*4882a593Smuzhiyun }
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun /* device/<typename>/<name> */
xenbus_probe_frontend(struct xen_bus_type * bus,const char * type,const char * name)53*4882a593Smuzhiyun static int xenbus_probe_frontend(struct xen_bus_type *bus, const char *type,
54*4882a593Smuzhiyun 				 const char *name)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun 	char *nodename;
57*4882a593Smuzhiyun 	int err;
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 	/* ignore console/0 */
60*4882a593Smuzhiyun 	if (!strncmp(type, "console", 7) && !strncmp(name, "0", 1)) {
61*4882a593Smuzhiyun 		DPRINTK("Ignoring buggy device entry console/0");
62*4882a593Smuzhiyun 		return 0;
63*4882a593Smuzhiyun 	}
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	nodename = kasprintf(GFP_KERNEL, "%s/%s/%s", bus->root, type, name);
66*4882a593Smuzhiyun 	if (!nodename)
67*4882a593Smuzhiyun 		return -ENOMEM;
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	DPRINTK("%s", nodename);
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 	err = xenbus_probe_node(bus, type, nodename);
72*4882a593Smuzhiyun 	kfree(nodename);
73*4882a593Smuzhiyun 	return err;
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun 
xenbus_uevent_frontend(struct device * _dev,struct kobj_uevent_env * env)76*4882a593Smuzhiyun static int xenbus_uevent_frontend(struct device *_dev,
77*4882a593Smuzhiyun 				  struct kobj_uevent_env *env)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun 	struct xenbus_device *dev = to_xenbus_device(_dev);
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	if (add_uevent_var(env, "MODALIAS=xen:%s", dev->devicetype))
82*4882a593Smuzhiyun 		return -ENOMEM;
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	return 0;
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 
backend_changed(struct xenbus_watch * watch,const char * path,const char * token)88*4882a593Smuzhiyun static void backend_changed(struct xenbus_watch *watch,
89*4882a593Smuzhiyun 			    const char *path, const char *token)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun 	xenbus_otherend_changed(watch, path, token, 1);
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun 
xenbus_frontend_delayed_resume(struct work_struct * w)94*4882a593Smuzhiyun static void xenbus_frontend_delayed_resume(struct work_struct *w)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	struct xenbus_device *xdev = container_of(w, struct xenbus_device, work);
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	xenbus_dev_resume(&xdev->dev);
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun 
xenbus_frontend_dev_resume(struct device * dev)101*4882a593Smuzhiyun static int xenbus_frontend_dev_resume(struct device *dev)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun 	/*
104*4882a593Smuzhiyun 	 * If xenstored is running in this domain, we cannot access the backend
105*4882a593Smuzhiyun 	 * state at the moment, so we need to defer xenbus_dev_resume
106*4882a593Smuzhiyun 	 */
107*4882a593Smuzhiyun 	if (xen_store_domain_type == XS_LOCAL) {
108*4882a593Smuzhiyun 		struct xenbus_device *xdev = to_xenbus_device(dev);
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 		schedule_work(&xdev->work);
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 		return 0;
113*4882a593Smuzhiyun 	}
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	return xenbus_dev_resume(dev);
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun 
xenbus_frontend_dev_probe(struct device * dev)118*4882a593Smuzhiyun static int xenbus_frontend_dev_probe(struct device *dev)
119*4882a593Smuzhiyun {
120*4882a593Smuzhiyun 	if (xen_store_domain_type == XS_LOCAL) {
121*4882a593Smuzhiyun 		struct xenbus_device *xdev = to_xenbus_device(dev);
122*4882a593Smuzhiyun 		INIT_WORK(&xdev->work, xenbus_frontend_delayed_resume);
123*4882a593Smuzhiyun 	}
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	return xenbus_dev_probe(dev);
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun 
xenbus_frontend_dev_shutdown(struct device * _dev)128*4882a593Smuzhiyun static void xenbus_frontend_dev_shutdown(struct device *_dev)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun 	struct xenbus_device *dev = to_xenbus_device(_dev);
131*4882a593Smuzhiyun 	unsigned long timeout = 5*HZ;
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	DPRINTK("%s", dev->nodename);
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	get_device(&dev->dev);
136*4882a593Smuzhiyun 	if (dev->state != XenbusStateConnected) {
137*4882a593Smuzhiyun 		pr_info("%s: %s: %s != Connected, skipping\n",
138*4882a593Smuzhiyun 			__func__, dev->nodename, xenbus_strstate(dev->state));
139*4882a593Smuzhiyun 		goto out;
140*4882a593Smuzhiyun 	}
141*4882a593Smuzhiyun 	xenbus_switch_state(dev, XenbusStateClosing);
142*4882a593Smuzhiyun 	timeout = wait_for_completion_timeout(&dev->down, timeout);
143*4882a593Smuzhiyun 	if (!timeout)
144*4882a593Smuzhiyun 		pr_info("%s: %s timeout closing device\n",
145*4882a593Smuzhiyun 			__func__, dev->nodename);
146*4882a593Smuzhiyun  out:
147*4882a593Smuzhiyun 	put_device(&dev->dev);
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun static const struct dev_pm_ops xenbus_pm_ops = {
151*4882a593Smuzhiyun 	.suspend	= xenbus_dev_suspend,
152*4882a593Smuzhiyun 	.resume		= xenbus_frontend_dev_resume,
153*4882a593Smuzhiyun 	.freeze		= xenbus_dev_suspend,
154*4882a593Smuzhiyun 	.thaw		= xenbus_dev_cancel,
155*4882a593Smuzhiyun 	.restore	= xenbus_dev_resume,
156*4882a593Smuzhiyun };
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun static struct xen_bus_type xenbus_frontend = {
159*4882a593Smuzhiyun 	.root = "device",
160*4882a593Smuzhiyun 	.levels = 2,		/* device/type/<id> */
161*4882a593Smuzhiyun 	.get_bus_id = frontend_bus_id,
162*4882a593Smuzhiyun 	.probe = xenbus_probe_frontend,
163*4882a593Smuzhiyun 	.otherend_changed = backend_changed,
164*4882a593Smuzhiyun 	.bus = {
165*4882a593Smuzhiyun 		.name		= "xen",
166*4882a593Smuzhiyun 		.match		= xenbus_match,
167*4882a593Smuzhiyun 		.uevent		= xenbus_uevent_frontend,
168*4882a593Smuzhiyun 		.probe		= xenbus_frontend_dev_probe,
169*4882a593Smuzhiyun 		.remove		= xenbus_dev_remove,
170*4882a593Smuzhiyun 		.shutdown	= xenbus_frontend_dev_shutdown,
171*4882a593Smuzhiyun 		.dev_groups	= xenbus_dev_groups,
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 		.pm		= &xenbus_pm_ops,
174*4882a593Smuzhiyun 	},
175*4882a593Smuzhiyun };
176*4882a593Smuzhiyun 
frontend_changed(struct xenbus_watch * watch,const char * path,const char * token)177*4882a593Smuzhiyun static void frontend_changed(struct xenbus_watch *watch,
178*4882a593Smuzhiyun 			     const char *path, const char *token)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun 	DPRINTK("");
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	xenbus_dev_changed(path, &xenbus_frontend);
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun /* We watch for devices appearing and vanishing. */
187*4882a593Smuzhiyun static struct xenbus_watch fe_watch = {
188*4882a593Smuzhiyun 	.node = "device",
189*4882a593Smuzhiyun 	.callback = frontend_changed,
190*4882a593Smuzhiyun };
191*4882a593Smuzhiyun 
read_backend_details(struct xenbus_device * xendev)192*4882a593Smuzhiyun static int read_backend_details(struct xenbus_device *xendev)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun 	return xenbus_read_otherend_details(xendev, "backend-id", "backend");
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun 
is_device_connecting(struct device * dev,void * data,bool ignore_nonessential)197*4882a593Smuzhiyun static int is_device_connecting(struct device *dev, void *data, bool ignore_nonessential)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun 	struct xenbus_device *xendev = to_xenbus_device(dev);
200*4882a593Smuzhiyun 	struct device_driver *drv = data;
201*4882a593Smuzhiyun 	struct xenbus_driver *xendrv;
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	/*
204*4882a593Smuzhiyun 	 * A device with no driver will never connect. We care only about
205*4882a593Smuzhiyun 	 * devices which should currently be in the process of connecting.
206*4882a593Smuzhiyun 	 */
207*4882a593Smuzhiyun 	if (!dev->driver)
208*4882a593Smuzhiyun 		return 0;
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	/* Is this search limited to a particular driver? */
211*4882a593Smuzhiyun 	if (drv && (dev->driver != drv))
212*4882a593Smuzhiyun 		return 0;
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 	if (ignore_nonessential) {
215*4882a593Smuzhiyun 		/* With older QEMU, for PVonHVM guests the guest config files
216*4882a593Smuzhiyun 		 * could contain: vfb = [ 'vnc=1, vnclisten=0.0.0.0']
217*4882a593Smuzhiyun 		 * which is nonsensical as there is no PV FB (there can be
218*4882a593Smuzhiyun 		 * a PVKB) running as HVM guest. */
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 		if ((strncmp(xendev->nodename, "device/vkbd", 11) == 0))
221*4882a593Smuzhiyun 			return 0;
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 		if ((strncmp(xendev->nodename, "device/vfb", 10) == 0))
224*4882a593Smuzhiyun 			return 0;
225*4882a593Smuzhiyun 	}
226*4882a593Smuzhiyun 	xendrv = to_xenbus_driver(dev->driver);
227*4882a593Smuzhiyun 	return (xendev->state < XenbusStateConnected ||
228*4882a593Smuzhiyun 		(xendev->state == XenbusStateConnected &&
229*4882a593Smuzhiyun 		 xendrv->is_ready && !xendrv->is_ready(xendev)));
230*4882a593Smuzhiyun }
essential_device_connecting(struct device * dev,void * data)231*4882a593Smuzhiyun static int essential_device_connecting(struct device *dev, void *data)
232*4882a593Smuzhiyun {
233*4882a593Smuzhiyun 	return is_device_connecting(dev, data, true /* ignore PV[KBB+FB] */);
234*4882a593Smuzhiyun }
non_essential_device_connecting(struct device * dev,void * data)235*4882a593Smuzhiyun static int non_essential_device_connecting(struct device *dev, void *data)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun 	return is_device_connecting(dev, data, false);
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun 
exists_essential_connecting_device(struct device_driver * drv)240*4882a593Smuzhiyun static int exists_essential_connecting_device(struct device_driver *drv)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun 	return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
243*4882a593Smuzhiyun 				essential_device_connecting);
244*4882a593Smuzhiyun }
exists_non_essential_connecting_device(struct device_driver * drv)245*4882a593Smuzhiyun static int exists_non_essential_connecting_device(struct device_driver *drv)
246*4882a593Smuzhiyun {
247*4882a593Smuzhiyun 	return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
248*4882a593Smuzhiyun 				non_essential_device_connecting);
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun 
print_device_status(struct device * dev,void * data)251*4882a593Smuzhiyun static int print_device_status(struct device *dev, void *data)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun 	struct xenbus_device *xendev = to_xenbus_device(dev);
254*4882a593Smuzhiyun 	struct device_driver *drv = data;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	/* Is this operation limited to a particular driver? */
257*4882a593Smuzhiyun 	if (drv && (dev->driver != drv))
258*4882a593Smuzhiyun 		return 0;
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	if (!dev->driver) {
261*4882a593Smuzhiyun 		/* Information only: is this too noisy? */
262*4882a593Smuzhiyun 		pr_info("Device with no driver: %s\n", xendev->nodename);
263*4882a593Smuzhiyun 	} else if (xendev->state < XenbusStateConnected) {
264*4882a593Smuzhiyun 		enum xenbus_state rstate = XenbusStateUnknown;
265*4882a593Smuzhiyun 		if (xendev->otherend)
266*4882a593Smuzhiyun 			rstate = xenbus_read_driver_state(xendev->otherend);
267*4882a593Smuzhiyun 		pr_warn("Timeout connecting to device: %s (local state %d, remote state %d)\n",
268*4882a593Smuzhiyun 			xendev->nodename, xendev->state, rstate);
269*4882a593Smuzhiyun 	}
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	return 0;
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun /* We only wait for device setup after most initcalls have run. */
275*4882a593Smuzhiyun static int ready_to_wait_for_devices;
276*4882a593Smuzhiyun 
wait_loop(unsigned long start,unsigned int max_delay,unsigned int * seconds_waited)277*4882a593Smuzhiyun static bool wait_loop(unsigned long start, unsigned int max_delay,
278*4882a593Smuzhiyun 		     unsigned int *seconds_waited)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun 	if (time_after(jiffies, start + (*seconds_waited+5)*HZ)) {
281*4882a593Smuzhiyun 		if (!*seconds_waited)
282*4882a593Smuzhiyun 			pr_warn("Waiting for devices to initialise: ");
283*4882a593Smuzhiyun 		*seconds_waited += 5;
284*4882a593Smuzhiyun 		pr_cont("%us...", max_delay - *seconds_waited);
285*4882a593Smuzhiyun 		if (*seconds_waited == max_delay) {
286*4882a593Smuzhiyun 			pr_cont("\n");
287*4882a593Smuzhiyun 			return true;
288*4882a593Smuzhiyun 		}
289*4882a593Smuzhiyun 	}
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	schedule_timeout_interruptible(HZ/10);
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	return false;
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun /*
296*4882a593Smuzhiyun  * On a 5-minute timeout, wait for all devices currently configured.  We need
297*4882a593Smuzhiyun  * to do this to guarantee that the filesystems and / or network devices
298*4882a593Smuzhiyun  * needed for boot are available, before we can allow the boot to proceed.
299*4882a593Smuzhiyun  *
300*4882a593Smuzhiyun  * This needs to be on a late_initcall, to happen after the frontend device
301*4882a593Smuzhiyun  * drivers have been initialised, but before the root fs is mounted.
302*4882a593Smuzhiyun  *
303*4882a593Smuzhiyun  * A possible improvement here would be to have the tools add a per-device
304*4882a593Smuzhiyun  * flag to the store entry, indicating whether it is needed at boot time.
305*4882a593Smuzhiyun  * This would allow people who knew what they were doing to accelerate their
306*4882a593Smuzhiyun  * boot slightly, but of course needs tools or manual intervention to set up
307*4882a593Smuzhiyun  * those flags correctly.
308*4882a593Smuzhiyun  */
wait_for_devices(struct xenbus_driver * xendrv)309*4882a593Smuzhiyun static void wait_for_devices(struct xenbus_driver *xendrv)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun 	unsigned long start = jiffies;
312*4882a593Smuzhiyun 	struct device_driver *drv = xendrv ? &xendrv->driver : NULL;
313*4882a593Smuzhiyun 	unsigned int seconds_waited = 0;
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 	if (!ready_to_wait_for_devices || !xen_domain())
316*4882a593Smuzhiyun 		return;
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	while (exists_non_essential_connecting_device(drv))
319*4882a593Smuzhiyun 		if (wait_loop(start, 30, &seconds_waited))
320*4882a593Smuzhiyun 			break;
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	/* Skips PVKB and PVFB check.*/
323*4882a593Smuzhiyun 	while (exists_essential_connecting_device(drv))
324*4882a593Smuzhiyun 		if (wait_loop(start, 270, &seconds_waited))
325*4882a593Smuzhiyun 			break;
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	if (seconds_waited)
328*4882a593Smuzhiyun 		printk("\n");
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
331*4882a593Smuzhiyun 			 print_device_status);
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun 
__xenbus_register_frontend(struct xenbus_driver * drv,struct module * owner,const char * mod_name)334*4882a593Smuzhiyun int __xenbus_register_frontend(struct xenbus_driver *drv, struct module *owner,
335*4882a593Smuzhiyun 			       const char *mod_name)
336*4882a593Smuzhiyun {
337*4882a593Smuzhiyun 	int ret;
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 	drv->read_otherend_details = read_backend_details;
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	ret = xenbus_register_driver_common(drv, &xenbus_frontend,
342*4882a593Smuzhiyun 					    owner, mod_name);
343*4882a593Smuzhiyun 	if (ret)
344*4882a593Smuzhiyun 		return ret;
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 	/* If this driver is loaded as a module wait for devices to attach. */
347*4882a593Smuzhiyun 	wait_for_devices(drv);
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	return 0;
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(__xenbus_register_frontend);
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun static DECLARE_WAIT_QUEUE_HEAD(backend_state_wq);
354*4882a593Smuzhiyun static int backend_state;
355*4882a593Smuzhiyun 
xenbus_reset_backend_state_changed(struct xenbus_watch * w,const char * path,const char * token)356*4882a593Smuzhiyun static void xenbus_reset_backend_state_changed(struct xenbus_watch *w,
357*4882a593Smuzhiyun 					const char *path, const char *token)
358*4882a593Smuzhiyun {
359*4882a593Smuzhiyun 	if (xenbus_scanf(XBT_NIL, path, "", "%i",
360*4882a593Smuzhiyun 			 &backend_state) != 1)
361*4882a593Smuzhiyun 		backend_state = XenbusStateUnknown;
362*4882a593Smuzhiyun 	printk(KERN_DEBUG "XENBUS: backend %s %s\n",
363*4882a593Smuzhiyun 	       path, xenbus_strstate(backend_state));
364*4882a593Smuzhiyun 	wake_up(&backend_state_wq);
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun 
xenbus_reset_wait_for_backend(char * be,int expected)367*4882a593Smuzhiyun static void xenbus_reset_wait_for_backend(char *be, int expected)
368*4882a593Smuzhiyun {
369*4882a593Smuzhiyun 	long timeout;
370*4882a593Smuzhiyun 	timeout = wait_event_interruptible_timeout(backend_state_wq,
371*4882a593Smuzhiyun 			backend_state == expected, 5 * HZ);
372*4882a593Smuzhiyun 	if (timeout <= 0)
373*4882a593Smuzhiyun 		pr_info("backend %s timed out\n", be);
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun /*
377*4882a593Smuzhiyun  * Reset frontend if it is in Connected or Closed state.
378*4882a593Smuzhiyun  * Wait for backend to catch up.
379*4882a593Smuzhiyun  * State Connected happens during kdump, Closed after kexec.
380*4882a593Smuzhiyun  */
xenbus_reset_frontend(char * fe,char * be,int be_state)381*4882a593Smuzhiyun static void xenbus_reset_frontend(char *fe, char *be, int be_state)
382*4882a593Smuzhiyun {
383*4882a593Smuzhiyun 	struct xenbus_watch be_watch;
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 	printk(KERN_DEBUG "XENBUS: backend %s %s\n",
386*4882a593Smuzhiyun 			be, xenbus_strstate(be_state));
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	memset(&be_watch, 0, sizeof(be_watch));
389*4882a593Smuzhiyun 	be_watch.node = kasprintf(GFP_NOIO | __GFP_HIGH, "%s/state", be);
390*4882a593Smuzhiyun 	if (!be_watch.node)
391*4882a593Smuzhiyun 		return;
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun 	be_watch.callback = xenbus_reset_backend_state_changed;
394*4882a593Smuzhiyun 	backend_state = XenbusStateUnknown;
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	pr_info("triggering reconnect on %s\n", be);
397*4882a593Smuzhiyun 	register_xenbus_watch(&be_watch);
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun 	/* fall through to forward backend to state XenbusStateInitialising */
400*4882a593Smuzhiyun 	switch (be_state) {
401*4882a593Smuzhiyun 	case XenbusStateConnected:
402*4882a593Smuzhiyun 		xenbus_printf(XBT_NIL, fe, "state", "%d", XenbusStateClosing);
403*4882a593Smuzhiyun 		xenbus_reset_wait_for_backend(be, XenbusStateClosing);
404*4882a593Smuzhiyun 		fallthrough;
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun 	case XenbusStateClosing:
407*4882a593Smuzhiyun 		xenbus_printf(XBT_NIL, fe, "state", "%d", XenbusStateClosed);
408*4882a593Smuzhiyun 		xenbus_reset_wait_for_backend(be, XenbusStateClosed);
409*4882a593Smuzhiyun 		fallthrough;
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	case XenbusStateClosed:
412*4882a593Smuzhiyun 		xenbus_printf(XBT_NIL, fe, "state", "%d", XenbusStateInitialising);
413*4882a593Smuzhiyun 		xenbus_reset_wait_for_backend(be, XenbusStateInitWait);
414*4882a593Smuzhiyun 	}
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 	unregister_xenbus_watch(&be_watch);
417*4882a593Smuzhiyun 	pr_info("reconnect done on %s\n", be);
418*4882a593Smuzhiyun 	kfree(be_watch.node);
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun 
xenbus_check_frontend(char * class,char * dev)421*4882a593Smuzhiyun static void xenbus_check_frontend(char *class, char *dev)
422*4882a593Smuzhiyun {
423*4882a593Smuzhiyun 	int be_state, fe_state, err;
424*4882a593Smuzhiyun 	char *backend, *frontend;
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 	frontend = kasprintf(GFP_NOIO | __GFP_HIGH, "device/%s/%s", class, dev);
427*4882a593Smuzhiyun 	if (!frontend)
428*4882a593Smuzhiyun 		return;
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 	err = xenbus_scanf(XBT_NIL, frontend, "state", "%i", &fe_state);
431*4882a593Smuzhiyun 	if (err != 1)
432*4882a593Smuzhiyun 		goto out;
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun 	switch (fe_state) {
435*4882a593Smuzhiyun 	case XenbusStateConnected:
436*4882a593Smuzhiyun 	case XenbusStateClosed:
437*4882a593Smuzhiyun 		printk(KERN_DEBUG "XENBUS: frontend %s %s\n",
438*4882a593Smuzhiyun 				frontend, xenbus_strstate(fe_state));
439*4882a593Smuzhiyun 		backend = xenbus_read(XBT_NIL, frontend, "backend", NULL);
440*4882a593Smuzhiyun 		if (!backend || IS_ERR(backend))
441*4882a593Smuzhiyun 			goto out;
442*4882a593Smuzhiyun 		err = xenbus_scanf(XBT_NIL, backend, "state", "%i", &be_state);
443*4882a593Smuzhiyun 		if (err == 1)
444*4882a593Smuzhiyun 			xenbus_reset_frontend(frontend, backend, be_state);
445*4882a593Smuzhiyun 		kfree(backend);
446*4882a593Smuzhiyun 		break;
447*4882a593Smuzhiyun 	default:
448*4882a593Smuzhiyun 		break;
449*4882a593Smuzhiyun 	}
450*4882a593Smuzhiyun out:
451*4882a593Smuzhiyun 	kfree(frontend);
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun 
xenbus_reset_state(void)454*4882a593Smuzhiyun static void xenbus_reset_state(void)
455*4882a593Smuzhiyun {
456*4882a593Smuzhiyun 	char **devclass, **dev;
457*4882a593Smuzhiyun 	int devclass_n, dev_n;
458*4882a593Smuzhiyun 	int i, j;
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 	devclass = xenbus_directory(XBT_NIL, "device", "", &devclass_n);
461*4882a593Smuzhiyun 	if (IS_ERR(devclass))
462*4882a593Smuzhiyun 		return;
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 	for (i = 0; i < devclass_n; i++) {
465*4882a593Smuzhiyun 		dev = xenbus_directory(XBT_NIL, "device", devclass[i], &dev_n);
466*4882a593Smuzhiyun 		if (IS_ERR(dev))
467*4882a593Smuzhiyun 			continue;
468*4882a593Smuzhiyun 		for (j = 0; j < dev_n; j++)
469*4882a593Smuzhiyun 			xenbus_check_frontend(devclass[i], dev[j]);
470*4882a593Smuzhiyun 		kfree(dev);
471*4882a593Smuzhiyun 	}
472*4882a593Smuzhiyun 	kfree(devclass);
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun 
frontend_probe_and_watch(struct notifier_block * notifier,unsigned long event,void * data)475*4882a593Smuzhiyun static int frontend_probe_and_watch(struct notifier_block *notifier,
476*4882a593Smuzhiyun 				   unsigned long event,
477*4882a593Smuzhiyun 				   void *data)
478*4882a593Smuzhiyun {
479*4882a593Smuzhiyun 	/* reset devices in Connected or Closed state */
480*4882a593Smuzhiyun 	if (xen_hvm_domain())
481*4882a593Smuzhiyun 		xenbus_reset_state();
482*4882a593Smuzhiyun 	/* Enumerate devices in xenstore and watch for changes. */
483*4882a593Smuzhiyun 	xenbus_probe_devices(&xenbus_frontend);
484*4882a593Smuzhiyun 	register_xenbus_watch(&fe_watch);
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun 	return NOTIFY_DONE;
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun 
489*4882a593Smuzhiyun 
xenbus_probe_frontend_init(void)490*4882a593Smuzhiyun static int __init xenbus_probe_frontend_init(void)
491*4882a593Smuzhiyun {
492*4882a593Smuzhiyun 	static struct notifier_block xenstore_notifier = {
493*4882a593Smuzhiyun 		.notifier_call = frontend_probe_and_watch
494*4882a593Smuzhiyun 	};
495*4882a593Smuzhiyun 	int err;
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun 	DPRINTK("");
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	/* Register ourselves with the kernel bus subsystem */
500*4882a593Smuzhiyun 	err = bus_register(&xenbus_frontend.bus);
501*4882a593Smuzhiyun 	if (err)
502*4882a593Smuzhiyun 		return err;
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun 	register_xenstore_notifier(&xenstore_notifier);
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun 	return 0;
507*4882a593Smuzhiyun }
508*4882a593Smuzhiyun subsys_initcall(xenbus_probe_frontend_init);
509*4882a593Smuzhiyun 
510*4882a593Smuzhiyun #ifndef MODULE
boot_wait_for_devices(void)511*4882a593Smuzhiyun static int __init boot_wait_for_devices(void)
512*4882a593Smuzhiyun {
513*4882a593Smuzhiyun 	if (!xen_has_pv_devices())
514*4882a593Smuzhiyun 		return -ENODEV;
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	ready_to_wait_for_devices = 1;
517*4882a593Smuzhiyun 	wait_for_devices(NULL);
518*4882a593Smuzhiyun 	return 0;
519*4882a593Smuzhiyun }
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun late_initcall(boot_wait_for_devices);
522*4882a593Smuzhiyun #endif
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun MODULE_LICENSE("GPL");
525