debug.c 37 KB

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