Loading drivers/scsi/ufs/ufs_quirks.c +2 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,8 @@ static struct ufs_card_fix ufs_fixups[] = { UFS_DEVICE_QUIRK_PA_TACTIVATE), UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9D8KBADG", UFS_DEVICE_QUIRK_PA_TACTIVATE), UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL, UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE), END_FIX }; Loading drivers/scsi/ufs/ufs_quirks.h +7 −0 Original line number Diff line number Diff line Loading @@ -122,6 +122,13 @@ struct ufs_card_fix { */ #define UFS_DEVICE_NO_FASTAUTO (1 << 5) /* * Some UFS devices require host PA_TACTIVATE to be lower than device * PA_TACTIVATE, enabling this quirk ensure this. */ #define UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE (1 << 6) struct ufs_hba; void ufs_advertise_fixup_device(struct ufs_hba *hba); #endif /* UFS_QUIRKS_H_ */ drivers/scsi/ufs/ufshcd.c +73 −0 Original line number Diff line number Diff line Loading @@ -6507,6 +6507,76 @@ out: return ret; } /** * ufshcd_quirk_tune_host_pa_tactivate - Ensures that host PA_TACTIVATE is * more than device PA_TACTIVATE time. * @hba: per-adapter instance * * Some UFS devices require host PA_TACTIVATE to be lower than device * PA_TACTIVATE, we need to enable UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE quirk * for such devices. * * Returns zero on success, non-zero error value on failure. */ static int ufshcd_quirk_tune_host_pa_tactivate(struct ufs_hba *hba) { int ret = 0; u32 granularity, peer_granularity; u32 pa_tactivate, peer_pa_tactivate; u32 pa_tactivate_us, peer_pa_tactivate_us; u8 gran_to_us_table[] = {1, 4, 8, 16, 32, 100}; ret = ufshcd_dme_get(hba, UIC_ARG_MIB(PA_GRANULARITY), &granularity); if (ret) goto out; ret = ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_GRANULARITY), &peer_granularity); if (ret) goto out; if ((granularity < PA_GRANULARITY_MIN_VAL) || (granularity > PA_GRANULARITY_MAX_VAL)) { dev_err(hba->dev, "%s: invalid host PA_GRANULARITY %d", __func__, granularity); return -EINVAL; } if ((peer_granularity < PA_GRANULARITY_MIN_VAL) || (peer_granularity > PA_GRANULARITY_MAX_VAL)) { dev_err(hba->dev, "%s: invalid device PA_GRANULARITY %d", __func__, peer_granularity); return -EINVAL; } ret = ufshcd_dme_get(hba, UIC_ARG_MIB(PA_TACTIVATE), &pa_tactivate); if (ret) goto out; ret = ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_TACTIVATE), &peer_pa_tactivate); if (ret) goto out; pa_tactivate_us = pa_tactivate * gran_to_us_table[granularity - 1]; peer_pa_tactivate_us = peer_pa_tactivate * gran_to_us_table[peer_granularity - 1]; if (pa_tactivate_us > peer_pa_tactivate_us) { u32 new_peer_pa_tactivate; new_peer_pa_tactivate = pa_tactivate_us / gran_to_us_table[peer_granularity - 1]; new_peer_pa_tactivate++; ret = ufshcd_dme_peer_set(hba, UIC_ARG_MIB(PA_TACTIVATE), new_peer_pa_tactivate); } out: return ret; } static void ufshcd_tune_unipro_params(struct ufs_hba *hba) { if (ufshcd_is_unipro_pa_params_tuning_req(hba)) { Loading @@ -6517,6 +6587,9 @@ static void ufshcd_tune_unipro_params(struct ufs_hba *hba) if (hba->dev_quirks & UFS_DEVICE_QUIRK_PA_TACTIVATE) /* set 1ms timeout for PA_TACTIVATE */ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE), 10); if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE) ufshcd_quirk_tune_host_pa_tactivate(hba); } static void ufshcd_clear_dbg_ufs_stats(struct ufs_hba *hba) Loading drivers/scsi/ufs/unipro.h +4 −0 Original line number Diff line number Diff line Loading @@ -91,6 +91,7 @@ #define PA_MAXRXHSGEAR 0x1587 #define PA_RXHSUNTERMCAP 0x15A5 #define PA_RXLSTERMCAP 0x15A6 #define PA_GRANULARITY 0x15AA #define PA_PACPREQTIMEOUT 0x1590 #define PA_PACPREQEOBTIMEOUT 0x1591 #define PA_HIBERN8TIME 0x15A7 Loading Loading @@ -121,6 +122,9 @@ #define PA_TACTIVATE_TIME_UNIT_US 10 #define PA_HIBERN8_TIME_UNIT_US 100 #define PA_GRANULARITY_MIN_VAL 1 #define PA_GRANULARITY_MAX_VAL 6 /* PHY Adapter Protocol Constants */ #define PA_MAXDATALANES 4 Loading Loading
drivers/scsi/ufs/ufs_quirks.c +2 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,8 @@ static struct ufs_card_fix ufs_fixups[] = { UFS_DEVICE_QUIRK_PA_TACTIVATE), UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9D8KBADG", UFS_DEVICE_QUIRK_PA_TACTIVATE), UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL, UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE), END_FIX }; Loading
drivers/scsi/ufs/ufs_quirks.h +7 −0 Original line number Diff line number Diff line Loading @@ -122,6 +122,13 @@ struct ufs_card_fix { */ #define UFS_DEVICE_NO_FASTAUTO (1 << 5) /* * Some UFS devices require host PA_TACTIVATE to be lower than device * PA_TACTIVATE, enabling this quirk ensure this. */ #define UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE (1 << 6) struct ufs_hba; void ufs_advertise_fixup_device(struct ufs_hba *hba); #endif /* UFS_QUIRKS_H_ */
drivers/scsi/ufs/ufshcd.c +73 −0 Original line number Diff line number Diff line Loading @@ -6507,6 +6507,76 @@ out: return ret; } /** * ufshcd_quirk_tune_host_pa_tactivate - Ensures that host PA_TACTIVATE is * more than device PA_TACTIVATE time. * @hba: per-adapter instance * * Some UFS devices require host PA_TACTIVATE to be lower than device * PA_TACTIVATE, we need to enable UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE quirk * for such devices. * * Returns zero on success, non-zero error value on failure. */ static int ufshcd_quirk_tune_host_pa_tactivate(struct ufs_hba *hba) { int ret = 0; u32 granularity, peer_granularity; u32 pa_tactivate, peer_pa_tactivate; u32 pa_tactivate_us, peer_pa_tactivate_us; u8 gran_to_us_table[] = {1, 4, 8, 16, 32, 100}; ret = ufshcd_dme_get(hba, UIC_ARG_MIB(PA_GRANULARITY), &granularity); if (ret) goto out; ret = ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_GRANULARITY), &peer_granularity); if (ret) goto out; if ((granularity < PA_GRANULARITY_MIN_VAL) || (granularity > PA_GRANULARITY_MAX_VAL)) { dev_err(hba->dev, "%s: invalid host PA_GRANULARITY %d", __func__, granularity); return -EINVAL; } if ((peer_granularity < PA_GRANULARITY_MIN_VAL) || (peer_granularity > PA_GRANULARITY_MAX_VAL)) { dev_err(hba->dev, "%s: invalid device PA_GRANULARITY %d", __func__, peer_granularity); return -EINVAL; } ret = ufshcd_dme_get(hba, UIC_ARG_MIB(PA_TACTIVATE), &pa_tactivate); if (ret) goto out; ret = ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_TACTIVATE), &peer_pa_tactivate); if (ret) goto out; pa_tactivate_us = pa_tactivate * gran_to_us_table[granularity - 1]; peer_pa_tactivate_us = peer_pa_tactivate * gran_to_us_table[peer_granularity - 1]; if (pa_tactivate_us > peer_pa_tactivate_us) { u32 new_peer_pa_tactivate; new_peer_pa_tactivate = pa_tactivate_us / gran_to_us_table[peer_granularity - 1]; new_peer_pa_tactivate++; ret = ufshcd_dme_peer_set(hba, UIC_ARG_MIB(PA_TACTIVATE), new_peer_pa_tactivate); } out: return ret; } static void ufshcd_tune_unipro_params(struct ufs_hba *hba) { if (ufshcd_is_unipro_pa_params_tuning_req(hba)) { Loading @@ -6517,6 +6587,9 @@ static void ufshcd_tune_unipro_params(struct ufs_hba *hba) if (hba->dev_quirks & UFS_DEVICE_QUIRK_PA_TACTIVATE) /* set 1ms timeout for PA_TACTIVATE */ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE), 10); if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE) ufshcd_quirk_tune_host_pa_tactivate(hba); } static void ufshcd_clear_dbg_ufs_stats(struct ufs_hba *hba) Loading
drivers/scsi/ufs/unipro.h +4 −0 Original line number Diff line number Diff line Loading @@ -91,6 +91,7 @@ #define PA_MAXRXHSGEAR 0x1587 #define PA_RXHSUNTERMCAP 0x15A5 #define PA_RXLSTERMCAP 0x15A6 #define PA_GRANULARITY 0x15AA #define PA_PACPREQTIMEOUT 0x1590 #define PA_PACPREQEOBTIMEOUT 0x1591 #define PA_HIBERN8TIME 0x15A7 Loading Loading @@ -121,6 +122,9 @@ #define PA_TACTIVATE_TIME_UNIT_US 10 #define PA_HIBERN8_TIME_UNIT_US 100 #define PA_GRANULARITY_MIN_VAL 1 #define PA_GRANULARITY_MAX_VAL 6 /* PHY Adapter Protocol Constants */ #define PA_MAXDATALANES 4 Loading