[SCSI] isci: Fix a race condition in the SSP task management path
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / scsi / isci / task.c
index 9bb020a..0d30ca8 100644 (file)
@@ -491,6 +491,7 @@ int isci_task_abort_task(struct sas_task *task)
        struct isci_tmf           tmf;
        int                       ret = TMF_RESP_FUNC_FAILED;
        unsigned long             flags;
+       int                       target_done_already = 0;
 
        /* Get the isci_request reference from the task.  Note that
         * this check does not depend on the pending request list
@@ -505,9 +506,11 @@ int isci_task_abort_task(struct sas_task *task)
        /* If task is already done, the request isn't valid */
        if (!(task->task_state_flags & SAS_TASK_STATE_DONE) &&
            (task->task_state_flags & SAS_TASK_AT_INITIATOR) &&
-           old_request)
+           old_request) {
                idev = isci_get_device(task->dev->lldd_dev);
-
+               target_done_already = test_bit(IREQ_COMPLETE_IN_TARGET,
+                                              &old_request->flags);
+       }
        spin_unlock(&task->task_state_lock);
        spin_unlock_irqrestore(&ihost->scic_lock, flags);
 
@@ -561,7 +564,7 @@ int isci_task_abort_task(struct sas_task *task)
 
        if (task->task_proto == SAS_PROTOCOL_SMP ||
            sas_protocol_ata(task->task_proto) ||
-           test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags) ||
+           target_done_already ||
            test_bit(IDEV_GONE, &idev->flags)) {
 
                spin_unlock_irqrestore(&ihost->scic_lock, flags);