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} |
|