Пример #1
0
/**
 * @brief This method searches the domain object to find a
 *        SCIF_SAS_REQUEST object associated with the supplied IO tag.
 *
 * @param[in]  fw_domain This parameter specifies the domain in which to
 *             to find the request object.
 * @param[in]  io_tag This parameter specifies the IO tag value for which
 *             to locate the corresponding request.
 *
 * @return This method returns a pointer to the SCIF_SAS_REQUEST object
 *         associated with the supplied IO tag.
 * @retval NULL This value is returned if the IO tag does not resolve to
 *         a request.
 */
SCIF_SAS_REQUEST_T * scif_sas_domain_get_request_by_io_tag(
   SCIF_SAS_DOMAIN_T * fw_domain,
   U16                 io_tag
)
{
   SCI_FAST_LIST_ELEMENT_T * element    = fw_domain->request_list.list_head;
   SCIF_SAS_IO_REQUEST_T   * io_request = NULL;

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(fw_domain),
      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
      "scif_sas_domain_get_request_by_io_tag(0x%x, 0x%x) enter\n",
      fw_domain, io_tag
   ));

   while (element != NULL)
   {
      io_request = (SCIF_SAS_IO_REQUEST_T*) sci_fast_list_get_object(element);

      // Check to see if we located the request with an identical IO tag.
      if (scic_io_request_get_io_tag(io_request->parent.core_object) == io_tag)
         return &io_request->parent;

      element = sci_fast_list_get_next(element);
   }

   return NULL;
}
Пример #2
0
/**
 * @brief This method remove an expander device and its child devices, in order to
 *        deal with a detected illeagal phy connection.
 *
 * @param[in] fw_domain The domain that a expander belongs to.
 * @param[in] fw_device The expander device to be removed.
 *
 * @return none.
 */
void scif_sas_domain_remove_expander_device(
   SCIF_SAS_DOMAIN_T        * fw_domain,
   SCIF_SAS_REMOTE_DEVICE_T * fw_device
)
{
   SCIF_SAS_SMP_REMOTE_DEVICE_T * smp_remote_device =
      &fw_device->protocol_device.smp_device;

   SCI_FAST_LIST_ELEMENT_T     * element = smp_remote_device->smp_phy_list.list_head;
   SCIF_SAS_SMP_PHY_T          * curr_smp_phy = NULL;
   SCIF_SAS_REMOTE_DEVICE_T    * current_device = NULL;

   while (element != NULL)
   {
      curr_smp_phy = (SCIF_SAS_SMP_PHY_T*) sci_fast_list_get_object(element);
      element = sci_fast_list_get_next(element);

      if ( curr_smp_phy->attached_device_type != SMP_NO_DEVICE_ATTACHED
          && curr_smp_phy->u.end_device != NULL )
      {
         if (curr_smp_phy->attached_device_type == SMP_END_DEVICE_ONLY)
            current_device = curr_smp_phy->u.end_device;
         else
            current_device = curr_smp_phy->u.attached_phy->owning_device;

         scif_cb_domain_device_removed(fw_domain->controller, fw_domain, current_device);
      }
   }

   //remove device itself
   scif_cb_domain_device_removed(fw_domain->controller, fw_domain, fw_device);
}
Пример #3
0
/**
 * @brief This method searches the domain's request list and counts outstanding
 *           smp IOs.
 *
 * @param[in] fw_domain The domain that its request list is to be searched.
 *
 * @return U8 The possible return value of this routine is 0 or 1.
 */
