*
* This method initializes the phy startup operations for controller start.
*/
-void scic_sds_controller_initialize_phy_startup(
+enum sci_status scic_sds_controller_initialize_phy_startup(
struct scic_sds_controller *this_controller)
{
this_controller->phy_startup_timer = isci_event_timer_create(
this_controller
);
- this_controller->next_phy_to_start = 0;
- this_controller->phy_startup_timer_pending = false;
+ if (this_controller->phy_startup_timer == NULL) {
+ return SCI_FAILURE_INSUFFICIENT_RESOURCES;
+ } else {
+ this_controller->next_phy_to_start = 0;
+ this_controller->phy_startup_timer_pending = false;
+ }
+
+ return SCI_SUCCESS;
}
/**
* to build the memory table.
*
*/
-static void scic_sds_controller_build_memory_descriptor_table(
+void scic_sds_controller_build_memory_descriptor_table(
struct scic_sds_controller *this_controller)
{
sci_base_mde_construct(
}
/**
+ * This method is called by the remote device to inform the controller
+ * that this remote device has started.
+ *
+ */
+
+void scic_sds_controller_remote_device_started(
+ struct scic_sds_controller *this_controller,
+ struct scic_sds_remote_device *the_device)
+{
+ u32 state;
+ scic_sds_controller_device_handler_t remote_device_started_handler;
+
+ state = this_controller->parent.state_machine.current_state_id;
+ remote_device_started_handler = scic_sds_controller_state_handler_table[state].remote_device_started_handler;
+
+ if (remote_device_started_handler != NULL)
+ remote_device_started_handler(this_controller, the_device);
+ else {
+ dev_warn(scic_to_dev(this_controller),
+ "%s: SCIC Controller 0x%p remote device started event "
+ "from device 0x%p in unexpected state %d\n",
+ __func__,
+ this_controller,
+ the_device,
+ sci_base_state_machine_get_state(
+ scic_sds_controller_get_base_state_machine(
+ this_controller)));
+ }
+}
+
+/**
+ * This is a helper method to determine if any remote devices on this
+ * controller are still in the stopping state.
+ *
+ */
+bool scic_sds_controller_has_remote_devices_stopping(
+ struct scic_sds_controller *this_controller)
+{
+ u32 index;
+
+ for (index = 0; index < this_controller->remote_node_entries; index++) {
+ if ((this_controller->device_table[index] != NULL) &&
+ (this_controller->device_table[index]->parent.state_machine.current_state_id
+ == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING))
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * This method is called by the remote device to inform the controller
+ * object that the remote device has stopped.
+ *
+ */
+
+void scic_sds_controller_remote_device_stopped(
+ struct scic_sds_controller *this_controller,
+ struct scic_sds_remote_device *the_device)
+{
+
+ u32 state;
+ scic_sds_controller_device_handler_t remote_device_stopped_handler;
+
+ state = this_controller->parent.state_machine.current_state_id;
+ remote_device_stopped_handler = scic_sds_controller_state_handler_table[state].remote_device_stopped_handler;
+
+ if (remote_device_stopped_handler != NULL)
+ remote_device_stopped_handler(this_controller, the_device);
+ else {
+ dev_warn(scic_to_dev(this_controller),
+ "%s: SCIC Controller 0x%p remote device stopped event "
+ "from device 0x%p in unexpected state %d\n",
+ __func__,
+ this_controller,
+ the_device,
+ sci_base_state_machine_get_state(
+ scic_sds_controller_get_base_state_machine(
+ this_controller)));
+ }
+}
+
+
+
+/**
* This method will write to the SCU PCP register the request value. The method
* is used to suspend/resume ports, devices, and phys.
* @this_controller:
* struct scic_sds_controller object.
* @remote_device: This is struct sci_base_remote_device which is cast to a
* struct scic_sds_remote_device object.
- * @io_request: This is the struct sci_base_request which is cast to a
- * SCIC_SDS_IO_REQUEST object.
*
* This method is called when the struct scic_sds_controller is in a stopping state
- * and the complete task handler is called. - This function is not yet
- * implemented enum sci_status SCI_FAILURE
- */
-
-/*
- * *****************************************************************************
- * * STOPPED STATE HANDLERS
- * ***************************************************************************** */
-
-/*
- * *****************************************************************************
- * * FAILED STATE HANDLERS
- * ***************************************************************************** */
+ * and the remote device has stopped.
+ **/
+void scic_sds_controller_stopping_state_device_stopped_handler(
+ struct scic_sds_controller *controller,
+ struct scic_sds_remote_device *remote_device
+)
+{
+ if (!scic_sds_controller_has_remote_devices_stopping(controller)) {
+ sci_base_state_machine_change_state(
+ &controller->parent.state_machine,
+ SCI_BASE_CONTROLLER_STATE_STOPPED
+ );
+ }
+}
const struct scic_sds_controller_state_handler scic_sds_controller_state_handler_table[] = {
[SCI_BASE_CONTROLLER_STATE_INITIAL] = {
.base.complete_io = scic_sds_controller_stopping_state_complete_io_handler,
.base.continue_io = scic_sds_controller_default_request_handler,
.terminate_request = scic_sds_controller_default_request_handler,
+ .remote_device_stopped_handler = scic_sds_controller_stopping_state_device_stopped_handler,
},
[SCI_BASE_CONTROLLER_STATE_STOPPED] = {
.base.reset = scic_sds_controller_general_reset_handler,
SCU_MAX_MDES
};
+
/**
*
*
typedef void (*scic_sds_controller_phy_handler_t)(struct scic_sds_controller *,
struct scic_sds_port *,
struct scic_sds_phy *);
+
+typedef void (*scic_sds_controller_device_handler_t)(struct scic_sds_controller *,
+ struct scic_sds_remote_device *);
+
+
/**
* struct scic_sds_controller_state_handler -
*
sci_base_controller_request_handler_t terminate_request;
scic_sds_controller_phy_handler_t link_up;
scic_sds_controller_phy_handler_t link_down;
+ scic_sds_controller_device_handler_t remote_device_started_handler;
+ scic_sds_controller_device_handler_t remote_device_stopped_handler;
};
extern const struct scic_sds_controller_state_handler
/*
* *****************************************************************************
+ * * CORE CONTROLLER REMOTE DEVICE MESSAGE PROCESSING
+ * ***************************************************************************** */
+
+bool scic_sds_controller_has_remote_devices_stopping(
+ struct scic_sds_controller *this_controller);
+
+void scic_sds_controller_remote_device_started(
+ struct scic_sds_controller *this_controller,
+ struct scic_sds_remote_device *the_device);
+
+void scic_sds_controller_remote_device_stopped(
+ struct scic_sds_controller *this_controller,
+ struct scic_sds_remote_device *the_device);
+
+
+/*
+ * *****************************************************************************
* * CORE CONTROLLER PRIVATE METHODS
* ***************************************************************************** */
void scic_sds_controller_reset_hardware(
struct scic_sds_controller *this_controller);
+enum sci_status scic_sds_controller_initialize_phy_startup(
+ struct scic_sds_controller *this_controller);
-void scic_sds_controller_initialize_phy_startup(
+void scic_sds_controller_build_memory_descriptor_table(
struct scic_sds_controller *this_controller);
#endif /* _SCIC_SDS_CONTROLLER_H_ */
* restart the starting substate machine since we dont know what has actually
* happening.
*/
-static void scic_sds_phy_sata_timeout(void *phy)
+void scic_sds_phy_sata_timeout(void *phy)
{
struct scic_sds_phy *sci_phy = phy;
this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN;
this_phy->link_layer_registers = NULL;
this_phy->max_negotiated_speed = SCI_SAS_NO_LINK_RATE;
+ this_phy->sata_timeout_timer = NULL;
/* Clear out the identification buffer data */
memset(&this_phy->phy_type, 0, sizeof(this_phy->phy_type));
*/
enum sci_status scic_sds_phy_initialize(
struct scic_sds_phy *sci_phy,
- struct scu_transport_layer_registers __iomem *transport_layer_registers,
- struct scu_link_layer_registers __iomem *link_layer_registers)
+ struct scu_transport_layer_registers __iomem *transport_layer_registers,
+ struct scu_link_layer_registers __iomem *link_layer_registers)
{
/* Create the SIGNATURE FIS Timeout timer for this phy */
sci_phy->sata_timeout_timer = isci_event_timer_create(
);
}
+/* ****************************************************************************
+ * SCIC SDS PHY general handlers
+ ************************************************************************** */
+static enum sci_status scic_sds_phy_starting_substate_general_stop_handler(
+ struct sci_base_phy *phy)
+{
+ struct scic_sds_phy *this_phy;
+ this_phy = (struct scic_sds_phy *)phy;
+
+ sci_base_state_machine_stop(&this_phy->starting_substate_machine);
+
+ sci_base_state_machine_change_state(&phy->state_machine,
+ SCI_BASE_PHY_STATE_STOPPED);
+
+ return SCI_SUCCESS;
+}
+
/*
* *****************************************************************************
* * SCIC SDS PHY EVENT_HANDLERS
return SCI_SUCCESS;
}
-/* --------------------------------------------------------------------------- */
-
const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_handler_table[] = {
[SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = {
.parent.start_handler = scic_sds_phy_default_start_handler,
- .parent.stop_handler = scic_sds_phy_default_stop_handler,
+ .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler,
.parent.reset_handler = scic_sds_phy_default_reset_handler,
.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
.frame_handler = scic_sds_phy_default_frame_handler,
},
[SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = {
.parent.start_handler = scic_sds_phy_default_start_handler,
- .parent.stop_handler = scic_sds_phy_default_stop_handler,
+ .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler,
.parent.reset_handler = scic_sds_phy_default_reset_handler,
.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
.frame_handler = scic_sds_phy_default_frame_handler,
},
[SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = {
.parent.start_handler = scic_sds_phy_default_start_handler,
- .parent.stop_handler = scic_sds_phy_default_stop_handler,
+ .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler,
.parent.reset_handler = scic_sds_phy_default_reset_handler,
.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
.frame_handler = scic_sds_phy_default_frame_handler,
},
[SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = {
.parent.start_handler = scic_sds_phy_default_start_handler,
- .parent.stop_handler = scic_sds_phy_default_stop_handler,
+ .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler,
.parent.reset_handler = scic_sds_phy_default_reset_handler,
.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
.frame_handler = scic_sds_phy_default_frame_handler,
},
[SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER] = {
.parent.start_handler = scic_sds_phy_default_start_handler,
- .parent.stop_handler = scic_sds_phy_default_stop_handler,
+ .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler,
.parent.reset_handler = scic_sds_phy_default_reset_handler,
.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
.frame_handler = scic_sds_phy_default_frame_handler,
},
[SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN] = {
.parent.start_handler = scic_sds_phy_default_start_handler,
- .parent.stop_handler = scic_sds_phy_default_stop_handler,
+ .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler,
.parent.reset_handler = scic_sds_phy_default_reset_handler,
.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
.frame_handler = scic_sds_phy_default_frame_handler,
},
[SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN] = {
.parent.start_handler = scic_sds_phy_default_start_handler,
- .parent.stop_handler = scic_sds_phy_default_stop_handler,
+ .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler,
.parent.reset_handler = scic_sds_phy_default_reset_handler,
.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
.frame_handler = scic_sds_phy_default_frame_handler,
},
[SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF] = {
.parent.start_handler = scic_sds_phy_default_start_handler,
- .parent.stop_handler = scic_sds_phy_default_stop_handler,
+ .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler,
.parent.reset_handler = scic_sds_phy_default_reset_handler,
.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
.frame_handler = scic_sds_phy_starting_substate_await_sig_fis_frame_handler,
},
[SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL] = {
.parent.start_handler = scic_sds_phy_default_start_handler,
- .parent.stop_handler = scic_sds_phy_default_stop_handler,
+ .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler,
.parent.reset_handler = scic_sds_phy_default_reset_handler,
.parent.destruct_handler = scic_sds_phy_default_destroy_handler,
.frame_handler = scic_sds_phy_default_frame_handler,
* start it. - The phy state machine is transitioned to the
* SCI_BASE_PHY_STATE_STARTING. enum sci_status SCI_SUCCESS
*/
-static enum sci_status scic_sds_phy_stopped_state_start_handler(
- struct sci_base_phy *phy)
+static enum sci_status scic_sds_phy_stopped_state_start_handler(struct sci_base_phy *phy)
{
struct scic_sds_phy *this_phy;
this_phy = (struct scic_sds_phy *)phy;
- sci_base_state_machine_change_state(
- scic_sds_phy_get_base_state_machine(this_phy),
- SCI_BASE_PHY_STATE_STARTING
- );
+ /* Create the SIGNATURE FIS Timeout timer for this phy */
+ this_phy->sata_timeout_timer = isci_event_timer_create(
+ scic_sds_phy_get_controller(this_phy),
+ scic_sds_phy_sata_timeout, this_phy);
+
+ if (this_phy->sata_timeout_timer != NULL) {
+ sci_base_state_machine_change_state(
+ scic_sds_phy_get_base_state_machine(this_phy),
+ SCI_BASE_PHY_STATE_STARTING);
+ }
return SCI_SUCCESS;
}
this_phy = (struct scic_sds_phy *)phy;
- /* / @todo what do we actually need to do here? */
+ /* @todo what do we actually need to do here? */
return SCI_SUCCESS;
}
this_phy = (struct scic_sds_phy *)object;
- scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_STOPPED);
+ scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_INITIAL);
}
/**
* handlers for the phy object base state machine initial state. - The SCU
* hardware is requested to stop the protocol engine. none
*/
-static void scic_sds_phy_stopped_state_enter(
- struct sci_base_object *object)
+static void scic_sds_phy_stopped_state_enter(struct sci_base_object *object)
{
- struct scic_sds_phy *this_phy;
+ struct scic_sds_phy *sci_phy;
- this_phy = (struct scic_sds_phy *)object;
+ sci_phy = (struct scic_sds_phy *)object;
/* / @todo We need to get to the controller to place this PE in a reset state */
- scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_STOPPED);
+ scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_STOPPED);
- scu_link_layer_stop_protocol_engine(this_phy);
+ if (sci_phy->sata_timeout_timer != NULL) {
+ isci_event_timer_destroy(scic_sds_phy_get_controller(sci_phy),
+ sci_phy->sata_timeout_timer);
+
+ sci_phy->sata_timeout_timer = NULL;
+ }
+
+ scu_link_layer_stop_protocol_engine(sci_phy);
}
/**