Exemple #1
0
void scic_cb_controller_stop_complete(
   SCI_CONTROLLER_HANDLE_T  controller,
   SCI_STATUS               completion_status
)
{
   SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*)
                                         sci_object_get_association(controller);

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(controller),
      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
      "scic_cb_controller_stop_complete(0x%x, 0x%x) enter\n",
      controller, completion_status
   ));

   if (completion_status == SCI_SUCCESS)
   {
      sci_base_state_machine_change_state(
         &fw_controller->parent.state_machine,
         SCI_BASE_CONTROLLER_STATE_STOPPED
      );
   }
   else
   {
      sci_base_state_machine_change_state(
         &fw_controller->parent.state_machine,
         SCI_BASE_CONTROLLER_STATE_FAILED
      );
   }

   scif_cb_controller_stop_complete(fw_controller, completion_status);
}
/**
 * @brief This method is responsible for processing a terminate/abort
 *        request for this TC while the request is waiting for the task
 *        management response unsolicited frame.
 *
 * @param[in] this_request This parameter specifies the request for which
 *            the termination was requested.
 *
 * @return This method returns an indication as to whether the abort
 *         request was successfully handled.
 *
 * @todo need to update to ensure the received UF doesn't cause damage
 *       to subsequent requests (i.e. put the extended tag in a holding
 *       pattern for this particular device).
 */
static
SCI_STATUS scic_sds_ssp_task_request_await_tc_response_abort_handler(
   SCI_BASE_REQUEST_T * request
)
{
   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request;

   SCIC_LOG_TRACE((
      sci_base_object_get_logger(this_request),
      SCIC_LOG_OBJECT_TASK_MANAGEMENT,
      "scic_sds_ssp_task_request_await_tc_response_abort_handler(0x%x) enter\n",
      this_request
   ));

   sci_base_state_machine_change_state(
      &this_request->parent.state_machine,
      SCI_BASE_REQUEST_STATE_ABORTING
   );

   sci_base_state_machine_change_state(
      &this_request->parent.state_machine,
      SCI_BASE_REQUEST_STATE_COMPLETED
   );

   return SCI_SUCCESS;
}
Exemple #3
0
/**
 * @brief This method provides STARTING AWAIT READY sub-state specific
 *        handling for when the core provides a device ready notification
 *        for the remote device.  This essentially, causes a transition
 *        of the framework remote device into the READY state.
 *
 * @param[in]  fw_device This parameter specifies the remote device
 *             object for which the notification has occurred.
 *
 * @return none.
 */
static
void scif_sas_remote_device_starting_await_ready_ready_handler(
   SCIF_SAS_REMOTE_DEVICE_T * fw_device
)
{
#if !defined(DISABLE_WIDE_PORTED_TARGETS)
   if (fw_device->destination_state ==
          SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_UPDATING_PORT_WIDTH)
   {
      {
         sci_base_state_machine_change_state(
            &fw_device->parent.state_machine,
            SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH
         );
      }
   }
   else
#endif
   {
      sci_base_state_machine_change_state(
         &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_READY
      );
   }

#if !defined(DISABLE_WIDE_PORTED_TARGETS)
   scif_sas_domain_remote_device_start_complete(fw_device->domain,fw_device);
#endif
}
/**
 *
 *
 * @param[in] this_device
 * @param[in] frame_index
 *
 * @return SCI_STATUS
 */
static
SCI_STATUS scic_sds_stp_remote_device_ready_ncq_substate_frame_handler(
   SCIC_SDS_REMOTE_DEVICE_T * this_device,
   U32                        frame_index
)
{
   SCI_STATUS           status;
   SATA_FIS_HEADER_T  * frame_header;

   status = scic_sds_unsolicited_frame_control_get_header(
      &(scic_sds_remote_device_get_controller(this_device)->uf_control),
      frame_index,
      (void **)&frame_header
   );

   if (status == SCI_SUCCESS)
   {
      if (
            (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS)
         && (frame_header->status & ATA_STATUS_REG_ERROR_BIT)
         )
      {
         this_device->not_ready_reason =
            SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;

         /** @todo Check sactive and complete associated IO if any. */

         sci_base_state_machine_change_state(
            &this_device->ready_substate_machine,
            SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
         );
      }
      else if (
            (frame_header->fis_type == SATA_FIS_TYPE_REGD2H)
         && (frame_header->status & ATA_STATUS_REG_ERROR_BIT)
         )
      {
         // Some devices return D2H FIS when an NCQ error is detected.
         // Treat this like an SDB error FIS ready reason.
         this_device->not_ready_reason =
            SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;

         sci_base_state_machine_change_state(
            &this_device->ready_substate_machine,
            SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
         );
      }
      else
      {
         status = SCI_FAILURE;
      }

      scic_sds_controller_release_frame(
         scic_sds_remote_device_get_controller(this_device), frame_index
      );
   }

   return status;
}
/**
 * This method will perform the STP request completion processing common
 * to IO requests and task requests of all types
 *
 * @param[in] device This parameter specifies the device for which the
 *            request is being completed.
 * @param[in] request This parameter specifies the request being completed.
 *
 * @return This method returns an indication as to whether the request
 *         processing completed successfully.
 */
