ufshcd_clk_scaling_start_busy(hba);
        if (unlikely(ufshcd_should_inform_monitor(hba, lrbp)))
                ufshcd_start_monitor(hba, lrbp);
-       spin_lock_irqsave(hba->host->host_lock, flags);
+
+       spin_lock_irqsave(&hba->outstanding_lock, flags);
        if (hba->vops && hba->vops->setup_xfer_req)
                hba->vops->setup_xfer_req(hba, task_tag, !!lrbp->cmd);
-       set_bit(task_tag, &hba->outstanding_reqs);
+       __set_bit(task_tag, &hba->outstanding_reqs);
        ufshcd_writel(hba, 1 << task_tag, REG_UTP_TRANSFER_REQ_DOOR_BELL);
-       spin_unlock_irqrestore(hba->host->host_lock, flags);
+       spin_unlock_irqrestore(&hba->outstanding_lock, flags);
+
        /* Make sure that doorbell is committed immediately */
        wmb();
 }
                 * we also need to clear the outstanding_request
                 * field in hba
                 */
-               clear_bit(lrbp->task_tag, &hba->outstanding_reqs);
+               spin_lock_irqsave(&hba->outstanding_lock, flags);
+               __clear_bit(lrbp->task_tag, &hba->outstanding_reqs);
+               spin_unlock_irqrestore(&hba->outstanding_lock, flags);
        }
 
        return err;
        bool update_scaling = false;
 
        for_each_set_bit(index, &completed_reqs, hba->nutrs) {
-               if (!test_and_clear_bit(index, &hba->outstanding_reqs))
-                       continue;
                lrbp = &hba->lrb[index];
                lrbp->compl_time_stamp = ktime_get();
                cmd = lrbp->cmd;
            !(hba->quirks & UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR))
                ufshcd_reset_intr_aggr(hba);
 
-       spin_lock_irqsave(hba->host->host_lock, flags);
+       spin_lock_irqsave(&hba->outstanding_lock, flags);
        tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
-       completed_reqs = tr_doorbell ^ hba->outstanding_reqs;
-       spin_unlock_irqrestore(hba->host->host_lock, flags);
+       completed_reqs = ~tr_doorbell & hba->outstanding_reqs;
+       WARN_ONCE(completed_reqs & ~hba->outstanding_reqs,
+                 "completed: %#lx; outstanding: %#lx\n", completed_reqs,
+                 hba->outstanding_reqs);
+       hba->outstanding_reqs &= ~completed_reqs;
+       spin_unlock_irqrestore(&hba->outstanding_lock, flags);
 
        if (completed_reqs) {
                __ufshcd_transfer_req_compl(hba, completed_reqs);
        hba = shost_priv(host);
        hba->host = host;
        hba->dev = dev;
-       *hba_handle = hba;
        hba->dev_ref_clk_freq = REF_CLK_FREQ_INVAL;
-
        INIT_LIST_HEAD(&hba->clk_list_head);
+       spin_lock_init(&hba->outstanding_lock);
+
+       *hba_handle = hba;
 
 out_error:
        return err;
 
  * @lrb: local reference block
  * @cmd_queue: Used to allocate command tags from hba->host->tag_set.
  * @outstanding_tasks: Bits representing outstanding task requests
+ * @outstanding_lock: Protects @outstanding_reqs.
  * @outstanding_reqs: Bits representing outstanding transfer requests
  * @capabilities: UFS Controller Capabilities
  * @nutrs: Transfer Request Queue depth supported by controller
        struct ufshcd_lrb *lrb;
 
        unsigned long outstanding_tasks;
+       spinlock_t outstanding_lock;
        unsigned long outstanding_reqs;
 
        u32 capabilities;