debugfs.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * mac80211 debugfs for wireless PHYs
  4. *
  5. * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
  6. * Copyright 2013-2014 Intel Mobile Communications GmbH
  7. * Copyright (C) 2018 - 2019, 2021-2024 Intel Corporation
  8. */
  9. #include <linux/debugfs.h>
  10. #include <linux/rtnetlink.h>
  11. #include <linux/vmalloc.h>
  12. #include "ieee80211_i.h"
  13. #include "driver-ops.h"
  14. #include "rate.h"
  15. #include "debugfs.h"
  16. #define DEBUGFS_FORMAT_BUFFER_SIZE 100
  17. int mac80211_format_buffer(char __user *userbuf, size_t count,
  18. loff_t *ppos, char *fmt, ...)
  19. {
  20. va_list args;
  21. char buf[DEBUGFS_FORMAT_BUFFER_SIZE];
  22. int res;
  23. va_start(args, fmt);
  24. res = vscnprintf(buf, sizeof(buf), fmt, args);
  25. va_end(args);
  26. return simple_read_from_buffer(userbuf, count, ppos, buf, res);
  27. }
  28. #define DEBUGFS_READONLY_FILE_FN(name, fmt, value...) \
  29. static ssize_t name## _read(struct file *file, char __user *userbuf, \
  30. size_t count, loff_t *ppos) \
  31. { \
  32. struct ieee80211_local *local = file->private_data; \
  33. \
  34. return mac80211_format_buffer(userbuf, count, ppos, \
  35. fmt "\n", ##value); \
  36. }
  37. #define DEBUGFS_READONLY_FILE_OPS(name) \
  38. static const struct file_operations name## _ops = { \
  39. .read = name## _read, \
  40. .open = simple_open, \
  41. .llseek = generic_file_llseek, \
  42. };
  43. #define DEBUGFS_READONLY_FILE(name, fmt, value...) \
  44. DEBUGFS_READONLY_FILE_FN(name, fmt, value) \
  45. DEBUGFS_READONLY_FILE_OPS(name)
  46. #define DEBUGFS_ADD(name) \
  47. debugfs_create_file(#name, 0400, phyd, local, &name## _ops)
  48. #define DEBUGFS_ADD_MODE(name, mode) \
  49. debugfs_create_file(#name, mode, phyd, local, &name## _ops);
  50. DEBUGFS_READONLY_FILE(hw_conf, "%x",
  51. local->hw.conf.flags);
  52. DEBUGFS_READONLY_FILE(user_power, "%d",
  53. local->user_power_level);
  54. DEBUGFS_READONLY_FILE(power, "%d",
  55. local->hw.conf.power_level);
  56. DEBUGFS_READONLY_FILE(total_ps_buffered, "%d",
  57. local->total_ps_buffered);
  58. DEBUGFS_READONLY_FILE(wep_iv, "%#08x",
  59. local->wep_iv & 0xffffff);
  60. DEBUGFS_READONLY_FILE(rate_ctrl_alg, "%s",
  61. local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver");
  62. static ssize_t aqm_read(struct file *file,
  63. char __user *user_buf,
  64. size_t count,
  65. loff_t *ppos)
  66. {
  67. struct ieee80211_local *local = file->private_data;
  68. struct fq *fq = &local->fq;
  69. char buf[200];
  70. int len = 0;
  71. spin_lock_bh(&local->fq.lock);
  72. rcu_read_lock();
  73. len = scnprintf(buf, sizeof(buf),
  74. "access name value\n"
  75. "R fq_flows_cnt %u\n"
  76. "R fq_backlog %u\n"
  77. "R fq_overlimit %u\n"
  78. "R fq_overmemory %u\n"
  79. "R fq_collisions %u\n"
  80. "R fq_memory_usage %u\n"
  81. "RW fq_memory_limit %u\n"
  82. "RW fq_limit %u\n"
  83. "RW fq_quantum %u\n",
  84. fq->flows_cnt,
  85. fq->backlog,
  86. fq->overmemory,
  87. fq->overlimit,
  88. fq->collisions,
  89. fq->memory_usage,
  90. fq->memory_limit,
  91. fq->limit,
  92. fq->quantum);
  93. rcu_read_unlock();
  94. spin_unlock_bh(&local->fq.lock);
  95. return simple_read_from_buffer(user_buf, count, ppos,
  96. buf, len);
  97. }
  98. static ssize_t aqm_write(struct file *file,
  99. const char __user *user_buf,
  100. size_t count,
  101. loff_t *ppos)
  102. {
  103. struct ieee80211_local *local = file->private_data;
  104. char buf[100];
  105. if (count >= sizeof(buf))
  106. return -EINVAL;
  107. if (copy_from_user(buf, user_buf, count))
  108. return -EFAULT;
  109. if (count && buf[count - 1] == '\n')
  110. buf[count - 1] = '\0';
  111. else
  112. buf[count] = '\0';
  113. if (sscanf(buf, "fq_limit %u", &local->fq.limit) == 1)
  114. return count;
  115. else if (sscanf(buf, "fq_memory_limit %u", &local->fq.memory_limit) == 1)
  116. return count;
  117. else if (sscanf(buf, "fq_quantum %u", &local->fq.quantum) == 1)
  118. return count;
  119. return -EINVAL;
  120. }
  121. static const struct file_operations aqm_ops = {
  122. .write = aqm_write,
  123. .read = aqm_read,
  124. .open = simple_open,
  125. .llseek = default_llseek,
  126. };
  127. static ssize_t airtime_flags_read(struct file *file,
  128. char __user *user_buf,
  129. size_t count, loff_t *ppos)
  130. {
  131. struct ieee80211_local *local = file->private_data;
  132. char buf[128] = {}, *pos, *end;
  133. pos = buf;
  134. end = pos + sizeof(buf) - 1;
  135. if (local->airtime_flags & AIRTIME_USE_TX)
  136. pos += scnprintf(pos, end - pos, "AIRTIME_TX\t(%lx)\n",
  137. AIRTIME_USE_TX);
  138. if (local->airtime_flags & AIRTIME_USE_RX)
  139. pos += scnprintf(pos, end - pos, "AIRTIME_RX\t(%lx)\n",
  140. AIRTIME_USE_RX);
  141. return simple_read_from_buffer(user_buf, count, ppos, buf,
  142. strlen(buf));
  143. }
  144. static ssize_t airtime_flags_write(struct file *file,
  145. const char __user *user_buf,
  146. size_t count, loff_t *ppos)
  147. {
  148. struct ieee80211_local *local = file->private_data;
  149. char buf[16];
  150. if (count >= sizeof(buf))
  151. return -EINVAL;
  152. if (copy_from_user(buf, user_buf, count))
  153. return -EFAULT;
  154. if (count && buf[count - 1] == '\n')
  155. buf[count - 1] = '\0';
  156. else
  157. buf[count] = '\0';
  158. if (kstrtou16(buf, 0, &local->airtime_flags))
  159. return -EINVAL;
  160. return count;
  161. }
  162. static const struct file_operations airtime_flags_ops = {
  163. .write = airtime_flags_write,
  164. .read = airtime_flags_read,
  165. .open = simple_open,
  166. .llseek = default_llseek,
  167. };
  168. static ssize_t aql_pending_read(struct file *file,
  169. char __user *user_buf,
  170. size_t count, loff_t *ppos)
  171. {
  172. struct ieee80211_local *local = file->private_data;
  173. char buf[400];
  174. int len = 0;
  175. len = scnprintf(buf, sizeof(buf),
  176. "AC AQL pending\n"
  177. "VO %u us\n"
  178. "VI %u us\n"
  179. "BE %u us\n"
  180. "BK %u us\n"
  181. "total %u us\n",
  182. atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_VO]),
  183. atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_VI]),
  184. atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_BE]),
  185. atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_BK]),
  186. atomic_read(&local->aql_total_pending_airtime));
  187. return simple_read_from_buffer(user_buf, count, ppos,
  188. buf, len);
  189. }
  190. static const struct file_operations aql_pending_ops = {
  191. .read = aql_pending_read,
  192. .open = simple_open,
  193. .llseek = default_llseek,
  194. };
  195. static ssize_t aql_txq_limit_read(struct file *file,
  196. char __user *user_buf,
  197. size_t count,
  198. loff_t *ppos)
  199. {
  200. struct ieee80211_local *local = file->private_data;
  201. char buf[400];
  202. int len = 0;
  203. len = scnprintf(buf, sizeof(buf),
  204. "AC AQL limit low AQL limit high\n"
  205. "VO %u %u\n"
  206. "VI %u %u\n"
  207. "BE %u %u\n"
  208. "BK %u %u\n",
  209. local->aql_txq_limit_low[IEEE80211_AC_VO],
  210. local->aql_txq_limit_high[IEEE80211_AC_VO],
  211. local->aql_txq_limit_low[IEEE80211_AC_VI],
  212. local->aql_txq_limit_high[IEEE80211_AC_VI],
  213. local->aql_txq_limit_low[IEEE80211_AC_BE],
  214. local->aql_txq_limit_high[IEEE80211_AC_BE],
  215. local->aql_txq_limit_low[IEEE80211_AC_BK],
  216. local->aql_txq_limit_high[IEEE80211_AC_BK]);
  217. return simple_read_from_buffer(user_buf, count, ppos,
  218. buf, len);
  219. }
  220. static ssize_t aql_txq_limit_write(struct file *file,
  221. const char __user *user_buf,
  222. size_t count,
  223. loff_t *ppos)
  224. {
  225. struct ieee80211_local *local = file->private_data;
  226. char buf[100];
  227. u32 ac, q_limit_low, q_limit_high, q_limit_low_old, q_limit_high_old;
  228. struct sta_info *sta;
  229. if (count >= sizeof(buf))
  230. return -EINVAL;
  231. if (copy_from_user(buf, user_buf, count))
  232. return -EFAULT;
  233. if (count && buf[count - 1] == '\n')
  234. buf[count - 1] = '\0';
  235. else
  236. buf[count] = '\0';
  237. if (sscanf(buf, "%u %u %u", &ac, &q_limit_low, &q_limit_high) != 3)
  238. return -EINVAL;
  239. if (ac >= IEEE80211_NUM_ACS)
  240. return -EINVAL;
  241. q_limit_low_old = local->aql_txq_limit_low[ac];
  242. q_limit_high_old = local->aql_txq_limit_high[ac];
  243. wiphy_lock(local->hw.wiphy);
  244. local->aql_txq_limit_low[ac] = q_limit_low;
  245. local->aql_txq_limit_high[ac] = q_limit_high;
  246. list_for_each_entry(sta, &local->sta_list, list) {
  247. /* If a sta has customized queue limits, keep it */
  248. if (sta->airtime[ac].aql_limit_low == q_limit_low_old &&
  249. sta->airtime[ac].aql_limit_high == q_limit_high_old) {
  250. sta->airtime[ac].aql_limit_low = q_limit_low;
  251. sta->airtime[ac].aql_limit_high = q_limit_high;
  252. }
  253. }
  254. wiphy_unlock(local->hw.wiphy);
  255. return count;
  256. }
  257. static const struct file_operations aql_txq_limit_ops = {
  258. .write = aql_txq_limit_write,
  259. .read = aql_txq_limit_read,
  260. .open = simple_open,
  261. .llseek = default_llseek,
  262. };
  263. static ssize_t aql_enable_read(struct file *file, char __user *user_buf,
  264. size_t count, loff_t *ppos)
  265. {
  266. char buf[3];
  267. int len;
  268. len = scnprintf(buf, sizeof(buf), "%d\n",
  269. !static_key_false(&aql_disable.key));
  270. return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  271. }
  272. static ssize_t aql_enable_write(struct file *file, const char __user *user_buf,
  273. size_t count, loff_t *ppos)
  274. {
  275. bool aql_disabled = static_key_false(&aql_disable.key);
  276. char buf[3];
  277. size_t len;
  278. if (count > sizeof(buf))
  279. return -EINVAL;
  280. if (copy_from_user(buf, user_buf, count))
  281. return -EFAULT;
  282. buf[sizeof(buf) - 1] = '\0';
  283. len = strlen(buf);
  284. if (len > 0 && buf[len - 1] == '\n')
  285. buf[len - 1] = 0;
  286. if (buf[0] == '0' && buf[1] == '\0') {
  287. if (!aql_disabled)
  288. static_branch_inc(&aql_disable);
  289. } else if (buf[0] == '1' && buf[1] == '\0') {
  290. if (aql_disabled)
  291. static_branch_dec(&aql_disable);
  292. } else {
  293. return -EINVAL;
  294. }
  295. return count;
  296. }
  297. static const struct file_operations aql_enable_ops = {
  298. .write = aql_enable_write,
  299. .read = aql_enable_read,
  300. .open = simple_open,
  301. .llseek = default_llseek,
  302. };
  303. static ssize_t force_tx_status_read(struct file *file,
  304. char __user *user_buf,
  305. size_t count,
  306. loff_t *ppos)
  307. {
  308. struct ieee80211_local *local = file->private_data;
  309. char buf[3];
  310. int len = 0;
  311. len = scnprintf(buf, sizeof(buf), "%d\n", (int)local->force_tx_status);
  312. return simple_read_from_buffer(user_buf, count, ppos,
  313. buf, len);
  314. }
  315. static ssize_t force_tx_status_write(struct file *file,
  316. const char __user *user_buf,
  317. size_t count,
  318. loff_t *ppos)
  319. {
  320. struct ieee80211_local *local = file->private_data;
  321. char buf[3];
  322. if (count >= sizeof(buf))
  323. return -EINVAL;
  324. if (copy_from_user(buf, user_buf, count))
  325. return -EFAULT;
  326. if (count && buf[count - 1] == '\n')
  327. buf[count - 1] = '\0';
  328. else
  329. buf[count] = '\0';
  330. if (buf[0] == '0' && buf[1] == '\0')
  331. local->force_tx_status = 0;
  332. else if (buf[0] == '1' && buf[1] == '\0')
  333. local->force_tx_status = 1;
  334. else
  335. return -EINVAL;
  336. return count;
  337. }
  338. static const struct file_operations force_tx_status_ops = {
  339. .write = force_tx_status_write,
  340. .read = force_tx_status_read,
  341. .open = simple_open,
  342. .llseek = default_llseek,
  343. };
  344. #ifdef CONFIG_PM
  345. static ssize_t reset_write(struct file *file, const char __user *user_buf,
  346. size_t count, loff_t *ppos)
  347. {
  348. struct ieee80211_local *local = file->private_data;
  349. int ret;
  350. rtnl_lock();
  351. wiphy_lock(local->hw.wiphy);
  352. __ieee80211_suspend(&local->hw, NULL);
  353. ret = __ieee80211_resume(&local->hw);
  354. wiphy_unlock(local->hw.wiphy);
  355. if (ret)
  356. cfg80211_shutdown_all_interfaces(local->hw.wiphy);
  357. rtnl_unlock();
  358. return count;
  359. }
  360. static const struct file_operations reset_ops = {
  361. .write = reset_write,
  362. .open = simple_open,
  363. .llseek = noop_llseek,
  364. };
  365. #endif
  366. static const char *hw_flag_names[] = {
  367. #define FLAG(F) [IEEE80211_HW_##F] = #F
  368. FLAG(HAS_RATE_CONTROL),
  369. FLAG(RX_INCLUDES_FCS),
  370. FLAG(HOST_BROADCAST_PS_BUFFERING),
  371. FLAG(SIGNAL_UNSPEC),
  372. FLAG(SIGNAL_DBM),
  373. FLAG(NEED_DTIM_BEFORE_ASSOC),
  374. FLAG(SPECTRUM_MGMT),
  375. FLAG(AMPDU_AGGREGATION),
  376. FLAG(SUPPORTS_PS),
  377. FLAG(PS_NULLFUNC_STACK),
  378. FLAG(SUPPORTS_DYNAMIC_PS),
  379. FLAG(MFP_CAPABLE),
  380. FLAG(WANT_MONITOR_VIF),
  381. FLAG(NO_AUTO_VIF),
  382. FLAG(SW_CRYPTO_CONTROL),
  383. FLAG(SUPPORT_FAST_XMIT),
  384. FLAG(REPORTS_TX_ACK_STATUS),
  385. FLAG(CONNECTION_MONITOR),
  386. FLAG(QUEUE_CONTROL),
  387. FLAG(SUPPORTS_PER_STA_GTK),
  388. FLAG(AP_LINK_PS),
  389. FLAG(TX_AMPDU_SETUP_IN_HW),
  390. FLAG(SUPPORTS_RC_TABLE),
  391. FLAG(P2P_DEV_ADDR_FOR_INTF),
  392. FLAG(TIMING_BEACON_ONLY),
  393. FLAG(SUPPORTS_HT_CCK_RATES),
  394. FLAG(CHANCTX_STA_CSA),
  395. FLAG(SUPPORTS_CLONED_SKBS),
  396. FLAG(SINGLE_SCAN_ON_ALL_BANDS),
  397. FLAG(TDLS_WIDER_BW),
  398. FLAG(SUPPORTS_AMSDU_IN_AMPDU),
  399. FLAG(BEACON_TX_STATUS),
  400. FLAG(NEEDS_UNIQUE_STA_ADDR),
  401. FLAG(SUPPORTS_REORDERING_BUFFER),
  402. FLAG(USES_RSS),
  403. FLAG(TX_AMSDU),
  404. FLAG(TX_FRAG_LIST),
  405. FLAG(REPORTS_LOW_ACK),
  406. FLAG(SUPPORTS_TX_FRAG),
  407. FLAG(SUPPORTS_TDLS_BUFFER_STA),
  408. FLAG(DOESNT_SUPPORT_QOS_NDP),
  409. FLAG(BUFF_MMPDU_TXQ),
  410. FLAG(SUPPORTS_VHT_EXT_NSS_BW),
  411. FLAG(STA_MMPDU_TXQ),
  412. FLAG(TX_STATUS_NO_AMPDU_LEN),
  413. FLAG(SUPPORTS_MULTI_BSSID),
  414. FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID),
  415. FLAG(AMPDU_KEYBORDER_SUPPORT),
  416. FLAG(SUPPORTS_TX_ENCAP_OFFLOAD),
  417. FLAG(SUPPORTS_RX_DECAP_OFFLOAD),
  418. FLAG(SUPPORTS_CONC_MON_RX_DECAP),
  419. FLAG(DETECTS_COLOR_COLLISION),
  420. FLAG(MLO_MCAST_MULTI_LINK_TX),
  421. FLAG(DISALLOW_PUNCTURING),
  422. FLAG(DISALLOW_PUNCTURING_5GHZ),
  423. FLAG(HANDLES_QUIET_CSA),
  424. FLAG(STRICT),
  425. #undef FLAG
  426. };
  427. static ssize_t hwflags_read(struct file *file, char __user *user_buf,
  428. size_t count, loff_t *ppos)
  429. {
  430. struct ieee80211_local *local = file->private_data;
  431. size_t bufsz = 30 * NUM_IEEE80211_HW_FLAGS;
  432. char *buf = kzalloc(bufsz, GFP_KERNEL);
  433. char *pos = buf, *end = buf + bufsz - 1;
  434. ssize_t rv;
  435. int i;
  436. if (!buf)
  437. return -ENOMEM;
  438. /* fail compilation if somebody adds or removes
  439. * a flag without updating the name array above
  440. */
  441. BUILD_BUG_ON(ARRAY_SIZE(hw_flag_names) != NUM_IEEE80211_HW_FLAGS);
  442. for (i = 0; i < NUM_IEEE80211_HW_FLAGS; i++) {
  443. if (test_bit(i, local->hw.flags))
  444. pos += scnprintf(pos, end - pos, "%s\n",
  445. hw_flag_names[i]);
  446. }
  447. rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
  448. kfree(buf);
  449. return rv;
  450. }
  451. static ssize_t hwflags_write(struct file *file, const char __user *user_buf,
  452. size_t count, loff_t *ppos)
  453. {
  454. struct ieee80211_local *local = file->private_data;
  455. char buf[100];
  456. int val;
  457. if (count >= sizeof(buf))
  458. return -EINVAL;
  459. if (copy_from_user(buf, user_buf, count))
  460. return -EFAULT;
  461. if (count && buf[count - 1] == '\n')
  462. buf[count - 1] = '\0';
  463. else
  464. buf[count] = '\0';
  465. if (sscanf(buf, "strict=%d", &val) == 1) {
  466. switch (val) {
  467. case 0:
  468. ieee80211_hw_set(&local->hw, STRICT);
  469. return count;
  470. case 1:
  471. __clear_bit(IEEE80211_HW_STRICT, local->hw.flags);
  472. return count;
  473. default:
  474. return -EINVAL;
  475. }
  476. }
  477. return -EINVAL;
  478. }
  479. static const struct file_operations hwflags_ops = {
  480. .open = simple_open,
  481. .read = hwflags_read,
  482. .write = hwflags_write,
  483. };
  484. static ssize_t misc_read(struct file *file, char __user *user_buf,
  485. size_t count, loff_t *ppos)
  486. {
  487. struct ieee80211_local *local = file->private_data;
  488. /* Max len of each line is 16 characters, plus 9 for 'pending:\n' */
  489. size_t bufsz = IEEE80211_MAX_QUEUES * 16 + 9;
  490. char *buf;
  491. char *pos, *end;
  492. ssize_t rv;
  493. int i;
  494. int ln;
  495. buf = kzalloc(bufsz, GFP_KERNEL);
  496. if (!buf)
  497. return -ENOMEM;
  498. pos = buf;
  499. end = buf + bufsz - 1;
  500. pos += scnprintf(pos, end - pos, "pending:\n");
  501. for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
  502. ln = skb_queue_len(&local->pending[i]);
  503. pos += scnprintf(pos, end - pos, "[%i] %d\n",
  504. i, ln);
  505. }
  506. rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
  507. kfree(buf);
  508. return rv;
  509. }
  510. static ssize_t queues_read(struct file *file, char __user *user_buf,
  511. size_t count, loff_t *ppos)
  512. {
  513. struct ieee80211_local *local = file->private_data;
  514. unsigned long flags;
  515. char buf[IEEE80211_MAX_QUEUES * 20];
  516. int q, res = 0;
  517. spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
  518. for (q = 0; q < local->hw.queues; q++)
  519. res += sprintf(buf + res, "%02d: %#.8lx/%d\n", q,
  520. local->queue_stop_reasons[q],
  521. skb_queue_len(&local->pending[q]));
  522. spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
  523. return simple_read_from_buffer(user_buf, count, ppos, buf, res);
  524. }
  525. DEBUGFS_READONLY_FILE_OPS(queues);
  526. DEBUGFS_READONLY_FILE_OPS(misc);
  527. /* statistics stuff */
  528. static ssize_t format_devstat_counter(struct ieee80211_local *local,
  529. char __user *userbuf,
  530. size_t count, loff_t *ppos,
  531. int (*printvalue)(struct ieee80211_low_level_stats *stats, char *buf,
  532. int buflen))
  533. {
  534. struct ieee80211_low_level_stats stats;
  535. char buf[20];
  536. int res;
  537. wiphy_lock(local->hw.wiphy);
  538. res = drv_get_stats(local, &stats);
  539. wiphy_unlock(local->hw.wiphy);
  540. if (res)
  541. return res;
  542. res = printvalue(&stats, buf, sizeof(buf));
  543. return simple_read_from_buffer(userbuf, count, ppos, buf, res);
  544. }
  545. #define DEBUGFS_DEVSTATS_FILE(name) \
  546. static int print_devstats_##name(struct ieee80211_low_level_stats *stats,\
  547. char *buf, int buflen) \
  548. { \
  549. return scnprintf(buf, buflen, "%u\n", stats->name); \
  550. } \
  551. static ssize_t stats_ ##name## _read(struct file *file, \
  552. char __user *userbuf, \
  553. size_t count, loff_t *ppos) \
  554. { \
  555. return format_devstat_counter(file->private_data, \
  556. userbuf, \
  557. count, \
  558. ppos, \
  559. print_devstats_##name); \
  560. } \
  561. \
  562. static const struct file_operations stats_ ##name## _ops = { \
  563. .read = stats_ ##name## _read, \
  564. .open = simple_open, \
  565. .llseek = generic_file_llseek, \
  566. };
  567. #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
  568. #define DEBUGFS_STATS_ADD(name) \
  569. debugfs_create_u32(#name, 0400, statsd, &local->name);
  570. #endif
  571. #define DEBUGFS_DEVSTATS_ADD(name) \
  572. debugfs_create_file(#name, 0400, statsd, local, &stats_ ##name## _ops);
  573. DEBUGFS_DEVSTATS_FILE(dot11ACKFailureCount);
  574. DEBUGFS_DEVSTATS_FILE(dot11RTSFailureCount);
  575. DEBUGFS_DEVSTATS_FILE(dot11FCSErrorCount);
  576. DEBUGFS_DEVSTATS_FILE(dot11RTSSuccessCount);
  577. void debugfs_hw_add(struct ieee80211_local *local)
  578. {
  579. struct dentry *phyd = local->hw.wiphy->debugfsdir;
  580. struct dentry *statsd;
  581. if (!phyd)
  582. return;
  583. local->debugfs.keys = debugfs_create_dir("keys", phyd);
  584. DEBUGFS_ADD(total_ps_buffered);
  585. DEBUGFS_ADD(wep_iv);
  586. DEBUGFS_ADD(rate_ctrl_alg);
  587. DEBUGFS_ADD(queues);
  588. DEBUGFS_ADD(misc);
  589. #ifdef CONFIG_PM
  590. DEBUGFS_ADD_MODE(reset, 0200);
  591. #endif
  592. DEBUGFS_ADD_MODE(hwflags, 0600);
  593. DEBUGFS_ADD(user_power);
  594. DEBUGFS_ADD(power);
  595. DEBUGFS_ADD(hw_conf);
  596. DEBUGFS_ADD_MODE(force_tx_status, 0600);
  597. DEBUGFS_ADD_MODE(aql_enable, 0600);
  598. DEBUGFS_ADD(aql_pending);
  599. DEBUGFS_ADD_MODE(aqm, 0600);
  600. DEBUGFS_ADD_MODE(airtime_flags, 0600);
  601. DEBUGFS_ADD(aql_txq_limit);
  602. debugfs_create_u32("aql_threshold", 0600,
  603. phyd, &local->aql_threshold);
  604. statsd = debugfs_create_dir("statistics", phyd);
  605. #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
  606. DEBUGFS_STATS_ADD(dot11TransmittedFragmentCount);
  607. DEBUGFS_STATS_ADD(dot11MulticastTransmittedFrameCount);
  608. DEBUGFS_STATS_ADD(dot11FailedCount);
  609. DEBUGFS_STATS_ADD(dot11RetryCount);
  610. DEBUGFS_STATS_ADD(dot11MultipleRetryCount);
  611. DEBUGFS_STATS_ADD(dot11FrameDuplicateCount);
  612. DEBUGFS_STATS_ADD(dot11ReceivedFragmentCount);
  613. DEBUGFS_STATS_ADD(dot11MulticastReceivedFrameCount);
  614. DEBUGFS_STATS_ADD(dot11TransmittedFrameCount);
  615. DEBUGFS_STATS_ADD(tx_handlers_drop);
  616. DEBUGFS_STATS_ADD(tx_handlers_queued);
  617. DEBUGFS_STATS_ADD(tx_handlers_drop_wep);
  618. DEBUGFS_STATS_ADD(tx_handlers_drop_not_assoc);
  619. DEBUGFS_STATS_ADD(tx_handlers_drop_unauth_port);
  620. DEBUGFS_STATS_ADD(rx_handlers_drop);
  621. DEBUGFS_STATS_ADD(rx_handlers_queued);
  622. DEBUGFS_STATS_ADD(rx_handlers_drop_nullfunc);
  623. DEBUGFS_STATS_ADD(rx_handlers_drop_defrag);
  624. DEBUGFS_STATS_ADD(tx_expand_skb_head);
  625. DEBUGFS_STATS_ADD(tx_expand_skb_head_cloned);
  626. DEBUGFS_STATS_ADD(rx_expand_skb_head_defrag);
  627. DEBUGFS_STATS_ADD(rx_handlers_fragments);
  628. DEBUGFS_STATS_ADD(tx_status_drop);
  629. #endif
  630. DEBUGFS_DEVSTATS_ADD(dot11ACKFailureCount);
  631. DEBUGFS_DEVSTATS_ADD(dot11RTSFailureCount);
  632. DEBUGFS_DEVSTATS_ADD(dot11FCSErrorCount);
  633. DEBUGFS_DEVSTATS_ADD(dot11RTSSuccessCount);
  634. }