static
SCI_STATUS scic_sds_stp_remote_device_complete_request(
   SCI_BASE_REMOTE_DEVICE_T * device,
   SCI_BASE_REQUEST_T       * request
)
{
   SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
   SCIC_SDS_REQUEST_T       * the_request = (SCIC_SDS_REQUEST_T *)request;
   SCI_STATUS                 status;

   status = scic_sds_io_request_complete(the_request);

   if (status == SCI_SUCCESS)
   {
      status = scic_sds_port_complete_io(
                  this_device->owning_port, this_device, the_request
               );

      if (status == SCI_SUCCESS)
      {
         scic_sds_remote_device_decrement_request_count(this_device);
         if (the_request->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED)
         {
            //This request causes hardware error, device needs to be Lun Reset.
            //So here we force the state machine to IDLE state so the rest IOs
            //can reach RNC state handler, these IOs will be completed by RNC with
            //status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE".
            sci_base_state_machine_change_state(
               &this_device->ready_substate_machine,
               SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET
            );
         }
         else if (scic_sds_remote_device_get_request_count(this_device) == 0)
         {
            sci_base_state_machine_change_state(
               &this_device->ready_substate_machine,
               SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
            );
         }
      }
   }

   if (status != SCI_SUCCESS)
   {
      SCIC_LOG_ERROR((
         sci_base_object_get_logger(this_device),
         SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
         "Port:0x%x Device:0x%x Request:0x%x Status:0x%x could not complete\n",
         this_device->owning_port, this_device, the_request, status
      ));
   }

   return status;
}
/**
 * This method will handle the start io operation for a sata device that is in
 * the command idle state.
 *    - Evalute the type of IO request to be started
 *    - If its an NCQ request change to NCQ substate
 *    - If its any other command change to the CMD substate
 *
 * @note If this is a softreset we may want to have a different substate.
 *
 * @param [in] device
 * @param [in] request
 *
 * @return SCI_STATUS
 */
static
SCI_STATUS scic_sds_stp_remote_device_ready_idle_substate_start_io_handler(
   SCI_BASE_REMOTE_DEVICE_T * device,
   SCI_BASE_REQUEST_T       * request
)
{
   SCI_STATUS status;
   SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
   SCIC_SDS_REQUEST_T       * io_request  = (SCIC_SDS_REQUEST_T       *)request;


   // Will the port allow the io request to start?
   status = this_device->owning_port->state_handlers->start_io_handler(
      this_device->owning_port,
      this_device,
      io_request
   );

   if (status == SCI_SUCCESS)
   {
      status =
         scic_sds_remote_node_context_start_io(this_device->rnc, io_request);

      if (status == SCI_SUCCESS)
      {
         status = io_request->state_handlers->parent.start_handler(request);
      }

      if (status == SCI_SUCCESS)
      {
         if (io_request->sat_protocol == SAT_PROTOCOL_FPDMA)
         {
            sci_base_state_machine_change_state(
               &this_device->ready_substate_machine,
               SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ
            );
         }
         else
         {
            this_device->working_request = io_request;

            sci_base_state_machine_change_state(
               &this_device->ready_substate_machine,
               SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD
            );
         }
      }

      scic_sds_remote_device_start_request(this_device, io_request, status);
   }

   return status;
}
/**
 * @brief This method provides STOPPED state specific handling for
 *        when the framework attempts to start the remote device.  This
 *        method attempts to transition the state machine into the
 *        STARTING state.  If this is unsuccessful, then there is a direct
 *        transition into the FAILED state.
 *
 * @param[in]  remote_device This parameter specifies the remote device
 *             object for which the framework is attempting to start.
 *
 * @return This method returns an indication as to whether the start
 *         operating began successfully.
 */
