aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2014-09-23 16:02:41 -0400
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2014-10-23 14:21:47 -0400
commit9180ac50716a097a407c6d7e7e4589754a922260 (patch)
tree175305c65dceb1e32571d9aaf33d60303b985682
parent35a9ad8af0bb0fa3525e6d0d20e32551d226f38e (diff)
iwlwifi: configure the LTR
The LTR is the handshake between the device and the root complex about the latency allowed when the bus exits power save. This configuration was missing and this led to high latency in the link power up. The end user could experience high latency in the network because of this. Cc: <stable@vger.kernel.org> [3.10+] Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-power.h35
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api.h1
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw.c9
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/ops.c1
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c16
6 files changed, 56 insertions, 8 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 9eb85249e89c..d8fc548c0d6c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -563,6 +563,7 @@ enum iwl_trans_state {
563 * Set during transport allocation. 563 * Set during transport allocation.
564 * @hw_id_str: a string with info about HW ID. Set during transport allocation. 564 * @hw_id_str: a string with info about HW ID. Set during transport allocation.
565 * @pm_support: set to true in start_hw if link pm is supported 565 * @pm_support: set to true in start_hw if link pm is supported
566 * @ltr_enabled: set to true if the LTR is enabled
566 * @dev_cmd_pool: pool for Tx cmd allocation - for internal use only. 567 * @dev_cmd_pool: pool for Tx cmd allocation - for internal use only.
567 * The user should use iwl_trans_{alloc,free}_tx_cmd. 568 * The user should use iwl_trans_{alloc,free}_tx_cmd.
568 * @dev_cmd_headroom: room needed for the transport's private use before the 569 * @dev_cmd_headroom: room needed for the transport's private use before the
@@ -589,6 +590,7 @@ struct iwl_trans {
589 u8 rx_mpdu_cmd, rx_mpdu_cmd_hdr_size; 590 u8 rx_mpdu_cmd, rx_mpdu_cmd_hdr_size;
590 591
591 bool pm_support; 592 bool pm_support;
593 bool ltr_enabled;
592 594
593 /* The following fields are internal only */ 595 /* The following fields are internal only */
594 struct kmem_cache *dev_cmd_pool; 596 struct kmem_cache *dev_cmd_pool;
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
index 27dd86395b39..2fd8ad4633e0 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
@@ -68,13 +68,46 @@
68 68
69/* Power Management Commands, Responses, Notifications */ 69/* Power Management Commands, Responses, Notifications */
70 70
71/**
72 * enum iwl_ltr_config_flags - masks for LTR config command flags
73 * @LTR_CFG_FLAG_FEATURE_ENABLE: Feature operational status
74 * @LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS: allow LTR change on shadow
75 * memory access
76 * @LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH: allow LTR msg send on ANY LTR
77 * reg change
78 * @LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3: allow LTR msg send on transition from
79 * D0 to D3
80 * @LTR_CFG_FLAG_SW_SET_SHORT: fixed static short LTR register
81 * @LTR_CFG_FLAG_SW_SET_LONG: fixed static short LONG register
82 * @LTR_CFG_FLAG_DENIE_C10_ON_PD: allow going into C10 on PD
83 */
84enum iwl_ltr_config_flags {
85 LTR_CFG_FLAG_FEATURE_ENABLE = BIT(0),
86 LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS = BIT(1),
87 LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH = BIT(2),
88 LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3 = BIT(3),
89 LTR_CFG_FLAG_SW_SET_SHORT = BIT(4),
90 LTR_CFG_FLAG_SW_SET_LONG = BIT(5),
91 LTR_CFG_FLAG_DENIE_C10_ON_PD = BIT(6),
92};
93
94/**
95 * struct iwl_ltr_config_cmd - configures the LTR
96 * @flags: See %enum iwl_ltr_config_flags
97 */
98struct iwl_ltr_config_cmd {
99 __le32 flags;
100 __le32 static_long;
101 __le32 static_short;
102} __packed;
103
71/* Radio LP RX Energy Threshold measured in dBm */ 104/* Radio LP RX Energy Threshold measured in dBm */
72#define POWER_LPRX_RSSI_THRESHOLD 75 105#define POWER_LPRX_RSSI_THRESHOLD 75
73#define POWER_LPRX_RSSI_THRESHOLD_MAX 94 106#define POWER_LPRX_RSSI_THRESHOLD_MAX 94
74#define POWER_LPRX_RSSI_THRESHOLD_MIN 30 107#define POWER_LPRX_RSSI_THRESHOLD_MIN 30
75 108
76/** 109/**
77 * enum iwl_scan_flags - masks for power table command flags 110 * enum iwl_power_flags - masks for power table command flags
78 * @POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off 111 * @POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off
79 * receiver and transmitter. '0' - does not allow. 112 * receiver and transmitter. '0' - does not allow.
80 * @POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK: '0' Driver disables power management, 113 * @POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK: '0' Driver disables power management,
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index 667a92274c87..c62575d86bcd 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -157,6 +157,7 @@ enum {
157 /* Power - legacy power table command */ 157 /* Power - legacy power table command */
158 POWER_TABLE_CMD = 0x77, 158 POWER_TABLE_CMD = 0x77,
159 PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION = 0x78, 159 PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION = 0x78,
160 LTR_CONFIG = 0xee,
160 161
161 /* Thermal Throttling*/ 162 /* Thermal Throttling*/
162 REPLY_THERMAL_MNG_BACKOFF = 0x7e, 163 REPLY_THERMAL_MNG_BACKOFF = 0x7e,
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
index 23fd711a67e4..e0d9f19650b0 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -480,6 +480,15 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
480 /* Initialize tx backoffs to the minimal possible */ 480 /* Initialize tx backoffs to the minimal possible */
481 iwl_mvm_tt_tx_backoff(mvm, 0); 481 iwl_mvm_tt_tx_backoff(mvm, 0);
482 482
483 if (mvm->trans->ltr_enabled) {
484 struct iwl_ltr_config_cmd cmd = {
485 .flags = cpu_to_le32(LTR_CFG_FLAG_FEATURE_ENABLE),
486 };
487
488 WARN_ON(iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0,
489 sizeof(cmd), &cmd));
490 }
491
483 ret = iwl_mvm_power_update_device(mvm); 492 ret = iwl_mvm_power_update_device(mvm);
484 if (ret) 493 if (ret)
485 goto error; 494 goto error;
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index 15aa298ee79c..48cb25a93591 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -336,6 +336,7 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
336 CMD(DTS_MEASUREMENT_NOTIFICATION), 336 CMD(DTS_MEASUREMENT_NOTIFICATION),
337 CMD(REPLY_THERMAL_MNG_BACKOFF), 337 CMD(REPLY_THERMAL_MNG_BACKOFF),
338 CMD(MAC_PM_POWER_TABLE), 338 CMD(MAC_PM_POWER_TABLE),
339 CMD(LTR_CONFIG),
339 CMD(BT_COEX_CI), 340 CMD(BT_COEX_CI),
340 CMD(BT_COEX_UPDATE_SW_BOOST), 341 CMD(BT_COEX_UPDATE_SW_BOOST),
341 CMD(BT_COEX_UPDATE_CORUN_LUT), 342 CMD(BT_COEX_UPDATE_CORUN_LUT),
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index 1393bac0025c..c706dba67cdd 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -174,6 +174,7 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans)
174{ 174{
175 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 175 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
176 u16 lctl; 176 u16 lctl;
177 u16 cap;
177 178
178 /* 179 /*
179 * HW bug W/A for instability in PCIe bus L0S->L1 transition. 180 * HW bug W/A for instability in PCIe bus L0S->L1 transition.
@@ -184,16 +185,17 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans)
184 * power savings, even without L1. 185 * power savings, even without L1.
185 */ 186 */
186 pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, &lctl); 187 pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, &lctl);
187 if (lctl & PCI_EXP_LNKCTL_ASPM_L1) { 188 if (lctl & PCI_EXP_LNKCTL_ASPM_L1)
188 /* L1-ASPM enabled; disable(!) L0S */
189 iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); 189 iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
190 dev_info(trans->dev, "L1 Enabled; Disabling L0S\n"); 190 else
191 } else {
192 /* L1-ASPM disabled; enable(!) L0S */
193 iwl_clear_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); 191 iwl_clear_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
194 dev_info(trans->dev, "L1 Disabled; Enabling L0S\n");
195 }
196 trans->pm_support = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S); 192 trans->pm_support = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S);
193
194 pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_DEVCTL2, &cap);
195 trans->ltr_enabled = cap & PCI_EXP_DEVCTL2_LTR_EN;
196 dev_info(trans->dev, "L1 %sabled - LTR %sabled\n",
197 (lctl & PCI_EXP_LNKCTL_ASPM_L1) ? "En" : "Dis",
198 trans->ltr_enabled ? "En" : "Dis");
197} 199}
198 200
199/* 201/*