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 busses 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: releng/11.1/sys/xen/xenbus/xenbusb.c 315668 2017-03-21 08:38:12Z royger $");
   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                 /*
  260                  * Device tree has been removed from Xenbus.
  261                  * Tear down the device.
  262                  */
  263                 xenbusb_delete_child(dev, child);
  264         }
  265 }
  266 
  267 /**
  268  * \brief Enumerate the devices on a XenBus bus and register them with
  269  *        the NewBus device tree.
  270  *
  271  * xenbusb_enumerate_bus() will create entries (in state DS_NOTPRESENT)
  272  * for nodes that appear in the XenStore, but will not invoke probe/attach
  273  * operations on drivers.  Probe/Attach processing must be separately
  274  * performed via an invocation of xenbusb_probe_children().  This is usually
  275  * done via the xbs_probe_children task.
  276  *
  277  * \param xbs  XenBus Bus device softc of the owner of the bus to enumerate.
  278  *
  279  * \return  On success, 0. Otherwise an errno value indicating the
  280  *          type of failure.
  281  */
  282 static int
  283 xenbusb_enumerate_bus(struct xenbusb_softc *xbs)
  284 {
  285         const char **types;
  286         u_int type_idx;
  287         u_int type_count;
  288         int error;
  289 
  290         error = xs_directory(XST_NIL, xbs->xbs_node, "", &type_count, &types);
  291         if (error)
  292                 return (error);
  293 
  294         for (type_idx = 0; type_idx < type_count; type_idx++)
  295                 XENBUSB_ENUMERATE_TYPE(xbs->xbs_dev, types[type_idx]);
  296 
  297         free(types, M_XENSTORE);
  298 
  299         return (0);
  300 }
  301 
  302 /**
  303  * Handler for all generic XenBus device systcl nodes.
  304  */
  305 static int
  306 xenbusb_device_sysctl_handler(SYSCTL_HANDLER_ARGS)  
  307 {
  308         device_t dev;
  309         const char *value;
  310 
  311         dev = (device_t)arg1;
  312         switch (arg2) {
  313         case XENBUS_IVAR_NODE:
  314                 value = xenbus_get_node(dev);
  315                 break;
  316         case XENBUS_IVAR_TYPE:
  317                 value = xenbus_get_type(dev);
  318                 break;
  319         case XENBUS_IVAR_STATE:
  320                 value = xenbus_strstate(xenbus_get_state(dev));
  321                 break;
  322         case XENBUS_IVAR_OTHEREND_ID:
  323                 return (sysctl_handle_int(oidp, NULL,
  324                                           xenbus_get_otherend_id(dev),
  325                                           req));
  326                 /* NOTREACHED */
  327         case XENBUS_IVAR_OTHEREND_PATH:
  328                 value = xenbus_get_otherend_path(dev);
  329                 break;
  330         default:
  331                 return (EINVAL);
  332         }
  333         return (SYSCTL_OUT_STR(req, value));
  334 }
  335 
  336 /**
  337  * Create read-only systcl nodes for xenbusb device ivar data.
  338  *
  339  * \param dev  The XenBus device instance to register with sysctl.
  340  */
  341 static void
  342 xenbusb_device_sysctl_init(device_t dev)
  343 {
  344         struct sysctl_ctx_list *ctx;
  345         struct sysctl_oid      *tree;
  346 
  347         ctx  = device_get_sysctl_ctx(dev);
  348         tree = device_get_sysctl_tree(dev);
  349 
  350         SYSCTL_ADD_PROC(ctx,
  351                         SYSCTL_CHILDREN(tree),
  352                         OID_AUTO,
  353                         "xenstore_path",
  354                         CTLTYPE_STRING | CTLFLAG_RD,
  355                         dev,
  356                         XENBUS_IVAR_NODE,
  357                         xenbusb_device_sysctl_handler,
  358                         "A",
  359                         "XenStore path to device");
  360 
  361         SYSCTL_ADD_PROC(ctx,
  362                         SYSCTL_CHILDREN(tree),
  363                         OID_AUTO,
  364                         "xenbus_dev_type",
  365                         CTLTYPE_STRING | CTLFLAG_RD,
  366                         dev,
  367                         XENBUS_IVAR_TYPE,
  368                         xenbusb_device_sysctl_handler,
  369                         "A",
  370                         "XenBus device type");
  371 
  372         SYSCTL_ADD_PROC(ctx,
  373                         SYSCTL_CHILDREN(tree),
  374                         OID_AUTO,
  375                         "xenbus_connection_state",
  376                         CTLTYPE_STRING | CTLFLAG_RD,
  377                         dev,
  378                         XENBUS_IVAR_STATE,
  379                         xenbusb_device_sysctl_handler,
  380                         "A",
  381                         "XenBus state of peer connection");
  382 
  383         SYSCTL_ADD_PROC(ctx,
  384                         SYSCTL_CHILDREN(tree),
  385                         OID_AUTO,
  386                         "xenbus_peer_domid",
  387                         CTLTYPE_INT | CTLFLAG_RD,
  388                         dev,
  389                         XENBUS_IVAR_OTHEREND_ID,
  390                         xenbusb_device_sysctl_handler,
  391                         "I",
  392                         "Xen domain ID of peer");
  393 
  394         SYSCTL_ADD_PROC(ctx,
  395                         SYSCTL_CHILDREN(tree),
  396                         OID_AUTO,
  397                         "xenstore_peer_path",
  398                         CTLTYPE_STRING | CTLFLAG_RD,
  399                         dev,
  400                         XENBUS_IVAR_OTHEREND_PATH,
  401                         xenbusb_device_sysctl_handler,
  402                         "A",
  403                         "XenStore path to peer device");
  404 }
  405 
  406 /**
  407  * \brief Decrement the number of XenBus child devices in the
  408  *        connecting state by one and release the xbs_attch_ch
  409  *        interrupt configuration hook if the connecting count
  410  *        drops to zero.
  411  *
  412  * \param xbs  XenBus Bus device softc of the owner of the bus to enumerate.
  413  */
  414 static void
  415 xenbusb_release_confighook(struct xenbusb_softc *xbs)
  416 {
  417         mtx_lock(&xbs->xbs_lock);
  418         KASSERT(xbs->xbs_connecting_children > 0,
  419                 ("Connecting device count error\n"));
  420         xbs->xbs_connecting_children--;
  421         if (xbs->xbs_connecting_children == 0
  422          && (xbs->xbs_flags & XBS_ATTACH_CH_ACTIVE) != 0) {
  423                 xbs->xbs_flags &= ~XBS_ATTACH_CH_ACTIVE;
  424                 mtx_unlock(&xbs->xbs_lock);
  425                 config_intrhook_disestablish(&xbs->xbs_attach_ch);
  426         } else {
  427                 mtx_unlock(&xbs->xbs_lock);
  428         }
  429 }
  430 
  431 /**
  432  * \brief Verify the existance of attached device instances and perform
  433  *        probe/attach processing for newly arrived devices.
  434  *
  435  * \param dev  The NewBus device representing this XenBus bus.
  436  *
  437  * \return  On success, 0. Otherwise an errno value indicating the
  438  *          type of failure.
  439  */
  440 static int
  441 xenbusb_probe_children(device_t dev)
  442 {
  443         device_t *kids;
  444         struct xenbus_device_ivars *ivars;
  445         int i, count, error;
  446 
  447         if (device_get_children(dev, &kids, &count) == 0) {
  448                 for (i = 0; i < count; i++) {
  449                         if (device_get_state(kids[i]) != DS_NOTPRESENT) {
  450                                 /*
  451                                  * We already know about this one.
  452                                  * Make sure it's still here.
  453                                  */
  454                                 xenbusb_verify_device(dev, kids[i]);
  455                                 continue;
  456                         }
  457 
  458                         error = device_probe_and_attach(kids[i]);
  459                         if (error == ENXIO) {
  460                                 struct xenbusb_softc *xbs;
  461 
  462                                 /*
  463                                  * We don't have a PV driver for this device.
  464                                  * However, an emulated device we do support
  465                                  * may share this backend.  Hide the node from
  466                                  * XenBus until the next rescan, but leave it's
  467                                  * state unchanged so we don't inadvertently
  468                                  * prevent attachment of any emulated device.
  469                                  */
  470                                 xenbusb_delete_child(dev, kids[i]);
  471 
  472                                 /*
  473                                  * Since the XenStore state of this device
  474                                  * still indicates a pending attach, manually
  475                                  * release it's hold on the boot process.
  476                                  */
  477                                 xbs = device_get_softc(dev);
  478                                 xenbusb_release_confighook(xbs);
  479 
  480                                 continue;
  481                         } else if (error) {
  482                                 /*
  483                                  * Transition device to the closed state
  484                                  * so the world knows that attachment will
  485                                  * not occur.
  486                                  */
  487                                 xenbus_set_state(kids[i], XenbusStateClosed);
  488 
  489                                 /*
  490                                  * Remove our record of this device.
  491                                  * So long as it remains in the closed
  492                                  * state in the XenStore, we will not find
  493                                  * it again.  The state will only change
  494                                  * if the control domain actively reconfigures
  495                                  * this device.
  496                                  */
  497                                 xenbusb_delete_child(dev, kids[i]);
  498 
  499                                 continue;
  500                         }
  501                         /*
  502                          * Augment default newbus provided dynamic sysctl
  503                          * variables with the standard ivar contents of
  504                          * XenBus devices.
  505                          */
  506                         xenbusb_device_sysctl_init(kids[i]);
  507 
  508                         /*
  509                          * Now that we have a driver managing this device
  510                          * that can receive otherend state change events,
  511                          * hook up a watch for them.
  512                          */
  513                         ivars = device_get_ivars(kids[i]);
  514                         xs_register_watch(&ivars->xd_otherend_watch);
  515                         xs_register_watch(&ivars->xd_local_watch);
  516                 }
  517                 free(kids, M_TEMP);
  518         }
  519 
  520         return (0);
  521 }
  522 
  523 /**
  524  * \brief Task callback function to perform XenBus probe operations
  525  *        from a known safe context.
  526  *
  527  * \param arg      The NewBus device_t representing the bus instance to
  528  *                 on which to perform probe processing.
  529  * \param pending  The number of times this task was queued before it could
  530  *                 be run.
  531  */
  532 static void
  533 xenbusb_probe_children_cb(void *arg, int pending __unused)
  534 {
  535         device_t dev = (device_t)arg;
  536 
  537         /*
  538          * Hold Giant until the Giant free newbus changes are committed.
  539          */
  540         mtx_lock(&Giant);
  541         xenbusb_probe_children(dev);
  542         mtx_unlock(&Giant);
  543 }
  544 
  545 /**
  546  * \brief XenStore watch callback for the root node of the XenStore
  547  *        subtree representing a XenBus.
  548  *
  549  * This callback performs, or delegates to the xbs_probe_children task,
  550  * all processing necessary to handle dynmaic device arrival and departure
  551  * events from a XenBus.
  552  *
  553  * \param watch  The XenStore watch object associated with this callback.
  554  * \param vec    The XenStore watch event data.
  555  * \param len    The number of fields in the event data stream.
  556  */
  557 static void
  558 xenbusb_devices_changed(struct xs_watch *watch, const char **vec,
  559                         unsigned int len)
  560 {
  561         struct xenbusb_softc *xbs;
  562         device_t dev;
  563         char *node;
  564         char *type;
  565         char *id;
  566         char *p;
  567         u_int component;
  568 
  569         xbs = (struct xenbusb_softc *)watch->callback_data;
  570         dev = xbs->xbs_dev;
  571 
  572         if (len <= XS_WATCH_PATH) {
  573                 device_printf(dev, "xenbusb_devices_changed: "
  574                               "Short Event Data.\n");
  575                 return;
  576         }
  577 
  578         node = strdup(vec[XS_WATCH_PATH], M_XENBUS);
  579         p = strchr(node, '/');
  580         if (p == NULL)
  581                 goto out;
  582         *p = 0;
  583         type = p + 1;
  584 
  585         p = strchr(type, '/');
  586         if (p == NULL)
  587                 goto out;
  588         *p++ = 0;
  589 
  590         /*
  591          * Extract the device ID.  A device ID has one or more path
  592          * components separated by the '/' character.
  593          *
  594          * e.g. "<frontend vm id>/<frontend dev id>" for backend devices.
  595          */
  596         id = p;
  597         for (component = 0; component < xbs->xbs_id_components; component++) {
  598                 p = strchr(p, '/');
  599                 if (p == NULL)
  600                         break;
  601                 p++;
  602         }
  603         if (p != NULL)
  604                 *p = 0;
  605 
  606         if (*id != 0 && component >= xbs->xbs_id_components - 1) {
  607                 xenbusb_add_device(xbs->xbs_dev, type, id);
  608                 taskqueue_enqueue(taskqueue_thread, &xbs->xbs_probe_children);
  609         }
  610 out:
  611         free(node, M_XENBUS);
  612 }
  613 
  614 /**
  615  * \brief Interrupt configuration hook callback associated with xbs_attch_ch.
  616  *
  617  * Since interrupts are always functional at the time of XenBus configuration,
  618  * there is nothing to be done when the callback occurs.  This hook is only
  619  * registered to hold up boot processing while XenBus devices come online.
  620  * 
  621  * \param arg  Unused configuration hook callback argument.
  622  */
  623 static void
  624 xenbusb_nop_confighook_cb(void *arg __unused)
  625 {
  626 }
  627 
  628 /*--------------------------- Public Functions -------------------------------*/
  629 /*--------- API comments for these methods can be found in xenbusb.h ---------*/
  630 void
  631 xenbusb_identify(driver_t *driver __unused, device_t parent)
  632 {
  633         /*
  634          * A single instance of each bus type for which we have a driver
  635          * is always present in a system operating under Xen.
  636          */
  637         BUS_ADD_CHILD(parent, 0, driver->name, 0);
  638 }
  639 
  640 int
  641 xenbusb_add_device(device_t dev, const char *type, const char *id)
  642 {
  643         struct xenbusb_softc *xbs;
  644         struct sbuf *devpath_sbuf;
  645         char *devpath;
  646         struct xenbus_device_ivars *ivars;
  647         int error;
  648 
  649         xbs = device_get_softc(dev);
  650         devpath_sbuf = sbuf_new_auto();
  651         sbuf_printf(devpath_sbuf, "%s/%s/%s", xbs->xbs_node, type, id);
  652         sbuf_finish(devpath_sbuf);
  653         devpath = sbuf_data(devpath_sbuf);
  654 
  655         ivars = malloc(sizeof(*ivars), M_XENBUS, M_ZERO|M_WAITOK);
  656         error = ENXIO;
  657 
  658         if (xs_exists(XST_NIL, devpath, "") != 0) {
  659                 device_t child;
  660                 enum xenbus_state state;
  661                 char *statepath;
  662 
  663                 child = xenbusb_device_exists(dev, devpath);
  664                 if (child != NULL) {
  665                         /*
  666                          * We are already tracking this node
  667                          */
  668                         error = 0;
  669                         goto out;
  670                 }
  671                         
  672                 state = xenbus_read_driver_state(devpath);
  673                 if (state != XenbusStateInitialising) {
  674                         /*
  675                          * Device is not new, so ignore it. This can
  676                          * happen if a device is going away after
  677                          * switching to Closed.
  678                          */
  679                         printf("xenbusb_add_device: Device %s ignored. "
  680                                "State %d\n", devpath, state);
  681                         error = 0;
  682                         goto out;
  683                 }
  684 
  685                 sx_init(&ivars->xd_lock, "xdlock");
  686                 ivars->xd_flags = XDF_CONNECTING;
  687                 ivars->xd_node = strdup(devpath, M_XENBUS);
  688                 ivars->xd_node_len = strlen(devpath);
  689                 ivars->xd_type  = strdup(type, M_XENBUS);
  690                 ivars->xd_state = XenbusStateInitialising;
  691 
  692                 error = XENBUSB_GET_OTHEREND_NODE(dev, ivars);
  693                 if (error) {
  694                         printf("xenbus_update_device: %s no otherend id\n",
  695                             devpath); 
  696                         goto out;
  697                 }
  698 
  699                 statepath = malloc(ivars->xd_otherend_path_len
  700                     + strlen("/state") + 1, M_XENBUS, M_WAITOK);
  701                 sprintf(statepath, "%s/state", ivars->xd_otherend_path);
  702                 ivars->xd_otherend_watch.node = statepath;
  703                 ivars->xd_otherend_watch.callback = xenbusb_otherend_watch_cb;
  704                 ivars->xd_otherend_watch.callback_data = (uintptr_t)ivars;
  705 
  706                 ivars->xd_local_watch.node = ivars->xd_node;
  707                 ivars->xd_local_watch.callback = xenbusb_local_watch_cb;
  708                 ivars->xd_local_watch.callback_data = (uintptr_t)ivars;
  709 
  710                 mtx_lock(&xbs->xbs_lock);
  711                 xbs->xbs_connecting_children++;
  712                 mtx_unlock(&xbs->xbs_lock);
  713 
  714                 child = device_add_child(dev, NULL, -1);
  715                 ivars->xd_dev = child;
  716                 device_set_ivars(child, ivars);
  717         }
  718 
  719 out:
  720         sbuf_delete(devpath_sbuf);
  721         if (error != 0)
  722                 xenbusb_free_child_ivars(ivars);
  723 
  724         return (error);
  725 }
  726 
  727 int
  728 xenbusb_attach(device_t dev, char *bus_node, u_int id_components)
  729 {
  730         struct xenbusb_softc *xbs;
  731 
  732         xbs = device_get_softc(dev);
  733         mtx_init(&xbs->xbs_lock, "xenbusb softc lock", NULL, MTX_DEF);
  734         xbs->xbs_node = bus_node;
  735         xbs->xbs_id_components = id_components;
  736         xbs->xbs_dev = dev;
  737 
  738         /*
  739          * Since XenBus busses are attached to the XenStore, and
  740          * the XenStore does not probe children until after interrupt
  741          * services are available, this config hook is used solely
  742          * to ensure that the remainder of the boot process (e.g.
  743          * mount root) is deferred until child devices are adequately
  744          * probed.  We unblock the boot process as soon as the
  745          * connecting child count in our softc goes to 0.
  746          */
  747         xbs->xbs_attach_ch.ich_func = xenbusb_nop_confighook_cb;
  748         xbs->xbs_attach_ch.ich_arg = dev;
  749         config_intrhook_establish(&xbs->xbs_attach_ch);
  750         xbs->xbs_flags |= XBS_ATTACH_CH_ACTIVE;
  751         xbs->xbs_connecting_children = 1;
  752 
  753         /*
  754          * The subtree for this bus type may not yet exist
  755          * causing initial enumeration to fail.  We still
  756          * want to return success from our attach though
  757          * so that we are ready to handle devices for this
  758          * bus when they are dynamically attached to us
  759          * by a Xen management action.
  760          */
  761         (void)xenbusb_enumerate_bus(xbs);
  762         xenbusb_probe_children(dev);
  763 
  764         xbs->xbs_device_watch.node = bus_node;
  765         xbs->xbs_device_watch.callback = xenbusb_devices_changed;
  766         xbs->xbs_device_watch.callback_data = (uintptr_t)xbs;
  767 
  768         TASK_INIT(&xbs->xbs_probe_children, 0, xenbusb_probe_children_cb, dev);
  769 
  770         xs_register_watch(&xbs->xbs_device_watch);
  771 
  772         xenbusb_release_confighook(xbs);
  773 
  774         return (0);
  775 }
  776 
  777 int
  778 xenbusb_resume(device_t dev)
  779 {
  780         device_t *kids;
  781         struct xenbus_device_ivars *ivars;
  782         int i, count, error;
  783         char *statepath;
  784 
  785         /*
  786          * We must re-examine each device and find the new path for
  787          * its backend.
  788          */
  789         if (device_get_children(dev, &kids, &count) == 0) {
  790                 for (i = 0; i < count; i++) {
  791                         if (device_get_state(kids[i]) == DS_NOTPRESENT)
  792                                 continue;
  793 
  794                         if (xen_suspend_cancelled) {
  795                                 DEVICE_RESUME(kids[i]);
  796                                 continue;
  797                         }
  798 
  799                         ivars = device_get_ivars(kids[i]);
  800 
  801                         xs_unregister_watch(&ivars->xd_otherend_watch);
  802                         xenbus_set_state(kids[i], XenbusStateInitialising);
  803 
  804                         /*
  805                          * Find the new backend details and
  806                          * re-register our watch.
  807                          */
  808                         error = XENBUSB_GET_OTHEREND_NODE(dev, ivars);
  809                         if (error)
  810                                 return (error);
  811 
  812                         statepath = malloc(ivars->xd_otherend_path_len
  813                             + strlen("/state") + 1, M_XENBUS, M_WAITOK);
  814                         sprintf(statepath, "%s/state", ivars->xd_otherend_path);
  815 
  816                         free(ivars->xd_otherend_watch.node, M_XENBUS);
  817                         ivars->xd_otherend_watch.node = statepath;
  818 
  819                         DEVICE_RESUME(kids[i]);
  820 
  821                         xs_register_watch(&ivars->xd_otherend_watch);
  822 #if 0
  823                         /*
  824                          * Can't do this yet since we are running in
  825                          * the xenwatch thread and if we sleep here,
  826                          * we will stop delivering watch notifications
  827                          * and the device will never come back online.
  828                          */
  829                         sx_xlock(&ivars->xd_lock);
  830                         while (ivars->xd_state != XenbusStateClosed
  831                             && ivars->xd_state != XenbusStateConnected)
  832                                 sx_sleep(&ivars->xd_state, &ivars->xd_lock,
  833                                     0, "xdresume", 0);
  834                         sx_xunlock(&ivars->xd_lock);
  835 #endif
  836                 }
  837                 free(kids, M_TEMP);
  838         }
  839 
  840         return (0);
  841 }
  842 
  843 int
  844 xenbusb_print_child(device_t dev, device_t child)
  845 {
  846         struct xenbus_device_ivars *ivars = device_get_ivars(child);
  847         int     retval = 0;
  848 
  849         retval += bus_print_child_header(dev, child);
  850         retval += printf(" at %s", ivars->xd_node);
  851         retval += bus_print_child_footer(dev, child);
  852 
  853         return (retval);
  854 }
  855 
  856 int
  857 xenbusb_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
  858 {
  859         struct xenbus_device_ivars *ivars = device_get_ivars(child);
  860 
  861         switch (index) {
  862         case XENBUS_IVAR_NODE:
  863                 *result = (uintptr_t) ivars->xd_node;
  864                 return (0);
  865 
  866         case XENBUS_IVAR_TYPE:
  867                 *result = (uintptr_t) ivars->xd_type;
  868                 return (0);
  869 
  870         case XENBUS_IVAR_STATE:
  871                 *result = (uintptr_t) ivars->xd_state;
  872                 return (0);
  873 
  874         case XENBUS_IVAR_OTHEREND_ID:
  875                 *result = (uintptr_t) ivars->xd_otherend_id;
  876                 return (0);
  877 
  878         case XENBUS_IVAR_OTHEREND_PATH:
  879                 *result = (uintptr_t) ivars->xd_otherend_path;
  880                 return (0);
  881         }
  882 
  883         return (ENOENT);
  884 }
  885 
  886 int
  887 xenbusb_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
  888 {
  889         struct xenbus_device_ivars *ivars = device_get_ivars(child);
  890         enum xenbus_state newstate;
  891         int currstate;
  892 
  893         switch (index) {
  894         case XENBUS_IVAR_STATE:
  895         {
  896                 int error;
  897 
  898                 newstate = (enum xenbus_state)value;
  899                 sx_xlock(&ivars->xd_lock);
  900                 if (ivars->xd_state == newstate) {
  901                         error = 0;
  902                         goto out;
  903                 }
  904 
  905                 error = xs_scanf(XST_NIL, ivars->xd_node, "state",
  906                     NULL, "%d", &currstate);
  907                 if (error)
  908                         goto out;
  909 
  910                 do {
  911                         error = xs_printf(XST_NIL, ivars->xd_node, "state",
  912                             "%d", newstate);
  913                 } while (error == EAGAIN);
  914                 if (error) {
  915                         /*
  916                          * Avoid looping through xenbus_dev_fatal()
  917                          * which calls xenbus_write_ivar to set the
  918                          * state to closing.
  919                          */
  920                         if (newstate != XenbusStateClosing)
  921                                 xenbus_dev_fatal(dev, error,
  922                                                  "writing new state");
  923                         goto out;
  924                 }
  925                 ivars->xd_state = newstate;
  926 
  927                 if ((ivars->xd_flags & XDF_CONNECTING) != 0
  928                  && (newstate == XenbusStateClosed
  929                   || newstate == XenbusStateConnected)) {
  930                         struct xenbusb_softc *xbs;
  931 
  932                         ivars->xd_flags &= ~XDF_CONNECTING;
  933                         xbs = device_get_softc(dev);
  934                         xenbusb_release_confighook(xbs);
  935                 }
  936 
  937                 wakeup(&ivars->xd_state);
  938         out:
  939                 sx_xunlock(&ivars->xd_lock);
  940                 return (error);
  941         }
  942 
  943         case XENBUS_IVAR_NODE:
  944         case XENBUS_IVAR_TYPE:
  945         case XENBUS_IVAR_OTHEREND_ID:
  946         case XENBUS_IVAR_OTHEREND_PATH:
  947                 /*
  948                  * These variables are read-only.
  949                  */
  950                 return (EINVAL);
  951         }
  952 
  953         return (ENOENT);
  954 }
  955 
  956 void
  957 xenbusb_otherend_changed(device_t bus, device_t child, enum xenbus_state state)
  958 {
  959         XENBUS_OTHEREND_CHANGED(child, state);
  960 }
  961 
  962 void
  963 xenbusb_localend_changed(device_t bus, device_t child, const char *path)
  964 {
  965 
  966         if (strcmp(path, "/state") != 0) {
  967                 struct xenbus_device_ivars *ivars;
  968 
  969                 ivars = device_get_ivars(child);
  970                 sx_xlock(&ivars->xd_lock);
  971                 ivars->xd_state = xenbus_read_driver_state(ivars->xd_node);
  972                 sx_xunlock(&ivars->xd_lock);
  973         }
  974         XENBUS_LOCALEND_CHANGED(child, path);
  975 }

Cache object: 42deb7ad9c5f09e553c221d752230a0b


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