static
SCI_STATUS scif_sas_remote_device_stopped_start_handler(
   SCI_BASE_REMOTE_DEVICE_T * remote_device
)
{
   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
                                          remote_device;

   sci_base_state_machine_change_state(
      &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STARTING
   );

   // Check to see if the state transition occurred without issue.
   if (sci_base_state_machine_get_state(&fw_device->parent.state_machine)
       == SCI_BASE_REMOTE_DEVICE_STATE_FAILED)
   {
      SCIF_LOG_WARNING((
         sci_base_object_get_logger(fw_device),
         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
         "Domain:0x%x Device:0x%x Status:0x%x failed to start\n",
         fw_device->domain, fw_device, fw_device->operation_status
      ));
   }

   return fw_device->operation_status;
}
static
SCI_STATUS scic_sds_remote_node_context_initial_state_resume_handler(
   SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
   SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
   void                                   * callback_parameter
)
{
   if (this_rnc->remote_node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
   {
      scic_sds_remote_node_context_setup_to_resume(
         this_rnc, the_callback, callback_parameter
            );

      scic_sds_remote_node_context_construct_buffer(this_rnc);

#if defined (SCI_LOGGING)
      // If a remote node context has a logger already, don't work on its state
      // logging.
      if (this_rnc->state_machine.previous_state_id
             != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE)
         scic_sds_remote_node_context_initialize_state_logging(this_rnc);
#endif

      sci_base_state_machine_change_state(
         &this_rnc->state_machine,
         SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
            );

      return SCI_SUCCESS;
   }

   return SCI_FAILURE_INVALID_STATE;
}
/**
 * @brief This handler is currently solely used by smp remote device for
 *        discovering.
 *
 * @param[in]  remote_device This parameter specifies the remote device
 *             object on which the user is attempting to perform a complete high
 *             priority IO operation.
 * @param[in]  io_request This parameter specifies the high priority IO request
 *             to be completed.
 *
 * @return SCI_STATUS indicate whether the io complete successfully.
 */
SCI_STATUS
scif_sas_remote_device_ready_task_management_complete_high_priority_io_handler(
   SCI_BASE_REMOTE_DEVICE_T * remote_device,
   SCI_BASE_REQUEST_T       * io_request,
   void                     * response_data,
   SCI_IO_STATUS              completion_status
)
{
   SCIF_SAS_REMOTE_DEVICE_T * fw_device  = (SCIF_SAS_REMOTE_DEVICE_T*)
                                           remote_device;
   SCIF_SAS_REQUEST_T       * fw_request = (SCIF_SAS_REQUEST_T*) io_request;
   SCI_STATUS                 status     = SCI_SUCCESS;
   SCIC_TRANSPORT_PROTOCOL    protocol;

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(remote_device),
      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_IO_REQUEST,
      "scif_sas_remote_device_ready_task_management_complete_high_priority_io_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
      remote_device, io_request, response_data, completion_status
   ));

   fw_device->request_count--;

   // we are back to ready operational sub state here.
   sci_base_state_machine_change_state(
      &fw_device->ready_substate_machine,
      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL
   );

   protocol = scic_io_request_get_protocol(fw_request->core_object);

   // If this request was an SMP initiator request we created, then
   // decode the response.
   if (protocol == SCIC_SMP_PROTOCOL)
   {
      if (completion_status != SCI_IO_FAILURE_TERMINATED)
      {
         status = scif_sas_smp_remote_device_decode_smp_response(
                     fw_device, fw_request, response_data, completion_status
                  );
      }
      else
         scif_sas_smp_remote_device_terminated_request_handler(fw_device, fw_request);
   }
   else
   {
      // Currently, there are only internal SMP requests.  So, default work
      // is simply to clean up the internal request.
      if (fw_request->is_internal == TRUE)
      {
         scif_sas_internal_io_request_complete(
            fw_device->domain->controller,
            (SCIF_SAS_INTERNAL_IO_REQUEST_T *)fw_request,
            SCI_SUCCESS
         );
      }
   }

   return status;
}
/**
 * @brief This method provides STOPPING state specific handling for
 *        when the core remote device object issues a stop completion
 *        notification.
 *
 * @note There is no need to ensure all IO/Task requests are complete
 *       before transitioning to the STOPPED state.  The SCI Core will
 *       ensure this is accomplished.
 *
 * @param[in]  remote_device This parameter specifies the remote device
 *             object for which the completion occurred.
 * @param[in]  completion_status This parameter specifies the status
 *             of the completion operation.
 *
 * @return none.
 */
