scsi: ufs: fix to clear the bit of outstanding_tasks
authorhgchu <hg.chu@samsung.com>
Fri, 12 Jan 2018 01:04:23 +0000 (10:04 +0900)
committerJaeHun Jung <jh0801.jung@samsung.com>
Tue, 8 May 2018 08:20:11 +0000 (17:20 +0900)
Change-Id: I5f24c3783eca5102b5b3c098cfcd39d75a0f451a
Signed-off-by: hgchu <hg.chu@samsung.com>
drivers/scsi/ufs/ufshcd.c

index 4a4a36e1fcee52616425d72d51f29b10ee3d9ab0..81ad7ba440629ee43e6004babe97da519f0f0e4c 100644 (file)
@@ -4501,9 +4501,6 @@ static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp)
 
        spin_lock_irqsave(hba->host->host_lock, flags);
 
-       /* Clear completed tasks from outstanding_tasks */
-       __clear_bit(index, &hba->outstanding_tasks);
-
        task_req_descp = hba->utmrdl_base_addr;
        ocs_value = ufshcd_get_tmr_ocs(&task_req_descp[index]);
 
@@ -5391,6 +5388,7 @@ static void ufshcd_tmc_handler(struct ufs_hba *hba)
 
        tm_doorbell = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
        hba->tm_condition = tm_doorbell ^ hba->outstanding_tasks;
+       hba->outstanding_tasks ^= hba->tm_condition;
        wake_up(&hba->tm_wq);
 }
 
@@ -5451,9 +5449,6 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag)
        u32 mask = 1 << tag;
        unsigned long flags;
 
-       if (!test_bit(tag, &hba->outstanding_tasks))
-               goto out;
-
        spin_lock_irqsave(hba->host->host_lock, flags);
        ufshcd_utmrl_clear(hba, tag);
        spin_unlock_irqrestore(hba->host->host_lock, flags);
@@ -5462,7 +5457,6 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag)
        err = ufshcd_wait_for_register(hba,
                        REG_UTP_TASK_REQ_DOOR_BELL,
                        mask, 0, 1000, 1000, true);
-out:
        return err;
 }
 
@@ -5543,9 +5537,14 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
        if (!err) {
                dev_err(hba->dev, "%s: task management cmd 0x%.2x timed-out\n",
                                __func__, tm_function);
-               if (ufshcd_clear_tm_cmd(hba, free_slot))
+               if (!ufshcd_clear_tm_cmd(hba, free_slot)) {
+                       spin_lock_irqsave(hba->host->host_lock, flags);
+                       __clear_bit(free_slot, &hba->outstanding_tasks);
+                       spin_unlock_irqrestore(hba->host->host_lock, flags);
+               } else {
                        dev_WARN(hba->dev, "%s: unable clear tm cmd (slot %d) after timeout\n",
                                        __func__, free_slot);
+               }
                err = -ETIMEDOUT;
        } else {
                err = ufshcd_task_req_compl(hba, free_slot, tm_response);