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/dev/isci/scil/scif_sas_remote_device_states.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  * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
    3  *
    4  * This file is provided under a dual BSD/GPLv2 license.  When using or
    5  * redistributing this file, you may do so under either license.
    6  *
    7  * GPL LICENSE SUMMARY
    8  *
    9  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
   10  *
   11  * This program is free software; you can redistribute it and/or modify
   12  * it under the terms of version 2 of the GNU General Public License as
   13  * published by the Free Software Foundation.
   14  *
   15  * This program is distributed in the hope that it will be useful, but
   16  * WITHOUT ANY WARRANTY; without even the implied warranty of
   17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   18  * General Public License for more details.
   19  *
   20  * You should have received a copy of the GNU General Public License
   21  * along with this program; if not, write to the Free Software
   22  * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
   23  * The full GNU General Public License is included in this distribution
   24  * in the file called LICENSE.GPL.
   25  *
   26  * BSD LICENSE
   27  *
   28  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
   29  * All rights reserved.
   30  *
   31  * Redistribution and use in source and binary forms, with or without
   32  * modification, are permitted provided that the following conditions
   33  * are met:
   34  *
   35  *   * Redistributions of source code must retain the above copyright
   36  *     notice, this list of conditions and the following disclaimer.
   37  *   * Redistributions in binary form must reproduce the above copyright
   38  *     notice, this list of conditions and the following disclaimer in
   39  *     the documentation and/or other materials provided with the
   40  *     distribution.
   41  *
   42  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   43  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   44  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   45  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   46  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   47  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   48  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   49  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   50  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   51  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   52  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   53  */
   54 
   55 #include <sys/cdefs.h>
   56 __FBSDID("$FreeBSD$");
   57 
   58 /**
   59  * @file
   60  *
   61  * @brief
   62  */
   63 
   64 #include <dev/isci/scil/scic_remote_device.h>
   65 
   66 #include <dev/isci/scil/scif_sas_remote_device.h>
   67 #include <dev/isci/scil/scif_sas_domain.h>
   68 #include <dev/isci/scil/scif_sas_logger.h>
   69 
   70 
   71 /**
   72  * This constant indicates the number of milliseconds to wait for the core
   73  * to start/stop it's remote device object.
   74  */
   75 //#define SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT 1000
   76 
   77 //******************************************************************************
   78 //* P R O T E C T E D   M E T H O D S
   79 //******************************************************************************
   80 
   81 /**
   82  * @brief This method implements the actions taken when entering the
   83  *        INITIAL state.  This basically, causes an immediate transition
   84  *        into the STOPPED state.
   85  *
   86  * @param[in]  object This parameter specifies the base object for which
   87  *             the state transition is occurring.  This is cast into a
   88  *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
   89  *
   90  * @return none
   91  */
   92 static
   93 void scif_sas_remote_device_initial_state_enter(
   94    SCI_BASE_OBJECT_T *object
   95 )
   96 {
   97    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
   98 
   99    SET_STATE_HANDLER(
  100       fw_device,
  101       scif_sas_remote_device_state_handler_table,
  102       SCI_BASE_REMOTE_DEVICE_STATE_INITIAL
  103    );
  104 
  105    // Initial state is a transitional state to the stopped state
  106    sci_base_state_machine_change_state(
  107       &fw_device->parent.state_machine,
  108       SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
  109    );
  110 }
  111 
  112 /**
  113  * @brief This method implements the actions taken when entering the
  114  *        STOPPED state.  This method updates the domains count of started
  115  *        devices and will invoke the destruct method if this entrance into
  116  *        the STOPPED state was due to a scif_remote_device_destruct()
  117  *        call by the user.
  118  *
  119  * @param[in]  object This parameter specifies the base object for which
  120  *             the state transition is occurring.  This is cast into a
  121  *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
  122  *
  123  * @return none
  124  */
  125 static
  126 void scif_sas_remote_device_stopped_state_enter(
  127    SCI_BASE_OBJECT_T *object
  128 )
  129 {
  130    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
  131 
  132    SET_STATE_HANDLER(
  133       fw_device,
  134       scif_sas_remote_device_state_handler_table,
  135       SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
  136    );
  137 
  138    // There should be no outstanding requests for this device in the
  139    // stopped state.
  140    ASSERT(fw_device->request_count == 0);
  141 
  142    // If we are entering the stopped state as a result of a destruct
  143    // request, then let's perform the actual destruct operation now.
  144    if (fw_device->destruct_when_stopped == TRUE)
  145       fw_device->operation_status
  146          = fw_device->state_handlers->parent.destruct_handler(
  147               &fw_device->parent
  148            );
  149 
  150    /// @todo What should we do if this call fails?
  151    fw_device->domain->state_handlers->device_stop_complete_handler(
  152       &fw_device->domain->parent, &fw_device->parent
  153    );
  154 }
  155 
  156 /**
  157  * @brief This method implements the actions taken when entering the
  158  *        STARTING state.  This method will attempt to start the core
  159  *        remote device and will kick-start the starting sub-state machine
  160  *        if no errors are encountered.
  161  *
  162  * @param[in]  object This parameter specifies the base object for which
  163  *             the state transition is occurring.  This is cast into a
  164  *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
  165  *
  166  * @return none
  167  */
  168 static
  169 void scif_sas_remote_device_starting_state_enter(
  170    SCI_BASE_OBJECT_T *object
  171 )
  172 {
  173    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
  174 
  175    SET_STATE_HANDLER(
  176       fw_device,
  177       scif_sas_remote_device_state_handler_table,
  178       SCI_BASE_REMOTE_DEVICE_STATE_STARTING
  179    );
  180 
  181    SCIF_LOG_INFO((
  182       sci_base_object_get_logger(fw_device),
  183       SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG,
  184       "RemoteDevice:0x%x starting/configuring\n",
  185       fw_device
  186    ));
  187 
  188    fw_device->destination_state =
  189       SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_READY;
  190 
  191    sci_base_state_machine_start(&fw_device->starting_substate_machine);
  192 
  193    fw_device->operation_status = scic_remote_device_start(
  194                                     fw_device->core_object,
  195                                     SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT
  196                                  );
  197 
  198    if (fw_device->operation_status != SCI_SUCCESS)
  199    {
  200       fw_device->state_handlers->parent.fail_handler(&fw_device->parent);
  201 
  202       // Something is seriously wrong.  Starting the core remote device
  203       // shouldn't fail in anyway in this state.
  204       scif_cb_controller_error(fw_device->domain->controller,
  205               SCI_CONTROLLER_REMOTE_DEVICE_ERROR);
  206    }
  207 }
  208 
  209 /**
  210  * @brief This method implements the actions taken when exiting the
  211  *        STARTING state.  Currently this method simply stops the
  212  *        sub-state machine.
  213  *
  214  * @param[in]  object This parameter specifies the base object for which
  215  *             the state transition is occurring.  This is cast into a
  216  *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
  217  *
  218  * @return none
  219  */
  220 static
  221 void scif_sas_remote_device_starting_state_exit(
  222    SCI_BASE_OBJECT_T *object
  223 )
  224 {
  225    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
  226 
  227    fw_device->destination_state =
  228       SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_UNSPECIFIED;
  229 
  230    // Transition immediately into the operational sub-state.
  231    sci_base_state_machine_stop(&fw_device->starting_substate_machine);
  232 }
  233 
  234 /**
  235  * @brief This method implements the actions taken when entering the
  236  *        READY state.  Currently this method simply starts the
  237  *        sub-state machine.
  238  *
  239  * @param[in]  object This parameter specifies the base object for which
  240  *             the state transition is occurring.  This is cast into a
  241  *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
  242  *
  243  * @return none
  244  */
  245 static
  246 void scif_sas_remote_device_ready_state_enter(
  247    SCI_BASE_OBJECT_T *object
  248 )
  249 {
  250    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
  251 
  252    // Transition immediately into the operational sub-state.
  253    sci_base_state_machine_start(&fw_device->ready_substate_machine);
  254 
  255 #if defined(DISABLE_WIDE_PORTED_TARGETS)
  256    scif_sas_domain_remote_device_start_complete(fw_device->domain,fw_device);
  257 #endif
  258 }
  259 
  260 /**
  261  * @brief This method implements the actions taken when exiting the
  262  *        READY state.  Currently this method simply stops the
  263  *        sub-state machine.
  264  *
  265  * @param[in]  object This parameter specifies the base object for which
  266  *             the state transition is occurring.  This is cast into a
  267  *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
  268  *
  269  * @return none
  270  */
  271 static
  272 void scif_sas_remote_device_ready_state_exit(
  273    SCI_BASE_OBJECT_T *object
  274 )
  275 {
  276    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
  277 
  278    // Transition immediately into the operational sub-state.
  279    sci_base_state_machine_stop(&fw_device->ready_substate_machine);
  280 }
  281 
  282 /**
  283  * @brief This method implements the actions taken when entering the
  284  *        STOPPING state.  This includes: stopping the core remote device
  285  *        and handling any errors that may occur.
  286  *
  287  * @param[in]  object This parameter specifies the base object for which
  288  *             the state transition is occurring.  This is cast into a
  289  *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
  290  *
  291  * @return none
  292  */
  293 static
  294 void scif_sas_remote_device_stopping_state_enter(
  295    SCI_BASE_OBJECT_T *object
  296 )
  297 {
  298    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
  299 
  300    SET_STATE_HANDLER(
  301       fw_device,
  302       scif_sas_remote_device_state_handler_table,
  303       SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
  304    );
  305 
  306    fw_device->operation_status = scic_remote_device_stop(
  307                                     fw_device->core_object,
  308                                     SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT
  309                                  );
  310 
  311    // If there was a failure, then transition directly to the stopped state.
  312    if (fw_device->operation_status != SCI_SUCCESS)
  313    {
  314       /**
  315        * @todo We may want to consider adding handling to reset the
  316        *       structure data for the framework and core devices here
  317        *       in order to help aid recovery.
  318        */
  319 
  320       fw_device->state_handlers->stop_complete_handler(
  321          fw_device, fw_device->operation_status
  322       );
  323    }
  324 }
  325 
  326 /**
  327  * @brief This method implements the actions taken when exiting the
  328  *        STOPPING state.
  329  *
  330  * @param[in]  object This parameter specifies the base object for which
  331  *             the state transition is occurring.  This is cast into a
  332  *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
  333  *
  334  * @return none
  335  */
  336 static
  337 void scif_sas_remote_device_stopping_state_exit(
  338    SCI_BASE_OBJECT_T *object
  339 )
  340 {
  341    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
  342 
  343    // Let the domain know that the device has stopped
  344    fw_device->domain->device_start_count--;
  345 }
  346 
  347 /**
  348  * @brief This method implements the actions taken when entering the
  349  *        FAILED state.  This includes setting the state handler methods
  350  *        and issuing a scif_cb_remote_device_failed() notification to
  351  *        the user.
  352  *
  353  * @param[in]  object This parameter specifies the base object for which
  354  *             the state transition is occurring.  This is cast into a
  355  *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
  356  *
  357  * @return none
  358  */
  359 static
  360 void scif_sas_remote_device_failed_state_enter(
  361    SCI_BASE_OBJECT_T *object
  362 )
  363 {
  364    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
  365 
  366    SET_STATE_HANDLER(
  367       fw_device,
  368       scif_sas_remote_device_state_handler_table,
  369       SCI_BASE_REMOTE_DEVICE_STATE_FAILED
  370    );
  371 
  372    SCIF_LOG_INFO((
  373       sci_base_object_get_logger(fw_device),
  374       SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG,
  375       "Domain:0x%x Device:0x%x Status:0x%x device failed\n",
  376       fw_device->domain, fw_device, fw_device->operation_status
  377    ));
  378 
  379    // Notify the user that the device has failed.
  380    scif_cb_remote_device_failed(
  381       fw_device->domain->controller,
  382       fw_device->domain,
  383       fw_device,
  384       fw_device->operation_status
  385    );
  386 
  387    // Only call start_complete for the remote device if the device failed
  388    // from the STARTING state.
  389    if (fw_device->parent.state_machine.previous_state_id
  390        == SCI_BASE_REMOTE_DEVICE_STATE_STARTING)
  391       scif_sas_domain_remote_device_start_complete(fw_device->domain,fw_device);
  392 }
  393 
  394 /**
  395  * @brief This method implements the actions taken when entering the RESETTING
  396  *        state.
  397  *
  398  * @param[in]  object This parameter specifies the base object for which
  399  *             the state transition is occurring.  This is cast into a
  400  *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
  401  *
  402  * @return none
  403  */
  404 static
  405 void scif_sas_remote_device_resetting_state_enter(
  406    SCI_BASE_OBJECT_T *object
  407 )
  408 {
  409 }
  410 
  411 #if !defined(DISABLE_WIDE_PORTED_TARGETS)
  412 /**
  413  * @brief This method implements the actions taken when entering the UPDATING
  414  *        PORT WIDTH state.
  415  *
  416  * @param[in]  object This parameter specifies the base object for which
  417  *             the state transition is occurring.  This is cast into a
  418  *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
  419  *
  420  * @return none
  421  */
  422 static
  423 void scif_sas_remote_device_updating_port_width_state_enter(
  424    SCI_BASE_OBJECT_T *object
  425 )
  426 {
  427    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
  428 
  429    SET_STATE_HANDLER(
  430       fw_device,
  431       scif_sas_remote_device_state_handler_table,
  432       SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH
  433    );
  434 
  435    fw_device->destination_state = SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_READY;
  436 
  437    //If the request count is zero, go ahead to update the RNC.
  438    //If not, don't do anything for now. The IO complete handler of this state
  439    //will update the RNC whenever the request count goes down to zero.
  440    if (fw_device->request_count == 0)
  441    {
  442       //stop the device, upon the stop complete callback, start the device again
  443       //with the updated port width.
  444       scic_remote_device_stop(
  445          fw_device->core_object, SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT);
  446    }
  447 }
  448 
  449 
  450 /**
  451  * @brief This method implements the actions taken when exiting the
  452  *        STOPPING state.
  453  *
  454  * @param[in]  object This parameter specifies the base object for which
  455  *             the state transition is occurring.  This is cast into a
  456  *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
  457  *
  458  * @return none
  459  */
  460 static
  461 void scif_sas_remote_device_updating_port_width_state_exit(
  462    SCI_BASE_OBJECT_T *object
  463 )
  464 {
  465    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
  466 
  467    fw_device->destination_state =
  468       SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_UNSPECIFIED;
  469 }
  470 
  471 
  472 #endif //#if !defined(DISABLE_WIDE_PORTED_TARGETS)
  473 
  474 /**
  475  * @brief This method implements the actions taken when entering the
  476  *        FINAL state.  This includes setting the FINAL state handler
  477  *        methods.
  478  *
  479  * @param[in]  object This parameter specifies the base object for which
  480  *             the state transition is occurring.  This is cast into a
  481  *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
  482  *
  483  * @return none
  484  */
  485 static
  486 void scif_sas_remote_device_final_state_enter(
  487    SCI_BASE_OBJECT_T *object
  488 )
  489 {
  490    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
  491 
  492    SET_STATE_HANDLER(
  493       fw_device,
  494       scif_sas_remote_device_state_handler_table,
  495       SCI_BASE_REMOTE_DEVICE_STATE_FINAL
  496    );
  497 }
  498 
  499 
  500 SCI_BASE_STATE_T
  501    scif_sas_remote_device_state_table[SCI_BASE_REMOTE_DEVICE_MAX_STATES] =
  502 {
  503    {
  504       SCI_BASE_REMOTE_DEVICE_STATE_INITIAL,
  505       scif_sas_remote_device_initial_state_enter,
  506       NULL
  507    },
  508    {
  509       SCI_BASE_REMOTE_DEVICE_STATE_STOPPED,
  510       scif_sas_remote_device_stopped_state_enter,
  511       NULL
  512    },
  513    {
  514       SCI_BASE_REMOTE_DEVICE_STATE_STARTING,
  515       scif_sas_remote_device_starting_state_enter,
  516       scif_sas_remote_device_starting_state_exit
  517    },
  518    {
  519       SCI_BASE_REMOTE_DEVICE_STATE_READY,
  520       scif_sas_remote_device_ready_state_enter,
  521       scif_sas_remote_device_ready_state_exit
  522    },
  523    {
  524       SCI_BASE_REMOTE_DEVICE_STATE_STOPPING,
  525       scif_sas_remote_device_stopping_state_enter,
  526       scif_sas_remote_device_stopping_state_exit
  527    },
  528    {
  529       SCI_BASE_REMOTE_DEVICE_STATE_FAILED,
  530       scif_sas_remote_device_failed_state_enter,
  531       NULL
  532    },
  533    {
  534       SCI_BASE_REMOTE_DEVICE_STATE_RESETTING,
  535       scif_sas_remote_device_resetting_state_enter,
  536       NULL
  537    },
  538 #if !defined(DISABLE_WIDE_PORTED_TARGETS)
  539    {
  540       SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH,
  541       scif_sas_remote_device_updating_port_width_state_enter,
  542       scif_sas_remote_device_updating_port_width_state_exit
  543    },
  544 #endif //#if !defined(DISABLE_WIDE_PORTED_TARGETS)
  545    {
  546       SCI_BASE_REMOTE_DEVICE_STATE_FINAL,
  547       scif_sas_remote_device_final_state_enter,
  548       NULL
  549    },
  550 };
  551 

Cache object: ebb630763e02049b9b935a0314dd517e


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