aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2015-01-14 11:58:57 -0500
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2015-03-01 09:55:08 -0500
commit777c9b6bba5266ea8eecb19b3fa8b63ad5251bd6 (patch)
treec92233bf65b0b3080b04618ae7bc2b032375fe84
parenta2227ce2a32cf9faeab1299894fe09d03e6a12b7 (diff)
iwlwifi: mvm: add statistics API version 10
New firmware versions will report statistics using a new version 10 of the API, instead of the current version 8. Add support for this. This enables getting beacon and radio statistics. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw-file.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h1
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h47
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rx.c62
4 files changed, 90 insertions, 22 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h
index 016d91384681..4602e3c7afda 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h
@@ -250,6 +250,7 @@ enum iwl_ucode_tlv_flag {
250 * @IWL_UCODE_TLV_API_SINGLE_SCAN_EBS: EBS is supported for single scans too. 250 * @IWL_UCODE_TLV_API_SINGLE_SCAN_EBS: EBS is supported for single scans too.
251 * @IWL_UCODE_TLV_API_ASYNC_DTM: Async temperature notifications are supported. 251 * @IWL_UCODE_TLV_API_ASYNC_DTM: Async temperature notifications are supported.
252 * @IWL_UCODE_TLV_API_LQ_SS_PARAMS: Configure STBC/BFER via LQ CMD ss_params 252 * @IWL_UCODE_TLV_API_LQ_SS_PARAMS: Configure STBC/BFER via LQ CMD ss_params
253 * @IWL_UCODE_TLV_API_STATS_V10: uCode supports/uses statistics API version 10
253 */ 254 */
254enum iwl_ucode_tlv_api { 255enum iwl_ucode_tlv_api {
255 IWL_UCODE_TLV_API_BT_COEX_SPLIT = BIT(3), 256 IWL_UCODE_TLV_API_BT_COEX_SPLIT = BIT(3),
@@ -263,6 +264,7 @@ enum iwl_ucode_tlv_api {
263 IWL_UCODE_TLV_API_SINGLE_SCAN_EBS = BIT(16), 264 IWL_UCODE_TLV_API_SINGLE_SCAN_EBS = BIT(16),
264 IWL_UCODE_TLV_API_ASYNC_DTM = BIT(17), 265 IWL_UCODE_TLV_API_ASYNC_DTM = BIT(17),
265 IWL_UCODE_TLV_API_LQ_SS_PARAMS = BIT(18), 266 IWL_UCODE_TLV_API_LQ_SS_PARAMS = BIT(18),
267 IWL_UCODE_TLV_API_STATS_V10 = BIT(19),
266}; 268};
267 269
268/** 270/**
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h
index c405cda1025f..aabaedd3b3ee 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h
@@ -70,6 +70,7 @@
70#define MAC_INDEX_AUX 4 70#define MAC_INDEX_AUX 4
71#define MAC_INDEX_MIN_DRIVER 0 71#define MAC_INDEX_MIN_DRIVER 0
72#define NUM_MAC_INDEX_DRIVER MAC_INDEX_AUX 72#define NUM_MAC_INDEX_DRIVER MAC_INDEX_AUX
73#define NUM_MAC_INDEX (MAC_INDEX_AUX + 1)
73 74
74enum iwl_ac { 75enum iwl_ac {
75 AC_BK, 76 AC_BK,
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h
index 928168b18346..5a9dfe074022 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h
@@ -65,6 +65,7 @@
65 65
66#ifndef __fw_api_stats_h__ 66#ifndef __fw_api_stats_h__
67#define __fw_api_stats_h__ 67#define __fw_api_stats_h__
68#include "fw-api-mac.h"
68 69
69struct mvm_statistics_dbg { 70struct mvm_statistics_dbg {
70 __le32 burst_check; 71 __le32 burst_check;
@@ -218,7 +219,7 @@ struct mvm_statistics_bt_activity {
218 __le32 lo_priority_rx_denied_cnt; 219 __le32 lo_priority_rx_denied_cnt;
219} __packed; /* STATISTICS_BT_ACTIVITY_API_S_VER_1 */ 220} __packed; /* STATISTICS_BT_ACTIVITY_API_S_VER_1 */
220 221
221struct mvm_statistics_general { 222struct mvm_statistics_general_v5 {
222 __le32 radio_temperature; 223 __le32 radio_temperature;
223 __le32 radio_voltage; 224 __le32 radio_voltage;
224 struct mvm_statistics_dbg dbg; 225 struct mvm_statistics_dbg dbg;
@@ -244,6 +245,39 @@ struct mvm_statistics_general {
244 struct mvm_statistics_bt_activity bt_activity; 245 struct mvm_statistics_bt_activity bt_activity;
245} __packed; /* STATISTICS_GENERAL_API_S_VER_5 */ 246} __packed; /* STATISTICS_GENERAL_API_S_VER_5 */
246 247
248struct mvm_statistics_general_v8 {
249 __le32 radio_temperature;
250 __le32 radio_voltage;
251 struct mvm_statistics_dbg dbg;
252 __le32 sleep_time;
253 __le32 slots_out;
254 __le32 slots_idle;
255 __le32 ttl_timestamp;
256 struct mvm_statistics_div slow_div;
257 __le32 rx_enable_counter;
258 /*
259 * num_of_sos_states:
260 * count the number of times we have to re-tune
261 * in order to get out of bad PHY status
262 */
263 __le32 num_of_sos_states;
264 __le32 beacon_filtered;
265 __le32 missed_beacons;
266 __s8 beacon_filter_average_energy;
267 __s8 beacon_filter_reason;
268 __s8 beacon_filter_current_energy;
269 __s8 beacon_filter_reserved;
270 __le32 beacon_filter_delta_time;
271 struct mvm_statistics_bt_activity bt_activity;
272 __le64 rx_time;
273 __le64 on_time_rf;
274 __le64 on_time_scan;
275 __le64 tx_time;
276 __le32 beacon_counter[NUM_MAC_INDEX];
277 u8 beacon_average_energy[NUM_MAC_INDEX];
278 u8 reserved[4 - (NUM_MAC_INDEX % 4)];
279} __packed; /* STATISTICS_GENERAL_API_S_VER_8 */
280
247struct mvm_statistics_rx { 281struct mvm_statistics_rx {
248 struct mvm_statistics_rx_phy ofdm; 282 struct mvm_statistics_rx_phy ofdm;
249 struct mvm_statistics_rx_phy cck; 283 struct mvm_statistics_rx_phy cck;
@@ -267,11 +301,18 @@ struct mvm_statistics_rx {
267 * one channel that has just been scanned. 301 * one channel that has just been scanned.
268 */ 302 */
269 303
270struct iwl_notif_statistics { 304struct iwl_notif_statistics_v8 {
271 __le32 flag; 305 __le32 flag;
272 struct mvm_statistics_rx rx; 306 struct mvm_statistics_rx rx;
273 struct mvm_statistics_tx tx; 307 struct mvm_statistics_tx tx;
274 struct mvm_statistics_general general; 308 struct mvm_statistics_general_v5 general;
275} __packed; /* STATISTICS_NTFY_API_S_VER_8 */ 309} __packed; /* STATISTICS_NTFY_API_S_VER_8 */
276 310
311struct iwl_notif_statistics_v10 {
312 __le32 flag;
313 struct mvm_statistics_rx rx;
314 struct mvm_statistics_tx tx;
315 struct mvm_statistics_general_v8 general;
316} __packed; /* STATISTICS_NTFY_API_S_VER_10 */
317
277#endif /* __fw_api_stats_h__ */ 318#endif /* __fw_api_stats_h__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c
index f922131b4eab..fffd89d5bdfb 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rx.c
@@ -6,7 +6,7 @@
6 * GPL LICENSE SUMMARY 6 * GPL LICENSE SUMMARY
7 * 7 *
8 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. 8 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
9 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH 9 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
10 * 10 *
11 * This program is free software; you can redistribute it and/or modify 11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of version 2 of the GNU General Public License as 12 * it under the terms of version 2 of the GNU General Public License as
@@ -32,7 +32,7 @@
32 * BSD LICENSE 32 * BSD LICENSE
33 * 33 *
34 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. 34 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
35 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH 35 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
36 * All rights reserved. 36 * All rights reserved.
37 * 37 *
38 * Redistribution and use in source and binary forms, with or without 38 * Redistribution and use in source and binary forms, with or without
@@ -416,33 +416,29 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
416} 416}
417 417
418static void iwl_mvm_update_rx_statistics(struct iwl_mvm *mvm, 418static void iwl_mvm_update_rx_statistics(struct iwl_mvm *mvm,
419 struct iwl_notif_statistics *stats) 419 struct mvm_statistics_rx *rx_stats)
420{ 420{
421 /*
422 * NOTE FW aggregates the statistics - BUT the statistics are cleared
423 * when the driver issues REPLY_STATISTICS_CMD 0x9c with CLEAR_STATS
424 * bit set.
425 */
426 lockdep_assert_held(&mvm->mutex); 421 lockdep_assert_held(&mvm->mutex);
427 memcpy(&mvm->rx_stats, &stats->rx, sizeof(struct mvm_statistics_rx)); 422
423 mvm->rx_stats = *rx_stats;
428} 424}
429 425
430struct iwl_mvm_stat_data { 426struct iwl_mvm_stat_data {
431 struct iwl_notif_statistics *stats;
432 struct iwl_mvm *mvm; 427 struct iwl_mvm *mvm;
428 __le32 mac_id;
429 __s8 beacon_filter_average_energy;
433}; 430};
434 431
435static void iwl_mvm_stat_iterator(void *_data, u8 *mac, 432static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
436 struct ieee80211_vif *vif) 433 struct ieee80211_vif *vif)
437{ 434{
438 struct iwl_mvm_stat_data *data = _data; 435 struct iwl_mvm_stat_data *data = _data;
439 struct iwl_notif_statistics *stats = data->stats;
440 struct iwl_mvm *mvm = data->mvm; 436 struct iwl_mvm *mvm = data->mvm;
441 int sig = -stats->general.beacon_filter_average_energy; 437 int sig = -data->beacon_filter_average_energy;
442 int last_event; 438 int last_event;
443 int thold = vif->bss_conf.cqm_rssi_thold; 439 int thold = vif->bss_conf.cqm_rssi_thold;
444 int hyst = vif->bss_conf.cqm_rssi_hyst; 440 int hyst = vif->bss_conf.cqm_rssi_hyst;
445 u16 id = le32_to_cpu(stats->rx.general.mac_id); 441 u16 id = le32_to_cpu(data->mac_id);
446 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 442 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
447 443
448 if (mvmvif->id != id) 444 if (mvmvif->id != id)
@@ -510,24 +506,52 @@ int iwl_mvm_rx_statistics(struct iwl_mvm *mvm,
510 struct iwl_device_cmd *cmd) 506 struct iwl_device_cmd *cmd)
511{ 507{
512 struct iwl_rx_packet *pkt = rxb_addr(rxb); 508 struct iwl_rx_packet *pkt = rxb_addr(rxb);
513 struct iwl_notif_statistics *stats = (void *)&pkt->data; 509 size_t v8_len = sizeof(struct iwl_notif_statistics_v8);
510 size_t v10_len = sizeof(struct iwl_notif_statistics_v10);
514 struct iwl_mvm_stat_data data = { 511 struct iwl_mvm_stat_data data = {
515 .stats = stats,
516 .mvm = mvm, 512 .mvm = mvm,
517 }; 513 };
514 u32 temperature;
515
516 if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_STATS_V10) {
517 struct iwl_notif_statistics_v10 *stats = (void *)&pkt->data;
518
519 if (iwl_rx_packet_payload_len(pkt) != v10_len)
520 goto invalid;
521
522 temperature = le32_to_cpu(stats->general.radio_temperature);
523 data.mac_id = stats->rx.general.mac_id;
524 data.beacon_filter_average_energy =
525 stats->general.beacon_filter_average_energy;
526
527 iwl_mvm_update_rx_statistics(mvm, &stats->rx);
528 } else {
529 struct iwl_notif_statistics_v8 *stats = (void *)&pkt->data;
530
531 if (iwl_rx_packet_payload_len(pkt) != v8_len)
532 goto invalid;
533
534 temperature = le32_to_cpu(stats->general.radio_temperature);
535 data.mac_id = stats->rx.general.mac_id;
536 data.beacon_filter_average_energy =
537 stats->general.beacon_filter_average_energy;
538
539 iwl_mvm_update_rx_statistics(mvm, &stats->rx);
540 }
518 541
519 /* Only handle rx statistics temperature changes if async temp 542 /* Only handle rx statistics temperature changes if async temp
520 * notifications are not supported 543 * notifications are not supported
521 */ 544 */
522 if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_ASYNC_DTM)) 545 if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_ASYNC_DTM))
523 iwl_mvm_tt_temp_changed(mvm, 546 iwl_mvm_tt_temp_changed(mvm, temperature);
524 le32_to_cpu(stats->general.radio_temperature));
525
526 iwl_mvm_update_rx_statistics(mvm, stats);
527 547
528 ieee80211_iterate_active_interfaces(mvm->hw, 548 ieee80211_iterate_active_interfaces(mvm->hw,
529 IEEE80211_IFACE_ITER_NORMAL, 549 IEEE80211_IFACE_ITER_NORMAL,
530 iwl_mvm_stat_iterator, 550 iwl_mvm_stat_iterator,
531 &data); 551 &data);
532 return 0; 552 return 0;
553 invalid:
554 IWL_ERR(mvm, "received invalid statistics size (%d)!\n",
555 iwl_rx_packet_payload_len(pkt));
556 return 0;
533} 557}