Example #1
0
U8 scic_cb_ssp_task_request_get_function(
   void * scic_user_task_request
)
{
   SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T*)
                                       scic_user_task_request;

   return scif_sas_task_request_get_function(fw_task);
}
void scic_cb_port_hard_reset_complete(
   SCI_CONTROLLER_HANDLE_T  controller,
   SCI_PORT_HANDLE_T        port,
   SCI_STATUS               completion_status
)
{
   SCIF_SAS_DOMAIN_T        * fw_domain = (SCIF_SAS_DOMAIN_T*)
                                   sci_object_get_association(port);
   SCIF_SAS_REMOTE_DEVICE_T * fw_device;
   SCI_FAST_LIST_ELEMENT_T  * element = fw_domain->request_list.list_head;
   SCIF_SAS_TASK_REQUEST_T  * task_request = NULL;

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(fw_domain),
      SCIF_LOG_OBJECT_DOMAIN,
      "scic_cb_port_hard_reset_complete(0x%x, 0x%x, 0x%x) enter\n",
      controller, port, completion_status
   ));

   while (element != NULL)
   {
      task_request = (SCIF_SAS_TASK_REQUEST_T*) sci_fast_list_get_object(element);
      element = sci_fast_list_get_next(element);

      if (scif_sas_task_request_get_function(task_request)
             == SCI_SAS_HARD_RESET)
      {
         fw_device = task_request->parent.device;

         if (fw_device->domain == fw_domain)
         {
            scic_remote_device_reset_complete(fw_device->core_object);

            scif_cb_task_request_complete(
               sci_object_get_association(controller),
               fw_device,
               task_request,
               (SCI_TASK_STATUS) completion_status
            );

            break;
         }
      }
   }
}
/**
 * @brief This method provides OPERATIONAL sub-state specific handling for
 *        when a user attempts to start a task management request on
 *        a remote device.  This includes terminating all of the affected
 *        ongoing IO requests (i.e. aborting them in the silicon) and then
 *        issuing the task management request to the silicon.
 *
 * @param[in]  remote_device This parameter specifies the remote device
 *             object on which the user is attempting to perform a start
 *             task operation.
 * @param[in]  task_request This parameter specifies the task management
 *             request to be started.
 *
 * @return This method returns an indication as to whether the task
 *         management request started successfully.
 */