static
void scif_sas_remote_device_stopping_stop_complete_handler(
   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
   SCI_STATUS                 completion_status
)
{
   // Transition directly to the STOPPED state since the core ensures
   // all IO/Tasks are complete.
   sci_base_state_machine_change_state(
      &fw_device->parent.state_machine,
      SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
   );

   if (completion_status != SCI_SUCCESS)
   {
      SCIF_LOG_ERROR((
         sci_base_object_get_logger(fw_device),
         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG,
         "Device:0x%x Status:0x%x failed to stop core device\n",
         fw_device, completion_status
      ));

      // Something is seriously wrong.  Stopping the core remote device
      // shouldn't fail in anyway.
      scif_cb_controller_error(fw_device->domain->controller,
              SCI_CONTROLLER_REMOTE_DEVICE_ERROR);
   }
}
Exemple #11
0
/**
 * @brief This method will attempt to transition to the stopped state.
 *        The transition will only occur if the criteria for transition is
 *        met (i.e. all IOs are complete and all devices are stopped).
 *
 * @param[in]  fw_domain This parameter specifies the domain in which to
 *             to attempt to perform the transition.
 *
 * @return none
 */
void scif_sas_domain_transition_to_stopped_state(
   SCIF_SAS_DOMAIN_T * fw_domain
)
{
   SCIF_LOG_TRACE((
      sci_base_object_get_logger(fw_domain),
      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
      "scif_sas_domain_transition_to_stopped_state(0x%x) enter\n",
      fw_domain
   ));

   // If IOs are quiesced, and all remote devices are stopped,
   // then transition directly to the STOPPED state.
   if (  (fw_domain->request_list.element_count == 0)
      && (fw_domain->device_start_count == 0) )
   {
      SCIF_LOG_INFO((
         sci_base_object_get_logger(fw_domain),
         SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
         "Domain:0x%x immediate transition to STOPPED\n",
         fw_domain
      ));

      sci_base_state_machine_change_state(
         &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_STOPPED
      );
   }
}
Exemple #12
0
/**
 * @brief This method implements the actions taken when entering the
 *        STARTING state.  This includes setting the state handlers and
 *        checking to see if the core port has already become READY.
 *
 * @param[in]  object This parameter specifies the base object for which
 *             the state transition is occurring.  This is cast into a
 *             SCIF_SAS_DOMAIN object in the method implementation.
 *
 * @return none
 */
static
void scif_sas_domain_starting_state_enter(
   SCI_BASE_OBJECT_T * object
)
{
   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)object;

   SET_STATE_HANDLER(
      fw_domain,
      scif_sas_domain_state_handler_table,
      SCI_BASE_DOMAIN_STATE_STARTING
   );

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(fw_domain),
      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
      "scif_sas_domain_starting_state_enter(0x%x) enter\n",
      fw_domain
   ));

   scif_sas_domain_transition_from_discovering_state(fw_domain);

   // If we entered the STARTING state and the core port is actually ready,
   // then directly transition into the READY state.  This can occur
   // if we were in the middle of discovery when the port failed
   // (causing a transition to STOPPING), then before reaching STOPPED
   // the port becomes ready again.
   if (fw_domain->is_port_ready == TRUE)
   {
      sci_base_state_machine_change_state(
         &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_READY
      );
   }
}
static
SCI_STATUS scic_sds_remote_node_context_posting_state_event_handler(
   struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
   U32                                   event_code
)
{
   SCI_STATUS status;

   switch (scu_get_event_code(event_code))
   {
      case SCU_EVENT_POST_RNC_COMPLETE:
         status = SCI_SUCCESS;

         sci_base_state_machine_change_state(
            &this_rnc->state_machine,
            SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
               );
         break;

      default:
         status = SCI_FAILURE;
         SCIC_LOG_WARNING((
            sci_base_object_get_logger(this_rnc->device),
            SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
               SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
               SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
            "SCIC Remote Node Context 0x%x requested to process unexpected event 0x%x while in posting state\n",
            this_rnc, event_code
               ));
         break;
   }

   return status;
}
/**
* This method will handle the suspend requests from the ready state.
*
* @param[in] this_rnc The remote node context object being suspended.
* @param[in] the_callback The callback when the suspension is complete.
* @param[in] callback_parameter The parameter that is to be passed into the
*       callback.
*
* @return SCI_SUCCESS
*/
static
SCI_STATUS scic_sds_remote_node_context_ready_state_suspend_handler(
   SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
   U32                                      suspend_type,
   SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
   void                                   * callback_parameter
)
{
   this_rnc->user_callback   = the_callback;
   this_rnc->user_cookie     = callback_parameter;
   this_rnc->suspension_code = suspend_type;

   if (suspend_type == SCI_SOFTWARE_SUSPENSION)
   {
      scic_sds_remote_device_post_request(
         this_rnc->device,
         SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX
            );
   }

   sci_base_state_machine_change_state(
      &this_rnc->state_machine,
      SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
         );

   return SCI_SUCCESS;
}
Exemple #15
0
void scic_cb_controller_start_complete(
   SCI_CONTROLLER_HANDLE_T  controller,
   SCI_STATUS               completion_status
)
{
   SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*)
                                         sci_object_get_association(controller);

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(controller),
      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
      "scic_cb_controller_start_complete(0x%x, 0x%x) enter\n",
      controller, completion_status
   ));

   if (completion_status == SCI_SUCCESS
       || completion_status == SCI_FAILURE_TIMEOUT)
   {
      // Even the initialization of the core controller timed out, framework
      // controller should still transit to READY state.
      sci_base_state_machine_change_state(
         &fw_controller->parent.state_machine,
         SCI_BASE_CONTROLLER_STATE_READY
      );
   }

   scif_cb_controller_start_complete(fw_controller, completion_status);
}
Exemple #16
0
/**
 * @brief This method provides COMPLETED state specific handling for
 *        when the user attempts to destruct the supplied task request.
 *
 * @param[in] task_request This parameter specifies the task request object
 *            to be destructed.
 *
 * @return This method returns a value indicating if the destruct
 *         operation was successful.
 * @retval SCI_SUCCESS This return value indicates that the destruct
 *         was successful.
 */
