/**
 * @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;
}
/**
 * @brief This method provides default handling (i.e. returns an error);
 *        for when the core issues a ready notification and such a
 *        notification isn't supported.
 *
 * @param[in]  remote_device This parameter specifies the remote device object
 *             for which the notification has occured.
 *
 * @return none.
 */
void scif_sas_remote_device_default_ready_handler(
   SCIF_SAS_REMOTE_DEVICE_T * fw_device
)
{
   SCIF_LOG_WARNING((
      sci_base_object_get_logger(fw_device),
      SCIF_LOG_OBJECT_REMOTE_DEVICE,
      "RemoteDevice:0x%x State:0x%x invalid state to handle ready\n",
      fw_device,
      sci_base_state_machine_get_state(&fw_device->parent.state_machine)
   ));
}
/**
 * @brief This method provides default handling (i.e. returns an error);
 *        for when the core issues a stop completion notification and
 *        such a notification isn't supported.
 *
 * @param[in]  remote_device This parameter specifies the remote device object
 *             for which the completion notification has occured.
 * @param[in]  completion_status This parameter specifies the status
 *             of the completion operation.
 *
 * @return none.
 */
void scif_sas_remote_device_default_stop_complete_handler(
   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
   SCI_STATUS                 completion_status
)
{
   SCIF_LOG_WARNING((
      sci_base_object_get_logger(fw_device),
      SCIF_LOG_OBJECT_REMOTE_DEVICE,
      "RemoteDevice:0x%x State:0x%x invalid state to stop complete\n",
      fw_device,
      sci_base_state_machine_get_state(&fw_device->parent.state_machine)
   ));
}
Esempio n. 4
0
SCI_STATUS scif_library_allocate_controller(
   SCI_LIBRARY_HANDLE_T      library,
   SCI_CONTROLLER_HANDLE_T * new_controller
)
{
   SCI_STATUS  status;

   // Ensure the user supplied a valid library handle.
   if (library != SCI_INVALID_HANDLE)
   {
      SCIF_SAS_LIBRARY_T * fw_library = (SCIF_SAS_LIBRARY_T *) library;

      // Allocate the framework library.
      SCI_BASE_LIBRARY_ALLOCATE_CONTROLLER(fw_library, new_controller, &status);
      if (status == SCI_SUCCESS)
      {
         SCIF_SAS_CONTROLLER_T * fw_controller;

         // Allocate the core controller and save the handle in the framework
         // controller object.
         fw_controller = (SCIF_SAS_CONTROLLER_T*) *new_controller;

         // Just clear out the memory of the structure to be safe.
         memset(fw_controller, 0, sizeof(SCIF_SAS_CONTROLLER_T));

         status = scic_library_allocate_controller(
                     fw_library->core_object, &(fw_controller->core_object)
                  );

         // Free the framework controller if the core controller allocation
         // failed.
         if (status != SCI_SUCCESS)
            scif_library_free_controller(library, fw_controller);
      }

      if (status != SCI_SUCCESS)
      {
         SCIF_LOG_WARNING((
            sci_base_object_get_logger(fw_library),
            SCIF_LOG_OBJECT_LIBRARY,
            "Library:0x%x Status:0x%x controller allocation failed\n",
            fw_library, status
         ));
      }
   }
   else
      status = SCI_FAILURE_INVALID_PARAMETER_VALUE;

   return status;
}
/**
 * @brief This method provides default handling (i.e. returns an error);
 *        when there is an attempt to complete a reset to the remote device
 *        from an invalid state.
 *
 * @param[in]  remote_device This parameter specifies the remote device
 *             object on which there is an attempt to fail the device.
 *
 * @return This method returns an indication that the fail transition is not
 *         allowed.
 * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
 */
