Deleted Added
full compact
xenbusb.c (217566) xenbusb.c (222975)
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

--- 38 unchanged lines hidden (view full) ---

47 * xbd0
48 * xbd1
49 * xenbusb_back0/
50 * xbbd0
51 * xnb0
52 * xnb1
53 */
54#include <sys/cdefs.h>
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

--- 38 unchanged lines hidden (view full) ---

47 * xbd0
48 * xbd1
49 * xenbusb_back0/
50 * xbbd0
51 * xnb0
52 * xnb1
53 */
54#include <sys/cdefs.h>
55__FBSDID("$FreeBSD: head/sys/xen/xenbus/xenbusb.c 217566 2011-01-19 00:57:58Z mdf $");
55__FBSDID("$FreeBSD: head/sys/xen/xenbus/xenbusb.c 222975 2011-06-11 04:59:01Z gibbs $");
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>

--- 21 unchanged lines hidden (view full) ---

85xenbusb_free_child_ivars(struct xenbus_device_ivars *ivars)
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
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>

--- 21 unchanged lines hidden (view full) ---

85xenbusb_free_child_ivars(struct xenbus_device_ivars *ivars)
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
93 if (ivars->xd_node != NULL) {
94 free(ivars->xd_node, M_XENBUS);
95 ivars->xd_node = NULL;
96 }
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;
97
98 if (ivars->xd_type != NULL) {
99 free(ivars->xd_type, M_XENBUS);
100 ivars->xd_type = NULL;
101 }
102
103 if (ivars->xd_otherend_path != NULL) {
104 free(ivars->xd_otherend_path, M_XENBUS);
105 ivars->xd_otherend_path = NULL;
106 }
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;
107
108 free(ivars, M_XENBUS);
109}
110
111/**
112 * XenBus watch callback registered against the "state" XenStore
113 * node of the other-end of a split device connection.
114 *
115 * This callback is invoked whenever the state of a device instance's
116 * peer changes.
117 *
118 * \param watch The xs_watch object used to register this callback
119 * function.
120 * \param vec An array of pointers to NUL terminated strings containing
121 * watch event data. The vector should be indexed via the
122 * xs_watch_type enum in xs_wire.h.
123 * \param vec_size The number of elements in vec.
114
115 free(ivars, M_XENBUS);
116}
117
118/**
119 * XenBus watch callback registered against the "state" XenStore
120 * node of the other-end of a split device connection.
121 *
122 * This callback is invoked whenever the state of a device instance's
123 * peer changes.
124 *
125 * \param watch The xs_watch object used to register this callback
126 * function.
127 * \param vec An array of pointers to NUL terminated strings containing
128 * watch event data. The vector should be indexed via the
129 * xs_watch_type enum in xs_wire.h.
130 * \param vec_size The number of elements in vec.
124 *
125 * \return The device_t of the found device if any, or NULL.
126 *
127 * \note device_t is a pointer type, so it can be compared against
128 * NULL for validity.
129 */
130static void
131 */
132static void
131xenbusb_otherend_changed(struct xs_watch *watch, const char **vec,
133xenbusb_otherend_watch_cb(struct xs_watch *watch, const char **vec,
132 unsigned int vec_size __unused)
133{
134 struct xenbus_device_ivars *ivars;
134 unsigned int vec_size __unused)
135{
136 struct xenbus_device_ivars *ivars;
135 device_t dev;
137 device_t child;
138 device_t bus;
139 const char *path;
136 enum xenbus_state newstate;
137
140 enum xenbus_state newstate;
141
138 ivars = (struct xenbus_device_ivars *) watch;
139 dev = ivars->xd_dev;
142 ivars = (struct xenbus_device_ivars *)watch->callback_data;
143 child = ivars->xd_dev;
144 bus = device_get_parent(child);
140
145
141 if (!ivars->xd_otherend_path
142 || strncmp(ivars->xd_otherend_path, vec[XS_WATCH_PATH],
143 strlen(ivars->xd_otherend_path)))
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))
144 return;
145
146 newstate = xenbus_read_driver_state(ivars->xd_otherend_path);
149 return;
150
151 newstate = xenbus_read_driver_state(ivars->xd_otherend_path);
147 XENBUS_OTHEREND_CHANGED(dev, newstate);
152 XENBUSB_OTHEREND_CHANGED(bus, child, newstate);
148}
149
150/**
153}
154
155/**
156 * XenBus watch callback registered against the XenStore sub-tree
157 * represnting the local half of a split device connection.
158 *
159 * This callback is invoked whenever any XenStore data in the subtree
160 * is modified, either by us or another privledged domain.
161 *
162 * \param watch The xs_watch object used to register this callback
163 * function.
164 * \param vec An array of pointers to NUL terminated strings containing
165 * watch event data. The vector should be indexed via the
166 * xs_watch_type enum in xs_wire.h.
167 * \param vec_size The number of elements in vec.
168 *
169 */
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
191/**
151 * Search our internal record of configured devices (not the XenStore)
152 * to determine if the XenBus device indicated by \a node is known to
153 * the system.
154 *
155 * \param dev The XenBus bus instance to search for device children.
156 * \param node The XenStore node path for the device to find.
157 *
158 * \return The device_t of the found device if any, or NULL.

--- 29 unchanged lines hidden (view full) ---

188xenbusb_delete_child(device_t dev, device_t child)
189{
190 struct xenbus_device_ivars *ivars;
191
192 ivars = device_get_ivars(child);
193
194 /*
195 * We no longer care about the otherend of the
192 * Search our internal record of configured devices (not the XenStore)
193 * to determine if the XenBus device indicated by \a node is known to
194 * the system.
195 *
196 * \param dev The XenBus bus instance to search for device children.
197 * \param node The XenStore node path for the device to find.
198 *
199 * \return The device_t of the found device if any, or NULL.

--- 29 unchanged lines hidden (view full) ---

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
196 * connection. Cancel the watch now so that we
237 * connection. Cancel the watches now so that we
197 * don't try to handle an event for a partially
198 * detached child.
199 */
200 if (ivars->xd_otherend_watch.node != NULL)
201 xs_unregister_watch(&ivars->xd_otherend_watch);
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);
202
203 device_delete_child(dev, child);
204 xenbusb_free_child_ivars(ivars);
205}
206
207/**
208 * \param dev The NewBus device representing this XenBus bus.
209 * \param child The NewBus device representing a child of dev%'s XenBus bus.

--- 206 unchanged lines hidden (view full) ---

416
417 /*
418 * Now that we have a driver managing this device
419 * that can receive otherend state change events,
420 * hook up a watch for them.
421 */
422 ivars = device_get_ivars(kids[i]);
423 xs_register_watch(&ivars->xd_otherend_watch);
245
246 device_delete_child(dev, child);
247 xenbusb_free_child_ivars(ivars);
248}
249
250/**
251 * \param dev The NewBus device representing this XenBus bus.
252 * \param child The NewBus device representing a child of dev%'s XenBus bus.

--- 206 unchanged lines hidden (view full) ---

459
460 /*
461 * Now that we have a driver managing this device
462 * that can receive otherend state change events,
463 * hook up a watch for them.
464 */
465 ivars = device_get_ivars(kids[i]);
466 xs_register_watch(&ivars->xd_otherend_watch);
467 xs_register_watch(&ivars->xd_local_watch);
424 }
425 free(kids, M_TEMP);
426 }
427
428 return (0);
429}
430
431/**

--- 38 unchanged lines hidden (view full) ---

470 device_t dev;
471 char *node;
472 char *bus;
473 char *type;
474 char *id;
475 char *p;
476 u_int component;
477
468 }
469 free(kids, M_TEMP);
470 }
471
472 return (0);
473}
474
475/**

--- 38 unchanged lines hidden (view full) ---

514 device_t dev;
515 char *node;
516 char *bus;
517 char *type;
518 char *id;
519 char *p;
520 u_int component;
521
478 xbs = (struct xenbusb_softc *)watch;
522 xbs = (struct xenbusb_softc *)watch->callback_data;
479 dev = xbs->xbs_dev;
480
481 if (len <= XS_WATCH_PATH) {
482 device_printf(dev, "xenbusb_devices_changed: "
483 "Short Event Data.\n");
484 return;
485 }
486

--- 128 unchanged lines hidden (view full) ---

615 "State %d\n", devpath, state);
616 error = 0;
617 goto out;
618 }
619
620 sx_init(&ivars->xd_lock, "xdlock");
621 ivars->xd_flags = XDF_CONNECTING;
622 ivars->xd_node = strdup(devpath, M_XENBUS);
523 dev = xbs->xbs_dev;
524
525 if (len <= XS_WATCH_PATH) {
526 device_printf(dev, "xenbusb_devices_changed: "
527 "Short Event Data.\n");
528 return;
529 }
530

--- 128 unchanged lines hidden (view full) ---

659 "State %d\n", devpath, state);
660 error = 0;
661 goto out;
662 }
663
664 sx_init(&ivars->xd_lock, "xdlock");
665 ivars->xd_flags = XDF_CONNECTING;
666 ivars->xd_node = strdup(devpath, M_XENBUS);
667 ivars->xd_node_len = strlen(devpath);
623 ivars->xd_type = strdup(type, M_XENBUS);
624 ivars->xd_state = XenbusStateInitialising;
625
626 error = XENBUSB_GET_OTHEREND_NODE(dev, ivars);
627 if (error) {
628 printf("xenbus_update_device: %s no otherend id\n",
629 devpath);
630 goto out;
631 }
632
668 ivars->xd_type = strdup(type, M_XENBUS);
669 ivars->xd_state = XenbusStateInitialising;
670
671 error = XENBUSB_GET_OTHEREND_NODE(dev, ivars);
672 if (error) {
673 printf("xenbus_update_device: %s no otherend id\n",
674 devpath);
675 goto out;
676 }
677
633 statepath = malloc(strlen(ivars->xd_otherend_path)
678 statepath = malloc(ivars->xd_otherend_path_len
634 + strlen("/state") + 1, M_XENBUS, M_WAITOK);
635 sprintf(statepath, "%s/state", ivars->xd_otherend_path);
679 + strlen("/state") + 1, M_XENBUS, M_WAITOK);
680 sprintf(statepath, "%s/state", ivars->xd_otherend_path);
636
637 ivars->xd_otherend_watch.node = statepath;
681 ivars->xd_otherend_watch.node = statepath;
638 ivars->xd_otherend_watch.callback = xenbusb_otherend_changed;
682 ivars->xd_otherend_watch.callback = xenbusb_otherend_watch_cb;
683 ivars->xd_otherend_watch.callback_data = (uintptr_t)ivars;
639
684
685 ivars->xd_local_watch.node = ivars->xd_node;
686 ivars->xd_local_watch.callback = xenbusb_local_watch_cb;
687 ivars->xd_local_watch.callback_data = (uintptr_t)ivars;
688
640 mtx_lock(&xbs->xbs_lock);
641 xbs->xbs_connecting_children++;
642 mtx_unlock(&xbs->xbs_lock);
643
644 child = device_add_child(dev, NULL, -1);
645 ivars->xd_dev = child;
646 device_set_ivars(child, ivars);
647 }

--- 40 unchanged lines hidden (view full) ---

688 * bus when they are dynamically attached to us
689 * by a Xen management action.
690 */
691 (void)xenbusb_enumerate_bus(xbs);
692 xenbusb_probe_children(dev);
693
694 xbs->xbs_device_watch.node = bus_node;
695 xbs->xbs_device_watch.callback = xenbusb_devices_changed;
689 mtx_lock(&xbs->xbs_lock);
690 xbs->xbs_connecting_children++;
691 mtx_unlock(&xbs->xbs_lock);
692
693 child = device_add_child(dev, NULL, -1);
694 ivars->xd_dev = child;
695 device_set_ivars(child, ivars);
696 }