static
SCI_STATUS scif_sas_task_request_completed_destruct_handler(
   SCI_BASE_REQUEST_T * task_request
)
{
   SCIF_SAS_REQUEST_T * fw_request = (SCIF_SAS_REQUEST_T *)task_request;

   sci_base_state_machine_change_state(
      &task_request->state_machine, SCI_BASE_REQUEST_STATE_FINAL
   );

   sci_base_state_machine_logger_deinitialize(
      &task_request->state_machine_logger,
      &task_request->state_machine
   );

   if (fw_request->is_internal == TRUE)
   {
      scif_sas_internal_task_request_destruct(
         (SCIF_SAS_TASK_REQUEST_T *)fw_request
      );
   }

   return SCI_SUCCESS;
}
/**
 * @brief This method provides handling of device start complete duing
 *        UPDATING_PORT_WIDTH state.
 *
 * @param[in]  remote_device This parameter specifies the remote device object
 *             which is start complete.
 *
 * @return none.
 */
static
SCI_STATUS scif_sas_remote_device_updating_port_width_state_complete_io_handler(
   SCI_BASE_REMOTE_DEVICE_T * remote_device,
   SCI_BASE_REQUEST_T       * io_request
)
{
   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
                                          remote_device;
   fw_device->request_count--;

   //If the request count is zero, go ahead to update the RNC.
   if (fw_device->request_count == 0 )
   {
      if (fw_device->destination_state == SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_STOPPING)
      {
         //if the destination state of this device change to STOPPING, no matter
         //whether we need to update the port width, just make the device
         //go to the STOPPING state, the device will be removed anyway.
         sci_base_state_machine_change_state(
            &fw_device->parent.state_machine,
            SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
         );
      }
      else
      {
         //stop the device, upon the stop complete callback, start the device again
         //with the updated port width.
         scic_remote_device_stop(
            fw_device->core_object, SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT);
      }
   }

   return SCI_SUCCESS;
}
/**
 * @brief This method provides TASK MANAGEMENT sub-state specific handling for
 *        when a user attempts to complete a task management request on
 *        a remote device.
 *
 * @param[in]  remote_device This parameter specifies the remote device object
 *             on which the user is attempting to perform a complete task
 *             operation.
 * @param[in]  task_request This parameter specifies the task management
 *             request to be completed.
 *
 * @return This method returns an indication as to whether the task
 *         management request succeeded.
 */
