diff options
author | Jeff Skirvin <jeffrey.d.skirvin@intel.com> | 2012-03-09 01:41:52 -0500 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2012-05-17 17:33:37 -0400 |
commit | 23ec2aa947e83d0a172220f361166b8224875221 (patch) | |
tree | 747e299efb5c534d99bc84b9631dedec02b033aa /drivers/scsi/isci | |
parent | 5b6bf225e7fc249c703e19bf2c983d1a59178874 (diff) |
isci: Remote device must be suspended for NCQ cleanup.
When the remote device enters the NCQ error state, the device must
be suspended so that the I/O terminations can take place.
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')
-rw-r--r-- | drivers/scsi/isci/remote_device.c | 25 |
1 files changed, 12 insertions, 13 deletions
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 4f76dcd1cec2..f40d429d2cc0 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c | |||
@@ -72,6 +72,14 @@ const char *dev_state_name(enum sci_remote_device_states state) | |||
72 | } | 72 | } |
73 | #undef C | 73 | #undef C |
74 | 74 | ||
75 | static enum sci_status sci_remote_device_suspend(struct isci_remote_device *idev) | ||
76 | { | ||
77 | return sci_remote_node_context_suspend(&idev->rnc, | ||
78 | SCI_SOFTWARE_SUSPENSION, | ||
79 | SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT, | ||
80 | NULL, NULL); | ||
81 | } | ||
82 | |||
75 | /** | 83 | /** |
76 | * isci_remote_device_not_ready() - This function is called by the ihost when | 84 | * isci_remote_device_not_ready() - This function is called by the ihost when |
77 | * the remote device is not ready. We mark the isci device as ready (not | 85 | * the remote device is not ready. We mark the isci device as ready (not |
@@ -96,6 +104,9 @@ static void isci_remote_device_not_ready(struct isci_host *ihost, | |||
96 | case SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED: | 104 | case SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED: |
97 | set_bit(IDEV_IO_NCQERROR, &idev->flags); | 105 | set_bit(IDEV_IO_NCQERROR, &idev->flags); |
98 | 106 | ||
107 | /* Suspend the remote device so the I/O can be terminated. */ | ||
108 | sci_remote_device_suspend(idev); | ||
109 | |||
99 | /* Kill all outstanding requests for the device. */ | 110 | /* Kill all outstanding requests for the device. */ |
100 | list_for_each_entry(ireq, &idev->reqs_in_process, dev_node) { | 111 | list_for_each_entry(ireq, &idev->reqs_in_process, dev_node) { |
101 | 112 | ||
@@ -103,9 +114,7 @@ static void isci_remote_device_not_ready(struct isci_host *ihost, | |||
103 | "%s: isci_device = %p request = %p\n", | 114 | "%s: isci_device = %p request = %p\n", |
104 | __func__, idev, ireq); | 115 | __func__, idev, ireq); |
105 | 116 | ||
106 | sci_controller_terminate_request(ihost, | 117 | sci_controller_terminate_request(ihost, idev, ireq); |
107 | idev, | ||
108 | ireq); | ||
109 | } | 118 | } |
110 | /* Fall through into the default case... */ | 119 | /* Fall through into the default case... */ |
111 | default: | 120 | default: |
@@ -133,16 +142,6 @@ static void isci_remote_device_ready(struct isci_host *ihost, struct isci_remote | |||
133 | wake_up(&ihost->eventq); | 142 | wake_up(&ihost->eventq); |
134 | } | 143 | } |
135 | 144 | ||
136 | static enum sci_status sci_remote_device_suspend( | ||
137 | struct isci_remote_device *idev) | ||
138 | { | ||
139 | return sci_remote_node_context_suspend( | ||
140 | &idev->rnc, | ||
141 | SCI_SOFTWARE_SUSPENSION, | ||
142 | SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT, | ||
143 | NULL, NULL); | ||
144 | } | ||
145 | |||
146 | static int isci_remote_device_suspendcheck(struct isci_remote_device *idev) | 145 | static int isci_remote_device_suspendcheck(struct isci_remote_device *idev) |
147 | { | 146 | { |
148 | return test_bit(IDEV_TXRX_SUSPENDED, &idev->flags) | 147 | return test_bit(IDEV_TXRX_SUSPENDED, &idev->flags) |