summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/isci/remote_node_context.c
diff options
context:
space:
mode:
authorJeff Skirvin <jeffrey.d.skirvin@intel.com>2012-03-08 22:41:48 -0800
committerDan Williams <dan.j.williams@intel.com>2012-05-17 14:33:36 -0700
commit6f48844e3f16b7d8a1f9a1a11bd9a11089a5292f (patch)
treeaeb95746d05e7bab2b33a9351443e03152e4dfa4 /drivers/scsi/isci/remote_node_context.c
parentfc25f79af321c01a739150ba2c09435cf977a63d (diff)
downloadlinux-6f48844e3f16b7d8a1f9a1a11bd9a11089a5292f.tar.bz2
isci: Manage the link layer hang detect timer for RNC suspensions.
For STP devices under certain protocol conditions, an RNC will not suspend until the current transfer state is broken with a SYNC/ESC sequence from the SCU. The SYNC/ESC driven by expiration of the SCU link layer hang detect timer, which has too small a dynamic range to support slow SATA devices, so normally it is disabled. This change enables the timer with the minimum period at the point when the suspension is requested. Note that there is potential collateral damage to other open connections to slow SATA devices on the same port, since there is no alternative but to enable the LLHANG timer on every phy in the port for the current suspension request - there is no way to tell on which phy the RNC in question is currently active. Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/scsi/isci/remote_node_context.c')
-rw-r--r--drivers/scsi/isci/remote_node_context.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c
index 8ce5a35891e1..3a55ba66b8ac 100644
--- a/drivers/scsi/isci/remote_node_context.c
+++ b/drivers/scsi/isci/remote_node_context.c
@@ -316,6 +316,15 @@ static void sci_remote_node_context_tx_rx_suspended_state_enter(struct sci_base_
sci_remote_node_context_continue_state_transitions(rnc);
}
+static void sci_remote_node_context_await_suspend_state_exit(
+ struct sci_base_state_machine *sm)
+{
+ struct sci_remote_node_context *rnc
+ = container_of(sm, typeof(*rnc), sm);
+
+ isci_dev_set_hang_detection_timeout(rnc_to_dev(rnc), 0);
+}
+
static const struct sci_base_state sci_remote_node_context_state_table[] = {
[SCI_RNC_INITIAL] = {
.enter_state = sci_remote_node_context_initial_state_enter,
@@ -338,7 +347,9 @@ static const struct sci_base_state sci_remote_node_context_state_table[] = {
[SCI_RNC_TX_RX_SUSPENDED] = {
.enter_state = sci_remote_node_context_tx_rx_suspended_state_enter,
},
- [SCI_RNC_AWAIT_SUSPENSION] = { },
+ [SCI_RNC_AWAIT_SUSPENSION] = {
+ .exit_state = sci_remote_node_context_await_suspend_state_exit,
+ },
};
void sci_remote_node_context_construct(struct sci_remote_node_context *rnc,
@@ -513,6 +524,8 @@ enum sci_status sci_remote_node_context_suspend(struct sci_remote_node_context *
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);
}
sci_change_state(&sci_rnc->sm, SCI_RNC_AWAIT_SUSPENSION);