/** * @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) )); }
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; }
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; }
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; }
/** * @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; }
/** * @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; }
/** * @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); } }
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 ); } } } }
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; }