Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 302552
b: refs/heads/master
c: ac78ed0
h: refs/heads/master
v: v3
  • Loading branch information
Jeff Skirvin authored and Dan Williams committed May 17, 2012
1 parent 55af09c commit 1b3c470
Show file tree
Hide file tree
Showing 8 changed files with 243 additions and 88 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 56d7c013e714c6feab2ab5ac854808e29048b069
refs/heads/master: ac78ed0f78eae5c3c918e132b5e2029cdc4fdedc
86 changes: 42 additions & 44 deletions trunk/drivers/scsi/isci/remote_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,20 +265,12 @@ enum sci_status sci_remote_device_reset_complete(struct isci_remote_device *idev
return SCI_SUCCESS;
}

enum sci_status sci_remote_device_suspend(struct isci_remote_device *idev,
u32 suspend_type)
enum sci_status sci_remote_device_suspend(struct isci_remote_device *idev)
{
struct sci_base_state_machine *sm = &idev->sm;
enum sci_remote_device_states state = sm->current_state_id;

if (state != SCI_STP_DEV_CMD) {
dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %s\n",
__func__, dev_state_name(state));
return SCI_FAILURE_INVALID_STATE;
}

return sci_remote_node_context_suspend(&idev->rnc,
suspend_type, NULL, NULL);
SCI_SOFTWARE_SUSPENSION,
SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT,
NULL, NULL);
}

enum sci_status sci_remote_device_frame_handler(struct isci_remote_device *idev,
Expand Down Expand Up @@ -412,8 +404,6 @@ static void atapi_remote_device_resume_done(void *_dev)
enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev,
u32 event_code)
{
struct sci_base_state_machine *sm = &idev->sm;
enum sci_remote_device_states state = sm->current_state_id;
enum sci_status status;

switch (scu_get_event_type(event_code)) {
Expand All @@ -427,9 +417,11 @@ enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev,
status = SCI_SUCCESS;

/* Suspend the associated RNC */
sci_remote_node_context_suspend(&idev->rnc,
SCI_SOFTWARE_SUSPENSION,
NULL, NULL);
sci_remote_node_context_suspend(
&idev->rnc,
SCI_SOFTWARE_SUSPENSION,
SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT,
NULL, NULL);

dev_dbg(scirdev_to_dev(idev),
"%s: device: %p event code: %x: %s\n",
Expand All @@ -455,26 +447,6 @@ enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev,
if (status != SCI_SUCCESS)
return status;

if (state == SCI_STP_DEV_ATAPI_ERROR) {
/* For ATAPI error state resume the RNC right away. */
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) {
return sci_remote_node_context_resume(&idev->rnc,
atapi_remote_device_resume_done,
idev);
}
}

if (state == SCI_STP_DEV_IDLE) {

/* We pick up suspension events to handle specifically to this
* state. We resume the RNC right away.
*/
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 = sci_remote_node_context_resume(&idev->rnc, NULL, NULL);
}

return status;
}

Expand Down Expand Up @@ -765,11 +737,11 @@ enum sci_status sci_remote_device_start_task(struct isci_host *ihost,
* the correct action when the remote node context is suspended
* and later resumed.
*/
sci_remote_node_context_suspend(&idev->rnc,
SCI_SOFTWARE_SUSPENSION, NULL, NULL);
sci_remote_node_context_resume(&idev->rnc,
sci_remote_device_continue_request,
idev);
sci_remote_node_context_suspend(
&idev->rnc, SCI_SOFTWARE_SUSPENSION,
SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT, NULL, NULL);
sci_remote_node_context_resume(
&idev->rnc, sci_remote_device_continue_request, idev);

out:
sci_remote_device_start_request(idev, ireq, status);
Expand Down Expand Up @@ -954,14 +926,23 @@ static void sci_remote_device_ready_state_exit(struct sci_base_state_machine *sm
static void sci_remote_device_resetting_state_enter(struct sci_base_state_machine *sm)
{
struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);
struct isci_host *ihost = idev->owning_port->owning_controller;

dev_dbg(&ihost->pdev->dev,
"%s: isci_device = %p\n", __func__, idev);

sci_remote_node_context_suspend(
&idev->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL);
&idev->rnc, SCI_SOFTWARE_SUSPENSION,
SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT, NULL, NULL);
}

static void sci_remote_device_resetting_state_exit(struct sci_base_state_machine *sm)
{
struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);
struct isci_host *ihost = idev->owning_port->owning_controller;

dev_dbg(&ihost->pdev->dev,
"%s: isci_device = %p\n", __func__, idev);

sci_remote_node_context_resume(&idev->rnc, NULL, NULL);
}
Expand Down Expand Up @@ -1004,6 +985,21 @@ static void sci_stp_remote_device_ready_ncq_error_substate_enter(struct sci_base
idev->not_ready_reason);
}

