aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2013-07-31 04:32:40 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2013-08-02 02:35:21 -0400
commit2e1dea40512d7e99a7e91ac88a6f434a5d7c6fde (patch)
treec8abfc11810c59cbacb2edf37de630e86f8bd3a5 /drivers
parent7c199997ded6c90fd45a50f49e9ac63adaacb95e (diff)
ath10k: implement get_survey()
This implements a limited subset of what can be reported in the survey dump. This can be used for assessing approximate channel load, e.g. for automatic channel selection. Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h7
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c36
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c75
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h5
4 files changed, 122 insertions, 1 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index ff42bb744d9e..e4bba563ed42 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -38,6 +38,7 @@
38#define ATH10K_SCAN_ID 0 38#define ATH10K_SCAN_ID 0
39#define WMI_READY_TIMEOUT (5 * HZ) 39#define WMI_READY_TIMEOUT (5 * HZ)
40#define ATH10K_FLUSH_TIMEOUT_HZ (5*HZ) 40#define ATH10K_FLUSH_TIMEOUT_HZ (5*HZ)
41#define ATH10K_NUM_CHANS 38
41 42
42/* Antenna noise floor */ 43/* Antenna noise floor */
43#define ATH10K_DEFAULT_NOISE_FLOOR -95 44#define ATH10K_DEFAULT_NOISE_FLOOR -95
@@ -375,6 +376,12 @@ struct ath10k {
375 376
376 struct work_struct restart_work; 377 struct work_struct restart_work;
377 378
379 /* cycle count is reported twice for each visited channel during scan.
380 * access protected by data_lock */
381 u32 survey_last_rx_clear_count;
382 u32 survey_last_cycle_count;
383 struct survey_info survey[ATH10K_NUM_CHANS];
384
378#ifdef CONFIG_ATH10K_DEBUGFS 385#ifdef CONFIG_ATH10K_DEBUGFS
379 struct ath10k_debug debug; 386 struct ath10k_debug debug;
380#endif 387#endif
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 57843377fa0b..9ea31f89b748 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2934,6 +2934,41 @@ static void ath10k_restart_complete(struct ieee80211_hw *hw)
2934 mutex_unlock(&ar->conf_mutex); 2934 mutex_unlock(&ar->conf_mutex);
2935} 2935}
2936 2936
2937static int ath10k_get_survey(struct ieee80211_hw *hw, int idx,
2938 struct survey_info *survey)
2939{
2940 struct ath10k *ar = hw->priv;
2941 struct ieee80211_supported_band *sband;
2942 struct survey_info *ar_survey = &ar->survey[idx];
2943 int ret = 0;
2944
2945 mutex_lock(&ar->conf_mutex);
2946
2947 sband = hw->wiphy->bands[IEEE80211_BAND_2GHZ];
2948 if (sband && idx >= sband->n_channels) {
2949 idx -= sband->n_channels;
2950 sband = NULL;
2951 }
2952
2953 if (!sband)
2954 sband = hw->wiphy->bands[IEEE80211_BAND_5GHZ];
2955
2956 if (!sband || idx >= sband->n_channels) {
2957 ret = -ENOENT;
2958 goto exit;
2959 }
2960
2961 spin_lock_bh(&ar->data_lock);
2962 memcpy(survey, ar_survey, sizeof(*survey));
2963 spin_unlock_bh(&ar->data_lock);
2964
2965 survey->channel = &sband->channels[idx];
2966
2967exit:
2968 mutex_unlock(&ar->conf_mutex);
2969 return ret;
2970}
2971
2937static const struct ieee80211_ops ath10k_ops = { 2972static const struct ieee80211_ops ath10k_ops = {
2938 .tx = ath10k_tx, 2973 .tx = ath10k_tx,
2939 .start = ath10k_start, 2974 .start = ath10k_start,
@@ -2955,6 +2990,7 @@ static const struct ieee80211_ops ath10k_ops = {
2955 .flush = ath10k_flush, 2990 .flush = ath10k_flush,
2956 .tx_last_beacon = ath10k_tx_last_beacon, 2991 .tx_last_beacon = ath10k_tx_last_beacon,
2957 .restart_complete = ath10k_restart_complete, 2992 .restart_complete = ath10k_restart_complete,
2993 .get_survey = ath10k_get_survey,
2958#ifdef CONFIG_PM 2994#ifdef CONFIG_PM
2959 .suspend = ath10k_suspend, 2995 .suspend = ath10k_suspend,
2960 .resume = ath10k_resume, 2996 .resume = ath10k_resume,
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 1cbcb2ea12f7..55f90c761868 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -390,9 +390,82 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
390 return 0; 390 return 0;
391} 391}
392 392
393static int freq_to_idx(struct ath10k *ar, int freq)
394{
395 struct ieee80211_supported_band *sband;
396 int band, ch, idx = 0;
397
398 for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) {
399 sband = ar->hw->wiphy->bands[band];
400 if (!sband)
401 continue;
402
403 for (ch = 0; ch < sband->n_channels; ch++, idx++)
404 if (sband->channels[ch].center_freq == freq)
405 goto exit;
406 }
407
408exit:
409 return idx;
410}
411
393static void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb) 412static void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb)
394{ 413{
395 ath10k_dbg(ATH10K_DBG_WMI, "WMI_CHAN_INFO_EVENTID\n"); 414 struct wmi_chan_info_event *ev;
415 struct survey_info *survey;
416 u32 err_code, freq, cmd_flags, noise_floor, rx_clear_count, cycle_count;
417 int idx;
418
419 ev = (struct wmi_chan_info_event *)skb->data;
420
421 err_code = __le32_to_cpu(ev->err_code);
422 freq = __le32_to_cpu(ev->freq);
423 cmd_flags = __le32_to_cpu(ev->cmd_flags);
424 noise_floor = __le32_to_cpu(ev->noise_floor);
425 rx_clear_count = __le32_to_cpu(ev->rx_clear_count);
426 cycle_count = __le32_to_cpu(ev->cycle_count);
427
428 ath10k_dbg(ATH10K_DBG_WMI,
429 "chan info err_code %d freq %d cmd_flags %d noise_floor %d rx_clear_count %d cycle_count %d\n",
430 err_code, freq, cmd_flags, noise_floor, rx_clear_count,
431 cycle_count);
432
433 spin_lock_bh(&ar->data_lock);
434
435 if (!ar->scan.in_progress) {
436 ath10k_warn("chan info event without a scan request?\n");
437 goto exit;
438 }
439
440 idx = freq_to_idx(ar, freq);
441 if (idx >= ARRAY_SIZE(ar->survey)) {
442 ath10k_warn("chan info: invalid frequency %d (idx %d out of bounds)\n",
443 freq, idx);
444 goto exit;
445 }
446
447 if (cmd_flags & WMI_CHAN_INFO_FLAG_COMPLETE) {
448 /* During scanning chan info is reported twice for each
449 * visited channel. The reported cycle count is global
450 * and per-channel cycle count must be calculated */
451
452 cycle_count -= ar->survey_last_cycle_count;
453 rx_clear_count -= ar->survey_last_rx_clear_count;
454
455 survey = &ar->survey[idx];
456 survey->channel_time = WMI_CHAN_INFO_MSEC(cycle_count);
457 survey->channel_time_rx = WMI_CHAN_INFO_MSEC(rx_clear_count);
458 survey->noise = noise_floor;
459 survey->filled = SURVEY_INFO_CHANNEL_TIME |
460 SURVEY_INFO_CHANNEL_TIME_RX |
461 SURVEY_INFO_NOISE_DBM;
462 }
463
464 ar->survey_last_rx_clear_count = rx_clear_count;
465 ar->survey_last_cycle_count = cycle_count;
466
467exit:
468 spin_unlock_bh(&ar->data_lock);
396} 469}
397 470
398static void ath10k_wmi_event_echo(struct ath10k *ar, struct sk_buff *skb) 471static void ath10k_wmi_event_echo(struct ath10k *ar, struct sk_buff *skb)
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index da3b2bc4c88a..2c5a4f8daf2e 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -2931,6 +2931,11 @@ struct wmi_chan_info_event {
2931 __le32 cycle_count; 2931 __le32 cycle_count;
2932} __packed; 2932} __packed;
2933 2933
2934#define WMI_CHAN_INFO_FLAG_COMPLETE BIT(0)
2935
2936/* FIXME: empirically extrapolated */
2937#define WMI_CHAN_INFO_MSEC(x) ((x) / 76595)
2938
2934/* Beacon filter wmi command info */ 2939/* Beacon filter wmi command info */
2935#define BCN_FLT_MAX_SUPPORTED_IES 256 2940#define BCN_FLT_MAX_SUPPORTED_IES 256
2936#define BCN_FLT_MAX_ELEMS_IE_LIST (BCN_FLT_MAX_SUPPORTED_IES / 32) 2941#define BCN_FLT_MAX_ELEMS_IE_LIST (BCN_FLT_MAX_SUPPORTED_IES / 32)