U8 scif_sas_domain_get_smp_request_count(
   SCIF_SAS_DOMAIN_T * fw_domain
)
{
   SCI_FAST_LIST_ELEMENT_T * element = fw_domain->request_list.list_head;
   SCIF_SAS_REQUEST_T      * request = NULL;
   U8                        count = 0;
   SCIC_TRANSPORT_PROTOCOL   protocol;

   // Cycle through the fast list of IO requests.  Terminate each
   // outstanding requests that matches the criteria supplied by the
   // caller.
   while (element != NULL)
   {
      request = (SCIF_SAS_REQUEST_T*) sci_fast_list_get_object(element);
      // The current element may be deleted from the list becasue of
      // IO completion so advance to the next element early
      element = sci_fast_list_get_next(element);

      protocol = scic_io_request_get_protocol(request->core_object);

      if ( protocol == SCIC_SMP_PROTOCOL)
         count++;
   }

   return count;
}
/**
 * @brief This method finds the next smp phy (from the anchor_phy) that link to
 *           a SATA end device.
 *
 * @param[in] fw_device the framework SMP device that is clearing affiliation for
 *               its remote SATA devices'
 *
 * @return SCIF_SAS_SMP_PHY_T a smp phy, to which clear affiliation phy control command
 *            is to be sent.
 */
static
SCIF_SAS_SMP_PHY_T * scif_sas_smp_remote_device_find_next_smp_phy_link_to_sata(
   SCIF_SAS_SMP_PHY_T * anchor_phy
)
{
   SCI_FAST_LIST_ELEMENT_T  * element = &anchor_phy->list_element;
   SCIF_SAS_SMP_PHY_T * curr_smp_phy = NULL;

   while (element != NULL)
   {
      curr_smp_phy = (SCIF_SAS_SMP_PHY_T*) sci_fast_list_get_object(element);
      element = sci_fast_list_get_next(element);

      if (curr_smp_phy->attached_device_type == SMP_END_DEVICE_ONLY
          && curr_smp_phy->u.end_device != NULL)
      {
         SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
         scic_remote_device_get_protocols(
            curr_smp_phy->u.end_device->core_object, &dev_protocols);

         if (dev_protocols.u.bits.attached_stp_target)
            return curr_smp_phy;
      }
   }

   return NULL;
}
Пример #5
0
struct SCIF_SAS_REQUEST *
scif_sas_stp_remote_device_get_request_by_ncq_tag(
   struct SCIF_SAS_REMOTE_DEVICE * fw_device,
   U8                              ncq_tag
)
{
   SCIF_SAS_DOMAIN_T                * fw_domain = fw_device->domain;
   SCI_FAST_LIST_ELEMENT_T          * pending_request_element;
   SCIF_SAS_REQUEST_T               * pending_request = NULL;
   SCIF_SAS_REQUEST_T               * matching_request = NULL;

   pending_request_element = fw_domain->request_list.list_head;

   while (pending_request_element != NULL)
   {
      pending_request =
         (SCIF_SAS_REQUEST_T*) sci_fast_list_get_object(pending_request_element);

      // The current element may be deleted from the list becasue of
      // IO completion so advance to the next element early
      pending_request_element = sci_fast_list_get_next(pending_request_element);

      if (
            (pending_request->device == fw_device) &&
            (pending_request->stp.sequence.protocol == SAT_PROTOCOL_FPDMA) &&
            (pending_request->stp.ncq_tag == ncq_tag)
         )
      {
         matching_request = pending_request;
      }
   }

   return matching_request;
}
Пример #6
0
/**
 * @brief This method will terminate the requests outstanding in the core
 *        based on the supplied criteria.
 *        - if the all three parameters are specified then only the single
 *          SCIF_SAS_REQUEST object is terminated.
 *        - if only the SCIF_SAS_DOMAIN and SCIF_SAS_REMOTE_DEVICE are
 *          specified, then all SCIF_SAS_REQUEST objects outstanding at
 *          the device are terminated.  The one exclusion to this rule is
 *          that the fw_requestor is not terminated.
 *        - if only the SCIF_SAS_DOMAIN object is specified, then all
 *          SCIF_SAS_REQUEST objects outstanding in the domain are
 *          terminated.
 *
 * @param[in]  fw_domain This parameter specifies the domain in which to
 *             terminate requests.
 * @param[in]  fw_device This parameter specifies the remote device in
 *             which to terminate requests.  This parameter can be NULL
 *             as long as the fw_request parameter is NULL.  It is a
 *             required parameter if the fw_request parameter is not NULL.
 * @param[in]  fw_request This parameter specifies the request object to
 *             be terminated.  This parameter can be NULL.
 * @param[in]  fw_requestor This parameter specifies the task management
 *             request that is responsible for the termination of requests.
 *
 * @return none
 */
