aboutsummaryrefslogtreecommitdiff
path: root/drivers/scsi/isci/remote_device.c
diff options
context:
space:
mode:
authorJeff Skirvin <jeffrey.d.skirvin@intel.com>2011-06-23 17:09:02 -0700
committerDan Williams <dan.j.williams@intel.com>2011-07-03 04:04:51 -0700
commit9274f45ea551421cd3bf329de9dd8d1e6208285a (patch)
tree25e21494d3c74a5b2965485f2d76c541d49cc68b /drivers/scsi/isci/remote_device.c
parent4cffe13e0dfd00f90c86b0153c751dab61a1bf1d (diff)
isci: Terminate dev requests on FIS err bit rx in NCQ
When the remote device transitions to a not-ready state because of an NCQ error condition, all outstanding requests to that device are terminated and completed to libsas on the normal path. The device then waits for a READ LOG EXT command to issue on the task management path. 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_device.c')
-rw-r--r--drivers/scsi/isci/remote_device.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c
index 9f45c2ba730..c5ce0f0f364 100644
--- a/drivers/scsi/isci/remote_device.c
+++ b/drivers/scsi/isci/remote_device.c
@@ -68,17 +68,39 @@
* @isci_host: This parameter specifies the isci host object.
* @isci_device: This parameter specifies the remote device
*
+ * scic_lock is held on entrance to this function.
*/
static void isci_remote_device_not_ready(struct isci_host *ihost,
struct isci_remote_device *idev, u32 reason)
{
+ struct isci_request * ireq;
+
dev_dbg(&ihost->pdev->dev,
"%s: isci_device = %p\n", __func__, idev);
- if (reason == SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED)
+ switch (reason) {
+ case SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED:
set_bit(IDEV_GONE, &idev->flags);
- else
+ break;
+ case SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED:
+ set_bit(IDEV_IO_NCQERROR, &idev->flags);
+
+ /* Kill all outstanding requests for the device. */
+ list_for_each_entry(ireq, &idev->reqs_in_process, dev_node) {
+
+ dev_dbg(&ihost->pdev->dev,
+ "%s: isci_device = %p request = %p\n",
+ __func__, idev, ireq);
+
+ scic_controller_terminate_request(&ihost->sci,
+ &idev->sci,
+ &ireq->sci);
+ }
+ /* Fall through into the default case... */
+ default:
clear_bit(IDEV_IO_READY, &idev->flags);
+ break;
+ }
}
/**
@@ -94,6 +116,7 @@ static void isci_remote_device_ready(struct isci_host *ihost, struct isci_remote
dev_dbg(&ihost->pdev->dev,
"%s: idev = %p\n", __func__, idev);
+ clear_bit(IDEV_IO_NCQERROR, &idev->flags);
set_bit(IDEV_IO_READY, &idev->flags);
if (test_and_clear_bit(IDEV_START_PENDING, &idev->flags))
wake_up(&ihost->eventq);