isci: unify rnc suspend/resume handlers

Unify rnc suspend/resume handlers and delete the state handlers.

Reported-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
Dan Williams 2011-05-12 08:50:23 -07:00
parent c845ae96bc
commit ed3efb7784
2 changed files with 104 additions and 234 deletions

View File

@ -195,60 +195,6 @@ static void scic_sds_remote_node_context_setup_to_destory(
sci_rnc->user_cookie = callback_parameter;
}
/**
*
* @sci_rnc:
* @callback:
*
* This method will continue to resume a remote node context. This is used in
* the states where a resume is requested while a resume is in progress.
*/
static enum sci_status scic_sds_remote_node_context_continue_to_resume_handler(
struct scic_sds_remote_node_context *sci_rnc,
scics_sds_remote_node_context_callback callback,
void *callback_parameter)
{
if (sci_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) {
sci_rnc->user_callback = callback;
sci_rnc->user_cookie = callback_parameter;
return SCI_SUCCESS;
}
return SCI_FAILURE_INVALID_STATE;
}
static enum sci_status scic_sds_remote_node_context_default_suspend_handler(
struct scic_sds_remote_node_context *sci_rnc,
u32 suspend_type,
scics_sds_remote_node_context_callback callback,
void *callback_parameter)
{
dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
"%s: SCIC Remote Node Context 0x%p requested to suspend "
"while in wrong state %d\n",
__func__,
sci_rnc,
sci_base_state_machine_get_state(&sci_rnc->state_machine));
return SCI_FAILURE_INVALID_STATE;
}
static enum sci_status scic_sds_remote_node_context_default_resume_handler(
struct scic_sds_remote_node_context *sci_rnc,
scics_sds_remote_node_context_callback callback,
void *callback_parameter)
{
dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
"%s: SCIC Remote Node Context 0x%p requested to resume "
"while in wrong state %d\n",
__func__,
sci_rnc,
sci_base_state_machine_get_state(&sci_rnc->state_machine));
return SCI_FAILURE_INVALID_STATE;
}
static enum sci_status scic_sds_remote_node_context_default_start_io_handler(
struct scic_sds_remote_node_context *sci_rnc,
struct scic_sds_request *sci_req)
@ -295,61 +241,6 @@ static enum sci_status scic_sds_remote_node_context_success_start_task_handler(
return SCI_SUCCESS;
}
static enum sci_status scic_sds_remote_node_context_initial_state_resume_handler(
struct scic_sds_remote_node_context *sci_rnc,
scics_sds_remote_node_context_callback callback,
void *callback_parameter)
{
if (sci_rnc->remote_node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) {
scic_sds_remote_node_context_setup_to_resume(
sci_rnc, callback, callback_parameter
);
scic_sds_remote_node_context_construct_buffer(sci_rnc);
sci_base_state_machine_change_state(
&sci_rnc->state_machine,
SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
);
return SCI_SUCCESS;
}
return SCI_FAILURE_INVALID_STATE;
}
/**
*
* @sci_rnc: The remote node context object being suspended.
* @callback: The callback when the suspension is complete.
* @callback_parameter: The parameter that is to be passed into the callback.
*
* This method will handle the suspend requests from the ready state.
* SCI_SUCCESS
*/
static enum sci_status scic_sds_remote_node_context_ready_state_suspend_handler(
struct scic_sds_remote_node_context *sci_rnc,
u32 suspend_type,
scics_sds_remote_node_context_callback callback,
void *callback_parameter)
{
sci_rnc->user_callback = callback;
sci_rnc->user_cookie = callback_parameter;
sci_rnc->suspension_code = suspend_type;
if (suspend_type == SCI_SOFTWARE_SUSPENSION) {
scic_sds_remote_device_post_request(rnc_to_dev(sci_rnc),
SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX);
}
sci_base_state_machine_change_state(
&sci_rnc->state_machine,
SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
);
return SCI_SUCCESS;
}
/**
*
* @sci_rnc: The rnc for which the io request is targeted.
@ -366,39 +257,6 @@ static enum sci_status scic_sds_remote_node_context_ready_state_start_io_handler
return SCI_SUCCESS;
}
static enum sci_status scic_sds_remote_node_context_tx_suspended_state_resume_handler(
struct scic_sds_remote_node_context *sci_rnc,
scics_sds_remote_node_context_callback callback,
void *callback_parameter)
{
struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc);
struct domain_device *dev = sci_dev_to_domain(sci_dev);
enum sci_status status = SCI_SUCCESS;
scic_sds_remote_node_context_setup_to_resume(sci_rnc, callback,
callback_parameter);
/* TODO: consider adding a resume action of NONE, INVALIDATE, WRITE_TLCR */
if (dev->dev_type == SAS_END_DEV || dev_is_expander(dev))
sci_base_state_machine_change_state(&sci_rnc->state_machine,
SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE);
else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) {
if (sci_dev->is_direct_attached) {
/* @todo Fix this since I am being silly in writing to the STPTLDARNI register. */
sci_base_state_machine_change_state(
&sci_rnc->state_machine,
SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE);
} else {
sci_base_state_machine_change_state(
&sci_rnc->state_machine,
SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE);
}
} else
status = SCI_FAILURE;
return status;
}
/**
*
* @sci_rnc: The remote node context which is to receive the task request.
@ -419,44 +277,6 @@ static enum sci_status scic_sds_remote_node_context_suspended_start_task_handler
return SCI_SUCCESS;
}
/* --------------------------------------------------------------------------- */
static enum sci_status scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler(
struct scic_sds_remote_node_context *sci_rnc,
scics_sds_remote_node_context_callback callback,
void *callback_parameter)
{
scic_sds_remote_node_context_setup_to_resume(
sci_rnc, callback, callback_parameter
);
sci_base_state_machine_change_state(
&sci_rnc->state_machine,
SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
);
return SCI_FAILURE_INVALID_STATE;
}
/* --------------------------------------------------------------------------- */
/**
*
*
*
*/
static enum sci_status scic_sds_remote_node_context_await_suspension_state_resume_handler(
struct scic_sds_remote_node_context *sci_rnc,
scics_sds_remote_node_context_callback callback,
void *callback_parameter)
{
scic_sds_remote_node_context_setup_to_resume(
sci_rnc, callback, callback_parameter
);
return SCI_SUCCESS;
}
/**
*
* @sci_rnc: The remote node context which is to receive the task request.
@ -477,50 +297,34 @@ static enum sci_status scic_sds_remote_node_context_await_suspension_state_start
static struct scic_sds_remote_node_context_handlers scic_sds_remote_node_context_state_handler_table[] = {
[SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE] = {
.suspend_handler = scic_sds_remote_node_context_default_suspend_handler,
.resume_handler = scic_sds_remote_node_context_initial_state_resume_handler,
.start_io_handler = scic_sds_remote_node_context_default_start_io_handler,
.start_task_handler = scic_sds_remote_node_context_default_start_task_handler,
},
[SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE] = {
.suspend_handler = scic_sds_remote_node_context_default_suspend_handler,
.resume_handler = scic_sds_remote_node_context_continue_to_resume_handler,
.start_io_handler = scic_sds_remote_node_context_default_start_io_handler,
.start_task_handler = scic_sds_remote_node_context_default_start_task_handler,
},
[SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE] = {
.suspend_handler = scic_sds_remote_node_context_default_suspend_handler,
.resume_handler = scic_sds_remote_node_context_continue_to_resume_handler,
.start_io_handler = scic_sds_remote_node_context_default_start_io_handler,
.start_task_handler = scic_sds_remote_node_context_default_start_task_handler,
},
[SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE] = {
.suspend_handler = scic_sds_remote_node_context_default_suspend_handler,
.resume_handler = scic_sds_remote_node_context_continue_to_resume_handler,
.start_io_handler = scic_sds_remote_node_context_default_start_io_handler,
.start_task_handler = scic_sds_remote_node_context_success_start_task_handler,
},
[SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE] = {
.suspend_handler = scic_sds_remote_node_context_ready_state_suspend_handler,
.resume_handler = scic_sds_remote_node_context_default_resume_handler,
.start_io_handler = scic_sds_remote_node_context_ready_state_start_io_handler,
.start_task_handler = scic_sds_remote_node_context_success_start_task_handler,
},
[SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE] = {
.suspend_handler = scic_sds_remote_node_context_default_suspend_handler,
.resume_handler = scic_sds_remote_node_context_tx_suspended_state_resume_handler,
.start_io_handler = scic_sds_remote_node_context_default_start_io_handler,
.start_task_handler = scic_sds_remote_node_context_suspended_start_task_handler,
},
[SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE] = {
.suspend_handler = scic_sds_remote_node_context_default_suspend_handler,
.resume_handler = scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler,
.start_io_handler = scic_sds_remote_node_context_default_start_io_handler,
.start_task_handler = scic_sds_remote_node_context_suspended_start_task_handler,
},
[SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE] = {
.suspend_handler = scic_sds_remote_node_context_default_suspend_handler,
.resume_handler = scic_sds_remote_node_context_await_suspension_state_resume_handler,
.start_io_handler = scic_sds_remote_node_context_default_start_io_handler,
.start_task_handler = scic_sds_remote_node_context_await_suspension_state_start_task_handler,
}
@ -548,21 +352,11 @@ static void scic_sds_remote_node_context_notify_user(
}
}
/**
*
*
* This method will continue the remote node context state machine by
* requesting to resume the remote node context state machine from its current
* state.
*/
static void scic_sds_remote_node_context_continue_state_transitions(
struct scic_sds_remote_node_context *rnc)
static void scic_sds_remote_node_context_continue_state_transitions(struct scic_sds_remote_node_context *rnc)
{
if (rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) {
rnc->state_handlers->resume_handler(
rnc, rnc->user_callback, rnc->user_cookie
);
}
if (rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY)
scic_sds_remote_node_context_resume(rnc, rnc->user_callback,
rnc->user_cookie);
}
/**
@ -989,3 +783,95 @@ enum sci_status scic_sds_remote_node_context_destruct(struct scic_sds_remote_nod
return SCI_FAILURE_INVALID_STATE;
}
}
enum sci_status scic_sds_remote_node_context_suspend(struct scic_sds_remote_node_context *sci_rnc,
u32 suspend_type,
scics_sds_remote_node_context_callback cb_fn,
void *cb_p)
{
enum scis_sds_remote_node_context_states state;
state = sci_rnc->state_machine.current_state_id;
if (state != SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE) {
dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
"%s: invalid state %d\n", __func__, state);
return SCI_FAILURE_INVALID_STATE;
}
sci_rnc->user_callback = cb_fn;
sci_rnc->user_cookie = cb_p;
sci_rnc->suspension_code = suspend_type;
if (suspend_type == SCI_SOFTWARE_SUSPENSION) {
scic_sds_remote_device_post_request(rnc_to_dev(sci_rnc),
SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX);
}
sci_base_state_machine_change_state(&sci_rnc->state_machine,
SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE);
return SCI_SUCCESS;
}
enum sci_status scic_sds_remote_node_context_resume(struct scic_sds_remote_node_context *sci_rnc,
scics_sds_remote_node_context_callback cb_fn,
void *cb_p)
{
enum scis_sds_remote_node_context_states state;
state = sci_rnc->state_machine.current_state_id;
switch (state) {
case SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE:
if (sci_rnc->remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
return SCI_FAILURE_INVALID_STATE;
scic_sds_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p);
scic_sds_remote_node_context_construct_buffer(sci_rnc);
sci_base_state_machine_change_state(&sci_rnc->state_machine,
SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE);
return SCI_SUCCESS;
case SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE:
case SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE:
case SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE:
if (sci_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY)
return SCI_FAILURE_INVALID_STATE;
sci_rnc->user_callback = cb_fn;
sci_rnc->user_cookie = cb_p;
return SCI_SUCCESS;
case SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE: {
struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc);
struct domain_device *dev = sci_dev_to_domain(sci_dev);
scic_sds_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p);
/* TODO: consider adding a resume action of NONE, INVALIDATE, WRITE_TLCR */
if (dev->dev_type == SAS_END_DEV || dev_is_expander(dev))
sci_base_state_machine_change_state(&sci_rnc->state_machine,
SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE);
else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) {
if (sci_dev->is_direct_attached) {
/* @todo Fix this since I am being silly in writing to the STPTLDARNI register. */
sci_base_state_machine_change_state(&sci_rnc->state_machine,
SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE);
} else {
sci_base_state_machine_change_state(&sci_rnc->state_machine,
SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE);
}
} else
return SCI_FAILURE;
return SCI_SUCCESS;
}
case SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE:
scic_sds_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p);
sci_base_state_machine_change_state(&sci_rnc->state_machine,
SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE);
return SCI_FAILURE_INVALID_STATE;
case SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE:
scic_sds_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p);
return SCI_SUCCESS;
default:
dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
"%s: invalid state %d\n", __func__, state);
return SCI_FAILURE_INVALID_STATE;
}
}

