aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSubhash Jadavani <subhashj@codeaurora.org>2017-04-04 15:32:07 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-04-12 06:41:17 -0400
commit3a87bcdebf6eeb094be139a42626edb7dce8c960 (patch)
treef051cfc8311bc7c068a297552ab8af9ea418b26b
parentd84be51d1c1d3fa148a3abdeeb1455690df59e63 (diff)
scsi: ufs: ensure that host pa_tactivate is higher than device
[ Upstream commit c6a6db439868c7ba5cc90d4c461d9697ec731fa1 ] Some UFS devices require host PA_TACTIVATE to be higher than device PA_TACTIVATE otherwise it may get stuck during hibern8 sequence. This change allows this by using quirk. Reviewed-by: Venkat Gopalakrishnan <venkatg@codeaurora.org> Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Sasha Levin <alexander.levin@verizon.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/scsi/ufs/ufs_quirks.h9
-rw-r--r--drivers/scsi/ufs/ufshcd.c73
-rw-r--r--drivers/scsi/ufs/unipro.h4
3 files changed, 86 insertions, 0 deletions
diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h
index 22f881e9253a..f7983058f3f7 100644
--- a/drivers/scsi/ufs/ufs_quirks.h
+++ b/drivers/scsi/ufs/ufs_quirks.h
@@ -128,6 +128,13 @@ struct ufs_dev_fix {
128 */ 128 */
129#define UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM (1 << 6) 129#define UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM (1 << 6)
130 130
131/*
132 * Some UFS devices require host PA_TACTIVATE to be lower than device
133 * PA_TACTIVATE, enabling this quirk ensure this.
134 */
135#define UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE (1 << 7)
136
137
131struct ufs_hba; 138struct ufs_hba;
132void ufs_advertise_fixup_device(struct ufs_hba *hba); 139void ufs_advertise_fixup_device(struct ufs_hba *hba);
133 140
@@ -140,6 +147,8 @@ static struct ufs_dev_fix ufs_fixups[] = {
140 UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS), 147 UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS),
141 UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL, 148 UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
142 UFS_DEVICE_NO_FASTAUTO), 149 UFS_DEVICE_NO_FASTAUTO),
150 UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
151 UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE),
143 UFS_FIX(UFS_VENDOR_TOSHIBA, UFS_ANY_MODEL, 152 UFS_FIX(UFS_VENDOR_TOSHIBA, UFS_ANY_MODEL,
144 UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM), 153 UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM),
145 UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9C8KBADG", 154 UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9C8KBADG",
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index b89618f27725..6f6a209fdae0 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -4979,6 +4979,76 @@ out:
4979 return ret; 4979 return ret;
4980} 4980}
4981 4981
4982/**
4983 * ufshcd_quirk_tune_host_pa_tactivate - Ensures that host PA_TACTIVATE is
4984 * less than device PA_TACTIVATE time.
4985 * @hba: per-adapter instance
4986 *
4987 * Some UFS devices require host PA_TACTIVATE to be lower than device
4988 * PA_TACTIVATE, we need to enable UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE quirk
4989 * for such devices.
4990 *
4991 * Returns zero on success, non-zero error value on failure.
4992 */
4993static int ufshcd_quirk_tune_host_pa_tactivate(struct ufs_hba *hba)
4994{
4995 int ret = 0;
4996 u32 granularity, peer_granularity;
4997 u32 pa_tactivate, peer_pa_tactivate;
4998 u32 pa_tactivate_us, peer_pa_tactivate_us;
4999 u8 gran_to_us_table[] = {1, 4, 8, 16, 32, 100};
5000
5001 ret = ufshcd_dme_get(hba, UIC_ARG_MIB(PA_GRANULARITY),
5002 &granularity);
5003 if (ret)
5004 goto out;
5005
5006 ret = ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_GRANULARITY),
5007 &peer_granularity);
5008 if (ret)
5009 goto out;
5010
5011 if ((granularity < PA_GRANULARITY_MIN_VAL) ||
5012 (granularity > PA_GRANULARITY_MAX_VAL)) {
5013 dev_err(hba->dev, "%s: invalid host PA_GRANULARITY %d",
5014 __func__, granularity);
5015 return -EINVAL;
5016 }
5017
5018 if ((peer_granularity < PA_GRANULARITY_MIN_VAL) ||
5019 (peer_granularity > PA_GRANULARITY_MAX_VAL)) {
5020 dev_err(hba->dev, "%s: invalid device PA_GRANULARITY %d",
5021 __func__, peer_granularity);
5022 return -EINVAL;
5023 }
5024
5025 ret = ufshcd_dme_get(hba, UIC_ARG_MIB(PA_TACTIVATE), &pa_tactivate);
5026 if (ret)
5027 goto out;
5028
5029 ret = ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_TACTIVATE),
5030 &peer_pa_tactivate);
5031 if (ret)
5032 goto out;
5033
5034 pa_tactivate_us = pa_tactivate * gran_to_us_table[granularity - 1];
5035 peer_pa_tactivate_us = peer_pa_tactivate *
5036 gran_to_us_table[peer_granularity - 1];
5037
5038 if (pa_tactivate_us > peer_pa_tactivate_us) {
5039 u32 new_peer_pa_tactivate;
5040
5041 new_peer_pa_tactivate = pa_tactivate_us /
5042 gran_to_us_table[peer_granularity - 1];
5043 new_peer_pa_tactivate++;
5044 ret = ufshcd_dme_peer_set(hba, UIC_ARG_MIB(PA_TACTIVATE),
5045 new_peer_pa_tactivate);
5046 }
5047
5048out:
5049 return ret;
5050}
5051
4982static void ufshcd_tune_unipro_params(struct ufs_hba *hba) 5052static void ufshcd_tune_unipro_params(struct ufs_hba *hba)
4983{ 5053{
4984 if (ufshcd_is_unipro_pa_params_tuning_req(hba)) { 5054 if (ufshcd_is_unipro_pa_params_tuning_req(hba)) {
@@ -4989,6 +5059,9 @@ static void ufshcd_tune_unipro_params(struct ufs_hba *hba)
4989 if (hba->dev_quirks & UFS_DEVICE_QUIRK_PA_TACTIVATE) 5059 if (hba->dev_quirks & UFS_DEVICE_QUIRK_PA_TACTIVATE)
4990 /* set 1ms timeout for PA_TACTIVATE */ 5060 /* set 1ms timeout for PA_TACTIVATE */
4991 ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE), 10); 5061 ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE), 10);
5062
5063 if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE)
5064 ufshcd_quirk_tune_host_pa_tactivate(hba);
4992} 5065}
4993 5066
4994/** 5067/**
diff --git a/drivers/scsi/ufs/unipro.h b/drivers/scsi/ufs/unipro.h
index eff8b5675575..23129d7b2678 100644
--- a/drivers/scsi/ufs/unipro.h
+++ b/drivers/scsi/ufs/unipro.h
@@ -123,6 +123,7 @@
123#define PA_MAXRXHSGEAR 0x1587 123#define PA_MAXRXHSGEAR 0x1587
124#define PA_RXHSUNTERMCAP 0x15A5 124#define PA_RXHSUNTERMCAP 0x15A5
125#define PA_RXLSTERMCAP 0x15A6 125#define PA_RXLSTERMCAP 0x15A6
126#define PA_GRANULARITY 0x15AA
126#define PA_PACPREQTIMEOUT 0x1590 127#define PA_PACPREQTIMEOUT 0x1590
127#define PA_PACPREQEOBTIMEOUT 0x1591 128#define PA_PACPREQEOBTIMEOUT 0x1591
128#define PA_HIBERN8TIME 0x15A7 129#define PA_HIBERN8TIME 0x15A7
@@ -158,6 +159,9 @@
158#define VS_DEBUGOMC 0xD09E 159#define VS_DEBUGOMC 0xD09E
159#define VS_POWERSTATE 0xD083 160#define VS_POWERSTATE 0xD083
160 161
162#define PA_GRANULARITY_MIN_VAL 1
163#define PA_GRANULARITY_MAX_VAL 6
164
161/* PHY Adapter Protocol Constants */ 165/* PHY Adapter Protocol Constants */
162#define PA_MAXDATALANES 4 166#define PA_MAXDATALANES 4
163 167