direct-io.hg

view linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c @ 8370:39a616126104

Put watch on device node only if probe was sucessful.

This fix segfault on netfront when creating more than three network devices on
domU.

Signed-off-by: Murillo F. Bernardes <mfb@br.ibm.com>
author emellor@leeni.uk.xensource.com
date Thu Dec 15 13:38:16 2005 +0000 (2005-12-15)
parents 5f574f9cb4bd
children b62e324574d2
line source
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 */
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
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>
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>
56 #include "xenbus_comms.h"
58 extern struct semaphore xenwatch_mutex;
60 #define streq(a, b) (strcmp((a), (b)) == 0)
62 static struct notifier_block *xenstore_chain;
64 /* If something in array of ids matches this device, return it. */
65 static const struct xenbus_device_id *
66 match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev)
67 {
68 for (; !streq(arr->devicetype, ""); arr++) {
69 if (streq(arr->devicetype, dev->devicetype))
70 return arr;
71 }
72 return NULL;
73 }
75 static int xenbus_match(struct device *_dev, struct device_driver *_drv)
76 {
77 struct xenbus_driver *drv = to_xenbus_driver(_drv);
79 if (!drv->ids)
80 return 0;
82 return match_device(drv->ids, to_xenbus_device(_dev)) != NULL;
83 }
85 struct xen_bus_type
86 {
87 char *root;
88 unsigned int levels;
89 int (*get_bus_id)(char bus_id[BUS_ID_SIZE], const char *nodename);
90 int (*probe)(const char *type, const char *dir);
91 struct bus_type bus;
92 struct device dev;
93 };
96 /* device/<type>/<id> => <type>-<id> */
97 static int frontend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename)
98 {
99 nodename = strchr(nodename, '/');
100 if (!nodename || strlen(nodename + 1) >= BUS_ID_SIZE) {
101 printk(KERN_WARNING "XENBUS: bad frontend %s\n", nodename);
102 return -EINVAL;
103 }
105 strlcpy(bus_id, nodename + 1, BUS_ID_SIZE);
106 if (!strchr(bus_id, '/')) {
107 printk(KERN_WARNING "XENBUS: bus_id %s no slash\n", bus_id);
108 return -EINVAL;
109 }
110 *strchr(bus_id, '/') = '-';
111 return 0;
112 }
115 static int read_otherend_details(struct xenbus_device *xendev,
116 char *id_node, char *path_node)
117 {
118 int err = xenbus_gather(NULL, xendev->nodename,
119 id_node, "%i", &xendev->otherend_id,
120 path_node, NULL, &xendev->otherend,
121 NULL);
122 if (err) {
123 xenbus_dev_fatal(xendev, err,
124 "reading other end details from %s",
125 xendev->nodename);
126 return err;
127 }
128 if (strlen(xendev->otherend) == 0 ||
129 !xenbus_exists(NULL, xendev->otherend, "")) {
130 xenbus_dev_fatal(xendev, -ENOENT, "missing other end from %s",
131 xendev->nodename);
132 kfree(xendev->otherend);
133 xendev->otherend = NULL;
134 return -ENOENT;
135 }
137 return 0;
138 }
141 static int read_backend_details(struct xenbus_device *xendev)
142 {
143 return read_otherend_details(xendev, "backend-id", "backend");
144 }
147 static int read_frontend_details(struct xenbus_device *xendev)
148 {
149 return read_otherend_details(xendev, "frontend-id", "frontend");
150 }
153 static void free_otherend_details(struct xenbus_device *dev)
154 {
155 kfree(dev->otherend);
156 dev->otherend = NULL;
157 }
160 static void free_otherend_watch(struct xenbus_device *dev)
161 {
162 if (dev->otherend_watch.node) {
163 unregister_xenbus_watch(&dev->otherend_watch);
164 kfree(dev->otherend_watch.node);
165 dev->otherend_watch.node = NULL;
166 }
167 }
170 /* Bus type for frontend drivers. */
171 static int xenbus_probe_frontend(const char *type, const char *name);
172 static struct xen_bus_type xenbus_frontend = {
173 .root = "device",
174 .levels = 2, /* device/type/<id> */
175 .get_bus_id = frontend_bus_id,
176 .probe = xenbus_probe_frontend,
177 .bus = {
178 .name = "xen",
179 .match = xenbus_match,
180 },
181 .dev = {
182 .bus_id = "xen",
183 },
184 };
186 /* backend/<type>/<fe-uuid>/<id> => <type>-<fe-domid>-<id> */
187 static int backend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename)
188 {
189 int domid, err;
190 const char *devid, *type, *frontend;
191 unsigned int typelen;
193 type = strchr(nodename, '/');
194 if (!type)
195 return -EINVAL;
196 type++;
197 typelen = strcspn(type, "/");
198 if (!typelen || type[typelen] != '/')
199 return -EINVAL;
201 devid = strrchr(nodename, '/') + 1;
203 err = xenbus_gather(NULL, nodename, "frontend-id", "%i", &domid,
204 "frontend", NULL, &frontend,
205 NULL);
206 if (err)
207 return err;
208 if (strlen(frontend) == 0)
209 err = -ERANGE;
210 if (!err && !xenbus_exists(NULL, frontend, ""))
211 err = -ENOENT;
213 kfree(frontend);
215 if (err)
216 return err;
218 if (snprintf(bus_id, BUS_ID_SIZE,
219 "%.*s-%i-%s", typelen, type, domid, devid) >= BUS_ID_SIZE)
220 return -ENOSPC;
221 return 0;
222 }
224 static int xenbus_hotplug_backend(struct device *dev, char **envp,
225 int num_envp, char *buffer, int buffer_size);
226 static int xenbus_probe_backend(const char *type, const char *domid);
227 static struct xen_bus_type xenbus_backend = {
228 .root = "backend",
229 .levels = 3, /* backend/type/<frontend>/<id> */
230 .get_bus_id = backend_bus_id,
231 .probe = xenbus_probe_backend,
232 .bus = {
233 .name = "xen-backend",
234 .match = xenbus_match,
235 .hotplug = xenbus_hotplug_backend,
236 },
237 .dev = {
238 .bus_id = "xen-backend",
239 },
240 };
242 static int xenbus_hotplug_backend(struct device *dev, char **envp,
243 int num_envp, char *buffer, int buffer_size)
244 {
245 struct xenbus_device *xdev;
246 struct xenbus_driver *drv;
247 int i = 0;
248 int length = 0;
250 DPRINTK("");
252 if (dev == NULL)
253 return -ENODEV;
255 xdev = to_xenbus_device(dev);
256 if (xdev == NULL)
257 return -ENODEV;
259 /* stuff we want to pass to /sbin/hotplug */
260 add_hotplug_env_var(envp, num_envp, &i,
261 buffer, buffer_size, &length,
262 "XENBUS_TYPE=%s", xdev->devicetype);
264 add_hotplug_env_var(envp, num_envp, &i,
265 buffer, buffer_size, &length,
266 "XENBUS_PATH=%s", xdev->nodename);
268 add_hotplug_env_var(envp, num_envp, &i,
269 buffer, buffer_size, &length,
270 "XENBUS_BASE_PATH=%s", xenbus_backend.root);
272 /* terminate, set to next free slot, shrink available space */
273 envp[i] = NULL;
274 envp = &envp[i];
275 num_envp -= i;
276 buffer = &buffer[length];
277 buffer_size -= length;
279 if (dev->driver) {
280 drv = to_xenbus_driver(dev->driver);
281 if (drv && drv->hotplug)
282 return drv->hotplug(xdev, envp, num_envp, buffer,
283 buffer_size);
284 }
286 return 0;
287 }
289 static void otherend_changed(struct xenbus_watch *watch,
290 const char **vec, unsigned int len)
291 {
292 struct xenbus_device *dev =
293 container_of(watch, struct xenbus_device, otherend_watch);
294 struct xenbus_driver *drv = to_xenbus_driver(dev->dev.driver);
295 XenbusState state;
297 /* Protect us against watches firing on old details when the otherend
298 details change, say immediately after a resume. */
299 if (!dev->otherend ||
300 strncmp(dev->otherend, vec[XS_WATCH_PATH],
301 strlen(dev->otherend))) {
302 DPRINTK("Ignoring watch at %s", vec[XS_WATCH_PATH]);
303 return;
304 }
306 state = xenbus_read_driver_state(dev->otherend);
308 DPRINTK("state is %d, %s, %s",
309 state, dev->otherend_watch.node, vec[XS_WATCH_PATH]);
310 if (drv->otherend_changed)
311 drv->otherend_changed(dev, state);
312 }
315 static int talk_to_otherend(struct xenbus_device *dev)
316 {
317 struct xenbus_driver *drv = to_xenbus_driver(dev->dev.driver);
318 int err;
320 free_otherend_watch(dev);
321 free_otherend_details(dev);
323 err = drv->read_otherend_details(dev);
324 if (err)
325 return err;
327 return xenbus_watch_path2(dev, dev->otherend, "state",
328 &dev->otherend_watch, otherend_changed);
329 }
332 static int xenbus_dev_probe(struct device *_dev)
333 {
334 struct xenbus_device *dev = to_xenbus_device(_dev);
335 struct xenbus_driver *drv = to_xenbus_driver(_dev->driver);
336 const struct xenbus_device_id *id;
337 int err;
339 DPRINTK("");
341 if (!drv->probe) {
342 err = -ENODEV;
343 goto fail;
344 }
346 id = match_device(drv->ids, dev);
347 if (!id) {
348 err = -ENODEV;
349 goto fail;
350 }
352 err = drv->probe(dev, id);
353 if (err)
354 goto fail;
356 err = talk_to_otherend(dev);
357 if (err) {
358 printk(KERN_WARNING
359 "xenbus_probe: talk_to_otherend on %s failed.\n",
360 dev->nodename);
361 return err;
362 }
364 return 0;
365 fail:
366 xenbus_dev_error(dev, err, "xenbus_dev_probe on %s", dev->nodename);
367 xenbus_switch_state(dev, NULL, XenbusStateClosed);
368 return -ENODEV;
370 }
372 static int xenbus_dev_remove(struct device *_dev)
373 {
374 struct xenbus_device *dev = to_xenbus_device(_dev);
375 struct xenbus_driver *drv = to_xenbus_driver(_dev->driver);
377 DPRINTK("");
379 free_otherend_watch(dev);
380 free_otherend_details(dev);
382 if (drv->remove)
383 drv->remove(dev);
385 xenbus_switch_state(dev, NULL, XenbusStateClosed);
386 return 0;
387 }
389 static int xenbus_register_driver_common(struct xenbus_driver *drv,
390 struct xen_bus_type *bus)
391 {
392 int ret;
394 drv->driver.name = drv->name;
395 drv->driver.bus = &bus->bus;
396 drv->driver.owner = drv->owner;
397 drv->driver.probe = xenbus_dev_probe;
398 drv->driver.remove = xenbus_dev_remove;
400 down(&xenwatch_mutex);
401 ret = driver_register(&drv->driver);
402 up(&xenwatch_mutex);
403 return ret;
404 }
406 int xenbus_register_frontend(struct xenbus_driver *drv)
407 {
408 drv->read_otherend_details = read_backend_details;
410 return xenbus_register_driver_common(drv, &xenbus_frontend);
411 }
412 EXPORT_SYMBOL(xenbus_register_frontend);
414 int xenbus_register_backend(struct xenbus_driver *drv)
415 {
416 drv->read_otherend_details = read_frontend_details;
418 return xenbus_register_driver_common(drv, &xenbus_backend);
419 }
420 EXPORT_SYMBOL(xenbus_register_backend);
422 void xenbus_unregister_driver(struct xenbus_driver *drv)
423 {
424 driver_unregister(&drv->driver);
425 }
426 EXPORT_SYMBOL(xenbus_unregister_driver);
428 struct xb_find_info
429 {
430 struct xenbus_device *dev;
431 const char *nodename;
432 };
434 static int cmp_dev(struct device *dev, void *data)
435 {
436 struct xenbus_device *xendev = to_xenbus_device(dev);
437 struct xb_find_info *info = data;
439 if (streq(xendev->nodename, info->nodename)) {
440 info->dev = xendev;
441 get_device(dev);
442 return 1;
443 }
444 return 0;
445 }
447 struct xenbus_device *xenbus_device_find(const char *nodename,
448 struct bus_type *bus)
449 {
450 struct xb_find_info info = { .dev = NULL, .nodename = nodename };
452 bus_for_each_dev(bus, NULL, &info, cmp_dev);
453 return info.dev;
454 }
456 static int cleanup_dev(struct device *dev, void *data)
457 {
458 struct xenbus_device *xendev = to_xenbus_device(dev);
459 struct xb_find_info *info = data;
460 int len = strlen(info->nodename);
462 DPRINTK("%s", info->nodename);
464 if (!strncmp(xendev->nodename, info->nodename, len)) {
465 info->dev = xendev;
466 get_device(dev);
467 return 1;
468 }
469 return 0;
470 }
472 static void xenbus_cleanup_devices(const char *path, struct bus_type *bus)
473 {
474 struct xb_find_info info = { .nodename = path };
476 do {
477 info.dev = NULL;
478 bus_for_each_dev(bus, NULL, &info, cleanup_dev);
479 if (info.dev) {
480 device_unregister(&info.dev->dev);
481 put_device(&info.dev->dev);
482 }
483 } while (info.dev);
484 }
486 static void xenbus_dev_free(struct xenbus_device *xendev)
487 {
488 kfree(xendev);
489 }
491 static void xenbus_dev_release(struct device *dev)
492 {
493 if (dev) {
494 xenbus_dev_free(to_xenbus_device(dev));
495 }
496 }
498 /* Simplified asprintf. */
499 static char *kasprintf(const char *fmt, ...)
500 {
501 va_list ap;
502 unsigned int len;
503 char *p, dummy[1];
505 va_start(ap, fmt);
506 /* FIXME: vsnprintf has a bug, NULL should work */
507 len = vsnprintf(dummy, 0, fmt, ap);
508 va_end(ap);
510 p = kmalloc(len + 1, GFP_KERNEL);
511 if (!p)
512 return NULL;
513 va_start(ap, fmt);
514 vsprintf(p, fmt, ap);
515 va_end(ap);
516 return p;
517 }
519 static ssize_t xendev_show_nodename(struct device *dev, char *buf)
520 {
521 return sprintf(buf, "%s\n", to_xenbus_device(dev)->nodename);
522 }
523 DEVICE_ATTR(nodename, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_nodename, NULL);
525 static ssize_t xendev_show_devtype(struct device *dev, char *buf)
526 {
527 return sprintf(buf, "%s\n", to_xenbus_device(dev)->devicetype);
528 }
529 DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL);
532 static int xenbus_probe_node(struct xen_bus_type *bus,
533 const char *type,
534 const char *nodename)
535 {
536 #define CHECK_FAIL \
537 do { \
538 if (err) \
539 goto fail; \
540 } \
541 while (0) \
544 int err;
545 struct xenbus_device *xendev;
546 size_t stringlen;
547 char *tmpstring;
549 XenbusState state = xenbus_read_driver_state(nodename);
551 if (state != XenbusStateInitialising) {
552 /* Device is not new, so ignore it. This can happen if a
553 device is going away after switching to Closed. */
554 return 0;
555 }
557 stringlen = strlen(nodename) + 1 + strlen(type) + 1;
558 xendev = kmalloc(sizeof(*xendev) + stringlen, GFP_KERNEL);
559 if (!xendev)
560 return -ENOMEM;
561 memset(xendev, 0, sizeof(*xendev));
563 /* Copy the strings into the extra space. */
565 tmpstring = (char *)(xendev + 1);
566 strcpy(tmpstring, nodename);
567 xendev->nodename = tmpstring;
569 tmpstring += strlen(tmpstring) + 1;
570 strcpy(tmpstring, type);
571 xendev->devicetype = tmpstring;
573 xendev->dev.parent = &bus->dev;
574 xendev->dev.bus = &bus->bus;
575 xendev->dev.release = xenbus_dev_release;
577 err = bus->get_bus_id(xendev->dev.bus_id, xendev->nodename);
578 CHECK_FAIL;
580 /* Register with generic device framework. */
581 err = device_register(&xendev->dev);
582 CHECK_FAIL;
584 device_create_file(&xendev->dev, &dev_attr_nodename);
585 device_create_file(&xendev->dev, &dev_attr_devtype);
587 return 0;
589 #undef CHECK_FAIL
591 fail:
592 xenbus_dev_free(xendev);
593 return err;
594 }
596 /* device/<typename>/<name> */
597 static int xenbus_probe_frontend(const char *type, const char *name)
598 {
599 char *nodename;
600 int err;
602 nodename = kasprintf("%s/%s/%s", xenbus_frontend.root, type, name);
603 if (!nodename)
604 return -ENOMEM;
606 DPRINTK("%s", nodename);
608 err = xenbus_probe_node(&xenbus_frontend, type, nodename);
609 kfree(nodename);
610 return err;
611 }
613 /* backend/<typename>/<frontend-uuid>/<name> */
614 static int xenbus_probe_backend_unit(const char *dir,
615 const char *type,
616 const char *name)
617 {
618 char *nodename;
619 int err;
621 nodename = kasprintf("%s/%s", dir, name);
622 if (!nodename)
623 return -ENOMEM;
625 DPRINTK("%s\n", nodename);
627 err = xenbus_probe_node(&xenbus_backend, type, nodename);
628 kfree(nodename);
629 return err;
630 }
632 /* backend/<typename>/<frontend-domid> */
633 static int xenbus_probe_backend(const char *type, const char *domid)
634 {
635 char *nodename;
636 int err = 0;
637 char **dir;
638 unsigned int i, dir_n = 0;
640 DPRINTK("");
642 nodename = kasprintf("%s/%s/%s", xenbus_backend.root, type, domid);
643 if (!nodename)
644 return -ENOMEM;
646 dir = xenbus_directory(NULL, nodename, "", &dir_n);
647 if (IS_ERR(dir)) {
648 kfree(nodename);
649 return PTR_ERR(dir);
650 }
652 for (i = 0; i < dir_n; i++) {
653 err = xenbus_probe_backend_unit(nodename, type, dir[i]);
654 if (err)
655 break;
656 }
657 kfree(dir);
658 kfree(nodename);
659 return err;
660 }
662 static int xenbus_probe_device_type(struct xen_bus_type *bus, const char *type)
663 {
664 int err = 0;
665 char **dir;
666 unsigned int dir_n = 0;
667 int i;
669 dir = xenbus_directory(NULL, bus->root, type, &dir_n);
670 if (IS_ERR(dir))
671 return PTR_ERR(dir);
673 for (i = 0; i < dir_n; i++) {
674 err = bus->probe(type, dir[i]);
675 if (err)
676 break;
677 }
678 kfree(dir);
679 return err;
680 }
682 static int xenbus_probe_devices(struct xen_bus_type *bus)
683 {
684 int err = 0;
685 char **dir;
686 unsigned int i, dir_n;
688 dir = xenbus_directory(NULL, bus->root, "", &dir_n);
689 if (IS_ERR(dir))
690 return PTR_ERR(dir);
692 for (i = 0; i < dir_n; i++) {
693 err = xenbus_probe_device_type(bus, dir[i]);
694 if (err)
695 break;
696 }
697 kfree(dir);
698 return err;
699 }
701 static unsigned int char_count(const char *str, char c)
702 {
703 unsigned int i, ret = 0;
705 for (i = 0; str[i]; i++)
706 if (str[i] == c)
707 ret++;
708 return ret;
709 }
711 static int strsep_len(const char *str, char c, unsigned int len)
712 {
713 unsigned int i;
715 for (i = 0; str[i]; i++)
716 if (str[i] == c) {
717 if (len == 0)
718 return i;
719 len--;
720 }
721 return (len == 0) ? i : -ERANGE;
722 }
724 static void dev_changed(const char *node, struct xen_bus_type *bus)
725 {
726 int exists, rootlen;
727 struct xenbus_device *dev;
728 char type[BUS_ID_SIZE];
729 const char *p, *root;
731 if (char_count(node, '/') < 2)
732 return;
734 exists = xenbus_exists(NULL, node, "");
735 if (!exists) {
736 xenbus_cleanup_devices(node, &bus->bus);
737 return;
738 }
740 /* backend/<type>/... or device/<type>/... */
741 p = strchr(node, '/') + 1;
742 snprintf(type, BUS_ID_SIZE, "%.*s", (int)strcspn(p, "/"), p);
743 type[BUS_ID_SIZE-1] = '\0';
745 rootlen = strsep_len(node, '/', bus->levels);
746 if (rootlen < 0)
747 return;
748 root = kasprintf("%.*s", rootlen, node);
749 if (!root)
750 return;
752 dev = xenbus_device_find(root, &bus->bus);
753 if (!dev)
754 xenbus_probe_node(bus, type, root);
755 else
756 put_device(&dev->dev);
758 kfree(root);
759 }
761 static void frontend_changed(struct xenbus_watch *watch,
762 const char **vec, unsigned int len)
763 {
764 DPRINTK("");
766 dev_changed(vec[XS_WATCH_PATH], &xenbus_frontend);
767 }
769 static void backend_changed(struct xenbus_watch *watch,
770 const char **vec, unsigned int len)
771 {
772 DPRINTK("");
774 dev_changed(vec[XS_WATCH_PATH], &xenbus_backend);
775 }
777 /* We watch for devices appearing and vanishing. */
778 static struct xenbus_watch fe_watch = {
779 .node = "device",
780 .callback = frontend_changed,
781 };
783 static struct xenbus_watch be_watch = {
784 .node = "backend",
785 .callback = backend_changed,
786 };
788 static int suspend_dev(struct device *dev, void *data)
789 {
790 int err = 0;
791 struct xenbus_driver *drv;
792 struct xenbus_device *xdev;
794 DPRINTK("");
796 if (dev->driver == NULL)
797 return 0;
798 drv = to_xenbus_driver(dev->driver);
799 xdev = container_of(dev, struct xenbus_device, dev);
800 if (drv->suspend)
801 err = drv->suspend(xdev);
802 if (err)
803 printk(KERN_WARNING
804 "xenbus: suspend %s failed: %i\n", dev->bus_id, err);
805 return 0;
806 }
808 static int resume_dev(struct device *dev, void *data)
809 {
810 int err;
811 struct xenbus_driver *drv;
812 struct xenbus_device *xdev;
814 DPRINTK("");
816 if (dev->driver == NULL)
817 return 0;
818 drv = to_xenbus_driver(dev->driver);
819 xdev = container_of(dev, struct xenbus_device, dev);
821 err = talk_to_otherend(xdev);
822 if (err) {
823 printk(KERN_WARNING
824 "xenbus: resume (talk_to_otherend) %s failed: %i\n",
825 dev->bus_id, err);
826 return err;
827 }
829 if (drv->resume)
830 err = drv->resume(xdev);
831 if (err)
832 printk(KERN_WARNING
833 "xenbus: resume %s failed: %i\n", dev->bus_id, err);
834 return err;
835 }
837 void xenbus_suspend(void)
838 {
839 DPRINTK("");
841 bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev);
842 bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, suspend_dev);
843 xs_suspend();
844 }
845 EXPORT_SYMBOL(xenbus_suspend);
847 void xenbus_resume(void)
848 {
849 xb_init_comms();
850 xs_resume();
851 bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev);
852 bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, resume_dev);
853 }
854 EXPORT_SYMBOL(xenbus_resume);
857 /* A flag to determine if xenstored is 'ready' (i.e. has started) */
858 int xenstored_ready = 0;
861 int register_xenstore_notifier(struct notifier_block *nb)
862 {
863 int ret = 0;
865 if (xenstored_ready > 0)
866 ret = nb->notifier_call(nb, 0, NULL);
867 else
868 notifier_chain_register(&xenstore_chain, nb);
870 return ret;
871 }
872 EXPORT_SYMBOL(register_xenstore_notifier);
874 void unregister_xenstore_notifier(struct notifier_block *nb)
875 {
876 notifier_chain_unregister(&xenstore_chain, nb);
877 }
878 EXPORT_SYMBOL(unregister_xenstore_notifier);
882 void xenbus_probe(void *unused)
883 {
884 BUG_ON((xenstored_ready <= 0));
886 /* Enumerate devices in xenstore. */
887 xenbus_probe_devices(&xenbus_frontend);
888 xenbus_probe_devices(&xenbus_backend);
890 /* Watch for changes. */
891 register_xenbus_watch(&fe_watch);
892 register_xenbus_watch(&be_watch);
894 /* Notify others that xenstore is up */
895 notifier_call_chain(&xenstore_chain, 0, NULL);
896 }
899 static struct proc_dir_entry *xsd_mfn_intf;
900 static struct proc_dir_entry *xsd_port_intf;
903 static int xsd_mfn_read(char *page, char **start, off_t off,
904 int count, int *eof, void *data)
905 {
906 int len;
907 len = sprintf(page, "%ld", xen_start_info->store_mfn);
908 *eof = 1;
909 return len;
910 }
912 static int xsd_port_read(char *page, char **start, off_t off,
913 int count, int *eof, void *data)
914 {
915 int len;
917 len = sprintf(page, "%d", xen_start_info->store_evtchn);
918 *eof = 1;
919 return len;
920 }
923 static int __init xenbus_probe_init(void)
924 {
925 int err = 0, dom0;
927 DPRINTK("");
929 if (xen_init() < 0) {
930 DPRINTK("failed");
931 return -ENODEV;
932 }
934 /* Register ourselves with the kernel bus & device subsystems */
935 bus_register(&xenbus_frontend.bus);
936 bus_register(&xenbus_backend.bus);
937 device_register(&xenbus_frontend.dev);
938 device_register(&xenbus_backend.dev);
940 /*
941 ** Domain0 doesn't have a store_evtchn or store_mfn yet.
942 */
943 dom0 = (xen_start_info->store_evtchn == 0);
945 if (dom0) {
947 unsigned long page;
948 evtchn_op_t op = { 0 };
949 int ret;
952 /* Allocate page. */
953 page = get_zeroed_page(GFP_KERNEL);
954 if (!page)
955 return -ENOMEM;
957 /* We don't refcnt properly, so set reserved on page.
958 * (this allocation is permanent) */
959 SetPageReserved(virt_to_page(page));
961 xen_start_info->store_mfn =
962 pfn_to_mfn(virt_to_phys((void *)page) >>
963 PAGE_SHIFT);
965 /* Next allocate a local port which xenstored can bind to */
966 op.cmd = EVTCHNOP_alloc_unbound;
967 op.u.alloc_unbound.dom = DOMID_SELF;
968 op.u.alloc_unbound.remote_dom = 0;
970 ret = HYPERVISOR_event_channel_op(&op);
971 BUG_ON(ret);
972 xen_start_info->store_evtchn = op.u.alloc_unbound.port;
974 /* And finally publish the above info in /proc/xen */
975 if((xsd_mfn_intf = create_xen_proc_entry("xsd_mfn", 0400)))
976 xsd_mfn_intf->read_proc = xsd_mfn_read;
977 if((xsd_port_intf = create_xen_proc_entry("xsd_port", 0400)))
978 xsd_port_intf->read_proc = xsd_port_read;
979 }
981 /* Initialize the interface to xenstore. */
982 err = xs_init();
983 if (err) {
984 printk(KERN_WARNING
985 "XENBUS: Error initializing xenstore comms: %i\n", err);
986 return err;
987 }
989 if (!dom0) {
990 xenstored_ready = 1;
991 xenbus_probe(NULL);
992 }
994 return 0;
995 }
997 postcore_initcall(xenbus_probe_init);
999 /*
1000 * Local variables:
1001 * c-file-style: "linux"
1002 * indent-tabs-mode: t
1003 * c-indent-level: 8
1004 * c-basic-offset: 8
1005 * tab-width: 8
1006 * End:
1007 */