diff options
Diffstat (limited to 'debugfs_sta.c')
| -rw-r--r-- | debugfs_sta.c | 142 |
1 files changed, 141 insertions, 1 deletions
diff --git a/debugfs_sta.c b/debugfs_sta.c index d89d0f28d890..621a8a8df4b8 100644 --- a/debugfs_sta.c +++ b/debugfs_sta.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ @@ -240,6 +239,140 @@ static const struct file_operations fops_tx_stats = { .llseek = default_llseek, }; +#ifdef CONFIG_ATH11K_CFR +static ssize_t ath11k_dbg_sta_write_cfr_capture(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_sta *sta = file->private_data; + struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta); + struct ath11k *ar = arsta->arvif->ar; + struct ath11k_cfr *cfr = &ar->cfr; + struct wmi_peer_cfr_capture_conf_arg arg; + u32 cfr_capture_enable = 0, cfr_capture_bw = 0; + u32 cfr_capture_method = 0, cfr_capture_period = 0; + char buf[64] = {}; + int ret; + + simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count); + + guard(mutex)(&ar->conf_mutex); + + if (ar->state != ATH11K_STATE_ON) + return -ENETDOWN; + + if (!ar->cfr_enabled) + return -EINVAL; + + ret = sscanf(buf, "%u %u %u %u", &cfr_capture_enable, &cfr_capture_bw, + &cfr_capture_period, &cfr_capture_method); + + if (ret < 1 || (cfr_capture_enable && ret != 4)) + return -EINVAL; + + if (cfr_capture_enable == arsta->cfr_capture.cfr_enable && + (cfr_capture_period && + cfr_capture_period == arsta->cfr_capture.cfr_period) && + cfr_capture_bw == arsta->cfr_capture.cfr_bw && + cfr_capture_method == arsta->cfr_capture.cfr_method) + return count; + + if (!cfr_capture_enable && + cfr_capture_enable == arsta->cfr_capture.cfr_enable) + return count; + + if (cfr_capture_enable > WMI_PEER_CFR_CAPTURE_ENABLE || + cfr_capture_bw > WMI_PEER_CFR_CAPTURE_BW_80 || + cfr_capture_method > ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME_WITH_PHASE || + cfr_capture_period > WMI_PEER_CFR_PERIODICITY_MAX) + return -EINVAL; + + /* Target expects cfr period in multiple of 10 */ + if (cfr_capture_period % 10) { + ath11k_err(ar->ab, "periodicity should be 10x\n"); + return -EINVAL; + } + + if (ar->cfr.cfr_enabled_peer_cnt >= ATH11K_MAX_CFR_ENABLED_CLIENTS && + !arsta->cfr_capture.cfr_enable) { + ath11k_err(ar->ab, "CFR enable peer threshold reached %u\n", + ar->cfr.cfr_enabled_peer_cnt); + return -EINVAL; + } + + if (!cfr_capture_enable) { + cfr_capture_bw = arsta->cfr_capture.cfr_bw; + cfr_capture_period = arsta->cfr_capture.cfr_period; + cfr_capture_method = arsta->cfr_capture.cfr_method; + } + + arg.request = cfr_capture_enable; + arg.periodicity = cfr_capture_period; + arg.bw = cfr_capture_bw; + arg.method = cfr_capture_method; + + ret = ath11k_wmi_peer_set_cfr_capture_conf(ar, arsta->arvif->vdev_id, + sta->addr, &arg); + if (ret) { + ath11k_warn(ar->ab, + "failed to send cfr capture info: vdev_id %u peer %pM: %d\n", + arsta->arvif->vdev_id, sta->addr, ret); + return ret; + } + + spin_lock_bh(&ar->cfr.lock); + + if (cfr_capture_enable && + cfr_capture_enable != arsta->cfr_capture.cfr_enable) + cfr->cfr_enabled_peer_cnt++; + else if (!cfr_capture_enable) + cfr->cfr_enabled_peer_cnt--; + + spin_unlock_bh(&ar->cfr.lock); + + arsta->cfr_capture.cfr_enable = cfr_capture_enable; + arsta->cfr_capture.cfr_period = cfr_capture_period; + arsta->cfr_capture.cfr_bw = cfr_capture_bw; + arsta->cfr_capture.cfr_method = cfr_capture_method; + + return count; +} + +static ssize_t ath11k_dbg_sta_read_cfr_capture(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_sta *sta = file->private_data; + struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta); + struct ath11k *ar = arsta->arvif->ar; + char buf[512] = {}; + int len = 0; + + mutex_lock(&ar->conf_mutex); + + len += scnprintf(buf + len, sizeof(buf) - len, "cfr_enabled = %d\n", + arsta->cfr_capture.cfr_enable); + len += scnprintf(buf + len, sizeof(buf) - len, "bandwidth = %d\n", + arsta->cfr_capture.cfr_bw); + len += scnprintf(buf + len, sizeof(buf) - len, "period = %d\n", + arsta->cfr_capture.cfr_period); + len += scnprintf(buf + len, sizeof(buf) - len, "cfr_method = %d\n", + arsta->cfr_capture.cfr_method); + + mutex_unlock(&ar->conf_mutex); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_peer_cfr_capture = { + .write = ath11k_dbg_sta_write_cfr_capture, + .read = ath11k_dbg_sta_read_cfr_capture, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; +#endif /* CONFIG_ATH11K_CFR */ + static ssize_t ath11k_dbg_sta_dump_rx_stats(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -877,6 +1010,13 @@ void ath11k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vi debugfs_create_file("htt_peer_stats_reset", 0600, dir, sta, &fops_htt_peer_stats_reset); +#ifdef CONFIG_ATH11K_CFR + if (test_bit(WMI_TLV_SERVICE_CFR_CAPTURE_SUPPORT, + ar->ab->wmi_ab.svc_map)) + debugfs_create_file("cfr_capture", 0600, dir, sta, + &fops_peer_cfr_capture); +#endif/* CONFIG_ATH11K_CFR */ + debugfs_create_file("peer_ps_state", 0400, dir, sta, &fops_peer_ps_state); |