static void sci_stp_remote_device_atapi_error_substate_enter(
struct sci_base_state_machine *sm)
{
struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);

/* This state is entered when an I/O is decoded with an error
* condition. By this point the RNC expected suspension state is set.
* The error conditions suspend the device, so unsuspend here if
* possible.
*/
sci_remote_node_context_resume(&idev->rnc,
atapi_remote_device_resume_done,
idev);
}

static void sci_smp_remote_device_ready_idle_substate_enter(struct sci_base_state_machine *sm)
{
struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);
Expand Down Expand Up @@ -1054,7 +1050,9 @@ static const struct sci_base_state sci_remote_device_state_table[] = {
[SCI_STP_DEV_NCQ_ERROR] = {
.enter_state = sci_stp_remote_device_ready_ncq_error_substate_enter,
},
[SCI_STP_DEV_ATAPI_ERROR] = { },
[SCI_STP_DEV_ATAPI_ERROR] = {
.enter_state = sci_stp_remote_device_atapi_error_substate_enter,
},
[SCI_STP_DEV_AWAIT_RESET] = { },
[SCI_SMP_DEV_IDLE] = {
.enter_state = sci_smp_remote_device_ready_idle_substate_enter,
Expand Down
4 changes: 0 additions & 4 deletions trunk/drivers/scsi/isci/remote_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -331,10 +331,6 @@ enum sci_status sci_remote_device_complete_io(
struct isci_remote_device *idev,
struct isci_request *ireq);

enum sci_status sci_remote_device_suspend(
struct isci_remote_device *idev,
u32 suspend_type);

void sci_remote_device_post_request(
struct isci_remote_device *idev,
u32 request);
Expand Down
74 changes: 51 additions & 23 deletions trunk/drivers/scsi/isci/remote_node_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ enum sci_status sci_remote_node_context_event_handler(struct sci_remote_node_con
u32 event_code)
{
enum scis_sds_remote_node_context_states state;
u32 next_state;

state = sci_rnc->sm.current_state_id;
switch (state) {
Expand Down Expand Up @@ -425,11 +426,11 @@ enum sci_status sci_remote_node_context_event_handler(struct sci_remote_node_con
switch (scu_get_event_type(event_code)) {
case SCU_EVENT_TL_RNC_SUSPEND_TX:
sci_change_state(&sci_rnc->sm, SCI_RNC_TX_SUSPENDED);
sci_rnc->suspension_code = scu_get_event_specifier(event_code);
sci_rnc->suspend_type = scu_get_event_type(event_code);
break;
case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
sci_change_state(&sci_rnc->sm, SCI_RNC_TX_RX_SUSPENDED);
sci_rnc->suspension_code = scu_get_event_specifier(event_code);
sci_rnc->suspend_type = scu_get_event_type(event_code);
break;
default:
goto out;
Expand All @@ -438,16 +439,16 @@ enum sci_status sci_remote_node_context_event_handler(struct sci_remote_node_con
case SCI_RNC_AWAIT_SUSPENSION:
switch (scu_get_event_type(event_code)) {
case SCU_EVENT_TL_RNC_SUSPEND_TX:
sci_change_state(&sci_rnc->sm, SCI_RNC_TX_SUSPENDED);
sci_rnc->suspension_code = scu_get_event_specifier(event_code);
next_state = SCI_RNC_TX_SUSPENDED;
break;
case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
sci_change_state(&sci_rnc->sm, SCI_RNC_TX_RX_SUSPENDED);
sci_rnc->suspension_code = scu_get_event_specifier(event_code);
next_state = SCI_RNC_TX_RX_SUSPENDED;
break;
default:
goto out;
}
if (sci_rnc->suspend_type == scu_get_event_type(event_code))
sci_change_state(&sci_rnc->sm, next_state);
break;
default:
dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
Expand Down Expand Up @@ -502,33 +503,60 @@ enum sci_status sci_remote_node_context_destruct(struct sci_remote_node_context
}
}

enum sci_status sci_remote_node_context_suspend(struct sci_remote_node_context *sci_rnc,
u32 suspend_type,
scics_sds_remote_node_context_callback cb_fn,
void *cb_p)
enum sci_status sci_remote_node_context_suspend(
struct sci_remote_node_context *sci_rnc,
enum sci_remote_node_suspension_reasons suspend_reason,
u32 suspend_type,
scics_sds_remote_node_context_callback cb_fn,
void *cb_p)
{
enum scis_sds_remote_node_context_states state;
enum scis_sds_remote_node_context_states state
= sci_rnc->sm.current_state_id;
struct isci_remote_device *idev = rnc_to_dev(sci_rnc);
enum sci_status status = SCI_FAILURE_INVALID_STATE;

state = sci_rnc->sm.current_state_id;
if (state != SCI_RNC_READY) {
/* Disable automatic state continuations if explicitly suspending. */
if (suspend_reason == SCI_SOFTWARE_SUSPENSION)
sci_rnc->destination_state
= SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
switch (state) {
case SCI_RNC_READY:
break;
case SCI_RNC_TX_SUSPENDED:
if (suspend_type == SCU_EVENT_TL_RNC_SUSPEND_TX)
status = SCI_SUCCESS;
break;
case SCI_RNC_TX_RX_SUSPENDED:
if (suspend_type == SCU_EVENT_TL_RNC_SUSPEND_TX_RX)
status = SCI_SUCCESS;
break;
case SCI_RNC_AWAIT_SUSPENSION:
if ((sci_rnc->suspend_type == SCU_EVENT_TL_RNC_SUSPEND_TX_RX)
|| (suspend_type == sci_rnc->suspend_type))
return SCI_SUCCESS;
break;
default:
dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
"%s: invalid state %s\n", __func__,
rnc_state_name(state));
return SCI_FAILURE_INVALID_STATE;
}
sci_rnc->user_callback = cb_fn;
sci_rnc->user_cookie = cb_p;
sci_rnc->suspend_type = suspend_type;

sci_rnc->user_callback = cb_fn;
sci_rnc->user_cookie = cb_p;
sci_rnc->suspension_code = suspend_type;

if (suspend_type == SCI_SOFTWARE_SUSPENSION) {
sci_remote_device_post_request(rnc_to_dev(sci_rnc),
SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX);
isci_dev_set_hang_detection_timeout(rnc_to_dev(sci_rnc),
0x00000001);
if (status == SCI_SUCCESS) { /* Already in the destination state? */
sci_remote_node_context_notify_user(sci_rnc);
return SCI_SUCCESS;
}
if (suspend_reason == SCI_SOFTWARE_SUSPENSION) {
isci_dev_set_hang_detection_timeout(idev, 0x00000001);
sci_remote_device_post_request(
idev, SCI_SOFTWARE_SUSPEND_CMD);
}
if (state != SCI_RNC_AWAIT_SUSPENSION)
sci_change_state(&sci_rnc->sm, SCI_RNC_AWAIT_SUSPENSION);

sci_change_state(&sci_rnc->sm, SCI_RNC_AWAIT_SUSPENSION);
return SCI_SUCCESS;
}

Expand Down
13 changes: 9 additions & 4 deletions trunk/drivers/scsi/isci/remote_node_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,12 @@
*/
#define SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX 0x0FFF

#define SCU_HARDWARE_SUSPENSION (0)
#define SCI_SOFTWARE_SUSPENSION (1)
enum sci_remote_node_suspension_reasons {
SCU_HARDWARE_SUSPENSION,
SCI_SOFTWARE_SUSPENSION
};
#define SCI_SOFTWARE_SUSPEND_CMD SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX
#define SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT SCU_EVENT_TL_RNC_SUSPEND_TX_RX

struct isci_request;
struct isci_remote_device;
Expand Down Expand Up @@ -156,10 +160,10 @@ struct sci_remote_node_context {
u16 remote_node_index;

/**
* This field is the recored suspension code or the reason for the remote node
* This field is the recored suspension type of the remote node
* context suspension.
*/
u32 suspension_code;
u32 suspend_type;

/**
* This field is true if the remote node context is resuming from its current
Expand Down Expand Up @@ -200,6 +204,7 @@ enum sci_status sci_remote_node_context_destruct(struct sci_remote_node_context
void *callback_parameter);
enum sci_status sci_remote_node_context_suspend(struct sci_remote_node_context *sci_rnc,
u32 suspend_type,
u32 suspension_code,
scics_sds_remote_node_context_callback cb_fn,
void *cb_p);
enum sci_status sci_remote_node_context_resume(struct sci_remote_node_context *sci_rnc,
Expand Down
Loading

0 comments on commit 1b3c470

Please sign in to comment.