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 existence 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         bus_topo_lock();
  537         xenbusb_probe_children(dev);
  538         bus_topo_unlock();
  539 }
  540 
  541 /**
  542  * \brief XenStore watch callback for the root node of the XenStore
  543  *        subtree representing a XenBus.
  544  *
  545  * This callback performs, or delegates to the xbs_probe_children task,
  546  * all processing necessary to handle dynmaic device arrival and departure
  547  * events from a XenBus.
  548  *
  549  * \param watch  The XenStore watch object associated with this callback.
  550  * \param vec    The XenStore watch event data.
  551  * \param len    The number of fields in the event data stream.
  552  */
  553 static void
  554 xenbusb_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         }
  606 out:
  607         free(node, M_XENBUS);
  608 }
  609 
  610 /**
  611  * \brief Interrupt configuration hook callback associated with xbs_attch_ch.
  612  *
  613  * Since interrupts are always functional at the time of XenBus configuration,
  614  * there is nothing to be done when the callback occurs.  This hook is only
  615  * registered to hold up boot processing while XenBus devices come online.
  616  * 
  617  * \param arg  Unused configuration hook callback argument.
  618  */
  619 static void
  620 xenbusb_nop_confighook_cb(void *arg __unused)
  621 {
  622 }
  623 
  624 /*--------------------------- Public Functions -------------------------------*/
  625 /*--------- API comments for these methods can be found in xenbusb.h ---------*/
  626 void
  627 xenbusb_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 
  636 int
  637 xenbusb_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;
  699                 ivars->xd_otherend_watch.callback = xenbusb_otherend_watch_cb;
  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);
  718                 xbs->xbs_connecting_children++;
  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 
  726 out:
  727         sbuf_delete(devpath_sbuf);
  728         if (error != 0)
  729                 xenbusb_free_child_ivars(ivars);
  730 
  731         return (error);
  732 }
  733 
  734 int
  735 xenbusb_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          */
  754         xbs->xbs_attach_ch.ich_func = xenbusb_nop_confighook_cb;
  755         xbs->xbs_attach_ch.ich_arg = dev;
  756         config_intrhook_establish(&xbs->xbs_attach_ch);
  757         xbs->xbs_flags |= XBS_ATTACH_CH_ACTIVE;
  758         xbs->xbs_connecting_children = 1;
  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);
  769         xenbusb_probe_children(dev);
  770 
  771         xbs->xbs_device_watch.node = bus_node;
  772         xbs->xbs_device_watch.callback = xenbusb_devices_changed;
  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 
  785         xenbusb_release_confighook(xbs);
  786 
  787         return (0);
  788 }
  789 
  790 int
  791 xenbusb_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 
  856 int
  857 xenbusb_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 
  869 int
  870 xenbusb_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 
  883         case XENBUS_IVAR_STATE:
  884                 *result = (uintptr_t) ivars->xd_state;
  885                 return (0);
  886 
  887         case XENBUS_IVAR_OTHEREND_ID:
  888                 *result = (uintptr_t) ivars->xd_otherend_id;
  889                 return (0);
  890 
  891         case XENBUS_IVAR_OTHEREND_PATH:
  892                 *result = (uintptr_t) ivars->xd_otherend_path;
  893                 return (0);
  894         }
  895 
  896         return (ENOENT);
  897 }
  898 
  899 int
  900 xenbusb_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) {
  907         case XENBUS_IVAR_STATE:
  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);
  947                         xenbusb_release_confighook(xbs);
  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:
  958         case XENBUS_IVAR_OTHEREND_ID:
  959         case XENBUS_IVAR_OTHEREND_PATH:
  960                 /*
  961                  * These variables are read-only.
  962                  */
  963                 return (EINVAL);
  964         }
  965 
  966         return (ENOENT);
  967 }
  968 
  969 void
  970 xenbusb_otherend_changed(device_t bus, device_t child, enum xenbus_state state)
  971 {
  972         XENBUS_OTHEREND_CHANGED(child, state);
  973 }
  974 
  975 void
  976 xenbusb_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);
  984                 ivars->xd_state = xenbus_read_driver_state(ivars->xd_node);
  985                 sx_xunlock(&ivars->xd_lock);
  986         }
  987         XENBUS_LOCALEND_CHANGED(child, path);
  988 }

Cache object: 128eab6e191b64ec01af7b85d38fb776


[ 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.