Merge "scsi: ufs-qcom: Adjust the order of bus bandwidth voting and unvoting"

This commit is contained in:
qctecmdr 2020-02-27 22:33:41 -08:00 • committed by Gerrit - the friendly Code Review server
commit c84acc8ce0
2 changed files with 73 additions and 40 deletions

View file

@ -64,7 +64,6 @@ struct ufs_qcom_dev_params {
static struct ufs_qcom_host *ufs_qcom_hosts[MAX_UFS_QCOM_HOSTS];
static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote);
static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host);
static int ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(struct ufs_hba *hba,
u32 clk_1us_cycles,
@ -1053,7 +1052,7 @@ static int ufs_qcom_get_ib_ab(struct ufs_qcom_host *host, int index,
return 0;
}
static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote)
static int __ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote)
{
int err = 0;
struct qcom_bus_scale_data *d = host->qbsd;
@ -1100,7 +1099,7 @@ static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host)
vote = ufs_qcom_get_bus_vote(host, mode);
if (vote >= 0)
err = ufs_qcom_set_bus_vote(host, vote);
err = __ufs_qcom_set_bus_vote(host, vote);
else
err = vote;
@ -1111,6 +1110,35 @@ static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host)
return err;
}
static int ufs_qcom_set_bus_vote(struct ufs_hba *hba, bool on)
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
int vote, err;
/*
* In case ufs_qcom_init() is not yet done, simply ignore.
* This ufs_qcom_set_bus_vote() shall be called from
* ufs_qcom_init() after init is done.
*/
if (!host)
return 0;
if (on) {
vote = host->bus_vote.saved_vote;
if (vote == host->bus_vote.min_bw_vote)
ufs_qcom_update_bus_bw_vote(host);
} else {
vote = host->bus_vote.min_bw_vote;
}
err = __ufs_qcom_set_bus_vote(host, vote);
if (err)
dev_err(hba->dev, "%s: set bus vote failed %d\n",
__func__, err);
return err;
}
static ssize_t
show_ufs_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr,
char *buf)
@ -1271,7 +1299,7 @@ static int ufs_qcom_bus_register(struct ufs_qcom_host *host)
err);
/* Full throttle */
err = ufs_qcom_set_bus_vote(host, host->bus_vote.max_bw_vote);
err = __ufs_qcom_set_bus_vote(host, host->bus_vote.max_bw_vote);
if (err)
dev_err(dev, "Error: (%d) Failed to set max bus vote\n", err);
@ -1550,8 +1578,7 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on,
enum ufs_notify_change_status status)
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
int err;
int vote = 0;
int err = 0;
/*
* In case ufs_qcom_init() is not yet done, simply ignore.
@ -1561,32 +1588,28 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on,
if (!host)
return 0;
if (on && (status == POST_CHANGE)) {
/* enable the device ref clock for HS mode*/
if (ufshcd_is_hs_mode(&hba->pwr_info))
ufs_qcom_dev_ref_clk_ctrl(host, true);
vote = host->bus_vote.saved_vote;
if (vote == host->bus_vote.min_bw_vote)
ufs_qcom_update_bus_bw_vote(host);
} else if (!on && (status == PRE_CHANGE)) {
if ((ufshcd_is_auto_hibern8_supported(hba) &&
!!hba->ahit) ||
!ufs_qcom_is_link_active(hba)) {
/* disable device ref_clk */
ufs_qcom_dev_ref_clk_ctrl(host, false);
/* powering off PHY during aggressive clk gating */
switch (status) {
case PRE_CHANGE:
if (on) {
err = ufs_qcom_set_bus_vote(hba, true);
} else {
if (!ufs_qcom_is_link_active(hba)) {
/* disable device ref_clk */
ufs_qcom_dev_ref_clk_ctrl(host, false);
}
}
vote = host->bus_vote.min_bw_vote;
break;
case POST_CHANGE:
if (on) {
/* enable the device ref clock for HS mode*/
if (ufshcd_is_hs_mode(&hba->pwr_info))
ufs_qcom_dev_ref_clk_ctrl(host, true);
} else {
err = ufs_qcom_set_bus_vote(hba, false);
}
break;
}
err = ufs_qcom_set_bus_vote(host, vote);
if (err)
dev_err(hba->dev, "%s: set bus vote failed %d\n",
__func__, err);
return err;
}
@ -1979,6 +2002,21 @@ ufs_qcom_ioctl(struct scsi_device *dev, unsigned int cmd, void __user *buffer)
return err;
}
static void ufs_qcom_parse_pm_level(struct ufs_hba *hba)
{
struct device *dev = hba->dev;
struct device_node *np = dev->of_node;
if (np) {
if (of_property_read_u32(np, "rpm-level",
&hba->rpm_lvl))
hba->rpm_lvl = -1;
if (of_property_read_u32(np, "spm-level",
&hba->spm_lvl))
hba->spm_lvl = -1;
}
}
/**
* ufs_qcom_init - bind phy with controller
* @hba: host controller instance
@ -2132,6 +2170,7 @@ static int ufs_qcom_init(struct ufs_hba *hba)
if (err)
goto out_set_load_vccq_parent;
ufs_qcom_parse_pm_level(hba);
ufs_qcom_parse_limits(host);
ufs_qcom_parse_lpm(host);
if (host->disable_lpm)
@ -2140,6 +2179,7 @@ static int ufs_qcom_init(struct ufs_hba *hba)
ufs_qcom_set_caps(hba);
ufs_qcom_advertise_quirks(hba);
ufs_qcom_set_bus_vote(hba, true);
ufs_qcom_setup_clocks(hba, true, POST_CHANGE);
if (hba->dev->id < MAX_UFS_QCOM_HOSTS)

View file

@ -8705,11 +8705,9 @@ static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on,
* this standard driver hence call the vendor specific setup_clocks
* before disabling the clocks managed here.
*/
if (!on) {
ret = ufshcd_vops_setup_clocks(hba, on, PRE_CHANGE);
if (ret)
goto out_unlock;
}
ret = ufshcd_vops_setup_clocks(hba, on, PRE_CHANGE);
if (ret)
return ret;
list_for_each_entry(clki, head, list) {
if (!IS_ERR_OR_NULL(clki->clk)) {
@ -8744,11 +8742,7 @@ static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on,
* this standard driver hence call the vendor specific setup_clocks
* after enabling the clocks managed here.
*/
if (on) {
ret = ufshcd_vops_setup_clocks(hba, on, POST_CHANGE);
if (ret)
goto out;
}
ret = ufshcd_vops_setup_clocks(hba, on, POST_CHANGE);
out:
if (ret) {
@ -8768,7 +8762,6 @@ out:
trace_ufshcd_profile_clk_gating(dev_name(hba->dev),
(on ? "on" : "off"),
ktime_to_us(ktime_sub(ktime_get(), start)), ret);
out_unlock:
return ret;
}