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 the implementation of the SCIF_SAS_REMOTE_DEVICE 60 * object. 61 */ 62 63 64 #include <dev/isci/scil/scic_remote_device.h> 65 #include <dev/isci/scil/scic_port.h> 66 #include <dev/isci/scil/scic_user_callback.h> 67 68 #include <dev/isci/scil/scif_sas_logger.h> 69 #include <dev/isci/scil/scif_sas_remote_device.h> 70 #include <dev/isci/scil/scif_sas_stp_remote_device.h> 71 #include <dev/isci/scil/scif_sas_domain.h> 72 #include <dev/isci/scil/scif_sas_controller.h> 73 #include <dev/isci/scil/sci_controller.h> 74 #include <dev/isci/scil/sci_util.h> 75 76 77 //****************************************************************************** 78 //* P U B L I C M E T H O D S 79 //****************************************************************************** 80 81 U32 scif_remote_device_get_object_size( 82 void 83 ) 84 { 85 return ( sizeof(SCIF_SAS_REMOTE_DEVICE_T) 86 + scic_remote_device_get_object_size() ); 87 } 88 89 // --------------------------------------------------------------------------- 90 91 void scif_remote_device_construct( 92 SCI_DOMAIN_HANDLE_T domain, 93 void * remote_device_memory, 94 SCI_REMOTE_DEVICE_HANDLE_T * new_scif_remote_device_handle 95 ) 96 { 97 SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *) domain; 98 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *) 99 remote_device_memory; 100 101 SCIF_LOG_TRACE(( 102 sci_base_object_get_logger(fw_domain), 103 SCIF_LOG_OBJECT_REMOTE_DEVICE, 104 "scif_remote_device_construct(0x%x, 0x%x, 0x%x) enter\n", 105 domain, remote_device_memory, new_scif_remote_device_handle 106 )); 107 108 memset(remote_device_memory, 0, sizeof(SCIF_SAS_REMOTE_DEVICE_T)); 109 110 // The user's handle to the remote device evaluates to the memory 111 // address where the remote device object is stored. 112 *new_scif_remote_device_handle = remote_device_memory; 113 114 fw_device->domain = fw_domain; 115 fw_device->destruct_when_stopped = FALSE; 116 //fw_device->parent.is_failed = FALSE; 117 fw_device->operation_status = SCI_SUCCESS; 118 fw_device->request_count = 0; 119 fw_device->task_request_count = 0; 120 fw_device->is_currently_discovered = TRUE; 121 fw_device->containing_device = NULL; 122 fw_device->device_port_width = 1; 123 fw_device->expander_phy_identifier = 0; 124 fw_device->destination_state = 125 SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_UNSPECIFIED; 126 fw_device->ea_target_reset_request_scheduled = NULL; 127 128 // Construct the base object first in order to ensure logging can 129 // function. 130 sci_base_remote_device_construct( 131 &fw_device->parent, 132 sci_base_object_get_logger(fw_domain), 133 scif_sas_remote_device_state_table 134 ); 135 136 sci_base_state_machine_construct( 137 &fw_device->starting_substate_machine, 138 &fw_device->parent.parent, 139 scif_sas_remote_device_starting_substate_table, 140 SCIF_SAS_REMOTE_DEVICE_STARTING_SUBSTATE_AWAIT_COMPLETE 141 ); 142 143 sci_base_state_machine_construct( 144 &fw_device->ready_substate_machine, 145 &fw_device->parent.parent, 146 scif_sas_remote_device_ready_substate_table, 147 SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL 148 ); 149 150 scif_sas_remote_device_initialize_state_logging(fw_device); 151 152 scic_remote_device_construct( 153 fw_domain->core_object, 154 ((U8*) remote_device_memory) + sizeof(SCIF_SAS_REMOTE_DEVICE_T), 155 &fw_device->core_object 156 ); 157 158 // Set the association in the core object, so that we are able to 159 // determine our framework remote device object from the core remote 160 // device. 161 sci_object_set_association(fw_device->core_object, fw_device); 162 } 163 164 // --------------------------------------------------------------------------- 165 166 SCI_STATUS scif_remote_device_da_construct( 167 SCI_REMOTE_DEVICE_HANDLE_T remote_device, 168 SCI_SAS_ADDRESS_T * sas_address, 169 SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols 170 ) 171 { 172 SCI_STATUS status = SCI_SUCCESS; 173 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *) 174 remote_device; 175 176 SCIF_LOG_TRACE(( 177 sci_base_object_get_logger(fw_device), 178 SCIF_LOG_OBJECT_REMOTE_DEVICE, 179 "scif_remote_device_da_construct(0x%x, 0x%x, 0x%x) enter\n", 180 remote_device, sas_address, protocols 181 )); 182 183 // Make sure the device hasn't already been constructed and added 184 // to the domain. 185 if (scif_domain_get_device_by_sas_address(fw_device->domain, sas_address) 186 == SCI_INVALID_HANDLE) 187 { 188 SCIC_PORT_PROPERTIES_T properties; 189 190 scic_port_get_properties(fw_device->domain->core_object, &properties); 191 192 // Check to see if this is the direct attached device. 193 if ( (sas_address->low == properties.remote.sas_address.low) 194 && (sas_address->high == properties.remote.sas_address.high) ) 195 { 196 //Get accurate port width from port's phy mask for a DA device. 197 SCI_GET_BITS_SET_COUNT(properties.phy_mask, fw_device->device_port_width); 198 199 status = scic_remote_device_da_construct(fw_device->core_object); 200 } 201 else 202 // Don't allow the user to construct a direct attached device 203 // if it's not a direct attached device. 204 status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; 205 } 206 else 207 status = SCI_FAILURE_DEVICE_EXISTS; 208 209 if (status == SCI_SUCCESS) 210 { 211 // Add the device to the domain list. 212 sci_abstract_list_pushback( 213 &fw_device->domain->remote_device_list, fw_device 214 ); 215 216 // If a SATA/STP device is connected, then construct it. 217 if (protocols->u.bits.stp_target) 218 scif_sas_stp_remote_device_construct(fw_device); 219 else if (protocols->u.bits.smp_target) 220 scif_sas_smp_remote_device_construct(fw_device); 221 222 SCIF_LOG_INFO(( 223 sci_base_object_get_logger(fw_device), 224 SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 225 "Domain:0x%x SasAddress:0x%x,0x%x remote device constructed\n", 226 fw_device->domain, sas_address->low, sas_address->high 227 )); 228 229 status = fw_device->state_handlers->parent.start_handler( 230 &fw_device->parent 231 ); 232 } 233 else 234 { 235 SCIF_LOG_WARNING(( 236 sci_base_object_get_logger(fw_device), 237 SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 238 "Domain:0x%x SasAddress:0x%x,0x%x Status:0x%x remote device construct failure\n", 239 fw_device->domain, sas_address->low, sas_address->high, status 240 )); 241 } 242 243 return status; 244 } 245 246 // --------------------------------------------------------------------------- 247 248 SCI_STATUS scif_remote_device_ea_construct( 249 SCI_REMOTE_DEVICE_HANDLE_T remote_device, 250 SCI_REMOTE_DEVICE_HANDLE_T containing_device, 251 SMP_RESPONSE_DISCOVER_T * smp_response 252 ) 253 { 254 SCI_SAS_ADDRESS_T * sas_address; 255 SCI_STATUS status = SCI_SUCCESS; 256 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *) 257 remote_device; 258 SCIF_SAS_REMOTE_DEVICE_T * fw_smp_device = (SCIF_SAS_REMOTE_DEVICE_T *) 259 containing_device; 260 261 fw_device->containing_device = fw_smp_device; 262 fw_device->expander_phy_identifier = 263 fw_smp_device->protocol_device.smp_device.current_activity_phy_index; 264 265 sas_address = &smp_response->attached_sas_address; 266 267 SCIF_LOG_TRACE(( 268 sci_base_object_get_logger(fw_device), 269 SCIF_LOG_OBJECT_REMOTE_DEVICE, 270 "scif_remote_device_ea_construct(0x%x, 0x%x) enter\n", 271 remote_device, smp_response 272 )); 273 274 // Make sure the device hasn't already been constructed and added 275 // to the domain. 276 if (scif_domain_get_device_by_sas_address(fw_device->domain, sas_address) 277 == SCI_INVALID_HANDLE) 278 { 279 //for sata device, we need another routine. likely 280 //scif_remote_device_ea_sata_construct. 281 status = scic_remote_device_ea_construct(fw_device->core_object, smp_response); 282 } 283 else 284 status = SCI_FAILURE_DEVICE_EXISTS; 285 286 if (status == SCI_SUCCESS) 287 { 288 // Add the device to the domain list. 289 sci_abstract_list_pushback( 290 &fw_device->domain->remote_device_list, fw_device 291 ); 292 293 if (smp_response->protocols.u.bits.attached_smp_target) 294 scif_sas_smp_remote_device_construct(fw_device); 295 else if (smp_response->protocols.u.bits.attached_stp_target) 296 scif_sas_stp_remote_device_construct(fw_device); 297 298 SCIF_LOG_INFO(( 299 sci_base_object_get_logger(fw_device), 300 SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 301 "Domain:0x%x SasAddress:0x%x,0x%x remote device constructed\n", 302 fw_device->domain, sas_address->low, sas_address->high 303 )); 304 305 //only start the device if the device is not a SATA disk on SPINUP_HOLD state. 306 if ( scic_remote_device_get_connection_rate(fw_device->core_object) != 307 SCI_SATA_SPINUP_HOLD ) 308 { 309 status = fw_device->state_handlers->parent.start_handler( 310 &fw_device->parent 311 ); 312 } 313 } 314 else 315 { 316 SCIF_LOG_WARNING(( 317 sci_base_object_get_logger(fw_device), 318 SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 319 "Domain:0x%x SasAddress:0x%x,0x%x Status:0x%x remote device construct failure\n", 320 fw_device->domain, sas_address->low, sas_address->high, status 321 )); 322 } 323 324 return status; 325 } 326 327 // --------------------------------------------------------------------------- 328 329 SCI_STATUS scif_remote_device_destruct( 330 SCI_REMOTE_DEVICE_HANDLE_T remote_device 331 ) 332 { 333 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*) 334 remote_device; 335 336 SCIF_LOG_TRACE(( 337 sci_base_object_get_logger(fw_device), 338 SCIF_LOG_OBJECT_REMOTE_DEVICE, 339 "scif_remote_device_destruct(0x%x) enter\n", 340 remote_device 341 )); 342 343 //remove the device from domain's remote_device_list 344 fw_device->domain->state_handlers->device_destruct_handler( 345 &fw_device->domain->parent, &fw_device->parent 346 ); 347 348 // The destruct process may not complete immediately, since the core 349 // remote device likely needs to be stopped first. However, the user 350 // is not given a callback notification for destruction. 351 return fw_device->state_handlers->parent.destruct_handler( 352 &fw_device->parent 353 ); 354 } 355 356 // --------------------------------------------------------------------------- 357 358 SCI_REMOTE_DEVICE_HANDLE_T scif_remote_device_get_scic_handle( 359 SCI_REMOTE_DEVICE_HANDLE_T scif_remote_device 360 ) 361 { 362 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*) 363 scif_remote_device; 364 365 if ( (fw_device == NULL) || (fw_device->core_object == SCI_INVALID_HANDLE) ) 366 return SCI_INVALID_HANDLE; 367 368 SCIF_LOG_WARNING(( 369 sci_base_object_get_logger(fw_device), 370 SCIF_LOG_OBJECT_REMOTE_DEVICE, 371 "RemoteDevice:0x%x no associated core device found\n", 372 fw_device 373 )); 374 375 return fw_device->core_object; 376 } 377 378 // --------------------------------------------------------------------------- 379 380 void scic_cb_remote_device_start_complete( 381 SCI_CONTROLLER_HANDLE_T controller, 382 SCI_REMOTE_DEVICE_HANDLE_T remote_device, 383 SCI_STATUS completion_status 384 ) 385 { 386 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*) 387 sci_object_get_association(remote_device); 388 389 SCIF_LOG_TRACE(( 390 sci_base_object_get_logger(fw_device), 391 SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG, 392 "scic_cb_remote_device_start_complete(0x%x, 0x%x, 0x%x) enter\n", 393 controller, remote_device, completion_status 394 )); 395 396 fw_device->state_handlers->start_complete_handler( 397 fw_device, completion_status 398 ); 399 } 400 401 // --------------------------------------------------------------------------- 402 403 void scic_cb_remote_device_stop_complete( 404 SCI_CONTROLLER_HANDLE_T controller, 405 SCI_REMOTE_DEVICE_HANDLE_T remote_device, 406 SCI_STATUS completion_status 407 ) 408 { 409 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*) 410 sci_object_get_association(remote_device); 411 412 SCIF_LOG_TRACE(( 413 sci_base_object_get_logger(fw_device), 414 SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG, 415 "scic_cb_remote_device_stop_complete(0x%x, 0x%x, 0x%x) enter\n", 416 controller, remote_device, completion_status 417 )); 418 419 fw_device->state_handlers->stop_complete_handler( 420 fw_device, completion_status 421 ); 422 } 423 424 // --------------------------------------------------------------------------- 425 426 void scic_cb_remote_device_ready( 427 SCI_CONTROLLER_HANDLE_T controller, 428 SCI_REMOTE_DEVICE_HANDLE_T remote_device 429 ) 430 { 431 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*) 432 sci_object_get_association(remote_device); 433 434 fw_device->state_handlers->ready_handler(fw_device); 435 } 436 437 // --------------------------------------------------------------------------- 438 439 void scic_cb_remote_device_not_ready( 440 SCI_CONTROLLER_HANDLE_T controller, 441 SCI_REMOTE_DEVICE_HANDLE_T remote_device, 442 U32 reason_code 443 ) 444 { 445 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*) 446 sci_object_get_association(remote_device); 447 448 fw_device->state_handlers->not_ready_handler(fw_device,reason_code); 449 } 450 451 // --------------------------------------------------------------------------- 452 453 U16 scif_remote_device_get_max_queue_depth( 454 SCI_REMOTE_DEVICE_HANDLE_T remote_device 455 ) 456 { 457 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*) 458 remote_device; 459 SMP_DISCOVER_RESPONSE_PROTOCOLS_T protocols; 460 461 scic_remote_device_get_protocols(fw_device->core_object, &protocols); 462 463 // If the target is a SATA/STP target, then determine the queue depth 464 // for either NCQ or for UDMA. 465 if (protocols.u.bits.attached_stp_target) 466 { 467 if (fw_device->protocol_device.stp_device.sati_device.capabilities 468 & SATI_DEVICE_CAP_NCQ_SUPPORTED_ENABLE) 469 { 470 return fw_device->protocol_device.stp_device.sati_device.ncq_depth; 471 } 472 else 473 { 474 // At the moment, we only allow a single UDMA request to be queued. 475 return 1; 476 } 477 } 478 479 // For SSP devices return a no maximum queue depth supported. 480 return SCIF_REMOTE_DEVICE_NO_MAX_QUEUE_DEPTH; 481 } 482 483 // --------------------------------------------------------------------------- 484 485 SCI_STATUS scif_remote_device_get_containing_device( 486 SCI_REMOTE_DEVICE_HANDLE_T remote_device, 487 SCI_REMOTE_DEVICE_HANDLE_T * containing_device 488 ) 489 { 490 SCI_STATUS status = SCI_FAILURE; 491 SCIF_SAS_REMOTE_DEVICE_T * this_device = (SCIF_SAS_REMOTE_DEVICE_T *) 492 remote_device; 493 494 if ( (this_device != NULL) && (containing_device != NULL) ) 495 { 496 *containing_device = (SCI_REMOTE_DEVICE_HANDLE_T)(this_device->containing_device); 497 if (*containing_device != NULL) 498 { 499 status = SCI_SUCCESS; 500 } 501 } 502 503 return status; 504 } 505 506 // --------------------------------------------------------------------------- 507 508 U32 scif_remote_device_get_started_io_count( 509 SCI_REMOTE_DEVICE_HANDLE_T remote_device 510 ) 511 { 512 SCIF_SAS_REMOTE_DEVICE_T * this_device = (SCIF_SAS_REMOTE_DEVICE_T *) 513 remote_device; 514 515 return this_device->request_count - this_device->task_request_count; 516 } 517 //****************************************************************************** 518 //* P R O T E C T E D M E T H O D S 519 //****************************************************************************** 520 521 /* 522 void scif_sas_remote_device_failure( 523 SCIF_SAS_REMOTE_DEVICE_T * fw_device 524 ) 525 { 526 fw_device->parent.is_failed = TRUE; 527 sci_base_state_machine_change_state( 528 &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STOPPING 529 ); 530 } 531 */ 532 533 534 /** 535 * @brief This method retrieves info from Report Phy Sata response and 536 * save the additional data for a SATA remote device, if necessary. 537 * 538 * @param[in] report_phy_sata_response SMP Report Phy Sata response 539 * 540 * @return none 541 */ 542 void scif_sas_remote_device_save_report_phy_sata_information( 543 SMP_RESPONSE_REPORT_PHY_SATA_T * report_phy_sata_response 544 ) 545 { 546 //do nothing currently. Later, if needed, we will search the existed 547 //remote device by stp_sas_address, then save more information for 548 //that device off the report_phy_sata_response. This assumes the 549 //stp_sas_address from report_phy_sata response is the same sas address 550 //from discover response. 551 552 return; 553 } 554 555 /** 556 * @brief This method does target reset for DA or EA remote device. 557 * 558 * @param[in] fw_controller, the controller object the target device belongs 559 * to. 560 * @param[in] fw_device, the target device to be hard reset. 561 * @param[in] fw_request, the scif task request object that asked for this 562 * target reset. 563 */ 564 void scif_sas_remote_device_target_reset( 565 SCIF_SAS_REMOTE_DEVICE_T * fw_device, 566 SCIF_SAS_REQUEST_T * fw_request 567 ) 568 { 569 SCIF_LOG_INFO(( 570 sci_base_object_get_logger(fw_device), 571 SCIF_LOG_OBJECT_REMOTE_DEVICE, 572 "scif_sas_remote_device_target_reset! fw_device:0x%x fw_request:0x%x\n", 573 fw_device, fw_request 574 )); 575 576 if (fw_device->containing_device == NULL) 577 { 578 SCI_PORT_HANDLE_T port; 579 580 port = scif_domain_get_scic_port_handle(fw_device->domain); 581 582 //Direct attached device target reset. 583 //calling core to do port reset. The fw_request will not be used here. 584 scic_port_hard_reset( 585 port, 586 scic_remote_device_get_suggested_reset_timeout(fw_device->core_object) 587 ); 588 } 589 else 590 { //Expander attached device target reset. 591 592 if ( fw_device->containing_device->protocol_device.smp_device.current_activity 593 == SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_TARGET_RESET ) 594 { 595 //The containing expander is in the middle of target resetting other of its 596 //remote disks. Flag this remote device to be target reset later. 597 SCIF_LOG_INFO(( 598 sci_base_object_get_logger(fw_device), 599 SCIF_LOG_OBJECT_REMOTE_DEVICE, 600 "scif_sas_remote_device_target_reset DELAYED! fw_device:0x%x fw_request:0x%x\n", 601 fw_device, fw_request 602 )); 603 604 fw_device->ea_target_reset_request_scheduled = fw_request; 605 return; 606 } 607 608 //set current_activity and current_smp_request to expander device. 609 scif_sas_smp_remote_device_start_target_reset( 610 fw_device->containing_device, fw_device, fw_request); 611 } 612 613 scic_remote_device_reset(fw_device->core_object); 614 } 615 616 617 /** 618 * @brief This method completes target reset for DA or EA remote device. 619 * 620 * @param[in] fw_device, the target device to be hard reset. 621 * @param[in] fw_request, the scif task request object that asked for this 622 * target reset. 623 * @param[in] completion_status 624 */ 625 void scif_sas_remote_device_target_reset_complete( 626 SCIF_SAS_REMOTE_DEVICE_T * fw_device, 627 SCIF_SAS_REQUEST_T * fw_request, 628 SCI_STATUS completion_status 629 ) 630 { 631 SCIF_LOG_INFO(( 632 sci_base_object_get_logger(fw_device), 633 SCIF_LOG_OBJECT_REMOTE_DEVICE, 634 "scif_sas_remote_device_target_reset_complete! " 635 "fw_device:0x%x fw_request:0x%x completion_status 0x%x\n", 636 fw_device, fw_request, completion_status 637 )); 638 639 scif_cb_task_request_complete( 640 fw_device->domain->controller, 641 fw_device, 642 fw_request, 643 (SCI_TASK_STATUS) completion_status 644 ); 645 646 scic_remote_device_reset_complete(fw_device->core_object); 647 648 //For expander attached device done target reset. 649 if (fw_device->containing_device != NULL) 650 { 651 //search for all the devices in the domain to find other remote devices 652 //needs to be target reset. 653 SCIF_SAS_REMOTE_DEVICE_T * next_device; 654 655 scif_sas_smp_remote_device_clear(fw_device->containing_device); 656 657 if( (next_device = scif_sas_domain_find_next_ea_target_reset(fw_device->domain)) 658 != NULL ) 659 { 660 scif_sas_smp_remote_device_start_target_reset( 661 next_device->containing_device, 662 next_device, 663 next_device->ea_target_reset_request_scheduled 664 ); 665 666 next_device->ea_target_reset_request_scheduled = NULL; 667 } 668 else 669 { 670 //if the domain is in the DISCOVER state, we should resume the DISCOVER. 671 if (fw_device->domain->parent.state_machine.current_state_id == 672 SCI_BASE_DOMAIN_STATE_DISCOVERING) 673 { 674 SCIF_SAS_REMOTE_DEVICE_T * top_expander = fw_device->containing_device; 675 676 while(top_expander->containing_device != NULL) 677 top_expander = top_expander->containing_device; 678 679 scif_sas_domain_start_smp_discover(fw_device->domain, top_expander); 680 } 681 else 682 { 683 //Tell driver to kick off Discover process. If the domain is already 684 //in Discovery state, this discovery requst will not be carried on. 685 scif_cb_domain_change_notification( 686 fw_device->domain->controller, fw_device->domain ); 687 } 688 } 689 } 690 else 691 { 692 //Tell driver to kick off Discover process. If the domain is already 693 //in Discovery state, this discovery requst will not be carried on. 694 scif_cb_domain_change_notification( 695 fw_device->domain->controller, fw_device->domain ); 696 } 697 } 698 699 #if !defined(DISABLE_WIDE_PORTED_TARGETS) 700 SCI_STATUS scif_sas_remote_device_update_port_width( 701 SCIF_SAS_REMOTE_DEVICE_T * fw_device, 702 U8 new_port_width 703 ) 704 { 705 SCIF_LOG_INFO(( 706 sci_base_object_get_logger(fw_device), 707 SCIF_LOG_OBJECT_REMOTE_DEVICE, 708 "scif_sas_remote_device_update_port_width (0x%x, 0x%x) enter\n", 709 fw_device, new_port_width 710 )); 711 712 fw_device->device_port_width = new_port_width; 713 714 //Don't Start a new update of port width if a device is already in 715 //UPDATING PORT WIDTH state. 716 if (fw_device->parent.state_machine.current_state_id == SCI_BASE_REMOTE_DEVICE_STATE_READY) 717 { 718 if (fw_device->device_port_width != 0) 719 { 720 //Change state to UPDATING_PORT_WIDTH 721 sci_base_state_machine_change_state( 722 &fw_device->parent.state_machine, 723 SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH 724 ); 725 } 726 727 return SCI_SUCCESS; 728 } 729 else if (fw_device->parent.state_machine.current_state_id == 730 SCI_BASE_REMOTE_DEVICE_STATE_STARTING) 731 { 732 fw_device->destination_state = 733 SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_UPDATING_PORT_WIDTH; 734 } 735 736 return SCI_FAILURE_INVALID_STATE; 737 } 738 #endif //#if !defined(DISABLE_WIDE_PORTED_TARGETS) 739 740 741 #ifdef SCI_LOGGING 742 void scif_sas_remote_device_initialize_state_logging( 743 SCIF_SAS_REMOTE_DEVICE_T * remote_device 744 ) 745 { 746 sci_base_state_machine_logger_initialize( 747 &remote_device->parent.state_machine_logger, 748 &remote_device->parent.state_machine, 749 &remote_device->parent.parent, 750 scif_cb_logger_log_states, 751 "SCIF_SAS_REMOTE_DEVICE_T", "base_state_machine", 752 SCIF_LOG_OBJECT_REMOTE_DEVICE 753 ); 754 755 sci_base_state_machine_logger_initialize( 756 &remote_device->starting_substate_machine_logger, 757 &remote_device->starting_substate_machine, 758 &remote_device->parent.parent, 759 scif_cb_logger_log_states, 760 "SCIF_SAS_REMOTE_DEVICE_T", "starting substate machine", 761 SCIF_LOG_OBJECT_REMOTE_DEVICE 762 ); 763 764 sci_base_state_machine_logger_initialize( 765 &remote_device->ready_substate_machine_logger, 766 &remote_device->ready_substate_machine, 767 &remote_device->parent.parent, 768 scif_cb_logger_log_states, 769 "SCIF_SAS_REMOTE_DEVICE_T", "ready substate machine", 770 SCIF_LOG_OBJECT_REMOTE_DEVICE 771 ); 772 } 773 774 void scif_sas_remote_device_deinitialize_state_logging( 775 SCIF_SAS_REMOTE_DEVICE_T * remote_device 776 ) 777 { 778 sci_base_state_machine_logger_deinitialize( 779 &remote_device->parent.state_machine_logger, 780 &remote_device->parent.state_machine 781 ); 782 783 sci_base_state_machine_logger_deinitialize( 784 &remote_device->starting_substate_machine_logger, 785 &remote_device->starting_substate_machine 786 ); 787 788 sci_base_state_machine_logger_deinitialize( 789 &remote_device->ready_substate_machine_logger, 790 &remote_device->ready_substate_machine 791 ); 792 } 793 #endif // SCI_LOGGING 794 795