17f904d7eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2e9f207f0SJiri Benc /*
3e9f207f0SJiri Benc * mac80211 debugfs for wireless PHYs
4e9f207f0SJiri Benc *
5e9f207f0SJiri Benc * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
6d98ad83eSJohannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH
76f0107d1SJohannes Berg * Copyright (C) 2018 - 2019, 2021-2024 Intel Corporation
8e9f207f0SJiri Benc */
9e9f207f0SJiri Benc
10e9f207f0SJiri Benc #include <linux/debugfs.h>
11e9f207f0SJiri Benc #include <linux/rtnetlink.h>
129399b86cSMichal Kazior #include <linux/vmalloc.h>
13e9f207f0SJiri Benc #include "ieee80211_i.h"
1424487981SJohannes Berg #include "driver-ops.h"
152c8dccc7SJohannes Berg #include "rate.h"
16e9f207f0SJiri Benc #include "debugfs.h"
17e9f207f0SJiri Benc
1807caf9d6SEliad Peller #define DEBUGFS_FORMAT_BUFFER_SIZE 100
1907caf9d6SEliad Peller
mac80211_format_buffer(char __user * userbuf,size_t count,loff_t * ppos,char * fmt,...)2007caf9d6SEliad Peller int mac80211_format_buffer(char __user *userbuf, size_t count,
2107caf9d6SEliad Peller loff_t *ppos, char *fmt, ...)
2207caf9d6SEliad Peller {
2307caf9d6SEliad Peller va_list args;
2407caf9d6SEliad Peller char buf[DEBUGFS_FORMAT_BUFFER_SIZE];
2507caf9d6SEliad Peller int res;
2607caf9d6SEliad Peller
2707caf9d6SEliad Peller va_start(args, fmt);
2807caf9d6SEliad Peller res = vscnprintf(buf, sizeof(buf), fmt, args);
2907caf9d6SEliad Peller va_end(args);
3007caf9d6SEliad Peller
3107caf9d6SEliad Peller return simple_read_from_buffer(userbuf, count, ppos, buf, res);
3207caf9d6SEliad Peller }
3307caf9d6SEliad Peller
34279daf64SBen Greear #define DEBUGFS_READONLY_FILE_FN(name, fmt, value...) \
35e9f207f0SJiri Benc static ssize_t name## _read(struct file *file, char __user *userbuf, \
36e9f207f0SJiri Benc size_t count, loff_t *ppos) \
37e9f207f0SJiri Benc { \
38e9f207f0SJiri Benc struct ieee80211_local *local = file->private_data; \
39e9f207f0SJiri Benc \
4007caf9d6SEliad Peller return mac80211_format_buffer(userbuf, count, ppos, \
4107caf9d6SEliad Peller fmt "\n", ##value); \
42279daf64SBen Greear }
43279daf64SBen Greear
44279daf64SBen Greear #define DEBUGFS_READONLY_FILE_OPS(name) \
45e9f207f0SJiri Benc static const struct file_operations name## _ops = { \
46e9f207f0SJiri Benc .read = name## _read, \
47234e3405SStephen Boyd .open = simple_open, \
482b18ab36SArnd Bergmann .llseek = generic_file_llseek, \
49e9f207f0SJiri Benc };
50e9f207f0SJiri Benc
51279daf64SBen Greear #define DEBUGFS_READONLY_FILE(name, fmt, value...) \
52279daf64SBen Greear DEBUGFS_READONLY_FILE_FN(name, fmt, value) \
53279daf64SBen Greear DEBUGFS_READONLY_FILE_OPS(name)
54279daf64SBen Greear
55e9f207f0SJiri Benc #define DEBUGFS_ADD(name) \
5684674ef4STom Rix debugfs_create_file(#name, 0400, phyd, local, &name## _ops)
57e9f207f0SJiri Benc
58827b1fb4SJohannes Berg #define DEBUGFS_ADD_MODE(name, mode) \
597bcfaf2fSJohannes Berg debugfs_create_file(#name, mode, phyd, local, &name## _ops);
60e9f207f0SJiri Benc
61e9f207f0SJiri Benc
62c90142a5SThomas Pedersen DEBUGFS_READONLY_FILE(hw_conf, "%x",
63c90142a5SThomas Pedersen local->hw.conf.flags);
6483bdf2a1SBen Greear DEBUGFS_READONLY_FILE(user_power, "%d",
6583bdf2a1SBen Greear local->user_power_level);
6683bdf2a1SBen Greear DEBUGFS_READONLY_FILE(power, "%d",
6783bdf2a1SBen Greear local->hw.conf.power_level);
6807caf9d6SEliad Peller DEBUGFS_READONLY_FILE(total_ps_buffered, "%d",
69e9f207f0SJiri Benc local->total_ps_buffered);
7007caf9d6SEliad Peller DEBUGFS_READONLY_FILE(wep_iv, "%#08x",
71e9f207f0SJiri Benc local->wep_iv & 0xffffff);
7207caf9d6SEliad Peller DEBUGFS_READONLY_FILE(rate_ctrl_alg, "%s",
73af65cd96SJohannes Berg local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver");
743b5d665bSAlina Friedrichsen
aqm_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)758d51dbb8SToke Høiland-Jørgensen static ssize_t aqm_read(struct file *file,
768d51dbb8SToke Høiland-Jørgensen char __user *user_buf,
778d51dbb8SToke Høiland-Jørgensen size_t count,
788d51dbb8SToke Høiland-Jørgensen loff_t *ppos)
799399b86cSMichal Kazior {
808d51dbb8SToke Høiland-Jørgensen struct ieee80211_local *local = file->private_data;
819399b86cSMichal Kazior struct fq *fq = &local->fq;
828d51dbb8SToke Høiland-Jørgensen char buf[200];
839399b86cSMichal Kazior int len = 0;
849399b86cSMichal Kazior
859399b86cSMichal Kazior spin_lock_bh(&local->fq.lock);
869399b86cSMichal Kazior rcu_read_lock();
879399b86cSMichal Kazior
888d51dbb8SToke Høiland-Jørgensen len = scnprintf(buf, sizeof(buf),
899399b86cSMichal Kazior "access name value\n"
909399b86cSMichal Kazior "R fq_flows_cnt %u\n"
919399b86cSMichal Kazior "R fq_backlog %u\n"
929399b86cSMichal Kazior "R fq_overlimit %u\n"
932a4e675dSToke Høiland-Jørgensen "R fq_overmemory %u\n"
949399b86cSMichal Kazior "R fq_collisions %u\n"
952a4e675dSToke Høiland-Jørgensen "R fq_memory_usage %u\n"
962a4e675dSToke Høiland-Jørgensen "RW fq_memory_limit %u\n"
979399b86cSMichal Kazior "RW fq_limit %u\n"
989399b86cSMichal Kazior "RW fq_quantum %u\n",
999399b86cSMichal Kazior fq->flows_cnt,
1009399b86cSMichal Kazior fq->backlog,
1012a4e675dSToke Høiland-Jørgensen fq->overmemory,
1029399b86cSMichal Kazior fq->overlimit,
1039399b86cSMichal Kazior fq->collisions,
1042a4e675dSToke Høiland-Jørgensen fq->memory_usage,
1052a4e675dSToke Høiland-Jørgensen fq->memory_limit,
1069399b86cSMichal Kazior fq->limit,
1079399b86cSMichal Kazior fq->quantum);
1089399b86cSMichal Kazior
1099399b86cSMichal Kazior rcu_read_unlock();
1109399b86cSMichal Kazior spin_unlock_bh(&local->fq.lock);
1119399b86cSMichal Kazior
1129399b86cSMichal Kazior return simple_read_from_buffer(user_buf, count, ppos,
1138d51dbb8SToke Høiland-Jørgensen buf, len);
1149399b86cSMichal Kazior }
1159399b86cSMichal Kazior
aqm_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)1169399b86cSMichal Kazior static ssize_t aqm_write(struct file *file,
1179399b86cSMichal Kazior const char __user *user_buf,
1189399b86cSMichal Kazior size_t count,
1199399b86cSMichal Kazior loff_t *ppos)
1209399b86cSMichal Kazior {
1218d51dbb8SToke Høiland-Jørgensen struct ieee80211_local *local = file->private_data;
1229399b86cSMichal Kazior char buf[100];
1239399b86cSMichal Kazior
1246020d534SShayne Chen if (count >= sizeof(buf))
1259399b86cSMichal Kazior return -EINVAL;
1269399b86cSMichal Kazior
1279399b86cSMichal Kazior if (copy_from_user(buf, user_buf, count))
1289399b86cSMichal Kazior return -EFAULT;
1299399b86cSMichal Kazior
1306020d534SShayne Chen if (count && buf[count - 1] == '\n')
1316020d534SShayne Chen buf[count - 1] = '\0';
1326020d534SShayne Chen else
1336020d534SShayne Chen buf[count] = '\0';
1349399b86cSMichal Kazior
1359399b86cSMichal Kazior if (sscanf(buf, "fq_limit %u", &local->fq.limit) == 1)
1369399b86cSMichal Kazior return count;
1372a4e675dSToke Høiland-Jørgensen else if (sscanf(buf, "fq_memory_limit %u", &local->fq.memory_limit) == 1)
1382a4e675dSToke Høiland-Jørgensen return count;
1399399b86cSMichal Kazior else if (sscanf(buf, "fq_quantum %u", &local->fq.quantum) == 1)
1409399b86cSMichal Kazior return count;
1419399b86cSMichal Kazior
1429399b86cSMichal Kazior return -EINVAL;
1439399b86cSMichal Kazior }
1449399b86cSMichal Kazior
1459399b86cSMichal Kazior static const struct file_operations aqm_ops = {
1469399b86cSMichal Kazior .write = aqm_write,
1479399b86cSMichal Kazior .read = aqm_read,
1488d51dbb8SToke Høiland-Jørgensen .open = simple_open,
1499399b86cSMichal Kazior .llseek = default_llseek,
1509399b86cSMichal Kazior };
1519399b86cSMichal Kazior
airtime_flags_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)152e322c07fSLorenzo Bianconi static ssize_t airtime_flags_read(struct file *file,
153e322c07fSLorenzo Bianconi char __user *user_buf,
154e322c07fSLorenzo Bianconi size_t count, loff_t *ppos)
155e322c07fSLorenzo Bianconi {
156e322c07fSLorenzo Bianconi struct ieee80211_local *local = file->private_data;
157e322c07fSLorenzo Bianconi char buf[128] = {}, *pos, *end;
158e322c07fSLorenzo Bianconi
159e322c07fSLorenzo Bianconi pos = buf;
160e322c07fSLorenzo Bianconi end = pos + sizeof(buf) - 1;
161e322c07fSLorenzo Bianconi
162e322c07fSLorenzo Bianconi if (local->airtime_flags & AIRTIME_USE_TX)
163e322c07fSLorenzo Bianconi pos += scnprintf(pos, end - pos, "AIRTIME_TX\t(%lx)\n",
164e322c07fSLorenzo Bianconi AIRTIME_USE_TX);
165e322c07fSLorenzo Bianconi if (local->airtime_flags & AIRTIME_USE_RX)
166e322c07fSLorenzo Bianconi pos += scnprintf(pos, end - pos, "AIRTIME_RX\t(%lx)\n",
167e322c07fSLorenzo Bianconi AIRTIME_USE_RX);
168e322c07fSLorenzo Bianconi
169e322c07fSLorenzo Bianconi return simple_read_from_buffer(user_buf, count, ppos, buf,
170e322c07fSLorenzo Bianconi strlen(buf));
171e322c07fSLorenzo Bianconi }
172e322c07fSLorenzo Bianconi
airtime_flags_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)173e322c07fSLorenzo Bianconi static ssize_t airtime_flags_write(struct file *file,
174e322c07fSLorenzo Bianconi const char __user *user_buf,
175e322c07fSLorenzo Bianconi size_t count, loff_t *ppos)
176e322c07fSLorenzo Bianconi {
177e322c07fSLorenzo Bianconi struct ieee80211_local *local = file->private_data;
178e322c07fSLorenzo Bianconi char buf[16];
179e322c07fSLorenzo Bianconi
1806020d534SShayne Chen if (count >= sizeof(buf))
181e322c07fSLorenzo Bianconi return -EINVAL;
182e322c07fSLorenzo Bianconi
183e322c07fSLorenzo Bianconi if (copy_from_user(buf, user_buf, count))
184e322c07fSLorenzo Bianconi return -EFAULT;
185e322c07fSLorenzo Bianconi
1866020d534SShayne Chen if (count && buf[count - 1] == '\n')
1876020d534SShayne Chen buf[count - 1] = '\0';
1886020d534SShayne Chen else
1896020d534SShayne Chen buf[count] = '\0';
190e322c07fSLorenzo Bianconi
191e322c07fSLorenzo Bianconi if (kstrtou16(buf, 0, &local->airtime_flags))
192e322c07fSLorenzo Bianconi return -EINVAL;
193e322c07fSLorenzo Bianconi
194e322c07fSLorenzo Bianconi return count;
195e322c07fSLorenzo Bianconi }
196e322c07fSLorenzo Bianconi
197e322c07fSLorenzo Bianconi static const struct file_operations airtime_flags_ops = {
198e322c07fSLorenzo Bianconi .write = airtime_flags_write,
199e322c07fSLorenzo Bianconi .read = airtime_flags_read,
200e322c07fSLorenzo Bianconi .open = simple_open,
201e322c07fSLorenzo Bianconi .llseek = default_llseek,
202e322c07fSLorenzo Bianconi };
203e322c07fSLorenzo Bianconi
aql_pending_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)2043db2c560SFelix Fietkau static ssize_t aql_pending_read(struct file *file,
2053db2c560SFelix Fietkau char __user *user_buf,
2063db2c560SFelix Fietkau size_t count, loff_t *ppos)
2073db2c560SFelix Fietkau {
2083db2c560SFelix Fietkau struct ieee80211_local *local = file->private_data;
2093db2c560SFelix Fietkau char buf[400];
2103db2c560SFelix Fietkau int len = 0;
2113db2c560SFelix Fietkau
2123db2c560SFelix Fietkau len = scnprintf(buf, sizeof(buf),
2133db2c560SFelix Fietkau "AC AQL pending\n"
2143db2c560SFelix Fietkau "VO %u us\n"
2153db2c560SFelix Fietkau "VI %u us\n"
2163db2c560SFelix Fietkau "BE %u us\n"
2173db2c560SFelix Fietkau "BK %u us\n"
2183db2c560SFelix Fietkau "total %u us\n",
2193db2c560SFelix Fietkau atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_VO]),
2203db2c560SFelix Fietkau atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_VI]),
2213db2c560SFelix Fietkau atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_BE]),
2223db2c560SFelix Fietkau atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_BK]),
2233db2c560SFelix Fietkau atomic_read(&local->aql_total_pending_airtime));
2243db2c560SFelix Fietkau return simple_read_from_buffer(user_buf, count, ppos,
2253db2c560SFelix Fietkau buf, len);
2263db2c560SFelix Fietkau }
2273db2c560SFelix Fietkau
2283db2c560SFelix Fietkau static const struct file_operations aql_pending_ops = {
2293db2c560SFelix Fietkau .read = aql_pending_read,
2303db2c560SFelix Fietkau .open = simple_open,
2313db2c560SFelix Fietkau .llseek = default_llseek,
2323db2c560SFelix Fietkau };
2333db2c560SFelix Fietkau
aql_txq_limit_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)2343ace10f5SKan Yan static ssize_t aql_txq_limit_read(struct file *file,
2353ace10f5SKan Yan char __user *user_buf,
2363ace10f5SKan Yan size_t count,
2373ace10f5SKan Yan loff_t *ppos)
2383ace10f5SKan Yan {
2393ace10f5SKan Yan struct ieee80211_local *local = file->private_data;
2403ace10f5SKan Yan char buf[400];
2413ace10f5SKan Yan int len = 0;
2423ace10f5SKan Yan
2433ace10f5SKan Yan len = scnprintf(buf, sizeof(buf),
2443ace10f5SKan Yan "AC AQL limit low AQL limit high\n"
2453ace10f5SKan Yan "VO %u %u\n"
2463ace10f5SKan Yan "VI %u %u\n"
2473ace10f5SKan Yan "BE %u %u\n"
2483ace10f5SKan Yan "BK %u %u\n",
249942741daSFelix Fietkau local->aql_txq_limit_low[IEEE80211_AC_VO],
250942741daSFelix Fietkau local->aql_txq_limit_high[IEEE80211_AC_VO],
251942741daSFelix Fietkau local->aql_txq_limit_low[IEEE80211_AC_VI],
252942741daSFelix Fietkau local->aql_txq_limit_high[IEEE80211_AC_VI],
253942741daSFelix Fietkau local->aql_txq_limit_low[IEEE80211_AC_BE],
254942741daSFelix Fietkau local->aql_txq_limit_high[IEEE80211_AC_BE],
255942741daSFelix Fietkau local->aql_txq_limit_low[IEEE80211_AC_BK],
256942741daSFelix Fietkau local->aql_txq_limit_high[IEEE80211_AC_BK]);
2573ace10f5SKan Yan return simple_read_from_buffer(user_buf, count, ppos,
2583ace10f5SKan Yan buf, len);
2593ace10f5SKan Yan }
2603ace10f5SKan Yan
aql_txq_limit_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)2613ace10f5SKan Yan static ssize_t aql_txq_limit_write(struct file *file,
2623ace10f5SKan Yan const char __user *user_buf,
2633ace10f5SKan Yan size_t count,
2643ace10f5SKan Yan loff_t *ppos)
2653ace10f5SKan Yan {
2663ace10f5SKan Yan struct ieee80211_local *local = file->private_data;
2673ace10f5SKan Yan char buf[100];
2683ace10f5SKan Yan u32 ac, q_limit_low, q_limit_high, q_limit_low_old, q_limit_high_old;
2693ace10f5SKan Yan struct sta_info *sta;
2703ace10f5SKan Yan
2716020d534SShayne Chen if (count >= sizeof(buf))
2723ace10f5SKan Yan return -EINVAL;
2733ace10f5SKan Yan
2743ace10f5SKan Yan if (copy_from_user(buf, user_buf, count))
2753ace10f5SKan Yan return -EFAULT;
2763ace10f5SKan Yan
2776020d534SShayne Chen if (count && buf[count - 1] == '\n')
2786020d534SShayne Chen buf[count - 1] = '\0';
2796020d534SShayne Chen else
2806020d534SShayne Chen buf[count] = '\0';
2813ace10f5SKan Yan
2823ace10f5SKan Yan if (sscanf(buf, "%u %u %u", &ac, &q_limit_low, &q_limit_high) != 3)
2833ace10f5SKan Yan return -EINVAL;
2843ace10f5SKan Yan
2853ace10f5SKan Yan if (ac >= IEEE80211_NUM_ACS)
2863ace10f5SKan Yan return -EINVAL;
2873ace10f5SKan Yan
288942741daSFelix Fietkau q_limit_low_old = local->aql_txq_limit_low[ac];
289942741daSFelix Fietkau q_limit_high_old = local->aql_txq_limit_high[ac];
2903ace10f5SKan Yan
2914d3acf43SJohannes Berg wiphy_lock(local->hw.wiphy);
292942741daSFelix Fietkau local->aql_txq_limit_low[ac] = q_limit_low;
293942741daSFelix Fietkau local->aql_txq_limit_high[ac] = q_limit_high;
2943ace10f5SKan Yan
2953ace10f5SKan Yan list_for_each_entry(sta, &local->sta_list, list) {
2963ace10f5SKan Yan /* If a sta has customized queue limits, keep it */
2973ace10f5SKan Yan if (sta->airtime[ac].aql_limit_low == q_limit_low_old &&
2983ace10f5SKan Yan sta->airtime[ac].aql_limit_high == q_limit_high_old) {
2993ace10f5SKan Yan sta->airtime[ac].aql_limit_low = q_limit_low;
3003ace10f5SKan Yan sta->airtime[ac].aql_limit_high = q_limit_high;
3013ace10f5SKan Yan }
3023ace10f5SKan Yan }
3034d3acf43SJohannes Berg wiphy_unlock(local->hw.wiphy);
3044d3acf43SJohannes Berg
3053ace10f5SKan Yan return count;
3063ace10f5SKan Yan }
3073ace10f5SKan Yan
3083ace10f5SKan Yan static const struct file_operations aql_txq_limit_ops = {
3093ace10f5SKan Yan .write = aql_txq_limit_write,
3103ace10f5SKan Yan .read = aql_txq_limit_read,
3113ace10f5SKan Yan .open = simple_open,
3123ace10f5SKan Yan .llseek = default_llseek,
3133ace10f5SKan Yan };
3143ace10f5SKan Yan
aql_enable_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)315e908435eSLorenzo Bianconi static ssize_t aql_enable_read(struct file *file, char __user *user_buf,
316e908435eSLorenzo Bianconi size_t count, loff_t *ppos)
317e908435eSLorenzo Bianconi {
318e908435eSLorenzo Bianconi char buf[3];
319e908435eSLorenzo Bianconi int len;
320e908435eSLorenzo Bianconi
321e908435eSLorenzo Bianconi len = scnprintf(buf, sizeof(buf), "%d\n",
322e908435eSLorenzo Bianconi !static_key_false(&aql_disable.key));
323e908435eSLorenzo Bianconi
324e908435eSLorenzo Bianconi return simple_read_from_buffer(user_buf, count, ppos, buf, len);
325e908435eSLorenzo Bianconi }
326e908435eSLorenzo Bianconi
aql_enable_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)327e908435eSLorenzo Bianconi static ssize_t aql_enable_write(struct file *file, const char __user *user_buf,
328e908435eSLorenzo Bianconi size_t count, loff_t *ppos)
329e908435eSLorenzo Bianconi {
330e908435eSLorenzo Bianconi bool aql_disabled = static_key_false(&aql_disable.key);
331e908435eSLorenzo Bianconi char buf[3];
332e908435eSLorenzo Bianconi size_t len;
333e908435eSLorenzo Bianconi
334e908435eSLorenzo Bianconi if (count > sizeof(buf))
335e908435eSLorenzo Bianconi return -EINVAL;
336e908435eSLorenzo Bianconi
337e908435eSLorenzo Bianconi if (copy_from_user(buf, user_buf, count))
338e908435eSLorenzo Bianconi return -EFAULT;
339e908435eSLorenzo Bianconi
340e908435eSLorenzo Bianconi buf[sizeof(buf) - 1] = '\0';
341e908435eSLorenzo Bianconi len = strlen(buf);
342e908435eSLorenzo Bianconi if (len > 0 && buf[len - 1] == '\n')
343e908435eSLorenzo Bianconi buf[len - 1] = 0;
344e908435eSLorenzo Bianconi
345e908435eSLorenzo Bianconi if (buf[0] == '0' && buf[1] == '\0') {
346e908435eSLorenzo Bianconi if (!aql_disabled)
347e908435eSLorenzo Bianconi static_branch_inc(&aql_disable);
348e908435eSLorenzo Bianconi } else if (buf[0] == '1' && buf[1] == '\0') {
349e908435eSLorenzo Bianconi if (aql_disabled)
350e908435eSLorenzo Bianconi static_branch_dec(&aql_disable);
351e908435eSLorenzo Bianconi } else {
352e908435eSLorenzo Bianconi return -EINVAL;
353e908435eSLorenzo Bianconi }
354e908435eSLorenzo Bianconi
355e908435eSLorenzo Bianconi return count;
356e908435eSLorenzo Bianconi }
357e908435eSLorenzo Bianconi
358e908435eSLorenzo Bianconi static const struct file_operations aql_enable_ops = {
359e908435eSLorenzo Bianconi .write = aql_enable_write,
360e908435eSLorenzo Bianconi .read = aql_enable_read,
361e908435eSLorenzo Bianconi .open = simple_open,
362e908435eSLorenzo Bianconi .llseek = default_llseek,
363e908435eSLorenzo Bianconi };
364e908435eSLorenzo Bianconi
force_tx_status_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)365276d9e82SJulius Niedworok static ssize_t force_tx_status_read(struct file *file,
366276d9e82SJulius Niedworok char __user *user_buf,
367276d9e82SJulius Niedworok size_t count,
368276d9e82SJulius Niedworok loff_t *ppos)
369276d9e82SJulius Niedworok {
370276d9e82SJulius Niedworok struct ieee80211_local *local = file->private_data;
371276d9e82SJulius Niedworok char buf[3];
372276d9e82SJulius Niedworok int len = 0;
373276d9e82SJulius Niedworok
374276d9e82SJulius Niedworok len = scnprintf(buf, sizeof(buf), "%d\n", (int)local->force_tx_status);
375276d9e82SJulius Niedworok
376276d9e82SJulius Niedworok return simple_read_from_buffer(user_buf, count, ppos,
377276d9e82SJulius Niedworok buf, len);
378276d9e82SJulius Niedworok }
379276d9e82SJulius Niedworok
force_tx_status_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)380276d9e82SJulius Niedworok static ssize_t force_tx_status_write(struct file *file,
381276d9e82SJulius Niedworok const char __user *user_buf,
382276d9e82SJulius Niedworok size_t count,
383276d9e82SJulius Niedworok loff_t *ppos)
384276d9e82SJulius Niedworok {
385276d9e82SJulius Niedworok struct ieee80211_local *local = file->private_data;
386276d9e82SJulius Niedworok char buf[3];
387276d9e82SJulius Niedworok
3886020d534SShayne Chen if (count >= sizeof(buf))
389276d9e82SJulius Niedworok return -EINVAL;
390276d9e82SJulius Niedworok
391276d9e82SJulius Niedworok if (copy_from_user(buf, user_buf, count))
392276d9e82SJulius Niedworok return -EFAULT;
393276d9e82SJulius Niedworok
3946020d534SShayne Chen if (count && buf[count - 1] == '\n')
3956020d534SShayne Chen buf[count - 1] = '\0';
3966020d534SShayne Chen else
3976020d534SShayne Chen buf[count] = '\0';
398276d9e82SJulius Niedworok
399276d9e82SJulius Niedworok if (buf[0] == '0' && buf[1] == '\0')
400276d9e82SJulius Niedworok local->force_tx_status = 0;
401276d9e82SJulius Niedworok else if (buf[0] == '1' && buf[1] == '\0')
402276d9e82SJulius Niedworok local->force_tx_status = 1;
403276d9e82SJulius Niedworok else
404276d9e82SJulius Niedworok return -EINVAL;
405276d9e82SJulius Niedworok
406276d9e82SJulius Niedworok return count;
407276d9e82SJulius Niedworok }
408276d9e82SJulius Niedworok
409276d9e82SJulius Niedworok static const struct file_operations force_tx_status_ops = {
410276d9e82SJulius Niedworok .write = force_tx_status_write,
411276d9e82SJulius Niedworok .read = force_tx_status_read,
412276d9e82SJulius Niedworok .open = simple_open,
413276d9e82SJulius Niedworok .llseek = default_llseek,
414276d9e82SJulius Niedworok };
415276d9e82SJulius Niedworok
4162ad4814fSJohannes Berg #ifdef CONFIG_PM
reset_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)417827b1fb4SJohannes Berg static ssize_t reset_write(struct file *file, const char __user *user_buf,
418827b1fb4SJohannes Berg size_t count, loff_t *ppos)
419827b1fb4SJohannes Berg {
420827b1fb4SJohannes Berg struct ieee80211_local *local = file->private_data;
421f5baf287SJohannes Berg int ret;
422827b1fb4SJohannes Berg
423827b1fb4SJohannes Berg rtnl_lock();
424adaed1b9SJohannes Berg wiphy_lock(local->hw.wiphy);
425eecc4800SJohannes Berg __ieee80211_suspend(&local->hw, NULL);
426f5baf287SJohannes Berg ret = __ieee80211_resume(&local->hw);
427adaed1b9SJohannes Berg wiphy_unlock(local->hw.wiphy);
428f5baf287SJohannes Berg
429f5baf287SJohannes Berg if (ret)
430f5baf287SJohannes Berg cfg80211_shutdown_all_interfaces(local->hw.wiphy);
431f5baf287SJohannes Berg
432827b1fb4SJohannes Berg rtnl_unlock();
433827b1fb4SJohannes Berg
434827b1fb4SJohannes Berg return count;
435827b1fb4SJohannes Berg }
436827b1fb4SJohannes Berg
437827b1fb4SJohannes Berg static const struct file_operations reset_ops = {
438827b1fb4SJohannes Berg .write = reset_write,
439234e3405SStephen Boyd .open = simple_open,
4406038f373SArnd Bergmann .llseek = noop_llseek,
441827b1fb4SJohannes Berg };
4422ad4814fSJohannes Berg #endif
443827b1fb4SJohannes Berg
44468920c97SAndrey Ryabinin static const char *hw_flag_names[] = {
44530686bf7SJohannes Berg #define FLAG(F) [IEEE80211_HW_##F] = #F
44630686bf7SJohannes Berg FLAG(HAS_RATE_CONTROL),
44730686bf7SJohannes Berg FLAG(RX_INCLUDES_FCS),
44830686bf7SJohannes Berg FLAG(HOST_BROADCAST_PS_BUFFERING),
44930686bf7SJohannes Berg FLAG(SIGNAL_UNSPEC),
45030686bf7SJohannes Berg FLAG(SIGNAL_DBM),
45130686bf7SJohannes Berg FLAG(NEED_DTIM_BEFORE_ASSOC),
45230686bf7SJohannes Berg FLAG(SPECTRUM_MGMT),
45330686bf7SJohannes Berg FLAG(AMPDU_AGGREGATION),
45430686bf7SJohannes Berg FLAG(SUPPORTS_PS),
45530686bf7SJohannes Berg FLAG(PS_NULLFUNC_STACK),
45630686bf7SJohannes Berg FLAG(SUPPORTS_DYNAMIC_PS),
45730686bf7SJohannes Berg FLAG(MFP_CAPABLE),
45830686bf7SJohannes Berg FLAG(WANT_MONITOR_VIF),
45930686bf7SJohannes Berg FLAG(NO_AUTO_VIF),
46030686bf7SJohannes Berg FLAG(SW_CRYPTO_CONTROL),
46130686bf7SJohannes Berg FLAG(SUPPORT_FAST_XMIT),
46230686bf7SJohannes Berg FLAG(REPORTS_TX_ACK_STATUS),
46330686bf7SJohannes Berg FLAG(CONNECTION_MONITOR),
46430686bf7SJohannes Berg FLAG(QUEUE_CONTROL),
46530686bf7SJohannes Berg FLAG(SUPPORTS_PER_STA_GTK),
46630686bf7SJohannes Berg FLAG(AP_LINK_PS),
46730686bf7SJohannes Berg FLAG(TX_AMPDU_SETUP_IN_HW),
46830686bf7SJohannes Berg FLAG(SUPPORTS_RC_TABLE),
46930686bf7SJohannes Berg FLAG(P2P_DEV_ADDR_FOR_INTF),
47030686bf7SJohannes Berg FLAG(TIMING_BEACON_ONLY),
47130686bf7SJohannes Berg FLAG(SUPPORTS_HT_CCK_RATES),
47230686bf7SJohannes Berg FLAG(CHANCTX_STA_CSA),
47330686bf7SJohannes Berg FLAG(SUPPORTS_CLONED_SKBS),
47430686bf7SJohannes Berg FLAG(SINGLE_SCAN_ON_ALL_BANDS),
475b98fb44fSArik Nemtsov FLAG(TDLS_WIDER_BW),
47699e7ca44SEmmanuel Grumbach FLAG(SUPPORTS_AMSDU_IN_AMPDU),
47735afa588SHelmut Schaa FLAG(BEACON_TX_STATUS),
47831104891SJohannes Berg FLAG(NEEDS_UNIQUE_STA_ADDR),
479412a6d80SSara Sharon FLAG(SUPPORTS_REORDERING_BUFFER),
480c9c5962bSJohannes Berg FLAG(USES_RSS),
4816e0456b5SFelix Fietkau FLAG(TX_AMSDU),
4826e0456b5SFelix Fietkau FLAG(TX_FRAG_LIST),
483e8a24cd4SRajkumar Manoharan FLAG(REPORTS_LOW_ACK),
484f3fe4e93SSara Sharon FLAG(SUPPORTS_TX_FRAG),
485e2fb1b83SYingying Tang FLAG(SUPPORTS_TDLS_BUFFER_STA),
4867c181f4fSBen Caradoc-Davies FLAG(DOESNT_SUPPORT_QOS_NDP),
487adf8ed01SJohannes Berg FLAG(BUFF_MMPDU_TXQ),
48809b4a4faSJohannes Berg FLAG(SUPPORTS_VHT_EXT_NSS_BW),
4890eeb2b67SSara Sharon FLAG(STA_MMPDU_TXQ),
49077f7ffdcSFelix Fietkau FLAG(TX_STATUS_NO_AMPDU_LEN),
491caf56338SSara Sharon FLAG(SUPPORTS_MULTI_BSSID),
492caf56338SSara Sharon FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID),
493dc3998ecSAlexander Wetzel FLAG(AMPDU_KEYBORDER_SUPPORT),
4946aea26ceSFelix Fietkau FLAG(SUPPORTS_TX_ENCAP_OFFLOAD),
49580a915ecSFelix Fietkau FLAG(SUPPORTS_RX_DECAP_OFFLOAD),
49655f8205eSSriram R FLAG(SUPPORTS_CONC_MON_RX_DECAP),
4976d945a33SLorenzo Bianconi FLAG(DETECTS_COLOR_COLLISION),
498963d0e8dSJohannes Berg FLAG(MLO_MCAST_MULTI_LINK_TX),
49942b941cdSJohannes Berg FLAG(DISALLOW_PUNCTURING),
500*6943e003SJohannes Berg FLAG(DISALLOW_PUNCTURING_5GHZ),
5016f0107d1SJohannes Berg FLAG(HANDLES_QUIET_CSA),
50230686bf7SJohannes Berg #undef FLAG
50330686bf7SJohannes Berg };
50430686bf7SJohannes Berg
hwflags_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)505279daf64SBen Greear static ssize_t hwflags_read(struct file *file, char __user *user_buf,
506279daf64SBen Greear size_t count, loff_t *ppos)
507279daf64SBen Greear {
508279daf64SBen Greear struct ieee80211_local *local = file->private_data;
50930686bf7SJohannes Berg size_t bufsz = 30 * NUM_IEEE80211_HW_FLAGS;
51030686bf7SJohannes Berg char *buf = kzalloc(bufsz, GFP_KERNEL);
51130686bf7SJohannes Berg char *pos = buf, *end = buf + bufsz - 1;
512279daf64SBen Greear ssize_t rv;
51330686bf7SJohannes Berg int i;
514279daf64SBen Greear
515d15b8459SJoe Perches if (!buf)
51630686bf7SJohannes Berg return -ENOMEM;
517d15b8459SJoe Perches
51830686bf7SJohannes Berg /* fail compilation if somebody adds or removes
51930686bf7SJohannes Berg * a flag without updating the name array above
52030686bf7SJohannes Berg */
52168920c97SAndrey Ryabinin BUILD_BUG_ON(ARRAY_SIZE(hw_flag_names) != NUM_IEEE80211_HW_FLAGS);
52230686bf7SJohannes Berg
52330686bf7SJohannes Berg for (i = 0; i < NUM_IEEE80211_HW_FLAGS; i++) {
52430686bf7SJohannes Berg if (test_bit(i, local->hw.flags))
5254633dfc3SMohammed Shafi Shajakhan pos += scnprintf(pos, end - pos, "%s\n",
52630686bf7SJohannes Berg hw_flag_names[i]);
52730686bf7SJohannes Berg }
528279daf64SBen Greear
529279daf64SBen Greear rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
530279daf64SBen Greear kfree(buf);
531279daf64SBen Greear return rv;
532279daf64SBen Greear }
533199d69f2SBenoit Papillault
misc_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)5344a5eccaaSBen Greear static ssize_t misc_read(struct file *file, char __user *user_buf,
5354a5eccaaSBen Greear size_t count, loff_t *ppos)
5364a5eccaaSBen Greear {
5374a5eccaaSBen Greear struct ieee80211_local *local = file->private_data;
5384a5eccaaSBen Greear /* Max len of each line is 16 characters, plus 9 for 'pending:\n' */
5394a5eccaaSBen Greear size_t bufsz = IEEE80211_MAX_QUEUES * 16 + 9;
540b2347a32SDan Carpenter char *buf;
541b2347a32SDan Carpenter char *pos, *end;
5424a5eccaaSBen Greear ssize_t rv;
5434a5eccaaSBen Greear int i;
5444a5eccaaSBen Greear int ln;
5454a5eccaaSBen Greear
546b2347a32SDan Carpenter buf = kzalloc(bufsz, GFP_KERNEL);
547b2347a32SDan Carpenter if (!buf)
548b2347a32SDan Carpenter return -ENOMEM;
549b2347a32SDan Carpenter
550b2347a32SDan Carpenter pos = buf;
551b2347a32SDan Carpenter end = buf + bufsz - 1;
552b2347a32SDan Carpenter
5534a5eccaaSBen Greear pos += scnprintf(pos, end - pos, "pending:\n");
5544a5eccaaSBen Greear
5554a5eccaaSBen Greear for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
5564a5eccaaSBen Greear ln = skb_queue_len(&local->pending[i]);
5574a5eccaaSBen Greear pos += scnprintf(pos, end - pos, "[%i] %d\n",
5584a5eccaaSBen Greear i, ln);
5594a5eccaaSBen Greear }
5604a5eccaaSBen Greear
5614a5eccaaSBen Greear rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
5624a5eccaaSBen Greear kfree(buf);
5634a5eccaaSBen Greear return rv;
5644a5eccaaSBen Greear }
5654a5eccaaSBen Greear
queues_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)566db2e6bd4SJohannes Berg static ssize_t queues_read(struct file *file, char __user *user_buf,
567db2e6bd4SJohannes Berg size_t count, loff_t *ppos)
568db2e6bd4SJohannes Berg {
569db2e6bd4SJohannes Berg struct ieee80211_local *local = file->private_data;
570db2e6bd4SJohannes Berg unsigned long flags;
571db2e6bd4SJohannes Berg char buf[IEEE80211_MAX_QUEUES * 20];
572db2e6bd4SJohannes Berg int q, res = 0;
573db2e6bd4SJohannes Berg
574db2e6bd4SJohannes Berg spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
575db2e6bd4SJohannes Berg for (q = 0; q < local->hw.queues; q++)
576db2e6bd4SJohannes Berg res += sprintf(buf + res, "%02d: %#.8lx/%d\n", q,
577db2e6bd4SJohannes Berg local->queue_stop_reasons[q],
5783b8d81e0SJohannes Berg skb_queue_len(&local->pending[q]));
579db2e6bd4SJohannes Berg spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
580db2e6bd4SJohannes Berg
581db2e6bd4SJohannes Berg return simple_read_from_buffer(user_buf, count, ppos, buf, res);
582db2e6bd4SJohannes Berg }
583db2e6bd4SJohannes Berg
584279daf64SBen Greear DEBUGFS_READONLY_FILE_OPS(hwflags);
585279daf64SBen Greear DEBUGFS_READONLY_FILE_OPS(queues);
5864a5eccaaSBen Greear DEBUGFS_READONLY_FILE_OPS(misc);
587db2e6bd4SJohannes Berg
588e9f207f0SJiri Benc /* statistics stuff */
589e9f207f0SJiri Benc
format_devstat_counter(struct ieee80211_local * local,char __user * userbuf,size_t count,loff_t * ppos,int (* printvalue)(struct ieee80211_low_level_stats * stats,char * buf,int buflen))590e9f207f0SJiri Benc static ssize_t format_devstat_counter(struct ieee80211_local *local,
591e9f207f0SJiri Benc char __user *userbuf,
592e9f207f0SJiri Benc size_t count, loff_t *ppos,
593e9f207f0SJiri Benc int (*printvalue)(struct ieee80211_low_level_stats *stats, char *buf,
594e9f207f0SJiri Benc int buflen))
595e9f207f0SJiri Benc {
596e9f207f0SJiri Benc struct ieee80211_low_level_stats stats;
597e9f207f0SJiri Benc char buf[20];
598e9f207f0SJiri Benc int res;
599e9f207f0SJiri Benc
600629ebb85SJohannes Berg wiphy_lock(local->hw.wiphy);
60124487981SJohannes Berg res = drv_get_stats(local, &stats);
602629ebb85SJohannes Berg wiphy_unlock(local->hw.wiphy);
60324487981SJohannes Berg if (res)
60424487981SJohannes Berg return res;
605e9f207f0SJiri Benc res = printvalue(&stats, buf, sizeof(buf));
606e9f207f0SJiri Benc return simple_read_from_buffer(userbuf, count, ppos, buf, res);
607e9f207f0SJiri Benc }
608e9f207f0SJiri Benc
609e9f207f0SJiri Benc #define DEBUGFS_DEVSTATS_FILE(name) \
610e9f207f0SJiri Benc static int print_devstats_##name(struct ieee80211_low_level_stats *stats,\
611e9f207f0SJiri Benc char *buf, int buflen) \
612e9f207f0SJiri Benc { \
613e9f207f0SJiri Benc return scnprintf(buf, buflen, "%u\n", stats->name); \
614e9f207f0SJiri Benc } \
615e9f207f0SJiri Benc static ssize_t stats_ ##name## _read(struct file *file, \
616e9f207f0SJiri Benc char __user *userbuf, \
617e9f207f0SJiri Benc size_t count, loff_t *ppos) \
618e9f207f0SJiri Benc { \
619e9f207f0SJiri Benc return format_devstat_counter(file->private_data, \
620e9f207f0SJiri Benc userbuf, \
621e9f207f0SJiri Benc count, \
622e9f207f0SJiri Benc ppos, \
623e9f207f0SJiri Benc print_devstats_##name); \
624e9f207f0SJiri Benc } \
625e9f207f0SJiri Benc \
626e9f207f0SJiri Benc static const struct file_operations stats_ ##name## _ops = { \
627e9f207f0SJiri Benc .read = stats_ ##name## _read, \
628234e3405SStephen Boyd .open = simple_open, \
6292b18ab36SArnd Bergmann .llseek = generic_file_llseek, \
630e9f207f0SJiri Benc };
631e9f207f0SJiri Benc
632453a2a82SJohannes Berg #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
633f1160434SJohannes Berg #define DEBUGFS_STATS_ADD(name) \
634f1160434SJohannes Berg debugfs_create_u32(#name, 0400, statsd, &local->name);
635453a2a82SJohannes Berg #endif
6362826bcd8SFelix Fietkau #define DEBUGFS_DEVSTATS_ADD(name) \
6377bcfaf2fSJohannes Berg debugfs_create_file(#name, 0400, statsd, local, &stats_ ##name## _ops);
638e9f207f0SJiri Benc
639e9f207f0SJiri Benc DEBUGFS_DEVSTATS_FILE(dot11ACKFailureCount);
640e9f207f0SJiri Benc DEBUGFS_DEVSTATS_FILE(dot11RTSFailureCount);
641e9f207f0SJiri Benc DEBUGFS_DEVSTATS_FILE(dot11FCSErrorCount);
642e9f207f0SJiri Benc DEBUGFS_DEVSTATS_FILE(dot11RTSSuccessCount);
643e9f207f0SJiri Benc
debugfs_hw_add(struct ieee80211_local * local)644e9f207f0SJiri Benc void debugfs_hw_add(struct ieee80211_local *local)
645e9f207f0SJiri Benc {
646e9f207f0SJiri Benc struct dentry *phyd = local->hw.wiphy->debugfsdir;
647e9f207f0SJiri Benc struct dentry *statsd;
648e9f207f0SJiri Benc
649e9f207f0SJiri Benc if (!phyd)
650e9f207f0SJiri Benc return;
651e9f207f0SJiri Benc
652e9f207f0SJiri Benc local->debugfs.keys = debugfs_create_dir("keys", phyd);
653e9f207f0SJiri Benc
654e9f207f0SJiri Benc DEBUGFS_ADD(total_ps_buffered);
655e9f207f0SJiri Benc DEBUGFS_ADD(wep_iv);
656bddb2afcSJohannes Berg DEBUGFS_ADD(rate_ctrl_alg);
657db2e6bd4SJohannes Berg DEBUGFS_ADD(queues);
6584a5eccaaSBen Greear DEBUGFS_ADD(misc);
6592ad4814fSJohannes Berg #ifdef CONFIG_PM
660827b1fb4SJohannes Berg DEBUGFS_ADD_MODE(reset, 0200);
6612ad4814fSJohannes Berg #endif
662279daf64SBen Greear DEBUGFS_ADD(hwflags);
66383bdf2a1SBen Greear DEBUGFS_ADD(user_power);
66483bdf2a1SBen Greear DEBUGFS_ADD(power);
665c90142a5SThomas Pedersen DEBUGFS_ADD(hw_conf);
666276d9e82SJulius Niedworok DEBUGFS_ADD_MODE(force_tx_status, 0600);
667e908435eSLorenzo Bianconi DEBUGFS_ADD_MODE(aql_enable, 0600);
6683db2c560SFelix Fietkau DEBUGFS_ADD(aql_pending);
6699399b86cSMichal Kazior DEBUGFS_ADD_MODE(aqm, 0600);
670e9f207f0SJiri Benc
671e322c07fSLorenzo Bianconi DEBUGFS_ADD_MODE(airtime_flags, 0600);
672b4809e94SToke Høiland-Jørgensen
6733ace10f5SKan Yan DEBUGFS_ADD(aql_txq_limit);
6743ace10f5SKan Yan debugfs_create_u32("aql_threshold", 0600,
6753ace10f5SKan Yan phyd, &local->aql_threshold);
6763ace10f5SKan Yan
677e9f207f0SJiri Benc statsd = debugfs_create_dir("statistics", phyd);
678e9f207f0SJiri Benc
679c206ca67SJohannes Berg #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
680f1160434SJohannes Berg DEBUGFS_STATS_ADD(dot11TransmittedFragmentCount);
681f1160434SJohannes Berg DEBUGFS_STATS_ADD(dot11MulticastTransmittedFrameCount);
682f1160434SJohannes Berg DEBUGFS_STATS_ADD(dot11FailedCount);
683f1160434SJohannes Berg DEBUGFS_STATS_ADD(dot11RetryCount);
684f1160434SJohannes Berg DEBUGFS_STATS_ADD(dot11MultipleRetryCount);
685f1160434SJohannes Berg DEBUGFS_STATS_ADD(dot11FrameDuplicateCount);
686f1160434SJohannes Berg DEBUGFS_STATS_ADD(dot11ReceivedFragmentCount);
687f1160434SJohannes Berg DEBUGFS_STATS_ADD(dot11MulticastReceivedFrameCount);
688f1160434SJohannes Berg DEBUGFS_STATS_ADD(dot11TransmittedFrameCount);
689f1160434SJohannes Berg DEBUGFS_STATS_ADD(tx_handlers_drop);
690f1160434SJohannes Berg DEBUGFS_STATS_ADD(tx_handlers_queued);
691f1160434SJohannes Berg DEBUGFS_STATS_ADD(tx_handlers_drop_wep);
692f1160434SJohannes Berg DEBUGFS_STATS_ADD(tx_handlers_drop_not_assoc);
693f1160434SJohannes Berg DEBUGFS_STATS_ADD(tx_handlers_drop_unauth_port);
694f1160434SJohannes Berg DEBUGFS_STATS_ADD(rx_handlers_drop);
695f1160434SJohannes Berg DEBUGFS_STATS_ADD(rx_handlers_queued);
696f1160434SJohannes Berg DEBUGFS_STATS_ADD(rx_handlers_drop_nullfunc);
697f1160434SJohannes Berg DEBUGFS_STATS_ADD(rx_handlers_drop_defrag);
698f1160434SJohannes Berg DEBUGFS_STATS_ADD(tx_expand_skb_head);
699f1160434SJohannes Berg DEBUGFS_STATS_ADD(tx_expand_skb_head_cloned);
700f1160434SJohannes Berg DEBUGFS_STATS_ADD(rx_expand_skb_head_defrag);
701f1160434SJohannes Berg DEBUGFS_STATS_ADD(rx_handlers_fragments);
702f1160434SJohannes Berg DEBUGFS_STATS_ADD(tx_status_drop);
703e9f207f0SJiri Benc #endif
7042826bcd8SFelix Fietkau DEBUGFS_DEVSTATS_ADD(dot11ACKFailureCount);
7052826bcd8SFelix Fietkau DEBUGFS_DEVSTATS_ADD(dot11RTSFailureCount);
7062826bcd8SFelix Fietkau DEBUGFS_DEVSTATS_ADD(dot11FCSErrorCount);
7072826bcd8SFelix Fietkau DEBUGFS_DEVSTATS_ADD(dot11RTSSuccessCount);
708e9f207f0SJiri Benc }
709