Commit 4543d9d7 authored by Can Guo's avatar Can Guo Committed by Martin K. Petersen

scsi: ufs: Refactor ufshcd_init/exit_clk_scaling/gating()

ufshcd_hba_exit() is always called after ufshcd_exit_clk_scaling() and
ufshcd_exit_clk_gating(). Move ufshcd_exit_clk_scaling/gating() to
ufshcd_hba_exit(). Meanwhile, add dedicated functions to initialize
and remove sysfs nodes of clock scaling/gating to make the code more
readable. Overall functionality remains same.

Link: https://lore.kernel.org/r/1611137065-14266-3-git-send-email-cang@codeaurora.orgReviewed-by: default avatarStanley Chu <stanley.chu@mediatek.com>
Signed-off-by: default avatarCan Guo <cang@codeaurora.org>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 0e9d4ca4
...@@ -1593,7 +1593,7 @@ static ssize_t ufshcd_clkscale_enable_store(struct device *dev, ...@@ -1593,7 +1593,7 @@ static ssize_t ufshcd_clkscale_enable_store(struct device *dev,
return err ? err : count; return err ? err : count;
} }
static void ufshcd_clkscaling_init_sysfs(struct ufs_hba *hba) static void ufshcd_init_clk_scaling_sysfs(struct ufs_hba *hba)
{ {
hba->clk_scaling.enable_attr.show = ufshcd_clkscale_enable_show; hba->clk_scaling.enable_attr.show = ufshcd_clkscale_enable_show;
hba->clk_scaling.enable_attr.store = ufshcd_clkscale_enable_store; hba->clk_scaling.enable_attr.store = ufshcd_clkscale_enable_store;
...@@ -1604,6 +1604,42 @@ static void ufshcd_clkscaling_init_sysfs(struct ufs_hba *hba) ...@@ -1604,6 +1604,42 @@ static void ufshcd_clkscaling_init_sysfs(struct ufs_hba *hba)
dev_err(hba->dev, "Failed to create sysfs for clkscale_enable\n"); dev_err(hba->dev, "Failed to create sysfs for clkscale_enable\n");
} }
static void ufshcd_remove_clk_scaling_sysfs(struct ufs_hba *hba)
{
if (hba->clk_scaling.enable_attr.attr.name)
device_remove_file(hba->dev, &hba->clk_scaling.enable_attr);
}
static void ufshcd_init_clk_scaling(struct ufs_hba *hba)
{
char wq_name[sizeof("ufs_clkscaling_00")];
if (!ufshcd_is_clkscaling_supported(hba))
return;
INIT_WORK(&hba->clk_scaling.suspend_work,
ufshcd_clk_scaling_suspend_work);
INIT_WORK(&hba->clk_scaling.resume_work,
ufshcd_clk_scaling_resume_work);
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 (!hba->clk_scaling.is_initialized)
return;
ufshcd_remove_clk_scaling_sysfs(hba);
destroy_workqueue(hba->clk_scaling.workq);
ufshcd_devfreq_remove(hba);
hba->clk_scaling.is_initialized = false;
}
static void ufshcd_ungate_work(struct work_struct *work) static void ufshcd_ungate_work(struct work_struct *work)
{ {
int ret; int ret;
...@@ -1895,35 +1931,31 @@ static ssize_t ufshcd_clkgate_enable_store(struct device *dev, ...@@ -1895,35 +1931,31 @@ static ssize_t ufshcd_clkgate_enable_store(struct device *dev,
return count; return count;
} }
static void ufshcd_init_clk_scaling(struct ufs_hba *hba) static void ufshcd_init_clk_gating_sysfs(struct ufs_hba *hba)
{ {
char wq_name[sizeof("ufs_clkscaling_00")]; hba->clk_gating.delay_attr.show = ufshcd_clkgate_delay_show;
hba->clk_gating.delay_attr.store = ufshcd_clkgate_delay_store;
if (!ufshcd_is_clkscaling_supported(hba)) sysfs_attr_init(&hba->clk_gating.delay_attr.attr);
return; hba->clk_gating.delay_attr.attr.name = "clkgate_delay_ms";
hba->clk_gating.delay_attr.attr.mode = 0644;
if (!hba->clk_scaling.min_gear) if (device_create_file(hba->dev, &hba->clk_gating.delay_attr))
hba->clk_scaling.min_gear = UFS_HS_G1; dev_err(hba->dev, "Failed to create sysfs for clkgate_delay\n");
INIT_WORK(&hba->clk_scaling.suspend_work,
ufshcd_clk_scaling_suspend_work);
INIT_WORK(&hba->clk_scaling.resume_work,
ufshcd_clk_scaling_resume_work);
snprintf(wq_name, sizeof(wq_name), "ufs_clkscaling_%d", hba->clk_gating.enable_attr.show = ufshcd_clkgate_enable_show;
hba->host->host_no); hba->clk_gating.enable_attr.store = ufshcd_clkgate_enable_store;
hba->clk_scaling.workq = create_singlethread_workqueue(wq_name); sysfs_attr_init(&hba->clk_gating.enable_attr.attr);
hba->clk_gating.enable_attr.attr.name = "clkgate_enable";
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");
} }
static void ufshcd_exit_clk_scaling(struct ufs_hba *hba) static void ufshcd_remove_clk_gating_sysfs(struct ufs_hba *hba)
{ {
if (!ufshcd_is_clkscaling_supported(hba)) if (hba->clk_gating.delay_attr.attr.name)
return; device_remove_file(hba->dev, &hba->clk_gating.delay_attr);
if (hba->clk_gating.enable_attr.attr.name)
if (hba->clk_scaling.enable_attr.attr.name) device_remove_file(hba->dev, &hba->clk_gating.enable_attr);
device_remove_file(hba->dev, &hba->clk_scaling.enable_attr);
destroy_workqueue(hba->clk_scaling.workq);
ufshcd_devfreq_remove(hba);
} }
static void ufshcd_init_clk_gating(struct ufs_hba *hba) static void ufshcd_init_clk_gating(struct ufs_hba *hba)
...@@ -1944,34 +1976,21 @@ static void ufshcd_init_clk_gating(struct ufs_hba *hba) ...@@ -1944,34 +1976,21 @@ static void ufshcd_init_clk_gating(struct ufs_hba *hba)
hba->clk_gating.clk_gating_workq = alloc_ordered_workqueue(wq_name, hba->clk_gating.clk_gating_workq = alloc_ordered_workqueue(wq_name,
WQ_MEM_RECLAIM | WQ_HIGHPRI); WQ_MEM_RECLAIM | WQ_HIGHPRI);
hba->clk_gating.is_enabled = true; ufshcd_init_clk_gating_sysfs(hba);
hba->clk_gating.delay_attr.show = ufshcd_clkgate_delay_show;
hba->clk_gating.delay_attr.store = ufshcd_clkgate_delay_store;
sysfs_attr_init(&hba->clk_gating.delay_attr.attr);
hba->clk_gating.delay_attr.attr.name = "clkgate_delay_ms";
hba->clk_gating.delay_attr.attr.mode = 0644;
if (device_create_file(hba->dev, &hba->clk_gating.delay_attr))
dev_err(hba->dev, "Failed to create sysfs for clkgate_delay\n");
hba->clk_gating.enable_attr.show = ufshcd_clkgate_enable_show; hba->clk_gating.is_enabled = true;
hba->clk_gating.enable_attr.store = ufshcd_clkgate_enable_store; hba->clk_gating.is_initialized = true;
sysfs_attr_init(&hba->clk_gating.enable_attr.attr);
hba->clk_gating.enable_attr.attr.name = "clkgate_enable";
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");
} }
static void ufshcd_exit_clk_gating(struct ufs_hba *hba) static void ufshcd_exit_clk_gating(struct ufs_hba *hba)
{ {
if (!ufshcd_is_clkgating_allowed(hba)) if (!hba->clk_gating.is_initialized)
return; return;
device_remove_file(hba->dev, &hba->clk_gating.delay_attr); ufshcd_remove_clk_gating_sysfs(hba);
device_remove_file(hba->dev, &hba->clk_gating.enable_attr);
cancel_work_sync(&hba->clk_gating.ungate_work); cancel_work_sync(&hba->clk_gating.ungate_work);
cancel_delayed_work_sync(&hba->clk_gating.gate_work); cancel_delayed_work_sync(&hba->clk_gating.gate_work);
destroy_workqueue(hba->clk_gating.clk_gating_workq); destroy_workqueue(hba->clk_gating.clk_gating_workq);
hba->clk_gating.is_initialized = false;
} }
/* Must be called with host lock acquired */ /* Must be called with host lock acquired */
...@@ -7766,7 +7785,7 @@ static int ufshcd_add_lus(struct ufs_hba *hba) ...@@ -7766,7 +7785,7 @@ static int ufshcd_add_lus(struct ufs_hba *hba)
goto out; goto out;
hba->clk_scaling.is_enabled = true; hba->clk_scaling.is_enabled = true;
ufshcd_clkscaling_init_sysfs(hba); ufshcd_init_clk_scaling_sysfs(hba);
} }
} }
...@@ -7954,7 +7973,6 @@ static void ufshcd_async_scan(void *data, async_cookie_t cookie) ...@@ -7954,7 +7973,6 @@ static void ufshcd_async_scan(void *data, async_cookie_t cookie)
*/ */
if (ret) { if (ret) {
pm_runtime_put_sync(hba->dev); pm_runtime_put_sync(hba->dev);
ufshcd_exit_clk_scaling(hba);
ufshcd_hba_exit(hba); ufshcd_hba_exit(hba);
} else { } else {
ufshcd_clear_ua_wluns(hba); ufshcd_clear_ua_wluns(hba);
...@@ -8386,13 +8404,13 @@ static int ufshcd_hba_init(struct ufs_hba *hba) ...@@ -8386,13 +8404,13 @@ static int ufshcd_hba_init(struct ufs_hba *hba)
static void ufshcd_hba_exit(struct ufs_hba *hba) static void ufshcd_hba_exit(struct ufs_hba *hba)
{ {
if (hba->is_powered) { if (hba->is_powered) {
ufshcd_exit_clk_scaling(hba);
ufshcd_exit_clk_gating(hba);
if (hba->eh_wq)
destroy_workqueue(hba->eh_wq);
ufs_debugfs_hba_exit(hba); ufs_debugfs_hba_exit(hba);
ufshcd_variant_hba_exit(hba); ufshcd_variant_hba_exit(hba);
ufshcd_setup_vreg(hba, false); 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_clocks(hba, false);
ufshcd_setup_hba_vreg(hba, false); ufshcd_setup_hba_vreg(hba, false);
hba->is_powered = false; hba->is_powered = false;
...@@ -9178,13 +9196,9 @@ void ufshcd_remove(struct ufs_hba *hba) ...@@ -9178,13 +9196,9 @@ void ufshcd_remove(struct ufs_hba *hba)
blk_mq_free_tag_set(&hba->tmf_tag_set); blk_mq_free_tag_set(&hba->tmf_tag_set);
blk_cleanup_queue(hba->cmd_queue); blk_cleanup_queue(hba->cmd_queue);
scsi_remove_host(hba->host); scsi_remove_host(hba->host);
destroy_workqueue(hba->eh_wq);
/* disable interrupts */ /* disable interrupts */
ufshcd_disable_intr(hba, hba->intr_mask); ufshcd_disable_intr(hba, hba->intr_mask);
ufshcd_hba_stop(hba); ufshcd_hba_stop(hba);
ufshcd_exit_clk_scaling(hba);
ufshcd_exit_clk_gating(hba);
ufshcd_hba_exit(hba); ufshcd_hba_exit(hba);
} }
EXPORT_SYMBOL_GPL(ufshcd_remove); EXPORT_SYMBOL_GPL(ufshcd_remove);
...@@ -9385,7 +9399,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) ...@@ -9385,7 +9399,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); err = devm_request_irq(dev, irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
if (err) { if (err) {
dev_err(hba->dev, "request irq failed\n"); dev_err(hba->dev, "request irq failed\n");
goto exit_gating; goto out_disable;
} else { } else {
hba->is_irq_enabled = true; hba->is_irq_enabled = true;
} }
...@@ -9393,7 +9407,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) ...@@ -9393,7 +9407,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
err = scsi_add_host(host, hba->dev); err = scsi_add_host(host, hba->dev);
if (err) { if (err) {
dev_err(hba->dev, "scsi_add_host failed\n"); 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); hba->cmd_queue = blk_mq_init_queue(&hba->host->tag_set);
...@@ -9476,10 +9490,6 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) ...@@ -9476,10 +9490,6 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
blk_cleanup_queue(hba->cmd_queue); blk_cleanup_queue(hba->cmd_queue);
out_remove_scsi_host: out_remove_scsi_host:
scsi_remove_host(hba->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: out_disable:
hba->is_irq_enabled = false; hba->is_irq_enabled = false;
ufshcd_hba_exit(hba); ufshcd_hba_exit(hba);
......
...@@ -383,6 +383,7 @@ enum clk_gating_state { ...@@ -383,6 +383,7 @@ enum clk_gating_state {
* @delay_attr: sysfs attribute to control delay_attr * @delay_attr: sysfs attribute to control delay_attr
* @enable_attr: sysfs attribute to enable/disable clock gating * @enable_attr: sysfs attribute to enable/disable clock gating
* @is_enabled: Indicates the current status of 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 * @active_reqs: number of requests that are pending and should be waited for
* completion before gating clocks. * completion before gating clocks.
*/ */
...@@ -395,6 +396,7 @@ struct ufs_clk_gating { ...@@ -395,6 +396,7 @@ struct ufs_clk_gating {
struct device_attribute delay_attr; struct device_attribute delay_attr;
struct device_attribute enable_attr; struct device_attribute enable_attr;
bool is_enabled; bool is_enabled;
bool is_initialized;
int active_reqs; int active_reqs;
struct workqueue_struct *clk_gating_workq; struct workqueue_struct *clk_gating_workq;
}; };
...@@ -423,6 +425,7 @@ struct ufs_saved_pwr_info { ...@@ -423,6 +425,7 @@ struct ufs_saved_pwr_info {
clkscale_enable sysfs node clkscale_enable sysfs node
* @is_allowed: tracks if scaling is currently allowed or not, used to block * @is_allowed: tracks if scaling is currently allowed or not, used to block
clock scaling which is not invoked from devfreq governor 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_busy_started: tracks if busy period has started or not
* @is_suspended: tracks if devfreq is suspended or not * @is_suspended: tracks if devfreq is suspended or not
*/ */
...@@ -439,6 +442,7 @@ struct ufs_clk_scaling { ...@@ -439,6 +442,7 @@ struct ufs_clk_scaling {
u32 min_gear; u32 min_gear;
bool is_enabled; bool is_enabled;
bool is_allowed; bool is_allowed;
bool is_initialized;
bool is_busy_started; bool is_busy_started;
bool is_suspended; bool is_suspended;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment