Message ID | 1566222208-19890-1-git-send-email-stanley.chu@mediatek.com (mailing list archive) |
---|---|
State | Mainlined |
Commit | b557217c8475f40bc765ee20ff6b3b9124c8a4fe |
Headers | show |
Series | [v3] scsi: ufs: fix broken hba->outstanding_tasks | expand |
> > Currently bits in hba->outstanding_tasks are cleared only after their > corresponding task management commands are successfully done by > __ufshcd_issue_tm_cmd(). > > If timeout happens in a task management command, its corresponding > bit in hba->outstanding_tasks will not be cleared until next task > management command with the same tag used successfully finishes. > > This is wrong and can lead to some issues, like power issue. > For example, ufshcd_release() and ufshcd_gate_work() will do nothing > if hba->outstanding_tasks is not zero even if both UFS host and devices > are actually idle. > > Solution is referried from error handling of device commands: bits in > hba->outstanding_tasks shall be cleared regardless of their execution > results. > > Signed-off-by: Stanley Chu <stanley.chu@mediatek.com> > Signed-off-by: Chun-Hung Wu <chun-hung.wu@mediatek.com> Reviewed-by: Avri Altman <avri.altman@wdc.com>
Stanley, > Currently bits in hba->outstanding_tasks are cleared only after their > corresponding task management commands are successfully done by > __ufshcd_issue_tm_cmd(). Applied to 5.4/scsi-queue. Thank you!
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 3804a704e565..30b752c61b97 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -5676,13 +5676,12 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba, memcpy(treq, hba->utmrdl_base_addr + free_slot, sizeof(*treq)); ufshcd_add_tm_upiu_trace(hba, task_tag, "tm_complete"); - - spin_lock_irqsave(hba->host->host_lock, flags); - __clear_bit(free_slot, &hba->outstanding_tasks); - spin_unlock_irqrestore(hba->host->host_lock, flags); - } + spin_lock_irqsave(hba->host->host_lock, flags); + __clear_bit(free_slot, &hba->outstanding_tasks); + spin_unlock_irqrestore(hba->host->host_lock, flags); + clear_bit(free_slot, &hba->tm_condition); ufshcd_put_tm_slot(hba, free_slot); wake_up(&hba->tm_tag_wq);