Commit ab2e8f7d authored by Dan Williams's avatar Dan Williams

isci: merge remote_device substates into a single state machine

A substate is just a state, so uplevel the smp and stp device substates.
Three tricks at work here:

1/ scic_sds_remote_device_ready_state_enter: needs to know the the device type
   so it can immediately transition to a stp or smp ready substate.

2/ scic_sds_remote_device_ready_state_exit: needs to know the device type. In
   the ssp case the device is no longer ready, in the stp, and smp case we have
   simply exited to a ready "substate".

3/ scic_sds_remote_device_resume_complete_handler: The one location
   where we directly check the current state against
   SCI_BASE_REMOTE_DEVICE_STATE_READY needed to comprehend the possible ready
   substates.
Reported-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent be2f41c6
...@@ -7,8 +7,6 @@ obj-$(CONFIG_SCSI_ISCI) += isci.o ...@@ -7,8 +7,6 @@ obj-$(CONFIG_SCSI_ISCI) += isci.o
isci-objs := init.o phy.o request.o sata.o \ isci-objs := init.o phy.o request.o sata.o \
remote_device.o port.o timers.o \ remote_device.o port.o timers.o \
host.o task.o probe_roms.o \ host.o task.o probe_roms.o \
stp_remote_device.o \
smp_remote_device.o \
remote_node_context.o \ remote_node_context.o \
remote_node_table.o \ remote_node_table.o \
core/scic_sds_controller.o \ core/scic_sds_controller.o \
......
...@@ -53,6 +53,7 @@ ...@@ -53,6 +53,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "intel_sas.h" #include "intel_sas.h"
#include "intel_ata.h"
#include "isci.h" #include "isci.h"
#include "port.h" #include "port.h"
#include "remote_device.h" #include "remote_device.h"
...@@ -71,6 +72,65 @@ ...@@ -71,6 +72,65 @@
#include "scu_event_codes.h" #include "scu_event_codes.h"
#include "task.h" #include "task.h"
/**
* isci_remote_device_change_state() - This function gets the status of the
* remote_device object.
* @isci_device: This parameter points to the isci_remote_device object
*
* status of the object as a isci_status enum.
*/
void isci_remote_device_change_state(
struct isci_remote_device *isci_device,
enum isci_status status)
{
unsigned long flags;
spin_lock_irqsave(&isci_device->state_lock, flags);
isci_device->status = status;
spin_unlock_irqrestore(&isci_device->state_lock, flags);
}
/**
* isci_remote_device_not_ready() - This function is called by the scic when
* the remote device is not ready. We mark the isci device as ready (not
* "ready_for_io") and signal the waiting proccess.
* @isci_host: This parameter specifies the isci host object.
* @isci_device: This parameter specifies the remote device
*
*/
static void isci_remote_device_not_ready(struct isci_host *ihost,
struct isci_remote_device *idev, u32 reason)
{
dev_dbg(&ihost->pdev->dev,
"%s: isci_device = %p\n", __func__, idev);
if (reason == SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED)
isci_remote_device_change_state(idev, isci_stopping);
else
/* device ready is actually a "not ready for io" state. */
isci_remote_device_change_state(idev, isci_ready);
}
/**
* isci_remote_device_ready() - This function is called by the scic when the
* remote device is ready. We mark the isci device as ready and signal the
* waiting proccess.
* @ihost: our valid isci_host
* @idev: remote device
*
*/
static void isci_remote_device_ready(struct isci_host *ihost, struct isci_remote_device *idev)
{
dev_dbg(&ihost->pdev->dev,
"%s: idev = %p\n", __func__, idev);
isci_remote_device_change_state(idev, isci_ready_for_io);
if (test_and_clear_bit(IDEV_START_PENDING, &idev->flags))
wake_up(&ihost->eventq);
}
enum sci_status scic_remote_device_stop( enum sci_status scic_remote_device_stop(
struct scic_sds_remote_device *sci_dev, struct scic_sds_remote_device *sci_dev,
u32 timeout) u32 timeout)
...@@ -228,49 +288,43 @@ void scic_sds_remote_device_post_request( ...@@ -228,49 +288,43 @@ void scic_sds_remote_device_post_request(
); );
} }
/** /* called once the remote node context is ready to be freed.
*
* @user_parameter: This is cast to a remote device object.
*
* This method is called once the remote node context is ready to be freed.
* The remote device can now report that its stop operation is complete. none * The remote device can now report that its stop operation is complete. none
*/ */
static void scic_sds_cb_remote_device_rnc_destruct_complete( static void scic_sds_cb_remote_device_rnc_destruct_complete(void *_dev)
void *user_parameter)
{ {
struct scic_sds_remote_device *sci_dev; struct scic_sds_remote_device *sci_dev = _dev;
sci_dev = (struct scic_sds_remote_device *)user_parameter;
BUG_ON(sci_dev->started_request_count != 0); BUG_ON(sci_dev->started_request_count != 0);
sci_base_state_machine_change_state(&sci_dev->state_machine, sci_base_state_machine_change_state(&sci_dev->state_machine,
SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); SCI_BASE_REMOTE_DEVICE_STATE_STOPPED);
} }
/** /* called once the remote node context has transisitioned to a
*
* @user_parameter: This is cast to a remote device object.
*
* This method is called once the remote node context has transisitioned to a
* ready state. This is the indication that the remote device object can also * ready state. This is the indication that the remote device object can also
* transition to ready. none * transition to ready.
*/ */
static void scic_sds_remote_device_resume_complete_handler( static void scic_sds_remote_device_resume_complete_handler(void *_dev)
void *user_parameter) {
{ struct scic_sds_remote_device *sci_dev = _dev;
struct scic_sds_remote_device *sci_dev; enum scic_sds_remote_device_states state;
sci_dev = (struct scic_sds_remote_device *)user_parameter; state = sci_dev->state_machine.current_state_id;
switch (state) {
if ( case SCI_BASE_REMOTE_DEVICE_STATE_READY:
sci_base_state_machine_get_state(&sci_dev->state_machine) case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE:
!= SCI_BASE_REMOTE_DEVICE_STATE_READY case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD:
) { case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ:
sci_base_state_machine_change_state( case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR:
&sci_dev->state_machine, case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET:
SCI_BASE_REMOTE_DEVICE_STATE_READY case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE:
); case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD:
break;
default:
/* go 'ready' if we are not already in a ready state */
sci_base_state_machine_change_state(&sci_dev->state_machine,
SCI_BASE_REMOTE_DEVICE_STATE_READY);
break;
} }
} }
...@@ -284,7 +338,7 @@ static void scic_sds_remote_device_resume_complete_handler( ...@@ -284,7 +338,7 @@ static void scic_sds_remote_device_resume_complete_handler(
* This method will perform the STP request start processing common to IO * This method will perform the STP request start processing common to IO
* requests and task requests of all types. none * requests and task requests of all types. none
*/ */
void scic_sds_remote_device_start_request( static void scic_sds_remote_device_start_request(
struct scic_sds_remote_device *sci_dev, struct scic_sds_remote_device *sci_dev,
struct scic_sds_request *sci_req, struct scic_sds_request *sci_req,
enum sci_status status) enum sci_status status)
...@@ -308,7 +362,7 @@ void scic_sds_remote_device_start_request( ...@@ -308,7 +362,7 @@ void scic_sds_remote_device_start_request(
* serves as a callback when RNC gets resumed during a task management * serves as a callback when RNC gets resumed during a task management
* sequence. none * sequence. none
*/ */
void scic_sds_remote_device_continue_request(void *dev) static void scic_sds_remote_device_continue_request(void *dev)
{ {
struct scic_sds_remote_device *sci_dev = dev; struct scic_sds_remote_device *sci_dev = dev;
...@@ -368,7 +422,7 @@ default_device_handler(struct scic_sds_remote_device *sci_dev, ...@@ -368,7 +422,7 @@ default_device_handler(struct scic_sds_remote_device *sci_dev,
return SCI_FAILURE_INVALID_STATE; return SCI_FAILURE_INVALID_STATE;
} }
enum sci_status scic_sds_remote_device_default_start_handler( static enum sci_status scic_sds_remote_device_default_start_handler(
struct scic_sds_remote_device *sci_dev) struct scic_sds_remote_device *sci_dev)
{ {
return default_device_handler(sci_dev, __func__); return default_device_handler(sci_dev, __func__);
...@@ -380,37 +434,37 @@ static enum sci_status scic_sds_remote_device_default_stop_handler( ...@@ -380,37 +434,37 @@ static enum sci_status scic_sds_remote_device_default_stop_handler(
return default_device_handler(sci_dev, __func__); return default_device_handler(sci_dev, __func__);
} }
enum sci_status scic_sds_remote_device_default_fail_handler( static enum sci_status scic_sds_remote_device_default_fail_handler(
struct scic_sds_remote_device *sci_dev) struct scic_sds_remote_device *sci_dev)
{ {
return default_device_handler(sci_dev, __func__); return default_device_handler(sci_dev, __func__);
} }
enum sci_status scic_sds_remote_device_default_destruct_handler( static enum sci_status scic_sds_remote_device_default_destruct_handler(
struct scic_sds_remote_device *sci_dev) struct scic_sds_remote_device *sci_dev)
{ {
return default_device_handler(sci_dev, __func__); return default_device_handler(sci_dev, __func__);
} }
enum sci_status scic_sds_remote_device_default_reset_handler( static enum sci_status scic_sds_remote_device_default_reset_handler(
struct scic_sds_remote_device *sci_dev) struct scic_sds_remote_device *sci_dev)
{ {
return default_device_handler(sci_dev, __func__); return default_device_handler(sci_dev, __func__);
} }
enum sci_status scic_sds_remote_device_default_reset_complete_handler( static enum sci_status scic_sds_remote_device_default_reset_complete_handler(
struct scic_sds_remote_device *sci_dev) struct scic_sds_remote_device *sci_dev)
{ {
return default_device_handler(sci_dev, __func__); return default_device_handler(sci_dev, __func__);
} }
enum sci_status scic_sds_remote_device_default_suspend_handler( static enum sci_status scic_sds_remote_device_default_suspend_handler(
struct scic_sds_remote_device *sci_dev, u32 suspend_type) struct scic_sds_remote_device *sci_dev, u32 suspend_type)
{ {
return default_device_handler(sci_dev, __func__); return default_device_handler(sci_dev, __func__);
} }
enum sci_status scic_sds_remote_device_default_resume_handler( static enum sci_status scic_sds_remote_device_default_resume_handler(
struct scic_sds_remote_device *sci_dev) struct scic_sds_remote_device *sci_dev)
{ {
return default_device_handler(sci_dev, __func__); return default_device_handler(sci_dev, __func__);
...@@ -505,7 +559,7 @@ static enum sci_status scic_sds_remote_device_default_event_handler( ...@@ -505,7 +559,7 @@ static enum sci_status scic_sds_remote_device_default_event_handler(
* releases the frame and returns a failure. enum sci_status * releases the frame and returns a failure. enum sci_status
* SCI_FAILURE_INVALID_STATE * SCI_FAILURE_INVALID_STATE
*/ */
enum sci_status scic_sds_remote_device_default_frame_handler( static enum sci_status scic_sds_remote_device_default_frame_handler(
struct scic_sds_remote_device *sci_dev, struct scic_sds_remote_device *sci_dev,
u32 frame_index) u32 frame_index)
{ {
...@@ -525,21 +579,21 @@ enum sci_status scic_sds_remote_device_default_frame_handler( ...@@ -525,21 +579,21 @@ enum sci_status scic_sds_remote_device_default_frame_handler(
return SCI_FAILURE_INVALID_STATE; return SCI_FAILURE_INVALID_STATE;
} }
enum sci_status scic_sds_remote_device_default_start_request_handler( static enum sci_status scic_sds_remote_device_default_start_request_handler(
struct scic_sds_remote_device *sci_dev, struct scic_sds_remote_device *sci_dev,
struct scic_sds_request *request) struct scic_sds_request *request)
{ {
return default_device_handler(sci_dev, __func__); return default_device_handler(sci_dev, __func__);
} }
enum sci_status scic_sds_remote_device_default_complete_request_handler( static enum sci_status scic_sds_remote_device_default_complete_request_handler(
struct scic_sds_remote_device *sci_dev, struct scic_sds_remote_device *sci_dev,
struct scic_sds_request *request) struct scic_sds_request *request)
{ {
return default_device_handler(sci_dev, __func__); return default_device_handler(sci_dev, __func__);
} }
enum sci_status scic_sds_remote_device_default_continue_request_handler( static enum sci_status scic_sds_remote_device_default_continue_request_handler(
struct scic_sds_remote_device *sci_dev, struct scic_sds_remote_device *sci_dev,
struct scic_sds_request *request) struct scic_sds_request *request)
{ {
...@@ -558,7 +612,7 @@ enum sci_status scic_sds_remote_device_default_continue_request_handler( ...@@ -558,7 +612,7 @@ enum sci_status scic_sds_remote_device_default_continue_request_handler(
* This method decodes the tag for the io request object and routes the * This method decodes the tag for the io request object and routes the
* unsolicited frame to that object. enum sci_status SCI_FAILURE_INVALID_STATE * unsolicited frame to that object. enum sci_status SCI_FAILURE_INVALID_STATE
*/ */
enum sci_status scic_sds_remote_device_general_frame_handler( static enum sci_status scic_sds_remote_device_general_frame_handler(
struct scic_sds_remote_device *sci_dev, struct scic_sds_remote_device *sci_dev,
u32 frame_index) u32 frame_index)
{ {
...@@ -602,7 +656,7 @@ enum sci_status scic_sds_remote_device_general_frame_handler( ...@@ -602,7 +656,7 @@ enum sci_status scic_sds_remote_device_general_frame_handler(
* This is a common method for handling events reported to the remote device * This is a common method for handling events reported to the remote device
* from the controller object. enum sci_status * from the controller object. enum sci_status
*/ */
enum sci_status scic_sds_remote_device_general_event_handler( static enum sci_status scic_sds_remote_device_general_event_handler(
struct scic_sds_remote_device *sci_dev, struct scic_sds_remote_device *sci_dev,
u32 event_code) u32 event_code)
{ {
...@@ -705,7 +759,7 @@ static enum sci_status scic_sds_remote_device_starting_state_stop_handler( ...@@ -705,7 +759,7 @@ static enum sci_status scic_sds_remote_device_starting_state_stop_handler(
return SCI_SUCCESS; return SCI_SUCCESS;
} }
enum sci_status scic_sds_remote_device_ready_state_stop_handler( static enum sci_status scic_sds_remote_device_ready_state_stop_handler(
struct scic_sds_remote_device *sci_dev) struct scic_sds_remote_device *sci_dev)
{ {
enum sci_status status = SCI_SUCCESS; enum sci_status status = SCI_SUCCESS;
...@@ -731,7 +785,7 @@ enum sci_status scic_sds_remote_device_ready_state_stop_handler( ...@@ -731,7 +785,7 @@ enum sci_status scic_sds_remote_device_ready_state_stop_handler(
* *
* This is the ready state device reset handler enum sci_status * This is the ready state device reset handler enum sci_status
*/ */
enum sci_status scic_sds_remote_device_ready_state_reset_handler( static enum sci_status scic_sds_remote_device_ready_state_reset_handler(
struct scic_sds_remote_device *sci_dev) struct scic_sds_remote_device *sci_dev)
{ {
/* Request the parent state machine to transition to the stopping state */ /* Request the parent state machine to transition to the stopping state */
...@@ -893,34 +947,15 @@ static enum sci_status scic_sds_remote_device_stopping_state_complete_request_ha ...@@ -893,34 +947,15 @@ static enum sci_status scic_sds_remote_device_stopping_state_complete_request_ha
return SCI_SUCCESS; return SCI_SUCCESS;
} }
/**
*
* @device: The struct scic_sds_remote_device which is to be cast into a
* struct scic_sds_remote_device object.
*
* This method will complete the reset operation when the device is in the
* resetting state. enum sci_status
*/
static enum sci_status scic_sds_remote_device_resetting_state_reset_complete_handler( static enum sci_status scic_sds_remote_device_resetting_state_reset_complete_handler(
struct scic_sds_remote_device *sci_dev) struct scic_sds_remote_device *sci_dev)
{ {
sci_base_state_machine_change_state(&sci_dev->state_machine,
sci_base_state_machine_change_state( SCI_BASE_REMOTE_DEVICE_STATE_READY);
&sci_dev->state_machine,
SCI_BASE_REMOTE_DEVICE_STATE_READY
);
return SCI_SUCCESS; return SCI_SUCCESS;
} }
/**
*
* @device: The struct scic_sds_remote_device which is to be cast into a
* struct scic_sds_remote_device object.
*
* This method will stop the remote device while in the resetting state.
* enum sci_status
*/
static enum sci_status scic_sds_remote_device_resetting_state_stop_handler( static enum sci_status scic_sds_remote_device_resetting_state_stop_handler(
struct scic_sds_remote_device *sci_dev) struct scic_sds_remote_device *sci_dev)
{ {
...@@ -932,12 +967,11 @@ static enum sci_status scic_sds_remote_device_resetting_state_stop_handler( ...@@ -932,12 +967,11 @@ static enum sci_status scic_sds_remote_device_resetting_state_stop_handler(
return SCI_SUCCESS; return SCI_SUCCESS;
} }
/* /* complete requests for this device while it is in the
* This method completes requests for this struct scic_sds_remote_device while it is * SCI_BASE_REMOTE_DEVICE_STATE_RESETTING state. This method calls the complete
* in the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING state. This method calls the * method for the request object and if that is successful the port object is
* complete method for the request object and if that is successful the port * called to complete the task request. Then the device object itself completes
* object is called to complete the task request. Then the device object itself * the task request. enum sci_status
* completes the task request. enum sci_status
*/ */
static enum sci_status scic_sds_remote_device_resetting_state_complete_request_handler( static enum sci_status scic_sds_remote_device_resetting_state_complete_request_handler(
struct scic_sds_remote_device *sci_dev, struct scic_sds_remote_device *sci_dev,
...@@ -960,173 +994,665 @@ static enum sci_status scic_sds_remote_device_resetting_state_complete_request_h ...@@ -960,173 +994,665 @@ static enum sci_status scic_sds_remote_device_resetting_state_complete_request_h
return status; return status;
} }
static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { static enum sci_status scic_sds_stp_remote_device_complete_request(struct scic_sds_remote_device *sci_dev,
[SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { struct scic_sds_request *sci_req)
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_default_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_default_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_remote_device_default_start_request_handler,
.complete_io_handler = scic_sds_remote_device_default_complete_request_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_remote_device_default_start_request_handler,
.complete_task_handler = scic_sds_remote_device_default_complete_request_handler,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_default_event_handler,
.frame_handler = scic_sds_remote_device_default_frame_handler
},
[SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = {
.start_handler = scic_sds_remote_device_stopped_state_start_handler,
.stop_handler = scic_sds_remote_device_stopped_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_stopped_state_destruct_handler,
.reset_handler = scic_sds_remote_device_default_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_remote_device_default_start_request_handler,
.complete_io_handler = scic_sds_remote_device_default_complete_request_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_remote_device_default_start_request_handler,
.complete_task_handler = scic_sds_remote_device_default_complete_request_handler,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_default_event_handler,
.frame_handler = scic_sds_remote_device_default_frame_handler
},
[SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_starting_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_default_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_remote_device_default_start_request_handler,
.complete_io_handler = scic_sds_remote_device_default_complete_request_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_remote_device_default_start_request_handler,
.complete_task_handler = scic_sds_remote_device_default_complete_request_handler,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_general_event_handler,
.frame_handler = scic_sds_remote_device_default_frame_handler
},
[SCI_BASE_REMOTE_DEVICE_STATE_READY] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_ready_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_ready_state_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_remote_device_ready_state_start_io_handler,
.complete_io_handler = scic_sds_remote_device_ready_state_complete_request_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_remote_device_ready_state_start_task_handler,
.complete_task_handler = scic_sds_remote_device_ready_state_complete_request_handler,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_general_event_handler,
.frame_handler = scic_sds_remote_device_general_frame_handler,
},
[SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_stopping_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_default_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_remote_device_default_start_request_handler,
.complete_io_handler = scic_sds_remote_device_stopping_state_complete_request_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_remote_device_default_start_request_handler,
.complete_task_handler = scic_sds_remote_device_stopping_state_complete_request_handler,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_general_event_handler,
.frame_handler = scic_sds_remote_device_general_frame_handler
},
[SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_default_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_default_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_remote_device_default_start_request_handler,
.complete_io_handler = scic_sds_remote_device_default_complete_request_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_remote_device_default_start_request_handler,
.complete_task_handler = scic_sds_remote_device_default_complete_request_handler,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_default_event_handler,
.frame_handler = scic_sds_remote_device_general_frame_handler
},
[SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_resetting_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_default_reset_handler,
.reset_complete_handler = scic_sds_remote_device_resetting_state_reset_complete_handler,
.start_io_handler = scic_sds_remote_device_default_start_request_handler,
.complete_io_handler = scic_sds_remote_device_resetting_state_complete_request_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_remote_device_default_start_request_handler,
.complete_task_handler = scic_sds_remote_device_resetting_state_complete_request_handler,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_default_event_handler,
.frame_handler = scic_sds_remote_device_general_frame_handler
},
[SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_default_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_default_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_remote_device_default_start_request_handler,
.complete_io_handler = scic_sds_remote_device_default_complete_request_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_remote_device_default_start_request_handler,
.complete_task_handler = scic_sds_remote_device_default_complete_request_handler,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_default_event_handler,
.frame_handler = scic_sds_remote_device_default_frame_handler
}
};
static void scic_sds_remote_device_initial_state_enter(void *object)
{ {
struct scic_sds_remote_device *sci_dev = object; enum sci_status status;
SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, status = scic_sds_io_request_complete(sci_req);
SCI_BASE_REMOTE_DEVICE_STATE_INITIAL); if (status != SCI_SUCCESS)
goto out;
/* Initial state is a transitional state to the stopped state */ status = scic_sds_port_complete_io(sci_dev->owning_port, sci_dev, sci_req);
sci_base_state_machine_change_state(&sci_dev->state_machine, if (status != SCI_SUCCESS)
SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); goto out;
scic_sds_remote_device_decrement_request_count(sci_dev);
if (sci_req->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) {
/* This request causes hardware error, device needs to be Lun Reset.
* So here we force the state machine to IDLE state so the rest IOs
* can reach RNC state handler, these IOs will be completed by RNC with
* status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE".
*/
sci_base_state_machine_change_state(&sci_dev->state_machine,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET);
} else if (scic_sds_remote_device_get_request_count(sci_dev) == 0)
sci_base_state_machine_change_state(&sci_dev->state_machine,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE);
out:
if (status != SCI_SUCCESS)
dev_err(scirdev_to_dev(sci_dev),
"%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x "
"could not complete\n", __func__, sci_dev->owning_port,
sci_dev, sci_req, status);
return status;
} }
/** /* scic_sds_stp_remote_device_ready_substate_start_request_handler - start stp
* isci_remote_device_change_state() - This function gets the status of the * @device: The target device a task management request towards to.
* remote_device object. * @request: The task request.
* @isci_device: This parameter points to the isci_remote_device object
* *
* status of the object as a isci_status enum. * This is the READY NCQ substate handler to start task management request. In
* this routine, we suspend and resume the RNC. enum sci_status Always return
* SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS status to let
* controller_start_task_handler know that the controller can't post TC for
* task request yet, instead, when RNC gets resumed, a controller_continue_task
* callback will be called.
*/ */
void isci_remote_device_change_state( static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_handler(
struct isci_remote_device *isci_device, struct scic_sds_remote_device *device,
enum isci_status status) struct scic_sds_request *request)
{
enum sci_status status;
/* Will the port allow the io request to start? */
status = device->owning_port->state_handlers->start_io_handler(
device->owning_port, device, request);
if (status != SCI_SUCCESS)
return status;
status = scic_sds_remote_node_context_start_task(&device->rnc, request);
if (status != SCI_SUCCESS)
goto out;
status = request->state_handlers->start_handler(request);
if (status != SCI_SUCCESS)
goto out;
/*
* Note: If the remote device state is not IDLE this will replace
* the request that probably resulted in the task management request.
*/
device->working_request = request;
sci_base_state_machine_change_state(&device->state_machine,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD);
/*
* The remote node context must cleanup the TCi to NCQ mapping table.
* The only way to do this correctly is to either write to the TLCR
* register or to invalidate and repost the RNC. In either case the
* remote node context state machine will take the correct action when
* the remote node context is suspended and later resumed.
*/
scic_sds_remote_node_context_suspend(&device->rnc,
SCI_SOFTWARE_SUSPENSION, NULL, NULL);
scic_sds_remote_node_context_resume(&device->rnc,
scic_sds_remote_device_continue_request,
device);
out:
scic_sds_remote_device_start_request(device, request, status);
/*
* We need to let the controller start request handler know that it can't
* post TC yet. We will provide a callback function to post TC when RNC gets
* resumed.
*/
return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS;
}
/* handle the start io operation for a sata device that is in the command idle
* state. - Evalute the type of IO request to be started - If its an NCQ
* request change to NCQ substate - If its any other command change to the CMD
* substate
*
* If this is a softreset we may want to have a different substate.
*/
static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_start_io_handler(
struct scic_sds_remote_device *sci_dev,
struct scic_sds_request *request)
{
enum sci_status status;
struct isci_request *isci_request = request->ireq;
enum scic_sds_remote_device_states new_state;
/* Will the port allow the io request to start? */
status = sci_dev->owning_port->state_handlers->start_io_handler(
sci_dev->owning_port, sci_dev, request);
if (status != SCI_SUCCESS)
return status;
status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request);
if (status != SCI_SUCCESS)
goto out;
status = request->state_handlers->start_handler(request);
if (status != SCI_SUCCESS)
goto out;
if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA)
new_state = SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ;
else {
sci_dev->working_request = request;
new_state = SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD;
}
sci_base_state_machine_change_state(&sci_dev->state_machine, new_state);
out:
scic_sds_remote_device_start_request(sci_dev, request, status);
return status;
}
static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_handler(
struct scic_sds_remote_device *sci_dev,
u32 event_code)
{
enum sci_status status;
status = scic_sds_remote_device_general_event_handler(sci_dev, event_code);
if (status != SCI_SUCCESS)
return status;
/* We pick up suspension events to handle specifically to this state. We
* resume the RNC right away. enum sci_status
*/
if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX ||
scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX)
status = scic_sds_remote_node_context_resume(&sci_dev->rnc, NULL, NULL);
return status;
}
static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler(
struct scic_sds_remote_device *sci_dev,
struct scic_sds_request *request)
{
enum sci_status status;
struct isci_request *isci_request = request->ireq;
scic_sds_port_io_request_handler_t start_io;
if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) {
start_io = sci_dev->owning_port->state_handlers->start_io_handler;
status = start_io(sci_dev->owning_port, sci_dev, request);
if (status != SCI_SUCCESS)
return status;
status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request);
if (status != SCI_SUCCESS)
return status;
status = request->state_handlers->start_handler(request);
scic_sds_remote_device_start_request(sci_dev, request, status);
} else
status = SCI_FAILURE_INVALID_STATE;
return status;
}
static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handler(struct scic_sds_remote_device *sci_dev,
u32 frame_index)
{
enum sci_status status;
struct sata_fis_header *frame_header;
struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller;
status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control,
frame_index,
(void **)&frame_header);
if (status != SCI_SUCCESS)
return status;
if (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS &&
(frame_header->status & ATA_STATUS_REG_ERROR_BIT)) {
sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
/* TODO Check sactive and complete associated IO if any. */
sci_base_state_machine_change_state(&sci_dev->state_machine,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR);
} else if (frame_header->fis_type == SATA_FIS_TYPE_REGD2H &&
(frame_header->status & ATA_STATUS_REG_ERROR_BIT)) {
/*
* Some devices return D2H FIS when an NCQ error is detected.
* Treat this like an SDB error FIS ready reason.
*/
sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
sci_base_state_machine_change_state(&sci_dev->state_machine,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR);
} else
status = SCI_FAILURE;
scic_sds_controller_release_frame(scic, frame_index);
return status;
}
static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler(
struct scic_sds_remote_device *device,
struct scic_sds_request *request)
{
/* device is already handling a command it can not accept new commands
* until this one is complete.
*/
return SCI_FAILURE_INVALID_STATE;
}
static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler(
struct scic_sds_remote_device *sci_dev,
u32 suspend_type)
{
enum sci_status status;
status = scic_sds_remote_node_context_suspend(&sci_dev->rnc,
suspend_type, NULL, NULL);
return status;
}
static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handler(
struct scic_sds_remote_device *sci_dev,
u32 frame_index)
{
/* The device doe not process any UF received from the hardware while
* in this state. All unsolicited frames are forwarded to the io
* request object.
*/
return scic_sds_io_request_frame_handler(sci_dev->working_request,
frame_index);
}
static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler(
struct scic_sds_remote_device *device,
struct scic_sds_request *request)
{
return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
}
static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler(
struct scic_sds_remote_device *device,
struct scic_sds_request *request)
{
struct scic_sds_request *sci_req = request;
enum sci_status status;
status = scic_sds_io_request_complete(sci_req);
if (status != SCI_SUCCESS)
goto out;
status = scic_sds_port_complete_io(device->owning_port, device, sci_req);
if (status != SCI_SUCCESS)
goto out;
scic_sds_remote_device_decrement_request_count(device);
out:
if (status != SCI_SUCCESS)
dev_err(scirdev_to_dev(device),
"%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x "
"could not complete\n",
__func__, device->owning_port, device, sci_req, status);
return status;
}
static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *_dev)
{
struct scic_sds_remote_device *sci_dev = _dev;
struct isci_remote_device *idev = sci_dev_to_idev(sci_dev);
struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller;
/* For NCQ operation we do not issue a isci_remote_device_not_ready().
* As a result, avoid sending the ready notification.
*/
if (sci_dev->state_machine.previous_state_id != SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ)
isci_remote_device_ready(scic->ihost, idev);
}
static enum sci_status scic_sds_smp_remote_device_ready_idle_substate_start_io_handler(
struct scic_sds_remote_device *sci_dev,
struct scic_sds_request *sci_req)
{
enum sci_status status;
/* Will the port allow the io request to start? */
status = sci_dev->owning_port->state_handlers->start_io_handler(
sci_dev->owning_port, sci_dev, sci_req);
if (status != SCI_SUCCESS)
return status;
status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, sci_req);
if (status != SCI_SUCCESS)
return status;
status = scic_sds_request_start(sci_req);
if (status != SCI_SUCCESS)
return status;
sci_dev->working_request = sci_req;
sci_base_state_machine_change_state(&sci_dev->state_machine,
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD);
scic_sds_remote_device_start_request(sci_dev, sci_req, status);
return status;
}
static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler(
struct scic_sds_remote_device *device,
struct scic_sds_request *request)
{
/* device is already handling a command it can not accept new commands
* until this one is complete.
*/
return SCI_FAILURE_INVALID_STATE;
}
static enum sci_status
scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler(struct scic_sds_remote_device *sci_dev,
struct scic_sds_request *sci_req)
{
enum sci_status status;
status = scic_sds_io_request_complete(sci_req);
if (status != SCI_SUCCESS)
return status;
status = scic_sds_port_complete_io(sci_dev->owning_port, sci_dev, sci_req);
if (status != SCI_SUCCESS) {
dev_err(scirdev_to_dev(sci_dev),
"%s: SCIC SDS Remote Device 0x%p io request "
"0x%p could not be completd on the port 0x%p "
"failed with status %d.\n", __func__, sci_dev, sci_req,
sci_dev->owning_port, status);
return status;
}
scic_sds_remote_device_decrement_request_count(sci_dev);
sci_base_state_machine_change_state(&sci_dev->state_machine,
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE);
return status;
}
static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handler(
struct scic_sds_remote_device *sci_dev,
u32 frame_index)
{
enum sci_status status;
/* The device does not process any UF received from the hardware while
* in this state. All unsolicited frames are forwarded to the io request
* object.
*/
status = scic_sds_io_request_frame_handler(
sci_dev->working_request,
frame_index
);
return status;
}
static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = {
[SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_default_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_default_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_remote_device_default_start_request_handler,
.complete_io_handler = scic_sds_remote_device_default_complete_request_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_remote_device_default_start_request_handler,
.complete_task_handler = scic_sds_remote_device_default_complete_request_handler,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_default_event_handler,
.frame_handler = scic_sds_remote_device_default_frame_handler
},
[SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = {
.start_handler = scic_sds_remote_device_stopped_state_start_handler,
.stop_handler = scic_sds_remote_device_stopped_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_stopped_state_destruct_handler,
.reset_handler = scic_sds_remote_device_default_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_remote_device_default_start_request_handler,
.complete_io_handler = scic_sds_remote_device_default_complete_request_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_remote_device_default_start_request_handler,
.complete_task_handler = scic_sds_remote_device_default_complete_request_handler,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_default_event_handler,
.frame_handler = scic_sds_remote_device_default_frame_handler
},
[SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_starting_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_default_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_remote_device_default_start_request_handler,
.complete_io_handler = scic_sds_remote_device_default_complete_request_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_remote_device_default_start_request_handler,
.complete_task_handler = scic_sds_remote_device_default_complete_request_handler,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_general_event_handler,
.frame_handler = scic_sds_remote_device_default_frame_handler
},
[SCI_BASE_REMOTE_DEVICE_STATE_READY] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_ready_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_ready_state_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_remote_device_ready_state_start_io_handler,
.complete_io_handler = scic_sds_remote_device_ready_state_complete_request_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_remote_device_ready_state_start_task_handler,
.complete_task_handler = scic_sds_remote_device_ready_state_complete_request_handler,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_general_event_handler,
.frame_handler = scic_sds_remote_device_general_frame_handler,
},
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_ready_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_ready_state_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_stp_remote_device_ready_idle_substate_start_io_handler,
.complete_io_handler = scic_sds_remote_device_default_complete_request_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler,
.complete_task_handler = scic_sds_remote_device_default_complete_request_handler,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_stp_remote_device_ready_idle_substate_event_handler,
.frame_handler = scic_sds_remote_device_default_frame_handler
},
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_ready_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_ready_state_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler,
.complete_io_handler = scic_sds_stp_remote_device_complete_request,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler,
.complete_task_handler = scic_sds_stp_remote_device_complete_request,
.suspend_handler = scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_general_event_handler,
.frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler
},
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_ready_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_ready_state_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler,
.complete_io_handler = scic_sds_stp_remote_device_complete_request,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler,
.complete_task_handler = scic_sds_stp_remote_device_complete_request,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_general_event_handler,
.frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler
},
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_ready_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_ready_state_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_remote_device_default_start_request_handler,
.complete_io_handler = scic_sds_stp_remote_device_complete_request,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler,
.complete_task_handler = scic_sds_stp_remote_device_complete_request,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_general_event_handler,
.frame_handler = scic_sds_remote_device_general_frame_handler
},
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_ready_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_ready_state_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler,
.complete_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler,
.complete_task_handler = scic_sds_stp_remote_device_complete_request,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_general_event_handler,
.frame_handler = scic_sds_remote_device_general_frame_handler
},
[SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_ready_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_default_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_smp_remote_device_ready_idle_substate_start_io_handler,
.complete_io_handler = scic_sds_remote_device_default_complete_request_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_remote_device_default_start_request_handler,
.complete_task_handler = scic_sds_remote_device_default_complete_request_handler,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_general_event_handler,
.frame_handler = scic_sds_remote_device_default_frame_handler
},
[SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_ready_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_default_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler,
.complete_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_remote_device_default_start_request_handler,
.complete_task_handler = scic_sds_remote_device_default_complete_request_handler,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_general_event_handler,
.frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler
},
[SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_stopping_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_default_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_remote_device_default_start_request_handler,
.complete_io_handler = scic_sds_remote_device_stopping_state_complete_request_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_remote_device_default_start_request_handler,
.complete_task_handler = scic_sds_remote_device_stopping_state_complete_request_handler,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_general_event_handler,
.frame_handler = scic_sds_remote_device_general_frame_handler
},
[SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_default_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_default_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_remote_device_default_start_request_handler,
.complete_io_handler = scic_sds_remote_device_default_complete_request_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_remote_device_default_start_request_handler,
.complete_task_handler = scic_sds_remote_device_default_complete_request_handler,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_default_event_handler,
.frame_handler = scic_sds_remote_device_general_frame_handler
},
[SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_resetting_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_default_reset_handler,
.reset_complete_handler = scic_sds_remote_device_resetting_state_reset_complete_handler,
.start_io_handler = scic_sds_remote_device_default_start_request_handler,
.complete_io_handler = scic_sds_remote_device_resetting_state_complete_request_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_remote_device_default_start_request_handler,
.complete_task_handler = scic_sds_remote_device_resetting_state_complete_request_handler,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_default_event_handler,
.frame_handler = scic_sds_remote_device_general_frame_handler
},
[SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_default_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_default_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_remote_device_default_start_request_handler,
.complete_io_handler = scic_sds_remote_device_default_complete_request_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_remote_device_default_start_request_handler,
.complete_task_handler = scic_sds_remote_device_default_complete_request_handler,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_default_event_handler,
.frame_handler = scic_sds_remote_device_default_frame_handler
}
};
static void scic_sds_remote_device_initial_state_enter(void *object)
{ {
unsigned long flags; struct scic_sds_remote_device *sci_dev = object;
spin_lock_irqsave(&isci_device->state_lock, flags); SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table,
isci_device->status = status; SCI_BASE_REMOTE_DEVICE_STATE_INITIAL);
spin_unlock_irqrestore(&isci_device->state_lock, flags);
/* Initial state is a transitional state to the stopped state */
sci_base_state_machine_change_state(&sci_dev->state_machine,
SCI_BASE_REMOTE_DEVICE_STATE_STOPPED);
} }
/** /**
...@@ -1242,9 +1768,8 @@ static void scic_sds_remote_device_starting_state_enter(void *object) ...@@ -1242,9 +1768,8 @@ static void scic_sds_remote_device_starting_state_enter(void *object)
static void scic_sds_remote_device_ready_state_enter(void *object) static void scic_sds_remote_device_ready_state_enter(void *object)
{ {
struct scic_sds_remote_device *sci_dev = object; struct scic_sds_remote_device *sci_dev = object;
struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller;
struct isci_host *ihost = scic->ihost; struct domain_device *dev = sci_dev_to_domain(sci_dev);
struct isci_remote_device *idev = sci_dev_to_idev(sci_dev);
SET_STATE_HANDLER(sci_dev, SET_STATE_HANDLER(sci_dev,
scic_sds_remote_device_state_handler_table, scic_sds_remote_device_state_handler_table,
...@@ -1252,23 +1777,26 @@ static void scic_sds_remote_device_ready_state_enter(void *object) ...@@ -1252,23 +1777,26 @@ static void scic_sds_remote_device_ready_state_enter(void *object)
scic->remote_device_sequence[sci_dev->rnc.remote_node_index]++; scic->remote_device_sequence[sci_dev->rnc.remote_node_index]++;
if (sci_dev->has_ready_substate_machine) if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_SATA)) {
sci_base_state_machine_start(&sci_dev->ready_substate_machine); sci_base_state_machine_change_state(&sci_dev->state_machine,
else SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE);
isci_remote_device_ready(ihost, idev); } else if (dev_is_expander(dev)) {
sci_base_state_machine_change_state(&sci_dev->state_machine,
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE);
} else
isci_remote_device_ready(scic->ihost, sci_dev_to_idev(sci_dev));
} }
static void scic_sds_remote_device_ready_state_exit(void *object) static void scic_sds_remote_device_ready_state_exit(void *object)
{ {
struct scic_sds_remote_device *sci_dev = object; struct scic_sds_remote_device *sci_dev = object;
if (sci_dev->has_ready_substate_machine) struct domain_device *dev = sci_dev_to_domain(sci_dev);
sci_base_state_machine_stop(&sci_dev->ready_substate_machine);
else { if (dev->dev_type == SAS_END_DEV) {
struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller;
struct isci_host *ihost = scic->ihost;
struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); struct isci_remote_device *idev = sci_dev_to_idev(sci_dev);
isci_remote_device_not_ready(ihost, idev, isci_remote_device_not_ready(scic->ihost, idev,
SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED); SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED);
} }
} }
...@@ -1327,6 +1855,101 @@ static void scic_sds_remote_device_final_state_enter(void *object) ...@@ -1327,6 +1855,101 @@ static void scic_sds_remote_device_final_state_enter(void *object)
); );
} }
static void scic_sds_stp_remote_device_ready_idle_substate_enter(void *object)
{
struct scic_sds_remote_device *sci_dev = object;
SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE);
sci_dev->working_request = NULL;
if (scic_sds_remote_node_context_is_ready(&sci_dev->rnc)) {
/*
* Since the RNC is ready, it's alright to finish completion
* processing (e.g. signal the remote device is ready). */
scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(sci_dev);
} else {
scic_sds_remote_node_context_resume(&sci_dev->rnc,
scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler,
sci_dev);
}
}
static void scic_sds_stp_remote_device_ready_cmd_substate_enter(void *object)
{
struct scic_sds_remote_device *sci_dev = object;
struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev);
BUG_ON(sci_dev->working_request == NULL);
SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD);
isci_remote_device_not_ready(scic->ihost, sci_dev_to_idev(sci_dev),
SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED);
}
static void scic_sds_stp_remote_device_ready_ncq_substate_enter(void *object)
{
struct scic_sds_remote_device *sci_dev = object;
SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ);
}
static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(void *object)
{
struct scic_sds_remote_device *sci_dev = object;
struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev);
struct isci_remote_device *idev = sci_dev_to_idev(sci_dev);
SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR);
if (sci_dev->not_ready_reason == SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED)
isci_remote_device_not_ready(scic->ihost, idev,
sci_dev->not_ready_reason);
}
static void scic_sds_stp_remote_device_ready_await_reset_substate_enter(void *object)
{
struct scic_sds_remote_device *sci_dev = object;
SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET);
}
static void scic_sds_smp_remote_device_ready_idle_substate_enter(void *object)
{
struct scic_sds_remote_device *sci_dev = object;
struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev);
SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table,
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE);
isci_remote_device_ready(scic->ihost, sci_dev_to_idev(sci_dev));
}
static void scic_sds_smp_remote_device_ready_cmd_substate_enter(void *object)
{
struct scic_sds_remote_device *sci_dev = object;
struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev);
BUG_ON(sci_dev->working_request == NULL);
SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table,
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD);
isci_remote_device_not_ready(scic->ihost, sci_dev_to_idev(sci_dev),
SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED);
}
static void scic_sds_smp_remote_device_ready_cmd_substate_exit(void *object)
{
struct scic_sds_remote_device *sci_dev = object;
sci_dev->working_request = NULL;
}
static const struct sci_base_state scic_sds_remote_device_state_table[] = { static const struct sci_base_state scic_sds_remote_device_state_table[] = {
[SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = {
...@@ -1342,6 +1965,28 @@ static const struct sci_base_state scic_sds_remote_device_state_table[] = { ...@@ -1342,6 +1965,28 @@ static const struct sci_base_state scic_sds_remote_device_state_table[] = {
.enter_state = scic_sds_remote_device_ready_state_enter, .enter_state = scic_sds_remote_device_ready_state_enter,
.exit_state = scic_sds_remote_device_ready_state_exit .exit_state = scic_sds_remote_device_ready_state_exit
}, },
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = {
.enter_state = scic_sds_stp_remote_device_ready_idle_substate_enter,
},
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = {
.enter_state = scic_sds_stp_remote_device_ready_cmd_substate_enter,
},
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = {
.enter_state = scic_sds_stp_remote_device_ready_ncq_substate_enter,
},
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = {
.enter_state = scic_sds_stp_remote_device_ready_ncq_error_substate_enter,
},
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = {
.enter_state = scic_sds_stp_remote_device_ready_await_reset_substate_enter,
},
[SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = {
.enter_state = scic_sds_smp_remote_device_ready_idle_substate_enter,
},
[SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = {
.enter_state = scic_sds_smp_remote_device_ready_cmd_substate_enter,
.exit_state = scic_sds_smp_remote_device_ready_cmd_substate_exit,
},
[SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = {
.enter_state = scic_sds_remote_device_stopping_state_enter, .enter_state = scic_sds_remote_device_stopping_state_enter,
}, },
...@@ -1406,7 +2051,6 @@ static enum sci_status scic_remote_device_da_construct(struct scic_sds_port *sci ...@@ -1406,7 +2051,6 @@ static enum sci_status scic_remote_device_da_construct(struct scic_sds_port *sci
struct scic_sds_remote_device *sci_dev) struct scic_sds_remote_device *sci_dev)
{ {
enum sci_status status; enum sci_status status;
u16 remote_node_index;
struct domain_device *dev = sci_dev_to_domain(sci_dev); struct domain_device *dev = sci_dev_to_domain(sci_dev);
scic_remote_device_construct(sci_port, sci_dev); scic_remote_device_construct(sci_port, sci_dev);
...@@ -1418,33 +2062,15 @@ static enum sci_status scic_remote_device_da_construct(struct scic_sds_port *sci ...@@ -1418,33 +2062,15 @@ static enum sci_status scic_remote_device_da_construct(struct scic_sds_port *sci
sci_dev->is_direct_attached = true; sci_dev->is_direct_attached = true;
status = scic_sds_controller_allocate_remote_node_context(sci_port->owning_controller, status = scic_sds_controller_allocate_remote_node_context(sci_port->owning_controller,
sci_dev, sci_dev,
&remote_node_index); &sci_dev->rnc.remote_node_index);
if (status != SCI_SUCCESS) if (status != SCI_SUCCESS)
return status; return status;
sci_dev->rnc.remote_node_index = remote_node_index; if (dev->dev_type == SAS_END_DEV || dev->dev_type == SATA_DEV ||
(dev->tproto & SAS_PROTOCOL_STP) || dev_is_expander(dev))
if (dev->dev_type == SAS_END_DEV) /* pass */;
sci_dev->has_ready_substate_machine = false; else
else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) {
sci_dev->has_ready_substate_machine = true;
sci_base_state_machine_construct(
&sci_dev->ready_substate_machine,
sci_dev,
scic_sds_stp_remote_device_ready_substate_table,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE);
} else if (dev_is_expander(dev)) {
sci_dev->has_ready_substate_machine = true;
/* add the SMP ready substate machine construction here */
sci_base_state_machine_construct(
&sci_dev->ready_substate_machine,
sci_dev,
scic_sds_smp_remote_device_ready_substate_table,
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE);
} else
return SCI_FAILURE_UNSUPPORTED_PROTOCOL; return SCI_FAILURE_UNSUPPORTED_PROTOCOL;
sci_dev->connection_rate = scic_sds_port_get_max_allowed_speed(sci_port); sci_dev->connection_rate = scic_sds_port_get_max_allowed_speed(sci_port);
...@@ -1470,37 +2096,22 @@ static enum sci_status scic_remote_device_da_construct(struct scic_sds_port *sci ...@@ -1470,37 +2096,22 @@ static enum sci_status scic_remote_device_da_construct(struct scic_sds_port *sci
static enum sci_status scic_remote_device_ea_construct(struct scic_sds_port *sci_port, static enum sci_status scic_remote_device_ea_construct(struct scic_sds_port *sci_port,
struct scic_sds_remote_device *sci_dev) struct scic_sds_remote_device *sci_dev)
{ {
struct scic_sds_controller *scic = sci_port->owning_controller;
struct domain_device *dev = sci_dev_to_domain(sci_dev); struct domain_device *dev = sci_dev_to_domain(sci_dev);
enum sci_status status; enum sci_status status;
scic_remote_device_construct(sci_port, sci_dev); scic_remote_device_construct(sci_port, sci_dev);
status = scic_sds_controller_allocate_remote_node_context( status = scic_sds_controller_allocate_remote_node_context(sci_port->owning_controller,
scic, sci_dev, &sci_dev->rnc.remote_node_index); sci_dev,
&sci_dev->rnc.remote_node_index);
if (status != SCI_SUCCESS) if (status != SCI_SUCCESS)
return status; return status;
if (dev->dev_type == SAS_END_DEV) if (dev->dev_type == SAS_END_DEV || dev->dev_type == SATA_DEV ||
sci_dev->has_ready_substate_machine = false; (dev->tproto & SAS_PROTOCOL_STP) || dev_is_expander(dev))
else if (dev_is_expander(dev)) { /* pass */;
sci_dev->has_ready_substate_machine = true; else
return SCI_FAILURE_UNSUPPORTED_PROTOCOL;
/* add the SMP ready substate machine construction here */
sci_base_state_machine_construct(
&sci_dev->ready_substate_machine,
sci_dev,
scic_sds_smp_remote_device_ready_substate_table,
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE);
} else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) {
sci_dev->has_ready_substate_machine = true;
sci_base_state_machine_construct(
&sci_dev->ready_substate_machine,
sci_dev,
scic_sds_stp_remote_device_ready_substate_table,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE);
}
/* /*
* For SAS-2 the physical link rate is actually a logical link * For SAS-2 the physical link rate is actually a logical link
...@@ -1515,7 +2126,7 @@ static enum sci_status scic_remote_device_ea_construct(struct scic_sds_port *sci ...@@ -1515,7 +2126,7 @@ static enum sci_status scic_remote_device_ea_construct(struct scic_sds_port *sci
/* / @todo Should I assign the port width by reading all of the phys on the port? */ /* / @todo Should I assign the port width by reading all of the phys on the port? */
sci_dev->device_port_width = 1; sci_dev->device_port_width = 1;
return status; return SCI_SUCCESS;
} }
/** /**
...@@ -1617,45 +2228,6 @@ isci_remote_device_alloc(struct isci_host *ihost, struct isci_port *iport) ...@@ -1617,45 +2228,6 @@ isci_remote_device_alloc(struct isci_host *ihost, struct isci_port *iport)
return idev; return idev;
} }
/**
* isci_remote_device_ready() - This function is called by the scic when the
* remote device is ready. We mark the isci device as ready and signal the
* waiting proccess.
* @ihost: our valid isci_host
* @idev: remote device
*
*/
void isci_remote_device_ready(struct isci_host *ihost, struct isci_remote_device *idev)
{
dev_dbg(&ihost->pdev->dev,
"%s: idev = %p\n", __func__, idev);
isci_remote_device_change_state(idev, isci_ready_for_io);
if (test_and_clear_bit(IDEV_START_PENDING, &idev->flags))
wake_up(&ihost->eventq);
}
/**
* isci_remote_device_not_ready() - This function is called by the scic when
* the remote device is not ready. We mark the isci device as ready (not
* "ready_for_io") and signal the waiting proccess.
* @isci_host: This parameter specifies the isci host object.
* @isci_device: This parameter specifies the remote device
*
*/
void isci_remote_device_not_ready(struct isci_host *ihost,
struct isci_remote_device *idev, u32 reason)
{
dev_dbg(&ihost->pdev->dev,
"%s: isci_device = %p\n", __func__, idev);
if (reason == SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED)
isci_remote_device_change_state(idev, isci_stopping);
else
/* device ready is actually a "not ready for io" state. */
isci_remote_device_change_state(idev, isci_ready);
}
/** /**
* isci_remote_device_stop() - This function is called internally to stop the * isci_remote_device_stop() - This function is called internally to stop the
* remote device. * remote device.
......
...@@ -68,9 +68,7 @@ enum scic_remote_device_not_ready_reason_code { ...@@ -68,9 +68,7 @@ enum scic_remote_device_not_ready_reason_code {
SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED, SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED,
SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED, SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED,
SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED, SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED,
SCIC_REMOTE_DEVICE_NOT_READY_REASON_CODE_MAX SCIC_REMOTE_DEVICE_NOT_READY_REASON_CODE_MAX
}; };
struct scic_sds_remote_device { struct scic_sds_remote_device {
...@@ -131,19 +129,6 @@ struct scic_sds_remote_device { ...@@ -131,19 +129,6 @@ struct scic_sds_remote_device {
*/ */
u32 not_ready_reason; u32 not_ready_reason;
/**
* This field is true if this remote device has an initialzied ready substate
* machine. SSP devices do not have a ready substate machine and STP devices
* have a ready substate machine.
*/
bool has_ready_substate_machine;
/**
* This field contains the state machine for the ready substate machine for
* this struct scic_sds_remote_device object.
*/
struct sci_base_state_machine ready_substate_machine;
/** /**
* This field maintains the set of state handlers for the remote device * This field maintains the set of state handlers for the remote device
* object. These are changed each time the remote device enters a new state. * object. These are changed each time the remote device enters a new state.
...@@ -171,10 +156,6 @@ enum sci_status isci_remote_device_stop(struct isci_host *ihost, ...@@ -171,10 +156,6 @@ enum sci_status isci_remote_device_stop(struct isci_host *ihost,
struct isci_remote_device *idev); struct isci_remote_device *idev);
void isci_remote_device_nuke_requests(struct isci_host *ihost, void isci_remote_device_nuke_requests(struct isci_host *ihost,
struct isci_remote_device *idev); struct isci_remote_device *idev);
void isci_remote_device_ready(struct isci_host *ihost,
struct isci_remote_device *idev);
void isci_remote_device_not_ready(struct isci_host *ihost,
struct isci_remote_device *idev, u32 reason);
void isci_remote_device_gone(struct domain_device *domain_dev); void isci_remote_device_gone(struct domain_device *domain_dev);
int isci_remote_device_found(struct domain_device *domain_dev); int isci_remote_device_found(struct domain_device *domain_dev);
bool isci_device_is_reset_pending(struct isci_host *ihost, bool isci_device_is_reset_pending(struct isci_host *ihost,
...@@ -277,77 +258,6 @@ enum scic_sds_remote_device_states { ...@@ -277,77 +258,6 @@ enum scic_sds_remote_device_states {
*/ */
SCI_BASE_REMOTE_DEVICE_STATE_READY, SCI_BASE_REMOTE_DEVICE_STATE_READY,
/**
* This state indicates that the remote device is in the process of
* stopping. In this state no new IO operations are permitted, but
* existing IO operations are allowed to complete.
* This state is entered from the READY state.
* This state is entered from the FAILED state.
*/
SCI_BASE_REMOTE_DEVICE_STATE_STOPPING,
/**
* This state indicates that the remote device has failed.
* In this state no new IO operations are permitted.
* This state is entered from the INITIALIZING state.
* This state is entered from the READY state.
*/
SCI_BASE_REMOTE_DEVICE_STATE_FAILED,
/**
* This state indicates the device is being reset.
* In this state no new IO operations are permitted.
* This state is entered from the READY state.
*/
SCI_BASE_REMOTE_DEVICE_STATE_RESETTING,
/**
* Simply the final state for the base remote device state machine.
*/
SCI_BASE_REMOTE_DEVICE_STATE_FINAL,
};
/**
* enum scic_sds_ssp_remote_device_ready_substates -
*
* This is the enumeration of the ready substates for the
* struct scic_sds_remote_device.
*/
enum scic_sds_ssp_remote_device_ready_substates {
/**
* This is the initial state for the remote device ready substate.
*/
SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_INITIAL,
/**
* This is the ready operational substate for the remote device.
* This is the normal operational state for a remote device.
*/
SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL,
/**
* This is the suspended state for the remote device. This is the state
* that the device is placed in when a RNC suspend is received by
* the SCU hardware.
*/
SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED,
/**
* This is the final state that the device is placed in before a change
* to the base state machine.
*/
SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_FINAL,
SCIC_SDS_SSP_REMOTE_DEVICE_READY_MAX_SUBSTATES
};
/**
* enum scic_sds_stp_remote_device_ready_substates -
*
* This is the enumeration for the struct scic_sds_remote_device ready substates
* for the STP remote device.
*/
enum scic_sds_stp_remote_device_ready_substates {
/** /**
* This is the idle substate for the stp remote device. When there are no * This is the idle substate for the stp remote device. When there are no
* active IO for the device it is is in this state. * active IO for the device it is is in this state.
...@@ -381,14 +291,7 @@ enum scic_sds_stp_remote_device_ready_substates { ...@@ -381,14 +291,7 @@ enum scic_sds_stp_remote_device_ready_substates {
* coming to be recovered from certain hardware specific error. * coming to be recovered from certain hardware specific error.
*/ */
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET,
};
/**
* enum scic_sds_smp_remote_device_ready_substates -
*
* This is the enumeration of the ready substates for the SMP REMOTE DEVICE.
*/
enum scic_sds_smp_remote_device_ready_substates {
/** /**
* This is the ready operational substate for the remote device. This is the * This is the ready operational substate for the remote device. This is the
* normal operational state for a remote device. * normal operational state for a remote device.
...@@ -400,6 +303,35 @@ enum scic_sds_smp_remote_device_ready_substates { ...@@ -400,6 +303,35 @@ enum scic_sds_smp_remote_device_ready_substates {
* the device is placed in when a RNC suspend is received by the SCU hardware. * the device is placed in when a RNC suspend is received by the SCU hardware.
*/ */
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD, SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD,
/**
* This state indicates that the remote device is in the process of
* stopping. In this state no new IO operations are permitted, but
* existing IO operations are allowed to complete.
* This state is entered from the READY state.
* This state is entered from the FAILED state.
*/
SCI_BASE_REMOTE_DEVICE_STATE_STOPPING,
/**
* This state indicates that the remote device has failed.
* In this state no new IO operations are permitted.
* This state is entered from the INITIALIZING state.
* This state is entered from the READY state.
*/
SCI_BASE_REMOTE_DEVICE_STATE_FAILED,
/**
* This state indicates the device is being reset.
* In this state no new IO operations are permitted.
* This state is entered from the READY state.
*/
SCI_BASE_REMOTE_DEVICE_STATE_RESETTING,
/**
* Simply the final state for the base remote device state machine.
*/
SCI_BASE_REMOTE_DEVICE_STATE_FINAL,
}; };
static inline struct scic_sds_remote_device *rnc_to_dev(struct scic_sds_remote_node_context *rnc) static inline struct scic_sds_remote_device *rnc_to_dev(struct scic_sds_remote_node_context *rnc)
...@@ -541,10 +473,6 @@ struct scic_sds_remote_device_state_handler { ...@@ -541,10 +473,6 @@ struct scic_sds_remote_device_state_handler {
scic_sds_remote_device_frame_handler_t frame_handler; scic_sds_remote_device_frame_handler_t frame_handler;
}; };
extern const struct sci_base_state scic_sds_ssp_remote_device_ready_substate_table[];
extern const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[];
extern const struct sci_base_state scic_sds_smp_remote_device_ready_substate_table[];
/** /**
* scic_sds_remote_device_increment_request_count() - * scic_sds_remote_device_increment_request_count() -
* *
...@@ -672,92 +600,24 @@ enum sci_status scic_sds_remote_device_start_io( ...@@ -672,92 +600,24 @@ enum sci_status scic_sds_remote_device_start_io(
struct scic_sds_remote_device *sci_dev, struct scic_sds_remote_device *sci_dev,
struct scic_sds_request *io_request); struct scic_sds_request *io_request);
enum sci_status scic_sds_remote_device_complete_io( enum sci_status scic_sds_remote_device_start_task(
struct scic_sds_controller *controller, struct scic_sds_controller *controller,
struct scic_sds_remote_device *sci_dev, struct scic_sds_remote_device *sci_dev,
struct scic_sds_request *io_request); struct scic_sds_request *io_request);
enum sci_status scic_sds_remote_device_resume( enum sci_status scic_sds_remote_device_complete_io(
struct scic_sds_remote_device *sci_dev); struct scic_sds_controller *controller,
struct scic_sds_remote_device *sci_dev,
struct scic_sds_request *io_request);
enum sci_status scic_sds_remote_device_suspend( enum sci_status scic_sds_remote_device_suspend(
struct scic_sds_remote_device *sci_dev, struct scic_sds_remote_device *sci_dev,
u32 suspend_type); u32 suspend_type);
enum sci_status scic_sds_remote_device_start_task(
struct scic_sds_controller *controller,
struct scic_sds_remote_device *sci_dev,
struct scic_sds_request *io_request);
void scic_sds_remote_device_post_request( void scic_sds_remote_device_post_request(
struct scic_sds_remote_device *sci_dev, struct scic_sds_remote_device *sci_dev,
u32 request); u32 request);
#define scic_sds_remote_device_is_atapi(sci_dev) false #define scic_sds_remote_device_is_atapi(sci_dev) false
void scic_sds_remote_device_start_request(
struct scic_sds_remote_device *sci_dev,
struct scic_sds_request *sci_req,
enum sci_status status);
void scic_sds_remote_device_continue_request(void *sci_dev);
enum sci_status scic_sds_remote_device_default_start_handler(
struct scic_sds_remote_device *sci_dev);
enum sci_status scic_sds_remote_device_default_fail_handler(
struct scic_sds_remote_device *sci_dev);
enum sci_status scic_sds_remote_device_default_destruct_handler(
struct scic_sds_remote_device *sci_dev);
enum sci_status scic_sds_remote_device_default_reset_handler(
struct scic_sds_remote_device *device);
enum sci_status scic_sds_remote_device_default_reset_complete_handler(
struct scic_sds_remote_device *device);
enum sci_status scic_sds_remote_device_default_start_request_handler(
struct scic_sds_remote_device *device,
struct scic_sds_request *request);
enum sci_status scic_sds_remote_device_default_complete_request_handler(
struct scic_sds_remote_device *device,
struct scic_sds_request *request);
enum sci_status scic_sds_remote_device_default_continue_request_handler(
struct scic_sds_remote_device *device,
struct scic_sds_request *request);
enum sci_status scic_sds_remote_device_default_suspend_handler(
struct scic_sds_remote_device *sci_dev,
u32 suspend_type);
enum sci_status scic_sds_remote_device_default_resume_handler(
struct scic_sds_remote_device *sci_dev);
enum sci_status scic_sds_remote_device_default_frame_handler(
struct scic_sds_remote_device *sci_dev,
u32 frame_index);
enum sci_status scic_sds_remote_device_ready_state_stop_handler(
struct scic_sds_remote_device *device);
enum sci_status scic_sds_remote_device_ready_state_reset_handler(
struct scic_sds_remote_device *device);
enum sci_status scic_sds_remote_device_general_frame_handler(
struct scic_sds_remote_device *sci_dev,
u32 frame_index);
enum sci_status scic_sds_remote_device_general_event_handler(
struct scic_sds_remote_device *sci_dev,
u32 event_code);
enum sci_status scic_sds_ssp_remote_device_ready_suspended_substate_resume_handler(
struct scic_sds_remote_device *sci_dev);
#endif /* !defined(_ISCI_REMOTE_DEVICE_H_) */ #endif /* !defined(_ISCI_REMOTE_DEVICE_H_) */
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "scic_sds_controller.h"
#include "scic_sds_port.h"
#include "remote_device.h"
#include "scic_sds_request.h"
#include "sci_environment.h"
#include "sci_util.h"
#include "scu_event_codes.h"
#include "scu_task_context.h"
/*
* *****************************************************************************
* * SMP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS
* ***************************************************************************** */
/**
*
* @[in]: device The device the io is sent to.
* @[in]: request The io to start.
*
* This method will handle the start io operation for a SMP device that is in
* the idle state. enum sci_status
*/
static enum sci_status scic_sds_smp_remote_device_ready_idle_substate_start_io_handler(
struct scic_sds_remote_device *device,
struct scic_sds_request *request)
{
enum sci_status status;
/* Will the port allow the io request to start? */
status = device->owning_port->state_handlers->start_io_handler(
device->owning_port, device, request);
if (status == SCI_SUCCESS) {
status = scic_sds_remote_node_context_start_io(&device->rnc, request);
if (status == SCI_SUCCESS)
status = scic_sds_request_start(request);
if (status == SCI_SUCCESS) {
device->working_request = request;
sci_base_state_machine_change_state(
&device->ready_substate_machine,
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD
);
}
scic_sds_remote_device_start_request(device, request, status);
}
return status;
}
/*
* ******************************************************************************
* * SMP REMOTE DEVICE READY SUBSTATE CMD HANDLERS
* ****************************************************************************** */
/**
*
* @device: This is the device object that is receiving the IO.
* @request: The io to start.
*
* This device is already handling a command it can not accept new commands
* until this one is complete. enum sci_status
*/
static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler(
struct scic_sds_remote_device *device,
struct scic_sds_request *request)
{
return SCI_FAILURE_INVALID_STATE;
}
/**
* this is the complete_io_handler for smp device at ready cmd substate.
* @device: This is the device object that is receiving the IO.
* @request: The io to start.
*
* enum sci_status
*/
static enum sci_status
scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler(
struct scic_sds_remote_device *device,
struct scic_sds_request *request)
{
enum sci_status status;
struct scic_sds_request *sci_req;
sci_req = (struct scic_sds_request *)request;
status = scic_sds_io_request_complete(sci_req);
if (status == SCI_SUCCESS) {
status = scic_sds_port_complete_io(
device->owning_port, device, sci_req);
if (status == SCI_SUCCESS) {
scic_sds_remote_device_decrement_request_count(device);
sci_base_state_machine_change_state(
&device->ready_substate_machine,
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
);
} else
dev_err(scirdev_to_dev(device),
"%s: SCIC SDS Remote Device 0x%p io request "
"0x%p could not be completd on the port 0x%p "
"failed with status %d.\n",
__func__,
device,
sci_req,
device->owning_port,
status);
}
return status;
}
/**
* This is frame handler for smp device ready cmd substate.
* @sci_dev: This is the device object that is receiving the frame.
* @frame_index: The index for the frame received.
*
* enum sci_status
*/
static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handler(
struct scic_sds_remote_device *sci_dev,
u32 frame_index)
{
enum sci_status status;
/*
* / The device does not process any UF received from the hardware while
* / in this state. All unsolicited frames are forwarded to the io request
* / object. */
status = scic_sds_io_request_frame_handler(
sci_dev->working_request,
frame_index
);
return status;
}
/* --------------------------------------------------------------------------- */
static const struct scic_sds_remote_device_state_handler scic_sds_smp_remote_device_ready_substate_handler_table[] = {
[SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_ready_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_default_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_smp_remote_device_ready_idle_substate_start_io_handler,
.complete_io_handler = scic_sds_remote_device_default_complete_request_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_remote_device_default_start_request_handler,
.complete_task_handler = scic_sds_remote_device_default_complete_request_handler,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_general_event_handler,
.frame_handler = scic_sds_remote_device_default_frame_handler
},
[SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_ready_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_default_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler,
.complete_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_remote_device_default_start_request_handler,
.complete_task_handler = scic_sds_remote_device_default_complete_request_handler,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_general_event_handler,
.frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler
}
};
/**
*
* @object: This is the object which is cast into a
* struct scic_sds_remote_device.
*
* This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE enter method.
* This function sets the ready cmd substate handlers and reports the device as
* ready. none
*/
static void scic_sds_smp_remote_device_ready_idle_substate_enter(void *object)
{
struct scic_sds_remote_device *sci_dev = object;
struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev);
struct isci_host *ihost = scic->ihost;
struct isci_remote_device *idev = sci_dev_to_idev(sci_dev);
SET_STATE_HANDLER(sci_dev,
scic_sds_smp_remote_device_ready_substate_handler_table,
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE);
isci_remote_device_ready(ihost, idev);
}
/**
*
* @object: This is the object which is cast into a
* struct scic_sds_remote_device.
*
* This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD enter method. This
* function sets the remote device objects ready cmd substate handlers, and
* notify core user that the device is not ready. none
*/
static void scic_sds_smp_remote_device_ready_cmd_substate_enter(void *object)
{
struct scic_sds_remote_device *sci_dev = object;
struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev);
struct isci_host *ihost = scic->ihost;
struct isci_remote_device *idev = sci_dev_to_idev(sci_dev);
BUG_ON(sci_dev->working_request == NULL);
SET_STATE_HANDLER(sci_dev,
scic_sds_smp_remote_device_ready_substate_handler_table,
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD);
isci_remote_device_not_ready(ihost, idev,
SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED);
}
/**
*
* @object: This is the object which is cast into a
* struct scic_sds_remote_device.
*
* This is the SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_CMD exit method. none
*/
static void scic_sds_smp_remote_device_ready_cmd_substate_exit(void *object)
{
struct scic_sds_remote_device *sci_dev = object;
sci_dev->working_request = NULL;
}
/* --------------------------------------------------------------------------- */
const struct sci_base_state scic_sds_smp_remote_device_ready_substate_table[] = {
[SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = {
.enter_state = scic_sds_smp_remote_device_ready_idle_substate_enter,
},
[SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = {
.enter_state = scic_sds_smp_remote_device_ready_cmd_substate_enter,
.exit_state = scic_sds_smp_remote_device_ready_cmd_substate_exit,
},
};
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "intel_ata.h"
#include "intel_sata.h"
#include "intel_sat.h"
#include "sci_base_state.h"
#include "scic_sds_controller.h"
#include "scic_sds_port.h"
#include "remote_device.h"
#include "scic_sds_request.h"
#include "sci_environment.h"
#include "sci_util.h"
#include "scu_event_codes.h"
/**
* This method will perform the STP request completion processing common to IO
* requests and task requests of all types
* @device: This parameter specifies the device for which the request is being
* completed.
* @request: This parameter specifies the request being completed.
*
* This method returns an indication as to whether the request processing
* completed successfully.
*/
static enum sci_status scic_sds_stp_remote_device_complete_request(
struct scic_sds_remote_device *device,
struct scic_sds_request *request)
{
enum sci_status status;
status = scic_sds_io_request_complete(request);
if (status == SCI_SUCCESS) {
status = scic_sds_port_complete_io(
device->owning_port, device, request);
if (status == SCI_SUCCESS) {
scic_sds_remote_device_decrement_request_count(device);
if (request->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) {
/*
* This request causes hardware error, device needs to be Lun Reset.
* So here we force the state machine to IDLE state so the rest IOs
* can reach RNC state handler, these IOs will be completed by RNC with
* status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE". */
sci_base_state_machine_change_state(
&device->ready_substate_machine,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET
);
} else if (scic_sds_remote_device_get_request_count(device) == 0) {
sci_base_state_machine_change_state(
&device->ready_substate_machine,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
);
}
}
}
if (status != SCI_SUCCESS)
dev_err(scirdev_to_dev(device),
"%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x "
"could not complete\n",
__func__,
device->owning_port,
device,
request,
status);
return status;
}
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY COMMON SUBSTATE HANDLERS
* ***************************************************************************** */
/**
* This is the READY NCQ substate handler to start task management request. In
* this routine, we suspend and resume the RNC.
* @device: The target device a task management request towards to.
* @request: The task request.
*
* enum sci_status Always return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS status to
* let controller_start_task_handler know that the controller can't post TC for
* task request yet, instead, when RNC gets resumed, a controller_continue_task
* callback will be called.
*/
static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_handler(
struct scic_sds_remote_device *device,
struct scic_sds_request *request)
{
enum sci_status status;
/* Will the port allow the io request to start? */
status = device->owning_port->state_handlers->start_io_handler(
device->owning_port, device, request);
if (status != SCI_SUCCESS)
return status;
status = scic_sds_remote_node_context_start_task(&device->rnc, request);
if (status != SCI_SUCCESS)
goto out;
status = request->state_handlers->start_handler(request);
if (status != SCI_SUCCESS)
goto out;
/*
* Note: If the remote device state is not IDLE this will replace
* the request that probably resulted in the task management request.
*/
device->working_request = request;
sci_base_state_machine_change_state(&device->ready_substate_machine,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD);
/*
* The remote node context must cleanup the TCi to NCQ mapping table.
* The only way to do this correctly is to either write to the TLCR
* register or to invalidate and repost the RNC. In either case the
* remote node context state machine will take the correct action when
* the remote node context is suspended and later resumed.
*/
scic_sds_remote_node_context_suspend(&device->rnc,
SCI_SOFTWARE_SUSPENSION, NULL, NULL);
scic_sds_remote_node_context_resume(&device->rnc,
scic_sds_remote_device_continue_request,
device);
out:
scic_sds_remote_device_start_request(device, request, status);
/*
* We need to let the controller start request handler know that it can't
* post TC yet. We will provide a callback function to post TC when RNC gets
* resumed.
*/
return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS;
}
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS
* ***************************************************************************** */
/**
* This method will handle the start io operation for a sata device that is in
* the command idle state. - Evalute the type of IO request to be started -
* If its an NCQ request change to NCQ substate - If its any other command
* change to the CMD substate
* @device:
* @request:
*
* If this is a softreset we may want to have a different substate.
* enum sci_status
*/
static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_start_io_handler(
struct scic_sds_remote_device *sci_dev,
struct scic_sds_request *request)
{
enum sci_status status;
struct isci_request *isci_request = request->ireq;
/* Will the port allow the io request to start? */
status = sci_dev->owning_port->state_handlers->start_io_handler(
sci_dev->owning_port, sci_dev, request);
if (status != SCI_SUCCESS)
return status;
status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request);
if (status != SCI_SUCCESS)
goto out;
status = request->state_handlers->start_handler(request);
if (status != SCI_SUCCESS)
goto out;
if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) {
sci_base_state_machine_change_state(&sci_dev->ready_substate_machine,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ);
} else {
sci_dev->working_request = request;
sci_base_state_machine_change_state(&sci_dev->ready_substate_machine,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD);
}
out:
scic_sds_remote_device_start_request(sci_dev, request, status);
return status;
}
/**
*
* @[in]: device The device received event.
* @[in]: event_code The event code.
*
* This method will handle the event for a sata device that is in the idle
* state. We pick up suspension events to handle specifically to this state. We
* resume the RNC right away. enum sci_status
*/
static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_handler(
struct scic_sds_remote_device *sci_dev,
u32 event_code)
{
enum sci_status status;
status = scic_sds_remote_device_general_event_handler(sci_dev, event_code);
if (status == SCI_SUCCESS) {
if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX
|| scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) {
status = scic_sds_remote_node_context_resume(
&sci_dev->rnc, NULL, NULL);
}
}
return status;
}
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS
* ***************************************************************************** */
static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler(
struct scic_sds_remote_device *sci_dev,
struct scic_sds_request *request)
{
enum sci_status status;
struct isci_request *isci_request = request->ireq;
if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) {
status = sci_dev->owning_port->state_handlers->start_io_handler(
sci_dev->owning_port,
sci_dev,
request);
if (status != SCI_SUCCESS)
return status;
status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request);
if (status != SCI_SUCCESS)
return status;
status = request->state_handlers->start_handler(request);
scic_sds_remote_device_start_request(sci_dev, request, status);
} else
status = SCI_FAILURE_INVALID_STATE;
return status;
}
/**
* This method will handle events received while the STP device is in the ready
* command substate.
* @sci_dev: This is the device object that is receiving the event.
* @event_code: The event code to process.
*
* enum sci_status
*/
static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handler(
struct scic_sds_remote_device *sci_dev,
u32 frame_index)
{
enum sci_status status;
struct sata_fis_header *frame_header;
status = scic_sds_unsolicited_frame_control_get_header(
&(scic_sds_remote_device_get_controller(sci_dev)->uf_control),
frame_index,
(void **)&frame_header
);
if (status == SCI_SUCCESS) {
if (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS &&
(frame_header->status & ATA_STATUS_REG_ERROR_BIT)) {
sci_dev->not_ready_reason =
SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
/*
* / @todo Check sactive and complete associated IO
* if any.
*/
sci_base_state_machine_change_state(
&sci_dev->ready_substate_machine,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
);
} else if (frame_header->fis_type == SATA_FIS_TYPE_REGD2H &&
(frame_header->status & ATA_STATUS_REG_ERROR_BIT)) {
/*
* Some devices return D2H FIS when an NCQ error is detected.
* Treat this like an SDB error FIS ready reason.
*/
sci_dev->not_ready_reason =
SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
sci_base_state_machine_change_state(
&sci_dev->ready_substate_machine,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
);
} else {
status = SCI_FAILURE;
}
scic_sds_controller_release_frame(
scic_sds_remote_device_get_controller(sci_dev), frame_index
);
}
return status;
}
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY CMD SUBSTATE HANDLERS
* ***************************************************************************** */
/**
* This device is already handling a command it can not accept new commands
* until this one is complete.
* @device:
* @request:
*
* enum sci_status
*/
static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler(
struct scic_sds_remote_device *device,
struct scic_sds_request *request)
{
return SCI_FAILURE_INVALID_STATE;
}
static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler(
struct scic_sds_remote_device *sci_dev,
u32 suspend_type)
{
enum sci_status status;
status = scic_sds_remote_node_context_suspend(&sci_dev->rnc,
suspend_type, NULL, NULL);
return status;
}
static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handler(
struct scic_sds_remote_device *sci_dev,
u32 frame_index)
{
enum sci_status status;
/*
* / The device doe not process any UF received from the hardware while
* / in this state. All unsolicited frames are forwarded to the io request
* / object. */
status = scic_sds_io_request_frame_handler(
sci_dev->working_request,
frame_index
);
return status;
}
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS
* ***************************************************************************** */
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY NCQ ERROR SUBSTATE HANDLERS
* ***************************************************************************** */
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY AWAIT RESET SUBSTATE HANDLERS
* ***************************************************************************** */
static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler(
struct scic_sds_remote_device *device,
struct scic_sds_request *request)
{
return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
}
/**
* This method will perform the STP request (both io or task) completion
* processing for await reset state.
* @device: This parameter specifies the device for which the request is being
* completed.
* @request: This parameter specifies the request being completed.
*
* This method returns an indication as to whether the request processing
* completed successfully.
*/
static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler(
struct scic_sds_remote_device *device,
struct scic_sds_request *request)
{
struct scic_sds_request *sci_req = (struct scic_sds_request *)request;
enum sci_status status;
status = scic_sds_io_request_complete(sci_req);
if (status == SCI_SUCCESS) {
status = scic_sds_port_complete_io(
device->owning_port, device, sci_req
);
if (status == SCI_SUCCESS)
scic_sds_remote_device_decrement_request_count(device);
}
if (status != SCI_SUCCESS)
dev_err(scirdev_to_dev(device),
"%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x "
"could not complete\n",
__func__,
device->owning_port,
device,
sci_req,
status);
return status;
}
static const struct scic_sds_remote_device_state_handler scic_sds_stp_remote_device_ready_substate_handler_table[] = {
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_ready_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_ready_state_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_stp_remote_device_ready_idle_substate_start_io_handler,
.complete_io_handler = scic_sds_remote_device_default_complete_request_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler,
.complete_task_handler = scic_sds_remote_device_default_complete_request_handler,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_stp_remote_device_ready_idle_substate_event_handler,
.frame_handler = scic_sds_remote_device_default_frame_handler
},
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_ready_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_ready_state_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler,
.complete_io_handler = scic_sds_stp_remote_device_complete_request,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler,
.complete_task_handler = scic_sds_stp_remote_device_complete_request,
.suspend_handler = scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_general_event_handler,
.frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler
},
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_ready_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_ready_state_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler,
.complete_io_handler = scic_sds_stp_remote_device_complete_request,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler,
.complete_task_handler = scic_sds_stp_remote_device_complete_request,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_general_event_handler,
.frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler
},
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_ready_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_ready_state_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_remote_device_default_start_request_handler,
.complete_io_handler = scic_sds_stp_remote_device_complete_request,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler,
.complete_task_handler = scic_sds_stp_remote_device_complete_request,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_general_event_handler,
.frame_handler = scic_sds_remote_device_general_frame_handler
},
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = {
.start_handler = scic_sds_remote_device_default_start_handler,
.stop_handler = scic_sds_remote_device_ready_state_stop_handler,
.fail_handler = scic_sds_remote_device_default_fail_handler,
.destruct_handler = scic_sds_remote_device_default_destruct_handler,
.reset_handler = scic_sds_remote_device_ready_state_reset_handler,
.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler,
.start_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler,
.complete_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler,
.continue_io_handler = scic_sds_remote_device_default_continue_request_handler,
.start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler,
.complete_task_handler = scic_sds_stp_remote_device_complete_request,
.suspend_handler = scic_sds_remote_device_default_suspend_handler,
.resume_handler = scic_sds_remote_device_default_resume_handler,
.event_handler = scic_sds_remote_device_general_event_handler,
.frame_handler = scic_sds_remote_device_general_frame_handler
}
};
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY SUBSTATE PRIVATE METHODS
* ***************************************************************************** */
static void
scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *user_cookie)
{
struct scic_sds_remote_device *sci_dev = user_cookie;
struct isci_remote_device *idev = sci_dev_to_idev(sci_dev);
struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev);
struct isci_host *ihost = scic->ihost;
/*
* For NCQ operation we do not issue a
* scic_cb_remote_device_not_ready(). As a result, avoid sending
* the ready notification.
*/
if (sci_dev->ready_substate_machine.previous_state_id !=
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ)
isci_remote_device_ready(ihost, idev);
}
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY IDLE SUBSTATE
* ***************************************************************************** */
/**
*
* @device: This is the object which is cast into a
* struct scic_sds_remote_device object.
*
*/
static void scic_sds_stp_remote_device_ready_idle_substate_enter(void *device)
{
struct scic_sds_remote_device *sci_dev = device;
SET_STATE_HANDLER(
sci_dev,
scic_sds_stp_remote_device_ready_substate_handler_table,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
);
sci_dev->working_request = NULL;
if (scic_sds_remote_node_context_is_ready(&sci_dev->rnc)) {
/*
* Since the RNC is ready, it's alright to finish completion
* processing (e.g. signal the remote device is ready). */
scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(
sci_dev
);
} else {
scic_sds_remote_node_context_resume(
&sci_dev->rnc,
scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler,
sci_dev);
}
}
static void scic_sds_stp_remote_device_ready_cmd_substate_enter(void *object)
{
struct scic_sds_remote_device *sci_dev = object;
struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev);
struct isci_host *ihost = scic->ihost;
struct isci_remote_device *idev = sci_dev_to_idev(sci_dev);
BUG_ON(sci_dev->working_request == NULL);
SET_STATE_HANDLER(sci_dev,
scic_sds_stp_remote_device_ready_substate_handler_table,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD);
isci_remote_device_not_ready(ihost, idev,
SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED);
}
static void scic_sds_stp_remote_device_ready_ncq_substate_enter(void *object)
{
struct scic_sds_remote_device *sci_dev = object;
SET_STATE_HANDLER(sci_dev,
scic_sds_stp_remote_device_ready_substate_handler_table,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ);
}
static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(
void *object)
{
struct scic_sds_remote_device *sci_dev = object;
struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev);
struct isci_host *ihost = scic->ihost;
struct isci_remote_device *idev = sci_dev_to_idev(sci_dev);
SET_STATE_HANDLER(sci_dev,
scic_sds_stp_remote_device_ready_substate_handler_table,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR);
if (sci_dev->not_ready_reason ==
SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED)
isci_remote_device_not_ready(ihost, idev, sci_dev->not_ready_reason);
}
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY AWAIT RESET SUBSTATE
* ***************************************************************************** */
/**
* The enter routine to READY AWAIT RESET substate.
* @device: This is the object which is cast into a
* struct scic_sds_remote_device object.
*
*/
static void scic_sds_stp_remote_device_ready_await_reset_substate_enter(
void *device)
{
struct scic_sds_remote_device *sci_dev;
sci_dev = (struct scic_sds_remote_device *)device;
SET_STATE_HANDLER(
sci_dev,
scic_sds_stp_remote_device_ready_substate_handler_table,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET
);
}
const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[] = {
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = {
.enter_state = scic_sds_stp_remote_device_ready_idle_substate_enter,
},
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = {
.enter_state = scic_sds_stp_remote_device_ready_cmd_substate_enter,
},
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = {
.enter_state = scic_sds_stp_remote_device_ready_ncq_substate_enter,
},
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = {
.enter_state = scic_sds_stp_remote_device_ready_ncq_error_substate_enter,
},
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = {
.enter_state = scic_sds_stp_remote_device_ready_await_reset_substate_enter,
},
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment