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