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 task management substate handlers for the 60 * SCIC_SDS_IO_REQUEST object. 61 * This file contains the enter/exit methods associated with each of 62 * the task management raw request states. For more information on the 63 * task management request state machine please refer to 64 * scic_sds_io_request.h 65 */ 66 67 #include <dev/isci/scil/intel_sas.h> 68 #include <dev/isci/scil/scic_sds_request.h> 69 #include <dev/isci/scil/scic_controller.h> 70 #include <dev/isci/scil/scic_sds_logger.h> 71 #include <dev/isci/scil/scic_sds_controller.h> 72 #include <dev/isci/scil/scu_completion_codes.h> 73 #include <dev/isci/scil/scu_task_context.h> 74 #include <dev/isci/scil/sci_base_state_machine.h> 75 76 /** 77 * @brief This method processes the completions transport layer (TL) status 78 * to determine if the RAW task management frame was sent successfully. 79 * If the raw frame was sent successfully, then the state for the 80 * task request transitions to waiting for a response frame. 81 * 82 * @param[in] this_request This parameter specifies the request for which 83 * the TC completion was received. 84 * @param[in] completion_code This parameter indicates the completion status 85 * information for the TC. 86 * 87 * @return Indicate if the tc completion handler was successful. 88 * @retval SCI_SUCCESS currently this method always returns success. 89 */ 90 static 91 SCI_STATUS scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler( 92 SCIC_SDS_REQUEST_T * this_request, 93 U32 completion_code 94 ) 95 { 96 SCIC_LOG_TRACE(( 97 sci_base_object_get_logger(this_request), 98 SCIC_LOG_OBJECT_TASK_MANAGEMENT, 99 "scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler(0x%x, 0x%x) enter\n", 100 this_request, completion_code 101 )); 102 103 switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) 104 { 105 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): 106 scic_sds_request_set_status( 107 this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS 108 ); 109 110 sci_base_state_machine_change_state( 111 &this_request->started_substate_machine, 112 SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE 113 ); 114 break; 115 116 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO): 117 // Currently, the decision is to simply allow the task request to 118 // timeout if the task IU wasn't received successfully. 119 // There is a potential for receiving multiple task responses if we 120 // decide to send the task IU again. 121 SCIC_LOG_WARNING(( 122 sci_base_object_get_logger(this_request), 123 SCIC_LOG_OBJECT_TASK_MANAGEMENT, 124 "TaskRequest:0x%x CompletionCode:%x - ACK/NAK timeout\n", 125 this_request, completion_code 126 )); 127 128 sci_base_state_machine_change_state( 129 &this_request->started_substate_machine, 130 SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE 131 ); 132 break; 133 134 default: 135 // All other completion status cause the IO to be complete. If a NAK 136 // was received, then it is up to the user to retry the request. 137 scic_sds_request_set_status( 138 this_request, 139 SCU_NORMALIZE_COMPLETION_STATUS(completion_code), 140 SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR 141 ); 142 143 sci_base_state_machine_change_state( 144 &this_request->parent.state_machine, 145 SCI_BASE_REQUEST_STATE_COMPLETED 146 ); 147 break; 148 } 149 150 return SCI_SUCCESS; 151 } 152 153 /** 154 * @brief This method is responsible for processing a terminate/abort 155 * request for this TC while the request is waiting for the task 156 * management response unsolicited frame. 157 * 158 * @param[in] this_request This parameter specifies the request for which 159 * the termination was requested. 160 * 161 * @return This method returns an indication as to whether the abort 162 * request was successfully handled. 163 * 164 * @todo need to update to ensure the received UF doesn't cause damage 165 * to subsequent requests (i.e. put the extended tag in a holding 166 * pattern for this particular device). 167 */ 168 static 169 SCI_STATUS scic_sds_ssp_task_request_await_tc_response_abort_handler( 170 SCI_BASE_REQUEST_T * request 171 ) 172 { 173 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request; 174 175 SCIC_LOG_TRACE(( 176 sci_base_object_get_logger(this_request), 177 SCIC_LOG_OBJECT_TASK_MANAGEMENT, 178 "scic_sds_ssp_task_request_await_tc_response_abort_handler(0x%x) enter\n", 179 this_request 180 )); 181 182 sci_base_state_machine_change_state( 183 &this_request->parent.state_machine, 184 SCI_BASE_REQUEST_STATE_ABORTING 185 ); 186 187 sci_base_state_machine_change_state( 188 &this_request->parent.state_machine, 189 SCI_BASE_REQUEST_STATE_COMPLETED 190 ); 191 192 return SCI_SUCCESS; 193 } 194 195 /** 196 * @brief This method processes an unsolicited frame while the task mgmt 197 * request is waiting for a response frame. It will copy the 198 * response data, release the unsolicited frame, and transition 199 * the request to the SCI_BASE_REQUEST_STATE_COMPLETED state. 200 * 201 * @param[in] this_request This parameter specifies the request for which 202 * the unsolicited frame was received. 203 * @param[in] frame_index This parameter indicates the unsolicited frame 204 * index that should contain the response. 205 * 206 * @return This method returns an indication of whether the TC response 207 * frame was handled successfully or not. 208 * @retval SCI_SUCCESS Currently this value is always returned and indicates 209 * successful processing of the TC response. 210 * 211 * @todo Should probably update to check frame type and make sure it is 212 * a response frame. 213 */ 214 static 215 SCI_STATUS scic_sds_ssp_task_request_await_tc_response_frame_handler( 216 SCIC_SDS_REQUEST_T * this_request, 217 U32 frame_index 218 ) 219 { 220 // Save off the controller, so that we do not touch the request after it 221 // is completed. 222 SCIC_SDS_CONTROLLER_T * owning_controller = this_request->owning_controller; 223 224 SCIC_LOG_TRACE(( 225 sci_base_object_get_logger(this_request), 226 SCIC_LOG_OBJECT_TASK_MANAGEMENT, 227 "scic_sds_ssp_task_request_await_tc_response_frame_handler(0x%x, 0x%x) enter\n", 228 this_request, frame_index 229 )); 230 231 scic_sds_io_request_copy_response(this_request); 232 233 sci_base_state_machine_change_state( 234 &this_request->parent.state_machine, 235 SCI_BASE_REQUEST_STATE_COMPLETED 236 ); 237 238 scic_sds_controller_release_frame( 239 owning_controller, frame_index 240 ); 241 242 return SCI_SUCCESS; 243 } 244 245 SCIC_SDS_IO_REQUEST_STATE_HANDLER_T 246 scic_sds_ssp_task_request_started_substate_handler_table 247 [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_MAX_SUBSTATES] = 248 { 249 // SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION 250 { 251 { 252 scic_sds_request_default_start_handler, 253 scic_sds_request_started_state_abort_handler, 254 scic_sds_request_default_complete_handler, 255 scic_sds_request_default_destruct_handler 256 }, 257 scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler, 258 scic_sds_request_default_event_handler, 259 scic_sds_request_default_frame_handler 260 }, 261 // SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE 262 { 263 { 264 scic_sds_request_default_start_handler, 265 scic_sds_ssp_task_request_await_tc_response_abort_handler, 266 scic_sds_request_default_complete_handler, 267 scic_sds_request_default_destruct_handler 268 }, 269 scic_sds_request_default_tc_completion_handler, 270 scic_sds_request_default_event_handler, 271 scic_sds_ssp_task_request_await_tc_response_frame_handler 272 } 273 }; 274 275 /** 276 * @brief This method performs the actions required when entering the 277 * SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION 278 * sub-state. This includes setting the IO request state handlers 279 * for this sub-state. 280 * 281 * @param[in] object This parameter specifies the request object for which 282 * the sub-state change is occurring. 283 * 284 * @return none. 285 */ 286 static 287 void scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter( 288 SCI_BASE_OBJECT_T *object 289 ) 290 { 291 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 292 293 SET_STATE_HANDLER( 294 this_request, 295 scic_sds_ssp_task_request_started_substate_handler_table, 296 SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION 297 ); 298 } 299 300 /** 301 * @brief This method performs the actions required when entering the 302 * SCIC_SDS_IO_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. 303 * This includes setting the IO request state handlers for this 304 * sub-state. 305 * 306 * @param[in] object This parameter specifies the request object for which 307 * the sub-state change is occurring. 308 * 309 * @return none. 310 */ 311 static 312 void scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter( 313 SCI_BASE_OBJECT_T *object 314 ) 315 { 316 SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 317 318 SET_STATE_HANDLER( 319 this_request, 320 scic_sds_ssp_task_request_started_substate_handler_table, 321 SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE 322 ); 323 } 324 325 SCI_BASE_STATE_T scic_sds_io_request_started_task_mgmt_substate_table 326 [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_MAX_SUBSTATES] = 327 { 328 { 329 SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION, 330 scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter, 331 NULL 332 }, 333 { 334 SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE, 335 scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter, 336 NULL 337 } 338 }; 339 340 341