SCI_STATUS scif_sas_remote_device_default_reset_complete_handler(
   SCI_BASE_REMOTE_DEVICE_T * remote_device
)
{
   SCIF_LOG_WARNING((
      sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
      SCIF_LOG_OBJECT_REMOTE_DEVICE,
      "RemoteDevice:0x%x State:0x%x invalid state to complete reset.\n",
      remote_device,
      sci_base_state_machine_get_state(
         &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
   ));

   return SCI_FAILURE_INVALID_STATE;
}
/**
 * @brief This method provides default handling (i.e. returns an error);
 *        when a user attempts to start a task on a remote device and a
 *        start task operation is not allowed.
 *
 * @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 that start task operations
 *         are not allowed.
 * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
 */
SCI_STATUS scif_sas_remote_device_default_start_task_handler(
   SCI_BASE_REMOTE_DEVICE_T * remote_device,
   SCI_BASE_REQUEST_T       * task_request
)
{
   SCIF_LOG_WARNING((
      sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
      "RemoteDevice:0x%x State:0x%x invalid state to start task\n",
      remote_device,
      sci_base_state_machine_get_state(
         &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
   ));

   return SCI_FAILURE_INVALID_STATE;
}
Esempio n. 7
0
SCI_PORT_HANDLE_T scif_domain_get_scic_port_handle(
   SCI_DOMAIN_HANDLE_T  domain
)
{
   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T*) domain;

   if ( (fw_domain == NULL) || (fw_domain->core_object == SCI_INVALID_HANDLE) )
      return SCI_INVALID_HANDLE;

   SCIF_LOG_WARNING((
      sci_base_object_get_logger(fw_domain),
      SCIF_LOG_OBJECT_DOMAIN,
      "Domain:0x%x no associated core port found\n",
      fw_domain
   ));

   return fw_domain->core_object;
}
/**
 * @brief This method provides default handling (i.e. returns an error);
 *        when a user attempts to complete an IO on a remote device and a
 *        complete IO operation is not allowed.
 *
 * @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 that complete IO operations
 *         are not allowed.
 * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
 */
SCI_STATUS scif_sas_remote_device_default_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_LOG_WARNING((
      sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
      SCIF_LOG_OBJECT_REMOTE_DEVICE,
      "RemoteDevice:0x%x State:0x%x invalid state to complete high priority IO\n",
      remote_device,
      sci_base_state_machine_get_state(
         &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
   ));

   return SCI_FAILURE_INVALID_STATE;
}
Esempio n. 9
0
SCI_STATUS scif_library_free_controller(
   SCI_LIBRARY_HANDLE_T     library,
   SCI_CONTROLLER_HANDLE_T  controller
)
{
   SCI_STATUS  status;

   if ( (library != SCI_INVALID_HANDLE) && (controller != SCI_INVALID_HANDLE) )
   {
      SCI_STATUS              core_status;
      SCIF_SAS_LIBRARY_T    * fw_library    = (SCIF_SAS_LIBRARY_T*) library;
      SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;

      core_status = scic_library_free_controller(
                       fw_library->core_object, fw_controller->core_object
                    );

      scif_sas_controller_destruct(fw_controller);

      SCI_BASE_LIBRARY_FREE_CONTROLLER(
         (SCIF_SAS_LIBRARY_T *) library,
         controller,
         SCIF_SAS_CONTROLLER_T,
         &status
      );

      if ( (status == SCI_SUCCESS) && (core_status != SCI_SUCCESS) )
         status = core_status;

      if (status != SCI_SUCCESS)
      {
         SCIF_LOG_WARNING((
            sci_base_object_get_logger(fw_library),
            SCIF_LOG_OBJECT_LIBRARY,
            "Library:0x%x Controller:0x%x Status:0x%x free controller failed\n",
            fw_library, fw_controller, status
         ));
      }
   }
   else
      status = SCI_FAILURE_INVALID_PARAMETER_VALUE;

   return status;
}
Esempio n. 10
0
/**
 * @brief This method provides AWAIT START COMPLETE sub-state specific
 *        handling for when the remote device undergoes a failure
 *        condition.
 *
 * @param[in]  remote_device This parameter specifies the remote device
 *             object for which the failure condition occurred.
 *
 * @return This method returns an indication as to whether the failure
 *         operation completed successfully.
 */
static
SCI_STATUS scif_sas_remote_device_starting_await_complete_fail_handler(
   SCI_BASE_REMOTE_DEVICE_T * remote_device
)
{
   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
                                          remote_device;

   SCIF_LOG_WARNING((
      sci_base_object_get_logger(fw_device),
      SCIF_LOG_OBJECT_REMOTE_DEVICE,
      "RemoteDevice:0x%x starting device failed, start complete not received\n",
      fw_device
   ));

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

   return SCI_SUCCESS;
}
Esempio n. 11
0
/**
 * @brief This method will attempt to handle an operation timeout (i.e.
 *        discovery or reset).
 *
 * @param[in]  cookie This parameter specifies the domain in which the
 *             timeout occurred.
 *
 * @return none
 */
static
void scif_sas_domain_operation_timeout_handler(
   void * cookie
)
{
   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T*) cookie;
   U32                 state;

   state = sci_base_state_machine_get_state(&fw_domain->parent.state_machine);

   // Based upon the state of the domain, we know whether we were in the
   // process of performing discovery or a reset.
   if (state == SCI_BASE_DOMAIN_STATE_DISCOVERING)
   {
      SCIF_LOG_WARNING((
         sci_base_object_get_logger(fw_domain),
         SCIF_LOG_OBJECT_DOMAIN,
         "Domain:0x%x State:0x%x DISCOVER timeout!\n",
         fw_domain, state
      ));

      fw_domain->operation.status = SCI_FAILURE_TIMEOUT;

      //search all the smp devices in the domain and cancel their activities
      //if there is any outstanding activity remained. The smp devices will terminate
      //all the started internal IOs.
      scif_sas_domain_cancel_smp_activities(fw_domain);

      scif_sas_domain_continue_discover(fw_domain);
   }
   else
   {
      SCIF_LOG_ERROR((
         sci_base_object_get_logger(fw_domain),
         SCIF_LOG_OBJECT_DOMAIN,
         "Domain:0x%x State:0x%x operation timeout in invalid state\n",
         fw_domain, state
      ));
   }
}
/**
 * @brief This method provides OPERATIONAL sub-state specific handling for
 *        when the remote device undergoes a failure condition.
 *
 * @param[in]  remote_device This parameter specifies the remote device
 *             object for which the failure condition occurred.
 *
 * @return This method returns an indication as to whether the failure
 *         operation completed successfully.
 */