View File

@ -90,32 +90,12 @@ typedef enum sci_status (*scic_sds_remote_node_context_operation)(
void *callback_parameter
);
typedef enum sci_status (*scic_sds_remote_node_context_suspend_operation)(
struct scic_sds_remote_node_context *sci_rnc,
u32 suspension_type,
scics_sds_remote_node_context_callback callback,
void *callback_parameter
);
typedef enum sci_status (*scic_sds_remote_node_context_io_request)(
struct scic_sds_remote_node_context *sci_rnc,
struct scic_sds_request *sci_req
);
struct scic_sds_remote_node_context_handlers {
/**
* This handler is invoked when there is a request to suspend the RNC. The
* callback is invoked after the hardware notification that the remote node is
* suspended.
*/
scic_sds_remote_node_context_suspend_operation suspend_handler;
/**
* This handler is invoked when there is a request to resume the RNC. The
* callback is invoked when after the RNC has reached the ready state.
*/
scic_sds_remote_node_context_operation resume_handler;
/**
* This handler is invoked when there is a request to start an io request
* operation.
@ -260,11 +240,15 @@ enum sci_status scic_sds_remote_node_context_event_handler(struct scic_sds_remot
enum sci_status scic_sds_remote_node_context_destruct(struct scic_sds_remote_node_context *sci_rnc,
scics_sds_remote_node_context_callback callback,
void *callback_parameter);
#define scic_sds_remote_node_context_resume(rnc, callback, parameter) \
((rnc)->state_handlers->resume_handler(rnc, callback, parameter))
#define scic_sds_remote_node_context_suspend(rnc, suspend_type, callback, parameter) \
((rnc)->state_handlers->suspend_handler(rnc, suspend_type, callback, parameter))
enum sci_status scic_sds_remote_node_context_suspend(struct scic_sds_remote_node_context *sci_rnc,
u32 suspend_type,
scics_sds_remote_node_context_callback cb_fn,
void *cb_p);
enum sci_status scic_sds_remote_node_context_resume(struct scic_sds_remote_node_context *sci_rnc,
scics_sds_remote_node_context_callback cb_fn,
void *cb_p);
#define scic_sds_remote_node_context_start_io(rnc, request) \
((rnc)->state_handlers->start_io_handler(rnc, request))