SCI_STATUS scif_sas_remote_device_ready_task_management_complete_task_handler(
   SCI_BASE_REMOTE_DEVICE_T * remote_device,
   SCI_BASE_REQUEST_T       * task_request
)
{
   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
                                          remote_device;

   SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T *)
                                       task_request;

   fw_device->request_count--;
   fw_device->task_request_count--;

   // All existing task management requests and all of the IO requests
   // affectected by the task management request must complete before
   // the remote device can transition back into the READY / OPERATIONAL
   // state.
   if (  (fw_device->task_request_count == 0)
      && (fw_task->affected_request_count == 0) )
   {
      sci_base_state_machine_change_state(
         &fw_device->ready_substate_machine,
         SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL
      );
   }

   return SCI_SUCCESS;
}
/**
 * @brief This method provides OPERATIONAL sub-state specific handling for
 *        when a user attempts to start a high priority IO request on a remote
 *        device.
 *
 * @param[in]  remote_device This parameter specifies the remote device
 *             object on which the user is attempting to perform a start
 *             IO operation.
 * @param[in]  io_request This parameter specifies the IO request to be
 *             started.
 *
 * @return This method returns an indication as to whether the IO request
 *         started successfully.
 */
static
SCI_STATUS scif_sas_remote_device_ready_operational_start_high_priority_io_handler(
   SCI_BASE_REMOTE_DEVICE_T * remote_device,
   SCI_BASE_REQUEST_T       * io_request
)
{
   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
                                          remote_device;
   SCIF_SAS_IO_REQUEST_T    * fw_io     = (SCIF_SAS_IO_REQUEST_T*) io_request;

   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;

   scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);

   if (dev_protocols.u.bits.attached_smp_target)
   {
      //transit to task management state for smp request phase.
      if (fw_device->ready_substate_machine.current_state_id
       != SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT)
      {
         sci_base_state_machine_change_state(
            &fw_device->ready_substate_machine,
            SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT
         );
      }
   }

   fw_device->request_count++;

   return fw_io->parent.state_handlers->start_handler(&fw_io->parent.parent);
}
/**
 * @brief This method processes an unsolicited frame while the task mgmt
 *        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 TC response
 *         frame was handled successfully or not.
 * @retval SCI_SUCCESS Currently this value is always returned and indicates
 *         successful processing of the TC response.
 *
 * @todo Should probably update to check frame type and make sure it is
 *       a response frame.
 */
static
SCI_STATUS scic_sds_ssp_task_request_await_tc_response_frame_handler(
   SCIC_SDS_REQUEST_T * this_request,
   U32                  frame_index
)
{
   // Save off the controller, so that we do not touch the request after it
   //  is completed.
   SCIC_SDS_CONTROLLER_T * owning_controller = this_request->owning_controller;

   SCIC_LOG_TRACE((
      sci_base_object_get_logger(this_request),
      SCIC_LOG_OBJECT_TASK_MANAGEMENT,
      "scic_sds_ssp_task_request_await_tc_response_frame_handler(0x%x, 0x%x) enter\n",
      this_request, frame_index
   ));

   scic_sds_io_request_copy_response(this_request);

   sci_base_state_machine_change_state(
      &this_request->parent.state_machine,
      SCI_BASE_REQUEST_STATE_COMPLETED
   );

   scic_sds_controller_release_frame(
      owning_controller, frame_index
   );

   return SCI_SUCCESS;
}
Exemple #21
0
/**
 * @brief This method is called by the SCI user to build an SMP pass-through
 *        IO request.
 *
 * @pre
 *        - The user must have previously called scic_io_request_construct()
 *          on the supplied IO request.
 *
 * @param[in]  scic_smp_request This parameter specifies the handle to the
 *             io request object to be built.
 *
 * @param[in]  passthru_cb This parameter specifies the pointer to the callback
 *             structure that contains the function pointers
 *
 * @return Indicate if the controller successfully built the IO request.
 */
