scsi: ufs: prevent i/o request during recovery-seq
authorhgchu <hg.chu@samsung.com>
Fri, 12 Jan 2018 03:43:34 +0000 (12:43 +0900)
committerJaeHun Jung <jh0801.jung@samsung.com>
Tue, 8 May 2018 08:20:20 +0000 (17:20 +0900)
Change-Id: I658dd2d95dcda721a9cd8ee8af50968975adc718
Signed-off-by: hgchu <hg.chu@samsung.com>
drivers/scsi/ufs/ufshcd.c
drivers/scsi/ufs/ufshcd.h

index 1e06f3d25c76406c3f8b82563a964eb991d43d1b..01c706d4deae9214426e682a558030b6aa0600da 100644 (file)
@@ -1479,6 +1479,10 @@ int ufshcd_hold(struct ufs_hba *hba, bool async)
 
 start:
        switch (hba->clk_gating.state) {
+       case __CLKS_ON:
+               rc = -EAGAIN;
+               if (async)
+                       hba->clk_gating.active_reqs--;
        case CLKS_ON:
                /*
                 * Wait for the ungate work to complete if in progress.
@@ -1581,7 +1585,9 @@ static void ufshcd_gate_work(struct work_struct *work)
                        spin_unlock_irqrestore(hba->host->host_lock, flags);
                        hba->clk_gating.is_suspended = true;
                        ufshcd_reset_and_restore(hba);
+                       spin_lock_irqsave(hba->host->host_lock, flags);
                        hba->clk_gating.state = CLKS_ON;
+                       spin_unlock_irqrestore(hba->host->host_lock, flags);
                        hba->clk_gating.is_suspended = false;
                        trace_ufshcd_clk_gating(dev_name(hba->dev),
                                                hba->clk_gating.state);
@@ -7313,7 +7319,20 @@ static int ufshcd_link_state_transition(struct ufs_hba *hba,
                if (!ret)
                        ufshcd_set_link_hibern8(hba);
                else {
+                       unsigned long flags;
+                       bool saved_is_suspended = hba->clk_gating.is_suspended;
+
+                       spin_lock_irqsave(hba->host->host_lock, flags);
+                       hba->clk_gating.state = __CLKS_ON;
+                       spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+                       hba->clk_gating.is_suspended = true;
                        ufshcd_host_reset_and_restore(hba);
+                       spin_lock_irqsave(hba->host->host_lock, flags);
+                       hba->clk_gating.state = CLKS_ON;
+                       spin_unlock_irqrestore(hba->host->host_lock, flags);
+                       hba->clk_gating.is_suspended = saved_is_suspended;
+
                        goto out;
        }
        /*
index abe402788a4360972c7d66b213029d30be680a31..00930bc7984c79b94a89ad0e04d989567d5dd992 100644 (file)
@@ -345,6 +345,7 @@ enum clk_gating_state {
        CLKS_ON,
        REQ_CLKS_OFF,
        REQ_CLKS_ON,
+       __CLKS_ON,
 };
 
 /**