aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2013-06-26 20:00:11 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-06-26 20:00:11 -0400
commit59731bb8c4f1536c5b698dc1aec82d7a5cef41eb (patch)
treeb6e245cfae009fe9e108d6adaed3e0f56fd2969e /drivers/net
parent729d8d182bbf296b32cb2e7f970801eb6ce33c6a (diff)
parentbd4ace2a36e7c87bb5f3eceb54d3b304d395dcf0 (diff)
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig10
-rw-r--r--drivers/net/wireless/iwlwifi/Makefile1
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/Makefile1
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/agn.h37
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/dev.h13
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/lib.c6
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/mac80211.c2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/main.c15
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/rs.c43
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/rx.c40
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/testmode.c471
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/tx.c12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-7000.c12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-config.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-drv.c16
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-modparams.h6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-test.c852
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-test.h161
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-testmode.h309
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/bt-coex.c21
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/d3.c6
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs.c27
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-power.h5
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c56
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h8
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/power.c22
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rs.c30
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tt.c22
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/rx.c71
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c17
31 files changed, 251 insertions, 2044 deletions
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 56c2040a955b..cbaa5c2c410f 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -128,16 +128,6 @@ config IWLWIFI_DEVICE_TRACING
128 occur. 128 occur.
129endmenu 129endmenu
130 130
131config IWLWIFI_DEVICE_TESTMODE
132 def_bool y
133 depends on IWLWIFI
134 depends on NL80211_TESTMODE
135 help
136 This option enables the testmode support for iwlwifi device through
137 NL80211_TESTMODE. This provide the capabilities of enable user space
138 validation applications to interacts with the device through the
139 generic netlink message via NL80211_TESTMODE channel.
140
141config IWLWIFI_P2P 131config IWLWIFI_P2P
142 def_bool y 132 def_bool y
143 bool "iwlwifi experimental P2P support" 133 bool "iwlwifi experimental P2P support"
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index f55a758b87f6..1fa64429bcc2 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -13,7 +13,6 @@ iwlwifi-$(CONFIG_IWLMVM) += iwl-7000.o
13iwlwifi-objs += $(iwlwifi-m) 13iwlwifi-objs += $(iwlwifi-m)
14 14
15iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o 15iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
16iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-test.o
17 16
18ccflags-y += -D__CHECK_ENDIAN__ -I$(src) 17ccflags-y += -D__CHECK_ENDIAN__ -I$(src)
19 18
diff --git a/drivers/net/wireless/iwlwifi/dvm/Makefile b/drivers/net/wireless/iwlwifi/dvm/Makefile
index 5ff76b204141..dce7ab2e0c4b 100644
--- a/drivers/net/wireless/iwlwifi/dvm/Makefile
+++ b/drivers/net/wireless/iwlwifi/dvm/Makefile
@@ -8,6 +8,5 @@ iwldvm-objs += scan.o led.o
8iwldvm-objs += rxon.o devices.o 8iwldvm-objs += rxon.o devices.o
9 9
10iwldvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o 10iwldvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o
11iwldvm-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += testmode.o
12 11
13ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../ 12ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../
diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h
index de2c9514bef6..18355110deff 100644
--- a/drivers/net/wireless/iwlwifi/dvm/agn.h
+++ b/drivers/net/wireless/iwlwifi/dvm/agn.h
@@ -405,43 +405,6 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
405 405
406extern int iwl_alive_start(struct iwl_priv *priv); 406extern int iwl_alive_start(struct iwl_priv *priv);
407 407
408/* testmode support */
409#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
410
411extern int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data,
412 int len);
413extern int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw,
414 struct sk_buff *skb,
415 struct netlink_callback *cb,
416 void *data, int len);
417extern void iwl_testmode_init(struct iwl_priv *priv);
418extern void iwl_testmode_free(struct iwl_priv *priv);
419
420#else
421
422static inline
423int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
424{
425 return -ENOSYS;
426}
427
428static inline
429int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
430 struct netlink_callback *cb,
431 void *data, int len)
432{
433 return -ENOSYS;
434}
435
436static inline void iwl_testmode_init(struct iwl_priv *priv)
437{
438}
439
440static inline void iwl_testmode_free(struct iwl_priv *priv)
441{
442}
443#endif
444
445#ifdef CONFIG_IWLWIFI_DEBUG 408#ifdef CONFIG_IWLWIFI_DEBUG
446void iwl_print_rx_config_cmd(struct iwl_priv *priv, 409void iwl_print_rx_config_cmd(struct iwl_priv *priv,
447 enum iwl_rxon_context_id ctxid); 410 enum iwl_rxon_context_id ctxid);
diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h
index 5cd87f949266..60a4e0d15715 100644
--- a/drivers/net/wireless/iwlwifi/dvm/dev.h
+++ b/drivers/net/wireless/iwlwifi/dvm/dev.h
@@ -52,8 +52,6 @@
52#include "rs.h" 52#include "rs.h"
53#include "tt.h" 53#include "tt.h"
54 54
55#include "iwl-test.h"
56
57/* CT-KILL constants */ 55/* CT-KILL constants */
58#define CT_KILL_THRESHOLD_LEGACY 110 /* in Celsius */ 56#define CT_KILL_THRESHOLD_LEGACY 110 /* in Celsius */
59#define CT_KILL_THRESHOLD 114 /* in Celsius */ 57#define CT_KILL_THRESHOLD 114 /* in Celsius */
@@ -691,10 +689,6 @@ struct iwl_priv {
691 struct iwl_spectrum_notification measure_report; 689 struct iwl_spectrum_notification measure_report;
692 u8 measurement_status; 690 u8 measurement_status;
693 691
694#define IWL_OWNERSHIP_DRIVER 0
695#define IWL_OWNERSHIP_TM 1
696 u8 ucode_owner;
697
698 /* ucode beacon time */ 692 /* ucode beacon time */
699 u32 ucode_beacon_time; 693 u32 ucode_beacon_time;
700 int missed_beacon_threshold; 694 int missed_beacon_threshold;
@@ -889,7 +883,7 @@ struct iwl_priv {
889#endif /* CONFIG_IWLWIFI_DEBUGFS */ 883#endif /* CONFIG_IWLWIFI_DEBUGFS */
890 884
891 struct iwl_nvm_data *nvm_data; 885 struct iwl_nvm_data *nvm_data;
892 /* eeprom blob for debugfs/testmode */ 886 /* eeprom blob for debugfs */
893 u8 *eeprom_blob; 887 u8 *eeprom_blob;
894 size_t eeprom_blob_size; 888 size_t eeprom_blob_size;
895 889
@@ -905,11 +899,6 @@ struct iwl_priv {
905 unsigned long blink_on, blink_off; 899 unsigned long blink_on, blink_off;
906 bool led_registered; 900 bool led_registered;
907 901
908#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
909 struct iwl_test tst;
910 u32 tm_fixed_rate;
911#endif
912
913 /* WoWLAN GTK rekey data */ 902 /* WoWLAN GTK rekey data */
914 u8 kck[NL80211_KCK_LEN], kek[NL80211_KEK_LEN]; 903 u8 kck[NL80211_KCK_LEN], kek[NL80211_KEK_LEN];
915 __le64 replay_ctr; 904 __le64 replay_ctr;
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c
index 9879550a0fea..3d5bdc4217a8 100644
--- a/drivers/net/wireless/iwlwifi/dvm/lib.c
+++ b/drivers/net/wireless/iwlwifi/dvm/lib.c
@@ -1288,12 +1288,6 @@ int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
1288 if (!(cmd->flags & CMD_ASYNC)) 1288 if (!(cmd->flags & CMD_ASYNC))
1289 lockdep_assert_held(&priv->mutex); 1289 lockdep_assert_held(&priv->mutex);
1290 1290
1291 if (priv->ucode_owner == IWL_OWNERSHIP_TM &&
1292 !(cmd->flags & CMD_ON_DEMAND)) {
1293 IWL_DEBUG_HC(priv, "tm own the uCode, no regular hcmd send\n");
1294 return -EIO;
1295 }
1296
1297 return iwl_trans_send_cmd(priv->trans, cmd); 1291 return iwl_trans_send_cmd(priv->trans, cmd);
1298} 1292}
1299 1293
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index eef64bb854f7..822f1a00efbb 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -1766,8 +1766,6 @@ struct ieee80211_ops iwlagn_hw_ops = {
1766 .remain_on_channel = iwlagn_mac_remain_on_channel, 1766 .remain_on_channel = iwlagn_mac_remain_on_channel,
1767 .cancel_remain_on_channel = iwlagn_mac_cancel_remain_on_channel, 1767 .cancel_remain_on_channel = iwlagn_mac_cancel_remain_on_channel,
1768 .rssi_callback = iwlagn_mac_rssi_callback, 1768 .rssi_callback = iwlagn_mac_rssi_callback,
1769 CFG80211_TESTMODE_CMD(iwlagn_mac_testmode_cmd)
1770 CFG80211_TESTMODE_DUMP(iwlagn_mac_testmode_dump)
1771 .set_tim = iwlagn_mac_set_tim, 1769 .set_tim = iwlagn_mac_set_tim,
1772}; 1770};
1773 1771
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c
index 7aa9c8dc33ef..3952ddf2ddb2 100644
--- a/drivers/net/wireless/iwlwifi/dvm/main.c
+++ b/drivers/net/wireless/iwlwifi/dvm/main.c
@@ -1105,8 +1105,6 @@ static int iwl_init_drv(struct iwl_priv *priv)
1105 priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; 1105 priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
1106 priv->agg_tids_count = 0; 1106 priv->agg_tids_count = 0;
1107 1107
1108 priv->ucode_owner = IWL_OWNERSHIP_DRIVER;
1109
1110 priv->rx_statistics_jiffies = jiffies; 1108 priv->rx_statistics_jiffies = jiffies;
1111 1109
1112 /* Choose which receivers/antennas to use */ 1110 /* Choose which receivers/antennas to use */
@@ -1172,12 +1170,6 @@ static void iwl_option_config(struct iwl_priv *priv)
1172 IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TRACING disabled\n"); 1170 IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TRACING disabled\n");
1173#endif 1171#endif
1174 1172
1175#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
1176 IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TESTMODE enabled\n");
1177#else
1178 IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TESTMODE disabled\n");
1179#endif
1180
1181#ifdef CONFIG_IWLWIFI_P2P 1173#ifdef CONFIG_IWLWIFI_P2P
1182 IWL_INFO(priv, "CONFIG_IWLWIFI_P2P enabled\n"); 1174 IWL_INFO(priv, "CONFIG_IWLWIFI_P2P enabled\n");
1183#else 1175#else
@@ -1355,8 +1347,8 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
1355 IWL_BT_ANTENNA_COUPLING_THRESHOLD) ? 1347 IWL_BT_ANTENNA_COUPLING_THRESHOLD) ?
1356 true : false; 1348 true : false;
1357 1349
1358 /* enable/disable bt channel inhibition */ 1350 /* bt channel inhibition enabled*/
1359 priv->bt_ch_announce = iwlwifi_mod_params.bt_ch_announce; 1351 priv->bt_ch_announce = true;
1360 IWL_DEBUG_INFO(priv, "BT channel inhibition is %s\n", 1352 IWL_DEBUG_INFO(priv, "BT channel inhibition is %s\n",
1361 (priv->bt_ch_announce) ? "On" : "Off"); 1353 (priv->bt_ch_announce) ? "On" : "Off");
1362 1354
@@ -1451,7 +1443,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
1451 ********************/ 1443 ********************/
1452 iwl_setup_deferred_work(priv); 1444 iwl_setup_deferred_work(priv);
1453 iwl_setup_rx_handlers(priv); 1445 iwl_setup_rx_handlers(priv);
1454 iwl_testmode_init(priv);
1455 1446
1456 iwl_power_initialize(priv); 1447 iwl_power_initialize(priv);
1457 iwl_tt_initialize(priv); 1448 iwl_tt_initialize(priv);
@@ -1488,7 +1479,6 @@ out_mac80211_unregister:
1488 iwlagn_mac_unregister(priv); 1479 iwlagn_mac_unregister(priv);
1489out_destroy_workqueue: 1480out_destroy_workqueue:
1490 iwl_tt_exit(priv); 1481 iwl_tt_exit(priv);
1491 iwl_testmode_free(priv);
1492 iwl_cancel_deferred_work(priv); 1482 iwl_cancel_deferred_work(priv);
1493 destroy_workqueue(priv->workqueue); 1483 destroy_workqueue(priv->workqueue);
1494 priv->workqueue = NULL; 1484 priv->workqueue = NULL;
@@ -1510,7 +1500,6 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
1510 1500
1511 IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); 1501 IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
1512 1502
1513 iwl_testmode_free(priv);
1514 iwlagn_mac_unregister(priv); 1503 iwlagn_mac_unregister(priv);
1515 1504
1516 iwl_tt_exit(priv); 1505 iwl_tt_exit(priv);
diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.c b/drivers/net/wireless/iwlwifi/dvm/rs.c
index 8fe76dc4f373..1b693944123b 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rs.c
@@ -351,12 +351,6 @@ static void rs_program_fix_rate(struct iwl_priv *priv,
351 lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ 351 lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */
352 lq_sta->active_mimo3_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ 352 lq_sta->active_mimo3_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */
353 353
354#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
355 /* testmode has higher priority to overwirte the fixed rate */
356 if (priv->tm_fixed_rate)
357 lq_sta->dbg_fixed_rate = priv->tm_fixed_rate;
358#endif
359
360 IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n", 354 IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n",
361 lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate); 355 lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate);
362 356
@@ -419,23 +413,18 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
419 413
420 load = rs_tl_get_load(lq_data, tid); 414 load = rs_tl_get_load(lq_data, tid);
421 415
422 if ((iwlwifi_mod_params.auto_agg) || (load > IWL_AGG_LOAD_THRESHOLD)) { 416 IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n",
423 IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", 417 sta->addr, tid);
424 sta->addr, tid); 418 ret = ieee80211_start_tx_ba_session(sta, tid, 5000);
425 ret = ieee80211_start_tx_ba_session(sta, tid, 5000); 419 if (ret == -EAGAIN) {
426 if (ret == -EAGAIN) { 420 /*
427 /* 421 * driver and mac80211 is out of sync
428 * driver and mac80211 is out of sync 422 * this might be cause by reloading firmware
429 * this might be cause by reloading firmware 423 * stop the tx ba session here
430 * stop the tx ba session here 424 */
431 */ 425 IWL_ERR(priv, "Fail start Tx agg on tid: %d\n",
432 IWL_ERR(priv, "Fail start Tx agg on tid: %d\n", 426 tid);
433 tid); 427 ieee80211_stop_tx_ba_session(sta, tid);
434 ieee80211_stop_tx_ba_session(sta, tid);
435 }
436 } else {
437 IWL_DEBUG_HT(priv, "Aggregation not enabled for tid %d "
438 "because load = %u\n", tid, load);
439 } 428 }
440 return ret; 429 return ret;
441} 430}
@@ -1083,11 +1072,6 @@ done:
1083 if (sta && sta->supp_rates[sband->band]) 1072 if (sta && sta->supp_rates[sband->band])
1084 rs_rate_scale_perform(priv, skb, sta, lq_sta); 1073 rs_rate_scale_perform(priv, skb, sta, lq_sta);
1085 1074
1086#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_IWLWIFI_DEVICE_TESTMODE)
1087 if ((priv->tm_fixed_rate) &&
1088 (priv->tm_fixed_rate != lq_sta->dbg_fixed_rate))
1089 rs_program_fix_rate(priv, lq_sta);
1090#endif
1091 if (priv->lib->bt_params && priv->lib->bt_params->advanced_bt_coexist) 1075 if (priv->lib->bt_params && priv->lib->bt_params->advanced_bt_coexist)
1092 rs_bt_update_lq(priv, ctx, lq_sta); 1076 rs_bt_update_lq(priv, ctx, lq_sta);
1093} 1077}
@@ -2913,9 +2897,6 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
2913 if (sband->band == IEEE80211_BAND_5GHZ) 2897 if (sband->band == IEEE80211_BAND_5GHZ)
2914 lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; 2898 lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
2915 lq_sta->is_agg = 0; 2899 lq_sta->is_agg = 0;
2916#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
2917 priv->tm_fixed_rate = 0;
2918#endif
2919#ifdef CONFIG_MAC80211_DEBUGFS 2900#ifdef CONFIG_MAC80211_DEBUGFS
2920 lq_sta->dbg_fixed_rate = 0; 2901 lq_sta->dbg_fixed_rate = 0;
2921#endif 2902#endif
diff --git a/drivers/net/wireless/iwlwifi/dvm/rx.c b/drivers/net/wireless/iwlwifi/dvm/rx.c
index 2f3fd160ab44..d71776dd1e6a 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rx.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rx.c
@@ -335,8 +335,7 @@ static void iwlagn_recover_from_statistics(struct iwl_priv *priv,
335 if (msecs < 99) 335 if (msecs < 99)
336 return; 336 return;
337 337
338 if (iwlwifi_mod_params.plcp_check && 338 if (!iwlagn_good_plcp_health(priv, cur_ofdm, cur_ofdm_ht, msecs))
339 !iwlagn_good_plcp_health(priv, cur_ofdm, cur_ofdm_ht, msecs))
340 iwl_force_rf_reset(priv, false); 339 iwl_force_rf_reset(priv, false);
341} 340}
342 341
@@ -1120,32 +1119,17 @@ int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb,
1120 */ 1119 */
1121 iwl_notification_wait_notify(&priv->notif_wait, pkt); 1120 iwl_notification_wait_notify(&priv->notif_wait, pkt);
1122 1121
1123#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE 1122 /* Based on type of command response or notification,
1124 /* 1123 * handle those that need handling via function in
1125 * RX data may be forwarded to userspace in one 1124 * rx_handlers table. See iwl_setup_rx_handlers() */
1126 * of two cases: the user owns the fw through testmode or when 1125 if (priv->rx_handlers[pkt->hdr.cmd]) {
1127 * the user requested to monitor the rx w/o affecting the regular flow. 1126 priv->rx_handlers_stats[pkt->hdr.cmd]++;
1128 * In these cases the iwl_test object will handle forwarding the rx 1127 err = priv->rx_handlers[pkt->hdr.cmd] (priv, rxb, cmd);
1129 * data to user space. 1128 } else {
1130 * Note that if the ownership flag != IWL_OWNERSHIP_TM the flow 1129 /* No handling needed */
1131 * continues. 1130 IWL_DEBUG_RX(priv, "No handler needed for %s, 0x%02x\n",
1132 */ 1131 iwl_dvm_get_cmd_string(pkt->hdr.cmd),
1133 iwl_test_rx(&priv->tst, rxb); 1132 pkt->hdr.cmd);
1134#endif
1135
1136 if (priv->ucode_owner != IWL_OWNERSHIP_TM) {
1137 /* Based on type of command response or notification,
1138 * handle those that need handling via function in
1139 * rx_handlers table. See iwl_setup_rx_handlers() */
1140 if (priv->rx_handlers[pkt->hdr.cmd]) {
1141 priv->rx_handlers_stats[pkt->hdr.cmd]++;
1142 err = priv->rx_handlers[pkt->hdr.cmd] (priv, rxb, cmd);
1143 } else {
1144 /* No handling needed */
1145 IWL_DEBUG_RX(priv, "No handler needed for %s, 0x%02x\n",
1146 iwl_dvm_get_cmd_string(pkt->hdr.cmd),
1147 pkt->hdr.cmd);
1148 }
1149 } 1133 }
1150 return err; 1134 return err;
1151} 1135}
diff --git a/drivers/net/wireless/iwlwifi/dvm/testmode.c b/drivers/net/wireless/iwlwifi/dvm/testmode.c
deleted file mode 100644
index b89b9d9b9969..000000000000
--- a/drivers/net/wireless/iwlwifi/dvm/testmode.c
+++ /dev/null
@@ -1,471 +0,0 @@
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) 2010 - 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) 2010 - 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/init.h>
65#include <linux/kernel.h>
66#include <linux/module.h>
67#include <linux/dma-mapping.h>
68#include <net/net_namespace.h>
69#include <linux/netdevice.h>
70#include <net/cfg80211.h>
71#include <net/mac80211.h>
72#include <net/netlink.h>
73
74#include "iwl-debug.h"
75#include "iwl-trans.h"
76#include "dev.h"
77#include "agn.h"
78#include "iwl-test.h"
79#include "iwl-testmode.h"
80
81static int iwl_testmode_send_cmd(struct iwl_op_mode *op_mode,
82 struct iwl_host_cmd *cmd)
83{
84 struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
85 return iwl_dvm_send_cmd(priv, cmd);
86}
87
88static bool iwl_testmode_valid_hw_addr(u32 addr)
89{
90 if (iwlagn_hw_valid_rtc_data_addr(addr))
91 return true;
92
93 if (IWLAGN_RTC_INST_LOWER_BOUND <= addr &&
94 addr < IWLAGN_RTC_INST_UPPER_BOUND)
95 return true;
96
97 return false;
98}
99
100static u32 iwl_testmode_get_fw_ver(struct iwl_op_mode *op_mode)
101{
102 struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
103 return priv->fw->ucode_ver;
104}
105
106static struct sk_buff*
107iwl_testmode_alloc_reply(struct iwl_op_mode *op_mode, int len)
108{
109 struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
110 return cfg80211_testmode_alloc_reply_skb(priv->hw->wiphy, len);
111}
112
113static int iwl_testmode_reply(struct iwl_op_mode *op_mode, struct sk_buff *skb)
114{
115 return cfg80211_testmode_reply(skb);
116}
117
118static struct sk_buff *iwl_testmode_alloc_event(struct iwl_op_mode *op_mode,
119 int len)
120{
121 struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
122 return cfg80211_testmode_alloc_event_skb(priv->hw->wiphy, len,
123 GFP_ATOMIC);
124}
125
126static void iwl_testmode_event(struct iwl_op_mode *op_mode, struct sk_buff *skb)
127{
128 return cfg80211_testmode_event(skb, GFP_ATOMIC);
129}
130
131static struct iwl_test_ops tst_ops = {
132 .send_cmd = iwl_testmode_send_cmd,
133 .valid_hw_addr = iwl_testmode_valid_hw_addr,
134 .get_fw_ver = iwl_testmode_get_fw_ver,
135 .alloc_reply = iwl_testmode_alloc_reply,
136 .reply = iwl_testmode_reply,
137 .alloc_event = iwl_testmode_alloc_event,
138 .event = iwl_testmode_event,
139};
140
141void iwl_testmode_init(struct iwl_priv *priv)
142{
143 iwl_test_init(&priv->tst, priv->trans, &tst_ops);
144}
145
146void iwl_testmode_free(struct iwl_priv *priv)
147{
148 iwl_test_free(&priv->tst);
149}
150
151static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv)
152{
153 struct iwl_notification_wait calib_wait;
154 static const u8 calib_complete[] = {
155 CALIBRATION_COMPLETE_NOTIFICATION
156 };
157 int ret;
158
159 iwl_init_notification_wait(&priv->notif_wait, &calib_wait,
160 calib_complete, ARRAY_SIZE(calib_complete),
161 NULL, NULL);
162 ret = iwl_init_alive_start(priv);
163 if (ret) {
164 IWL_ERR(priv, "Fail init calibration: %d\n", ret);
165 goto cfg_init_calib_error;
166 }
167
168 ret = iwl_wait_notification(&priv->notif_wait, &calib_wait, 2 * HZ);
169 if (ret)
170 IWL_ERR(priv, "Error detecting"
171 " CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret);
172 return ret;
173
174cfg_init_calib_error:
175 iwl_remove_notification(&priv->notif_wait, &calib_wait);
176 return ret;
177}
178
179/*
180 * This function handles the user application commands for driver.
181 *
182 * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the
183 * handlers respectively.
184 *
185 * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned
186 * value of the actual command execution is replied to the user application.
187 *
188 * If there's any message responding to the user space, IWL_TM_ATTR_SYNC_RSP
189 * is used for carry the message while IWL_TM_ATTR_COMMAND must set to
190 * IWL_TM_CMD_DEV2APP_SYNC_RSP.
191 *
192 * @hw: ieee80211_hw object that represents the device
193 * @tb: gnl message fields from the user space
194 */
195static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
196{
197 struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
198 struct iwl_trans *trans = priv->trans;
199 struct sk_buff *skb;
200 unsigned char *rsp_data_ptr = NULL;
201 int status = 0, rsp_data_len = 0;
202 u32 inst_size = 0, data_size = 0;
203 const struct fw_img *img;
204
205 switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
206 case IWL_TM_CMD_APP2DEV_GET_DEVICENAME:
207 rsp_data_ptr = (unsigned char *)priv->cfg->name;
208 rsp_data_len = strlen(priv->cfg->name);
209 skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
210 rsp_data_len + 20);
211 if (!skb) {
212 IWL_ERR(priv, "Memory allocation fail\n");
213 return -ENOMEM;
214 }
215 if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND,
216 IWL_TM_CMD_DEV2APP_SYNC_RSP) ||
217 nla_put(skb, IWL_TM_ATTR_SYNC_RSP,
218 rsp_data_len, rsp_data_ptr))
219 goto nla_put_failure;
220 status = cfg80211_testmode_reply(skb);
221 if (status < 0)
222 IWL_ERR(priv, "Error sending msg : %d\n", status);
223 break;
224
225 case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
226 status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_INIT);
227 if (status)
228 IWL_ERR(priv, "Error loading init ucode: %d\n", status);
229 break;
230
231 case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
232 iwl_testmode_cfg_init_calib(priv);
233 priv->ucode_loaded = false;
234 iwl_trans_stop_device(trans);
235 break;
236
237 case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
238 status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR);
239 if (status) {
240 IWL_ERR(priv,
241 "Error loading runtime ucode: %d\n", status);
242 break;
243 }
244 status = iwl_alive_start(priv);
245 if (status)
246 IWL_ERR(priv,
247 "Error starting the device: %d\n", status);
248 break;
249
250 case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW:
251 iwl_scan_cancel_timeout(priv, 200);
252 priv->ucode_loaded = false;
253 iwl_trans_stop_device(trans);
254 status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN);
255 if (status) {
256 IWL_ERR(priv,
257 "Error loading WOWLAN ucode: %d\n", status);
258 break;
259 }
260 status = iwl_alive_start(priv);
261 if (status)
262 IWL_ERR(priv,
263 "Error starting the device: %d\n", status);
264 break;
265
266 case IWL_TM_CMD_APP2DEV_GET_EEPROM:
267 if (priv->eeprom_blob) {
268 skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
269 priv->eeprom_blob_size + 20);
270 if (!skb) {
271 IWL_ERR(priv, "Memory allocation fail\n");
272 return -ENOMEM;
273 }
274 if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND,
275 IWL_TM_CMD_DEV2APP_EEPROM_RSP) ||
276 nla_put(skb, IWL_TM_ATTR_EEPROM,
277 priv->eeprom_blob_size,
278 priv->eeprom_blob))
279 goto nla_put_failure;
280 status = cfg80211_testmode_reply(skb);
281 if (status < 0)
282 IWL_ERR(priv, "Error sending msg : %d\n",
283 status);
284 } else
285 return -ENODATA;
286 break;
287
288 case IWL_TM_CMD_APP2DEV_FIXRATE_REQ:
289 if (!tb[IWL_TM_ATTR_FIXRATE]) {
290 IWL_ERR(priv, "Missing fixrate setting\n");
291 return -ENOMSG;
292 }
293 priv->tm_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]);
294 break;
295
296 case IWL_TM_CMD_APP2DEV_GET_FW_INFO:
297 skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20 + 8);
298 if (!skb) {
299 IWL_ERR(priv, "Memory allocation fail\n");
300 return -ENOMEM;
301 }
302 if (!priv->ucode_loaded) {
303 IWL_ERR(priv, "No uCode has not been loaded\n");
304 return -EINVAL;
305 } else {
306 img = &priv->fw->img[priv->cur_ucode];
307 inst_size = img->sec[IWL_UCODE_SECTION_INST].len;
308 data_size = img->sec[IWL_UCODE_SECTION_DATA].len;
309 }
310 if (nla_put_u32(skb, IWL_TM_ATTR_FW_TYPE, priv->cur_ucode) ||
311 nla_put_u32(skb, IWL_TM_ATTR_FW_INST_SIZE, inst_size) ||
312 nla_put_u32(skb, IWL_TM_ATTR_FW_DATA_SIZE, data_size))
313 goto nla_put_failure;
314 status = cfg80211_testmode_reply(skb);
315 if (status < 0)
316 IWL_ERR(priv, "Error sending msg : %d\n", status);
317 break;
318
319 default:
320 IWL_ERR(priv, "Unknown testmode driver command ID\n");
321 return -ENOSYS;
322 }
323 return status;
324
325nla_put_failure:
326 kfree_skb(skb);
327 return -EMSGSIZE;
328}
329
330/*
331 * This function handles the user application switch ucode ownership.
332 *
333 * It retrieves the mandatory fields IWL_TM_ATTR_UCODE_OWNER and
334 * decide who the current owner of the uCode
335 *
336 * If the current owner is OWNERSHIP_TM, then the only host command
337 * can deliver to uCode is from testmode, all the other host commands
338 * will dropped.
339 *
340 * default driver is the owner of uCode in normal operational mode
341 *
342 * @hw: ieee80211_hw object that represents the device
343 * @tb: gnl message fields from the user space
344 */
345static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb)
346{
347 struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
348 u8 owner;
349
350 if (!tb[IWL_TM_ATTR_UCODE_OWNER]) {
351 IWL_ERR(priv, "Missing ucode owner\n");
352 return -ENOMSG;
353 }
354
355 owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]);
356 if (owner == IWL_OWNERSHIP_DRIVER) {
357 priv->ucode_owner = owner;
358 iwl_test_enable_notifications(&priv->tst, false);
359 } else if (owner == IWL_OWNERSHIP_TM) {
360 priv->ucode_owner = owner;
361 iwl_test_enable_notifications(&priv->tst, true);
362 } else {
363 IWL_ERR(priv, "Invalid owner\n");
364 return -EINVAL;
365 }
366 return 0;
367}
368
369/* The testmode gnl message handler that takes the gnl message from the
370 * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then
371 * invoke the corresponding handlers.
372 *
373 * This function is invoked when there is user space application sending
374 * gnl message through the testmode tunnel NL80211_CMD_TESTMODE regulated
375 * by nl80211.
376 *
377 * It retrieves the mandatory field, IWL_TM_ATTR_COMMAND, before
378 * dispatching it to the corresponding handler.
379 *
380 * If IWL_TM_ATTR_COMMAND is missing, -ENOMSG is replied to user application;
381 * -ENOSYS is replied to the user application if the command is unknown;
382 * Otherwise, the command is dispatched to the respective handler.
383 *
384 * @hw: ieee80211_hw object that represents the device
385 * @data: pointer to user space message
386 * @len: length in byte of @data
387 */
388int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
389{
390 struct nlattr *tb[IWL_TM_ATTR_MAX];
391 struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
392 int result;
393
394 result = iwl_test_parse(&priv->tst, tb, data, len);
395 if (result)
396 return result;
397
398 /* in case multiple accesses to the device happens */
399 mutex_lock(&priv->mutex);
400 switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
401 case IWL_TM_CMD_APP2DEV_UCODE:
402 case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32:
403 case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32:
404 case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8:
405 case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
406 case IWL_TM_CMD_APP2DEV_END_TRACE:
407 case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ:
408 case IWL_TM_CMD_APP2DEV_NOTIFICATIONS:
409 case IWL_TM_CMD_APP2DEV_GET_FW_VERSION:
410 case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID:
411 case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE:
412 result = iwl_test_handle_cmd(&priv->tst, tb);
413 break;
414
415 case IWL_TM_CMD_APP2DEV_GET_DEVICENAME:
416 case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
417 case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
418 case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
419 case IWL_TM_CMD_APP2DEV_GET_EEPROM:
420 case IWL_TM_CMD_APP2DEV_FIXRATE_REQ:
421 case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW:
422 case IWL_TM_CMD_APP2DEV_GET_FW_INFO:
423 IWL_DEBUG_INFO(priv, "testmode cmd to driver\n");
424 result = iwl_testmode_driver(hw, tb);
425 break;
426
427 case IWL_TM_CMD_APP2DEV_OWNERSHIP:
428 IWL_DEBUG_INFO(priv, "testmode change uCode ownership\n");
429 result = iwl_testmode_ownership(hw, tb);
430 break;
431
432 default:
433 IWL_ERR(priv, "Unknown testmode command\n");
434 result = -ENOSYS;
435 break;
436 }
437 mutex_unlock(&priv->mutex);
438
439 if (result)
440 IWL_ERR(priv, "Test cmd failed result=%d\n", result);
441 return result;
442}
443
444int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
445 struct netlink_callback *cb,
446 void *data, int len)
447{
448 struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
449 int result;
450 u32 cmd;
451
452 if (cb->args[3]) {
453 /* offset by 1 since commands start at 0 */
454 cmd = cb->args[3] - 1;
455 } else {
456 struct nlattr *tb[IWL_TM_ATTR_MAX];
457
458 result = iwl_test_parse(&priv->tst, tb, data, len);
459 if (result)
460 return result;
461
462 cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]);
463 cb->args[3] = cmd + 1;
464 }
465
466 /* in case multiple accesses to the device happens */
467 mutex_lock(&priv->mutex);
468 result = iwl_test_dump(&priv->tst, cmd, skb, cb);
469 mutex_unlock(&priv->mutex);
470 return result;
471}
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c
index 353a053b4eb1..5ee983faa679 100644
--- a/drivers/net/wireless/iwlwifi/dvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/dvm/tx.c
@@ -162,18 +162,6 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
162 if (ieee80211_is_data(fc)) { 162 if (ieee80211_is_data(fc)) {
163 tx_cmd->initial_rate_index = 0; 163 tx_cmd->initial_rate_index = 0;
164 tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; 164 tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
165#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
166 if (priv->tm_fixed_rate) {
167 /*
168 * rate overwrite by testmode
169 * we not only send lq command to change rate
170 * we also re-enforce per data pkt base.
171 */
172 tx_cmd->tx_flags &= ~TX_CMD_FLG_STA_RATE_MSK;
173 memcpy(&tx_cmd->rate_n_flags, &priv->tm_fixed_rate,
174 sizeof(tx_cmd->rate_n_flags));
175 }
176#endif
177 return; 165 return;
178 } else if (ieee80211_is_back_req(fc)) 166 } else if (ieee80211_is_back_req(fc))
179 tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; 167 tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c
index d4f3b4864ab1..22b7fa5b971a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-7000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-7000.c
@@ -67,16 +67,16 @@
67#include "iwl-agn-hw.h" 67#include "iwl-agn-hw.h"
68 68
69/* Highest firmware API version supported */ 69/* Highest firmware API version supported */
70#define IWL7260_UCODE_API_MAX 6 70#define IWL7260_UCODE_API_MAX 7
71#define IWL3160_UCODE_API_MAX 6 71#define IWL3160_UCODE_API_MAX 7
72 72
73/* Oldest version we won't warn about */ 73/* Oldest version we won't warn about */
74#define IWL7260_UCODE_API_OK 6 74#define IWL7260_UCODE_API_OK 7
75#define IWL3160_UCODE_API_OK 6 75#define IWL3160_UCODE_API_OK 7
76 76
77/* Lowest firmware API version supported */ 77/* Lowest firmware API version supported */
78#define IWL7260_UCODE_API_MIN 6 78#define IWL7260_UCODE_API_MIN 7
79#define IWL3160_UCODE_API_MIN 6 79#define IWL3160_UCODE_API_MIN 7
80 80
81/* NVM versions */ 81/* NVM versions */
82#define IWL7260_NVM_VERSION 0x0a1d 82#define IWL7260_NVM_VERSION 0x0a1d
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h
index 0189b9050f22..83b9ff6ff3ad 100644
--- a/drivers/net/wireless/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/iwlwifi/iwl-config.h
@@ -222,6 +222,7 @@ struct iwl_cfg {
222 const u32 max_inst_size; 222 const u32 max_inst_size;
223 u8 valid_tx_ant; 223 u8 valid_tx_ant;
224 u8 valid_rx_ant; 224 u8 valid_rx_ant;
225 bool bt_shared_single_ant;
225 u16 nvm_ver; 226 u16 nvm_ver;
226 u16 nvm_calib_ver; 227 u16 nvm_calib_ver;
227 /* params not likely to change within a device family */ 228 /* params not likely to change within a device family */
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index 2f690e578b5c..d0162d426f88 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -1111,11 +1111,8 @@ void iwl_drv_stop(struct iwl_drv *drv)
1111/* shared module parameters */ 1111/* shared module parameters */
1112struct iwl_mod_params iwlwifi_mod_params = { 1112struct iwl_mod_params iwlwifi_mod_params = {
1113 .restart_fw = true, 1113 .restart_fw = true,
1114 .plcp_check = true,
1115 .bt_coex_active = true, 1114 .bt_coex_active = true,
1116 .power_level = IWL_POWER_INDEX_1, 1115 .power_level = IWL_POWER_INDEX_1,
1117 .bt_ch_announce = true,
1118 .auto_agg = true,
1119 .wd_disable = true, 1116 .wd_disable = true,
1120 /* the rest are 0 by default */ 1117 /* the rest are 0 by default */
1121}; 1118};
@@ -1223,14 +1220,6 @@ module_param_named(antenna_coupling, iwlwifi_mod_params.ant_coupling,
1223MODULE_PARM_DESC(antenna_coupling, 1220MODULE_PARM_DESC(antenna_coupling,
1224 "specify antenna coupling in dB (defualt: 0 dB)"); 1221 "specify antenna coupling in dB (defualt: 0 dB)");
1225 1222
1226module_param_named(bt_ch_inhibition, iwlwifi_mod_params.bt_ch_announce,
1227 bool, S_IRUGO);
1228MODULE_PARM_DESC(bt_ch_inhibition,
1229 "Enable BT channel inhibition (default: enable)");
1230
1231module_param_named(plcp_check, iwlwifi_mod_params.plcp_check, bool, S_IRUGO);
1232MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])");
1233
1234module_param_named(wd_disable, iwlwifi_mod_params.wd_disable, int, S_IRUGO); 1223module_param_named(wd_disable, iwlwifi_mod_params.wd_disable, int, S_IRUGO);
1235MODULE_PARM_DESC(wd_disable, 1224MODULE_PARM_DESC(wd_disable,
1236 "Disable stuck queue watchdog timer 0=system default, " 1225 "Disable stuck queue watchdog timer 0=system default, "
@@ -1272,8 +1261,3 @@ module_param_named(power_level, iwlwifi_mod_params.power_level,
1272 int, S_IRUGO); 1261 int, S_IRUGO);
1273MODULE_PARM_DESC(power_level, 1262MODULE_PARM_DESC(power_level,
1274 "default power save level (range from 1 - 5, default: 1)"); 1263 "default power save level (range from 1 - 5, default: 1)");
1275
1276module_param_named(auto_agg, iwlwifi_mod_params.auto_agg,
1277 bool, S_IRUGO);
1278MODULE_PARM_DESC(auto_agg,
1279 "enable agg w/o check traffic load (default: enable)");
diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h
index d4ad505b0a4b..a1f580c0c6c6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-modparams.h
+++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h
@@ -93,7 +93,6 @@ enum iwl_power_level {
93 * use IWL_DISABLE_HT_* constants 93 * use IWL_DISABLE_HT_* constants
94 * @amsdu_size_8K: enable 8K amsdu size, default = 0 94 * @amsdu_size_8K: enable 8K amsdu size, default = 0
95 * @restart_fw: restart firmware, default = 1 95 * @restart_fw: restart firmware, default = 1
96 * @plcp_check: enable plcp health check, default = true
97 * @wd_disable: enable stuck queue check, default = 0 96 * @wd_disable: enable stuck queue check, default = 0
98 * @bt_coex_active: enable bt coex, default = true 97 * @bt_coex_active: enable bt coex, default = true
99 * @led_mode: system default, default = 0 98 * @led_mode: system default, default = 0
@@ -101,15 +100,12 @@ enum iwl_power_level {
101 * @power_level: power level, default = 1 100 * @power_level: power level, default = 1
102 * @debug_level: levels are IWL_DL_* 101 * @debug_level: levels are IWL_DL_*
103 * @ant_coupling: antenna coupling in dB, default = 0 102 * @ant_coupling: antenna coupling in dB, default = 0
104 * @bt_ch_announce: BT channel inhibition, default = enable
105 * @auto_agg: enable agg. without check, default = true
106 */ 103 */
107struct iwl_mod_params { 104struct iwl_mod_params {
108 int sw_crypto; 105 int sw_crypto;
109 unsigned int disable_11n; 106 unsigned int disable_11n;
110 int amsdu_size_8K; 107 int amsdu_size_8K;
111 bool restart_fw; 108 bool restart_fw;
112 bool plcp_check;
113 int wd_disable; 109 int wd_disable;
114 bool bt_coex_active; 110 bool bt_coex_active;
115 int led_mode; 111 int led_mode;
@@ -119,8 +115,6 @@ struct iwl_mod_params {
119 u32 debug_level; 115 u32 debug_level;
120#endif 116#endif
121 int ant_coupling; 117 int ant_coupling;
122 bool bt_ch_announce;
123 bool auto_agg;
124 char *nvm_file; 118 char *nvm_file;
125}; 119};
126 120
diff --git a/drivers/net/wireless/iwlwifi/iwl-test.c b/drivers/net/wireless/iwlwifi/iwl-test.c
deleted file mode 100644
index 5cfd55b86ed3..000000000000
--- a/drivers/net/wireless/iwlwifi/iwl-test.c
+++ /dev/null
@@ -1,852 +0,0 @@
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) 2010 - 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) 2010 - 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/export.h>
65#include <net/netlink.h>
66
67#include "iwl-drv.h"
68#include "iwl-io.h"
69#include "iwl-fh.h"
70#include "iwl-prph.h"
71#include "iwl-trans.h"
72#include "iwl-test.h"
73#include "iwl-csr.h"
74#include "iwl-testmode.h"
75
76/*
77 * Periphery registers absolute lower bound. This is used in order to
78 * differentiate registery access through HBUS_TARG_PRPH_* and
79 * HBUS_TARG_MEM_* accesses.
80 */
81#define IWL_ABS_PRPH_START (0xA00000)
82
83/*
84 * The TLVs used in the gnl message policy between the kernel module and
85 * user space application. iwl_testmode_gnl_msg_policy is to be carried
86 * through the NL80211_CMD_TESTMODE channel regulated by nl80211.
87 * See iwl-testmode.h
88 */
89static
90struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = {
91 [IWL_TM_ATTR_COMMAND] = { .type = NLA_U32, },
92
93 [IWL_TM_ATTR_UCODE_CMD_ID] = { .type = NLA_U8, },
94 [IWL_TM_ATTR_UCODE_CMD_DATA] = { .type = NLA_UNSPEC, },
95
96 [IWL_TM_ATTR_REG_OFFSET] = { .type = NLA_U32, },
97 [IWL_TM_ATTR_REG_VALUE8] = { .type = NLA_U8, },
98 [IWL_TM_ATTR_REG_VALUE32] = { .type = NLA_U32, },
99
100 [IWL_TM_ATTR_SYNC_RSP] = { .type = NLA_UNSPEC, },
101 [IWL_TM_ATTR_UCODE_RX_PKT] = { .type = NLA_UNSPEC, },
102
103 [IWL_TM_ATTR_EEPROM] = { .type = NLA_UNSPEC, },
104
105 [IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, },
106 [IWL_TM_ATTR_TRACE_DUMP] = { .type = NLA_UNSPEC, },
107 [IWL_TM_ATTR_TRACE_SIZE] = { .type = NLA_U32, },
108
109 [IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, },
110
111 [IWL_TM_ATTR_UCODE_OWNER] = { .type = NLA_U8, },
112
113 [IWL_TM_ATTR_MEM_ADDR] = { .type = NLA_U32, },
114 [IWL_TM_ATTR_BUFFER_SIZE] = { .type = NLA_U32, },
115 [IWL_TM_ATTR_BUFFER_DUMP] = { .type = NLA_UNSPEC, },
116
117 [IWL_TM_ATTR_FW_VERSION] = { .type = NLA_U32, },
118 [IWL_TM_ATTR_DEVICE_ID] = { .type = NLA_U32, },
119 [IWL_TM_ATTR_FW_TYPE] = { .type = NLA_U32, },
120 [IWL_TM_ATTR_FW_INST_SIZE] = { .type = NLA_U32, },
121 [IWL_TM_ATTR_FW_DATA_SIZE] = { .type = NLA_U32, },
122
123 [IWL_TM_ATTR_ENABLE_NOTIFICATION] = {.type = NLA_FLAG, },
124};
125
126static inline void iwl_test_trace_clear(struct iwl_test *tst)
127{
128 memset(&tst->trace, 0, sizeof(struct iwl_test_trace));
129}
130
131static void iwl_test_trace_stop(struct iwl_test *tst)
132{
133 if (!tst->trace.enabled)
134 return;
135
136 if (tst->trace.cpu_addr && tst->trace.dma_addr)
137 dma_free_coherent(tst->trans->dev,
138 tst->trace.tsize,
139 tst->trace.cpu_addr,
140 tst->trace.dma_addr);
141
142 iwl_test_trace_clear(tst);
143}
144
145static inline void iwl_test_mem_clear(struct iwl_test *tst)
146{
147 memset(&tst->mem, 0, sizeof(struct iwl_test_mem));
148}
149
150static inline void iwl_test_mem_stop(struct iwl_test *tst)
151{
152 if (!tst->mem.in_read)
153 return;
154
155 iwl_test_mem_clear(tst);
156}
157
158/*
159 * Initializes the test object
160 * During the lifetime of the test object it is assumed that the transport is
161 * started. The test object should be stopped before the transport is stopped.
162 */
163void iwl_test_init(struct iwl_test *tst, struct iwl_trans *trans,
164 struct iwl_test_ops *ops)
165{
166 tst->trans = trans;
167 tst->ops = ops;
168
169 iwl_test_trace_clear(tst);
170 iwl_test_mem_clear(tst);
171}
172EXPORT_SYMBOL_GPL(iwl_test_init);
173
174/*
175 * Stop the test object
176 */
177void iwl_test_free(struct iwl_test *tst)
178{
179 iwl_test_mem_stop(tst);
180 iwl_test_trace_stop(tst);
181}
182EXPORT_SYMBOL_GPL(iwl_test_free);
183
184static inline int iwl_test_send_cmd(struct iwl_test *tst,
185 struct iwl_host_cmd *cmd)
186{
187 return tst->ops->send_cmd(tst->trans->op_mode, cmd);
188}
189
190static inline bool iwl_test_valid_hw_addr(struct iwl_test *tst, u32 addr)
191{
192 return tst->ops->valid_hw_addr(addr);
193}
194
195static inline u32 iwl_test_fw_ver(struct iwl_test *tst)
196{
197 return tst->ops->get_fw_ver(tst->trans->op_mode);
198}
199
200static inline struct sk_buff*
201iwl_test_alloc_reply(struct iwl_test *tst, int len)
202{
203 return tst->ops->alloc_reply(tst->trans->op_mode, len);
204}
205
206static inline int iwl_test_reply(struct iwl_test *tst, struct sk_buff *skb)
207{
208 return tst->ops->reply(tst->trans->op_mode, skb);
209}
210
211static inline struct sk_buff*
212iwl_test_alloc_event(struct iwl_test *tst, int len)
213{
214 return tst->ops->alloc_event(tst->trans->op_mode, len);
215}
216
217static inline void
218iwl_test_event(struct iwl_test *tst, struct sk_buff *skb)
219{
220 return tst->ops->event(tst->trans->op_mode, skb);
221}
222
223/*
224 * This function handles the user application commands to the fw. The fw
225 * commands are sent in a synchronuous manner. In case that the user requested
226 * to get commands response, it is send to the user.
227 */
228static int iwl_test_fw_cmd(struct iwl_test *tst, struct nlattr **tb)
229{
230 struct iwl_host_cmd cmd;
231 struct iwl_rx_packet *pkt;
232 struct sk_buff *skb;
233 void *reply_buf;
234 u32 reply_len;
235 int ret;
236 bool cmd_want_skb;
237
238 memset(&cmd, 0, sizeof(struct iwl_host_cmd));
239
240 if (!tb[IWL_TM_ATTR_UCODE_CMD_ID] ||
241 !tb[IWL_TM_ATTR_UCODE_CMD_DATA]) {
242 IWL_ERR(tst->trans, "Missing fw command mandatory fields\n");
243 return -ENOMSG;
244 }
245
246 cmd.flags = CMD_ON_DEMAND | CMD_SYNC;
247 cmd_want_skb = nla_get_flag(tb[IWL_TM_ATTR_UCODE_CMD_SKB]);
248 if (cmd_want_skb)
249 cmd.flags |= CMD_WANT_SKB;
250
251 cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]);
252 cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
253 cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
254 cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
255 IWL_DEBUG_INFO(tst->trans, "test fw cmd=0x%x, flags 0x%x, len %d\n",
256 cmd.id, cmd.flags, cmd.len[0]);
257
258 ret = iwl_test_send_cmd(tst, &cmd);
259 if (ret) {
260 IWL_ERR(tst->trans, "Failed to send hcmd\n");
261 return ret;
262 }
263 if (!cmd_want_skb)
264 return ret;
265
266 /* Handling return of SKB to the user */
267 pkt = cmd.resp_pkt;
268 if (!pkt) {
269 IWL_ERR(tst->trans, "HCMD received a null response packet\n");
270 return ret;
271 }
272
273 reply_len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
274 skb = iwl_test_alloc_reply(tst, reply_len + 20);
275 reply_buf = kmemdup(&pkt->hdr, reply_len, GFP_KERNEL);
276 if (!skb || !reply_buf) {
277 kfree_skb(skb);
278 kfree(reply_buf);
279 return -ENOMEM;
280 }
281
282 /* The reply is in a page, that we cannot send to user space. */
283 iwl_free_resp(&cmd);
284
285 if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND,
286 IWL_TM_CMD_DEV2APP_UCODE_RX_PKT) ||
287 nla_put(skb, IWL_TM_ATTR_UCODE_RX_PKT, reply_len, reply_buf))
288 goto nla_put_failure;
289 return iwl_test_reply(tst, skb);
290
291nla_put_failure:
292 IWL_DEBUG_INFO(tst->trans, "Failed creating NL attributes\n");
293 kfree(reply_buf);
294 kfree_skb(skb);
295 return -ENOMSG;
296}
297
298/*
299 * Handles the user application commands for register access.
300 */
301static int iwl_test_reg(struct iwl_test *tst, struct nlattr **tb)
302{
303 u32 ofs, val32, cmd;
304 u8 val8;
305 struct sk_buff *skb;
306 int status = 0;
307 struct iwl_trans *trans = tst->trans;
308
309 if (!tb[IWL_TM_ATTR_REG_OFFSET]) {
310 IWL_ERR(trans, "Missing reg offset\n");
311 return -ENOMSG;
312 }
313
314 ofs = nla_get_u32(tb[IWL_TM_ATTR_REG_OFFSET]);
315 IWL_DEBUG_INFO(trans, "test reg access cmd offset=0x%x\n", ofs);
316
317 cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]);
318
319 /*
320 * Allow access only to FH/CSR/HBUS in direct mode.
321 * Since we don't have the upper bounds for the CSR and HBUS segments,
322 * we will use only the upper bound of FH for sanity check.
323 */
324 if (ofs >= FH_MEM_UPPER_BOUND) {
325 IWL_ERR(trans, "offset out of segment (0x0 - 0x%x)\n",
326 FH_MEM_UPPER_BOUND);
327 return -EINVAL;
328 }
329
330 switch (cmd) {
331 case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32:
332 val32 = iwl_read_direct32(tst->trans, ofs);
333 IWL_DEBUG_INFO(trans, "32 value to read 0x%x\n", val32);
334
335 skb = iwl_test_alloc_reply(tst, 20);
336 if (!skb) {
337 IWL_ERR(trans, "Memory allocation fail\n");
338 return -ENOMEM;
339 }
340 if (nla_put_u32(skb, IWL_TM_ATTR_REG_VALUE32, val32))
341 goto nla_put_failure;
342 status = iwl_test_reply(tst, skb);
343 if (status < 0)
344 IWL_ERR(trans, "Error sending msg : %d\n", status);
345 break;
346
347 case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32:
348 if (!tb[IWL_TM_ATTR_REG_VALUE32]) {
349 IWL_ERR(trans, "Missing value to write\n");
350 return -ENOMSG;
351 } else {
352 val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]);
353 IWL_DEBUG_INFO(trans, "32b write val=0x%x\n", val32);
354 iwl_write_direct32(tst->trans, ofs, val32);
355 }
356 break;
357
358 case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8:
359 if (!tb[IWL_TM_ATTR_REG_VALUE8]) {
360 IWL_ERR(trans, "Missing value to write\n");
361 return -ENOMSG;
362 } else {
363 val8 = nla_get_u8(tb[IWL_TM_ATTR_REG_VALUE8]);
364 IWL_DEBUG_INFO(trans, "8b write val=0x%x\n", val8);
365 iwl_write8(tst->trans, ofs, val8);
366 }
367 break;
368
369 default:
370 IWL_ERR(trans, "Unknown test register cmd ID\n");
371 return -ENOMSG;
372 }
373
374 return status;
375
376nla_put_failure:
377 kfree_skb(skb);
378 return -EMSGSIZE;
379}
380
381/*
382 * Handles the request to start FW tracing. Allocates of the trace buffer
383 * and sends a reply to user space with the address of the allocated buffer.
384 */
385static int iwl_test_trace_begin(struct iwl_test *tst, struct nlattr **tb)
386{
387 struct sk_buff *skb;
388 int status = 0;
389
390 if (tst->trace.enabled)
391 return -EBUSY;
392
393 if (!tb[IWL_TM_ATTR_TRACE_SIZE])
394 tst->trace.size = TRACE_BUFF_SIZE_DEF;
395 else
396 tst->trace.size =
397 nla_get_u32(tb[IWL_TM_ATTR_TRACE_SIZE]);
398
399 if (!tst->trace.size)
400 return -EINVAL;
401
402 if (tst->trace.size < TRACE_BUFF_SIZE_MIN ||
403 tst->trace.size > TRACE_BUFF_SIZE_MAX)
404 return -EINVAL;
405
406 tst->trace.tsize = tst->trace.size + TRACE_BUFF_PADD;
407 tst->trace.cpu_addr = dma_alloc_coherent(tst->trans->dev,
408 tst->trace.tsize,
409 &tst->trace.dma_addr,
410 GFP_KERNEL);
411 if (!tst->trace.cpu_addr)
412 return -ENOMEM;
413
414 tst->trace.enabled = true;
415 tst->trace.trace_addr = (u8 *)PTR_ALIGN(tst->trace.cpu_addr, 0x100);
416
417 memset(tst->trace.trace_addr, 0x03B, tst->trace.size);
418
419 skb = iwl_test_alloc_reply(tst, sizeof(tst->trace.dma_addr) + 20);
420 if (!skb) {
421 IWL_ERR(tst->trans, "Memory allocation fail\n");
422 iwl_test_trace_stop(tst);
423 return -ENOMEM;
424 }
425
426 if (nla_put(skb, IWL_TM_ATTR_TRACE_ADDR,
427 sizeof(tst->trace.dma_addr),
428 (u64 *)&tst->trace.dma_addr))
429 goto nla_put_failure;
430
431 status = iwl_test_reply(tst, skb);
432 if (status < 0)
433 IWL_ERR(tst->trans, "Error sending msg : %d\n", status);
434
435 tst->trace.nchunks = DIV_ROUND_UP(tst->trace.size,
436 DUMP_CHUNK_SIZE);
437
438 return status;
439
440nla_put_failure:
441 kfree_skb(skb);
442 if (nla_get_u32(tb[IWL_TM_ATTR_COMMAND]) ==
443 IWL_TM_CMD_APP2DEV_BEGIN_TRACE)
444 iwl_test_trace_stop(tst);
445 return -EMSGSIZE;
446}
447
448/*
449 * Handles indirect read from the periphery or the SRAM. The read is performed
450 * to a temporary buffer. The user space application should later issue a dump
451 */
452static int iwl_test_indirect_read(struct iwl_test *tst, u32 addr, u32 size)
453{
454 struct iwl_trans *trans = tst->trans;
455 unsigned long flags;
456 int i;
457
458 if (size & 0x3)
459 return -EINVAL;
460
461 tst->mem.size = size;
462 tst->mem.addr = kmalloc(tst->mem.size, GFP_KERNEL);
463 if (tst->mem.addr == NULL)
464 return -ENOMEM;
465
466 /* Hard-coded periphery absolute address */
467 if (IWL_ABS_PRPH_START <= addr &&
468 addr < IWL_ABS_PRPH_START + PRPH_END) {
469 if (!iwl_trans_grab_nic_access(trans, false, &flags)) {
470 return -EIO;
471 }
472 iwl_write32(trans, HBUS_TARG_PRPH_RADDR,
473 addr | (3 << 24));
474 for (i = 0; i < size; i += 4)
475 *(u32 *)(tst->mem.addr + i) =
476 iwl_read32(trans, HBUS_TARG_PRPH_RDAT);
477 iwl_trans_release_nic_access(trans, &flags);
478 } else { /* target memory (SRAM) */
479 iwl_trans_read_mem(trans, addr, tst->mem.addr,
480 tst->mem.size / 4);
481 }
482
483 tst->mem.nchunks =
484 DIV_ROUND_UP(tst->mem.size, DUMP_CHUNK_SIZE);
485 tst->mem.in_read = true;
486 return 0;
487
488}
489
490/*
491 * Handles indirect write to the periphery or SRAM. The is performed to a
492 * temporary buffer.
493 */
494static int iwl_test_indirect_write(struct iwl_test *tst, u32 addr,
495 u32 size, unsigned char *buf)
496{
497 struct iwl_trans *trans = tst->trans;
498 u32 val, i;
499 unsigned long flags;
500
501 if (IWL_ABS_PRPH_START <= addr &&
502 addr < IWL_ABS_PRPH_START + PRPH_END) {
503 /* Periphery writes can be 1-3 bytes long, or DWORDs */
504 if (size < 4) {
505 memcpy(&val, buf, size);
506 if (!iwl_trans_grab_nic_access(trans, false, &flags))
507 return -EIO;
508 iwl_write32(trans, HBUS_TARG_PRPH_WADDR,
509 (addr & 0x0000FFFF) |
510 ((size - 1) << 24));
511 iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val);
512 iwl_trans_release_nic_access(trans, &flags);
513 } else {
514 if (size % 4)
515 return -EINVAL;
516 for (i = 0; i < size; i += 4)
517 iwl_write_prph(trans, addr+i,
518 *(u32 *)(buf+i));
519 }
520 } else if (iwl_test_valid_hw_addr(tst, addr)) {
521 iwl_trans_write_mem(trans, addr, buf, size / 4);
522 } else {
523 return -EINVAL;
524 }
525 return 0;
526}
527
528/*
529 * Handles the user application commands for indirect read/write
530 * to/from the periphery or the SRAM.
531 */
532static int iwl_test_indirect_mem(struct iwl_test *tst, struct nlattr **tb)
533{
534 u32 addr, size, cmd;
535 unsigned char *buf;
536
537 /* Both read and write should be blocked, for atomicity */
538 if (tst->mem.in_read)
539 return -EBUSY;
540
541 cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]);
542 if (!tb[IWL_TM_ATTR_MEM_ADDR]) {
543 IWL_ERR(tst->trans, "Error finding memory offset address\n");
544 return -ENOMSG;
545 }
546 addr = nla_get_u32(tb[IWL_TM_ATTR_MEM_ADDR]);
547 if (!tb[IWL_TM_ATTR_BUFFER_SIZE]) {
548 IWL_ERR(tst->trans, "Error finding size for memory reading\n");
549 return -ENOMSG;
550 }
551 size = nla_get_u32(tb[IWL_TM_ATTR_BUFFER_SIZE]);
552
553 if (cmd == IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ) {
554 return iwl_test_indirect_read(tst, addr, size);
555 } else {
556 if (!tb[IWL_TM_ATTR_BUFFER_DUMP])
557 return -EINVAL;
558 buf = (unsigned char *)nla_data(tb[IWL_TM_ATTR_BUFFER_DUMP]);
559 return iwl_test_indirect_write(tst, addr, size, buf);
560 }
561}
562
563/*
564 * Enable notifications to user space
565 */
566static int iwl_test_notifications(struct iwl_test *tst,
567 struct nlattr **tb)
568{
569 tst->notify = nla_get_flag(tb[IWL_TM_ATTR_ENABLE_NOTIFICATION]);
570 return 0;
571}
572
573/*
574 * Handles the request to get the device id
575 */
576static int iwl_test_get_dev_id(struct iwl_test *tst, struct nlattr **tb)
577{
578 u32 devid = tst->trans->hw_id;
579 struct sk_buff *skb;
580 int status;
581
582 IWL_DEBUG_INFO(tst->trans, "hw version: 0x%x\n", devid);
583
584 skb = iwl_test_alloc_reply(tst, 20);
585 if (!skb) {
586 IWL_ERR(tst->trans, "Memory allocation fail\n");
587 return -ENOMEM;
588 }
589
590 if (nla_put_u32(skb, IWL_TM_ATTR_DEVICE_ID, devid))
591 goto nla_put_failure;
592 status = iwl_test_reply(tst, skb);
593 if (status < 0)
594 IWL_ERR(tst->trans, "Error sending msg : %d\n", status);
595
596 return 0;
597
598nla_put_failure:
599 kfree_skb(skb);
600 return -EMSGSIZE;
601}
602
603/*
604 * Handles the request to get the FW version
605 */
606static int iwl_test_get_fw_ver(struct iwl_test *tst, struct nlattr **tb)
607{
608 struct sk_buff *skb;
609 int status;
610 u32 ver = iwl_test_fw_ver(tst);
611
612 IWL_DEBUG_INFO(tst->trans, "uCode version raw: 0x%x\n", ver);
613
614 skb = iwl_test_alloc_reply(tst, 20);
615 if (!skb) {
616 IWL_ERR(tst->trans, "Memory allocation fail\n");
617 return -ENOMEM;
618 }
619
620 if (nla_put_u32(skb, IWL_TM_ATTR_FW_VERSION, ver))
621 goto nla_put_failure;
622
623 status = iwl_test_reply(tst, skb);
624 if (status < 0)
625 IWL_ERR(tst->trans, "Error sending msg : %d\n", status);
626
627 return 0;
628
629nla_put_failure:
630 kfree_skb(skb);
631 return -EMSGSIZE;
632}
633
634/*
635 * Parse the netlink message and validate that the IWL_TM_ATTR_CMD exists
636 */
637int iwl_test_parse(struct iwl_test *tst, struct nlattr **tb,
638 void *data, int len)
639{
640 int result;
641
642 result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len,
643 iwl_testmode_gnl_msg_policy);
644 if (result) {
645 IWL_ERR(tst->trans, "Fail parse gnl msg: %d\n", result);
646 return result;
647 }
648
649 /* IWL_TM_ATTR_COMMAND is absolutely mandatory */
650 if (!tb[IWL_TM_ATTR_COMMAND]) {
651 IWL_ERR(tst->trans, "Missing testmode command type\n");
652 return -ENOMSG;
653 }
654 return 0;
655}
656IWL_EXPORT_SYMBOL(iwl_test_parse);
657
658/*
659 * Handle test commands.
660 * Returns 1 for unknown commands (not handled by the test object); negative
661 * value in case of error.
662 */
663int iwl_test_handle_cmd(struct iwl_test *tst, struct nlattr **tb)
664{
665 int result;
666
667 switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
668 case IWL_TM_CMD_APP2DEV_UCODE:
669 IWL_DEBUG_INFO(tst->trans, "test cmd to uCode\n");
670 result = iwl_test_fw_cmd(tst, tb);
671 break;
672
673 case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32:
674 case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32:
675 case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8:
676 IWL_DEBUG_INFO(tst->trans, "test cmd to register\n");
677 result = iwl_test_reg(tst, tb);
678 break;
679
680 case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
681 IWL_DEBUG_INFO(tst->trans, "test uCode trace cmd to driver\n");
682 result = iwl_test_trace_begin(tst, tb);
683 break;
684
685 case IWL_TM_CMD_APP2DEV_END_TRACE:
686 iwl_test_trace_stop(tst);
687 result = 0;
688 break;
689
690 case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ:
691 case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE:
692 IWL_DEBUG_INFO(tst->trans, "test indirect memory cmd\n");
693 result = iwl_test_indirect_mem(tst, tb);
694 break;
695
696 case IWL_TM_CMD_APP2DEV_NOTIFICATIONS:
697 IWL_DEBUG_INFO(tst->trans, "test notifications cmd\n");
698 result = iwl_test_notifications(tst, tb);
699 break;
700
701 case IWL_TM_CMD_APP2DEV_GET_FW_VERSION:
702 IWL_DEBUG_INFO(tst->trans, "test get FW ver cmd\n");
703 result = iwl_test_get_fw_ver(tst, tb);
704 break;
705
706 case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID:
707 IWL_DEBUG_INFO(tst->trans, "test Get device ID cmd\n");
708 result = iwl_test_get_dev_id(tst, tb);
709 break;
710
711 default:
712 IWL_DEBUG_INFO(tst->trans, "Unknown test command\n");
713 result = 1;
714 break;
715 }
716 return result;
717}
718IWL_EXPORT_SYMBOL(iwl_test_handle_cmd);
719
720static int iwl_test_trace_dump(struct iwl_test *tst, struct sk_buff *skb,
721 struct netlink_callback *cb)
722{
723 int idx, length;
724
725 if (!tst->trace.enabled || !tst->trace.trace_addr)
726 return -EFAULT;
727
728 idx = cb->args[4];
729 if (idx >= tst->trace.nchunks)
730 return -ENOENT;
731
732 length = DUMP_CHUNK_SIZE;
733 if (((idx + 1) == tst->trace.nchunks) &&
734 (tst->trace.size % DUMP_CHUNK_SIZE))
735 length = tst->trace.size %
736 DUMP_CHUNK_SIZE;
737
738 if (nla_put(skb, IWL_TM_ATTR_TRACE_DUMP, length,
739 tst->trace.trace_addr + (DUMP_CHUNK_SIZE * idx)))
740 goto nla_put_failure;
741
742 cb->args[4] = ++idx;
743 return 0;
744
745 nla_put_failure:
746 return -ENOBUFS;
747}
748
749static int iwl_test_buffer_dump(struct iwl_test *tst, struct sk_buff *skb,
750 struct netlink_callback *cb)
751{
752 int idx, length;
753
754 if (!tst->mem.in_read)
755 return -EFAULT;
756
757 idx = cb->args[4];
758 if (idx >= tst->mem.nchunks) {
759 iwl_test_mem_stop(tst);
760 return -ENOENT;
761 }
762
763 length = DUMP_CHUNK_SIZE;
764 if (((idx + 1) == tst->mem.nchunks) &&
765 (tst->mem.size % DUMP_CHUNK_SIZE))
766 length = tst->mem.size % DUMP_CHUNK_SIZE;
767
768 if (nla_put(skb, IWL_TM_ATTR_BUFFER_DUMP, length,
769 tst->mem.addr + (DUMP_CHUNK_SIZE * idx)))
770 goto nla_put_failure;
771
772 cb->args[4] = ++idx;
773 return 0;
774
775 nla_put_failure:
776 return -ENOBUFS;
777}
778
779/*
780 * Handle dump commands.
781 * Returns 1 for unknown commands (not handled by the test object); negative
782 * value in case of error.
783 */
784int iwl_test_dump(struct iwl_test *tst, u32 cmd, struct sk_buff *skb,
785 struct netlink_callback *cb)
786{
787 int result;
788
789 switch (cmd) {
790 case IWL_TM_CMD_APP2DEV_READ_TRACE:
791 IWL_DEBUG_INFO(tst->trans, "uCode trace cmd\n");
792 result = iwl_test_trace_dump(tst, skb, cb);
793 break;
794
795 case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP:
796 IWL_DEBUG_INFO(tst->trans, "testmode sram dump cmd\n");
797 result = iwl_test_buffer_dump(tst, skb, cb);
798 break;
799
800 default:
801 result = 1;
802 break;
803 }
804 return result;
805}
806IWL_EXPORT_SYMBOL(iwl_test_dump);
807
808/*
809 * Multicast a spontaneous messages from the device to the user space.
810 */
811static void iwl_test_send_rx(struct iwl_test *tst,
812 struct iwl_rx_cmd_buffer *rxb)
813{
814 struct sk_buff *skb;
815 struct iwl_rx_packet *data;
816 int length;
817
818 data = rxb_addr(rxb);
819 length = le32_to_cpu(data->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
820
821 /* the length doesn't include len_n_flags field, so add it manually */
822 length += sizeof(__le32);
823
824 skb = iwl_test_alloc_event(tst, length + 20);
825 if (skb == NULL) {
826 IWL_ERR(tst->trans, "Out of memory for message to user\n");
827 return;
828 }
829
830 if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND,
831 IWL_TM_CMD_DEV2APP_UCODE_RX_PKT) ||
832 nla_put(skb, IWL_TM_ATTR_UCODE_RX_PKT, length, data))
833 goto nla_put_failure;
834
835 iwl_test_event(tst, skb);
836 return;
837
838nla_put_failure:
839 kfree_skb(skb);
840 IWL_ERR(tst->trans, "Ouch, overran buffer, check allocation!\n");
841}
842
843/*
844 * Called whenever a Rx frames is recevied from the device. If notifications to
845 * the user space are requested, sends the frames to the user.
846 */
847void iwl_test_rx(struct iwl_test *tst, struct iwl_rx_cmd_buffer *rxb)
848{
849 if (tst->notify)
850 iwl_test_send_rx(tst, rxb);
851}
852IWL_EXPORT_SYMBOL(iwl_test_rx);
diff --git a/drivers/net/wireless/iwlwifi/iwl-test.h b/drivers/net/wireless/iwlwifi/iwl-test.h
deleted file mode 100644
index 8fbd21704840..000000000000
--- a/drivers/net/wireless/iwlwifi/iwl-test.h
+++ /dev/null
@@ -1,161 +0,0 @@
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) 2010 - 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) 2010 - 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#ifndef __IWL_TEST_H__
65#define __IWL_TEST_H__
66
67#include <linux/types.h>
68#include "iwl-trans.h"
69
70struct iwl_test_trace {
71 u32 size;
72 u32 tsize;
73 u32 nchunks;
74 u8 *cpu_addr;
75 u8 *trace_addr;
76 dma_addr_t dma_addr;
77 bool enabled;
78};
79
80struct iwl_test_mem {
81 u32 size;
82 u32 nchunks;
83 u8 *addr;
84 bool in_read;
85};
86
87/*
88 * struct iwl_test_ops: callback to the op mode
89 *
90 * The structure defines the callbacks that the op_mode should handle,
91 * inorder to handle logic that is out of the scope of iwl_test. The
92 * op_mode must set all the callbacks.
93
94 * @send_cmd: handler that is used by the test object to request the
95 * op_mode to send a command to the fw.
96 *
97 * @valid_hw_addr: handler that is used by the test object to request the
98 * op_mode to check if the given address is a valid address.
99 *
100 * @get_fw_ver: handler used to get the FW version.
101 *
102 * @alloc_reply: handler used by the test object to request the op_mode
103 * to allocate an skb for sending a reply to the user, and initialize
104 * the skb. It is assumed that the test object only fills the required
105 * attributes.
106 *
107 * @reply: handler used by the test object to request the op_mode to reply
108 * to a request. The skb is an skb previously allocated by the the
109 * alloc_reply callback.
110 I
111 * @alloc_event: handler used by the test object to request the op_mode
112 * to allocate an skb for sending an event, and initialize
113 * the skb. It is assumed that the test object only fills the required
114 * attributes.
115 *
116 * @reply: handler used by the test object to request the op_mode to send
117 * an event. The skb is an skb previously allocated by the the
118 * alloc_event callback.
119 */
120struct iwl_test_ops {
121 int (*send_cmd)(struct iwl_op_mode *op_modes,
122 struct iwl_host_cmd *cmd);
123 bool (*valid_hw_addr)(u32 addr);
124 u32 (*get_fw_ver)(struct iwl_op_mode *op_mode);
125
126 struct sk_buff *(*alloc_reply)(struct iwl_op_mode *op_mode, int len);
127 int (*reply)(struct iwl_op_mode *op_mode, struct sk_buff *skb);
128 struct sk_buff* (*alloc_event)(struct iwl_op_mode *op_mode, int len);
129 void (*event)(struct iwl_op_mode *op_mode, struct sk_buff *skb);
130};
131
132struct iwl_test {
133 struct iwl_trans *trans;
134 struct iwl_test_ops *ops;
135 struct iwl_test_trace trace;
136 struct iwl_test_mem mem;
137 bool notify;
138};
139
140void iwl_test_init(struct iwl_test *tst, struct iwl_trans *trans,
141 struct iwl_test_ops *ops);
142
143void iwl_test_free(struct iwl_test *tst);
144
145int iwl_test_parse(struct iwl_test *tst, struct nlattr **tb,
146 void *data, int len);
147
148int iwl_test_handle_cmd(struct iwl_test *tst, struct nlattr **tb);
149
150int iwl_test_dump(struct iwl_test *tst, u32 cmd, struct sk_buff *skb,
151 struct netlink_callback *cb);
152
153void iwl_test_rx(struct iwl_test *tst, struct iwl_rx_cmd_buffer *rxb);
154
155static inline void iwl_test_enable_notifications(struct iwl_test *tst,
156 bool enable)
157{
158 tst->notify = enable;
159}
160
161#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h
deleted file mode 100644
index 98f48a9afc98..000000000000
--- a/drivers/net/wireless/iwlwifi/iwl-testmode.h
+++ /dev/null
@@ -1,309 +0,0 @@
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) 2010 - 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) 2010 - 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 __IWL_TESTMODE_H__
64#define __IWL_TESTMODE_H__
65
66#include <linux/types.h>
67
68
69/*
70 * Commands from user space to kernel space(IWL_TM_CMD_ID_APP2DEV_XX) and
71 * from and kernel space to user space(IWL_TM_CMD_ID_DEV2APP_XX).
72 * The command ID is carried with IWL_TM_ATTR_COMMAND.
73 *
74 * @IWL_TM_CMD_APP2DEV_UCODE:
75 * commands from user application to the uCode,
76 * the actual uCode host command ID is carried with
77 * IWL_TM_ATTR_UCODE_CMD_ID
78 *
79 * @IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32:
80 * @IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32:
81 * @IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8:
82 * commands from user applicaiton to access register
83 *
84 * @IWL_TM_CMD_APP2DEV_GET_DEVICENAME: retrieve device name
85 * @IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: load initial uCode image
86 * @IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: perform calibration
87 * @IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: load runtime uCode image
88 * @IWL_TM_CMD_APP2DEV_GET_EEPROM: request EEPROM data
89 * @IWL_TM_CMD_APP2DEV_FIXRATE_REQ: set fix MCS
90 * commands fom user space for pure driver level operations
91 *
92 * @IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
93 * @IWL_TM_CMD_APP2DEV_END_TRACE:
94 * @IWL_TM_CMD_APP2DEV_READ_TRACE:
95 * commands fom user space for uCode trace operations
96 *
97 * @IWL_TM_CMD_DEV2APP_SYNC_RSP:
98 * commands from kernel space to carry the synchronous response
99 * to user application
100 * @IWL_TM_CMD_DEV2APP_UCODE_RX_PKT:
101 * commands from kernel space to multicast the spontaneous messages
102 * to user application, or reply of host commands
103 * @IWL_TM_CMD_DEV2APP_EEPROM_RSP:
104 * commands from kernel space to carry the eeprom response
105 * to user application
106 *
107 * @IWL_TM_CMD_APP2DEV_OWNERSHIP:
108 * commands from user application to own change the ownership of the uCode
109 * if application has the ownership, the only host command from
110 * testmode will deliver to uCode. Default owner is driver
111 *
112 * @IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: load Wake On Wireless LAN uCode image
113 * @IWL_TM_CMD_APP2DEV_GET_FW_VERSION: retrieve uCode version
114 * @IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: retrieve ID information in device
115 * @IWL_TM_CMD_APP2DEV_GET_FW_INFO:
116 * retrieve information of existing loaded uCode image
117 *
118 * @IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ:
119 * @IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP:
120 * @IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE:
121 * Commands to read/write data from periphery or SRAM memory ranges.
122 * Fore reading, a READ command is sent from the userspace and the data
123 * is returned when the user calls a DUMP command.
124 * For writing, only a WRITE command is used.
125 * @IWL_TM_CMD_APP2DEV_NOTIFICATIONS:
126 * Command to enable/disable notifications (currently RX packets) from the
127 * driver to userspace.
128 */
129enum iwl_tm_cmd_t {
130 IWL_TM_CMD_APP2DEV_UCODE = 1,
131 IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32 = 2,
132 IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32 = 3,
133 IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8 = 4,
134 IWL_TM_CMD_APP2DEV_GET_DEVICENAME = 5,
135 IWL_TM_CMD_APP2DEV_LOAD_INIT_FW = 6,
136 IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB = 7,
137 IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW = 8,
138 IWL_TM_CMD_APP2DEV_GET_EEPROM = 9,
139 IWL_TM_CMD_APP2DEV_FIXRATE_REQ = 10,
140 IWL_TM_CMD_APP2DEV_BEGIN_TRACE = 11,
141 IWL_TM_CMD_APP2DEV_END_TRACE = 12,
142 IWL_TM_CMD_APP2DEV_READ_TRACE = 13,
143 IWL_TM_CMD_DEV2APP_SYNC_RSP = 14,
144 IWL_TM_CMD_DEV2APP_UCODE_RX_PKT = 15,
145 IWL_TM_CMD_DEV2APP_EEPROM_RSP = 16,
146 IWL_TM_CMD_APP2DEV_OWNERSHIP = 17,
147 RESERVED_18 = 18,
148 RESERVED_19 = 19,
149 RESERVED_20 = 20,
150 RESERVED_21 = 21,
151 IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW = 22,
152 IWL_TM_CMD_APP2DEV_GET_FW_VERSION = 23,
153 IWL_TM_CMD_APP2DEV_GET_DEVICE_ID = 24,
154 IWL_TM_CMD_APP2DEV_GET_FW_INFO = 25,
155 IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ = 26,
156 IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP = 27,
157 IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE = 28,
158 IWL_TM_CMD_APP2DEV_NOTIFICATIONS = 29,
159 IWL_TM_CMD_MAX = 30,
160};
161
162/*
163 * Atrribute filed in testmode command
164 * See enum iwl_tm_cmd_t.
165 *
166 * @IWL_TM_ATTR_NOT_APPLICABLE:
167 * The attribute is not applicable or invalid
168 * @IWL_TM_ATTR_COMMAND:
169 * From user space to kernel space:
170 * the command either destines to ucode, driver, or register;
171 * From kernel space to user space:
172 * the command either carries synchronous response,
173 * or the spontaneous message multicast from the device;
174 *
175 * @IWL_TM_ATTR_UCODE_CMD_ID:
176 * @IWL_TM_ATTR_UCODE_CMD_DATA:
177 * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE,
178 * The mandatory fields are :
179 * IWL_TM_ATTR_UCODE_CMD_ID for recognizable command ID;
180 * IWL_TM_ATTR_UCODE_CMD_DATA for the actual command payload
181 * to the ucode
182 *
183 * @IWL_TM_ATTR_REG_OFFSET:
184 * @IWL_TM_ATTR_REG_VALUE8:
185 * @IWL_TM_ATTR_REG_VALUE32:
186 * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_REG_XXX,
187 * The mandatory fields are:
188 * IWL_TM_ATTR_REG_OFFSET for the offset of the target register;
189 * IWL_TM_ATTR_REG_VALUE8 or IWL_TM_ATTR_REG_VALUE32 for value
190 *
191 * @IWL_TM_ATTR_SYNC_RSP:
192 * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_SYNC_RSP,
193 * The mandatory fields are:
194 * IWL_TM_ATTR_SYNC_RSP for the data content responding to the user
195 * application command
196 *
197 * @IWL_TM_ATTR_UCODE_RX_PKT:
198 * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_UCODE_RX_PKT,
199 * The mandatory fields are:
200 * IWL_TM_ATTR_UCODE_RX_PKT for the data content multicast to the user
201 * application
202 *
203 * @IWL_TM_ATTR_EEPROM:
204 * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_EEPROM,
205 * The mandatory fields are:
206 * IWL_TM_ATTR_EEPROM for the data content responging to the user
207 * application
208 *
209 * @IWL_TM_ATTR_TRACE_ADDR:
210 * @IWL_TM_ATTR_TRACE_SIZE:
211 * @IWL_TM_ATTR_TRACE_DUMP:
212 * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_XXX_TRACE,
213 * The mandatory fields are:
214 * IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address
215 * IWL_TM_ATTR_MEM_TRACE_SIZE for the trace buffer size
216 * IWL_TM_ATTR_MEM_TRACE_DUMP for the trace dump
217 *
218 * @IWL_TM_ATTR_FIXRATE:
219 * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_FIXRATE_REQ,
220 * The mandatory fields are:
221 * IWL_TM_ATTR_FIXRATE for the fixed rate
222 *
223 * @IWL_TM_ATTR_UCODE_OWNER:
224 * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_OWNERSHIP,
225 * The mandatory fields are:
226 * IWL_TM_ATTR_UCODE_OWNER for the new owner
227 *
228 * @IWL_TM_ATTR_MEM_ADDR:
229 * @IWL_TM_ATTR_BUFFER_SIZE:
230 * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ
231 * or IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE.
232 * The mandatory fields are:
233 * IWL_TM_ATTR_MEM_ADDR for the address in SRAM/periphery to read/write
234 * IWL_TM_ATTR_BUFFER_SIZE for the buffer size of data to read/write.
235 *
236 * @IWL_TM_ATTR_BUFFER_DUMP:
237 * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP,
238 * IWL_TM_ATTR_BUFFER_DUMP is used for the data that was read.
239 * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE,
240 * this attribute contains the data to write.
241 *
242 * @IWL_TM_ATTR_FW_VERSION:
243 * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_GET_FW_VERSION,
244 * IWL_TM_ATTR_FW_VERSION for the uCode version
245 *
246 * @IWL_TM_ATTR_DEVICE_ID:
247 * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_GET_DEVICE_ID,
248 * IWL_TM_ATTR_DEVICE_ID for the device ID information
249 *
250 * @IWL_TM_ATTR_FW_TYPE:
251 * @IWL_TM_ATTR_FW_INST_SIZE:
252 * @IWL_TM_ATTR_FW_DATA_SIZE:
253 * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_GET_FW_INFO,
254 * The mandatory fields are:
255 * IWL_TM_ATTR_FW_TYPE for the uCode type (INIT/RUNTIME/...)
256 * IWL_TM_ATTR_FW_INST_SIZE for the size of instruction section
257 * IWL_TM_ATTR_FW_DATA_SIZE for the size of data section
258 *
259 * @IWL_TM_ATTR_UCODE_CMD_SKB:
260 * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE this flag
261 * indicates that the user wants to receive the response of the command
262 * in a reply SKB. If it's not present, the response is not returned.
263 * @IWL_TM_ATTR_ENABLE_NOTIFICATIONS:
264 * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_NOTIFICATIONS, this
265 * flag enables (if present) or disables (if not) the forwarding
266 * to userspace.
267 */
268enum iwl_tm_attr_t {
269 IWL_TM_ATTR_NOT_APPLICABLE = 0,
270 IWL_TM_ATTR_COMMAND = 1,
271 IWL_TM_ATTR_UCODE_CMD_ID = 2,
272 IWL_TM_ATTR_UCODE_CMD_DATA = 3,
273 IWL_TM_ATTR_REG_OFFSET = 4,
274 IWL_TM_ATTR_REG_VALUE8 = 5,
275 IWL_TM_ATTR_REG_VALUE32 = 6,
276 IWL_TM_ATTR_SYNC_RSP = 7,
277 IWL_TM_ATTR_UCODE_RX_PKT = 8,
278 IWL_TM_ATTR_EEPROM = 9,
279 IWL_TM_ATTR_TRACE_ADDR = 10,
280 IWL_TM_ATTR_TRACE_SIZE = 11,
281 IWL_TM_ATTR_TRACE_DUMP = 12,
282 IWL_TM_ATTR_FIXRATE = 13,
283 IWL_TM_ATTR_UCODE_OWNER = 14,
284 IWL_TM_ATTR_MEM_ADDR = 15,
285 IWL_TM_ATTR_BUFFER_SIZE = 16,
286 IWL_TM_ATTR_BUFFER_DUMP = 17,
287 IWL_TM_ATTR_FW_VERSION = 18,
288 IWL_TM_ATTR_DEVICE_ID = 19,
289 IWL_TM_ATTR_FW_TYPE = 20,
290 IWL_TM_ATTR_FW_INST_SIZE = 21,
291 IWL_TM_ATTR_FW_DATA_SIZE = 22,
292 IWL_TM_ATTR_UCODE_CMD_SKB = 23,
293 IWL_TM_ATTR_ENABLE_NOTIFICATION = 24,
294 IWL_TM_ATTR_MAX = 25,
295};
296
297/* uCode trace buffer */
298#define TRACE_BUFF_SIZE_MAX 0x200000
299#define TRACE_BUFF_SIZE_MIN 0x20000
300#define TRACE_BUFF_SIZE_DEF TRACE_BUFF_SIZE_MIN
301#define TRACE_BUFF_PADD 0x2000
302
303/* Maximum data size of each dump it packet */
304#define DUMP_CHUNK_SIZE (PAGE_SIZE - 1024)
305
306/* Address offset of data segment in SRAM */
307#define SRAM_DATA_SEG_OFFSET 0x800000
308
309#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index be4b2ac3dbbf..8d91422c5982 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -183,14 +183,12 @@ struct iwl_rx_packet {
183 * @CMD_ASYNC: Return right away and don't want for the response 183 * @CMD_ASYNC: Return right away and don't want for the response
184 * @CMD_WANT_SKB: valid only with CMD_SYNC. The caller needs the buffer of the 184 * @CMD_WANT_SKB: valid only with CMD_SYNC. The caller needs the buffer of the
185 * response. The caller needs to call iwl_free_resp when done. 185 * response. The caller needs to call iwl_free_resp when done.
186 * @CMD_ON_DEMAND: This command is sent by the test mode pipe.
187 */ 186 */
188enum CMD_MODE { 187enum CMD_MODE {
189 CMD_SYNC = 0, 188 CMD_SYNC = 0,
190 CMD_ASYNC = BIT(0), 189 CMD_ASYNC = BIT(0),
191 CMD_WANT_SKB = BIT(1), 190 CMD_WANT_SKB = BIT(1),
192 CMD_SEND_IN_RFKILL = BIT(2), 191 CMD_SEND_IN_RFKILL = BIT(2),
193 CMD_ON_DEMAND = BIT(3),
194}; 192};
195 193
196#define DEF_CMD_PAYLOAD_SIZE 320 194#define DEF_CMD_PAYLOAD_SIZE 320
diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
index 9a4d94a1f90d..dbd622a3929c 100644
--- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
+++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
@@ -202,6 +202,22 @@ static const __le32 iwl_concurrent_lookup[BT_COEX_LUT_SIZE] = {
202 cpu_to_le32(0x00000000), 202 cpu_to_le32(0x00000000),
203}; 203};
204 204
205/* single shared antenna */
206static const __le32 iwl_single_shared_ant_lookup[BT_COEX_LUT_SIZE] = {
207 cpu_to_le32(0x40000000),
208 cpu_to_le32(0x00000000),
209 cpu_to_le32(0x44000000),
210 cpu_to_le32(0x00000000),
211 cpu_to_le32(0x40000000),
212 cpu_to_le32(0x00000000),
213 cpu_to_le32(0x44000000),
214 cpu_to_le32(0x00000000),
215 cpu_to_le32(0xC0004000),
216 cpu_to_le32(0xF0005000),
217 cpu_to_le32(0xC0004000),
218 cpu_to_le32(0xF0005000),
219};
220
205int iwl_send_bt_init_conf(struct iwl_mvm *mvm) 221int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
206{ 222{
207 struct iwl_bt_coex_cmd cmd = { 223 struct iwl_bt_coex_cmd cmd = {
@@ -225,7 +241,10 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
225 BT_VALID_REDUCED_TX_POWER | 241 BT_VALID_REDUCED_TX_POWER |
226 BT_VALID_LUT); 242 BT_VALID_LUT);
227 243
228 if (is_loose_coex()) 244 if (mvm->cfg->bt_shared_single_ant)
245 memcpy(&cmd.decision_lut, iwl_single_shared_ant_lookup,
246 sizeof(iwl_single_shared_ant_lookup));
247 else if (is_loose_coex())
229 memcpy(&cmd.decision_lut, iwl_loose_lookup, 248 memcpy(&cmd.decision_lut, iwl_loose_lookup,
230 sizeof(iwl_tight_lookup)); 249 sizeof(iwl_tight_lookup));
231 else 250 else
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c
index 8c49db02c9c1..7e5e5c2f9f87 100644
--- a/drivers/net/wireless/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/iwlwifi/mvm/d3.c
@@ -1026,6 +1026,12 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
1026 if (ret) 1026 if (ret)
1027 goto out; 1027 goto out;
1028 1028
1029#ifdef CONFIG_IWLWIFI_DEBUGFS
1030 if (mvm->d3_wake_sysassert)
1031 d3_cfg_cmd_data.wakeup_flags |=
1032 cpu_to_le32(IWL_WAKEUP_D3_CONFIG_FW_ERROR);
1033#endif
1034
1029 /* must be last -- this switches firmware state */ 1035 /* must be last -- this switches firmware state */
1030 ret = iwl_mvm_send_cmd(mvm, &d3_cfg_cmd); 1036 ret = iwl_mvm_send_cmd(mvm, &d3_cfg_cmd);
1031 if (ret) 1037 if (ret)
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index b7643c16201f..e56ed2a84888 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -344,6 +344,13 @@ static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm,
344 case MVM_DEBUGFS_PM_DISABLE_POWER_OFF: 344 case MVM_DEBUGFS_PM_DISABLE_POWER_OFF:
345 IWL_DEBUG_POWER(mvm, "disable_power_off=%d\n", val); 345 IWL_DEBUG_POWER(mvm, "disable_power_off=%d\n", val);
346 dbgfs_pm->disable_power_off = val; 346 dbgfs_pm->disable_power_off = val;
347 case MVM_DEBUGFS_PM_LPRX_ENA:
348 IWL_DEBUG_POWER(mvm, "lprx %s\n", val ? "enabled" : "disabled");
349 dbgfs_pm->lprx_ena = val;
350 break;
351 case MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD:
352 IWL_DEBUG_POWER(mvm, "lprx_rssi_threshold=%d\n", val);
353 dbgfs_pm->lprx_rssi_threshold = val;
347 break; 354 break;
348 } 355 }
349} 356}
@@ -387,6 +394,17 @@ static ssize_t iwl_dbgfs_pm_params_write(struct file *file,
387 if (sscanf(buf + 18, "%d", &val) != 1) 394 if (sscanf(buf + 18, "%d", &val) != 1)
388 return -EINVAL; 395 return -EINVAL;
389 param = MVM_DEBUGFS_PM_DISABLE_POWER_OFF; 396 param = MVM_DEBUGFS_PM_DISABLE_POWER_OFF;
397 } else if (!strncmp("lprx=", buf, 5)) {
398 if (sscanf(buf + 5, "%d", &val) != 1)
399 return -EINVAL;
400 param = MVM_DEBUGFS_PM_LPRX_ENA;
401 } else if (!strncmp("lprx_rssi_threshold=", buf, 20)) {
402 if (sscanf(buf + 20, "%d", &val) != 1)
403 return -EINVAL;
404 if (val > POWER_LPRX_RSSI_THRESHOLD_MAX || val <
405 POWER_LPRX_RSSI_THRESHOLD_MIN)
406 return -EINVAL;
407 param = MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD;
390 } else { 408 } else {
391 return -EINVAL; 409 return -EINVAL;
392 } 410 }
@@ -421,7 +439,7 @@ static ssize_t iwl_dbgfs_pm_params_read(struct file *file,
421 le32_to_cpu(cmd.skip_dtim_periods)); 439 le32_to_cpu(cmd.skip_dtim_periods));
422 pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n", 440 pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
423 iwlmvm_mod_params.power_scheme); 441 iwlmvm_mod_params.power_scheme);
424 pos += scnprintf(buf+pos, bufsz-pos, "flags = %d\n", 442 pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
425 le16_to_cpu(cmd.flags)); 443 le16_to_cpu(cmd.flags));
426 pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n", 444 pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
427 cmd.keep_alive_seconds); 445 cmd.keep_alive_seconds);
@@ -435,6 +453,10 @@ static ssize_t iwl_dbgfs_pm_params_read(struct file *file,
435 le32_to_cpu(cmd.rx_data_timeout)); 453 le32_to_cpu(cmd.rx_data_timeout));
436 pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n", 454 pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
437 le32_to_cpu(cmd.tx_data_timeout)); 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));
438 } 460 }
439 461
440 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 462 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
@@ -939,6 +961,9 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
939#ifdef CONFIG_PM_SLEEP 961#ifdef CONFIG_PM_SLEEP
940 MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR); 962 MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
941 MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, S_IRUSR); 963 MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, S_IRUSR);
964 if (!debugfs_create_bool("d3_wake_sysassert", S_IRUSR | S_IWUSR,
965 mvm->debugfs_dir, &mvm->d3_wake_sysassert))
966 goto err;
942#endif 967#endif
943 968
944 /* 969 /*
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
index d8e19290b0f3..a6da359a80c3 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
@@ -66,6 +66,11 @@
66 66
67/* Power Management Commands, Responses, Notifications */ 67/* Power Management Commands, Responses, Notifications */
68 68
69/* Radio LP RX Energy Threshold measured in dBm */
70#define POWER_LPRX_RSSI_THRESHOLD 75
71#define POWER_LPRX_RSSI_THRESHOLD_MAX 94
72#define POWER_LPRX_RSSI_THRESHOLD_MIN 30
73
69/** 74/**
70 * enum iwl_scan_flags - masks for power table command flags 75 * enum iwl_scan_flags - masks for power table command flags
71 * @POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off 76 * @POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
index 273b0cc197ab..94aae9c8562c 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
@@ -865,6 +865,30 @@ int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
865 return ret; 865 return ret;
866} 866}
867 867
868struct iwl_mvm_mac_ap_iterator_data {
869 struct iwl_mvm *mvm;
870 struct ieee80211_vif *vif;
871 u32 beacon_device_ts;
872 u16 beacon_int;
873};
874
875/* Find the beacon_device_ts and beacon_int for a managed interface */
876static void iwl_mvm_mac_ap_iterator(void *_data, u8 *mac,
877 struct ieee80211_vif *vif)
878{
879 struct iwl_mvm_mac_ap_iterator_data *data = _data;
880
881 if (vif->type != NL80211_IFTYPE_STATION || !vif->bss_conf.assoc)
882 return;
883
884 /* Station client has higher priority over P2P client*/
885 if (vif->p2p && data->beacon_device_ts)
886 return;
887
888 data->beacon_device_ts = vif->bss_conf.sync_device_ts;
889 data->beacon_int = vif->bss_conf.beacon_int;
890}
891
868/* 892/*
869 * Fill the specific data for mac context of type AP of P2P GO 893 * Fill the specific data for mac context of type AP of P2P GO
870 */ 894 */
@@ -874,6 +898,11 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
874 bool add) 898 bool add)
875{ 899{
876 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 900 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
901 struct iwl_mvm_mac_ap_iterator_data data = {
902 .mvm = mvm,
903 .vif = vif,
904 .beacon_device_ts = 0
905 };
877 906
878 ctxt_ap->bi = cpu_to_le32(vif->bss_conf.beacon_int); 907 ctxt_ap->bi = cpu_to_le32(vif->bss_conf.beacon_int);
879 ctxt_ap->bi_reciprocal = 908 ctxt_ap->bi_reciprocal =
@@ -887,16 +916,33 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
887 ctxt_ap->mcast_qid = cpu_to_le32(vif->cab_queue); 916 ctxt_ap->mcast_qid = cpu_to_le32(vif->cab_queue);
888 917
889 /* 918 /*
890 * Only read the system time when the MAC is being added, when we 919 * Only set the beacon time when the MAC is being added, when we
891 * just modify the MAC then we should keep the time -- the firmware 920 * just modify the MAC then we should keep the time -- the firmware
892 * can otherwise have a "jumping" TBTT. 921 * can otherwise have a "jumping" TBTT.
893 */ 922 */
894 if (add) 923 if (add) {
895 mvmvif->ap_beacon_time = 924 /*
896 iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG); 925 * If there is a station/P2P client interface which is
926 * associated, set the AP's TBTT far enough from the station's
927 * TBTT. Otherwise, set it to the current system time
928 */
929 ieee80211_iterate_active_interfaces_atomic(
930 mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
931 iwl_mvm_mac_ap_iterator, &data);
932
933 if (data.beacon_device_ts) {
934 u32 rand = (prandom_u32() % (80 - 20)) + 20;
935 mvmvif->ap_beacon_time = data.beacon_device_ts +
936 ieee80211_tu_to_usec(data.beacon_int * rand /
937 100);
938 } else {
939 mvmvif->ap_beacon_time =
940 iwl_read_prph(mvm->trans,
941 DEVICE_SYSTEM_TIME_REG);
942 }
943 }
897 944
898 ctxt_ap->beacon_time = cpu_to_le32(mvmvif->ap_beacon_time); 945 ctxt_ap->beacon_time = cpu_to_le32(mvmvif->ap_beacon_time);
899
900 ctxt_ap->beacon_tsf = 0; /* unused */ 946 ctxt_ap->beacon_tsf = 0; /* unused */
901 947
902 /* TODO: Assume that the beacon id == mac context id */ 948 /* TODO: Assume that the beacon id == mac context id */
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index c7409f159a36..d40d7db185d6 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -73,7 +73,6 @@
73#include "iwl-trans.h" 73#include "iwl-trans.h"
74#include "iwl-notif-wait.h" 74#include "iwl-notif-wait.h"
75#include "iwl-eeprom-parse.h" 75#include "iwl-eeprom-parse.h"
76#include "iwl-test.h"
77#include "iwl-trans.h" 76#include "iwl-trans.h"
78#include "sta.h" 77#include "sta.h"
79#include "fw-api.h" 78#include "fw-api.h"
@@ -159,6 +158,8 @@ enum iwl_dbgfs_pm_mask {
159 MVM_DEBUGFS_PM_RX_DATA_TIMEOUT = BIT(3), 158 MVM_DEBUGFS_PM_RX_DATA_TIMEOUT = BIT(3),
160 MVM_DEBUGFS_PM_TX_DATA_TIMEOUT = BIT(4), 159 MVM_DEBUGFS_PM_TX_DATA_TIMEOUT = BIT(4),
161 MVM_DEBUGFS_PM_DISABLE_POWER_OFF = BIT(5), 160 MVM_DEBUGFS_PM_DISABLE_POWER_OFF = BIT(5),
161 MVM_DEBUGFS_PM_LPRX_ENA = BIT(6),
162 MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD = BIT(7),
162}; 163};
163 164
164struct iwl_dbgfs_pm { 165struct iwl_dbgfs_pm {
@@ -168,6 +169,8 @@ struct iwl_dbgfs_pm {
168 bool skip_over_dtim; 169 bool skip_over_dtim;
169 u8 skip_dtim_periods; 170 u8 skip_dtim_periods;
170 bool disable_power_off; 171 bool disable_power_off;
172 bool lprx_ena;
173 u32 lprx_rssi_threshold;
171 int mask; 174 int mask;
172}; 175};
173 176
@@ -353,12 +356,14 @@ struct iwl_tt_params {
353 * @dynamic_smps: Is thermal throttling enabled dynamic_smps? 356 * @dynamic_smps: Is thermal throttling enabled dynamic_smps?
354 * @tx_backoff: The current thremal throttling tx backoff in uSec. 357 * @tx_backoff: The current thremal throttling tx backoff in uSec.
355 * @params: Parameters to configure the thermal throttling algorithm. 358 * @params: Parameters to configure the thermal throttling algorithm.
359 * @throttle: Is thermal throttling is active?
356 */ 360 */
357struct iwl_mvm_tt_mgmt { 361struct iwl_mvm_tt_mgmt {
358 struct delayed_work ct_kill_exit; 362 struct delayed_work ct_kill_exit;
359 bool dynamic_smps; 363 bool dynamic_smps;
360 u32 tx_backoff; 364 u32 tx_backoff;
361 const struct iwl_tt_params *params; 365 const struct iwl_tt_params *params;
366 bool throttle;
362}; 367};
363 368
364struct iwl_mvm { 369struct iwl_mvm {
@@ -461,6 +466,7 @@ struct iwl_mvm {
461 struct wiphy_wowlan_support wowlan; 466 struct wiphy_wowlan_support wowlan;
462 int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen; 467 int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen;
463#ifdef CONFIG_IWLWIFI_DEBUGFS 468#ifdef CONFIG_IWLWIFI_DEBUGFS
469 u32 d3_wake_sysassert; /* must be u32 for debugfs_create_bool */
464 bool d3_test_active; 470 bool d3_test_active;
465 bool store_d3_resume_sram; 471 bool store_d3_resume_sram;
466 void *d3_resume_sram; 472 void *d3_resume_sram;
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c
index 3760a33ca3a4..e7ca965a89b8 100644
--- a/drivers/net/wireless/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/iwlwifi/mvm/power.c
@@ -137,11 +137,12 @@ static void iwl_mvm_power_log(struct iwl_mvm *mvm,
137 le32_to_cpu(cmd->rx_data_timeout)); 137 le32_to_cpu(cmd->rx_data_timeout));
138 IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n", 138 IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n",
139 le32_to_cpu(cmd->tx_data_timeout)); 139 le32_to_cpu(cmd->tx_data_timeout));
140 IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
141 cmd->lprx_rssi_threshold);
142 if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) 140 if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK))
143 IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n", 141 IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n",
144 le32_to_cpu(cmd->skip_dtim_periods)); 142 le32_to_cpu(cmd->skip_dtim_periods));
143 if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
144 IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
145 le32_to_cpu(cmd->lprx_rssi_threshold));
145 } 146 }
146} 147}
147 148
@@ -181,6 +182,14 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
181 182
182 cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK); 183 cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
183 184
185 if (vif->bss_conf.beacon_rate &&
186 (vif->bss_conf.beacon_rate->bitrate == 10 ||
187 vif->bss_conf.beacon_rate->bitrate == 60)) {
188 cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
189 cmd->lprx_rssi_threshold =
190 cpu_to_le32(POWER_LPRX_RSSI_THRESHOLD);
191 }
192
184 dtimper = hw->conf.ps_dtim_period ?: 1; 193 dtimper = hw->conf.ps_dtim_period ?: 1;
185 194
186 /* Check if radar detection is required on current channel */ 195 /* Check if radar detection is required on current channel */
@@ -236,6 +245,15 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
236 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS) 245 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS)
237 cmd->skip_dtim_periods = 246 cmd->skip_dtim_periods =
238 cpu_to_le32(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) {
249 if (mvmvif->dbgfs_pm.lprx_ena)
250 cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
251 else
252 cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK);
253 }
254 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD)
255 cmd->lprx_rssi_threshold =
256 cpu_to_le32(mvmvif->dbgfs_pm.lprx_rssi_threshold);
239#endif /* CONFIG_IWLWIFI_DEBUGFS */ 257#endif /* CONFIG_IWLWIFI_DEBUGFS */
240} 258}
241 259
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index 31587a318f8b..b328a988c130 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -412,24 +412,18 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_mvm *mvm,
412 return ret; 412 return ret;
413 } 413 }
414 414
415 if ((iwlwifi_mod_params.auto_agg) || (load > IWL_AGG_LOAD_THRESHOLD)) { 415 IWL_DEBUG_HT(mvm, "Starting Tx agg: STA: %pM tid: %d\n",
416 IWL_DEBUG_HT(mvm, "Starting Tx agg: STA: %pM tid: %d\n", 416 sta->addr, tid);
417 sta->addr, tid); 417 ret = ieee80211_start_tx_ba_session(sta, tid, 5000);
418 ret = ieee80211_start_tx_ba_session(sta, tid, 5000); 418 if (ret == -EAGAIN) {
419 if (ret == -EAGAIN) { 419 /*
420 /* 420 * driver and mac80211 is out of sync
421 * driver and mac80211 is out of sync 421 * this might be cause by reloading firmware
422 * this might be cause by reloading firmware 422 * stop the tx ba session here
423 * stop the tx ba session here 423 */
424 */ 424 IWL_ERR(mvm, "Fail start Tx agg on tid: %d\n",
425 IWL_ERR(mvm, "Fail start Tx agg on tid: %d\n", 425 tid);
426 tid); 426 ieee80211_stop_tx_ba_session(sta, tid);
427 ieee80211_stop_tx_ba_session(sta, tid);
428 }
429 } else {
430 IWL_DEBUG_HT(mvm,
431 "Aggregation not enabled for tid %d because load = %u\n",
432 tid, load);
433 } 427 }
434 return ret; 428 return ret;
435} 429}
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c
index a7e3b8ddf22b..d6ae7f16ac11 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tt.c
@@ -427,6 +427,7 @@ void iwl_mvm_tt_handler(struct iwl_mvm *mvm)
427 const struct iwl_tt_params *params = mvm->thermal_throttle.params; 427 const struct iwl_tt_params *params = mvm->thermal_throttle.params;
428 struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle; 428 struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle;
429 s32 temperature = mvm->temperature; 429 s32 temperature = mvm->temperature;
430 bool throttle_enable = false;
430 int i; 431 int i;
431 u32 tx_backoff; 432 u32 tx_backoff;
432 433
@@ -445,6 +446,7 @@ void iwl_mvm_tt_handler(struct iwl_mvm *mvm)
445 ieee80211_iterate_active_interfaces_atomic( 446 ieee80211_iterate_active_interfaces_atomic(
446 mvm->hw, IEEE80211_IFACE_ITER_NORMAL, 447 mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
447 iwl_mvm_tt_smps_iterator, mvm); 448 iwl_mvm_tt_smps_iterator, mvm);
449 throttle_enable = true;
448 } else if (tt->dynamic_smps && 450 } else if (tt->dynamic_smps &&
449 temperature <= params->dynamic_smps_exit) { 451 temperature <= params->dynamic_smps_exit) {
450 IWL_DEBUG_TEMP(mvm, "Disable dynamic SMPS\n"); 452 IWL_DEBUG_TEMP(mvm, "Disable dynamic SMPS\n");
@@ -456,10 +458,12 @@ void iwl_mvm_tt_handler(struct iwl_mvm *mvm)
456 } 458 }
457 459
458 if (params->support_tx_protection) { 460 if (params->support_tx_protection) {
459 if (temperature >= params->tx_protection_entry) 461 if (temperature >= params->tx_protection_entry) {
460 iwl_mvm_tt_tx_protection(mvm, true); 462 iwl_mvm_tt_tx_protection(mvm, true);
461 else if (temperature <= params->tx_protection_exit) 463 throttle_enable = true;
464 } else if (temperature <= params->tx_protection_exit) {
462 iwl_mvm_tt_tx_protection(mvm, false); 465 iwl_mvm_tt_tx_protection(mvm, false);
466 }
463 } 467 }
464 468
465 if (params->support_tx_backoff) { 469 if (params->support_tx_backoff) {
@@ -469,9 +473,22 @@ void iwl_mvm_tt_handler(struct iwl_mvm *mvm)
469 break; 473 break;
470 tx_backoff = params->tx_backoff[i].backoff; 474 tx_backoff = params->tx_backoff[i].backoff;
471 } 475 }
476 if (tx_backoff != 0)
477 throttle_enable = true;
472 if (tt->tx_backoff != tx_backoff) 478 if (tt->tx_backoff != tx_backoff)
473 iwl_mvm_tt_tx_backoff(mvm, tx_backoff); 479 iwl_mvm_tt_tx_backoff(mvm, tx_backoff);
474 } 480 }
481
482 if (!tt->throttle && throttle_enable) {
483 IWL_WARN(mvm,
484 "Due to high temperature thermal throttling initiated\n");
485 tt->throttle = true;
486 } else if (tt->throttle && !tt->dynamic_smps && tt->tx_backoff == 0 &&
487 temperature <= params->tx_protection_exit) {
488 IWL_WARN(mvm,
489 "Temperature is back to normal thermal throttling stopped\n");
490 tt->throttle = false;
491 }
475} 492}
476 493
477static const struct iwl_tt_params iwl7000_tt_params = { 494static const struct iwl_tt_params iwl7000_tt_params = {
@@ -502,6 +519,7 @@ void iwl_mvm_tt_initialize(struct iwl_mvm *mvm)
502 519
503 IWL_DEBUG_TEMP(mvm, "Initialize Thermal Throttling\n"); 520 IWL_DEBUG_TEMP(mvm, "Initialize Thermal Throttling\n");
504 tt->params = &iwl7000_tt_params; 521 tt->params = &iwl7000_tt_params;
522 tt->throttle = false;
505 INIT_DELAYED_WORK(&tt->ct_kill_exit, check_exit_ctkill); 523 INIT_DELAYED_WORK(&tt->ct_kill_exit, check_exit_ctkill);
506} 524}
507 525
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 3688dc5ba1ac..fd848cd1583e 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -110,9 +110,10 @@
110/* 110/*
111 * iwl_rxq_space - Return number of free slots available in queue. 111 * iwl_rxq_space - Return number of free slots available in queue.
112 */ 112 */
113static int iwl_rxq_space(const struct iwl_rxq *q) 113static int iwl_rxq_space(const struct iwl_rxq *rxq)
114{ 114{
115 int s = q->read - q->write; 115 int s = rxq->read - rxq->write;
116
116 if (s <= 0) 117 if (s <= 0)
117 s += RX_QUEUE_SIZE; 118 s += RX_QUEUE_SIZE;
118 /* keep some buffer to not confuse full and empty queue */ 119 /* keep some buffer to not confuse full and empty queue */
@@ -143,21 +144,22 @@ int iwl_pcie_rx_stop(struct iwl_trans *trans)
143/* 144/*
144 * iwl_pcie_rxq_inc_wr_ptr - Update the write pointer for the RX queue 145 * iwl_pcie_rxq_inc_wr_ptr - Update the write pointer for the RX queue
145 */ 146 */
146static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_rxq *q) 147static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans,
148 struct iwl_rxq *rxq)
147{ 149{
148 unsigned long flags; 150 unsigned long flags;
149 u32 reg; 151 u32 reg;
150 152
151 spin_lock_irqsave(&q->lock, flags); 153 spin_lock_irqsave(&rxq->lock, flags);
152 154
153 if (q->need_update == 0) 155 if (rxq->need_update == 0)
154 goto exit_unlock; 156 goto exit_unlock;
155 157
156 if (trans->cfg->base_params->shadow_reg_enable) { 158 if (trans->cfg->base_params->shadow_reg_enable) {
157 /* shadow register enabled */ 159 /* shadow register enabled */
158 /* Device expects a multiple of 8 */ 160 /* Device expects a multiple of 8 */
159 q->write_actual = (q->write & ~0x7); 161 rxq->write_actual = (rxq->write & ~0x7);
160 iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, q->write_actual); 162 iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual);
161 } else { 163 } else {
162 struct iwl_trans_pcie *trans_pcie = 164 struct iwl_trans_pcie *trans_pcie =
163 IWL_TRANS_GET_PCIE_TRANS(trans); 165 IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -175,22 +177,22 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_rxq *q)
175 goto exit_unlock; 177 goto exit_unlock;
176 } 178 }
177 179
178 q->write_actual = (q->write & ~0x7); 180 rxq->write_actual = (rxq->write & ~0x7);
179 iwl_write_direct32(trans, FH_RSCSR_CHNL0_WPTR, 181 iwl_write_direct32(trans, FH_RSCSR_CHNL0_WPTR,
180 q->write_actual); 182 rxq->write_actual);
181 183
182 /* Else device is assumed to be awake */ 184 /* Else device is assumed to be awake */
183 } else { 185 } else {
184 /* Device expects a multiple of 8 */ 186 /* Device expects a multiple of 8 */
185 q->write_actual = (q->write & ~0x7); 187 rxq->write_actual = (rxq->write & ~0x7);
186 iwl_write_direct32(trans, FH_RSCSR_CHNL0_WPTR, 188 iwl_write_direct32(trans, FH_RSCSR_CHNL0_WPTR,
187 q->write_actual); 189 rxq->write_actual);
188 } 190 }
189 } 191 }
190 q->need_update = 0; 192 rxq->need_update = 0;
191 193
192 exit_unlock: 194 exit_unlock:
193 spin_unlock_irqrestore(&q->lock, flags); 195 spin_unlock_irqrestore(&rxq->lock, flags);
194} 196}
195 197
196/* 198/*
@@ -355,19 +357,16 @@ static void iwl_pcie_rxq_free_rbs(struct iwl_trans *trans)
355 struct iwl_rxq *rxq = &trans_pcie->rxq; 357 struct iwl_rxq *rxq = &trans_pcie->rxq;
356 int i; 358 int i;
357 359
358 /* Fill the rx_used queue with _all_ of the Rx buffers */ 360 lockdep_assert_held(&rxq->lock);
361
359 for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { 362 for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
360 /* In the reset function, these buffers may have been allocated 363 if (!rxq->pool[i].page)
361 * to an SKB, so we need to unmap and free potential storage */ 364 continue;
362 if (rxq->pool[i].page != NULL) { 365 dma_unmap_page(trans->dev, rxq->pool[i].page_dma,
363 dma_unmap_page(trans->dev, rxq->pool[i].page_dma, 366 PAGE_SIZE << trans_pcie->rx_page_order,
364 PAGE_SIZE << trans_pcie->rx_page_order, 367 DMA_FROM_DEVICE);
365 DMA_FROM_DEVICE); 368 __free_pages(rxq->pool[i].page, trans_pcie->rx_page_order);
366 __free_pages(rxq->pool[i].page, 369 rxq->pool[i].page = NULL;
367 trans_pcie->rx_page_order);
368 rxq->pool[i].page = NULL;
369 }
370 list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
371 } 370 }
372} 371}
373 372
@@ -491,6 +490,20 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq)
491 iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); 490 iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);
492} 491}
493 492
493static void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq)
494{
495 int i;
496
497 lockdep_assert_held(&rxq->lock);
498
499 INIT_LIST_HEAD(&rxq->rx_free);
500 INIT_LIST_HEAD(&rxq->rx_used);
501 rxq->free_count = 0;
502
503 for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++)
504 list_add(&rxq->pool[i].list, &rxq->rx_used);
505}
506
494int iwl_pcie_rx_init(struct iwl_trans *trans) 507int iwl_pcie_rx_init(struct iwl_trans *trans)
495{ 508{
496 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 509 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -505,13 +518,12 @@ int iwl_pcie_rx_init(struct iwl_trans *trans)
505 } 518 }
506 519
507 spin_lock_irqsave(&rxq->lock, flags); 520 spin_lock_irqsave(&rxq->lock, flags);
508 INIT_LIST_HEAD(&rxq->rx_free);
509 INIT_LIST_HEAD(&rxq->rx_used);
510 521
511 INIT_WORK(&trans_pcie->rx_replenish, 522 INIT_WORK(&trans_pcie->rx_replenish, iwl_pcie_rx_replenish_work);
512 iwl_pcie_rx_replenish_work);
513 523
524 /* free all first - we might be reconfigured for a different size */
514 iwl_pcie_rxq_free_rbs(trans); 525 iwl_pcie_rxq_free_rbs(trans);
526 iwl_pcie_rx_init_rxb_lists(rxq);
515 527
516 for (i = 0; i < RX_QUEUE_SIZE; i++) 528 for (i = 0; i < RX_QUEUE_SIZE; i++)
517 rxq->queue[i] = NULL; 529 rxq->queue[i] = NULL;
@@ -520,7 +532,6 @@ int iwl_pcie_rx_init(struct iwl_trans *trans)
520 * not restocked the Rx queue with fresh buffers */ 532 * not restocked the Rx queue with fresh buffers */
521 rxq->read = rxq->write = 0; 533 rxq->read = rxq->write = 0;
522 rxq->write_actual = 0; 534 rxq->write_actual = 0;
523 rxq->free_count = 0;
524 memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts)); 535 memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts));
525 spin_unlock_irqrestore(&rxq->lock, flags); 536 spin_unlock_irqrestore(&rxq->lock, flags);
526 537
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index 197dbe0a868c..826c15602c46 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -838,8 +838,9 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent,
838 unsigned long *flags) 838 unsigned long *flags)
839{ 839{
840 int ret; 840 int ret;
841 struct iwl_trans_pcie *pcie_trans = IWL_TRANS_GET_PCIE_TRANS(trans); 841 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
842 spin_lock_irqsave(&pcie_trans->reg_lock, *flags); 842
843 spin_lock_irqsave(&trans_pcie->reg_lock, *flags);
843 844
844 /* this bit wakes up the NIC */ 845 /* this bit wakes up the NIC */
845 __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL, 846 __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
@@ -875,7 +876,7 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent,
875 WARN_ONCE(1, 876 WARN_ONCE(1,
876 "Timeout waiting for hardware access (CSR_GP_CNTRL 0x%08x)\n", 877 "Timeout waiting for hardware access (CSR_GP_CNTRL 0x%08x)\n",
877 val); 878 val);
878 spin_unlock_irqrestore(&pcie_trans->reg_lock, *flags); 879 spin_unlock_irqrestore(&trans_pcie->reg_lock, *flags);
879 return false; 880 return false;
880 } 881 }
881 } 882 }
@@ -884,22 +885,22 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent,
884 * Fool sparse by faking we release the lock - sparse will 885 * Fool sparse by faking we release the lock - sparse will
885 * track nic_access anyway. 886 * track nic_access anyway.
886 */ 887 */
887 __release(&pcie_trans->reg_lock); 888 __release(&trans_pcie->reg_lock);
888 return true; 889 return true;
889} 890}
890 891
891static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans, 892static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans,
892 unsigned long *flags) 893 unsigned long *flags)
893{ 894{
894 struct iwl_trans_pcie *pcie_trans = IWL_TRANS_GET_PCIE_TRANS(trans); 895 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
895 896
896 lockdep_assert_held(&pcie_trans->reg_lock); 897 lockdep_assert_held(&trans_pcie->reg_lock);
897 898
898 /* 899 /*
899 * Fool sparse by faking we acquiring the lock - sparse will 900 * Fool sparse by faking we acquiring the lock - sparse will
900 * track nic_access anyway. 901 * track nic_access anyway.
901 */ 902 */
902 __acquire(&pcie_trans->reg_lock); 903 __acquire(&trans_pcie->reg_lock);
903 904
904 __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, 905 __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
905 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 906 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
@@ -910,7 +911,7 @@ static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans,
910 * scheduled on different CPUs (after we drop reg_lock). 911 * scheduled on different CPUs (after we drop reg_lock).
911 */ 912 */
912 mmiowb(); 913 mmiowb();
913 spin_unlock_irqrestore(&pcie_trans->reg_lock, *flags); 914 spin_unlock_irqrestore(&trans_pcie->reg_lock, *flags);
914} 915}
915 916
916static int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr, 917static int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr,