The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/xen/xenbus/xenbusb.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 
   30 /**
   31  * \file xenbusb.c
   32  *
   33  * \brief Shared support functions for managing the NewBus buses that contain
   34  *        Xen front and back end device instances.
   35  *
   36  * The NewBus implementation of XenBus attaches a xenbusb_front and xenbusb_back
   37  * child bus to the xenstore device.  This strategy allows the small differences
   38  * in the handling of XenBus operations for front and back devices to be handled
   39  * as overrides in xenbusb_front/back.c.  Front and back specific device
   40  * classes are also provided so device drivers can register for the devices they
   41  * can handle without the need to filter within their probe routines.  The
   42  * net result is a device hierarchy that might look like this:
   43  *
   44  * xenstore0/
   45  *           xenbusb_front0/
   46  *                         xn0
   47  *                         xbd0
   48  *                         xbd1
   49  *           xenbusb_back0/
   50  *                        xbbd0
   51  *                        xnb0
   52  *                        xnb1
   53  */
   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/xen/xen-os.h>
   71 #include <machine/stdarg.h>
   72 
   73 #include <xen/gnttab.h>
   74 #include <xen/xenstore/xenstorevar.h>
   75 #include <xen/xenbus/xenbusb.h>
   76 #include <xen/xenbus/xenbusvar.h>
   77 
   78 /*------------------------- Private Functions --------------------------------*/
   79 /**
   80  * \brief Deallocate XenBus device instance variables.
   81  *
   82  * \param ivars  The instance variable block to free.
   83  */
   84 static void
   85 xenbusb_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 
   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 
  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.
  131  */
  132 static void
  133 xenbusb_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 
  151         newstate = xenbus_read_driver_state(ivars->xd_otherend_path);
  152         XENBUSB_OTHEREND_CHANGED(bus, child, newstate);
  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  */
  170 static void
  171 xenbusb_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 /**
  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.
  200  *
  201  * \note device_t is a pointer type, so it can be compared against
  202  *       NULL for validity. 
  203  */
  204 static device_t
  205 xenbusb_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 
  228 static void
  229 xenbusb_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);
  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.
  253  */
  254 static void
  255 xenbusb_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 
  266 /**
  267  * \brief Enumerate the devices on a XenBus bus and register them with
  268  *        the NewBus device tree.
  269  *
  270  * xenbusb_enumerate_bus() will create entries (in state DS_NOTPRESENT)
  271  * for nodes that appear in the XenStore, but will not invoke probe/attach
  272  * operations on drivers.  Probe/Attach processing must be separately
  273  * performed via an invocation of xenbusb_probe_children().  This is usually
  274  * done via the xbs_probe_children task.
  275  *
  276  * \param xbs  XenBus Bus device softc of the owner of the bus to enumerate.
  277  *
  278  * \return  On success, 0. Otherwise an errno value indicating the
  279  *          type of failure.
  280  */
  281 static int
  282 xenbusb_enumerate_bus(struct xenbusb_softc *xbs)
  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 
  301 /**
  302  * Handler for all generic XenBus device systcl nodes.
  303  */
  304 static int
  305 xenbusb_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;
  318         case XENBUS_IVAR_STATE:
  319                 value = xenbus_strstate(xenbus_get_state(dev));
  320                 break;
  321         case XENBUS_IVAR_OTHEREND_ID:
  322                 return (sysctl_handle_int(oidp, NULL,
  323                                           xenbus_get_otherend_id(dev),
  324                                           req));
  325                 /* NOTREACHED */
  326         case XENBUS_IVAR_OTHEREND_PATH:
  327                 value = xenbus_get_otherend_path(dev);
  328                 break;
  329         default:
  330                 return (EINVAL);
  331         }
  332         return (SYSCTL_OUT_STR(req, value));
  333 }
  334 
  335 /**
  336  * Create read-only systcl nodes for xenbusb device ivar data.
  337  *
  338  * \param dev  The XenBus device instance to register with sysctl.
  339  */
  340 static void
  341 xenbusb_device_sysctl_init(device_t dev)
  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,
  355                         XENBUS_IVAR_NODE,
  356                         xenbusb_device_sysctl_handler,
  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,
  366                         XENBUS_IVAR_TYPE,
  367                         xenbusb_device_sysctl_handler,
  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,
  377                         XENBUS_IVAR_STATE,
  378                         xenbusb_device_sysctl_handler,
  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,
  388                         XENBUS_IVAR_OTHEREND_ID,
  389                         xenbusb_device_sysctl_handler,
  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,
  399                         XENBUS_IVAR_OTHEREND_PATH,
  400                         xenbusb_device_sysctl_handler,
  401                         "A",
  402                         "XenStore path to peer device");
  403 }
  404 
  405 /**
  406  * \brief Decrement the number of XenBus child devices in the
  407  *        connecting state by one and release the xbs_attch_ch
  408  *        interrupt configuration hook if the connecting count
  409  *        drops to zero.
  410  *
  411  * \param xbs  XenBus Bus device softc of the owner of the bus to enumerate.
  412  */
  413 static void
  414 xenbusb_release_confighook(struct xenbusb_softc *xbs)
  415 {
  416         mtx_lock(&xbs->xbs_lock);
  417         KASSERT(xbs->xbs_connecting_children > 0,
  418                 ("Connecting device count error\n"));
  419         xbs->xbs_connecting_children--;
  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 
  430 /**
  431  * \brief Verify the existance of attached device instances and perform
  432  *        probe/attach processing for newly arrived devices.
  433  *
  434  * \param dev  The NewBus device representing this XenBus bus.
  435  *
  436  * \return  On success, 0. Otherwise an errno value indicating the
  437  *          type of failure.
  438  */
  439 static int
  440 xenbusb_probe_children(device_t dev)
  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);
  477                                 xenbusb_release_confighook(xbs);
  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                          */
  505                         xenbusb_device_sysctl_init(kids[i]);
  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 
  522 /**
  523  * \brief Task callback function to perform XenBus probe operations
  524  *        from a known safe context.
  525  *
  526  * \param arg      The NewBus device_t representing the bus instance to
  527  *                 on which to perform probe processing.
  528  * \param pending  The number of times this task was queued before it could
  529  *                 be run.
  530  */
  531 static void
  532 xenbusb_probe_children_cb(void *arg, int pending __unused)
  533 {
  534         device_t dev = (device_t)arg;
  535 
  536         /*
  537          * Hold Giant until the Giant free newbus changes are committed.
  538          */
  539         mtx_lock(&Giant);
  540         xenbusb_probe_children(dev);
  541         mtx_unlock(&Giant);
  542 }
  543 
  544 /**
  545  * \brief XenStore watch callback for the root node of the XenStore
  546  *        subtree representing a XenBus.
  547  *
  548  * This callback performs, or delegates to the xbs_probe_children task,
  549  * all processing necessary to handle dynmaic device arrival and departure
  550  * events from a XenBus.
  551  *
  552  * \param watch  The XenStore watch object associated with this callback.
  553  * \param vec    The XenStore watch event data.
  554  * \param len    The number of fields in the event data stream.
  555  */
  556 static void
  557 xenbusb_devices_changed(struct xs_watch *watch, const char **vec,
  558                         unsigned int len)
  559 {
  560         struct xenbusb_softc *xbs;
  561         device_t dev;
  562         char *node;
  563         char *type;
  564         char *id;
  565         char *p;
  566         u_int component;
  567 
  568         xbs = (struct xenbusb_softc *)watch->callback_data;
  569         dev = xbs->xbs_dev;
  570 
  571         if (len <= XS_WATCH_PATH) {
  572                 device_printf(dev, "xenbusb_devices_changed: "
  573                               "Short Event Data.\n");
  574                 return;
  575         }
  576 
  577         node = strdup(vec[XS_WATCH_PATH], M_XENBUS);
  578         p = strchr(node, '/');
  579         if (p == NULL)
  580                 goto out;
  581         *p = 0;
  582         type = p + 1;
  583 
  584         p = strchr(type, '/');
  585         if (p == NULL)
  586                 goto out;
  587         *p++ = 0;
  588 
  589         /*
  590          * Extract the device ID.  A device ID has one or more path
  591          * components separated by the '/' character.
  592          *
  593          * e.g. "<frontend vm id>/<frontend dev id>" for backend devices.
  594          */
  595         id = p;
  596         for (component = 0; component < xbs->xbs_id_components; component++) {
  597                 p = strchr(p, '/');
  598                 if (p == NULL)
  599                         break;
  600                 p++;
  601         }
  602         if (p != NULL)
  603                 *p = 0;
  604 
  605         if (*id != 0 && component >= xbs->xbs_id_components - 1) {
  606                 xenbusb_add_device(xbs->xbs_dev, type, id);
  607                 taskqueue_enqueue(taskqueue_thread, &xbs->xbs_probe_children);
  608         }
  609 out:
  610         free(node, M_XENBUS);
  611 }
  612 
  613 /**
  614  * \brief Interrupt configuration hook callback associated with xbs_attch_ch.
  615  *
  616  * Since interrupts are always functional at the time of XenBus configuration,
  617  * there is nothing to be done when the callback occurs.  This hook is only
  618  * registered to hold up boot processing while XenBus devices come online.
  619  * 
  620  * \param arg  Unused configuration hook callback argument.
  621  */
  622 static void
  623 xenbusb_nop_confighook_cb(void *arg __unused)
  624 {
  625 }
  626 
  627 /*--------------------------- Public Functions -------------------------------*/
  628 /*--------- API comments for these methods can be found in xenbusb.h ---------*/
  629 void
  630 xenbusb_identify(driver_t *driver __unused, device_t parent)
  631 {
  632         /*
  633          * A single instance of each bus type for which we have a driver
  634          * is always present in a system operating under Xen.
  635          */
  636         BUS_ADD_CHILD(parent, 0, driver->name, 0);
  637 }
  638 
  639 int
  640 xenbusb_add_device(device_t dev, const char *type, const char *id)
  641 {
  642         struct xenbusb_softc *xbs;
  643         struct sbuf *devpath_sbuf;
  644         char *devpath;
  645         struct xenbus_device_ivars *ivars;
  646         int error;
  647 
  648         xbs = device_get_softc(dev);
  649         devpath_sbuf = sbuf_new_auto();
  650         sbuf_printf(devpath_sbuf, "%s/%s/%s", xbs->xbs_node, type, id);
  651         sbuf_finish(devpath_sbuf);
  652         devpath = sbuf_data(devpath_sbuf);
  653 
  654         ivars = malloc(sizeof(*ivars), M_XENBUS, M_ZERO|M_WAITOK);
  655         error = ENXIO;
  656 
  657         if (xs_exists(XST_NIL, devpath, "") != 0) {
  658                 device_t child;
  659                 enum xenbus_state state;
  660                 char *statepath;
  661 
  662                 child = xenbusb_device_exists(dev, devpath);
  663                 if (child != NULL) {
  664                         /*
  665                          * We are already tracking this node
  666                          */
  667                         error = 0;
  668                         goto out;
  669                 }
  670                         
  671                 state = xenbus_read_driver_state(devpath);
  672                 if (state != XenbusStateInitialising) {
  673                         /*
  674                          * Device is not new, so ignore it. This can
  675                          * happen if a device is going away after
  676                          * switching to Closed.
  677                          */
  678                         printf("xenbusb_add_device: Device %s ignored. "
  679                                "State %d\n", devpath, state);
  680                         error = 0;
  681                         goto out;
  682                 }
  683 
  684                 sx_init(&ivars->xd_lock, "xdlock");
  685                 ivars->xd_flags = XDF_CONNECTING;
  686                 ivars->xd_node = strdup(devpath, M_XENBUS);
  687                 ivars->xd_node_len = strlen(devpath);
  688                 ivars->xd_type  = strdup(type, M_XENBUS);
  689                 ivars->xd_state = XenbusStateInitialising;
  690 
  691                 error = XENBUSB_GET_OTHEREND_NODE(dev, ivars);
  692                 if (error) {
  693                         printf("xenbus_update_device: %s no otherend id\n",
  694                             devpath); 
  695                         goto out;
  696                 }
  697 
  698                 statepath = malloc(ivars->xd_otherend_path_len
  699                     + strlen("/state") + 1, M_XENBUS, M_WAITOK);
  700                 sprintf(statepath, "%s/state", ivars->xd_otherend_path);
  701                 ivars->xd_otherend_watch.node = statepath;
  702                 ivars->xd_otherend_watch.callback = xenbusb_otherend_watch_cb;
  703                 ivars->xd_otherend_watch.callback_data = (uintptr_t)ivars;
  704                 /*
  705                  * Other end state node watch, limit to one pending event
  706                  * to prevent frontends from queuing too many events that
  707                  * could cause resource starvation.
  708                  */
  709                 ivars->xd_otherend_watch.max_pending = 1;
  710 
  711                 ivars->xd_local_watch.node = ivars->xd_node;
  712                 ivars->xd_local_watch.callback = xenbusb_local_watch_cb;
  713                 ivars->xd_local_watch.callback_data = (uintptr_t)ivars;
  714                 /*
  715                  * Watch our local path, only writable by us or a privileged
  716                  * domain, no need to limit.
  717                  */
  718                 ivars->xd_local_watch.max_pending = 0;
  719 
  720                 mtx_lock(&xbs->xbs_lock);
  721                 xbs->xbs_connecting_children++;
  722                 mtx_unlock(&xbs->xbs_lock);
  723 
  724                 child = device_add_child(dev, NULL, -1);
  725                 ivars->xd_dev = child;
  726                 device_set_ivars(child, ivars);
  727         }
  728 
  729 out:
  730         sbuf_delete(devpath_sbuf);
  731         if (error != 0)
  732                 xenbusb_free_child_ivars(ivars);
  733 
  734         return (error);
  735 }
  736 
  737 int
  738 xenbusb_attach(device_t dev, char *bus_node, u_int id_components)
  739 {
  740         struct xenbusb_softc *xbs;
  741 
  742         xbs = device_get_softc(dev);
  743         mtx_init(&xbs->xbs_lock, "xenbusb softc lock", NULL, MTX_DEF);
  744         xbs->xbs_node = bus_node;
  745         xbs->xbs_id_components = id_components;
  746         xbs->xbs_dev = dev;
  747 
  748         /*
  749          * Since XenBus buses are attached to the XenStore, and
  750          * the XenStore does not probe children until after interrupt
  751          * services are available, this config hook is used solely
  752          * to ensure that the remainder of the boot process (e.g.
  753          * mount root) is deferred until child devices are adequately
  754          * probed.  We unblock the boot process as soon as the
  755          * connecting child count in our softc goes to 0.
  756          */
  757         xbs->xbs_attach_ch.ich_func = xenbusb_nop_confighook_cb;
  758         xbs->xbs_attach_ch.ich_arg = dev;
  759         config_intrhook_establish(&xbs->xbs_attach_ch);
  760         xbs->xbs_flags |= XBS_ATTACH_CH_ACTIVE;
  761         xbs->xbs_connecting_children = 1;
  762 
  763         /*
  764          * The subtree for this bus type may not yet exist
  765          * causing initial enumeration to fail.  We still
  766          * want to return success from our attach though
  767          * so that we are ready to handle devices for this
  768          * bus when they are dynamically attached to us
  769          * by a Xen management action.
  770          */
  771         (void)xenbusb_enumerate_bus(xbs);
  772         xenbusb_probe_children(dev);
  773 
  774         xbs->xbs_device_watch.node = bus_node;
  775         xbs->xbs_device_watch.callback = xenbusb_devices_changed;
  776         xbs->xbs_device_watch.callback_data = (uintptr_t)xbs;
  777         /*
  778          * Allow for unlimited pending watches, as those are local paths
  779          * either controlled by the guest or only writable by privileged
  780          * domains.
  781          */
  782         xbs->xbs_device_watch.max_pending = 0;
  783 
  784         TASK_INIT(&xbs->xbs_probe_children, 0, xenbusb_probe_children_cb, dev);
  785 
  786         xs_register_watch(&xbs->xbs_device_watch);
  787 
  788         xenbusb_release_confighook(xbs);
  789 
  790         return (0);
  791 }
  792 
  793 int
  794 xenbusb_resume(device_t dev)
  795 {
  796         device_t *kids;
  797         struct xenbus_device_ivars *ivars;
  798         int i, count, error;
  799         char *statepath;
  800 
  801         /*
  802          * We must re-examine each device and find the new path for
  803          * its backend.
  804          */
  805         if (device_get_children(dev, &kids, &count) == 0) {
  806                 for (i = 0; i < count; i++) {
  807                         if (device_get_state(kids[i]) == DS_NOTPRESENT)
  808                                 continue;
  809 
  810                         if (xen_suspend_cancelled) {
  811                                 DEVICE_RESUME(kids[i]);
  812                                 continue;
  813                         }
  814 
  815                         ivars = device_get_ivars(kids[i]);
  816 
  817                         xs_unregister_watch(&ivars->xd_otherend_watch);
  818                         xenbus_set_state(kids[i], XenbusStateInitialising);
  819 
  820                         /*
  821                          * Find the new backend details and
  822                          * re-register our watch.
  823                          */
  824                         error = XENBUSB_GET_OTHEREND_NODE(dev, ivars);
  825                         if (error)
  826                                 return (error);
  827 
  828                         statepath = malloc(ivars->xd_otherend_path_len
  829                             + strlen("/state") + 1, M_XENBUS, M_WAITOK);
  830                         sprintf(statepath, "%s/state", ivars->xd_otherend_path);
  831 
  832                         free(ivars->xd_otherend_watch.node, M_XENBUS);
  833                         ivars->xd_otherend_watch.node = statepath;
  834 
  835                         DEVICE_RESUME(kids[i]);
  836 
  837                         xs_register_watch(&ivars->xd_otherend_watch);
  838 #if 0
  839                         /*
  840                          * Can't do this yet since we are running in
  841                          * the xenwatch thread and if we sleep here,
  842                          * we will stop delivering watch notifications
  843                          * and the device will never come back online.
  844                          */
  845                         sx_xlock(&ivars->xd_lock);
  846                         while (ivars->xd_state != XenbusStateClosed
  847                             && ivars->xd_state != XenbusStateConnected)
  848                                 sx_sleep(&ivars->xd_state, &ivars->xd_lock,
  849                                     0, "xdresume", 0);
  850                         sx_xunlock(&ivars->xd_lock);
  851 #endif
  852                 }
  853                 free(kids, M_TEMP);
  854         }
  855 
  856         return (0);
  857 }
  858 
  859 int
  860 xenbusb_print_child(device_t dev, device_t child)
  861 {
  862         struct xenbus_device_ivars *ivars = device_get_ivars(child);
  863         int     retval = 0;
  864 
  865         retval += bus_print_child_header(dev, child);
  866         retval += printf(" at %s", ivars->xd_node);
  867         retval += bus_print_child_footer(dev, child);
  868 
  869         return (retval);
  870 }
  871 
  872 int
  873 xenbusb_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
  874 {
  875         struct xenbus_device_ivars *ivars = device_get_ivars(child);
  876 
  877         switch (index) {
  878         case XENBUS_IVAR_NODE:
  879                 *result = (uintptr_t) ivars->xd_node;
  880                 return (0);
  881 
  882         case XENBUS_IVAR_TYPE:
  883                 *result = (uintptr_t) ivars->xd_type;
  884                 return (0);
  885 
  886         case XENBUS_IVAR_STATE:
  887                 *result = (uintptr_t) ivars->xd_state;
  888                 return (0);
  889 
  890         case XENBUS_IVAR_OTHEREND_ID:
  891                 *result = (uintptr_t) ivars->xd_otherend_id;
  892                 return (0);
  893 
  894         case XENBUS_IVAR_OTHEREND_PATH:
  895                 *result = (uintptr_t) ivars->xd_otherend_path;
  896                 return (0);
  897         }
  898 
  899         return (ENOENT);
  900 }
  901 
  902 int
  903 xenbusb_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
  904 {
  905         struct xenbus_device_ivars *ivars = device_get_ivars(child);
  906         enum xenbus_state newstate;
  907         int currstate;
  908 
  909         switch (index) {
  910         case XENBUS_IVAR_STATE:
  911         {
  912                 int error;
  913 
  914                 newstate = (enum xenbus_state)value;
  915                 sx_xlock(&ivars->xd_lock);
  916                 if (ivars->xd_state == newstate) {
  917                         error = 0;
  918                         goto out;
  919                 }
  920 
  921                 error = xs_scanf(XST_NIL, ivars->xd_node, "state",
  922                     NULL, "%d", &currstate);
  923                 if (error)
  924                         goto out;
  925 
  926                 do {
  927                         error = xs_printf(XST_NIL, ivars->xd_node, "state",
  928                             "%d", newstate);
  929                 } while (error == EAGAIN);
  930                 if (error) {
  931                         /*
  932                          * Avoid looping through xenbus_dev_fatal()
  933                          * which calls xenbus_write_ivar to set the
  934                          * state to closing.
  935                          */
  936                         if (newstate != XenbusStateClosing)
  937                                 xenbus_dev_fatal(dev, error,
  938                                                  "writing new state");
  939                         goto out;
  940                 }
  941                 ivars->xd_state = newstate;
  942 
  943                 if ((ivars->xd_flags & XDF_CONNECTING) != 0
  944                  && (newstate == XenbusStateClosed
  945                   || newstate == XenbusStateConnected)) {
  946                         struct xenbusb_softc *xbs;
  947 
  948                         ivars->xd_flags &= ~XDF_CONNECTING;
  949                         xbs = device_get_softc(dev);
  950                         xenbusb_release_confighook(xbs);
  951                 }
  952 
  953                 wakeup(&ivars->xd_state);
  954         out:
  955                 sx_xunlock(&ivars->xd_lock);
  956                 return (error);
  957         }
  958 
  959         case XENBUS_IVAR_NODE:
  960         case XENBUS_IVAR_TYPE:
  961         case XENBUS_IVAR_OTHEREND_ID:
  962         case XENBUS_IVAR_OTHEREND_PATH:
  963                 /*
  964                  * These variables are read-only.
  965                  */
  966                 return (EINVAL);
  967         }
  968 
  969         return (ENOENT);
  970 }
  971 
  972 void
  973 xenbusb_otherend_changed(device_t bus, device_t child, enum xenbus_state state)
  974 {
  975         XENBUS_OTHEREND_CHANGED(child, state);
  976 }
  977 
  978 void
  979 xenbusb_localend_changed(device_t bus, device_t child, const char *path)
  980 {
  981 
  982         if (strcmp(path, "/state") != 0) {
  983                 struct xenbus_device_ivars *ivars;
  984 
  985                 ivars = device_get_ivars(child);
  986                 sx_xlock(&ivars->xd_lock);
  987                 ivars->xd_state = xenbus_read_driver_state(ivars->xd_node);
  988                 sx_xunlock(&ivars->xd_lock);
  989         }
  990         XENBUS_LOCALEND_CHANGED(child, path);
  991 }

Cache object: 3fe71b42803317c90615b76f931a22bd


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.