void scif_sas_domain_terminate_requests(
   SCIF_SAS_DOMAIN_T        * fw_domain,
   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
   SCIF_SAS_REQUEST_T       * fw_request,
   SCIF_SAS_TASK_REQUEST_T  * fw_requestor
)
{
   SCIF_LOG_TRACE((
      sci_base_object_get_logger(fw_domain),
      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
      "scif_sas_domain_terminate_requests(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
      fw_domain, fw_device, fw_request, fw_requestor
   ));

   if (fw_request != NULL)
   {
      fw_request->terminate_requestor = fw_requestor;
      fw_request->state_handlers->abort_handler(&fw_request->parent);
   }
   else
   {
      SCI_FAST_LIST_ELEMENT_T * element = fw_domain->request_list.list_head;
      SCIF_SAS_REQUEST_T      * request = NULL;

      // Cycle through the fast list of IO requests.  Terminate each
      // outstanding requests that matches the criteria supplied by the
      // caller.
      while (element != NULL)
      {
         request = (SCIF_SAS_REQUEST_T*) sci_fast_list_get_object(element);
         // The current element may be deleted from the list becasue of
         // IO completion so advance to the next element early
         element = sci_fast_list_get_next(element);

         // Ensure we pass the supplied criteria before terminating the
         // request.
         if (
               (fw_device == NULL)
            || (
                  (request->device == fw_device)
               && (fw_requestor != (SCIF_SAS_TASK_REQUEST_T*) request)
               )
            )
         {
            if (
                  (request->is_waiting_for_abort_task_set == FALSE) ||
                  (request->terminate_requestor == NULL)
               )
            {
               request->terminate_requestor = fw_requestor;
               request->state_handlers->abort_handler(&request->parent);
            }
         }
      }
   }
}
Пример #7
0
/**
 * @brief This method provides handling for failed stp TASK MANAGEMENT
 *           request.
 *
 * @param[in] fw_device This parameter specifies the target device the
 *            task management request towards to.
 * @param[in] fw_request This parameter specifies the failed task management
 *            request.
 * @param[in] completion_status This parameter sprecifies the completion
 *            status of the task management request's core status.
 *
 * @return None.
 */
void scif_sas_stp_task_request_abort_task_set_failure_handler(
   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
   SCIF_SAS_TASK_REQUEST_T  * fw_task
)
{
#if !defined(DISABLE_SATI_TASK_MANAGEMENT)
   SCIF_SAS_DOMAIN_T         * fw_domain = fw_device->domain;
   SCI_FAST_LIST_ELEMENT_T   * pending_request_element;
   SCIF_SAS_REQUEST_T        * pending_request = NULL;

   pending_request_element = fw_domain->request_list.list_head;

   // Cycle through the list of IO requests. search all the
   // outstanding IOs with "waiting for abort task set" flag,
   // completes them now.
   while (pending_request_element != NULL)
   {
      pending_request =
         (SCIF_SAS_REQUEST_T*) sci_fast_list_get_object(pending_request_element);

      // The current element may be deleted from the list becasue of
      // IO completion so advance to the next element early
      pending_request_element = sci_fast_list_get_next(pending_request_element);

      if ( pending_request->device == fw_device
           && pending_request->is_waiting_for_abort_task_set == TRUE )
      {
         //In case the pending_request is still in the middle of aborting.
         //abort it again to the core.
         SCI_STATUS abort_status;

         //Reset the flag now since we are process the read log ext command now.
         pending_request->is_waiting_for_abort_task_set = FALSE;

         abort_status = scic_controller_terminate_request(
                           fw_domain->controller->core_object,
                           fw_device->core_object,
                           pending_request->core_object
                        );

         if (abort_status == SCI_FAILURE_INVALID_STATE)
         {
            //the request must have not be in aborting state anymore, complete it now.
            scif_cb_io_request_complete(
               fw_domain->controller,
               fw_device,
               pending_request,
               SCI_IO_FAILURE_TERMINATED
            );
         }
         //otherwise, the abort succeeded. Since the waiting flag is cleared,
         //the pending request will be completed later.
      }
   }
#endif //#if !defined(DISABLE_SATI_TASK_MANAGEMENT)
}
Пример #8
0
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;
         }
      }
   }
}
Пример #9
0
/**
 * @brief This method find The next smp phy that is in the smp phy list and
 *           resides in the same wide port as this_smp_phy.
 *
 * @param[in] this_smp_phy The smp phy whose neighbor phy that is in the same
 *               same wide port is to be find.
 *
 * @return The next smp phy that is in the smp phy list and resides in the same
 *            wide port as this_smp_phy.
 */
