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