aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2013-08-02 15:37:34 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-08-02 15:37:34 -0400
commit204162296edf0d0ac3e4dfd5bd0cac4af731b583 (patch)
treefdf941fd23fae6097500db4998d4ca96467fc352
parente3d5291436ff9efeeb968459724af5332305dded (diff)
parent147fc9be81d10e6e863323c0b54e140b42fd1ed6 (diff)
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
-rw-r--r--MAINTAINERS2
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig17
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/agn.h6
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/debugfs.c15
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/dev.h7
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/mac80211.c172
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/main.c62
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/rs.c3
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/rxon.c6
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/scan.c105
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/tx.c19
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-7000.c11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-config.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw.h19
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-io.c67
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-io.h3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-nvm-parse.c8
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/Makefile2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/bt-coex.c162
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/constants.h71
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/d3.c66
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs.c116
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h49
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-power.h143
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h5
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api.h27
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw.c55
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c3
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c40
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h83
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/ops.c56
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/power.c198
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/power_legacy.c319
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/quota.c16
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rs.c10
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rs.h4
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rx.c78
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/scan.c2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/sta.c3
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tt.c32
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tx.c2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/utils.c23
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/drv.c6
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/internal.h1
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/rx.c2
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c95
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/tx.c5
48 files changed, 1309 insertions, 893 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 7a403ba167d2..2a3faf5b8301 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4362,7 +4362,7 @@ F: drivers/net/wireless/iwlegacy/
4362 4362
4363INTEL WIRELESS WIFI LINK (iwlwifi) 4363INTEL WIRELESS WIFI LINK (iwlwifi)
4364M: Johannes Berg <johannes.berg@intel.com> 4364M: Johannes Berg <johannes.berg@intel.com>
4365M: Wey-Yi Guy <wey-yi.w.guy@intel.com> 4365M: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
4366M: Intel Linux Wireless <ilw@linux.intel.com> 4366M: Intel Linux Wireless <ilw@linux.intel.com>
4367L: linux-wireless@vger.kernel.org 4367L: linux-wireless@vger.kernel.org
4368W: http://intellinuxwireless.org 4368W: http://intellinuxwireless.org
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index cbaa5c2c410f..e5c133ee7901 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -127,20 +127,3 @@ config IWLWIFI_DEVICE_TRACING
127 If unsure, say Y so we can help you better when problems 127 If unsure, say Y so we can help you better when problems
128 occur. 128 occur.
129endmenu 129endmenu
130
131config IWLWIFI_P2P
132 def_bool y
133 bool "iwlwifi experimental P2P support"
134 depends on IWLWIFI
135 help
136 This option enables experimental P2P support for some devices
137 based on microcode support. Since P2P support is still under
138 development, this option may even enable it for some devices
139 now that turn out to not support it in the future due to
140 microcode restrictions.
141
142 To determine if your microcode supports the experimental P2P
143 offered by this option, check if the driver advertises AP
144 support when it is loaded.
145
146 Say Y only if you want to experiment with P2P.
diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h
index 18355110deff..f2a86ffc3b4c 100644
--- a/drivers/net/wireless/iwlwifi/dvm/agn.h
+++ b/drivers/net/wireless/iwlwifi/dvm/agn.h
@@ -106,7 +106,6 @@ extern const struct iwl_dvm_cfg iwl_dvm_6030_cfg;
106#define STATUS_CHANNEL_SWITCH_PENDING 11 106#define STATUS_CHANNEL_SWITCH_PENDING 11
107#define STATUS_SCAN_COMPLETE 12 107#define STATUS_SCAN_COMPLETE 12
108#define STATUS_POWER_PMI 13 108#define STATUS_POWER_PMI 13
109#define STATUS_SCAN_ROC_EXPIRED 14
110 109
111struct iwl_ucode_capabilities; 110struct iwl_ucode_capabilities;
112 111
@@ -250,7 +249,6 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid);
250 249
251/* scan */ 250/* scan */
252void iwlagn_post_scan(struct iwl_priv *priv); 251void iwlagn_post_scan(struct iwl_priv *priv);
253void iwlagn_disable_roc(struct iwl_priv *priv);
254int iwl_force_rf_reset(struct iwl_priv *priv, bool external); 252int iwl_force_rf_reset(struct iwl_priv *priv, bool external);
255void iwl_init_scan_params(struct iwl_priv *priv); 253void iwl_init_scan_params(struct iwl_priv *priv);
256int iwl_scan_cancel(struct iwl_priv *priv); 254int iwl_scan_cancel(struct iwl_priv *priv);
@@ -265,10 +263,6 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
265 enum iwl_scan_type scan_type, 263 enum iwl_scan_type scan_type,
266 enum ieee80211_band band); 264 enum ieee80211_band band);
267 265
268void iwl_scan_roc_expired(struct iwl_priv *priv);
269void iwl_scan_offchannel_skb(struct iwl_priv *priv);
270void iwl_scan_offchannel_skb_status(struct iwl_priv *priv);
271
272/* For faster active scanning, scan will move to the next channel if fewer than 266/* For faster active scanning, scan will move to the next channel if fewer than
273 * PLCP_QUIET_THRESH packets are heard on this channel within 267 * PLCP_QUIET_THRESH packets are heard on this channel within
274 * ACTIVE_QUIET_TIME after sending probe request. This shortens the dwell 268 * ACTIVE_QUIET_TIME after sending probe request. This shortens the dwell
diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c
index d5329489245a..d94f8ab15004 100644
--- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c
@@ -69,19 +69,7 @@
69} while (0) 69} while (0)
70 70
71/* file operation */ 71/* file operation */
72#define DEBUGFS_READ_FUNC(name) \
73static ssize_t iwl_dbgfs_##name##_read(struct file *file, \
74 char __user *user_buf, \
75 size_t count, loff_t *ppos);
76
77#define DEBUGFS_WRITE_FUNC(name) \
78static ssize_t iwl_dbgfs_##name##_write(struct file *file, \
79 const char __user *user_buf, \
80 size_t count, loff_t *ppos);
81
82
83#define DEBUGFS_READ_FILE_OPS(name) \ 72#define DEBUGFS_READ_FILE_OPS(name) \
84 DEBUGFS_READ_FUNC(name); \
85static const struct file_operations iwl_dbgfs_##name##_ops = { \ 73static const struct file_operations iwl_dbgfs_##name##_ops = { \
86 .read = iwl_dbgfs_##name##_read, \ 74 .read = iwl_dbgfs_##name##_read, \
87 .open = simple_open, \ 75 .open = simple_open, \
@@ -89,7 +77,6 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \
89}; 77};
90 78
91#define DEBUGFS_WRITE_FILE_OPS(name) \ 79#define DEBUGFS_WRITE_FILE_OPS(name) \
92 DEBUGFS_WRITE_FUNC(name); \
93static const struct file_operations iwl_dbgfs_##name##_ops = { \ 80static const struct file_operations iwl_dbgfs_##name##_ops = { \
94 .write = iwl_dbgfs_##name##_write, \ 81 .write = iwl_dbgfs_##name##_write, \
95 .open = simple_open, \ 82 .open = simple_open, \
@@ -98,8 +85,6 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \
98 85
99 86
100#define DEBUGFS_READ_WRITE_FILE_OPS(name) \ 87#define DEBUGFS_READ_WRITE_FILE_OPS(name) \
101 DEBUGFS_READ_FUNC(name); \
102 DEBUGFS_WRITE_FUNC(name); \
103static const struct file_operations iwl_dbgfs_##name##_ops = { \ 88static const struct file_operations iwl_dbgfs_##name##_ops = { \
104 .write = iwl_dbgfs_##name##_write, \ 89 .write = iwl_dbgfs_##name##_write, \
105 .read = iwl_dbgfs_##name##_read, \ 90 .read = iwl_dbgfs_##name##_read, \
diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h
index 60a4e0d15715..a79fdd137f95 100644
--- a/drivers/net/wireless/iwlwifi/dvm/dev.h
+++ b/drivers/net/wireless/iwlwifi/dvm/dev.h
@@ -540,7 +540,6 @@ struct iwl_rxon_context {
540enum iwl_scan_type { 540enum iwl_scan_type {
541 IWL_SCAN_NORMAL, 541 IWL_SCAN_NORMAL,
542 IWL_SCAN_RADIO_RESET, 542 IWL_SCAN_RADIO_RESET,
543 IWL_SCAN_ROC,
544}; 543};
545 544
546/** 545/**
@@ -825,12 +824,6 @@ struct iwl_priv {
825 struct reply_tx_error_statistics reply_tx_stats; 824 struct reply_tx_error_statistics reply_tx_stats;
826 struct reply_agg_tx_error_statistics reply_agg_tx_stats; 825 struct reply_agg_tx_error_statistics reply_agg_tx_stats;
827 826
828 /* remain-on-channel offload support */
829 struct ieee80211_channel *hw_roc_channel;
830 struct delayed_work hw_roc_disable_work;
831 int hw_roc_duration;
832 bool hw_roc_setup, hw_roc_start_notified;
833
834 /* bt coex */ 827 /* bt coex */
835 u8 bt_enable_flag; 828 u8 bt_enable_flag;
836 u8 bt_status; 829 u8 bt_status;
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index 822f1a00efbb..f0a2c957d503 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -76,29 +76,6 @@ static const struct ieee80211_iface_limit iwlagn_2sta_limits[] = {
76 }, 76 },
77}; 77};
78 78
79static const struct ieee80211_iface_limit iwlagn_p2p_sta_go_limits[] = {
80 {
81 .max = 1,
82 .types = BIT(NL80211_IFTYPE_STATION),
83 },
84 {
85 .max = 1,
86 .types = BIT(NL80211_IFTYPE_P2P_GO) |
87 BIT(NL80211_IFTYPE_AP),
88 },
89};
90
91static const struct ieee80211_iface_limit iwlagn_p2p_2sta_limits[] = {
92 {
93 .max = 2,
94 .types = BIT(NL80211_IFTYPE_STATION),
95 },
96 {
97 .max = 1,
98 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
99 },
100};
101
102static const struct ieee80211_iface_combination 79static const struct ieee80211_iface_combination
103iwlagn_iface_combinations_dualmode[] = { 80iwlagn_iface_combinations_dualmode[] = {
104 { .num_different_channels = 1, 81 { .num_different_channels = 1,
@@ -114,21 +91,6 @@ iwlagn_iface_combinations_dualmode[] = {
114 }, 91 },
115}; 92};
116 93
117static const struct ieee80211_iface_combination
118iwlagn_iface_combinations_p2p[] = {
119 { .num_different_channels = 1,
120 .max_interfaces = 2,
121 .beacon_int_infra_match = true,
122 .limits = iwlagn_p2p_sta_go_limits,
123 .n_limits = ARRAY_SIZE(iwlagn_p2p_sta_go_limits),
124 },
125 { .num_different_channels = 1,
126 .max_interfaces = 2,
127 .limits = iwlagn_p2p_2sta_limits,
128 .n_limits = ARRAY_SIZE(iwlagn_p2p_2sta_limits),
129 },
130};
131
132/* 94/*
133 * Not a mac80211 entry point function, but it fits in with all the 95 * Not a mac80211 entry point function, but it fits in with all the
134 * other mac80211 functions grouped here. 96 * other mac80211 functions grouped here.
@@ -186,19 +148,13 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
186 148
187 BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); 149 BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
188 150
189 if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) { 151 if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) {
190 hw->wiphy->iface_combinations = iwlagn_iface_combinations_p2p;
191 hw->wiphy->n_iface_combinations =
192 ARRAY_SIZE(iwlagn_iface_combinations_p2p);
193 } else if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) {
194 hw->wiphy->iface_combinations = 152 hw->wiphy->iface_combinations =
195 iwlagn_iface_combinations_dualmode; 153 iwlagn_iface_combinations_dualmode;
196 hw->wiphy->n_iface_combinations = 154 hw->wiphy->n_iface_combinations =
197 ARRAY_SIZE(iwlagn_iface_combinations_dualmode); 155 ARRAY_SIZE(iwlagn_iface_combinations_dualmode);
198 } 156 }
199 157
200 hw->wiphy->max_remain_on_channel_duration = 500;
201
202 hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | 158 hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
203 WIPHY_FLAG_DISABLE_BEACON_HINTS | 159 WIPHY_FLAG_DISABLE_BEACON_HINTS |
204 WIPHY_FLAG_IBSS_RSN; 160 WIPHY_FLAG_IBSS_RSN;
@@ -1156,126 +1112,6 @@ done:
1156 IWL_DEBUG_MAC80211(priv, "leave\n"); 1112 IWL_DEBUG_MAC80211(priv, "leave\n");
1157} 1113}
1158 1114
1159static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
1160 struct ieee80211_vif *vif,
1161 struct ieee80211_channel *channel,
1162 int duration,
1163 enum ieee80211_roc_type type)
1164{
1165 struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
1166 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
1167 int err = 0;
1168
1169 if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
1170 return -EOPNOTSUPP;
1171
1172 if (!(ctx->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)))
1173 return -EOPNOTSUPP;
1174
1175 IWL_DEBUG_MAC80211(priv, "enter\n");
1176 mutex_lock(&priv->mutex);
1177
1178 if (test_bit(STATUS_SCAN_HW, &priv->status)) {
1179 /* mac80211 should not scan while ROC or ROC while scanning */
1180 if (WARN_ON_ONCE(priv->scan_type != IWL_SCAN_RADIO_RESET)) {
1181 err = -EBUSY;
1182 goto out;
1183 }
1184
1185 iwl_scan_cancel_timeout(priv, 100);
1186
1187 if (test_bit(STATUS_SCAN_HW, &priv->status)) {
1188 err = -EBUSY;
1189 goto out;
1190 }
1191 }
1192
1193 priv->hw_roc_channel = channel;
1194 /* convert from ms to TU */
1195 priv->hw_roc_duration = DIV_ROUND_UP(1000 * duration, 1024);
1196 priv->hw_roc_start_notified = false;
1197 cancel_delayed_work(&priv->hw_roc_disable_work);
1198
1199 if (!ctx->is_active) {
1200 static const struct iwl_qos_info default_qos_data = {
1201 .def_qos_parm = {
1202 .ac[0] = {
1203 .cw_min = cpu_to_le16(3),
1204 .cw_max = cpu_to_le16(7),
1205 .aifsn = 2,
1206 .edca_txop = cpu_to_le16(1504),
1207 },
1208 .ac[1] = {
1209 .cw_min = cpu_to_le16(7),
1210 .cw_max = cpu_to_le16(15),
1211 .aifsn = 2,
1212 .edca_txop = cpu_to_le16(3008),
1213 },
1214 .ac[2] = {
1215 .cw_min = cpu_to_le16(15),
1216 .cw_max = cpu_to_le16(1023),
1217 .aifsn = 3,
1218 },
1219 .ac[3] = {
1220 .cw_min = cpu_to_le16(15),
1221 .cw_max = cpu_to_le16(1023),
1222 .aifsn = 7,
1223 },
1224 },
1225 };
1226
1227 ctx->is_active = true;
1228 ctx->qos_data = default_qos_data;
1229 ctx->staging.dev_type = RXON_DEV_TYPE_P2P;
1230 memcpy(ctx->staging.node_addr,
1231 priv->contexts[IWL_RXON_CTX_BSS].staging.node_addr,
1232 ETH_ALEN);
1233 memcpy(ctx->staging.bssid_addr,
1234 priv->contexts[IWL_RXON_CTX_BSS].staging.node_addr,
1235 ETH_ALEN);
1236 err = iwlagn_commit_rxon(priv, ctx);
1237 if (err)
1238 goto out;
1239 ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK |
1240 RXON_FILTER_PROMISC_MSK |
1241 RXON_FILTER_CTL2HOST_MSK;
1242
1243 err = iwlagn_commit_rxon(priv, ctx);
1244 if (err) {
1245 iwlagn_disable_roc(priv);
1246 goto out;
1247 }
1248 priv->hw_roc_setup = true;
1249 }
1250
1251 err = iwl_scan_initiate(priv, ctx->vif, IWL_SCAN_ROC, channel->band);
1252 if (err)
1253 iwlagn_disable_roc(priv);
1254
1255 out:
1256 mutex_unlock(&priv->mutex);
1257 IWL_DEBUG_MAC80211(priv, "leave\n");
1258
1259 return err;
1260}
1261
1262static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
1263{
1264 struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
1265
1266 if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
1267 return -EOPNOTSUPP;
1268
1269 IWL_DEBUG_MAC80211(priv, "enter\n");
1270 mutex_lock(&priv->mutex);
1271 iwl_scan_cancel_timeout(priv, priv->hw_roc_duration);
1272 iwlagn_disable_roc(priv);
1273 mutex_unlock(&priv->mutex);
1274 IWL_DEBUG_MAC80211(priv, "leave\n");
1275
1276 return 0;
1277}
1278
1279static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, 1115static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
1280 struct ieee80211_vif *vif, 1116 struct ieee80211_vif *vif,
1281 enum ieee80211_rssi_event rssi_event) 1117 enum ieee80211_rssi_event rssi_event)
@@ -1431,12 +1267,8 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
1431 IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", 1267 IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
1432 viftype, vif->addr); 1268 viftype, vif->addr);
1433 1269
1434 cancel_delayed_work_sync(&priv->hw_roc_disable_work);
1435
1436 mutex_lock(&priv->mutex); 1270 mutex_lock(&priv->mutex);
1437 1271
1438 iwlagn_disable_roc(priv);
1439
1440 if (!iwl_is_ready_rf(priv)) { 1272 if (!iwl_is_ready_rf(priv)) {
1441 IWL_WARN(priv, "Try to add interface when device not ready\n"); 1273 IWL_WARN(priv, "Try to add interface when device not ready\n");
1442 err = -EINVAL; 1274 err = -EINVAL;
@@ -1763,8 +1595,6 @@ struct ieee80211_ops iwlagn_hw_ops = {
1763 .channel_switch = iwlagn_mac_channel_switch, 1595 .channel_switch = iwlagn_mac_channel_switch,
1764 .flush = iwlagn_mac_flush, 1596 .flush = iwlagn_mac_flush,
1765 .tx_last_beacon = iwlagn_mac_tx_last_beacon, 1597 .tx_last_beacon = iwlagn_mac_tx_last_beacon,
1766 .remain_on_channel = iwlagn_mac_remain_on_channel,
1767 .cancel_remain_on_channel = iwlagn_mac_cancel_remain_on_channel,
1768 .rssi_callback = iwlagn_mac_rssi_callback, 1598 .rssi_callback = iwlagn_mac_rssi_callback,
1769 .set_tim = iwlagn_mac_set_tim, 1599 .set_tim = iwlagn_mac_set_tim,
1770}; 1600};
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c
index 1531a4fc0960..7aad766865cf 100644
--- a/drivers/net/wireless/iwlwifi/dvm/main.c
+++ b/drivers/net/wireless/iwlwifi/dvm/main.c
@@ -587,11 +587,6 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
587 priv->contexts[IWL_RXON_CTX_PAN].interface_modes = 587 priv->contexts[IWL_RXON_CTX_PAN].interface_modes =
588 BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP); 588 BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP);
589 589
590 if (ucode_flags & IWL_UCODE_TLV_FLAGS_P2P)
591 priv->contexts[IWL_RXON_CTX_PAN].interface_modes |=
592 BIT(NL80211_IFTYPE_P2P_CLIENT) |
593 BIT(NL80211_IFTYPE_P2P_GO);
594
595 priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP; 590 priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP;
596 priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA; 591 priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA;
597 priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P; 592 priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P;
@@ -854,14 +849,6 @@ void iwl_down(struct iwl_priv *priv)
854 849
855 iwl_scan_cancel_timeout(priv, 200); 850 iwl_scan_cancel_timeout(priv, 200);
856 851
857 /*
858 * If active, scanning won't cancel it, so say it expired.
859 * No race since we hold the mutex here and a new one
860 * can't come in at this time.
861 */
862 if (priv->ucode_loaded && priv->cur_ucode != IWL_UCODE_INIT)
863 ieee80211_remain_on_channel_expired(priv->hw);
864
865 exit_pending = 852 exit_pending =
866 test_and_set_bit(STATUS_EXIT_PENDING, &priv->status); 853 test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
867 854
@@ -1002,41 +989,6 @@ static void iwl_bg_restart(struct work_struct *data)
1002 } 989 }
1003} 990}
1004 991
1005
1006
1007
1008void iwlagn_disable_roc(struct iwl_priv *priv)
1009{
1010 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
1011
1012 lockdep_assert_held(&priv->mutex);
1013
1014 if (!priv->hw_roc_setup)
1015 return;
1016
1017 ctx->staging.dev_type = RXON_DEV_TYPE_P2P;
1018 ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
1019
1020 priv->hw_roc_channel = NULL;
1021
1022 memset(ctx->staging.node_addr, 0, ETH_ALEN);
1023
1024 iwlagn_commit_rxon(priv, ctx);
1025
1026 ctx->is_active = false;
1027 priv->hw_roc_setup = false;
1028}
1029
1030static void iwlagn_disable_roc_work(struct work_struct *work)
1031{
1032 struct iwl_priv *priv = container_of(work, struct iwl_priv,
1033 hw_roc_disable_work.work);
1034
1035 mutex_lock(&priv->mutex);
1036 iwlagn_disable_roc(priv);
1037 mutex_unlock(&priv->mutex);
1038}
1039
1040/***************************************************************************** 992/*****************************************************************************
1041 * 993 *
1042 * driver setup and teardown 994 * driver setup and teardown
@@ -1053,8 +1005,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
1053 INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush); 1005 INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush);
1054 INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency); 1006 INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency);
1055 INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config); 1007 INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config);
1056 INIT_DELAYED_WORK(&priv->hw_roc_disable_work,
1057 iwlagn_disable_roc_work);
1058 1008
1059 iwl_setup_scan_deferred_work(priv); 1009 iwl_setup_scan_deferred_work(priv);
1060 1010
@@ -1082,7 +1032,6 @@ void iwl_cancel_deferred_work(struct iwl_priv *priv)
1082 1032
1083 cancel_work_sync(&priv->bt_full_concurrency); 1033 cancel_work_sync(&priv->bt_full_concurrency);
1084 cancel_work_sync(&priv->bt_runtime_config); 1034 cancel_work_sync(&priv->bt_runtime_config);
1085 cancel_delayed_work_sync(&priv->hw_roc_disable_work);
1086 1035
1087 del_timer_sync(&priv->statistics_periodic); 1036 del_timer_sync(&priv->statistics_periodic);
1088 del_timer_sync(&priv->ucode_trace); 1037 del_timer_sync(&priv->ucode_trace);
@@ -1169,12 +1118,6 @@ static void iwl_option_config(struct iwl_priv *priv)
1169#else 1118#else
1170 IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TRACING disabled\n"); 1119 IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TRACING disabled\n");
1171#endif 1120#endif
1172
1173#ifdef CONFIG_IWLWIFI_P2P
1174 IWL_INFO(priv, "CONFIG_IWLWIFI_P2P enabled\n");
1175#else
1176 IWL_INFO(priv, "CONFIG_IWLWIFI_P2P disabled\n");
1177#endif
1178} 1121}
1179 1122
1180static int iwl_eeprom_init_hw_params(struct iwl_priv *priv) 1123static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
@@ -1315,10 +1258,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
1315 1258
1316 ucode_flags = fw->ucode_capa.flags; 1259 ucode_flags = fw->ucode_capa.flags;
1317 1260
1318#ifndef CONFIG_IWLWIFI_P2P
1319 ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P;
1320#endif
1321
1322 if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) { 1261 if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) {
1323 priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; 1262 priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
1324 trans_cfg.cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; 1263 trans_cfg.cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
@@ -1413,7 +1352,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
1413 * if not PAN, then don't support P2P -- might be a uCode 1352 * if not PAN, then don't support P2P -- might be a uCode
1414 * packaging bug or due to the eeprom check above 1353 * packaging bug or due to the eeprom check above
1415 */ 1354 */
1416 ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P;
1417 priv->sta_key_max_num = STA_KEY_MAX_NUM; 1355 priv->sta_key_max_num = STA_KEY_MAX_NUM;
1418 trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; 1356 trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
1419 1357
diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.c b/drivers/net/wireless/iwlwifi/dvm/rs.c
index 91eb09b9b56f..b647e506564c 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rs.c
@@ -2826,9 +2826,6 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
2826 2826
2827 lq_sta->flush_timer = 0; 2827 lq_sta->flush_timer = 0;
2828 lq_sta->supp_rates = sta->supp_rates[sband->band]; 2828 lq_sta->supp_rates = sta->supp_rates[sband->band];
2829 for (j = 0; j < LQ_SIZE; j++)
2830 for (i = 0; i < IWL_RATE_COUNT; i++)
2831 rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]);
2832 2829
2833 IWL_DEBUG_RATE(priv, "LQ: *** rate scale station global init for station %d ***\n", 2830 IWL_DEBUG_RATE(priv, "LQ: *** rate scale station global init for station %d ***\n",
2834 sta_id); 2831 sta_id);
diff --git a/drivers/net/wireless/iwlwifi/dvm/rxon.c b/drivers/net/wireless/iwlwifi/dvm/rxon.c
index cd1ad0019185..d7ce2f12a907 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rxon.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rxon.c
@@ -564,11 +564,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
564 cmd.slots[0].type = 0; /* BSS */ 564 cmd.slots[0].type = 0; /* BSS */
565 cmd.slots[1].type = 1; /* PAN */ 565 cmd.slots[1].type = 1; /* PAN */
566 566
567 if (priv->hw_roc_setup) { 567 if (ctx_bss->vif && ctx_pan->vif) {
568 /* both contexts must be used for this to happen */
569 slot1 = IWL_MIN_SLOT_TIME;
570 slot0 = 3000;
571 } else if (ctx_bss->vif && ctx_pan->vif) {
572 int bcnint = ctx_pan->beacon_int; 568 int bcnint = ctx_pan->beacon_int;
573 int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1; 569 int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1;
574 570
diff --git a/drivers/net/wireless/iwlwifi/dvm/scan.c b/drivers/net/wireless/iwlwifi/dvm/scan.c
index 8c686a5b90ac..35e0ee8b4e5b 100644
--- a/drivers/net/wireless/iwlwifi/dvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/dvm/scan.c
@@ -100,9 +100,6 @@ static void iwl_complete_scan(struct iwl_priv *priv, bool aborted)
100 ieee80211_scan_completed(priv->hw, aborted); 100 ieee80211_scan_completed(priv->hw, aborted);
101 } 101 }
102 102
103 if (priv->scan_type == IWL_SCAN_ROC)
104 iwl_scan_roc_expired(priv);
105
106 priv->scan_type = IWL_SCAN_NORMAL; 103 priv->scan_type = IWL_SCAN_NORMAL;
107 priv->scan_vif = NULL; 104 priv->scan_vif = NULL;
108 priv->scan_request = NULL; 105 priv->scan_request = NULL;
@@ -130,9 +127,6 @@ static void iwl_process_scan_complete(struct iwl_priv *priv)
130 goto out_settings; 127 goto out_settings;
131 } 128 }
132 129
133 if (priv->scan_type == IWL_SCAN_ROC)
134 iwl_scan_roc_expired(priv);
135
136 if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) { 130 if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) {
137 int err; 131 int err;
138 132
@@ -284,12 +278,6 @@ static int iwl_rx_scan_start_notif(struct iwl_priv *priv,
284 le32_to_cpu(notif->tsf_low), 278 le32_to_cpu(notif->tsf_low),
285 notif->status, notif->beacon_timer); 279 notif->status, notif->beacon_timer);
286 280
287 if (priv->scan_type == IWL_SCAN_ROC &&
288 !priv->hw_roc_start_notified) {
289 ieee80211_ready_on_channel(priv->hw);
290 priv->hw_roc_start_notified = true;
291 }
292
293 return 0; 281 return 0;
294} 282}
295 283
@@ -697,8 +685,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
697 scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; 685 scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
698 scan->quiet_time = IWL_ACTIVE_QUIET_TIME; 686 scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
699 687
700 if (priv->scan_type != IWL_SCAN_ROC && 688 if (iwl_is_any_associated(priv)) {
701 iwl_is_any_associated(priv)) {
702 u16 interval = 0; 689 u16 interval = 0;
703 u32 extra; 690 u32 extra;
704 u32 suspend_time = 100; 691 u32 suspend_time = 100;
@@ -706,9 +693,6 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
706 693
707 IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); 694 IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
708 switch (priv->scan_type) { 695 switch (priv->scan_type) {
709 case IWL_SCAN_ROC:
710 WARN_ON(1);
711 break;
712 case IWL_SCAN_RADIO_RESET: 696 case IWL_SCAN_RADIO_RESET:
713 interval = 0; 697 interval = 0;
714 break; 698 break;
@@ -728,11 +712,6 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
728 scan->suspend_time = cpu_to_le32(scan_suspend_time); 712 scan->suspend_time = cpu_to_le32(scan_suspend_time);
729 IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n", 713 IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n",
730 scan_suspend_time, interval); 714 scan_suspend_time, interval);
731 } else if (priv->scan_type == IWL_SCAN_ROC) {
732 scan->suspend_time = 0;
733 scan->max_out_time = 0;
734 scan->quiet_time = 0;
735 scan->quiet_plcp_th = 0;
736 } 715 }
737 716
738 switch (priv->scan_type) { 717 switch (priv->scan_type) {
@@ -774,9 +753,6 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
774 } else 753 } else
775 IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); 754 IWL_DEBUG_SCAN(priv, "Start passive scan.\n");
776 break; 755 break;
777 case IWL_SCAN_ROC:
778 IWL_DEBUG_SCAN(priv, "Start ROC scan.\n");
779 break;
780 } 756 }
781 757
782 scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; 758 scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
@@ -898,7 +874,6 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
898 scan_cmd_size - sizeof(*scan)); 874 scan_cmd_size - sizeof(*scan));
899 break; 875 break;
900 case IWL_SCAN_RADIO_RESET: 876 case IWL_SCAN_RADIO_RESET:
901 case IWL_SCAN_ROC:
902 /* use bcast addr, will not be transmitted but must be valid */ 877 /* use bcast addr, will not be transmitted but must be valid */
903 cmd_len = iwl_fill_probe_req( 878 cmd_len = iwl_fill_probe_req(
904 (struct ieee80211_mgmt *)scan->data, 879 (struct ieee80211_mgmt *)scan->data,
@@ -926,46 +901,6 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
926 is_active, n_probes, 901 is_active, n_probes,
927 (void *)&scan->data[cmd_len]); 902 (void *)&scan->data[cmd_len]);
928 break; 903 break;
929 case IWL_SCAN_ROC: {
930 struct iwl_scan_channel *scan_ch;
931 int n_chan, i;
932 u16 dwell;
933
934 dwell = iwl_limit_dwell(priv, priv->hw_roc_duration);
935 n_chan = DIV_ROUND_UP(priv->hw_roc_duration, dwell);
936
937 scan->channel_count = n_chan;
938
939 scan_ch = (void *)&scan->data[cmd_len];
940
941 for (i = 0; i < n_chan; i++) {
942 scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
943 scan_ch->channel =
944 cpu_to_le16(priv->hw_roc_channel->hw_value);
945
946 if (i == n_chan - 1)
947 dwell = priv->hw_roc_duration - i * dwell;
948
949 scan_ch->active_dwell =
950 scan_ch->passive_dwell = cpu_to_le16(dwell);
951
952 /* Set txpower levels to defaults */
953 scan_ch->dsp_atten = 110;
954
955 /* NOTE: if we were doing 6Mb OFDM for scans we'd use
956 * power level:
957 * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
958 */
959 if (priv->hw_roc_channel->band == IEEE80211_BAND_5GHZ)
960 scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
961 else
962 scan_ch->tx_gain = ((1 << 5) | (5 << 3));
963
964 scan_ch++;
965 }
966 }
967
968 break;
969 } 904 }
970 905
971 if (scan->channel_count == 0) { 906 if (scan->channel_count == 0) {
@@ -1035,7 +970,6 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
1035 970
1036 IWL_DEBUG_SCAN(priv, "Starting %sscan...\n", 971 IWL_DEBUG_SCAN(priv, "Starting %sscan...\n",
1037 scan_type == IWL_SCAN_NORMAL ? "" : 972 scan_type == IWL_SCAN_NORMAL ? "" :
1038 scan_type == IWL_SCAN_ROC ? "remain-on-channel " :
1039 "internal short "); 973 "internal short ");
1040 974
1041 set_bit(STATUS_SCANNING, &priv->status); 975 set_bit(STATUS_SCANNING, &priv->status);
@@ -1149,40 +1083,3 @@ void iwl_cancel_scan_deferred_work(struct iwl_priv *priv)
1149 mutex_unlock(&priv->mutex); 1083 mutex_unlock(&priv->mutex);
1150 } 1084 }
1151} 1085}
1152
1153void iwl_scan_roc_expired(struct iwl_priv *priv)
1154{
1155 /*
1156 * The status bit should be set here, to prevent a race
1157 * where the atomic_read returns 1, but before the execution continues
1158 * iwl_scan_offchannel_skb_status() checks if the status bit is set
1159 */
1160 set_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status);
1161
1162 if (atomic_read(&priv->num_aux_in_flight) == 0) {
1163 ieee80211_remain_on_channel_expired(priv->hw);
1164 priv->hw_roc_channel = NULL;
1165 schedule_delayed_work(&priv->hw_roc_disable_work,
1166 10 * HZ);
1167
1168 clear_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status);
1169 } else {
1170 IWL_DEBUG_SCAN(priv, "ROC done with %d frames in aux\n",
1171 atomic_read(&priv->num_aux_in_flight));
1172 }
1173}
1174
1175void iwl_scan_offchannel_skb(struct iwl_priv *priv)
1176{
1177 WARN_ON(!priv->hw_roc_start_notified);
1178 atomic_inc(&priv->num_aux_in_flight);
1179}
1180
1181void iwl_scan_offchannel_skb_status(struct iwl_priv *priv)
1182{
1183 if (atomic_dec_return(&priv->num_aux_in_flight) == 0 &&
1184 test_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status)) {
1185 IWL_DEBUG_SCAN(priv, "0 aux frames. Calling ROC expired\n");
1186 iwl_scan_roc_expired(priv);
1187 }
1188}
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c
index 5ee983faa679..3db0bbb1d123 100644
--- a/drivers/net/wireless/iwlwifi/dvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/dvm/tx.c
@@ -478,9 +478,6 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
478 if (sta_priv && sta_priv->client && !is_agg) 478 if (sta_priv && sta_priv->client && !is_agg)
479 atomic_inc(&sta_priv->pending_frames); 479 atomic_inc(&sta_priv->pending_frames);
480 480
481 if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
482 iwl_scan_offchannel_skb(priv);
483
484 return 0; 481 return 0;
485 482
486drop_unlock_sta: 483drop_unlock_sta:
@@ -1158,7 +1155,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
1158 struct sk_buff *skb; 1155 struct sk_buff *skb;
1159 struct iwl_rxon_context *ctx; 1156 struct iwl_rxon_context *ctx;
1160 bool is_agg = (txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); 1157 bool is_agg = (txq_id >= IWLAGN_FIRST_AMPDU_QUEUE);
1161 bool is_offchannel_skb;
1162 1158
1163 tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> 1159 tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >>
1164 IWLAGN_TX_RES_TID_POS; 1160 IWLAGN_TX_RES_TID_POS;
@@ -1178,8 +1174,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
1178 1174
1179 __skb_queue_head_init(&skbs); 1175 __skb_queue_head_init(&skbs);
1180 1176
1181 is_offchannel_skb = false;
1182
1183 if (tx_resp->frame_count == 1) { 1177 if (tx_resp->frame_count == 1) {
1184 u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl); 1178 u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl);
1185 next_reclaimed = IEEE80211_SEQ_TO_SN(next_reclaimed + 0x10); 1179 next_reclaimed = IEEE80211_SEQ_TO_SN(next_reclaimed + 0x10);
@@ -1256,8 +1250,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
1256 if (!is_agg) 1250 if (!is_agg)
1257 iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); 1251 iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1);
1258 1252
1259 is_offchannel_skb =
1260 (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN);
1261 freed++; 1253 freed++;
1262 } 1254 }
1263 1255
@@ -1271,14 +1263,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
1271 if (!is_agg && freed != 1) 1263 if (!is_agg && freed != 1)
1272 IWL_ERR(priv, "Q: %d, freed %d\n", txq_id, freed); 1264 IWL_ERR(priv, "Q: %d, freed %d\n", txq_id, freed);
1273 1265
1274 /*
1275 * An offchannel frame can be send only on the AUX queue, where
1276 * there is no aggregation (and reordering) so it only is single
1277 * skb is expected to be processed.
1278 */
1279 if (is_offchannel_skb && freed != 1)
1280 IWL_ERR(priv, "OFFCHANNEL SKB freed %d\n", freed);
1281
1282 IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x)\n", txq_id, 1266 IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x)\n", txq_id,
1283 iwl_get_tx_fail_reason(status), status); 1267 iwl_get_tx_fail_reason(status), status);
1284 1268
@@ -1298,9 +1282,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
1298 ieee80211_tx_status_ni(priv->hw, skb); 1282 ieee80211_tx_status_ni(priv->hw, skb);
1299 } 1283 }
1300 1284
1301 if (is_offchannel_skb)
1302 iwl_scan_offchannel_skb_status(priv);
1303
1304 return 0; 1285 return 0;
1305} 1286}
1306 1287
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c
index 22b7fa5b971a..76e14c046d94 100644
--- a/drivers/net/wireless/iwlwifi/iwl-7000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-7000.c
@@ -99,6 +99,7 @@ static const struct iwl_base_params iwl7000_base_params = {
99 .wd_timeout = IWL_LONG_WD_TIMEOUT, 99 .wd_timeout = IWL_LONG_WD_TIMEOUT,
100 .max_event_log_size = 512, 100 .max_event_log_size = 512,
101 .shadow_reg_enable = true, 101 .shadow_reg_enable = true,
102 .pcie_l1_allowed = true,
102}; 103};
103 104
104static const struct iwl_ht_params iwl7000_ht_params = { 105static const struct iwl_ht_params iwl7000_ht_params = {
@@ -126,6 +127,16 @@ const struct iwl_cfg iwl7260_2ac_cfg = {
126 .nvm_calib_ver = IWL7260_TX_POWER_VERSION, 127 .nvm_calib_ver = IWL7260_TX_POWER_VERSION,
127}; 128};
128 129
130const struct iwl_cfg iwl7260_2ac_cfg_high_temp = {
131 .name = "Intel(R) Dual Band Wireless AC 7260",
132 .fw_name_pre = IWL7260_FW_PRE,
133 IWL_DEVICE_7000,
134 .ht_params = &iwl7000_ht_params,
135 .nvm_ver = IWL7260_NVM_VERSION,
136 .nvm_calib_ver = IWL7260_TX_POWER_VERSION,
137 .high_temp = true,
138};
139
129const struct iwl_cfg iwl7260_2n_cfg = { 140const struct iwl_cfg iwl7260_2n_cfg = {
130 .name = "Intel(R) Dual Band Wireless N 7260", 141 .name = "Intel(R) Dual Band Wireless N 7260",
131 .fw_name_pre = IWL7260_FW_PRE, 142 .fw_name_pre = IWL7260_FW_PRE,
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h
index 83b9ff6ff3ad..e4d370bff306 100644
--- a/drivers/net/wireless/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/iwlwifi/iwl-config.h
@@ -152,6 +152,7 @@ struct iwl_base_params {
152 unsigned int wd_timeout; 152 unsigned int wd_timeout;
153 u32 max_event_log_size; 153 u32 max_event_log_size;
154 const bool shadow_reg_enable; 154 const bool shadow_reg_enable;
155 const bool pcie_l1_allowed;
155}; 156};
156 157
157/* 158/*
@@ -205,6 +206,7 @@ struct iwl_eeprom_params {
205 * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off) 206 * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off)
206 * @rx_with_siso_diversity: 1x1 device with rx antenna diversity 207 * @rx_with_siso_diversity: 1x1 device with rx antenna diversity
207 * @internal_wimax_coex: internal wifi/wimax combo device 208 * @internal_wimax_coex: internal wifi/wimax combo device
209 * @high_temp: Is this NIC is designated to be in high temperature.
208 * 210 *
209 * We enable the driver to be backward compatible wrt. hardware features. 211 * We enable the driver to be backward compatible wrt. hardware features.
210 * API differences in uCode shouldn't be handled here but through TLVs 212 * API differences in uCode shouldn't be handled here but through TLVs
@@ -233,6 +235,7 @@ struct iwl_cfg {
233 enum iwl_led_mode led_mode; 235 enum iwl_led_mode led_mode;
234 const bool rx_with_siso_diversity; 236 const bool rx_with_siso_diversity;
235 const bool internal_wimax_coex; 237 const bool internal_wimax_coex;
238 bool high_temp;
236}; 239};
237 240
238/* 241/*
@@ -283,6 +286,7 @@ extern const struct iwl_cfg iwl135_bgn_cfg;
283#endif /* CONFIG_IWLDVM */ 286#endif /* CONFIG_IWLDVM */
284#if IS_ENABLED(CONFIG_IWLMVM) 287#if IS_ENABLED(CONFIG_IWLMVM)
285extern const struct iwl_cfg iwl7260_2ac_cfg; 288extern const struct iwl_cfg iwl7260_2ac_cfg;
289extern const struct iwl_cfg iwl7260_2ac_cfg_high_temp;
286extern const struct iwl_cfg iwl7260_2n_cfg; 290extern const struct iwl_cfg iwl7260_2n_cfg;
287extern const struct iwl_cfg iwl7260_n_cfg; 291extern const struct iwl_cfg iwl7260_n_cfg;
288extern const struct iwl_cfg iwl3160_2ac_cfg; 292extern const struct iwl_cfg iwl3160_2ac_cfg;
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h
index f844d5c748c0..bd335f0c40d1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw.h
@@ -74,13 +74,22 @@
74 * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w). 74 * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
75 * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P. 75 * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
76 * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS 76 * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS
77 * @IWL_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD
78 * @IWL_UCODE_TLV_FLAGS_RX_ENERGY_API: supports rx signal strength api
79 * @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six
80 * (rather than two) IPv6 addresses
81 * @IWL_UCODE_TLV_FLAGS_BF_UPDATED: new beacon filtering API
77 */ 82 */
78enum iwl_ucode_tlv_flag { 83enum iwl_ucode_tlv_flag {
79 IWL_UCODE_TLV_FLAGS_PAN = BIT(0), 84 IWL_UCODE_TLV_FLAGS_PAN = BIT(0),
80 IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1), 85 IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1),
81 IWL_UCODE_TLV_FLAGS_MFP = BIT(2), 86 IWL_UCODE_TLV_FLAGS_MFP = BIT(2),
82 IWL_UCODE_TLV_FLAGS_P2P = BIT(3), 87 IWL_UCODE_TLV_FLAGS_P2P = BIT(3),
83 IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4), 88 IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4),
89 IWL_UCODE_TLV_FLAGS_UAPSD = BIT(6),
90 IWL_UCODE_TLV_FLAGS_RX_ENERGY_API = BIT(8),
91 IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS = BIT(10),
92 IWL_UCODE_TLV_FLAGS_BF_UPDATED = BIT(11),
84}; 93};
85 94
86/* The default calibrate table size if not specified by firmware file */ 95/* The default calibrate table size if not specified by firmware file */
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c
index 305c81f2c2b4..dfa4d2e3aaa2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.c
+++ b/drivers/net/wireless/iwlwifi/iwl-io.c
@@ -33,6 +33,8 @@
33#include "iwl-io.h" 33#include "iwl-io.h"
34#include "iwl-csr.h" 34#include "iwl-csr.h"
35#include "iwl-debug.h" 35#include "iwl-debug.h"
36#include "iwl-fh.h"
37#include "iwl-csr.h"
36 38
37#define IWL_POLL_INTERVAL 10 /* microseconds */ 39#define IWL_POLL_INTERVAL 10 /* microseconds */
38 40
@@ -166,3 +168,68 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
166 } 168 }
167} 169}
168IWL_EXPORT_SYMBOL(iwl_clear_bits_prph); 170IWL_EXPORT_SYMBOL(iwl_clear_bits_prph);
171
172static const char *get_fh_string(int cmd)
173{
174#define IWL_CMD(x) case x: return #x
175 switch (cmd) {
176 IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
177 IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
178 IWL_CMD(FH_RSCSR_CHNL0_WPTR);
179 IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
180 IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
181 IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
182 IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
183 IWL_CMD(FH_TSSR_TX_STATUS_REG);
184 IWL_CMD(FH_TSSR_TX_ERROR_REG);
185 default:
186 return "UNKNOWN";
187 }
188#undef IWL_CMD
189}
190
191int iwl_dump_fh(struct iwl_trans *trans, char **buf)
192{
193 int i;
194 static const u32 fh_tbl[] = {
195 FH_RSCSR_CHNL0_STTS_WPTR_REG,
196 FH_RSCSR_CHNL0_RBDCB_BASE_REG,
197 FH_RSCSR_CHNL0_WPTR,
198 FH_MEM_RCSR_CHNL0_CONFIG_REG,
199 FH_MEM_RSSR_SHARED_CTRL_REG,
200 FH_MEM_RSSR_RX_STATUS_REG,
201 FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
202 FH_TSSR_TX_STATUS_REG,
203 FH_TSSR_TX_ERROR_REG
204 };
205
206#ifdef CONFIG_IWLWIFI_DEBUGFS
207 if (buf) {
208 int pos = 0;
209 size_t bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
210
211 *buf = kmalloc(bufsz, GFP_KERNEL);
212 if (!*buf)
213 return -ENOMEM;
214
215 pos += scnprintf(*buf + pos, bufsz - pos,
216 "FH register values:\n");
217
218 for (i = 0; i < ARRAY_SIZE(fh_tbl); i++)
219 pos += scnprintf(*buf + pos, bufsz - pos,
220 " %34s: 0X%08x\n",
221 get_fh_string(fh_tbl[i]),
222 iwl_read_direct32(trans, fh_tbl[i]));
223
224 return pos;
225 }
226#endif
227
228 IWL_ERR(trans, "FH register values:\n");
229 for (i = 0; i < ARRAY_SIZE(fh_tbl); i++)
230 IWL_ERR(trans, " %34s: 0X%08x\n",
231 get_fh_string(fh_tbl[i]),
232 iwl_read_direct32(trans, fh_tbl[i]));
233
234 return 0;
235}
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h
index fd9f5b97fff3..63d10ec08dbc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.h
+++ b/drivers/net/wireless/iwlwifi/iwl-io.h
@@ -77,4 +77,7 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
77 u32 bits, u32 mask); 77 u32 bits, u32 mask);
78void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); 78void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);
79 79
80/* Error handling */
81int iwl_dump_fh(struct iwl_trans *trans, char **buf);
82
80#endif 83#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
index acd2665afb8c..b76a9a8fc0b3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
@@ -118,6 +118,7 @@ static const u8 iwl_nvm_channels[] = {
118#define LAST_2GHZ_HT_PLUS 9 118#define LAST_2GHZ_HT_PLUS 9
119#define LAST_5GHZ_HT 161 119#define LAST_5GHZ_HT 161
120 120
121#define DEFAULT_MAX_TX_POWER 16
121 122
122/* rate data (static) */ 123/* rate data (static) */
123static struct ieee80211_rate iwl_cfg80211_rates[] = { 124static struct ieee80211_rate iwl_cfg80211_rates[] = {
@@ -232,8 +233,11 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
232 233
233 /* Initialize regulatory-based run-time data */ 234 /* Initialize regulatory-based run-time data */
234 235
235 /* TODO: read the real value from the NVM */ 236 /*
236 channel->max_power = 0; 237 * Default value - highest tx power value. max_power
238 * is not used in mvm, and is used for backwards compatibility
239 */
240 channel->max_power = DEFAULT_MAX_TX_POWER;
237 is_5ghz = channel->band == IEEE80211_BAND_5GHZ; 241 is_5ghz = channel->band == IEEE80211_BAND_5GHZ;
238 IWL_DEBUG_EEPROM(dev, 242 IWL_DEBUG_EEPROM(dev,
239 "Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n", 243 "Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n",
diff --git a/drivers/net/wireless/iwlwifi/mvm/Makefile b/drivers/net/wireless/iwlwifi/mvm/Makefile
index ff856e543ae8..6d73817850ce 100644
--- a/drivers/net/wireless/iwlwifi/mvm/Makefile
+++ b/drivers/net/wireless/iwlwifi/mvm/Makefile
@@ -2,7 +2,7 @@ obj-$(CONFIG_IWLMVM) += iwlmvm.o
2iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o 2iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o
3iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o 3iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o
4iwlmvm-y += scan.o time-event.o rs.o 4iwlmvm-y += scan.o time-event.o rs.o
5iwlmvm-y += power.o bt-coex.o 5iwlmvm-y += power.o power_legacy.o bt-coex.o
6iwlmvm-y += led.o tt.o 6iwlmvm-y += led.o tt.o
7iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o 7iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o
8iwlmvm-$(CONFIG_PM_SLEEP) += d3.o 8iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
index dbd622a3929c..0fad98b85f60 100644
--- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
+++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
@@ -220,66 +220,87 @@ static const __le32 iwl_single_shared_ant_lookup[BT_COEX_LUT_SIZE] = {
220 220
221int iwl_send_bt_init_conf(struct iwl_mvm *mvm) 221int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
222{ 222{
223 struct iwl_bt_coex_cmd cmd = { 223 struct iwl_bt_coex_cmd *bt_cmd;
224 .max_kill = 5, 224 struct iwl_host_cmd cmd = {
225 .bt3_time_t7_value = 1, 225 .id = BT_CONFIG,
226 .bt3_prio_sample_time = 2, 226 .len = { sizeof(*bt_cmd), },
227 .bt3_timer_t2_value = 0xc, 227 .dataflags = { IWL_HCMD_DFL_NOCOPY, },
228 .flags = CMD_SYNC,
228 }; 229 };
229 int ret; 230 int ret;
230 231
231 cmd.flags = iwlwifi_mod_params.bt_coex_active ? 232 /* go to CALIB state in internal BT-Coex state machine */
233 ret = iwl_send_bt_env(mvm, BT_COEX_ENV_OPEN,
234 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
235 if (ret)
236 return ret;
237
238 ret = iwl_send_bt_env(mvm, BT_COEX_ENV_CLOSE,
239 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
240 if (ret)
241 return ret;
242
243 bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
244 if (!bt_cmd)
245 return -ENOMEM;
246 cmd.data[0] = bt_cmd;
247
248 bt_cmd->max_kill = 5;
249 bt_cmd->bt3_time_t7_value = 1;
250 bt_cmd->bt3_prio_sample_time = 2;
251 bt_cmd->bt3_timer_t2_value = 0xc;
252
253 bt_cmd->flags = iwlwifi_mod_params.bt_coex_active ?
232 BT_COEX_NW : BT_COEX_DISABLE; 254 BT_COEX_NW : BT_COEX_DISABLE;
233 cmd.flags |= BT_CH_PRIMARY_EN | BT_SYNC_2_BT_DISABLE; 255 bt_cmd->flags |= BT_CH_PRIMARY_EN | BT_SYNC_2_BT_DISABLE;
234 256
235 cmd.valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE | 257 bt_cmd->valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE |
236 BT_VALID_BT_PRIO_BOOST | 258 BT_VALID_BT_PRIO_BOOST |
237 BT_VALID_MAX_KILL | 259 BT_VALID_MAX_KILL |
238 BT_VALID_3W_TMRS | 260 BT_VALID_3W_TMRS |
239 BT_VALID_KILL_ACK | 261 BT_VALID_KILL_ACK |
240 BT_VALID_KILL_CTS | 262 BT_VALID_KILL_CTS |
241 BT_VALID_REDUCED_TX_POWER | 263 BT_VALID_REDUCED_TX_POWER |
242 BT_VALID_LUT); 264 BT_VALID_LUT);
243 265
244 if (mvm->cfg->bt_shared_single_ant) 266 if (mvm->cfg->bt_shared_single_ant)
245 memcpy(&cmd.decision_lut, iwl_single_shared_ant_lookup, 267 memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant_lookup,
246 sizeof(iwl_single_shared_ant_lookup)); 268 sizeof(iwl_single_shared_ant_lookup));
247 else if (is_loose_coex()) 269 else if (is_loose_coex())
248 memcpy(&cmd.decision_lut, iwl_loose_lookup, 270 memcpy(&bt_cmd->decision_lut, iwl_loose_lookup,
249 sizeof(iwl_tight_lookup)); 271 sizeof(iwl_tight_lookup));
250 else 272 else
251 memcpy(&cmd.decision_lut, iwl_tight_lookup, 273 memcpy(&bt_cmd->decision_lut, iwl_tight_lookup,
252 sizeof(iwl_tight_lookup)); 274 sizeof(iwl_tight_lookup));
253 275
254 cmd.bt_prio_boost = cpu_to_le32(IWL_BT_DEFAULT_BOOST); 276 bt_cmd->bt_prio_boost = cpu_to_le32(IWL_BT_DEFAULT_BOOST);
255 cmd.kill_ack_msk = 277 bt_cmd->kill_ack_msk =
256 cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]); 278 cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]);
257 cmd.kill_cts_msk = 279 bt_cmd->kill_cts_msk =
258 cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]); 280 cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]);
259 281
260 memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); 282 memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
261 283
262 /* go to CALIB state in internal BT-Coex state machine */ 284 ret = iwl_mvm_send_cmd(mvm, &cmd);
263 ret = iwl_send_bt_env(mvm, BT_COEX_ENV_OPEN,
264 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
265 if (ret)
266 return ret;
267
268 ret = iwl_send_bt_env(mvm, BT_COEX_ENV_CLOSE,
269 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
270 if (ret)
271 return ret;
272 285
273 return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC, 286 kfree(bt_cmd);
274 sizeof(cmd), &cmd); 287 return ret;
275} 288}
276 289
277static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm, 290static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
278 bool reduced_tx_power) 291 bool reduced_tx_power)
279{ 292{
280 enum iwl_bt_kill_msk bt_kill_msk; 293 enum iwl_bt_kill_msk bt_kill_msk;
281 struct iwl_bt_coex_cmd cmd = {}; 294 struct iwl_bt_coex_cmd *bt_cmd;
282 struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif; 295 struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
296 struct iwl_host_cmd cmd = {
297 .id = BT_CONFIG,
298 .data[0] = &bt_cmd,
299 .len = { sizeof(*bt_cmd), },
300 .dataflags = { IWL_HCMD_DFL_NOCOPY, },
301 .flags = CMD_SYNC,
302 };
303 int ret = 0;
283 304
284 lockdep_assert_held(&mvm->mutex); 305 lockdep_assert_held(&mvm->mutex);
285 306
@@ -308,24 +329,40 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
308 return 0; 329 return 0;
309 330
310 mvm->bt_kill_msk = bt_kill_msk; 331 mvm->bt_kill_msk = bt_kill_msk;
311 cmd.kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]); 332
312 cmd.kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]); 333 bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
313 cmd.valid_bit_msk = cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS); 334 if (!bt_cmd)
335 return -ENOMEM;
336 cmd.data[0] = bt_cmd;
337
338 bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]);
339 bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]);
340 bt_cmd->valid_bit_msk =
341 cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS);
314 342
315 IWL_DEBUG_COEX(mvm, "bt_kill_msk = %d\n", bt_kill_msk); 343 IWL_DEBUG_COEX(mvm, "bt_kill_msk = %d\n", bt_kill_msk);
316 return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC, 344
317 sizeof(cmd), &cmd); 345 ret = iwl_mvm_send_cmd(mvm, &cmd);
346
347 kfree(bt_cmd);
348 return ret;
318} 349}
319 350
320static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, 351static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
321 bool enable) 352 bool enable)
322{ 353{
323 struct iwl_bt_coex_cmd cmd = { 354 struct iwl_bt_coex_cmd *bt_cmd;
324 .valid_bit_msk = cpu_to_le16(BT_VALID_REDUCED_TX_POWER), 355 /* Send ASYNC since this can be sent from an atomic context */
325 .bt_reduced_tx_power = sta_id, 356 struct iwl_host_cmd cmd = {
357 .id = BT_CONFIG,
358 .len = { sizeof(*bt_cmd), },
359 .dataflags = { IWL_HCMD_DFL_DUP, },
360 .flags = CMD_ASYNC,
326 }; 361 };
362
327 struct ieee80211_sta *sta; 363 struct ieee80211_sta *sta;
328 struct iwl_mvm_sta *mvmsta; 364 struct iwl_mvm_sta *mvmsta;
365 int ret;
329 366
330 /* This can happen if the station has been removed right now */ 367 /* This can happen if the station has been removed right now */
331 if (sta_id == IWL_MVM_STATION_COUNT) 368 if (sta_id == IWL_MVM_STATION_COUNT)
@@ -339,17 +376,26 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
339 if (mvmsta->bt_reduced_txpower == enable) 376 if (mvmsta->bt_reduced_txpower == enable)
340 return 0; 377 return 0;
341 378
379 bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_ATOMIC);
380 if (!bt_cmd)
381 return -ENOMEM;
382 cmd.data[0] = bt_cmd;
383
384 bt_cmd->valid_bit_msk = cpu_to_le16(BT_VALID_REDUCED_TX_POWER),
385 bt_cmd->bt_reduced_tx_power = sta_id;
386
342 if (enable) 387 if (enable)
343 cmd.bt_reduced_tx_power |= BT_REDUCED_TX_POWER_BIT; 388 bt_cmd->bt_reduced_tx_power |= BT_REDUCED_TX_POWER_BIT;
344 389
345 IWL_DEBUG_COEX(mvm, "%sable reduced Tx Power for sta %d\n", 390 IWL_DEBUG_COEX(mvm, "%sable reduced Tx Power for sta %d\n",
346 enable ? "en" : "dis", sta_id); 391 enable ? "en" : "dis", sta_id);
347 392
348 mvmsta->bt_reduced_txpower = enable; 393 mvmsta->bt_reduced_txpower = enable;
349 394
350 /* Send ASYNC since this can be sent from an atomic context */ 395 ret = iwl_mvm_send_cmd(mvm, &cmd);
351 return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_ASYNC, 396
352 sizeof(cmd), &cmd); 397 kfree(bt_cmd);
398 return ret;
353} 399}
354 400
355struct iwl_bt_iterator_data { 401struct iwl_bt_iterator_data {
@@ -384,6 +430,10 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
384 430
385 smps_mode = IEEE80211_SMPS_AUTOMATIC; 431 smps_mode = IEEE80211_SMPS_AUTOMATIC;
386 432
433 /* non associated BSSes aren't to be considered */
434 if (!vif->bss_conf.assoc)
435 return;
436
387 if (band != IEEE80211_BAND_2GHZ) { 437 if (band != IEEE80211_BAND_2GHZ) {
388 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, 438 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
389 smps_mode); 439 smps_mode);
@@ -523,6 +573,8 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
523 lockdep_is_held(&mvm->mutex)); 573 lockdep_is_held(&mvm->mutex));
524 mvmsta = (void *)sta->drv_priv; 574 mvmsta = (void *)sta->drv_priv;
525 575
576 data->num_bss_ifaces++;
577
526 /* 578 /*
527 * This interface doesn't support reduced Tx power (because of low 579 * This interface doesn't support reduced Tx power (because of low
528 * RSSI probably), then set bt_kill_msk to default values. 580 * RSSI probably), then set bt_kill_msk to default values.
@@ -588,23 +640,5 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
588 640
589void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif) 641void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
590{ 642{
591 struct ieee80211_chanctx_conf *chanctx_conf;
592 enum ieee80211_band band;
593
594 rcu_read_lock();
595 chanctx_conf = rcu_dereference(vif->chanctx_conf);
596 if (chanctx_conf && chanctx_conf->def.chan)
597 band = chanctx_conf->def.chan->band;
598 else
599 band = -1;
600 rcu_read_unlock();
601
602 /* if we are in 2GHz we will get a notification from the fw */
603 if (band == IEEE80211_BAND_2GHZ)
604 return;
605
606 /* else, we can remove all the constraints */
607 memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
608
609 iwl_mvm_bt_coex_notif_handle(mvm); 643 iwl_mvm_bt_coex_notif_handle(mvm);
610} 644}
diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h
new file mode 100644
index 000000000000..64656e0c8f91
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/mvm/constants.h
@@ -0,0 +1,71 @@
1/******************************************************************************
2 *
3 * This file is provided under a dual BSD/GPLv2 license. When using or
4 * redistributing this file, you may do so under either license.
5 *
6 * GPL LICENSE SUMMARY
7 *
8 * Copyright(c) 2013 Intel Corporation. All rights reserved.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
22 * USA
23 *
24 * The full GNU General Public License is included in this distribution
25 * in the file called COPYING.
26 *
27 * Contact Information:
28 * Intel Linux Wireless <ilw@linux.intel.com>
29 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30 *
31 * BSD LICENSE
32 *
33 * Copyright(c) 2013 Intel Corporation. All rights reserved.
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 *
40 * * Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * * Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in
44 * the documentation and/or other materials provided with the
45 * distribution.
46 * * Neither the name Intel Corporation nor the names of its
47 * contributors may be used to endorse or promote products derived
48 * from this software without specific prior written permission.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
54 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
56 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
60 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 *
62 *****************************************************************************/
63#ifndef __MVM_CONSTANTS_H
64#define __MVM_CONSTANTS_H
65
66#define IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT (100 * USEC_PER_MSEC)
67#define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC)
68#define IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT (10 * USEC_PER_MSEC)
69#define IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT (10 * USEC_PER_MSEC)
70
71#endif /* __MVM_CONSTANTS_H */
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c
index 7e5e5c2f9f87..ebf7f9468926 100644
--- a/drivers/net/wireless/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/iwlwifi/mvm/d3.c
@@ -105,7 +105,7 @@ void iwl_mvm_ipv6_addr_change(struct ieee80211_hw *hw,
105 list_for_each_entry(ifa, &idev->addr_list, if_list) { 105 list_for_each_entry(ifa, &idev->addr_list, if_list) {
106 mvmvif->target_ipv6_addrs[idx] = ifa->addr; 106 mvmvif->target_ipv6_addrs[idx] = ifa->addr;
107 idx++; 107 idx++;
108 if (idx >= IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS) 108 if (idx >= IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX)
109 break; 109 break;
110 } 110 }
111 read_unlock_bh(&idev->lock); 111 read_unlock_bh(&idev->lock);
@@ -373,36 +373,68 @@ static int iwl_mvm_send_patterns(struct iwl_mvm *mvm,
373static int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, 373static int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
374 struct ieee80211_vif *vif) 374 struct ieee80211_vif *vif)
375{ 375{
376 struct iwl_proto_offload_cmd cmd = {}; 376 union {
377 struct iwl_proto_offload_cmd_v1 v1;
378 struct iwl_proto_offload_cmd_v2 v2;
379 } cmd = {};
380 struct iwl_proto_offload_cmd_common *common;
381 u32 enabled = 0, size;
377#if IS_ENABLED(CONFIG_IPV6) 382#if IS_ENABLED(CONFIG_IPV6)
378 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 383 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
379 int i; 384 int i;
380 385
381 if (mvmvif->num_target_ipv6_addrs) { 386 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS) {
382 cmd.enabled |= cpu_to_le32(IWL_D3_PROTO_OFFLOAD_NS); 387 if (mvmvif->num_target_ipv6_addrs) {
383 memcpy(cmd.ndp_mac_addr, vif->addr, ETH_ALEN); 388 enabled |= IWL_D3_PROTO_OFFLOAD_NS;
384 } 389 memcpy(cmd.v2.ndp_mac_addr, vif->addr, ETH_ALEN);
390 }
391
392 BUILD_BUG_ON(sizeof(cmd.v2.target_ipv6_addr[0]) !=
393 sizeof(mvmvif->target_ipv6_addrs[0]));
394
395 for (i = 0; i < min(mvmvif->num_target_ipv6_addrs,
396 IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2); i++)
397 memcpy(cmd.v2.target_ipv6_addr[i],
398 &mvmvif->target_ipv6_addrs[i],
399 sizeof(cmd.v2.target_ipv6_addr[i]));
400 } else {
401 if (mvmvif->num_target_ipv6_addrs) {
402 enabled |= IWL_D3_PROTO_OFFLOAD_NS;
403 memcpy(cmd.v1.ndp_mac_addr, vif->addr, ETH_ALEN);
404 }
385 405
386 BUILD_BUG_ON(sizeof(cmd.target_ipv6_addr[i]) != 406 BUILD_BUG_ON(sizeof(cmd.v1.target_ipv6_addr[0]) !=
387 sizeof(mvmvif->target_ipv6_addrs[i])); 407 sizeof(mvmvif->target_ipv6_addrs[0]));
388 408
389 for (i = 0; i < mvmvif->num_target_ipv6_addrs; i++) 409 for (i = 0; i < min(mvmvif->num_target_ipv6_addrs,
390 memcpy(cmd.target_ipv6_addr[i], 410 IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1); i++)
391 &mvmvif->target_ipv6_addrs[i], 411 memcpy(cmd.v1.target_ipv6_addr[i],
392 sizeof(cmd.target_ipv6_addr[i])); 412 &mvmvif->target_ipv6_addrs[i],
413 sizeof(cmd.v1.target_ipv6_addr[i]));
414 }
393#endif 415#endif
394 416
417 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS) {
418 common = &cmd.v2.common;
419 size = sizeof(cmd.v2);
420 } else {
421 common = &cmd.v1.common;
422 size = sizeof(cmd.v1);
423 }
424
395 if (vif->bss_conf.arp_addr_cnt) { 425 if (vif->bss_conf.arp_addr_cnt) {
396 cmd.enabled |= cpu_to_le32(IWL_D3_PROTO_OFFLOAD_ARP); 426 enabled |= IWL_D3_PROTO_OFFLOAD_ARP;
397 cmd.host_ipv4_addr = vif->bss_conf.arp_addr_list[0]; 427 common->host_ipv4_addr = vif->bss_conf.arp_addr_list[0];
398 memcpy(cmd.arp_mac_addr, vif->addr, ETH_ALEN); 428 memcpy(common->arp_mac_addr, vif->addr, ETH_ALEN);
399 } 429 }
400 430
401 if (!cmd.enabled) 431 if (!enabled)
402 return 0; 432 return 0;
403 433
434 common->enabled = cpu_to_le32(enabled);
435
404 return iwl_mvm_send_cmd_pdu(mvm, PROT_OFFLOAD_CONFIG_CMD, CMD_SYNC, 436 return iwl_mvm_send_cmd_pdu(mvm, PROT_OFFLOAD_CONFIG_CMD, CMD_SYNC,
405 sizeof(cmd), &cmd); 437 size, &cmd);
406} 438}
407 439
408enum iwl_mvm_tcp_packet_type { 440enum iwl_mvm_tcp_packet_type {
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index c24a744910ac..56f6827b19e5 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -424,40 +424,11 @@ static ssize_t iwl_dbgfs_pm_params_read(struct file *file,
424 struct ieee80211_vif *vif = file->private_data; 424 struct ieee80211_vif *vif = file->private_data;
425 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 425 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
426 struct iwl_mvm *mvm = mvmvif->dbgfs_data; 426 struct iwl_mvm *mvm = mvmvif->dbgfs_data;
427 struct iwl_powertable_cmd cmd = {};
428 char buf[256]; 427 char buf[256];
429 int bufsz = sizeof(buf); 428 int bufsz = sizeof(buf);
430 int pos = 0; 429 int pos;
431 430
432 iwl_mvm_power_build_cmd(mvm, vif, &cmd); 431 pos = iwl_mvm_power_dbgfs_read(mvm, vif, buf, bufsz);
433
434 pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n",
435 (cmd.flags &
436 cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ?
437 0 : 1);
438 pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
439 le32_to_cpu(cmd.skip_dtim_periods));
440 pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
441 iwlmvm_mod_params.power_scheme);
442 pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
443 le16_to_cpu(cmd.flags));
444 pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
445 cmd.keep_alive_seconds);
446
447 if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
448 pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
449 (cmd.flags &
450 cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ?
451 1 : 0);
452 pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n",
453 le32_to_cpu(cmd.rx_data_timeout));
454 pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
455 le32_to_cpu(cmd.tx_data_timeout));
456 if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
457 pos += scnprintf(buf+pos, bufsz-pos,
458 "lprx_rssi_threshold = %d\n",
459 le32_to_cpu(cmd.lprx_rssi_threshold));
460 }
461 432
462 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 433 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
463} 434}
@@ -626,20 +597,19 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct file *file,
626 size_t count, loff_t *ppos) 597 size_t count, loff_t *ppos)
627{ 598{
628 struct iwl_mvm *mvm = file->private_data; 599 struct iwl_mvm *mvm = file->private_data;
629 bool restart_fw = iwlwifi_mod_params.restart_fw;
630 int ret; 600 int ret;
631 601
632 iwlwifi_mod_params.restart_fw = true;
633
634 mutex_lock(&mvm->mutex); 602 mutex_lock(&mvm->mutex);
635 603
604 /* allow one more restart that we're provoking here */
605 if (mvm->restart_fw >= 0)
606 mvm->restart_fw++;
607
636 /* take the return value to make compiler happy - it will fail anyway */ 608 /* take the return value to make compiler happy - it will fail anyway */
637 ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_ERROR, CMD_SYNC, 0, NULL); 609 ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_ERROR, CMD_SYNC, 0, NULL);
638 610
639 mutex_unlock(&mvm->mutex); 611 mutex_unlock(&mvm->mutex);
640 612
641 iwlwifi_mod_params.restart_fw = restart_fw;
642
643 return count; 613 return count;
644} 614}
645 615
@@ -661,8 +631,14 @@ static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif,
661 case MVM_DEBUGFS_BF_ROAMING_STATE: 631 case MVM_DEBUGFS_BF_ROAMING_STATE:
662 dbgfs_bf->bf_roaming_state = value; 632 dbgfs_bf->bf_roaming_state = value;
663 break; 633 break;
664 case MVM_DEBUGFS_BF_TEMPERATURE_DELTA: 634 case MVM_DEBUGFS_BF_TEMP_THRESHOLD:
665 dbgfs_bf->bf_temperature_delta = value; 635 dbgfs_bf->bf_temp_threshold = value;
636 break;
637 case MVM_DEBUGFS_BF_TEMP_FAST_FILTER:
638 dbgfs_bf->bf_temp_fast_filter = value;
639 break;
640 case MVM_DEBUGFS_BF_TEMP_SLOW_FILTER:
641 dbgfs_bf->bf_temp_slow_filter = value;
666 break; 642 break;
667 case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER: 643 case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER:
668 dbgfs_bf->bf_enable_beacon_filter = value; 644 dbgfs_bf->bf_enable_beacon_filter = value;
@@ -721,13 +697,27 @@ static ssize_t iwl_dbgfs_bf_params_write(struct file *file,
721 value > IWL_BF_ROAMING_STATE_MAX) 697 value > IWL_BF_ROAMING_STATE_MAX)
722 return -EINVAL; 698 return -EINVAL;
723 param = MVM_DEBUGFS_BF_ROAMING_STATE; 699 param = MVM_DEBUGFS_BF_ROAMING_STATE;
724 } else if (!strncmp("bf_temperature_delta=", buf, 21)) { 700 } else if (!strncmp("bf_temp_threshold=", buf, 18)) {
725 if (sscanf(buf+21, "%d", &value) != 1) 701 if (sscanf(buf+18, "%d", &value) != 1)
702 return -EINVAL;
703 if (value < IWL_BF_TEMP_THRESHOLD_MIN ||
704 value > IWL_BF_TEMP_THRESHOLD_MAX)
705 return -EINVAL;
706 param = MVM_DEBUGFS_BF_TEMP_THRESHOLD;
707 } else if (!strncmp("bf_temp_fast_filter=", buf, 20)) {
708 if (sscanf(buf+20, "%d", &value) != 1)
709 return -EINVAL;
710 if (value < IWL_BF_TEMP_FAST_FILTER_MIN ||
711 value > IWL_BF_TEMP_FAST_FILTER_MAX)
712 return -EINVAL;
713 param = MVM_DEBUGFS_BF_TEMP_FAST_FILTER;
714 } else if (!strncmp("bf_temp_slow_filter=", buf, 20)) {
715 if (sscanf(buf+20, "%d", &value) != 1)
726 return -EINVAL; 716 return -EINVAL;
727 if (value < IWL_BF_TEMPERATURE_DELTA_MIN || 717 if (value < IWL_BF_TEMP_SLOW_FILTER_MIN ||
728 value > IWL_BF_TEMPERATURE_DELTA_MAX) 718 value > IWL_BF_TEMP_SLOW_FILTER_MAX)
729 return -EINVAL; 719 return -EINVAL;
730 param = MVM_DEBUGFS_BF_TEMPERATURE_DELTA; 720 param = MVM_DEBUGFS_BF_TEMP_SLOW_FILTER;
731 } else if (!strncmp("bf_enable_beacon_filter=", buf, 24)) { 721 } else if (!strncmp("bf_enable_beacon_filter=", buf, 24)) {
732 if (sscanf(buf+24, "%d", &value) != 1) 722 if (sscanf(buf+24, "%d", &value) != 1)
733 return -EINVAL; 723 return -EINVAL;
@@ -789,41 +779,41 @@ static ssize_t iwl_dbgfs_bf_params_read(struct file *file,
789 int pos = 0; 779 int pos = 0;
790 const size_t bufsz = sizeof(buf); 780 const size_t bufsz = sizeof(buf);
791 struct iwl_beacon_filter_cmd cmd = { 781 struct iwl_beacon_filter_cmd cmd = {
792 .bf_energy_delta = IWL_BF_ENERGY_DELTA_DEFAULT, 782 IWL_BF_CMD_CONFIG_DEFAULTS,
793 .bf_roaming_energy_delta = IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT, 783 .bf_enable_beacon_filter =
794 .bf_roaming_state = IWL_BF_ROAMING_STATE_DEFAULT, 784 cpu_to_le32(IWL_BF_ENABLE_BEACON_FILTER_DEFAULT),
795 .bf_temperature_delta = IWL_BF_TEMPERATURE_DELTA_DEFAULT, 785 .ba_enable_beacon_abort =
796 .bf_enable_beacon_filter = IWL_BF_ENABLE_BEACON_FILTER_DEFAULT, 786 cpu_to_le32(IWL_BA_ENABLE_BEACON_ABORT_DEFAULT),
797 .bf_debug_flag = IWL_BF_DEBUG_FLAG_DEFAULT,
798 .bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT),
799 .ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT),
800 .ba_enable_beacon_abort = IWL_BA_ENABLE_BEACON_ABORT_DEFAULT,
801 }; 787 };
802 788
803 iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); 789 iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
804 if (mvmvif->bf_enabled) 790 if (mvmvif->bf_enabled)
805 cmd.bf_enable_beacon_filter = 1; 791 cmd.bf_enable_beacon_filter = cpu_to_le32(1);
806 else 792 else
807 cmd.bf_enable_beacon_filter = 0; 793 cmd.bf_enable_beacon_filter = 0;
808 794
809 pos += scnprintf(buf+pos, bufsz-pos, "bf_energy_delta = %d\n", 795 pos += scnprintf(buf+pos, bufsz-pos, "bf_energy_delta = %d\n",
810 cmd.bf_energy_delta); 796 le32_to_cpu(cmd.bf_energy_delta));
811 pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_energy_delta = %d\n", 797 pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_energy_delta = %d\n",
812 cmd.bf_roaming_energy_delta); 798 le32_to_cpu(cmd.bf_roaming_energy_delta));
813 pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_state = %d\n", 799 pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_state = %d\n",
814 cmd.bf_roaming_state); 800 le32_to_cpu(cmd.bf_roaming_state));
815 pos += scnprintf(buf+pos, bufsz-pos, "bf_temperature_delta = %d\n", 801 pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_threshold = %d\n",
816 cmd.bf_temperature_delta); 802 le32_to_cpu(cmd.bf_temp_threshold));
803 pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_fast_filter = %d\n",
804 le32_to_cpu(cmd.bf_temp_fast_filter));
805 pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_slow_filter = %d\n",
806 le32_to_cpu(cmd.bf_temp_slow_filter));
817 pos += scnprintf(buf+pos, bufsz-pos, "bf_enable_beacon_filter = %d\n", 807 pos += scnprintf(buf+pos, bufsz-pos, "bf_enable_beacon_filter = %d\n",
818 cmd.bf_enable_beacon_filter); 808 le32_to_cpu(cmd.bf_enable_beacon_filter));
819 pos += scnprintf(buf+pos, bufsz-pos, "bf_debug_flag = %d\n", 809 pos += scnprintf(buf+pos, bufsz-pos, "bf_debug_flag = %d\n",
820 cmd.bf_debug_flag); 810 le32_to_cpu(cmd.bf_debug_flag));
821 pos += scnprintf(buf+pos, bufsz-pos, "bf_escape_timer = %d\n", 811 pos += scnprintf(buf+pos, bufsz-pos, "bf_escape_timer = %d\n",
822 cmd.bf_escape_timer); 812 le32_to_cpu(cmd.bf_escape_timer));
823 pos += scnprintf(buf+pos, bufsz-pos, "ba_escape_timer = %d\n", 813 pos += scnprintf(buf+pos, bufsz-pos, "ba_escape_timer = %d\n",
824 cmd.ba_escape_timer); 814 le32_to_cpu(cmd.ba_escape_timer));
825 pos += scnprintf(buf+pos, bufsz-pos, "ba_enable_beacon_abort = %d\n", 815 pos += scnprintf(buf+pos, bufsz-pos, "ba_enable_beacon_abort = %d\n",
826 cmd.ba_enable_beacon_abort); 816 le32_to_cpu(cmd.ba_enable_beacon_abort));
827 817
828 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 818 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
829} 819}
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
index 6f8b2c16ae17..df72fcdf8170 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
@@ -98,34 +98,63 @@ enum iwl_proto_offloads {
98 IWL_D3_PROTO_OFFLOAD_NS = BIT(1), 98 IWL_D3_PROTO_OFFLOAD_NS = BIT(1),
99}; 99};
100 100
101#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS 2 101#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1 2
102#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2 6
103#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX 6
102 104
103/** 105/**
104 * struct iwl_proto_offload_cmd - ARP/NS offload configuration 106 * struct iwl_proto_offload_cmd_common - ARP/NS offload common part
105 * @enabled: enable flags 107 * @enabled: enable flags
106 * @remote_ipv4_addr: remote address to answer to (or zero if all) 108 * @remote_ipv4_addr: remote address to answer to (or zero if all)
107 * @host_ipv4_addr: our IPv4 address to respond to queries for 109 * @host_ipv4_addr: our IPv4 address to respond to queries for
108 * @arp_mac_addr: our MAC address for ARP responses 110 * @arp_mac_addr: our MAC address for ARP responses
109 * @remote_ipv6_addr: remote address to answer to (or zero if all) 111 * @reserved: unused
110 * @solicited_node_ipv6_addr: broken -- solicited node address exists
111 * for each target address
112 * @target_ipv6_addr: our target addresses
113 * @ndp_mac_addr: neighbor soliciation response MAC address
114 */ 112 */
115struct iwl_proto_offload_cmd { 113struct iwl_proto_offload_cmd_common {
116 __le32 enabled; 114 __le32 enabled;
117 __be32 remote_ipv4_addr; 115 __be32 remote_ipv4_addr;
118 __be32 host_ipv4_addr; 116 __be32 host_ipv4_addr;
119 u8 arp_mac_addr[ETH_ALEN]; 117 u8 arp_mac_addr[ETH_ALEN];
120 __le16 reserved1; 118 __le16 reserved;
119} __packed;
121 120
121/**
122 * struct iwl_proto_offload_cmd_v1 - ARP/NS offload configuration
123 * @common: common/IPv4 configuration
124 * @remote_ipv6_addr: remote address to answer to (or zero if all)
125 * @solicited_node_ipv6_addr: broken -- solicited node address exists
126 * for each target address
127 * @target_ipv6_addr: our target addresses
128 * @ndp_mac_addr: neighbor soliciation response MAC address
129 */
130struct iwl_proto_offload_cmd_v1 {
131 struct iwl_proto_offload_cmd_common common;
122 u8 remote_ipv6_addr[16]; 132 u8 remote_ipv6_addr[16];
123 u8 solicited_node_ipv6_addr[16]; 133 u8 solicited_node_ipv6_addr[16];
124 u8 target_ipv6_addr[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS][16]; 134 u8 target_ipv6_addr[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1][16];
125 u8 ndp_mac_addr[ETH_ALEN]; 135 u8 ndp_mac_addr[ETH_ALEN];
126 __le16 reserved2; 136 __le16 reserved2;
127} __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_1 */ 137} __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_1 */
128 138
139/**
140 * struct iwl_proto_offload_cmd_v2 - ARP/NS offload configuration
141 * @common: common/IPv4 configuration
142 * @remote_ipv6_addr: remote address to answer to (or zero if all)
143 * @solicited_node_ipv6_addr: broken -- solicited node address exists
144 * for each target address
145 * @target_ipv6_addr: our target addresses
146 * @ndp_mac_addr: neighbor soliciation response MAC address
147 */
148struct iwl_proto_offload_cmd_v2 {
149 struct iwl_proto_offload_cmd_common common;
150 u8 remote_ipv6_addr[16];
151 u8 solicited_node_ipv6_addr[16];
152 u8 target_ipv6_addr[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2][16];
153 u8 ndp_mac_addr[ETH_ALEN];
154 u8 numValidIPv6Addresses;
155 u8 reserved2[3];
156} __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_2 */
157
129 158
130/* 159/*
131 * WOWLAN_PATTERNS 160 * WOWLAN_PATTERNS
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
index a6da359a80c3..060e630b3d82 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
@@ -79,6 +79,10 @@
79 * '1' Driver enables PM (use rest of parameters) 79 * '1' Driver enables PM (use rest of parameters)
80 * @POWER_FLAGS_SKIP_OVER_DTIM_MSK: '0' PM have to walk up every DTIM, 80 * @POWER_FLAGS_SKIP_OVER_DTIM_MSK: '0' PM have to walk up every DTIM,
81 * '1' PM could sleep over DTIM till listen Interval. 81 * '1' PM could sleep over DTIM till listen Interval.
82 * @POWER_FLAGS_SNOOZE_ENA_MSK: Enable snoozing only if uAPSD is enabled and all
83 * access categories are both delivery and trigger enabled.
84 * @POWER_FLAGS_BT_SCO_ENA: Enable BT SCO coex only if uAPSD and
85 * PBW Snoozing enabled
82 * @POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask 86 * @POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask
83 * @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable. 87 * @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable.
84*/ 88*/
@@ -86,6 +90,8 @@ enum iwl_power_flags {
86 POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0), 90 POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0),
87 POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK = BIT(1), 91 POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK = BIT(1),
88 POWER_FLAGS_SKIP_OVER_DTIM_MSK = BIT(2), 92 POWER_FLAGS_SKIP_OVER_DTIM_MSK = BIT(2),
93 POWER_FLAGS_SNOOZE_ENA_MSK = BIT(5),
94 POWER_FLAGS_BT_SCO_ENA = BIT(8),
89 POWER_FLAGS_ADVANCE_PM_ENA_MSK = BIT(9), 95 POWER_FLAGS_ADVANCE_PM_ENA_MSK = BIT(9),
90 POWER_FLAGS_LPRX_ENA_MSK = BIT(11), 96 POWER_FLAGS_LPRX_ENA_MSK = BIT(11),
91}; 97};
@@ -93,7 +99,8 @@ enum iwl_power_flags {
93#define IWL_POWER_VEC_SIZE 5 99#define IWL_POWER_VEC_SIZE 5
94 100
95/** 101/**
96 * struct iwl_powertable_cmd - Power Table Command 102 * struct iwl_powertable_cmd - legacy power command. Beside old API support this
103 * is used also with a new power API for device wide power settings.
97 * POWER_TABLE_CMD = 0x77 (command, has simple generic response) 104 * POWER_TABLE_CMD = 0x77 (command, has simple generic response)
98 * 105 *
99 * @flags: Power table command flags from POWER_FLAGS_* 106 * @flags: Power table command flags from POWER_FLAGS_*
@@ -125,6 +132,72 @@ struct iwl_powertable_cmd {
125} __packed; 132} __packed;
126 133
127/** 134/**
135 * struct iwl_mac_power_cmd - New power command containing uAPSD support
136 * MAC_PM_POWER_TABLE = 0xA9 (command, has simple generic response)
137 * @id_and_color: MAC contex identifier
138 * @flags: Power table command flags from POWER_FLAGS_*
139 * @keep_alive_seconds: Keep alive period in seconds. Default - 25 sec.
140 * Minimum allowed:- 3 * DTIM. Keep alive period must be
141 * set regardless of power scheme or current power state.
142 * FW use this value also when PM is disabled.
143 * @rx_data_timeout: Minimum time (usec) from last Rx packet for AM to
144 * PSM transition - legacy PM
145 * @tx_data_timeout: Minimum time (usec) from last Tx packet for AM to
146 * PSM transition - legacy PM
147 * @sleep_interval: not in use
148 * @skip_dtim_periods: Number of DTIM periods to skip if Skip over DTIM flag
149 * is set. For example, if it is required to skip over
150 * one DTIM, this value need to be set to 2 (DTIM periods).
151 * @rx_data_timeout_uapsd: Minimum time (usec) from last Rx packet for AM to
152 * PSM transition - uAPSD
153 * @tx_data_timeout_uapsd: Minimum time (usec) from last Tx packet for AM to
154 * PSM transition - uAPSD
155 * @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled.
156 * Default: 80dbm
157 * @num_skip_dtim: Number of DTIMs to skip if Skip over DTIM flag is set
158 * @snooze_interval: TBD
159 * @snooze_window: TBD
160 * @snooze_step: TBD
161 * @qndp_tid: TID client shall use for uAPSD QNDP triggers
162 * @uapsd_ac_flags: Set trigger-enabled and delivery-enabled indication for
163 * each corresponding AC.
164 * Use IEEE80211_WMM_IE_STA_QOSINFO_AC* for correct values.
165 * @uapsd_max_sp: Use IEEE80211_WMM_IE_STA_QOSINFO_SP_* for correct
166 * values.
167 * @heavy_traffic_thr_tx_pkts: TX threshold measured in number of packets
168 * @heavy_traffic_thr_rx_pkts: RX threshold measured in number of packets
169 * @heavy_traffic_thr_tx_load: TX threshold measured in load's percentage
170 * @heavy_traffic_thr_rx_load: RX threshold measured in load's percentage
171 * @limited_ps_threshold:
172*/
173struct iwl_mac_power_cmd {
174 /* CONTEXT_DESC_API_T_VER_1 */
175 __le32 id_and_color;
176
177 /* CLIENT_PM_POWER_TABLE_S_VER_1 */
178 __le16 flags;
179 __le16 keep_alive_seconds;
180 __le32 rx_data_timeout;
181 __le32 tx_data_timeout;
182 __le32 rx_data_timeout_uapsd;
183 __le32 tx_data_timeout_uapsd;
184 u8 lprx_rssi_threshold;
185 u8 skip_dtim_periods;
186 __le16 snooze_interval;
187 __le16 snooze_window;
188 u8 snooze_step;
189 u8 qndp_tid;
190 u8 uapsd_ac_flags;
191 u8 uapsd_max_sp;
192 u8 heavy_traffic_threshold_tx_packets;
193 u8 heavy_traffic_threshold_rx_packets;
194 u8 heavy_traffic_threshold_tx_percentage;
195 u8 heavy_traffic_threshold_rx_percentage;
196 u8 limited_ps_threshold;
197 u8 reserved;
198} __packed;
199
200/**
128 * struct iwl_beacon_filter_cmd 201 * struct iwl_beacon_filter_cmd
129 * REPLY_BEACON_FILTERING_CMD = 0xd2 (command) 202 * REPLY_BEACON_FILTERING_CMD = 0xd2 (command)
130 * @id_and_color: MAC contex identifier 203 * @id_and_color: MAC contex identifier
@@ -143,11 +216,21 @@ struct iwl_powertable_cmd {
143 * calculated for current beacon is less than the threshold, use 216 * calculated for current beacon is less than the threshold, use
144 * Roaming Energy Delta Threshold, otherwise use normal Energy Delta 217 * Roaming Energy Delta Threshold, otherwise use normal Energy Delta
145 * Threshold. Typical energy threshold is -72dBm. 218 * Threshold. Typical energy threshold is -72dBm.
146 * @bf_temperature_delta: Send Beacon to driver if delta in temperature values 219 * @bf_temp_threshold: This threshold determines the type of temperature
147 * calculated for this and the last passed beacon is greater than this 220 * filtering (Slow or Fast) that is selected (Units are in Celsuis):
148 * threshold. Zero value means that the temperature changeis ignored for 221 * If the current temperature is above this threshold - Fast filter
222 * will be used, If the current temperature is below this threshold -
223 * Slow filter will be used.
224 * @bf_temp_fast_filter: Send Beacon to driver if delta in temperature values
225 * calculated for this and the last passed beacon is greater than this
226 * threshold. Zero value means that the temperature change is ignored for
149 * beacon filtering; beacons will not be forced to be sent to driver 227 * beacon filtering; beacons will not be forced to be sent to driver
150 * regardless of whether its temerature has been changed. 228 * regardless of whether its temerature has been changed.
229 * @bf_temp_slow_filter: Send Beacon to driver if delta in temperature values
230 * calculated for this and the last passed beacon is greater than this
231 * threshold. Zero value means that the temperature change is ignored for
232 * beacon filtering; beacons will not be forced to be sent to driver
233 * regardless of whether its temerature has been changed.
151 * @bf_enable_beacon_filter: 1, beacon filtering is enabled; 0, disabled. 234 * @bf_enable_beacon_filter: 1, beacon filtering is enabled; 0, disabled.
152 * @bf_filter_escape_timer: Send beacons to to driver if no beacons were passed 235 * @bf_filter_escape_timer: Send beacons to to driver if no beacons were passed
153 * for a specific period of time. Units: Beacons. 236 * for a specific period of time. Units: Beacons.
@@ -156,17 +239,17 @@ struct iwl_powertable_cmd {
156 * @ba_enable_beacon_abort: 1, beacon abort is enabled; 0, disabled. 239 * @ba_enable_beacon_abort: 1, beacon abort is enabled; 0, disabled.
157 */ 240 */
158struct iwl_beacon_filter_cmd { 241struct iwl_beacon_filter_cmd {
159 u8 bf_energy_delta; 242 __le32 bf_energy_delta;
160 u8 bf_roaming_energy_delta; 243 __le32 bf_roaming_energy_delta;
161 u8 bf_roaming_state; 244 __le32 bf_roaming_state;
162 u8 bf_temperature_delta; 245 __le32 bf_temp_threshold;
163 u8 bf_enable_beacon_filter; 246 __le32 bf_temp_fast_filter;
164 u8 bf_debug_flag; 247 __le32 bf_temp_slow_filter;
165 __le16 reserved1; 248 __le32 bf_enable_beacon_filter;
249 __le32 bf_debug_flag;
166 __le32 bf_escape_timer; 250 __le32 bf_escape_timer;
167 __le32 ba_escape_timer; 251 __le32 ba_escape_timer;
168 u8 ba_enable_beacon_abort; 252 __le32 ba_enable_beacon_abort;
169 u8 reserved2[3];
170} __packed; 253} __packed;
171 254
172/* Beacon filtering and beacon abort */ 255/* Beacon filtering and beacon abort */
@@ -182,9 +265,17 @@ struct iwl_beacon_filter_cmd {
182#define IWL_BF_ROAMING_STATE_MAX 255 265#define IWL_BF_ROAMING_STATE_MAX 255
183#define IWL_BF_ROAMING_STATE_MIN 0 266#define IWL_BF_ROAMING_STATE_MIN 0
184 267
185#define IWL_BF_TEMPERATURE_DELTA_DEFAULT 5 268#define IWL_BF_TEMP_THRESHOLD_DEFAULT 112
186#define IWL_BF_TEMPERATURE_DELTA_MAX 255 269#define IWL_BF_TEMP_THRESHOLD_MAX 255
187#define IWL_BF_TEMPERATURE_DELTA_MIN 0 270#define IWL_BF_TEMP_THRESHOLD_MIN 0
271
272#define IWL_BF_TEMP_FAST_FILTER_DEFAULT 1
273#define IWL_BF_TEMP_FAST_FILTER_MAX 255
274#define IWL_BF_TEMP_FAST_FILTER_MIN 0
275
276#define IWL_BF_TEMP_SLOW_FILTER_DEFAULT 5
277#define IWL_BF_TEMP_SLOW_FILTER_MAX 255
278#define IWL_BF_TEMP_SLOW_FILTER_MIN 0
188 279
189#define IWL_BF_ENABLE_BEACON_FILTER_DEFAULT 1 280#define IWL_BF_ENABLE_BEACON_FILTER_DEFAULT 1
190 281
@@ -194,19 +285,23 @@ struct iwl_beacon_filter_cmd {
194#define IWL_BF_ESCAPE_TIMER_MAX 1024 285#define IWL_BF_ESCAPE_TIMER_MAX 1024
195#define IWL_BF_ESCAPE_TIMER_MIN 0 286#define IWL_BF_ESCAPE_TIMER_MIN 0
196 287
197#define IWL_BA_ESCAPE_TIMER_DEFAULT 3 288#define IWL_BA_ESCAPE_TIMER_DEFAULT 6
289#define IWL_BA_ESCAPE_TIMER_D3 6
198#define IWL_BA_ESCAPE_TIMER_MAX 1024 290#define IWL_BA_ESCAPE_TIMER_MAX 1024
199#define IWL_BA_ESCAPE_TIMER_MIN 0 291#define IWL_BA_ESCAPE_TIMER_MIN 0
200 292
201#define IWL_BA_ENABLE_BEACON_ABORT_DEFAULT 1 293#define IWL_BA_ENABLE_BEACON_ABORT_DEFAULT 1
202 294
203#define IWL_BF_CMD_CONFIG_DEFAULTS \ 295#define IWL_BF_CMD_CONFIG_DEFAULTS \
204 .bf_energy_delta = IWL_BF_ENERGY_DELTA_DEFAULT, \ 296 .bf_energy_delta = cpu_to_le32(IWL_BF_ENERGY_DELTA_DEFAULT), \
205 .bf_roaming_energy_delta = IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT, \ 297 .bf_roaming_energy_delta = \
206 .bf_roaming_state = IWL_BF_ROAMING_STATE_DEFAULT, \ 298 cpu_to_le32(IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT), \
207 .bf_temperature_delta = IWL_BF_TEMPERATURE_DELTA_DEFAULT, \ 299 .bf_roaming_state = cpu_to_le32(IWL_BF_ROAMING_STATE_DEFAULT), \
208 .bf_debug_flag = IWL_BF_DEBUG_FLAG_DEFAULT, \ 300 .bf_temp_threshold = cpu_to_le32(IWL_BF_TEMP_THRESHOLD_DEFAULT), \
209 .bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT), \ 301 .bf_temp_fast_filter = cpu_to_le32(IWL_BF_TEMP_FAST_FILTER_DEFAULT), \
302 .bf_temp_slow_filter = cpu_to_le32(IWL_BF_TEMP_SLOW_FILTER_DEFAULT), \
303 .bf_debug_flag = cpu_to_le32(IWL_BF_DEBUG_FLAG_DEFAULT), \
304 .bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT), \
210 .ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT) 305 .ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT)
211 306
212#endif 307#endif
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
index b60d14151721..c33ff8e61f4f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
@@ -138,6 +138,8 @@ struct iwl_ssid_ie {
138 *@SCAN_FLAGS_DELAYED_SCAN_LOWBAND: 138 *@SCAN_FLAGS_DELAYED_SCAN_LOWBAND:
139 *@SCAN_FLAGS_DELAYED_SCAN_HIGHBAND: 139 *@SCAN_FLAGS_DELAYED_SCAN_HIGHBAND:
140 *@SCAN_FLAGS_FRAGMENTED_SCAN: 140 *@SCAN_FLAGS_FRAGMENTED_SCAN:
141 *@SCAN_FLAGS_PASSIVE2ACTIVE: use active scan on channels that was active
142 * in the past hour, even if they are marked as passive.
141 */ 143 */
142enum iwl_scan_flags { 144enum iwl_scan_flags {
143 SCAN_FLAGS_PERIODIC_SCAN = BIT(0), 145 SCAN_FLAGS_PERIODIC_SCAN = BIT(0),
@@ -145,6 +147,7 @@ enum iwl_scan_flags {
145 SCAN_FLAGS_DELAYED_SCAN_LOWBAND = BIT(2), 147 SCAN_FLAGS_DELAYED_SCAN_LOWBAND = BIT(2),
146 SCAN_FLAGS_DELAYED_SCAN_HIGHBAND = BIT(3), 148 SCAN_FLAGS_DELAYED_SCAN_HIGHBAND = BIT(3),
147 SCAN_FLAGS_FRAGMENTED_SCAN = BIT(4), 149 SCAN_FLAGS_FRAGMENTED_SCAN = BIT(4),
150 SCAN_FLAGS_PASSIVE2ACTIVE = BIT(5),
148}; 151};
149 152
150/** 153/**
@@ -179,7 +182,7 @@ enum iwl_scan_type {
179 * @quiet_time: in msecs, dwell this time for active scan on quiet channels 182 * @quiet_time: in msecs, dwell this time for active scan on quiet channels
180 * @quiet_plcp_th: quiet PLCP threshold (channel is quiet if less than 183 * @quiet_plcp_th: quiet PLCP threshold (channel is quiet if less than
181 * this number of packets were received (typically 1) 184 * this number of packets were received (typically 1)
182 * @passive2active: is auto switching from passive to active allowed (0 or 1) 185 * @passive2active: is auto switching from passive to active during scan allowed
183 * @rxchain_sel_flags: RXON_RX_CHAIN_* 186 * @rxchain_sel_flags: RXON_RX_CHAIN_*
184 * @max_out_time: in usecs, max out of serving channel time 187 * @max_out_time: in usecs, max out of serving channel time
185 * @suspend_time: how long to pause scan when returning to service channel: 188 * @suspend_time: how long to pause scan when returning to service channel:
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h
index 700cce731770..d606197bde8f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h
@@ -91,7 +91,6 @@
91 * @TX_CMD_FLG_RESP_TO_DRV: zero this if the response should go only to FW 91 * @TX_CMD_FLG_RESP_TO_DRV: zero this if the response should go only to FW
92 * @TX_CMD_FLG_CCMP_AGG: this frame uses CCMP for aggregation acceleration 92 * @TX_CMD_FLG_CCMP_AGG: this frame uses CCMP for aggregation acceleration
93 * @TX_CMD_FLG_TKIP_MIC_DONE: FW already performed TKIP MIC calculation 93 * @TX_CMD_FLG_TKIP_MIC_DONE: FW already performed TKIP MIC calculation
94 * @TX_CMD_FLG_CTS_ONLY: send CTS only, no data after that
95 * @TX_CMD_FLG_DUR: disable duration overwriting used in PS-Poll Assoc-id 94 * @TX_CMD_FLG_DUR: disable duration overwriting used in PS-Poll Assoc-id
96 * @TX_CMD_FLG_FW_DROP: FW should mark frame to be dropped 95 * @TX_CMD_FLG_FW_DROP: FW should mark frame to be dropped
97 * @TX_CMD_FLG_EXEC_PAPD: execute PAPD 96 * @TX_CMD_FLG_EXEC_PAPD: execute PAPD
@@ -120,7 +119,6 @@ enum iwl_tx_flags {
120 TX_CMD_FLG_RESP_TO_DRV = BIT(21), 119 TX_CMD_FLG_RESP_TO_DRV = BIT(21),
121 TX_CMD_FLG_CCMP_AGG = BIT(22), 120 TX_CMD_FLG_CCMP_AGG = BIT(22),
122 TX_CMD_FLG_TKIP_MIC_DONE = BIT(23), 121 TX_CMD_FLG_TKIP_MIC_DONE = BIT(23),
123 TX_CMD_FLG_CTS_ONLY = BIT(24),
124 TX_CMD_FLG_DUR = BIT(25), 122 TX_CMD_FLG_DUR = BIT(25),
125 TX_CMD_FLG_FW_DROP = BIT(26), 123 TX_CMD_FLG_FW_DROP = BIT(26),
126 TX_CMD_FLG_EXEC_PAPD = BIT(27), 124 TX_CMD_FLG_EXEC_PAPD = BIT(27),
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index cbfb3beae783..55854a309f94 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -136,7 +136,7 @@ enum {
136 CALIB_RES_NOTIF_PHY_DB = 0x6b, 136 CALIB_RES_NOTIF_PHY_DB = 0x6b,
137 /* PHY_DB_CMD = 0x6c, */ 137 /* PHY_DB_CMD = 0x6c, */
138 138
139 /* Power */ 139 /* Power - legacy power table command */
140 POWER_TABLE_CMD = 0x77, 140 POWER_TABLE_CMD = 0x77,
141 141
142 /* Thermal Throttling*/ 142 /* Thermal Throttling*/
@@ -159,6 +159,7 @@ enum {
159 TX_ANT_CONFIGURATION_CMD = 0x98, 159 TX_ANT_CONFIGURATION_CMD = 0x98,
160 BT_CONFIG = 0x9b, 160 BT_CONFIG = 0x9b,
161 STATISTICS_NOTIFICATION = 0x9d, 161 STATISTICS_NOTIFICATION = 0x9d,
162 REDUCE_TX_POWER_CMD = 0x9f,
162 163
163 /* RF-KILL commands and notifications */ 164 /* RF-KILL commands and notifications */
164 CARD_STATE_CMD = 0xa0, 165 CARD_STATE_CMD = 0xa0,
@@ -166,6 +167,9 @@ enum {
166 167
167 MISSED_BEACONS_NOTIFICATION = 0xa2, 168 MISSED_BEACONS_NOTIFICATION = 0xa2,
168 169
170 /* Power - new power table command */
171 MAC_PM_POWER_TABLE = 0xa9,
172
169 REPLY_RX_PHY_CMD = 0xc0, 173 REPLY_RX_PHY_CMD = 0xc0,
170 REPLY_RX_MPDU_CMD = 0xc1, 174 REPLY_RX_MPDU_CMD = 0xc1,
171 BA_NOTIF = 0xc5, 175 BA_NOTIF = 0xc5,
@@ -223,6 +227,19 @@ struct iwl_tx_ant_cfg_cmd {
223 __le32 valid; 227 __le32 valid;
224} __packed; 228} __packed;
225 229
230/**
231 * struct iwl_reduce_tx_power_cmd - TX power reduction command
232 * REDUCE_TX_POWER_CMD = 0x9f
233 * @flags: (reserved for future implementation)
234 * @mac_context_id: id of the mac ctx for which we are reducing TX power.
235 * @pwr_restriction: TX power restriction in dBms.
236 */
237struct iwl_reduce_tx_power_cmd {
238 u8 flags;
239 u8 mac_context_id;
240 __le16 pwr_restriction;
241} __packed; /* TX_REDUCED_POWER_API_S_VER_1 */
242
226/* 243/*
227 * Calibration control struct. 244 * Calibration control struct.
228 * Sent as part of the phy configuration command. 245 * Sent as part of the phy configuration command.
@@ -765,6 +782,14 @@ struct iwl_phy_context_cmd {
765} __packed; /* PHY_CONTEXT_CMD_API_VER_1 */ 782} __packed; /* PHY_CONTEXT_CMD_API_VER_1 */
766 783
767#define IWL_RX_INFO_PHY_CNT 8 784#define IWL_RX_INFO_PHY_CNT 8
785#define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1
786#define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff
787#define IWL_RX_INFO_ENERGY_ANT_B_MSK 0x0000ff00
788#define IWL_RX_INFO_ENERGY_ANT_C_MSK 0x00ff0000
789#define IWL_RX_INFO_ENERGY_ANT_A_POS 0
790#define IWL_RX_INFO_ENERGY_ANT_B_POS 8
791#define IWL_RX_INFO_ENERGY_ANT_C_POS 16
792
768#define IWL_RX_INFO_AGC_IDX 1 793#define IWL_RX_INFO_AGC_IDX 1
769#define IWL_RX_INFO_RSSI_AB_IDX 2 794#define IWL_RX_INFO_RSSI_AB_IDX 2
770#define IWL_OFDM_AGC_A_MSK 0x0000007f 795#define IWL_OFDM_AGC_A_MSK 0x0000007f
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
index cd7c0032cc58..c76299a3a1e0 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -78,22 +78,6 @@
78 78
79#define UCODE_VALID_OK cpu_to_le32(0x1) 79#define UCODE_VALID_OK cpu_to_le32(0x1)
80 80
81/* Default calibration values for WkP - set to INIT image w/o running */
82static const u8 wkp_calib_values_rx_iq_skew[] = { 0x00, 0x00, 0x01, 0x00 };
83static const u8 wkp_calib_values_tx_iq_skew[] = { 0x01, 0x00, 0x00, 0x00 };
84
85struct iwl_calib_default_data {
86 u16 size;
87 void *data;
88};
89
90#define CALIB_SIZE_N_DATA(_buf) {.size = sizeof(_buf), .data = &_buf}
91
92static const struct iwl_calib_default_data wkp_calib_default_data[12] = {
93 [9] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq_skew),
94 [11] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq_skew),
95};
96
97struct iwl_mvm_alive_data { 81struct iwl_mvm_alive_data {
98 bool valid; 82 bool valid;
99 u32 scd_base_addr; 83 u32 scd_base_addr;
@@ -248,40 +232,6 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
248 sizeof(phy_cfg_cmd), &phy_cfg_cmd); 232 sizeof(phy_cfg_cmd), &phy_cfg_cmd);
249} 233}
250 234
251static int iwl_set_default_calibrations(struct iwl_mvm *mvm)
252{
253 u8 cmd_raw[16]; /* holds the variable size commands */
254 struct iwl_set_calib_default_cmd *cmd =
255 (struct iwl_set_calib_default_cmd *)cmd_raw;
256 int ret, i;
257
258 /* Setting default values for calibrations we don't run */
259 for (i = 0; i < ARRAY_SIZE(wkp_calib_default_data); i++) {
260 u16 cmd_len;
261
262 if (wkp_calib_default_data[i].size == 0)
263 continue;
264
265 memset(cmd_raw, 0, sizeof(cmd_raw));
266 cmd_len = wkp_calib_default_data[i].size + sizeof(cmd);
267 cmd->calib_index = cpu_to_le16(i);
268 cmd->length = cpu_to_le16(wkp_calib_default_data[i].size);
269 if (WARN_ONCE(cmd_len > sizeof(cmd_raw),
270 "Need to enlarge cmd_raw to %d\n", cmd_len))
271 break;
272 memcpy(cmd->data, wkp_calib_default_data[i].data,
273 wkp_calib_default_data[i].size);
274 ret = iwl_mvm_send_cmd_pdu(mvm, SET_CALIB_DEFAULT_CMD, 0,
275 sizeof(*cmd) +
276 wkp_calib_default_data[i].size,
277 cmd);
278 if (ret)
279 return ret;
280 }
281
282 return 0;
283}
284
285int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) 235int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
286{ 236{
287 struct iwl_notification_wait calib_wait; 237 struct iwl_notification_wait calib_wait;
@@ -342,11 +292,6 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
342 if (ret) 292 if (ret)
343 goto error; 293 goto error;
344 294
345 /* need to set default values */
346 ret = iwl_set_default_calibrations(mvm);
347 if (ret)
348 goto error;
349
350 /* 295 /*
351 * Send phy configurations command to init uCode 296 * Send phy configurations command to init uCode
352 * to start the 16.0 uCode init image internal calibrations. 297 * to start the 16.0 uCode init image internal calibrations.
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
index 94aae9c8562c..5fe23a5ea9b6 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
@@ -264,7 +264,8 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm,
264 return 0; 264 return 0;
265 265
266 /* Therefore, in recovery, we can't get here */ 266 /* Therefore, in recovery, we can't get here */
267 WARN_ON_ONCE(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)); 267 if (WARN_ON_ONCE(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
268 return -EBUSY;
268 269
269 mvmvif->id = find_first_bit(data.available_mac_ids, 270 mvmvif->id = find_first_bit(data.available_mac_ids,
270 NUM_MAC_INDEX_DRIVER); 271 NUM_MAC_INDEX_DRIVER);
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 1eedc424051c..fc61b274780c 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -153,7 +153,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
153 IEEE80211_HW_SUPPORTS_DYNAMIC_PS | 153 IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
154 IEEE80211_HW_AMPDU_AGGREGATION | 154 IEEE80211_HW_AMPDU_AGGREGATION |
155 IEEE80211_HW_TIMING_BEACON_ONLY | 155 IEEE80211_HW_TIMING_BEACON_ONLY |
156 IEEE80211_HW_CONNECTION_MONITOR; 156 IEEE80211_HW_CONNECTION_MONITOR |
157 IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
158 IEEE80211_HW_SUPPORTS_STATIC_SMPS;
157 159
158 hw->queues = IWL_MVM_FIRST_AGG_QUEUE; 160 hw->queues = IWL_MVM_FIRST_AGG_QUEUE;
159 hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE; 161 hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE;
@@ -531,6 +533,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
531 goto out_release; 533 goto out_release;
532 } 534 }
533 535
536 iwl_mvm_vif_dbgfs_register(mvm, vif);
534 goto out_unlock; 537 goto out_unlock;
535 } 538 }
536 539
@@ -567,7 +570,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
567 570
568 /* beacon filtering */ 571 /* beacon filtering */
569 if (!mvm->bf_allowed_vif && 572 if (!mvm->bf_allowed_vif &&
570 vif->type == NL80211_IFTYPE_STATION && !vif->p2p){ 573 vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
574 mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BF_UPDATED){
571 mvm->bf_allowed_vif = mvmvif; 575 mvm->bf_allowed_vif = mvmvif;
572 vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; 576 vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
573 } 577 }
@@ -719,6 +723,20 @@ out_release:
719 mutex_unlock(&mvm->mutex); 723 mutex_unlock(&mvm->mutex);
720} 724}
721 725
726static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
727 s8 tx_power)
728{
729 /* FW is in charge of regulatory enforcement */
730 struct iwl_reduce_tx_power_cmd reduce_txpwr_cmd = {
731 .mac_context_id = iwl_mvm_vif_from_mac80211(vif)->id,
732 .pwr_restriction = cpu_to_le16(tx_power),
733 };
734
735 return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, CMD_SYNC,
736 sizeof(reduce_txpwr_cmd),
737 &reduce_txpwr_cmd);
738}
739
722static int iwl_mvm_mac_config(struct ieee80211_hw *hw, u32 changed) 740static int iwl_mvm_mac_config(struct ieee80211_hw *hw, u32 changed)
723{ 741{
724 return 0; 742 return 0;
@@ -766,7 +784,6 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
766 IWL_ERR(mvm, "failed to update quotas\n"); 784 IWL_ERR(mvm, "failed to update quotas\n");
767 return; 785 return;
768 } 786 }
769 iwl_mvm_bt_coex_vif_assoc(mvm, vif);
770 iwl_mvm_configure_mcast_filter(mvm, vif); 787 iwl_mvm_configure_mcast_filter(mvm, vif);
771 } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) { 788 } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) {
772 /* remove AP station now that the MAC is unassoc */ 789 /* remove AP station now that the MAC is unassoc */
@@ -779,9 +796,15 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
779 if (ret) 796 if (ret)
780 IWL_ERR(mvm, "failed to update quotas\n"); 797 IWL_ERR(mvm, "failed to update quotas\n");
781 } 798 }
782 ret = iwl_mvm_power_update_mode(mvm, vif); 799 if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD)) {
783 if (ret) 800 /* Workaround for FW bug, otherwise FW disables device
784 IWL_ERR(mvm, "failed to update power mode\n"); 801 * power save upon disassociation
802 */
803 ret = iwl_mvm_power_update_mode(mvm, vif);
804 if (ret)
805 IWL_ERR(mvm, "failed to update power mode\n");
806 }
807 iwl_mvm_bt_coex_vif_assoc(mvm, vif);
785 } else if (changes & BSS_CHANGED_BEACON_INFO) { 808 } else if (changes & BSS_CHANGED_BEACON_INFO) {
786 /* 809 /*
787 * We received a beacon _after_ association so 810 * We received a beacon _after_ association so
@@ -794,6 +817,11 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
794 if (ret) 817 if (ret)
795 IWL_ERR(mvm, "failed to update power mode\n"); 818 IWL_ERR(mvm, "failed to update power mode\n");
796 } 819 }
820 if (changes & BSS_CHANGED_TXPOWER) {
821 IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d\n",
822 bss_conf->txpower);
823 iwl_mvm_set_tx_power(mvm, vif, bss_conf->txpower);
824 }
797} 825}
798 826
799static int iwl_mvm_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) 827static int iwl_mvm_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 420e82d379d9..29bebae7f003 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -76,6 +76,7 @@
76#include "iwl-trans.h" 76#include "iwl-trans.h"
77#include "sta.h" 77#include "sta.h"
78#include "fw-api.h" 78#include "fw-api.h"
79#include "constants.h"
79 80
80#define IWL_INVALID_MAC80211_QUEUE 0xff 81#define IWL_INVALID_MAC80211_QUEUE 0xff
81#define IWL_MVM_MAX_ADDRESSES 5 82#define IWL_MVM_MAX_ADDRESSES 5
@@ -91,6 +92,9 @@ enum iwl_mvm_tx_fifo {
91}; 92};
92 93
93extern struct ieee80211_ops iwl_mvm_hw_ops; 94extern struct ieee80211_ops iwl_mvm_hw_ops;
95extern const struct iwl_mvm_power_ops pm_legacy_ops;
96extern const struct iwl_mvm_power_ops pm_mac_ops;
97
94/** 98/**
95 * struct iwl_mvm_mod_params - module parameters for iwlmvm 99 * struct iwl_mvm_mod_params - module parameters for iwlmvm
96 * @init_dbg: if true, then the NIC won't be stopped if the INIT fw asserted. 100 * @init_dbg: if true, then the NIC won't be stopped if the INIT fw asserted.
@@ -150,6 +154,17 @@ enum iwl_power_scheme {
150 154
151#define IWL_CONN_MAX_LISTEN_INTERVAL 70 155#define IWL_CONN_MAX_LISTEN_INTERVAL 70
152 156
157struct iwl_mvm_power_ops {
158 int (*power_update_mode)(struct iwl_mvm *mvm,
159 struct ieee80211_vif *vif);
160 int (*power_disable)(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
161#ifdef CONFIG_IWLWIFI_DEBUGFS
162 int (*power_dbgfs_read)(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
163 char *buf, int bufsz);
164#endif
165};
166
167
153#ifdef CONFIG_IWLWIFI_DEBUGFS 168#ifdef CONFIG_IWLWIFI_DEBUGFS
154enum iwl_dbgfs_pm_mask { 169enum iwl_dbgfs_pm_mask {
155 MVM_DEBUGFS_PM_KEEP_ALIVE = BIT(0), 170 MVM_DEBUGFS_PM_KEEP_ALIVE = BIT(0),
@@ -163,7 +178,7 @@ enum iwl_dbgfs_pm_mask {
163}; 178};
164 179
165struct iwl_dbgfs_pm { 180struct iwl_dbgfs_pm {
166 u8 keep_alive_seconds; 181 u16 keep_alive_seconds;
167 u32 rx_data_timeout; 182 u32 rx_data_timeout;
168 u32 tx_data_timeout; 183 u32 tx_data_timeout;
169 bool skip_over_dtim; 184 bool skip_over_dtim;
@@ -180,24 +195,28 @@ enum iwl_dbgfs_bf_mask {
180 MVM_DEBUGFS_BF_ENERGY_DELTA = BIT(0), 195 MVM_DEBUGFS_BF_ENERGY_DELTA = BIT(0),
181 MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA = BIT(1), 196 MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA = BIT(1),
182 MVM_DEBUGFS_BF_ROAMING_STATE = BIT(2), 197 MVM_DEBUGFS_BF_ROAMING_STATE = BIT(2),
183 MVM_DEBUGFS_BF_TEMPERATURE_DELTA = BIT(3), 198 MVM_DEBUGFS_BF_TEMP_THRESHOLD = BIT(3),
184 MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER = BIT(4), 199 MVM_DEBUGFS_BF_TEMP_FAST_FILTER = BIT(4),
185 MVM_DEBUGFS_BF_DEBUG_FLAG = BIT(5), 200 MVM_DEBUGFS_BF_TEMP_SLOW_FILTER = BIT(5),
186 MVM_DEBUGFS_BF_ESCAPE_TIMER = BIT(6), 201 MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER = BIT(6),
187 MVM_DEBUGFS_BA_ESCAPE_TIMER = BIT(7), 202 MVM_DEBUGFS_BF_DEBUG_FLAG = BIT(7),
188 MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT = BIT(8), 203 MVM_DEBUGFS_BF_ESCAPE_TIMER = BIT(8),
204 MVM_DEBUGFS_BA_ESCAPE_TIMER = BIT(9),
205 MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT = BIT(10),
189}; 206};
190 207
191struct iwl_dbgfs_bf { 208struct iwl_dbgfs_bf {
192 u8 bf_energy_delta; 209 u32 bf_energy_delta;
193 u8 bf_roaming_energy_delta; 210 u32 bf_roaming_energy_delta;
194 u8 bf_roaming_state; 211 u32 bf_roaming_state;
195 u8 bf_temperature_delta; 212 u32 bf_temp_threshold;
196 u8 bf_enable_beacon_filter; 213 u32 bf_temp_fast_filter;
197 u8 bf_debug_flag; 214 u32 bf_temp_slow_filter;
215 u32 bf_enable_beacon_filter;
216 u32 bf_debug_flag;
198 u32 bf_escape_timer; 217 u32 bf_escape_timer;
199 u32 ba_escape_timer; 218 u32 ba_escape_timer;
200 u8 ba_enable_beacon_abort; 219 u32 ba_enable_beacon_abort;
201 int mask; 220 int mask;
202}; 221};
203#endif 222#endif
@@ -268,7 +287,7 @@ struct iwl_mvm_vif {
268 287
269#if IS_ENABLED(CONFIG_IPV6) 288#if IS_ENABLED(CONFIG_IPV6)
270 /* IPv6 addresses for WoWLAN */ 289 /* IPv6 addresses for WoWLAN */
271 struct in6_addr target_ipv6_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS]; 290 struct in6_addr target_ipv6_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX];
272 int num_target_ipv6_addrs; 291 int num_target_ipv6_addrs;
273#endif 292#endif
274#endif 293#endif
@@ -459,6 +478,9 @@ struct iwl_mvm {
459 */ 478 */
460 u8 vif_count; 479 u8 vif_count;
461 480
481 /* -1 for always, 0 for never, >0 for that many times */
482 s8 restart_fw;
483
462 struct led_classdev led; 484 struct led_classdev led;
463 485
464 struct ieee80211_vif *p2p_device_vif; 486 struct ieee80211_vif *p2p_device_vif;
@@ -482,6 +504,8 @@ struct iwl_mvm {
482 /* Thermal Throttling and CTkill */ 504 /* Thermal Throttling and CTkill */
483 struct iwl_mvm_tt_mgmt thermal_throttle; 505 struct iwl_mvm_tt_mgmt thermal_throttle;
484 s32 temperature; /* Celsius */ 506 s32 temperature; /* Celsius */
507
508 const struct iwl_mvm_power_ops *pm_ops;
485}; 509};
486 510
487/* Extract MVM priv from op_mode and _hw */ 511/* Extract MVM priv from op_mode and _hw */
@@ -525,6 +549,7 @@ int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,
525 enum ieee80211_band band); 549 enum ieee80211_band band);
526u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx); 550u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx);
527void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm); 551void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm);
552void iwl_mvm_dump_sram(struct iwl_mvm *mvm);
528u8 first_antenna(u8 mask); 553u8 first_antenna(u8 mask);
529u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx); 554u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx);
530 555
@@ -660,10 +685,26 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq,
660 u8 flags, bool init); 685 u8 flags, bool init);
661 686
662/* power managment */ 687/* power managment */
663int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif); 688static inline int iwl_mvm_power_update_mode(struct iwl_mvm *mvm,
664int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif); 689 struct ieee80211_vif *vif)
665void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 690{
666 struct iwl_powertable_cmd *cmd); 691 return mvm->pm_ops->power_update_mode(mvm, vif);
692}
693
694static inline int iwl_mvm_power_disable(struct iwl_mvm *mvm,
695 struct ieee80211_vif *vif)
696{
697 return mvm->pm_ops->power_disable(mvm, vif);
698}
699
700#ifdef CONFIG_IWLWIFI_DEBUGFS
701static inline int iwl_mvm_power_dbgfs_read(struct iwl_mvm *mvm,
702 struct ieee80211_vif *vif,
703 char *buf, int bufsz)
704{
705 return mvm->pm_ops->power_dbgfs_read(mvm, vif, buf, bufsz);
706}
707#endif
667 708
668int iwl_mvm_leds_init(struct iwl_mvm *mvm); 709int iwl_mvm_leds_init(struct iwl_mvm *mvm);
669void iwl_mvm_leds_exit(struct iwl_mvm *mvm); 710void iwl_mvm_leds_exit(struct iwl_mvm *mvm);
@@ -707,6 +748,10 @@ int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
707 struct ieee80211_vif *vif); 748 struct ieee80211_vif *vif);
708int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, 749int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
709 struct ieee80211_vif *vif); 750 struct ieee80211_vif *vif);
751int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
752 struct iwl_beacon_filter_cmd *cmd);
753int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm,
754 struct ieee80211_vif *vif, bool enable);
710 755
711/* SMPS */ 756/* SMPS */
712void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 757void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index af79a14063a9..65e5fb86291f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -275,6 +275,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
275 CMD(BEACON_NOTIFICATION), 275 CMD(BEACON_NOTIFICATION),
276 CMD(BEACON_TEMPLATE_CMD), 276 CMD(BEACON_TEMPLATE_CMD),
277 CMD(STATISTICS_NOTIFICATION), 277 CMD(STATISTICS_NOTIFICATION),
278 CMD(REDUCE_TX_POWER_CMD),
278 CMD(TX_ANT_CONFIGURATION_CMD), 279 CMD(TX_ANT_CONFIGURATION_CMD),
279 CMD(D3_CONFIG_CMD), 280 CMD(D3_CONFIG_CMD),
280 CMD(PROT_OFFLOAD_CONFIG_CMD), 281 CMD(PROT_OFFLOAD_CONFIG_CMD),
@@ -301,6 +302,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
301 CMD(MCAST_FILTER_CMD), 302 CMD(MCAST_FILTER_CMD),
302 CMD(REPLY_BEACON_FILTERING_CMD), 303 CMD(REPLY_BEACON_FILTERING_CMD),
303 CMD(REPLY_THERMAL_MNG_BACKOFF), 304 CMD(REPLY_THERMAL_MNG_BACKOFF),
305 CMD(MAC_PM_POWER_TABLE),
304}; 306};
305#undef CMD 307#undef CMD
306 308
@@ -340,6 +342,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
340 mvm->fw = fw; 342 mvm->fw = fw;
341 mvm->hw = hw; 343 mvm->hw = hw;
342 344
345 mvm->restart_fw = iwlwifi_mod_params.restart_fw ? -1 : 0;
346
343 mutex_init(&mvm->mutex); 347 mutex_init(&mvm->mutex);
344 spin_lock_init(&mvm->async_handlers_lock); 348 spin_lock_init(&mvm->async_handlers_lock);
345 INIT_LIST_HEAD(&mvm->time_event_list); 349 INIT_LIST_HEAD(&mvm->time_event_list);
@@ -431,6 +435,11 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
431 if (err) 435 if (err)
432 goto out_unregister; 436 goto out_unregister;
433 437
438 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD)
439 mvm->pm_ops = &pm_mac_ops;
440 else
441 mvm->pm_ops = &pm_legacy_ops;
442
434 return op_mode; 443 return op_mode;
435 444
436 out_unregister: 445 out_unregister:
@@ -638,6 +647,22 @@ static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
638 ieee80211_free_txskb(mvm->hw, skb); 647 ieee80211_free_txskb(mvm->hw, skb);
639} 648}
640 649
650struct iwl_mvm_reprobe {
651 struct device *dev;
652 struct work_struct work;
653};
654
655static void iwl_mvm_reprobe_wk(struct work_struct *wk)
656{
657 struct iwl_mvm_reprobe *reprobe;
658
659 reprobe = container_of(wk, struct iwl_mvm_reprobe, work);
660 if (device_reprobe(reprobe->dev))
661 dev_err(reprobe->dev, "reprobe failed!\n");
662 kfree(reprobe);
663 module_put(THIS_MODULE);
664}
665
641static void iwl_mvm_nic_restart(struct iwl_mvm *mvm) 666static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
642{ 667{
643 iwl_abort_notification_waits(&mvm->notif_wait); 668 iwl_abort_notification_waits(&mvm->notif_wait);
@@ -649,9 +674,30 @@ static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
649 * can't recover this since we're already half suspended. 674 * can't recover this since we're already half suspended.
650 */ 675 */
651 if (test_and_set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { 676 if (test_and_set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
652 IWL_ERR(mvm, "Firmware error during reconfiguration! Abort.\n"); 677 struct iwl_mvm_reprobe *reprobe;
653 } else if (mvm->cur_ucode == IWL_UCODE_REGULAR && 678
654 iwlwifi_mod_params.restart_fw) { 679 IWL_ERR(mvm,
680 "Firmware error during reconfiguration - reprobe!\n");
681
682 /*
683 * get a module reference to avoid doing this while unloading
684 * anyway and to avoid scheduling a work with code that's
685 * being removed.
686 */
687 if (!try_module_get(THIS_MODULE)) {
688 IWL_ERR(mvm, "Module is being unloaded - abort\n");
689 return;
690 }
691
692 reprobe = kzalloc(sizeof(*reprobe), GFP_ATOMIC);
693 if (!reprobe) {
694 module_put(THIS_MODULE);
695 return;
696 }
697 reprobe->dev = mvm->trans->dev;
698 INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk);
699 schedule_work(&reprobe->work);
700 } else if (mvm->cur_ucode == IWL_UCODE_REGULAR && mvm->restart_fw) {
655 /* 701 /*
656 * This is a bit racy, but worst case we tell mac80211 about 702 * This is a bit racy, but worst case we tell mac80211 about
657 * a stopped/aborted (sched) scan when that was already done 703 * a stopped/aborted (sched) scan when that was already done
@@ -669,6 +715,8 @@ static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
669 break; 715 break;
670 } 716 }
671 717
718 if (mvm->restart_fw > 0)
719 mvm->restart_fw--;
672 ieee80211_restart_hw(mvm->hw); 720 ieee80211_restart_hw(mvm->hw);
673 } 721 }
674} 722}
@@ -678,6 +726,8 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode)
678 struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); 726 struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
679 727
680 iwl_mvm_dump_nic_error_log(mvm); 728 iwl_mvm_dump_nic_error_log(mvm);
729 if (!mvm->restart_fw)
730 iwl_mvm_dump_sram(mvm);
681 731
682 iwl_mvm_nic_restart(mvm); 732 iwl_mvm_nic_restart(mvm);
683} 733}
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c
index e7ca965a89b8..4e7c9f245846 100644
--- a/drivers/net/wireless/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/iwlwifi/mvm/power.c
@@ -75,8 +75,8 @@
75 75
76#define POWER_KEEP_ALIVE_PERIOD_SEC 25 76#define POWER_KEEP_ALIVE_PERIOD_SEC 25
77 77
78static int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm, 78int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
79 struct iwl_beacon_filter_cmd *cmd) 79 struct iwl_beacon_filter_cmd *cmd)
80{ 80{
81 int ret; 81 int ret;
82 82
@@ -85,52 +85,60 @@ static int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
85 85
86 if (!ret) { 86 if (!ret) {
87 IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n", 87 IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n",
88 cmd->ba_enable_beacon_abort); 88 le32_to_cpu(cmd->ba_enable_beacon_abort));
89 IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n", 89 IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n",
90 cmd->ba_escape_timer); 90 le32_to_cpu(cmd->ba_escape_timer));
91 IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n", 91 IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n",
92 cmd->bf_debug_flag); 92 le32_to_cpu(cmd->bf_debug_flag));
93 IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n", 93 IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n",
94 cmd->bf_enable_beacon_filter); 94 le32_to_cpu(cmd->bf_enable_beacon_filter));
95 IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n", 95 IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n",
96 cmd->bf_energy_delta); 96 le32_to_cpu(cmd->bf_energy_delta));
97 IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n", 97 IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n",
98 cmd->bf_escape_timer); 98 le32_to_cpu(cmd->bf_escape_timer));
99 IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n", 99 IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n",
100 cmd->bf_roaming_energy_delta); 100 le32_to_cpu(cmd->bf_roaming_energy_delta));
101 IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n", 101 IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n",
102 cmd->bf_roaming_state); 102 le32_to_cpu(cmd->bf_roaming_state));
103 IWL_DEBUG_POWER(mvm, "bf_temperature_delta is: %d\n", 103 IWL_DEBUG_POWER(mvm, "bf_temp_threshold is: %d\n",
104 cmd->bf_temperature_delta); 104 le32_to_cpu(cmd->bf_temp_threshold));
105 IWL_DEBUG_POWER(mvm, "bf_temp_fast_filter is: %d\n",
106 le32_to_cpu(cmd->bf_temp_fast_filter));
107 IWL_DEBUG_POWER(mvm, "bf_temp_slow_filter is: %d\n",
108 le32_to_cpu(cmd->bf_temp_slow_filter));
105 } 109 }
106 return ret; 110 return ret;
107} 111}
108 112
109static int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm, 113int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm,
110 struct ieee80211_vif *vif, bool enable) 114 struct ieee80211_vif *vif, bool enable)
111{ 115{
112 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 116 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
113 struct iwl_beacon_filter_cmd cmd = { 117 struct iwl_beacon_filter_cmd cmd = {
114 IWL_BF_CMD_CONFIG_DEFAULTS, 118 IWL_BF_CMD_CONFIG_DEFAULTS,
115 .bf_enable_beacon_filter = 1, 119 .bf_enable_beacon_filter = cpu_to_le32(1),
116 .ba_enable_beacon_abort = enable, 120 .ba_enable_beacon_abort = cpu_to_le32(enable),
117 }; 121 };
118 122
119 if (!mvmvif->bf_enabled) 123 if (!mvmvif->bf_enabled)
120 return 0; 124 return 0;
121 125
126 if (mvm->cur_ucode == IWL_UCODE_WOWLAN)
127 cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3);
128
122 iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); 129 iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
123 return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); 130 return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
124} 131}
125 132
126static void iwl_mvm_power_log(struct iwl_mvm *mvm, 133static void iwl_mvm_power_log(struct iwl_mvm *mvm,
127 struct iwl_powertable_cmd *cmd) 134 struct iwl_mac_power_cmd *cmd)
128{ 135{
129 IWL_DEBUG_POWER(mvm, 136 IWL_DEBUG_POWER(mvm,
130 "Sending power table command for power level %d, flags = 0x%X\n", 137 "Sending power table command on mac id 0x%X for power level %d, flags = 0x%X\n",
131 iwlmvm_mod_params.power_scheme, 138 cmd->id_and_color, iwlmvm_mod_params.power_scheme,
132 le16_to_cpu(cmd->flags)); 139 le16_to_cpu(cmd->flags));
133 IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n", cmd->keep_alive_seconds); 140 IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n",
141 le16_to_cpu(cmd->keep_alive_seconds));
134 142
135 if (cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) { 143 if (cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
136 IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n", 144 IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n",
@@ -139,15 +147,16 @@ static void iwl_mvm_power_log(struct iwl_mvm *mvm,
139 le32_to_cpu(cmd->tx_data_timeout)); 147 le32_to_cpu(cmd->tx_data_timeout));
140 if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) 148 if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK))
141 IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n", 149 IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n",
142 le32_to_cpu(cmd->skip_dtim_periods)); 150 cmd->skip_dtim_periods);
143 if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK)) 151 if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
144 IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n", 152 IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
145 le32_to_cpu(cmd->lprx_rssi_threshold)); 153 cmd->lprx_rssi_threshold);
146 } 154 }
147} 155}
148 156
149void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 157static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
150 struct iwl_powertable_cmd *cmd) 158 struct ieee80211_vif *vif,
159 struct iwl_mac_power_cmd *cmd)
151{ 160{
152 struct ieee80211_hw *hw = mvm->hw; 161 struct ieee80211_hw *hw = mvm->hw;
153 struct ieee80211_chanctx_conf *chanctx_conf; 162 struct ieee80211_chanctx_conf *chanctx_conf;
@@ -158,19 +167,26 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
158 struct iwl_mvm_vif *mvmvif __maybe_unused = 167 struct iwl_mvm_vif *mvmvif __maybe_unused =
159 iwl_mvm_vif_from_mac80211(vif); 168 iwl_mvm_vif_from_mac80211(vif);
160 169
170 cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
171 mvmvif->color));
172 dtimper = hw->conf.ps_dtim_period ?: 1;
173
161 /* 174 /*
162 * Regardless of power management state the driver must set 175 * Regardless of power management state the driver must set
163 * keep alive period. FW will use it for sending keep alive NDPs 176 * keep alive period. FW will use it for sending keep alive NDPs
164 * immediately after association. 177 * immediately after association. Check that keep alive period
178 * is at least 3 * DTIM
165 */ 179 */
166 cmd->keep_alive_seconds = POWER_KEEP_ALIVE_PERIOD_SEC; 180 dtimper_msec = dtimper * vif->bss_conf.beacon_int;
181 keep_alive = max_t(int, 3 * dtimper_msec,
182 MSEC_PER_SEC * POWER_KEEP_ALIVE_PERIOD_SEC);
183 keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
184 cmd->keep_alive_seconds = cpu_to_le16(keep_alive);
167 185
168 if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) 186 if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
169 return; 187 return;
170 188
171 cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); 189 cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
172 if (!vif->bss_conf.assoc)
173 cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
174 190
175#ifdef CONFIG_IWLWIFI_DEBUGFS 191#ifdef CONFIG_IWLWIFI_DEBUGFS
176 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF && 192 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF &&
@@ -186,12 +202,9 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
186 (vif->bss_conf.beacon_rate->bitrate == 10 || 202 (vif->bss_conf.beacon_rate->bitrate == 10 ||
187 vif->bss_conf.beacon_rate->bitrate == 60)) { 203 vif->bss_conf.beacon_rate->bitrate == 60)) {
188 cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK); 204 cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
189 cmd->lprx_rssi_threshold = 205 cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD;
190 cpu_to_le32(POWER_LPRX_RSSI_THRESHOLD);
191 } 206 }
192 207
193 dtimper = hw->conf.ps_dtim_period ?: 1;
194
195 /* Check if radar detection is required on current channel */ 208 /* Check if radar detection is required on current channel */
196 rcu_read_lock(); 209 rcu_read_lock();
197 chanctx_conf = rcu_dereference(vif->chanctx_conf); 210 chanctx_conf = rcu_dereference(vif->chanctx_conf);
@@ -207,27 +220,25 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
207 (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP || 220 (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP ||
208 mvm->cur_ucode == IWL_UCODE_WOWLAN)) { 221 mvm->cur_ucode == IWL_UCODE_WOWLAN)) {
209 cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); 222 cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
210 cmd->skip_dtim_periods = cpu_to_le32(3); 223 cmd->skip_dtim_periods = 3;
211 } 224 }
212 225
213 /* Check that keep alive period is at least 3 * DTIM */
214 dtimper_msec = dtimper * vif->bss_conf.beacon_int;
215 keep_alive = max_t(int, 3 * dtimper_msec,
216 MSEC_PER_SEC * cmd->keep_alive_seconds);
217 keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
218 cmd->keep_alive_seconds = keep_alive;
219
220 if (mvm->cur_ucode != IWL_UCODE_WOWLAN) { 226 if (mvm->cur_ucode != IWL_UCODE_WOWLAN) {
221 cmd->rx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC); 227 cmd->rx_data_timeout =
222 cmd->tx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC); 228 cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT);
229 cmd->tx_data_timeout =
230 cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT);
223 } else { 231 } else {
224 cmd->rx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC); 232 cmd->rx_data_timeout =
225 cmd->tx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC); 233 cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
234 cmd->tx_data_timeout =
235 cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
226 } 236 }
227 237
228#ifdef CONFIG_IWLWIFI_DEBUGFS 238#ifdef CONFIG_IWLWIFI_DEBUGFS
229 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE) 239 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE)
230 cmd->keep_alive_seconds = mvmvif->dbgfs_pm.keep_alive_seconds; 240 cmd->keep_alive_seconds =
241 cpu_to_le16(mvmvif->dbgfs_pm.keep_alive_seconds);
231 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) { 242 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) {
232 if (mvmvif->dbgfs_pm.skip_over_dtim) 243 if (mvmvif->dbgfs_pm.skip_over_dtim)
233 cmd->flags |= 244 cmd->flags |=
@@ -243,8 +254,7 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
243 cmd->tx_data_timeout = 254 cmd->tx_data_timeout =
244 cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout); 255 cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout);
245 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS) 256 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS)
246 cmd->skip_dtim_periods = 257 cmd->skip_dtim_periods = mvmvif->dbgfs_pm.skip_dtim_periods;
247 cpu_to_le32(mvmvif->dbgfs_pm.skip_dtim_periods);
248 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) { 258 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) {
249 if (mvmvif->dbgfs_pm.lprx_ena) 259 if (mvmvif->dbgfs_pm.lprx_ena)
250 cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK); 260 cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
@@ -252,16 +262,16 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
252 cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK); 262 cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK);
253 } 263 }
254 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD) 264 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD)
255 cmd->lprx_rssi_threshold = 265 cmd->lprx_rssi_threshold = mvmvif->dbgfs_pm.lprx_rssi_threshold;
256 cpu_to_le32(mvmvif->dbgfs_pm.lprx_rssi_threshold);
257#endif /* CONFIG_IWLWIFI_DEBUGFS */ 266#endif /* CONFIG_IWLWIFI_DEBUGFS */
258} 267}
259 268
260int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif) 269static int iwl_mvm_power_mac_update_mode(struct iwl_mvm *mvm,
270 struct ieee80211_vif *vif)
261{ 271{
262 int ret; 272 int ret;
263 bool ba_enable; 273 bool ba_enable;
264 struct iwl_powertable_cmd cmd = {}; 274 struct iwl_mac_power_cmd cmd = {};
265 275
266 if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) 276 if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
267 return 0; 277 return 0;
@@ -280,7 +290,7 @@ int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
280 iwl_mvm_power_build_cmd(mvm, vif, &cmd); 290 iwl_mvm_power_build_cmd(mvm, vif, &cmd);
281 iwl_mvm_power_log(mvm, &cmd); 291 iwl_mvm_power_log(mvm, &cmd);
282 292
283 ret = iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC, 293 ret = iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, CMD_SYNC,
284 sizeof(cmd), &cmd); 294 sizeof(cmd), &cmd);
285 if (ret) 295 if (ret)
286 return ret; 296 return ret;
@@ -291,15 +301,19 @@ int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
291 return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable); 301 return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable);
292} 302}
293 303
294int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif) 304static int iwl_mvm_power_mac_disable(struct iwl_mvm *mvm,
305 struct ieee80211_vif *vif)
295{ 306{
296 struct iwl_powertable_cmd cmd = {}; 307 struct iwl_mac_power_cmd cmd = {};
297 struct iwl_mvm_vif *mvmvif __maybe_unused = 308 struct iwl_mvm_vif *mvmvif __maybe_unused =
298 iwl_mvm_vif_from_mac80211(vif); 309 iwl_mvm_vif_from_mac80211(vif);
299 310
300 if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) 311 if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
301 return 0; 312 return 0;
302 313
314 cmd.id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
315 mvmvif->color));
316
303 if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM) 317 if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM)
304 cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); 318 cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
305 319
@@ -310,11 +324,50 @@ int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
310#endif 324#endif
311 iwl_mvm_power_log(mvm, &cmd); 325 iwl_mvm_power_log(mvm, &cmd);
312 326
313 return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC, 327 return iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, CMD_ASYNC,
314 sizeof(cmd), &cmd); 328 sizeof(cmd), &cmd);
315} 329}
316 330
317#ifdef CONFIG_IWLWIFI_DEBUGFS 331#ifdef CONFIG_IWLWIFI_DEBUGFS
332static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
333 struct ieee80211_vif *vif, char *buf,
334 int bufsz)
335{
336 struct iwl_mac_power_cmd cmd = {};
337 int pos = 0;
338
339 iwl_mvm_power_build_cmd(mvm, vif, &cmd);
340
341 pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n",
342 (cmd.flags &
343 cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ?
344 0 : 1);
345 pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
346 cmd.skip_dtim_periods);
347 pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
348 iwlmvm_mod_params.power_scheme);
349 pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
350 le16_to_cpu(cmd.flags));
351 pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
352 le16_to_cpu(cmd.keep_alive_seconds));
353
354 if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
355 pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
356 (cmd.flags &
357 cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ?
358 1 : 0);
359 pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n",
360 le32_to_cpu(cmd.rx_data_timeout));
361 pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
362 le32_to_cpu(cmd.tx_data_timeout));
363 if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
364 pos += scnprintf(buf+pos, bufsz-pos,
365 "lprx_rssi_threshold = %d\n",
366 cmd.lprx_rssi_threshold);
367 }
368 return pos;
369}
370
318void 371void
319iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif, 372iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
320 struct iwl_beacon_filter_cmd *cmd) 373 struct iwl_beacon_filter_cmd *cmd)
@@ -323,22 +376,30 @@ iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
323 struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf; 376 struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf;
324 377
325 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ENERGY_DELTA) 378 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ENERGY_DELTA)
326 cmd->bf_energy_delta = dbgfs_bf->bf_energy_delta; 379 cmd->bf_energy_delta = cpu_to_le32(dbgfs_bf->bf_energy_delta);
327 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA) 380 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA)
328 cmd->bf_roaming_energy_delta = 381 cmd->bf_roaming_energy_delta =
329 dbgfs_bf->bf_roaming_energy_delta; 382 cpu_to_le32(dbgfs_bf->bf_roaming_energy_delta);
330 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_STATE) 383 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_STATE)
331 cmd->bf_roaming_state = dbgfs_bf->bf_roaming_state; 384 cmd->bf_roaming_state = cpu_to_le32(dbgfs_bf->bf_roaming_state);
332 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMPERATURE_DELTA) 385 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_THRESHOLD)
333 cmd->bf_temperature_delta = dbgfs_bf->bf_temperature_delta; 386 cmd->bf_temp_threshold =
387 cpu_to_le32(dbgfs_bf->bf_temp_threshold);
388 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_FAST_FILTER)
389 cmd->bf_temp_fast_filter =
390 cpu_to_le32(dbgfs_bf->bf_temp_fast_filter);
391 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_SLOW_FILTER)
392 cmd->bf_temp_slow_filter =
393 cpu_to_le32(dbgfs_bf->bf_temp_slow_filter);
334 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_DEBUG_FLAG) 394 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_DEBUG_FLAG)
335 cmd->bf_debug_flag = dbgfs_bf->bf_debug_flag; 395 cmd->bf_debug_flag = cpu_to_le32(dbgfs_bf->bf_debug_flag);
336 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ESCAPE_TIMER) 396 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ESCAPE_TIMER)
337 cmd->bf_escape_timer = cpu_to_le32(dbgfs_bf->bf_escape_timer); 397 cmd->bf_escape_timer = cpu_to_le32(dbgfs_bf->bf_escape_timer);
338 if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ESCAPE_TIMER) 398 if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ESCAPE_TIMER)
339 cmd->ba_escape_timer = cpu_to_le32(dbgfs_bf->ba_escape_timer); 399 cmd->ba_escape_timer = cpu_to_le32(dbgfs_bf->ba_escape_timer);
340 if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT) 400 if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT)
341 cmd->ba_enable_beacon_abort = dbgfs_bf->ba_enable_beacon_abort; 401 cmd->ba_enable_beacon_abort =
402 cpu_to_le32(dbgfs_bf->ba_enable_beacon_abort);
342} 403}
343#endif 404#endif
344 405
@@ -348,7 +409,7 @@ int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
348 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 409 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
349 struct iwl_beacon_filter_cmd cmd = { 410 struct iwl_beacon_filter_cmd cmd = {
350 IWL_BF_CMD_CONFIG_DEFAULTS, 411 IWL_BF_CMD_CONFIG_DEFAULTS,
351 .bf_enable_beacon_filter = 1, 412 .bf_enable_beacon_filter = cpu_to_le32(1),
352 }; 413 };
353 int ret; 414 int ret;
354 415
@@ -372,7 +433,8 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
372 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 433 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
373 int ret; 434 int ret;
374 435
375 if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) 436 if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BF_UPDATED) ||
437 vif->type != NL80211_IFTYPE_STATION || vif->p2p)
376 return 0; 438 return 0;
377 439
378 ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); 440 ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
@@ -382,3 +444,11 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
382 444
383 return ret; 445 return ret;
384} 446}
447
448const struct iwl_mvm_power_ops pm_mac_ops = {
449 .power_update_mode = iwl_mvm_power_mac_update_mode,
450 .power_disable = iwl_mvm_power_mac_disable,
451#ifdef CONFIG_IWLWIFI_DEBUGFS
452 .power_dbgfs_read = iwl_mvm_power_mac_dbgfs_read,
453#endif
454};
diff --git a/drivers/net/wireless/iwlwifi/mvm/power_legacy.c b/drivers/net/wireless/iwlwifi/mvm/power_legacy.c
new file mode 100644
index 000000000000..2ce79bad5845
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/mvm/power_legacy.c
@@ -0,0 +1,319 @@
1/******************************************************************************
2 *
3 * This file is provided under a dual BSD/GPLv2 license. When using or
4 * redistributing this file, you may do so under either license.
5 *
6 * GPL LICENSE SUMMARY
7 *
8 * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
22 * USA
23 *
24 * The full GNU General Public License is included in this distribution
25 * in the file called COPYING.
26 *
27 * Contact Information:
28 * Intel Linux Wireless <ilw@linux.intel.com>
29 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30 *
31 * BSD LICENSE
32 *
33 * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 *
40 * * Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * * Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in
44 * the documentation and/or other materials provided with the
45 * distribution.
46 * * Neither the name Intel Corporation nor the names of its
47 * contributors may be used to endorse or promote products derived
48 * from this software without specific prior written permission.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
54 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
56 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
60 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 *
62 *****************************************************************************/
63
64#include <linux/kernel.h>
65#include <linux/module.h>
66#include <linux/slab.h>
67#include <linux/init.h>
68
69#include <net/mac80211.h>
70
71#include "iwl-debug.h"
72#include "mvm.h"
73#include "iwl-modparams.h"
74#include "fw-api-power.h"
75
76#define POWER_KEEP_ALIVE_PERIOD_SEC 25
77
78static void iwl_mvm_power_log(struct iwl_mvm *mvm,
79 struct iwl_powertable_cmd *cmd)
80{
81 IWL_DEBUG_POWER(mvm,
82 "Sending power table command for power level %d, flags = 0x%X\n",
83 iwlmvm_mod_params.power_scheme,
84 le16_to_cpu(cmd->flags));
85 IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n", cmd->keep_alive_seconds);
86
87 if (cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
88 IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n",
89 le32_to_cpu(cmd->rx_data_timeout));
90 IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n",
91 le32_to_cpu(cmd->tx_data_timeout));
92 if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK))
93 IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n",
94 le32_to_cpu(cmd->skip_dtim_periods));
95 if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
96 IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
97 le32_to_cpu(cmd->lprx_rssi_threshold));
98 }
99}
100
101static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
102 struct ieee80211_vif *vif,
103 struct iwl_powertable_cmd *cmd)
104{
105 struct ieee80211_hw *hw = mvm->hw;
106 struct ieee80211_chanctx_conf *chanctx_conf;
107 struct ieee80211_channel *chan;
108 int dtimper, dtimper_msec;
109 int keep_alive;
110 bool radar_detect = false;
111 struct iwl_mvm_vif *mvmvif __maybe_unused =
112 iwl_mvm_vif_from_mac80211(vif);
113
114 /*
115 * Regardless of power management state the driver must set
116 * keep alive period. FW will use it for sending keep alive NDPs
117 * immediately after association.
118 */
119 cmd->keep_alive_seconds = POWER_KEEP_ALIVE_PERIOD_SEC;
120
121 if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
122 return;
123
124 cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
125 if (!vif->bss_conf.assoc)
126 cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
127
128#ifdef CONFIG_IWLWIFI_DEBUGFS
129 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF &&
130 mvmvif->dbgfs_pm.disable_power_off)
131 cmd->flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK);
132#endif
133 if (!vif->bss_conf.ps)
134 return;
135
136 cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
137
138 if (vif->bss_conf.beacon_rate &&
139 (vif->bss_conf.beacon_rate->bitrate == 10 ||
140 vif->bss_conf.beacon_rate->bitrate == 60)) {
141 cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
142 cmd->lprx_rssi_threshold =
143 cpu_to_le32(POWER_LPRX_RSSI_THRESHOLD);
144 }
145
146 dtimper = hw->conf.ps_dtim_period ?: 1;
147
148 /* Check if radar detection is required on current channel */
149 rcu_read_lock();
150 chanctx_conf = rcu_dereference(vif->chanctx_conf);
151 WARN_ON(!chanctx_conf);
152 if (chanctx_conf) {
153 chan = chanctx_conf->def.chan;
154 radar_detect = chan->flags & IEEE80211_CHAN_RADAR;
155 }
156 rcu_read_unlock();
157
158 /* Check skip over DTIM conditions */
159 if (!radar_detect && (dtimper <= 10) &&
160 (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP ||
161 mvm->cur_ucode == IWL_UCODE_WOWLAN)) {
162 cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
163 cmd->skip_dtim_periods = cpu_to_le32(3);
164 }
165
166 /* Check that keep alive period is at least 3 * DTIM */
167 dtimper_msec = dtimper * vif->bss_conf.beacon_int;
168 keep_alive = max_t(int, 3 * dtimper_msec,
169 MSEC_PER_SEC * cmd->keep_alive_seconds);
170 keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
171 cmd->keep_alive_seconds = keep_alive;
172
173 if (mvm->cur_ucode != IWL_UCODE_WOWLAN) {
174 cmd->rx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
175 cmd->tx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
176 } else {
177 cmd->rx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
178 cmd->tx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
179 }
180
181#ifdef CONFIG_IWLWIFI_DEBUGFS
182 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE)
183 cmd->keep_alive_seconds = mvmvif->dbgfs_pm.keep_alive_seconds;
184 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) {
185 if (mvmvif->dbgfs_pm.skip_over_dtim)
186 cmd->flags |=
187 cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
188 else
189 cmd->flags &=
190 cpu_to_le16(~POWER_FLAGS_SKIP_OVER_DTIM_MSK);
191 }
192 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_RX_DATA_TIMEOUT)
193 cmd->rx_data_timeout =
194 cpu_to_le32(mvmvif->dbgfs_pm.rx_data_timeout);
195 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_TX_DATA_TIMEOUT)
196 cmd->tx_data_timeout =
197 cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout);
198 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS)
199 cmd->skip_dtim_periods =
200 cpu_to_le32(mvmvif->dbgfs_pm.skip_dtim_periods);
201 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) {
202 if (mvmvif->dbgfs_pm.lprx_ena)
203 cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
204 else
205 cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK);
206 }
207 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD)
208 cmd->lprx_rssi_threshold =
209 cpu_to_le32(mvmvif->dbgfs_pm.lprx_rssi_threshold);
210#endif /* CONFIG_IWLWIFI_DEBUGFS */
211}
212
213static int iwl_mvm_power_legacy_update_mode(struct iwl_mvm *mvm,
214 struct ieee80211_vif *vif)
215{
216 int ret;
217 bool ba_enable;
218 struct iwl_powertable_cmd cmd = {};
219
220 if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
221 return 0;
222
223 /*
224 * TODO: The following vif_count verification is temporary condition.
225 * Avoid power mode update if more than one interface is currently
226 * active. Remove this condition when FW will support power management
227 * on multiple MACs.
228 */
229 IWL_DEBUG_POWER(mvm, "Currently %d interfaces active\n",
230 mvm->vif_count);
231 if (mvm->vif_count > 1)
232 return 0;
233
234 iwl_mvm_power_build_cmd(mvm, vif, &cmd);
235 iwl_mvm_power_log(mvm, &cmd);
236
237 ret = iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC,
238 sizeof(cmd), &cmd);
239 if (ret)
240 return ret;
241
242 ba_enable = !!(cmd.flags &
243 cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK));
244
245 return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable);
246}
247
248static int iwl_mvm_power_legacy_disable(struct iwl_mvm *mvm,
249 struct ieee80211_vif *vif)
250{
251 struct iwl_powertable_cmd cmd = {};
252 struct iwl_mvm_vif *mvmvif __maybe_unused =
253 iwl_mvm_vif_from_mac80211(vif);
254
255 if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
256 return 0;
257
258 if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM)
259 cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
260
261#ifdef CONFIG_IWLWIFI_DEBUGFS
262 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF &&
263 mvmvif->dbgfs_pm.disable_power_off)
264 cmd.flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK);
265#endif
266 iwl_mvm_power_log(mvm, &cmd);
267
268 return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC,
269 sizeof(cmd), &cmd);
270}
271
272#ifdef CONFIG_IWLWIFI_DEBUGFS
273static int iwl_mvm_power_legacy_dbgfs_read(struct iwl_mvm *mvm,
274 struct ieee80211_vif *vif, char *buf,
275 int bufsz)
276{
277 struct iwl_powertable_cmd cmd = {};
278 int pos = 0;
279
280 iwl_mvm_power_build_cmd(mvm, vif, &cmd);
281
282 pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n",
283 (cmd.flags &
284 cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ?
285 0 : 1);
286 pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
287 le32_to_cpu(cmd.skip_dtim_periods));
288 pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
289 iwlmvm_mod_params.power_scheme);
290 pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
291 le16_to_cpu(cmd.flags));
292 pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
293 cmd.keep_alive_seconds);
294
295 if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
296 pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
297 (cmd.flags &
298 cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ?
299 1 : 0);
300 pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n",
301 le32_to_cpu(cmd.rx_data_timeout));
302 pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
303 le32_to_cpu(cmd.tx_data_timeout));
304 if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
305 pos += scnprintf(buf+pos, bufsz-pos,
306 "lprx_rssi_threshold = %d\n",
307 le32_to_cpu(cmd.lprx_rssi_threshold));
308 }
309 return pos;
310}
311#endif
312
313const struct iwl_mvm_power_ops pm_legacy_ops = {
314 .power_update_mode = iwl_mvm_power_legacy_update_mode,
315 .power_disable = iwl_mvm_power_legacy_disable,
316#ifdef CONFIG_IWLWIFI_DEBUGFS
317 .power_dbgfs_read = iwl_mvm_power_legacy_dbgfs_read,
318#endif
319};
diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c
index 29d49cf0fdb2..18973874b77a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/quota.c
+++ b/drivers/net/wireless/iwlwifi/mvm/quota.c
@@ -132,7 +132,7 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
132int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) 132int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
133{ 133{
134 struct iwl_time_quota_cmd cmd; 134 struct iwl_time_quota_cmd cmd;
135 int i, idx, ret, num_active_bindings, quota, quota_rem; 135 int i, idx, ret, num_active_macs, quota, quota_rem;
136 struct iwl_mvm_quota_iterator_data data = { 136 struct iwl_mvm_quota_iterator_data data = {
137 .n_interfaces = {}, 137 .n_interfaces = {},
138 .colors = { -1, -1, -1, -1 }, 138 .colors = { -1, -1, -1, -1 },
@@ -162,18 +162,17 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
162 * IWL_MVM_MAX_QUOTA fragments. Divide these fragments 162 * IWL_MVM_MAX_QUOTA fragments. Divide these fragments
163 * equally between all the bindings that require quota 163 * equally between all the bindings that require quota
164 */ 164 */
165 num_active_bindings = 0; 165 num_active_macs = 0;
166 for (i = 0; i < MAX_BINDINGS; i++) { 166 for (i = 0; i < MAX_BINDINGS; i++) {
167 cmd.quotas[i].id_and_color = cpu_to_le32(FW_CTXT_INVALID); 167 cmd.quotas[i].id_and_color = cpu_to_le32(FW_CTXT_INVALID);
168 if (data.n_interfaces[i] > 0) 168 num_active_macs += data.n_interfaces[i];
169 num_active_bindings++;
170 } 169 }
171 170
172 quota = 0; 171 quota = 0;
173 quota_rem = 0; 172 quota_rem = 0;
174 if (num_active_bindings) { 173 if (num_active_macs) {
175 quota = IWL_MVM_MAX_QUOTA / num_active_bindings; 174 quota = IWL_MVM_MAX_QUOTA / num_active_macs;
176 quota_rem = IWL_MVM_MAX_QUOTA % num_active_bindings; 175 quota_rem = IWL_MVM_MAX_QUOTA % num_active_macs;
177 } 176 }
178 177
179 for (idx = 0, i = 0; i < MAX_BINDINGS; i++) { 178 for (idx = 0, i = 0; i < MAX_BINDINGS; i++) {
@@ -187,7 +186,8 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
187 cmd.quotas[idx].quota = cpu_to_le32(0); 186 cmd.quotas[idx].quota = cpu_to_le32(0);
188 cmd.quotas[idx].max_duration = cpu_to_le32(0); 187 cmd.quotas[idx].max_duration = cpu_to_le32(0);
189 } else { 188 } else {
190 cmd.quotas[idx].quota = cpu_to_le32(quota); 189 cmd.quotas[idx].quota =
190 cpu_to_le32(quota * data.n_interfaces[i]);
191 cmd.quotas[idx].max_duration = 191 cmd.quotas[idx].max_duration =
192 cpu_to_le32(IWL_MVM_MAX_QUOTA); 192 cpu_to_le32(IWL_MVM_MAX_QUOTA);
193 } 193 }
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index 376ea2112de2..9eeb21f62ef7 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -2688,9 +2688,6 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
2688 2688
2689 lq_sta->flush_timer = 0; 2689 lq_sta->flush_timer = 0;
2690 lq_sta->supp_rates = sta->supp_rates[sband->band]; 2690 lq_sta->supp_rates = sta->supp_rates[sband->band];
2691 for (j = 0; j < LQ_SIZE; j++)
2692 for (i = 0; i < IWL_RATE_COUNT; i++)
2693 rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]);
2694 2691
2695 IWL_DEBUG_RATE(mvm, 2692 IWL_DEBUG_RATE(mvm,
2696 "LQ: *** rate scale station global init for station %d ***\n", 2693 "LQ: *** rate scale station global init for station %d ***\n",
@@ -3194,13 +3191,14 @@ void iwl_mvm_rate_control_unregister(void)
3194 * iwl_mvm_tx_protection - Gets LQ command, change it to enable/disable 3191 * iwl_mvm_tx_protection - Gets LQ command, change it to enable/disable
3195 * Tx protection, according to this rquest and previous requests, 3192 * Tx protection, according to this rquest and previous requests,
3196 * and send the LQ command. 3193 * and send the LQ command.
3197 * @lq: The LQ command
3198 * @mvmsta: The station 3194 * @mvmsta: The station
3199 * @enable: Enable Tx protection? 3195 * @enable: Enable Tx protection?
3200 */ 3196 */
3201int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, 3197int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
3202 struct iwl_mvm_sta *mvmsta, bool enable) 3198 bool enable)
3203{ 3199{
3200 struct iwl_lq_cmd *lq = &mvmsta->lq_sta.lq;
3201
3204 lockdep_assert_held(&mvm->mutex); 3202 lockdep_assert_held(&mvm->mutex);
3205 3203
3206 if (enable) { 3204 if (enable) {
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h
index cff4f6da7733..29d699ac07c9 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.h
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.h
@@ -404,7 +404,7 @@ extern void iwl_mvm_rate_control_unregister(void);
404 404
405struct iwl_mvm_sta; 405struct iwl_mvm_sta;
406 406
407int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, 407int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
408 struct iwl_mvm_sta *mvmsta, bool enable); 408 bool enable);
409 409
410#endif /* __rs__ */ 410#endif /* __rs__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c
index e4930d5027d2..6fd7fae30c0a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rx.c
@@ -124,24 +124,15 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
124 ieee80211_rx_ni(mvm->hw, skb); 124 ieee80211_rx_ni(mvm->hw, skb);
125} 125}
126 126
127/* 127static void iwl_mvm_calc_rssi(struct iwl_mvm *mvm,
128 * iwl_mvm_calc_rssi - calculate the rssi in dBm 128 struct iwl_rx_phy_info *phy_info,
129 * @phy_info: the phy information for the coming packet 129 struct ieee80211_rx_status *rx_status)
130 */
131static int iwl_mvm_calc_rssi(struct iwl_mvm *mvm,
132 struct iwl_rx_phy_info *phy_info)
133{ 130{
134 int rssi_a, rssi_b, rssi_a_dbm, rssi_b_dbm, max_rssi_dbm; 131 int rssi_a, rssi_b, rssi_a_dbm, rssi_b_dbm, max_rssi_dbm;
135 int rssi_all_band_a, rssi_all_band_b; 132 int rssi_all_band_a, rssi_all_band_b;
136 u32 agc_a, agc_b, max_agc; 133 u32 agc_a, agc_b, max_agc;
137 u32 val; 134 u32 val;
138 135
139 /* Find max rssi among 2 possible receivers.
140 * These values are measured by the Digital Signal Processor (DSP).
141 * They should stay fairly constant even as the signal strength varies,
142 * if the radio's Automatic Gain Control (AGC) is working right.
143 * AGC value (see below) will provide the "interesting" info.
144 */
145 val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]); 136 val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]);
146 agc_a = (val & IWL_OFDM_AGC_A_MSK) >> IWL_OFDM_AGC_A_POS; 137 agc_a = (val & IWL_OFDM_AGC_A_MSK) >> IWL_OFDM_AGC_A_POS;
147 agc_b = (val & IWL_OFDM_AGC_B_MSK) >> IWL_OFDM_AGC_B_POS; 138 agc_b = (val & IWL_OFDM_AGC_B_MSK) >> IWL_OFDM_AGC_B_POS;
@@ -166,7 +157,45 @@ static int iwl_mvm_calc_rssi(struct iwl_mvm *mvm,
166 IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d Max %d AGCA %d AGCB %d\n", 157 IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d Max %d AGCA %d AGCB %d\n",
167 rssi_a_dbm, rssi_b_dbm, max_rssi_dbm, agc_a, agc_b); 158 rssi_a_dbm, rssi_b_dbm, max_rssi_dbm, agc_a, agc_b);
168 159
169 return max_rssi_dbm; 160 rx_status->signal = max_rssi_dbm;
161 rx_status->chains = (le16_to_cpu(phy_info->phy_flags) &
162 RX_RES_PHY_FLAGS_ANTENNA)
163 >> RX_RES_PHY_FLAGS_ANTENNA_POS;
164 rx_status->chain_signal[0] = rssi_a_dbm;
165 rx_status->chain_signal[1] = rssi_b_dbm;
166}
167
168/*
169 * iwl_mvm_get_signal_strength - use new rx PHY INFO API
170 */
171static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,
172 struct iwl_rx_phy_info *phy_info,
173 struct ieee80211_rx_status *rx_status)
174{
175 int energy_a, energy_b, energy_c, max_energy;
176 u32 val;
177
178 val =
179 le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_ENERGY_ANT_ABC_IDX]);
180 energy_a = -((val & IWL_RX_INFO_ENERGY_ANT_A_MSK) >>
181 IWL_RX_INFO_ENERGY_ANT_A_POS);
182 energy_b = -((val & IWL_RX_INFO_ENERGY_ANT_B_MSK) >>
183 IWL_RX_INFO_ENERGY_ANT_B_POS);
184 energy_c = -((val & IWL_RX_INFO_ENERGY_ANT_C_MSK) >>
185 IWL_RX_INFO_ENERGY_ANT_C_POS);
186 max_energy = max(energy_a, energy_b);
187 max_energy = max(max_energy, energy_c);
188
189 IWL_DEBUG_STATS(mvm, "energy In A %d B %d C %d , and max %d\n",
190 energy_a, energy_b, energy_c, max_energy);
191
192 rx_status->signal = max_energy;
193 rx_status->chains = (le16_to_cpu(phy_info->phy_flags) &
194 RX_RES_PHY_FLAGS_ANTENNA)
195 >> RX_RES_PHY_FLAGS_ANTENNA_POS;
196 rx_status->chain_signal[0] = energy_a;
197 rx_status->chain_signal[1] = energy_b;
198 rx_status->chain_signal[2] = energy_c;
170} 199}
171 200
172/* 201/*
@@ -289,29 +318,14 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
289 */ 318 */
290 /*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/ 319 /*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/
291 320
292 /* Find max signal strength (dBm) among 3 antenna/receiver chains */ 321 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_RX_ENERGY_API)
293 rx_status.signal = iwl_mvm_calc_rssi(mvm, phy_info); 322 iwl_mvm_get_signal_strength(mvm, phy_info, &rx_status);
323 else
324 iwl_mvm_calc_rssi(mvm, phy_info, &rx_status);
294 325
295 IWL_DEBUG_STATS_LIMIT(mvm, "Rssi %d, TSF %llu\n", rx_status.signal, 326 IWL_DEBUG_STATS_LIMIT(mvm, "Rssi %d, TSF %llu\n", rx_status.signal,
296 (unsigned long long)rx_status.mactime); 327 (unsigned long long)rx_status.mactime);
297 328
298 /*
299 * "antenna number"
300 *
301 * It seems that the antenna field in the phy flags value
302 * is actually a bit field. This is undefined by radiotap,
303 * it wants an actual antenna number but I always get "7"
304 * for most legacy frames I receive indicating that the
305 * same frame was received on all three RX chains.
306 *
307 * I think this field should be removed in favor of a
308 * new 802.11n radiotap field "RX chains" that is defined
309 * as a bitmask.
310 */
311 rx_status.antenna = (le16_to_cpu(phy_info->phy_flags) &
312 RX_RES_PHY_FLAGS_ANTENNA)
313 >> RX_RES_PHY_FLAGS_ANTENNA_POS;
314
315 /* set the preamble flag if appropriate */ 329 /* set the preamble flag if appropriate */
316 if (phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_SHORT_PREAMBLE)) 330 if (phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_SHORT_PREAMBLE))
317 rx_status.flag |= RX_FLAG_SHORTPRE; 331 rx_status.flag |= RX_FLAG_SHORTPRE;
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c
index 268f027b45b0..14c1b457ca50 100644
--- a/drivers/net/wireless/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
@@ -308,10 +308,12 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm,
308 */ 308 */
309 if (req->n_ssids > 0) { 309 if (req->n_ssids > 0) {
310 cmd->passive2active = cpu_to_le16(1); 310 cmd->passive2active = cpu_to_le16(1);
311 cmd->scan_flags |= SCAN_FLAGS_PASSIVE2ACTIVE;
311 ssid = req->ssids[0].ssid; 312 ssid = req->ssids[0].ssid;
312 ssid_len = req->ssids[0].ssid_len; 313 ssid_len = req->ssids[0].ssid_len;
313 } else { 314 } else {
314 cmd->passive2active = 0; 315 cmd->passive2active = 0;
316 cmd->scan_flags &= ~SCAN_FLAGS_PASSIVE2ACTIVE;
315 } 317 }
316 318
317 iwl_mvm_scan_fill_ssids(cmd, req); 319 iwl_mvm_scan_fill_ssids(cmd, req);
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c
index 85d4bbe52157..8b302774b70c 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.c
@@ -826,8 +826,7 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
826 * method for HT traffic 826 * method for HT traffic
827 * this function also sends the LQ command 827 * this function also sends the LQ command
828 */ 828 */
829 return iwl_mvm_tx_protection(mvm, &mvmsta->lq_sta.lq, 829 return iwl_mvm_tx_protection(mvm, mvmsta, true);
830 mvmsta, true);
831 /* 830 /*
832 * TODO: remove the TLC_RTS flag when we tear down the last 831 * TODO: remove the TLC_RTS flag when we tear down the last
833 * AGG session (agg_tids_count in DVM) 832 * AGG session (agg_tids_count in DVM)
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c
index d6ae7f16ac11..1f3282dff513 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tt.c
@@ -391,8 +391,7 @@ static void iwl_mvm_tt_tx_protection(struct iwl_mvm *mvm, bool enable)
391 mvmsta = (void *)sta->drv_priv; 391 mvmsta = (void *)sta->drv_priv;
392 if (enable == mvmsta->tt_tx_protection) 392 if (enable == mvmsta->tt_tx_protection)
393 continue; 393 continue;
394 err = iwl_mvm_tx_protection(mvm, &mvmsta->lq_sta.lq, 394 err = iwl_mvm_tx_protection(mvm, mvmsta, enable);
395 mvmsta, enable);
396 if (err) { 395 if (err) {
397 IWL_ERR(mvm, "Failed to %s Tx protection\n", 396 IWL_ERR(mvm, "Failed to %s Tx protection\n",
398 enable ? "enable" : "disable"); 397 enable ? "enable" : "disable");
@@ -513,12 +512,39 @@ static const struct iwl_tt_params iwl7000_tt_params = {
513 .support_tx_backoff = true, 512 .support_tx_backoff = true,
514}; 513};
515 514
515static const struct iwl_tt_params iwl7000_high_temp_tt_params = {
516 .ct_kill_entry = 118,
517 .ct_kill_exit = 96,
518 .ct_kill_duration = 5,
519 .dynamic_smps_entry = 114,
520 .dynamic_smps_exit = 110,
521 .tx_protection_entry = 114,
522 .tx_protection_exit = 108,
523 .tx_backoff = {
524 {.temperature = 112, .backoff = 300},
525 {.temperature = 113, .backoff = 800},
526 {.temperature = 114, .backoff = 1500},
527 {.temperature = 115, .backoff = 3000},
528 {.temperature = 116, .backoff = 5000},
529 {.temperature = 117, .backoff = 10000},
530 },
531 .support_ct_kill = true,
532 .support_dynamic_smps = true,
533 .support_tx_protection = true,
534 .support_tx_backoff = true,
535};
536
516void iwl_mvm_tt_initialize(struct iwl_mvm *mvm) 537void iwl_mvm_tt_initialize(struct iwl_mvm *mvm)
517{ 538{
518 struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle; 539 struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle;
519 540
520 IWL_DEBUG_TEMP(mvm, "Initialize Thermal Throttling\n"); 541 IWL_DEBUG_TEMP(mvm, "Initialize Thermal Throttling\n");
521 tt->params = &iwl7000_tt_params; 542
543 if (mvm->cfg->high_temp)
544 tt->params = &iwl7000_high_temp_tt_params;
545 else
546 tt->params = &iwl7000_tt_params;
547
522 tt->throttle = false; 548 tt->throttle = false;
523 INIT_DELAYED_WORK(&tt->ct_kill_exit, check_exit_ctkill); 549 INIT_DELAYED_WORK(&tt->ct_kill_exit, check_exit_ctkill);
524} 550}
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index f0e96a927407..7694b8fa4c37 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -123,6 +123,8 @@ static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
123 * it 123 * it
124 */ 124 */
125 WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU); 125 WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU);
126 } else if (skb->protocol == cpu_to_be16(ETH_P_PAE)) {
127 tx_cmd->pm_frame_timeout = cpu_to_le16(2);
126 } else { 128 } else {
127 tx_cmd->pm_frame_timeout = 0; 129 tx_cmd->pm_frame_timeout = 0;
128 } 130 }
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c
index 1e1332839e4a..a9c357491434 100644
--- a/drivers/net/wireless/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/iwlwifi/mvm/utils.c
@@ -453,6 +453,29 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
453 IWL_ERR(mvm, "0x%08X | flow_handler\n", table.flow_handler); 453 IWL_ERR(mvm, "0x%08X | flow_handler\n", table.flow_handler);
454} 454}
455 455
456void iwl_mvm_dump_sram(struct iwl_mvm *mvm)
457{
458 const struct fw_img *img;
459 int ofs, len = 0;
460 u8 *buf;
461
462 if (!mvm->ucode_loaded)
463 return;
464
465 img = &mvm->fw->img[mvm->cur_ucode];
466 ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
467 len = img->sec[IWL_UCODE_SECTION_DATA].len;
468
469 buf = kzalloc(len, GFP_KERNEL);
470 if (!buf)
471 return;
472
473 iwl_trans_read_mem_bytes(mvm->trans, ofs, buf, len);
474 iwl_print_hex_error(mvm->trans, buf, len);
475
476 kfree(buf);
477}
478
456/** 479/**
457 * iwl_mvm_send_lq_cmd() - Send link quality command 480 * iwl_mvm_send_lq_cmd() - Send link quality command
458 * @init: This command is sent as part of station initialization right 481 * @init: This command is sent as part of station initialization right
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c
index 81f3ea5b09a4..db6be2491d7c 100644
--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
@@ -272,9 +272,9 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
272 {IWL_PCI_DEVICE(0x08B1, 0x4462, iwl7260_n_cfg)}, 272 {IWL_PCI_DEVICE(0x08B1, 0x4462, iwl7260_n_cfg)},
273 {IWL_PCI_DEVICE(0x08B1, 0x4870, iwl7260_2ac_cfg)}, 273 {IWL_PCI_DEVICE(0x08B1, 0x4870, iwl7260_2ac_cfg)},
274 {IWL_PCI_DEVICE(0x08B1, 0x486E, iwl7260_2ac_cfg)}, 274 {IWL_PCI_DEVICE(0x08B1, 0x486E, iwl7260_2ac_cfg)},
275 {IWL_PCI_DEVICE(0x08B1, 0x4A70, iwl7260_2ac_cfg)}, 275 {IWL_PCI_DEVICE(0x08B1, 0x4A70, iwl7260_2ac_cfg_high_temp)},
276 {IWL_PCI_DEVICE(0x08B1, 0x4A6E, iwl7260_2ac_cfg)}, 276 {IWL_PCI_DEVICE(0x08B1, 0x4A6E, iwl7260_2ac_cfg_high_temp)},
277 {IWL_PCI_DEVICE(0x08B1, 0x4A6C, iwl7260_2ac_cfg)}, 277 {IWL_PCI_DEVICE(0x08B1, 0x4A6C, iwl7260_2ac_cfg_high_temp)},
278 {IWL_PCI_DEVICE(0x08B1, 0x4020, iwl7260_2n_cfg)}, 278 {IWL_PCI_DEVICE(0x08B1, 0x4020, iwl7260_2n_cfg)},
279 {IWL_PCI_DEVICE(0x08B2, 0x4220, iwl7260_2n_cfg)}, 279 {IWL_PCI_DEVICE(0x08B2, 0x4220, iwl7260_2n_cfg)},
280 {IWL_PCI_DEVICE(0x08B1, 0x4420, iwl7260_2n_cfg)}, 280 {IWL_PCI_DEVICE(0x08B1, 0x4420, iwl7260_2n_cfg)},
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
index b654dcdd048a..fa22639b63c9 100644
--- a/drivers/net/wireless/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
@@ -392,7 +392,6 @@ void iwl_trans_pcie_tx_reset(struct iwl_trans *trans);
392/***************************************************** 392/*****************************************************
393* Error handling 393* Error handling
394******************************************************/ 394******************************************************/
395int iwl_pcie_dump_fh(struct iwl_trans *trans, char **buf);
396void iwl_pcie_dump_csr(struct iwl_trans *trans); 395void iwl_pcie_dump_csr(struct iwl_trans *trans);
397 396
398/***************************************************** 397/*****************************************************
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index fd848cd1583e..5fdb4eea146d 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -793,7 +793,7 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
793 } 793 }
794 794
795 iwl_pcie_dump_csr(trans); 795 iwl_pcie_dump_csr(trans);
796 iwl_pcie_dump_fh(trans, NULL); 796 iwl_dump_fh(trans, NULL);
797 797
798 set_bit(STATUS_FW_ERROR, &trans_pcie->status); 798 set_bit(STATUS_FW_ERROR, &trans_pcie->status);
799 clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); 799 clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index 826c15602c46..cec0c8991285 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -1033,71 +1033,6 @@ static void iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans, u32 reg,
1033 spin_unlock_irqrestore(&trans_pcie->reg_lock, flags); 1033 spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
1034} 1034}
1035 1035
1036static const char *get_fh_string(int cmd)
1037{
1038#define IWL_CMD(x) case x: return #x
1039 switch (cmd) {
1040 IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
1041 IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
1042 IWL_CMD(FH_RSCSR_CHNL0_WPTR);
1043 IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
1044 IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
1045 IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
1046 IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
1047 IWL_CMD(FH_TSSR_TX_STATUS_REG);
1048 IWL_CMD(FH_TSSR_TX_ERROR_REG);
1049 default:
1050 return "UNKNOWN";
1051 }
1052#undef IWL_CMD
1053}
1054
1055int iwl_pcie_dump_fh(struct iwl_trans *trans, char **buf)
1056{
1057 int i;
1058 static const u32 fh_tbl[] = {
1059 FH_RSCSR_CHNL0_STTS_WPTR_REG,
1060 FH_RSCSR_CHNL0_RBDCB_BASE_REG,
1061 FH_RSCSR_CHNL0_WPTR,
1062 FH_MEM_RCSR_CHNL0_CONFIG_REG,
1063 FH_MEM_RSSR_SHARED_CTRL_REG,
1064 FH_MEM_RSSR_RX_STATUS_REG,
1065 FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
1066 FH_TSSR_TX_STATUS_REG,
1067 FH_TSSR_TX_ERROR_REG
1068 };
1069
1070#ifdef CONFIG_IWLWIFI_DEBUGFS
1071 if (buf) {
1072 int pos = 0;
1073 size_t bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
1074
1075 *buf = kmalloc(bufsz, GFP_KERNEL);
1076 if (!*buf)
1077 return -ENOMEM;
1078
1079 pos += scnprintf(*buf + pos, bufsz - pos,
1080 "FH register values:\n");
1081
1082 for (i = 0; i < ARRAY_SIZE(fh_tbl); i++)
1083 pos += scnprintf(*buf + pos, bufsz - pos,
1084 " %34s: 0X%08x\n",
1085 get_fh_string(fh_tbl[i]),
1086 iwl_read_direct32(trans, fh_tbl[i]));
1087
1088 return pos;
1089 }
1090#endif
1091
1092 IWL_ERR(trans, "FH register values:\n");
1093 for (i = 0; i < ARRAY_SIZE(fh_tbl); i++)
1094 IWL_ERR(trans, " %34s: 0X%08x\n",
1095 get_fh_string(fh_tbl[i]),
1096 iwl_read_direct32(trans, fh_tbl[i]));
1097
1098 return 0;
1099}
1100
1101static const char *get_csr_string(int cmd) 1036static const char *get_csr_string(int cmd)
1102{ 1037{
1103#define IWL_CMD(x) case x: return #x 1038#define IWL_CMD(x) case x: return #x
@@ -1178,18 +1113,7 @@ void iwl_pcie_dump_csr(struct iwl_trans *trans)
1178} while (0) 1113} while (0)
1179 1114
1180/* file operation */ 1115/* file operation */
1181#define DEBUGFS_READ_FUNC(name) \
1182static ssize_t iwl_dbgfs_##name##_read(struct file *file, \
1183 char __user *user_buf, \
1184 size_t count, loff_t *ppos);
1185
1186#define DEBUGFS_WRITE_FUNC(name) \
1187static ssize_t iwl_dbgfs_##name##_write(struct file *file, \
1188 const char __user *user_buf, \
1189 size_t count, loff_t *ppos);
1190
1191#define DEBUGFS_READ_FILE_OPS(name) \ 1116#define DEBUGFS_READ_FILE_OPS(name) \
1192 DEBUGFS_READ_FUNC(name); \
1193static const struct file_operations iwl_dbgfs_##name##_ops = { \ 1117static const struct file_operations iwl_dbgfs_##name##_ops = { \
1194 .read = iwl_dbgfs_##name##_read, \ 1118 .read = iwl_dbgfs_##name##_read, \
1195 .open = simple_open, \ 1119 .open = simple_open, \
@@ -1197,7 +1121,6 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \
1197}; 1121};
1198 1122
1199#define DEBUGFS_WRITE_FILE_OPS(name) \ 1123#define DEBUGFS_WRITE_FILE_OPS(name) \
1200 DEBUGFS_WRITE_FUNC(name); \
1201static const struct file_operations iwl_dbgfs_##name##_ops = { \ 1124static const struct file_operations iwl_dbgfs_##name##_ops = { \
1202 .write = iwl_dbgfs_##name##_write, \ 1125 .write = iwl_dbgfs_##name##_write, \
1203 .open = simple_open, \ 1126 .open = simple_open, \
@@ -1205,8 +1128,6 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \
1205}; 1128};
1206 1129
1207#define DEBUGFS_READ_WRITE_FILE_OPS(name) \ 1130#define DEBUGFS_READ_WRITE_FILE_OPS(name) \
1208 DEBUGFS_READ_FUNC(name); \
1209 DEBUGFS_WRITE_FUNC(name); \
1210static const struct file_operations iwl_dbgfs_##name##_ops = { \ 1131static const struct file_operations iwl_dbgfs_##name##_ops = { \
1211 .write = iwl_dbgfs_##name##_write, \ 1132 .write = iwl_dbgfs_##name##_write, \
1212 .read = iwl_dbgfs_##name##_read, \ 1133 .read = iwl_dbgfs_##name##_read, \
@@ -1390,7 +1311,7 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
1390 int pos = 0; 1311 int pos = 0;
1391 ssize_t ret = -EFAULT; 1312 ssize_t ret = -EFAULT;
1392 1313
1393 ret = pos = iwl_pcie_dump_fh(trans, &buf); 1314 ret = pos = iwl_dump_fh(trans, &buf);
1394 if (buf) { 1315 if (buf) {
1395 ret = simple_read_from_buffer(user_buf, 1316 ret = simple_read_from_buffer(user_buf,
1396 count, ppos, buf, pos); 1317 count, ppos, buf, pos);
@@ -1497,10 +1418,16 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
1497 spin_lock_init(&trans_pcie->reg_lock); 1418 spin_lock_init(&trans_pcie->reg_lock);
1498 init_waitqueue_head(&trans_pcie->ucode_write_waitq); 1419 init_waitqueue_head(&trans_pcie->ucode_write_waitq);
1499 1420
1500 /* W/A - seems to solve weird behavior. We need to remove this if we 1421 if (!cfg->base_params->pcie_l1_allowed) {
1501 * don't want to stay in L1 all the time. This wastes a lot of power */ 1422 /*
1502 pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | 1423 * W/A - seems to solve weird behavior. We need to remove this
1503 PCIE_LINK_STATE_CLKPM); 1424 * if we don't want to stay in L1 all the time. This wastes a
1425 * lot of power.
1426 */
1427 pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S |
1428 PCIE_LINK_STATE_L1 |
1429 PCIE_LINK_STATE_CLKPM);
1430 }
1504 1431
1505 if (pci_enable_device(pdev)) { 1432 if (pci_enable_device(pdev)) {
1506 err = -ENODEV; 1433 err = -ENODEV;
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index c47c92165aba..134f7a109f47 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -1619,10 +1619,9 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
1619 txq = &trans_pcie->txq[txq_id]; 1619 txq = &trans_pcie->txq[txq_id];
1620 q = &txq->q; 1620 q = &txq->q;
1621 1621
1622 if (unlikely(!test_bit(txq_id, trans_pcie->queue_used))) { 1622 if (WARN_ONCE(!test_bit(txq_id, trans_pcie->queue_used),
1623 WARN_ON_ONCE(1); 1623 "TX on unused queue %d\n", txq_id))
1624 return -EINVAL; 1624 return -EINVAL;
1625 }
1626 1625
1627 spin_lock(&txq->lock); 1626 spin_lock(&txq->lock);
1628 1627