blob: ed2ba474a5602158c8d1061207438430f42417c3 [file] [log] [blame]
Ian Campbell2de06cc2009-02-09 12:05:51 -08001#define DPRINTK(fmt, args...) \
2 pr_debug("xenbus_probe (%s:%d) " fmt ".\n", \
3 __func__, __LINE__, ##args)
4
5#include <linux/kernel.h>
6#include <linux/err.h>
7#include <linux/string.h>
8#include <linux/ctype.h>
9#include <linux/fcntl.h>
10#include <linux/mm.h>
11#include <linux/proc_fs.h>
12#include <linux/notifier.h>
13#include <linux/kthread.h>
14#include <linux/mutex.h>
15#include <linux/io.h>
16
17#include <asm/page.h>
18#include <asm/pgtable.h>
19#include <asm/xen/hypervisor.h>
20#include <xen/xenbus.h>
21#include <xen/events.h>
22#include <xen/page.h>
23
24#include <xen/platform_pci.h>
25
26#include "xenbus_comms.h"
27#include "xenbus_probe.h"
28
29
30/* device/<type>/<id> => <type>-<id> */
31static int frontend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename)
32{
33 nodename = strchr(nodename, '/');
34 if (!nodename || strlen(nodename + 1) >= XEN_BUS_ID_SIZE) {
35 printk(KERN_WARNING "XENBUS: bad frontend %s\n", nodename);
36 return -EINVAL;
37 }
38
39 strlcpy(bus_id, nodename + 1, XEN_BUS_ID_SIZE);
40 if (!strchr(bus_id, '/')) {
41 printk(KERN_WARNING "XENBUS: bus_id %s no slash\n", bus_id);
42 return -EINVAL;
43 }
44 *strchr(bus_id, '/') = '-';
45 return 0;
46}
47
48/* device/<typename>/<name> */
Ian Campbell6bac7f92010-12-10 14:39:15 +000049static int xenbus_probe_frontend(struct xen_bus_type *bus, const char *type,
50 const char *name)
Ian Campbell2de06cc2009-02-09 12:05:51 -080051{
52 char *nodename;
53 int err;
54
55 nodename = kasprintf(GFP_KERNEL, "%s/%s/%s", bus->root, type, name);
56 if (!nodename)
57 return -ENOMEM;
58
59 DPRINTK("%s", nodename);
60
61 err = xenbus_probe_node(bus, type, nodename);
62 kfree(nodename);
63 return err;
64}
65
Ian Campbell6bac7f92010-12-10 14:39:15 +000066static int xenbus_uevent_frontend(struct device *_dev,
67 struct kobj_uevent_env *env)
Ian Campbelldf660252009-02-09 12:05:51 -080068{
69 struct xenbus_device *dev = to_xenbus_device(_dev);
70
71 if (add_uevent_var(env, "MODALIAS=xen:%s", dev->devicetype))
72 return -ENOMEM;
73
74 return 0;
75}
76
77
Ian Campbell2de06cc2009-02-09 12:05:51 -080078static void backend_changed(struct xenbus_watch *watch,
79 const char **vec, unsigned int len)
80{
81 xenbus_otherend_changed(watch, vec, len, 1);
82}
83
Kazuhiro SUZUKIc7853ae2011-02-18 14:43:07 -080084static const struct dev_pm_ops xenbus_pm_ops = {
Shriram Rajagopalanb3e96c02011-02-22 14:59:06 -080085 .suspend = xenbus_dev_suspend,
86 .resume = xenbus_dev_resume,
87 .freeze = xenbus_dev_suspend,
88 .thaw = xenbus_dev_cancel,
89 .restore = xenbus_dev_resume,
Kazuhiro SUZUKIc7853ae2011-02-18 14:43:07 -080090};
91
Ian Campbell2de06cc2009-02-09 12:05:51 -080092static struct xen_bus_type xenbus_frontend = {
93 .root = "device",
Ian Campbell6bac7f92010-12-10 14:39:15 +000094 .levels = 2, /* device/type/<id> */
Ian Campbell2de06cc2009-02-09 12:05:51 -080095 .get_bus_id = frontend_bus_id,
96 .probe = xenbus_probe_frontend,
97 .otherend_changed = backend_changed,
98 .bus = {
Ian Campbell6bac7f92010-12-10 14:39:15 +000099 .name = "xen",
100 .match = xenbus_match,
101 .uevent = xenbus_uevent_frontend,
102 .probe = xenbus_dev_probe,
103 .remove = xenbus_dev_remove,
104 .shutdown = xenbus_dev_shutdown,
Bastian Blankcc85e932011-06-29 14:39:26 +0200105 .dev_attrs = xenbus_dev_attrs,
Ian Campbell2de06cc2009-02-09 12:05:51 -0800106
Kazuhiro SUZUKIc7853ae2011-02-18 14:43:07 -0800107 .pm = &xenbus_pm_ops,
Ian Campbell2de06cc2009-02-09 12:05:51 -0800108 },
109};
110
111static void frontend_changed(struct xenbus_watch *watch,
112 const char **vec, unsigned int len)
113{
114 DPRINTK("");
115
116 xenbus_dev_changed(vec[XS_WATCH_PATH], &xenbus_frontend);
117}
118
119
120/* We watch for devices appearing and vanishing. */
121static struct xenbus_watch fe_watch = {
122 .node = "device",
123 .callback = frontend_changed,
124};
125
126static int read_backend_details(struct xenbus_device *xendev)
127{
128 return xenbus_read_otherend_details(xendev, "backend-id", "backend");
129}
130
131static int is_device_connecting(struct device *dev, void *data)
132{
133 struct xenbus_device *xendev = to_xenbus_device(dev);
134 struct device_driver *drv = data;
135 struct xenbus_driver *xendrv;
136
137 /*
138 * A device with no driver will never connect. We care only about
139 * devices which should currently be in the process of connecting.
140 */
141 if (!dev->driver)
142 return 0;
143
144 /* Is this search limited to a particular driver? */
145 if (drv && (dev->driver != drv))
146 return 0;
147
148 xendrv = to_xenbus_driver(dev->driver);
149 return (xendev->state < XenbusStateConnected ||
150 (xendev->state == XenbusStateConnected &&
151 xendrv->is_ready && !xendrv->is_ready(xendev)));
152}
153
154static int exists_connecting_device(struct device_driver *drv)
155{
156 return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
157 is_device_connecting);
158}
159
160static int print_device_status(struct device *dev, void *data)
161{
162 struct xenbus_device *xendev = to_xenbus_device(dev);
163 struct device_driver *drv = data;
164
165 /* Is this operation limited to a particular driver? */
166 if (drv && (dev->driver != drv))
167 return 0;
168
169 if (!dev->driver) {
170 /* Information only: is this too noisy? */
171 printk(KERN_INFO "XENBUS: Device with no driver: %s\n",
172 xendev->nodename);
173 } else if (xendev->state < XenbusStateConnected) {
174 enum xenbus_state rstate = XenbusStateUnknown;
175 if (xendev->otherend)
176 rstate = xenbus_read_driver_state(xendev->otherend);
177 printk(KERN_WARNING "XENBUS: Timeout connecting "
178 "to device: %s (local state %d, remote state %d)\n",
179 xendev->nodename, xendev->state, rstate);
180 }
181
182 return 0;
183}
184
185/* We only wait for device setup after most initcalls have run. */
186static int ready_to_wait_for_devices;
187
188/*
189 * On a 5-minute timeout, wait for all devices currently configured. We need
190 * to do this to guarantee that the filesystems and / or network devices
191 * needed for boot are available, before we can allow the boot to proceed.
192 *
193 * This needs to be on a late_initcall, to happen after the frontend device
194 * drivers have been initialised, but before the root fs is mounted.
195 *
196 * A possible improvement here would be to have the tools add a per-device
197 * flag to the store entry, indicating whether it is needed at boot time.
198 * This would allow people who knew what they were doing to accelerate their
199 * boot slightly, but of course needs tools or manual intervention to set up
200 * those flags correctly.
201 */
202static void wait_for_devices(struct xenbus_driver *xendrv)
203{
204 unsigned long start = jiffies;
205 struct device_driver *drv = xendrv ? &xendrv->driver : NULL;
206 unsigned int seconds_waited = 0;
207
208 if (!ready_to_wait_for_devices || !xen_domain())
209 return;
210
211 while (exists_connecting_device(drv)) {
212 if (time_after(jiffies, start + (seconds_waited+5)*HZ)) {
213 if (!seconds_waited)
214 printk(KERN_WARNING "XENBUS: Waiting for "
215 "devices to initialise: ");
216 seconds_waited += 5;
217 printk("%us...", 300 - seconds_waited);
218 if (seconds_waited == 300)
219 break;
220 }
221
222 schedule_timeout_interruptible(HZ/10);
223 }
224
225 if (seconds_waited)
226 printk("\n");
227
228 bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
229 print_device_status);
230}
231
232int __xenbus_register_frontend(struct xenbus_driver *drv,
233 struct module *owner, const char *mod_name)
234{
235 int ret;
236
237 drv->read_otherend_details = read_backend_details;
238
239 ret = xenbus_register_driver_common(drv, &xenbus_frontend,
240 owner, mod_name);
241 if (ret)
242 return ret;
243
244 /* If this driver is loaded as a module wait for devices to attach. */
245 wait_for_devices(drv);
246
247 return 0;
248}
249EXPORT_SYMBOL_GPL(__xenbus_register_frontend);
250
Ian Campbelldf660252009-02-09 12:05:51 -0800251static int frontend_probe_and_watch(struct notifier_block *notifier,
252 unsigned long event,
253 void *data)
254{
255 /* Enumerate devices in xenstore and watch for changes. */
256 xenbus_probe_devices(&xenbus_frontend);
Ian Campbelldf660252009-02-09 12:05:51 -0800257 register_xenbus_watch(&fe_watch);
Jeremy Fitzhardinge0ff4fdf2010-03-29 14:38:54 -0700258
Ian Campbelldf660252009-02-09 12:05:51 -0800259 return NOTIFY_DONE;
260}
261
262
Ian Campbell2de06cc2009-02-09 12:05:51 -0800263static int __init xenbus_probe_frontend_init(void)
264{
Ian Campbelldf660252009-02-09 12:05:51 -0800265 static struct notifier_block xenstore_notifier = {
266 .notifier_call = frontend_probe_and_watch
267 };
Ian Campbell2de06cc2009-02-09 12:05:51 -0800268 int err;
269
270 DPRINTK("");
271
272 /* Register ourselves with the kernel bus subsystem */
273 err = bus_register(&xenbus_frontend.bus);
Jeremy Fitzhardinge0ff4fdf2010-03-29 14:38:54 -0700274 if (err)
Ian Campbell2de06cc2009-02-09 12:05:51 -0800275 return err;
Ian Campbell2de06cc2009-02-09 12:05:51 -0800276
Ian Campbelldf660252009-02-09 12:05:51 -0800277 register_xenstore_notifier(&xenstore_notifier);
Ian Campbell2de06cc2009-02-09 12:05:51 -0800278
279 return 0;
280}
Jeremy Fitzhardinge806f5462009-03-04 22:31:45 -0800281subsys_initcall(xenbus_probe_frontend_init);
Ian Campbell2de06cc2009-02-09 12:05:51 -0800282
283#ifndef MODULE
284static int __init boot_wait_for_devices(void)
285{
286 if (xen_hvm_domain() && !xen_platform_pci_unplug)
287 return -ENODEV;
288
289 ready_to_wait_for_devices = 1;
290 wait_for_devices(NULL);
291 return 0;
292}
293
294late_initcall(boot_wait_for_devices);
295#endif
Jeremy Fitzhardinge1b31a142009-03-27 16:29:44 -0700296
297MODULE_LICENSE("GPL");