scif_sas_task_request.c revision 230557
1275970Scy/*- 2275970Scy * This file is provided under a dual BSD/GPLv2 license. When using or 3275970Scy * redistributing this file, you may do so under either license. 4275970Scy * 5275970Scy * GPL LICENSE SUMMARY 6275970Scy * 7275970Scy * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 8275970Scy * 9275970Scy * This program is free software; you can redistribute it and/or modify 10275970Scy * it under the terms of version 2 of the GNU General Public License as 11275970Scy * published by the Free Software Foundation. 12275970Scy * 13275970Scy * This program is distributed in the hope that it will be useful, but 14275970Scy * WITHOUT ANY WARRANTY; without even the implied warranty of 15275970Scy * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16275970Scy * General Public License for more details. 17275970Scy * 18275970Scy * You should have received a copy of the GNU General Public License 19275970Scy * along with this program; if not, write to the Free Software 20275970Scy * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 21275970Scy * The full GNU General Public License is included in this distribution 22275970Scy * in the file called LICENSE.GPL. 23275970Scy * 24275970Scy * BSD LICENSE 25275970Scy * 26275970Scy * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 27275970Scy * All rights reserved. 28275970Scy * 29275970Scy * Redistribution and use in source and binary forms, with or without 30275970Scy * modification, are permitted provided that the following conditions 31275970Scy * are met: 32275970Scy * 33275970Scy * * Redistributions of source code must retain the above copyright 34275970Scy * notice, this list of conditions and the following disclaimer. 35275970Scy * * Redistributions in binary form must reproduce the above copyright 36275970Scy * notice, this list of conditions and the following disclaimer in 37275970Scy * the documentation and/or other materials provided with the 38275970Scy * distribution. 39275970Scy * 40275970Scy * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41275970Scy * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42275970Scy * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43275970Scy * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 44275970Scy * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45275970Scy * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 46275970Scy * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 47275970Scy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 48275970Scy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 49275970Scy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 50275970Scy * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51275970Scy */ 52275970Scy 53275970Scy#include <sys/cdefs.h> 54275970Scy__FBSDID("$FreeBSD$"); 55275970Scy 56275970Scy/** 57275970Scy * @file 58275970Scy * 59275970Scy * @brief This file contains the task management request object 60275970Scy * (SCIF_SAS_TASK_REQUEST) method implementations. 61275970Scy */ 62275970Scy 63275970Scy 64275970Scy#include <dev/isci/scil/intel_sas.h> 65275970Scy 66275970Scy#include <dev/isci/scil/scic_task_request.h> 67275970Scy#include <dev/isci/scil/scic_remote_device.h> 68275970Scy#include <dev/isci/scil/scic_user_callback.h> 69275970Scy#include <dev/isci/scil/scic_controller.h> 70275970Scy#include <dev/isci/scil/scif_user_callback.h> 71275970Scy 72275970Scy#include <dev/isci/scil/scif_sas_request.h> 73275970Scy#include <dev/isci/scil/scif_sas_task_request.h> 74275970Scy#include <dev/isci/scil/scif_sas_stp_task_request.h> 75275970Scy#include <dev/isci/scil/scif_sas_logger.h> 76275970Scy#include <dev/isci/scil/scif_sas_controller.h> 77275970Scy#include <dev/isci/scil/scif_sas_domain.h> 78275970Scy#include <dev/isci/scil/scif_sas_remote_device.h> 79275970Scy#include <dev/isci/scil/scif_sas_smp_io_request.h> 80275970Scy 81280849Scy//****************************************************************************** 82280849Scy//* P U B L I C M E T H O D S 83280849Scy//****************************************************************************** 84280849Scy 85280849ScyU32 scif_task_request_get_object_size( 86280849Scy void 87275970Scy) 88275970Scy{ 89275970Scy return (sizeof(SCIF_SAS_TASK_REQUEST_T) + scic_task_request_get_object_size()); 90275970Scy} 91275970Scy 92275970Scy// --------------------------------------------------------------------------- 93275970Scy 94275970ScyU8 scif_sas_task_request_get_function( 95275970Scy SCIF_SAS_TASK_REQUEST_T *fw_task 96275970Scy) 97275970Scy{ 98275970Scy return fw_task->function; 99275970Scy} 100275970Scy 101275970Scy// --------------------------------------------------------------------------- 102275970Scy 103275970Scystatic 104275970ScySCI_STATUS scif_sas_task_request_generic_construct( 105275970Scy SCI_CONTROLLER_HANDLE_T scif_controller, 106275970Scy SCI_REMOTE_DEVICE_HANDLE_T scif_remote_device, 107275970Scy U16 io_tag, 108275970Scy void * user_task_request_object, 109275970Scy void * task_request_memory, 110275970Scy SCI_TASK_REQUEST_HANDLE_T * scif_task_request, 111275970Scy U8 task_function 112275970Scy) 113275970Scy{ 114275970Scy SCI_STATUS status; 115275970Scy SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) 116275970Scy scif_controller; 117275970Scy SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T*) 118275970Scy task_request_memory; 119275970Scy SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*) 120275970Scy scif_remote_device; 121275970Scy U8 * core_request_memory; 122275970Scy 123275970Scy SCIF_LOG_TRACE(( 124275970Scy sci_base_object_get_logger(fw_controller), 125275970Scy SCIF_LOG_OBJECT_TASK_MANAGEMENT, 126275970Scy "scif_task_request_construct(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) enter\n", 127275970Scy scif_controller, scif_remote_device, io_tag, user_task_request_object, 128275970Scy task_request_memory, scif_task_request 129275970Scy )); 130275970Scy 131275970Scy // Initialize the user's handle to the framework task request. 132275970Scy *scif_task_request = fw_task; 133275970Scy 134275970Scy // initialize affected request count 135275970Scy fw_task->affected_request_count = 0; 136275970Scy fw_task->io_tag_to_manage = SCI_CONTROLLER_INVALID_IO_TAG; 137275970Scy fw_task->function = task_function; 138275970Scy 139275970Scy if (task_function == SCI_SAS_HARD_RESET ) 140275970Scy { 141275970Scy if (fw_device->containing_device != NULL ) 142275970Scy {// Target Reset is for an expander attached device, 143275970Scy // go down to construct smp Phy Control request. 144275970Scy scif_sas_smp_request_construct_phy_control( 145275970Scy fw_controller, 146275970Scy fw_device->containing_device, 147275970Scy PHY_OPERATION_HARD_RESET, 148275970Scy fw_device->expander_phy_identifier, 149275970Scy user_task_request_object, 150275970Scy task_request_memory 151275970Scy ); 152275970Scy } 153275970Scy else 154275970Scy { 155275970Scy scif_sas_request_construct( 156275970Scy &fw_task->parent, 157275970Scy fw_device, 158275970Scy sci_base_object_get_logger(fw_controller), 159275970Scy scif_sas_task_request_state_table 160275970Scy ); 161275970Scy 162275970Scy // If target reset is for a DA device, don't build task at all. 163275970Scy // Just set object association. 164275970Scy sci_object_set_association(fw_task, user_task_request_object); 165275970Scy } 166298770Sdelphij 167275970Scy return SCI_SUCCESS; 168275970Scy } 169275970Scy 170275970Scy // Construct the parent object first in order to ensure logging can 171275970Scy // function. 172275970Scy scif_sas_request_construct( 173275970Scy &fw_task->parent, 174275970Scy fw_device, 175275970Scy sci_base_object_get_logger(fw_controller), 176275970Scy scif_sas_task_request_state_table 177275970Scy ); 178275970Scy 179275970Scy core_request_memory = (U8 *)task_request_memory + sizeof(SCIF_SAS_TASK_REQUEST_T); 180275970Scy 181275970Scy status = scic_task_request_construct( 182275970Scy fw_controller->core_object, 183275970Scy fw_device->core_object, 184275970Scy io_tag, 185275970Scy fw_task, 186275970Scy core_request_memory, 187275970Scy &fw_task->parent.core_object 188275970Scy ); 189275970Scy 190275970Scy if (status == SCI_SUCCESS) 191275970Scy { 192275970Scy SMP_DISCOVER_RESPONSE_PROTOCOLS_T dev_protocols; 193275970Scy 194275970Scy // These associations must be set early for the core io request 195275970Scy // object construction to complete correctly as there will be 196275970Scy // callbacks into the user driver framework during core construction 197275970Scy sci_object_set_association(fw_task, user_task_request_object); 198275970Scy sci_object_set_association(fw_task->parent.core_object, fw_task); 199275970Scy 200275970Scy // Perform protocol specific core IO request construction. 201275970Scy scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols); 202275970Scy if (dev_protocols.u.bits.attached_ssp_target) 203275970Scy status = scic_task_request_construct_ssp(fw_task->parent.core_object); 204275970Scy else if (dev_protocols.u.bits.attached_stp_target) 205275970Scy status = scif_sas_stp_task_request_construct(fw_task); 206275970Scy else 207275970Scy status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; 208275970Scy 209275970Scy if (status == SCI_SUCCESS) 210275970Scy { 211275970Scy sci_base_state_machine_logger_initialize( 212275970Scy &fw_task->parent.parent.state_machine_logger, 213275970Scy &fw_task->parent.parent.state_machine, 214275970Scy &fw_task->parent.parent.parent, 215275970Scy scif_cb_logger_log_states, 216275970Scy "SCIF_SAS_TASK_REQUEST_T", "base_state_machine", 217275970Scy SCIF_LOG_OBJECT_TASK_MANAGEMENT 218275970Scy ); 219275970Scy } 220275970Scy else 221275970Scy { 222275970Scy SCIF_LOG_WARNING(( 223275970Scy sci_base_object_get_logger(fw_task), 224275970Scy SCIF_LOG_OBJECT_TASK_MANAGEMENT, 225275970Scy "Device:0x%x TaskRequest:0x%x Function:0x%x construct failed\n", 226275970Scy fw_device, fw_task, scif_sas_task_request_get_function(fw_task) 227275970Scy )); 228275970Scy } 229275970Scy } 230275970Scy 231275970Scy return status; 232275970Scy} 233275970Scy 234275970Scy// --------------------------------------------------------------------------- 235275970Scy 236275970ScySCI_STATUS scif_sas_internal_task_request_construct( 237275970Scy SCI_CONTROLLER_HANDLE_T scif_controller, 238275970Scy SCI_REMOTE_DEVICE_HANDLE_T scif_remote_device, 239275970Scy U16 io_tag, 240275970Scy void * task_request_memory, 241275970Scy SCI_TASK_REQUEST_HANDLE_T * scif_task_request, 242275970Scy U8 task_function 243275970Scy) 244275970Scy{ 245275970Scy SCI_STATUS status; 246275970Scy SCIF_SAS_TASK_REQUEST_T * fw_task; 247275970Scy 248275970Scy status = scif_sas_task_request_generic_construct( 249275970Scy scif_controller, 250275970Scy scif_remote_device, 251275970Scy io_tag, 252275970Scy NULL, 253275970Scy task_request_memory, 254275970Scy scif_task_request, 255275970Scy task_function 256275970Scy ); 257275970Scy 258275970Scy fw_task = (SCIF_SAS_TASK_REQUEST_T *)task_request_memory; 259275970Scy 260275970Scy fw_task->parent.is_internal = TRUE; 261275970Scy 262275970Scy return status; 263275970Scy} 264275970Scy 265275970Scy// --------------------------------------------------------------------------- 266275970Scy 267275970ScySCI_STATUS scif_task_request_construct( 268275970Scy SCI_CONTROLLER_HANDLE_T scif_controller, 269275970Scy SCI_REMOTE_DEVICE_HANDLE_T scif_remote_device, 270275970Scy U16 io_tag, 271275970Scy void * user_task_request_object, 272275970Scy void * task_request_memory, 273275970Scy SCI_TASK_REQUEST_HANDLE_T * scif_task_request 274275970Scy) 275275970Scy{ 276275970Scy SCI_STATUS status; 277275970Scy U8 task_function = 278275970Scy scif_cb_task_request_get_function(user_task_request_object); 279275970Scy 280275970Scy status = scif_sas_task_request_generic_construct( 281275970Scy scif_controller, 282275970Scy scif_remote_device, 283275970Scy io_tag, 284275970Scy user_task_request_object, 285275970Scy task_request_memory, 286275970Scy scif_task_request, 287275970Scy task_function 288275970Scy ); 289275970Scy 290275970Scy return status; 291275970Scy} 292275970Scy 293275970Scy// --------------------------------------------------------------------------- 294275970Scy 295275970Scyvoid scif_sas_internal_task_request_destruct( 296275970Scy SCIF_SAS_TASK_REQUEST_T * fw_internal_task 297275970Scy) 298275970Scy{ 299275970Scy SCIF_SAS_CONTROLLER_T * fw_controller = 300275970Scy fw_internal_task->parent.device->domain->controller; 301275970Scy scif_sas_controller_free_internal_request(fw_controller, fw_internal_task); 302275970Scy} 303275970Scy 304275970Scy// --------------------------------------------------------------------------- 305275970Scy 306275970Scyvoid scic_cb_task_request_complete( 307275970Scy SCI_CONTROLLER_HANDLE_T controller, 308275970Scy SCI_REMOTE_DEVICE_HANDLE_T remote_device, 309275970Scy SCI_TASK_REQUEST_HANDLE_T task_request, 310275970Scy SCI_TASK_STATUS completion_status 311275970Scy) 312275970Scy{ 313275970Scy SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) 314275970Scy sci_object_get_association(controller); 315275970Scy SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*) 316275970Scy sci_object_get_association(remote_device); 317275970Scy SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T*) 318275970Scy sci_object_get_association(task_request); 319275970Scy SCI_STATUS status; 320275970Scy 321275970Scy SCIF_LOG_TRACE(( 322275970Scy sci_base_object_get_logger(fw_controller), 323275970Scy SCIF_LOG_OBJECT_TASK_MANAGEMENT, 324275970Scy "scic_cb_task_request_complete(0x%x, 0x%x, 0x%x, 0x%x) enter\n", 325275970Scy controller, remote_device, task_request, completion_status 326275970Scy )); 327275970Scy 328275970Scy status = fw_task->parent.state_handlers->complete_handler( 329275970Scy &fw_task->parent.parent 330275970Scy ); 331275970Scy 332289997Sglebius if (status == SCI_SUCCESS) 333289997Sglebius { 334275970Scy if (fw_task->parent.protocol_complete_handler != NULL) 335275970Scy { 336275970Scy status = fw_task->parent.protocol_complete_handler( 337275970Scy fw_controller, fw_device, &fw_task->parent, (SCI_STATUS *)&completion_status 338275970Scy ); 339275970Scy } 340275970Scy 341275970Scy if (status == SCI_SUCCESS) 342275970Scy { 343275970Scy SCIF_LOG_WARNING(( 344275970Scy sci_base_object_get_logger(fw_task), 345275970Scy SCIF_LOG_OBJECT_TASK_MANAGEMENT, 346275970Scy "RemoteDevice:0x%x TaskRequest:0x%x Function:0x%x CompletionStatus:0x%x " 347275970Scy "completed\n", 348275970Scy fw_device, fw_task, 349275970Scy scif_sas_task_request_get_function(fw_task), 350275970Scy completion_status 351275970Scy )); 352275970Scy 353275970Scy // If this isn't an internal framework IO request, then simply pass the 354275970Scy // notification up to the SCIF user. Otherwise, immediately complete the 355275970Scy // task since there is no SCIF user to notify. 356275970Scy if (fw_task->parent.is_internal == FALSE) 357275970Scy { 358275970Scy scif_cb_task_request_complete( 359275970Scy fw_controller, fw_device, fw_task, completion_status 360275970Scy ); 361275970Scy } 362275970Scy else 363275970Scy { 364275970Scy scif_controller_complete_task( 365275970Scy fw_controller, 366275970Scy fw_device, 367275970Scy fw_task 368275970Scy ); 369275970Scy } 370275970Scy } 371275970Scy } 372275970Scy} 373275970Scy 374275970Scy// --------------------------------------------------------------------------- 375275970Scy 376275970ScyU32 scic_cb_ssp_task_request_get_lun( 377275970Scy void * scic_user_task_request 378275970Scy) 379275970Scy{ 380275970Scy SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T*) 381275970Scy scic_user_task_request; 382275970Scy 383275970Scy fw_task->parent.lun = scif_cb_task_request_get_lun( 384275970Scy fw_task->parent.parent.parent.associated_object 385275970Scy ); 386275970Scy 387275970Scy return fw_task->parent.lun; 388275970Scy} 389275970Scy 390275970Scy// --------------------------------------------------------------------------- 391275970Scy 392275970ScyU8 scic_cb_ssp_task_request_get_function( 393275970Scy void * scic_user_task_request 394275970Scy) 395275970Scy{ 396275970Scy SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T*) 397275970Scy scic_user_task_request; 398275970Scy 399275970Scy return scif_sas_task_request_get_function(fw_task); 400275970Scy} 401275970Scy 402275970Scy// --------------------------------------------------------------------------- 403275970Scy 404275970ScyU16 scic_cb_ssp_task_request_get_io_tag_to_manage( 405275970Scy void * scic_user_task_request 406275970Scy) 407275970Scy{ 408275970Scy SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T*) 409275970Scy scic_user_task_request; 410275970Scy 411275970Scy fw_task->io_tag_to_manage 412275970Scy = scif_cb_task_request_get_io_tag_to_manage( 413275970Scy fw_task->parent.parent.parent.associated_object 414275970Scy ); 415275970Scy 416275970Scy return fw_task->io_tag_to_manage; 417275970Scy} 418275970Scy 419275970Scy// --------------------------------------------------------------------------- 420275970Scy 421275970Scyvoid * scic_cb_ssp_task_request_get_response_data_address( 422275970Scy void * scic_user_task_request 423275970Scy) 424275970Scy{ 425275970Scy SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T*) 426275970Scy scic_user_task_request; 427275970Scy 428275970Scy return scif_cb_task_request_get_response_data_address( 429275970Scy fw_task->parent.parent.parent.associated_object 430275970Scy ); 431275970Scy} 432275970Scy 433275970Scy// --------------------------------------------------------------------------- 434275970Scy 435275970ScyU32 scic_cb_ssp_task_request_get_response_data_length( 436275970Scy void * scic_user_task_request 437275970Scy) 438275970Scy{ 439275970Scy SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T*) 440275970Scy scic_user_task_request; 441275970Scy 442275970Scy return scif_cb_task_request_get_response_data_length( 443275970Scy fw_task->parent.parent.parent.associated_object 444275970Scy ); 445275970Scy} 446275970Scy 447275970Scy//****************************************************************************** 448275970Scy//* P R O T E C T E D M E T H O D S 449275970Scy//****************************************************************************** 450275970Scy 451275970Scy/** 452275970Scy * @brief This method performs functionality required after a task management 453275970Scy * operation (either a task management request or a silicon task 454275970Scy * termination) has finished. 455275970Scy * 456275970Scy * @param[in] fw_task This parameter specifies the request that has 457275970Scy * the operation completing. 458275970Scy * 459275970Scy * @return none 460275970Scy */ 461275970Scyvoid scif_sas_task_request_operation_complete( 462275970Scy SCIF_SAS_TASK_REQUEST_T * fw_task 463275970Scy) 464275970Scy{ 465275970Scy SCIF_LOG_TRACE(( 466275970Scy sci_base_object_get_logger(fw_task), 467275970Scy SCIF_LOG_OBJECT_TASK_MANAGEMENT, 468275970Scy "scif_sas_task_request_operation_complete(0x%x) enter\n", 469275970Scy fw_task 470275970Scy )); 471275970Scy 472275970Scy fw_task->affected_request_count--; 473275970Scy 474275970Scy SCIF_LOG_INFO(( 475275970Scy sci_base_object_get_logger(fw_task), 476275970Scy SCIF_LOG_OBJECT_TASK_MANAGEMENT, 477275970Scy "TaskRequest:0x%x current affected request count:0x%x\n", 478275970Scy fw_task, fw_task->affected_request_count 479275970Scy )); 480275970Scy} 481275970Scy 482275970Scy