diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-06-26 20:00:11 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-06-26 20:00:11 -0400 |
commit | 59731bb8c4f1536c5b698dc1aec82d7a5cef41eb (patch) | |
tree | b6e245cfae009fe9e108d6adaed3e0f56fd2969e /drivers/net | |
parent | 729d8d182bbf296b32cb2e7f970801eb6ce33c6a (diff) | |
parent | bd4ace2a36e7c87bb5f3eceb54d3b304d395dcf0 (diff) |
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
Diffstat (limited to 'drivers/net')
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. |
129 | endmenu | 129 | endmenu |
130 | 130 | ||
131 | config 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 | |||
141 | config IWLWIFI_P2P | 131 | config 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 | |||
13 | iwlwifi-objs += $(iwlwifi-m) | 13 | iwlwifi-objs += $(iwlwifi-m) |
14 | 14 | ||
15 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o | 15 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o |
16 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-test.o | ||
17 | 16 | ||
18 | ccflags-y += -D__CHECK_ENDIAN__ -I$(src) | 17 | ccflags-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 | |||
8 | iwldvm-objs += rxon.o devices.o | 8 | iwldvm-objs += rxon.o devices.o |
9 | 9 | ||
10 | iwldvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o | 10 | iwldvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o |
11 | iwldvm-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += testmode.o | ||
12 | 11 | ||
13 | ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../ | 12 | ccflags-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 | ||
406 | extern int iwl_alive_start(struct iwl_priv *priv); | 406 | extern int iwl_alive_start(struct iwl_priv *priv); |
407 | 407 | ||
408 | /* testmode support */ | ||
409 | #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE | ||
410 | |||
411 | extern int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, | ||
412 | int len); | ||
413 | extern int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, | ||
414 | struct sk_buff *skb, | ||
415 | struct netlink_callback *cb, | ||
416 | void *data, int len); | ||
417 | extern void iwl_testmode_init(struct iwl_priv *priv); | ||
418 | extern void iwl_testmode_free(struct iwl_priv *priv); | ||
419 | |||
420 | #else | ||
421 | |||
422 | static inline | ||
423 | int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) | ||
424 | { | ||
425 | return -ENOSYS; | ||
426 | } | ||
427 | |||
428 | static inline | ||
429 | int 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 | |||
436 | static inline void iwl_testmode_init(struct iwl_priv *priv) | ||
437 | { | ||
438 | } | ||
439 | |||
440 | static inline void iwl_testmode_free(struct iwl_priv *priv) | ||
441 | { | ||
442 | } | ||
443 | #endif | ||
444 | |||
445 | #ifdef CONFIG_IWLWIFI_DEBUG | 408 | #ifdef CONFIG_IWLWIFI_DEBUG |
446 | void iwl_print_rx_config_cmd(struct iwl_priv *priv, | 409 | void 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); |
1489 | out_destroy_workqueue: | 1480 | out_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 | |||
81 | static 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 | |||
88 | static 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 | |||
100 | static 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 | |||
106 | static struct sk_buff* | ||
107 | iwl_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 | |||
113 | static int iwl_testmode_reply(struct iwl_op_mode *op_mode, struct sk_buff *skb) | ||
114 | { | ||
115 | return cfg80211_testmode_reply(skb); | ||
116 | } | ||
117 | |||
118 | static 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 | |||
126 | static 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 | |||
131 | static 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 | |||
141 | void iwl_testmode_init(struct iwl_priv *priv) | ||
142 | { | ||
143 | iwl_test_init(&priv->tst, priv->trans, &tst_ops); | ||
144 | } | ||
145 | |||
146 | void iwl_testmode_free(struct iwl_priv *priv) | ||
147 | { | ||
148 | iwl_test_free(&priv->tst); | ||
149 | } | ||
150 | |||
151 | static 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 | |||
174 | cfg_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 | */ | ||
195 | static 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 | |||
325 | nla_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 | */ | ||
345 | static 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 | */ | ||
388 | int 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 | |||
444 | int 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 */ |
1112 | struct iwl_mod_params iwlwifi_mod_params = { | 1112 | struct 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, | |||
1223 | MODULE_PARM_DESC(antenna_coupling, | 1220 | MODULE_PARM_DESC(antenna_coupling, |
1224 | "specify antenna coupling in dB (defualt: 0 dB)"); | 1221 | "specify antenna coupling in dB (defualt: 0 dB)"); |
1225 | 1222 | ||
1226 | module_param_named(bt_ch_inhibition, iwlwifi_mod_params.bt_ch_announce, | ||
1227 | bool, S_IRUGO); | ||
1228 | MODULE_PARM_DESC(bt_ch_inhibition, | ||
1229 | "Enable BT channel inhibition (default: enable)"); | ||
1230 | |||
1231 | module_param_named(plcp_check, iwlwifi_mod_params.plcp_check, bool, S_IRUGO); | ||
1232 | MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])"); | ||
1233 | |||
1234 | module_param_named(wd_disable, iwlwifi_mod_params.wd_disable, int, S_IRUGO); | 1223 | module_param_named(wd_disable, iwlwifi_mod_params.wd_disable, int, S_IRUGO); |
1235 | MODULE_PARM_DESC(wd_disable, | 1224 | MODULE_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); |
1273 | MODULE_PARM_DESC(power_level, | 1262 | MODULE_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 | |||
1276 | module_param_named(auto_agg, iwlwifi_mod_params.auto_agg, | ||
1277 | bool, S_IRUGO); | ||
1278 | MODULE_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 | */ |
107 | struct iwl_mod_params { | 104 | struct 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 | */ | ||
89 | static | ||
90 | struct 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 | |||
126 | static inline void iwl_test_trace_clear(struct iwl_test *tst) | ||
127 | { | ||
128 | memset(&tst->trace, 0, sizeof(struct iwl_test_trace)); | ||
129 | } | ||
130 | |||
131 | static 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 | |||
145 | static inline void iwl_test_mem_clear(struct iwl_test *tst) | ||
146 | { | ||
147 | memset(&tst->mem, 0, sizeof(struct iwl_test_mem)); | ||
148 | } | ||
149 | |||
150 | static 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 | */ | ||
163 | void 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 | } | ||
172 | EXPORT_SYMBOL_GPL(iwl_test_init); | ||
173 | |||
174 | /* | ||
175 | * Stop the test object | ||
176 | */ | ||
177 | void iwl_test_free(struct iwl_test *tst) | ||
178 | { | ||
179 | iwl_test_mem_stop(tst); | ||
180 | iwl_test_trace_stop(tst); | ||
181 | } | ||
182 | EXPORT_SYMBOL_GPL(iwl_test_free); | ||
183 | |||
184 | static 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 | |||
190 | static inline bool iwl_test_valid_hw_addr(struct iwl_test *tst, u32 addr) | ||
191 | { | ||
192 | return tst->ops->valid_hw_addr(addr); | ||
193 | } | ||
194 | |||
195 | static inline u32 iwl_test_fw_ver(struct iwl_test *tst) | ||
196 | { | ||
197 | return tst->ops->get_fw_ver(tst->trans->op_mode); | ||
198 | } | ||
199 | |||
200 | static inline struct sk_buff* | ||
201 | iwl_test_alloc_reply(struct iwl_test *tst, int len) | ||
202 | { | ||
203 | return tst->ops->alloc_reply(tst->trans->op_mode, len); | ||
204 | } | ||
205 | |||
206 | static 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 | |||
211 | static inline struct sk_buff* | ||
212 | iwl_test_alloc_event(struct iwl_test *tst, int len) | ||
213 | { | ||
214 | return tst->ops->alloc_event(tst->trans->op_mode, len); | ||
215 | } | ||
216 | |||
217 | static inline void | ||
218 | iwl_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 | */ | ||
228 | static 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 | |||
291 | nla_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 | */ | ||
301 | static 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 | |||
376 | nla_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 | */ | ||
385 | static 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 | |||
440 | nla_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 | */ | ||
452 | static 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 | */ | ||
494 | static 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 | */ | ||
532 | static 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 | */ | ||
566 | static 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 | */ | ||
576 | static 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 | |||
598 | nla_put_failure: | ||
599 | kfree_skb(skb); | ||
600 | return -EMSGSIZE; | ||
601 | } | ||
602 | |||
603 | /* | ||
604 | * Handles the request to get the FW version | ||
605 | */ | ||
606 | static 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 | |||
629 | nla_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 | */ | ||
637 | int 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 | } | ||
656 | IWL_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 | */ | ||
663 | int 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 | } | ||
718 | IWL_EXPORT_SYMBOL(iwl_test_handle_cmd); | ||
719 | |||
720 | static 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 | |||
749 | static 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 | */ | ||
784 | int 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 | } | ||
806 | IWL_EXPORT_SYMBOL(iwl_test_dump); | ||
807 | |||
808 | /* | ||
809 | * Multicast a spontaneous messages from the device to the user space. | ||
810 | */ | ||
811 | static 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 | |||
838 | nla_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 | */ | ||
847 | void 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 | } | ||
852 | IWL_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 | |||
70 | struct 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 | |||
80 | struct 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 | */ | ||
120 | struct 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 | |||
132 | struct 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 | |||
140 | void iwl_test_init(struct iwl_test *tst, struct iwl_trans *trans, | ||
141 | struct iwl_test_ops *ops); | ||
142 | |||
143 | void iwl_test_free(struct iwl_test *tst); | ||
144 | |||
145 | int iwl_test_parse(struct iwl_test *tst, struct nlattr **tb, | ||
146 | void *data, int len); | ||
147 | |||
148 | int iwl_test_handle_cmd(struct iwl_test *tst, struct nlattr **tb); | ||
149 | |||
150 | int iwl_test_dump(struct iwl_test *tst, u32 cmd, struct sk_buff *skb, | ||
151 | struct netlink_callback *cb); | ||
152 | |||
153 | void iwl_test_rx(struct iwl_test *tst, struct iwl_rx_cmd_buffer *rxb); | ||
154 | |||
155 | static 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 | */ | ||
129 | enum 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 | */ | ||
268 | enum 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 | */ |
188 | enum CMD_MODE { | 187 | enum 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 */ | ||
206 | static 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 | |||
205 | int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | 221 | int 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 | ||
868 | struct 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 */ | ||
876 | static 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 | ||
164 | struct iwl_dbgfs_pm { | 165 | struct 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 | */ |
357 | struct iwl_mvm_tt_mgmt { | 361 | struct 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 | ||
364 | struct iwl_mvm { | 369 | struct 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 | ||
477 | static const struct iwl_tt_params iwl7000_tt_params = { | 494 | static 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 | */ |
113 | static int iwl_rxq_space(const struct iwl_rxq *q) | 113 | static 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 | */ |
146 | static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_rxq *q) | 147 | static 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 | ||
493 | static 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 | |||
494 | int iwl_pcie_rx_init(struct iwl_trans *trans) | 507 | int 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 | ||
891 | static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans, | 892 | static 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 | ||
916 | static int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr, | 917 | static int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr, |