SCI_STATUS scic_io_request_construct_smp_pass_through(
   SCI_IO_REQUEST_HANDLE_T  scic_smp_request,
   SCIC_SMP_PASSTHRU_REQUEST_CALLBACKS_T *passthru_cb
)
{
   SMP_REQUEST_T smp_request;
   U8 * request_buffer;
   U32 request_buffer_length_in_bytes;

   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *) scic_smp_request;
   SCIC_LOG_TRACE((
      sci_base_object_get_logger(this_request),
      SCIC_LOG_OBJECT_SMP_IO_REQUEST,
      "scic_io_request_construct_smp_pass_through(0x%x) enter\n",
      this_request
   ));

   this_request->protocol                     = SCIC_SMP_PROTOCOL;
   this_request->has_started_substate_machine = TRUE;

   // Call the callback function to retrieve the SMP passthrough request
   request_buffer_length_in_bytes = passthru_cb->scic_cb_smp_passthru_get_request (
                                       (void *)this_request,
                                       &request_buffer
                                    );

   //copy the request to smp request
   memcpy((char *)&smp_request.request.vendor_specific_request,
        request_buffer,
        request_buffer_length_in_bytes);

   //the header length in smp_request is in dwords - the sas spec has similar way,
   //but the csmi header contains the number of bytes, so we need to convert the
   //number of bytes to number of dwords
   smp_request.header.request_length = (U8) (request_buffer_length_in_bytes / sizeof (U32));

   //Grab the other needed fields from the smp request using callbacks
   smp_request.header.smp_frame_type = passthru_cb->scic_cb_smp_passthru_get_frame_type ((void *)this_request);
   smp_request.header.function = passthru_cb->scic_cb_smp_passthru_get_function ((void *)this_request);
   smp_request.header.allocated_response_length = passthru_cb->scic_cb_smp_passthru_get_allocated_response_length((void *)this_request);

   // Construct the started sub-state machine.
   sci_base_state_machine_construct(
      &this_request->started_substate_machine,
      &this_request->parent.parent,
      scic_sds_smp_request_started_substate_table,
      SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE
   );

   // Construct the SMP SCU Task Context
   scu_smp_request_construct_task_context (this_request, &smp_request);

   sci_base_state_machine_change_state(
      &this_request->parent.state_machine,
      SCI_BASE_REQUEST_STATE_CONSTRUCTED
   );

   return SCI_SUCCESS;
}
static
SCI_STATUS scic_sds_remote_node_context_await_suspension_state_event_handler(
   struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
   U32                                   event_code
)
{
   SCI_STATUS status;

   switch (scu_get_event_type(event_code))
   {
      case SCU_EVENT_TL_RNC_SUSPEND_TX:
         sci_base_state_machine_change_state(
            &this_rnc->state_machine,
            SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
               );

         this_rnc->suspension_code = scu_get_event_specifier(event_code);
         status = SCI_SUCCESS;
         break;

      case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
         sci_base_state_machine_change_state(
            &this_rnc->state_machine,
            SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
               );

         this_rnc->suspension_code = scu_get_event_specifier(event_code);
         status = SCI_SUCCESS;
         break;

      default:
         SCIC_LOG_WARNING((
            sci_base_object_get_logger(this_rnc->device),
            SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
               SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
               SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
            "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n",
            this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
               ));

         status = SCI_FAILURE;
         break;
   }

   return status;
}
Exemple #23
0
SCI_STATUS scif_controller_construct(
   SCI_LIBRARY_HANDLE_T      library,
   SCI_CONTROLLER_HANDLE_T   controller,
   void *                    user_object
)
{
   SCI_STATUS              status        = SCI_SUCCESS;
   SCIF_SAS_LIBRARY_T    * fw_library    = (SCIF_SAS_LIBRARY_T*) library;
   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;

   // Validate the user supplied parameters.
   if ((library == SCI_INVALID_HANDLE) || (controller == SCI_INVALID_HANDLE))
      return SCI_FAILURE_INVALID_PARAMETER_VALUE;

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(library),
      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
      "scif_controller_construct(0x%x, 0x%x) enter\n",
      library, controller
   ));

   // Construct the base controller.  As part of constructing the base
   // controller we ask it to also manage the MDL iteration for the Core.
   sci_base_controller_construct(
      &fw_controller->parent,
      sci_base_object_get_logger(fw_library),
      scif_sas_controller_state_table,
      fw_controller->mdes,
      SCIF_SAS_MAX_MEMORY_DESCRIPTORS,
      sci_controller_get_memory_descriptor_list_handle(fw_controller->core_object)
   );

   scif_sas_controller_initialize_state_logging(fw_controller);

   sci_object_set_association(fw_controller, user_object);

   status = scic_controller_construct(
               fw_library->core_object, fw_controller->core_object, fw_controller
            );

   // If the core controller was successfully constructed, then
   // finish construction of the framework controller.
   if (status == SCI_SUCCESS)
   {
      // Set the association in the core controller to this framework
      // controller.
      sci_object_set_association(
         (SCI_OBJECT_HANDLE_T) fw_controller->core_object, fw_controller
      );

      sci_base_state_machine_change_state(
        &fw_controller->parent.state_machine,
         SCI_BASE_CONTROLLER_STATE_RESET
      );
   }

   return status;
}
Exemple #24
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;
}
Exemple #25
0
/**
 * @brief This method is called upon entrance to DISCOVERING state. Right before
 *           transitioning to DISCOVERING state, we temporarily change interrupt
 *           coalescence scheme.
 *
 * @param[in]  fw_domain This parameter specifies the domain for which
 *             the state transition has occurred.
 *
 * @return none
 */
