mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 10:04:04 +02:00
wifi: ath11k: Register debugfs for CFR configuration
Provide debugfs interfaces support to config CFR from the user space.
To enable/disable cfr feature use command,
echo <val> > /sys/kernel/debug/ieee80211/phyX/ath11k/enable_cfr
where, val: 0 to disable CFR and 1 to enable CFR.
To enable CFR capture for associated peers,
echo "<val> <bw> <periodicity> <method>"
>
/sys/kernel/debug/ieee80211/phyX/netdev\:wlanx/stations/<mac>/cfr_capture
val: 0 - stop CFR capture
1 - start CFR capture
bw: CFR capture bandwidth
0 - 20MHZ
1 - 40MHZ
2 - 80MHZ
Periodicity: Periodicity at which hardware is expected to collect CFR
dump.
0 - single shot capture.
non zero - for Periodic captures (value must be multiple of 10 ms)
method: Method used by hardware to collect the CFR dump.
0 - from the ACKs of QOS NULL packets.
Also, send the required WMI commands to the firmware based on the CFR
configurations.
Tested-on: IPQ8074 hw2.0 PCI IPQ8074 WLAN.HK.2.5.0.1-00991-QCAHKSWPL_SILICONZ-1
Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-04685-QCAHSPSWPL_V1_V2_SILICONZ_IOE-1
Signed-off-by: Venkateswara Naralasetty <quic_vnaralas@quicinc.com>
Co-developed-by: Yu Zhang (Yuriy) <yu.zhang@oss.qualcomm.com>
Signed-off-by: Yu Zhang (Yuriy) <yu.zhang@oss.qualcomm.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
Signed-off-by: Qian Zhang <qian.zhang@oss.qualcomm.com>
Link: https://patch.msgid.link/20251230082520.3401007-3-qian.zhang@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
This commit is contained in:
parent
9b2e3b4ebe
commit
9754d4ba4d
|
|
@ -14,6 +14,193 @@ static int ath11k_cfr_process_data(struct ath11k *ar,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ath11k_cfr_decrement_peer_count(struct ath11k *ar,
|
||||
struct ath11k_sta *arsta)
|
||||
{
|
||||
struct ath11k_cfr *cfr = &ar->cfr;
|
||||
|
||||
spin_lock_bh(&cfr->lock);
|
||||
|
||||
if (arsta->cfr_capture.cfr_enable)
|
||||
cfr->cfr_enabled_peer_cnt--;
|
||||
|
||||
spin_unlock_bh(&cfr->lock);
|
||||
}
|
||||
|
||||
static enum ath11k_wmi_cfr_capture_bw
|
||||
ath11k_cfr_bw_to_fw_cfr_bw(enum ath11k_cfr_capture_bw bw)
|
||||
{
|
||||
switch (bw) {
|
||||
case ATH11K_CFR_CAPTURE_BW_20:
|
||||
return WMI_PEER_CFR_CAPTURE_BW_20;
|
||||
case ATH11K_CFR_CAPTURE_BW_40:
|
||||
return WMI_PEER_CFR_CAPTURE_BW_40;
|
||||
case ATH11K_CFR_CAPTURE_BW_80:
|
||||
return WMI_PEER_CFR_CAPTURE_BW_80;
|
||||
default:
|
||||
return WMI_PEER_CFR_CAPTURE_BW_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
static enum ath11k_wmi_cfr_capture_method
|
||||
ath11k_cfr_method_to_fw_cfr_method(enum ath11k_cfr_capture_method method)
|
||||
{
|
||||
switch (method) {
|
||||
case ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME:
|
||||
return WMI_CFR_CAPTURE_METHOD_NULL_FRAME;
|
||||
case ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME_WITH_PHASE:
|
||||
return WMI_CFR_CAPTURE_METHOD_NULL_FRAME_WITH_PHASE;
|
||||
case ATH11K_CFR_CAPTURE_METHOD_PROBE_RESP:
|
||||
return WMI_CFR_CAPTURE_METHOD_PROBE_RESP;
|
||||
default:
|
||||
return WMI_CFR_CAPTURE_METHOD_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
int ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k *ar,
|
||||
struct ath11k_sta *arsta,
|
||||
struct ath11k_per_peer_cfr_capture *params,
|
||||
const u8 *peer_mac)
|
||||
{
|
||||
struct ath11k_cfr *cfr = &ar->cfr;
|
||||
struct wmi_peer_cfr_capture_conf_arg arg;
|
||||
enum ath11k_wmi_cfr_capture_bw bw;
|
||||
enum ath11k_wmi_cfr_capture_method method;
|
||||
int ret = 0;
|
||||
|
||||
if (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",
|
||||
cfr->cfr_enabled_peer_cnt);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
if (params->cfr_enable == arsta->cfr_capture.cfr_enable &&
|
||||
params->cfr_period == arsta->cfr_capture.cfr_period &&
|
||||
params->cfr_method == arsta->cfr_capture.cfr_method &&
|
||||
params->cfr_bw == arsta->cfr_capture.cfr_bw)
|
||||
return ret;
|
||||
|
||||
if (!params->cfr_enable && !arsta->cfr_capture.cfr_enable)
|
||||
return ret;
|
||||
|
||||
bw = ath11k_cfr_bw_to_fw_cfr_bw(params->cfr_bw);
|
||||
if (bw >= WMI_PEER_CFR_CAPTURE_BW_MAX) {
|
||||
ath11k_warn(ar->ab, "FW doesn't support configured bw %d\n",
|
||||
params->cfr_bw);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
method = ath11k_cfr_method_to_fw_cfr_method(params->cfr_method);
|
||||
if (method >= WMI_CFR_CAPTURE_METHOD_MAX) {
|
||||
ath11k_warn(ar->ab, "FW doesn't support configured method %d\n",
|
||||
params->cfr_method);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
arg.request = params->cfr_enable;
|
||||
arg.periodicity = params->cfr_period;
|
||||
arg.bw = bw;
|
||||
arg.method = method;
|
||||
|
||||
ret = ath11k_wmi_peer_set_cfr_capture_conf(ar, arsta->arvif->vdev_id,
|
||||
peer_mac, &arg);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab,
|
||||
"failed to send cfr capture info: vdev_id %u peer %pM: %d\n",
|
||||
arsta->arvif->vdev_id, peer_mac, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
spin_lock_bh(&cfr->lock);
|
||||
|
||||
if (params->cfr_enable &&
|
||||
params->cfr_enable != arsta->cfr_capture.cfr_enable)
|
||||
cfr->cfr_enabled_peer_cnt++;
|
||||
else if (!params->cfr_enable)
|
||||
cfr->cfr_enabled_peer_cnt--;
|
||||
|
||||
spin_unlock_bh(&cfr->lock);
|
||||
|
||||
arsta->cfr_capture.cfr_enable = params->cfr_enable;
|
||||
arsta->cfr_capture.cfr_period = params->cfr_period;
|
||||
arsta->cfr_capture.cfr_method = params->cfr_method;
|
||||
arsta->cfr_capture.cfr_bw = params->cfr_bw;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t ath11k_read_file_enable_cfr(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath11k *ar = file->private_data;
|
||||
char buf[32] = {};
|
||||
size_t len;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
len = scnprintf(buf, sizeof(buf), "%d\n", ar->cfr_enabled);
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t ath11k_write_file_enable_cfr(struct file *file,
|
||||
const char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath11k *ar = file->private_data;
|
||||
u32 enable_cfr;
|
||||
int ret;
|
||||
|
||||
if (kstrtouint_from_user(ubuf, count, 0, &enable_cfr))
|
||||
return -EINVAL;
|
||||
|
||||
guard(mutex)(&ar->conf_mutex);
|
||||
|
||||
if (ar->state != ATH11K_STATE_ON)
|
||||
return -ENETDOWN;
|
||||
|
||||
if (enable_cfr > 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (ar->cfr_enabled == enable_cfr)
|
||||
return count;
|
||||
|
||||
ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PER_PEER_CFR_ENABLE,
|
||||
enable_cfr, ar->pdev->pdev_id);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab,
|
||||
"Failed to enable/disable per peer cfr %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ar->cfr_enabled = enable_cfr;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_enable_cfr = {
|
||||
.read = ath11k_read_file_enable_cfr,
|
||||
.write = ath11k_write_file_enable_cfr,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static void ath11k_cfr_debug_unregister(struct ath11k *ar)
|
||||
{
|
||||
debugfs_remove(ar->cfr.enable_cfr);
|
||||
ar->cfr.enable_cfr = NULL;
|
||||
}
|
||||
|
||||
static void ath11k_cfr_debug_register(struct ath11k *ar)
|
||||
{
|
||||
ar->cfr.enable_cfr = debugfs_create_file("enable_cfr", 0600,
|
||||
ar->debug.debugfs_pdev, ar,
|
||||
&fops_enable_cfr);
|
||||
}
|
||||
|
||||
void ath11k_cfr_lut_update_paddr(struct ath11k *ar, dma_addr_t paddr,
|
||||
u32 buf_id)
|
||||
{
|
||||
|
|
@ -88,6 +275,7 @@ void ath11k_cfr_deinit(struct ath11k_base *ab)
|
|||
if (!cfr->enabled)
|
||||
continue;
|
||||
|
||||
ath11k_cfr_debug_unregister(ar);
|
||||
ath11k_cfr_ring_free(ar);
|
||||
|
||||
spin_lock_bh(&cfr->lut_lock);
|
||||
|
|
@ -146,6 +334,8 @@ int ath11k_cfr_init(struct ath11k_base *ab)
|
|||
|
||||
cfr->lut_num = num_lut_entries;
|
||||
cfr->enabled = true;
|
||||
|
||||
ath11k_cfr_debug_register(ar);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -158,6 +348,7 @@ int ath11k_cfr_init(struct ath11k_base *ab)
|
|||
if (!cfr->enabled)
|
||||
continue;
|
||||
|
||||
ath11k_cfr_debug_unregister(ar);
|
||||
ath11k_cfr_ring_free(ar);
|
||||
|
||||
spin_lock_bh(&cfr->lut_lock);
|
||||
|
|
|
|||
|
|
@ -14,10 +14,14 @@
|
|||
#define ATH11K_CFR_EVENT_TIMEOUT_MS 1
|
||||
#define ATH11K_CFR_NUM_RING_ENTRIES 1
|
||||
|
||||
#define ATH11K_MAX_CFR_ENABLED_CLIENTS 10
|
||||
#define CFR_MAX_LUT_ENTRIES 136
|
||||
|
||||
#define HOST_MAX_CHAINS 8
|
||||
|
||||
struct ath11k_sta;
|
||||
struct ath11k_per_peer_cfr_capture;
|
||||
|
||||
struct ath11k_cfr_dma_hdr {
|
||||
u16 info0;
|
||||
u16 info1;
|
||||
|
|
@ -48,6 +52,8 @@ struct ath11k_cfr {
|
|||
/* Protect for lut entries */
|
||||
spinlock_t lut_lock;
|
||||
struct ath11k_look_up_table *lut;
|
||||
struct dentry *enable_cfr;
|
||||
u8 cfr_enabled_peer_cnt;
|
||||
u32 lut_num;
|
||||
u64 tx_evt_cnt;
|
||||
u64 dbr_evt_cnt;
|
||||
|
|
@ -62,11 +68,32 @@ struct ath11k_cfr {
|
|||
bool enabled;
|
||||
};
|
||||
|
||||
enum ath11k_cfr_capture_method {
|
||||
ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME,
|
||||
ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME_WITH_PHASE,
|
||||
ATH11K_CFR_CAPTURE_METHOD_PROBE_RESP,
|
||||
ATH11K_CFR_CAPTURE_METHOD_MAX,
|
||||
};
|
||||
|
||||
enum ath11k_cfr_capture_bw {
|
||||
ATH11K_CFR_CAPTURE_BW_20,
|
||||
ATH11K_CFR_CAPTURE_BW_40,
|
||||
ATH11K_CFR_CAPTURE_BW_80,
|
||||
ATH11K_CFR_CAPTURE_BW_MAX,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ATH11K_CFR
|
||||
int ath11k_cfr_init(struct ath11k_base *ab);
|
||||
void ath11k_cfr_deinit(struct ath11k_base *ab);
|
||||
void ath11k_cfr_lut_update_paddr(struct ath11k *ar, dma_addr_t paddr,
|
||||
u32 buf_id);
|
||||
void ath11k_cfr_decrement_peer_count(struct ath11k *ar,
|
||||
struct ath11k_sta *arsta);
|
||||
int ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k *ar,
|
||||
struct ath11k_sta *arsta,
|
||||
struct ath11k_per_peer_cfr_capture *params,
|
||||
const u8 *peer_mac);
|
||||
|
||||
#else
|
||||
static inline int ath11k_cfr_init(struct ath11k_base *ab)
|
||||
{
|
||||
|
|
@ -81,5 +108,19 @@ static inline void ath11k_cfr_lut_update_paddr(struct ath11k *ar,
|
|||
dma_addr_t paddr, u32 buf_id)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void ath11k_cfr_decrement_peer_count(struct ath11k *ar,
|
||||
struct ath11k_sta *arsta)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int
|
||||
ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k *ar,
|
||||
struct ath11k_sta *arsta,
|
||||
struct ath11k_per_peer_cfr_capture *params,
|
||||
const u8 *peer_mac)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_ATH11K_CFR */
|
||||
#endif /* ATH11K_CFR_H */
|
||||
|
|
|
|||
|
|
@ -532,6 +532,13 @@ struct ath11k_per_ppdu_tx_stats {
|
|||
|
||||
DECLARE_EWMA(avg_rssi, 10, 8)
|
||||
|
||||
struct ath11k_per_peer_cfr_capture {
|
||||
enum ath11k_cfr_capture_method cfr_method;
|
||||
enum ath11k_cfr_capture_bw cfr_bw;
|
||||
u32 cfr_enable;
|
||||
u32 cfr_period;
|
||||
};
|
||||
|
||||
struct ath11k_sta {
|
||||
struct ath11k_vif *arvif;
|
||||
|
||||
|
|
@ -572,6 +579,10 @@ struct ath11k_sta {
|
|||
bool peer_current_ps_valid;
|
||||
|
||||
u32 bw_prev;
|
||||
|
||||
#ifdef CONFIG_ATH11K_CFR
|
||||
struct ath11k_per_peer_cfr_capture cfr_capture;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define ATH11K_MIN_5G_FREQ 4150
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -9979,6 +9979,8 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
|
|||
}
|
||||
spin_unlock_bh(&ar->ab->base_lock);
|
||||
mutex_unlock(&ar->ab->tbl_mtx_lock);
|
||||
|
||||
ath11k_cfr_decrement_peer_count(ar, arsta);
|
||||
} else if (old_state == IEEE80211_STA_AUTH &&
|
||||
new_state == IEEE80211_STA_ASSOC &&
|
||||
(vif->type == NL80211_IFTYPE_AP ||
|
||||
|
|
|
|||
|
|
@ -3941,6 +3941,47 @@ int ath11k_wmi_fils_discovery_tmpl(struct ath11k *ar, u32 vdev_id,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ath11k_wmi_peer_set_cfr_capture_conf(struct ath11k *ar,
|
||||
u32 vdev_id, const u8 *mac_addr,
|
||||
struct wmi_peer_cfr_capture_conf_arg *arg)
|
||||
{
|
||||
struct ath11k_pdev_wmi *wmi = ar->wmi;
|
||||
struct wmi_peer_cfr_capture_cmd_fixed_param *cmd;
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
|
||||
skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_peer_cfr_capture_cmd_fixed_param *)skb->data;
|
||||
cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG,
|
||||
WMI_TAG_PEER_CFR_CAPTURE_CMD) |
|
||||
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
|
||||
|
||||
memcpy(&cmd->mac_addr, mac_addr, ETH_ALEN);
|
||||
cmd->request = arg->request;
|
||||
cmd->vdev_id = vdev_id;
|
||||
cmd->periodicity = arg->periodicity;
|
||||
cmd->bandwidth = arg->bw;
|
||||
cmd->capture_method = arg->method;
|
||||
|
||||
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_PEER_CFR_CAPTURE_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab,
|
||||
"WMI vdev %d failed to send peer cfr capture cmd: %d\n",
|
||||
vdev_id, ret);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
|
||||
"WMI peer CFR capture cmd req %u id %u period %u bw %u mode %u\n",
|
||||
arg->request, vdev_id, arg->periodicity,
|
||||
arg->bw, arg->method);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_probe_resp_tmpl(struct ath11k *ar, u32 vdev_id,
|
||||
struct sk_buff *tmpl)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -362,6 +362,10 @@ enum wmi_tlv_cmd_id {
|
|||
WMI_PEER_REORDER_QUEUE_REMOVE_CMDID,
|
||||
WMI_PEER_SET_RX_BLOCKSIZE_CMDID,
|
||||
WMI_PEER_ANTDIV_INFO_REQ_CMDID,
|
||||
WMI_PEER_RESERVED0_CMDID,
|
||||
WMI_PEER_TID_MSDUQ_QDEPTH_THRESH_UPDATE_CMDID,
|
||||
WMI_PEER_TID_CONFIGURATIONS_CMDID,
|
||||
WMI_PEER_CFR_CAPTURE_CMDID,
|
||||
WMI_BCN_TX_CMDID = WMI_TLV_CMD(WMI_GRP_MGMT),
|
||||
WMI_PDEV_SEND_BCN_CMDID,
|
||||
WMI_BCN_TMPL_CMDID,
|
||||
|
|
@ -3833,7 +3837,8 @@ struct wmi_scan_prob_req_oui_cmd {
|
|||
#define WMI_TX_PARAMS_DWORD1_BW_MASK GENMASK(14, 8)
|
||||
#define WMI_TX_PARAMS_DWORD1_PREAMBLE_TYPE GENMASK(19, 15)
|
||||
#define WMI_TX_PARAMS_DWORD1_FRAME_TYPE BIT(20)
|
||||
#define WMI_TX_PARAMS_DWORD1_RSVD GENMASK(31, 21)
|
||||
#define WMI_TX_PARAMS_DWORD1_CFR_CAPTURE BIT(21)
|
||||
#define WMI_TX_PARAMS_DWORD1_RSVD GENMASK(31, 22)
|
||||
|
||||
struct wmi_mgmt_send_params {
|
||||
u32 tlv_header;
|
||||
|
|
@ -4218,6 +4223,45 @@ enum cc_setting_code {
|
|||
*/
|
||||
};
|
||||
|
||||
enum ath11k_wmi_cfr_capture_bw {
|
||||
WMI_PEER_CFR_CAPTURE_BW_20,
|
||||
WMI_PEER_CFR_CAPTURE_BW_40,
|
||||
WMI_PEER_CFR_CAPTURE_BW_80,
|
||||
WMI_PEER_CFR_CAPTURE_BW_MAX,
|
||||
};
|
||||
|
||||
enum ath11k_wmi_cfr_capture_method {
|
||||
WMI_CFR_CAPTURE_METHOD_NULL_FRAME,
|
||||
WMI_CFR_CAPTURE_METHOD_NULL_FRAME_WITH_PHASE,
|
||||
WMI_CFR_CAPTURE_METHOD_PROBE_RESP,
|
||||
WMI_CFR_CAPTURE_METHOD_MAX,
|
||||
};
|
||||
|
||||
struct wmi_peer_cfr_capture_conf_arg {
|
||||
enum ath11k_wmi_cfr_capture_bw bw;
|
||||
enum ath11k_wmi_cfr_capture_method method;
|
||||
u32 request;
|
||||
u32 periodicity;
|
||||
};
|
||||
|
||||
struct wmi_peer_cfr_capture_cmd_fixed_param {
|
||||
u32 tlv_header;
|
||||
u32 request;
|
||||
struct wmi_mac_addr mac_addr;
|
||||
u32 vdev_id;
|
||||
u32 periodicity;
|
||||
/* BW of measurement - of type enum ath11k_wmi_cfr_capture_bw */
|
||||
u32 bandwidth;
|
||||
/* Method used to capture CFR - of type enum ath11k_wmi_cfr_capture_method */
|
||||
u32 capture_method;
|
||||
} __packed;
|
||||
|
||||
#define WMI_PEER_CFR_CAPTURE_ENABLE 1
|
||||
#define WMI_PEER_CFR_CAPTURE_DISABLE 0
|
||||
|
||||
/*periodicity in ms */
|
||||
#define WMI_PEER_CFR_PERIODICITY_MAX 600000
|
||||
|
||||
static inline enum cc_setting_code
|
||||
ath11k_wmi_cc_setting_code_to_reg(enum wmi_reg_cc_setting_code status_code)
|
||||
{
|
||||
|
|
@ -6532,5 +6576,7 @@ bool ath11k_wmi_supports_6ghz_cc_ext(struct ath11k *ar);
|
|||
int ath11k_wmi_send_vdev_set_tpc_power(struct ath11k *ar,
|
||||
u32 vdev_id,
|
||||
struct ath11k_reg_tpc_power_info *param);
|
||||
|
||||
int ath11k_wmi_peer_set_cfr_capture_conf(struct ath11k *ar,
|
||||
u32 vdev_id, const u8 *mac,
|
||||
struct wmi_peer_cfr_capture_conf_arg *arg);
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user