debug.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. /*
  2. * Copyright (c) 2004-2011 Atheros Communications Inc.
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #include "core.h"
  17. #include <linux/circ_buf.h>
  18. #include <linux/fs.h>
  19. #include "debug.h"
  20. #include "target.h"
  21. struct ath6kl_fwlog_slot {
  22. __le32 timestamp;
  23. __le32 length;
  24. /* max ATH6KL_FWLOG_PAYLOAD_SIZE bytes */
  25. u8 payload[0];
  26. };
  27. #define ATH6KL_FWLOG_SIZE 32768
  28. #define ATH6KL_FWLOG_SLOT_SIZE (sizeof(struct ath6kl_fwlog_slot) + \
  29. ATH6KL_FWLOG_PAYLOAD_SIZE)
  30. #define ATH6KL_FWLOG_VALID_MASK 0x1ffff
  31. int ath6kl_printk(const char *level, const char *fmt, ...)
  32. {
  33. struct va_format vaf;
  34. va_list args;
  35. int rtn;
  36. va_start(args, fmt);
  37. vaf.fmt = fmt;
  38. vaf.va = &args;
  39. rtn = printk("%sath6kl: %pV", level, &vaf);
  40. va_end(args);
  41. return rtn;
  42. }
  43. #ifdef CONFIG_ATH6KL_DEBUG
  44. void ath6kl_dump_registers(struct ath6kl_device *dev,
  45. struct ath6kl_irq_proc_registers *irq_proc_reg,
  46. struct ath6kl_irq_enable_reg *irq_enable_reg)
  47. {
  48. ath6kl_dbg(ATH6KL_DBG_ANY, ("<------- Register Table -------->\n"));
  49. if (irq_proc_reg != NULL) {
  50. ath6kl_dbg(ATH6KL_DBG_ANY,
  51. "Host Int status: 0x%x\n",
  52. irq_proc_reg->host_int_status);
  53. ath6kl_dbg(ATH6KL_DBG_ANY,
  54. "CPU Int status: 0x%x\n",
  55. irq_proc_reg->cpu_int_status);
  56. ath6kl_dbg(ATH6KL_DBG_ANY,
  57. "Error Int status: 0x%x\n",
  58. irq_proc_reg->error_int_status);
  59. ath6kl_dbg(ATH6KL_DBG_ANY,
  60. "Counter Int status: 0x%x\n",
  61. irq_proc_reg->counter_int_status);
  62. ath6kl_dbg(ATH6KL_DBG_ANY,
  63. "Mbox Frame: 0x%x\n",
  64. irq_proc_reg->mbox_frame);
  65. ath6kl_dbg(ATH6KL_DBG_ANY,
  66. "Rx Lookahead Valid: 0x%x\n",
  67. irq_proc_reg->rx_lkahd_valid);
  68. ath6kl_dbg(ATH6KL_DBG_ANY,
  69. "Rx Lookahead 0: 0x%x\n",
  70. irq_proc_reg->rx_lkahd[0]);
  71. ath6kl_dbg(ATH6KL_DBG_ANY,
  72. "Rx Lookahead 1: 0x%x\n",
  73. irq_proc_reg->rx_lkahd[1]);
  74. if (dev->ar->mbox_info.gmbox_addr != 0) {
  75. /*
  76. * If the target supports GMBOX hardware, dump some
  77. * additional state.
  78. */
  79. ath6kl_dbg(ATH6KL_DBG_ANY,
  80. "GMBOX Host Int status 2: 0x%x\n",
  81. irq_proc_reg->host_int_status2);
  82. ath6kl_dbg(ATH6KL_DBG_ANY,
  83. "GMBOX RX Avail: 0x%x\n",
  84. irq_proc_reg->gmbox_rx_avail);
  85. ath6kl_dbg(ATH6KL_DBG_ANY,
  86. "GMBOX lookahead alias 0: 0x%x\n",
  87. irq_proc_reg->rx_gmbox_lkahd_alias[0]);
  88. ath6kl_dbg(ATH6KL_DBG_ANY,
  89. "GMBOX lookahead alias 1: 0x%x\n",
  90. irq_proc_reg->rx_gmbox_lkahd_alias[1]);
  91. }
  92. }
  93. if (irq_enable_reg != NULL) {
  94. ath6kl_dbg(ATH6KL_DBG_ANY,
  95. "Int status Enable: 0x%x\n",
  96. irq_enable_reg->int_status_en);
  97. ath6kl_dbg(ATH6KL_DBG_ANY, "Counter Int status Enable: 0x%x\n",
  98. irq_enable_reg->cntr_int_status_en);
  99. }
  100. ath6kl_dbg(ATH6KL_DBG_ANY, "<------------------------------->\n");
  101. }
  102. static void dump_cred_dist(struct htc_endpoint_credit_dist *ep_dist)
  103. {
  104. ath6kl_dbg(ATH6KL_DBG_ANY,
  105. "--- endpoint: %d svc_id: 0x%X ---\n",
  106. ep_dist->endpoint, ep_dist->svc_id);
  107. ath6kl_dbg(ATH6KL_DBG_ANY, " dist_flags : 0x%X\n",
  108. ep_dist->dist_flags);
  109. ath6kl_dbg(ATH6KL_DBG_ANY, " cred_norm : %d\n",
  110. ep_dist->cred_norm);
  111. ath6kl_dbg(ATH6KL_DBG_ANY, " cred_min : %d\n",
  112. ep_dist->cred_min);
  113. ath6kl_dbg(ATH6KL_DBG_ANY, " credits : %d\n",
  114. ep_dist->credits);
  115. ath6kl_dbg(ATH6KL_DBG_ANY, " cred_assngd : %d\n",
  116. ep_dist->cred_assngd);
  117. ath6kl_dbg(ATH6KL_DBG_ANY, " seek_cred : %d\n",
  118. ep_dist->seek_cred);
  119. ath6kl_dbg(ATH6KL_DBG_ANY, " cred_sz : %d\n",
  120. ep_dist->cred_sz);
  121. ath6kl_dbg(ATH6KL_DBG_ANY, " cred_per_msg : %d\n",
  122. ep_dist->cred_per_msg);
  123. ath6kl_dbg(ATH6KL_DBG_ANY, " cred_to_dist : %d\n",
  124. ep_dist->cred_to_dist);
  125. ath6kl_dbg(ATH6KL_DBG_ANY, " txq_depth : %d\n",
  126. get_queue_depth(&((struct htc_endpoint *)
  127. ep_dist->htc_rsvd)->txq));
  128. ath6kl_dbg(ATH6KL_DBG_ANY,
  129. "----------------------------------\n");
  130. }
  131. void dump_cred_dist_stats(struct htc_target *target)
  132. {
  133. struct htc_endpoint_credit_dist *ep_list;
  134. if (!AR_DBG_LVL_CHECK(ATH6KL_DBG_TRC))
  135. return;
  136. list_for_each_entry(ep_list, &target->cred_dist_list, list)
  137. dump_cred_dist(ep_list);
  138. ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:%p dist:%p\n",
  139. target->cred_dist_cntxt, NULL);
  140. ath6kl_dbg(ATH6KL_DBG_TRC, "credit distribution, total : %d, free : %d\n",
  141. target->cred_dist_cntxt->total_avail_credits,
  142. target->cred_dist_cntxt->cur_free_credits);
  143. }
  144. static int ath6kl_debugfs_open(struct inode *inode, struct file *file)
  145. {
  146. file->private_data = inode->i_private;
  147. return 0;
  148. }
  149. static void ath6kl_debug_fwlog_add(struct ath6kl *ar, const void *buf,
  150. size_t buf_len)
  151. {
  152. struct circ_buf *fwlog = &ar->debug.fwlog_buf;
  153. size_t space;
  154. int i;
  155. /* entries must all be equal size */
  156. if (WARN_ON(buf_len != ATH6KL_FWLOG_SLOT_SIZE))
  157. return;
  158. space = CIRC_SPACE(fwlog->head, fwlog->tail, ATH6KL_FWLOG_SIZE);
  159. if (space < buf_len)
  160. /* discard oldest slot */
  161. fwlog->tail = (fwlog->tail + ATH6KL_FWLOG_SLOT_SIZE) &
  162. (ATH6KL_FWLOG_SIZE - 1);
  163. for (i = 0; i < buf_len; i += space) {
  164. space = CIRC_SPACE_TO_END(fwlog->head, fwlog->tail,
  165. ATH6KL_FWLOG_SIZE);
  166. if ((size_t) space > buf_len - i)
  167. space = buf_len - i;
  168. memcpy(&fwlog->buf[fwlog->head], buf, space);
  169. fwlog->head = (fwlog->head + space) & (ATH6KL_FWLOG_SIZE - 1);
  170. }
  171. }
  172. void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len)
  173. {
  174. struct ath6kl_fwlog_slot *slot = ar->debug.fwlog_tmp;
  175. size_t slot_len;
  176. if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE))
  177. return;
  178. spin_lock_bh(&ar->debug.fwlog_lock);
  179. slot->timestamp = cpu_to_le32(jiffies);
  180. slot->length = cpu_to_le32(len);
  181. memcpy(slot->payload, buf, len);
  182. slot_len = sizeof(*slot) + len;
  183. if (slot_len < ATH6KL_FWLOG_SLOT_SIZE)
  184. memset(slot->payload + len, 0,
  185. ATH6KL_FWLOG_SLOT_SIZE - slot_len);
  186. ath6kl_debug_fwlog_add(ar, slot, ATH6KL_FWLOG_SLOT_SIZE);
  187. spin_unlock_bh(&ar->debug.fwlog_lock);
  188. }
  189. static bool ath6kl_debug_fwlog_empty(struct ath6kl *ar)
  190. {
  191. return CIRC_CNT(ar->debug.fwlog_buf.head,
  192. ar->debug.fwlog_buf.tail,
  193. ATH6KL_FWLOG_SLOT_SIZE) == 0;
  194. }
  195. static ssize_t ath6kl_fwlog_read(struct file *file, char __user *user_buf,
  196. size_t count, loff_t *ppos)
  197. {
  198. struct ath6kl *ar = file->private_data;
  199. struct circ_buf *fwlog = &ar->debug.fwlog_buf;
  200. size_t len = 0, buf_len = count;
  201. ssize_t ret_cnt;
  202. char *buf;
  203. int ccnt;
  204. buf = vmalloc(buf_len);
  205. if (!buf)
  206. return -ENOMEM;
  207. /* read undelivered logs from firmware */
  208. ath6kl_read_fwlogs(ar);
  209. spin_lock_bh(&ar->debug.fwlog_lock);
  210. while (len < buf_len && !ath6kl_debug_fwlog_empty(ar)) {
  211. ccnt = CIRC_CNT_TO_END(fwlog->head, fwlog->tail,
  212. ATH6KL_FWLOG_SIZE);
  213. if ((size_t) ccnt > buf_len - len)
  214. ccnt = buf_len - len;
  215. memcpy(buf + len, &fwlog->buf[fwlog->tail], ccnt);
  216. len += ccnt;
  217. fwlog->tail = (fwlog->tail + ccnt) &
  218. (ATH6KL_FWLOG_SIZE - 1);
  219. }
  220. spin_unlock_bh(&ar->debug.fwlog_lock);
  221. if (WARN_ON(len > buf_len))
  222. len = buf_len;
  223. ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
  224. vfree(buf);
  225. return ret_cnt;
  226. }
  227. static const struct file_operations fops_fwlog = {
  228. .open = ath6kl_debugfs_open,
  229. .read = ath6kl_fwlog_read,
  230. .owner = THIS_MODULE,
  231. .llseek = default_llseek,
  232. };
  233. static ssize_t ath6kl_fwlog_mask_read(struct file *file, char __user *user_buf,
  234. size_t count, loff_t *ppos)
  235. {
  236. struct ath6kl *ar = file->private_data;
  237. char buf[16];
  238. int len;
  239. len = snprintf(buf, sizeof(buf), "0x%x\n", ar->debug.fwlog_mask);
  240. return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  241. }
  242. static ssize_t ath6kl_fwlog_mask_write(struct file *file,
  243. const char __user *user_buf,
  244. size_t count, loff_t *ppos)
  245. {
  246. struct ath6kl *ar = file->private_data;
  247. int ret;
  248. ret = kstrtou32_from_user(user_buf, count, 0, &ar->debug.fwlog_mask);
  249. if (ret)
  250. return ret;
  251. ret = ath6kl_wmi_config_debug_module_cmd(ar->wmi,
  252. ATH6KL_FWLOG_VALID_MASK,
  253. ar->debug.fwlog_mask);
  254. if (ret)
  255. return ret;
  256. return count;
  257. }
  258. static const struct file_operations fops_fwlog_mask = {
  259. .open = ath6kl_debugfs_open,
  260. .read = ath6kl_fwlog_mask_read,
  261. .write = ath6kl_fwlog_mask_write,
  262. .owner = THIS_MODULE,
  263. .llseek = default_llseek,
  264. };
  265. static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
  266. size_t count, loff_t *ppos)
  267. {
  268. struct ath6kl *ar = file->private_data;
  269. struct target_stats *tgt_stats = &ar->target_stats;
  270. char *buf;
  271. unsigned int len = 0, buf_len = 1500;
  272. int i;
  273. long left;
  274. ssize_t ret_cnt;
  275. buf = kzalloc(buf_len, GFP_KERNEL);
  276. if (!buf)
  277. return -ENOMEM;
  278. if (down_interruptible(&ar->sem)) {
  279. kfree(buf);
  280. return -EBUSY;
  281. }
  282. set_bit(STATS_UPDATE_PEND, &ar->flag);
  283. if (ath6kl_wmi_get_stats_cmd(ar->wmi)) {
  284. up(&ar->sem);
  285. kfree(buf);
  286. return -EIO;
  287. }
  288. left = wait_event_interruptible_timeout(ar->event_wq,
  289. !test_bit(STATS_UPDATE_PEND,
  290. &ar->flag), WMI_TIMEOUT);
  291. up(&ar->sem);
  292. if (left <= 0) {
  293. kfree(buf);
  294. return -ETIMEDOUT;
  295. }
  296. len += scnprintf(buf + len, buf_len - len, "\n");
  297. len += scnprintf(buf + len, buf_len - len, "%25s\n",
  298. "Target Tx stats");
  299. len += scnprintf(buf + len, buf_len - len, "%25s\n\n",
  300. "=================");
  301. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  302. "Ucast packets", tgt_stats->tx_ucast_pkt);
  303. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  304. "Bcast packets", tgt_stats->tx_bcast_pkt);
  305. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  306. "Ucast byte", tgt_stats->tx_ucast_byte);
  307. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  308. "Bcast byte", tgt_stats->tx_bcast_byte);
  309. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  310. "Rts success cnt", tgt_stats->tx_rts_success_cnt);
  311. for (i = 0; i < 4; i++)
  312. len += scnprintf(buf + len, buf_len - len,
  313. "%18s %d %10llu\n", "PER on ac",
  314. i, tgt_stats->tx_pkt_per_ac[i]);
  315. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  316. "Error", tgt_stats->tx_err);
  317. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  318. "Fail count", tgt_stats->tx_fail_cnt);
  319. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  320. "Retry count", tgt_stats->tx_retry_cnt);
  321. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  322. "Multi retry cnt", tgt_stats->tx_mult_retry_cnt);
  323. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  324. "Rts fail cnt", tgt_stats->tx_rts_fail_cnt);
  325. len += scnprintf(buf + len, buf_len - len, "%25s %10llu\n\n",
  326. "TKIP counter measure used",
  327. tgt_stats->tkip_cnter_measures_invoked);
  328. len += scnprintf(buf + len, buf_len - len, "%25s\n",
  329. "Target Rx stats");
  330. len += scnprintf(buf + len, buf_len - len, "%25s\n",
  331. "=================");
  332. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  333. "Ucast packets", tgt_stats->rx_ucast_pkt);
  334. len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",
  335. "Ucast Rate", tgt_stats->rx_ucast_rate);
  336. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  337. "Bcast packets", tgt_stats->rx_bcast_pkt);
  338. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  339. "Ucast byte", tgt_stats->rx_ucast_byte);
  340. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  341. "Bcast byte", tgt_stats->rx_bcast_byte);
  342. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  343. "Fragmented pkt", tgt_stats->rx_frgment_pkt);
  344. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  345. "Error", tgt_stats->rx_err);
  346. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  347. "CRC Err", tgt_stats->rx_crc_err);
  348. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  349. "Key chache miss", tgt_stats->rx_key_cache_miss);
  350. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  351. "Decrypt Err", tgt_stats->rx_decrypt_err);
  352. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  353. "Duplicate frame", tgt_stats->rx_dupl_frame);
  354. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  355. "Tkip Mic failure", tgt_stats->tkip_local_mic_fail);
  356. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  357. "TKIP format err", tgt_stats->tkip_fmt_err);
  358. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  359. "CCMP format Err", tgt_stats->ccmp_fmt_err);
  360. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n",
  361. "CCMP Replay Err", tgt_stats->ccmp_replays);
  362. len += scnprintf(buf + len, buf_len - len, "%25s\n",
  363. "Misc Target stats");
  364. len += scnprintf(buf + len, buf_len - len, "%25s\n",
  365. "=================");
  366. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  367. "Beacon Miss count", tgt_stats->cs_bmiss_cnt);
  368. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  369. "Num Connects", tgt_stats->cs_connect_cnt);
  370. len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
  371. "Num disconnects", tgt_stats->cs_discon_cnt);
  372. len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",
  373. "Beacon avg rssi", tgt_stats->cs_ave_beacon_rssi);
  374. if (len > buf_len)
  375. len = buf_len;
  376. ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
  377. kfree(buf);
  378. return ret_cnt;
  379. }
  380. static const struct file_operations fops_tgt_stats = {
  381. .read = read_file_tgt_stats,
  382. .open = ath6kl_debugfs_open,
  383. .owner = THIS_MODULE,
  384. .llseek = default_llseek,
  385. };
  386. #define print_credit_info(fmt_str, ep_list_field) \
  387. (len += scnprintf(buf + len, buf_len - len, fmt_str, \
  388. ep_list->ep_list_field))
  389. #define CREDIT_INFO_DISPLAY_STRING_LEN 200
  390. #define CREDIT_INFO_LEN 128
  391. static ssize_t read_file_credit_dist_stats(struct file *file,
  392. char __user *user_buf,
  393. size_t count, loff_t *ppos)
  394. {
  395. struct ath6kl *ar = file->private_data;
  396. struct htc_target *target = ar->htc_target;
  397. struct htc_endpoint_credit_dist *ep_list;
  398. char *buf;
  399. unsigned int buf_len, len = 0;
  400. ssize_t ret_cnt;
  401. buf_len = CREDIT_INFO_DISPLAY_STRING_LEN +
  402. get_queue_depth(&target->cred_dist_list) * CREDIT_INFO_LEN;
  403. buf = kzalloc(buf_len, GFP_KERNEL);
  404. if (!buf)
  405. return -ENOMEM;
  406. len += scnprintf(buf + len, buf_len - len, "%25s%5d\n",
  407. "Total Avail Credits: ",
  408. target->cred_dist_cntxt->total_avail_credits);
  409. len += scnprintf(buf + len, buf_len - len, "%25s%5d\n",
  410. "Free credits :",
  411. target->cred_dist_cntxt->cur_free_credits);
  412. len += scnprintf(buf + len, buf_len - len,
  413. " Epid Flags Cred_norm Cred_min Credits Cred_assngd"
  414. " Seek_cred Cred_sz Cred_per_msg Cred_to_dist"
  415. " qdepth\n");
  416. list_for_each_entry(ep_list, &target->cred_dist_list, list) {
  417. print_credit_info(" %2d", endpoint);
  418. print_credit_info("%10x", dist_flags);
  419. print_credit_info("%8d", cred_norm);
  420. print_credit_info("%9d", cred_min);
  421. print_credit_info("%9d", credits);
  422. print_credit_info("%10d", cred_assngd);
  423. print_credit_info("%13d", seek_cred);
  424. print_credit_info("%12d", cred_sz);
  425. print_credit_info("%9d", cred_per_msg);
  426. print_credit_info("%14d", cred_to_dist);
  427. len += scnprintf(buf + len, buf_len - len, "%12d\n",
  428. get_queue_depth(&((struct htc_endpoint *)
  429. ep_list->htc_rsvd)->txq));
  430. }
  431. if (len > buf_len)
  432. len = buf_len;
  433. ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
  434. kfree(buf);
  435. return ret_cnt;
  436. }
  437. static const struct file_operations fops_credit_dist_stats = {
  438. .read = read_file_credit_dist_stats,
  439. .open = ath6kl_debugfs_open,
  440. .owner = THIS_MODULE,
  441. .llseek = default_llseek,
  442. };
  443. int ath6kl_debug_init(struct ath6kl *ar)
  444. {
  445. ar->debug.fwlog_buf.buf = vmalloc(ATH6KL_FWLOG_SIZE);
  446. if (ar->debug.fwlog_buf.buf == NULL)
  447. return -ENOMEM;
  448. ar->debug.fwlog_tmp = kmalloc(ATH6KL_FWLOG_SLOT_SIZE, GFP_KERNEL);
  449. if (ar->debug.fwlog_tmp == NULL) {
  450. vfree(ar->debug.fwlog_buf.buf);
  451. return -ENOMEM;
  452. }
  453. spin_lock_init(&ar->debug.fwlog_lock);
  454. /*
  455. * Actually we are lying here but don't know how to read the mask
  456. * value from the firmware.
  457. */
  458. ar->debug.fwlog_mask = 0;
  459. ar->debugfs_phy = debugfs_create_dir("ath6kl",
  460. ar->wdev->wiphy->debugfsdir);
  461. if (!ar->debugfs_phy) {
  462. vfree(ar->debug.fwlog_buf.buf);
  463. kfree(ar->debug.fwlog_tmp);
  464. return -ENOMEM;
  465. }
  466. debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar,
  467. &fops_tgt_stats);
  468. debugfs_create_file("credit_dist_stats", S_IRUSR, ar->debugfs_phy, ar,
  469. &fops_credit_dist_stats);
  470. debugfs_create_file("fwlog", S_IRUSR, ar->debugfs_phy, ar,
  471. &fops_fwlog);
  472. debugfs_create_file("fwlog_mask", S_IRUSR | S_IWUSR, ar->debugfs_phy,
  473. ar, &fops_fwlog_mask);
  474. return 0;
  475. }
  476. void ath6kl_debug_cleanup(struct ath6kl *ar)
  477. {
  478. vfree(ar->debug.fwlog_buf.buf);
  479. kfree(ar->debug.fwlog_tmp);
  480. }
  481. #endif