From: Xiang Chen Date: Wed, 14 Jun 2017 15:33:11 +0000 (+0800) Subject: scsi: hisi_sas: fix timeout check in hisi_sas_internal_task_abort() X-Git-Tag: v4.13-rc1~136^2~122 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=f64a6988268aae866bb6ce6edb910d454ccef331;p=karo-tx-linux.git scsi: hisi_sas: fix timeout check in hisi_sas_internal_task_abort() We need to check for timeout before task status, or the task will be mistook as completed internal abort command. Also add protection for sas_task.task_state_flags in hisi_sas_tmf_timedout(). Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index f720d3ced851..3605d28a2c60 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -691,8 +691,13 @@ static void hisi_sas_task_done(struct sas_task *task) static void hisi_sas_tmf_timedout(unsigned long data) { struct sas_task *task = (struct sas_task *)data; + unsigned long flags; + + spin_lock_irqsave(&task->task_state_lock, flags); + if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) + task->task_state_flags |= SAS_TASK_STATE_ABORTED; + spin_unlock_irqrestore(&task->task_state_lock, flags); - task->task_state_flags |= SAS_TASK_STATE_ABORTED; complete(&task->slow_task->completion); } @@ -1247,6 +1252,17 @@ hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, wait_for_completion(&task->slow_task->completion); res = TMF_RESP_FUNC_FAILED; + /* Internal abort timed out */ + if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { + if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { + struct hisi_sas_slot *slot = task->lldd_task; + + if (slot) + slot->task = NULL; + dev_err(dev, "internal task abort: timeout.\n"); + } + } + if (task->task_status.resp == SAS_TASK_COMPLETE && task->task_status.stat == TMF_RESP_FUNC_COMPLETE) { res = TMF_RESP_FUNC_COMPLETE; @@ -1259,13 +1275,6 @@ hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, goto exit; } - /* Internal abort timed out */ - if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { - if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { - dev_err(dev, "internal task abort: timeout.\n"); - } - } - exit: dev_dbg(dev, "internal task abort: task to dev %016llx task=%p " "resp: 0x%x sts 0x%x\n",