SCIF_SAS_SMP_PHY_T * scif_sas_smp_phy_find_next_phy_in_wide_port(
   SCIF_SAS_SMP_PHY_T * this_smp_phy
)
{
   SCI_FAST_LIST_ELEMENT_T * next_phy_element = sci_fast_list_get_next(
      &(this_smp_phy->list_element) );

   SCIF_SAS_SMP_PHY_T * next_phy;

   while (next_phy_element != NULL)
   {
      next_phy = (SCIF_SAS_SMP_PHY_T *)sci_fast_list_get_object(next_phy_element);

      next_phy_element = sci_fast_list_get_next( &(next_phy->list_element));

      if (next_phy->attached_sas_address.high == this_smp_phy->attached_sas_address.high
          &&next_phy->attached_sas_address.low == this_smp_phy->attached_sas_address.low)
         return next_phy;
   }

   return NULL;
}
/**
* @brief This method implements the actions taken when entering the
*        READY NCQ ERROR substate.  This includes setting the state
*        handler methods.
*
* @param[in]  object This parameter specifies the base object for which
*             the state transition is occurring.  This is cast into a
*             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
*
* @return none
*/
static
void scif_sas_remote_device_ready_ncq_error_substate_enter(
   SCI_BASE_OBJECT_T *object
)
{
   SCIF_SAS_REMOTE_DEVICE_T         * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
   SCI_STATUS                         status = SCI_SUCCESS;
   SCI_TASK_REQUEST_HANDLE_T          handle;
   SCIF_SAS_CONTROLLER_T            * fw_controller = fw_device->domain->controller;
   SCIF_SAS_TASK_REQUEST_T          * fw_task_request;
   SCIF_SAS_REQUEST_T               * fw_request;
   void                             * internal_task_memory;
   SCIF_SAS_DOMAIN_T                * fw_domain = fw_device->domain;
   SCI_FAST_LIST_ELEMENT_T          * pending_request_element;
   SCIF_SAS_REQUEST_T               * pending_request = NULL;

   SET_STATE_HANDLER(
      fw_device,
      scif_sas_remote_device_ready_substate_handler_table,
      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
   );

   internal_task_memory = scif_sas_controller_allocate_internal_request(fw_controller);
   ASSERT(internal_task_memory != NULL);

   fw_task_request = (SCIF_SAS_TASK_REQUEST_T*)internal_task_memory;

   fw_request = &fw_task_request->parent;

   //construct the scif io request
   status = scif_sas_internal_task_request_construct(
      fw_controller,
      fw_device,
      SCI_CONTROLLER_INVALID_IO_TAG,
      (void *)fw_task_request,
      &handle,
      SCI_SAS_ABORT_TASK_SET
   );

   pending_request_element = fw_domain->request_list.list_head;

   // Cycle through the fast list of IO requests.  Mark each request
   //  pending to this remote device so that they are not completed
   //  to the operating system when the request is terminated, but
   //  rather when the abort task set completes.
   while (pending_request_element != NULL)
   {
      pending_request =
         (SCIF_SAS_REQUEST_T*) sci_fast_list_get_object(pending_request_element);

      // The current element may be deleted from the list because of
      // IO completion so advance to the next element early
      pending_request_element = sci_fast_list_get_next(pending_request_element);

      if (pending_request->device == fw_device)
      {
         pending_request->is_waiting_for_abort_task_set = TRUE;
      }
   }

   scif_controller_start_task(
      fw_controller,
      fw_device,
      fw_request,
      SCI_CONTROLLER_INVALID_IO_TAG
   );
}