iwl-debugfs.c 44 KB

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