scsi: hisi_sas: check for SAS_TASK_STATE_ABORTED in slot complete
authorJohn Garry <john.garry@huawei.com>
Wed, 22 Mar 2017 17:25:27 +0000 (01:25 +0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 23 Mar 2017 15:12:02 +0000 (11:12 -0400)
Check in slot_complete_v2_hw() for whether a task has already been
completed by upper layer.

Signed-off-by: John Garry <john.garry@huawei.com>
Reviewed-by: Xiang Chen <chenxiang66@hisilicon.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/hisi_sas/hisi_sas_v2_hw.c

index ad5a7e6970436e1530190bdc22fa3b411ac35e5d..f4d8200ae7e298ebfb23dd8dc952ec41ba6e123a 100644 (file)
@@ -1737,6 +1737,7 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
                        hisi_hba->complete_hdr[slot->cmplt_queue];
        struct hisi_sas_complete_v2_hdr *complete_hdr =
                        &complete_queue[slot->cmplt_queue_slot];
+       int aborted;
 
        if (unlikely(!task || !task->lldd_task || !task->dev))
                return -EINVAL;
@@ -1745,12 +1746,21 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
        device = task->dev;
        sas_dev = device->lldd_dev;
 
+       spin_lock(&task->task_state_lock);
+       aborted = task->task_state_flags & SAS_TASK_STATE_ABORTED;
        task->task_state_flags &=
                ~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR);
+       spin_unlock(&task->task_state_lock);
 
        memset(ts, 0, sizeof(*ts));
        ts->resp = SAS_TASK_COMPLETE;
 
+       if (unlikely(aborted)) {
+               ts->stat = SAS_ABORTED_TASK;
+               hisi_sas_slot_task_free(hisi_hba, task, slot);
+               return -1;
+       }
+
        if (unlikely(!sas_dev)) {
                dev_dbg(dev, "slot complete: port has no device\n");
                ts->stat = SAS_PHY_DOWN;