ufshcd_hba_exit() is always called after ufshcd_exit_clk_scaling() and
ufshcd_exit_clk_gating(), so move ufshcd_exit_clk_scaling/gating() to
ufshcd_hba_exit().

Reviewed-by: Stanley Chu <stanley....@mediatek.com>
Reviewed-by: Bean Huo <bean...@micron.com>
Signed-off-by: Can Guo <c...@codeaurora.org>
---
 drivers/scsi/ufs/ufshcd.c | 32 +++++++++++++++-----------------
 drivers/scsi/ufs/ufshcd.h |  4 ++++
 2 files changed, 19 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 79752a7..2dee21e 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1857,11 +1857,14 @@ static void ufshcd_init_clk_scaling(struct ufs_hba *hba)
        snprintf(wq_name, sizeof(wq_name), "ufs_clkscaling_%d",
                 hba->host->host_no);
        hba->clk_scaling.workq = create_singlethread_workqueue(wq_name);
+
+       hba->clk_scaling.is_initialized = true;
 }
 
 static void ufshcd_exit_clk_scaling(struct ufs_hba *hba)
 {
-       if (!ufshcd_is_clkscaling_supported(hba))
+       if (!ufshcd_is_clkscaling_supported(hba) ||
+           !hba->clk_scaling.is_initialized)
                return;
 
        if (hba->devfreq)
@@ -1905,12 +1908,16 @@ static void ufshcd_init_clk_gating(struct ufs_hba *hba)
        hba->clk_gating.enable_attr.attr.mode = 0644;
        if (device_create_file(hba->dev, &hba->clk_gating.enable_attr))
                dev_err(hba->dev, "Failed to create sysfs for 
clkgate_enable\n");
+
+       hba->clk_gating.is_initialized = true;
 }
 
 static void ufshcd_exit_clk_gating(struct ufs_hba *hba)
 {
-       if (!ufshcd_is_clkgating_allowed(hba))
+       if (!ufshcd_is_clkgating_allowed(hba) ||
+           !hba->clk_gating.is_initialized)
                return;
+
        device_remove_file(hba->dev, &hba->clk_gating.delay_attr);
        device_remove_file(hba->dev, &hba->clk_gating.enable_attr);
        cancel_work_sync(&hba->clk_gating.ungate_work);
@@ -7775,7 +7782,6 @@ static void ufshcd_async_scan(void *data, async_cookie_t 
cookie)
         */
        if (ret) {
                pm_runtime_put_sync(hba->dev);
-               ufshcd_exit_clk_scaling(hba);
                ufshcd_hba_exit(hba);
        }
 }
@@ -8212,12 +8218,12 @@ static int ufshcd_hba_init(struct ufs_hba *hba)
 static void ufshcd_hba_exit(struct ufs_hba *hba)
 {
        if (hba->is_powered) {
+               ufshcd_exit_clk_scaling(hba);
+               ufshcd_exit_clk_gating(hba);
+               if (hba->eh_wq)
+                       destroy_workqueue(hba->eh_wq);
                ufshcd_variant_hba_exit(hba);
                ufshcd_setup_vreg(hba, false);
-               ufshcd_suspend_clkscaling(hba);
-               if (ufshcd_is_clkscaling_supported(hba))
-                       if (hba->devfreq)
-                               ufshcd_suspend_clkscaling(hba);
                ufshcd_setup_clocks(hba, false);
                ufshcd_setup_hba_vreg(hba, false);
                hba->is_powered = false;
@@ -8964,13 +8970,9 @@ void ufshcd_remove(struct ufs_hba *hba)
        blk_mq_free_tag_set(&hba->tmf_tag_set);
        blk_cleanup_queue(hba->cmd_queue);
        scsi_remove_host(hba->host);
-       destroy_workqueue(hba->eh_wq);
        /* disable interrupts */
        ufshcd_disable_intr(hba, hba->intr_mask);
        ufshcd_hba_stop(hba);
-
-       ufshcd_exit_clk_scaling(hba);
-       ufshcd_exit_clk_gating(hba);
        ufshcd_hba_exit(hba);
 }
 EXPORT_SYMBOL_GPL(ufshcd_remove);
@@ -9169,7 +9171,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem 
*mmio_base, unsigned int irq)
        err = devm_request_irq(dev, irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
        if (err) {
                dev_err(hba->dev, "request irq failed\n");
-               goto exit_gating;
+               goto out_disable;
        } else {
                hba->is_irq_enabled = true;
        }
@@ -9177,7 +9179,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem 
*mmio_base, unsigned int irq)
        err = scsi_add_host(host, hba->dev);
        if (err) {
                dev_err(hba->dev, "scsi_add_host failed\n");
-               goto exit_gating;
+               goto out_disable;
        }
 
        hba->cmd_queue = blk_mq_init_queue(&hba->host->tag_set);
@@ -9260,10 +9262,6 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem 
*mmio_base, unsigned int irq)
        blk_cleanup_queue(hba->cmd_queue);
 out_remove_scsi_host:
        scsi_remove_host(hba->host);
-exit_gating:
-       ufshcd_exit_clk_scaling(hba);
-       ufshcd_exit_clk_gating(hba);
-       destroy_workqueue(hba->eh_wq);
 out_disable:
        hba->is_irq_enabled = false;
        ufshcd_hba_exit(hba);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 5737679..cb9075d 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -347,6 +347,7 @@ enum clk_gating_state {
  * @delay_attr: sysfs attribute to control delay_attr
  * @enable_attr: sysfs attribute to enable/disable clock gating
  * @is_enabled: Indicates the current status of clock gating
+ * @is_initialized: Indicates whether clock gating is initialized or not
  * @active_reqs: number of requests that are pending and should be waited for
  * completion before gating clocks.
  */
@@ -359,6 +360,7 @@ struct ufs_clk_gating {
        struct device_attribute delay_attr;
        struct device_attribute enable_attr;
        bool is_enabled;
+       bool is_initialized;
        int active_reqs;
        struct workqueue_struct *clk_gating_workq;
 };
@@ -386,6 +388,7 @@ struct ufs_saved_pwr_info {
                clkscale_enable sysfs node
  * @is_allowed: tracks if scaling is currently allowed or not, used to block
                clock scaling which is not invoked from devfreq governor
+ * @is_initialized: Indicates whether clock scaling is initialized or not
  * @is_busy_started: tracks if busy period has started or not
  * @is_suspended: tracks if devfreq is suspended or not
  */
@@ -401,6 +404,7 @@ struct ufs_clk_scaling {
        struct work_struct resume_work;
        bool is_enabled;
        bool is_allowed;
+       bool is_initialized;
        bool is_busy_started;
        bool is_suspended;
 };
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux 
Foundation Collaborative Project.

Reply via email to