Re: [PATCH v6 03/10] scsi: ufs: add quirk to enable host controller without hce

Can Guo
2020-04-21T06:01:31Z

On 2020-04-21 13:59, Can Guo wrote:
> On 2020-04-18 01:59, Alim Akhtar wrote:
>> Some host controllers don't support host controller enable via HCE.
>>
>> Signed-off-by: Seungwon Jeon <essuuj@gmail.com>
>> Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
>
> They are back again finally...
>
> Reviewd-by: Can Guo <cang@codeaurora.org>

Reviewed-by: Can Guo <cang@codeaurora.org>

>
>> ---
>> drivers/scsi/ufs/ufshcd.c | 76
>> +++++++++++++++++++++++++++++++++++++--
>> drivers/scsi/ufs/ufshcd.h | 6 ++++
>> 2 files changed, 80 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
>> index 0e9704da58bd..ee30ed6cc805 100644
>> --- a/drivers/scsi/ufs/ufshcd.c
>> +++ b/drivers/scsi/ufs/ufshcd.c
>> @@ -3534,6 +3534,52 @@ static int ufshcd_dme_link_startup(struct
>> ufs_hba *hba)
>> "dme-link-startup: error code %d\n", ret);
>> return ret;
>> }
>> +/**
>> + * ufshcd_dme_reset - UIC command for DME_RESET
>> + * @hba: per adapter instance
>> + *
>> + * DME_RESET command is issued in order to reset UniPro stack.
>> + * This function now deal with cold reset.
>> + *
>> + * Returns 0 on success, non-zero value on failure
>> + */
>> +static int ufshcd_dme_reset(struct ufs_hba *hba)
>> +{
>> + struct uic_command uic_cmd = {0};
>> + int ret;
>> +
>> + uic_cmd.command = UIC_CMD_DME_RESET;
>> +
>> + ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
>> + if (ret)
>> + dev_err(hba->dev,
>> + "dme-reset: error code %d\n", ret);
>> +
>> + return ret;
>> +}
>> +
>> +/**
>> + * ufshcd_dme_enable - UIC command for DME_ENABLE
>> + * @hba: per adapter instance
>> + *
>> + * DME_ENABLE command is issued in order to enable UniPro stack.
>> + *
>> + * Returns 0 on success, non-zero value on failure
>> + */
>> +static int ufshcd_dme_enable(struct ufs_hba *hba)
>> +{
>> + struct uic_command uic_cmd = {0};
>> + int ret;
>> +
>> + uic_cmd.command = UIC_CMD_DME_ENABLE;
>> +
>> + ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
>> + if (ret)
>> + dev_err(hba->dev,
>> + "dme-reset: error code %d\n", ret);
>> +
>> + return ret;
>> +}
>>
>> static inline void ufshcd_add_delay_before_dme_cmd(struct ufs_hba
>> *hba)
>> {
>> @@ -4251,7 +4297,7 @@ static inline void ufshcd_hba_stop(struct
>> ufs_hba *hba, bool can_sleep)
>> }
>>
>> /**
>> - * ufshcd_hba_enable - initialize the controller
>> + * ufshcd_hba_execute_hce - initialize the controller
>> * @hba: per adapter instance
>> *
>> * The controller resets itself and controller firmware
>> initialization
>> @@ -4260,7 +4306,7 @@ static inline void ufshcd_hba_stop(struct
>> ufs_hba *hba, bool can_sleep)
>> *
>> * Returns 0 on success, non-zero value on failure
>> */
>> -int ufshcd_hba_enable(struct ufs_hba *hba)
>> +static int ufshcd_hba_execute_hce(struct ufs_hba *hba)
>> {
>> int retry;
>>
>> @@ -4308,6 +4354,32 @@ int ufshcd_hba_enable(struct ufs_hba *hba)
>>
>> return 0;
>> }
>> +
>> +int ufshcd_hba_enable(struct ufs_hba *hba)
>> +{
>> + int ret;
>> +
>> + if (hba->quirks & UFSHCI_QUIRK_BROKEN_HCE) {
>> + ufshcd_set_link_off(hba);
>> + ufshcd_vops_hce_enable_notify(hba, PRE_CHANGE);
>> +
>> + /* enable UIC related interrupts */
>> + ufshcd_enable_intr(hba, UFSHCD_UIC_MASK);
>> + ret = ufshcd_dme_reset(hba);
>> + if (!ret) {
>> + ret = ufshcd_dme_enable(hba);
>> + if (!ret)
>> + ufshcd_vops_hce_enable_notify(hba, POST_CHANGE);
>> + if (ret)
>> + dev_err(hba->dev,
>> + "Host controller enable failed with non-hce\n");
>> + }
>> + } else {
>> + ret = ufshcd_hba_execute_hce(hba);
>> + }
>> +
>> + return ret;
>> +}
>> EXPORT_SYMBOL_GPL(ufshcd_hba_enable);
>>
>> static int ufshcd_disable_tx_lcc(struct ufs_hba *hba, bool peer)
>> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
>> index 53096642f9a8..f8d08cb9caf7 100644
>> --- a/drivers/scsi/ufs/ufshcd.h
>> +++ b/drivers/scsi/ufs/ufshcd.h
>> @@ -529,6 +529,12 @@ enum ufshcd_quirks {
>> * that the interrupt aggregation timer and counter are reset by
>> s/w.
>> */
>> UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR = 1 << 7,
>> +
>> + /*
>> + * This quirks needs to be enabled if host controller cannot be
>> + * enabled via HCE register.
>> + */
>> + UFSHCI_QUIRK_BROKEN_HCE = 1 << 8,
>> };
>>
>> enum ufshcd_caps {