UFS driver general fixes bundle 2
Subsystems (2)
v6 cover UFS driver general fixes bundle 2
This bundle includes 2 general fixes for UFS driver.
Changes since v5:
- Fixed a compilation error
Changes since v4:
- Incoperated comments from Avri.
- Added trace back to func ufshcd_scale_clks()
- Removed scale_up_gear goto
- Added "Fixes" tag to commit messages
Changes since v3:
- Removed trivial spaces in comments
Changes since v2:
- Rebased on 5.7/scsi-queue and fixed minor conflicts
Changes since v1:
- Fixed minor typo
Can Guo (1):
scsi: ufs: Do not rely on prefetched data
Subhash Jadavani (1):
scsi: ufs: Clean up ufshcd_scale_clks() and clock scaling error out
path
drivers/scsi/ufs/ufshcd.c | 91 ++++++++++++++++++++++++++++++----------------- drivers/scsi/ufs/ufshcd.h | 11 ------ 2 files changed, 59 insertions(+), 43 deletions(-)
Signature · 1 line
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
PATCH v6 1/2 scsi: ufs: Clean up ufshcd_scale_clks() and clock scaling error out path
From: Subhash Jadavani <[email protected]>
This change introduces a func ufshcd_set_clk_freq() to explicitly set clock frequency so that it can be used in reset_and_resotre path and in ufshcd_scale_clks(). Meanwhile, this change cleans up the clock scaling error out path.
--- drivers/scsi/ufs/ufshcd.c | 65 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 21 deletions(-)
drivers/scsi/ufs/ufshcd.c +44 -21
@@ -855,28 +855,29 @@ static bool ufshcd_is_unipro_pa_params_tuning_req(struct ufs_hba *hba)return false; } -static int ufshcd_scale_clks (struct ufs_hba *hba,bool scale_up) +/** +* ufshcd_set_clk_freq - set UFS controller clock frequencies +* @hba: per adapter instance +* @scale_up: If True, set max possible frequency othewise set low frequency +* +* Returns 0 if successful +* Returns < 0 for any other errors +*/ +static int ufshcd_set_clk_freq (struct ufs_hba *hba,bool scale_up) {int ret =0 ;struct ufs_clk_info *clki;struct list_head *head = &hba->clk_list_head; -ktime_t start =ktime_get (); -bool clk_state_changed = false;if (list_empty (head)) goto out; - ret =ufshcd_vops_clk_scale_notify (hba, scale_up,PRE_CHANGE ); -if (ret) -return ret; -list_for_each_entry (clki, head, list) {if (!IS_ERR_OR_NULL (clki->clk)) {if (scale_up && clki->max_freq) {if (clki->curr_freq == clki->max_freq)continue ; - clk_state_changed = true; ret =clk_set_rate (clki->clk, clki->max_freq);if (ret) { dev_err(hba->dev, "%s: %s clk set rate(%dHz) failed, %d\n",
@@ -895,7 +896,6 @@ static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up)if (clki->curr_freq == clki->min_freq)continue ; - clk_state_changed = true; ret =clk_set_rate (clki->clk, clki->min_freq);if (ret) { dev_err(hba->dev, "%s: %s clk set rate(%dHz) failed, %d\n",
@@ -914,11 +914,37 @@ static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up) clki->name, clk_get_rate(clki->clk)); } +out: +return ret; +} + +/** +* ufshcd_scale_clks - scale up or scale down UFS controller clocks +* @hba: per adapter instance +* @scale_up: True if scaling up and false if scaling down +* +* Returns 0 if successful +* Returns < 0 for any other errors +*/ +static int ufshcd_scale_clks (struct ufs_hba *hba,bool scale_up) +{ +int ret =0 ; +ktime_t start =ktime_get (); + + ret =ufshcd_vops_clk_scale_notify (hba, scale_up,PRE_CHANGE ); +if (ret) + goto out; + + ret =ufshcd_set_clk_freq (hba, scale_up); +if (ret) + goto out; + ret =ufshcd_vops_clk_scale_notify (hba, scale_up,POST_CHANGE ); +if (ret) +ufshcd_set_clk_freq (hba, !scale_up); out: -if (clk_state_changed) -trace_ufshcd_profile_clk_scaling (dev_name (hba->dev), +trace_ufshcd_profile_clk_scaling (dev_name (hba->dev), (scale_up ?"up" :"down" ),ktime_to_us (ktime_sub (ktime_get (), start)), ret);return ret;
@@ -1106,35 +1132,32 @@ static int ufshcd_devfreq_scale(struct ufs_hba *hba, bool scale_up) ret =ufshcd_clock_scaling_prepare (hba);if (ret) -return ret; + goto out;/* scale down the gear before scaling down clocks */ if (!scale_up) { ret =ufshcd_scale_gear (hba, false);if (ret) - goto out; + goto out_unprepare; } ret =ufshcd_scale_clks (hba, scale_up);if (ret) {if (!scale_up)ufshcd_scale_gear (hba, true); - goto out; + goto out_unprepare; }/* scale up the gear after scaling up clocks */ if (scale_up) { ret =ufshcd_scale_gear (hba, true); -if (ret) { +if (ret)ufshcd_scale_clks (hba, false); - goto out; - } } - ret =ufshcd_vops_clk_scale_notify (hba, scale_up,POST_CHANGE ); - -out: +out_unprepare:ufshcd_clock_scaling_unprepare (hba); +out:ufshcd_release (hba);return ret; }
@@ -6251,7 +6274,7 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba)spin_unlock_irqrestore (hba->host->host_lock, flags);/* scale up clocks to max frequency before full reinitialization */ -ufshcd_scale_clks (hba, true); +ufshcd_set_clk_freq (hba, true); err =ufshcd_hba_enable (hba);if (err)
Signature · 1 line
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
RE: [EXT] [PATCH v6 1/2] scsi: ufs: Clean up ufshcd_scale_clks() and clock scaling error out path
Quoted 3 lines
Fixes a3cd5ec55f6c ("scsi: ufs: add load based scaling of UFS gear")Signed-off-by Subhash Jadavani <[email protected]>Signed-off-by Can Guo <[email protected]>
Martin K. Petersen
AppliedRe: [PATCH v6 1/2] scsi: ufs: Clean up ufshcd_scale_clks() and clock scaling error out path
In reply to Can GuoCan,
Quoted 4 lines
This change introduces a func
ufshcd_set_clk_freq()to explicitly set clock frequency so that it can be used inreset_and_resotrepath and inufshcd_scale_clks(). Meanwhile, this change cleans up the clock scaling error out path.
Applied to 5.7/scsi-queue, thanks!
Signature · 1 line
Martin K. Petersen Oracle Linux Engineering
PATCH v6 2/2 scsi: ufs: Do not rely on prefetched data
In reply to Can GuoWe were setting bActiveICCLevel attribute for UFS device only once but type of this attribute has changed from persistent to volatile since UFS device specification v2.1. This attribute is set to the default value after power cycle or hardware reset event. It isn't safe to rely on prefetched data (only used for bActiveICCLevel attribute now). Hence this change removes the code related to data prefetching and set this parameter on every attempt to probe the UFS device.
--- drivers/scsi/ufs/ufshcd.c | 26 +++++++++++++++----------- drivers/scsi/ufs/ufshcd.h | 11 ----------- 2 files changed, 15 insertions(+), 22 deletions(-)
drivers/scsi/ufs/ufshcd.c +15 -11
@@ -6457,11 +6457,12 @@ static u32 ufshcd_find_max_sup_active_icc_level(struct ufs_hba *hba,return icc_level; } -static void ufshcd_init_icc_levels (struct ufs_hba *hba) +static void ufshcd_set_active_icc_lvl (struct ufs_hba *hba) {int ret;int buff_len = hba->desc_size.pwr_desc;u8 *desc_buf; +u32 icc_level; desc_buf =kmalloc (buff_len,GFP_KERNEL );if (!desc_buf)
@@ -6476,20 +6477,17 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba) goto out; } - hba->init_prefetch_data.icc_level = -ufshcd_find_max_sup_active_icc_level (hba, - desc_buf, buff_len); -dev_dbg (hba->dev,"%s: setting icc_level 0x%x" , - __func__, hba->init_prefetch_data.icc_level); + icc_level =ufshcd_find_max_sup_active_icc_level (hba, desc_buf, + buff_len); +dev_dbg (hba->dev,"%s: setting icc_level 0x%x" , __func__, icc_level); ret =ufshcd_query_attr_retry (hba,UPIU_QUERY_OPCODE_WRITE_ATTR , -QUERY_ATTR_IDN_ACTIVE_ICC_LVL ,0 ,0 , - &hba->init_prefetch_data.icc_level); +QUERY_ATTR_IDN_ACTIVE_ICC_LVL ,0 ,0 , &icc_level);if (ret)dev_err (hba->dev,"%s: Failed configuring bActiveICCLevel = %d ret = %d" , - __func__, hba->init_prefetch_data.icc_level , ret); + __func__, icc_level, ret); out:kfree (desc_buf);
@@ -6995,8 +6993,6 @@ static int ufshcd_add_lus(struct ufs_hba *hba) {int ret; -ufshcd_init_icc_levels (hba); -/* Add required well known logical units to scsi mid layer */ ret =ufshcd_scsi_add_wlus (hba);if (ret)
@@ -7094,6 +7090,14 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool async) } } +/* +* bActiveICCLevel is volatile for UFS device (as per latest v2.1 spec) +* and for removable UFS card as well, hence always set the parameter. +* Note: Error handler may issue the device reset hence resetting +* bActiveICCLevel as well so it is always safe to set this here. +*/ +ufshcd_set_active_icc_lvl (hba); +/* set the state as operational after switching to desired gear */ hba->ufshcd_state =UFSHCD_STATE_OPERATIONAL ;
drivers/scsi/ufs/ufshcd.h +0 -11
@@ -404,15 +404,6 @@ struct ufs_clk_scaling {bool is_suspended; }; -/** -* struct ufs_init_prefetch - contains data that is pre-fetched once during -* initialization -* @icc_level: icc level which was read during initialization -*/ -struct ufs_init_prefetch { -u32 icc_level; -}; -#define UFS_ERR_REG_HIST_LENGTH 8/** * struct ufs_err_reg_hist - keeps history of errors
@@ -544,7 +535,6 @@ enum ufshcd_quirks {* @intr_mask: Interrupt Mask Bits * @ee_ctrl_mask: Exception event control mask * @is_powered: flag to check if HBA is powered -* @init_prefetch_data: data pre-fetched during initialization * @eh_work: Worker to handle UFS errors that require s/w attention * @eeh_work: Worker to handle exception events * @errors: HBA errors
@@ -632,7 +622,6 @@ struct ufs_hba {u32 intr_mask;u16 ee_ctrl_mask;bool is_powered; -struct ufs_init_prefetch init_prefetch_data;/* Work Queues */ struct work_struct eh_work;
Signature · 7 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project. _______________________________________________ linux-arm-kernel mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Martin K. Petersen
AppliedRe: [PATCH v6 2/2] scsi: ufs: Do not rely on prefetched data
Can,
Quoted 7 lines
We were setting bActiveICCLevel attribute for UFS device only once but type of this attribute has changed from persistent to volatile since UFS device specification v2.1. This attribute is set to the default value after power cycle or hardware reset event. It isn't safe to rely on prefetched data (only used for bActiveICCLevel attribute now). Hence this change removes the code related to data prefetching and set this parameter on every attempt to probe the UFS device.
Applied patch #2 to 5.7/scsi-queue. Awaiting Avri's feedback on patch #1. Thanks!
Signature · 6 lines
Martin K. Petersen Oracle Linux Engineering _______________________________________________ linux-arm-kernel mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
RE: [PATCH v6 2/2] scsi: ufs: Do not rely on prefetched data
Quoted 13 lines
Can,
Quoted 7 lines
We were setting bActiveICCLevel attribute for UFS device only once but type of this attribute has changed from persistent to volatile since UFS device specification v2.1. This attribute is set to the default value after power cycle or hardware reset event. It isn't safe to rely on prefetched data (only used for bActiveICCLevel attribute now). Hence this change removes the code related to data prefetching and set this parameter on every attempt to probe the UFS device.
Quoted 2 lines
Applied patch #2 to 5.7/scsi-queue. Awaiting Avri's feedback on patch #1. Thanks!
It looks fine.
Thanks,
Avri
Quoted 3 lines
--
Martin K. Petersen Oracle Linux Engineering