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_CONTROLLER 60 * object. 61 */ 62 63 64 #include <dev/isci/scil/sci_status.h> 65 #include <dev/isci/scil/sci_util.h> 66 #include <dev/isci/scil/sci_controller.h> 67 #include <dev/isci/scil/scic_controller.h> 68 #include <dev/isci/scil/scic_user_callback.h> 69 #include <dev/isci/scil/scif_user_callback.h> 70 71 #include <dev/isci/scil/scif_sas_controller.h> 72 #include <dev/isci/scil/scif_sas_library.h> 73 #include <dev/isci/scil/scif_sas_logger.h> 74 75 76 //****************************************************************************** 77 //* P U B L I C M E T H O D S 78 //****************************************************************************** 79 80 SCI_STATUS scif_controller_construct( 81 SCI_LIBRARY_HANDLE_T library, 82 SCI_CONTROLLER_HANDLE_T controller, 83 void * user_object 84 ) 85 { 86 SCI_STATUS status = SCI_SUCCESS; 87 SCIF_SAS_LIBRARY_T * fw_library = (SCIF_SAS_LIBRARY_T*) library; 88 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; 89 90 SCIF_LOG_TRACE(( 91 sci_base_object_get_logger(library), 92 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION, 93 "scif_controller_construct(0x%x, 0x%x) enter\n", 94 library, controller 95 )); 96 97 // Validate the user supplied parameters. 98 if ((library == SCI_INVALID_HANDLE) || (controller == SCI_INVALID_HANDLE)) 99 return SCI_FAILURE_INVALID_PARAMETER_VALUE; 100 101 // Construct the base controller. As part of constructing the base 102 // controller we ask it to also manage the MDL iteration for the Core. 103 sci_base_controller_construct( 104 &fw_controller->parent, 105 sci_base_object_get_logger(fw_library), 106 scif_sas_controller_state_table, 107 fw_controller->mdes, 108 SCIF_SAS_MAX_MEMORY_DESCRIPTORS, 109 sci_controller_get_memory_descriptor_list_handle(fw_controller->core_object) 110 ); 111 112 scif_sas_controller_initialize_state_logging(fw_controller); 113 114 sci_object_set_association(fw_controller, user_object); 115 116 status = scic_controller_construct( 117 fw_library->core_object, fw_controller->core_object, fw_controller 118 ); 119 120 // If the core controller was successfully constructed, then 121 // finish construction of the framework controller. 122 if (status == SCI_SUCCESS) 123 { 124 // Set the association in the core controller to this framework 125 // controller. 126 sci_object_set_association( 127 (SCI_OBJECT_HANDLE_T) fw_controller->core_object, fw_controller 128 ); 129 130 sci_base_state_machine_change_state( 131 &fw_controller->parent.state_machine, 132 SCI_BASE_CONTROLLER_STATE_RESET 133 ); 134 } 135 136 return status; 137 } 138 139 // --------------------------------------------------------------------------- 140 141 SCI_STATUS scif_controller_initialize( 142 SCI_CONTROLLER_HANDLE_T controller 143 ) 144 { 145 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; 146 147 SCIF_LOG_TRACE(( 148 sci_base_object_get_logger(controller), 149 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION, 150 "scif_controller_initialize(0x%x) enter\n", 151 controller 152 )); 153 154 // Validate the user supplied parameters. 155 if (controller == SCI_INVALID_HANDLE) 156 return SCI_FAILURE_INVALID_PARAMETER_VALUE; 157 158 return fw_controller->state_handlers->initialize_handler( 159 &fw_controller->parent 160 ); 161 } 162 163 // --------------------------------------------------------------------------- 164 165 U32 scif_controller_get_suggested_start_timeout( 166 SCI_CONTROLLER_HANDLE_T controller 167 ) 168 { 169 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; 170 171 // Validate the user supplied parameters. 172 if (controller == SCI_INVALID_HANDLE) 173 return 0; 174 175 // Currently we aren't adding any additional time into the suggested 176 // timeout value for the start operation. Simply utilize the core 177 // value. 178 return scic_controller_get_suggested_start_timeout(fw_controller->core_object); 179 } 180 181 // --------------------------------------------------------------------------- 182 183 SCI_STATUS scif_controller_start( 184 SCI_CONTROLLER_HANDLE_T controller, 185 U32 timeout 186 ) 187 { 188 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; 189 190 SCIF_LOG_TRACE(( 191 sci_base_object_get_logger(controller), 192 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION, 193 "scif_controller_start(0x%x, 0x%x) enter\n", 194 controller, timeout 195 )); 196 197 // Validate the user supplied parameters. 198 if (controller == SCI_INVALID_HANDLE) 199 return SCI_FAILURE_INVALID_PARAMETER_VALUE; 200 201 return fw_controller->state_handlers-> 202 start_handler(&fw_controller->parent, timeout); 203 } 204 205 // --------------------------------------------------------------------------- 206 207 SCI_STATUS scif_controller_stop( 208 SCI_CONTROLLER_HANDLE_T controller, 209 U32 timeout 210 ) 211 { 212 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; 213 214 SCIF_LOG_TRACE(( 215 sci_base_object_get_logger(controller), 216 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN, 217 "scif_controller_stop(0x%x, 0x%x) enter\n", 218 controller, timeout 219 )); 220 221 // Validate the user supplied parameters. 222 if (controller == SCI_INVALID_HANDLE) 223 return SCI_FAILURE_INVALID_PARAMETER_VALUE; 224 225 return fw_controller->state_handlers-> 226 stop_handler(&fw_controller->parent, timeout); 227 228 } 229 230 // --------------------------------------------------------------------------- 231 232 SCI_STATUS scif_controller_reset( 233 SCI_CONTROLLER_HANDLE_T controller 234 ) 235 { 236 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; 237 238 SCIF_LOG_TRACE(( 239 sci_base_object_get_logger(controller), 240 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_CONTROLLER_RESET, 241 "scif_controller_reset(0x%x) enter\n", 242 controller 243 )); 244 245 // Validate the user supplied parameters. 246 if (controller == SCI_INVALID_HANDLE) 247 return SCI_FAILURE_INVALID_PARAMETER_VALUE; 248 249 return fw_controller->state_handlers-> 250 reset_handler(&fw_controller->parent); 251 } 252 253 // --------------------------------------------------------------------------- 254 255 SCI_CONTROLLER_HANDLE_T scif_controller_get_scic_handle( 256 SCI_CONTROLLER_HANDLE_T controller 257 ) 258 { 259 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; 260 261 return fw_controller->core_object; 262 } 263 264 // --------------------------------------------------------------------------- 265 266 SCI_IO_STATUS scif_controller_start_io( 267 SCI_CONTROLLER_HANDLE_T controller, 268 SCI_REMOTE_DEVICE_HANDLE_T remote_device, 269 SCI_IO_REQUEST_HANDLE_T io_request, 270 U16 io_tag 271 ) 272 { 273 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; 274 275 SCIF_LOG_TRACE(( 276 sci_base_object_get_logger(controller), 277 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST, 278 "scif_controller_start_io(0x%x, 0x%x, 0x%x, 0x%x) enter\n", 279 controller, remote_device, io_request, io_tag 280 )); 281 282 if ( 283 sci_pool_empty(fw_controller->hprq.pool) 284 || scif_sas_controller_sufficient_resource(controller) 285 ) 286 { 287 return fw_controller->state_handlers->start_io_handler( 288 (SCI_BASE_CONTROLLER_T*) controller, 289 (SCI_BASE_REMOTE_DEVICE_T*) remote_device, 290 (SCI_BASE_REQUEST_T*) io_request, 291 io_tag 292 ); 293 } 294 else 295 return SCI_FAILURE_INSUFFICIENT_RESOURCES; 296 } 297 298 // --------------------------------------------------------------------------- 299 300 SCI_TASK_STATUS scif_controller_start_task( 301 SCI_CONTROLLER_HANDLE_T controller, 302 SCI_REMOTE_DEVICE_HANDLE_T remote_device, 303 SCI_TASK_REQUEST_HANDLE_T task_request, 304 U16 io_tag 305 ) 306 { 307 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; 308 309 SCIF_LOG_TRACE(( 310 sci_base_object_get_logger(controller), 311 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_TASK_MANAGEMENT, 312 "scif_controller_start_task(0x%x, 0x%x, 0x%x, 0x%x) enter\n", 313 controller, remote_device, task_request, io_tag 314 )); 315 316 // Validate the user supplied parameters. 317 if ( (controller == SCI_INVALID_HANDLE) 318 || (remote_device == SCI_INVALID_HANDLE) 319 || (task_request == SCI_INVALID_HANDLE) ) 320 { 321 return SCI_FAILURE_INVALID_PARAMETER_VALUE; 322 } 323 324 if (scif_sas_controller_sufficient_resource(controller)) 325 { 326 return fw_controller->state_handlers->start_task_handler( 327 (SCI_BASE_CONTROLLER_T*) controller, 328 (SCI_BASE_REMOTE_DEVICE_T*) remote_device, 329 (SCI_BASE_REQUEST_T*) task_request, 330 io_tag 331 ); 332 } 333 else 334 return SCI_FAILURE_INSUFFICIENT_RESOURCES; 335 } 336 337 // --------------------------------------------------------------------------- 338 339 SCI_STATUS scif_controller_complete_io( 340 SCI_CONTROLLER_HANDLE_T controller, 341 SCI_REMOTE_DEVICE_HANDLE_T remote_device, 342 SCI_IO_REQUEST_HANDLE_T io_request 343 ) 344 { 345 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; 346 347 SCIF_LOG_TRACE(( 348 sci_base_object_get_logger(controller), 349 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST, 350 "scif_controller_complete_io(0x%x, 0x%x, 0x%x) enter\n", 351 controller, remote_device, io_request 352 )); 353 354 return fw_controller->state_handlers->complete_io_handler( 355 (SCI_BASE_CONTROLLER_T*) controller, 356 (SCI_BASE_REMOTE_DEVICE_T*) remote_device, 357 (SCI_BASE_REQUEST_T*) io_request 358 ); 359 } 360 361 // --------------------------------------------------------------------------- 362 363 SCI_STATUS scif_controller_complete_task( 364 SCI_CONTROLLER_HANDLE_T controller, 365 SCI_REMOTE_DEVICE_HANDLE_T remote_device, 366 SCI_TASK_REQUEST_HANDLE_T task_request 367 ) 368 { 369 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; 370 371 SCIF_LOG_TRACE(( 372 sci_base_object_get_logger(controller), 373 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_TASK_MANAGEMENT, 374 "scif_controller_complete_task(0x%x, 0x%x, 0x%x) enter\n", 375 controller, remote_device, task_request 376 )); 377 378 // Validate the user supplied parameters. 379 if ( (controller == SCI_INVALID_HANDLE) 380 || (remote_device == SCI_INVALID_HANDLE) 381 || (task_request == SCI_INVALID_HANDLE) ) 382 { 383 return SCI_FAILURE_INVALID_PARAMETER_VALUE; 384 } 385 386 return fw_controller->state_handlers->complete_task_handler( 387 (SCI_BASE_CONTROLLER_T*) controller, 388 (SCI_BASE_REMOTE_DEVICE_T*) remote_device, 389 (SCI_BASE_REQUEST_T*) task_request 390 ); 391 } 392 393 // --------------------------------------------------------------------------- 394 395 SCI_STATUS scif_controller_get_domain_handle( 396 SCI_CONTROLLER_HANDLE_T controller, 397 U8 port_index, 398 SCI_DOMAIN_HANDLE_T * domain_handle 399 ) 400 { 401 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; 402 403 // Validate the user supplied parameters. 404 if (controller == SCI_INVALID_HANDLE) 405 return SCI_FAILURE_INVALID_PARAMETER_VALUE; 406 407 // Retrieve the domain handle if the supplied index is legitimate. 408 if (port_index < SCI_MAX_PORTS) 409 { 410 *domain_handle = &fw_controller->domains[port_index]; 411 return SCI_SUCCESS; 412 } 413 414 return SCI_FAILURE_INVALID_PORT; 415 } 416 417 /** 418 * @brief This method builds the memory descriptor list for this 419 * controller. 420 * 421 * @param[in] fw_controller This parameter specifies the framework 422 * controller object for which to build the MDL. 423 * 424 * @return none 425 */ 426 void scif_sas_controller_build_mdl( 427 SCIF_SAS_CONTROLLER_T * fw_controller 428 ) 429 { 430 // one internal request for each domain. 431 sci_base_mde_construct( 432 &fw_controller->mdes[SCIF_SAS_MDE_INTERNAL_IO], 433 4, 434 fw_controller->internal_request_entries * 435 scif_sas_internal_request_get_object_size(), 436 SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS 437 ); 438 } 439 440 // --------------------------------------------------------------------------- 441 442 SCI_STATUS scif_controller_set_mode( 443 SCI_CONTROLLER_HANDLE_T controller, 444 SCI_CONTROLLER_MODE mode 445 ) 446 { 447 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; 448 SCI_STATUS status = SCI_SUCCESS; 449 450 if ( 451 (fw_controller->parent.state_machine.current_state_id 452 == SCI_BASE_CONTROLLER_STATE_INITIALIZING) 453 || (fw_controller->parent.state_machine.current_state_id 454 == SCI_BASE_CONTROLLER_STATE_INITIALIZED) 455 ) 456 { 457 switch (mode) 458 { 459 case SCI_MODE_SPEED: 460 fw_controller->internal_request_entries = 461 MIN(fw_controller->internal_request_entries, SCIF_SAS_MAX_INTERNAL_REQUEST_COUNT); 462 scif_sas_controller_build_mdl(fw_controller); 463 break; 464 465 case SCI_MODE_SIZE: 466 fw_controller->internal_request_entries = 467 MIN(fw_controller->internal_request_entries, SCIF_SAS_MIN_INTERNAL_REQUEST_COUNT); 468 scif_sas_controller_build_mdl(fw_controller); 469 break; 470 471 default: 472 status = SCI_FAILURE_INVALID_PARAMETER_VALUE; 473 break; 474 } 475 } 476 else 477 status = SCI_FAILURE_INVALID_STATE; 478 479 if (status != SCI_SUCCESS) 480 { 481 return status; 482 } 483 else 484 { 485 // Currently, the framework doesn't change any configurations for 486 // speed or size modes. Default to speed mode basically. 487 return scic_controller_set_mode(fw_controller->core_object, mode); 488 } 489 } 490 491 // --------------------------------------------------------------------------- 492 493 U32 scif_controller_get_sat_compliance_version( 494 void 495 ) 496 { 497 /// @todo Fix return of SAT compliance version. 498 return 0; 499 } 500 501 // --------------------------------------------------------------------------- 502 503 U32 scif_controller_get_sat_compliance_version_revision( 504 void 505 ) 506 { 507 /// @todo Fix return of SAT compliance revision. 508 return 0; 509 } 510 511 // --------------------------------------------------------------------------- 512 513 SCI_STATUS scif_user_parameters_set( 514 SCI_CONTROLLER_HANDLE_T controller, 515 SCIF_USER_PARAMETERS_T * scif_parms 516 ) 517 { 518 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; 519 520 //validate all the registry entries before overwriting the default parameter 521 //values. 522 if (scif_parms->sas.is_sata_ncq_enabled != 1 && scif_parms->sas.is_sata_ncq_enabled != 0) 523 return SCI_FAILURE_INVALID_PARAMETER_VALUE; 524 525 if (scif_parms->sas.max_ncq_depth < 1 && scif_parms->sas.max_ncq_depth > 32) 526 return SCI_FAILURE_INVALID_PARAMETER_VALUE; 527 528 if (scif_parms->sas.is_sata_standby_timer_enabled != 1 529 && scif_parms->sas.is_sata_standby_timer_enabled != 0) 530 return SCI_FAILURE_INVALID_PARAMETER_VALUE; 531 532 if (scif_parms->sas.is_non_zero_buffer_offsets_enabled != 1 533 && scif_parms->sas.is_non_zero_buffer_offsets_enabled != 0) 534 return SCI_FAILURE_INVALID_PARAMETER_VALUE; 535 536 if (scif_parms->sas.reset_type != SCI_SAS_ABORT_TASK 537 && scif_parms->sas.reset_type != SCI_SAS_ABORT_TASK_SET 538 && scif_parms->sas.reset_type != SCI_SAS_CLEAR_TASK_SET 539 && scif_parms->sas.reset_type != SCI_SAS_LOGICAL_UNIT_RESET 540 && scif_parms->sas.reset_type != SCI_SAS_I_T_NEXUS_RESET 541 && scif_parms->sas.reset_type != SCI_SAS_CLEAR_ACA 542 && scif_parms->sas.reset_type != SCI_SAS_QUERY_TASK 543 && scif_parms->sas.reset_type != SCI_SAS_QUERY_TASK_SET 544 && scif_parms->sas.reset_type != SCI_SAS_QUERY_ASYNCHRONOUS_EVENT 545 && scif_parms->sas.reset_type != SCI_SAS_HARD_RESET) 546 return SCI_FAILURE_INVALID_PARAMETER_VALUE; 547 548 if (scif_parms->sas.clear_affiliation_during_controller_stop != 1 549 && scif_parms->sas.clear_affiliation_during_controller_stop !=0) 550 return SCI_FAILURE_INVALID_PARAMETER_VALUE; 551 552 memcpy((&fw_controller->user_parameters), scif_parms, sizeof(*scif_parms)); 553 554 // In the future more could be done to prevent setting parameters at the 555 // wrong time, but for now we'll simply set the values even if it is too 556 // late for them to take affect. 557 return SCI_SUCCESS; 558 } 559 560 // --------------------------------------------------------------------------- 561 562 #if !defined(DISABLE_INTERRUPTS) 563 564 /** 565 * @brief This routine check each domain of the controller to see if 566 * any domain is overriding interrupt coalescence. 567 * 568 * @param[in] fw_controller frame controller 569 * @param[in] fw_smp_phy The smp phy to be freed. 570 * 571 * @return none 572 */ 573 static 574 BOOL scif_sas_controller_is_overriding_interrupt_coalescence( 575 SCIF_SAS_CONTROLLER_T * fw_controller 576 ) 577 { 578 U8 index; 579 580 for(index = 0; index < SCI_MAX_DOMAINS; index++) 581 { 582 if(fw_controller->domains[index].parent.state_machine.current_state_id == 583 SCI_BASE_DOMAIN_STATE_DISCOVERING) 584 return TRUE; 585 } 586 587 return FALSE; 588 } 589 590 SCI_STATUS scif_controller_set_interrupt_coalescence( 591 SCI_CONTROLLER_HANDLE_T controller, 592 U32 coalesce_number, 593 U32 coalesce_timeout 594 ) 595 { 596 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T * )controller; 597 598 ///when framework is in the middle of temporarily overriding the interrupt 599 ///coalescence values, user's request of setting interrupt coalescence 600 ///will be saved. As soon as the framework done the temporary overriding, 601 ///it will serve user's request to set new interrupt coalescence. 602 if (scif_sas_controller_is_overriding_interrupt_coalescence(fw_controller)) 603 { 604 U32 curr_coalesce_number; 605 U32 curr_coalesce_timeout; 606 SCI_STATUS core_status; 607 608 // save current interrupt coalescence info. 609 scic_controller_get_interrupt_coalescence ( 610 fw_controller->core_object, &curr_coalesce_number, &curr_coalesce_timeout); 611 612 //try user's request out in the core, but immediately restore core's 613 //current setting. 614 core_status = scic_controller_set_interrupt_coalescence( 615 fw_controller->core_object, coalesce_number, coalesce_timeout); 616 617 if ( core_status == SCI_SUCCESS ) 618 { 619 fw_controller->saved_interrupt_coalesce_number = (U16)coalesce_number; 620 fw_controller->saved_interrupt_coalesce_timeout = coalesce_timeout; 621 } 622 623 //restore current interrupt coalescence. 624 scic_controller_set_interrupt_coalescence( 625 fw_controller->core_object, curr_coalesce_number, curr_coalesce_timeout); 626 627 return core_status; 628 } 629 else 630 { 631 ///If framework is not internally overriding the interrupt coalescence, 632 ///serve user's request immediately by passing the reqeust to core. 633 return scic_controller_set_interrupt_coalescence( 634 fw_controller->core_object, coalesce_number, coalesce_timeout); 635 } 636 } 637 638 // --------------------------------------------------------------------------- 639 640 void scif_controller_get_interrupt_coalescence( 641 SCI_CONTROLLER_HANDLE_T controller, 642 U32 * coalesce_number, 643 U32 * coalesce_timeout 644 ) 645 { 646 SCIF_SAS_CONTROLLER_T * scif_controller = (SCIF_SAS_CONTROLLER_T * )controller; 647 648 scic_controller_get_interrupt_coalescence( 649 scif_controller->core_object, coalesce_number, coalesce_timeout); 650 } 651 652 /** 653 * @brief This method will save the interrupt coalescence values. If 654 * the interrupt coalescence values have already been saved, 655 * then this method performs no operations. 656 * 657 * @param[in,out] fw_controller This parameter specifies the controller 658 * for which to save the interrupt coalescence values. 659 * 660 * @return none 661 */ 662 void scif_sas_controller_save_interrupt_coalescence( 663 SCIF_SAS_CONTROLLER_T * fw_controller 664 ) 665 { 666 if ( !scif_sas_controller_is_overriding_interrupt_coalescence(fw_controller)) 667 { 668 // Override core's interrupt coalescing settings during SMP 669 // DISCOVER process cause' there is only 1 outstanding SMP 670 // request per domain is allowed. 671 scic_controller_get_interrupt_coalescence( 672 fw_controller->core_object, 673 (U32*)&(fw_controller->saved_interrupt_coalesce_number), 674 &(fw_controller->saved_interrupt_coalesce_timeout) 675 ); 676 677 // Temporarily disable the interrupt coalescing. 678 scic_controller_set_interrupt_coalescence(fw_controller->core_object,0,0); 679 } 680 } 681 682 /** 683 * @brief This method will restore the interrupt coalescence values. If 684 * the interrupt coalescence values have not already been saved, 685 * then this method performs no operations. 686 * 687 * @param[in,out] fw_controller This parameter specifies the controller 688 * for which to restore the interrupt coalescence values. 689 * 690 * @return none 691 */ 692 void scif_sas_controller_restore_interrupt_coalescence( 693 SCIF_SAS_CONTROLLER_T * fw_controller 694 ) 695 { 696 if ( !scif_sas_controller_is_overriding_interrupt_coalescence(fw_controller)) 697 scic_controller_set_interrupt_coalescence( 698 fw_controller->core_object, 699 fw_controller->saved_interrupt_coalesce_number, 700 fw_controller->saved_interrupt_coalesce_timeout 701 ); 702 } 703 704 #endif // !defined(DISABLE_INTERRUPTS) 705 706 // --------------------------------------------------------------------------- 707 708 void scic_cb_controller_start_complete( 709 SCI_CONTROLLER_HANDLE_T controller, 710 SCI_STATUS completion_status 711 ) 712 { 713 SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*) 714 sci_object_get_association(controller); 715 716 SCIF_LOG_TRACE(( 717 sci_base_object_get_logger(controller), 718 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION, 719 "scic_cb_controller_start_complete(0x%x, 0x%x) enter\n", 720 controller, completion_status 721 )); 722 723 if (completion_status == SCI_SUCCESS 724 || completion_status == SCI_FAILURE_TIMEOUT) 725 { 726 // Even the initialization of the core controller timed out, framework 727 // controller should still transit to READY state. 728 sci_base_state_machine_change_state( 729 &fw_controller->parent.state_machine, 730 SCI_BASE_CONTROLLER_STATE_READY 731 ); 732 } 733 734 scif_cb_controller_start_complete(fw_controller, completion_status); 735 } 736 737 // --------------------------------------------------------------------------- 738 739 void scic_cb_controller_stop_complete( 740 SCI_CONTROLLER_HANDLE_T controller, 741 SCI_STATUS completion_status 742 ) 743 { 744 SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*) 745 sci_object_get_association(controller); 746 747 SCIF_LOG_TRACE(( 748 sci_base_object_get_logger(controller), 749 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN, 750 "scic_cb_controller_stop_complete(0x%x, 0x%x) enter\n", 751 controller, completion_status 752 )); 753 754 if (completion_status == SCI_SUCCESS) 755 { 756 sci_base_state_machine_change_state( 757 &fw_controller->parent.state_machine, 758 SCI_BASE_CONTROLLER_STATE_STOPPED 759 ); 760 } 761 else 762 { 763 sci_base_state_machine_change_state( 764 &fw_controller->parent.state_machine, 765 SCI_BASE_CONTROLLER_STATE_FAILED 766 ); 767 } 768 769 scif_cb_controller_stop_complete(fw_controller, completion_status); 770 } 771 772 773 // --------------------------------------------------------------------------- 774 775 void scic_cb_controller_error( 776 SCI_CONTROLLER_HANDLE_T controller, 777 SCI_CONTROLLER_ERROR error 778 ) 779 { 780 SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*) 781 sci_object_get_association(controller); 782 783 fw_controller->parent.error = error; 784 785 SCIF_LOG_TRACE(( 786 sci_base_object_get_logger(controller), 787 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN, 788 "scic_cb_controller_not_ready(0x%x) enter\n", 789 controller 790 )); 791 792 sci_base_state_machine_change_state( 793 &fw_controller->parent.state_machine, 794 SCI_BASE_CONTROLLER_STATE_FAILED 795 ); 796 } 797 798 //****************************************************************************** 799 //* P R O T E C T E D M E T H O D S 800 //****************************************************************************** 801 802 /** 803 * @brief This method is utilized to continue an internal IO operation 804 * on the controller. This method is utilized for SAT translated 805 * requests that generate multiple ATA commands in order to fulfill 806 * the original SCSI request. 807 * 808 * @param[in] controller This parameter specifies the controller on which 809 * to continue an internal IO request. 810 * @param[in] remote_device This parameter specifies the remote device 811 * on which to continue an internal IO request. 812 * @param[in] io_request This parameter specifies the IO request to be 813 * continue. 814 * 815 * @return Indicate if the continue operation was successful. 816 * @retval SCI_SUCCESS This value is returned if the operation succeeded. 817 */ 818 SCI_STATUS scif_sas_controller_continue_io( 819 SCI_CONTROLLER_HANDLE_T controller, 820 SCI_REMOTE_DEVICE_HANDLE_T remote_device, 821 SCI_IO_REQUEST_HANDLE_T io_request 822 ) 823 { 824 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; 825 826 return fw_controller->state_handlers->continue_io_handler( 827 (SCI_BASE_CONTROLLER_T*) controller, 828 (SCI_BASE_REMOTE_DEVICE_T*) remote_device, 829 (SCI_BASE_REQUEST_T*) io_request 830 ); 831 } 832 833 /** 834 * @brief This method will attempt to destruct a framework controller. 835 * This includes free any resources retreived from the user (e.g. 836 * timers). 837 * 838 * @param[in] fw_controller This parameter specifies the framework 839 * controller to destructed. 840 * 841 * @return none 842 */ 843 void scif_sas_controller_destruct( 844 SCIF_SAS_CONTROLLER_T * fw_controller 845 ) 846 { 847 SCIF_LOG_TRACE(( 848 sci_base_object_get_logger(fw_controller), 849 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN, 850 "scif_sas_controller_destruct(0x%x) enter\n", 851 fw_controller 852 )); 853 } 854 855 //----------------------------------------------------------------------------- 856 // INTERNAL REQUEST RELATED METHODS 857 //----------------------------------------------------------------------------- 858 859 /** 860 * @brief This routine is to allocate the memory for creating a new internal 861 * request. 862 * 863 * @param[in] scif_controller handle to frame controller 864 * 865 * @return void* address to internal request memory 866 */ 867 void * scif_sas_controller_allocate_internal_request( 868 SCIF_SAS_CONTROLLER_T * fw_controller 869 ) 870 { 871 POINTER_UINT internal_io_address; 872 873 if( !sci_pool_empty(fw_controller->internal_request_memory_pool) ) 874 { 875 sci_pool_get( 876 fw_controller->internal_request_memory_pool, internal_io_address 877 ); 878 879 //clean the memory. 880 memset((char*)internal_io_address, 0, scif_sas_internal_request_get_object_size()); 881 882 return (void *) internal_io_address; 883 } 884 else 885 return NULL; 886 } 887 888 /** 889 * @brief This routine is to free the memory for a completed internal request. 890 * 891 * @param[in] scif_controller handle to frame controller 892 * @param[in] fw_internal_io The internal IO to be freed. 893 * 894 * @return none 895 */ 896 void scif_sas_controller_free_internal_request( 897 SCIF_SAS_CONTROLLER_T * fw_controller, 898 void * fw_internal_request_buffer 899 ) 900 { 901 SCIF_LOG_TRACE(( 902 sci_base_object_get_logger(fw_controller), 903 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST, 904 "scif_controller_free_internal_request(0x%x, 0x%x) enter\n", 905 fw_controller, fw_internal_request_buffer 906 )); 907 908 //return the memory to to pool. 909 if( !sci_pool_full(fw_controller->internal_request_memory_pool) ) 910 { 911 sci_pool_put( 912 fw_controller->internal_request_memory_pool, 913 (POINTER_UINT) fw_internal_request_buffer 914 ); 915 } 916 } 917 918 919 /** 920 * @brief this routine is called by OS' DPC to start io requests from internal 921 * high priority request queue 922 * @param[in] fw_controller The framework controller. 923 * 924 * @return none 925 */ 926 void scif_sas_controller_start_high_priority_io( 927 SCIF_SAS_CONTROLLER_T * fw_controller 928 ) 929 { 930 POINTER_UINT io_address; 931 SCIF_SAS_IO_REQUEST_T * fw_io; 932 SCI_STATUS status; 933 934 SCIF_LOG_TRACE(( 935 sci_base_object_get_logger(fw_controller), 936 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST, 937 "scif_controller_start_high_priority_io(0x%x) enter\n", 938 fw_controller 939 )); 940 941 while ( !sci_pool_empty(fw_controller->hprq.pool) ) 942 { 943 sci_pool_get(fw_controller->hprq.pool, io_address); 944 945 fw_io = (SCIF_SAS_IO_REQUEST_T *)io_address; 946 947 status = fw_controller->state_handlers->start_high_priority_io_handler( 948 (SCI_BASE_CONTROLLER_T*) fw_controller, 949 (SCI_BASE_REMOTE_DEVICE_T*) fw_io->parent.device, 950 (SCI_BASE_REQUEST_T*) fw_io, 951 SCI_CONTROLLER_INVALID_IO_TAG 952 ); 953 } 954 } 955 956 /** 957 * @brief This method will check how many outstanding IOs currently and number 958 * of IOs in high priority queue, if the overall number exceeds the max_tc, 959 * return FALSE. 960 * 961 * @param[in] fw_controller The framework controller. 962 * 963 * @return BOOL Indicate whether there is sufficient resource to start an IO. 964 * @retvalue TRUE The controller has sufficient resource. 965 * @retvalue FALSE There is not sufficient resource available. 966 */ 967 BOOL scif_sas_controller_sufficient_resource( 968 SCIF_SAS_CONTROLLER_T *fw_controller 969 ) 970 { 971 SCIF_SAS_DOMAIN_T * fw_domain; 972 U32 domain_index; 973 U32 outstanding_io_count = 0; 974 U32 high_priority_io_count = 0; 975 976 for(domain_index = 0; domain_index < SCI_MAX_DOMAINS; domain_index++) 977 { 978 fw_domain = &fw_controller->domains[domain_index]; 979 outstanding_io_count += fw_domain->request_list.element_count; 980 } 981 982 high_priority_io_count = sci_pool_count(fw_controller->hprq.pool); 983 984 if ( (outstanding_io_count + high_priority_io_count) > SCI_MAX_IO_REQUESTS ) 985 return FALSE; 986 987 return TRUE; 988 } 989 990 991 /** 992 * @brief This method is the starting point to complete high prority io for a 993 * controller then down to domain, device. 994 * 995 * @param[in] fw_controller The framework controller 996 * @param[in] remote_device The framework remote device. 997 * @param[in] io_request The high priority io request to be completed. 998 * 999 * @return SCI_STATUS indicate the completion status from framework down to the 1000 * core. 1001 */ 1002 SCI_STATUS scif_sas_controller_complete_high_priority_io( 1003 SCIF_SAS_CONTROLLER_T *fw_controller, 1004 SCIF_SAS_REMOTE_DEVICE_T *remote_device, 1005 SCIF_SAS_REQUEST_T *io_request 1006 ) 1007 { 1008 SCIF_LOG_TRACE(( 1009 sci_base_object_get_logger(fw_controller), 1010 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST, 1011 "scif_sas_controller_complete_high_priority_io(0x%x, 0x%x, 0x%x) enter\n", 1012 fw_controller, remote_device, io_request 1013 )); 1014 1015 //call controller's new added complete_high_priority_io_handler 1016 return fw_controller->state_handlers->complete_high_priority_io_handler( 1017 (SCI_BASE_CONTROLLER_T*) fw_controller, 1018 (SCI_BASE_REMOTE_DEVICE_T*) remote_device, 1019 (SCI_BASE_REQUEST_T*) io_request 1020 ); 1021 } 1022 1023 /** 1024 1025 * @brief This routine is to allocate the memory for creating a smp phy object. 1026 * 1027 * @param[in] scif_controller handle to frame controller 1028 * 1029 * @return SCIF_SAS_SMP_PHY_T * An allocated space for smp phy. If failed to allocate, 1030 * return NULL. 1031 */ 1032 SCIF_SAS_SMP_PHY_T * scif_sas_controller_allocate_smp_phy( 1033 SCIF_SAS_CONTROLLER_T * fw_controller 1034 ) 1035 { 1036 SCIF_SAS_SMP_PHY_T * smp_phy; 1037 1038 SCIF_LOG_TRACE(( 1039 sci_base_object_get_logger(fw_controller), 1040 SCIF_LOG_OBJECT_CONTROLLER, 1041 "scif_controller_allocate_smp_phy(0x%x) enter\n", 1042 fw_controller 1043 )); 1044 1045 if( !sci_fast_list_is_empty(&fw_controller->smp_phy_memory_list) ) 1046 { 1047 smp_phy = (SCIF_SAS_SMP_PHY_T *) 1048 sci_fast_list_remove_head(&fw_controller->smp_phy_memory_list); 1049 1050 //clean the memory. 1051 memset((char*)smp_phy, 1052 0, 1053 sizeof(SCIF_SAS_SMP_PHY_T) 1054 ); 1055 1056 return smp_phy; 1057 } 1058 else 1059 return NULL; 1060 } 1061 1062 /** 1063 * @brief This routine is to free the memory for a released smp phy. 1064 * 1065 * @param[in] fw_controller The framework controller, a smp phy is released 1066 * to its memory. 1067 * @param[in] fw_smp_phy The smp phy to be freed. 1068 * 1069 * @return none 1070 */ 1071 void scif_sas_controller_free_smp_phy( 1072 SCIF_SAS_CONTROLLER_T * fw_controller, 1073 SCIF_SAS_SMP_PHY_T * smp_phy 1074 ) 1075 { 1076 SCIF_LOG_TRACE(( 1077 sci_base_object_get_logger(fw_controller), 1078 SCIF_LOG_OBJECT_CONTROLLER, 1079 "scif_controller_free_smp_phy(0x%x, 0x%x) enter\n", 1080 fw_controller, smp_phy 1081 )); 1082 1083 //return the memory to the list. 1084 sci_fast_list_insert_tail( 1085 &fw_controller->smp_phy_memory_list, 1086 &smp_phy->list_element 1087 ); 1088 } 1089 1090 1091 /** 1092 * @brief This method clear affiliation for all the EA SATA devices associated 1093 * to this controller. 1094 * 1095 * @param[in] fw_controller This parameter specifies the framework 1096 * controller object for whose remote devices are to be stopped. 1097 * 1098 * @return This method returns a value indicating if the operation completed. 1099 * @retval SCI_COMPLETE This value indicates that all the EA SATA devices' 1100 * affiliation was cleared. 1101 * @retval SCI_INCOMPLETE This value indicates clear affiliation activity is 1102 * yet to be completed. 1103 */ 1104 SCI_STATUS scif_sas_controller_clear_affiliation( 1105 SCIF_SAS_CONTROLLER_T * fw_controller 1106 ) 1107 { 1108 U8 index; 1109 SCI_STATUS status; 1110 SCIF_SAS_DOMAIN_T * fw_domain; 1111 1112 SCIF_LOG_TRACE(( 1113 sci_base_object_get_logger(fw_controller), 1114 SCIF_LOG_OBJECT_CONTROLLER, 1115 "scif_sas_controller_clear_affiliation(0x%x) enter\n", 1116 fw_controller 1117 )); 1118 1119 index = fw_controller->current_domain_to_clear_affiliation; 1120 1121 if (index < SCI_MAX_DOMAINS) 1122 { 1123 fw_domain = &fw_controller->domains[index]; 1124 1125 //Need to stop all the on-going smp activities before clearing affiliation. 1126 scif_sas_domain_cancel_smp_activities(fw_domain); 1127 1128 scif_sas_domain_start_clear_affiliation(fw_domain); 1129 1130 status = SCI_WARNING_SEQUENCE_INCOMPLETE; 1131 } 1132 else 1133 { //the controller has done clear affiliation work to all its domains. 1134 scif_sas_controller_continue_to_stop(fw_controller); 1135 status = SCI_SUCCESS; 1136 } 1137 1138 return status; 1139 } 1140 1141 1142 /** 1143 * @brief This method sets SCIF user parameters to 1144 * default values. Users can override these values utilizing 1145 * the sciF_user_parameters_set() methods. 1146 * 1147 * @param[in] controller This parameter specifies the controller for 1148 * which to set the configuration parameters to their 1149 * default values. 1150 * 1151 * @return none 1152 */ 1153 void scif_sas_controller_set_default_config_parameters( 1154 SCIF_SAS_CONTROLLER_T * this_controller 1155 ) 1156 { 1157 SCIF_USER_PARAMETERS_T * scif_parms = &(this_controller->user_parameters); 1158 1159 scif_parms->sas.is_sata_ncq_enabled = TRUE; 1160 scif_parms->sas.max_ncq_depth = 32; 1161 scif_parms->sas.is_sata_standby_timer_enabled = FALSE; 1162 scif_parms->sas.is_non_zero_buffer_offsets_enabled = FALSE; 1163 scif_parms->sas.reset_type = SCI_SAS_LOGICAL_UNIT_RESET; 1164 scif_parms->sas.clear_affiliation_during_controller_stop = TRUE; 1165 scif_parms->sas.ignore_fua = FALSE; 1166 1167 } 1168 1169 1170 /** 1171 * @brief This method releases resource for framework controller and associated 1172 * objects. 1173 * 1174 * @param[in] fw_controller This parameter specifies the framework 1175 * controller and associated objects whose resources are to be released. 1176 * 1177 * @return This method returns a value indicating if the operation succeeded. 1178 * @retval SCI_SUCCESS This value indicates that resource release succeeded. 1179 * @retval SCI_FAILURE This value indicates certain failure during the process 1180 * of resource release. 1181 */ 1182 SCI_STATUS scif_sas_controller_release_resource( 1183 SCIF_SAS_CONTROLLER_T * fw_controller 1184 ) 1185 { 1186 U8 index; 1187 SCIF_SAS_DOMAIN_T * fw_domain; 1188 1189 SCIF_LOG_TRACE(( 1190 sci_base_object_get_logger(fw_controller), 1191 SCIF_LOG_OBJECT_CONTROLLER, 1192 "scif_sas_controller_release_resource(0x%x) enter\n", 1193 fw_controller 1194 )); 1195 1196 //currently the only resource to be released is domain's timer. 1197 for (index = 0; index < SCI_MAX_DOMAINS; index++) 1198 { 1199 fw_domain = &fw_controller->domains[index]; 1200 1201 scif_sas_domain_release_resource(fw_controller, fw_domain); 1202 } 1203 1204 return SCI_SUCCESS; 1205 } 1206 1207 1208 #ifdef SCI_LOGGING 1209 /** 1210 * This method will start state transition logging for the framework 1211 * controller object. 1212 * 1213 * @param[in] fw_controller The framework controller object on which to 1214 * observe state changes. 1215 * 1216 * @return none 1217 */ 1218 void scif_sas_controller_initialize_state_logging( 1219 SCIF_SAS_CONTROLLER_T * fw_controller 1220 ) 1221 { 1222 sci_base_state_machine_logger_initialize( 1223 &fw_controller->parent.state_machine_logger, 1224 &fw_controller->parent.state_machine, 1225 &fw_controller->parent.parent, 1226 scif_cb_logger_log_states, 1227 "SCIF_SAS_CONTROLLER_T", "base state machine", 1228 SCIF_LOG_OBJECT_CONTROLLER 1229 ); 1230 } 1231 1232 /** 1233 * This method will remove the logging of state transitions from the framework 1234 * controller object. 1235 * 1236 * @param[in] fw_controller The framework controller to change. 1237 * 1238 * @return none 1239 */ 1240 void scif_sas_controller_deinitialize_state_logging( 1241 SCIF_SAS_CONTROLLER_T * fw_controller 1242 ) 1243 { 1244 sci_base_state_machine_logger_deinitialize( 1245 &fw_controller->parent.state_machine_logger, 1246 &fw_controller->parent.state_machine 1247 ); 1248 } 1249 #endif // SCI_LOGGING 1250