Re: [PATCH v4 04/12] scsi: ufs: core: Add support for TX Equalization
From: Bean Huo
Date: Sun Mar 22 2026 - 05:49:32 EST
> Can,
>
>
> + * to ensure both host and device use adequate TX adapt length.
> + *
> + * Returns 0 on success, negative error code otherwise
> + */
> +static int ufshcd_setup_tx_eqtr_adapt_length(struct ufs_hba *hba,
> + struct ufshcd_tx_eq_params
> *params,
> + u32 gear)
> +{
> + u32 adapt_eqtr;
> + int ret;
> +
> + if (gear == UFS_HS_G4 || gear == UFS_HS_G5) {
> + u64 t_adapt, t_adapt_local, t_adapt_peer;
> + u32 adapt_cap_local, adapt_cap_peer, adapt_length;
> +
> + ret = ufshcd_dme_get(hba,
> UIC_ARG_MIB_SEL(rx_adapt_initial_cap[gear - 1],
> + UIC_ARG_MPHY_RX_GEN_SEL_INDEX(0)),
> + &adapt_cap_local);
> + if (ret)
> + return ret;
> +
> + if (adapt_cap_local > ADAPT_LENGTH_MAX) {
> + dev_err(hba->dev, "local RX_HS_G%u_ADAPT_INITIAL_CAP
> (0x%x) exceeds MAX\n",
> + gear, adapt_cap_local);
> + return -EINVAL;
> + }
> +
> + ret = ufshcd_dme_get(hba,
> UIC_ARG_MIB(pa_peer_rx_adapt_initial[gear - 1]),
> + &adapt_cap_peer);
> + if (ret)
> + return ret;
> +
> + if (adapt_cap_peer > ADAPT_LENGTH_MAX) {
> + dev_err(hba->dev, "local RX_HS_G%u_ADAPT_INITIAL_CAP
here should pear: local --> peer
> (0x%x) exceeds MAX\n",
> + gear, adapt_cap_peer);
> + return -EINVAL;
> + }
> +
> + t_adapt_local = adapt_cap_to_t_adapt(adapt_cap_local);
> + t_adapt_peer = adapt_cap_to_t_adapt(adapt_cap_peer);
> + t_adapt = max(t_adapt_local, t_adapt_peer);
> +
> + dev_dbg(hba->dev, "local RX_HS_G%u_ADAPT_INITIAL_CAP =
> 0x%x\n",
> + gear, adapt_cap_local);
> + dev_dbg(hba->dev, "peer RX_HS_G%u_ADAPT_INITIAL_CAP = 0x%x\n",
> + gear, adapt_cap_peer);
> + dev_dbg(hba->dev, "t_adapt_local = %llu UI, t_adapt_peer =
> %llu UI\n",
> + t_adapt_local, t_adapt_peer);
> + dev_dbg(hba->dev, "TAdapt %llu UI selected for TX EQTR\n",
> + t_adapt);
>
...
> +
> +/**
> + * ufshcd_config_tx_eq_settings - Configure TX Equalization settings
> + * @hba: per adapter instance
> + * @pwr_mode: target power mode containing gear and rate information
> + *
> + * This function finds and sets the TX Equalization settings for the given
> + * target power mode.
> + *
> + * Returns 0 on success, error code otherwise
> + */
> +int ufshcd_config_tx_eq_settings(struct ufs_hba *hba,
> + struct ufs_pa_layer_attr *pwr_mode)
> +{
> + struct ufshcd_tx_eq_params *params;
> + u32 gear, rate;
> +
> + if (!ufshcd_is_tx_eq_supported(hba) || !use_adaptive_txeq)
> + return 0;
> +
> + if (!hba->max_pwr_info.is_valid) {
> + dev_err(hba->dev, "Max power info is invalid\n");
> + return -EINVAL;
> + }
> +
> + if (!pwr_mode) {
> + dev_err(hba->dev, "Target power mode is NULL\n");
> + return -EINVAL;
> + }
> +
> + gear = pwr_mode->gear_tx;
> + rate = pwr_mode->hs_rate;
> + params = &hba->tx_eq_params[gear - 1];
> +
> + if (gear < UFS_HS_G1 || gear > UFS_HS_GEAR_MAX) {
> + dev_err(hba->dev, "Invalid HS-Gear (%u) for TX
> Equalization\n",
> + gear);
> + return -EINVAL;
> + } else if (gear < adaptive_txeq_gear) {
> + return 0;
> + }
> +
> + if (rate != PA_HS_MODE_A && rate != PA_HS_MODE_B) {
> + dev_err(hba->dev, "Invalid HS-Rate (%u) for TX
> Equalization\n",
> + rate);
> + return -EINVAL;
> + }
> +
> + /* TX EQTR is supported for HS-G4 and higher Gears */
> + if (gear < UFS_HS_G4)
> + goto apply_tx_eq_settings;
> +
> + if (!params->is_valid) {
> + int ret;
> +
> + ret = ufshcd_tx_eqtr(hba, params, pwr_mode);
> + if (ret) {
> + dev_err(hba->dev, "Failed to train TX Equalization for
> HS-G%u, Rate-%s: %d\n",
> + gear, ufs_hs_rate_to_str(rate), ret);
> + return ret;
> + }
> +
> + /* Mark TX Equalization settings as valid */
> + params->is_valid = true;
> + params->is_applied = false;
after eqtr completes here, the trained settings are only kept in memory. UFS 5.0
introduced qTxEQGnSettings and wTxEQGnSettingsExt as persistent device
attributes for storing optimal TX EQ results across power cycles. should we
write back to these attributes after training, and read them on next boot to
skip EQTR if valid settings already exist? That would save the training overhead
on every boot?
Kind regards,
Bean