[PATCH 2/3] scsi: ufs: core: Tolerate RX_FOM read failures in TX EQTR
From: Can Guo
Date: Sat Jun 20 2026 - 04:05:51 EST
ufshcd_get_rx_fom() aborted TX EQTR when a per-lane RX_FOM DME read failed.
That makes the whole training flow fragile even though these reads can be
treated as best effort.
Keep TX EQTR running by logging RX_FOM read failures and continuing.
Make failed lanes deterministic by initializing each lane FOM to 0 before
reading and only updating it when the DME read succeeds. This avoids
propagating stale or uninitialized values into EQTR evaluation.
Also update the kerneldoc return description to match behavior: RX_FOM
DME read failures are logged for debug visibility, while get_rx_fom()
vops failures are still propagated to the caller.
Signed-off-by: Can Guo <can.guo@xxxxxxxxxxxxxxxx>
---
drivers/ufs/core/ufs-txeq.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/drivers/ufs/core/ufs-txeq.c b/drivers/ufs/core/ufs-txeq.c
index 9dca0cd344b8..23a12e221d31 100644
--- a/drivers/ufs/core/ufs-txeq.c
+++ b/drivers/ufs/core/ufs-txeq.c
@@ -482,7 +482,9 @@ static void ufshcd_evaluate_tx_eqtr_fom(struct ufs_hba *hba,
* @h_iter: host TX EQTR iterator data structure
* @d_iter: device TX EQTR iterator data structure
*
- * Returns 0 on success, negative error code otherwise
+ * Returns 0 on success, negative error code if get_rx_fom vops fails.
+ * RX_FOM DME get failures are debug-logged and treated as 0 FOM for
+ * that lane.
*/
static int ufshcd_get_rx_fom(struct ufs_hba *hba,
struct ufs_pa_layer_attr *pwr_mode,
@@ -494,22 +496,30 @@ static int ufshcd_get_rx_fom(struct ufs_hba *hba,
/* Get FOM of host's TX lanes from device's RX_FOM. */
for (lane = 0; lane < pwr_mode->lane_tx; lane++) {
+ h_iter->fom[lane] = 0;
ret = ufshcd_dme_peer_get(hba, UIC_ARG_MIB_SEL(RX_FOM,
UIC_ARG_MPHY_RX_GEN_SEL_INDEX(lane)),
&fom);
- if (ret)
- return ret;
+ if (ret) {
+ dev_dbg(hba->dev, "Failed to get FOM for Host TX Lane %d: %d\n",
+ lane, ret);
+ continue;
+ }
h_iter->fom[lane] = (u8)fom;
}
/* Get FOM of device's TX lanes from host's RX_FOM. */
for (lane = 0; lane < pwr_mode->lane_rx; lane++) {
+ d_iter->fom[lane] = 0;
ret = ufshcd_dme_get(hba, UIC_ARG_MIB_SEL(RX_FOM,
UIC_ARG_MPHY_RX_GEN_SEL_INDEX(lane)),
&fom);
- if (ret)
- return ret;
+ if (ret) {
+ dev_dbg(hba->dev, "Failed to get FOM for Device TX Lane %d: %d\n",
+ lane, ret);
+ continue;
+ }
d_iter->fom[lane] = (u8)fom;
}
--
2.34.1