--- 40 unchanged lines hidden (view full) ---

737 * bus when they are dynamically attached to us
738 * by a Xen management action.
739 */
740 (void)xenbusb_enumerate_bus(xbs);
741 xenbusb_probe_children(dev);
742
743 xbs->xbs_device_watch.node = bus_node;
744 xbs->xbs_device_watch.callback = xenbusb_devices_changed;
745 xbs->xbs_device_watch.callback_data = (uintptr_t)xbs;
696
697 TASK_INIT(&xbs->xbs_probe_children, 0, xenbusb_probe_children_cb, dev);
698
699 xs_register_watch(&xbs->xbs_device_watch);
700
701 xenbusb_release_confighook(xbs);
702
703 return (0);

--- 26 unchanged lines hidden (view full) ---

730 * re-register our watch.
731 */
732 error = XENBUSB_GET_OTHEREND_NODE(dev, ivars);
733 if (error)
734 return (error);
735
736 DEVICE_RESUME(kids[i]);
737
746
747 TASK_INIT(&xbs->xbs_probe_children, 0, xenbusb_probe_children_cb, dev);
748
749 xs_register_watch(&xbs->xbs_device_watch);
750
751 xenbusb_release_confighook(xbs);
752
753 return (0);

--- 26 unchanged lines hidden (view full) ---