void scif_sas_domain_transition_to_discovering_state(
   SCIF_SAS_DOMAIN_T * fw_domain
)
{
   scif_sas_controller_save_interrupt_coalescence(fw_domain->controller);

   sci_base_state_machine_change_state(
      &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_DISCOVERING
   );
}
/**
 * @brief This method provides handling of device start complete duing
 *        UPDATING_PORT_WIDTH state.
 *
 * @param[in]  remote_device This parameter specifies the remote device object
 *             which is start complete.
 *
 * @return none.
 */
static
void scif_sas_remote_device_updating_port_width_state_start_complete_handler(
   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
   SCI_STATUS                 completion_status
)
{
   SCIF_LOG_INFO((
      sci_base_object_get_logger(fw_device),
      SCIF_LOG_OBJECT_REMOTE_DEVICE,
      "RemoteDevice:0x%x updating port width state start complete handler\n",
      fw_device,
      sci_base_state_machine_get_state(&fw_device->parent.state_machine)
   ));

   if ( fw_device->destination_state
           == SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_STOPPING )
   {
      //if the destination state of this device change to STOPPING, no matter
      //whether we need to update the port width again, just make the device
      //go to the STOPPING state.
      sci_base_state_machine_change_state(
         &fw_device->parent.state_machine,
         SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
      );
   }
   else if ( scic_remote_device_get_port_width(fw_device->core_object)
                != fw_device->device_port_width
            && fw_device->device_port_width != 0)
   {
      scic_remote_device_stop(
         fw_device->core_object,
         SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT
      );
   }
   else
   {
      //Port width updating succeeds. Transfer to destination state.
      sci_base_state_machine_change_state(
         &fw_device->parent.state_machine,
         SCI_BASE_REMOTE_DEVICE_STATE_READY
      );
   }
}
Exemple #27
0
/**
 * @brief This method provides CONSTRUCTED state specific handling for
 *        when the user attempts to abort the supplied IO request.
 *
 * @param[in] io_request This parameter specifies the IO request object
 *            to be aborted.
 *
 * @return This method returns a value indicating if the IO request was
 *         successfully aborted or not.
 * @retval SCI_SUCCESS This return value indicates successful aborting
 *         of the IO request.
 */
SCI_STATUS scif_sas_io_request_constructed_abort_handler(
   SCI_BASE_REQUEST_T * io_request
)
{
   sci_base_state_machine_change_state(
      &io_request->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED
   );

   return SCI_SUCCESS;
}
/**
 * @brief This method provides SUSPENDED sub-state specific handling for
 *        when the core remote device object issues a device ready
 *        notification.  This effectively causes the framework remote
 *        device to transition back into the OPERATIONAL state.
 *
 * @param[in]  remote_device This parameter specifies the remote device
 *             object for which the notification occurred.
 *
 * @return none.
 */
static
void scif_sas_remote_device_ready_suspended_ready_handler(
   SCIF_SAS_REMOTE_DEVICE_T * fw_device
)
{
   sci_base_state_machine_change_state(
      &fw_device->ready_substate_machine,
      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL
   );
}
Exemple #29
0
/**
 * @brief This method provides ABORTING state specific handling for
 *        when the user attempts to complete the supplied task request.
 *
 * @param[in] task_request This parameter specifies the task request object
 *            to be completed.
 *
 * @return This method returns a value indicating if the completion
 *         operation was successful.
 * @retval SCI_SUCCESS This return value indicates that the completion
 *         was successful.
 */
static
SCI_STATUS scif_sas_task_request_aborting_complete_handler(
   SCI_BASE_REQUEST_T * task_request
)
{
   sci_base_state_machine_change_state(
      &task_request->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED
   );

   return SCI_SUCCESS;
}
Exemple #30
0
/**
 * @brief This method provides CONSTRUCTED state specific handling for
 *        when the user attempts to start the supplied task request.
 *
 * @param[in] task_request This parameter specifies the task request object
 *            to be started.
 *
 * @return This method returns a value indicating if the task request was
 *         successfully started or not.
 * @retval SCI_SUCCESS This return value indicates successful starting
 *         of the task request.
 */
static
SCI_STATUS scif_sas_task_request_constructed_start_handler(
   SCI_BASE_REQUEST_T * task_request
)
{
   sci_base_state_machine_change_state(
      &task_request->state_machine, SCI_BASE_REQUEST_STATE_STARTED
   );

   return SCI_SUCCESS;
}