scsi: ufs: core: Add support for reinitializing the UFS device

Some platforms like Qcom, requires the UFS device to be reinitialized after
switching to maximum gear speed. So add support for that in UFS core by
introducing a new quirk (UFSHCD_CAP_REINIT_AFTER_MAX_GEAR_SWITCH) and doing
the reinitialization, if the quirk is enabled by the controller driver.

Suggested-by: Can Guo <quic_cang@quicinc.com>
Tested-by: Andrew Halaney <ahalaney@redhat.com> # Qdrive3/sa8540p-ride
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Manivannan Sadhasivam 2022-12-22 19:39:57 +05:30 committed by Martin K. Petersen
parent c2c38c573a
commit 96a7141da3
2 changed files with 53 additions and 16 deletions

View File

@ -8231,27 +8231,18 @@ out:
return ret;
}
/**
* ufshcd_probe_hba - probe hba to detect device and initialize it
* @hba: per-adapter instance
* @init_dev_params: whether or not to call ufshcd_device_params_init().
*
* Execute link-startup and verify device initialization
*/
static int ufshcd_probe_hba(struct ufs_hba *hba, bool init_dev_params)
static int ufshcd_device_init(struct ufs_hba *hba, bool init_dev_params)
{
int ret;
unsigned long flags;
ktime_t start = ktime_get();
hba->ufshcd_state = UFSHCD_STATE_RESET;
ret = ufshcd_link_startup(hba);
if (ret)
goto out;
return ret;
if (hba->quirks & UFSHCD_QUIRK_SKIP_PH_CONFIGURATION)
goto out;
return ret;
/* Debug counters initialization */
ufshcd_clear_dbg_ufs_stats(hba);
@ -8262,12 +8253,12 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool init_dev_params)
/* Verify device initialization by sending NOP OUT UPIU */
ret = ufshcd_verify_dev_init(hba);
if (ret)
goto out;
return ret;
/* Initiate UFS initialization, and waiting until completion */
ret = ufshcd_complete_dev_init(hba);
if (ret)
goto out;
return ret;
/*
* Initialize UFS device parameters used by driver, these
@ -8276,7 +8267,7 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool init_dev_params)
if (init_dev_params) {
ret = ufshcd_device_params_init(hba);
if (ret)
goto out;
return ret;
}
ufshcd_tune_unipro_params(hba);
@ -8297,11 +8288,51 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool init_dev_params)
if (ret) {
dev_err(hba->dev, "%s: Failed setting power mode, err = %d\n",
__func__, ret);
return ret;
}
}
return 0;
}
/**
* ufshcd_probe_hba - probe hba to detect device and initialize it
* @hba: per-adapter instance
* @init_dev_params: whether or not to call ufshcd_device_params_init().
*
* Execute link-startup and verify device initialization
*/
static int ufshcd_probe_hba(struct ufs_hba *hba, bool init_dev_params)
{
ktime_t start = ktime_get();
unsigned long flags;
int ret;
ret = ufshcd_device_init(hba, init_dev_params);
if (ret)
goto out;
if (hba->quirks & UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH) {
/* Reset the device and controller before doing reinit */
ufshcd_device_reset(hba);
ufshcd_hba_stop(hba);
ufshcd_vops_reinit_notify(hba);
ret = ufshcd_hba_enable(hba);
if (ret) {
dev_err(hba->dev, "Host controller enable failed\n");
ufshcd_print_evt_hist(hba);
ufshcd_print_host_state(hba);
goto out;
}
ufshcd_print_pwr_info(hba);
/* Reinit the device */
ret = ufshcd_device_init(hba, init_dev_params);
if (ret)
goto out;
}
ufshcd_print_pwr_info(hba);
/*
* bActiveICCLevel is volatile for UFS device (as per latest v2.1 spec)
* and for removable UFS card as well, hence always set the parameter.

View File

@ -596,6 +596,12 @@ enum ufshcd_quirks {
* auto-hibernate capability but it's FASTAUTO only.
*/
UFSHCD_QUIRK_HIBERN_FASTAUTO = 1 << 18,
/*
* This quirk needs to be enabled if the host controller needs
* to reinit the device after switching to maximum gear.
*/
UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH = 1 << 19,
};
enum ufshcd_caps {