FreeBSD xen subsystem code
xenbusb.c
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (C) 2010 Spectra Logic Corporation
3 * Copyright (C) 2008 Doug Rabson
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
54#include <sys/cdefs.h>
55__FBSDID("$FreeBSD$");
56
57#include <sys/param.h>
58#include <sys/bus.h>
59#include <sys/kernel.h>
60#include <sys/lock.h>
61#include <sys/malloc.h>
62#include <sys/module.h>
63#include <sys/sbuf.h>
64#include <sys/sysctl.h>
65#include <sys/syslog.h>
66#include <sys/systm.h>
67#include <sys/sx.h>
68#include <sys/taskqueue.h>
69
70#include <machine/stdarg.h>
71
72#include <xen/xen-os.h>
73#include <xen/gnttab.h>
74#include <xen/xenstore/xenstorevar.h>
75#include <xen/xenbus/xenbusb.h>
77
78/*------------------------- Private Functions --------------------------------*/
84static void
86{
87 if (ivars->xd_otherend_watch.node != NULL) {
88 xs_unregister_watch(&ivars->xd_otherend_watch);
89 free(ivars->xd_otherend_watch.node, M_XENBUS);
90 ivars->xd_otherend_watch.node = NULL;
91 }
92
93 if (ivars->xd_local_watch.node != NULL) {
94 xs_unregister_watch(&ivars->xd_local_watch);
95 ivars->xd_local_watch.node = NULL;
96 }
97
98 if (ivars->xd_node != NULL) {
99 free(ivars->xd_node, M_XENBUS);
100 ivars->xd_node = NULL;
101 }
102 ivars->xd_node_len = 0;
103
104 if (ivars->xd_type != NULL) {
105 free(ivars->xd_type, M_XENBUS);
106 ivars->xd_type = NULL;
107 }
108
109 if (ivars->xd_otherend_path != NULL) {
110 free(ivars->xd_otherend_path, M_XENBUS);
111 ivars->xd_otherend_path = NULL;
112 }
113 ivars->xd_otherend_path_len = 0;
114
115 free(ivars, M_XENBUS);
116}
117
132static void
133xenbusb_otherend_watch_cb(struct xs_watch *watch, const char **vec,
134 unsigned int vec_size __unused)
135{
136 struct xenbus_device_ivars *ivars;
137 device_t child;
138 device_t bus;
139 const char *path;
140 enum xenbus_state newstate;
141
142 ivars = (struct xenbus_device_ivars *)watch->callback_data;
143 child = ivars->xd_dev;
144 bus = device_get_parent(child);
145
146 path = vec[XS_WATCH_PATH];
147 if (ivars->xd_otherend_path == NULL
148 || strncmp(ivars->xd_otherend_path, path, ivars->xd_otherend_path_len))
149 return;
150
152 XENBUSB_OTHEREND_CHANGED(bus, child, newstate);
153}
154
170static void
171xenbusb_local_watch_cb(struct xs_watch *watch, const char **vec,
172 unsigned int vec_size __unused)
173{
174 struct xenbus_device_ivars *ivars;
175 device_t child;
176 device_t bus;
177 const char *path;
178
179 ivars = (struct xenbus_device_ivars *)watch->callback_data;
180 child = ivars->xd_dev;
181 bus = device_get_parent(child);
182
183 path = vec[XS_WATCH_PATH];
184 if (ivars->xd_node == NULL
185 || strncmp(ivars->xd_node, path, ivars->xd_node_len))
186 return;
187
188 XENBUSB_LOCALEND_CHANGED(bus, child, &path[ivars->xd_node_len]);
189}
190
204static device_t
205xenbusb_device_exists(device_t dev, const char *node)
206{
207 device_t *kids;
208 device_t result;
209 struct xenbus_device_ivars *ivars;
210 int i, count;
211
212 if (device_get_children(dev, &kids, &count))
213 return (FALSE);
214
215 result = NULL;
216 for (i = 0; i < count; i++) {
217 ivars = device_get_ivars(kids[i]);
218 if (!strcmp(ivars->xd_node, node)) {
219 result = kids[i];
220 break;
221 }
222 }
223 free(kids, M_TEMP);
224
225 return (result);
226}
227
228static void
229xenbusb_delete_child(device_t dev, device_t child)
230{
231 struct xenbus_device_ivars *ivars;
232
233 ivars = device_get_ivars(child);
234
235 /*
236 * We no longer care about the otherend of the
237 * connection. Cancel the watches now so that we
238 * don't try to handle an event for a partially
239 * detached child.
240 */
241 if (ivars->xd_otherend_watch.node != NULL)
242 xs_unregister_watch(&ivars->xd_otherend_watch);
243 if (ivars->xd_local_watch.node != NULL)
244 xs_unregister_watch(&ivars->xd_local_watch);
245
246 device_delete_child(dev, child);
248}
249
254static void
255xenbusb_verify_device(device_t dev, device_t child)
256{
257 if (xs_exists(XST_NIL, xenbus_get_node(child), "") == 0) {
258 /*
259 * Device tree has been removed from Xenbus.
260 * Tear down the device.
261 */
262 xenbusb_delete_child(dev, child);
263 }
264}
265
281static int
283{
284 const char **types;
285 u_int type_idx;
286 u_int type_count;
287 int error;
288
289 error = xs_directory(XST_NIL, xbs->xbs_node, "", &type_count, &types);
290 if (error)
291 return (error);
292
293 for (type_idx = 0; type_idx < type_count; type_idx++)
294 XENBUSB_ENUMERATE_TYPE(xbs->xbs_dev, types[type_idx]);
295
296 free(types, M_XENSTORE);
297
298 return (0);
299}
300
304static int
305xenbusb_device_sysctl_handler(SYSCTL_HANDLER_ARGS)
306{
307 device_t dev;
308 const char *value;
309
310 dev = (device_t)arg1;
311 switch (arg2) {
312 case XENBUS_IVAR_NODE:
313 value = xenbus_get_node(dev);
314 break;
315 case XENBUS_IVAR_TYPE:
316 value = xenbus_get_type(dev);
317 break;
319 value = xenbus_strstate(xenbus_get_state(dev));
320 break;
322 return (sysctl_handle_int(oidp, NULL,
323 xenbus_get_otherend_id(dev),
324 req));
325 /* NOTREACHED */
327 value = xenbus_get_otherend_path(dev);
328 break;
329 default:
330 return (EINVAL);
331 }
332 return (SYSCTL_OUT_STR(req, value));
333}
334
340static void
342{
343 struct sysctl_ctx_list *ctx;
344 struct sysctl_oid *tree;
345
346 ctx = device_get_sysctl_ctx(dev);
347 tree = device_get_sysctl_tree(dev);
348
349 SYSCTL_ADD_PROC(ctx,
350 SYSCTL_CHILDREN(tree),
351 OID_AUTO,
352 "xenstore_path",
353 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
354 dev,
357 "A",
358 "XenStore path to device");
359
360 SYSCTL_ADD_PROC(ctx,
361 SYSCTL_CHILDREN(tree),
362 OID_AUTO,
363 "xenbus_dev_type",
364 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
365 dev,
368 "A",
369 "XenBus device type");
370
371 SYSCTL_ADD_PROC(ctx,
372 SYSCTL_CHILDREN(tree),
373 OID_AUTO,
374 "xenbus_connection_state",
375 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
376 dev,
379 "A",
380 "XenBus state of peer connection");
381
382 SYSCTL_ADD_PROC(ctx,
383 SYSCTL_CHILDREN(tree),
384 OID_AUTO,
385 "xenbus_peer_domid",
386 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
387 dev,
390 "I",
391 "Xen domain ID of peer");
392
393 SYSCTL_ADD_PROC(ctx,
394 SYSCTL_CHILDREN(tree),
395 OID_AUTO,
396 "xenstore_peer_path",
397 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
398 dev,
401 "A",
402 "XenStore path to peer device");
403}
404
413static void
415{
416 mtx_lock(&xbs->xbs_lock);
417 KASSERT(xbs->xbs_connecting_children > 0,
418 ("Connecting device count error\n"));
420 if (xbs->xbs_connecting_children == 0
421 && (xbs->xbs_flags & XBS_ATTACH_CH_ACTIVE) != 0) {
422 xbs->xbs_flags &= ~XBS_ATTACH_CH_ACTIVE;
423 mtx_unlock(&xbs->xbs_lock);
424 config_intrhook_disestablish(&xbs->xbs_attach_ch);
425 } else {
426 mtx_unlock(&xbs->xbs_lock);
427 }
428}
429
439static int
441{
442 device_t *kids;
443 struct xenbus_device_ivars *ivars;
444 int i, count, error;
445
446 if (device_get_children(dev, &kids, &count) == 0) {
447 for (i = 0; i < count; i++) {
448 if (device_get_state(kids[i]) != DS_NOTPRESENT) {
449 /*
450 * We already know about this one.
451 * Make sure it's still here.
452 */
453 xenbusb_verify_device(dev, kids[i]);
454 continue;
455 }
456
457 error = device_probe_and_attach(kids[i]);
458 if (error == ENXIO) {
459 struct xenbusb_softc *xbs;
460
461 /*
462 * We don't have a PV driver for this device.
463 * However, an emulated device we do support
464 * may share this backend. Hide the node from
465 * XenBus until the next rescan, but leave it's
466 * state unchanged so we don't inadvertently
467 * prevent attachment of any emulated device.
468 */
469 xenbusb_delete_child(dev, kids[i]);
470
471 /*
472 * Since the XenStore state of this device
473 * still indicates a pending attach, manually
474 * release it's hold on the boot process.
475 */
476 xbs = device_get_softc(dev);
478
479 continue;
480 } else if (error) {
481 /*
482 * Transition device to the closed state
483 * so the world knows that attachment will
484 * not occur.
485 */
486 xenbus_set_state(kids[i], XenbusStateClosed);
487
488 /*
489 * Remove our record of this device.
490 * So long as it remains in the closed
491 * state in the XenStore, we will not find
492 * it again. The state will only change
493 * if the control domain actively reconfigures
494 * this device.
495 */
496 xenbusb_delete_child(dev, kids[i]);
497
498 continue;
499 }
500 /*
501 * Augment default newbus provided dynamic sysctl
502 * variables with the standard ivar contents of
503 * XenBus devices.
504 */
506
507 /*
508 * Now that we have a driver managing this device
509 * that can receive otherend state change events,
510 * hook up a watch for them.
511 */
512 ivars = device_get_ivars(kids[i]);
513 xs_register_watch(&ivars->xd_otherend_watch);
514 xs_register_watch(&ivars->xd_local_watch);
515 }
516 free(kids, M_TEMP);
517 }
518
519 return (0);
520}
521
531static void
532xenbusb_probe_children_cb(void *arg, int pending __unused)
533{
534 device_t dev = (device_t)arg;
535
536 bus_topo_lock();
538 bus_topo_unlock();
539}
540
553static void
554xenbusb_devices_changed(struct xs_watch *watch, const char **vec,
555 unsigned int len)
556{
557 struct xenbusb_softc *xbs;
558 device_t dev;
559 char *node;
560 char *type;
561 char *id;
562 char *p;
563 u_int component;
564
565 xbs = (struct xenbusb_softc *)watch->callback_data;
566 dev = xbs->xbs_dev;
567
568 if (len <= XS_WATCH_PATH) {
569 device_printf(dev, "xenbusb_devices_changed: "
570 "Short Event Data.\n");
571 return;
572 }
573
574 node = strdup(vec[XS_WATCH_PATH], M_XENBUS);
575 p = strchr(node, '/');
576 if (p == NULL)
577 goto out;
578 *p = 0;
579 type = p + 1;
580
581 p = strchr(type, '/');
582 if (p == NULL)
583 goto out;
584 *p++ = 0;
585
586 /*
587 * Extract the device ID. A device ID has one or more path
588 * components separated by the '/' character.
589 *
590 * e.g. "<frontend vm id>/<frontend dev id>" for backend devices.
591 */
592 id = p;
593 for (component = 0; component < xbs->xbs_id_components; component++) {
594 p = strchr(p, '/');
595 if (p == NULL)
596 break;
597 p++;
598 }
599 if (p != NULL)
600 *p = 0;
601
602 if (*id != 0 && component >= xbs->xbs_id_components - 1) {
603 xenbusb_add_device(xbs->xbs_dev, type, id);
604 taskqueue_enqueue(taskqueue_thread, &xbs->xbs_probe_children);
605 }
606out:
607 free(node, M_XENBUS);
608}
609
619static void
620xenbusb_nop_confighook_cb(void *arg __unused)
621{
622}
623
624/*--------------------------- Public Functions -------------------------------*/
625/*--------- API comments for these methods can be found in xenbusb.h ---------*/
626void
627xenbusb_identify(driver_t *driver __unused, device_t parent)
628{
629 /*
630 * A single instance of each bus type for which we have a driver
631 * is always present in a system operating under Xen.
632 */
633 BUS_ADD_CHILD(parent, 0, driver->name, 0);
634}
635
636int
637xenbusb_add_device(device_t dev, const char *type, const char *id)
638{
639 struct xenbusb_softc *xbs;
640 struct sbuf *devpath_sbuf;
641 char *devpath;
642 struct xenbus_device_ivars *ivars;
643 int error;
644
645 xbs = device_get_softc(dev);
646 devpath_sbuf = sbuf_new_auto();
647 sbuf_printf(devpath_sbuf, "%s/%s/%s", xbs->xbs_node, type, id);
648 sbuf_finish(devpath_sbuf);
649 devpath = sbuf_data(devpath_sbuf);
650
651 ivars = malloc(sizeof(*ivars), M_XENBUS, M_ZERO|M_WAITOK);
652 error = ENXIO;
653
654 if (xs_exists(XST_NIL, devpath, "") != 0) {
655 device_t child;
656 enum xenbus_state state;
657 char *statepath;
658
659 child = xenbusb_device_exists(dev, devpath);
660 if (child != NULL) {
661 /*
662 * We are already tracking this node
663 */
664 error = 0;
665 goto out;
666 }
667
668 state = xenbus_read_driver_state(devpath);
669 if (state != XenbusStateInitialising) {
670 /*
671 * Device is not new, so ignore it. This can
672 * happen if a device is going away after
673 * switching to Closed.
674 */
675 printf("xenbusb_add_device: Device %s ignored. "
676 "State %d\n", devpath, state);
677 error = 0;
678 goto out;
679 }
680
681 sx_init(&ivars->xd_lock, "xdlock");
682 ivars->xd_flags = XDF_CONNECTING;
683 ivars->xd_node = strdup(devpath, M_XENBUS);
684 ivars->xd_node_len = strlen(devpath);
685 ivars->xd_type = strdup(type, M_XENBUS);
686 ivars->xd_state = XenbusStateInitialising;
687
688 error = XENBUSB_GET_OTHEREND_NODE(dev, ivars);
689 if (error) {
690 printf("xenbus_update_device: %s no otherend id\n",
691 devpath);
692 goto out;
693 }
694
695 statepath = malloc(ivars->xd_otherend_path_len
696 + strlen("/state") + 1, M_XENBUS, M_WAITOK);
697 sprintf(statepath, "%s/state", ivars->xd_otherend_path);
698 ivars->xd_otherend_watch.node = statepath;
700 ivars->xd_otherend_watch.callback_data = (uintptr_t)ivars;
701 /*
702 * Other end state node watch, limit to one pending event
703 * to prevent frontends from queuing too many events that
704 * could cause resource starvation.
705 */
706 ivars->xd_otherend_watch.max_pending = 1;
707
708 ivars->xd_local_watch.node = ivars->xd_node;
709 ivars->xd_local_watch.callback = xenbusb_local_watch_cb;
710 ivars->xd_local_watch.callback_data = (uintptr_t)ivars;
711 /*
712 * Watch our local path, only writable by us or a privileged
713 * domain, no need to limit.
714 */
715 ivars->xd_local_watch.max_pending = 0;
716
717 mtx_lock(&xbs->xbs_lock);
719 mtx_unlock(&xbs->xbs_lock);
720
721 child = device_add_child(dev, NULL, -1);
722 ivars->xd_dev = child;
723 device_set_ivars(child, ivars);
724 }
725
726out:
727 sbuf_delete(devpath_sbuf);
728 if (error != 0)
730
731 return (error);
732}
733
734int
735xenbusb_attach(device_t dev, char *bus_node, u_int id_components)
736{
737 struct xenbusb_softc *xbs;
738
739 xbs = device_get_softc(dev);
740 mtx_init(&xbs->xbs_lock, "xenbusb softc lock", NULL, MTX_DEF);
741 xbs->xbs_node = bus_node;
742 xbs->xbs_id_components = id_components;
743 xbs->xbs_dev = dev;
744
745 /*
746 * Since XenBus buses are attached to the XenStore, and
747 * the XenStore does not probe children until after interrupt
748 * services are available, this config hook is used solely
749 * to ensure that the remainder of the boot process (e.g.
750 * mount root) is deferred until child devices are adequately
751 * probed. We unblock the boot process as soon as the
752 * connecting child count in our softc goes to 0.
753 */
755 xbs->xbs_attach_ch.ich_arg = dev;
756 config_intrhook_establish(&xbs->xbs_attach_ch);
757 xbs->xbs_flags |= XBS_ATTACH_CH_ACTIVE;
759
760 /*
761 * The subtree for this bus type may not yet exist
762 * causing initial enumeration to fail. We still
763 * want to return success from our attach though
764 * so that we are ready to handle devices for this
765 * bus when they are dynamically attached to us
766 * by a Xen management action.
767 */
768 (void)xenbusb_enumerate_bus(xbs);
770
771 xbs->xbs_device_watch.node = bus_node;
773 xbs->xbs_device_watch.callback_data = (uintptr_t)xbs;
774 /*
775 * Allow for unlimited pending watches, as those are local paths
776 * either controlled by the guest or only writable by privileged
777 * domains.
778 */
779 xbs->xbs_device_watch.max_pending = 0;
780
781 TASK_INIT(&xbs->xbs_probe_children, 0, xenbusb_probe_children_cb, dev);
782
783 xs_register_watch(&xbs->xbs_device_watch);
784
786
787 return (0);
788}
789
790int
791xenbusb_resume(device_t dev)
792{
793 device_t *kids;
794 struct xenbus_device_ivars *ivars;
795 int i, count, error;
796 char *statepath;
797
798 /*
799 * We must re-examine each device and find the new path for
800 * its backend.
801 */
802 if (device_get_children(dev, &kids, &count) == 0) {
803 for (i = 0; i < count; i++) {
804 if (device_get_state(kids[i]) == DS_NOTPRESENT)
805 continue;
806
807 if (xen_suspend_cancelled) {
808 DEVICE_RESUME(kids[i]);
809 continue;
810 }
811
812 ivars = device_get_ivars(kids[i]);
813
814 xs_unregister_watch(&ivars->xd_otherend_watch);
815 xenbus_set_state(kids[i], XenbusStateInitialising);
816
817 /*
818 * Find the new backend details and
819 * re-register our watch.
820 */
821 error = XENBUSB_GET_OTHEREND_NODE(dev, ivars);
822 if (error)
823 return (error);
824
825 statepath = malloc(ivars->xd_otherend_path_len
826 + strlen("/state") + 1, M_XENBUS, M_WAITOK);
827 sprintf(statepath, "%s/state", ivars->xd_otherend_path);
828
829 free(ivars->xd_otherend_watch.node, M_XENBUS);
830 ivars->xd_otherend_watch.node = statepath;
831
832 DEVICE_RESUME(kids[i]);
833
834 xs_register_watch(&ivars->xd_otherend_watch);
835#if 0
836 /*
837 * Can't do this yet since we are running in
838 * the xenwatch thread and if we sleep here,
839 * we will stop delivering watch notifications
840 * and the device will never come back online.
841 */
842 sx_xlock(&ivars->xd_lock);
843 while (ivars->xd_state != XenbusStateClosed
844 && ivars->xd_state != XenbusStateConnected)
845 sx_sleep(&ivars->xd_state, &ivars->xd_lock,
846 0, "xdresume", 0);
847 sx_xunlock(&ivars->xd_lock);
848#endif
849 }
850 free(kids, M_TEMP);
851 }
852
853 return (0);
854}
855
856int
857xenbusb_print_child(device_t dev, device_t child)
858{
859 struct xenbus_device_ivars *ivars = device_get_ivars(child);
860 int retval = 0;
861
862 retval += bus_print_child_header(dev, child);
863 retval += printf(" at %s", ivars->xd_node);
864 retval += bus_print_child_footer(dev, child);
865
866 return (retval);
867}
868
869int
870xenbusb_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
871{
872 struct xenbus_device_ivars *ivars = device_get_ivars(child);
873
874 switch (index) {
875 case XENBUS_IVAR_NODE:
876 *result = (uintptr_t) ivars->xd_node;
877 return (0);
878
879 case XENBUS_IVAR_TYPE:
880 *result = (uintptr_t) ivars->xd_type;
881 return (0);
882
884 *result = (uintptr_t) ivars->xd_state;
885 return (0);
886
888 *result = (uintptr_t) ivars->xd_otherend_id;
889 return (0);
890
892 *result = (uintptr_t) ivars->xd_otherend_path;
893 return (0);
894 }
895
896 return (ENOENT);
897}
898
899int
900xenbusb_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
901{
902 struct xenbus_device_ivars *ivars = device_get_ivars(child);
903 enum xenbus_state newstate;
904 int currstate;
905
906 switch (index) {
908 {
909 int error;
910
911 newstate = (enum xenbus_state)value;
912 sx_xlock(&ivars->xd_lock);
913 if (ivars->xd_state == newstate) {
914 error = 0;
915 goto out;
916 }
917
918 error = xs_scanf(XST_NIL, ivars->xd_node, "state",
919 NULL, "%d", &currstate);
920 if (error)
921 goto out;
922
923 do {
924 error = xs_printf(XST_NIL, ivars->xd_node, "state",
925 "%d", newstate);
926 } while (error == EAGAIN);
927 if (error) {
928 /*
929 * Avoid looping through xenbus_dev_fatal()
930 * which calls xenbus_write_ivar to set the
931 * state to closing.
932 */
933 if (newstate != XenbusStateClosing)
934 xenbus_dev_fatal(dev, error,
935 "writing new state");
936 goto out;
937 }
938 ivars->xd_state = newstate;
939
940 if ((ivars->xd_flags & XDF_CONNECTING) != 0
941 && (newstate == XenbusStateClosed
942 || newstate == XenbusStateConnected)) {
943 struct xenbusb_softc *xbs;
944
945 ivars->xd_flags &= ~XDF_CONNECTING;
946 xbs = device_get_softc(dev);
948 }
949
950 wakeup(&ivars->xd_state);
951 out:
952 sx_xunlock(&ivars->xd_lock);
953 return (error);
954 }
955
956 case XENBUS_IVAR_NODE:
957 case XENBUS_IVAR_TYPE:
960 /*
961 * These variables are read-only.
962 */
963 return (EINVAL);
964 }
965
966 return (ENOENT);
967}
968
969void
970xenbusb_otherend_changed(device_t bus, device_t child, enum xenbus_state state)
971{
972 XENBUS_OTHEREND_CHANGED(child, state);
973}
974
975void
976xenbusb_localend_changed(device_t bus, device_t child, const char *path)
977{
978
979 if (strcmp(path, "/state") != 0) {
980 struct xenbus_device_ivars *ivars;
981
982 ivars = device_get_ivars(child);
983 sx_xlock(&ivars->xd_lock);
985 sx_xunlock(&ivars->xd_lock);
986 }
987 XENBUS_LOCALEND_CHANGED(child, path);
988}
struct xs_watch xd_local_watch
Definition: xenbusb.h:139
char * xd_otherend_path
Definition: xenbusb.h:174
struct xs_watch xd_otherend_watch
Definition: xenbusb.h:131
enum xenbus_state xd_state
Definition: xenbusb.h:165
xenbus_dev_flag xd_flags
Definition: xenbusb.h:145
device_t xd_dev
Definition: xenbusb.h:148
int xd_otherend_path_len
Definition: xenbusb.h:177
struct sx xd_lock
Definition: xenbusb.h:142
Container for all state needed to manage a Xenbus Bus attachment.
Definition: xenbusb.h:62
struct intr_config_hook xbs_attach_ch
Definition: xenbusb.h:87
struct xs_watch xbs_device_watch
Definition: xenbusb.h:68
const char * xbs_node
Definition: xenbusb.h:103
device_t xbs_dev
Definition: xenbusb.h:97
xenbusb_softc_flag xbs_flags
Definition: xenbusb.h:74
u_int xbs_connecting_children
Definition: xenbusb.h:94
u_int xbs_id_components
Definition: xenbusb.h:109
struct task xbs_probe_children
Definition: xenbusb.h:80
struct mtx xbs_lock
Definition: xenbusb.h:71
XenbusState xenbus_read_driver_state(const char *path)
Definition: xenbus.c:185
int xenbusb_attach(device_t dev, char *bus_node, u_int id_components)
Perform common XenBus bus attach processing.
Definition: xenbusb.c:735
static void xenbusb_local_watch_cb(struct xs_watch *watch, const char **vec, unsigned int vec_size __unused)
Definition: xenbusb.c:171
static void xenbusb_otherend_watch_cb(struct xs_watch *watch, const char **vec, unsigned int vec_size __unused)
Definition: xenbusb.c:133
int xenbusb_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
Common XenBus child instance variable read access method.
Definition: xenbusb.c:870
static void xenbusb_release_confighook(struct xenbusb_softc *xbs)
Decrement the number of XenBus child devices in the connecting state by one and release the xbs_attch...
Definition: xenbusb.c:414
int xenbusb_print_child(device_t dev, device_t child)
Pretty-prints information about a child of a XenBus bus.
Definition: xenbusb.c:857
static device_t xenbusb_device_exists(device_t dev, const char *node)
Definition: xenbusb.c:205
static int xenbusb_enumerate_bus(struct xenbusb_softc *xbs)
Enumerate the devices on a XenBus bus and register them with the NewBus device tree.
Definition: xenbusb.c:282
void xenbusb_localend_changed(device_t bus, device_t child, const char *path)
Common XenBus method implementing responses to local XenStore changes.
Definition: xenbusb.c:976
static void xenbusb_free_child_ivars(struct xenbus_device_ivars *ivars)
Deallocate XenBus device instance variables.
Definition: xenbusb.c:85
static void xenbusb_verify_device(device_t dev, device_t child)
Definition: xenbusb.c:255
static int xenbusb_probe_children(device_t dev)
Verify the existence of attached device instances and perform probe/attach processing for newly arriv...
Definition: xenbusb.c:440
static int xenbusb_device_sysctl_handler(SYSCTL_HANDLER_ARGS)
Definition: xenbusb.c:305
int xenbusb_add_device(device_t dev, const char *type, const char *id)
Attempt to add a XenBus device instance to this XenBus bus.
Definition: xenbusb.c:637
void xenbusb_identify(driver_t *driver __unused, device_t parent)
Identify instances of this device type in the system.
Definition: xenbusb.c:627
void xenbusb_otherend_changed(device_t bus, device_t child, enum xenbus_state state)
Common XenBus method implementing responses to peer state changes.
Definition: xenbusb.c:970
static void xenbusb_device_sysctl_init(device_t dev)
Definition: xenbusb.c:341
static void xenbusb_nop_confighook_cb(void *arg __unused)
Interrupt configuration hook callback associated with xbs_attch_ch.
Definition: xenbusb.c:620
static void xenbusb_probe_children_cb(void *arg, int pending __unused)
Task callback function to perform XenBus probe operations from a known safe context.
Definition: xenbusb.c:532
int xenbusb_resume(device_t dev)
Perform common XenBus bus resume handling.
Definition: xenbusb.c:791
static void xenbusb_devices_changed(struct xs_watch *watch, const char **vec, unsigned int len)
XenStore watch callback for the root node of the XenStore subtree representing a XenBus.
Definition: xenbusb.c:554
int xenbusb_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
Common XenBus child instance variable write access method.
Definition: xenbusb.c:900
@ XDF_CONNECTING
Definition: xenbusb.h:121
Datastructures and function declarations for usedby device drivers operating on the XenBus.
void void void xenbus_dev_fatal(device_t dev, int err, const char *fmt,...) __attribute__((format(printf
@ XENBUS_IVAR_STATE
Definition: xenbusvar.h:71
@ XENBUS_IVAR_OTHEREND_PATH
Definition: xenbusvar.h:81
@ XENBUS_IVAR_NODE
Definition: xenbusvar.h:61
@ XENBUS_IVAR_OTHEREND_ID
Definition: xenbusvar.h:76
@ XENBUS_IVAR_TYPE
Definition: xenbusvar.h:66
void void void void const char * xenbus_strstate(enum xenbus_state state)