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-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
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/9.2/sys/xen/xenbus/xenbusb.c 251973 2013-06-18 23:14:21Z gibbs $");
   56 
   57 #include <sys/param.h>
   58 #include <sys/bus.h>
   59 #include <sys/kernel.h>
   60 #include <sys/lock.h>
   61 #include <sys/malloc.h>
   62 #include <sys/module.h>
   63 #include <sys/sbuf.h>
   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(req, value, strlen(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 *bus;
  565         char *type;
  566         char *id;
  567         char *p;
  568         u_int component;
  569 
  570         xbs = (struct xenbusb_softc *)watch->callback_data;
  571         dev = xbs->xbs_dev;
  572 
  573         if (len <= XS_WATCH_PATH) {
  574                 device_printf(dev, "xenbusb_devices_changed: "
  575                               "Short Event Data.\n");
  576                 return;
  577         }
  578 
  579         node = strdup(vec[XS_WATCH_PATH], M_XENBUS);
  580         p = strchr(node, '/');
  581         if (p == NULL)
  582                 goto out;
  583         bus = node;
  584         *p = 0;
  585         type = p + 1;
  586 
  587         p = strchr(type, '/');
  588         if (p == NULL)
  589                 goto out;
  590         *p++ = 0;
  591 
  592         /*
  593          * Extract the device ID.  A device ID has one or more path
  594          * components separated by the '/' character.
  595          *
  596          * e.g. "<frontend vm id>/<frontend dev id>" for backend devices.
  597          */
  598         id = p;
  599         for (component = 0; component < xbs->xbs_id_components; component++) {
  600                 p = strchr(p, '/');
  601                 if (p == NULL)
  602                         break;
  603                 p++;
  604         }
  605         if (p != NULL)
  606                 *p = 0;
  607 
  608         if (*id != 0 && component >= xbs->xbs_id_components - 1) {
  609                 xenbusb_add_device(xbs->xbs_dev, type, id);
  610                 taskqueue_enqueue(taskqueue_thread, &xbs->xbs_probe_children);
  611         }
  612 out:
  613         free(node, M_XENBUS);
  614 }
  615 
  616 /**
  617  * \brief Interrupt configuration hook callback associated with xbs_attch_ch.
  618  *
  619  * Since interrupts are always functional at the time of XenBus configuration,
  620  * there is nothing to be done when the callback occurs.  This hook is only
  621  * registered to hold up boot processing while XenBus devices come online.
  622  * 
  623  * \param arg  Unused configuration hook callback argument.
  624  */
  625 static void
  626 xenbusb_nop_confighook_cb(void *arg __unused)
  627 {
  628 }
  629 
  630 /*--------------------------- Public Functions -------------------------------*/
  631 /*--------- API comments for these methods can be found in xenbusb.h ---------*/
  632 void
  633 xenbusb_identify(driver_t *driver __unused, device_t parent)
  634 {
  635         /*
  636          * A single instance of each bus type for which we have a driver
  637          * is always present in a system operating under Xen.
  638          */
  639         BUS_ADD_CHILD(parent, 0, driver->name, 0);
  640 }
  641 
  642 int
  643 xenbusb_add_device(device_t dev, const char *type, const char *id)
  644 {
  645         struct xenbusb_softc *xbs;
  646         struct sbuf *devpath_sbuf;
  647         char *devpath;
  648         struct xenbus_device_ivars *ivars;
  649         int error;
  650 
  651         xbs = device_get_softc(dev);
  652         devpath_sbuf = sbuf_new_auto();
  653         sbuf_printf(devpath_sbuf, "%s/%s/%s", xbs->xbs_node, type, id);
  654         sbuf_finish(devpath_sbuf);
  655         devpath = sbuf_data(devpath_sbuf);
  656 
  657         ivars = malloc(sizeof(*ivars), M_XENBUS, M_ZERO|M_WAITOK);
  658         error = ENXIO;
  659 
  660         if (xs_exists(XST_NIL, devpath, "") != 0) {
  661                 device_t child;
  662                 enum xenbus_state state;
  663                 char *statepath;
  664 
  665                 child = xenbusb_device_exists(dev, devpath);
  666                 if (child != NULL) {
  667                         /*
  668                          * We are already tracking this node
  669                          */
  670                         error = 0;
  671                         goto out;
  672                 }
  673                         
  674                 state = xenbus_read_driver_state(devpath);
  675                 if (state != XenbusStateInitialising) {
  676                         /*
  677                          * Device is not new, so ignore it. This can
  678                          * happen if a device is going away after
  679                          * switching to Closed.
  680                          */
  681                         printf("xenbusb_add_device: Device %s ignored. "
  682                                "State %d\n", devpath, state);
  683                         error = 0;
  684                         goto out;
  685                 }
  686 
  687                 sx_init(&ivars->xd_lock, "xdlock");
  688                 ivars->xd_flags = XDF_CONNECTING;
  689                 ivars->xd_node = strdup(devpath, M_XENBUS);
  690                 ivars->xd_node_len = strlen(devpath);
  691                 ivars->xd_type  = strdup(type, M_XENBUS);
  692                 ivars->xd_state = XenbusStateInitialising;
  693 
  694                 error = XENBUSB_GET_OTHEREND_NODE(dev, ivars);
  695                 if (error) {
  696                         printf("xenbus_update_device: %s no otherend id\n",
  697                             devpath); 
  698                         goto out;
  699                 }
  700 
  701                 statepath = malloc(ivars->xd_otherend_path_len
  702                     + strlen("/state") + 1, M_XENBUS, M_WAITOK);
  703                 sprintf(statepath, "%s/state", ivars->xd_otherend_path);
  704                 ivars->xd_otherend_watch.node = statepath;
  705                 ivars->xd_otherend_watch.callback = xenbusb_otherend_watch_cb;
  706                 ivars->xd_otherend_watch.callback_data = (uintptr_t)ivars;
  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                 mtx_lock(&xbs->xbs_lock);
  713                 xbs->xbs_connecting_children++;
  714                 mtx_unlock(&xbs->xbs_lock);
  715 
  716                 child = device_add_child(dev, NULL, -1);
  717                 ivars->xd_dev = child;
  718                 device_set_ivars(child, ivars);
  719         }
  720 
  721 out:
  722         sbuf_delete(devpath_sbuf);
  723         if (error != 0)
  724                 xenbusb_free_child_ivars(ivars);
  725 
  726         return (error);
  727 }
  728 
  729 int
  730 xenbusb_attach(device_t dev, char *bus_node, u_int id_components)
  731 {
  732         struct xenbusb_softc *xbs;
  733 
  734         xbs = device_get_softc(dev);
  735         mtx_init(&xbs->xbs_lock, "xenbusb softc lock", NULL, MTX_DEF);
  736         xbs->xbs_node = bus_node;
  737         xbs->xbs_id_components = id_components;
  738         xbs->xbs_dev = dev;
  739 
  740         /*
  741          * Since XenBus busses are attached to the XenStore, and
  742          * the XenStore does not probe children until after interrupt
  743          * services are available, this config hook is used solely
  744          * to ensure that the remainder of the boot process (e.g.
  745          * mount root) is deferred until child devices are adequately
  746          * probed.  We unblock the boot process as soon as the
  747          * connecting child count in our softc goes to 0.
  748          */
  749         xbs->xbs_attach_ch.ich_func = xenbusb_nop_confighook_cb;
  750         xbs->xbs_attach_ch.ich_arg = dev;
  751         config_intrhook_establish(&xbs->xbs_attach_ch);
  752         xbs->xbs_flags |= XBS_ATTACH_CH_ACTIVE;
  753         xbs->xbs_connecting_children = 1;
  754 
  755         /*
  756          * The subtree for this bus type may not yet exist
  757          * causing initial enumeration to fail.  We still
  758          * want to return success from our attach though
  759          * so that we are ready to handle devices for this
  760          * bus when they are dynamically attached to us
  761          * by a Xen management action.
  762          */
  763         (void)xenbusb_enumerate_bus(xbs);
  764         xenbusb_probe_children(dev);
  765 
  766         xbs->xbs_device_watch.node = bus_node;
  767         xbs->xbs_device_watch.callback = xenbusb_devices_changed;
  768         xbs->xbs_device_watch.callback_data = (uintptr_t)xbs;
  769 
  770         TASK_INIT(&xbs->xbs_probe_children, 0, xenbusb_probe_children_cb, dev);
  771 
  772         xs_register_watch(&xbs->xbs_device_watch);
  773 
  774         xenbusb_release_confighook(xbs);
  775 
  776         return (0);
  777 }
  778 
  779 int
  780 xenbusb_resume(device_t dev)
  781 {
  782         device_t *kids;
  783         struct xenbus_device_ivars *ivars;
  784         int i, count, error;
  785         char *statepath;
  786 
  787         /*
  788          * We must re-examine each device and find the new path for
  789          * its backend.
  790          */
  791         if (device_get_children(dev, &kids, &count) == 0) {
  792                 for (i = 0; i < count; i++) {
  793                         if (device_get_state(kids[i]) == DS_NOTPRESENT)
  794                                 continue;
  795 
  796                         ivars = device_get_ivars(kids[i]);
  797 
  798                         xs_unregister_watch(&ivars->xd_otherend_watch);
  799                         xenbus_set_state(kids[i], XenbusStateInitialising);
  800 
  801                         /*
  802                          * Find the new backend details and
  803                          * re-register our watch.
  804                          */
  805                         error = XENBUSB_GET_OTHEREND_NODE(dev, ivars);
  806                         if (error)
  807                                 return (error);
  808 
  809                         statepath = malloc(ivars->xd_otherend_path_len
  810                             + strlen("/state") + 1, M_XENBUS, M_WAITOK);
  811                         sprintf(statepath, "%s/state", ivars->xd_otherend_path);
  812 
  813                         free(ivars->xd_otherend_watch.node, M_XENBUS);
  814                         ivars->xd_otherend_watch.node = statepath;
  815 
  816                         DEVICE_RESUME(kids[i]);
  817 
  818                         xs_register_watch(&ivars->xd_otherend_watch);
  819 #if 0
  820                         /*
  821                          * Can't do this yet since we are running in
  822                          * the xenwatch thread and if we sleep here,
  823                          * we will stop delivering watch notifications
  824                          * and the device will never come back online.
  825                          */
  826                         sx_xlock(&ivars->xd_lock);
  827                         while (ivars->xd_state != XenbusStateClosed
  828                             && ivars->xd_state != XenbusStateConnected)
  829                                 sx_sleep(&ivars->xd_state, &ivars->xd_lock,
  830                                     0, "xdresume", 0);
  831                         sx_xunlock(&ivars->xd_lock);
  832 #endif
  833                 }
  834                 free(kids, M_TEMP);
  835         }
  836 
  837         return (0);
  838 }
  839 
  840 int
  841 xenbusb_print_child(device_t dev, device_t child)
  842 {
  843         struct xenbus_device_ivars *ivars = device_get_ivars(child);
  844         int     retval = 0;
  845 
  846         retval += bus_print_child_header(dev, child);
  847         retval += printf(" at %s", ivars->xd_node);
  848         retval += bus_print_child_footer(dev, child);
  849 
  850         return (retval);
  851 }
  852 
  853 int
  854 xenbusb_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
  855 {
  856         struct xenbus_device_ivars *ivars = device_get_ivars(child);
  857 
  858         switch (index) {
  859         case XENBUS_IVAR_NODE:
  860                 *result = (uintptr_t) ivars->xd_node;
  861                 return (0);
  862 
  863         case XENBUS_IVAR_TYPE:
  864                 *result = (uintptr_t) ivars->xd_type;
  865                 return (0);
  866 
  867         case XENBUS_IVAR_STATE:
  868                 *result = (uintptr_t) ivars->xd_state;
  869                 return (0);
  870 
  871         case XENBUS_IVAR_OTHEREND_ID:
  872                 *result = (uintptr_t) ivars->xd_otherend_id;
  873                 return (0);
  874 
  875         case XENBUS_IVAR_OTHEREND_PATH:
  876                 *result = (uintptr_t) ivars->xd_otherend_path;
  877                 return (0);
  878         }
  879 
  880         return (ENOENT);
  881 }
  882 
  883 int
  884 xenbusb_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
  885 {
  886         struct xenbus_device_ivars *ivars = device_get_ivars(child);
  887         enum xenbus_state newstate;
  888         int currstate;
  889 
  890         switch (index) {
  891         case XENBUS_IVAR_STATE:
  892         {
  893                 int error;
  894 
  895                 newstate = (enum xenbus_state)value;
  896                 sx_xlock(&ivars->xd_lock);
  897                 if (ivars->xd_state == newstate) {
  898                         error = 0;
  899                         goto out;
  900                 }
  901 
  902                 error = xs_scanf(XST_NIL, ivars->xd_node, "state",
  903                     NULL, "%d", &currstate);
  904                 if (error)
  905                         goto out;
  906 
  907                 do {
  908                         error = xs_printf(XST_NIL, ivars->xd_node, "state",
  909                             "%d", newstate);
  910                 } while (error == EAGAIN);
  911                 if (error) {
  912                         /*
  913                          * Avoid looping through xenbus_dev_fatal()
  914                          * which calls xenbus_write_ivar to set the
  915                          * state to closing.
  916                          */
  917                         if (newstate != XenbusStateClosing)
  918                                 xenbus_dev_fatal(dev, error,
  919                                                  "writing new state");
  920                         goto out;
  921                 }
  922                 ivars->xd_state = newstate;
  923 
  924                 if ((ivars->xd_flags & XDF_CONNECTING) != 0
  925                  && (newstate == XenbusStateClosed
  926                   || newstate == XenbusStateConnected)) {
  927                         struct xenbusb_softc *xbs;
  928 
  929                         ivars->xd_flags &= ~XDF_CONNECTING;
  930                         xbs = device_get_softc(dev);
  931                         xenbusb_release_confighook(xbs);
  932                 }
  933 
  934                 wakeup(&ivars->xd_state);
  935         out:
  936                 sx_xunlock(&ivars->xd_lock);
  937                 return (error);
  938         }
  939 
  940         case XENBUS_IVAR_NODE:
  941         case XENBUS_IVAR_TYPE:
  942         case XENBUS_IVAR_OTHEREND_ID:
  943         case XENBUS_IVAR_OTHEREND_PATH:
  944                 /*
  945                  * These variables are read-only.
  946                  */
  947                 return (EINVAL);
  948         }
  949 
  950         return (ENOENT);
  951 }
  952 
  953 void
  954 xenbusb_otherend_changed(device_t bus, device_t child, enum xenbus_state state)
  955 {
  956         XENBUS_OTHEREND_CHANGED(child, state);
  957 }
  958 
  959 void
  960 xenbusb_localend_changed(device_t bus, device_t child, const char *path)
  961 {
  962 
  963         if (strcmp(path, "/state") != 0) {
  964                 struct xenbus_device_ivars *ivars;
  965 
  966                 ivars = device_get_ivars(child);
  967                 sx_xlock(&ivars->xd_lock);
  968                 ivars->xd_state = xenbus_read_driver_state(ivars->xd_node);
  969                 sx_xunlock(&ivars->xd_lock);
  970         }
  971         XENBUS_LOCALEND_CHANGED(child, path);
  972 }

Cache object: 0c272c9942f62a77fef919bf9cf8fa34


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