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