direct-io.hg

view linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c @ 7530:813e504dc716

Necessary change to make ia64 dom0 rework:
- All even channels on xen/ia64 shares one common interrupt vector
- xen_start_info is initialized only after xen_init, so adjust
sequence to avoid access before initialization

Signed-off-by Kevin Tian <kevin.tian@intel.com>
author djm@kirby.fc.hp.com
date Mon Oct 24 09:15:53 2005 -0600 (2005-10-24)
parents 75ec60b67f64
children eee0489b3a17
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 *
7 * This file may be distributed separately from the Linux kernel, or
8 * incorporated into other software packages, subject to the following license:
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this source file (the "Software"), to deal in the Software without
12 * restriction, including without limitation the rights to use, copy, modify,
13 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
14 * and to permit persons to whom the Software is furnished to do so, subject to
15 * the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
26 * IN THE SOFTWARE.
27 */
28 #define DEBUG
30 #include <linux/kernel.h>
31 #include <linux/err.h>
32 #include <linux/string.h>
33 #include <linux/ctype.h>
34 #include <linux/fcntl.h>
35 #include <linux/mm.h>
36 #include <linux/notifier.h>
37 #include <linux/kthread.h>
39 #include <asm/io.h>
40 #include <asm/page.h>
41 #include <asm/pgtable.h>
42 #include <asm/hypervisor.h>
43 #include <asm-xen/xenbus.h>
44 #include <asm-xen/xen_proc.h>
45 #include <asm-xen/balloon.h>
46 #include <asm-xen/evtchn.h>
47 #include <asm-xen/linux-public/evtchn.h>
49 #include "xenbus_comms.h"
51 extern struct semaphore xenwatch_mutex;
53 #define streq(a, b) (strcmp((a), (b)) == 0)
55 static struct notifier_block *xenstore_chain;
57 /* If something in array of ids matches this device, return it. */
58 static const struct xenbus_device_id *
59 match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev)
60 {
61 for (; !streq(arr->devicetype, ""); arr++) {
62 if (streq(arr->devicetype, dev->devicetype))
63 return arr;
64 }
65 return NULL;
66 }
68 static int xenbus_match(struct device *_dev, struct device_driver *_drv)
69 {
70 struct xenbus_driver *drv = to_xenbus_driver(_drv);
72 if (!drv->ids)
73 return 0;
75 return match_device(drv->ids, to_xenbus_device(_dev)) != NULL;
76 }
78 struct xen_bus_type
79 {
80 char *root;
81 unsigned int levels;
82 int (*get_bus_id)(char bus_id[BUS_ID_SIZE], const char *nodename);
83 int (*probe)(const char *type, const char *dir);
84 struct bus_type bus;
85 struct device dev;
86 };
88 /* device/<type>/<id> => <type>-<id> */
89 static int frontend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename)
90 {
91 nodename = strchr(nodename, '/');
92 if (!nodename || strlen(nodename + 1) >= BUS_ID_SIZE) {
93 printk(KERN_WARNING "XENBUS: bad frontend %s\n", nodename);
94 return -EINVAL;
95 }
97 strlcpy(bus_id, nodename + 1, BUS_ID_SIZE);
98 if (!strchr(bus_id, '/')) {
99 printk(KERN_WARNING "XENBUS: bus_id %s no slash\n", bus_id);
100 return -EINVAL;
101 }
102 *strchr(bus_id, '/') = '-';
103 return 0;
104 }
106 /* Bus type for frontend drivers. */
107 static int xenbus_probe_frontend(const char *type, const char *name);
108 static struct xen_bus_type xenbus_frontend = {
109 .root = "device",
110 .levels = 2, /* device/type/<id> */
111 .get_bus_id = frontend_bus_id,
112 .probe = xenbus_probe_frontend,
113 .bus = {
114 .name = "xen",
115 .match = xenbus_match,
116 },
117 .dev = {
118 .bus_id = "xen",
119 },
120 };
122 /* backend/<type>/<fe-uuid>/<id> => <type>-<fe-domid>-<id> */
123 static int backend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename)
124 {
125 int domid, err;
126 const char *devid, *type, *frontend;
127 unsigned int typelen;
129 type = strchr(nodename, '/');
130 if (!type)
131 return -EINVAL;
132 type++;
133 typelen = strcspn(type, "/");
134 if (!typelen || type[typelen] != '/')
135 return -EINVAL;
137 devid = strrchr(nodename, '/') + 1;
139 err = xenbus_gather(NULL, nodename, "frontend-id", "%i", &domid,
140 "frontend", NULL, &frontend,
141 NULL);
142 if (err)
143 return err;
144 if (strlen(frontend) == 0)
145 err = -ERANGE;
147 if (!err && !xenbus_exists(NULL, frontend, ""))
148 err = -ENOENT;
150 if (err) {
151 kfree(frontend);
152 return err;
153 }
155 if (snprintf(bus_id, BUS_ID_SIZE,
156 "%.*s-%i-%s", typelen, type, domid, devid) >= BUS_ID_SIZE)
157 return -ENOSPC;
158 return 0;
159 }
161 static int xenbus_hotplug_backend(struct device *dev, char **envp,
162 int num_envp, char *buffer, int buffer_size)
163 {
164 struct xenbus_device *xdev;
165 int i = 0;
166 int length = 0;
168 if (dev == NULL)
169 return -ENODEV;
171 xdev = to_xenbus_device(dev);
172 if (xdev == NULL)
173 return -ENODEV;
175 /* stuff we want to pass to /sbin/hotplug */
176 add_hotplug_env_var(envp, num_envp, &i,
177 buffer, buffer_size, &length,
178 "XENBUS_TYPE=%s", xdev->devicetype);
180 add_hotplug_env_var(envp, num_envp, &i,
181 buffer, buffer_size, &length,
182 "XENBUS_PATH=%s", xdev->nodename);
184 /* terminate, set to next free slot, shrink available space */
185 envp[i] = NULL;
186 envp = &envp[i];
187 num_envp -= i;
188 buffer = &buffer[length];
189 buffer_size -= length;
191 if (dev->driver && to_xenbus_driver(dev->driver)->hotplug)
192 return to_xenbus_driver(dev->driver)->hotplug
193 (xdev, envp, num_envp, buffer, buffer_size);
195 return 0;
196 }
198 static int xenbus_probe_backend(const char *type, const char *domid);
199 static struct xen_bus_type xenbus_backend = {
200 .root = "backend",
201 .levels = 3, /* backend/type/<frontend>/<id> */
202 .get_bus_id = backend_bus_id,
203 .probe = xenbus_probe_backend,
204 .bus = {
205 .name = "xen-backend",
206 .match = xenbus_match,
207 .hotplug = xenbus_hotplug_backend,
208 },
209 .dev = {
210 .bus_id = "xen-backend",
211 },
212 };
214 static int xenbus_dev_probe(struct device *_dev)
215 {
216 struct xenbus_device *dev = to_xenbus_device(_dev);
217 struct xenbus_driver *drv = to_xenbus_driver(_dev->driver);
218 const struct xenbus_device_id *id;
220 if (!drv->probe)
221 return -ENODEV;
223 id = match_device(drv->ids, dev);
224 if (!id)
225 return -ENODEV;
227 return drv->probe(dev, id);
228 }
230 static int xenbus_dev_remove(struct device *_dev)
231 {
232 struct xenbus_device *dev = to_xenbus_device(_dev);
233 struct xenbus_driver *drv = to_xenbus_driver(_dev->driver);
235 if (!drv->remove)
236 return 0;
237 return drv->remove(dev);
238 }
240 static int xenbus_register_driver_common(struct xenbus_driver *drv,
241 struct xen_bus_type *bus)
242 {
243 int ret;
245 drv->driver.name = drv->name;
246 drv->driver.bus = &bus->bus;
247 drv->driver.owner = drv->owner;
248 drv->driver.probe = xenbus_dev_probe;
249 drv->driver.remove = xenbus_dev_remove;
251 down(&xenwatch_mutex);
252 ret = driver_register(&drv->driver);
253 up(&xenwatch_mutex);
254 return ret;
255 }
257 int xenbus_register_driver(struct xenbus_driver *drv)
258 {
259 return xenbus_register_driver_common(drv, &xenbus_frontend);
260 }
261 EXPORT_SYMBOL(xenbus_register_driver);
263 int xenbus_register_backend(struct xenbus_driver *drv)
264 {
265 return xenbus_register_driver_common(drv, &xenbus_backend);
266 }
268 void xenbus_unregister_driver(struct xenbus_driver *drv)
269 {
270 driver_unregister(&drv->driver);
271 }
272 EXPORT_SYMBOL(xenbus_unregister_driver);
274 struct xb_find_info
275 {
276 struct xenbus_device *dev;
277 const char *nodename;
278 };
280 static int cmp_dev(struct device *dev, void *data)
281 {
282 struct xenbus_device *xendev = to_xenbus_device(dev);
283 struct xb_find_info *info = data;
285 if (streq(xendev->nodename, info->nodename)) {
286 info->dev = xendev;
287 get_device(dev);
288 return 1;
289 }
290 return 0;
291 }
293 struct xenbus_device *xenbus_device_find(const char *nodename,
294 struct bus_type *bus)
295 {
296 struct xb_find_info info = { .dev = NULL, .nodename = nodename };
298 bus_for_each_dev(bus, NULL, &info, cmp_dev);
299 return info.dev;
300 }
302 static int cleanup_dev(struct device *dev, void *data)
303 {
304 struct xenbus_device *xendev = to_xenbus_device(dev);
305 struct xb_find_info *info = data;
306 int len = strlen(info->nodename);
308 if (!strncmp(xendev->nodename, info->nodename, len)) {
309 info->dev = xendev;
310 get_device(dev);
311 return 1;
312 }
313 return 0;
314 }
316 static void xenbus_cleanup_devices(const char *path, struct bus_type *bus)
317 {
318 struct xb_find_info info = { .nodename = path };
320 do {
321 info.dev = NULL;
322 bus_for_each_dev(bus, NULL, &info, cleanup_dev);
323 if (info.dev) {
324 device_unregister(&info.dev->dev);
325 put_device(&info.dev->dev);
326 }
327 } while (info.dev);
328 }
330 static void xenbus_release_device(struct device *dev)
331 {
332 if (dev) {
333 struct xenbus_device *xendev = to_xenbus_device(dev);
335 kfree(xendev);
336 }
337 }
339 /* Simplified asprintf. */
340 static char *kasprintf(const char *fmt, ...)
341 {
342 va_list ap;
343 unsigned int len;
344 char *p, dummy[1];
346 va_start(ap, fmt);
347 /* FIXME: vsnprintf has a bug, NULL should work */
348 len = vsnprintf(dummy, 0, fmt, ap);
349 va_end(ap);
351 p = kmalloc(len + 1, GFP_KERNEL);
352 if (!p)
353 return NULL;
354 va_start(ap, fmt);
355 vsprintf(p, fmt, ap);
356 va_end(ap);
357 return p;
358 }
360 static ssize_t xendev_show_nodename(struct device *dev, char *buf)
361 {
362 return sprintf(buf, "%s\n", to_xenbus_device(dev)->nodename);
363 }
364 DEVICE_ATTR(nodename, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_nodename, NULL);
366 static ssize_t xendev_show_devtype(struct device *dev, char *buf)
367 {
368 return sprintf(buf, "%s\n", to_xenbus_device(dev)->devicetype);
369 }
370 DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL);
372 static int xenbus_probe_node(struct xen_bus_type *bus,
373 const char *type,
374 const char *nodename)
375 {
376 int err;
377 struct xenbus_device *xendev;
378 unsigned int stringlen;
380 stringlen = strlen(nodename) + 1 + strlen(type) + 1;
381 xendev = kmalloc(sizeof(*xendev) + stringlen, GFP_KERNEL);
382 if (!xendev)
383 return -ENOMEM;
384 memset(xendev, 0, sizeof(*xendev));
386 /* Copy the strings into the extra space. */
387 xendev->nodename = (char *)(xendev + 1);
388 strcpy(xendev->nodename, nodename);
389 xendev->devicetype = xendev->nodename + strlen(xendev->nodename) + 1;
390 strcpy(xendev->devicetype, type);
392 xendev->dev.parent = &bus->dev;
393 xendev->dev.bus = &bus->bus;
394 xendev->dev.release = xenbus_release_device;
396 err = bus->get_bus_id(xendev->dev.bus_id, xendev->nodename);
397 if (err) {
398 kfree(xendev);
399 return err;
400 }
402 /* Register with generic device framework. */
403 err = device_register(&xendev->dev);
404 if (err) {
405 printk("XENBUS: Registering %s device %s: error %i\n",
406 bus->bus.name, xendev->dev.bus_id, err);
407 kfree(xendev);
408 } else {
409 device_create_file(&xendev->dev, &dev_attr_nodename);
410 device_create_file(&xendev->dev, &dev_attr_devtype);
411 }
412 return err;
413 }
415 /* device/<typename>/<name> */
416 static int xenbus_probe_frontend(const char *type, const char *name)
417 {
418 char *nodename;
419 int err;
421 nodename = kasprintf("%s/%s/%s", xenbus_frontend.root, type, name);
422 if (!nodename)
423 return -ENOMEM;
425 err = xenbus_probe_node(&xenbus_frontend, type, nodename);
426 kfree(nodename);
427 return err;
428 }
430 /* backend/<typename>/<frontend-uuid>/<name> */
431 static int xenbus_probe_backend_unit(const char *dir,
432 const char *type,
433 const char *name)
434 {
435 char *nodename;
436 int err;
438 nodename = kasprintf("%s/%s", dir, name);
439 if (!nodename)
440 return -ENOMEM;
442 err = xenbus_probe_node(&xenbus_backend, type, nodename);
443 kfree(nodename);
444 return err;
445 }
447 /* backend/<typename>/<frontend-domid> */
448 static int xenbus_probe_backend(const char *type, const char *domid)
449 {
450 char *nodename;
451 int err = 0;
452 char **dir;
453 unsigned int i, dir_n = 0;
455 nodename = kasprintf("%s/%s/%s", xenbus_backend.root, type, domid);
456 if (!nodename)
457 return -ENOMEM;
459 dir = xenbus_directory(NULL, nodename, "", &dir_n);
460 if (IS_ERR(dir)) {
461 kfree(nodename);
462 return PTR_ERR(dir);
463 }
465 for (i = 0; i < dir_n; i++) {
466 err = xenbus_probe_backend_unit(nodename, type, dir[i]);
467 if (err)
468 break;
469 }
470 kfree(dir);
471 kfree(nodename);
472 return err;
473 }
475 static int xenbus_probe_device_type(struct xen_bus_type *bus, const char *type)
476 {
477 int err = 0;
478 char **dir;
479 unsigned int dir_n = 0;
480 int i;
482 dir = xenbus_directory(NULL, bus->root, type, &dir_n);
483 if (IS_ERR(dir))
484 return PTR_ERR(dir);
486 for (i = 0; i < dir_n; i++) {
487 err = bus->probe(type, dir[i]);
488 if (err)
489 break;
490 }
491 kfree(dir);
492 return err;
493 }
495 static int xenbus_probe_devices(struct xen_bus_type *bus)
496 {
497 int err = 0;
498 char **dir;
499 unsigned int i, dir_n;
501 dir = xenbus_directory(NULL, bus->root, "", &dir_n);
502 if (IS_ERR(dir))
503 return PTR_ERR(dir);
505 for (i = 0; i < dir_n; i++) {
506 err = xenbus_probe_device_type(bus, dir[i]);
507 if (err)
508 break;
509 }
510 kfree(dir);
511 return err;
512 }
514 static unsigned int char_count(const char *str, char c)
515 {
516 unsigned int i, ret = 0;
518 for (i = 0; str[i]; i++)
519 if (str[i] == c)
520 ret++;
521 return ret;
522 }
524 static int strsep_len(const char *str, char c, unsigned int len)
525 {
526 unsigned int i;
528 for (i = 0; str[i]; i++)
529 if (str[i] == c) {
530 if (len == 0)
531 return i;
532 len--;
533 }
534 return (len == 0) ? i : -ERANGE;
535 }
537 static void dev_changed(const char *node, struct xen_bus_type *bus)
538 {
539 int exists, rootlen;
540 struct xenbus_device *dev;
541 char type[BUS_ID_SIZE];
542 const char *p, *root;
544 if (char_count(node, '/') < 2)
545 return;
547 exists = xenbus_exists(NULL, node, "");
548 if (!exists) {
549 xenbus_cleanup_devices(node, &bus->bus);
550 return;
551 }
553 /* backend/<type>/... or device/<type>/... */
554 p = strchr(node, '/') + 1;
555 snprintf(type, BUS_ID_SIZE, "%.*s", strcspn(p, "/"), p);
556 type[BUS_ID_SIZE-1] = '\0';
558 rootlen = strsep_len(node, '/', bus->levels);
559 if (rootlen < 0)
560 return;
561 root = kasprintf("%.*s", rootlen, node);
562 if (!root)
563 return;
565 dev = xenbus_device_find(root, &bus->bus);
566 if (!dev)
567 xenbus_probe_node(bus, type, root);
568 else
569 put_device(&dev->dev);
571 kfree(root);
572 }
574 static void frontend_changed(struct xenbus_watch *watch,
575 const char **vec, unsigned int len)
576 {
577 dev_changed(vec[XS_WATCH_PATH], &xenbus_frontend);
578 }
580 static void backend_changed(struct xenbus_watch *watch,
581 const char **vec, unsigned int len)
582 {
583 dev_changed(vec[XS_WATCH_PATH], &xenbus_backend);
584 }
586 /* We watch for devices appearing and vanishing. */
587 static struct xenbus_watch fe_watch = {
588 .node = "device",
589 .callback = frontend_changed,
590 };
592 static struct xenbus_watch be_watch = {
593 .node = "backend",
594 .callback = backend_changed,
595 };
597 static int suspend_dev(struct device *dev, void *data)
598 {
599 int err = 0;
600 struct xenbus_driver *drv;
601 struct xenbus_device *xdev;
603 if (dev->driver == NULL)
604 return 0;
605 drv = to_xenbus_driver(dev->driver);
606 xdev = container_of(dev, struct xenbus_device, dev);
607 if (drv->suspend)
608 err = drv->suspend(xdev);
609 if (err)
610 printk("xenbus: suspend %s failed: %i\n", dev->bus_id, err);
611 return 0;
612 }
614 static int resume_dev(struct device *dev, void *data)
615 {
616 int err = 0;
617 struct xenbus_driver *drv;
618 struct xenbus_device *xdev;
620 if (dev->driver == NULL)
621 return 0;
622 drv = to_xenbus_driver(dev->driver);
623 xdev = container_of(dev, struct xenbus_device, dev);
624 if (drv->resume)
625 err = drv->resume(xdev);
626 if (err)
627 printk("xenbus: resume %s failed: %i\n", dev->bus_id, err);
628 return 0;
629 }
631 void xenbus_suspend(void)
632 {
633 bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev);
634 bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, suspend_dev);
635 xs_suspend();
636 }
638 void xenbus_resume(void)
639 {
640 xb_init_comms();
641 xs_resume();
642 bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev);
643 bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, resume_dev);
644 }
647 /* A flag to determine if xenstored is 'ready' (i.e. has started) */
648 int xenstored_ready = 0;
651 int register_xenstore_notifier(struct notifier_block *nb)
652 {
653 int ret = 0;
655 if(xenstored_ready > 0)
656 ret = nb->notifier_call(nb, 0, NULL);
657 else
658 notifier_chain_register(&xenstore_chain, nb);
660 return ret;
661 }
662 EXPORT_SYMBOL(register_xenstore_notifier);
664 void unregister_xenstore_notifier(struct notifier_block *nb)
665 {
666 notifier_chain_unregister(&xenstore_chain, nb);
667 }
668 EXPORT_SYMBOL(unregister_xenstore_notifier);
672 void xenbus_probe(void *unused)
673 {
674 BUG_ON((xenstored_ready <= 0));
676 /* Enumerate devices in xenstore. */
677 xenbus_probe_devices(&xenbus_frontend);
678 xenbus_probe_devices(&xenbus_backend);
680 /* Watch for changes. */
681 register_xenbus_watch(&fe_watch);
682 register_xenbus_watch(&be_watch);
684 /* Notify others that xenstore is up */
685 notifier_call_chain(&xenstore_chain, 0, 0);
687 return;
688 }
691 static struct proc_dir_entry *xsd_mfn_intf;
692 static struct proc_dir_entry *xsd_port_intf;
695 static int xsd_mfn_read(char *page, char **start, off_t off,
696 int count, int *eof, void *data)
697 {
698 int len;
699 len = sprintf(page, "%ld", xen_start_info->store_mfn);
700 *eof = 1;
701 return len;
702 }
704 static int xsd_port_read(char *page, char **start, off_t off,
705 int count, int *eof, void *data)
706 {
707 int len;
709 len = sprintf(page, "%d", xen_start_info->store_evtchn);
710 *eof = 1;
711 return len;
712 }
715 static int __init xenbus_probe_init(void)
716 {
717 int err = 0, dom0;
719 printk("xenbus_probe_init\n");
721 if (xen_init() < 0) {
722 printk("xen_init failed\n");
723 return -ENODEV;
724 }
726 /* Register ourselves with the kernel bus & device subsystems */
727 bus_register(&xenbus_frontend.bus);
728 bus_register(&xenbus_backend.bus);
729 device_register(&xenbus_frontend.dev);
730 device_register(&xenbus_backend.dev);
732 /*
733 ** Domain0 doesn't have a store_evtchn or store_mfn yet.
734 */
735 dom0 = (xen_start_info->store_evtchn == 0);
737 if (dom0) {
739 unsigned long page;
740 evtchn_op_t op = { 0 };
743 /* Allocate page. */
744 page = get_zeroed_page(GFP_KERNEL);
745 if (!page)
746 return -ENOMEM;
748 /* We don't refcnt properly, so set reserved on page.
749 * (this allocation is permanent) */
750 SetPageReserved(virt_to_page(page));
752 xen_start_info->store_mfn =
753 pfn_to_mfn(virt_to_phys((void *)page) >>
754 PAGE_SHIFT);
756 /* Next allocate a local port which xenstored can bind to */
757 op.cmd = EVTCHNOP_alloc_unbound;
758 op.u.alloc_unbound.dom = DOMID_SELF;
759 op.u.alloc_unbound.remote_dom = 0;
761 BUG_ON(HYPERVISOR_event_channel_op(&op));
762 xen_start_info->store_evtchn = op.u.alloc_unbound.port;
764 /* And finally publish the above info in /proc/xen */
765 if((xsd_mfn_intf = create_xen_proc_entry("xsd_mfn", 0400)))
766 xsd_mfn_intf->read_proc = xsd_mfn_read;
767 if((xsd_port_intf = create_xen_proc_entry("xsd_port", 0400)))
768 xsd_port_intf->read_proc = xsd_port_read;
769 }
771 /* Initialize the interface to xenstore. */
772 err = xs_init();
773 if (err) {
774 printk("XENBUS: Error initializing xenstore comms: %i\n", err);
775 return err;
776 }
778 if (!dom0) {
779 xenstored_ready = 1;
780 xenbus_probe(NULL);
781 }
783 return 0;
784 }
786 postcore_initcall(xenbus_probe_init);
788 /*
789 * Local variables:
790 * c-file-style: "linux"
791 * indent-tabs-mode: t
792 * c-indent-level: 8
793 * c-basic-offset: 8
794 * tab-width: 8
795 * End:
796 */