debug.c 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426
  1. /******************************************************************************
  2. *
  3. * GPL LICENSE SUMMARY
  4. *
  5. * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of version 2 of the GNU General Public License as
  9. * published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
  19. * USA
  20. *
  21. * The full GNU General Public License is included in this distribution
  22. * in the file called LICENSE.GPL.
  23. *
  24. * Contact Information:
  25. * Intel Linux Wireless <ilw@linux.intel.com>
  26. * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  27. *****************************************************************************/
  28. #include <linux/ieee80211.h>
  29. #include <linux/export.h>
  30. #include <net/mac80211.h>
  31. #include "common.h"
  32. static void
  33. il_clear_traffic_stats(struct il_priv *il)
  34. {
  35. memset(&il->tx_stats, 0, sizeof(struct traffic_stats));
  36. memset(&il->rx_stats, 0, sizeof(struct traffic_stats));
  37. }
  38. /*
  39. * il_update_stats function record all the MGMT, CTRL and DATA pkt for
  40. * both TX and Rx . Use debugfs to display the rx/rx_stats
  41. */
  42. void
  43. il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len)
  44. {
  45. struct traffic_stats *stats;
  46. if (is_tx)
  47. stats = &il->tx_stats;
  48. else
  49. stats = &il->rx_stats;
  50. if (ieee80211_is_mgmt(fc)) {
  51. switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
  52. case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
  53. stats->mgmt[MANAGEMENT_ASSOC_REQ]++;
  54. break;
  55. case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
  56. stats->mgmt[MANAGEMENT_ASSOC_RESP]++;
  57. break;
  58. case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
  59. stats->mgmt[MANAGEMENT_REASSOC_REQ]++;
  60. break;
  61. case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
  62. stats->mgmt[MANAGEMENT_REASSOC_RESP]++;
  63. break;
  64. case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ):
  65. stats->mgmt[MANAGEMENT_PROBE_REQ]++;
  66. break;
  67. case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
  68. stats->mgmt[MANAGEMENT_PROBE_RESP]++;
  69. break;
  70. case cpu_to_le16(IEEE80211_STYPE_BEACON):
  71. stats->mgmt[MANAGEMENT_BEACON]++;
  72. break;
  73. case cpu_to_le16(IEEE80211_STYPE_ATIM):
  74. stats->mgmt[MANAGEMENT_ATIM]++;
  75. break;
  76. case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
  77. stats->mgmt[MANAGEMENT_DISASSOC]++;
  78. break;
  79. case cpu_to_le16(IEEE80211_STYPE_AUTH):
  80. stats->mgmt[MANAGEMENT_AUTH]++;
  81. break;
  82. case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
  83. stats->mgmt[MANAGEMENT_DEAUTH]++;
  84. break;
  85. case cpu_to_le16(IEEE80211_STYPE_ACTION):
  86. stats->mgmt[MANAGEMENT_ACTION]++;
  87. break;
  88. }
  89. } else if (ieee80211_is_ctl(fc)) {
  90. switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
  91. case cpu_to_le16(IEEE80211_STYPE_BACK_REQ):
  92. stats->ctrl[CONTROL_BACK_REQ]++;
  93. break;
  94. case cpu_to_le16(IEEE80211_STYPE_BACK):
  95. stats->ctrl[CONTROL_BACK]++;
  96. break;
  97. case cpu_to_le16(IEEE80211_STYPE_PSPOLL):
  98. stats->ctrl[CONTROL_PSPOLL]++;
  99. break;
  100. case cpu_to_le16(IEEE80211_STYPE_RTS):
  101. stats->ctrl[CONTROL_RTS]++;
  102. break;
  103. case cpu_to_le16(IEEE80211_STYPE_CTS):
  104. stats->ctrl[CONTROL_CTS]++;
  105. break;
  106. case cpu_to_le16(IEEE80211_STYPE_ACK):
  107. stats->ctrl[CONTROL_ACK]++;
  108. break;
  109. case cpu_to_le16(IEEE80211_STYPE_CFEND):
  110. stats->ctrl[CONTROL_CFEND]++;
  111. break;
  112. case cpu_to_le16(IEEE80211_STYPE_CFENDACK):
  113. stats->ctrl[CONTROL_CFENDACK]++;
  114. break;
  115. }
  116. } else {
  117. /* data */
  118. stats->data_cnt++;
  119. stats->data_bytes += len;
  120. }
  121. }
  122. EXPORT_SYMBOL(il_update_stats);
  123. /* create and remove of files */
  124. #define DEBUGFS_ADD_FILE(name, parent, mode) do { \
  125. if (!debugfs_create_file(#name, mode, parent, il, \
  126. &il_dbgfs_##name##_ops)) \
  127. goto err; \
  128. } while (0)
  129. #define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \
  130. struct dentry *__tmp; \
  131. __tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \
  132. parent, ptr); \
  133. if (IS_ERR(__tmp) || !__tmp) \
  134. goto err; \
  135. } while (0)
  136. #define DEBUGFS_ADD_X32(name, parent, ptr) do { \
  137. struct dentry *__tmp; \
  138. __tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR, \
  139. parent, ptr); \
  140. if (IS_ERR(__tmp) || !__tmp) \
  141. goto err; \
  142. } while (0)
  143. /* file operation */
  144. #define DEBUGFS_READ_FUNC(name) \
  145. static ssize_t il_dbgfs_##name##_read(struct file *file, \
  146. char __user *user_buf, \
  147. size_t count, loff_t *ppos);
  148. #define DEBUGFS_WRITE_FUNC(name) \
  149. static ssize_t il_dbgfs_##name##_write(struct file *file, \
  150. const char __user *user_buf, \
  151. size_t count, loff_t *ppos);
  152. #define DEBUGFS_READ_FILE_OPS(name) \
  153. DEBUGFS_READ_FUNC(name); \
  154. static const struct file_operations il_dbgfs_##name##_ops = { \
  155. .read = il_dbgfs_##name##_read, \
  156. .open = simple_open, \
  157. .llseek = generic_file_llseek, \
  158. };
  159. #define DEBUGFS_WRITE_FILE_OPS(name) \
  160. DEBUGFS_WRITE_FUNC(name); \
  161. static const struct file_operations il_dbgfs_##name##_ops = { \
  162. .write = il_dbgfs_##name##_write, \
  163. .open = simple_open, \
  164. .llseek = generic_file_llseek, \
  165. };
  166. #define DEBUGFS_READ_WRITE_FILE_OPS(name) \
  167. DEBUGFS_READ_FUNC(name); \
  168. DEBUGFS_WRITE_FUNC(name); \
  169. static const struct file_operations il_dbgfs_##name##_ops = { \
  170. .write = il_dbgfs_##name##_write, \
  171. .read = il_dbgfs_##name##_read, \
  172. .open = simple_open, \
  173. .llseek = generic_file_llseek, \
  174. };
  175. static const char *
  176. il_get_mgmt_string(int cmd)
  177. {
  178. switch (cmd) {
  179. IL_CMD(MANAGEMENT_ASSOC_REQ);
  180. IL_CMD(MANAGEMENT_ASSOC_RESP);
  181. IL_CMD(MANAGEMENT_REASSOC_REQ);
  182. IL_CMD(MANAGEMENT_REASSOC_RESP);
  183. IL_CMD(MANAGEMENT_PROBE_REQ);
  184. IL_CMD(MANAGEMENT_PROBE_RESP);
  185. IL_CMD(MANAGEMENT_BEACON);
  186. IL_CMD(MANAGEMENT_ATIM);
  187. IL_CMD(MANAGEMENT_DISASSOC);
  188. IL_CMD(MANAGEMENT_AUTH);
  189. IL_CMD(MANAGEMENT_DEAUTH);
  190. IL_CMD(MANAGEMENT_ACTION);
  191. default:
  192. return "UNKNOWN";
  193. }
  194. }
  195. static const char *
  196. il_get_ctrl_string(int cmd)
  197. {
  198. switch (cmd) {
  199. IL_CMD(CONTROL_BACK_REQ);
  200. IL_CMD(CONTROL_BACK);
  201. IL_CMD(CONTROL_PSPOLL);
  202. IL_CMD(CONTROL_RTS);
  203. IL_CMD(CONTROL_CTS);
  204. IL_CMD(CONTROL_ACK);
  205. IL_CMD(CONTROL_CFEND);
  206. IL_CMD(CONTROL_CFENDACK);
  207. default:
  208. return "UNKNOWN";
  209. }
  210. }
  211. static ssize_t
  212. il_dbgfs_tx_stats_read(struct file *file, char __user *user_buf, size_t count,
  213. loff_t *ppos)
  214. {
  215. struct il_priv *il = file->private_data;
  216. char *buf;
  217. int pos = 0;
  218. int cnt;
  219. ssize_t ret;
  220. const size_t bufsz =
  221. 100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
  222. buf = kzalloc(bufsz, GFP_KERNEL);
  223. if (!buf)
  224. return -ENOMEM;
  225. pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
  226. for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
  227. pos +=
  228. scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
  229. il_get_mgmt_string(cnt), il->tx_stats.mgmt[cnt]);
  230. }
  231. pos += scnprintf(buf + pos, bufsz - pos, "Control\n");
  232. for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
  233. pos +=
  234. scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
  235. il_get_ctrl_string(cnt), il->tx_stats.ctrl[cnt]);
  236. }
  237. pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
  238. pos +=
  239. scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
  240. il->tx_stats.data_cnt);
  241. pos +=
  242. scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
  243. il->tx_stats.data_bytes);
  244. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  245. kfree(buf);
  246. return ret;
  247. }
  248. static ssize_t
  249. il_dbgfs_clear_traffic_stats_write(struct file *file,
  250. const char __user *user_buf, size_t count,
  251. loff_t *ppos)
  252. {
  253. struct il_priv *il = file->private_data;
  254. u32 clear_flag;
  255. char buf[8];
  256. int buf_size;
  257. memset(buf, 0, sizeof(buf));
  258. buf_size = min(count, sizeof(buf) - 1);
  259. if (copy_from_user(buf, user_buf, buf_size))
  260. return -EFAULT;
  261. if (sscanf(buf, "%x", &clear_flag) != 1)
  262. return -EFAULT;
  263. il_clear_traffic_stats(il);
  264. return count;
  265. }
  266. static ssize_t
  267. il_dbgfs_rx_stats_read(struct file *file, char __user *user_buf, size_t count,
  268. loff_t *ppos)
  269. {
  270. struct il_priv *il = file->private_data;
  271. char *buf;
  272. int pos = 0;
  273. int cnt;
  274. ssize_t ret;
  275. const size_t bufsz =
  276. 100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
  277. buf = kzalloc(bufsz, GFP_KERNEL);
  278. if (!buf)
  279. return -ENOMEM;
  280. pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
  281. for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
  282. pos +=
  283. scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
  284. il_get_mgmt_string(cnt), il->rx_stats.mgmt[cnt]);
  285. }
  286. pos += scnprintf(buf + pos, bufsz - pos, "Control:\n");
  287. for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
  288. pos +=
  289. scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
  290. il_get_ctrl_string(cnt), il->rx_stats.ctrl[cnt]);
  291. }
  292. pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
  293. pos +=
  294. scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
  295. il->rx_stats.data_cnt);
  296. pos +=
  297. scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
  298. il->rx_stats.data_bytes);
  299. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  300. kfree(buf);
  301. return ret;
  302. }
  303. #define BYTE1_MASK 0x000000ff;
  304. #define BYTE2_MASK 0x0000ffff;
  305. #define BYTE3_MASK 0x00ffffff;
  306. static ssize_t
  307. il_dbgfs_sram_read(struct file *file, char __user *user_buf, size_t count,
  308. loff_t *ppos)
  309. {
  310. u32 val;
  311. char *buf;
  312. ssize_t ret;
  313. int i;
  314. int pos = 0;
  315. struct il_priv *il = file->private_data;
  316. size_t bufsz;
  317. /* default is to dump the entire data segment */
  318. if (!il->dbgfs_sram_offset && !il->dbgfs_sram_len) {
  319. il->dbgfs_sram_offset = 0x800000;
  320. if (il->ucode_type == UCODE_INIT)
  321. il->dbgfs_sram_len = il->ucode_init_data.len;
  322. else
  323. il->dbgfs_sram_len = il->ucode_data.len;
  324. }
  325. bufsz = 30 + il->dbgfs_sram_len * sizeof(char) * 10;
  326. buf = kmalloc(bufsz, GFP_KERNEL);
  327. if (!buf)
  328. return -ENOMEM;
  329. pos +=
  330. scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n",
  331. il->dbgfs_sram_len);
  332. pos +=
  333. scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n",
  334. il->dbgfs_sram_offset);
  335. for (i = il->dbgfs_sram_len; i > 0; i -= 4) {
  336. val =
  337. il_read_targ_mem(il,
  338. il->dbgfs_sram_offset +
  339. il->dbgfs_sram_len - i);
  340. if (i < 4) {
  341. switch (i) {
  342. case 1:
  343. val &= BYTE1_MASK;
  344. break;
  345. case 2:
  346. val &= BYTE2_MASK;
  347. break;
  348. case 3:
  349. val &= BYTE3_MASK;
  350. break;
  351. }
  352. }
  353. if (!(i % 16))
  354. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  355. pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
  356. }
  357. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  358. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  359. kfree(buf);
  360. return ret;
  361. }
  362. static ssize_t
  363. il_dbgfs_sram_write(struct file *file, const char __user *user_buf,
  364. size_t count, loff_t *ppos)
  365. {
  366. struct il_priv *il = file->private_data;
  367. char buf[64];
  368. int buf_size;
  369. u32 offset, len;
  370. memset(buf, 0, sizeof(buf));
  371. buf_size = min(count, sizeof(buf) - 1);
  372. if (copy_from_user(buf, user_buf, buf_size))
  373. return -EFAULT;
  374. if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
  375. il->dbgfs_sram_offset = offset;
  376. il->dbgfs_sram_len = len;
  377. } else {
  378. il->dbgfs_sram_offset = 0;
  379. il->dbgfs_sram_len = 0;
  380. }
  381. return count;
  382. }
  383. static ssize_t
  384. il_dbgfs_stations_read(struct file *file, char __user *user_buf, size_t count,
  385. loff_t *ppos)
  386. {
  387. struct il_priv *il = file->private_data;
  388. struct il_station_entry *station;
  389. int max_sta = il->hw_params.max_stations;
  390. char *buf;
  391. int i, j, pos = 0;
  392. ssize_t ret;
  393. /* Add 30 for initial string */
  394. const size_t bufsz = 30 + sizeof(char) * 500 * (il->num_stations);
  395. buf = kmalloc(bufsz, GFP_KERNEL);
  396. if (!buf)
  397. return -ENOMEM;
  398. pos +=
  399. scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
  400. il->num_stations);
  401. for (i = 0; i < max_sta; i++) {
  402. station = &il->stations[i];
  403. if (!station->used)
  404. continue;
  405. pos +=
  406. scnprintf(buf + pos, bufsz - pos,
  407. "station %d - addr: %pM, flags: %#x\n", i,
  408. station->sta.sta.addr,
  409. station->sta.station_flags_msk);
  410. pos +=
  411. scnprintf(buf + pos, bufsz - pos,
  412. "TID\tseq_num\ttxq_id\tframes\ttfds\t");
  413. pos +=
  414. scnprintf(buf + pos, bufsz - pos,
  415. "start_idx\tbitmap\t\t\trate_n_flags\n");
  416. for (j = 0; j < MAX_TID_COUNT; j++) {
  417. pos +=
  418. scnprintf(buf + pos, bufsz - pos,
  419. "%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x",
  420. j, station->tid[j].seq_number,
  421. station->tid[j].agg.txq_id,
  422. station->tid[j].agg.frame_count,
  423. station->tid[j].tfds_in_queue,
  424. station->tid[j].agg.start_idx,
  425. station->tid[j].agg.bitmap,
  426. station->tid[j].agg.rate_n_flags);
  427. if (station->tid[j].agg.wait_for_ba)
  428. pos +=
  429. scnprintf(buf + pos, bufsz - pos,
  430. " - waitforba");
  431. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  432. }
  433. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  434. }
  435. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  436. kfree(buf);
  437. return ret;
  438. }
  439. static ssize_t
  440. il_dbgfs_nvm_read(struct file *file, char __user *user_buf, size_t count,
  441. loff_t *ppos)
  442. {
  443. ssize_t ret;
  444. struct il_priv *il = file->private_data;
  445. int pos = 0, ofs = 0, buf_size = 0;
  446. const u8 *ptr;
  447. char *buf;
  448. u16 eeprom_ver;
  449. size_t eeprom_len = il->cfg->eeprom_size;
  450. buf_size = 4 * eeprom_len + 256;
  451. if (eeprom_len % 16) {
  452. IL_ERR("NVM size is not multiple of 16.\n");
  453. return -ENODATA;
  454. }
  455. ptr = il->eeprom;
  456. if (!ptr) {
  457. IL_ERR("Invalid EEPROM memory\n");
  458. return -ENOMEM;
  459. }
  460. /* 4 characters for byte 0xYY */
  461. buf = kzalloc(buf_size, GFP_KERNEL);
  462. if (!buf) {
  463. IL_ERR("Can not allocate Buffer\n");
  464. return -ENOMEM;
  465. }
  466. eeprom_ver = il_eeprom_query16(il, EEPROM_VERSION);
  467. pos +=
  468. scnprintf(buf + pos, buf_size - pos, "EEPROM " "version: 0x%x\n",
  469. eeprom_ver);
  470. for (ofs = 0; ofs < eeprom_len; ofs += 16) {
  471. pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x %16ph\n",
  472. ofs, ptr + ofs);
  473. }
  474. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  475. kfree(buf);
  476. return ret;
  477. }
  478. static ssize_t
  479. il_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count,
  480. loff_t *ppos)
  481. {
  482. struct il_priv *il = file->private_data;
  483. struct ieee80211_channel *channels = NULL;
  484. const struct ieee80211_supported_band *supp_band = NULL;
  485. int pos = 0, i, bufsz = PAGE_SIZE;
  486. char *buf;
  487. ssize_t ret;
  488. if (!test_bit(S_GEO_CONFIGURED, &il->status))
  489. return -EAGAIN;
  490. buf = kzalloc(bufsz, GFP_KERNEL);
  491. if (!buf) {
  492. IL_ERR("Can not allocate Buffer\n");
  493. return -ENOMEM;
  494. }
  495. supp_band = il_get_hw_mode(il, IEEE80211_BAND_2GHZ);
  496. if (supp_band) {
  497. channels = supp_band->channels;
  498. pos +=
  499. scnprintf(buf + pos, bufsz - pos,
  500. "Displaying %d channels in 2.4GHz band 802.11bg):\n",
  501. supp_band->n_channels);
  502. for (i = 0; i < supp_band->n_channels; i++)
  503. pos +=
  504. scnprintf(buf + pos, bufsz - pos,
  505. "%d: %ddBm: BSS%s%s, %s.\n",
  506. channels[i].hw_value,
  507. channels[i].max_power,
  508. channels[i].
  509. flags & IEEE80211_CHAN_RADAR ?
  510. " (IEEE 802.11h required)" : "",
  511. ((channels[i].
  512. flags & IEEE80211_CHAN_NO_IR) ||
  513. (channels[i].
  514. flags & IEEE80211_CHAN_RADAR)) ? "" :
  515. ", IBSS",
  516. channels[i].
  517. flags & IEEE80211_CHAN_NO_IR ?
  518. "passive only" : "active/passive");
  519. }
  520. supp_band = il_get_hw_mode(il, IEEE80211_BAND_5GHZ);
  521. if (supp_band) {
  522. channels = supp_band->channels;
  523. pos +=
  524. scnprintf(buf + pos, bufsz - pos,
  525. "Displaying %d channels in 5.2GHz band (802.11a)\n",
  526. supp_band->n_channels);
  527. for (i = 0; i < supp_band->n_channels; i++)
  528. pos +=
  529. scnprintf(buf + pos, bufsz - pos,
  530. "%d: %ddBm: BSS%s%s, %s.\n",
  531. channels[i].hw_value,
  532. channels[i].max_power,
  533. channels[i].
  534. flags & IEEE80211_CHAN_RADAR ?
  535. " (IEEE 802.11h required)" : "",
  536. ((channels[i].
  537. flags & IEEE80211_CHAN_NO_IR) ||
  538. (channels[i].
  539. flags & IEEE80211_CHAN_RADAR)) ? "" :
  540. ", IBSS",
  541. channels[i].
  542. flags & IEEE80211_CHAN_NO_IR ?
  543. "passive only" : "active/passive");
  544. }
  545. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  546. kfree(buf);
  547. return ret;
  548. }
  549. static ssize_t
  550. il_dbgfs_status_read(struct file *file, char __user *user_buf, size_t count,
  551. loff_t *ppos)
  552. {
  553. struct il_priv *il = file->private_data;
  554. char buf[512];
  555. int pos = 0;
  556. const size_t bufsz = sizeof(buf);
  557. pos +=
  558. scnprintf(buf + pos, bufsz - pos, "S_HCMD_ACTIVE:\t %d\n",
  559. test_bit(S_HCMD_ACTIVE, &il->status));
  560. pos +=
  561. scnprintf(buf + pos, bufsz - pos, "S_INT_ENABLED:\t %d\n",
  562. test_bit(S_INT_ENABLED, &il->status));
  563. pos +=
  564. scnprintf(buf + pos, bufsz - pos, "S_RFKILL:\t %d\n",
  565. test_bit(S_RFKILL, &il->status));
  566. pos +=
  567. scnprintf(buf + pos, bufsz - pos, "S_CT_KILL:\t\t %d\n",
  568. test_bit(S_CT_KILL, &il->status));
  569. pos +=
  570. scnprintf(buf + pos, bufsz - pos, "S_INIT:\t\t %d\n",
  571. test_bit(S_INIT, &il->status));
  572. pos +=
  573. scnprintf(buf + pos, bufsz - pos, "S_ALIVE:\t\t %d\n",
  574. test_bit(S_ALIVE, &il->status));
  575. pos +=
  576. scnprintf(buf + pos, bufsz - pos, "S_READY:\t\t %d\n",
  577. test_bit(S_READY, &il->status));
  578. pos +=
  579. scnprintf(buf + pos, bufsz - pos, "S_TEMPERATURE:\t %d\n",
  580. test_bit(S_TEMPERATURE, &il->status));
  581. pos +=
  582. scnprintf(buf + pos, bufsz - pos, "S_GEO_CONFIGURED:\t %d\n",
  583. test_bit(S_GEO_CONFIGURED, &il->status));
  584. pos +=
  585. scnprintf(buf + pos, bufsz - pos, "S_EXIT_PENDING:\t %d\n",
  586. test_bit(S_EXIT_PENDING, &il->status));
  587. pos +=
  588. scnprintf(buf + pos, bufsz - pos, "S_STATS:\t %d\n",
  589. test_bit(S_STATS, &il->status));
  590. pos +=
  591. scnprintf(buf + pos, bufsz - pos, "S_SCANNING:\t %d\n",
  592. test_bit(S_SCANNING, &il->status));
  593. pos +=
  594. scnprintf(buf + pos, bufsz - pos, "S_SCAN_ABORTING:\t %d\n",
  595. test_bit(S_SCAN_ABORTING, &il->status));
  596. pos +=
  597. scnprintf(buf + pos, bufsz - pos, "S_SCAN_HW:\t\t %d\n",
  598. test_bit(S_SCAN_HW, &il->status));
  599. pos +=
  600. scnprintf(buf + pos, bufsz - pos, "S_POWER_PMI:\t %d\n",
  601. test_bit(S_POWER_PMI, &il->status));
  602. pos +=
  603. scnprintf(buf + pos, bufsz - pos, "S_FW_ERROR:\t %d\n",
  604. test_bit(S_FW_ERROR, &il->status));
  605. return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  606. }
  607. static ssize_t
  608. il_dbgfs_interrupt_read(struct file *file, char __user *user_buf, size_t count,
  609. loff_t *ppos)
  610. {
  611. struct il_priv *il = file->private_data;
  612. int pos = 0;
  613. int cnt = 0;
  614. char *buf;
  615. int bufsz = 24 * 64; /* 24 items * 64 char per item */
  616. ssize_t ret;
  617. buf = kzalloc(bufsz, GFP_KERNEL);
  618. if (!buf) {
  619. IL_ERR("Can not allocate Buffer\n");
  620. return -ENOMEM;
  621. }
  622. pos +=
  623. scnprintf(buf + pos, bufsz - pos, "Interrupt Statistics Report:\n");
  624. pos +=
  625. scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
  626. il->isr_stats.hw);
  627. pos +=
  628. scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
  629. il->isr_stats.sw);
  630. if (il->isr_stats.sw || il->isr_stats.hw) {
  631. pos +=
  632. scnprintf(buf + pos, bufsz - pos,
  633. "\tLast Restarting Code: 0x%X\n",
  634. il->isr_stats.err_code);
  635. }
  636. #ifdef CONFIG_IWLEGACY_DEBUG
  637. pos +=
  638. scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
  639. il->isr_stats.sch);
  640. pos +=
  641. scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
  642. il->isr_stats.alive);
  643. #endif
  644. pos +=
  645. scnprintf(buf + pos, bufsz - pos,
  646. "HW RF KILL switch toggled:\t %u\n",
  647. il->isr_stats.rfkill);
  648. pos +=
  649. scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
  650. il->isr_stats.ctkill);
  651. pos +=
  652. scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
  653. il->isr_stats.wakeup);
  654. pos +=
  655. scnprintf(buf + pos, bufsz - pos, "Rx command responses:\t\t %u\n",
  656. il->isr_stats.rx);
  657. for (cnt = 0; cnt < IL_CN_MAX; cnt++) {
  658. if (il->isr_stats.handlers[cnt] > 0)
  659. pos +=
  660. scnprintf(buf + pos, bufsz - pos,
  661. "\tRx handler[%36s]:\t\t %u\n",
  662. il_get_cmd_string(cnt),
  663. il->isr_stats.handlers[cnt]);
  664. }
  665. pos +=
  666. scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
  667. il->isr_stats.tx);
  668. pos +=
  669. scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
  670. il->isr_stats.unhandled);
  671. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  672. kfree(buf);
  673. return ret;
  674. }
  675. static ssize_t
  676. il_dbgfs_interrupt_write(struct file *file, const char __user *user_buf,
  677. size_t count, loff_t *ppos)
  678. {
  679. struct il_priv *il = file->private_data;
  680. char buf[8];
  681. int buf_size;
  682. u32 reset_flag;
  683. memset(buf, 0, sizeof(buf));
  684. buf_size = min(count, sizeof(buf) - 1);
  685. if (copy_from_user(buf, user_buf, buf_size))
  686. return -EFAULT;
  687. if (sscanf(buf, "%x", &reset_flag) != 1)
  688. return -EFAULT;
  689. if (reset_flag == 0)
  690. il_clear_isr_stats(il);
  691. return count;
  692. }
  693. static ssize_t
  694. il_dbgfs_qos_read(struct file *file, char __user *user_buf, size_t count,
  695. loff_t *ppos)
  696. {
  697. struct il_priv *il = file->private_data;
  698. int pos = 0, i;
  699. char buf[256];
  700. const size_t bufsz = sizeof(buf);
  701. for (i = 0; i < AC_NUM; i++) {
  702. pos +=
  703. scnprintf(buf + pos, bufsz - pos,
  704. "\tcw_min\tcw_max\taifsn\ttxop\n");
  705. pos +=
  706. scnprintf(buf + pos, bufsz - pos,
  707. "AC[%d]\t%u\t%u\t%u\t%u\n", i,
  708. il->qos_data.def_qos_parm.ac[i].cw_min,
  709. il->qos_data.def_qos_parm.ac[i].cw_max,
  710. il->qos_data.def_qos_parm.ac[i].aifsn,
  711. il->qos_data.def_qos_parm.ac[i].edca_txop);
  712. }
  713. return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  714. }
  715. static ssize_t
  716. il_dbgfs_disable_ht40_write(struct file *file, const char __user *user_buf,
  717. size_t count, loff_t *ppos)
  718. {
  719. struct il_priv *il = file->private_data;
  720. char buf[8];
  721. int buf_size;
  722. int ht40;
  723. memset(buf, 0, sizeof(buf));
  724. buf_size = min(count, sizeof(buf) - 1);
  725. if (copy_from_user(buf, user_buf, buf_size))
  726. return -EFAULT;
  727. if (sscanf(buf, "%d", &ht40) != 1)
  728. return -EFAULT;
  729. if (!il_is_any_associated(il))
  730. il->disable_ht40 = ht40 ? true : false;
  731. else {
  732. IL_ERR("Sta associated with AP - "
  733. "Change to 40MHz channel support is not allowed\n");
  734. return -EINVAL;
  735. }
  736. return count;
  737. }
  738. static ssize_t
  739. il_dbgfs_disable_ht40_read(struct file *file, char __user *user_buf,
  740. size_t count, loff_t *ppos)
  741. {
  742. struct il_priv *il = file->private_data;
  743. char buf[100];
  744. int pos = 0;
  745. const size_t bufsz = sizeof(buf);
  746. pos +=
  747. scnprintf(buf + pos, bufsz - pos, "11n 40MHz Mode: %s\n",
  748. il->disable_ht40 ? "Disabled" : "Enabled");
  749. return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  750. }
  751. DEBUGFS_READ_WRITE_FILE_OPS(sram);
  752. DEBUGFS_READ_FILE_OPS(nvm);
  753. DEBUGFS_READ_FILE_OPS(stations);
  754. DEBUGFS_READ_FILE_OPS(channels);
  755. DEBUGFS_READ_FILE_OPS(status);
  756. DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
  757. DEBUGFS_READ_FILE_OPS(qos);
  758. DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
  759. static ssize_t
  760. il_dbgfs_tx_queue_read(struct file *file, char __user *user_buf, size_t count,
  761. loff_t *ppos)
  762. {
  763. struct il_priv *il = file->private_data;
  764. struct il_tx_queue *txq;
  765. struct il_queue *q;
  766. char *buf;
  767. int pos = 0;
  768. int cnt;
  769. int ret;
  770. const size_t bufsz =
  771. sizeof(char) * 64 * il->cfg->num_of_queues;
  772. if (!il->txq) {
  773. IL_ERR("txq not ready\n");
  774. return -EAGAIN;
  775. }
  776. buf = kzalloc(bufsz, GFP_KERNEL);
  777. if (!buf)
  778. return -ENOMEM;
  779. for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) {
  780. txq = &il->txq[cnt];
  781. q = &txq->q;
  782. pos +=
  783. scnprintf(buf + pos, bufsz - pos,
  784. "hwq %.2d: read=%u write=%u stop=%d"
  785. " swq_id=%#.2x (ac %d/hwq %d)\n", cnt,
  786. q->read_ptr, q->write_ptr,
  787. !!test_bit(cnt, il->queue_stopped),
  788. txq->swq_id, txq->swq_id & 3,
  789. (txq->swq_id >> 2) & 0x1f);
  790. if (cnt >= 4)
  791. continue;
  792. /* for the ACs, display the stop count too */
  793. pos +=
  794. scnprintf(buf + pos, bufsz - pos,
  795. " stop-count: %d\n",
  796. atomic_read(&il->queue_stop_count[cnt]));
  797. }
  798. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  799. kfree(buf);
  800. return ret;
  801. }
  802. static ssize_t
  803. il_dbgfs_rx_queue_read(struct file *file, char __user *user_buf, size_t count,
  804. loff_t *ppos)
  805. {
  806. struct il_priv *il = file->private_data;
  807. struct il_rx_queue *rxq = &il->rxq;
  808. char buf[256];
  809. int pos = 0;
  810. const size_t bufsz = sizeof(buf);
  811. pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", rxq->read);
  812. pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", rxq->write);
  813. pos +=
  814. scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
  815. rxq->free_count);
  816. if (rxq->rb_stts) {
  817. pos +=
  818. scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
  819. le16_to_cpu(rxq->rb_stts->
  820. closed_rb_num) & 0x0FFF);
  821. } else {
  822. pos +=
  823. scnprintf(buf + pos, bufsz - pos,
  824. "closed_rb_num: Not Allocated\n");
  825. }
  826. return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  827. }
  828. static ssize_t
  829. il_dbgfs_ucode_rx_stats_read(struct file *file, char __user *user_buf,
  830. size_t count, loff_t *ppos)
  831. {
  832. struct il_priv *il = file->private_data;
  833. return il->debugfs_ops->rx_stats_read(file, user_buf, count, ppos);
  834. }
  835. static ssize_t
  836. il_dbgfs_ucode_tx_stats_read(struct file *file, char __user *user_buf,
  837. size_t count, loff_t *ppos)
  838. {
  839. struct il_priv *il = file->private_data;
  840. return il->debugfs_ops->tx_stats_read(file, user_buf, count, ppos);
  841. }
  842. static ssize_t
  843. il_dbgfs_ucode_general_stats_read(struct file *file, char __user *user_buf,
  844. size_t count, loff_t *ppos)
  845. {
  846. struct il_priv *il = file->private_data;
  847. return il->debugfs_ops->general_stats_read(file, user_buf, count, ppos);
  848. }
  849. static ssize_t
  850. il_dbgfs_sensitivity_read(struct file *file, char __user *user_buf,
  851. size_t count, loff_t *ppos)
  852. {
  853. struct il_priv *il = file->private_data;
  854. int pos = 0;
  855. int cnt = 0;
  856. char *buf;
  857. int bufsz = sizeof(struct il_sensitivity_data) * 4 + 100;
  858. ssize_t ret;
  859. struct il_sensitivity_data *data;
  860. data = &il->sensitivity_data;
  861. buf = kzalloc(bufsz, GFP_KERNEL);
  862. if (!buf) {
  863. IL_ERR("Can not allocate Buffer\n");
  864. return -ENOMEM;
  865. }
  866. pos +=
  867. scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
  868. data->auto_corr_ofdm);
  869. pos +=
  870. scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc:\t\t %u\n",
  871. data->auto_corr_ofdm_mrc);
  872. pos +=
  873. scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
  874. data->auto_corr_ofdm_x1);
  875. pos +=
  876. scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc_x1:\t\t %u\n",
  877. data->auto_corr_ofdm_mrc_x1);
  878. pos +=
  879. scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
  880. data->auto_corr_cck);
  881. pos +=
  882. scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
  883. data->auto_corr_cck_mrc);
  884. pos +=
  885. scnprintf(buf + pos, bufsz - pos,
  886. "last_bad_plcp_cnt_ofdm:\t\t %u\n",
  887. data->last_bad_plcp_cnt_ofdm);
  888. pos +=
  889. scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
  890. data->last_fa_cnt_ofdm);
  891. pos +=
  892. scnprintf(buf + pos, bufsz - pos, "last_bad_plcp_cnt_cck:\t\t %u\n",
  893. data->last_bad_plcp_cnt_cck);
  894. pos +=
  895. scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
  896. data->last_fa_cnt_cck);
  897. pos +=
  898. scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
  899. data->nrg_curr_state);
  900. pos +=
  901. scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
  902. data->nrg_prev_state);
  903. pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
  904. for (cnt = 0; cnt < 10; cnt++) {
  905. pos +=
  906. scnprintf(buf + pos, bufsz - pos, " %u",
  907. data->nrg_value[cnt]);
  908. }
  909. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  910. pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
  911. for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
  912. pos +=
  913. scnprintf(buf + pos, bufsz - pos, " %u",
  914. data->nrg_silence_rssi[cnt]);
  915. }
  916. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  917. pos +=
  918. scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
  919. data->nrg_silence_ref);
  920. pos +=
  921. scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
  922. data->nrg_energy_idx);
  923. pos +=
  924. scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
  925. data->nrg_silence_idx);
  926. pos +=
  927. scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
  928. data->nrg_th_cck);
  929. pos +=
  930. scnprintf(buf + pos, bufsz - pos,
  931. "nrg_auto_corr_silence_diff:\t %u\n",
  932. data->nrg_auto_corr_silence_diff);
  933. pos +=
  934. scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
  935. data->num_in_cck_no_fa);
  936. pos +=
  937. scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
  938. data->nrg_th_ofdm);
  939. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  940. kfree(buf);
  941. return ret;
  942. }
  943. static ssize_t
  944. il_dbgfs_chain_noise_read(struct file *file, char __user *user_buf,
  945. size_t count, loff_t *ppos)
  946. {
  947. struct il_priv *il = file->private_data;
  948. int pos = 0;
  949. int cnt = 0;
  950. char *buf;
  951. int bufsz = sizeof(struct il_chain_noise_data) * 4 + 100;
  952. ssize_t ret;
  953. struct il_chain_noise_data *data;
  954. data = &il->chain_noise_data;
  955. buf = kzalloc(bufsz, GFP_KERNEL);
  956. if (!buf) {
  957. IL_ERR("Can not allocate Buffer\n");
  958. return -ENOMEM;
  959. }
  960. pos +=
  961. scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
  962. data->active_chains);
  963. pos +=
  964. scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
  965. data->chain_noise_a);
  966. pos +=
  967. scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
  968. data->chain_noise_b);
  969. pos +=
  970. scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
  971. data->chain_noise_c);
  972. pos +=
  973. scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
  974. data->chain_signal_a);
  975. pos +=
  976. scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
  977. data->chain_signal_b);
  978. pos +=
  979. scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
  980. data->chain_signal_c);
  981. pos +=
  982. scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
  983. data->beacon_count);
  984. pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
  985. for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
  986. pos +=
  987. scnprintf(buf + pos, bufsz - pos, " %u",
  988. data->disconn_array[cnt]);
  989. }
  990. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  991. pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
  992. for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
  993. pos +=
  994. scnprintf(buf + pos, bufsz - pos, " %u",
  995. data->delta_gain_code[cnt]);
  996. }
  997. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  998. pos +=
  999. scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
  1000. data->radio_write);
  1001. pos +=
  1002. scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
  1003. data->state);
  1004. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  1005. kfree(buf);
  1006. return ret;
  1007. }
  1008. static ssize_t
  1009. il_dbgfs_power_save_status_read(struct file *file, char __user *user_buf,
  1010. size_t count, loff_t *ppos)
  1011. {
  1012. struct il_priv *il = file->private_data;
  1013. char buf[60];
  1014. int pos = 0;
  1015. const size_t bufsz = sizeof(buf);
  1016. u32 pwrsave_status;
  1017. pwrsave_status =
  1018. _il_rd(il, CSR_GP_CNTRL) & CSR_GP_REG_POWER_SAVE_STATUS_MSK;
  1019. pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: ");
  1020. pos +=
  1021. scnprintf(buf + pos, bufsz - pos, "%s\n",
  1022. (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" :
  1023. (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" :
  1024. (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" :
  1025. "error");
  1026. return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  1027. }
  1028. static ssize_t
  1029. il_dbgfs_clear_ucode_stats_write(struct file *file,
  1030. const char __user *user_buf, size_t count,
  1031. loff_t *ppos)
  1032. {
  1033. struct il_priv *il = file->private_data;
  1034. char buf[8];
  1035. int buf_size;
  1036. int clear;
  1037. memset(buf, 0, sizeof(buf));
  1038. buf_size = min(count, sizeof(buf) - 1);
  1039. if (copy_from_user(buf, user_buf, buf_size))
  1040. return -EFAULT;
  1041. if (sscanf(buf, "%d", &clear) != 1)
  1042. return -EFAULT;
  1043. /* make request to uCode to retrieve stats information */
  1044. mutex_lock(&il->mutex);
  1045. il_send_stats_request(il, CMD_SYNC, true);
  1046. mutex_unlock(&il->mutex);
  1047. return count;
  1048. }
  1049. static ssize_t
  1050. il_dbgfs_rxon_flags_read(struct file *file, char __user *user_buf,
  1051. size_t count, loff_t *ppos)
  1052. {
  1053. struct il_priv *il = file->private_data;
  1054. int len = 0;
  1055. char buf[20];
  1056. len = sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.flags));
  1057. return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  1058. }
  1059. static ssize_t
  1060. il_dbgfs_rxon_filter_flags_read(struct file *file, char __user *user_buf,
  1061. size_t count, loff_t *ppos)
  1062. {
  1063. struct il_priv *il = file->private_data;
  1064. int len = 0;
  1065. char buf[20];
  1066. len =
  1067. sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.filter_flags));
  1068. return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  1069. }
  1070. static ssize_t
  1071. il_dbgfs_fh_reg_read(struct file *file, char __user *user_buf, size_t count,
  1072. loff_t *ppos)
  1073. {
  1074. struct il_priv *il = file->private_data;
  1075. char *buf;
  1076. int pos = 0;
  1077. ssize_t ret = -EFAULT;
  1078. if (il->ops->dump_fh) {
  1079. ret = pos = il->ops->dump_fh(il, &buf, true);
  1080. if (buf) {
  1081. ret =
  1082. simple_read_from_buffer(user_buf, count, ppos, buf,
  1083. pos);
  1084. kfree(buf);
  1085. }
  1086. }
  1087. return ret;
  1088. }
  1089. static ssize_t
  1090. il_dbgfs_missed_beacon_read(struct file *file, char __user *user_buf,
  1091. size_t count, loff_t *ppos)
  1092. {
  1093. struct il_priv *il = file->private_data;
  1094. int pos = 0;
  1095. char buf[12];
  1096. const size_t bufsz = sizeof(buf);
  1097. pos +=
  1098. scnprintf(buf + pos, bufsz - pos, "%d\n",
  1099. il->missed_beacon_threshold);
  1100. return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  1101. }
  1102. static ssize_t
  1103. il_dbgfs_missed_beacon_write(struct file *file, const char __user *user_buf,
  1104. size_t count, loff_t *ppos)
  1105. {
  1106. struct il_priv *il = file->private_data;
  1107. char buf[8];
  1108. int buf_size;
  1109. int missed;
  1110. memset(buf, 0, sizeof(buf));
  1111. buf_size = min(count, sizeof(buf) - 1);
  1112. if (copy_from_user(buf, user_buf, buf_size))
  1113. return -EFAULT;
  1114. if (sscanf(buf, "%d", &missed) != 1)
  1115. return -EINVAL;
  1116. if (missed < IL_MISSED_BEACON_THRESHOLD_MIN ||
  1117. missed > IL_MISSED_BEACON_THRESHOLD_MAX)
  1118. il->missed_beacon_threshold = IL_MISSED_BEACON_THRESHOLD_DEF;
  1119. else
  1120. il->missed_beacon_threshold = missed;
  1121. return count;
  1122. }
  1123. static ssize_t
  1124. il_dbgfs_force_reset_read(struct file *file, char __user *user_buf,
  1125. size_t count, loff_t *ppos)
  1126. {
  1127. struct il_priv *il = file->private_data;
  1128. int pos = 0;
  1129. char buf[300];
  1130. const size_t bufsz = sizeof(buf);
  1131. struct il_force_reset *force_reset;
  1132. force_reset = &il->force_reset;
  1133. pos +=
  1134. scnprintf(buf + pos, bufsz - pos, "\tnumber of reset request: %d\n",
  1135. force_reset->reset_request_count);
  1136. pos +=
  1137. scnprintf(buf + pos, bufsz - pos,
  1138. "\tnumber of reset request success: %d\n",
  1139. force_reset->reset_success_count);
  1140. pos +=
  1141. scnprintf(buf + pos, bufsz - pos,
  1142. "\tnumber of reset request reject: %d\n",
  1143. force_reset->reset_reject_count);
  1144. pos +=
  1145. scnprintf(buf + pos, bufsz - pos, "\treset duration: %lu\n",
  1146. force_reset->reset_duration);
  1147. return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  1148. }
  1149. static ssize_t
  1150. il_dbgfs_force_reset_write(struct file *file, const char __user *user_buf,
  1151. size_t count, loff_t *ppos)
  1152. {
  1153. int ret;
  1154. struct il_priv *il = file->private_data;
  1155. ret = il_force_reset(il, true);
  1156. return ret ? ret : count;
  1157. }
  1158. static ssize_t
  1159. il_dbgfs_wd_timeout_write(struct file *file, const char __user *user_buf,
  1160. size_t count, loff_t *ppos)
  1161. {
  1162. struct il_priv *il = file->private_data;
  1163. char buf[8];
  1164. int buf_size;
  1165. int timeout;
  1166. memset(buf, 0, sizeof(buf));
  1167. buf_size = min(count, sizeof(buf) - 1);
  1168. if (copy_from_user(buf, user_buf, buf_size))
  1169. return -EFAULT;
  1170. if (sscanf(buf, "%d", &timeout) != 1)
  1171. return -EINVAL;
  1172. if (timeout < 0 || timeout > IL_MAX_WD_TIMEOUT)
  1173. timeout = IL_DEF_WD_TIMEOUT;
  1174. il->cfg->wd_timeout = timeout;
  1175. il_setup_watchdog(il);
  1176. return count;
  1177. }
  1178. DEBUGFS_READ_FILE_OPS(rx_stats);
  1179. DEBUGFS_READ_FILE_OPS(tx_stats);
  1180. DEBUGFS_READ_FILE_OPS(rx_queue);
  1181. DEBUGFS_READ_FILE_OPS(tx_queue);
  1182. DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
  1183. DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
  1184. DEBUGFS_READ_FILE_OPS(ucode_general_stats);
  1185. DEBUGFS_READ_FILE_OPS(sensitivity);
  1186. DEBUGFS_READ_FILE_OPS(chain_noise);
  1187. DEBUGFS_READ_FILE_OPS(power_save_status);
  1188. DEBUGFS_WRITE_FILE_OPS(clear_ucode_stats);
  1189. DEBUGFS_WRITE_FILE_OPS(clear_traffic_stats);
  1190. DEBUGFS_READ_FILE_OPS(fh_reg);
  1191. DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
  1192. DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
  1193. DEBUGFS_READ_FILE_OPS(rxon_flags);
  1194. DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
  1195. DEBUGFS_WRITE_FILE_OPS(wd_timeout);
  1196. /*
  1197. * Create the debugfs files and directories
  1198. *
  1199. */
  1200. int
  1201. il_dbgfs_register(struct il_priv *il, const char *name)
  1202. {
  1203. struct dentry *phyd = il->hw->wiphy->debugfsdir;
  1204. struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug;
  1205. dir_drv = debugfs_create_dir(name, phyd);
  1206. if (!dir_drv)
  1207. return -ENOMEM;
  1208. il->debugfs_dir = dir_drv;
  1209. dir_data = debugfs_create_dir("data", dir_drv);
  1210. if (!dir_data)
  1211. goto err;
  1212. dir_rf = debugfs_create_dir("rf", dir_drv);
  1213. if (!dir_rf)
  1214. goto err;
  1215. dir_debug = debugfs_create_dir("debug", dir_drv);
  1216. if (!dir_debug)
  1217. goto err;
  1218. DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR);
  1219. DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR);
  1220. DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
  1221. DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
  1222. DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
  1223. DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);
  1224. DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
  1225. DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR);
  1226. DEBUGFS_ADD_FILE(rx_stats, dir_debug, S_IRUSR);
  1227. DEBUGFS_ADD_FILE(tx_stats, dir_debug, S_IRUSR);
  1228. DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR);
  1229. DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR);
  1230. DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR);
  1231. DEBUGFS_ADD_FILE(clear_ucode_stats, dir_debug, S_IWUSR);
  1232. DEBUGFS_ADD_FILE(clear_traffic_stats, dir_debug, S_IWUSR);
  1233. DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR);
  1234. DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
  1235. DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR);
  1236. DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
  1237. DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
  1238. DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
  1239. if (il->cfg->sensitivity_calib_by_driver)
  1240. DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
  1241. if (il->cfg->chain_noise_calib_by_driver)
  1242. DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
  1243. DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
  1244. DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
  1245. DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
  1246. if (il->cfg->sensitivity_calib_by_driver)
  1247. DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
  1248. &il->disable_sens_cal);
  1249. if (il->cfg->chain_noise_calib_by_driver)
  1250. DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
  1251. &il->disable_chain_noise_cal);
  1252. DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, &il->disable_tx_power_cal);
  1253. return 0;
  1254. err:
  1255. IL_ERR("Can't create the debugfs directory\n");
  1256. il_dbgfs_unregister(il);
  1257. return -ENOMEM;
  1258. }
  1259. EXPORT_SYMBOL(il_dbgfs_register);
  1260. /**
  1261. * Remove the debugfs files and directories
  1262. *
  1263. */
  1264. void
  1265. il_dbgfs_unregister(struct il_priv *il)
  1266. {
  1267. if (!il->debugfs_dir)
  1268. return;
  1269. debugfs_remove_recursive(il->debugfs_dir);
  1270. il->debugfs_dir = NULL;
  1271. }
  1272. EXPORT_SYMBOL(il_dbgfs_unregister);