summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/isci/task.c
diff options
context:
space:
mode:
authorJeff Skirvin <jeffrey.d.skirvin@intel.com>2011-06-24 02:09:02 +0200
committerDan Williams <dan.j.williams@intel.com>2011-07-03 13:04:51 +0200
commit9274f45ea551421cd3bf329de9dd8d1e6208285a (patch)
tree25e21494d3c74a5b2965485f2d76c541d49cc68b /drivers/scsi/isci/task.c
parentisci: fix frame received locking (diff)
downloadlinux-9274f45ea551421cd3bf329de9dd8d1e6208285a.tar.xz
linux-9274f45ea551421cd3bf329de9dd8d1e6208285a.zip
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/task.c')
-rw-r--r--drivers/scsi/isci/task.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
index 0835a2c2dc71..157e9978183a 100644
--- a/drivers/scsi/isci/task.c
+++ b/drivers/scsi/isci/task.c
@@ -133,6 +133,15 @@ static void isci_task_refuse(struct isci_host *ihost, struct sas_task *task,
for (; num > 0; num--,\
task = list_entry(task->list.next, struct sas_task, list))
+
+static inline int isci_device_io_ready(struct isci_remote_device *idev,
+ struct sas_task *task)
+{
+ return idev ? test_bit(IDEV_IO_READY, &idev->flags) ||
+ (test_bit(IDEV_IO_NCQERROR, &idev->flags) &&
+ isci_task_is_ncq_recovery(task))
+ : 0;
+}
/**
* isci_task_execute_task() - This function is one of the SAS Domain Template
* functions. This function is called by libsas to send a task down to
@@ -165,7 +174,7 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags)
for_each_sas_task(num, task) {
spin_lock_irqsave(&ihost->scic_lock, flags);
idev = isci_lookup_device(task->dev);
- io_ready = idev ? test_bit(IDEV_IO_READY, &idev->flags) : 0;
+ io_ready = isci_device_io_ready(idev, task);
spin_unlock_irqrestore(&ihost->scic_lock, flags);
dev_dbg(&ihost->pdev->dev,
@@ -178,6 +187,7 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags)
SAS_DEVICE_UNKNOWN);
isci_host_can_dequeue(ihost, 1);
} else if (!io_ready) {
+
/* Indicate QUEUE_FULL so that the scsi midlayer
* retries.
*/
@@ -299,7 +309,9 @@ int isci_task_execute_tmf(struct isci_host *ihost,
/* sanity check, return TMF_RESP_FUNC_FAILED
* if the device is not there and ready.
*/
- if (!isci_device || !test_bit(IDEV_IO_READY, &isci_device->flags)) {
+ if (!isci_device ||
+ (!test_bit(IDEV_IO_READY, &isci_device->flags) &&
+ !test_bit(IDEV_IO_NCQERROR, &isci_device->flags))) {
dev_dbg(&ihost->pdev->dev,
"%s: isci_device = %p not ready (%#lx)\n",
__func__,