780 * re-register our watch.
781 */
782 error = XENBUSB_GET_OTHEREND_NODE(dev, ivars);
783 if (error)
784 return (error);
785
786 DEVICE_RESUME(kids[i]);
787
738 statepath = malloc(strlen(ivars->xd_otherend_path)
788 statepath = malloc(ivars->xd_otherend_path_len
739 + strlen("/state") + 1, M_XENBUS, M_WAITOK);
740 sprintf(statepath, "%s/state", ivars->xd_otherend_path);
741
742 free(ivars->xd_otherend_watch.node, M_XENBUS);
743 ivars->xd_otherend_watch.node = statepath;
744 xs_register_watch(&ivars->xd_otherend_watch);
745
746#if 0

--- 67 unchanged lines hidden (view full) ---

814 enum xenbus_state newstate;
815 int currstate;
816
817 switch (index) {
818 case XENBUS_IVAR_STATE:
819 {
820 int error;
821
789 + strlen("/state") + 1, M_XENBUS, M_WAITOK);
790 sprintf(statepath, "%s/state", ivars->xd_otherend_path);
791
792 free(ivars->xd_otherend_watch.node, M_XENBUS);
793 ivars->xd_otherend_watch.node = statepath;
794 xs_register_watch(&ivars->xd_otherend_watch);
795
796#if 0

--- 67 unchanged lines hidden (view full) ---

864 enum xenbus_state newstate;
865 int currstate;
866
867 switch (index) {
868 case XENBUS_IVAR_STATE:
869 {
870 int error;
871
822 newstate = (enum xenbus_state) value;
872 newstate = (enum xenbus_state)value;
823 sx_xlock(&ivars->xd_lock);
824 if (ivars->xd_state == newstate) {
825 error = 0;
826 goto out;
827 }
828
829 error = xs_scanf(XST_NIL, ivars->xd_node, "state",
830 NULL, "%d", &currstate);

--- 40 unchanged lines hidden (view full) ---

871 /*
872 * These variables are read-only.
873 */
874 return (EINVAL);
875 }
876
877 return (ENOENT);
878}
873 sx_xlock(&ivars->xd_lock);
874 if (ivars->xd_state == newstate) {
875 error = 0;
876 goto out;
877 }
878
879 error = xs_scanf(XST_NIL, ivars->xd_node, "state",
880 NULL, "%d", &currstate);

--- 40 unchanged lines hidden (view full) ---

921 /*
922 * These variables are read-only.
923 */
924 return (EINVAL);
925 }
926
927 return (ENOENT);
928}
929
930void
931xenbusb_otherend_changed(device_t bus, device_t child, enum xenbus_state state)
932{
933 XENBUS_OTHEREND_CHANGED(child, state);
934}
935
936void
937xenbusb_localend_changed(device_t bus, device_t child, const char *path)
938{
939
940 if (strcmp(path, "/state") != 0) {
941 struct xenbus_device_ivars *ivars;
942
943 ivars = device_get_ivars(child);
944 sx_xlock(&ivars->xd_lock);
945 ivars->xd_state = xenbus_read_driver_state(ivars->xd_node);
946 sx_xunlock(&ivars->xd_lock);
947 }
948 XENBUS_LOCALEND_CHANGED(child, path);
949}