static
SCI_STATUS scif_sas_remote_device_ready_operational_start_task_handler(
   SCI_BASE_REMOTE_DEVICE_T * remote_device,
   SCI_BASE_REQUEST_T       * task_request
)
{
   SCI_STATUS                 status     = SCI_FAILURE;
   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;
   U8 task_function =
         scif_sas_task_request_get_function(fw_task);

   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;

   scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);
   if (   dev_protocols.u.bits.attached_ssp_target
       || dev_protocols.u.bits.attached_stp_target)
   {
      // //NOTE: For STP/SATA targets we currently terminate all requests for
      //       any type of task management.
      if (  (task_function == SCI_SAS_ABORT_TASK_SET)
         || (task_function == SCI_SAS_CLEAR_TASK_SET)
         || (task_function == SCI_SAS_LOGICAL_UNIT_RESET)
         || (task_function == SCI_SAS_I_T_NEXUS_RESET)
         || (task_function == SCI_SAS_HARD_RESET) )
      {
         // Terminate all of the requests in the silicon for this device.
         scif_sas_domain_terminate_requests(
            fw_device->domain, fw_device, NULL, fw_task
         );

         status = scif_sas_remote_device_start_task_request(fw_device, fw_task);
      }
      else if (  (task_function == SCI_SAS_CLEAR_ACA)
              || (task_function == SCI_SAS_QUERY_TASK)
              || (task_function == SCI_SAS_QUERY_TASK_SET)
              || (task_function == SCI_SAS_QUERY_ASYNCHRONOUS_EVENT) )
      {
       ASSERT(!dev_protocols.u.bits.attached_stp_target);
         status = scif_sas_remote_device_start_task_request(fw_device, fw_task);
      }
      else if (task_function == SCI_SAS_ABORT_TASK)
      {
         SCIF_SAS_REQUEST_T * fw_request
            = scif_sas_domain_get_request_by_io_tag(
                 fw_device->domain, fw_task->io_tag_to_manage
              );

         // Determine if the request being aborted was found.
         if (fw_request != NULL)
         {
            scif_sas_domain_terminate_requests(
               fw_device->domain, fw_device, fw_request, fw_task
            );

            status = scif_sas_remote_device_start_task_request(
                        fw_device, fw_task
                     );
         }
         else
            status = SCI_FAILURE_INVALID_IO_TAG;
      }
   }
   else
      status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;

   if (status != SCI_SUCCESS)
   {
      SCIF_LOG_ERROR((
         sci_base_object_get_logger(fw_device),
         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
         "Controller:0x%x TaskRequest:0x%x Status:0x%x start task failure\n",
         fw_device, fw_task, status
      ));
   }

   return status;
}
Example #4
0
void scic_cb_task_request_complete(
   SCI_CONTROLLER_HANDLE_T     controller,
   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
   SCI_TASK_REQUEST_HANDLE_T   task_request,
   SCI_TASK_STATUS             completion_status
)
{
   SCIF_SAS_CONTROLLER_T    * fw_controller = (SCIF_SAS_CONTROLLER_T*)
                                         sci_object_get_association(controller);
   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
                                      sci_object_get_association(remote_device);
   SCIF_SAS_TASK_REQUEST_T  * fw_task = (SCIF_SAS_TASK_REQUEST_T*)
                                       sci_object_get_association(task_request);
   SCI_STATUS                 status;

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(fw_controller),
      SCIF_LOG_OBJECT_TASK_MANAGEMENT,
      "scic_cb_task_request_complete(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
      controller, remote_device, task_request, completion_status
   ));

   status = fw_task->parent.state_handlers->complete_handler(
               &fw_task->parent.parent
            );

   if (status == SCI_SUCCESS)
   {
      if (fw_task->parent.protocol_complete_handler != NULL)
      {
         status = fw_task->parent.protocol_complete_handler(
            fw_controller, fw_device, &fw_task->parent, (SCI_STATUS *)&completion_status
         );
      }

      if (status == SCI_SUCCESS)
      {
         SCIF_LOG_WARNING((
            sci_base_object_get_logger(fw_task),
            SCIF_LOG_OBJECT_TASK_MANAGEMENT,
            "RemoteDevice:0x%x TaskRequest:0x%x Function:0x%x CompletionStatus:0x%x "
            "completed\n",
            fw_device, fw_task,
            scif_sas_task_request_get_function(fw_task),
            completion_status
         ));

         // If this isn't an internal framework IO request, then simply pass the
         // notification up to the SCIF user.  Otherwise, immediately complete the
         // task since there is no SCIF user to notify.
         if (fw_task->parent.is_internal == FALSE)
         {
            scif_cb_task_request_complete(
               fw_controller, fw_device, fw_task, completion_status
            );
         }
         else
         {
            scif_controller_complete_task(
               fw_controller,
               fw_device,
               fw_task
            );
         }
      }
   }
}
Example #5
0
static
SCI_STATUS scif_sas_task_request_generic_construct(
   SCI_CONTROLLER_HANDLE_T      scif_controller,
   SCI_REMOTE_DEVICE_HANDLE_T   scif_remote_device,
   U16                          io_tag,
   void                       * user_task_request_object,
   void                       * task_request_memory,
   SCI_TASK_REQUEST_HANDLE_T  * scif_task_request,
   U8                           task_function
)
{
   SCI_STATUS                 status;
   SCIF_SAS_CONTROLLER_T    * fw_controller   = (SCIF_SAS_CONTROLLER_T*)
                                                scif_controller;
   SCIF_SAS_TASK_REQUEST_T  * fw_task         = (SCIF_SAS_TASK_REQUEST_T*)
                                                task_request_memory;
   SCIF_SAS_REMOTE_DEVICE_T * fw_device       = (SCIF_SAS_REMOTE_DEVICE_T*)
                                                scif_remote_device;
   U8                       * core_request_memory;

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(fw_controller),
      SCIF_LOG_OBJECT_TASK_MANAGEMENT,
      "scif_task_request_construct(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) enter\n",
      scif_controller, scif_remote_device, io_tag, user_task_request_object,
      task_request_memory, scif_task_request
   ));

   // Initialize the user's handle to the framework task request.
   *scif_task_request = fw_task;

   // initialize affected request count
   fw_task->affected_request_count = 0;
   fw_task->io_tag_to_manage = SCI_CONTROLLER_INVALID_IO_TAG;
   fw_task->function = task_function;

   if (task_function == SCI_SAS_HARD_RESET )
   {
      if (fw_device->containing_device != NULL )
      {// Target Reset is for an expander attached device,
       // go down to construct smp Phy Control request.
         scif_sas_smp_request_construct_phy_control(
            fw_controller,
            fw_device->containing_device,
            PHY_OPERATION_HARD_RESET,
            fw_device->expander_phy_identifier,
            user_task_request_object,
            task_request_memory
         );
      }
      else
      {
         scif_sas_request_construct(
            &fw_task->parent,
            fw_device,
            sci_base_object_get_logger(fw_controller),
            scif_sas_task_request_state_table
         );

         // If target reset is for a DA device, don't build task at all.
         // Just set object association.
         sci_object_set_association(fw_task, user_task_request_object);
      }

      return SCI_SUCCESS;
   }

   // Construct the parent object first in order to ensure logging can
   // function.
   scif_sas_request_construct(
      &fw_task->parent,
      fw_device,
      sci_base_object_get_logger(fw_controller),
      scif_sas_task_request_state_table
   );

   core_request_memory = (U8 *)task_request_memory + sizeof(SCIF_SAS_TASK_REQUEST_T);

   status = scic_task_request_construct(
               fw_controller->core_object,
               fw_device->core_object,
               io_tag,
               fw_task,
               core_request_memory,
               &fw_task->parent.core_object
            );

   if (status == SCI_SUCCESS)
   {
      SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;

      // These associations must be set early for the core io request
      // object construction to complete correctly as there will be
      // callbacks into the user driver framework during core construction
      sci_object_set_association(fw_task, user_task_request_object);
      sci_object_set_association(fw_task->parent.core_object, fw_task);

      // Perform protocol specific core IO request construction.
      scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);
      if (dev_protocols.u.bits.attached_ssp_target)
         status = scic_task_request_construct_ssp(fw_task->parent.core_object);
      else if (dev_protocols.u.bits.attached_stp_target)
         status = scif_sas_stp_task_request_construct(fw_task);
      else
         status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;

      if (status == SCI_SUCCESS)
      {
         sci_base_state_machine_logger_initialize(
            &fw_task->parent.parent.state_machine_logger,
            &fw_task->parent.parent.state_machine,
            &fw_task->parent.parent.parent,
            scif_cb_logger_log_states,
            "SCIF_SAS_TASK_REQUEST_T", "base_state_machine",
            SCIF_LOG_OBJECT_TASK_MANAGEMENT
         );
      }
      else
      {
         SCIF_LOG_WARNING((
            sci_base_object_get_logger(fw_task),
            SCIF_LOG_OBJECT_TASK_MANAGEMENT,
            "Device:0x%x TaskRequest:0x%x Function:0x%x construct failed\n",
            fw_device, fw_task, scif_sas_task_request_get_function(fw_task)
         ));
      }
   }

   return status;
}
/**
 * @brief This method provides SATA/STP STARTED state specific handling for
 *        when the user attempts to complete the supplied IO request.
 *        It will perform data/response translation and free NCQ tags
 *        if necessary.
 *
 * @param[in] io_request This parameter specifies the IO request object
 *            to be started.
 *
 * @return This method returns a value indicating if the IO request was
 *         successfully completed or not.
 */