static
SCI_STATUS scif_sas_remote_device_ready_operational_fail_handler(
   SCI_BASE_REMOTE_DEVICE_T * remote_device
)
{
   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
                                          remote_device;

   SCIF_LOG_WARNING((
      sci_base_object_get_logger(fw_device),
      SCIF_LOG_OBJECT_REMOTE_DEVICE,
      "RemoteDevice:0x%x ready device failed\n",
      fw_device
   ));

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

   /// @todo Fix the return code handling.
   return SCI_FAILURE;
}
Esempio n. 13
0
/**
 * @brief This method provides AWAIT START COMPLETE sub-state specific
 *        handling for when the core provides a start complete notification
 *        for the remote device.  If the start completion status indicates
 *        a successful start, then the device is transitioned into the
 *        READY state.  All other status cause a transition to the
 *        FAILED state and a scif_cb_controller_error() notification
 *        message to the framework user.
 *
 * @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_complete_start_complete_handler(
   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
   SCI_STATUS                 completion_status
)
{
   if (completion_status == SCI_SUCCESS)
   {
      /** @todo need to add support for resetting the device first.  This can
                wait until 1.3. */
      /** @todo Update to comprehend situations (i.e. SATA) where config is
                needed. */

      sci_base_state_machine_change_state(
         &fw_device->starting_substate_machine,
         SCIF_SAS_REMOTE_DEVICE_STARTING_SUBSTATE_AWAIT_READY
      );
   }
   else
   {
      SCIF_LOG_WARNING((
         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 start core device\n",
         fw_device
      ));

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

      // Something is seriously wrong.  Starting the core remote device
      // shouldn't fail in anyway in this state.
      scif_cb_controller_error(fw_device->domain->controller,
              SCI_CONTROLLER_REMOTE_DEVICE_ERROR);
   }
}
Esempio n. 14
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
            );
         }
      }
   }
}
Esempio n. 15
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;
}