Commit 911a0771 authored by subhashj@codeaurora.org's avatar subhashj@codeaurora.org Committed by Martin K. Petersen

scsi: ufs: add time profiling support

This patch adds the profiling support for some of the time critical
operations like hibern8 enter/exit, clock gating & clock scaling.
Reviewed-by: default avatarVenkat Gopalakrishnan <venkatg@codeaurora.org>
Signed-off-by: default avatarSubhash Jadavani <subhashj@codeaurora.org>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent d2aebb9b
...@@ -3021,11 +3021,14 @@ static int __ufshcd_uic_hibern8_enter(struct ufs_hba *hba) ...@@ -3021,11 +3021,14 @@ static int __ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
{ {
int ret; int ret;
struct uic_command uic_cmd = {0}; struct uic_command uic_cmd = {0};
ktime_t start = ktime_get();
ufshcd_vops_hibern8_notify(hba, UIC_CMD_DME_HIBER_ENTER, PRE_CHANGE); ufshcd_vops_hibern8_notify(hba, UIC_CMD_DME_HIBER_ENTER, PRE_CHANGE);
uic_cmd.command = UIC_CMD_DME_HIBER_ENTER; uic_cmd.command = UIC_CMD_DME_HIBER_ENTER;
ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd); ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd);
trace_ufshcd_profile_hibern8(dev_name(hba->dev), "enter",
ktime_to_us(ktime_sub(ktime_get(), start)), ret);
if (ret) { if (ret) {
dev_err(hba->dev, "%s: hibern8 enter failed. ret = %d\n", dev_err(hba->dev, "%s: hibern8 enter failed. ret = %d\n",
...@@ -3061,11 +3064,15 @@ static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba) ...@@ -3061,11 +3064,15 @@ static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba)
{ {
struct uic_command uic_cmd = {0}; struct uic_command uic_cmd = {0};
int ret; int ret;
ktime_t start = ktime_get();
ufshcd_vops_hibern8_notify(hba, UIC_CMD_DME_HIBER_EXIT, PRE_CHANGE); ufshcd_vops_hibern8_notify(hba, UIC_CMD_DME_HIBER_EXIT, PRE_CHANGE);
uic_cmd.command = UIC_CMD_DME_HIBER_EXIT; uic_cmd.command = UIC_CMD_DME_HIBER_EXIT;
ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd); ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd);
trace_ufshcd_profile_hibern8(dev_name(hba->dev), "exit",
ktime_to_us(ktime_sub(ktime_get(), start)), ret);
if (ret) { if (ret) {
dev_err(hba->dev, "%s: hibern8 exit failed. ret = %d\n", dev_err(hba->dev, "%s: hibern8 exit failed. ret = %d\n",
__func__, ret); __func__, ret);
...@@ -5950,6 +5957,8 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, ...@@ -5950,6 +5957,8 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on,
struct ufs_clk_info *clki; struct ufs_clk_info *clki;
struct list_head *head = &hba->clk_list_head; struct list_head *head = &hba->clk_list_head;
unsigned long flags; unsigned long flags;
ktime_t start = ktime_get();
bool clk_state_changed = false;
if (!head || list_empty(head)) if (!head || list_empty(head))
goto out; goto out;
...@@ -5963,6 +5972,7 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, ...@@ -5963,6 +5972,7 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on,
if (skip_ref_clk && !strcmp(clki->name, "ref_clk")) if (skip_ref_clk && !strcmp(clki->name, "ref_clk"))
continue; continue;
clk_state_changed = on ^ clki->enabled;
if (on && !clki->enabled) { if (on && !clki->enabled) {
ret = clk_prepare_enable(clki->clk); ret = clk_prepare_enable(clki->clk);
if (ret) { if (ret) {
...@@ -5997,6 +6007,10 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, ...@@ -5997,6 +6007,10 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on,
spin_unlock_irqrestore(hba->host->host_lock, flags); spin_unlock_irqrestore(hba->host->host_lock, flags);
} }
if (clk_state_changed)
trace_ufshcd_profile_clk_gating(dev_name(hba->dev),
(on ? "on" : "off"),
ktime_to_us(ktime_sub(ktime_get(), start)), ret);
return ret; return ret;
} }
...@@ -6996,6 +7010,8 @@ static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up) ...@@ -6996,6 +7010,8 @@ static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up)
int ret = 0; int ret = 0;
struct ufs_clk_info *clki; struct ufs_clk_info *clki;
struct list_head *head = &hba->clk_list_head; struct list_head *head = &hba->clk_list_head;
ktime_t start = ktime_get();
bool clk_state_changed = false;
if (!head || list_empty(head)) if (!head || list_empty(head))
goto out; goto out;
...@@ -7009,6 +7025,8 @@ static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up) ...@@ -7009,6 +7025,8 @@ static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up)
if (scale_up && clki->max_freq) { if (scale_up && clki->max_freq) {
if (clki->curr_freq == clki->max_freq) if (clki->curr_freq == clki->max_freq)
continue; continue;
clk_state_changed = true;
ret = clk_set_rate(clki->clk, clki->max_freq); ret = clk_set_rate(clki->clk, clki->max_freq);
if (ret) { if (ret) {
dev_err(hba->dev, "%s: %s clk set rate(%dHz) failed, %d\n", dev_err(hba->dev, "%s: %s clk set rate(%dHz) failed, %d\n",
...@@ -7026,6 +7044,8 @@ static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up) ...@@ -7026,6 +7044,8 @@ static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up)
} else if (!scale_up && clki->min_freq) { } else if (!scale_up && clki->min_freq) {
if (clki->curr_freq == clki->min_freq) if (clki->curr_freq == clki->min_freq)
continue; continue;
clk_state_changed = true;
ret = clk_set_rate(clki->clk, clki->min_freq); ret = clk_set_rate(clki->clk, clki->min_freq);
if (ret) { if (ret) {
dev_err(hba->dev, "%s: %s clk set rate(%dHz) failed, %d\n", dev_err(hba->dev, "%s: %s clk set rate(%dHz) failed, %d\n",
...@@ -7047,6 +7067,10 @@ static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up) ...@@ -7047,6 +7067,10 @@ static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up)
ret = ufshcd_vops_clk_scale_notify(hba, scale_up, POST_CHANGE); ret = ufshcd_vops_clk_scale_notify(hba, scale_up, POST_CHANGE);
out: out:
if (clk_state_changed)
trace_ufshcd_profile_clk_scaling(dev_name(hba->dev),
(scale_up ? "up" : "down"),
ktime_to_us(ktime_sub(ktime_get(), start)), ret);
return ret; return ret;
} }
......
...@@ -123,6 +123,46 @@ TRACE_EVENT(ufshcd_auto_bkops_state, ...@@ -123,6 +123,46 @@ TRACE_EVENT(ufshcd_auto_bkops_state,
__get_str(dev_name), __get_str(state)) __get_str(dev_name), __get_str(state))
); );
DECLARE_EVENT_CLASS(ufshcd_profiling_template,
TP_PROTO(const char *dev_name, const char *profile_info, s64 time_us,
int err),
TP_ARGS(dev_name, profile_info, time_us, err),
TP_STRUCT__entry(
__string(dev_name, dev_name)
__string(profile_info, profile_info)
__field(s64, time_us)
__field(int, err)
),
TP_fast_assign(
__assign_str(dev_name, dev_name);
__assign_str(profile_info, profile_info);
__entry->time_us = time_us;
__entry->err = err;
),
TP_printk("%s: %s: took %lld usecs, err %d",
__get_str(dev_name), __get_str(profile_info),
__entry->time_us, __entry->err)
);
DEFINE_EVENT(ufshcd_profiling_template, ufshcd_profile_hibern8,
TP_PROTO(const char *dev_name, const char *profile_info, s64 time_us,
int err),
TP_ARGS(dev_name, profile_info, time_us, err));
DEFINE_EVENT(ufshcd_profiling_template, ufshcd_profile_clk_gating,
TP_PROTO(const char *dev_name, const char *profile_info, s64 time_us,
int err),
TP_ARGS(dev_name, profile_info, time_us, err));
DEFINE_EVENT(ufshcd_profiling_template, ufshcd_profile_clk_scaling,
TP_PROTO(const char *dev_name, const char *profile_info, s64 time_us,
int err),
TP_ARGS(dev_name, profile_info, time_us, err));
DECLARE_EVENT_CLASS(ufshcd_template, DECLARE_EVENT_CLASS(ufshcd_template,
TP_PROTO(const char *dev_name, int err, s64 usecs, TP_PROTO(const char *dev_name, int err, s64 usecs,
int dev_state, int link_state), int dev_state, int link_state),
......
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