/** * @brief This method processes the completions transport layer (TL) status * to determine if the SMP request was sent successfully. If the SMP * request was sent successfully, then the state for the SMP request * transits to waiting for a response frame. * * @param[in] this_request This parameter specifies the request for which * the TC completion was received. * @param[in] completion_code This parameter indicates the completion status * information for the TC. * * @return Indicate if the tc completion handler was successful. * @retval SCI_SUCCESS currently this method always returns success. */ static SCI_STATUS scic_sds_smp_request_await_tc_completion_tc_completion_handler( SCIC_SDS_REQUEST_T * this_request, U32 completion_code ) { SCIC_LOG_TRACE(( sci_base_object_get_logger(this_request), SCIC_LOG_OBJECT_SMP_IO_REQUEST, "scic_sds_smp_request_await_tc_completion_tc_completion_handler(0x%x, 0x%x) enter\n", this_request, completion_code )); switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): scic_sds_request_set_status( this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS ); sci_base_state_machine_change_state( &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); break; default: // All other completion status cause the IO to be complete. If a NAK // was received, then it is up to the user to retry the request. scic_sds_request_set_status( this_request, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); sci_base_state_machine_change_state( &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); break; } return SCI_SUCCESS; }
/** * @brief This method processes the completions transport layer (TL) status * to determine if the RAW task management frame was sent successfully. * If the raw frame was sent successfully, then the state for the * task request transitions to waiting for a response frame. * * @param[in] this_request This parameter specifies the request for which * the TC completion was received. * @param[in] completion_code This parameter indicates the completion status * information for the TC. * * @return Indicate if the tc completion handler was successful. * @retval SCI_SUCCESS currently this method always returns success. */ static SCI_STATUS scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler( SCIC_SDS_REQUEST_T * this_request, U32 completion_code ) { SCIC_LOG_TRACE(( sci_base_object_get_logger(this_request), SCIC_LOG_OBJECT_TASK_MANAGEMENT, "scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler(0x%x, 0x%x) enter\n", this_request, completion_code )); switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): scic_sds_request_set_status( this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS ); sci_base_state_machine_change_state( &this_request->started_substate_machine, SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE ); break; case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO): // Currently, the decision is to simply allow the task request to // timeout if the task IU wasn't received successfully. // There is a potential for receiving multiple task responses if we // decide to send the task IU again. SCIC_LOG_WARNING(( sci_base_object_get_logger(this_request), SCIC_LOG_OBJECT_TASK_MANAGEMENT, "TaskRequest:0x%x CompletionCode:%x - ACK/NAK timeout\n", this_request, completion_code )); sci_base_state_machine_change_state( &this_request->started_substate_machine, SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE ); break; default: // All other completion status cause the IO to be complete. If a NAK // was received, then it is up to the user to retry the request. scic_sds_request_set_status( this_request, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); sci_base_state_machine_change_state( &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); break; } return SCI_SUCCESS; }
/** * @brief This method processes an abnormal TC completion while the SMP * request is waiting for a response frame. It decides what * happened to the IO based on TC completion status. * * @param[in] this_request This parameter specifies the request for which * the TC completion was received. * @param[in] completion_code This parameter indicates the completion status * information for the TC. * * @return Indicate if the tc completion handler was successful. * @retval SCI_SUCCESS currently this method always returns success. */ static SCI_STATUS scic_sds_smp_request_await_response_tc_completion_handler( SCIC_SDS_REQUEST_T * this_request, U32 completion_code ) { SCIC_LOG_TRACE(( sci_base_object_get_logger(this_request), SCIC_LOG_OBJECT_SMP_IO_REQUEST, "scic_sds_smp_request_await_response_tc_completion_handler(0x%x, 0x%x) enter\n", this_request, completion_code )); switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): //In the AWAIT RESPONSE state, any TC completion is unexpected. //but if the TC has success status, we complete the IO anyway. scic_sds_request_set_status( this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS ); sci_base_state_machine_change_state( &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); break; case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR): //These status has been seen in a specific LSI expander, which sometimes //is not able to send smp response within 2 ms. This causes our hardware //break the connection and set TC completion with one of these SMP_XXX_XX_ERR //status. For these type of error, we ask scic user to retry the request. scic_sds_request_set_status( this_request, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED ); sci_base_state_machine_change_state( &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); break; default: // All other completion status cause the IO to be complete. If a NAK // was received, then it is up to the user to retry the request. scic_sds_request_set_status( this_request, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); sci_base_state_machine_change_state( &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); break; } return SCI_SUCCESS; }
/** * @brief This method processes an unsolicited frame while the SMP request is * waiting for a response frame. It will copy the response data, release * the unsolicited frame, and transition the request to the * SCI_BASE_REQUEST_STATE_COMPLETED state. * * @param[in] this_request This parameter specifies the request for which * the unsolicited frame was received. * @param[in] frame_index This parameter indicates the unsolicited frame * index that should contain the response. * * @return This method returns an indication of whether the response * frame was handled successfully or not. * @retval SCI_SUCCESS Currently this value is always returned and indicates * successful processing of the TC response. */ static SCI_STATUS scic_sds_smp_request_await_response_frame_handler( SCIC_SDS_REQUEST_T * this_request, U32 frame_index ) { SCI_STATUS status; void * frame_header; SMP_RESPONSE_HEADER_T * this_frame_header; U8 * user_smp_buffer = this_request->response_buffer; // Save off the controller, so that we do not touch the request after it // is completed. SCIC_SDS_CONTROLLER_T * controller = scic_sds_request_get_controller(this_request); SCIC_LOG_TRACE(( sci_base_object_get_logger(this_request), SCIC_LOG_OBJECT_SMP_IO_REQUEST, "scic_sds_smp_request_await_response_frame_handler(0x%x, 0x%x) enter\n", this_request, frame_index )); status = scic_sds_unsolicited_frame_control_get_header( &(controller->uf_control), frame_index, &frame_header ); //byte swap the header. scic_word_copy_with_swap( (U32*) user_smp_buffer, frame_header, sizeof(SMP_RESPONSE_HEADER_T)/sizeof(U32) ); this_frame_header = (SMP_RESPONSE_HEADER_T*) user_smp_buffer; if (this_frame_header->smp_frame_type == SMP_FRAME_TYPE_RESPONSE) { void * smp_response_buffer; status = scic_sds_unsolicited_frame_control_get_buffer( &(controller->uf_control), frame_index, &smp_response_buffer ); scic_word_copy_with_swap( (U32*) (user_smp_buffer + sizeof(SMP_RESPONSE_HEADER_T)), smp_response_buffer, sizeof(SMP_RESPONSE_BODY_T)/sizeof(U32) ); if (this_frame_header->function == SMP_FUNCTION_DISCOVER) { SMP_RESPONSE_T * this_smp_response; this_smp_response = (SMP_RESPONSE_T *)user_smp_buffer; // Some expanders only report an attached SATA device, and // not an STP target. Since the core depends on the STP // target attribute to correctly build I/O, set the bit now // if necessary. if (this_smp_response->response.discover.protocols.u.bits.attached_sata_device && !this_smp_response->response.discover.protocols.u.bits.attached_stp_target) { this_smp_response->response.discover.protocols.u.bits.attached_stp_target = 1; SCIC_LOG_TRACE(( sci_base_object_get_logger(this_request), SCIC_LOG_OBJECT_SMP_IO_REQUEST, "scic_sds_smp_request_await_response_frame_handler(0x%x) Found SATA dev, setting STP bit.\n", this_request )); } } //Don't need to copy to user space. User instead will refer to //core request's response buffer. //copy the smp response to framework smp request's response buffer. //scic_sds_smp_request_copy_response(this_request); scic_sds_request_set_status( this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS ); sci_base_state_machine_change_state( &this_request->started_substate_machine, SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION ); } else { // This was not a response frame why did it get forwarded? SCIC_LOG_ERROR(( sci_base_object_get_logger(this_request), SCIC_LOG_OBJECT_SMP_IO_REQUEST, "SCIC SMP Request 0x%08x received unexpected frame %d type 0x%02x\n", this_request, frame_index, this_frame_header->smp_frame_type )); scic_sds_request_set_status( this_request, SCU_TASK_DONE_SMP_FRM_TYPE_ERR, SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); sci_base_state_machine_change_state( &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); } scic_sds_controller_release_frame( controller, frame_index ); return SCI_SUCCESS; }