iwl-debugfs.c 50 KB

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