^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright 2003-2005 Devicescape Software, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright 2013-2014 Intel Mobile Communications GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright(c) 2016 Intel Deutschland GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2018 - 2020 Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/ieee80211.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "ieee80211_i.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "debugfs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "debugfs_sta.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "sta_info.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "driver-ops.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /* sta attributtes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define STA_READ(name, field, format_string) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static ssize_t sta_ ##name## _read(struct file *file, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) char __user *userbuf, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) size_t count, loff_t *ppos) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct sta_info *sta = file->private_data; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) return mac80211_format_buffer(userbuf, count, ppos, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) format_string, sta->field); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define STA_READ_D(name, field) STA_READ(name, field, "%d\n")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define STA_OPS(name) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static const struct file_operations sta_ ##name## _ops = { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) .read = sta_##name##_read, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) .open = simple_open, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) .llseek = generic_file_llseek, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define STA_OPS_RW(name) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static const struct file_operations sta_ ##name## _ops = { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) .read = sta_##name##_read, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) .write = sta_##name##_write, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) .open = simple_open, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) .llseek = generic_file_llseek, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define STA_FILE(name, field, format) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) STA_READ_##format(name, field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) STA_OPS(name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) STA_FILE(aid, sta.aid, D);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static const char * const sta_flag_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define FLAG(F) [WLAN_STA_##F] = #F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) FLAG(AUTH),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) FLAG(ASSOC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) FLAG(PS_STA),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) FLAG(AUTHORIZED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) FLAG(SHORT_PREAMBLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) FLAG(WDS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) FLAG(CLEAR_PS_FILT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) FLAG(MFP),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) FLAG(BLOCK_BA),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) FLAG(PS_DRIVER),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) FLAG(PSPOLL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) FLAG(TDLS_PEER),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) FLAG(TDLS_PEER_AUTH),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) FLAG(TDLS_INITIATOR),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) FLAG(TDLS_CHAN_SWITCH),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) FLAG(TDLS_OFF_CHANNEL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) FLAG(TDLS_WIDER_BW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) FLAG(UAPSD),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) FLAG(SP),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) FLAG(4ADDR_EVENT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) FLAG(INSERTED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) FLAG(RATE_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) FLAG(TOFFSET_KNOWN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) FLAG(MPSP_OWNER),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) FLAG(MPSP_RECIPIENT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) FLAG(PS_DELIVER),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) FLAG(USES_ENCRYPTION),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #undef FLAG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) char buf[16 * NUM_WLAN_STA_FLAGS], *pos = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) char *end = buf + sizeof(buf) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct sta_info *sta = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) unsigned int flg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) BUILD_BUG_ON(ARRAY_SIZE(sta_flag_names) != NUM_WLAN_STA_FLAGS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) for (flg = 0; flg < NUM_WLAN_STA_FLAGS; flg++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (test_sta_flag(sta, flg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) pos += scnprintf(pos, end - pos, "%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) sta_flag_names[flg]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) STA_OPS(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static ssize_t sta_num_ps_buf_frames_read(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) char __user *userbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct sta_info *sta = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) char buf[17*IEEE80211_NUM_ACS], *p = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) int ac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) p += scnprintf(p, sizeof(buf)+buf-p, "AC%d: %d\n", ac,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) skb_queue_len(&sta->ps_tx_buf[ac]) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) skb_queue_len(&sta->tx_filtered[ac]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) STA_OPS(num_ps_buf_frames);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static ssize_t sta_last_seq_ctrl_read(struct file *file, char __user *userbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) char buf[15*IEEE80211_NUM_TIDS], *p = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct sta_info *sta = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) for (i = 0; i < IEEE80211_NUM_TIDS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) p += scnprintf(p, sizeof(buf)+buf-p, "%x ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) le16_to_cpu(sta->last_seq_ctrl[i]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) p += scnprintf(p, sizeof(buf)+buf-p, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) STA_OPS(last_seq_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define AQM_TXQ_ENTRY_LEN 130
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static ssize_t sta_aqm_read(struct file *file, char __user *userbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct sta_info *sta = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct ieee80211_local *local = sta->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) size_t bufsz = AQM_TXQ_ENTRY_LEN * (IEEE80211_NUM_TIDS + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) char *buf = kzalloc(bufsz, GFP_KERNEL), *p = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) struct txq_info *txqi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) ssize_t rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) spin_lock_bh(&local->fq.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) p += scnprintf(p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) bufsz+buf-p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) "target %uus interval %uus ecn %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) codel_time_to_us(sta->cparams.target),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) codel_time_to_us(sta->cparams.interval),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) sta->cparams.ecn ? "yes" : "no");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) p += scnprintf(p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) bufsz+buf-p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) "tid ac backlog-bytes backlog-packets new-flows drops marks overlimit collisions tx-bytes tx-packets flags\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (!sta->sta.txq[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) txqi = to_txq_info(sta->sta.txq[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) p += scnprintf(p, bufsz+buf-p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) "%d %d %u %u %u %u %u %u %u %u %u 0x%lx(%s%s%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) txqi->txq.tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) txqi->txq.ac,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) txqi->tin.backlog_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) txqi->tin.backlog_packets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) txqi->tin.flows,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) txqi->cstats.drop_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) txqi->cstats.ecn_mark,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) txqi->tin.overlimit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) txqi->tin.collisions,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) txqi->tin.tx_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) txqi->tin.tx_packets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) txqi->flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) test_bit(IEEE80211_TXQ_STOP, &txqi->flags) ? "STOP" : "RUN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags) ? " AMPDU" : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) test_bit(IEEE80211_TXQ_NO_AMSDU, &txqi->flags) ? " NO-AMSDU" : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) spin_unlock_bh(&local->fq.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) rv = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) STA_OPS(aqm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static ssize_t sta_airtime_read(struct file *file, char __user *userbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct sta_info *sta = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) struct ieee80211_local *local = sta->sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) size_t bufsz = 400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) char *buf = kzalloc(bufsz, GFP_KERNEL), *p = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) u64 rx_airtime = 0, tx_airtime = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) s64 deficit[IEEE80211_NUM_ACS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) ssize_t rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) int ac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) spin_lock_bh(&local->active_txq_lock[ac]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) rx_airtime += sta->airtime[ac].rx_airtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) tx_airtime += sta->airtime[ac].tx_airtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) deficit[ac] = sta->airtime[ac].deficit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) spin_unlock_bh(&local->active_txq_lock[ac]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) p += scnprintf(p, bufsz + buf - p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) "RX: %llu us\nTX: %llu us\nWeight: %u\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) "Deficit: VO: %lld us VI: %lld us BE: %lld us BK: %lld us\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) rx_airtime, tx_airtime, sta->airtime_weight,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) deficit[0], deficit[1], deficit[2], deficit[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) rv = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) static ssize_t sta_airtime_write(struct file *file, const char __user *userbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) struct sta_info *sta = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) struct ieee80211_local *local = sta->sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) int ac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) spin_lock_bh(&local->active_txq_lock[ac]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) sta->airtime[ac].rx_airtime = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) sta->airtime[ac].tx_airtime = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) sta->airtime[ac].deficit = sta->airtime_weight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) spin_unlock_bh(&local->active_txq_lock[ac]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) STA_OPS_RW(airtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) static ssize_t sta_aql_read(struct file *file, char __user *userbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct sta_info *sta = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) struct ieee80211_local *local = sta->sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) size_t bufsz = 400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) char *buf = kzalloc(bufsz, GFP_KERNEL), *p = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) u32 q_depth[IEEE80211_NUM_ACS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) u32 q_limit_l[IEEE80211_NUM_ACS], q_limit_h[IEEE80211_NUM_ACS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) ssize_t rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) int ac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) spin_lock_bh(&local->active_txq_lock[ac]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) q_limit_l[ac] = sta->airtime[ac].aql_limit_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) q_limit_h[ac] = sta->airtime[ac].aql_limit_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) spin_unlock_bh(&local->active_txq_lock[ac]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) q_depth[ac] = atomic_read(&sta->airtime[ac].aql_tx_pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) p += scnprintf(p, bufsz + buf - p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) "Q depth: VO: %u us VI: %u us BE: %u us BK: %u us\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) "Q limit[low/high]: VO: %u/%u VI: %u/%u BE: %u/%u BK: %u/%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) q_depth[0], q_depth[1], q_depth[2], q_depth[3],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) q_limit_l[0], q_limit_h[0], q_limit_l[1], q_limit_h[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) q_limit_l[2], q_limit_h[2], q_limit_l[3], q_limit_h[3]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) rv = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static ssize_t sta_aql_write(struct file *file, const char __user *userbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) struct sta_info *sta = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) u32 ac, q_limit_l, q_limit_h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) char _buf[100] = {}, *buf = _buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (count > sizeof(_buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (copy_from_user(buf, userbuf, count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) buf[sizeof(_buf) - 1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (sscanf(buf, "limit %u %u %u", &ac, &q_limit_l, &q_limit_h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) != 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (ac >= IEEE80211_NUM_ACS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) sta->airtime[ac].aql_limit_low = q_limit_l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) sta->airtime[ac].aql_limit_high = q_limit_h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) STA_OPS_RW(aql);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) char buf[71 + IEEE80211_NUM_TIDS * 40], *p = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) struct sta_info *sta = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct tid_ampdu_rx *tid_rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) struct tid_ampdu_tx *tid_tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) sta->ampdu_mlme.dialog_token_allocator + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) p += scnprintf(p, sizeof(buf) + buf - p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) "TID\t\tRX\tDTKN\tSSN\t\tTX\tDTKN\tpending\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) bool tid_rx_valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) tid_rx_valid = test_bit(i, sta->ampdu_mlme.agg_session_valid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) tid_rx_valid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) tid_rx_valid ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) sta->ampdu_mlme.tid_rx_token[i] : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) tid_rx ? tid_rx->ssn : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", !!tid_tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) tid_tx ? tid_tx->dialog_token : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) p += scnprintf(p, sizeof(buf) + buf - p, "\t%03d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) tid_tx ? skb_queue_len(&tid_tx->pending) : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) p += scnprintf(p, sizeof(buf) + buf - p, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) static ssize_t sta_agg_status_write(struct file *file, const char __user *userbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) char _buf[25] = {}, *buf = _buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) struct sta_info *sta = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) bool start, tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) unsigned long tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) char *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) int ret, timeout = 5000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (count > sizeof(_buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (copy_from_user(buf, userbuf, count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) buf[sizeof(_buf) - 1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) pos = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) buf = strsep(&pos, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (!strcmp(buf, "tx"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) tx = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) else if (!strcmp(buf, "rx"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) tx = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) buf = strsep(&pos, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (!strcmp(buf, "start")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) start = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (!tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) } else if (!strcmp(buf, "stop")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) start = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) buf = strsep(&pos, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (sscanf(buf, "timeout=%d", &timeout) == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) buf = strsep(&pos, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (!buf || !tx || !start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) ret = kstrtoul(buf, 0, &tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (ret || tid >= IEEE80211_NUM_TIDS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (tx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) ret = ieee80211_start_tx_ba_session(&sta->sta, tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) ret = ieee80211_stop_tx_ba_session(&sta->sta, tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 3, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) return ret ?: count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) STA_OPS_RW(agg_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) #define PRINT_HT_CAP(_cond, _str) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (_cond) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) p += scnprintf(p, sizeof(buf)+buf-p, "\t" _str "\n"); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) char buf[512], *p = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) struct sta_info *sta = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) struct ieee80211_sta_ht_cap *htc = &sta->sta.ht_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) p += scnprintf(p, sizeof(buf) + buf - p, "ht %ssupported\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) htc->ht_supported ? "" : "not ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (htc->ht_supported) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) p += scnprintf(p, sizeof(buf)+buf-p, "cap: %#.4x\n", htc->cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) PRINT_HT_CAP((htc->cap & BIT(0)), "RX LDPC");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) PRINT_HT_CAP((htc->cap & BIT(1)), "HT20/HT40");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) PRINT_HT_CAP(!(htc->cap & BIT(1)), "HT20");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) PRINT_HT_CAP(((htc->cap >> 2) & 0x3) == 0, "Static SM Power Save");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) PRINT_HT_CAP(((htc->cap >> 2) & 0x3) == 1, "Dynamic SM Power Save");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) PRINT_HT_CAP(((htc->cap >> 2) & 0x3) == 3, "SM Power Save disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) PRINT_HT_CAP((htc->cap & BIT(4)), "RX Greenfield");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) PRINT_HT_CAP((htc->cap & BIT(5)), "RX HT20 SGI");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) PRINT_HT_CAP((htc->cap & BIT(6)), "RX HT40 SGI");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) PRINT_HT_CAP((htc->cap & BIT(7)), "TX STBC");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 0, "No RX STBC");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 1, "RX STBC 1-stream");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 2, "RX STBC 2-streams");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 3, "RX STBC 3-streams");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) PRINT_HT_CAP((htc->cap & BIT(10)), "HT Delayed Block Ack");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) PRINT_HT_CAP(!(htc->cap & BIT(11)), "Max AMSDU length: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) "3839 bytes");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) PRINT_HT_CAP((htc->cap & BIT(11)), "Max AMSDU length: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) "7935 bytes");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) * For beacons and probe response this would mean the BSS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * does or does not allow the usage of DSSS/CCK HT40.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) * Otherwise it means the STA does or does not use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * DSSS/CCK HT40.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) PRINT_HT_CAP((htc->cap & BIT(12)), "DSSS/CCK HT40");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) PRINT_HT_CAP(!(htc->cap & BIT(12)), "No DSSS/CCK HT40");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) /* BIT(13) is reserved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) PRINT_HT_CAP((htc->cap & BIT(14)), "40 MHz Intolerant");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) PRINT_HT_CAP((htc->cap & BIT(15)), "L-SIG TXOP protection");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) p += scnprintf(p, sizeof(buf)+buf-p, "ampdu factor/density: %d/%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) htc->ampdu_factor, htc->ampdu_density);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) p += scnprintf(p, sizeof(buf)+buf-p, "MCS mask:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) p += scnprintf(p, sizeof(buf)+buf-p, " %.2x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) htc->mcs.rx_mask[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) p += scnprintf(p, sizeof(buf)+buf-p, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) /* If not set this is meaningless */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (le16_to_cpu(htc->mcs.rx_highest)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) p += scnprintf(p, sizeof(buf)+buf-p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) "MCS rx highest: %d Mbps\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) le16_to_cpu(htc->mcs.rx_highest));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) p += scnprintf(p, sizeof(buf)+buf-p, "MCS tx params: %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) htc->mcs.tx_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) STA_OPS(ht_capa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) static ssize_t sta_vht_capa_read(struct file *file, char __user *userbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) char buf[512], *p = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) struct sta_info *sta = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) struct ieee80211_sta_vht_cap *vhtc = &sta->sta.vht_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) p += scnprintf(p, sizeof(buf) + buf - p, "VHT %ssupported\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) vhtc->vht_supported ? "" : "not ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (vhtc->vht_supported) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) p += scnprintf(p, sizeof(buf) + buf - p, "cap: %#.8x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) vhtc->cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) #define PFLAG(a, b) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (vhtc->cap & IEEE80211_VHT_CAP_ ## a) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) p += scnprintf(p, sizeof(buf) + buf - p, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) "\t\t%s\n", b); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) switch (vhtc->cap & 0x3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) p += scnprintf(p, sizeof(buf) + buf - p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) "\t\tMAX-MPDU-3895\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) p += scnprintf(p, sizeof(buf) + buf - p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) "\t\tMAX-MPDU-7991\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) p += scnprintf(p, sizeof(buf) + buf - p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) "\t\tMAX-MPDU-11454\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) p += scnprintf(p, sizeof(buf) + buf - p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) "\t\tMAX-MPDU-UNKNOWN\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) switch (vhtc->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) p += scnprintf(p, sizeof(buf) + buf - p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) "\t\t80Mhz\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) p += scnprintf(p, sizeof(buf) + buf - p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) "\t\t160Mhz\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) p += scnprintf(p, sizeof(buf) + buf - p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) "\t\t80+80Mhz\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) p += scnprintf(p, sizeof(buf) + buf - p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) "\t\tUNKNOWN-MHZ: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) (vhtc->cap >> 2) & 0x3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) PFLAG(RXLDPC, "RXLDPC");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) PFLAG(SHORT_GI_80, "SHORT-GI-80");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) PFLAG(SHORT_GI_160, "SHORT-GI-160");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) PFLAG(TXSTBC, "TXSTBC");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) p += scnprintf(p, sizeof(buf) + buf - p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) "\t\tRXSTBC_%d\n", (vhtc->cap >> 8) & 0x7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) PFLAG(SU_BEAMFORMER_CAPABLE, "SU-BEAMFORMER-CAPABLE");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) PFLAG(SU_BEAMFORMEE_CAPABLE, "SU-BEAMFORMEE-CAPABLE");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) p += scnprintf(p, sizeof(buf) + buf - p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) "\t\tBEAMFORMEE-STS: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) (vhtc->cap & IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) p += scnprintf(p, sizeof(buf) + buf - p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) "\t\tSOUNDING-DIMENSIONS: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) (vhtc->cap & IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) >> IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) PFLAG(MU_BEAMFORMER_CAPABLE, "MU-BEAMFORMER-CAPABLE");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) PFLAG(MU_BEAMFORMEE_CAPABLE, "MU-BEAMFORMEE-CAPABLE");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) PFLAG(VHT_TXOP_PS, "TXOP-PS");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) PFLAG(HTC_VHT, "HTC-VHT");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) p += scnprintf(p, sizeof(buf) + buf - p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) "\t\tMPDU-LENGTH-EXPONENT: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) (vhtc->cap & IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) PFLAG(VHT_LINK_ADAPTATION_VHT_UNSOL_MFB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) "LINK-ADAPTATION-VHT-UNSOL-MFB");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) p += scnprintf(p, sizeof(buf) + buf - p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) "\t\tLINK-ADAPTATION-VHT-MRQ-MFB: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) (vhtc->cap & IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB) >> 26);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) PFLAG(RX_ANTENNA_PATTERN, "RX-ANTENNA-PATTERN");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) PFLAG(TX_ANTENNA_PATTERN, "TX-ANTENNA-PATTERN");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) p += scnprintf(p, sizeof(buf)+buf-p, "RX MCS: %.4x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) le16_to_cpu(vhtc->vht_mcs.rx_mcs_map));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (vhtc->vht_mcs.rx_highest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) p += scnprintf(p, sizeof(buf)+buf-p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) "MCS RX highest: %d Mbps\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) le16_to_cpu(vhtc->vht_mcs.rx_highest));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) p += scnprintf(p, sizeof(buf)+buf-p, "TX MCS: %.4x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) le16_to_cpu(vhtc->vht_mcs.tx_mcs_map));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (vhtc->vht_mcs.tx_highest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) p += scnprintf(p, sizeof(buf)+buf-p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) "MCS TX highest: %d Mbps\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) le16_to_cpu(vhtc->vht_mcs.tx_highest));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) #undef PFLAG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) STA_OPS(vht_capa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) static ssize_t sta_he_capa_read(struct file *file, char __user *userbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) char *buf, *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) size_t buf_sz = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) struct sta_info *sta = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) struct ieee80211_sta_he_cap *hec = &sta->sta.he_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) struct ieee80211_he_mcs_nss_supp *nss = &hec->he_mcs_nss_supp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) u8 ppe_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) u8 *cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) ssize_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) buf = kmalloc(buf_sz, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) p = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) p += scnprintf(p, buf_sz + buf - p, "HE %ssupported\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) hec->has_he ? "" : "not ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (!hec->has_he)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) cap = hec->he_cap_elem.mac_cap_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) p += scnprintf(p, buf_sz + buf - p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) "MAC-CAP: %#.2x %#.2x %#.2x %#.2x %#.2x %#.2x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) cap[0], cap[1], cap[2], cap[3], cap[4], cap[5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) #define PRINT(fmt, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) p += scnprintf(p, buf_sz + buf - p, "\t\t" fmt "\n", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) ##__VA_ARGS__)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) #define PFLAG(t, n, a, b) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) if (cap[n] & IEEE80211_HE_##t##_CAP##n##_##a) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) PRINT("%s", b); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) #define PFLAG_RANGE(t, i, n, s, m, off, fmt) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) u8 msk = IEEE80211_HE_##t##_CAP##i##_##n##_MASK; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) u8 idx = ((cap[i] & msk) >> (ffs(msk) - 1)) + off; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) PRINT(fmt, (s << idx) + (m * idx)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) #define PFLAG_RANGE_DEFAULT(t, i, n, s, m, off, fmt, a, b) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if (cap[i] == IEEE80211_HE_##t ##_CAP##i##_##n##_##a) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) PRINT("%s", b); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) break; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) PFLAG_RANGE(t, i, n, s, m, off, fmt); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) PFLAG(MAC, 0, HTC_HE, "HTC-HE");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) PFLAG(MAC, 0, TWT_REQ, "TWT-REQ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) PFLAG(MAC, 0, TWT_RES, "TWT-RES");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) PFLAG_RANGE_DEFAULT(MAC, 0, DYNAMIC_FRAG, 0, 1, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) "DYNAMIC-FRAG-LEVEL-%d", NOT_SUPP, "NOT-SUPP");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) PFLAG_RANGE_DEFAULT(MAC, 0, MAX_NUM_FRAG_MSDU, 1, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) "MAX-NUM-FRAG-MSDU-%d", UNLIMITED, "UNLIMITED");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) PFLAG_RANGE_DEFAULT(MAC, 1, MIN_FRAG_SIZE, 128, 0, -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) "MIN-FRAG-SIZE-%d", UNLIMITED, "UNLIMITED");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) PFLAG_RANGE_DEFAULT(MAC, 1, TF_MAC_PAD_DUR, 0, 8, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) "TF-MAC-PAD-DUR-%dUS", MASK, "UNKNOWN");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) PFLAG_RANGE(MAC, 1, MULTI_TID_AGG_RX_QOS, 0, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) "MULTI-TID-AGG-RX-QOS-%d");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (cap[0] & IEEE80211_HE_MAC_CAP0_HTC_HE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) switch (((cap[2] << 1) | (cap[1] >> 7)) & 0x3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) PRINT("LINK-ADAPTATION-NO-FEEDBACK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) PRINT("LINK-ADAPTATION-RESERVED");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) PRINT("LINK-ADAPTATION-UNSOLICITED-FEEDBACK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) PRINT("LINK-ADAPTATION-BOTH");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) PFLAG(MAC, 2, ALL_ACK, "ALL-ACK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) PFLAG(MAC, 2, TRS, "TRS");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) PFLAG(MAC, 2, BSR, "BSR");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) PFLAG(MAC, 2, BCAST_TWT, "BCAST-TWT");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) PFLAG(MAC, 2, 32BIT_BA_BITMAP, "32BIT-BA-BITMAP");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) PFLAG(MAC, 2, MU_CASCADING, "MU-CASCADING");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) PFLAG(MAC, 2, ACK_EN, "ACK-EN");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) PFLAG(MAC, 3, OMI_CONTROL, "OMI-CONTROL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) PFLAG(MAC, 3, OFDMA_RA, "OFDMA-RA");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) switch (cap[3] & IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) case IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_USE_VHT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) PRINT("MAX-AMPDU-LEN-EXP-USE-VHT");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) case IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_VHT_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) PRINT("MAX-AMPDU-LEN-EXP-VHT-1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) case IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_VHT_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) PRINT("MAX-AMPDU-LEN-EXP-VHT-2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) case IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_RESERVED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) PRINT("MAX-AMPDU-LEN-EXP-RESERVED");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) PFLAG(MAC, 3, AMSDU_FRAG, "AMSDU-FRAG");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) PFLAG(MAC, 3, FLEX_TWT_SCHED, "FLEX-TWT-SCHED");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) PFLAG(MAC, 3, RX_CTRL_FRAME_TO_MULTIBSS, "RX-CTRL-FRAME-TO-MULTIBSS");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) PFLAG(MAC, 4, BSRP_BQRP_A_MPDU_AGG, "BSRP-BQRP-A-MPDU-AGG");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) PFLAG(MAC, 4, QTP, "QTP");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) PFLAG(MAC, 4, BQR, "BQR");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) PFLAG(MAC, 4, SRP_RESP, "SRP-RESP");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) PFLAG(MAC, 4, NDP_FB_REP, "NDP-FB-REP");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) PFLAG(MAC, 4, OPS, "OPS");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) PFLAG(MAC, 4, AMDSU_IN_AMPDU, "AMSDU-IN-AMPDU");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) PRINT("MULTI-TID-AGG-TX-QOS-%d", ((cap[5] << 1) | (cap[4] >> 7)) & 0x7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) PFLAG(MAC, 5, SUBCHAN_SELECVITE_TRANSMISSION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) "SUBCHAN-SELECVITE-TRANSMISSION");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) PFLAG(MAC, 5, UL_2x996_TONE_RU, "UL-2x996-TONE-RU");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) PFLAG(MAC, 5, OM_CTRL_UL_MU_DATA_DIS_RX, "OM-CTRL-UL-MU-DATA-DIS-RX");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) PFLAG(MAC, 5, HE_DYNAMIC_SM_PS, "HE-DYNAMIC-SM-PS");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) PFLAG(MAC, 5, PUNCTURED_SOUNDING, "PUNCTURED-SOUNDING");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) PFLAG(MAC, 5, HT_VHT_TRIG_FRAME_RX, "HT-VHT-TRIG-FRAME-RX");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) cap = hec->he_cap_elem.phy_cap_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) p += scnprintf(p, buf_sz + buf - p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) "PHY CAP: %#.2x %#.2x %#.2x %#.2x %#.2x %#.2x %#.2x %#.2x %#.2x %#.2x %#.2x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) cap[0], cap[1], cap[2], cap[3], cap[4], cap[5], cap[6],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) cap[7], cap[8], cap[9], cap[10]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) PFLAG(PHY, 0, CHANNEL_WIDTH_SET_40MHZ_IN_2G,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) "CHANNEL-WIDTH-SET-40MHZ-IN-2G");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) PFLAG(PHY, 0, CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) "CHANNEL-WIDTH-SET-40MHZ-80MHZ-IN-5G");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) PFLAG(PHY, 0, CHANNEL_WIDTH_SET_160MHZ_IN_5G,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) "CHANNEL-WIDTH-SET-160MHZ-IN-5G");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) PFLAG(PHY, 0, CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) "CHANNEL-WIDTH-SET-80PLUS80-MHZ-IN-5G");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) PFLAG(PHY, 0, CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) "CHANNEL-WIDTH-SET-RU-MAPPING-IN-2G");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) PFLAG(PHY, 0, CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) "CHANNEL-WIDTH-SET-RU-MAPPING-IN-5G");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) switch (cap[1] & IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) case IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_80MHZ_ONLY_SECOND_20MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) PRINT("PREAMBLE-PUNC-RX-80MHZ-ONLY-SECOND-20MHZ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) case IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_80MHZ_ONLY_SECOND_40MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) PRINT("PREAMBLE-PUNC-RX-80MHZ-ONLY-SECOND-40MHZ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) case IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_160MHZ_ONLY_SECOND_20MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) PRINT("PREAMBLE-PUNC-RX-160MHZ-ONLY-SECOND-20MHZ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) case IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_160MHZ_ONLY_SECOND_40MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) PRINT("PREAMBLE-PUNC-RX-160MHZ-ONLY-SECOND-40MHZ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) PFLAG(PHY, 1, DEVICE_CLASS_A,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) "IEEE80211-HE-PHY-CAP1-DEVICE-CLASS-A");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) PFLAG(PHY, 1, LDPC_CODING_IN_PAYLOAD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) "LDPC-CODING-IN-PAYLOAD");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) PFLAG(PHY, 1, HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) "HY-CAP1-HE-LTF-AND-GI-FOR-HE-PPDUS-0-8US");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) PRINT("MIDAMBLE-RX-MAX-NSTS-%d", ((cap[2] << 1) | (cap[1] >> 7)) & 0x3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) PFLAG(PHY, 2, NDP_4x_LTF_AND_3_2US, "NDP-4X-LTF-AND-3-2US");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) PFLAG(PHY, 2, STBC_TX_UNDER_80MHZ, "STBC-TX-UNDER-80MHZ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) PFLAG(PHY, 2, STBC_RX_UNDER_80MHZ, "STBC-RX-UNDER-80MHZ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) PFLAG(PHY, 2, DOPPLER_TX, "DOPPLER-TX");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) PFLAG(PHY, 2, DOPPLER_RX, "DOPPLER-RX");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) PFLAG(PHY, 2, UL_MU_FULL_MU_MIMO, "UL-MU-FULL-MU-MIMO");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) PFLAG(PHY, 2, UL_MU_PARTIAL_MU_MIMO, "UL-MU-PARTIAL-MU-MIMO");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) switch (cap[3] & IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) case IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_NO_DCM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) PRINT("DCM-MAX-CONST-TX-NO-DCM");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) case IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_BPSK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) PRINT("DCM-MAX-CONST-TX-BPSK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) case IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) PRINT("DCM-MAX-CONST-TX-QPSK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) case IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_16_QAM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) PRINT("DCM-MAX-CONST-TX-16-QAM");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) PFLAG(PHY, 3, DCM_MAX_TX_NSS_1, "DCM-MAX-TX-NSS-1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) PFLAG(PHY, 3, DCM_MAX_TX_NSS_2, "DCM-MAX-TX-NSS-2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) switch (cap[3] & IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) case IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_NO_DCM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) PRINT("DCM-MAX-CONST-RX-NO-DCM");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) case IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_BPSK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) PRINT("DCM-MAX-CONST-RX-BPSK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) case IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) PRINT("DCM-MAX-CONST-RX-QPSK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) case IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) PRINT("DCM-MAX-CONST-RX-16-QAM");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) PFLAG(PHY, 3, DCM_MAX_RX_NSS_1, "DCM-MAX-RX-NSS-1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) PFLAG(PHY, 3, DCM_MAX_RX_NSS_2, "DCM-MAX-RX-NSS-2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) PFLAG(PHY, 3, RX_HE_MU_PPDU_FROM_NON_AP_STA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) "RX-HE-MU-PPDU-FROM-NON-AP-STA");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) PFLAG(PHY, 3, SU_BEAMFORMER, "SU-BEAMFORMER");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) PFLAG(PHY, 4, SU_BEAMFORMEE, "SU-BEAMFORMEE");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) PFLAG(PHY, 4, MU_BEAMFORMER, "MU-BEAMFORMER");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) PFLAG_RANGE(PHY, 4, BEAMFORMEE_MAX_STS_UNDER_80MHZ, 0, 1, 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) "BEAMFORMEE-MAX-STS-UNDER-%d");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) PFLAG_RANGE(PHY, 4, BEAMFORMEE_MAX_STS_ABOVE_80MHZ, 0, 1, 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) "BEAMFORMEE-MAX-STS-ABOVE-%d");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) PFLAG_RANGE(PHY, 5, BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ, 0, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) "NUM-SND-DIM-UNDER-80MHZ-%d");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) PFLAG_RANGE(PHY, 5, BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ, 0, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) "NUM-SND-DIM-ABOVE-80MHZ-%d");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) PFLAG(PHY, 5, NG16_SU_FEEDBACK, "NG16-SU-FEEDBACK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) PFLAG(PHY, 5, NG16_MU_FEEDBACK, "NG16-MU-FEEDBACK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) PFLAG(PHY, 6, CODEBOOK_SIZE_42_SU, "CODEBOOK-SIZE-42-SU");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) PFLAG(PHY, 6, CODEBOOK_SIZE_75_MU, "CODEBOOK-SIZE-75-MU");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) PFLAG(PHY, 6, TRIG_SU_BEAMFORMER_FB, "TRIG-SU-BEAMFORMER-FB");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) PFLAG(PHY, 6, TRIG_MU_BEAMFORMER_FB, "TRIG-MU-BEAMFORMER-FB");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) PFLAG(PHY, 6, TRIG_CQI_FB, "TRIG-CQI-FB");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) PFLAG(PHY, 6, PARTIAL_BW_EXT_RANGE, "PARTIAL-BW-EXT-RANGE");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) PFLAG(PHY, 6, PARTIAL_BANDWIDTH_DL_MUMIMO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) "PARTIAL-BANDWIDTH-DL-MUMIMO");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) PFLAG(PHY, 6, PPE_THRESHOLD_PRESENT, "PPE-THRESHOLD-PRESENT");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) PFLAG(PHY, 7, SRP_BASED_SR, "SRP-BASED-SR");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) PFLAG(PHY, 7, POWER_BOOST_FACTOR_AR, "POWER-BOOST-FACTOR-AR");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) PFLAG(PHY, 7, HE_SU_MU_PPDU_4XLTF_AND_08_US_GI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) "HE-SU-MU-PPDU-4XLTF-AND-08-US-GI");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) PFLAG_RANGE(PHY, 7, MAX_NC, 0, 1, 1, "MAX-NC-%d");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) PFLAG(PHY, 7, STBC_TX_ABOVE_80MHZ, "STBC-TX-ABOVE-80MHZ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) PFLAG(PHY, 7, STBC_RX_ABOVE_80MHZ, "STBC-RX-ABOVE-80MHZ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) PFLAG(PHY, 8, HE_ER_SU_PPDU_4XLTF_AND_08_US_GI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) "HE-ER-SU-PPDU-4XLTF-AND-08-US-GI");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) PFLAG(PHY, 8, 20MHZ_IN_40MHZ_HE_PPDU_IN_2G,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) "20MHZ-IN-40MHZ-HE-PPDU-IN-2G");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) PFLAG(PHY, 8, 20MHZ_IN_160MHZ_HE_PPDU, "20MHZ-IN-160MHZ-HE-PPDU");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) PFLAG(PHY, 8, 80MHZ_IN_160MHZ_HE_PPDU, "80MHZ-IN-160MHZ-HE-PPDU");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) PFLAG(PHY, 8, HE_ER_SU_1XLTF_AND_08_US_GI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) "HE-ER-SU-1XLTF-AND-08-US-GI");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) PFLAG(PHY, 8, MIDAMBLE_RX_TX_2X_AND_1XLTF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) "MIDAMBLE-RX-TX-2X-AND-1XLTF");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) switch (cap[8] & IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) case IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_242:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) PRINT("DCM-MAX-RU-242");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) case IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_484:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) PRINT("DCM-MAX-RU-484");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) case IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_996:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) PRINT("DCM-MAX-RU-996");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) case IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_2x996:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) PRINT("DCM-MAX-RU-2x996");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) PFLAG(PHY, 9, LONGER_THAN_16_SIGB_OFDM_SYM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) "LONGER-THAN-16-SIGB-OFDM-SYM");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) PFLAG(PHY, 9, NON_TRIGGERED_CQI_FEEDBACK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) "NON-TRIGGERED-CQI-FEEDBACK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) PFLAG(PHY, 9, TX_1024_QAM_LESS_THAN_242_TONE_RU,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) "TX-1024-QAM-LESS-THAN-242-TONE-RU");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) PFLAG(PHY, 9, RX_1024_QAM_LESS_THAN_242_TONE_RU,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) "RX-1024-QAM-LESS-THAN-242-TONE-RU");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) PFLAG(PHY, 9, RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) "RX-FULL-BW-SU-USING-MU-WITH-COMP-SIGB");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) PFLAG(PHY, 9, RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) "RX-FULL-BW-SU-USING-MU-WITH-NON-COMP-SIGB");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) switch (cap[9] & IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) case IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_0US:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) PRINT("NOMINAL-PACKET-PADDING-0US");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) case IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_8US:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) PRINT("NOMINAL-PACKET-PADDING-8US");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) case IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_16US:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) PRINT("NOMINAL-PACKET-PADDING-16US");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) #undef PFLAG_RANGE_DEFAULT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) #undef PFLAG_RANGE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) #undef PFLAG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) #define PRINT_NSS_SUPP(f, n) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) int _i; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) u16 v = le16_to_cpu(nss->f); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) p += scnprintf(p, buf_sz + buf - p, n ": %#.4x\n", v); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) for (_i = 0; _i < 8; _i += 2) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) switch ((v >> _i) & 0x3) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) case 0: \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) PRINT(n "-%d-SUPPORT-0-7", _i / 2); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) break; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) case 1: \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) PRINT(n "-%d-SUPPORT-0-9", _i / 2); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) break; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) case 2: \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) PRINT(n "-%d-SUPPORT-0-11", _i / 2); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) break; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) case 3: \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) PRINT(n "-%d-NOT-SUPPORTED", _i / 2); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) break; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) PRINT_NSS_SUPP(rx_mcs_80, "RX-MCS-80");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) PRINT_NSS_SUPP(tx_mcs_80, "TX-MCS-80");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) if (cap[0] & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) PRINT_NSS_SUPP(rx_mcs_160, "RX-MCS-160");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) PRINT_NSS_SUPP(tx_mcs_160, "TX-MCS-160");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) if (cap[0] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) PRINT_NSS_SUPP(rx_mcs_80p80, "RX-MCS-80P80");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) PRINT_NSS_SUPP(tx_mcs_80p80, "TX-MCS-80P80");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) #undef PRINT_NSS_SUPP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) #undef PRINT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) if (!(cap[6] & IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) p += scnprintf(p, buf_sz + buf - p, "PPE-THRESHOLDS: %#.2x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) hec->ppe_thres[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) ppe_size = ieee80211_he_ppe_size(hec->ppe_thres[0], cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) for (i = 1; i < ppe_size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) p += scnprintf(p, buf_sz + buf - p, " %#.2x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) hec->ppe_thres[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) p += scnprintf(p, buf_sz + buf - p, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) ret = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) STA_OPS(he_capa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) #define DEBUGFS_ADD(name) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) debugfs_create_file(#name, 0400, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) sta->debugfs_dir, sta, &sta_ ##name## _ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) #define DEBUGFS_ADD_COUNTER(name, field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) debugfs_create_ulong(#name, 0400, sta->debugfs_dir, &sta->field);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) void ieee80211_sta_debugfs_add(struct sta_info *sta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) struct ieee80211_local *local = sta->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) struct ieee80211_sub_if_data *sdata = sta->sdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) struct dentry *stations_dir = sta->sdata->debugfs.subdir_stations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) u8 mac[3*ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) if (!stations_dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) snprintf(mac, sizeof(mac), "%pM", sta->sta.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) * This might fail due to a race condition:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) * When mac80211 unlinks a station, the debugfs entries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) * remain, but it is already possible to link a new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) * station with the same address which triggers adding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) * it to debugfs; therefore, if the old station isn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) * destroyed quickly enough the old station's debugfs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) * dir might still be around.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) sta->debugfs_dir = debugfs_create_dir(mac, stations_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) DEBUGFS_ADD(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) DEBUGFS_ADD(aid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) DEBUGFS_ADD(num_ps_buf_frames);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) DEBUGFS_ADD(last_seq_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) DEBUGFS_ADD(agg_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) DEBUGFS_ADD(ht_capa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) DEBUGFS_ADD(vht_capa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) DEBUGFS_ADD(he_capa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) DEBUGFS_ADD_COUNTER(rx_duplicates, rx_stats.num_duplicates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) DEBUGFS_ADD_COUNTER(rx_fragments, rx_stats.fragments);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) DEBUGFS_ADD_COUNTER(tx_filtered, status_stats.filtered);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) if (local->ops->wake_tx_queue) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) DEBUGFS_ADD(aqm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) DEBUGFS_ADD(airtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (wiphy_ext_feature_isset(local->hw.wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) NL80211_EXT_FEATURE_AQL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) DEBUGFS_ADD(aql);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) debugfs_create_xul("driver_buffered_tids", 0400, sta->debugfs_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) &sta->driver_buffered_tids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) drv_sta_add_debugfs(local, sdata, &sta->sta, sta->debugfs_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) void ieee80211_sta_debugfs_remove(struct sta_info *sta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) debugfs_remove_recursive(sta->debugfs_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) sta->debugfs_dir = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }