iwl-debugfs.c 49 KB

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