summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Skirvin <jeffrey.d.skirvin@intel.com>2012-09-05 21:36:47 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-11-26 12:14:20 -0800
commit0c46d72c25ddabd39d02ce5d63fc722f59671c1d (patch)
treee7dc342ff21a4edbb5e34b5817762138ca2acd23
parent605e644a5c9a8665b39d544354cfc4aafcefc694 (diff)
downloadlwn-0c46d72c25ddabd39d02ce5d63fc722f59671c1d.tar.gz
lwn-0c46d72c25ddabd39d02ce5d63fc722f59671c1d.zip
SCSI: isci: Allow SSP tasks into the task management path.
commit 54b46677757ff8d6c282305fc7710f466b63d6dc upstream. This commit fixes a driver bug for SSP tasks that require task management in the target after they complete in the SCU hardware. The problem was manifested in the function "isci_task_abort_task", which tests to see if the sas_task.lldd_task is non-NULL before allowing task management; this bug would always NULL lldd_task in the SCU I/O completion path even if target management was required, which would prevent task / target manangement from happening. Note that in the case of SATA/STP targets, error recovery is provided by the libata error handler which is why SATA/STP device recovery worked correctly even though SSP handling did not. Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com> Cc: "Dorau, Lukasz" <lukasz.dorau@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/scsi/isci/host.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c
index 45385f531649..446fdd831b08 100644
--- a/drivers/scsi/isci/host.c
+++ b/drivers/scsi/isci/host.c
@@ -1079,7 +1079,6 @@ static void sci_controller_completion_handler(struct isci_host *ihost)
void ireq_done(struct isci_host *ihost, struct isci_request *ireq, struct sas_task *task)
{
- task->lldd_task = NULL;
if (!test_bit(IREQ_ABORT_PATH_ACTIVE, &ireq->flags) &&
!(task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
if (test_bit(IREQ_COMPLETE_IN_TARGET, &ireq->flags)) {
@@ -1087,16 +1086,19 @@ void ireq_done(struct isci_host *ihost, struct isci_request *ireq, struct sas_ta
dev_dbg(&ihost->pdev->dev,
"%s: Normal - ireq/task = %p/%p\n",
__func__, ireq, task);
-
+ task->lldd_task = NULL;
task->task_done(task);
} else {
dev_dbg(&ihost->pdev->dev,
"%s: Error - ireq/task = %p/%p\n",
__func__, ireq, task);
-
+ if (sas_protocol_ata(task->task_proto))
+ task->lldd_task = NULL;
sas_task_abort(task);
}
- }
+ } else
+ task->lldd_task = NULL;
+
if (test_and_clear_bit(IREQ_ABORT_PATH_ACTIVE, &ireq->flags))
wake_up_all(&ihost->eventq);