1 /*- 2 * This file is provided under a dual BSD/GPLv2 license. When using or 3 * redistributing this file, you may do so under either license. 4 * 5 * GPL LICENSE SUMMARY 6 * 7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of version 2 of the GNU General Public License as 11 * published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 21 * The full GNU General Public License is included in this distribution 22 * in the file called LICENSE.GPL. 23 * 24 * BSD LICENSE 25 * 26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 27 * All rights reserved. 28 * 29 * Redistribution and use in source and binary forms, with or without 30 * modification, are permitted provided that the following conditions 31 * are met: 32 * 33 * * Redistributions of source code must retain the above copyright 34 * notice, this list of conditions and the following disclaimer. 35 * * Redistributions in binary form must reproduce the above copyright 36 * notice, this list of conditions and the following disclaimer in 37 * the documentation and/or other materials provided with the 38 * distribution. 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 44 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 46 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 47 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 48 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 49 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 50 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51 */ 52 53 #include <sys/cdefs.h> 54 __FBSDID("$FreeBSD$"); 55 56 /** 57 * @file 58 * 59 * @brief This file contains all of the entrance and exit methods for each 60 * of the controller states defined by the SCI_BASE_CONTROLLER state 61 * machine. 62 */ 63 64 #include <dev/isci/scil/scic_controller.h> 65 66 #include <dev/isci/scil/scif_sas_logger.h> 67 #include <dev/isci/scil/scif_sas_controller.h> 68 69 //****************************************************************************** 70 //* P R O T E C T E D M E T H O D S 71 //****************************************************************************** 72 73 /** 74 * @brief This method implements the actions taken when entering the 75 * INITIAL state. 76 * 77 * @param[in] object This parameter specifies the base object for which 78 * the state transition is occurring. This is cast into a 79 * SCIF_SAS_CONTROLLER object in the method implementation. 80 * 81 * @return none 82 */ 83 static 84 void scif_sas_controller_initial_state_enter( 85 SCI_BASE_OBJECT_T * object 86 ) 87 { 88 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object; 89 90 SET_STATE_HANDLER( 91 fw_controller, 92 scif_sas_controller_state_handler_table, 93 SCI_BASE_CONTROLLER_STATE_INITIAL 94 ); 95 } 96 97 /** 98 * @brief This method implements the actions taken when entering the 99 * RESET state. 100 * 101 * @param[in] object This parameter specifies the base object for which 102 * the state transition is occurring. This is cast into a 103 * SCIF_SAS_CONTROLLER object in the method implementation. 104 * 105 * @return none 106 */ 107 static 108 void scif_sas_controller_reset_state_enter( 109 SCI_BASE_OBJECT_T * object 110 ) 111 { 112 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object; 113 U8 index; 114 U16 smp_phy_index; 115 116 SET_STATE_HANDLER( 117 fw_controller, 118 scif_sas_controller_state_handler_table, 119 SCI_BASE_CONTROLLER_STATE_RESET 120 ); 121 122 scif_sas_high_priority_request_queue_construct( 123 &fw_controller->hprq, sci_base_object_get_logger(fw_controller) 124 ); 125 126 // Construct the abstract element pool. This pool will store the 127 // references to the framework's remote devices objects. 128 sci_abstract_element_pool_construct( 129 &fw_controller->free_remote_device_pool, 130 fw_controller->remote_device_pool_elements, 131 SCI_MAX_REMOTE_DEVICES 132 ); 133 134 // Construct the domain objects. 135 for (index = 0; index < SCI_MAX_DOMAINS; index++) 136 { 137 scif_sas_domain_construct( 138 &fw_controller->domains[index], index, fw_controller 139 ); 140 } 141 142 //Initialize SMP PHY MEMORY LIST. 143 sci_fast_list_init(&fw_controller->smp_phy_memory_list); 144 145 for (smp_phy_index = 0; 146 smp_phy_index < SCIF_SAS_SMP_PHY_COUNT; 147 smp_phy_index++) 148 { 149 sci_fast_list_element_init( 150 &fw_controller->smp_phy_array[smp_phy_index], 151 &(fw_controller->smp_phy_array[smp_phy_index].list_element) 152 ); 153 154 //insert to owning device's smp phy list. 155 sci_fast_list_insert_tail( 156 (&(fw_controller->smp_phy_memory_list)), 157 (&(fw_controller->smp_phy_array[smp_phy_index].list_element)) 158 ); 159 } 160 161 scif_sas_controller_set_default_config_parameters(fw_controller); 162 163 fw_controller->internal_request_entries = 164 SCIF_SAS_MAX_INTERNAL_REQUEST_COUNT; 165 166 //@Todo: may need to verify all timers are released. Including domain's 167 //operation timer and all the Internal IO's timer. 168 169 //take care of the lock. 170 scif_cb_lock_disassociate(fw_controller, &fw_controller->hprq.lock); 171 } 172 173 /** 174 * @brief This method implements the actions taken when entering the 175 * INITIALIZING state. 176 * 177 * @param[in] object This parameter specifies the base object for which 178 * the state transition is occurring. This is cast into a 179 * SCIF_SAS_CONTROLLER object in the method implementation. 180 * 181 * @return none 182 */ 183 static 184 void scif_sas_controller_initializing_state_enter( 185 SCI_BASE_OBJECT_T * object 186 ) 187 { 188 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object; 189 190 SET_STATE_HANDLER( 191 fw_controller, 192 scif_sas_controller_state_handler_table, 193 SCI_BASE_CONTROLLER_STATE_INITIALIZING 194 ); 195 } 196 197 /** 198 * @brief This method implements the actions taken when entering the 199 * INITIALIZED state. 200 * 201 * @param[in] object This parameter specifies the base object for which 202 * the state transition is occurring. This is cast into a 203 * SCIF_SAS_CONTROLLER object in the method implementation. 204 * 205 * @return none 206 */ 207 static 208 void scif_sas_controller_initialized_state_enter( 209 SCI_BASE_OBJECT_T * object 210 ) 211 { 212 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object; 213 214 SET_STATE_HANDLER( 215 fw_controller, 216 scif_sas_controller_state_handler_table, 217 SCI_BASE_CONTROLLER_STATE_INITIALIZED 218 ); 219 } 220 221 /** 222 * @brief This method implements the actions taken when entering the 223 * STARTING state. 224 * 225 * @param[in] object This parameter specifies the base object for which 226 * the state transition is occurring. This is cast into a 227 * SCIF_SAS_CONTROLLER object in the method implementation. 228 * 229 * @return none 230 */ 231 static 232 void scif_sas_controller_starting_state_enter( 233 SCI_BASE_OBJECT_T * object 234 ) 235 { 236 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object; 237 238 SET_STATE_HANDLER( 239 fw_controller, 240 scif_sas_controller_state_handler_table, 241 SCI_BASE_CONTROLLER_STATE_STARTING 242 ); 243 } 244 245 /** 246 * @brief This method implements the actions taken when entering the 247 * READY state. 248 * 249 * @param[in] object This parameter specifies the base object for which 250 * the state transition is occurring. This is cast into a 251 * SCIF_SAS_CONTROLLER object in the method implementation. 252 * 253 * @return none 254 */ 255 static 256 void scif_sas_controller_ready_state_enter( 257 SCI_BASE_OBJECT_T * object 258 ) 259 { 260 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object; 261 262 SET_STATE_HANDLER( 263 fw_controller, 264 scif_sas_controller_state_handler_table, 265 SCI_BASE_CONTROLLER_STATE_READY 266 ); 267 } 268 269 /** 270 * @brief This method implements the actions taken when entering the 271 * STOPPING state. 272 * 273 * @param[in] object This parameter specifies the base object for which 274 * the state transition is occurring. This is cast into a 275 * SCIF_SAS_CONTROLLER object in the method implementation. 276 * 277 * @return none 278 */ 279 static 280 void scif_sas_controller_stopping_state_enter( 281 SCI_BASE_OBJECT_T * object 282 ) 283 { 284 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object; 285 286 SET_STATE_HANDLER( 287 fw_controller, 288 scif_sas_controller_state_handler_table, 289 SCI_BASE_CONTROLLER_STATE_STOPPING 290 ); 291 } 292 293 /** 294 * @brief This method implements the actions taken when entering the 295 * STOPPED state. 296 * 297 * @param[in] object This parameter specifies the base object for which 298 * the state transition is occurring. This is cast into a 299 * SCIF_SAS_CONTROLLER object in the method implementation. 300 * 301 * @return none 302 */ 303 static 304 void scif_sas_controller_stopped_state_enter( 305 SCI_BASE_OBJECT_T * object 306 ) 307 { 308 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object; 309 310 SET_STATE_HANDLER( 311 fw_controller, 312 scif_sas_controller_state_handler_table, 313 SCI_BASE_CONTROLLER_STATE_STOPPED 314 ); 315 } 316 317 /** 318 * @brief This method implements the actions taken when entering the 319 * RESETTING state. 320 * 321 * @param[in] object This parameter specifies the base object for which 322 * the state transition is occurring. This is cast into a 323 * SCIF_SAS_CONTROLLER object in the method implementation. 324 * 325 * @return none 326 */ 327 static 328 void scif_sas_controller_resetting_state_enter( 329 SCI_BASE_OBJECT_T * object 330 ) 331 { 332 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object; 333 334 SET_STATE_HANDLER( 335 fw_controller, 336 scif_sas_controller_state_handler_table, 337 SCI_BASE_CONTROLLER_STATE_RESETTING 338 ); 339 340 // Attempt to reset the core controller. 341 fw_controller->operation_status = scic_controller_reset( 342 fw_controller->core_object 343 ); 344 if (fw_controller->operation_status == SCI_SUCCESS) 345 { 346 // Reset the framework controller. 347 sci_base_state_machine_change_state( 348 &fw_controller->parent.state_machine, 349 SCI_BASE_CONTROLLER_STATE_RESET 350 ); 351 } 352 else 353 { 354 SCIF_LOG_ERROR(( 355 sci_base_object_get_logger(fw_controller), 356 SCIF_LOG_OBJECT_CONTROLLER, 357 "Controller: unable to successfully reset controller.\n" 358 )); 359 360 sci_base_state_machine_change_state( 361 &fw_controller->parent.state_machine, 362 SCI_BASE_CONTROLLER_STATE_FAILED 363 ); 364 } 365 } 366 367 /** 368 * @brief This method implements the actions taken when entering the 369 * FAILED state. 370 * 371 * @param[in] object This parameter specifies the base object for which 372 * the state transition is occurring. This is cast into a 373 * SCIF_SAS_CONTROLLER object in the method implementation. 374 * 375 * @return none 376 */ 377 static 378 void scif_sas_controller_failed_state_enter( 379 SCI_BASE_OBJECT_T * object 380 ) 381 { 382 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object; 383 384 SCIF_LOG_ERROR(( 385 sci_base_object_get_logger(fw_controller), 386 SCIF_LOG_OBJECT_CONTROLLER, 387 "Controller: entered FAILED state.\n" 388 )); 389 390 SET_STATE_HANDLER( 391 fw_controller, 392 scif_sas_controller_state_handler_table, 393 SCI_BASE_CONTROLLER_STATE_FAILED 394 ); 395 396 if (fw_controller->parent.error != SCI_CONTROLLER_FATAL_MEMORY_ERROR) 397 { 398 //clean timers to avoid timer leak. 399 scif_sas_controller_release_resource(fw_controller); 400 401 //notify user. 402 scif_cb_controller_error(fw_controller, fw_controller->parent.error); 403 } 404 } 405 406 SCI_BASE_STATE_T 407 scif_sas_controller_state_table[SCI_BASE_CONTROLLER_MAX_STATES] = 408 { 409 { 410 SCI_BASE_CONTROLLER_STATE_INITIAL, 411 scif_sas_controller_initial_state_enter, 412 NULL, 413 }, 414 { 415 SCI_BASE_CONTROLLER_STATE_RESET, 416 scif_sas_controller_reset_state_enter, 417 NULL, 418 }, 419 { 420 SCI_BASE_CONTROLLER_STATE_INITIALIZING, 421 scif_sas_controller_initializing_state_enter, 422 NULL, 423 }, 424 { 425 SCI_BASE_CONTROLLER_STATE_INITIALIZED, 426 scif_sas_controller_initialized_state_enter, 427 NULL, 428 }, 429 { 430 SCI_BASE_CONTROLLER_STATE_STARTING, 431 scif_sas_controller_starting_state_enter, 432 NULL, 433 }, 434 { 435 SCI_BASE_CONTROLLER_STATE_READY, 436 scif_sas_controller_ready_state_enter, 437 NULL, 438 }, 439 { 440 SCI_BASE_CONTROLLER_STATE_RESETTING, 441 scif_sas_controller_resetting_state_enter, 442 NULL, 443 }, 444 { 445 SCI_BASE_CONTROLLER_STATE_STOPPING, 446 scif_sas_controller_stopping_state_enter, 447 NULL, 448 }, 449 { 450 SCI_BASE_CONTROLLER_STATE_STOPPED, 451 scif_sas_controller_stopped_state_enter, 452 NULL, 453 }, 454 { 455 SCI_BASE_CONTROLLER_STATE_FAILED, 456 scif_sas_controller_failed_state_enter, 457 NULL, 458 } 459 }; 460 461