static
SCI_STATUS scif_sas_stp_core_cb_task_request_complete_handler(
   SCIF_SAS_CONTROLLER_T    * fw_controller,
   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
   SCIF_SAS_REQUEST_T       * fw_request,
   SCI_STATUS               * completion_status
)
{
#if !defined(DISABLE_SATI_TASK_MANAGEMENT)
   SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T *) fw_request;

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(fw_controller),
      SCIF_LOG_OBJECT_TASK_MANAGEMENT,
      "scif_sas_stp_core_cb_task_request_complete_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
      fw_controller, fw_device, fw_request, *completion_status
   ));

   // Translating the response is only necessary if some sort of error
   // occurred resulting in having the error bit set in the ATA status
   // register and values to decode in the ATA error register.
   if (  (*completion_status == SCI_SUCCESS)
      || (*completion_status == SCI_FAILURE_IO_RESPONSE_VALID) )
   {
      SATI_STATUS sati_status = sati_translate_task_response(
                                   &fw_task->parent.stp.sequence,
                                   fw_task,
                                   fw_task
                                );

      if (sati_status == SATI_COMPLETE)
         *completion_status = SCI_SUCCESS;
      else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA)
         *completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
      else if (sati_status == SATI_SEQUENCE_INCOMPLETE)
      {
         // The translation indicates that additional SATA requests are
         // necessary to finish the original SCSI request.  As a result,
         // do not complete the IO and begin the next stage of the
         // translation.
         /// @todo multiple ATA commands are required, but not supported yet.
         return SCI_FAILURE;
      }
      else
      {
         // Something unexpected occurred during translation.  Fail the
         // IO request to the user.
         *completion_status = SCI_FAILURE;
      }
   }
   else  //A stp task request sometimes fails.
   {
      if (scif_sas_task_request_get_function(fw_task) == SCI_SAS_ABORT_TASK_SET)
      {
         scif_sas_stp_task_request_abort_task_set_failure_handler(
            fw_device, fw_task);
      }
   }

   return SCI_SUCCESS;
#else // !defined(DISABLE_SATI_TASK_MANAGEMENT)
   return SCI_FAILURE;
#endif // !defined(DISABLE_SATI_TASK_MANAGEMENT)
}