debugfs.c 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049
  1. /*
  2. * Copyright (c) 2012 Qualcomm Atheros, 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 <linux/module.h>
  17. #include <linux/debugfs.h>
  18. #include <linux/seq_file.h>
  19. #include <linux/pci.h>
  20. #include <linux/rtnetlink.h>
  21. #include <linux/power_supply.h>
  22. #include "wil6210.h"
  23. #include "txrx.h"
  24. /* Nasty hack. Better have per device instances */
  25. static u32 mem_addr;
  26. static u32 dbg_txdesc_index;
  27. static u32 dbg_vring_index; /* 24+ for Rx, 0..23 for Tx */
  28. static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil,
  29. const char *name, struct vring *vring,
  30. char _s, char _h)
  31. {
  32. void __iomem *x = wmi_addr(wil, vring->hwtail);
  33. seq_printf(s, "VRING %s = {\n", name);
  34. seq_printf(s, " pa = %pad\n", &vring->pa);
  35. seq_printf(s, " va = 0x%p\n", vring->va);
  36. seq_printf(s, " size = %d\n", vring->size);
  37. seq_printf(s, " swtail = %d\n", vring->swtail);
  38. seq_printf(s, " swhead = %d\n", vring->swhead);
  39. seq_printf(s, " hwtail = [0x%08x] -> ", vring->hwtail);
  40. if (x)
  41. seq_printf(s, "0x%08x\n", ioread32(x));
  42. else
  43. seq_printf(s, "???\n");
  44. if (vring->va && (vring->size < 1025)) {
  45. uint i;
  46. for (i = 0; i < vring->size; i++) {
  47. volatile struct vring_tx_desc *d = &vring->va[i].tx;
  48. if ((i % 64) == 0 && (i != 0))
  49. seq_printf(s, "\n");
  50. seq_printf(s, "%c", (d->dma.status & BIT(0)) ?
  51. _s : (vring->ctx[i].skb ? _h : 'h'));
  52. }
  53. seq_printf(s, "\n");
  54. }
  55. seq_printf(s, "}\n");
  56. }
  57. static int wil_vring_debugfs_show(struct seq_file *s, void *data)
  58. {
  59. uint i;
  60. struct wil6210_priv *wil = s->private;
  61. wil_print_vring(s, wil, "rx", &wil->vring_rx, 'S', '_');
  62. for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) {
  63. struct vring *vring = &(wil->vring_tx[i]);
  64. struct vring_tx_data *txdata = &wil->vring_tx_data[i];
  65. if (vring->va) {
  66. int cid = wil->vring2cid_tid[i][0];
  67. int tid = wil->vring2cid_tid[i][1];
  68. u32 swhead = vring->swhead;
  69. u32 swtail = vring->swtail;
  70. int used = (vring->size + swhead - swtail)
  71. % vring->size;
  72. int avail = vring->size - used - 1;
  73. char name[10];
  74. /* performance monitoring */
  75. cycles_t now = get_cycles();
  76. cycles_t idle = txdata->idle * 100;
  77. cycles_t total = now - txdata->begin;
  78. do_div(idle, total);
  79. txdata->begin = now;
  80. txdata->idle = 0ULL;
  81. snprintf(name, sizeof(name), "tx_%2d", i);
  82. seq_printf(s, "\n%pM CID %d TID %d [%3d|%3d] idle %3d%%\n",
  83. wil->sta[cid].addr, cid, tid, used, avail,
  84. (int)idle);
  85. wil_print_vring(s, wil, name, vring, '_', 'H');
  86. }
  87. }
  88. return 0;
  89. }
  90. static int wil_vring_seq_open(struct inode *inode, struct file *file)
  91. {
  92. return single_open(file, wil_vring_debugfs_show, inode->i_private);
  93. }
  94. static const struct file_operations fops_vring = {
  95. .open = wil_vring_seq_open,
  96. .release = single_release,
  97. .read = seq_read,
  98. .llseek = seq_lseek,
  99. };
  100. static void wil_print_ring(struct seq_file *s, const char *prefix,
  101. void __iomem *off)
  102. {
  103. struct wil6210_priv *wil = s->private;
  104. struct wil6210_mbox_ring r;
  105. int rsize;
  106. uint i;
  107. wil_memcpy_fromio_32(&r, off, sizeof(r));
  108. wil_mbox_ring_le2cpus(&r);
  109. /*
  110. * we just read memory block from NIC. This memory may be
  111. * garbage. Check validity before using it.
  112. */
  113. rsize = r.size / sizeof(struct wil6210_mbox_ring_desc);
  114. seq_printf(s, "ring %s = {\n", prefix);
  115. seq_printf(s, " base = 0x%08x\n", r.base);
  116. seq_printf(s, " size = 0x%04x bytes -> %d entries\n", r.size, rsize);
  117. seq_printf(s, " tail = 0x%08x\n", r.tail);
  118. seq_printf(s, " head = 0x%08x\n", r.head);
  119. seq_printf(s, " entry size = %d\n", r.entry_size);
  120. if (r.size % sizeof(struct wil6210_mbox_ring_desc)) {
  121. seq_printf(s, " ??? size is not multiple of %zd, garbage?\n",
  122. sizeof(struct wil6210_mbox_ring_desc));
  123. goto out;
  124. }
  125. if (!wmi_addr(wil, r.base) ||
  126. !wmi_addr(wil, r.tail) ||
  127. !wmi_addr(wil, r.head)) {
  128. seq_printf(s, " ??? pointers are garbage?\n");
  129. goto out;
  130. }
  131. for (i = 0; i < rsize; i++) {
  132. struct wil6210_mbox_ring_desc d;
  133. struct wil6210_mbox_hdr hdr;
  134. size_t delta = i * sizeof(d);
  135. void __iomem *x = wil->csr + HOSTADDR(r.base) + delta;
  136. wil_memcpy_fromio_32(&d, x, sizeof(d));
  137. seq_printf(s, " [%2x] %s %s%s 0x%08x", i,
  138. d.sync ? "F" : "E",
  139. (r.tail - r.base == delta) ? "t" : " ",
  140. (r.head - r.base == delta) ? "h" : " ",
  141. le32_to_cpu(d.addr));
  142. if (0 == wmi_read_hdr(wil, d.addr, &hdr)) {
  143. u16 len = le16_to_cpu(hdr.len);
  144. seq_printf(s, " -> %04x %04x %04x %02x\n",
  145. le16_to_cpu(hdr.seq), len,
  146. le16_to_cpu(hdr.type), hdr.flags);
  147. if (len <= MAX_MBOXITEM_SIZE) {
  148. int n = 0;
  149. char printbuf[16 * 3 + 2];
  150. unsigned char databuf[MAX_MBOXITEM_SIZE];
  151. void __iomem *src = wmi_buffer(wil, d.addr) +
  152. sizeof(struct wil6210_mbox_hdr);
  153. /*
  154. * No need to check @src for validity -
  155. * we already validated @d.addr while
  156. * reading header
  157. */
  158. wil_memcpy_fromio_32(databuf, src, len);
  159. while (n < len) {
  160. int l = min(len - n, 16);
  161. hex_dump_to_buffer(databuf + n, l,
  162. 16, 1, printbuf,
  163. sizeof(printbuf),
  164. false);
  165. seq_printf(s, " : %s\n", printbuf);
  166. n += l;
  167. }
  168. }
  169. } else {
  170. seq_printf(s, "\n");
  171. }
  172. }
  173. out:
  174. seq_printf(s, "}\n");
  175. }
  176. static int wil_mbox_debugfs_show(struct seq_file *s, void *data)
  177. {
  178. struct wil6210_priv *wil = s->private;
  179. wil_print_ring(s, "tx", wil->csr + HOST_MBOX +
  180. offsetof(struct wil6210_mbox_ctl, tx));
  181. wil_print_ring(s, "rx", wil->csr + HOST_MBOX +
  182. offsetof(struct wil6210_mbox_ctl, rx));
  183. return 0;
  184. }
  185. static int wil_mbox_seq_open(struct inode *inode, struct file *file)
  186. {
  187. return single_open(file, wil_mbox_debugfs_show, inode->i_private);
  188. }
  189. static const struct file_operations fops_mbox = {
  190. .open = wil_mbox_seq_open,
  191. .release = single_release,
  192. .read = seq_read,
  193. .llseek = seq_lseek,
  194. };
  195. static int wil_debugfs_iomem_x32_set(void *data, u64 val)
  196. {
  197. iowrite32(val, (void __iomem *)data);
  198. wmb(); /* make sure write propagated to HW */
  199. return 0;
  200. }
  201. static int wil_debugfs_iomem_x32_get(void *data, u64 *val)
  202. {
  203. *val = ioread32((void __iomem *)data);
  204. return 0;
  205. }
  206. DEFINE_SIMPLE_ATTRIBUTE(fops_iomem_x32, wil_debugfs_iomem_x32_get,
  207. wil_debugfs_iomem_x32_set, "0x%08llx\n");
  208. static struct dentry *wil_debugfs_create_iomem_x32(const char *name,
  209. umode_t mode,
  210. struct dentry *parent,
  211. void __iomem *value)
  212. {
  213. return debugfs_create_file(name, mode, parent, (void * __force)value,
  214. &fops_iomem_x32);
  215. }
  216. static int wil_debugfs_ulong_set(void *data, u64 val)
  217. {
  218. *(ulong *)data = val;
  219. return 0;
  220. }
  221. static int wil_debugfs_ulong_get(void *data, u64 *val)
  222. {
  223. *val = *(ulong *)data;
  224. return 0;
  225. }
  226. DEFINE_SIMPLE_ATTRIBUTE(wil_fops_ulong, wil_debugfs_ulong_get,
  227. wil_debugfs_ulong_set, "%llu\n");
  228. static struct dentry *wil_debugfs_create_ulong(const char *name, umode_t mode,
  229. struct dentry *parent,
  230. ulong *value)
  231. {
  232. return debugfs_create_file(name, mode, parent, value, &wil_fops_ulong);
  233. }
  234. static int wil6210_debugfs_create_ISR(struct wil6210_priv *wil,
  235. const char *name,
  236. struct dentry *parent, u32 off)
  237. {
  238. struct dentry *d = debugfs_create_dir(name, parent);
  239. if (IS_ERR_OR_NULL(d))
  240. return -ENODEV;
  241. wil_debugfs_create_iomem_x32("ICC", S_IRUGO | S_IWUSR, d,
  242. wil->csr + off);
  243. wil_debugfs_create_iomem_x32("ICR", S_IRUGO | S_IWUSR, d,
  244. wil->csr + off + 4);
  245. wil_debugfs_create_iomem_x32("ICM", S_IRUGO | S_IWUSR, d,
  246. wil->csr + off + 8);
  247. wil_debugfs_create_iomem_x32("ICS", S_IWUSR, d,
  248. wil->csr + off + 12);
  249. wil_debugfs_create_iomem_x32("IMV", S_IRUGO | S_IWUSR, d,
  250. wil->csr + off + 16);
  251. wil_debugfs_create_iomem_x32("IMS", S_IWUSR, d,
  252. wil->csr + off + 20);
  253. wil_debugfs_create_iomem_x32("IMC", S_IWUSR, d,
  254. wil->csr + off + 24);
  255. return 0;
  256. }
  257. static int wil6210_debugfs_create_pseudo_ISR(struct wil6210_priv *wil,
  258. struct dentry *parent)
  259. {
  260. struct dentry *d = debugfs_create_dir("PSEUDO_ISR", parent);
  261. if (IS_ERR_OR_NULL(d))
  262. return -ENODEV;
  263. wil_debugfs_create_iomem_x32("CAUSE", S_IRUGO, d, wil->csr +
  264. HOSTADDR(RGF_DMA_PSEUDO_CAUSE));
  265. wil_debugfs_create_iomem_x32("MASK_SW", S_IRUGO, d, wil->csr +
  266. HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW));
  267. wil_debugfs_create_iomem_x32("MASK_FW", S_IRUGO, d, wil->csr +
  268. HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_FW));
  269. return 0;
  270. }
  271. static int wil6210_debugfs_create_ITR_CNT(struct wil6210_priv *wil,
  272. struct dentry *parent)
  273. {
  274. struct dentry *d = debugfs_create_dir("ITR_CNT", parent);
  275. if (IS_ERR_OR_NULL(d))
  276. return -ENODEV;
  277. wil_debugfs_create_iomem_x32("TRSH", S_IRUGO | S_IWUSR, d, wil->csr +
  278. HOSTADDR(RGF_DMA_ITR_CNT_TRSH));
  279. wil_debugfs_create_iomem_x32("DATA", S_IRUGO | S_IWUSR, d, wil->csr +
  280. HOSTADDR(RGF_DMA_ITR_CNT_DATA));
  281. wil_debugfs_create_iomem_x32("CTL", S_IRUGO | S_IWUSR, d, wil->csr +
  282. HOSTADDR(RGF_DMA_ITR_CNT_CRL));
  283. return 0;
  284. }
  285. static int wil_memread_debugfs_show(struct seq_file *s, void *data)
  286. {
  287. struct wil6210_priv *wil = s->private;
  288. void __iomem *a = wmi_buffer(wil, cpu_to_le32(mem_addr));
  289. if (a)
  290. seq_printf(s, "[0x%08x] = 0x%08x\n", mem_addr, ioread32(a));
  291. else
  292. seq_printf(s, "[0x%08x] = INVALID\n", mem_addr);
  293. return 0;
  294. }
  295. static int wil_memread_seq_open(struct inode *inode, struct file *file)
  296. {
  297. return single_open(file, wil_memread_debugfs_show, inode->i_private);
  298. }
  299. static const struct file_operations fops_memread = {
  300. .open = wil_memread_seq_open,
  301. .release = single_release,
  302. .read = seq_read,
  303. .llseek = seq_lseek,
  304. };
  305. static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf,
  306. size_t count, loff_t *ppos)
  307. {
  308. enum { max_count = 4096 };
  309. struct debugfs_blob_wrapper *blob = file->private_data;
  310. loff_t pos = *ppos;
  311. size_t available = blob->size;
  312. void *buf;
  313. size_t ret;
  314. if (pos < 0)
  315. return -EINVAL;
  316. if (pos >= available || !count)
  317. return 0;
  318. if (count > available - pos)
  319. count = available - pos;
  320. if (count > max_count)
  321. count = max_count;
  322. buf = kmalloc(count, GFP_KERNEL);
  323. if (!buf)
  324. return -ENOMEM;
  325. wil_memcpy_fromio_32(buf, (const volatile void __iomem *)blob->data +
  326. pos, count);
  327. ret = copy_to_user(user_buf, buf, count);
  328. kfree(buf);
  329. if (ret == count)
  330. return -EFAULT;
  331. count -= ret;
  332. *ppos = pos + count;
  333. return count;
  334. }
  335. static const struct file_operations fops_ioblob = {
  336. .read = wil_read_file_ioblob,
  337. .open = simple_open,
  338. .llseek = default_llseek,
  339. };
  340. static
  341. struct dentry *wil_debugfs_create_ioblob(const char *name,
  342. umode_t mode,
  343. struct dentry *parent,
  344. struct debugfs_blob_wrapper *blob)
  345. {
  346. return debugfs_create_file(name, mode, parent, blob, &fops_ioblob);
  347. }
  348. /*---reset---*/
  349. static ssize_t wil_write_file_reset(struct file *file, const char __user *buf,
  350. size_t len, loff_t *ppos)
  351. {
  352. struct wil6210_priv *wil = file->private_data;
  353. struct net_device *ndev = wil_to_ndev(wil);
  354. /**
  355. * BUG:
  356. * this code does NOT sync device state with the rest of system
  357. * use with care, debug only!!!
  358. */
  359. rtnl_lock();
  360. dev_close(ndev);
  361. ndev->flags &= ~IFF_UP;
  362. rtnl_unlock();
  363. wil_reset(wil);
  364. return len;
  365. }
  366. static const struct file_operations fops_reset = {
  367. .write = wil_write_file_reset,
  368. .open = simple_open,
  369. };
  370. /*---write channel 1..4 to rxon for it, 0 to rxoff---*/
  371. static ssize_t wil_write_file_rxon(struct file *file, const char __user *buf,
  372. size_t len, loff_t *ppos)
  373. {
  374. struct wil6210_priv *wil = file->private_data;
  375. int rc;
  376. long channel;
  377. bool on;
  378. char *kbuf = kmalloc(len + 1, GFP_KERNEL);
  379. if (!kbuf)
  380. return -ENOMEM;
  381. if (copy_from_user(kbuf, buf, len))
  382. return -EIO;
  383. kbuf[len] = '\0';
  384. rc = kstrtol(kbuf, 0, &channel);
  385. kfree(kbuf);
  386. if (rc)
  387. return rc;
  388. if ((channel < 0) || (channel > 4)) {
  389. wil_err(wil, "Invalid channel %ld\n", channel);
  390. return -EINVAL;
  391. }
  392. on = !!channel;
  393. if (on) {
  394. rc = wmi_set_channel(wil, (int)channel);
  395. if (rc)
  396. return rc;
  397. }
  398. rc = wmi_rxon(wil, on);
  399. if (rc)
  400. return rc;
  401. return len;
  402. }
  403. static const struct file_operations fops_rxon = {
  404. .write = wil_write_file_rxon,
  405. .open = simple_open,
  406. };
  407. /*---tx_mgmt---*/
  408. /* Write mgmt frame to this file to send it */
  409. static ssize_t wil_write_file_txmgmt(struct file *file, const char __user *buf,
  410. size_t len, loff_t *ppos)
  411. {
  412. struct wil6210_priv *wil = file->private_data;
  413. struct wiphy *wiphy = wil_to_wiphy(wil);
  414. struct wireless_dev *wdev = wil_to_wdev(wil);
  415. struct cfg80211_mgmt_tx_params params;
  416. int rc;
  417. void *frame = kmalloc(len, GFP_KERNEL);
  418. if (!frame)
  419. return -ENOMEM;
  420. if (copy_from_user(frame, buf, len))
  421. return -EIO;
  422. params.buf = frame;
  423. params.len = len;
  424. params.chan = wdev->preset_chandef.chan;
  425. rc = wil_cfg80211_mgmt_tx(wiphy, wdev, &params, NULL);
  426. kfree(frame);
  427. wil_info(wil, "%s() -> %d\n", __func__, rc);
  428. return len;
  429. }
  430. static const struct file_operations fops_txmgmt = {
  431. .write = wil_write_file_txmgmt,
  432. .open = simple_open,
  433. };
  434. /* Write WMI command (w/o mbox header) to this file to send it
  435. * WMI starts from wil6210_mbox_hdr_wmi header
  436. */
  437. static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf,
  438. size_t len, loff_t *ppos)
  439. {
  440. struct wil6210_priv *wil = file->private_data;
  441. struct wil6210_mbox_hdr_wmi *wmi;
  442. void *cmd;
  443. int cmdlen = len - sizeof(struct wil6210_mbox_hdr_wmi);
  444. u16 cmdid;
  445. int rc, rc1;
  446. if (cmdlen <= 0)
  447. return -EINVAL;
  448. wmi = kmalloc(len, GFP_KERNEL);
  449. if (!wmi)
  450. return -ENOMEM;
  451. rc = simple_write_to_buffer(wmi, len, ppos, buf, len);
  452. if (rc < 0)
  453. return rc;
  454. cmd = &wmi[1];
  455. cmdid = le16_to_cpu(wmi->id);
  456. rc1 = wmi_send(wil, cmdid, cmd, cmdlen);
  457. kfree(wmi);
  458. wil_info(wil, "%s(0x%04x[%d]) -> %d\n", __func__, cmdid, cmdlen, rc1);
  459. return rc;
  460. }
  461. static const struct file_operations fops_wmi = {
  462. .write = wil_write_file_wmi,
  463. .open = simple_open,
  464. };
  465. static void wil_seq_hexdump(struct seq_file *s, void *p, int len,
  466. const char *prefix)
  467. {
  468. char printbuf[16 * 3 + 2];
  469. int i = 0;
  470. while (i < len) {
  471. int l = min(len - i, 16);
  472. hex_dump_to_buffer(p + i, l, 16, 1, printbuf,
  473. sizeof(printbuf), false);
  474. seq_printf(s, "%s%s\n", prefix, printbuf);
  475. i += l;
  476. }
  477. }
  478. static void wil_seq_print_skb(struct seq_file *s, struct sk_buff *skb)
  479. {
  480. int i = 0;
  481. int len = skb_headlen(skb);
  482. void *p = skb->data;
  483. int nr_frags = skb_shinfo(skb)->nr_frags;
  484. seq_printf(s, " len = %d\n", len);
  485. wil_seq_hexdump(s, p, len, " : ");
  486. if (nr_frags) {
  487. seq_printf(s, " nr_frags = %d\n", nr_frags);
  488. for (i = 0; i < nr_frags; i++) {
  489. const struct skb_frag_struct *frag =
  490. &skb_shinfo(skb)->frags[i];
  491. len = skb_frag_size(frag);
  492. p = skb_frag_address_safe(frag);
  493. seq_printf(s, " [%2d] : len = %d\n", i, len);
  494. wil_seq_hexdump(s, p, len, " : ");
  495. }
  496. }
  497. }
  498. /*---------Tx/Rx descriptor------------*/
  499. static int wil_txdesc_debugfs_show(struct seq_file *s, void *data)
  500. {
  501. struct wil6210_priv *wil = s->private;
  502. struct vring *vring;
  503. bool tx = (dbg_vring_index < WIL6210_MAX_TX_RINGS);
  504. if (tx)
  505. vring = &(wil->vring_tx[dbg_vring_index]);
  506. else
  507. vring = &wil->vring_rx;
  508. if (!vring->va) {
  509. if (tx)
  510. seq_printf(s, "No Tx[%2d] VRING\n", dbg_vring_index);
  511. else
  512. seq_puts(s, "No Rx VRING\n");
  513. return 0;
  514. }
  515. if (dbg_txdesc_index < vring->size) {
  516. /* use struct vring_tx_desc for Rx as well,
  517. * only field used, .dma.length, is the same
  518. */
  519. volatile struct vring_tx_desc *d =
  520. &(vring->va[dbg_txdesc_index].tx);
  521. volatile u32 *u = (volatile u32 *)d;
  522. struct sk_buff *skb = vring->ctx[dbg_txdesc_index].skb;
  523. if (tx)
  524. seq_printf(s, "Tx[%2d][%3d] = {\n", dbg_vring_index,
  525. dbg_txdesc_index);
  526. else
  527. seq_printf(s, "Rx[%3d] = {\n", dbg_txdesc_index);
  528. seq_printf(s, " MAC = 0x%08x 0x%08x 0x%08x 0x%08x\n",
  529. u[0], u[1], u[2], u[3]);
  530. seq_printf(s, " DMA = 0x%08x 0x%08x 0x%08x 0x%08x\n",
  531. u[4], u[5], u[6], u[7]);
  532. seq_printf(s, " SKB = 0x%p\n", skb);
  533. if (skb) {
  534. skb_get(skb);
  535. wil_seq_print_skb(s, skb);
  536. kfree_skb(skb);
  537. }
  538. seq_printf(s, "}\n");
  539. } else {
  540. if (tx)
  541. seq_printf(s, "[%2d] TxDesc index (%d) >= size (%d)\n",
  542. dbg_vring_index, dbg_txdesc_index,
  543. vring->size);
  544. else
  545. seq_printf(s, "RxDesc index (%d) >= size (%d)\n",
  546. dbg_txdesc_index, vring->size);
  547. }
  548. return 0;
  549. }
  550. static int wil_txdesc_seq_open(struct inode *inode, struct file *file)
  551. {
  552. return single_open(file, wil_txdesc_debugfs_show, inode->i_private);
  553. }
  554. static const struct file_operations fops_txdesc = {
  555. .open = wil_txdesc_seq_open,
  556. .release = single_release,
  557. .read = seq_read,
  558. .llseek = seq_lseek,
  559. };
  560. /*---------beamforming------------*/
  561. static int wil_bf_debugfs_show(struct seq_file *s, void *data)
  562. {
  563. struct wil6210_priv *wil = s->private;
  564. seq_printf(s,
  565. "TSF : 0x%016llx\n"
  566. "TxMCS : %d\n"
  567. "Sectors(rx:tx) my %2d:%2d peer %2d:%2d\n",
  568. wil->stats.tsf, wil->stats.bf_mcs,
  569. wil->stats.my_rx_sector, wil->stats.my_tx_sector,
  570. wil->stats.peer_rx_sector, wil->stats.peer_tx_sector);
  571. return 0;
  572. }
  573. static int wil_bf_seq_open(struct inode *inode, struct file *file)
  574. {
  575. return single_open(file, wil_bf_debugfs_show, inode->i_private);
  576. }
  577. static const struct file_operations fops_bf = {
  578. .open = wil_bf_seq_open,
  579. .release = single_release,
  580. .read = seq_read,
  581. .llseek = seq_lseek,
  582. };
  583. /*---------SSID------------*/
  584. static ssize_t wil_read_file_ssid(struct file *file, char __user *user_buf,
  585. size_t count, loff_t *ppos)
  586. {
  587. struct wil6210_priv *wil = file->private_data;
  588. struct wireless_dev *wdev = wil_to_wdev(wil);
  589. return simple_read_from_buffer(user_buf, count, ppos,
  590. wdev->ssid, wdev->ssid_len);
  591. }
  592. static ssize_t wil_write_file_ssid(struct file *file, const char __user *buf,
  593. size_t count, loff_t *ppos)
  594. {
  595. struct wil6210_priv *wil = file->private_data;
  596. struct wireless_dev *wdev = wil_to_wdev(wil);
  597. struct net_device *ndev = wil_to_ndev(wil);
  598. if (*ppos != 0) {
  599. wil_err(wil, "Unable to set SSID substring from [%d]\n",
  600. (int)*ppos);
  601. return -EINVAL;
  602. }
  603. if (count > sizeof(wdev->ssid)) {
  604. wil_err(wil, "SSID too long, len = %d\n", (int)count);
  605. return -EINVAL;
  606. }
  607. if (netif_running(ndev)) {
  608. wil_err(wil, "Unable to change SSID on running interface\n");
  609. return -EINVAL;
  610. }
  611. wdev->ssid_len = count;
  612. return simple_write_to_buffer(wdev->ssid, wdev->ssid_len, ppos,
  613. buf, count);
  614. }
  615. static const struct file_operations fops_ssid = {
  616. .read = wil_read_file_ssid,
  617. .write = wil_write_file_ssid,
  618. .open = simple_open,
  619. };
  620. /*---------temp------------*/
  621. static void print_temp(struct seq_file *s, const char *prefix, u32 t)
  622. {
  623. switch (t) {
  624. case 0:
  625. case ~(u32)0:
  626. seq_printf(s, "%s N/A\n", prefix);
  627. break;
  628. default:
  629. seq_printf(s, "%s %d.%03d\n", prefix, t / 1000, t % 1000);
  630. break;
  631. }
  632. }
  633. static int wil_temp_debugfs_show(struct seq_file *s, void *data)
  634. {
  635. struct wil6210_priv *wil = s->private;
  636. u32 t_m, t_r;
  637. int rc = wmi_get_temperature(wil, &t_m, &t_r);
  638. if (rc) {
  639. seq_printf(s, "Failed\n");
  640. return 0;
  641. }
  642. print_temp(s, "T_mac =", t_m);
  643. print_temp(s, "T_radio =", t_r);
  644. return 0;
  645. }
  646. static int wil_temp_seq_open(struct inode *inode, struct file *file)
  647. {
  648. return single_open(file, wil_temp_debugfs_show, inode->i_private);
  649. }
  650. static const struct file_operations fops_temp = {
  651. .open = wil_temp_seq_open,
  652. .release = single_release,
  653. .read = seq_read,
  654. .llseek = seq_lseek,
  655. };
  656. /*---------freq------------*/
  657. static int wil_freq_debugfs_show(struct seq_file *s, void *data)
  658. {
  659. struct wil6210_priv *wil = s->private;
  660. struct wireless_dev *wdev = wil_to_wdev(wil);
  661. u16 freq = wdev->chandef.chan ? wdev->chandef.chan->center_freq : 0;
  662. seq_printf(s, "Freq = %d\n", freq);
  663. return 0;
  664. }
  665. static int wil_freq_seq_open(struct inode *inode, struct file *file)
  666. {
  667. return single_open(file, wil_freq_debugfs_show, inode->i_private);
  668. }
  669. static const struct file_operations fops_freq = {
  670. .open = wil_freq_seq_open,
  671. .release = single_release,
  672. .read = seq_read,
  673. .llseek = seq_lseek,
  674. };
  675. /*---------link------------*/
  676. static int wil_link_debugfs_show(struct seq_file *s, void *data)
  677. {
  678. struct wil6210_priv *wil = s->private;
  679. struct station_info sinfo;
  680. int i, rc;
  681. for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
  682. struct wil_sta_info *p = &wil->sta[i];
  683. char *status = "unknown";
  684. switch (p->status) {
  685. case wil_sta_unused:
  686. status = "unused ";
  687. break;
  688. case wil_sta_conn_pending:
  689. status = "pending ";
  690. break;
  691. case wil_sta_connected:
  692. status = "connected";
  693. break;
  694. }
  695. seq_printf(s, "[%d] %pM %s%s\n", i, p->addr, status,
  696. (p->data_port_open ? " data_port_open" : ""));
  697. if (p->status == wil_sta_connected) {
  698. rc = wil_cid_fill_sinfo(wil, i, &sinfo);
  699. if (rc)
  700. return rc;
  701. seq_printf(s, " Tx_mcs = %d\n", sinfo.txrate.mcs);
  702. seq_printf(s, " Rx_mcs = %d\n", sinfo.rxrate.mcs);
  703. seq_printf(s, " SQ = %d\n", sinfo.signal);
  704. }
  705. }
  706. return 0;
  707. }
  708. static int wil_link_seq_open(struct inode *inode, struct file *file)
  709. {
  710. return single_open(file, wil_link_debugfs_show, inode->i_private);
  711. }
  712. static const struct file_operations fops_link = {
  713. .open = wil_link_seq_open,
  714. .release = single_release,
  715. .read = seq_read,
  716. .llseek = seq_lseek,
  717. };
  718. /*---------info------------*/
  719. static int wil_info_debugfs_show(struct seq_file *s, void *data)
  720. {
  721. struct wil6210_priv *wil = s->private;
  722. struct net_device *ndev = wil_to_ndev(wil);
  723. int is_ac = power_supply_is_system_supplied();
  724. int rx = atomic_xchg(&wil->isr_count_rx, 0);
  725. int tx = atomic_xchg(&wil->isr_count_tx, 0);
  726. static ulong rxf_old, txf_old;
  727. ulong rxf = ndev->stats.rx_packets;
  728. ulong txf = ndev->stats.tx_packets;
  729. unsigned int i;
  730. /* >0 : AC; 0 : battery; <0 : error */
  731. seq_printf(s, "AC powered : %d\n", is_ac);
  732. seq_printf(s, "Rx irqs:packets : %8d : %8ld\n", rx, rxf - rxf_old);
  733. seq_printf(s, "Tx irqs:packets : %8d : %8ld\n", tx, txf - txf_old);
  734. rxf_old = rxf;
  735. txf_old = txf;
  736. #define CHECK_QSTATE(x) (state & BIT(__QUEUE_STATE_ ## x)) ? \
  737. " " __stringify(x) : ""
  738. for (i = 0; i < ndev->num_tx_queues; i++) {
  739. struct netdev_queue *txq = netdev_get_tx_queue(ndev, i);
  740. unsigned long state = txq->state;
  741. seq_printf(s, "Tx queue[%i] state : 0x%lx%s%s%s\n", i, state,
  742. CHECK_QSTATE(DRV_XOFF),
  743. CHECK_QSTATE(STACK_XOFF),
  744. CHECK_QSTATE(FROZEN)
  745. );
  746. }
  747. #undef CHECK_QSTATE
  748. return 0;
  749. }
  750. static int wil_info_seq_open(struct inode *inode, struct file *file)
  751. {
  752. return single_open(file, wil_info_debugfs_show, inode->i_private);
  753. }
  754. static const struct file_operations fops_info = {
  755. .open = wil_info_seq_open,
  756. .release = single_release,
  757. .read = seq_read,
  758. .llseek = seq_lseek,
  759. };
  760. /*---------Station matrix------------*/
  761. static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r)
  762. {
  763. int i;
  764. u16 index = ((r->head_seq_num - r->ssn) & 0xfff) % r->buf_size;
  765. seq_printf(s, "0x%03x [", r->head_seq_num);
  766. for (i = 0; i < r->buf_size; i++) {
  767. if (i == index)
  768. seq_printf(s, "%c", r->reorder_buf[i] ? 'O' : '|');
  769. else
  770. seq_printf(s, "%c", r->reorder_buf[i] ? '*' : '_');
  771. }
  772. seq_printf(s, "] last drop 0x%03x\n", r->ssn_last_drop);
  773. }
  774. static int wil_sta_debugfs_show(struct seq_file *s, void *data)
  775. {
  776. struct wil6210_priv *wil = s->private;
  777. int i, tid;
  778. for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
  779. struct wil_sta_info *p = &wil->sta[i];
  780. char *status = "unknown";
  781. switch (p->status) {
  782. case wil_sta_unused:
  783. status = "unused ";
  784. break;
  785. case wil_sta_conn_pending:
  786. status = "pending ";
  787. break;
  788. case wil_sta_connected:
  789. status = "connected";
  790. break;
  791. }
  792. seq_printf(s, "[%d] %pM %s%s\n", i, p->addr, status,
  793. (p->data_port_open ? " data_port_open" : ""));
  794. if (p->status == wil_sta_connected) {
  795. for (tid = 0; tid < WIL_STA_TID_NUM; tid++) {
  796. struct wil_tid_ampdu_rx *r = p->tid_rx[tid];
  797. if (r) {
  798. seq_printf(s, "[%2d] ", tid);
  799. wil_print_rxtid(s, r);
  800. }
  801. }
  802. }
  803. }
  804. return 0;
  805. }
  806. static int wil_sta_seq_open(struct inode *inode, struct file *file)
  807. {
  808. return single_open(file, wil_sta_debugfs_show, inode->i_private);
  809. }
  810. static const struct file_operations fops_sta = {
  811. .open = wil_sta_seq_open,
  812. .release = single_release,
  813. .read = seq_read,
  814. .llseek = seq_lseek,
  815. };
  816. /*----------------*/
  817. int wil6210_debugfs_init(struct wil6210_priv *wil)
  818. {
  819. struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME,
  820. wil_to_wiphy(wil)->debugfsdir);
  821. if (IS_ERR_OR_NULL(dbg))
  822. return -ENODEV;
  823. debugfs_create_file("mbox", S_IRUGO, dbg, wil, &fops_mbox);
  824. debugfs_create_file("vrings", S_IRUGO, dbg, wil, &fops_vring);
  825. debugfs_create_file("stations", S_IRUGO, dbg, wil, &fops_sta);
  826. debugfs_create_file("desc", S_IRUGO, dbg, wil, &fops_txdesc);
  827. debugfs_create_u32("desc_index", S_IRUGO | S_IWUSR, dbg,
  828. &dbg_txdesc_index);
  829. debugfs_create_u32("vring_index", S_IRUGO | S_IWUSR, dbg,
  830. &dbg_vring_index);
  831. debugfs_create_file("bf", S_IRUGO, dbg, wil, &fops_bf);
  832. debugfs_create_file("ssid", S_IRUGO | S_IWUSR, dbg, wil, &fops_ssid);
  833. debugfs_create_u32("secure_pcp", S_IRUGO | S_IWUSR, dbg,
  834. &wil->secure_pcp);
  835. wil_debugfs_create_ulong("status", S_IRUGO | S_IWUSR, dbg,
  836. &wil->status);
  837. wil6210_debugfs_create_ISR(wil, "USER_ICR", dbg,
  838. HOSTADDR(RGF_USER_USER_ICR));
  839. wil6210_debugfs_create_ISR(wil, "DMA_EP_TX_ICR", dbg,
  840. HOSTADDR(RGF_DMA_EP_TX_ICR));
  841. wil6210_debugfs_create_ISR(wil, "DMA_EP_RX_ICR", dbg,
  842. HOSTADDR(RGF_DMA_EP_RX_ICR));
  843. wil6210_debugfs_create_ISR(wil, "DMA_EP_MISC_ICR", dbg,
  844. HOSTADDR(RGF_DMA_EP_MISC_ICR));
  845. wil6210_debugfs_create_pseudo_ISR(wil, dbg);
  846. wil6210_debugfs_create_ITR_CNT(wil, dbg);
  847. debugfs_create_u32("mem_addr", S_IRUGO | S_IWUSR, dbg, &mem_addr);
  848. debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread);
  849. debugfs_create_file("reset", S_IWUSR, dbg, wil, &fops_reset);
  850. debugfs_create_file("rxon", S_IWUSR, dbg, wil, &fops_rxon);
  851. debugfs_create_file("tx_mgmt", S_IWUSR, dbg, wil, &fops_txmgmt);
  852. debugfs_create_file("wmi_send", S_IWUSR, dbg, wil, &fops_wmi);
  853. debugfs_create_file("temp", S_IRUGO, dbg, wil, &fops_temp);
  854. debugfs_create_file("freq", S_IRUGO, dbg, wil, &fops_freq);
  855. debugfs_create_file("link", S_IRUGO, dbg, wil, &fops_link);
  856. debugfs_create_file("info", S_IRUGO, dbg, wil, &fops_info);
  857. wil->rgf_blob.data = (void * __force)wil->csr + 0;
  858. wil->rgf_blob.size = 0xa000;
  859. wil_debugfs_create_ioblob("blob_rgf", S_IRUGO, dbg, &wil->rgf_blob);
  860. wil->fw_code_blob.data = (void * __force)wil->csr + 0x40000;
  861. wil->fw_code_blob.size = 0x40000;
  862. wil_debugfs_create_ioblob("blob_fw_code", S_IRUGO, dbg,
  863. &wil->fw_code_blob);
  864. wil->fw_data_blob.data = (void * __force)wil->csr + 0x80000;
  865. wil->fw_data_blob.size = 0x8000;
  866. wil_debugfs_create_ioblob("blob_fw_data", S_IRUGO, dbg,
  867. &wil->fw_data_blob);
  868. wil->fw_peri_blob.data = (void * __force)wil->csr + 0x88000;
  869. wil->fw_peri_blob.size = 0x18000;
  870. wil_debugfs_create_ioblob("blob_fw_peri", S_IRUGO, dbg,
  871. &wil->fw_peri_blob);
  872. wil->uc_code_blob.data = (void * __force)wil->csr + 0xa0000;
  873. wil->uc_code_blob.size = 0x10000;
  874. wil_debugfs_create_ioblob("blob_uc_code", S_IRUGO, dbg,
  875. &wil->uc_code_blob);
  876. wil->uc_data_blob.data = (void * __force)wil->csr + 0xb0000;
  877. wil->uc_data_blob.size = 0x4000;
  878. wil_debugfs_create_ioblob("blob_uc_data", S_IRUGO, dbg,
  879. &wil->uc_data_blob);
  880. return 0;
  881. }
  882. void wil6210_debugfs_remove(struct wil6210_priv *wil)
  883. {
  884. debugfs_remove_recursive(wil->debug);
  885. wil->debug = NULL;
  886. }