Beispiel #1
0
/**
 * @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;
}
Beispiel #3
0
/**
 * @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;
}
Beispiel #4
0
/**
 * @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;
}