* [PATCH v1 0/2] Add post change sequence for link start notify
@ 2026-03-11 6:09 palash.kambar
2026-03-11 6:09 ` [PATCH v1 1/2] ufs: core: Configure only active lanes during link palash.kambar
2026-03-11 6:09 ` [PATCH v1 2/2] ufs: ufs-qcom: Enable Auto Hibern8 clock request support palash.kambar
0 siblings, 2 replies; 7+ messages in thread
From: palash.kambar @ 2026-03-11 6:09 UTC (permalink / raw)
To: mani, James.Bottomley, martin.petersen
Cc: linux-arm-msm, linux-scsi, linux-kernel, nitin.rawat, Palash Kambar
From: Palash Kambar <palash.kambar@oss.qualcomm.com>
This patch series introduces two updates to the UFS subsystem aimed at
improving link stability and power efficiency on platforms using the
Qualcomm UFS host controller.
During link startup, the number of active TX/RX lanes discovered may be
fewer than the lanes specified in the device tree. The current UFS core
driver configures all DT-defined lanes unconditionally, which can lead to
mismatches during power mode changes. Patch 1/2 ensures to warn on this.
Additionally, certain Qualcomm platforms support Auto Hibern8 (AH8), where
the UFS controller autonomously de-asserts clk_req signals to the GCC
during Hibern8 state. Enabling this mechanism allows the clock controller
to gate unused clocks, providing meaningful power savings. Patch 2/2 adds
support for enabling this feature as recommended by the Hardware
Programming Guidelines.
Palash Kambar (2):
ufs: core: Configure only active lanes during link
ufs: ufs-qcom: Enable Auto Hibern8 clock request support
drivers/ufs/core/ufshcd.c | 39 +++++++++++++++++++++++++++++++++++++
drivers/ufs/host/ufs-qcom.c | 11 +++++++++++
drivers/ufs/host/ufs-qcom.h | 11 +++++++++++
3 files changed, 61 insertions(+)
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v1 1/2] ufs: core: Configure only active lanes during link
2026-03-11 6:09 [PATCH v1 0/2] Add post change sequence for link start notify palash.kambar
@ 2026-03-11 6:09 ` palash.kambar
2026-03-11 6:53 ` Shawn Lin
2026-03-23 15:43 ` Bart Van Assche
2026-03-11 6:09 ` [PATCH v1 2/2] ufs: ufs-qcom: Enable Auto Hibern8 clock request support palash.kambar
1 sibling, 2 replies; 7+ messages in thread
From: palash.kambar @ 2026-03-11 6:09 UTC (permalink / raw)
To: mani, James.Bottomley, martin.petersen
Cc: linux-arm-msm, linux-scsi, linux-kernel, nitin.rawat, Palash Kambar
From: Palash Kambar <palash.kambar@oss.qualcomm.com>
The number of active lanes detected during UFS link startup can be
fewer than the lanes specified in the device tree. The current driver
logic attempts to configure all lanes defined in the device tree,
regardless of their actual availability. This mismatch may cause
failures during power mode changes.
Hence, add check to identify only the lanes that were successfully
discovered during link startup, to warn on power mode change errors
caused by mismatched lane counts.
Signed-off-by: Palash Kambar <palash.kambar@oss.qualcomm.com>
---
drivers/ufs/core/ufshcd.c | 39 +++++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 31950fc51a4c..c956fab32932 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -5035,6 +5035,42 @@ void ufshcd_update_evt_hist(struct ufs_hba *hba, u32 id, u32 val)
}
EXPORT_SYMBOL_GPL(ufshcd_update_evt_hist);
+static int ufshcd_get_connected_tx_lanes(struct ufs_hba *hba, u32 *tx_lanes)
+{
+ return ufshcd_dme_get(hba,
+ UIC_ARG_MIB(PA_CONNECTEDTXDATALANES), tx_lanes);
+}
+
+static int ufshcd_get_connected_rx_lanes(struct ufs_hba *hba, u32 *rx_lanes)
+{
+ return ufshcd_dme_get(hba,
+ UIC_ARG_MIB(PA_CONNECTEDRXDATALANES), rx_lanes);
+}
+
+static void ufshcd_validate_link_params(struct ufs_hba *hba)
+{
+ int val = 0;
+
+ if (ufshcd_get_connected_tx_lanes(hba, &val))
+ return;
+
+ if (val != hba->lanes_per_direction) {
+ dev_err(hba->dev, "Tx lane mismatch [config,reported] [%d,%d]\n",
+ hba->lanes_per_direction, val);
+ return;
+ }
+
+ val = 0;
+
+ if (ufshcd_get_connected_rx_lanes(hba, &val))
+ return;
+
+ if (val != hba->lanes_per_direction) {
+ dev_err(hba->dev, "Rx lane mismatch [config,reported] [%d,%d]\n",
+ hba->lanes_per_direction, val);
+ }
+}
+
/**
* ufshcd_link_startup - Initialize unipro link startup
* @hba: per adapter instance
@@ -5108,6 +5144,9 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
goto out;
}
+ /* Check successfully detected lanes */
+ ufshcd_validate_link_params(hba);
+
/* Include any host controller configuration via UIC commands */
ret = ufshcd_vops_link_startup_notify(hba, POST_CHANGE);
if (ret)
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v1 2/2] ufs: ufs-qcom: Enable Auto Hibern8 clock request support
2026-03-11 6:09 [PATCH v1 0/2] Add post change sequence for link start notify palash.kambar
2026-03-11 6:09 ` [PATCH v1 1/2] ufs: core: Configure only active lanes during link palash.kambar
@ 2026-03-11 6:09 ` palash.kambar
1 sibling, 0 replies; 7+ messages in thread
From: palash.kambar @ 2026-03-11 6:09 UTC (permalink / raw)
To: mani, James.Bottomley, martin.petersen
Cc: linux-arm-msm, linux-scsi, linux-kernel, nitin.rawat, Palash Kambar
From: Palash Kambar <palash.kambar@oss.qualcomm.com>
On platforms that support Auto Hibern8 (AH8), the UFS controller can
autonomously de-assert clk_req signals to the GCC when entering the
Hibern8 state. This allows GCC to gate unused clocks, improving
power efficiency.
Enable the Clock Request feature by setting the UFS_HW_CLK_CTRL_EN
bit in the UFS_AH8_CFG register, as recommended in the Hardware
Programming Guidelines.
Signed-off-by: Palash Kambar <palash.kambar@oss.qualcomm.com>
---
drivers/ufs/host/ufs-qcom.c | 11 +++++++++++
drivers/ufs/host/ufs-qcom.h | 11 +++++++++++
2 files changed, 22 insertions(+)
diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
index 8ebee0cc5313..0e653b34b00d 100644
--- a/drivers/ufs/host/ufs-qcom.c
+++ b/drivers/ufs/host/ufs-qcom.c
@@ -683,6 +683,14 @@ static int ufs_qcom_cfg_timers(struct ufs_hba *hba, bool is_pre_scale_up, unsign
return 0;
}
+static void ufs_qcom_link_startup_post_change(struct ufs_hba *hba)
+{
+ if (ufshcd_is_auto_hibern8_supported(hba)) {
+ ufshcd_rmwl(hba, UFS_HW_CLK_CTRL_EN, UFS_HW_CLK_CTRL_EN,
+ UFS_AH8_CFG);
+ }
+}
+
static int ufs_qcom_link_startup_notify(struct ufs_hba *hba,
enum ufs_notify_change_status status)
{
@@ -708,6 +716,9 @@ static int ufs_qcom_link_startup_notify(struct ufs_hba *hba,
*/
err = ufshcd_disable_host_tx_lcc(hba);
+ break;
+ case POST_CHANGE:
+ ufs_qcom_link_startup_post_change(hba);
break;
default:
break;
diff --git a/drivers/ufs/host/ufs-qcom.h b/drivers/ufs/host/ufs-qcom.h
index 380d02333d38..f19def37c86f 100644
--- a/drivers/ufs/host/ufs-qcom.h
+++ b/drivers/ufs/host/ufs-qcom.h
@@ -228,6 +228,17 @@ enum {
*/
#define NUM_TX_R1W1 13
+/* bit definitions for UFS_AH8_CFG register */
+#define CC_UFS_SYS_CLK_REQ_EN BIT(2)
+#define CC_UFS_ICE_CORE_CLK_REQ_EN BIT(3)
+#define CC_UFS_UNIPRO_CORE_CLK_REQ_EN BIT(4)
+#define CC_UFS_AUXCLK_REQ_EN BIT(5)
+
+#define UFS_HW_CLK_CTRL_EN (CC_UFS_SYS_CLK_REQ_EN |\
+ CC_UFS_ICE_CORE_CLK_REQ_EN |\
+ CC_UFS_UNIPRO_CORE_CLK_REQ_EN |\
+ CC_UFS_AUXCLK_REQ_EN)
+
static inline void
ufs_qcom_get_controller_revision(struct ufs_hba *hba,
u8 *major, u16 *minor, u16 *step)
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v1 1/2] ufs: core: Configure only active lanes during link
2026-03-11 6:09 ` [PATCH v1 1/2] ufs: core: Configure only active lanes during link palash.kambar
@ 2026-03-11 6:53 ` Shawn Lin
2026-03-23 13:14 ` Palash Kambar
2026-03-23 15:43 ` Bart Van Assche
1 sibling, 1 reply; 7+ messages in thread
From: Shawn Lin @ 2026-03-11 6:53 UTC (permalink / raw)
To: palash.kambar
Cc: shawn.lin, linux-arm-msm, linux-scsi, linux-kernel, nitin.rawat,
mani, James.Bottomley, martin.petersen
Hi Palash
在 2026/03/11 星期三 14:09, palash.kambar@oss.qualcomm.com 写道:
> From: Palash Kambar <palash.kambar@oss.qualcomm.com>
>
> The number of active lanes detected during UFS link startup can be
connected lanes(which is used in the code blow) or active lanes? There
are different primitives in UniPro context.
> fewer than the lanes specified in the device tree. The current driver
> logic attempts to configure all lanes defined in the device tree,
> regardless of their actual availability. This mismatch may cause
> failures during power mode changes.
>
It sounds vague, how it causes failures, could you quote some clue from
spec?
> Hence, add check to identify only the lanes that were successfully
> discovered during link startup, to warn on power mode change errors
> caused by mismatched lane counts.
>
> Signed-off-by: Palash Kambar <palash.kambar@oss.qualcomm.com>
> ---
> drivers/ufs/core/ufshcd.c | 39 +++++++++++++++++++++++++++++++++++++++
> 1 file changed, 39 insertions(+)
>
> diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
> index 31950fc51a4c..c956fab32932 100644
> --- a/drivers/ufs/core/ufshcd.c
> +++ b/drivers/ufs/core/ufshcd.c
> @@ -5035,6 +5035,42 @@ void ufshcd_update_evt_hist(struct ufs_hba *hba, u32 id, u32 val)
> }
> EXPORT_SYMBOL_GPL(ufshcd_update_evt_hist);
>
> +static int ufshcd_get_connected_tx_lanes(struct ufs_hba *hba, u32 *tx_lanes)
> +{
> + return ufshcd_dme_get(hba,
> + UIC_ARG_MIB(PA_CONNECTEDTXDATALANES), tx_lanes);
> +}
> +
> +static int ufshcd_get_connected_rx_lanes(struct ufs_hba *hba, u32 *rx_lanes)
> +{
> + return ufshcd_dme_get(hba,
> + UIC_ARG_MIB(PA_CONNECTEDRXDATALANES), rx_lanes);
> +}
> +
> +static void ufshcd_validate_link_params(struct ufs_hba *hba)
> +{
> + int val = 0;
> +
> + if (ufshcd_get_connected_tx_lanes(hba, &val))
> + return;
> +
> + if (val != hba->lanes_per_direction) {
> + dev_err(hba->dev, "Tx lane mismatch [config,reported] [%d,%d]\n",
> + hba->lanes_per_direction, val);
> + return;
> + }
> +
> + val = 0;
> +
> + if (ufshcd_get_connected_rx_lanes(hba, &val))
> + return;
> +
> + if (val != hba->lanes_per_direction) {
> + dev_err(hba->dev, "Rx lane mismatch [config,reported] [%d,%d]\n",
> + hba->lanes_per_direction, val);
> + }
> +}
> +
> /**
> * ufshcd_link_startup - Initialize unipro link startup
> * @hba: per adapter instance
> @@ -5108,6 +5144,9 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
> goto out;
> }
>
> + /* Check successfully detected lanes */
> + ufshcd_validate_link_params(hba);
> +
> /* Include any host controller configuration via UIC commands */
> ret = ufshcd_vops_link_startup_notify(hba, POST_CHANGE);
> if (ret)
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v1 1/2] ufs: core: Configure only active lanes during link
2026-03-11 6:53 ` Shawn Lin
@ 2026-03-23 13:14 ` Palash Kambar
0 siblings, 0 replies; 7+ messages in thread
From: Palash Kambar @ 2026-03-23 13:14 UTC (permalink / raw)
To: Shawn Lin
Cc: linux-arm-msm, linux-scsi, linux-kernel, nitin.rawat, mani,
James.Bottomley, martin.petersen
On 3/11/2026 12:23 PM, Shawn Lin wrote:
> Hi Palash
>
> 在 2026/03/11 星期三 14:09, palash.kambar@oss.qualcomm.com 写道:
>> From: Palash Kambar <palash.kambar@oss.qualcomm.com>
>>
>> The number of active lanes detected during UFS link startup can be
>
> connected lanes(which is used in the code blow) or active lanes? There
> are different primitives in UniPro context.
Yes, I meant connected lanes, will fix comment.
>
>> fewer than the lanes specified in the device tree. The current driver
>> logic attempts to configure all lanes defined in the device tree,
>> regardless of their actual availability. This mismatch may cause
>> failures during power mode changes.
>>
>
> It sounds vague, how it causes failures, could you quote some clue from
> spec?
There was a negotiation mismatch for connected lanes during
link startup phase. So when host sends power mode change(PMC) after
UFS link startup, device returns a failure for PMC command with WR_ERROR_CAP
due to mismatch in the connected lane capability between host and device.
>
>> Hence, add check to identify only the lanes that were successfully
>> discovered during link startup, to warn on power mode change errors
>> caused by mismatched lane counts.
>>
>> Signed-off-by: Palash Kambar <palash.kambar@oss.qualcomm.com>
>> ---
>> drivers/ufs/core/ufshcd.c | 39 +++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 39 insertions(+)
>>
>> diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
>> index 31950fc51a4c..c956fab32932 100644
>> --- a/drivers/ufs/core/ufshcd.c
>> +++ b/drivers/ufs/core/ufshcd.c
>> @@ -5035,6 +5035,42 @@ void ufshcd_update_evt_hist(struct ufs_hba *hba, u32 id, u32 val)
>> }
>> EXPORT_SYMBOL_GPL(ufshcd_update_evt_hist);
>> +static int ufshcd_get_connected_tx_lanes(struct ufs_hba *hba, u32 *tx_lanes)
>> +{
>> + return ufshcd_dme_get(hba,
>> + UIC_ARG_MIB(PA_CONNECTEDTXDATALANES), tx_lanes);
>> +}
>> +
>> +static int ufshcd_get_connected_rx_lanes(struct ufs_hba *hba, u32 *rx_lanes)
>> +{
>> + return ufshcd_dme_get(hba,
>> + UIC_ARG_MIB(PA_CONNECTEDRXDATALANES), rx_lanes);
>> +}
>> +
>> +static void ufshcd_validate_link_params(struct ufs_hba *hba)
>> +{
>> + int val = 0;
>> +
>> + if (ufshcd_get_connected_tx_lanes(hba, &val))
>> + return;
>> +
>> + if (val != hba->lanes_per_direction) {
>> + dev_err(hba->dev, "Tx lane mismatch [config,reported] [%d,%d]\n",
>> + hba->lanes_per_direction, val);
>> + return;
>> + }
>> +
>> + val = 0;
>> +
>> + if (ufshcd_get_connected_rx_lanes(hba, &val))
>> + return;
>> +
>> + if (val != hba->lanes_per_direction) {
>> + dev_err(hba->dev, "Rx lane mismatch [config,reported] [%d,%d]\n",
>> + hba->lanes_per_direction, val);
>> + }
>> +}
>> +
>> /**
>> * ufshcd_link_startup - Initialize unipro link startup
>> * @hba: per adapter instance
>> @@ -5108,6 +5144,9 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
>> goto out;
>> }
>> + /* Check successfully detected lanes */
>> + ufshcd_validate_link_params(hba);
>> +
>> /* Include any host controller configuration via UIC commands */
>> ret = ufshcd_vops_link_startup_notify(hba, POST_CHANGE);
>> if (ret)
>>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v1 1/2] ufs: core: Configure only active lanes during link
2026-03-11 6:09 ` [PATCH v1 1/2] ufs: core: Configure only active lanes during link palash.kambar
2026-03-11 6:53 ` Shawn Lin
@ 2026-03-23 15:43 ` Bart Van Assche
2026-03-26 16:17 ` Palash Kambar
1 sibling, 1 reply; 7+ messages in thread
From: Bart Van Assche @ 2026-03-23 15:43 UTC (permalink / raw)
To: palash.kambar, mani, James.Bottomley, martin.petersen
Cc: linux-arm-msm, linux-scsi, linux-kernel, nitin.rawat
On 3/10/26 11:09 PM, palash.kambar@oss.qualcomm.com wrote:
> [ ... ]
> +static int ufshcd_get_connected_tx_lanes(struct ufs_hba *hba, u32
*tx_lanes)
> +{
> + return ufshcd_dme_get(hba,
> + UIC_ARG_MIB(PA_CONNECTEDTXDATALANES), tx_lanes);
> +}
> +
> +static int ufshcd_get_connected_rx_lanes(struct ufs_hba *hba, u32 *rx_lanes)
> +{
> + return ufshcd_dme_get(hba,
> + UIC_ARG_MIB(PA_CONNECTEDRXDATALANES), rx_lanes);
> +}
The body of the above two functions is very short. Please remove these
functions and instead inline these function into their only caller.
> +static void ufshcd_validate_link_params(struct ufs_hba *hba)
> +{
> + int val = 0;
> +
> + if (ufshcd_get_connected_tx_lanes(hba, &val))
> + return;
Shouldn't it be reported if ufshcd_get_connected_tx_lanes() fails?
> + if (ufshcd_get_connected_rx_lanes(hba, &val))
> + return;
Same question here - shouldn't it be reported if
ufshcd_get_connected_rx_lanes() fails?
Why does this patch only call dev_err() in case of a mismatch instead of
adjusting hba->lanes_per_direction or making initialization fail?
Thanks,
Bart.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v1 1/2] ufs: core: Configure only active lanes during link
2026-03-23 15:43 ` Bart Van Assche
@ 2026-03-26 16:17 ` Palash Kambar
0 siblings, 0 replies; 7+ messages in thread
From: Palash Kambar @ 2026-03-26 16:17 UTC (permalink / raw)
To: Bart Van Assche, mani, James.Bottomley, martin.petersen
Cc: linux-arm-msm, linux-scsi, linux-kernel, nitin.rawat
On 3/23/2026 9:13 PM, Bart Van Assche wrote:
> On 3/10/26 11:09 PM, palash.kambar@oss.qualcomm.com wrote:
>> [ ... ]
>> +static int ufshcd_get_connected_tx_lanes(struct ufs_hba *hba, u32 *tx_lanes)
>> +{
>> + return ufshcd_dme_get(hba,
>> + UIC_ARG_MIB(PA_CONNECTEDTXDATALANES), tx_lanes);
>> +}
>> +
>> +static int ufshcd_get_connected_rx_lanes(struct ufs_hba *hba, u32 *rx_lanes)
>> +{
>> + return ufshcd_dme_get(hba,
>> + UIC_ARG_MIB(PA_CONNECTEDRXDATALANES), rx_lanes);
>> +}
>
> The body of the above two functions is very short. Please remove these
> functions and instead inline these function into their only caller.
Sure Bart, will address this.
>
>> +static void ufshcd_validate_link_params(struct ufs_hba *hba)
>> +{
>> + int val = 0;
>> +
>> + if (ufshcd_get_connected_tx_lanes(hba, &val))
>> + return;
>
> Shouldn't it be reported if ufshcd_get_connected_tx_lanes() fails?
>
>> + if (ufshcd_get_connected_rx_lanes(hba, &val))
>> + return;
>
> Same question here - shouldn't it be reported if
> ufshcd_get_connected_rx_lanes() fails?
>
> Why does this patch only call dev_err() in case of a mismatch instead of adjusting hba->lanes_per_direction or making initialization fail?
Idea was just to warn and catch the failure scenario. But I agree on your feedback. Will fix it.
>
> Thanks,
>
> Bart.
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-03-26 16:17 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-03-11 6:09 [PATCH v1 0/2] Add post change sequence for link start notify palash.kambar
2026-03-11 6:09 ` [PATCH v1 1/2] ufs: core: Configure only active lanes during link palash.kambar
2026-03-11 6:53 ` Shawn Lin
2026-03-23 13:14 ` Palash Kambar
2026-03-23 15:43 ` Bart Van Assche
2026-03-26 16:17 ` Palash Kambar
2026-03-11 6:09 ` [PATCH v1 2/2] ufs: ufs-qcom: Enable Auto Hibern8 clock request support palash.kambar
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®