xenbus_probe.c revision 1.1 1 /******************************************************************************
2 * Talks to Xen Store to figure out what devices we have.
3 *
4 * Copyright (C) 2005 Rusty Russell, IBM Corporation
5 * Copyright (C) 2005 Mike Wray, Hewlett-Packard
6 * Copyright (C) 2005 XenSource Ltd
7 *
8 * This file may be distributed separately from the Linux kernel, or
9 * incorporated into other software packages, subject to the following license:
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this source file (the "Software"), to deal in the Software without
13 * restriction, including without limitation the rights to use, copy, modify,
14 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
15 * and to permit persons to whom the Software is furnished to do so, subject to
16 * the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
27 * IN THE SOFTWARE.
28 */
29
30 #if 0
31 #define DPRINTK(fmt, args...) \
32 printk("xenbus_probe (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
33 #else
34 #define DPRINTK(fmt, args...) ((void)0)
35 #endif
36
37 #include <linux/kernel.h>
38 #include <linux/err.h>
39 #include <linux/string.h>
40 #include <linux/ctype.h>
41 #include <linux/fcntl.h>
42 #include <linux/mm.h>
43 #include <linux/notifier.h>
44 #include <linux/kthread.h>
45
46 #include <asm/io.h>
47 #include <asm/page.h>
48 #include <asm/pgtable.h>
49 #include <asm/hypervisor.h>
50 #include <asm-xen/xenbus.h>
51 #include <asm-xen/xen_proc.h>
52 #include <asm-xen/balloon.h>
53 #include <asm-xen/evtchn.h>
54 #include <asm-xen/linux-public/evtchn.h>
55
56 #include "xenbus_comms.h"
57
58 extern struct semaphore xenwatch_mutex;
59
60 #define streq(a, b) (strcmp((a), (b)) == 0)
61
62 static char *kasprintf(const char *fmt, ...);
63
64 static struct notifier_block *xenstore_chain;
65
66 /* If something in array of ids matches this device, return it. */
67 static const struct xenbus_device_id *
68 match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev)
69 {
70 for (; !streq(arr->devicetype, ""); arr++) {
71 if (streq(arr->devicetype, dev->devicetype))
72 return arr;
73 }
74 return NULL;
75 }
76
77 static int xenbus_match(struct device *_dev, struct device_driver *_drv)
78 {
79 struct xenbus_driver *drv = to_xenbus_driver(_drv);
80
81 if (!drv->ids)
82 return 0;
83
84 return match_device(drv->ids, to_xenbus_device(_dev)) != NULL;
85 }
86
87 struct xen_bus_type
88 {
89 char *root;
90 unsigned int levels;
91 int (*get_bus_id)(char bus_id[BUS_ID_SIZE], const char *nodename);
92 int (*probe)(const char *type, const char *dir);
93 struct bus_type bus;
94 struct device dev;
95 };
96
97
98 /* device/<type>/<id> => <type>-<id> */
99 static int frontend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename)
100 {
101 nodename = strchr(nodename, '/');
102 if (!nodename || strlen(nodename + 1) >= BUS_ID_SIZE) {
103 printk(KERN_WARNING "XENBUS: bad frontend %s\n", nodename);
104 return -EINVAL;
105 }
106
107 strlcpy(bus_id, nodename + 1, BUS_ID_SIZE);
108 if (!strchr(bus_id, '/')) {
109 printk(KERN_WARNING "XENBUS: bus_id %s no slash\n", bus_id);
110 return -EINVAL;
111 }
112 *strchr(bus_id, '/') = '-';
113 return 0;
114 }
115
116
117 static int read_otherend_details(struct xenbus_device *xendev,
118 char *id_node, char *path_node)
119 {
120 int err = xenbus_gather(NULL, xendev->nodename,
121 id_node, "%i", &xendev->otherend_id,
122 path_node, NULL, &xendev->otherend,
123 NULL);
124 if (err) {
125 xenbus_dev_fatal(xendev, err,
126 "reading other end details from %s",
127 xendev->nodename);
128 return err;
129 }
130 if (strlen(xendev->otherend) == 0 ||
131 !xenbus_exists(NULL, xendev->otherend, "")) {
132 xenbus_dev_fatal(xendev, -ENOENT, "missing other end from %s",
133 xendev->nodename);
134 kfree(xendev->otherend);
135 xendev->otherend = NULL;
136 return -ENOENT;
137 }
138
139 return 0;
140 }
141
142
143 static int read_backend_details(struct xenbus_device *xendev)
144 {
145 return read_otherend_details(xendev, "backend-id", "backend");
146 }
147
148
149 static int read_frontend_details(struct xenbus_device *xendev)
150 {
151 return read_otherend_details(xendev, "frontend-id", "frontend");
152 }
153
154
155 static void free_otherend_details(struct xenbus_device *dev)
156 {
157 kfree(dev->otherend);
158 dev->otherend = NULL;
159 }
160
161
162 static void free_otherend_watch(struct xenbus_device *dev)
163 {
164 if (dev->otherend_watch.node) {
165 unregister_xenbus_watch(&dev->otherend_watch);
166 kfree(dev->otherend_watch.node);
167 dev->otherend_watch.node = NULL;
168 }
169 }
170
171
172 /* Bus type for frontend drivers. */
173 static int xenbus_probe_frontend(const char *type, const char *name);
174 static struct xen_bus_type xenbus_frontend = {
175 .root = "device",
176 .levels = 2, /* device/type/<id> */
177 .get_bus_id = frontend_bus_id,
178 .probe = xenbus_probe_frontend,
179 .bus = {
180 .name = "xen",
181 .match = xenbus_match,
182 },
183 .dev = {
184 .bus_id = "xen",
185 },
186 };
187
188 /* backend/<type>/<fe-uuid>/<id> => <type>-<fe-domid>-<id> */
189 static int backend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename)
190 {
191 int domid, err;
192 const char *devid, *type, *frontend;
193 unsigned int typelen;
194
195 type = strchr(nodename, '/');
196 if (!type)
197 return -EINVAL;
198 type++;
199 typelen = strcspn(type, "/");
200 if (!typelen || type[typelen] != '/')
201 return -EINVAL;
202
203 devid = strrchr(nodename, '/') + 1;
204
205 err = xenbus_gather(NULL, nodename, "frontend-id", "%i", &domid,
206 "frontend", NULL, &frontend,
207 NULL);
208 if (err)
209 return err;
210 if (strlen(frontend) == 0)
211 err = -ERANGE;
212
213 if (!err && !xenbus_exists(NULL, frontend, ""))
214 err = -ENOENT;
215
216 if (err) {
217 kfree(frontend);
218 return err;
219 }
220
221 if (snprintf(bus_id, BUS_ID_SIZE,
222 "%.*s-%i-%s", typelen, type, domid, devid) >= BUS_ID_SIZE)
223 return -ENOSPC;
224 return 0;
225 }
226
227 static int xenbus_hotplug_backend(struct device *dev, char **envp,
228 int num_envp, char *buffer, int buffer_size)
229 {
230 struct xenbus_device *xdev;
231 struct xenbus_driver *drv = NULL;
232 int i = 0;
233 int length = 0;
234 char *basepath_end;
235 char *frontend_id;
236
237 DPRINTK("");
238
239 if (dev == NULL)
240 return -ENODEV;
241
242 xdev = to_xenbus_device(dev);
243 if (xdev == NULL)
244 return -ENODEV;
245
246 if (dev->driver)
247 drv = to_xenbus_driver(dev->driver);
248
249 /* stuff we want to pass to /sbin/hotplug */
250 add_hotplug_env_var(envp, num_envp, &i,
251 buffer, buffer_size, &length,
252 "XENBUS_TYPE=%s", xdev->devicetype);
253
254 add_hotplug_env_var(envp, num_envp, &i,
255 buffer, buffer_size, &length,
256 "XENBUS_PATH=%s", xdev->nodename);
257
258 add_hotplug_env_var(envp, num_envp, &i,
259 buffer, buffer_size, &length,
260 "XENBUS_BASE_PATH=%s", xdev->nodename);
261
262 basepath_end = strrchr(envp[i - 1], '/');
263 length -= strlen(basepath_end);
264 *basepath_end = '\0';
265 basepath_end = strrchr(envp[i - 1], '/');
266 length -= strlen(basepath_end);
267 *basepath_end = '\0';
268
269 basepath_end++;
270 frontend_id = kmalloc(strlen(basepath_end) + 1, GFP_KERNEL);
271 strcpy(frontend_id, basepath_end);
272 add_hotplug_env_var(envp, num_envp, &i,
273 buffer, buffer_size, &length,
274 "XENBUS_FRONTEND_ID=%s", frontend_id);
275 kfree(frontend_id);
276
277 /* terminate, set to next free slot, shrink available space */
278 envp[i] = NULL;
279 envp = &envp[i];
280 num_envp -= i;
281 buffer = &buffer[length];
282 buffer_size -= length;
283
284 if (drv && drv->hotplug)
285 return drv->hotplug(xdev, envp, num_envp, buffer,
286 buffer_size);
287
288 return 0;
289 }
290
291 static int xenbus_probe_backend(const char *type, const char *domid);
292 static struct xen_bus_type xenbus_backend = {
293 .root = "backend",
294 .levels = 3, /* backend/type/<frontend>/<id> */
295 .get_bus_id = backend_bus_id,
296 .probe = xenbus_probe_backend,
297 .bus = {
298 .name = "xen-backend",
299 .match = xenbus_match,
300 .hotplug = xenbus_hotplug_backend,
301 },
302 .dev = {
303 .bus_id = "xen-backend",
304 },
305 };
306
307
308 static void otherend_changed(struct xenbus_watch *watch,
309 const char **vec, unsigned int len)
310 {
311 struct xenbus_device *dev =
312 container_of(watch, struct xenbus_device, otherend_watch);
313 struct xenbus_driver *drv = to_xenbus_driver(dev->dev.driver);
314 XenbusState state;
315
316 /* Protect us against watches firing on old details when the otherend
317 details change, say immediately after a resume. */
318 if (!dev->otherend ||
319 strncmp(dev->otherend, vec[XS_WATCH_PATH],
320 strlen(dev->otherend))) {
321 DPRINTK("Ignoring watch at %s", vec[XS_WATCH_PATH]);
322 return;
323 }
324
325 state = xenbus_read_driver_state(dev->otherend);
326
327 DPRINTK("state is %d, %s, %s",
328 state, dev->otherend_watch.node, vec[XS_WATCH_PATH]);
329 if (drv->otherend_changed)
330 drv->otherend_changed(dev, state);
331 }
332
333
334 static int talk_to_otherend(struct xenbus_device *dev)
335 {
336 struct xenbus_driver *drv = to_xenbus_driver(dev->dev.driver);
337 int err;
338
339 free_otherend_watch(dev);
340 free_otherend_details(dev);
341
342 err = drv->read_otherend_details(dev);
343 if (err)
344 return err;
345
346 return xenbus_watch_path2(dev, dev->otherend, "state",
347 &dev->otherend_watch, otherend_changed);
348 }
349
350
351 static int xenbus_dev_probe(struct device *_dev)
352 {
353 struct xenbus_device *dev = to_xenbus_device(_dev);
354 struct xenbus_driver *drv = to_xenbus_driver(_dev->driver);
355 const struct xenbus_device_id *id;
356 int err;
357
358 DPRINTK("");
359
360 err = talk_to_otherend(dev);
361 if (err) {
362 printk(KERN_WARNING
363 "xenbus_probe: talk_to_otherend on %s failed.\n",
364 dev->nodename);
365 return err;
366 }
367
368 if (!drv->probe) {
369 err = -ENODEV;
370 goto fail;
371 }
372
373 id = match_device(drv->ids, dev);
374 if (!id) {
375 err = -ENODEV;
376 goto fail;
377 }
378
379 err = drv->probe(dev, id);
380 if (err)
381 goto fail;
382
383 return 0;
384 fail:
385 xenbus_dev_error(dev, err, "xenbus_dev_probe on %s", dev->nodename);
386 xenbus_switch_state(dev, NULL, XenbusStateClosed);
387 return -ENODEV;
388
389 }
390
391 static int xenbus_dev_remove(struct device *_dev)
392 {
393 struct xenbus_device *dev = to_xenbus_device(_dev);
394 struct xenbus_driver *drv = to_xenbus_driver(_dev->driver);
395
396 DPRINTK("");
397
398 free_otherend_watch(dev);
399 free_otherend_details(dev);
400
401 if (drv->remove)
402 drv->remove(dev);
403
404 xenbus_switch_state(dev, NULL, XenbusStateClosed);
405 return 0;
406 }
407
408 static int xenbus_register_driver_common(struct xenbus_driver *drv,
409 struct xen_bus_type *bus)
410 {
411 int ret;
412
413 drv->driver.name = drv->name;
414 drv->driver.bus = &bus->bus;
415 drv->driver.owner = drv->owner;
416 drv->driver.probe = xenbus_dev_probe;
417 drv->driver.remove = xenbus_dev_remove;
418
419 down(&xenwatch_mutex);
420 ret = driver_register(&drv->driver);
421 up(&xenwatch_mutex);
422 return ret;
423 }
424
425 int xenbus_register_frontend(struct xenbus_driver *drv)
426 {
427 drv->read_otherend_details = read_backend_details;
428
429 return xenbus_register_driver_common(drv, &xenbus_frontend);
430 }
431 EXPORT_SYMBOL(xenbus_register_frontend);
432
433 int xenbus_register_backend(struct xenbus_driver *drv)
434 {
435 drv->read_otherend_details = read_frontend_details;
436
437 return xenbus_register_driver_common(drv, &xenbus_backend);
438 }
439 EXPORT_SYMBOL(xenbus_register_backend);
440
441 void xenbus_unregister_driver(struct xenbus_driver *drv)
442 {
443 driver_unregister(&drv->driver);
444 }
445 EXPORT_SYMBOL(xenbus_unregister_driver);
446
447 struct xb_find_info
448 {
449 struct xenbus_device *dev;
450 const char *nodename;
451 };
452
453 static int cmp_dev(struct device *dev, void *data)
454 {
455 struct xenbus_device *xendev = to_xenbus_device(dev);
456 struct xb_find_info *info = data;
457
458 if (streq(xendev->nodename, info->nodename)) {
459 info->dev = xendev;
460 get_device(dev);
461 return 1;
462 }
463 return 0;
464 }
465
466 struct xenbus_device *xenbus_device_find(const char *nodename,
467 struct bus_type *bus)
468 {
469 struct xb_find_info info = { .dev = NULL, .nodename = nodename };
470
471 bus_for_each_dev(bus, NULL, &info, cmp_dev);
472 return info.dev;
473 }
474
475 static int cleanup_dev(struct device *dev, void *data)
476 {
477 struct xenbus_device *xendev = to_xenbus_device(dev);
478 struct xb_find_info *info = data;
479 int len = strlen(info->nodename);
480
481 DPRINTK("%s", info->nodename);
482
483 if (!strncmp(xendev->nodename, info->nodename, len)) {
484 info->dev = xendev;
485 get_device(dev);
486 return 1;
487 }
488 return 0;
489 }
490
491 static void xenbus_cleanup_devices(const char *path, struct bus_type *bus)
492 {
493 struct xb_find_info info = { .nodename = path };
494
495 do {
496 info.dev = NULL;
497 bus_for_each_dev(bus, NULL, &info, cleanup_dev);
498 if (info.dev) {
499 device_unregister(&info.dev->dev);
500 put_device(&info.dev->dev);
501 }
502 } while (info.dev);
503 }
504
505 static void xenbus_dev_free(struct xenbus_device *xendev)
506 {
507 kfree(xendev);
508 }
509
510 static void xenbus_dev_release(struct device *dev)
511 {
512 if (dev) {
513 xenbus_dev_free(to_xenbus_device(dev));
514 }
515 }
516
517 /* Simplified asprintf. */
518 static char *kasprintf(const char *fmt, ...)
519 {
520 va_list ap;
521 unsigned int len;
522 char *p, dummy[1];
523
524 va_start(ap, fmt);
525 /* FIXME: vsnprintf has a bug, NULL should work */
526 len = vsnprintf(dummy, 0, fmt, ap);
527 va_end(ap);
528
529 p = kmalloc(len + 1, GFP_KERNEL);
530 if (!p)
531 return NULL;
532 va_start(ap, fmt);
533 vsprintf(p, fmt, ap);
534 va_end(ap);
535 return p;
536 }
537
538 static ssize_t xendev_show_nodename(struct device *dev, char *buf)
539 {
540 return sprintf(buf, "%s\n", to_xenbus_device(dev)->nodename);
541 }
542 DEVICE_ATTR(nodename, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_nodename, NULL);
543
544 static ssize_t xendev_show_devtype(struct device *dev, char *buf)
545 {
546 return sprintf(buf, "%s\n", to_xenbus_device(dev)->devicetype);
547 }
548 DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL);
549
550
551 static int xenbus_probe_node(struct xen_bus_type *bus,
552 const char *type,
553 const char *nodename)
554 {
555 #define CHECK_FAIL \
556 do { \
557 if (err) \
558 goto fail; \
559 } \
560 while (0) \
561
562
563 int err;
564 struct xenbus_device *xendev;
565 size_t stringlen;
566 char *tmpstring;
567
568 XenbusState state = xenbus_read_driver_state(nodename);
569
570 if (state != XenbusStateInitialising) {
571 /* Device is not new, so ignore it. This can happen if a
572 device is going away after switching to Closed. */
573 return 0;
574 }
575
576 stringlen = strlen(nodename) + 1 + strlen(type) + 1;
577 xendev = kmalloc(sizeof(*xendev) + stringlen, GFP_KERNEL);
578 if (!xendev)
579 return -ENOMEM;
580 memset(xendev, 0, sizeof(*xendev));
581
582 /* Copy the strings into the extra space. */
583
584 tmpstring = (char *)(xendev + 1);
585 strcpy(tmpstring, nodename);
586 xendev->nodename = tmpstring;
587
588 tmpstring += strlen(tmpstring) + 1;
589 strcpy(tmpstring, type);
590 xendev->devicetype = tmpstring;
591
592 xendev->dev.parent = &bus->dev;
593 xendev->dev.bus = &bus->bus;
594 xendev->dev.release = xenbus_dev_release;
595
596 err = bus->get_bus_id(xendev->dev.bus_id, xendev->nodename);
597 CHECK_FAIL;
598
599 /* Register with generic device framework. */
600 err = device_register(&xendev->dev);
601 CHECK_FAIL;
602
603 device_create_file(&xendev->dev, &dev_attr_nodename);
604 device_create_file(&xendev->dev, &dev_attr_devtype);
605
606 return 0;
607
608 #undef CHECK_FAIL
609
610 fail:
611 xenbus_dev_free(xendev);
612 return err;
613 }
614
615 /* device/<typename>/<name> */
616 static int xenbus_probe_frontend(const char *type, const char *name)
617 {
618 char *nodename;
619 int err;
620
621 nodename = kasprintf("%s/%s/%s", xenbus_frontend.root, type, name);
622 if (!nodename)
623 return -ENOMEM;
624
625 DPRINTK("%s", nodename);
626
627 err = xenbus_probe_node(&xenbus_frontend, type, nodename);
628 kfree(nodename);
629 return err;
630 }
631
632 /* backend/<typename>/<frontend-uuid>/<name> */
633 static int xenbus_probe_backend_unit(const char *dir,
634 const char *type,
635 const char *name)
636 {
637 char *nodename;
638 int err;
639
640 nodename = kasprintf("%s/%s", dir, name);
641 if (!nodename)
642 return -ENOMEM;
643
644 DPRINTK("%s\n", nodename);
645
646 err = xenbus_probe_node(&xenbus_backend, type, nodename);
647 kfree(nodename);
648 return err;
649 }
650
651 /* backend/<typename>/<frontend-domid> */
652 static int xenbus_probe_backend(const char *type, const char *domid)
653 {
654 char *nodename;
655 int err = 0;
656 char **dir;
657 unsigned int i, dir_n = 0;
658
659 DPRINTK("");
660
661 nodename = kasprintf("%s/%s/%s", xenbus_backend.root, type, domid);
662 if (!nodename)
663 return -ENOMEM;
664
665 dir = xenbus_directory(NULL, nodename, "", &dir_n);
666 if (IS_ERR(dir)) {
667 kfree(nodename);
668 return PTR_ERR(dir);
669 }
670
671 for (i = 0; i < dir_n; i++) {
672 err = xenbus_probe_backend_unit(nodename, type, dir[i]);
673 if (err)
674 break;
675 }
676 kfree(dir);
677 kfree(nodename);
678 return err;
679 }
680
681 static int xenbus_probe_device_type(struct xen_bus_type *bus, const char *type)
682 {
683 int err = 0;
684 char **dir;
685 unsigned int dir_n = 0;
686 int i;
687
688 dir = xenbus_directory(NULL, bus->root, type, &dir_n);
689 if (IS_ERR(dir))
690 return PTR_ERR(dir);
691
692 for (i = 0; i < dir_n; i++) {
693 err = bus->probe(type, dir[i]);
694 if (err)
695 break;
696 }
697 kfree(dir);
698 return err;
699 }
700
701 static int xenbus_probe_devices(struct xen_bus_type *bus)
702 {
703 int err = 0;
704 char **dir;
705 unsigned int i, dir_n;
706
707 dir = xenbus_directory(NULL, bus->root, "", &dir_n);
708 if (IS_ERR(dir))
709 return PTR_ERR(dir);
710
711 for (i = 0; i < dir_n; i++) {
712 err = xenbus_probe_device_type(bus, dir[i]);
713 if (err)
714 break;
715 }
716 kfree(dir);
717 return err;
718 }
719
720 static unsigned int char_count(const char *str, char c)
721 {
722 unsigned int i, ret = 0;
723
724 for (i = 0; str[i]; i++)
725 if (str[i] == c)
726 ret++;
727 return ret;
728 }
729
730 static int strsep_len(const char *str, char c, unsigned int len)
731 {
732 unsigned int i;
733
734 for (i = 0; str[i]; i++)
735 if (str[i] == c) {
736 if (len == 0)
737 return i;
738 len--;
739 }
740 return (len == 0) ? i : -ERANGE;
741 }
742
743 static void dev_changed(const char *node, struct xen_bus_type *bus)
744 {
745 int exists, rootlen;
746 struct xenbus_device *dev;
747 char type[BUS_ID_SIZE];
748 const char *p, *root;
749
750 if (char_count(node, '/') < 2)
751 return;
752
753 exists = xenbus_exists(NULL, node, "");
754 if (!exists) {
755 xenbus_cleanup_devices(node, &bus->bus);
756 return;
757 }
758
759 /* backend/<type>/... or device/<type>/... */
760 p = strchr(node, '/') + 1;
761 snprintf(type, BUS_ID_SIZE, "%.*s", (int)strcspn(p, "/"), p);
762 type[BUS_ID_SIZE-1] = '\0';
763
764 rootlen = strsep_len(node, '/', bus->levels);
765 if (rootlen < 0)
766 return;
767 root = kasprintf("%.*s", rootlen, node);
768 if (!root)
769 return;
770
771 dev = xenbus_device_find(root, &bus->bus);
772 if (!dev)
773 xenbus_probe_node(bus, type, root);
774 else
775 put_device(&dev->dev);
776
777 kfree(root);
778 }
779
780 static void frontend_changed(struct xenbus_watch *watch,
781 const char **vec, unsigned int len)
782 {
783 DPRINTK("");
784
785 dev_changed(vec[XS_WATCH_PATH], &xenbus_frontend);
786 }
787
788 static void backend_changed(struct xenbus_watch *watch,
789 const char **vec, unsigned int len)
790 {
791 DPRINTK("");
792
793 dev_changed(vec[XS_WATCH_PATH], &xenbus_backend);
794 }
795
796 /* We watch for devices appearing and vanishing. */
797 static struct xenbus_watch fe_watch = {
798 .node = "device",
799 .callback = frontend_changed,
800 };
801
802 static struct xenbus_watch be_watch = {
803 .node = "backend",
804 .callback = backend_changed,
805 };
806
807 static int suspend_dev(struct device *dev, void *data)
808 {
809 int err = 0;
810 struct xenbus_driver *drv;
811 struct xenbus_device *xdev;
812
813 DPRINTK("");
814
815 if (dev->driver == NULL)
816 return 0;
817 drv = to_xenbus_driver(dev->driver);
818 xdev = container_of(dev, struct xenbus_device, dev);
819 if (drv->suspend)
820 err = drv->suspend(xdev);
821 if (err)
822 printk(KERN_WARNING
823 "xenbus: suspend %s failed: %i\n", dev->bus_id, err);
824 return 0;
825 }
826
827 static int resume_dev(struct device *dev, void *data)
828 {
829 int err;
830 struct xenbus_driver *drv;
831 struct xenbus_device *xdev;
832
833 DPRINTK("");
834
835 if (dev->driver == NULL)
836 return 0;
837 drv = to_xenbus_driver(dev->driver);
838 xdev = container_of(dev, struct xenbus_device, dev);
839
840 err = talk_to_otherend(xdev);
841 if (err) {
842 printk(KERN_WARNING
843 "xenbus: resume (talk_to_otherend) %s failed: %i\n",
844 dev->bus_id, err);
845 return err;
846 }
847
848 if (drv->resume)
849 err = drv->resume(xdev);
850 if (err)
851 printk(KERN_WARNING
852 "xenbus: resume %s failed: %i\n", dev->bus_id, err);
853 return err;
854 }
855
856 void xenbus_suspend(void)
857 {
858 DPRINTK("");
859
860 bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev);
861 bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, suspend_dev);
862 xs_suspend();
863 }
864 EXPORT_SYMBOL(xenbus_suspend);
865
866 void xenbus_resume(void)
867 {
868 xb_init_comms();
869 xs_resume();
870 bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev);
871 bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, resume_dev);
872 }
873 EXPORT_SYMBOL(xenbus_resume);
874
875
876 /* A flag to determine if xenstored is 'ready' (i.e. has started) */
877 int xenstored_ready = 0;
878
879
880 int register_xenstore_notifier(struct notifier_block *nb)
881 {
882 int ret = 0;
883
884 if (xenstored_ready > 0)
885 ret = nb->notifier_call(nb, 0, NULL);
886 else
887 notifier_chain_register(&xenstore_chain, nb);
888
889 return ret;
890 }
891 EXPORT_SYMBOL(register_xenstore_notifier);
892
893 void unregister_xenstore_notifier(struct notifier_block *nb)
894 {
895 notifier_chain_unregister(&xenstore_chain, nb);
896 }
897 EXPORT_SYMBOL(unregister_xenstore_notifier);
898
899
900
901 void xenbus_probe(void *unused)
902 {
903 BUG_ON((xenstored_ready <= 0));
904
905 /* Enumerate devices in xenstore. */
906 xenbus_probe_devices(&xenbus_frontend);
907 xenbus_probe_devices(&xenbus_backend);
908
909 /* Watch for changes. */
910 register_xenbus_watch(&fe_watch);
911 register_xenbus_watch(&be_watch);
912
913 /* Notify others that xenstore is up */
914 notifier_call_chain(&xenstore_chain, 0, NULL);
915 }
916
917
918 static struct proc_dir_entry *xsd_mfn_intf;
919 static struct proc_dir_entry *xsd_port_intf;
920
921
922 static int xsd_mfn_read(char *page, char **start, off_t off,
923 int count, int *eof, void *data)
924 {
925 int len;
926 len = sprintf(page, "%ld", xen_start_info->store_mfn);
927 *eof = 1;
928 return len;
929 }
930
931 static int xsd_port_read(char *page, char **start, off_t off,
932 int count, int *eof, void *data)
933 {
934 int len;
935
936 len = sprintf(page, "%d", xen_start_info->store_evtchn);
937 *eof = 1;
938 return len;
939 }
940
941
942 static int __init xenbus_probe_init(void)
943 {
944 int err = 0, dom0;
945
946 DPRINTK("");
947
948 if (xen_init() < 0) {
949 DPRINTK("failed");
950 return -ENODEV;
951 }
952
953 /* Register ourselves with the kernel bus & device subsystems */
954 bus_register(&xenbus_frontend.bus);
955 bus_register(&xenbus_backend.bus);
956 device_register(&xenbus_frontend.dev);
957 device_register(&xenbus_backend.dev);
958
959 /*
960 ** Domain0 doesn't have a store_evtchn or store_mfn yet.
961 */
962 dom0 = (xen_start_info->store_evtchn == 0);
963
964 if (dom0) {
965
966 unsigned long page;
967 evtchn_op_t op = { 0 };
968 int ret;
969
970
971 /* Allocate page. */
972 page = get_zeroed_page(GFP_KERNEL);
973 if (!page)
974 return -ENOMEM;
975
976 /* We don't refcnt properly, so set reserved on page.
977 * (this allocation is permanent) */
978 SetPageReserved(virt_to_page(page));
979
980 xen_start_info->store_mfn =
981 pfn_to_mfn(virt_to_phys((void *)page) >>
982 PAGE_SHIFT);
983
984 /* Next allocate a local port which xenstored can bind to */
985 op.cmd = EVTCHNOP_alloc_unbound;
986 op.u.alloc_unbound.dom = DOMID_SELF;
987 op.u.alloc_unbound.remote_dom = 0;
988
989 ret = HYPERVISOR_event_channel_op(&op);
990 BUG_ON(ret);
991 xen_start_info->store_evtchn = op.u.alloc_unbound.port;
992
993 /* And finally publish the above info in /proc/xen */
994 if((xsd_mfn_intf = create_xen_proc_entry("xsd_mfn", 0400)))
995 xsd_mfn_intf->read_proc = xsd_mfn_read;
996 if((xsd_port_intf = create_xen_proc_entry("xsd_port", 0400)))
997 xsd_port_intf->read_proc = xsd_port_read;
998 }
999
1000 /* Initialize the interface to xenstore. */
1001 err = xs_init();
1002 if (err) {
1003 printk(KERN_WARNING
1004 "XENBUS: Error initializing xenstore comms: %i\n", err);
1005 return err;
1006 }
1007
1008 if (!dom0) {
1009 xenstored_ready = 1;
1010 xenbus_probe(NULL);
1011 }
1012
1013 return 0;
1014 }
1015
1016 postcore_initcall(xenbus_probe_init);
1017
1018 /*
1019 * Local variables:
1020 * c-file-style: "linux"
1021 * indent-tabs-mode: t
1022 * c-indent-level: 8
1023 * c-basic-offset: 8
1024 * tab-width: 8
1025 * End:
1026 */
1027