diff options
author | Jeff Skirvin <jeffrey.d.skirvin@intel.com> | 2012-03-09 07:41:50 +0100 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2012-05-17 23:33:37 +0200 |
commit | 726980d56908f2e230624394f03743689db3110c (patch) | |
tree | 6aca898ea8f57c276088feb2eed5770fba6dfd86 /drivers/scsi/isci/remote_node_context.c | |
parent | isci: Handle all suspending TC completions (diff) | |
download | linux-726980d56908f2e230624394f03743689db3110c.tar.xz linux-726980d56908f2e230624394f03743689db3110c.zip |
isci: Terminate outstanding TCs on TX/RX RNC suspensions.
TCs must only be terminated when RNCs are suspended.
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.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index f180c726c5bb..7a8347e51767 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -268,6 +268,8 @@ static void sci_remote_node_context_invalidating_state_enter(struct sci_base_sta { struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); + /* Terminate outstanding requests pending abort. */ + sci_remote_device_abort_requests_pending_abort(rnc_to_dev(rnc)); sci_remote_node_context_invalidate_context_buffer(rnc); } @@ -312,10 +314,28 @@ static void sci_remote_node_context_tx_suspended_state_enter(struct sci_base_sta static void sci_remote_node_context_tx_rx_suspended_state_enter(struct sci_base_state_machine *sm) { struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); + struct isci_remote_device *idev = rnc_to_dev(rnc); + struct isci_host *ihost = idev->owning_port->owning_controller; + + set_bit(IDEV_TXRX_SUSPENDED, &idev->flags); + /* Terminate outstanding requests pending abort. */ + sci_remote_device_abort_requests_pending_abort(idev); + + wake_up(&ihost->eventq); sci_remote_node_context_continue_state_transitions(rnc); } +static void sci_remote_node_context_tx_rx_suspended_state_exit( + struct sci_base_state_machine *sm) +{ + struct sci_remote_node_context *rnc + = container_of(sm, typeof(*rnc), sm); + struct isci_remote_device *idev = rnc_to_dev(rnc); + + clear_bit(IDEV_TXRX_SUSPENDED, &idev->flags); +} + static void sci_remote_node_context_await_suspend_state_exit( struct sci_base_state_machine *sm) { @@ -346,6 +366,8 @@ 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, + .exit_state + = sci_remote_node_context_tx_rx_suspended_state_exit, }, [SCI_RNC_AWAIT_SUSPENSION] = { .exit_state = sci_remote_node_context_await_suspend_state_exit, @@ -515,6 +537,13 @@ enum sci_status sci_remote_node_context_suspend( struct isci_remote_device *idev = rnc_to_dev(sci_rnc); enum sci_status status = SCI_FAILURE_INVALID_STATE; + dev_dbg(scirdev_to_dev(idev), + "%s: current state %d, current suspend_type %x dest state %d," + " arg suspend_reason %d, arg suspend_type %x", + __func__, state, sci_rnc->suspend_type, + sci_rnc->destination_state, suspend_reason, + suspend_type); + /* Disable automatic state continuations if explicitly suspending. */ if (suspend_reason == SCI_SOFTWARE_SUSPENSION) sci_rnc->destination_state @@ -546,7 +575,10 @@ enum sci_status sci_remote_node_context_suspend( sci_rnc->suspend_type = suspend_type; if (status == SCI_SUCCESS) { /* Already in the destination state? */ + struct isci_host *ihost = idev->owning_port->owning_controller; + sci_remote_node_context_notify_user(sci_rnc); + wake_up_all(&ihost->eventq); /* Let observers look. */ return SCI_SUCCESS; } if (suspend_reason == SCI_SOFTWARE_SUSPENSION) { @@ -661,3 +693,27 @@ enum sci_status sci_remote_node_context_start_task(struct sci_remote_node_contex return SCI_FAILURE_INVALID_STATE; } } + +int sci_remote_node_context_is_safe_to_abort( + struct sci_remote_node_context *sci_rnc) +{ + enum scis_sds_remote_node_context_states state; + + state = sci_rnc->sm.current_state_id; + switch (state) { + case SCI_RNC_INVALIDATING: + case SCI_RNC_TX_RX_SUSPENDED: + return 1; + case SCI_RNC_POSTING: + case SCI_RNC_RESUMING: + case SCI_RNC_READY: + case SCI_RNC_TX_SUSPENDED: + case SCI_RNC_AWAIT_SUSPENSION: + case SCI_RNC_INITIAL: + return 0; + default: + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: invalid state %d\n", __func__, state); + return 0; + } +} |