iwl-debugfs.c 65 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976
  1. /******************************************************************************
  2. *
  3. * GPL LICENSE SUMMARY
  4. *
  5. * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved.
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of version 2 of the GNU General Public License as
  9. * published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
  19. * USA
  20. *
  21. * The full GNU General Public License is included in this distribution
  22. * in the file called LICENSE.GPL.
  23. *
  24. * Contact Information:
  25. * Intel Linux Wireless <ilw@linux.intel.com>
  26. * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  27. *****************************************************************************/
  28. #include <linux/kernel.h>
  29. #include <linux/module.h>
  30. #include <linux/debugfs.h>
  31. #include <linux/ieee80211.h>
  32. #include <net/mac80211.h>
  33. #include "iwl-dev.h"
  34. #include "iwl-debug.h"
  35. #include "iwl-core.h"
  36. #include "iwl-io.h"
  37. #include "iwl-calib.h"
  38. /* create and remove of files */
  39. #define DEBUGFS_ADD_DIR(name, parent) do { \
  40. dbgfs->dir_##name = debugfs_create_dir(#name, parent); \
  41. if (!(dbgfs->dir_##name)) \
  42. goto err; \
  43. } while (0)
  44. #define DEBUGFS_ADD_FILE(name, parent, mode) do { \
  45. dbgfs->dbgfs_##parent##_files.file_##name = \
  46. debugfs_create_file(#name, mode, \
  47. dbgfs->dir_##parent, priv, \
  48. &iwl_dbgfs_##name##_ops); \
  49. if (!(dbgfs->dbgfs_##parent##_files.file_##name)) \
  50. goto err; \
  51. } while (0)
  52. #define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \
  53. dbgfs->dbgfs_##parent##_files.file_##name = \
  54. debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \
  55. dbgfs->dir_##parent, ptr); \
  56. if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \
  57. || !dbgfs->dbgfs_##parent##_files.file_##name) \
  58. goto err; \
  59. } while (0)
  60. #define DEBUGFS_ADD_X32(name, parent, ptr) do { \
  61. dbgfs->dbgfs_##parent##_files.file_##name = \
  62. debugfs_create_x32(#name, S_IRUSR, dbgfs->dir_##parent, ptr); \
  63. if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \
  64. || !dbgfs->dbgfs_##parent##_files.file_##name) \
  65. goto err; \
  66. } while (0)
  67. #define DEBUGFS_REMOVE(name) do { \
  68. debugfs_remove(name); \
  69. name = NULL; \
  70. } while (0);
  71. /* file operation */
  72. #define DEBUGFS_READ_FUNC(name) \
  73. static ssize_t iwl_dbgfs_##name##_read(struct file *file, \
  74. char __user *user_buf, \
  75. size_t count, loff_t *ppos);
  76. #define DEBUGFS_WRITE_FUNC(name) \
  77. static ssize_t iwl_dbgfs_##name##_write(struct file *file, \
  78. const char __user *user_buf, \
  79. size_t count, loff_t *ppos);
  80. static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file)
  81. {
  82. file->private_data = inode->i_private;
  83. return 0;
  84. }
  85. #define DEBUGFS_READ_FILE_OPS(name) \
  86. DEBUGFS_READ_FUNC(name); \
  87. static const struct file_operations iwl_dbgfs_##name##_ops = { \
  88. .read = iwl_dbgfs_##name##_read, \
  89. .open = iwl_dbgfs_open_file_generic, \
  90. };
  91. #define DEBUGFS_WRITE_FILE_OPS(name) \
  92. DEBUGFS_WRITE_FUNC(name); \
  93. static const struct file_operations iwl_dbgfs_##name##_ops = { \
  94. .write = iwl_dbgfs_##name##_write, \
  95. .open = iwl_dbgfs_open_file_generic, \
  96. };
  97. #define DEBUGFS_READ_WRITE_FILE_OPS(name) \
  98. DEBUGFS_READ_FUNC(name); \
  99. DEBUGFS_WRITE_FUNC(name); \
  100. static const struct file_operations iwl_dbgfs_##name##_ops = { \
  101. .write = iwl_dbgfs_##name##_write, \
  102. .read = iwl_dbgfs_##name##_read, \
  103. .open = iwl_dbgfs_open_file_generic, \
  104. };
  105. static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file,
  106. char __user *user_buf,
  107. size_t count, loff_t *ppos) {
  108. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  109. char *buf;
  110. int pos = 0;
  111. int cnt;
  112. ssize_t ret;
  113. const size_t bufsz = 100 +
  114. sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
  115. buf = kzalloc(bufsz, GFP_KERNEL);
  116. if (!buf)
  117. return -ENOMEM;
  118. pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
  119. for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
  120. pos += scnprintf(buf + pos, bufsz - pos,
  121. "\t%25s\t\t: %u\n",
  122. get_mgmt_string(cnt),
  123. priv->tx_stats.mgmt[cnt]);
  124. }
  125. pos += scnprintf(buf + pos, bufsz - pos, "Control\n");
  126. for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
  127. pos += scnprintf(buf + pos, bufsz - pos,
  128. "\t%25s\t\t: %u\n",
  129. get_ctrl_string(cnt),
  130. priv->tx_stats.ctrl[cnt]);
  131. }
  132. pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
  133. pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
  134. priv->tx_stats.data_cnt);
  135. pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
  136. priv->tx_stats.data_bytes);
  137. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  138. kfree(buf);
  139. return ret;
  140. }
  141. static ssize_t iwl_dbgfs_clear_traffic_statistics_write(struct file *file,
  142. const char __user *user_buf,
  143. size_t count, loff_t *ppos)
  144. {
  145. struct iwl_priv *priv = file->private_data;
  146. u32 clear_flag;
  147. char buf[8];
  148. int buf_size;
  149. memset(buf, 0, sizeof(buf));
  150. buf_size = min(count, sizeof(buf) - 1);
  151. if (copy_from_user(buf, user_buf, buf_size))
  152. return -EFAULT;
  153. if (sscanf(buf, "%x", &clear_flag) != 1)
  154. return -EFAULT;
  155. iwl_clear_traffic_stats(priv);
  156. return count;
  157. }
  158. static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file,
  159. char __user *user_buf,
  160. size_t count, loff_t *ppos) {
  161. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  162. char *buf;
  163. int pos = 0;
  164. int cnt;
  165. ssize_t ret;
  166. const size_t bufsz = 100 +
  167. sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
  168. buf = kzalloc(bufsz, GFP_KERNEL);
  169. if (!buf)
  170. return -ENOMEM;
  171. pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
  172. for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
  173. pos += scnprintf(buf + pos, bufsz - pos,
  174. "\t%25s\t\t: %u\n",
  175. get_mgmt_string(cnt),
  176. priv->rx_stats.mgmt[cnt]);
  177. }
  178. pos += scnprintf(buf + pos, bufsz - pos, "Control:\n");
  179. for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
  180. pos += scnprintf(buf + pos, bufsz - pos,
  181. "\t%25s\t\t: %u\n",
  182. get_ctrl_string(cnt),
  183. priv->rx_stats.ctrl[cnt]);
  184. }
  185. pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
  186. pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
  187. priv->rx_stats.data_cnt);
  188. pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
  189. priv->rx_stats.data_bytes);
  190. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  191. kfree(buf);
  192. return ret;
  193. }
  194. #define BYTE1_MASK 0x000000ff;
  195. #define BYTE2_MASK 0x0000ffff;
  196. #define BYTE3_MASK 0x00ffffff;
  197. static ssize_t iwl_dbgfs_sram_read(struct file *file,
  198. char __user *user_buf,
  199. size_t count, loff_t *ppos)
  200. {
  201. u32 val;
  202. char buf[1024];
  203. ssize_t ret;
  204. int i;
  205. int pos = 0;
  206. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  207. const size_t bufsz = sizeof(buf);
  208. for (i = priv->dbgfs->sram_len; i > 0; i -= 4) {
  209. val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \
  210. priv->dbgfs->sram_len - i);
  211. if (i < 4) {
  212. switch (i) {
  213. case 1:
  214. val &= BYTE1_MASK;
  215. break;
  216. case 2:
  217. val &= BYTE2_MASK;
  218. break;
  219. case 3:
  220. val &= BYTE3_MASK;
  221. break;
  222. }
  223. }
  224. pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
  225. }
  226. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  227. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  228. return ret;
  229. }
  230. static ssize_t iwl_dbgfs_sram_write(struct file *file,
  231. const char __user *user_buf,
  232. size_t count, loff_t *ppos)
  233. {
  234. struct iwl_priv *priv = file->private_data;
  235. char buf[64];
  236. int buf_size;
  237. u32 offset, len;
  238. memset(buf, 0, sizeof(buf));
  239. buf_size = min(count, sizeof(buf) - 1);
  240. if (copy_from_user(buf, user_buf, buf_size))
  241. return -EFAULT;
  242. if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
  243. priv->dbgfs->sram_offset = offset;
  244. priv->dbgfs->sram_len = len;
  245. } else {
  246. priv->dbgfs->sram_offset = 0;
  247. priv->dbgfs->sram_len = 0;
  248. }
  249. return count;
  250. }
  251. static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
  252. size_t count, loff_t *ppos)
  253. {
  254. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  255. struct iwl_station_entry *station;
  256. int max_sta = priv->hw_params.max_stations;
  257. char *buf;
  258. int i, j, pos = 0;
  259. ssize_t ret;
  260. /* Add 30 for initial string */
  261. const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations);
  262. buf = kmalloc(bufsz, GFP_KERNEL);
  263. if (!buf)
  264. return -ENOMEM;
  265. pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
  266. priv->num_stations);
  267. for (i = 0; i < max_sta; i++) {
  268. station = &priv->stations[i];
  269. if (station->used) {
  270. pos += scnprintf(buf + pos, bufsz - pos,
  271. "station %d:\ngeneral data:\n", i+1);
  272. pos += scnprintf(buf + pos, bufsz - pos, "id: %u\n",
  273. station->sta.sta.sta_id);
  274. pos += scnprintf(buf + pos, bufsz - pos, "mode: %u\n",
  275. station->sta.mode);
  276. pos += scnprintf(buf + pos, bufsz - pos,
  277. "flags: 0x%x\n",
  278. station->sta.station_flags_msk);
  279. pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n");
  280. pos += scnprintf(buf + pos, bufsz - pos,
  281. "seq_num\t\ttxq_id");
  282. pos += scnprintf(buf + pos, bufsz - pos,
  283. "\tframe_count\twait_for_ba\t");
  284. pos += scnprintf(buf + pos, bufsz - pos,
  285. "start_idx\tbitmap0\t");
  286. pos += scnprintf(buf + pos, bufsz - pos,
  287. "bitmap1\trate_n_flags");
  288. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  289. for (j = 0; j < MAX_TID_COUNT; j++) {
  290. pos += scnprintf(buf + pos, bufsz - pos,
  291. "[%d]:\t\t%u", j,
  292. station->tid[j].seq_number);
  293. pos += scnprintf(buf + pos, bufsz - pos,
  294. "\t%u\t\t%u\t\t%u\t\t",
  295. station->tid[j].agg.txq_id,
  296. station->tid[j].agg.frame_count,
  297. station->tid[j].agg.wait_for_ba);
  298. pos += scnprintf(buf + pos, bufsz - pos,
  299. "%u\t%llu\t%u",
  300. station->tid[j].agg.start_idx,
  301. (unsigned long long)station->tid[j].agg.bitmap,
  302. station->tid[j].agg.rate_n_flags);
  303. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  304. }
  305. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  306. }
  307. }
  308. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  309. kfree(buf);
  310. return ret;
  311. }
  312. static ssize_t iwl_dbgfs_nvm_read(struct file *file,
  313. char __user *user_buf,
  314. size_t count,
  315. loff_t *ppos)
  316. {
  317. ssize_t ret;
  318. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  319. int pos = 0, ofs = 0, buf_size = 0;
  320. const u8 *ptr;
  321. char *buf;
  322. u16 eeprom_ver;
  323. size_t eeprom_len = priv->cfg->eeprom_size;
  324. buf_size = 4 * eeprom_len + 256;
  325. if (eeprom_len % 16) {
  326. IWL_ERR(priv, "NVM size is not multiple of 16.\n");
  327. return -ENODATA;
  328. }
  329. ptr = priv->eeprom;
  330. if (!ptr) {
  331. IWL_ERR(priv, "Invalid EEPROM/OTP memory\n");
  332. return -ENOMEM;
  333. }
  334. /* 4 characters for byte 0xYY */
  335. buf = kzalloc(buf_size, GFP_KERNEL);
  336. if (!buf) {
  337. IWL_ERR(priv, "Can not allocate Buffer\n");
  338. return -ENOMEM;
  339. }
  340. eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
  341. pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s, "
  342. "version: 0x%x\n",
  343. (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
  344. ? "OTP" : "EEPROM", eeprom_ver);
  345. for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) {
  346. pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs);
  347. hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos,
  348. buf_size - pos, 0);
  349. pos += strlen(buf + pos);
  350. if (buf_size - pos > 0)
  351. buf[pos++] = '\n';
  352. }
  353. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  354. kfree(buf);
  355. return ret;
  356. }
  357. static ssize_t iwl_dbgfs_log_event_write(struct file *file,
  358. const char __user *user_buf,
  359. size_t count, loff_t *ppos)
  360. {
  361. struct iwl_priv *priv = file->private_data;
  362. u32 event_log_flag;
  363. char buf[8];
  364. int buf_size;
  365. memset(buf, 0, sizeof(buf));
  366. buf_size = min(count, sizeof(buf) - 1);
  367. if (copy_from_user(buf, user_buf, buf_size))
  368. return -EFAULT;
  369. if (sscanf(buf, "%d", &event_log_flag) != 1)
  370. return -EFAULT;
  371. if (event_log_flag == 1)
  372. priv->cfg->ops->lib->dump_nic_event_log(priv);
  373. return count;
  374. }
  375. static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
  376. size_t count, loff_t *ppos)
  377. {
  378. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  379. struct ieee80211_channel *channels = NULL;
  380. const struct ieee80211_supported_band *supp_band = NULL;
  381. int pos = 0, i, bufsz = PAGE_SIZE;
  382. char *buf;
  383. ssize_t ret;
  384. if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
  385. return -EAGAIN;
  386. buf = kzalloc(bufsz, GFP_KERNEL);
  387. if (!buf) {
  388. IWL_ERR(priv, "Can not allocate Buffer\n");
  389. return -ENOMEM;
  390. }
  391. supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ);
  392. if (supp_band) {
  393. channels = supp_band->channels;
  394. pos += scnprintf(buf + pos, bufsz - pos,
  395. "Displaying %d channels in 2.4GHz band 802.11bg):\n",
  396. supp_band->n_channels);
  397. for (i = 0; i < supp_band->n_channels; i++)
  398. pos += scnprintf(buf + pos, bufsz - pos,
  399. "%d: %ddBm: BSS%s%s, %s.\n",
  400. ieee80211_frequency_to_channel(
  401. channels[i].center_freq),
  402. channels[i].max_power,
  403. channels[i].flags & IEEE80211_CHAN_RADAR ?
  404. " (IEEE 802.11h required)" : "",
  405. ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
  406. || (channels[i].flags &
  407. IEEE80211_CHAN_RADAR)) ? "" :
  408. ", IBSS",
  409. channels[i].flags &
  410. IEEE80211_CHAN_PASSIVE_SCAN ?
  411. "passive only" : "active/passive");
  412. }
  413. supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ);
  414. if (supp_band) {
  415. channels = supp_band->channels;
  416. pos += scnprintf(buf + pos, bufsz - pos,
  417. "Displaying %d channels in 5.2GHz band (802.11a)\n",
  418. supp_band->n_channels);
  419. for (i = 0; i < supp_band->n_channels; i++)
  420. pos += scnprintf(buf + pos, bufsz - pos,
  421. "%d: %ddBm: BSS%s%s, %s.\n",
  422. ieee80211_frequency_to_channel(
  423. channels[i].center_freq),
  424. channels[i].max_power,
  425. channels[i].flags & IEEE80211_CHAN_RADAR ?
  426. " (IEEE 802.11h required)" : "",
  427. ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
  428. || (channels[i].flags &
  429. IEEE80211_CHAN_RADAR)) ? "" :
  430. ", IBSS",
  431. channels[i].flags &
  432. IEEE80211_CHAN_PASSIVE_SCAN ?
  433. "passive only" : "active/passive");
  434. }
  435. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  436. kfree(buf);
  437. return ret;
  438. }
  439. static ssize_t iwl_dbgfs_status_read(struct file *file,
  440. char __user *user_buf,
  441. size_t count, loff_t *ppos) {
  442. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  443. char buf[512];
  444. int pos = 0;
  445. const size_t bufsz = sizeof(buf);
  446. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n",
  447. test_bit(STATUS_HCMD_ACTIVE, &priv->status));
  448. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_SYNC_ACTIVE: %d\n",
  449. test_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status));
  450. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n",
  451. test_bit(STATUS_INT_ENABLED, &priv->status));
  452. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
  453. test_bit(STATUS_RF_KILL_HW, &priv->status));
  454. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n",
  455. test_bit(STATUS_CT_KILL, &priv->status));
  456. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n",
  457. test_bit(STATUS_INIT, &priv->status));
  458. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n",
  459. test_bit(STATUS_ALIVE, &priv->status));
  460. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n",
  461. test_bit(STATUS_READY, &priv->status));
  462. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n",
  463. test_bit(STATUS_TEMPERATURE, &priv->status));
  464. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n",
  465. test_bit(STATUS_GEO_CONFIGURED, &priv->status));
  466. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n",
  467. test_bit(STATUS_EXIT_PENDING, &priv->status));
  468. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n",
  469. test_bit(STATUS_STATISTICS, &priv->status));
  470. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n",
  471. test_bit(STATUS_SCANNING, &priv->status));
  472. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n",
  473. test_bit(STATUS_SCAN_ABORTING, &priv->status));
  474. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n",
  475. test_bit(STATUS_SCAN_HW, &priv->status));
  476. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n",
  477. test_bit(STATUS_POWER_PMI, &priv->status));
  478. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n",
  479. test_bit(STATUS_FW_ERROR, &priv->status));
  480. pos += scnprintf(buf + pos, bufsz - pos, "STATUS_MODE_PENDING:\t %d\n",
  481. test_bit(STATUS_MODE_PENDING, &priv->status));
  482. return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  483. }
  484. static ssize_t iwl_dbgfs_interrupt_read(struct file *file,
  485. char __user *user_buf,
  486. size_t count, loff_t *ppos) {
  487. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  488. int pos = 0;
  489. int cnt = 0;
  490. char *buf;
  491. int bufsz = 24 * 64; /* 24 items * 64 char per item */
  492. ssize_t ret;
  493. buf = kzalloc(bufsz, GFP_KERNEL);
  494. if (!buf) {
  495. IWL_ERR(priv, "Can not allocate Buffer\n");
  496. return -ENOMEM;
  497. }
  498. pos += scnprintf(buf + pos, bufsz - pos,
  499. "Interrupt Statistics Report:\n");
  500. pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
  501. priv->isr_stats.hw);
  502. pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
  503. priv->isr_stats.sw);
  504. if (priv->isr_stats.sw > 0) {
  505. pos += scnprintf(buf + pos, bufsz - pos,
  506. "\tLast Restarting Code: 0x%X\n",
  507. priv->isr_stats.sw_err);
  508. }
  509. #ifdef CONFIG_IWLWIFI_DEBUG
  510. pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
  511. priv->isr_stats.sch);
  512. pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
  513. priv->isr_stats.alive);
  514. #endif
  515. pos += scnprintf(buf + pos, bufsz - pos,
  516. "HW RF KILL switch toggled:\t %u\n",
  517. priv->isr_stats.rfkill);
  518. pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
  519. priv->isr_stats.ctkill);
  520. pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
  521. priv->isr_stats.wakeup);
  522. pos += scnprintf(buf + pos, bufsz - pos,
  523. "Rx command responses:\t\t %u\n",
  524. priv->isr_stats.rx);
  525. for (cnt = 0; cnt < REPLY_MAX; cnt++) {
  526. if (priv->isr_stats.rx_handlers[cnt] > 0)
  527. pos += scnprintf(buf + pos, bufsz - pos,
  528. "\tRx handler[%36s]:\t\t %u\n",
  529. get_cmd_string(cnt),
  530. priv->isr_stats.rx_handlers[cnt]);
  531. }
  532. pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
  533. priv->isr_stats.tx);
  534. pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
  535. priv->isr_stats.unhandled);
  536. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  537. kfree(buf);
  538. return ret;
  539. }
  540. static ssize_t iwl_dbgfs_interrupt_write(struct file *file,
  541. const char __user *user_buf,
  542. size_t count, loff_t *ppos)
  543. {
  544. struct iwl_priv *priv = file->private_data;
  545. char buf[8];
  546. int buf_size;
  547. u32 reset_flag;
  548. memset(buf, 0, sizeof(buf));
  549. buf_size = min(count, sizeof(buf) - 1);
  550. if (copy_from_user(buf, user_buf, buf_size))
  551. return -EFAULT;
  552. if (sscanf(buf, "%x", &reset_flag) != 1)
  553. return -EFAULT;
  554. if (reset_flag == 0)
  555. iwl_clear_isr_stats(priv);
  556. return count;
  557. }
  558. static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf,
  559. size_t count, loff_t *ppos)
  560. {
  561. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  562. int pos = 0, i;
  563. char buf[256];
  564. const size_t bufsz = sizeof(buf);
  565. ssize_t ret;
  566. for (i = 0; i < AC_NUM; i++) {
  567. pos += scnprintf(buf + pos, bufsz - pos,
  568. "\tcw_min\tcw_max\taifsn\ttxop\n");
  569. pos += scnprintf(buf + pos, bufsz - pos,
  570. "AC[%d]\t%u\t%u\t%u\t%u\n", i,
  571. priv->qos_data.def_qos_parm.ac[i].cw_min,
  572. priv->qos_data.def_qos_parm.ac[i].cw_max,
  573. priv->qos_data.def_qos_parm.ac[i].aifsn,
  574. priv->qos_data.def_qos_parm.ac[i].edca_txop);
  575. }
  576. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  577. return ret;
  578. }
  579. static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf,
  580. size_t count, loff_t *ppos)
  581. {
  582. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  583. int pos = 0;
  584. char buf[256];
  585. const size_t bufsz = sizeof(buf);
  586. ssize_t ret;
  587. pos += scnprintf(buf + pos, bufsz - pos,
  588. "allow blinking: %s\n",
  589. (priv->allow_blinking) ? "True" : "False");
  590. if (priv->allow_blinking) {
  591. pos += scnprintf(buf + pos, bufsz - pos,
  592. "Led blinking rate: %u\n",
  593. priv->last_blink_rate);
  594. pos += scnprintf(buf + pos, bufsz - pos,
  595. "Last blink time: %lu\n",
  596. priv->last_blink_time);
  597. }
  598. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  599. return ret;
  600. }
  601. static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
  602. char __user *user_buf,
  603. size_t count, loff_t *ppos)
  604. {
  605. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  606. struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
  607. struct iwl_tt_restriction *restriction;
  608. char buf[100];
  609. int pos = 0;
  610. const size_t bufsz = sizeof(buf);
  611. ssize_t ret;
  612. pos += scnprintf(buf + pos, bufsz - pos,
  613. "Thermal Throttling Mode: %s\n",
  614. tt->advanced_tt ? "Advance" : "Legacy");
  615. pos += scnprintf(buf + pos, bufsz - pos,
  616. "Thermal Throttling State: %d\n",
  617. tt->state);
  618. if (tt->advanced_tt) {
  619. restriction = tt->restriction + tt->state;
  620. pos += scnprintf(buf + pos, bufsz - pos,
  621. "Tx mode: %d\n",
  622. restriction->tx_stream);
  623. pos += scnprintf(buf + pos, bufsz - pos,
  624. "Rx mode: %d\n",
  625. restriction->rx_stream);
  626. pos += scnprintf(buf + pos, bufsz - pos,
  627. "HT mode: %d\n",
  628. restriction->is_ht);
  629. }
  630. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  631. return ret;
  632. }
  633. static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file,
  634. const char __user *user_buf,
  635. size_t count, loff_t *ppos)
  636. {
  637. struct iwl_priv *priv = file->private_data;
  638. char buf[8];
  639. int buf_size;
  640. int ht40;
  641. memset(buf, 0, sizeof(buf));
  642. buf_size = min(count, sizeof(buf) - 1);
  643. if (copy_from_user(buf, user_buf, buf_size))
  644. return -EFAULT;
  645. if (sscanf(buf, "%d", &ht40) != 1)
  646. return -EFAULT;
  647. if (!iwl_is_associated(priv))
  648. priv->disable_ht40 = ht40 ? true : false;
  649. else {
  650. IWL_ERR(priv, "Sta associated with AP - "
  651. "Change to 40MHz channel support is not allowed\n");
  652. return -EINVAL;
  653. }
  654. return count;
  655. }
  656. static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file,
  657. char __user *user_buf,
  658. size_t count, loff_t *ppos)
  659. {
  660. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  661. char buf[100];
  662. int pos = 0;
  663. const size_t bufsz = sizeof(buf);
  664. ssize_t ret;
  665. pos += scnprintf(buf + pos, bufsz - pos,
  666. "11n 40MHz Mode: %s\n",
  667. priv->disable_ht40 ? "Disabled" : "Enabled");
  668. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  669. return ret;
  670. }
  671. static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file,
  672. const char __user *user_buf,
  673. size_t count, loff_t *ppos)
  674. {
  675. struct iwl_priv *priv = file->private_data;
  676. char buf[8];
  677. int buf_size;
  678. int value;
  679. memset(buf, 0, sizeof(buf));
  680. buf_size = min(count, sizeof(buf) - 1);
  681. if (copy_from_user(buf, user_buf, buf_size))
  682. return -EFAULT;
  683. if (sscanf(buf, "%d", &value) != 1)
  684. return -EINVAL;
  685. /*
  686. * Our users expect 0 to be "CAM", but 0 isn't actually
  687. * valid here. However, let's not confuse them and present
  688. * IWL_POWER_INDEX_1 as "1", not "0".
  689. */
  690. if (value == 0)
  691. return -EINVAL;
  692. else if (value > 0)
  693. value -= 1;
  694. if (value != -1 && (value < 0 || value >= IWL_POWER_NUM))
  695. return -EINVAL;
  696. if (!iwl_is_ready_rf(priv))
  697. return -EAGAIN;
  698. priv->power_data.debug_sleep_level_override = value;
  699. iwl_power_update_mode(priv, true);
  700. return count;
  701. }
  702. static ssize_t iwl_dbgfs_sleep_level_override_read(struct file *file,
  703. char __user *user_buf,
  704. size_t count, loff_t *ppos)
  705. {
  706. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  707. char buf[10];
  708. int pos, value;
  709. const size_t bufsz = sizeof(buf);
  710. /* see the write function */
  711. value = priv->power_data.debug_sleep_level_override;
  712. if (value >= 0)
  713. value += 1;
  714. pos = scnprintf(buf, bufsz, "%d\n", value);
  715. return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  716. }
  717. static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file,
  718. char __user *user_buf,
  719. size_t count, loff_t *ppos)
  720. {
  721. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  722. char buf[200];
  723. int pos = 0, i;
  724. const size_t bufsz = sizeof(buf);
  725. struct iwl_powertable_cmd *cmd = &priv->power_data.sleep_cmd;
  726. pos += scnprintf(buf + pos, bufsz - pos,
  727. "flags: %#.2x\n", le16_to_cpu(cmd->flags));
  728. pos += scnprintf(buf + pos, bufsz - pos,
  729. "RX/TX timeout: %d/%d usec\n",
  730. le32_to_cpu(cmd->rx_data_timeout),
  731. le32_to_cpu(cmd->tx_data_timeout));
  732. for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
  733. pos += scnprintf(buf + pos, bufsz - pos,
  734. "sleep_interval[%d]: %d\n", i,
  735. le32_to_cpu(cmd->sleep_interval[i]));
  736. return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  737. }
  738. DEBUGFS_READ_WRITE_FILE_OPS(sram);
  739. DEBUGFS_WRITE_FILE_OPS(log_event);
  740. DEBUGFS_READ_FILE_OPS(nvm);
  741. DEBUGFS_READ_FILE_OPS(stations);
  742. DEBUGFS_READ_FILE_OPS(channels);
  743. DEBUGFS_READ_FILE_OPS(status);
  744. DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
  745. DEBUGFS_READ_FILE_OPS(qos);
  746. DEBUGFS_READ_FILE_OPS(led);
  747. DEBUGFS_READ_FILE_OPS(thermal_throttling);
  748. DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
  749. DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override);
  750. DEBUGFS_READ_FILE_OPS(current_sleep_command);
  751. static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
  752. char __user *user_buf,
  753. size_t count, loff_t *ppos)
  754. {
  755. struct iwl_priv *priv = file->private_data;
  756. int pos = 0, ofs = 0;
  757. int cnt = 0, entry;
  758. struct iwl_tx_queue *txq;
  759. struct iwl_queue *q;
  760. struct iwl_rx_queue *rxq = &priv->rxq;
  761. char *buf;
  762. int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
  763. (priv->cfg->num_of_queues * 32 * 8) + 400;
  764. const u8 *ptr;
  765. ssize_t ret;
  766. if (!priv->txq) {
  767. IWL_ERR(priv, "txq not ready\n");
  768. return -EAGAIN;
  769. }
  770. buf = kzalloc(bufsz, GFP_KERNEL);
  771. if (!buf) {
  772. IWL_ERR(priv, "Can not allocate buffer\n");
  773. return -ENOMEM;
  774. }
  775. pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n");
  776. for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
  777. txq = &priv->txq[cnt];
  778. q = &txq->q;
  779. pos += scnprintf(buf + pos, bufsz - pos,
  780. "q[%d]: read_ptr: %u, write_ptr: %u\n",
  781. cnt, q->read_ptr, q->write_ptr);
  782. }
  783. if (priv->tx_traffic && (iwl_debug_level & IWL_DL_TX)) {
  784. ptr = priv->tx_traffic;
  785. pos += scnprintf(buf + pos, bufsz - pos,
  786. "Tx Traffic idx: %u\n", priv->tx_traffic_idx);
  787. for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
  788. for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
  789. entry++, ofs += 16) {
  790. pos += scnprintf(buf + pos, bufsz - pos,
  791. "0x%.4x ", ofs);
  792. hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
  793. buf + pos, bufsz - pos, 0);
  794. pos += strlen(buf + pos);
  795. if (bufsz - pos > 0)
  796. buf[pos++] = '\n';
  797. }
  798. }
  799. }
  800. pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n");
  801. pos += scnprintf(buf + pos, bufsz - pos,
  802. "read: %u, write: %u\n",
  803. rxq->read, rxq->write);
  804. if (priv->rx_traffic && (iwl_debug_level & IWL_DL_RX)) {
  805. ptr = priv->rx_traffic;
  806. pos += scnprintf(buf + pos, bufsz - pos,
  807. "Rx Traffic idx: %u\n", priv->rx_traffic_idx);
  808. for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
  809. for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
  810. entry++, ofs += 16) {
  811. pos += scnprintf(buf + pos, bufsz - pos,
  812. "0x%.4x ", ofs);
  813. hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
  814. buf + pos, bufsz - pos, 0);
  815. pos += strlen(buf + pos);
  816. if (bufsz - pos > 0)
  817. buf[pos++] = '\n';
  818. }
  819. }
  820. }
  821. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  822. kfree(buf);
  823. return ret;
  824. }
  825. static ssize_t iwl_dbgfs_traffic_log_write(struct file *file,
  826. const char __user *user_buf,
  827. size_t count, loff_t *ppos)
  828. {
  829. struct iwl_priv *priv = file->private_data;
  830. char buf[8];
  831. int buf_size;
  832. int traffic_log;
  833. memset(buf, 0, sizeof(buf));
  834. buf_size = min(count, sizeof(buf) - 1);
  835. if (copy_from_user(buf, user_buf, buf_size))
  836. return -EFAULT;
  837. if (sscanf(buf, "%d", &traffic_log) != 1)
  838. return -EFAULT;
  839. if (traffic_log == 0)
  840. iwl_reset_traffic_log(priv);
  841. return count;
  842. }
  843. static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
  844. char __user *user_buf,
  845. size_t count, loff_t *ppos) {
  846. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  847. struct iwl_tx_queue *txq;
  848. struct iwl_queue *q;
  849. char *buf;
  850. int pos = 0;
  851. int cnt;
  852. int ret;
  853. const size_t bufsz = sizeof(char) * 60 * priv->cfg->num_of_queues;
  854. if (!priv->txq) {
  855. IWL_ERR(priv, "txq not ready\n");
  856. return -EAGAIN;
  857. }
  858. buf = kzalloc(bufsz, GFP_KERNEL);
  859. if (!buf)
  860. return -ENOMEM;
  861. for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
  862. txq = &priv->txq[cnt];
  863. q = &txq->q;
  864. pos += scnprintf(buf + pos, bufsz - pos,
  865. "hwq %.2d: read=%u write=%u stop=%d"
  866. " swq_id=%#.2x (ac %d/hwq %d)\n",
  867. cnt, q->read_ptr, q->write_ptr,
  868. !!test_bit(cnt, priv->queue_stopped),
  869. txq->swq_id,
  870. txq->swq_id & 0x80 ? txq->swq_id & 3 :
  871. txq->swq_id,
  872. txq->swq_id & 0x80 ? (txq->swq_id >> 2) &
  873. 0x1f : txq->swq_id);
  874. if (cnt >= 4)
  875. continue;
  876. /* for the ACs, display the stop count too */
  877. pos += scnprintf(buf + pos, bufsz - pos,
  878. " stop-count: %d\n",
  879. atomic_read(&priv->queue_stop_count[cnt]));
  880. }
  881. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  882. kfree(buf);
  883. return ret;
  884. }
  885. static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
  886. char __user *user_buf,
  887. size_t count, loff_t *ppos) {
  888. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  889. struct iwl_rx_queue *rxq = &priv->rxq;
  890. char buf[256];
  891. int pos = 0;
  892. const size_t bufsz = sizeof(buf);
  893. pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n",
  894. rxq->read);
  895. pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n",
  896. rxq->write);
  897. pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
  898. rxq->free_count);
  899. pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
  900. le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF);
  901. return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  902. }
  903. static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf,
  904. int bufsz)
  905. {
  906. int p = 0;
  907. p += scnprintf(buf + p, bufsz - p,
  908. "Statistics Flag(0x%X):\n",
  909. le32_to_cpu(priv->statistics.flag));
  910. if (le32_to_cpu(priv->statistics.flag) & UCODE_STATISTICS_CLEAR_MSK)
  911. p += scnprintf(buf + p, bufsz - p,
  912. "\tStatistics have been cleared\n");
  913. p += scnprintf(buf + p, bufsz - p,
  914. "\tOperational Frequency: %s\n",
  915. (le32_to_cpu(priv->statistics.flag) &
  916. UCODE_STATISTICS_FREQUENCY_MSK)
  917. ? "2.4 GHz" : "5.2 GHz");
  918. p += scnprintf(buf + p, bufsz - p,
  919. "\tTGj Narrow Band: %s\n",
  920. (le32_to_cpu(priv->statistics.flag) &
  921. UCODE_STATISTICS_NARROW_BAND_MSK)
  922. ? "enabled" : "disabled");
  923. return p;
  924. }
  925. static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
  926. char __user *user_buf,
  927. size_t count, loff_t *ppos)
  928. {
  929. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  930. int pos = 0;
  931. char *buf;
  932. int bufsz = sizeof(struct statistics_rx_phy) * 20 +
  933. sizeof(struct statistics_rx_non_phy) * 20 +
  934. sizeof(struct statistics_rx_ht_phy) * 20 + 400;
  935. ssize_t ret;
  936. struct statistics_rx_phy *ofdm, *accum_ofdm;
  937. struct statistics_rx_phy *cck, *accum_cck;
  938. struct statistics_rx_non_phy *general, *accum_general;
  939. struct statistics_rx_ht_phy *ht, *accum_ht;
  940. if (!iwl_is_alive(priv))
  941. return -EAGAIN;
  942. /* make request to uCode to retrieve statistics information */
  943. mutex_lock(&priv->mutex);
  944. ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
  945. mutex_unlock(&priv->mutex);
  946. if (ret) {
  947. IWL_ERR(priv,
  948. "Error sending statistics request: %zd\n", ret);
  949. return -EAGAIN;
  950. }
  951. buf = kzalloc(bufsz, GFP_KERNEL);
  952. if (!buf) {
  953. IWL_ERR(priv, "Can not allocate Buffer\n");
  954. return -ENOMEM;
  955. }
  956. /* the statistic information display here is based on
  957. * the last statistics notification from uCode
  958. * might not reflect the current uCode activity
  959. */
  960. ofdm = &priv->statistics.rx.ofdm;
  961. cck = &priv->statistics.rx.cck;
  962. general = &priv->statistics.rx.general;
  963. ht = &priv->statistics.rx.ofdm_ht;
  964. accum_ofdm = &priv->accum_statistics.rx.ofdm;
  965. accum_cck = &priv->accum_statistics.rx.cck;
  966. accum_general = &priv->accum_statistics.rx.general;
  967. accum_ht = &priv->accum_statistics.rx.ofdm_ht;
  968. pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
  969. pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM:\n");
  970. pos += scnprintf(buf + pos, bufsz - pos,
  971. "\t\t\tcurrent\t\t\taccumulative\n");
  972. pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt:\t\t%u\t\t\t%u\n",
  973. le32_to_cpu(ofdm->ina_cnt), accum_ofdm->ina_cnt);
  974. pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt:\t\t%u\t\t\t%u\n",
  975. le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt);
  976. pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n",
  977. le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err);
  978. pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n",
  979. le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err);
  980. pos += scnprintf(buf + pos, bufsz - pos,
  981. "overrun_err:\t\t%u\t\t\t%u\n",
  982. le32_to_cpu(ofdm->overrun_err),
  983. accum_ofdm->overrun_err);
  984. pos += scnprintf(buf + pos, bufsz - pos,
  985. "early_overrun_err:\t%u\t\t\t%u\n",
  986. le32_to_cpu(ofdm->early_overrun_err),
  987. accum_ofdm->early_overrun_err);
  988. pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n",
  989. le32_to_cpu(ofdm->crc32_good),
  990. accum_ofdm->crc32_good);
  991. pos += scnprintf(buf + pos, bufsz - pos,
  992. "false_alarm_cnt:\t%u\t\t\t%u\n",
  993. le32_to_cpu(ofdm->false_alarm_cnt),
  994. accum_ofdm->false_alarm_cnt);
  995. pos += scnprintf(buf + pos, bufsz - pos,
  996. "fina_sync_err_cnt:\t%u\t\t\t%u\n",
  997. le32_to_cpu(ofdm->fina_sync_err_cnt),
  998. accum_ofdm->fina_sync_err_cnt);
  999. pos += scnprintf(buf + pos, bufsz - pos,
  1000. "sfd_timeout:\t\t%u\t\t\t%u\n",
  1001. le32_to_cpu(ofdm->sfd_timeout),
  1002. accum_ofdm->sfd_timeout);
  1003. pos += scnprintf(buf + pos, bufsz - pos,
  1004. "fina_timeout:\t\t%u\t\t\t%u\n",
  1005. le32_to_cpu(ofdm->fina_timeout),
  1006. accum_ofdm->fina_timeout);
  1007. pos += scnprintf(buf + pos, bufsz - pos,
  1008. "unresponded_rts:\t%u\t\t\t%u\n",
  1009. le32_to_cpu(ofdm->unresponded_rts),
  1010. accum_ofdm->unresponded_rts);
  1011. pos += scnprintf(buf + pos, bufsz - pos,
  1012. "rxe_frame_lmt_ovrun:\t%u\t\t\t%u\n",
  1013. le32_to_cpu(ofdm->rxe_frame_limit_overrun),
  1014. accum_ofdm->rxe_frame_limit_overrun);
  1015. pos += scnprintf(buf + pos, bufsz - pos,
  1016. "sent_ack_cnt:\t\t%u\t\t\t%u\n",
  1017. le32_to_cpu(ofdm->sent_ack_cnt),
  1018. accum_ofdm->sent_ack_cnt);
  1019. pos += scnprintf(buf + pos, bufsz - pos,
  1020. "sent_cts_cnt:\t\t%u\t\t\t%u\n",
  1021. le32_to_cpu(ofdm->sent_cts_cnt),
  1022. accum_ofdm->sent_cts_cnt);
  1023. pos += scnprintf(buf + pos, bufsz - pos,
  1024. "sent_ba_rsp_cnt:\t%u\t\t\t%u\n",
  1025. le32_to_cpu(ofdm->sent_ba_rsp_cnt),
  1026. accum_ofdm->sent_ba_rsp_cnt);
  1027. pos += scnprintf(buf + pos, bufsz - pos,
  1028. "dsp_self_kill:\t\t%u\t\t\t%u\n",
  1029. le32_to_cpu(ofdm->dsp_self_kill),
  1030. accum_ofdm->dsp_self_kill);
  1031. pos += scnprintf(buf + pos, bufsz - pos,
  1032. "mh_format_err:\t\t%u\t\t\t%u\n",
  1033. le32_to_cpu(ofdm->mh_format_err),
  1034. accum_ofdm->mh_format_err);
  1035. pos += scnprintf(buf + pos, bufsz - pos,
  1036. "re_acq_main_rssi_sum:\t%u\t\t\t%u\n",
  1037. le32_to_cpu(ofdm->re_acq_main_rssi_sum),
  1038. accum_ofdm->re_acq_main_rssi_sum);
  1039. pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - CCK:\n");
  1040. pos += scnprintf(buf + pos, bufsz - pos,
  1041. "\t\t\tcurrent\t\t\taccumulative\n");
  1042. pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt:\t\t%u\t\t\t%u\n",
  1043. le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt);
  1044. pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt:\t\t%u\t\t\t%u\n",
  1045. le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt);
  1046. pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n",
  1047. le32_to_cpu(cck->plcp_err), accum_cck->plcp_err);
  1048. pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n",
  1049. le32_to_cpu(cck->crc32_err), accum_cck->crc32_err);
  1050. pos += scnprintf(buf + pos, bufsz - pos,
  1051. "overrun_err:\t\t%u\t\t\t%u\n",
  1052. le32_to_cpu(cck->overrun_err),
  1053. accum_cck->overrun_err);
  1054. pos += scnprintf(buf + pos, bufsz - pos,
  1055. "early_overrun_err:\t%u\t\t\t%u\n",
  1056. le32_to_cpu(cck->early_overrun_err),
  1057. accum_cck->early_overrun_err);
  1058. pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n",
  1059. le32_to_cpu(cck->crc32_good), accum_cck->crc32_good);
  1060. pos += scnprintf(buf + pos, bufsz - pos,
  1061. "false_alarm_cnt:\t%u\t\t\t%u\n",
  1062. le32_to_cpu(cck->false_alarm_cnt),
  1063. accum_cck->false_alarm_cnt);
  1064. pos += scnprintf(buf + pos, bufsz - pos,
  1065. "fina_sync_err_cnt:\t%u\t\t\t%u\n",
  1066. le32_to_cpu(cck->fina_sync_err_cnt),
  1067. accum_cck->fina_sync_err_cnt);
  1068. pos += scnprintf(buf + pos, bufsz - pos,
  1069. "sfd_timeout:\t\t%u\t\t\t%u\n",
  1070. le32_to_cpu(cck->sfd_timeout),
  1071. accum_cck->sfd_timeout);
  1072. pos += scnprintf(buf + pos, bufsz - pos,
  1073. "fina_timeout:\t\t%u\t\t\t%u\n",
  1074. le32_to_cpu(cck->fina_timeout),
  1075. accum_cck->fina_timeout);
  1076. pos += scnprintf(buf + pos, bufsz - pos,
  1077. "unresponded_rts:\t%u\t\t\t%u\n",
  1078. le32_to_cpu(cck->unresponded_rts),
  1079. accum_cck->unresponded_rts);
  1080. pos += scnprintf(buf + pos, bufsz - pos,
  1081. "rxe_frame_lmt_ovrun:\t%u\t\t\t%u\n",
  1082. le32_to_cpu(cck->rxe_frame_limit_overrun),
  1083. accum_cck->rxe_frame_limit_overrun);
  1084. pos += scnprintf(buf + pos, bufsz - pos,
  1085. "sent_ack_cnt:\t\t%u\t\t\t%u\n",
  1086. le32_to_cpu(cck->sent_ack_cnt),
  1087. accum_cck->sent_ack_cnt);
  1088. pos += scnprintf(buf + pos, bufsz - pos,
  1089. "sent_cts_cnt:\t\t%u\t\t\t%u\n",
  1090. le32_to_cpu(cck->sent_cts_cnt),
  1091. accum_cck->sent_cts_cnt);
  1092. pos += scnprintf(buf + pos, bufsz - pos,
  1093. "sent_ba_rsp_cnt:\t%u\t\t\t%u\n",
  1094. le32_to_cpu(cck->sent_ba_rsp_cnt),
  1095. accum_cck->sent_ba_rsp_cnt);
  1096. pos += scnprintf(buf + pos, bufsz - pos,
  1097. "dsp_self_kill:\t\t%u\t\t\t%u\n",
  1098. le32_to_cpu(cck->dsp_self_kill),
  1099. accum_cck->dsp_self_kill);
  1100. pos += scnprintf(buf + pos, bufsz - pos,
  1101. "mh_format_err:\t\t%u\t\t\t%u\n",
  1102. le32_to_cpu(cck->mh_format_err),
  1103. accum_cck->mh_format_err);
  1104. pos += scnprintf(buf + pos, bufsz - pos,
  1105. "re_acq_main_rssi_sum:\t%u\t\t\t%u\n",
  1106. le32_to_cpu(cck->re_acq_main_rssi_sum),
  1107. accum_cck->re_acq_main_rssi_sum);
  1108. pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - GENERAL:\n");
  1109. pos += scnprintf(buf + pos, bufsz - pos,
  1110. "\t\t\tcurrent\t\t\taccumulative\n");
  1111. pos += scnprintf(buf + pos, bufsz - pos, "bogus_cts:\t\t%u\t\t\t%u\n",
  1112. le32_to_cpu(general->bogus_cts),
  1113. accum_general->bogus_cts);
  1114. pos += scnprintf(buf + pos, bufsz - pos, "bogus_ack:\t\t%u\t\t\t%u\n",
  1115. le32_to_cpu(general->bogus_ack),
  1116. accum_general->bogus_ack);
  1117. pos += scnprintf(buf + pos, bufsz - pos,
  1118. "non_bssid_frames:\t%u\t\t\t%u\n",
  1119. le32_to_cpu(general->non_bssid_frames),
  1120. accum_general->non_bssid_frames);
  1121. pos += scnprintf(buf + pos, bufsz - pos,
  1122. "filtered_frames:\t%u\t\t\t%u\n",
  1123. le32_to_cpu(general->filtered_frames),
  1124. accum_general->filtered_frames);
  1125. pos += scnprintf(buf + pos, bufsz - pos,
  1126. "non_channel_beacons:\t%u\t\t\t%u\n",
  1127. le32_to_cpu(general->non_channel_beacons),
  1128. accum_general->non_channel_beacons);
  1129. pos += scnprintf(buf + pos, bufsz - pos,
  1130. "channel_beacons:\t%u\t\t\t%u\n",
  1131. le32_to_cpu(general->channel_beacons),
  1132. accum_general->channel_beacons);
  1133. pos += scnprintf(buf + pos, bufsz - pos,
  1134. "num_missed_bcon:\t%u\t\t\t%u\n",
  1135. le32_to_cpu(general->num_missed_bcon),
  1136. accum_general->num_missed_bcon);
  1137. pos += scnprintf(buf + pos, bufsz - pos,
  1138. "adc_rx_saturation_time:\t%u\t\t\t%u\n",
  1139. le32_to_cpu(general->adc_rx_saturation_time),
  1140. accum_general->adc_rx_saturation_time);
  1141. pos += scnprintf(buf + pos, bufsz - pos,
  1142. "ina_detect_search_tm:\t%u\t\t\t%u\n",
  1143. le32_to_cpu(general->ina_detection_search_time),
  1144. accum_general->ina_detection_search_time);
  1145. pos += scnprintf(buf + pos, bufsz - pos,
  1146. "beacon_silence_rssi_a:\t%u\t\t\t%u\n",
  1147. le32_to_cpu(general->beacon_silence_rssi_a),
  1148. accum_general->beacon_silence_rssi_a);
  1149. pos += scnprintf(buf + pos, bufsz - pos,
  1150. "beacon_silence_rssi_b:\t%u\t\t\t%u\n",
  1151. le32_to_cpu(general->beacon_silence_rssi_b),
  1152. accum_general->beacon_silence_rssi_b);
  1153. pos += scnprintf(buf + pos, bufsz - pos,
  1154. "beacon_silence_rssi_c:\t%u\t\t\t%u\n",
  1155. le32_to_cpu(general->beacon_silence_rssi_c),
  1156. accum_general->beacon_silence_rssi_c);
  1157. pos += scnprintf(buf + pos, bufsz - pos,
  1158. "interference_data_flag:\t%u\t\t\t%u\n",
  1159. le32_to_cpu(general->interference_data_flag),
  1160. accum_general->interference_data_flag);
  1161. pos += scnprintf(buf + pos, bufsz - pos,
  1162. "channel_load:\t\t%u\t\t\t%u\n",
  1163. le32_to_cpu(general->channel_load),
  1164. accum_general->channel_load);
  1165. pos += scnprintf(buf + pos, bufsz - pos,
  1166. "dsp_false_alarms:\t%u\t\t\t%u\n",
  1167. le32_to_cpu(general->dsp_false_alarms),
  1168. accum_general->dsp_false_alarms);
  1169. pos += scnprintf(buf + pos, bufsz - pos,
  1170. "beacon_rssi_a:\t\t%u\t\t\t%u\n",
  1171. le32_to_cpu(general->beacon_rssi_a),
  1172. accum_general->beacon_rssi_a);
  1173. pos += scnprintf(buf + pos, bufsz - pos,
  1174. "beacon_rssi_b:\t\t%u\t\t\t%u\n",
  1175. le32_to_cpu(general->beacon_rssi_b),
  1176. accum_general->beacon_rssi_b);
  1177. pos += scnprintf(buf + pos, bufsz - pos,
  1178. "beacon_rssi_c:\t\t%u\t\t\t%u\n",
  1179. le32_to_cpu(general->beacon_rssi_c),
  1180. accum_general->beacon_rssi_c);
  1181. pos += scnprintf(buf + pos, bufsz - pos,
  1182. "beacon_energy_a:\t%u\t\t\t%u\n",
  1183. le32_to_cpu(general->beacon_energy_a),
  1184. accum_general->beacon_energy_a);
  1185. pos += scnprintf(buf + pos, bufsz - pos,
  1186. "beacon_energy_b:\t%u\t\t\t%u\n",
  1187. le32_to_cpu(general->beacon_energy_b),
  1188. accum_general->beacon_energy_b);
  1189. pos += scnprintf(buf + pos, bufsz - pos,
  1190. "beacon_energy_c:\t%u\t\t\t%u\n",
  1191. le32_to_cpu(general->beacon_energy_c),
  1192. accum_general->beacon_energy_c);
  1193. pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n");
  1194. pos += scnprintf(buf + pos, bufsz - pos,
  1195. "\t\t\tcurrent\t\t\taccumulative\n");
  1196. pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n",
  1197. le32_to_cpu(ht->plcp_err), accum_ht->plcp_err);
  1198. pos += scnprintf(buf + pos, bufsz - pos,
  1199. "overrun_err:\t\t%u\t\t\t%u\n",
  1200. le32_to_cpu(ht->overrun_err), accum_ht->overrun_err);
  1201. pos += scnprintf(buf + pos, bufsz - pos,
  1202. "early_overrun_err:\t%u\t\t\t%u\n",
  1203. le32_to_cpu(ht->early_overrun_err),
  1204. accum_ht->early_overrun_err);
  1205. pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n",
  1206. le32_to_cpu(ht->crc32_good), accum_ht->crc32_good);
  1207. pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n",
  1208. le32_to_cpu(ht->crc32_err), accum_ht->crc32_err);
  1209. pos += scnprintf(buf + pos, bufsz - pos,
  1210. "mh_format_err:\t\t%u\t\t\t%u\n",
  1211. le32_to_cpu(ht->mh_format_err),
  1212. accum_ht->mh_format_err);
  1213. pos += scnprintf(buf + pos, bufsz - pos,
  1214. "agg_crc32_good:\t\t%u\t\t\t%u\n",
  1215. le32_to_cpu(ht->agg_crc32_good),
  1216. accum_ht->agg_crc32_good);
  1217. pos += scnprintf(buf + pos, bufsz - pos,
  1218. "agg_mpdu_cnt:\t\t%u\t\t\t%u\n",
  1219. le32_to_cpu(ht->agg_mpdu_cnt),
  1220. accum_ht->agg_mpdu_cnt);
  1221. pos += scnprintf(buf + pos, bufsz - pos, "agg_cnt:\t\t%u\t\t\t%u\n",
  1222. le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt);
  1223. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  1224. kfree(buf);
  1225. return ret;
  1226. }
  1227. static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
  1228. char __user *user_buf,
  1229. size_t count, loff_t *ppos)
  1230. {
  1231. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  1232. int pos = 0;
  1233. char *buf;
  1234. int bufsz = (sizeof(struct statistics_tx) * 24) + 250;
  1235. ssize_t ret;
  1236. struct statistics_tx *tx, *accum_tx;
  1237. if (!iwl_is_alive(priv))
  1238. return -EAGAIN;
  1239. /* make request to uCode to retrieve statistics information */
  1240. mutex_lock(&priv->mutex);
  1241. ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
  1242. mutex_unlock(&priv->mutex);
  1243. if (ret) {
  1244. IWL_ERR(priv,
  1245. "Error sending statistics request: %zd\n", ret);
  1246. return -EAGAIN;
  1247. }
  1248. buf = kzalloc(bufsz, GFP_KERNEL);
  1249. if (!buf) {
  1250. IWL_ERR(priv, "Can not allocate Buffer\n");
  1251. return -ENOMEM;
  1252. }
  1253. /* the statistic information display here is based on
  1254. * the last statistics notification from uCode
  1255. * might not reflect the current uCode activity
  1256. */
  1257. tx = &priv->statistics.tx;
  1258. accum_tx = &priv->accum_statistics.tx;
  1259. pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
  1260. pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Tx:\n");
  1261. pos += scnprintf(buf + pos, bufsz - pos,
  1262. "\t\t\tcurrent\t\t\taccumulative\n");
  1263. pos += scnprintf(buf + pos, bufsz - pos, "preamble:\t\t\t%u\t\t\t%u\n",
  1264. le32_to_cpu(tx->preamble_cnt),
  1265. accum_tx->preamble_cnt);
  1266. pos += scnprintf(buf + pos, bufsz - pos,
  1267. "rx_detected_cnt:\t\t%u\t\t\t%u\n",
  1268. le32_to_cpu(tx->rx_detected_cnt),
  1269. accum_tx->rx_detected_cnt);
  1270. pos += scnprintf(buf + pos, bufsz - pos,
  1271. "bt_prio_defer_cnt:\t\t%u\t\t\t%u\n",
  1272. le32_to_cpu(tx->bt_prio_defer_cnt),
  1273. accum_tx->bt_prio_defer_cnt);
  1274. pos += scnprintf(buf + pos, bufsz - pos,
  1275. "bt_prio_kill_cnt:\t\t%u\t\t\t%u\n",
  1276. le32_to_cpu(tx->bt_prio_kill_cnt),
  1277. accum_tx->bt_prio_kill_cnt);
  1278. pos += scnprintf(buf + pos, bufsz - pos,
  1279. "few_bytes_cnt:\t\t\t%u\t\t\t%u\n",
  1280. le32_to_cpu(tx->few_bytes_cnt),
  1281. accum_tx->few_bytes_cnt);
  1282. pos += scnprintf(buf + pos, bufsz - pos,
  1283. "cts_timeout:\t\t\t%u\t\t\t%u\n",
  1284. le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout);
  1285. pos += scnprintf(buf + pos, bufsz - pos,
  1286. "ack_timeout:\t\t\t%u\t\t\t%u\n",
  1287. le32_to_cpu(tx->ack_timeout),
  1288. accum_tx->ack_timeout);
  1289. pos += scnprintf(buf + pos, bufsz - pos,
  1290. "expected_ack_cnt:\t\t%u\t\t\t%u\n",
  1291. le32_to_cpu(tx->expected_ack_cnt),
  1292. accum_tx->expected_ack_cnt);
  1293. pos += scnprintf(buf + pos, bufsz - pos,
  1294. "actual_ack_cnt:\t\t\t%u\t\t\t%u\n",
  1295. le32_to_cpu(tx->actual_ack_cnt),
  1296. accum_tx->actual_ack_cnt);
  1297. pos += scnprintf(buf + pos, bufsz - pos,
  1298. "dump_msdu_cnt:\t\t\t%u\t\t\t%u\n",
  1299. le32_to_cpu(tx->dump_msdu_cnt),
  1300. accum_tx->dump_msdu_cnt);
  1301. pos += scnprintf(buf + pos, bufsz - pos,
  1302. "abort_nxt_frame_mismatch:"
  1303. "\t%u\t\t\t%u\n",
  1304. le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt),
  1305. accum_tx->burst_abort_next_frame_mismatch_cnt);
  1306. pos += scnprintf(buf + pos, bufsz - pos,
  1307. "abort_missing_nxt_frame:"
  1308. "\t%u\t\t\t%u\n",
  1309. le32_to_cpu(tx->burst_abort_missing_next_frame_cnt),
  1310. accum_tx->burst_abort_missing_next_frame_cnt);
  1311. pos += scnprintf(buf + pos, bufsz - pos,
  1312. "cts_timeout_collision:\t\t%u\t\t\t%u\n",
  1313. le32_to_cpu(tx->cts_timeout_collision),
  1314. accum_tx->cts_timeout_collision);
  1315. pos += scnprintf(buf + pos, bufsz - pos,
  1316. "ack_ba_timeout_collision:\t%u\t\t\t%u\n",
  1317. le32_to_cpu(tx->ack_or_ba_timeout_collision),
  1318. accum_tx->ack_or_ba_timeout_collision);
  1319. pos += scnprintf(buf + pos, bufsz - pos,
  1320. "agg ba_timeout:\t\t\t%u\t\t\t%u\n",
  1321. le32_to_cpu(tx->agg.ba_timeout),
  1322. accum_tx->agg.ba_timeout);
  1323. pos += scnprintf(buf + pos, bufsz - pos,
  1324. "agg ba_resched_frames:\t\t%u\t\t\t%u\n",
  1325. le32_to_cpu(tx->agg.ba_reschedule_frames),
  1326. accum_tx->agg.ba_reschedule_frames);
  1327. pos += scnprintf(buf + pos, bufsz - pos,
  1328. "agg scd_query_agg_frame:\t%u\t\t\t%u\n",
  1329. le32_to_cpu(tx->agg.scd_query_agg_frame_cnt),
  1330. accum_tx->agg.scd_query_agg_frame_cnt);
  1331. pos += scnprintf(buf + pos, bufsz - pos,
  1332. "agg scd_query_no_agg:\t\t%u\t\t\t%u\n",
  1333. le32_to_cpu(tx->agg.scd_query_no_agg),
  1334. accum_tx->agg.scd_query_no_agg);
  1335. pos += scnprintf(buf + pos, bufsz - pos,
  1336. "agg scd_query_agg:\t\t%u\t\t\t%u\n",
  1337. le32_to_cpu(tx->agg.scd_query_agg),
  1338. accum_tx->agg.scd_query_agg);
  1339. pos += scnprintf(buf + pos, bufsz - pos,
  1340. "agg scd_query_mismatch:\t\t%u\t\t\t%u\n",
  1341. le32_to_cpu(tx->agg.scd_query_mismatch),
  1342. accum_tx->agg.scd_query_mismatch);
  1343. pos += scnprintf(buf + pos, bufsz - pos,
  1344. "agg frame_not_ready:\t\t%u\t\t\t%u\n",
  1345. le32_to_cpu(tx->agg.frame_not_ready),
  1346. accum_tx->agg.frame_not_ready);
  1347. pos += scnprintf(buf + pos, bufsz - pos,
  1348. "agg underrun:\t\t\t%u\t\t\t%u\n",
  1349. le32_to_cpu(tx->agg.underrun),
  1350. accum_tx->agg.underrun);
  1351. pos += scnprintf(buf + pos, bufsz - pos,
  1352. "agg bt_prio_kill:\t\t%u\t\t\t%u\n",
  1353. le32_to_cpu(tx->agg.bt_prio_kill),
  1354. accum_tx->agg.bt_prio_kill);
  1355. pos += scnprintf(buf + pos, bufsz - pos,
  1356. "agg rx_ba_rsp_cnt:\t\t%u\t\t\t%u\n",
  1357. le32_to_cpu(tx->agg.rx_ba_rsp_cnt),
  1358. accum_tx->agg.rx_ba_rsp_cnt);
  1359. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  1360. kfree(buf);
  1361. return ret;
  1362. }
  1363. static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
  1364. char __user *user_buf,
  1365. size_t count, loff_t *ppos)
  1366. {
  1367. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  1368. int pos = 0;
  1369. char *buf;
  1370. int bufsz = sizeof(struct statistics_general) * 4 + 250;
  1371. ssize_t ret;
  1372. struct statistics_general *general, *accum_general;
  1373. struct statistics_dbg *dbg, *accum_dbg;
  1374. struct statistics_div *div, *accum_div;
  1375. if (!iwl_is_alive(priv))
  1376. return -EAGAIN;
  1377. /* make request to uCode to retrieve statistics information */
  1378. mutex_lock(&priv->mutex);
  1379. ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
  1380. mutex_unlock(&priv->mutex);
  1381. if (ret) {
  1382. IWL_ERR(priv,
  1383. "Error sending statistics request: %zd\n", ret);
  1384. return -EAGAIN;
  1385. }
  1386. buf = kzalloc(bufsz, GFP_KERNEL);
  1387. if (!buf) {
  1388. IWL_ERR(priv, "Can not allocate Buffer\n");
  1389. return -ENOMEM;
  1390. }
  1391. /* the statistic information display here is based on
  1392. * the last statistics notification from uCode
  1393. * might not reflect the current uCode activity
  1394. */
  1395. general = &priv->statistics.general;
  1396. dbg = &priv->statistics.general.dbg;
  1397. div = &priv->statistics.general.div;
  1398. accum_general = &priv->accum_statistics.general;
  1399. accum_dbg = &priv->accum_statistics.general.dbg;
  1400. accum_div = &priv->accum_statistics.general.div;
  1401. pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
  1402. pos += scnprintf(buf + pos, bufsz - pos, "Statistics_General:\n");
  1403. pos += scnprintf(buf + pos, bufsz - pos,
  1404. "\t\t\tcurrent\t\t\taccumulative\n");
  1405. pos += scnprintf(buf + pos, bufsz - pos, "temperature:\t\t\t%u\n",
  1406. le32_to_cpu(general->temperature));
  1407. pos += scnprintf(buf + pos, bufsz - pos, "temperature_m:\t\t\t%u\n",
  1408. le32_to_cpu(general->temperature_m));
  1409. pos += scnprintf(buf + pos, bufsz - pos,
  1410. "burst_check:\t\t\t%u\t\t\t%u\n",
  1411. le32_to_cpu(dbg->burst_check),
  1412. accum_dbg->burst_check);
  1413. pos += scnprintf(buf + pos, bufsz - pos,
  1414. "burst_count:\t\t\t%u\t\t\t%u\n",
  1415. le32_to_cpu(dbg->burst_count),
  1416. accum_dbg->burst_count);
  1417. pos += scnprintf(buf + pos, bufsz - pos,
  1418. "sleep_time:\t\t\t%u\t\t\t%u\n",
  1419. le32_to_cpu(general->sleep_time),
  1420. accum_general->sleep_time);
  1421. pos += scnprintf(buf + pos, bufsz - pos,
  1422. "slots_out:\t\t\t%u\t\t\t%u\n",
  1423. le32_to_cpu(general->slots_out),
  1424. accum_general->slots_out);
  1425. pos += scnprintf(buf + pos, bufsz - pos,
  1426. "slots_idle:\t\t\t%u\t\t\t%u\n",
  1427. le32_to_cpu(general->slots_idle),
  1428. accum_general->slots_idle);
  1429. pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n",
  1430. le32_to_cpu(general->ttl_timestamp));
  1431. pos += scnprintf(buf + pos, bufsz - pos, "tx_on_a:\t\t\t%u\t\t\t%u\n",
  1432. le32_to_cpu(div->tx_on_a), accum_div->tx_on_a);
  1433. pos += scnprintf(buf + pos, bufsz - pos, "tx_on_b:\t\t\t%u\t\t\t%u\n",
  1434. le32_to_cpu(div->tx_on_b), accum_div->tx_on_b);
  1435. pos += scnprintf(buf + pos, bufsz - pos,
  1436. "exec_time:\t\t\t%u\t\t\t%u\n",
  1437. le32_to_cpu(div->exec_time), accum_div->exec_time);
  1438. pos += scnprintf(buf + pos, bufsz - pos,
  1439. "probe_time:\t\t\t%u\t\t\t%u\n",
  1440. le32_to_cpu(div->probe_time), accum_div->probe_time);
  1441. pos += scnprintf(buf + pos, bufsz - pos,
  1442. "rx_enable_counter:\t\t%u\t\t\t%u\n",
  1443. le32_to_cpu(general->rx_enable_counter),
  1444. accum_general->rx_enable_counter);
  1445. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  1446. kfree(buf);
  1447. return ret;
  1448. }
  1449. static ssize_t iwl_dbgfs_sensitivity_read(struct file *file,
  1450. char __user *user_buf,
  1451. size_t count, loff_t *ppos) {
  1452. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  1453. int pos = 0;
  1454. int cnt = 0;
  1455. char *buf;
  1456. int bufsz = sizeof(struct iwl_sensitivity_data) * 4 + 100;
  1457. ssize_t ret;
  1458. struct iwl_sensitivity_data *data;
  1459. data = &priv->sensitivity_data;
  1460. buf = kzalloc(bufsz, GFP_KERNEL);
  1461. if (!buf) {
  1462. IWL_ERR(priv, "Can not allocate Buffer\n");
  1463. return -ENOMEM;
  1464. }
  1465. pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
  1466. data->auto_corr_ofdm);
  1467. pos += scnprintf(buf + pos, bufsz - pos,
  1468. "auto_corr_ofdm_mrc:\t\t %u\n",
  1469. data->auto_corr_ofdm_mrc);
  1470. pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
  1471. data->auto_corr_ofdm_x1);
  1472. pos += scnprintf(buf + pos, bufsz - pos,
  1473. "auto_corr_ofdm_mrc_x1:\t\t %u\n",
  1474. data->auto_corr_ofdm_mrc_x1);
  1475. pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
  1476. data->auto_corr_cck);
  1477. pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
  1478. data->auto_corr_cck_mrc);
  1479. pos += scnprintf(buf + pos, bufsz - pos,
  1480. "last_bad_plcp_cnt_ofdm:\t\t %u\n",
  1481. data->last_bad_plcp_cnt_ofdm);
  1482. pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
  1483. data->last_fa_cnt_ofdm);
  1484. pos += scnprintf(buf + pos, bufsz - pos,
  1485. "last_bad_plcp_cnt_cck:\t\t %u\n",
  1486. data->last_bad_plcp_cnt_cck);
  1487. pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
  1488. data->last_fa_cnt_cck);
  1489. pos += scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
  1490. data->nrg_curr_state);
  1491. pos += scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
  1492. data->nrg_prev_state);
  1493. pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
  1494. for (cnt = 0; cnt < 10; cnt++) {
  1495. pos += scnprintf(buf + pos, bufsz - pos, " %u",
  1496. data->nrg_value[cnt]);
  1497. }
  1498. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  1499. pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
  1500. for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
  1501. pos += scnprintf(buf + pos, bufsz - pos, " %u",
  1502. data->nrg_silence_rssi[cnt]);
  1503. }
  1504. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  1505. pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
  1506. data->nrg_silence_ref);
  1507. pos += scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
  1508. data->nrg_energy_idx);
  1509. pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
  1510. data->nrg_silence_idx);
  1511. pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
  1512. data->nrg_th_cck);
  1513. pos += scnprintf(buf + pos, bufsz - pos,
  1514. "nrg_auto_corr_silence_diff:\t %u\n",
  1515. data->nrg_auto_corr_silence_diff);
  1516. pos += scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
  1517. data->num_in_cck_no_fa);
  1518. pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
  1519. data->nrg_th_ofdm);
  1520. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  1521. kfree(buf);
  1522. return ret;
  1523. }
  1524. static ssize_t iwl_dbgfs_chain_noise_read(struct file *file,
  1525. char __user *user_buf,
  1526. size_t count, loff_t *ppos) {
  1527. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  1528. int pos = 0;
  1529. int cnt = 0;
  1530. char *buf;
  1531. int bufsz = sizeof(struct iwl_chain_noise_data) * 4 + 100;
  1532. ssize_t ret;
  1533. struct iwl_chain_noise_data *data;
  1534. data = &priv->chain_noise_data;
  1535. buf = kzalloc(bufsz, GFP_KERNEL);
  1536. if (!buf) {
  1537. IWL_ERR(priv, "Can not allocate Buffer\n");
  1538. return -ENOMEM;
  1539. }
  1540. pos += scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
  1541. data->active_chains);
  1542. pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
  1543. data->chain_noise_a);
  1544. pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
  1545. data->chain_noise_b);
  1546. pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
  1547. data->chain_noise_c);
  1548. pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
  1549. data->chain_signal_a);
  1550. pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
  1551. data->chain_signal_b);
  1552. pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
  1553. data->chain_signal_c);
  1554. pos += scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
  1555. data->beacon_count);
  1556. pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
  1557. for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
  1558. pos += scnprintf(buf + pos, bufsz - pos, " %u",
  1559. data->disconn_array[cnt]);
  1560. }
  1561. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  1562. pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
  1563. for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
  1564. pos += scnprintf(buf + pos, bufsz - pos, " %u",
  1565. data->delta_gain_code[cnt]);
  1566. }
  1567. pos += scnprintf(buf + pos, bufsz - pos, "\n");
  1568. pos += scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
  1569. data->radio_write);
  1570. pos += scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
  1571. data->state);
  1572. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  1573. kfree(buf);
  1574. return ret;
  1575. }
  1576. static ssize_t iwl_dbgfs_tx_power_read(struct file *file,
  1577. char __user *user_buf,
  1578. size_t count, loff_t *ppos) {
  1579. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  1580. char buf[128];
  1581. int pos = 0;
  1582. ssize_t ret;
  1583. const size_t bufsz = sizeof(buf);
  1584. struct statistics_tx *tx;
  1585. if (!iwl_is_alive(priv))
  1586. pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
  1587. else {
  1588. /* make request to uCode to retrieve statistics information */
  1589. mutex_lock(&priv->mutex);
  1590. ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
  1591. mutex_unlock(&priv->mutex);
  1592. if (ret) {
  1593. IWL_ERR(priv, "Error sending statistics request: %zd\n",
  1594. ret);
  1595. return -EAGAIN;
  1596. }
  1597. tx = &priv->statistics.tx;
  1598. if (tx->tx_power.ant_a ||
  1599. tx->tx_power.ant_b ||
  1600. tx->tx_power.ant_c) {
  1601. pos += scnprintf(buf + pos, bufsz - pos,
  1602. "tx power: (1/2 dB step)\n");
  1603. if ((priv->cfg->valid_tx_ant & ANT_A) &&
  1604. tx->tx_power.ant_a)
  1605. pos += scnprintf(buf + pos, bufsz - pos,
  1606. "\tantenna A: 0x%X\n",
  1607. tx->tx_power.ant_a);
  1608. if ((priv->cfg->valid_tx_ant & ANT_B) &&
  1609. tx->tx_power.ant_b)
  1610. pos += scnprintf(buf + pos, bufsz - pos,
  1611. "\tantenna B: 0x%X\n",
  1612. tx->tx_power.ant_b);
  1613. if ((priv->cfg->valid_tx_ant & ANT_C) &&
  1614. tx->tx_power.ant_c)
  1615. pos += scnprintf(buf + pos, bufsz - pos,
  1616. "\tantenna C: 0x%X\n",
  1617. tx->tx_power.ant_c);
  1618. } else
  1619. pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
  1620. }
  1621. return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  1622. }
  1623. static ssize_t iwl_dbgfs_power_save_status_read(struct file *file,
  1624. char __user *user_buf,
  1625. size_t count, loff_t *ppos)
  1626. {
  1627. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  1628. char buf[60];
  1629. int pos = 0;
  1630. const size_t bufsz = sizeof(buf);
  1631. u32 pwrsave_status;
  1632. pwrsave_status = iwl_read32(priv, CSR_GP_CNTRL) &
  1633. CSR_GP_REG_POWER_SAVE_STATUS_MSK;
  1634. pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: ");
  1635. pos += scnprintf(buf + pos, bufsz - pos, "%s\n",
  1636. (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" :
  1637. (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" :
  1638. (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" :
  1639. "error");
  1640. return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  1641. }
  1642. static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file,
  1643. const char __user *user_buf,
  1644. size_t count, loff_t *ppos)
  1645. {
  1646. struct iwl_priv *priv = file->private_data;
  1647. char buf[8];
  1648. int buf_size;
  1649. int clear;
  1650. memset(buf, 0, sizeof(buf));
  1651. buf_size = min(count, sizeof(buf) - 1);
  1652. if (copy_from_user(buf, user_buf, buf_size))
  1653. return -EFAULT;
  1654. if (sscanf(buf, "%d", &clear) != 1)
  1655. return -EFAULT;
  1656. /* make request to uCode to retrieve statistics information */
  1657. mutex_lock(&priv->mutex);
  1658. iwl_send_statistics_request(priv, CMD_SYNC, true);
  1659. mutex_unlock(&priv->mutex);
  1660. return count;
  1661. }
  1662. DEBUGFS_READ_FILE_OPS(rx_statistics);
  1663. DEBUGFS_READ_FILE_OPS(tx_statistics);
  1664. DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
  1665. DEBUGFS_READ_FILE_OPS(rx_queue);
  1666. DEBUGFS_READ_FILE_OPS(tx_queue);
  1667. DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
  1668. DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
  1669. DEBUGFS_READ_FILE_OPS(ucode_general_stats);
  1670. DEBUGFS_READ_FILE_OPS(sensitivity);
  1671. DEBUGFS_READ_FILE_OPS(chain_noise);
  1672. DEBUGFS_READ_FILE_OPS(tx_power);
  1673. DEBUGFS_READ_FILE_OPS(power_save_status);
  1674. DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics);
  1675. DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics);
  1676. /*
  1677. * Create the debugfs files and directories
  1678. *
  1679. */
  1680. int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
  1681. {
  1682. struct iwl_debugfs *dbgfs;
  1683. struct dentry *phyd = priv->hw->wiphy->debugfsdir;
  1684. int ret = 0;
  1685. dbgfs = kzalloc(sizeof(struct iwl_debugfs), GFP_KERNEL);
  1686. if (!dbgfs) {
  1687. ret = -ENOMEM;
  1688. goto err;
  1689. }
  1690. priv->dbgfs = dbgfs;
  1691. dbgfs->name = name;
  1692. dbgfs->dir_drv = debugfs_create_dir(name, phyd);
  1693. if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)) {
  1694. ret = -ENOENT;
  1695. goto err;
  1696. }
  1697. DEBUGFS_ADD_DIR(data, dbgfs->dir_drv);
  1698. DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv);
  1699. DEBUGFS_ADD_DIR(debug, dbgfs->dir_drv);
  1700. DEBUGFS_ADD_FILE(nvm, data, S_IRUSR);
  1701. DEBUGFS_ADD_FILE(sram, data, S_IWUSR | S_IRUSR);
  1702. DEBUGFS_ADD_FILE(log_event, data, S_IWUSR);
  1703. DEBUGFS_ADD_FILE(stations, data, S_IRUSR);
  1704. DEBUGFS_ADD_FILE(channels, data, S_IRUSR);
  1705. DEBUGFS_ADD_FILE(status, data, S_IRUSR);
  1706. DEBUGFS_ADD_FILE(interrupt, data, S_IWUSR | S_IRUSR);
  1707. DEBUGFS_ADD_FILE(qos, data, S_IRUSR);
  1708. DEBUGFS_ADD_FILE(led, data, S_IRUSR);
  1709. DEBUGFS_ADD_FILE(sleep_level_override, data, S_IWUSR | S_IRUSR);
  1710. DEBUGFS_ADD_FILE(current_sleep_command, data, S_IRUSR);
  1711. DEBUGFS_ADD_FILE(thermal_throttling, data, S_IRUSR);
  1712. DEBUGFS_ADD_FILE(disable_ht40, data, S_IWUSR | S_IRUSR);
  1713. DEBUGFS_ADD_FILE(rx_statistics, debug, S_IRUSR);
  1714. DEBUGFS_ADD_FILE(tx_statistics, debug, S_IRUSR);
  1715. DEBUGFS_ADD_FILE(traffic_log, debug, S_IWUSR | S_IRUSR);
  1716. DEBUGFS_ADD_FILE(rx_queue, debug, S_IRUSR);
  1717. DEBUGFS_ADD_FILE(tx_queue, debug, S_IRUSR);
  1718. DEBUGFS_ADD_FILE(tx_power, debug, S_IRUSR);
  1719. DEBUGFS_ADD_FILE(power_save_status, debug, S_IRUSR);
  1720. DEBUGFS_ADD_FILE(clear_ucode_statistics, debug, S_IWUSR);
  1721. DEBUGFS_ADD_FILE(clear_traffic_statistics, debug, S_IWUSR);
  1722. if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
  1723. DEBUGFS_ADD_FILE(ucode_rx_stats, debug, S_IRUSR);
  1724. DEBUGFS_ADD_FILE(ucode_tx_stats, debug, S_IRUSR);
  1725. DEBUGFS_ADD_FILE(ucode_general_stats, debug, S_IRUSR);
  1726. DEBUGFS_ADD_FILE(sensitivity, debug, S_IRUSR);
  1727. DEBUGFS_ADD_FILE(chain_noise, debug, S_IRUSR);
  1728. }
  1729. DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal);
  1730. DEBUGFS_ADD_BOOL(disable_chain_noise, rf,
  1731. &priv->disable_chain_noise_cal);
  1732. if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) ||
  1733. ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945))
  1734. DEBUGFS_ADD_BOOL(disable_tx_power, rf,
  1735. &priv->disable_tx_power_cal);
  1736. return 0;
  1737. err:
  1738. IWL_ERR(priv, "Can't open the debugfs directory\n");
  1739. iwl_dbgfs_unregister(priv);
  1740. return ret;
  1741. }
  1742. EXPORT_SYMBOL(iwl_dbgfs_register);
  1743. /**
  1744. * Remove the debugfs files and directories
  1745. *
  1746. */
  1747. void iwl_dbgfs_unregister(struct iwl_priv *priv)
  1748. {
  1749. if (!priv->dbgfs)
  1750. return;
  1751. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sleep_level_override);
  1752. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_current_sleep_command);
  1753. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm);
  1754. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
  1755. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event);
  1756. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
  1757. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels);
  1758. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status);
  1759. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt);
  1760. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_qos);
  1761. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_led);
  1762. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling);
  1763. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40);
  1764. DEBUGFS_REMOVE(priv->dbgfs->dir_data);
  1765. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_statistics);
  1766. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_statistics);
  1767. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_traffic_log);
  1768. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_queue);
  1769. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue);
  1770. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_power);
  1771. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_power_save_status);
  1772. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
  1773. file_clear_ucode_statistics);
  1774. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
  1775. file_clear_traffic_statistics);
  1776. if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
  1777. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
  1778. file_ucode_rx_stats);
  1779. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
  1780. file_ucode_tx_stats);
  1781. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
  1782. file_ucode_general_stats);
  1783. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
  1784. file_sensitivity);
  1785. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
  1786. file_chain_noise);
  1787. }
  1788. DEBUGFS_REMOVE(priv->dbgfs->dir_debug);
  1789. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity);
  1790. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise);
  1791. if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) ||
  1792. ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945))
  1793. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_tx_power);
  1794. DEBUGFS_REMOVE(priv->dbgfs->dir_rf);
  1795. DEBUGFS_REMOVE(priv->dbgfs->dir_drv);
  1796. kfree(priv->dbgfs);
  1797. priv->dbgfs = NULL;
  1798. }
  1799. EXPORT_SYMBOL(iwl_dbgfs_unregister);