iwl-debugfs.c 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621
  1. /******************************************************************************
  2. *
  3. * GPL LICENSE SUMMARY
  4. *
  5. * Copyright(c) 2008 - 2009 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/kernel.h>
  29. #include <linux/module.h>
  30. #include <linux/debugfs.h>
  31. #include <linux/ieee80211.h>
  32. #include <net/mac80211.h>
  33. #include "iwl-dev.h"
  34. #include "iwl-debug.h"
  35. #include "iwl-core.h"
  36. #include "iwl-io.h"
  37. #include "iwl-calib.h"
  38. /* create and remove of files */
  39. #define DEBUGFS_ADD_DIR(name, parent) do { \
  40. dbgfs->dir_##name = debugfs_create_dir(#name, parent); \
  41. if (!(dbgfs->dir_##name)) \
  42. goto err; \
  43. } while (0)
  44. #define DEBUGFS_ADD_FILE(name, parent) do { \
  45. dbgfs->dbgfs_##parent##_files.file_##name = \
  46. debugfs_create_file(#name, S_IWUSR | S_IRUSR, \
  47. dbgfs->dir_##parent, priv, \
  48. &iwl_dbgfs_##name##_ops); \
  49. if (!(dbgfs->dbgfs_##parent##_files.file_##name)) \
  50. goto err; \
  51. } while (0)
  52. #define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \
  53. dbgfs->dbgfs_##parent##_files.file_##name = \
  54. debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \
  55. dbgfs->dir_##parent, ptr); \
  56. if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \
  57. || !dbgfs->dbgfs_##parent##_files.file_##name) \
  58. goto err; \
  59. } while (0)
  60. #define DEBUGFS_ADD_X32(name, parent, ptr) do { \
  61. dbgfs->dbgfs_##parent##_files.file_##name = \
  62. debugfs_create_x32(#name, S_IRUSR, dbgfs->dir_##parent, ptr); \
  63. if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \
  64. || !dbgfs->dbgfs_##parent##_files.file_##name) \
  65. goto err; \
  66. } while (0)
  67. #define DEBUGFS_REMOVE(name) do { \
  68. debugfs_remove(name); \
  69. name = NULL; \
  70. } while (0);
  71. /* file operation */
  72. #define DEBUGFS_READ_FUNC(name) \
  73. static ssize_t iwl_dbgfs_##name##_read(struct file *file, \
  74. char __user *user_buf, \
  75. size_t count, loff_t *ppos);
  76. #define DEBUGFS_WRITE_FUNC(name) \
  77. static ssize_t iwl_dbgfs_##name##_write(struct file *file, \
  78. const char __user *user_buf, \
  79. size_t count, loff_t *ppos);
  80. static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file)
  81. {
  82. file->private_data = inode->i_private;
  83. return 0;
  84. }
  85. #define DEBUGFS_READ_FILE_OPS(name) \
  86. DEBUGFS_READ_FUNC(name); \
  87. static const struct file_operations iwl_dbgfs_##name##_ops = { \
  88. .read = iwl_dbgfs_##name##_read, \
  89. .open = iwl_dbgfs_open_file_generic, \
  90. };
  91. #define DEBUGFS_WRITE_FILE_OPS(name) \
  92. DEBUGFS_WRITE_FUNC(name); \
  93. static const struct file_operations iwl_dbgfs_##name##_ops = { \
  94. .write = iwl_dbgfs_##name##_write, \
  95. .open = iwl_dbgfs_open_file_generic, \
  96. };
  97. #define DEBUGFS_READ_WRITE_FILE_OPS(name) \
  98. DEBUGFS_READ_FUNC(name); \
  99. DEBUGFS_WRITE_FUNC(name); \
  100. static const struct file_operations iwl_dbgfs_##name##_ops = { \
  101. .write = iwl_dbgfs_##name##_write, \
  102. .read = iwl_dbgfs_##name##_read, \
  103. .open = iwl_dbgfs_open_file_generic, \
  104. };
  105. static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file,
  106. char __user *user_buf,
  107. size_t count, loff_t *ppos) {
  108. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  109. char *buf;
  110. int pos = 0;
  111. int cnt;
  112. ssize_t ret;
  113. const size_t bufsz = 100 + sizeof(char) * 24 * (MANAGEMENT_MAX + CONTROL_MAX);
  114. buf = kzalloc(bufsz, GFP_KERNEL);
  115. if (!buf)
  116. return -ENOMEM;
  117. pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
  118. for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
  119. pos += scnprintf(buf + pos, bufsz - pos,
  120. "\t%s\t\t: %u\n",
  121. get_mgmt_string(cnt),
  122. priv->tx_stats.mgmt[cnt]);
  123. }
  124. pos += scnprintf(buf + pos, bufsz - pos, "Control\n");
  125. for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
  126. pos += scnprintf(buf + pos, bufsz - pos,
  127. "\t%s\t\t: %u\n",
  128. get_ctrl_string(cnt),
  129. priv->tx_stats.ctrl[cnt]);
  130. }
  131. pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
  132. pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
  133. priv->tx_stats.data_cnt);
  134. pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
  135. priv->tx_stats.data_bytes);
  136. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  137. kfree(buf);
  138. return ret;
  139. }
  140. static ssize_t iwl_dbgfs_tx_statistics_write(struct file *file,
  141. const char __user *user_buf,
  142. size_t count, loff_t *ppos)
  143. {
  144. struct iwl_priv *priv = file->private_data;
  145. u32 clear_flag;
  146. char buf[8];
  147. int buf_size;
  148. memset(buf, 0, sizeof(buf));
  149. buf_size = min(count, sizeof(buf) - 1);
  150. if (copy_from_user(buf, user_buf, buf_size))
  151. return -EFAULT;
  152. if (sscanf(buf, "%x", &clear_flag) != 1)
  153. return -EFAULT;
  154. if (clear_flag == 1)
  155. iwl_clear_tx_stats(priv);
  156. return count;
  157. }
  158. static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file,
  159. char __user *user_buf,
  160. size_t count, loff_t *ppos) {
  161. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  162. char *buf;
  163. int pos = 0;
  164. int cnt;
  165. ssize_t ret;
  166. const size_t bufsz = 100 +
  167. sizeof(char) * 24 * (MANAGEMENT_MAX + CONTROL_MAX);
  168. buf = kzalloc(bufsz, GFP_KERNEL);
  169. if (!buf)
  170. return -ENOMEM;
  171. pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
  172. for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
  173. pos += scnprintf(buf + pos, bufsz - pos,
  174. "\t%s\t\t: %u\n",
  175. get_mgmt_string(cnt),
  176. priv->rx_stats.mgmt[cnt]);
  177. }
  178. pos += scnprintf(buf + pos, bufsz - pos, "Control:\n");
  179. for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
  180. pos += scnprintf(buf + pos, bufsz - pos,
  181. "\t%s\t\t: %u\n",
  182. get_ctrl_string(cnt),
  183. priv->rx_stats.ctrl[cnt]);
  184. }
  185. pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
  186. pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
  187. priv->rx_stats.data_cnt);
  188. pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
  189. priv->rx_stats.data_bytes);
  190. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  191. kfree(buf);
  192. return ret;
  193. }
  194. static ssize_t iwl_dbgfs_rx_statistics_write(struct file *file,
  195. const char __user *user_buf,
  196. size_t count, loff_t *ppos)
  197. {
  198. struct iwl_priv *priv = file->private_data;
  199. u32 clear_flag;
  200. char buf[8];
  201. int buf_size;
  202. memset(buf, 0, sizeof(buf));
  203. buf_size = min(count, sizeof(buf) - 1);
  204. if (copy_from_user(buf, user_buf, buf_size))
  205. return -EFAULT;
  206. if (sscanf(buf, "%x", &clear_flag) != 1)
  207. return -EFAULT;
  208. if (clear_flag == 1)
  209. iwl_clear_rx_stats(priv);
  210. return count;
  211. }
  212. #define BYTE1_MASK 0x000000ff;
  213. #define BYTE2_MASK 0x0000ffff;
  214. #define BYTE3_MASK 0x00ffffff;
  215. static ssize_t iwl_dbgfs_sram_read(struct file *file,
  216. char __user *user_buf,
  217. size_t count, loff_t *ppos)
  218. {
  219. u32 val;
  220. char buf[1024];
  221. ssize_t ret;
  222. int i;
  223. int pos = 0;
  224. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  225. const size_t bufsz = sizeof(buf);
  226. for (i = priv->dbgfs->sram_len; i > 0; i -= 4) {
  227. val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \
  228. priv->dbgfs->sram_len - i);
  229. if (i < 4) {
  230. switch (i) {
  231. case 1:
  232. val &= BYTE1_MASK;
  233. break;
  234. case 2:
  235. val &= BYTE2_MASK;
  236. break;
  237. case 3:
  238. val &= BYTE3_MASK;
  239. break;
  240. }
  241. }
  242. pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
  243. }
  244. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  245. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  246. return ret;
  247. }
  248. static ssize_t iwl_dbgfs_sram_write(struct file *file,
  249. const char __user *user_buf,
  250. size_t count, loff_t *ppos)
  251. {
  252. struct iwl_priv *priv = file->private_data;
  253. char buf[64];
  254. int buf_size;
  255. u32 offset, len;
  256. memset(buf, 0, sizeof(buf));
  257. buf_size = min(count, sizeof(buf) - 1);
  258. if (copy_from_user(buf, user_buf, buf_size))
  259. return -EFAULT;
  260. if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
  261. priv->dbgfs->sram_offset = offset;
  262. priv->dbgfs->sram_len = len;
  263. } else {
  264. priv->dbgfs->sram_offset = 0;
  265. priv->dbgfs->sram_len = 0;
  266. }
  267. return count;
  268. }
  269. static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
  270. size_t count, loff_t *ppos)
  271. {
  272. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  273. struct iwl_station_entry *station;
  274. int max_sta = priv->hw_params.max_stations;
  275. char *buf;
  276. int i, j, pos = 0;
  277. ssize_t ret;
  278. /* Add 30 for initial string */
  279. const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations);
  280. buf = kmalloc(bufsz, GFP_KERNEL);
  281. if (!buf)
  282. return -ENOMEM;
  283. pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
  284. priv->num_stations);
  285. for (i = 0; i < max_sta; i++) {
  286. station = &priv->stations[i];
  287. if (station->used) {
  288. pos += scnprintf(buf + pos, bufsz - pos,
  289. "station %d:\ngeneral data:\n", i+1);
  290. pos += scnprintf(buf + pos, bufsz - pos, "id: %u\n",
  291. station->sta.sta.sta_id);
  292. pos += scnprintf(buf + pos, bufsz - pos, "mode: %u\n",
  293. station->sta.mode);
  294. pos += scnprintf(buf + pos, bufsz - pos,
  295. "flags: 0x%x\n",
  296. station->sta.station_flags_msk);
  297. pos += scnprintf(buf + pos, bufsz - pos,
  298. "ps_status: %u\n", station->ps_status);
  299. pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n");
  300. pos += scnprintf(buf + pos, bufsz - pos,
  301. "seq_num\t\ttxq_id");
  302. pos += scnprintf(buf + pos, bufsz - pos,
  303. "\tframe_count\twait_for_ba\t");
  304. pos += scnprintf(buf + pos, bufsz - pos,
  305. "start_idx\tbitmap0\t");
  306. pos += scnprintf(buf + pos, bufsz - pos,
  307. "bitmap1\trate_n_flags");
  308. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  309. for (j = 0; j < MAX_TID_COUNT; j++) {
  310. pos += scnprintf(buf + pos, bufsz - pos,
  311. "[%d]:\t\t%u", j,
  312. station->tid[j].seq_number);
  313. pos += scnprintf(buf + pos, bufsz - pos,
  314. "\t%u\t\t%u\t\t%u\t\t",
  315. station->tid[j].agg.txq_id,
  316. station->tid[j].agg.frame_count,
  317. station->tid[j].agg.wait_for_ba);
  318. pos += scnprintf(buf + pos, bufsz - pos,
  319. "%u\t%llu\t%u",
  320. station->tid[j].agg.start_idx,
  321. (unsigned long long)station->tid[j].agg.bitmap,
  322. station->tid[j].agg.rate_n_flags);
  323. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  324. }
  325. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  326. }
  327. }
  328. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  329. kfree(buf);
  330. return ret;
  331. }
  332. static ssize_t iwl_dbgfs_nvm_read(struct file *file,
  333. char __user *user_buf,
  334. size_t count,
  335. loff_t *ppos)
  336. {
  337. ssize_t ret;
  338. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  339. int pos = 0, ofs = 0, buf_size = 0;
  340. const u8 *ptr;
  341. char *buf;
  342. size_t eeprom_len = priv->cfg->eeprom_size;
  343. buf_size = 4 * eeprom_len + 256;
  344. if (eeprom_len % 16) {
  345. IWL_ERR(priv, "NVM size is not multiple of 16.\n");
  346. return -ENODATA;
  347. }
  348. ptr = priv->eeprom;
  349. if (!ptr) {
  350. IWL_ERR(priv, "Invalid EEPROM/OTP memory\n");
  351. return -ENOMEM;
  352. }
  353. /* 4 characters for byte 0xYY */
  354. buf = kzalloc(buf_size, GFP_KERNEL);
  355. if (!buf) {
  356. IWL_ERR(priv, "Can not allocate Buffer\n");
  357. return -ENOMEM;
  358. }
  359. pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s\n",
  360. (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
  361. ? "OTP" : "EEPROM");
  362. for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) {
  363. pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs);
  364. hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos,
  365. buf_size - pos, 0);
  366. pos += strlen(buf);
  367. if (buf_size - pos > 0)
  368. buf[pos++] = '\n';
  369. }
  370. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  371. kfree(buf);
  372. return ret;
  373. }
  374. static ssize_t iwl_dbgfs_log_event_write(struct file *file,
  375. const char __user *user_buf,
  376. size_t count, loff_t *ppos)
  377. {
  378. struct iwl_priv *priv = file->private_data;
  379. u32 event_log_flag;
  380. char buf[8];
  381. int buf_size;
  382. memset(buf, 0, sizeof(buf));
  383. buf_size = min(count, sizeof(buf) - 1);
  384. if (copy_from_user(buf, user_buf, buf_size))
  385. return -EFAULT;
  386. if (sscanf(buf, "%d", &event_log_flag) != 1)
  387. return -EFAULT;
  388. if (event_log_flag == 1)
  389. iwl_dump_nic_event_log(priv);
  390. return count;
  391. }
  392. static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
  393. size_t count, loff_t *ppos)
  394. {
  395. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  396. struct ieee80211_channel *channels = NULL;
  397. const struct ieee80211_supported_band *supp_band = NULL;
  398. int pos = 0, i, bufsz = PAGE_SIZE;
  399. char *buf;
  400. ssize_t ret;
  401. if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
  402. return -EAGAIN;
  403. buf = kzalloc(bufsz, GFP_KERNEL);
  404. if (!buf) {
  405. IWL_ERR(priv, "Can not allocate Buffer\n");
  406. return -ENOMEM;
  407. }
  408. supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ);
  409. if (supp_band) {
  410. channels = supp_band->channels;
  411. pos += scnprintf(buf + pos, bufsz - pos,
  412. "Displaying %d channels in 2.4GHz band 802.11bg):\n",
  413. supp_band->n_channels);
  414. for (i = 0; i < supp_band->n_channels; i++)
  415. pos += scnprintf(buf + pos, bufsz - pos,
  416. "%d: %ddBm: BSS%s%s, %s.\n",
  417. ieee80211_frequency_to_channel(
  418. channels[i].center_freq),
  419. channels[i].max_power,
  420. channels[i].flags & IEEE80211_CHAN_RADAR ?
  421. " (IEEE 802.11h required)" : "",
  422. ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
  423. || (channels[i].flags &
  424. IEEE80211_CHAN_RADAR)) ? "" :
  425. ", IBSS",
  426. channels[i].flags &
  427. IEEE80211_CHAN_PASSIVE_SCAN ?
  428. "passive only" : "active/passive");
  429. }
  430. supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ);
  431. if (supp_band) {
  432. channels = supp_band->channels;
  433. pos += scnprintf(buf + pos, bufsz - pos,
  434. "Displaying %d channels in 5.2GHz band (802.11a)\n",
  435. supp_band->n_channels);
  436. for (i = 0; i < supp_band->n_channels; i++)
  437. pos += scnprintf(buf + pos, bufsz - pos,
  438. "%d: %ddBm: BSS%s%s, %s.\n",
  439. ieee80211_frequency_to_channel(
  440. channels[i].center_freq),
  441. channels[i].max_power,
  442. channels[i].flags & IEEE80211_CHAN_RADAR ?
  443. " (IEEE 802.11h required)" : "",
  444. ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
  445. || (channels[i].flags &
  446. IEEE80211_CHAN_RADAR)) ? "" :
  447. ", IBSS",
  448. channels[i].flags &
  449. IEEE80211_CHAN_PASSIVE_SCAN ?
  450. "passive only" : "active/passive");
  451. }
  452. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  453. kfree(buf);
  454. return ret;
  455. }
  456. static ssize_t iwl_dbgfs_status_read(struct file *file,
  457. char __user *user_buf,
  458. size_t count, loff_t *ppos) {
  459. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  460. char buf[512];
  461. int pos = 0;
  462. const size_t bufsz = sizeof(buf);
  463. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n",
  464. test_bit(STATUS_HCMD_ACTIVE, &priv->status));
  465. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_SYNC_ACTIVE: %d\n",
  466. test_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status));
  467. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n",
  468. test_bit(STATUS_INT_ENABLED, &priv->status));
  469. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
  470. test_bit(STATUS_RF_KILL_HW, &priv->status));
  471. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n",
  472. test_bit(STATUS_INIT, &priv->status));
  473. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n",
  474. test_bit(STATUS_ALIVE, &priv->status));
  475. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n",
  476. test_bit(STATUS_READY, &priv->status));
  477. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n",
  478. test_bit(STATUS_TEMPERATURE, &priv->status));
  479. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n",
  480. test_bit(STATUS_GEO_CONFIGURED, &priv->status));
  481. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n",
  482. test_bit(STATUS_EXIT_PENDING, &priv->status));
  483. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n",
  484. test_bit(STATUS_STATISTICS, &priv->status));
  485. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n",
  486. test_bit(STATUS_SCANNING, &priv->status));
  487. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n",
  488. test_bit(STATUS_SCAN_ABORTING, &priv->status));
  489. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n",
  490. test_bit(STATUS_SCAN_HW, &priv->status));
  491. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n",
  492. test_bit(STATUS_POWER_PMI, &priv->status));
  493. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n",
  494. test_bit(STATUS_FW_ERROR, &priv->status));
  495. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_MODE_PENDING:\t %d\n",
  496. test_bit(STATUS_MODE_PENDING, &priv->status));
  497. return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  498. }
  499. static ssize_t iwl_dbgfs_interrupt_read(struct file *file,
  500. char __user *user_buf,
  501. size_t count, loff_t *ppos) {
  502. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  503. int pos = 0;
  504. int cnt = 0;
  505. char *buf;
  506. int bufsz = 24 * 64; /* 24 items * 64 char per item */
  507. ssize_t ret;
  508. buf = kzalloc(bufsz, GFP_KERNEL);
  509. if (!buf) {
  510. IWL_ERR(priv, "Can not allocate Buffer\n");
  511. return -ENOMEM;
  512. }
  513. pos += scnprintf(buf + pos, bufsz - pos,
  514. "Interrupt Statistics Report:\n");
  515. pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
  516. priv->isr_stats.hw);
  517. pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
  518. priv->isr_stats.sw);
  519. if (priv->isr_stats.sw > 0) {
  520. pos += scnprintf(buf + pos, bufsz - pos,
  521. "\tLast Restarting Code: 0x%X\n",
  522. priv->isr_stats.sw_err);
  523. }
  524. #ifdef CONFIG_IWLWIFI_DEBUG
  525. pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
  526. priv->isr_stats.sch);
  527. pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
  528. priv->isr_stats.alive);
  529. #endif
  530. pos += scnprintf(buf + pos, bufsz - pos,
  531. "HW RF KILL switch toggled:\t %u\n",
  532. priv->isr_stats.rfkill);
  533. pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
  534. priv->isr_stats.ctkill);
  535. pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
  536. priv->isr_stats.wakeup);
  537. pos += scnprintf(buf + pos, bufsz - pos,
  538. "Rx command responses:\t\t %u\n",
  539. priv->isr_stats.rx);
  540. for (cnt = 0; cnt < REPLY_MAX; cnt++) {
  541. if (priv->isr_stats.rx_handlers[cnt] > 0)
  542. pos += scnprintf(buf + pos, bufsz - pos,
  543. "\tRx handler[%36s]:\t\t %u\n",
  544. get_cmd_string(cnt),
  545. priv->isr_stats.rx_handlers[cnt]);
  546. }
  547. pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
  548. priv->isr_stats.tx);
  549. pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
  550. priv->isr_stats.unhandled);
  551. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  552. kfree(buf);
  553. return ret;
  554. }
  555. static ssize_t iwl_dbgfs_interrupt_write(struct file *file,
  556. const char __user *user_buf,
  557. size_t count, loff_t *ppos)
  558. {
  559. struct iwl_priv *priv = file->private_data;
  560. char buf[8];
  561. int buf_size;
  562. u32 reset_flag;
  563. memset(buf, 0, sizeof(buf));
  564. buf_size = min(count, sizeof(buf) - 1);
  565. if (copy_from_user(buf, user_buf, buf_size))
  566. return -EFAULT;
  567. if (sscanf(buf, "%x", &reset_flag) != 1)
  568. return -EFAULT;
  569. if (reset_flag == 0)
  570. iwl_clear_isr_stats(priv);
  571. return count;
  572. }
  573. static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf,
  574. size_t count, loff_t *ppos)
  575. {
  576. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  577. int pos = 0, i;
  578. char buf[256];
  579. const size_t bufsz = sizeof(buf);
  580. ssize_t ret;
  581. for (i = 0; i < AC_NUM; i++) {
  582. pos += scnprintf(buf + pos, bufsz - pos,
  583. "\tcw_min\tcw_max\taifsn\ttxop\n");
  584. pos += scnprintf(buf + pos, bufsz - pos,
  585. "AC[%d]\t%u\t%u\t%u\t%u\n", i,
  586. priv->qos_data.def_qos_parm.ac[i].cw_min,
  587. priv->qos_data.def_qos_parm.ac[i].cw_max,
  588. priv->qos_data.def_qos_parm.ac[i].aifsn,
  589. priv->qos_data.def_qos_parm.ac[i].edca_txop);
  590. }
  591. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  592. return ret;
  593. }
  594. #ifdef CONFIG_IWLWIFI_LEDS
  595. static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf,
  596. size_t count, loff_t *ppos)
  597. {
  598. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  599. int pos = 0;
  600. char buf[256];
  601. const size_t bufsz = sizeof(buf);
  602. ssize_t ret;
  603. pos += scnprintf(buf + pos, bufsz - pos,
  604. "allow blinking: %s\n",
  605. (priv->allow_blinking) ? "True" : "False");
  606. if (priv->allow_blinking) {
  607. pos += scnprintf(buf + pos, bufsz - pos,
  608. "Led blinking rate: %u\n",
  609. priv->last_blink_rate);
  610. pos += scnprintf(buf + pos, bufsz - pos,
  611. "Last blink time: %lu\n",
  612. priv->last_blink_time);
  613. }
  614. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  615. return ret;
  616. }
  617. #endif
  618. static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
  619. char __user *user_buf,
  620. size_t count, loff_t *ppos)
  621. {
  622. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  623. struct iwl_tt_mgmt *tt = &priv->power_data.tt;
  624. struct iwl_tt_restriction *restriction;
  625. char buf[100];
  626. int pos = 0;
  627. const size_t bufsz = sizeof(buf);
  628. ssize_t ret;
  629. pos += scnprintf(buf + pos, bufsz - pos,
  630. "Thermal Throttling Mode: %s\n",
  631. (priv->power_data.adv_tt)
  632. ? "Advance" : "Legacy");
  633. pos += scnprintf(buf + pos, bufsz - pos,
  634. "Thermal Throttling State: %d\n",
  635. tt->state);
  636. if (priv->power_data.adv_tt) {
  637. restriction = tt->restriction + tt->state;
  638. pos += scnprintf(buf + pos, bufsz - pos,
  639. "Tx mode: %d\n",
  640. restriction->tx_stream);
  641. pos += scnprintf(buf + pos, bufsz - pos,
  642. "Rx mode: %d\n",
  643. restriction->rx_stream);
  644. pos += scnprintf(buf + pos, bufsz - pos,
  645. "HT mode: %d\n",
  646. restriction->is_ht);
  647. }
  648. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  649. return ret;
  650. }
  651. static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file,
  652. const char __user *user_buf,
  653. size_t count, loff_t *ppos)
  654. {
  655. struct iwl_priv *priv = file->private_data;
  656. char buf[8];
  657. int buf_size;
  658. int ht40;
  659. memset(buf, 0, sizeof(buf));
  660. buf_size = min(count, sizeof(buf) - 1);
  661. if (copy_from_user(buf, user_buf, buf_size))
  662. return -EFAULT;
  663. if (sscanf(buf, "%d", &ht40) != 1)
  664. return -EFAULT;
  665. if (!iwl_is_associated(priv))
  666. priv->disable_ht40 = ht40 ? true : false;
  667. else {
  668. IWL_ERR(priv, "Sta associated with AP - "
  669. "Change to 40MHz channel support is not allowed\n");
  670. return -EINVAL;
  671. }
  672. return count;
  673. }
  674. static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file,
  675. char __user *user_buf,
  676. size_t count, loff_t *ppos)
  677. {
  678. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  679. char buf[100];
  680. int pos = 0;
  681. const size_t bufsz = sizeof(buf);
  682. ssize_t ret;
  683. pos += scnprintf(buf + pos, bufsz - pos,
  684. "11n 40MHz Mode: %s\n",
  685. priv->disable_ht40 ? "Disabled" : "Enabled");
  686. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  687. return ret;
  688. }
  689. DEBUGFS_READ_WRITE_FILE_OPS(sram);
  690. DEBUGFS_WRITE_FILE_OPS(log_event);
  691. DEBUGFS_READ_FILE_OPS(nvm);
  692. DEBUGFS_READ_FILE_OPS(stations);
  693. DEBUGFS_READ_FILE_OPS(channels);
  694. DEBUGFS_READ_FILE_OPS(status);
  695. DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
  696. DEBUGFS_READ_FILE_OPS(qos);
  697. #ifdef CONFIG_IWLWIFI_LEDS
  698. DEBUGFS_READ_FILE_OPS(led);
  699. #endif
  700. DEBUGFS_READ_FILE_OPS(thermal_throttling);
  701. DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
  702. static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
  703. char __user *user_buf,
  704. size_t count, loff_t *ppos)
  705. {
  706. struct iwl_priv *priv = file->private_data;
  707. int pos = 0, ofs = 0;
  708. int cnt = 0, entry;
  709. struct iwl_tx_queue *txq;
  710. struct iwl_queue *q;
  711. struct iwl_rx_queue *rxq = &priv->rxq;
  712. char *buf;
  713. int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
  714. (IWL_MAX_NUM_QUEUES * 32 * 8) + 400;
  715. const u8 *ptr;
  716. ssize_t ret;
  717. buf = kzalloc(bufsz, GFP_KERNEL);
  718. if (!buf) {
  719. IWL_ERR(priv, "Can not allocate buffer\n");
  720. return -ENOMEM;
  721. }
  722. pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n");
  723. for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
  724. txq = &priv->txq[cnt];
  725. q = &txq->q;
  726. pos += scnprintf(buf + pos, bufsz - pos,
  727. "q[%d]: read_ptr: %u, write_ptr: %u\n",
  728. cnt, q->read_ptr, q->write_ptr);
  729. }
  730. if (priv->tx_traffic && (iwl_debug_level & IWL_DL_TX)) {
  731. ptr = priv->tx_traffic;
  732. pos += scnprintf(buf + pos, bufsz - pos,
  733. "Tx Traffic idx: %u\n", priv->tx_traffic_idx);
  734. for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
  735. for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
  736. entry++, ofs += 16) {
  737. pos += scnprintf(buf + pos, bufsz - pos,
  738. "0x%.4x ", ofs);
  739. hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
  740. buf + pos, bufsz - pos, 0);
  741. pos += strlen(buf);
  742. if (bufsz - pos > 0)
  743. buf[pos++] = '\n';
  744. }
  745. }
  746. }
  747. pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n");
  748. pos += scnprintf(buf + pos, bufsz - pos,
  749. "read: %u, write: %u\n",
  750. rxq->read, rxq->write);
  751. if (priv->rx_traffic && (iwl_debug_level & IWL_DL_RX)) {
  752. ptr = priv->rx_traffic;
  753. pos += scnprintf(buf + pos, bufsz - pos,
  754. "Rx Traffic idx: %u\n", priv->rx_traffic_idx);
  755. for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
  756. for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
  757. entry++, ofs += 16) {
  758. pos += scnprintf(buf + pos, bufsz - pos,
  759. "0x%.4x ", ofs);
  760. hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
  761. buf + pos, bufsz - pos, 0);
  762. pos += strlen(buf);
  763. if (bufsz - pos > 0)
  764. buf[pos++] = '\n';
  765. }
  766. }
  767. }
  768. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  769. kfree(buf);
  770. return ret;
  771. }
  772. static ssize_t iwl_dbgfs_traffic_log_write(struct file *file,
  773. const char __user *user_buf,
  774. size_t count, loff_t *ppos)
  775. {
  776. struct iwl_priv *priv = file->private_data;
  777. char buf[8];
  778. int buf_size;
  779. int traffic_log;
  780. memset(buf, 0, sizeof(buf));
  781. buf_size = min(count, sizeof(buf) - 1);
  782. if (copy_from_user(buf, user_buf, buf_size))
  783. return -EFAULT;
  784. if (sscanf(buf, "%d", &traffic_log) != 1)
  785. return -EFAULT;
  786. if (traffic_log == 0)
  787. iwl_reset_traffic_log(priv);
  788. return count;
  789. }
  790. static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
  791. char __user *user_buf,
  792. size_t count, loff_t *ppos) {
  793. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  794. struct iwl_tx_queue *txq;
  795. struct iwl_queue *q;
  796. char *buf;
  797. int pos = 0;
  798. int cnt;
  799. int ret;
  800. const size_t bufsz = sizeof(char) * 60 * IWL_MAX_NUM_QUEUES;
  801. buf = kzalloc(bufsz, GFP_KERNEL);
  802. if (!buf)
  803. return -ENOMEM;
  804. for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
  805. txq = &priv->txq[cnt];
  806. q = &txq->q;
  807. pos += scnprintf(buf + pos, bufsz - pos,
  808. "hwq %.2d: read=%u write=%u stop=%d"
  809. " swq_id=%#.2x (ac %d/hwq %d)\n",
  810. cnt, q->read_ptr, q->write_ptr,
  811. !!test_bit(cnt, priv->queue_stopped),
  812. txq->swq_id,
  813. txq->swq_id & 0x80 ? txq->swq_id & 3 :
  814. txq->swq_id,
  815. txq->swq_id & 0x80 ? (txq->swq_id >> 2) &
  816. 0x1f : txq->swq_id);
  817. if (cnt >= 4)
  818. continue;
  819. /* for the ACs, display the stop count too */
  820. pos += scnprintf(buf + pos, bufsz - pos,
  821. " stop-count: %d\n",
  822. atomic_read(&priv->queue_stop_count[cnt]));
  823. }
  824. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  825. kfree(buf);
  826. return ret;
  827. }
  828. static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
  829. char __user *user_buf,
  830. size_t count, loff_t *ppos) {
  831. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  832. struct iwl_rx_queue *rxq = &priv->rxq;
  833. char buf[256];
  834. int pos = 0;
  835. const size_t bufsz = sizeof(buf);
  836. pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n",
  837. rxq->read);
  838. pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n",
  839. rxq->write);
  840. pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
  841. rxq->free_count);
  842. pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
  843. le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF);
  844. return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  845. }
  846. #define UCODE_STATISTICS_CLEAR_MSK (0x1 << 0)
  847. #define UCODE_STATISTICS_FREQUENCY_MSK (0x1 << 1)
  848. #define UCODE_STATISTICS_NARROW_BAND_MSK (0x1 << 2)
  849. static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf,
  850. int bufsz)
  851. {
  852. int p = 0;
  853. p += scnprintf(buf + p, bufsz - p,
  854. "Statistics Flag(0x%X):\n",
  855. le32_to_cpu(priv->statistics.flag));
  856. if (le32_to_cpu(priv->statistics.flag) & UCODE_STATISTICS_CLEAR_MSK)
  857. p += scnprintf(buf + p, bufsz - p,
  858. "\tStatistics have been cleared\n");
  859. p += scnprintf(buf + p, bufsz - p,
  860. "\tOperational Frequency: %s\n",
  861. (le32_to_cpu(priv->statistics.flag) &
  862. UCODE_STATISTICS_FREQUENCY_MSK)
  863. ? "2.4 GHz" : "5.2 GHz");
  864. p += scnprintf(buf + p, bufsz - p,
  865. "\tTGj Narrow Band: %s\n",
  866. (le32_to_cpu(priv->statistics.flag) &
  867. UCODE_STATISTICS_NARROW_BAND_MSK)
  868. ? "enabled" : "disabled");
  869. return p;
  870. }
  871. static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
  872. char __user *user_buf,
  873. size_t count, loff_t *ppos)
  874. {
  875. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  876. int pos = 0;
  877. char *buf;
  878. int bufsz = sizeof(struct statistics_rx_phy) * 20 +
  879. sizeof(struct statistics_rx_non_phy) * 20 +
  880. sizeof(struct statistics_rx_ht_phy) * 20 + 400;
  881. ssize_t ret;
  882. struct statistics_rx_phy *ofdm;
  883. struct statistics_rx_phy *cck;
  884. struct statistics_rx_non_phy *general;
  885. struct statistics_rx_ht_phy *ht;
  886. if (!iwl_is_alive(priv))
  887. return -EAGAIN;
  888. /* make request to uCode to retrieve statistics information */
  889. mutex_lock(&priv->mutex);
  890. ret = iwl_send_statistics_request(priv, 0);
  891. mutex_unlock(&priv->mutex);
  892. if (ret) {
  893. IWL_ERR(priv,
  894. "Error sending statistics request: %zd\n", ret);
  895. return -EAGAIN;
  896. }
  897. buf = kzalloc(bufsz, GFP_KERNEL);
  898. if (!buf) {
  899. IWL_ERR(priv, "Can not allocate Buffer\n");
  900. return -ENOMEM;
  901. }
  902. /* the statistic information display here is based on
  903. * the last statistics notification from uCode
  904. * might not reflect the current uCode activity
  905. */
  906. ofdm = &priv->statistics.rx.ofdm;
  907. cck = &priv->statistics.rx.cck;
  908. general = &priv->statistics.rx.general;
  909. ht = &priv->statistics.rx.ofdm_ht;
  910. pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
  911. pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM:\n");
  912. pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt: %u\n",
  913. le32_to_cpu(ofdm->ina_cnt));
  914. pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt: %u\n",
  915. le32_to_cpu(ofdm->fina_cnt));
  916. pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
  917. le32_to_cpu(ofdm->plcp_err));
  918. pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
  919. le32_to_cpu(ofdm->crc32_err));
  920. pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
  921. le32_to_cpu(ofdm->overrun_err));
  922. pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
  923. le32_to_cpu(ofdm->early_overrun_err));
  924. pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
  925. le32_to_cpu(ofdm->crc32_good));
  926. pos += scnprintf(buf + pos, bufsz - pos, "false_alarm_cnt: %u\n",
  927. le32_to_cpu(ofdm->false_alarm_cnt));
  928. pos += scnprintf(buf + pos, bufsz - pos, "fina_sync_err_cnt: %u\n",
  929. le32_to_cpu(ofdm->fina_sync_err_cnt));
  930. pos += scnprintf(buf + pos, bufsz - pos, "sfd_timeout: %u\n",
  931. le32_to_cpu(ofdm->sfd_timeout));
  932. pos += scnprintf(buf + pos, bufsz - pos, "fina_timeout: %u\n",
  933. le32_to_cpu(ofdm->fina_timeout));
  934. pos += scnprintf(buf + pos, bufsz - pos, "unresponded_rts: %u\n",
  935. le32_to_cpu(ofdm->unresponded_rts));
  936. pos += scnprintf(buf + pos, bufsz - pos,
  937. "rxe_frame_limit_overrun: %u\n",
  938. le32_to_cpu(ofdm->rxe_frame_limit_overrun));
  939. pos += scnprintf(buf + pos, bufsz - pos, "sent_ack_cnt: %u\n",
  940. le32_to_cpu(ofdm->sent_ack_cnt));
  941. pos += scnprintf(buf + pos, bufsz - pos, "sent_cts_cnt: %u\n",
  942. le32_to_cpu(ofdm->sent_cts_cnt));
  943. pos += scnprintf(buf + pos, bufsz - pos, "sent_ba_rsp_cnt: %u\n",
  944. le32_to_cpu(ofdm->sent_ba_rsp_cnt));
  945. pos += scnprintf(buf + pos, bufsz - pos, "dsp_self_kill: %u\n",
  946. le32_to_cpu(ofdm->dsp_self_kill));
  947. pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
  948. le32_to_cpu(ofdm->mh_format_err));
  949. pos += scnprintf(buf + pos, bufsz - pos, "re_acq_main_rssi_sum: %u\n",
  950. le32_to_cpu(ofdm->re_acq_main_rssi_sum));
  951. pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - CCK:\n");
  952. pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt: %u\n",
  953. le32_to_cpu(cck->ina_cnt));
  954. pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt: %u\n",
  955. le32_to_cpu(cck->fina_cnt));
  956. pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
  957. le32_to_cpu(cck->plcp_err));
  958. pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
  959. le32_to_cpu(cck->crc32_err));
  960. pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
  961. le32_to_cpu(cck->overrun_err));
  962. pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
  963. le32_to_cpu(cck->early_overrun_err));
  964. pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
  965. le32_to_cpu(cck->crc32_good));
  966. pos += scnprintf(buf + pos, bufsz - pos, "false_alarm_cnt: %u\n",
  967. le32_to_cpu(cck->false_alarm_cnt));
  968. pos += scnprintf(buf + pos, bufsz - pos, "fina_sync_err_cnt: %u\n",
  969. le32_to_cpu(cck->fina_sync_err_cnt));
  970. pos += scnprintf(buf + pos, bufsz - pos, "sfd_timeout: %u\n",
  971. le32_to_cpu(cck->sfd_timeout));
  972. pos += scnprintf(buf + pos, bufsz - pos, "fina_timeout: %u\n",
  973. le32_to_cpu(cck->fina_timeout));
  974. pos += scnprintf(buf + pos, bufsz - pos, "unresponded_rts: %u\n",
  975. le32_to_cpu(cck->unresponded_rts));
  976. pos += scnprintf(buf + pos, bufsz - pos,
  977. "rxe_frame_limit_overrun: %u\n",
  978. le32_to_cpu(cck->rxe_frame_limit_overrun));
  979. pos += scnprintf(buf + pos, bufsz - pos, "sent_ack_cnt: %u\n",
  980. le32_to_cpu(cck->sent_ack_cnt));
  981. pos += scnprintf(buf + pos, bufsz - pos, "sent_cts_cnt: %u\n",
  982. le32_to_cpu(cck->sent_cts_cnt));
  983. pos += scnprintf(buf + pos, bufsz - pos, "sent_ba_rsp_cnt: %u\n",
  984. le32_to_cpu(cck->sent_ba_rsp_cnt));
  985. pos += scnprintf(buf + pos, bufsz - pos, "dsp_self_kill: %u\n",
  986. le32_to_cpu(cck->dsp_self_kill));
  987. pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
  988. le32_to_cpu(cck->mh_format_err));
  989. pos += scnprintf(buf + pos, bufsz - pos, "re_acq_main_rssi_sum: %u\n",
  990. le32_to_cpu(cck->re_acq_main_rssi_sum));
  991. pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - GENERAL:\n");
  992. pos += scnprintf(buf + pos, bufsz - pos, "bogus_cts: %u\n",
  993. le32_to_cpu(general->bogus_cts));
  994. pos += scnprintf(buf + pos, bufsz - pos, "bogus_ack: %u\n",
  995. le32_to_cpu(general->bogus_ack));
  996. pos += scnprintf(buf + pos, bufsz - pos, "non_bssid_frames: %u\n",
  997. le32_to_cpu(general->non_bssid_frames));
  998. pos += scnprintf(buf + pos, bufsz - pos, "filtered_frames: %u\n",
  999. le32_to_cpu(general->filtered_frames));
  1000. pos += scnprintf(buf + pos, bufsz - pos, "non_channel_beacons: %u\n",
  1001. le32_to_cpu(general->non_channel_beacons));
  1002. pos += scnprintf(buf + pos, bufsz - pos, "channel_beacons: %u\n",
  1003. le32_to_cpu(general->channel_beacons));
  1004. pos += scnprintf(buf + pos, bufsz - pos, "num_missed_bcon: %u\n",
  1005. le32_to_cpu(general->num_missed_bcon));
  1006. pos += scnprintf(buf + pos, bufsz - pos,
  1007. "adc_rx_saturation_time: %u\n",
  1008. le32_to_cpu(general->adc_rx_saturation_time));
  1009. pos += scnprintf(buf + pos, bufsz - pos,
  1010. "ina_detection_search_time: %u\n",
  1011. le32_to_cpu(general->ina_detection_search_time));
  1012. pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_a: %u\n",
  1013. le32_to_cpu(general->beacon_silence_rssi_a));
  1014. pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_b: %u\n",
  1015. le32_to_cpu(general->beacon_silence_rssi_b));
  1016. pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_c: %u\n",
  1017. le32_to_cpu(general->beacon_silence_rssi_c));
  1018. pos += scnprintf(buf + pos, bufsz - pos,
  1019. "interference_data_flag: %u\n",
  1020. le32_to_cpu(general->interference_data_flag));
  1021. pos += scnprintf(buf + pos, bufsz - pos, "channel_load: %u\n",
  1022. le32_to_cpu(general->channel_load));
  1023. pos += scnprintf(buf + pos, bufsz - pos, "dsp_false_alarms: %u\n",
  1024. le32_to_cpu(general->dsp_false_alarms));
  1025. pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_a: %u\n",
  1026. le32_to_cpu(general->beacon_rssi_a));
  1027. pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_b: %u\n",
  1028. le32_to_cpu(general->beacon_rssi_b));
  1029. pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_c: %u\n",
  1030. le32_to_cpu(general->beacon_rssi_c));
  1031. pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_a: %u\n",
  1032. le32_to_cpu(general->beacon_energy_a));
  1033. pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_b: %u\n",
  1034. le32_to_cpu(general->beacon_energy_b));
  1035. pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_c: %u\n",
  1036. le32_to_cpu(general->beacon_energy_c));
  1037. pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n");
  1038. pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
  1039. le32_to_cpu(ht->plcp_err));
  1040. pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
  1041. le32_to_cpu(ht->overrun_err));
  1042. pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
  1043. le32_to_cpu(ht->early_overrun_err));
  1044. pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
  1045. le32_to_cpu(ht->crc32_good));
  1046. pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
  1047. le32_to_cpu(ht->crc32_err));
  1048. pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
  1049. le32_to_cpu(ht->mh_format_err));
  1050. pos += scnprintf(buf + pos, bufsz - pos, "agg_crc32_good: %u\n",
  1051. le32_to_cpu(ht->agg_crc32_good));
  1052. pos += scnprintf(buf + pos, bufsz - pos, "agg_mpdu_cnt: %u\n",
  1053. le32_to_cpu(ht->agg_mpdu_cnt));
  1054. pos += scnprintf(buf + pos, bufsz - pos, "agg_cnt: %u\n",
  1055. le32_to_cpu(ht->agg_cnt));
  1056. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  1057. kfree(buf);
  1058. return ret;
  1059. }
  1060. static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
  1061. char __user *user_buf,
  1062. size_t count, loff_t *ppos)
  1063. {
  1064. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  1065. int pos = 0;
  1066. char *buf;
  1067. int bufsz = (sizeof(struct statistics_tx) * 24) + 250;
  1068. ssize_t ret;
  1069. struct statistics_tx *tx;
  1070. if (!iwl_is_alive(priv))
  1071. return -EAGAIN;
  1072. /* make request to uCode to retrieve statistics information */
  1073. mutex_lock(&priv->mutex);
  1074. ret = iwl_send_statistics_request(priv, 0);
  1075. mutex_unlock(&priv->mutex);
  1076. if (ret) {
  1077. IWL_ERR(priv,
  1078. "Error sending statistics request: %zd\n", ret);
  1079. return -EAGAIN;
  1080. }
  1081. buf = kzalloc(bufsz, GFP_KERNEL);
  1082. if (!buf) {
  1083. IWL_ERR(priv, "Can not allocate Buffer\n");
  1084. return -ENOMEM;
  1085. }
  1086. /* the statistic information display here is based on
  1087. * the last statistics notification from uCode
  1088. * might not reflect the current uCode activity
  1089. */
  1090. tx = &priv->statistics.tx;
  1091. pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
  1092. pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Tx:\n");
  1093. pos += scnprintf(buf + pos, bufsz - pos, "preamble: %u\n",
  1094. le32_to_cpu(tx->preamble_cnt));
  1095. pos += scnprintf(buf + pos, bufsz - pos, "rx_detected_cnt: %u\n",
  1096. le32_to_cpu(tx->rx_detected_cnt));
  1097. pos += scnprintf(buf + pos, bufsz - pos, "bt_prio_defer_cnt: %u\n",
  1098. le32_to_cpu(tx->bt_prio_defer_cnt));
  1099. pos += scnprintf(buf + pos, bufsz - pos, "bt_prio_kill_cnt: %u\n",
  1100. le32_to_cpu(tx->bt_prio_kill_cnt));
  1101. pos += scnprintf(buf + pos, bufsz - pos, "few_bytes_cnt: %u\n",
  1102. le32_to_cpu(tx->few_bytes_cnt));
  1103. pos += scnprintf(buf + pos, bufsz - pos, "cts_timeout: %u\n",
  1104. le32_to_cpu(tx->cts_timeout));
  1105. pos += scnprintf(buf + pos, bufsz - pos, "ack_timeout: %u\n",
  1106. le32_to_cpu(tx->ack_timeout));
  1107. pos += scnprintf(buf + pos, bufsz - pos, "expected_ack_cnt: %u\n",
  1108. le32_to_cpu(tx->expected_ack_cnt));
  1109. pos += scnprintf(buf + pos, bufsz - pos, "actual_ack_cnt: %u\n",
  1110. le32_to_cpu(tx->actual_ack_cnt));
  1111. pos += scnprintf(buf + pos, bufsz - pos, "dump_msdu_cnt: %u\n",
  1112. le32_to_cpu(tx->dump_msdu_cnt));
  1113. pos += scnprintf(buf + pos, bufsz - pos,
  1114. "burst_abort_next_frame_mismatch_cnt: %u\n",
  1115. le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt));
  1116. pos += scnprintf(buf + pos, bufsz - pos,
  1117. "burst_abort_missing_next_frame_cnt: %u\n",
  1118. le32_to_cpu(tx->burst_abort_missing_next_frame_cnt));
  1119. pos += scnprintf(buf + pos, bufsz - pos, "cts_timeout_collision: %u\n",
  1120. le32_to_cpu(tx->cts_timeout_collision));
  1121. pos += scnprintf(buf + pos, bufsz - pos,
  1122. "ack_or_ba_timeout_collision: %u\n",
  1123. le32_to_cpu(tx->ack_or_ba_timeout_collision));
  1124. pos += scnprintf(buf + pos, bufsz - pos, "agg ba_timeout: %u\n",
  1125. le32_to_cpu(tx->agg.ba_timeout));
  1126. pos += scnprintf(buf + pos, bufsz - pos,
  1127. "agg ba_reschedule_frames: %u\n",
  1128. le32_to_cpu(tx->agg.ba_reschedule_frames));
  1129. pos += scnprintf(buf + pos, bufsz - pos,
  1130. "agg scd_query_agg_frame_cnt: %u\n",
  1131. le32_to_cpu(tx->agg.scd_query_agg_frame_cnt));
  1132. pos += scnprintf(buf + pos, bufsz - pos, "agg scd_query_no_agg: %u\n",
  1133. le32_to_cpu(tx->agg.scd_query_no_agg));
  1134. pos += scnprintf(buf + pos, bufsz - pos, "agg scd_query_agg: %u\n",
  1135. le32_to_cpu(tx->agg.scd_query_agg));
  1136. pos += scnprintf(buf + pos, bufsz - pos,
  1137. "agg scd_query_mismatch: %u\n",
  1138. le32_to_cpu(tx->agg.scd_query_mismatch));
  1139. pos += scnprintf(buf + pos, bufsz - pos, "agg frame_not_ready: %u\n",
  1140. le32_to_cpu(tx->agg.frame_not_ready));
  1141. pos += scnprintf(buf + pos, bufsz - pos, "agg underrun: %u\n",
  1142. le32_to_cpu(tx->agg.underrun));
  1143. pos += scnprintf(buf + pos, bufsz - pos, "agg bt_prio_kill: %u\n",
  1144. le32_to_cpu(tx->agg.bt_prio_kill));
  1145. pos += scnprintf(buf + pos, bufsz - pos, "agg rx_ba_rsp_cnt: %u\n",
  1146. le32_to_cpu(tx->agg.rx_ba_rsp_cnt));
  1147. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  1148. kfree(buf);
  1149. return ret;
  1150. }
  1151. static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
  1152. char __user *user_buf,
  1153. size_t count, loff_t *ppos)
  1154. {
  1155. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  1156. int pos = 0;
  1157. char *buf;
  1158. int bufsz = sizeof(struct statistics_general) * 4 + 250;
  1159. ssize_t ret;
  1160. struct statistics_general *general;
  1161. struct statistics_dbg *dbg;
  1162. struct statistics_div *div;
  1163. if (!iwl_is_alive(priv))
  1164. return -EAGAIN;
  1165. /* make request to uCode to retrieve statistics information */
  1166. mutex_lock(&priv->mutex);
  1167. ret = iwl_send_statistics_request(priv, 0);
  1168. mutex_unlock(&priv->mutex);
  1169. if (ret) {
  1170. IWL_ERR(priv,
  1171. "Error sending statistics request: %zd\n", ret);
  1172. return -EAGAIN;
  1173. }
  1174. buf = kzalloc(bufsz, GFP_KERNEL);
  1175. if (!buf) {
  1176. IWL_ERR(priv, "Can not allocate Buffer\n");
  1177. return -ENOMEM;
  1178. }
  1179. /* the statistic information display here is based on
  1180. * the last statistics notification from uCode
  1181. * might not reflect the current uCode activity
  1182. */
  1183. general = &priv->statistics.general;
  1184. dbg = &priv->statistics.general.dbg;
  1185. div = &priv->statistics.general.div;
  1186. pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
  1187. pos += scnprintf(buf + pos, bufsz - pos, "Statistics_General:\n");
  1188. pos += scnprintf(buf + pos, bufsz - pos, "temperature: %u\n",
  1189. le32_to_cpu(general->temperature));
  1190. pos += scnprintf(buf + pos, bufsz - pos, "temperature_m: %u\n",
  1191. le32_to_cpu(general->temperature_m));
  1192. pos += scnprintf(buf + pos, bufsz - pos, "burst_check: %u\n",
  1193. le32_to_cpu(dbg->burst_check));
  1194. pos += scnprintf(buf + pos, bufsz - pos, "burst_count: %u\n",
  1195. le32_to_cpu(dbg->burst_count));
  1196. pos += scnprintf(buf + pos, bufsz - pos, "sleep_time: %u\n",
  1197. le32_to_cpu(general->sleep_time));
  1198. pos += scnprintf(buf + pos, bufsz - pos, "slots_out: %u\n",
  1199. le32_to_cpu(general->slots_out));
  1200. pos += scnprintf(buf + pos, bufsz - pos, "slots_idle: %u\n",
  1201. le32_to_cpu(general->slots_idle));
  1202. pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp: %u\n",
  1203. le32_to_cpu(general->ttl_timestamp));
  1204. pos += scnprintf(buf + pos, bufsz - pos, "tx_on_a: %u\n",
  1205. le32_to_cpu(div->tx_on_a));
  1206. pos += scnprintf(buf + pos, bufsz - pos, "tx_on_b: %u\n",
  1207. le32_to_cpu(div->tx_on_b));
  1208. pos += scnprintf(buf + pos, bufsz - pos, "exec_time: %u\n",
  1209. le32_to_cpu(div->exec_time));
  1210. pos += scnprintf(buf + pos, bufsz - pos, "probe_time: %u\n",
  1211. le32_to_cpu(div->probe_time));
  1212. pos += scnprintf(buf + pos, bufsz - pos, "rx_enable_counter: %u\n",
  1213. le32_to_cpu(general->rx_enable_counter));
  1214. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  1215. kfree(buf);
  1216. return ret;
  1217. }
  1218. static ssize_t iwl_dbgfs_sensitivity_read(struct file *file,
  1219. char __user *user_buf,
  1220. size_t count, loff_t *ppos) {
  1221. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  1222. int pos = 0;
  1223. int cnt = 0;
  1224. char *buf;
  1225. int bufsz = sizeof(struct iwl_sensitivity_data) * 4 + 100;
  1226. ssize_t ret;
  1227. struct iwl_sensitivity_data *data;
  1228. data = &priv->sensitivity_data;
  1229. buf = kzalloc(bufsz, GFP_KERNEL);
  1230. if (!buf) {
  1231. IWL_ERR(priv, "Can not allocate Buffer\n");
  1232. return -ENOMEM;
  1233. }
  1234. pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
  1235. data->auto_corr_ofdm);
  1236. pos += scnprintf(buf + pos, bufsz - pos,
  1237. "auto_corr_ofdm_mrc:\t\t %u\n",
  1238. data->auto_corr_ofdm_mrc);
  1239. pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
  1240. data->auto_corr_ofdm_x1);
  1241. pos += scnprintf(buf + pos, bufsz - pos,
  1242. "auto_corr_ofdm_mrc_x1:\t\t %u\n",
  1243. data->auto_corr_ofdm_mrc_x1);
  1244. pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
  1245. data->auto_corr_cck);
  1246. pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
  1247. data->auto_corr_cck_mrc);
  1248. pos += scnprintf(buf + pos, bufsz - pos,
  1249. "last_bad_plcp_cnt_ofdm:\t\t %u\n",
  1250. data->last_bad_plcp_cnt_ofdm);
  1251. pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
  1252. data->last_fa_cnt_ofdm);
  1253. pos += scnprintf(buf + pos, bufsz - pos,
  1254. "last_bad_plcp_cnt_cck:\t\t %u\n",
  1255. data->last_bad_plcp_cnt_cck);
  1256. pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
  1257. data->last_fa_cnt_cck);
  1258. pos += scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
  1259. data->nrg_curr_state);
  1260. pos += scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
  1261. data->nrg_prev_state);
  1262. pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
  1263. for (cnt = 0; cnt < 10; cnt++) {
  1264. pos += scnprintf(buf + pos, bufsz - pos, " %u",
  1265. data->nrg_value[cnt]);
  1266. }
  1267. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  1268. pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
  1269. for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
  1270. pos += scnprintf(buf + pos, bufsz - pos, " %u",
  1271. data->nrg_silence_rssi[cnt]);
  1272. }
  1273. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  1274. pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
  1275. data->nrg_silence_ref);
  1276. pos += scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
  1277. data->nrg_energy_idx);
  1278. pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
  1279. data->nrg_silence_idx);
  1280. pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
  1281. data->nrg_th_cck);
  1282. pos += scnprintf(buf + pos, bufsz - pos,
  1283. "nrg_auto_corr_silence_diff:\t %u\n",
  1284. data->nrg_auto_corr_silence_diff);
  1285. pos += scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
  1286. data->num_in_cck_no_fa);
  1287. pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
  1288. data->nrg_th_ofdm);
  1289. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  1290. kfree(buf);
  1291. return ret;
  1292. }
  1293. static ssize_t iwl_dbgfs_chain_noise_read(struct file *file,
  1294. char __user *user_buf,
  1295. size_t count, loff_t *ppos) {
  1296. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  1297. int pos = 0;
  1298. int cnt = 0;
  1299. char *buf;
  1300. int bufsz = sizeof(struct iwl_chain_noise_data) * 4 + 100;
  1301. ssize_t ret;
  1302. struct iwl_chain_noise_data *data;
  1303. data = &priv->chain_noise_data;
  1304. buf = kzalloc(bufsz, GFP_KERNEL);
  1305. if (!buf) {
  1306. IWL_ERR(priv, "Can not allocate Buffer\n");
  1307. return -ENOMEM;
  1308. }
  1309. pos += scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
  1310. data->active_chains);
  1311. pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
  1312. data->chain_noise_a);
  1313. pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
  1314. data->chain_noise_b);
  1315. pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
  1316. data->chain_noise_c);
  1317. pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
  1318. data->chain_signal_a);
  1319. pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
  1320. data->chain_signal_b);
  1321. pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
  1322. data->chain_signal_c);
  1323. pos += scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
  1324. data->beacon_count);
  1325. pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
  1326. for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
  1327. pos += scnprintf(buf + pos, bufsz - pos, " %u",
  1328. data->disconn_array[cnt]);
  1329. }
  1330. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  1331. pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
  1332. for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
  1333. pos += scnprintf(buf + pos, bufsz - pos, " %u",
  1334. data->delta_gain_code[cnt]);
  1335. }
  1336. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  1337. pos += scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
  1338. data->radio_write);
  1339. pos += scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
  1340. data->state);
  1341. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  1342. kfree(buf);
  1343. return ret;
  1344. }
  1345. DEBUGFS_READ_WRITE_FILE_OPS(rx_statistics);
  1346. DEBUGFS_READ_WRITE_FILE_OPS(tx_statistics);
  1347. DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
  1348. DEBUGFS_READ_FILE_OPS(rx_queue);
  1349. DEBUGFS_READ_FILE_OPS(tx_queue);
  1350. DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
  1351. DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
  1352. DEBUGFS_READ_FILE_OPS(ucode_general_stats);
  1353. DEBUGFS_READ_FILE_OPS(sensitivity);
  1354. DEBUGFS_READ_FILE_OPS(chain_noise);
  1355. /*
  1356. * Create the debugfs files and directories
  1357. *
  1358. */
  1359. int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
  1360. {
  1361. struct iwl_debugfs *dbgfs;
  1362. struct dentry *phyd = priv->hw->wiphy->debugfsdir;
  1363. int ret = 0;
  1364. dbgfs = kzalloc(sizeof(struct iwl_debugfs), GFP_KERNEL);
  1365. if (!dbgfs) {
  1366. ret = -ENOMEM;
  1367. goto err;
  1368. }
  1369. priv->dbgfs = dbgfs;
  1370. dbgfs->name = name;
  1371. dbgfs->dir_drv = debugfs_create_dir(name, phyd);
  1372. if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)) {
  1373. ret = -ENOENT;
  1374. goto err;
  1375. }
  1376. DEBUGFS_ADD_DIR(data, dbgfs->dir_drv);
  1377. DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv);
  1378. DEBUGFS_ADD_DIR(debug, dbgfs->dir_drv);
  1379. DEBUGFS_ADD_FILE(nvm, data);
  1380. DEBUGFS_ADD_FILE(sram, data);
  1381. DEBUGFS_ADD_FILE(log_event, data);
  1382. DEBUGFS_ADD_FILE(stations, data);
  1383. DEBUGFS_ADD_FILE(channels, data);
  1384. DEBUGFS_ADD_FILE(status, data);
  1385. DEBUGFS_ADD_FILE(interrupt, data);
  1386. DEBUGFS_ADD_FILE(qos, data);
  1387. #ifdef CONFIG_IWLWIFI_LEDS
  1388. DEBUGFS_ADD_FILE(led, data);
  1389. #endif
  1390. DEBUGFS_ADD_FILE(thermal_throttling, data);
  1391. DEBUGFS_ADD_FILE(disable_ht40, data);
  1392. DEBUGFS_ADD_FILE(rx_statistics, debug);
  1393. DEBUGFS_ADD_FILE(tx_statistics, debug);
  1394. DEBUGFS_ADD_FILE(traffic_log, debug);
  1395. DEBUGFS_ADD_FILE(rx_queue, debug);
  1396. DEBUGFS_ADD_FILE(tx_queue, debug);
  1397. if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
  1398. DEBUGFS_ADD_FILE(ucode_rx_stats, debug);
  1399. DEBUGFS_ADD_FILE(ucode_tx_stats, debug);
  1400. DEBUGFS_ADD_FILE(ucode_general_stats, debug);
  1401. DEBUGFS_ADD_FILE(sensitivity, debug);
  1402. DEBUGFS_ADD_FILE(chain_noise, debug);
  1403. }
  1404. DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal);
  1405. DEBUGFS_ADD_BOOL(disable_chain_noise, rf,
  1406. &priv->disable_chain_noise_cal);
  1407. if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) ||
  1408. ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945))
  1409. DEBUGFS_ADD_BOOL(disable_tx_power, rf,
  1410. &priv->disable_tx_power_cal);
  1411. return 0;
  1412. err:
  1413. IWL_ERR(priv, "Can't open the debugfs directory\n");
  1414. iwl_dbgfs_unregister(priv);
  1415. return ret;
  1416. }
  1417. EXPORT_SYMBOL(iwl_dbgfs_register);
  1418. /**
  1419. * Remove the debugfs files and directories
  1420. *
  1421. */
  1422. void iwl_dbgfs_unregister(struct iwl_priv *priv)
  1423. {
  1424. if (!priv->dbgfs)
  1425. return;
  1426. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm);
  1427. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
  1428. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event);
  1429. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
  1430. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels);
  1431. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status);
  1432. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt);
  1433. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_qos);
  1434. #ifdef CONFIG_IWLWIFI_LEDS
  1435. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_led);
  1436. #endif
  1437. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling);
  1438. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40);
  1439. DEBUGFS_REMOVE(priv->dbgfs->dir_data);
  1440. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_statistics);
  1441. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_statistics);
  1442. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_traffic_log);
  1443. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_queue);
  1444. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue);
  1445. if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
  1446. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
  1447. file_ucode_rx_stats);
  1448. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
  1449. file_ucode_tx_stats);
  1450. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
  1451. file_ucode_general_stats);
  1452. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
  1453. file_sensitivity);
  1454. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
  1455. file_chain_noise);
  1456. }
  1457. DEBUGFS_REMOVE(priv->dbgfs->dir_debug);
  1458. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity);
  1459. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise);
  1460. if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) ||
  1461. ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945))
  1462. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_tx_power);
  1463. DEBUGFS_REMOVE(priv->dbgfs->dir_rf);
  1464. DEBUGFS_REMOVE(priv->dbgfs->dir_drv);
  1465. kfree(priv->dbgfs);
  1466. priv->dbgfs = NULL;
  1467. }
  1468. EXPORT_SYMBOL(iwl_dbgfs_unregister);