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/8.4/sys/xen/xenbus/xenbusb.c 231759 2012-02-15 14:23:01Z ken $");
   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                         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                         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                         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                         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                         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 Verify the existance of attached device instances and perform
  408  *        probe/attach processing for newly arrived devices.
  409  *
  410  * \param dev  The NewBus device representing this XenBus bus.
  411  *
  412  * \return  On success, 0. Otherwise an errno value indicating the
  413  *          type of failure.
  414  */
  415 static int
  416 xenbusb_probe_children(device_t dev)
  417 {
  418         device_t *kids;
  419         struct xenbus_device_ivars *ivars;
  420         int i, count;
  421 
  422         if (device_get_children(dev, &kids, &count) == 0) {
  423                 for (i = 0; i < count; i++) {
  424                         if (device_get_state(kids[i]) != DS_NOTPRESENT) {
  425                                 /*
  426                                  * We already know about this one.
  427                                  * Make sure it's still here.
  428                                  */
  429                                 xenbusb_verify_device(dev, kids[i]);
  430                                 continue;
  431                         }
  432 
  433                         if (device_probe_and_attach(kids[i])) {
  434                                 /*
  435                                  * Transition device to the closed state
  436                                  * so the world knows that attachment will
  437                                  * not occur.
  438                                  */
  439                                 xenbus_set_state(kids[i], XenbusStateClosed);
  440 
  441                                 /*
  442                                  * Remove our record of this device.
  443                                  * So long as it remains in the closed
  444                                  * state in the XenStore, we will not find
  445                                  * it again.  The state will only change
  446                                  * if the control domain actively reconfigures
  447                                  * this device.
  448                                  */
  449                                 xenbusb_delete_child(dev, kids[i]);
  450 
  451                                 continue;
  452                         }
  453                         /*
  454                          * Augment default newbus provided dynamic sysctl
  455                          * variables with the standard ivar contents of
  456                          * XenBus devices.
  457                          */
  458                         xenbusb_device_sysctl_init(kids[i]);
  459 
  460                         /*
  461                          * Now that we have a driver managing this device
  462                          * that can receive otherend state change events,
  463                          * hook up a watch for them.
  464                          */
  465                         ivars = device_get_ivars(kids[i]);
  466                         xs_register_watch(&ivars->xd_otherend_watch);
  467                         xs_register_watch(&ivars->xd_local_watch);
  468                 }
  469                 free(kids, M_TEMP);
  470         }
  471 
  472         return (0);
  473 }
  474 
  475 /**
  476  * \brief Task callback function to perform XenBus probe operations
  477  *        from a known safe context.
  478  *
  479  * \param arg      The NewBus device_t representing the bus instance to
  480  *                 on which to perform probe processing.
  481  * \param pending  The number of times this task was queued before it could
  482  *                 be run.
  483  */
  484 static void
  485 xenbusb_probe_children_cb(void *arg, int pending __unused)
  486 {
  487         device_t dev = (device_t)arg;
  488 
  489         /*
  490          * Hold Giant until the Giant free newbus changes are committed.
  491          */
  492         mtx_lock(&Giant);
  493         xenbusb_probe_children(dev);
  494         mtx_unlock(&Giant);
  495 }
  496 
  497 /**
  498  * \brief XenStore watch callback for the root node of the XenStore
  499  *        subtree representing a XenBus.
  500  *
  501  * This callback performs, or delegates to the xbs_probe_children task,
  502  * all processing necessary to handle dynmaic device arrival and departure
  503  * events from a XenBus.
  504  *
  505  * \param watch  The XenStore watch object associated with this callback.
  506  * \param vec    The XenStore watch event data.
  507  * \param len    The number of fields in the event data stream.
  508  */
  509 static void
  510 xenbusb_devices_changed(struct xs_watch *watch, const char **vec,
  511                         unsigned int len)
  512 {
  513         struct xenbusb_softc *xbs;
  514         device_t dev;
  515         char *node;
  516         char *bus;
  517         char *type;
  518         char *id;
  519         char *p;
  520         u_int component;
  521 
  522         xbs = (struct xenbusb_softc *)watch->callback_data;
  523         dev = xbs->xbs_dev;
  524 
  525         if (len <= XS_WATCH_PATH) {
  526                 device_printf(dev, "xenbusb_devices_changed: "
  527                               "Short Event Data.\n");
  528                 return;
  529         }
  530 
  531         node = strdup(vec[XS_WATCH_PATH], M_XENBUS);
  532         p = strchr(node, '/');
  533         if (p == NULL)
  534                 goto out;
  535         bus = node;
  536         *p = 0;
  537         type = p + 1;
  538 
  539         p = strchr(type, '/');
  540         if (p == NULL)
  541                 goto out;
  542         *p++ = 0;
  543 
  544         /*
  545          * Extract the device ID.  A device ID has one or more path
  546          * components separated by the '/' character.
  547          *
  548          * e.g. "<frontend vm id>/<frontend dev id>" for backend devices.
  549          */
  550         id = p;
  551         for (component = 0; component < xbs->xbs_id_components; component++) {
  552                 p = strchr(p, '/');
  553                 if (p == NULL)
  554                         break;
  555                 p++;
  556         }
  557         if (p != NULL)
  558                 *p = 0;
  559 
  560         if (*id != 0 && component >= xbs->xbs_id_components - 1) {
  561                 xenbusb_add_device(xbs->xbs_dev, type, id);
  562                 taskqueue_enqueue(taskqueue_thread, &xbs->xbs_probe_children);
  563         }
  564 out:
  565         free(node, M_XENBUS);
  566 }
  567 
  568 /**
  569  * \brief Interrupt configuration hook callback associated with xbs_attch_ch.
  570  *
  571  * Since interrupts are always functional at the time of XenBus configuration,
  572  * there is nothing to be done when the callback occurs.  This hook is only
  573  * registered to hold up boot processing while XenBus devices come online.
  574  * 
  575  * \param arg  Unused configuration hook callback argument.
  576  */
  577 static void
  578 xenbusb_nop_confighook_cb(void *arg __unused)
  579 {
  580 }
  581 
  582 /**
  583  * \brief Decrement the number of XenBus child devices in the
  584  *        connecting state by one and release the xbs_attch_ch
  585  *        interrupt configuration hook if the connecting count
  586  *        drops to zero.
  587  *
  588  * \param xbs  XenBus Bus device softc of the owner of the bus to enumerate.
  589  */
  590 static void
  591 xenbusb_release_confighook(struct xenbusb_softc *xbs)
  592 {
  593         mtx_lock(&xbs->xbs_lock);
  594         KASSERT(xbs->xbs_connecting_children > 0,
  595                 ("Connecting device count error\n"));
  596         xbs->xbs_connecting_children--;
  597         if (xbs->xbs_connecting_children == 0
  598          && (xbs->xbs_flags & XBS_ATTACH_CH_ACTIVE) != 0) {
  599                 xbs->xbs_flags &= ~XBS_ATTACH_CH_ACTIVE;
  600                 mtx_unlock(&xbs->xbs_lock);
  601                 config_intrhook_disestablish(&xbs->xbs_attach_ch);
  602         } else {
  603                 mtx_unlock(&xbs->xbs_lock);
  604         }
  605 }
  606 
  607 /*--------------------------- Public Functions -------------------------------*/
  608 /*--------- API comments for these methods can be found in xenbusb.h ---------*/
  609 void
  610 xenbusb_identify(driver_t *driver __unused, device_t parent)
  611 {
  612         /*
  613          * A single instance of each bus type for which we have a driver
  614          * is always present in a system operating under Xen.
  615          */
  616         BUS_ADD_CHILD(parent, 0, driver->name, 0);
  617 }
  618 
  619 int
  620 xenbusb_add_device(device_t dev, const char *type, const char *id)
  621 {
  622         struct xenbusb_softc *xbs;
  623         struct sbuf *devpath_sbuf;
  624         char *devpath;
  625         struct xenbus_device_ivars *ivars;
  626         int error;
  627 
  628         xbs = device_get_softc(dev);
  629         devpath_sbuf = sbuf_new_auto();
  630         sbuf_printf(devpath_sbuf, "%s/%s/%s", xbs->xbs_node, type, id);
  631         sbuf_finish(devpath_sbuf);
  632         devpath = sbuf_data(devpath_sbuf);
  633 
  634         ivars = malloc(sizeof(*ivars), M_XENBUS, M_ZERO|M_WAITOK);
  635         error = ENXIO;
  636 
  637         if (xs_exists(XST_NIL, devpath, "") != 0) {
  638                 device_t child;
  639                 enum xenbus_state state;
  640                 char *statepath;
  641 
  642                 child = xenbusb_device_exists(dev, devpath);
  643                 if (child != NULL) {
  644                         /*
  645                          * We are already tracking this node
  646                          */
  647                         error = 0;
  648                         goto out;
  649                 }
  650                         
  651                 state = xenbus_read_driver_state(devpath);
  652                 if (state != XenbusStateInitialising) {
  653                         /*
  654                          * Device is not new, so ignore it. This can
  655                          * happen if a device is going away after
  656                          * switching to Closed.
  657                          */
  658                         printf("xenbusb_add_device: Device %s ignored. "
  659                                "State %d\n", devpath, state);
  660                         error = 0;
  661                         goto out;
  662                 }
  663 
  664                 sx_init(&ivars->xd_lock, "xdlock");
  665                 ivars->xd_flags = XDF_CONNECTING;
  666                 ivars->xd_node = strdup(devpath, M_XENBUS);
  667                 ivars->xd_node_len = strlen(devpath);
  668                 ivars->xd_type  = strdup(type, M_XENBUS);
  669                 ivars->xd_state = XenbusStateInitialising;
  670 
  671                 error = XENBUSB_GET_OTHEREND_NODE(dev, ivars);
  672                 if (error) {
  673                         printf("xenbus_update_device: %s no otherend id\n",
  674                             devpath); 
  675                         goto out;
  676                 }
  677 
  678                 statepath = malloc(ivars->xd_otherend_path_len
  679                     + strlen("/state") + 1, M_XENBUS, M_WAITOK);
  680                 sprintf(statepath, "%s/state", ivars->xd_otherend_path);
  681                 ivars->xd_otherend_watch.node = statepath;
  682                 ivars->xd_otherend_watch.callback = xenbusb_otherend_watch_cb;
  683                 ivars->xd_otherend_watch.callback_data = (uintptr_t)ivars;
  684 
  685                 ivars->xd_local_watch.node = ivars->xd_node;
  686                 ivars->xd_local_watch.callback = xenbusb_local_watch_cb;
  687                 ivars->xd_local_watch.callback_data = (uintptr_t)ivars;
  688 
  689                 mtx_lock(&xbs->xbs_lock);
  690                 xbs->xbs_connecting_children++;
  691                 mtx_unlock(&xbs->xbs_lock);
  692 
  693                 child = device_add_child(dev, NULL, -1);
  694                 ivars->xd_dev = child;
  695                 device_set_ivars(child, ivars);
  696         }
  697 
  698 out:
  699         sbuf_delete(devpath_sbuf);
  700         if (error != 0)
  701                 xenbusb_free_child_ivars(ivars);
  702 
  703         return (error);
  704 }
  705 
  706 int
  707 xenbusb_attach(device_t dev, char *bus_node, u_int id_components)
  708 {
  709         struct xenbusb_softc *xbs;
  710 
  711         xbs = device_get_softc(dev);
  712         mtx_init(&xbs->xbs_lock, "xenbusb softc lock", NULL, MTX_DEF);
  713         xbs->xbs_node = bus_node;
  714         xbs->xbs_id_components = id_components;
  715         xbs->xbs_dev = dev;
  716 
  717         /*
  718          * Since XenBus busses are attached to the XenStore, and
  719          * the XenStore does not probe children until after interrupt
  720          * services are available, this config hook is used solely
  721          * to ensure that the remainder of the boot process (e.g.
  722          * mount root) is deferred until child devices are adequately
  723          * probed.  We unblock the boot process as soon as the
  724          * connecting child count in our softc goes to 0.
  725          */
  726         xbs->xbs_attach_ch.ich_func = xenbusb_nop_confighook_cb;
  727         xbs->xbs_attach_ch.ich_arg = dev;
  728         config_intrhook_establish(&xbs->xbs_attach_ch);
  729         xbs->xbs_flags |= XBS_ATTACH_CH_ACTIVE;
  730         xbs->xbs_connecting_children = 1;
  731 
  732         /*
  733          * The subtree for this bus type may not yet exist
  734          * causing initial enumeration to fail.  We still
  735          * want to return success from our attach though
  736          * so that we are ready to handle devices for this
  737          * bus when they are dynamically attached to us
  738          * by a Xen management action.
  739          */
  740         (void)xenbusb_enumerate_bus(xbs);
  741         xenbusb_probe_children(dev);
  742 
  743         xbs->xbs_device_watch.node = bus_node;
  744         xbs->xbs_device_watch.callback = xenbusb_devices_changed;
  745         xbs->xbs_device_watch.callback_data = (uintptr_t)xbs;
  746 
  747         TASK_INIT(&xbs->xbs_probe_children, 0, xenbusb_probe_children_cb, dev);
  748 
  749         xs_register_watch(&xbs->xbs_device_watch);
  750 
  751         xenbusb_release_confighook(xbs);
  752 
  753         return (0);
  754 }
  755 
  756 int
  757 xenbusb_resume(device_t dev)
  758 {
  759         device_t *kids;
  760         struct xenbus_device_ivars *ivars;
  761         int i, count, error;
  762         char *statepath;
  763 
  764         /*
  765          * We must re-examine each device and find the new path for
  766          * its backend.
  767          */
  768         if (device_get_children(dev, &kids, &count) == 0) {
  769                 for (i = 0; i < count; i++) {
  770                         if (device_get_state(kids[i]) == DS_NOTPRESENT)
  771                                 continue;
  772 
  773                         ivars = device_get_ivars(kids[i]);
  774 
  775                         xs_unregister_watch(&ivars->xd_otherend_watch);
  776                         xenbus_set_state(kids[i], XenbusStateInitialising);
  777 
  778                         /*
  779                          * Find the new backend details and
  780                          * re-register our watch.
  781                          */
  782                         error = XENBUSB_GET_OTHEREND_NODE(dev, ivars);
  783                         if (error)
  784                                 return (error);
  785 
  786                         statepath = malloc(ivars->xd_otherend_path_len
  787                             + strlen("/state") + 1, M_XENBUS, M_WAITOK);
  788                         sprintf(statepath, "%s/state", ivars->xd_otherend_path);
  789 
  790                         free(ivars->xd_otherend_watch.node, M_XENBUS);
  791                         ivars->xd_otherend_watch.node = statepath;
  792 
  793                         DEVICE_RESUME(kids[i]);
  794 
  795                         xs_register_watch(&ivars->xd_otherend_watch);
  796 #if 0
  797                         /*
  798                          * Can't do this yet since we are running in
  799                          * the xenwatch thread and if we sleep here,
  800                          * we will stop delivering watch notifications
  801                          * and the device will never come back online.
  802                          */
  803                         sx_xlock(&ivars->xd_lock);
  804                         while (ivars->xd_state != XenbusStateClosed
  805                             && ivars->xd_state != XenbusStateConnected)
  806                                 sx_sleep(&ivars->xd_state, &ivars->xd_lock,
  807                                     0, "xdresume", 0);
  808                         sx_xunlock(&ivars->xd_lock);
  809 #endif
  810                 }
  811                 free(kids, M_TEMP);
  812         }
  813 
  814         return (0);
  815 }
  816 
  817 int
  818 xenbusb_print_child(device_t dev, device_t child)
  819 {
  820         struct xenbus_device_ivars *ivars = device_get_ivars(child);
  821         int     retval = 0;
  822 
  823         retval += bus_print_child_header(dev, child);
  824         retval += printf(" at %s", ivars->xd_node);
  825         retval += bus_print_child_footer(dev, child);
  826 
  827         return (retval);
  828 }
  829 
  830 int
  831 xenbusb_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
  832 {
  833         struct xenbus_device_ivars *ivars = device_get_ivars(child);
  834 
  835         switch (index) {
  836         case XENBUS_IVAR_NODE:
  837                 *result = (uintptr_t) ivars->xd_node;
  838                 return (0);
  839 
  840         case XENBUS_IVAR_TYPE:
  841                 *result = (uintptr_t) ivars->xd_type;
  842                 return (0);
  843 
  844         case XENBUS_IVAR_STATE:
  845                 *result = (uintptr_t) ivars->xd_state;
  846                 return (0);
  847 
  848         case XENBUS_IVAR_OTHEREND_ID:
  849                 *result = (uintptr_t) ivars->xd_otherend_id;
  850                 return (0);
  851 
  852         case XENBUS_IVAR_OTHEREND_PATH:
  853                 *result = (uintptr_t) ivars->xd_otherend_path;
  854                 return (0);
  855         }
  856 
  857         return (ENOENT);
  858 }
  859 
  860 int
  861 xenbusb_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
  862 {
  863         struct xenbus_device_ivars *ivars = device_get_ivars(child);
  864         enum xenbus_state newstate;
  865         int currstate;
  866 
  867         switch (index) {
  868         case XENBUS_IVAR_STATE:
  869         {
  870                 int error;
  871 
  872                 newstate = (enum xenbus_state)value;
  873                 sx_xlock(&ivars->xd_lock);
  874                 if (ivars->xd_state == newstate) {
  875                         error = 0;
  876                         goto out;
  877                 }
  878 
  879                 error = xs_scanf(XST_NIL, ivars->xd_node, "state",
  880                     NULL, "%d", &currstate);
  881                 if (error)
  882                         goto out;
  883 
  884                 do {
  885                         error = xs_printf(XST_NIL, ivars->xd_node, "state",
  886                             "%d", newstate);
  887                 } while (error == EAGAIN);
  888                 if (error) {
  889                         /*
  890                          * Avoid looping through xenbus_dev_fatal()
  891                          * which calls xenbus_write_ivar to set the
  892                          * state to closing.
  893                          */
  894                         if (newstate != XenbusStateClosing)
  895                                 xenbus_dev_fatal(dev, error,
  896                                                  "writing new state");
  897                         goto out;
  898                 }
  899                 ivars->xd_state = newstate;
  900 
  901                 if ((ivars->xd_flags & XDF_CONNECTING) != 0
  902                  && (newstate == XenbusStateClosed
  903                   || newstate == XenbusStateConnected)) {
  904                         struct xenbusb_softc *xbs;
  905 
  906                         ivars->xd_flags &= ~XDF_CONNECTING;
  907                         xbs = device_get_softc(dev);
  908                         xenbusb_release_confighook(xbs);
  909                 }
  910 
  911                 wakeup(&ivars->xd_state);
  912         out:
  913                 sx_xunlock(&ivars->xd_lock);
  914                 return (error);
  915         }
  916 
  917         case XENBUS_IVAR_NODE:
  918         case XENBUS_IVAR_TYPE:
  919         case XENBUS_IVAR_OTHEREND_ID:
  920         case XENBUS_IVAR_OTHEREND_PATH:
  921                 /*
  922                  * These variables are read-only.
  923                  */
  924                 return (EINVAL);
  925         }
  926 
  927         return (ENOENT);
  928 }
  929 
  930 void
  931 xenbusb_otherend_changed(device_t bus, device_t child, enum xenbus_state state)
  932 {
  933         XENBUS_OTHEREND_CHANGED(child, state);
  934 }
  935 
  936 void
  937 xenbusb_localend_changed(device_t bus, device_t child, const char *path)
  938 {
  939 
  940         if (strcmp(path, "/state") != 0) {
  941                 struct xenbus_device_ivars *ivars;
  942 
  943                 ivars = device_get_ivars(child);
  944                 sx_xlock(&ivars->xd_lock);
  945                 ivars->xd_state = xenbus_read_driver_state(ivars->xd_node);
  946                 sx_xunlock(&ivars->xd_lock);
  947         }
  948         XENBUS_LOCALEND_CHANGED(child, path);
  949 }

Cache object: 9b942eb8674b2f11ea711464086c5d40


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