aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorYaniv Gardi <ygardi@codeaurora.org>2016-03-10 10:37:16 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2016-03-14 21:04:45 -0400
commit371131065de99b57d39620ac159d94e0d3773f13 (patch)
tree91e9ead0d5b477dc0a97b5050d29ab254b0a94b6 /drivers/scsi
parentafdfff59a0e0c5527610d3bc5d338a0da03dd23d (diff)
scsi: ufs: tune UniPro parameters to optimize hibern8 exit time
Optimal values of local UniPro parameters like PA_Hibern8Time & PA_TActivate can help reduce the hibern8 exit latency. If both host and device supports UniPro ver1.6 or later, these parameters will be automatically tuned during link startup itself. But if either host or device doesn't support UniPro ver 1.6 or later, we have to manually tune them. But to keep manual tuning logic simple, we will only do manual tuning if local unipro version doesn't support ver1.6 or later. Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org> Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/ufs/ufshcd.c118
-rw-r--r--drivers/scsi/ufs/ufshcd.h1
-rw-r--r--drivers/scsi/ufs/ufshci.h2
-rw-r--r--drivers/scsi/ufs/unipro.h21
4 files changed, 142 insertions, 0 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 82a4b1c3a837..305210fda370 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -570,6 +570,34 @@ static inline int ufshcd_is_hba_active(struct ufs_hba *hba)
570 return (ufshcd_readl(hba, REG_CONTROLLER_ENABLE) & 0x1) ? 0 : 1; 570 return (ufshcd_readl(hba, REG_CONTROLLER_ENABLE) & 0x1) ? 0 : 1;
571} 571}
572 572
573u32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba)
574{
575 /* HCI version 1.0 and 1.1 supports UniPro 1.41 */
576 if ((hba->ufs_version == UFSHCI_VERSION_10) ||
577 (hba->ufs_version == UFSHCI_VERSION_11))
578 return UFS_UNIPRO_VER_1_41;
579 else
580 return UFS_UNIPRO_VER_1_6;
581}
582EXPORT_SYMBOL(ufshcd_get_local_unipro_ver);
583
584static bool ufshcd_is_unipro_pa_params_tuning_req(struct ufs_hba *hba)
585{
586 /*
587 * If both host and device support UniPro ver1.6 or later, PA layer
588 * parameters tuning happens during link startup itself.
589 *
590 * We can manually tune PA layer parameters if either host or device
591 * doesn't support UniPro ver 1.6 or later. But to keep manual tuning
592 * logic simple, we will only do manual tuning if local unipro version
593 * doesn't support ver1.6 or later.
594 */
595 if (ufshcd_get_local_unipro_ver(hba) < UFS_UNIPRO_VER_1_6)
596 return true;
597 else
598 return false;
599}
600
573static void ufshcd_ungate_work(struct work_struct *work) 601static void ufshcd_ungate_work(struct work_struct *work)
574{ 602{
575 int ret; 603 int ret;
@@ -4852,6 +4880,95 @@ void ufs_advertise_fixup_device(struct ufs_hba *hba)
4852} 4880}
4853 4881
4854/** 4882/**
4883 * ufshcd_tune_pa_tactivate - Tunes PA_TActivate of local UniPro
4884 * @hba: per-adapter instance
4885 *
4886 * PA_TActivate parameter can be tuned manually if UniPro version is less than
4887 * 1.61. PA_TActivate needs to be greater than or equal to peerM-PHY's
4888 * RX_MIN_ACTIVATETIME_CAPABILITY attribute. This optimal value can help reduce
4889 * the hibern8 exit latency.
4890 *
4891 * Returns zero on success, non-zero error value on failure.
4892 */
4893static int ufshcd_tune_pa_tactivate(struct ufs_hba *hba)
4894{
4895 int ret = 0;
4896 u32 peer_rx_min_activatetime = 0, tuned_pa_tactivate;
4897
4898 ret = ufshcd_dme_peer_get(hba,
4899 UIC_ARG_MIB_SEL(
4900 RX_MIN_ACTIVATETIME_CAPABILITY,
4901 UIC_ARG_MPHY_RX_GEN_SEL_INDEX(0)),
4902 &peer_rx_min_activatetime);
4903 if (ret)
4904 goto out;
4905
4906 /* make sure proper unit conversion is applied */
4907 tuned_pa_tactivate =
4908 ((peer_rx_min_activatetime * RX_MIN_ACTIVATETIME_UNIT_US)
4909 / PA_TACTIVATE_TIME_UNIT_US);
4910 ret = ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE),
4911 tuned_pa_tactivate);
4912
4913out:
4914 return ret;
4915}
4916
4917/**
4918 * ufshcd_tune_pa_hibern8time - Tunes PA_Hibern8Time of local UniPro
4919 * @hba: per-adapter instance
4920 *
4921 * PA_Hibern8Time parameter can be tuned manually if UniPro version is less than
4922 * 1.61. PA_Hibern8Time needs to be maximum of local M-PHY's
4923 * TX_HIBERN8TIME_CAPABILITY & peer M-PHY's RX_HIBERN8TIME_CAPABILITY.
4924 * This optimal value can help reduce the hibern8 exit latency.
4925 *
4926 * Returns zero on success, non-zero error value on failure.
4927 */
4928static int ufshcd_tune_pa_hibern8time(struct ufs_hba *hba)
4929{
4930 int ret = 0;
4931 u32 local_tx_hibern8_time_cap = 0, peer_rx_hibern8_time_cap = 0;
4932 u32 max_hibern8_time, tuned_pa_hibern8time;
4933
4934 ret = ufshcd_dme_get(hba,
4935 UIC_ARG_MIB_SEL(TX_HIBERN8TIME_CAPABILITY,
4936 UIC_ARG_MPHY_TX_GEN_SEL_INDEX(0)),
4937 &local_tx_hibern8_time_cap);
4938 if (ret)
4939 goto out;
4940
4941 ret = ufshcd_dme_peer_get(hba,
4942 UIC_ARG_MIB_SEL(RX_HIBERN8TIME_CAPABILITY,
4943 UIC_ARG_MPHY_RX_GEN_SEL_INDEX(0)),
4944 &peer_rx_hibern8_time_cap);
4945 if (ret)
4946 goto out;
4947
4948 max_hibern8_time = max(local_tx_hibern8_time_cap,
4949 peer_rx_hibern8_time_cap);
4950 /* make sure proper unit conversion is applied */
4951 tuned_pa_hibern8time = ((max_hibern8_time * HIBERN8TIME_UNIT_US)
4952 / PA_HIBERN8_TIME_UNIT_US);
4953 ret = ufshcd_dme_set(hba, UIC_ARG_MIB(PA_HIBERN8TIME),
4954 tuned_pa_hibern8time);
4955out:
4956 return ret;
4957}
4958
4959static void ufshcd_tune_unipro_params(struct ufs_hba *hba)
4960{
4961 if (ufshcd_is_unipro_pa_params_tuning_req(hba)) {
4962 ufshcd_tune_pa_tactivate(hba);
4963 ufshcd_tune_pa_hibern8time(hba);
4964 }
4965
4966 if (hba->dev_quirks & UFS_DEVICE_QUIRK_PA_TACTIVATE)
4967 /* set 1ms timeout for PA_TACTIVATE */
4968 ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE), 10);
4969}
4970
4971/**
4855 * ufshcd_probe_hba - probe hba to detect device and initialize 4972 * ufshcd_probe_hba - probe hba to detect device and initialize
4856 * @hba: per-adapter instance 4973 * @hba: per-adapter instance
4857 * 4974 *
@@ -4883,6 +5000,7 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
4883 goto out; 5000 goto out;
4884 5001
4885 ufs_advertise_fixup_device(hba); 5002 ufs_advertise_fixup_device(hba);
5003 ufshcd_tune_unipro_params(hba);
4886 5004
4887 ret = ufshcd_set_vccq_rail_unused(hba, 5005 ret = ufshcd_set_vccq_rail_unused(hba,
4888 (hba->dev_quirks & UFS_DEVICE_NO_VCCQ) ? true : false); 5006 (hba->dev_quirks & UFS_DEVICE_NO_VCCQ) ? true : false);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 65f29aa881d6..41d9bfd17fac 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -699,6 +699,7 @@ int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
699 enum flag_idn idn, bool *flag_res); 699 enum flag_idn idn, bool *flag_res);
700int ufshcd_hold(struct ufs_hba *hba, bool async); 700int ufshcd_hold(struct ufs_hba *hba, bool async);
701void ufshcd_release(struct ufs_hba *hba); 701void ufshcd_release(struct ufs_hba *hba);
702u32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba);
702 703
703/* Wrapper functions for safely calling variant operations */ 704/* Wrapper functions for safely calling variant operations */
704static inline const char *ufshcd_get_var_name(struct ufs_hba *hba) 705static inline const char *ufshcd_get_var_name(struct ufs_hba *hba)
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
index 2b05bfb6b3d7..4cb1cc63f1a1 100644
--- a/drivers/scsi/ufs/ufshci.h
+++ b/drivers/scsi/ufs/ufshci.h
@@ -92,6 +92,7 @@ enum {
92 UFSHCI_VERSION_10 = 0x00010000, /* 1.0 */ 92 UFSHCI_VERSION_10 = 0x00010000, /* 1.0 */
93 UFSHCI_VERSION_11 = 0x00010100, /* 1.1 */ 93 UFSHCI_VERSION_11 = 0x00010100, /* 1.1 */
94 UFSHCI_VERSION_20 = 0x00000200, /* 2.0 */ 94 UFSHCI_VERSION_20 = 0x00000200, /* 2.0 */
95 UFSHCI_VERSION_21 = 0x00000210, /* 2.1 */
95}; 96};
96 97
97/* 98/*
@@ -211,6 +212,7 @@ enum {
211 212
212/* GenSelectorIndex calculation macros for M-PHY attributes */ 213/* GenSelectorIndex calculation macros for M-PHY attributes */
213#define UIC_ARG_MPHY_TX_GEN_SEL_INDEX(lane) (lane) 214#define UIC_ARG_MPHY_TX_GEN_SEL_INDEX(lane) (lane)
215#define UIC_ARG_MPHY_RX_GEN_SEL_INDEX(lane) (PA_MAXDATALANES + (lane))
214 216
215#define UIC_ARG_MIB_SEL(attr, sel) ((((attr) & 0xFFFF) << 16) |\ 217#define UIC_ARG_MIB_SEL(attr, sel) ((((attr) & 0xFFFF) << 16) |\
216 ((sel) & 0xFFFF)) 218 ((sel) & 0xFFFF))
diff --git a/drivers/scsi/ufs/unipro.h b/drivers/scsi/ufs/unipro.h
index 816a8a46efb8..80820209e045 100644
--- a/drivers/scsi/ufs/unipro.h
+++ b/drivers/scsi/ufs/unipro.h
@@ -15,6 +15,7 @@
15/* 15/*
16 * M-TX Configuration Attributes 16 * M-TX Configuration Attributes
17 */ 17 */
18#define TX_HIBERN8TIME_CAPABILITY 0x000F
18#define TX_MODE 0x0021 19#define TX_MODE 0x0021
19#define TX_HSRATE_SERIES 0x0022 20#define TX_HSRATE_SERIES 0x0022
20#define TX_HSGEAR 0x0023 21#define TX_HSGEAR 0x0023
@@ -48,8 +49,12 @@
48#define RX_ENTER_HIBERN8 0x00A7 49#define RX_ENTER_HIBERN8 0x00A7
49#define RX_BYPASS_8B10B_ENABLE 0x00A8 50#define RX_BYPASS_8B10B_ENABLE 0x00A8
50#define RX_TERMINATION_FORCE_ENABLE 0x0089 51#define RX_TERMINATION_FORCE_ENABLE 0x0089
52#define RX_MIN_ACTIVATETIME_CAPABILITY 0x008F
53#define RX_HIBERN8TIME_CAPABILITY 0x0092
51 54
52#define is_mphy_tx_attr(attr) (attr < RX_MODE) 55#define is_mphy_tx_attr(attr) (attr < RX_MODE)
56#define RX_MIN_ACTIVATETIME_UNIT_US 100
57#define HIBERN8TIME_UNIT_US 100
53/* 58/*
54 * PHY Adpater attributes 59 * PHY Adpater attributes
55 */ 60 */
@@ -110,6 +115,12 @@
110#define PA_STALLNOCONFIGTIME 0x15A3 115#define PA_STALLNOCONFIGTIME 0x15A3
111#define PA_SAVECONFIGTIME 0x15A4 116#define PA_SAVECONFIGTIME 0x15A4
112 117
118#define PA_TACTIVATE_TIME_UNIT_US 10
119#define PA_HIBERN8_TIME_UNIT_US 100
120
121/* PHY Adapter Protocol Constants */
122#define PA_MAXDATALANES 4
123
113/* PA power modes */ 124/* PA power modes */
114enum { 125enum {
115 FAST_MODE = 1, 126 FAST_MODE = 1,
@@ -143,6 +154,16 @@ enum ufs_hs_gear_tag {
143 UFS_HS_G3, /* HS Gear 3 */ 154 UFS_HS_G3, /* HS Gear 3 */
144}; 155};
145 156
157enum ufs_unipro_ver {
158 UFS_UNIPRO_VER_RESERVED = 0,
159 UFS_UNIPRO_VER_1_40 = 1, /* UniPro version 1.40 */
160 UFS_UNIPRO_VER_1_41 = 2, /* UniPro version 1.41 */
161 UFS_UNIPRO_VER_1_6 = 3, /* UniPro version 1.6 */
162 UFS_UNIPRO_VER_MAX = 4, /* UniPro unsupported version */
163 /* UniPro version field mask in PA_LOCALVERINFO */
164 UFS_UNIPRO_VER_MASK = 0xF,
165};
166
146/* 167/*
147 * Data Link Layer Attributes 168 * Data Link Layer Attributes
148 */ 169 */