diff options
author | Maharaja Kennadyrajan <mkenna@codeaurora.org> | 2018-09-18 02:34:27 -0400 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2018-10-01 10:02:08 -0400 |
commit | d70c0d463f9dd67037426bad243f647efec527d3 (patch) | |
tree | 9b0d98ede7b7e6c3d4307174776e489be3aaaf66 /drivers/net/wireless/ath | |
parent | 4be3b05e7a83c6820095005e794432ca1711fa7f (diff) |
ath10k: add debugfs support to get power save state change of STA
This patch helps to get the power save state change of each peer
connected to the AP. With WMI_10_4_PEER_STA_PS_STATECHG_EVENTID
event, ps state of each peer is reported to user space via
debugfs.
Use the below command to get the ps state of each sta:
cat /sys/kernel/debug/ieee80211/phyX/netdev::wlanX/stations/
XX:XX:XX:XX:XX:XX/peer_ps_state
If STA is in power save state, we get the peer_ps_state value as 1.
if STA is not in power save state, we get the peer_ps_state value as 0.
If ps_state event is disabled, we get the peer_ps_state value as 2.
We can enable/disable the ps_state events using the debugfs flag
"ps_state_enable"
echo Y > /sys/kernel/debug/ieee80211/phyX/ath10k/ps_state_enable
Y = 1 to enable and Y = 0 to disable
Tested in QCA4019 with firmware ver 10.4-3.2.1.1-00011
Signed-off-by: Maharaja Kennadyrajan <mkenna@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r-- | drivers/net/wireless/ath/ath10k/core.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/debug.c | 82 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/debugfs_sta.c | 29 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/mac.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/wmi.c | 39 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/wmi.h | 7 |
6 files changed, 161 insertions, 1 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 7328df1bf39f..c76af343db3d 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h | |||
@@ -505,6 +505,8 @@ struct ath10k_sta { | |||
505 | /* Protected with ar->data_lock */ | 505 | /* Protected with ar->data_lock */ |
506 | struct ath10k_sta_tid_stats tid_stats[IEEE80211_NUM_TIDS + 1]; | 506 | struct ath10k_sta_tid_stats tid_stats[IEEE80211_NUM_TIDS + 1]; |
507 | #endif | 507 | #endif |
508 | /* Protected with ar->data_lock */ | ||
509 | u32 peer_ps_state; | ||
508 | }; | 510 | }; |
509 | 511 | ||
510 | #define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5 * HZ) | 512 | #define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5 * HZ) |
@@ -946,6 +948,8 @@ struct ath10k { | |||
946 | u32 low_5ghz_chan; | 948 | u32 low_5ghz_chan; |
947 | u32 high_5ghz_chan; | 949 | u32 high_5ghz_chan; |
948 | bool ani_enabled; | 950 | bool ani_enabled; |
951 | /* protected by conf_mutex */ | ||
952 | u8 ps_state_enable; | ||
949 | 953 | ||
950 | bool p2p; | 954 | bool p2p; |
951 | 955 | ||
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index ada29a4cc9c8..2c0cb6757fc6 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c | |||
@@ -2398,6 +2398,85 @@ static const struct file_operations fops_warm_hw_reset = { | |||
2398 | .llseek = default_llseek, | 2398 | .llseek = default_llseek, |
2399 | }; | 2399 | }; |
2400 | 2400 | ||
2401 | static void ath10k_peer_ps_state_disable(void *data, | ||
2402 | struct ieee80211_sta *sta) | ||
2403 | { | ||
2404 | struct ath10k *ar = data; | ||
2405 | struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; | ||
2406 | |||
2407 | spin_lock_bh(&ar->data_lock); | ||
2408 | arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED; | ||
2409 | spin_unlock_bh(&ar->data_lock); | ||
2410 | } | ||
2411 | |||
2412 | static ssize_t ath10k_write_ps_state_enable(struct file *file, | ||
2413 | const char __user *user_buf, | ||
2414 | size_t count, loff_t *ppos) | ||
2415 | { | ||
2416 | struct ath10k *ar = file->private_data; | ||
2417 | int ret; | ||
2418 | u32 param; | ||
2419 | u8 ps_state_enable; | ||
2420 | |||
2421 | if (kstrtou8_from_user(user_buf, count, 0, &ps_state_enable)) | ||
2422 | return -EINVAL; | ||
2423 | |||
2424 | if (ps_state_enable > 1 || ps_state_enable < 0) | ||
2425 | return -EINVAL; | ||
2426 | |||
2427 | mutex_lock(&ar->conf_mutex); | ||
2428 | |||
2429 | if (ar->ps_state_enable == ps_state_enable) { | ||
2430 | ret = count; | ||
2431 | goto exit; | ||
2432 | } | ||
2433 | |||
2434 | param = ar->wmi.pdev_param->peer_sta_ps_statechg_enable; | ||
2435 | ret = ath10k_wmi_pdev_set_param(ar, param, ps_state_enable); | ||
2436 | if (ret) { | ||
2437 | ath10k_warn(ar, "failed to enable ps_state_enable: %d\n", | ||
2438 | ret); | ||
2439 | goto exit; | ||
2440 | } | ||
2441 | ar->ps_state_enable = ps_state_enable; | ||
2442 | |||
2443 | if (!ar->ps_state_enable) | ||
2444 | ieee80211_iterate_stations_atomic(ar->hw, | ||
2445 | ath10k_peer_ps_state_disable, | ||
2446 | ar); | ||
2447 | |||
2448 | ret = count; | ||
2449 | |||
2450 | exit: | ||
2451 | mutex_unlock(&ar->conf_mutex); | ||
2452 | |||
2453 | return ret; | ||
2454 | } | ||
2455 | |||
2456 | static ssize_t ath10k_read_ps_state_enable(struct file *file, | ||
2457 | char __user *user_buf, | ||
2458 | size_t count, loff_t *ppos) | ||
2459 | { | ||
2460 | struct ath10k *ar = file->private_data; | ||
2461 | int len = 0; | ||
2462 | char buf[32]; | ||
2463 | |||
2464 | mutex_lock(&ar->conf_mutex); | ||
2465 | len = scnprintf(buf, sizeof(buf) - len, "%d\n", | ||
2466 | ar->ps_state_enable); | ||
2467 | mutex_unlock(&ar->conf_mutex); | ||
2468 | |||
2469 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
2470 | } | ||
2471 | |||
2472 | static const struct file_operations fops_ps_state_enable = { | ||
2473 | .read = ath10k_read_ps_state_enable, | ||
2474 | .write = ath10k_write_ps_state_enable, | ||
2475 | .open = simple_open, | ||
2476 | .owner = THIS_MODULE, | ||
2477 | .llseek = default_llseek, | ||
2478 | }; | ||
2479 | |||
2401 | int ath10k_debug_create(struct ath10k *ar) | 2480 | int ath10k_debug_create(struct ath10k *ar) |
2402 | { | 2481 | { |
2403 | ar->debug.cal_data = vzalloc(ATH10K_DEBUG_CAL_DATA_LEN); | 2482 | ar->debug.cal_data = vzalloc(ATH10K_DEBUG_CAL_DATA_LEN); |
@@ -2534,6 +2613,9 @@ int ath10k_debug_register(struct ath10k *ar) | |||
2534 | debugfs_create_file("warm_hw_reset", 0600, ar->debug.debugfs_phy, ar, | 2613 | debugfs_create_file("warm_hw_reset", 0600, ar->debug.debugfs_phy, ar, |
2535 | &fops_warm_hw_reset); | 2614 | &fops_warm_hw_reset); |
2536 | 2615 | ||
2616 | debugfs_create_file("ps_state_enable", 0600, ar->debug.debugfs_phy, ar, | ||
2617 | &fops_ps_state_enable); | ||
2618 | |||
2537 | return 0; | 2619 | return 0; |
2538 | } | 2620 | } |
2539 | 2621 | ||
diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c index 929f2f66fdce..b09cdc699c69 100644 --- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c | |||
@@ -460,6 +460,33 @@ static const struct file_operations fops_peer_debug_trigger = { | |||
460 | .llseek = default_llseek, | 460 | .llseek = default_llseek, |
461 | }; | 461 | }; |
462 | 462 | ||
463 | static ssize_t ath10k_dbg_sta_read_peer_ps_state(struct file *file, | ||
464 | char __user *user_buf, | ||
465 | size_t count, loff_t *ppos) | ||
466 | { | ||
467 | struct ieee80211_sta *sta = file->private_data; | ||
468 | struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; | ||
469 | struct ath10k *ar = arsta->arvif->ar; | ||
470 | char buf[20]; | ||
471 | int len = 0; | ||
472 | |||
473 | spin_lock_bh(&ar->data_lock); | ||
474 | |||
475 | len = scnprintf(buf, sizeof(buf) - len, "%d\n", | ||
476 | arsta->peer_ps_state); | ||
477 | |||
478 | spin_unlock_bh(&ar->data_lock); | ||
479 | |||
480 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
481 | } | ||
482 | |||
483 | static const struct file_operations fops_peer_ps_state = { | ||
484 | .open = simple_open, | ||
485 | .read = ath10k_dbg_sta_read_peer_ps_state, | ||
486 | .owner = THIS_MODULE, | ||
487 | .llseek = default_llseek, | ||
488 | }; | ||
489 | |||
463 | static char *get_err_str(enum ath10k_pkt_rx_err i) | 490 | static char *get_err_str(enum ath10k_pkt_rx_err i) |
464 | { | 491 | { |
465 | switch (i) { | 492 | switch (i) { |
@@ -738,4 +765,6 @@ void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
738 | ath10k_debug_is_extd_tx_stats_enabled(ar)) | 765 | ath10k_debug_is_extd_tx_stats_enabled(ar)) |
739 | debugfs_create_file("tx_stats", 0400, dir, sta, | 766 | debugfs_create_file("tx_stats", 0400, dir, sta, |
740 | &fops_tx_stats); | 767 | &fops_tx_stats); |
768 | debugfs_create_file("peer_ps_state", 0400, dir, sta, | ||
769 | &fops_peer_ps_state); | ||
741 | } | 770 | } |
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 79b3da25a1a1..dc4e3cc2e882 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c | |||
@@ -6256,6 +6256,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, | |||
6256 | new_state == IEEE80211_STA_NONE) { | 6256 | new_state == IEEE80211_STA_NONE) { |
6257 | memset(arsta, 0, sizeof(*arsta)); | 6257 | memset(arsta, 0, sizeof(*arsta)); |
6258 | arsta->arvif = arvif; | 6258 | arsta->arvif = arvif; |
6259 | arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED; | ||
6259 | INIT_WORK(&arsta->update_wk, ath10k_sta_rc_update_wk); | 6260 | INIT_WORK(&arsta->update_wk, ath10k_sta_rc_update_wk); |
6260 | 6261 | ||
6261 | for (i = 0; i < ARRAY_SIZE(sta->txq); i++) | 6262 | for (i = 0; i < ARRAY_SIZE(sta->txq); i++) |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index c1a46af5f13f..25e8fa789e8d 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c | |||
@@ -1307,7 +1307,8 @@ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = { | |||
1307 | .set_mcast2ucast_mode = WMI_PDEV_PARAM_UNSUPPORTED, | 1307 | .set_mcast2ucast_mode = WMI_PDEV_PARAM_UNSUPPORTED, |
1308 | .set_mcast2ucast_buffer = WMI_PDEV_PARAM_UNSUPPORTED, | 1308 | .set_mcast2ucast_buffer = WMI_PDEV_PARAM_UNSUPPORTED, |
1309 | .remove_mcast2ucast_buffer = WMI_PDEV_PARAM_UNSUPPORTED, | 1309 | .remove_mcast2ucast_buffer = WMI_PDEV_PARAM_UNSUPPORTED, |
1310 | .peer_sta_ps_statechg_enable = WMI_PDEV_PARAM_UNSUPPORTED, | 1310 | .peer_sta_ps_statechg_enable = |
1311 | WMI_10X_PDEV_PARAM_PEER_STA_PS_STATECHG_ENABLE, | ||
1311 | .igmpmld_ac_override = WMI_PDEV_PARAM_UNSUPPORTED, | 1312 | .igmpmld_ac_override = WMI_PDEV_PARAM_UNSUPPORTED, |
1312 | .block_interbss = WMI_PDEV_PARAM_UNSUPPORTED, | 1313 | .block_interbss = WMI_PDEV_PARAM_UNSUPPORTED, |
1313 | .set_disable_reset_cmdid = WMI_PDEV_PARAM_UNSUPPORTED, | 1314 | .set_disable_reset_cmdid = WMI_PDEV_PARAM_UNSUPPORTED, |
@@ -5048,6 +5049,36 @@ ath10k_wmi_handle_tdls_peer_event(struct ath10k *ar, struct sk_buff *skb) | |||
5048 | } | 5049 | } |
5049 | } | 5050 | } |
5050 | 5051 | ||
5052 | static void | ||
5053 | ath10k_wmi_event_peer_sta_ps_state_chg(struct ath10k *ar, struct sk_buff *skb) | ||
5054 | { | ||
5055 | struct wmi_peer_sta_ps_state_chg_event *ev; | ||
5056 | struct ieee80211_sta *sta; | ||
5057 | struct ath10k_sta *arsta; | ||
5058 | u8 peer_addr[ETH_ALEN]; | ||
5059 | |||
5060 | lockdep_assert_held(&ar->data_lock); | ||
5061 | |||
5062 | ev = (struct wmi_peer_sta_ps_state_chg_event *)skb->data; | ||
5063 | ether_addr_copy(peer_addr, ev->peer_macaddr.addr); | ||
5064 | |||
5065 | rcu_read_lock(); | ||
5066 | |||
5067 | sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer_addr, NULL); | ||
5068 | |||
5069 | if (!sta) { | ||
5070 | ath10k_warn(ar, "failed to find station entry %pM\n", | ||
5071 | peer_addr); | ||
5072 | goto exit; | ||
5073 | } | ||
5074 | |||
5075 | arsta = (struct ath10k_sta *)sta->drv_priv; | ||
5076 | arsta->peer_ps_state = __le32_to_cpu(ev->peer_ps_state); | ||
5077 | |||
5078 | exit: | ||
5079 | rcu_read_unlock(); | ||
5080 | } | ||
5081 | |||
5051 | void ath10k_wmi_event_pdev_ftm_intg(struct ath10k *ar, struct sk_buff *skb) | 5082 | void ath10k_wmi_event_pdev_ftm_intg(struct ath10k *ar, struct sk_buff *skb) |
5052 | { | 5083 | { |
5053 | ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PDEV_FTM_INTG_EVENTID\n"); | 5084 | ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PDEV_FTM_INTG_EVENTID\n"); |
@@ -5978,6 +6009,9 @@ static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb) | |||
5978 | ath10k_dbg(ar, ATH10K_DBG_WMI, | 6009 | ath10k_dbg(ar, ATH10K_DBG_WMI, |
5979 | "received event id %d not implemented\n", id); | 6010 | "received event id %d not implemented\n", id); |
5980 | break; | 6011 | break; |
6012 | case WMI_10_2_PEER_STA_PS_STATECHG_EVENTID: | ||
6013 | ath10k_wmi_event_peer_sta_ps_state_chg(ar, skb); | ||
6014 | break; | ||
5981 | default: | 6015 | default: |
5982 | ath10k_warn(ar, "Unknown eventid: %d\n", id); | 6016 | ath10k_warn(ar, "Unknown eventid: %d\n", id); |
5983 | break; | 6017 | break; |
@@ -6095,6 +6129,9 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb) | |||
6095 | case WMI_10_4_DFS_STATUS_CHECK_EVENTID: | 6129 | case WMI_10_4_DFS_STATUS_CHECK_EVENTID: |
6096 | ath10k_wmi_event_dfs_status_check(ar, skb); | 6130 | ath10k_wmi_event_dfs_status_check(ar, skb); |
6097 | break; | 6131 | break; |
6132 | case WMI_10_4_PEER_STA_PS_STATECHG_EVENTID: | ||
6133 | ath10k_wmi_event_peer_sta_ps_state_chg(ar, skb); | ||
6134 | break; | ||
6098 | default: | 6135 | default: |
6099 | ath10k_warn(ar, "Unknown eventid: %d\n", id); | 6136 | ath10k_warn(ar, "Unknown eventid: %d\n", id); |
6100 | break; | 6137 | break; |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 3c09b0e6bd9b..21d1e93632ec 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h | |||
@@ -4161,6 +4161,13 @@ enum wmi_tpc_pream_5ghz { | |||
4161 | WMI_TPC_PREAM_5GHZ_HTCUP, | 4161 | WMI_TPC_PREAM_5GHZ_HTCUP, |
4162 | }; | 4162 | }; |
4163 | 4163 | ||
4164 | #define WMI_PEER_PS_STATE_DISABLED 2 | ||
4165 | |||
4166 | struct wmi_peer_sta_ps_state_chg_event { | ||
4167 | struct wmi_mac_addr peer_macaddr; | ||
4168 | __le32 peer_ps_state; | ||
4169 | } __packed; | ||
4170 | |||
4164 | struct wmi_pdev_chanlist_update_event { | 4171 | struct wmi_pdev_chanlist_update_event { |
4165 | /* number of channels */ | 4172 | /* number of channels */ |
4166 | __le32 num_chan; | 4173 | __le32 num_chan; |