Loading drivers/scsi/ufs/ufs_quirks.c +2 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ static struct ufs_card_fix ufs_fixups[] = { UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL, UFS_DEVICE_NO_VCCQ), UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL, UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS), UFS_FIX(UFS_VENDOR_TOSHIBA, UFS_ANY_MODEL, UFS_DEVICE_QUIRK_NO_LINK_OFF), END_FIX }; Loading drivers/scsi/ufs/ufs_quirks.h +7 −0 Original line number Diff line number Diff line Loading @@ -99,6 +99,13 @@ struct ufs_card_fix { */ #define UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS (1 << 2) /* * Some UFS devices may not work properly after resume if the link was kept * in off state during suspend. Enabling this quirk will not allow the * link to be kept in off state during suspend. */ #define UFS_DEVICE_QUIRK_NO_LINK_OFF (1 << 3) struct ufs_hba; void ufs_advertise_fixup_device(struct ufs_hba *hba); #endif /* UFS_QUIRKS_H_ */ drivers/scsi/ufs/ufshcd.c +26 −0 Original line number Diff line number Diff line Loading @@ -6102,6 +6102,30 @@ static void ufshcd_clear_dbg_ufs_stats(struct ufs_hba *hba) memset(&hba->ufs_stats.dme_err, 0, err_reg_hist_size); } static void ufshcd_apply_pm_quirks(struct ufs_hba *hba) { if (hba->dev_quirks & UFS_DEVICE_QUIRK_NO_LINK_OFF) { if (ufs_get_pm_lvl_to_link_pwr_state(hba->rpm_lvl) == UIC_LINK_OFF_STATE) { hba->rpm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state( UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE); dev_info(hba->dev, "UFS_DEVICE_QUIRK_NO_LINK_OFF enabled, changed rpm_lvl to %d\n", hba->rpm_lvl); } if (ufs_get_pm_lvl_to_link_pwr_state(hba->spm_lvl) == UIC_LINK_OFF_STATE) { hba->spm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state( UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE); dev_info(hba->dev, "UFS_DEVICE_QUIRK_NO_LINK_OFF enabled, changed spm_lvl to %d\n", hba->spm_lvl); } } } /** * ufshcd_probe_hba - probe hba to detect device and initialize * @hba: per-adapter instance Loading Loading @@ -6134,6 +6158,7 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) ufs_advertise_fixup_device(hba); ufshcd_tune_unipro_params(hba); ufshcd_apply_pm_quirks(hba); ret = ufshcd_set_vccq_rail_unused(hba, (hba->dev_quirks & UFS_DEVICE_NO_VCCQ) ? true : false); if (ret) Loading Loading @@ -7597,6 +7622,7 @@ static inline ssize_t ufshcd_pm_lvl_store(struct device *dev, hba->rpm_lvl = value; else hba->spm_lvl = value; ufshcd_apply_pm_quirks(hba); spin_unlock_irqrestore(hba->host->host_lock, flags); return count; } Loading Loading
drivers/scsi/ufs/ufs_quirks.c +2 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ static struct ufs_card_fix ufs_fixups[] = { UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL, UFS_DEVICE_NO_VCCQ), UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL, UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS), UFS_FIX(UFS_VENDOR_TOSHIBA, UFS_ANY_MODEL, UFS_DEVICE_QUIRK_NO_LINK_OFF), END_FIX }; Loading
drivers/scsi/ufs/ufs_quirks.h +7 −0 Original line number Diff line number Diff line Loading @@ -99,6 +99,13 @@ struct ufs_card_fix { */ #define UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS (1 << 2) /* * Some UFS devices may not work properly after resume if the link was kept * in off state during suspend. Enabling this quirk will not allow the * link to be kept in off state during suspend. */ #define UFS_DEVICE_QUIRK_NO_LINK_OFF (1 << 3) struct ufs_hba; void ufs_advertise_fixup_device(struct ufs_hba *hba); #endif /* UFS_QUIRKS_H_ */
drivers/scsi/ufs/ufshcd.c +26 −0 Original line number Diff line number Diff line Loading @@ -6102,6 +6102,30 @@ static void ufshcd_clear_dbg_ufs_stats(struct ufs_hba *hba) memset(&hba->ufs_stats.dme_err, 0, err_reg_hist_size); } static void ufshcd_apply_pm_quirks(struct ufs_hba *hba) { if (hba->dev_quirks & UFS_DEVICE_QUIRK_NO_LINK_OFF) { if (ufs_get_pm_lvl_to_link_pwr_state(hba->rpm_lvl) == UIC_LINK_OFF_STATE) { hba->rpm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state( UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE); dev_info(hba->dev, "UFS_DEVICE_QUIRK_NO_LINK_OFF enabled, changed rpm_lvl to %d\n", hba->rpm_lvl); } if (ufs_get_pm_lvl_to_link_pwr_state(hba->spm_lvl) == UIC_LINK_OFF_STATE) { hba->spm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state( UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE); dev_info(hba->dev, "UFS_DEVICE_QUIRK_NO_LINK_OFF enabled, changed spm_lvl to %d\n", hba->spm_lvl); } } } /** * ufshcd_probe_hba - probe hba to detect device and initialize * @hba: per-adapter instance Loading Loading @@ -6134,6 +6158,7 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) ufs_advertise_fixup_device(hba); ufshcd_tune_unipro_params(hba); ufshcd_apply_pm_quirks(hba); ret = ufshcd_set_vccq_rail_unused(hba, (hba->dev_quirks & UFS_DEVICE_NO_VCCQ) ? true : false); if (ret) Loading Loading @@ -7597,6 +7622,7 @@ static inline ssize_t ufshcd_pm_lvl_store(struct device *dev, hba->rpm_lvl = value; else hba->spm_lvl = value; ufshcd_apply_pm_quirks(hba); spin_unlock_irqrestore(hba->host->host_lock, flags); return count; } Loading