diff options
author | Jeff Skirvin <jeffrey.d.skirvin@intel.com> | 2012-09-06 00:36:47 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-09-24 04:11:04 -0400 |
commit | 54b46677757ff8d6c282305fc7710f466b63d6dc (patch) | |
tree | f9d228e23ee1e5567746cce654a033bff27e7441 /drivers/scsi/isci | |
parent | 2c8bd81010ed9377e761893487803a9b7408014d (diff) |
[SCSI] isci: Allow SSP tasks into the task management path.
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>
Diffstat (limited to 'drivers/scsi/isci')
-rw-r--r-- | drivers/scsi/isci/host.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index bc8981ed02b..d4daa0f2459 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) | |||
1079 | 1079 | ||
1080 | void ireq_done(struct isci_host *ihost, struct isci_request *ireq, struct sas_task *task) | 1080 | void ireq_done(struct isci_host *ihost, struct isci_request *ireq, struct sas_task *task) |
1081 | { | 1081 | { |
1082 | task->lldd_task = NULL; | ||
1083 | if (!test_bit(IREQ_ABORT_PATH_ACTIVE, &ireq->flags) && | 1082 | if (!test_bit(IREQ_ABORT_PATH_ACTIVE, &ireq->flags) && |
1084 | !(task->task_state_flags & SAS_TASK_STATE_ABORTED)) { | 1083 | !(task->task_state_flags & SAS_TASK_STATE_ABORTED)) { |
1085 | if (test_bit(IREQ_COMPLETE_IN_TARGET, &ireq->flags)) { | 1084 | 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 | |||
1087 | dev_dbg(&ihost->pdev->dev, | 1086 | dev_dbg(&ihost->pdev->dev, |
1088 | "%s: Normal - ireq/task = %p/%p\n", | 1087 | "%s: Normal - ireq/task = %p/%p\n", |
1089 | __func__, ireq, task); | 1088 | __func__, ireq, task); |
1090 | 1089 | task->lldd_task = NULL; | |
1091 | task->task_done(task); | 1090 | task->task_done(task); |
1092 | } else { | 1091 | } else { |
1093 | dev_dbg(&ihost->pdev->dev, | 1092 | dev_dbg(&ihost->pdev->dev, |
1094 | "%s: Error - ireq/task = %p/%p\n", | 1093 | "%s: Error - ireq/task = %p/%p\n", |
1095 | __func__, ireq, task); | 1094 | __func__, ireq, task); |
1096 | 1095 | if (sas_protocol_ata(task->task_proto)) | |
1096 | task->lldd_task = NULL; | ||
1097 | sas_task_abort(task); | 1097 | sas_task_abort(task); |
1098 | } | 1098 | } |
1099 | } | 1099 | } else |
1100 | task->lldd_task = NULL; | ||
1101 | |||
1100 | if (test_and_clear_bit(IREQ_ABORT_PATH_ACTIVE, &ireq->flags)) | 1102 | if (test_and_clear_bit(IREQ_ABORT_PATH_ACTIVE, &ireq->flags)) |
1101 | wake_up_all(&ihost->eventq); | 1103 | wake_up_all(&ihost->eventq); |
1102 | 1104 | ||