bnad_debugfs.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. /*
  2. * Linux network driver for QLogic BR-series Converged Network Adapter.
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License (GPL) Version 2 as
  6. * published by the Free Software Foundation
  7. *
  8. * This program is distributed in the hope that it will be useful, but
  9. * WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. * General Public License for more details.
  12. */
  13. /*
  14. * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
  15. * Copyright (c) 2014-2015 QLogic Corporation
  16. * All rights reserved
  17. * www.qlogic.com
  18. */
  19. #include <linux/debugfs.h>
  20. #include <linux/module.h>
  21. #include "bnad.h"
  22. /*
  23. * BNA debufs interface
  24. *
  25. * To access the interface, debugfs file system should be mounted
  26. * if not already mounted using:
  27. * mount -t debugfs none /sys/kernel/debug
  28. *
  29. * BNA Hierarchy:
  30. * - bna/pci_dev:<pci_name>
  31. * where the pci_name corresponds to the one under /sys/bus/pci/drivers/bna
  32. *
  33. * Debugging service available per pci_dev:
  34. * fwtrc: To collect current firmware trace.
  35. * fwsave: To collect last saved fw trace as a result of firmware crash.
  36. * regwr: To write one word to chip register
  37. * regrd: To read one or more words from chip register.
  38. */
  39. struct bnad_debug_info {
  40. char *debug_buffer;
  41. void *i_private;
  42. int buffer_len;
  43. };
  44. static int
  45. bnad_debugfs_open_fwtrc(struct inode *inode, struct file *file)
  46. {
  47. struct bnad *bnad = inode->i_private;
  48. struct bnad_debug_info *fw_debug;
  49. unsigned long flags;
  50. int rc;
  51. fw_debug = kzalloc(sizeof(struct bnad_debug_info), GFP_KERNEL);
  52. if (!fw_debug)
  53. return -ENOMEM;
  54. fw_debug->buffer_len = BNA_DBG_FWTRC_LEN;
  55. fw_debug->debug_buffer = kzalloc(fw_debug->buffer_len, GFP_KERNEL);
  56. if (!fw_debug->debug_buffer) {
  57. kfree(fw_debug);
  58. fw_debug = NULL;
  59. return -ENOMEM;
  60. }
  61. spin_lock_irqsave(&bnad->bna_lock, flags);
  62. rc = bfa_nw_ioc_debug_fwtrc(&bnad->bna.ioceth.ioc,
  63. fw_debug->debug_buffer,
  64. &fw_debug->buffer_len);
  65. spin_unlock_irqrestore(&bnad->bna_lock, flags);
  66. if (rc != BFA_STATUS_OK) {
  67. kfree(fw_debug->debug_buffer);
  68. fw_debug->debug_buffer = NULL;
  69. kfree(fw_debug);
  70. fw_debug = NULL;
  71. netdev_warn(bnad->netdev, "failed to collect fwtrc\n");
  72. return -ENOMEM;
  73. }
  74. file->private_data = fw_debug;
  75. return 0;
  76. }
  77. static int
  78. bnad_debugfs_open_fwsave(struct inode *inode, struct file *file)
  79. {
  80. struct bnad *bnad = inode->i_private;
  81. struct bnad_debug_info *fw_debug;
  82. unsigned long flags;
  83. int rc;
  84. fw_debug = kzalloc(sizeof(struct bnad_debug_info), GFP_KERNEL);
  85. if (!fw_debug)
  86. return -ENOMEM;
  87. fw_debug->buffer_len = BNA_DBG_FWTRC_LEN;
  88. fw_debug->debug_buffer = kzalloc(fw_debug->buffer_len, GFP_KERNEL);
  89. if (!fw_debug->debug_buffer) {
  90. kfree(fw_debug);
  91. fw_debug = NULL;
  92. return -ENOMEM;
  93. }
  94. spin_lock_irqsave(&bnad->bna_lock, flags);
  95. rc = bfa_nw_ioc_debug_fwsave(&bnad->bna.ioceth.ioc,
  96. fw_debug->debug_buffer,
  97. &fw_debug->buffer_len);
  98. spin_unlock_irqrestore(&bnad->bna_lock, flags);
  99. if (rc != BFA_STATUS_OK && rc != BFA_STATUS_ENOFSAVE) {
  100. kfree(fw_debug->debug_buffer);
  101. fw_debug->debug_buffer = NULL;
  102. kfree(fw_debug);
  103. fw_debug = NULL;
  104. netdev_warn(bnad->netdev, "failed to collect fwsave\n");
  105. return -ENOMEM;
  106. }
  107. file->private_data = fw_debug;
  108. return 0;
  109. }
  110. static int
  111. bnad_debugfs_open_reg(struct inode *inode, struct file *file)
  112. {
  113. struct bnad_debug_info *reg_debug;
  114. reg_debug = kzalloc(sizeof(struct bnad_debug_info), GFP_KERNEL);
  115. if (!reg_debug)
  116. return -ENOMEM;
  117. reg_debug->i_private = inode->i_private;
  118. file->private_data = reg_debug;
  119. return 0;
  120. }
  121. static int
  122. bnad_get_debug_drvinfo(struct bnad *bnad, void *buffer, u32 len)
  123. {
  124. struct bnad_drvinfo *drvinfo = (struct bnad_drvinfo *) buffer;
  125. struct bnad_iocmd_comp fcomp;
  126. unsigned long flags = 0;
  127. int ret = BFA_STATUS_FAILED;
  128. /* Get IOC info */
  129. spin_lock_irqsave(&bnad->bna_lock, flags);
  130. bfa_nw_ioc_get_attr(&bnad->bna.ioceth.ioc, &drvinfo->ioc_attr);
  131. spin_unlock_irqrestore(&bnad->bna_lock, flags);
  132. /* Retrieve CEE related info */
  133. fcomp.bnad = bnad;
  134. fcomp.comp_status = 0;
  135. init_completion(&fcomp.comp);
  136. spin_lock_irqsave(&bnad->bna_lock, flags);
  137. ret = bfa_nw_cee_get_attr(&bnad->bna.cee, &drvinfo->cee_attr,
  138. bnad_cb_completion, &fcomp);
  139. if (ret != BFA_STATUS_OK) {
  140. spin_unlock_irqrestore(&bnad->bna_lock, flags);
  141. goto out;
  142. }
  143. spin_unlock_irqrestore(&bnad->bna_lock, flags);
  144. wait_for_completion(&fcomp.comp);
  145. drvinfo->cee_status = fcomp.comp_status;
  146. /* Retrieve flash partition info */
  147. fcomp.comp_status = 0;
  148. reinit_completion(&fcomp.comp);
  149. spin_lock_irqsave(&bnad->bna_lock, flags);
  150. ret = bfa_nw_flash_get_attr(&bnad->bna.flash, &drvinfo->flash_attr,
  151. bnad_cb_completion, &fcomp);
  152. if (ret != BFA_STATUS_OK) {
  153. spin_unlock_irqrestore(&bnad->bna_lock, flags);
  154. goto out;
  155. }
  156. spin_unlock_irqrestore(&bnad->bna_lock, flags);
  157. wait_for_completion(&fcomp.comp);
  158. drvinfo->flash_status = fcomp.comp_status;
  159. out:
  160. return ret;
  161. }
  162. static int
  163. bnad_debugfs_open_drvinfo(struct inode *inode, struct file *file)
  164. {
  165. struct bnad *bnad = inode->i_private;
  166. struct bnad_debug_info *drv_info;
  167. int rc;
  168. drv_info = kzalloc(sizeof(struct bnad_debug_info), GFP_KERNEL);
  169. if (!drv_info)
  170. return -ENOMEM;
  171. drv_info->buffer_len = sizeof(struct bnad_drvinfo);
  172. drv_info->debug_buffer = kzalloc(drv_info->buffer_len, GFP_KERNEL);
  173. if (!drv_info->debug_buffer) {
  174. kfree(drv_info);
  175. drv_info = NULL;
  176. return -ENOMEM;
  177. }
  178. mutex_lock(&bnad->conf_mutex);
  179. rc = bnad_get_debug_drvinfo(bnad, drv_info->debug_buffer,
  180. drv_info->buffer_len);
  181. mutex_unlock(&bnad->conf_mutex);
  182. if (rc != BFA_STATUS_OK) {
  183. kfree(drv_info->debug_buffer);
  184. drv_info->debug_buffer = NULL;
  185. kfree(drv_info);
  186. drv_info = NULL;
  187. netdev_warn(bnad->netdev, "failed to collect drvinfo\n");
  188. return -ENOMEM;
  189. }
  190. file->private_data = drv_info;
  191. return 0;
  192. }
  193. /* Changes the current file position */
  194. static loff_t
  195. bnad_debugfs_lseek(struct file *file, loff_t offset, int orig)
  196. {
  197. struct bnad_debug_info *debug = file->private_data;
  198. if (!debug)
  199. return -EINVAL;
  200. return fixed_size_llseek(file, offset, orig, debug->buffer_len);
  201. }
  202. static ssize_t
  203. bnad_debugfs_read(struct file *file, char __user *buf,
  204. size_t nbytes, loff_t *pos)
  205. {
  206. struct bnad_debug_info *debug = file->private_data;
  207. if (!debug || !debug->debug_buffer)
  208. return 0;
  209. return simple_read_from_buffer(buf, nbytes, pos,
  210. debug->debug_buffer, debug->buffer_len);
  211. }
  212. #define BFA_REG_CT_ADDRSZ (0x40000)
  213. #define BFA_REG_CB_ADDRSZ (0x20000)
  214. #define BFA_REG_ADDRSZ(__ioc) \
  215. ((u32)(bfa_asic_id_ctc(bfa_ioc_devid(__ioc)) ? \
  216. BFA_REG_CT_ADDRSZ : BFA_REG_CB_ADDRSZ))
  217. #define BFA_REG_ADDRMSK(__ioc) (BFA_REG_ADDRSZ(__ioc) - 1)
  218. /*
  219. * Function to check if the register offset passed is valid.
  220. */
  221. static int
  222. bna_reg_offset_check(struct bfa_ioc *ioc, u32 offset, u32 len)
  223. {
  224. u8 area;
  225. /* check [16:15] */
  226. area = (offset >> 15) & 0x7;
  227. if (area == 0) {
  228. /* PCIe core register */
  229. if (offset + (len << 2) > 0x8000) /* 8k dwords or 32KB */
  230. return BFA_STATUS_EINVAL;
  231. } else if (area == 0x1) {
  232. /* CB 32 KB memory page */
  233. if (offset + (len << 2) > 0x10000) /* 8k dwords or 32KB */
  234. return BFA_STATUS_EINVAL;
  235. } else {
  236. /* CB register space 64KB */
  237. if (offset + (len << 2) > BFA_REG_ADDRMSK(ioc))
  238. return BFA_STATUS_EINVAL;
  239. }
  240. return BFA_STATUS_OK;
  241. }
  242. static ssize_t
  243. bnad_debugfs_read_regrd(struct file *file, char __user *buf,
  244. size_t nbytes, loff_t *pos)
  245. {
  246. struct bnad_debug_info *regrd_debug = file->private_data;
  247. struct bnad *bnad = (struct bnad *)regrd_debug->i_private;
  248. ssize_t rc;
  249. if (!bnad->regdata)
  250. return 0;
  251. rc = simple_read_from_buffer(buf, nbytes, pos,
  252. bnad->regdata, bnad->reglen);
  253. if ((*pos + nbytes) >= bnad->reglen) {
  254. kfree(bnad->regdata);
  255. bnad->regdata = NULL;
  256. bnad->reglen = 0;
  257. }
  258. return rc;
  259. }
  260. static ssize_t
  261. bnad_debugfs_write_regrd(struct file *file, const char __user *buf,
  262. size_t nbytes, loff_t *ppos)
  263. {
  264. struct bnad_debug_info *regrd_debug = file->private_data;
  265. struct bnad *bnad = (struct bnad *)regrd_debug->i_private;
  266. struct bfa_ioc *ioc = &bnad->bna.ioceth.ioc;
  267. int rc, i;
  268. u32 addr, len;
  269. u32 *regbuf;
  270. void __iomem *rb, *reg_addr;
  271. unsigned long flags;
  272. void *kern_buf;
  273. /* Copy the user space buf */
  274. kern_buf = memdup_user(buf, nbytes);
  275. if (IS_ERR(kern_buf))
  276. return PTR_ERR(kern_buf);
  277. rc = sscanf(kern_buf, "%x:%x", &addr, &len);
  278. if (rc < 2) {
  279. netdev_warn(bnad->netdev, "failed to read user buffer\n");
  280. kfree(kern_buf);
  281. return -EINVAL;
  282. }
  283. kfree(kern_buf);
  284. kfree(bnad->regdata);
  285. bnad->reglen = 0;
  286. bnad->regdata = kzalloc(len << 2, GFP_KERNEL);
  287. if (!bnad->regdata)
  288. return -ENOMEM;
  289. bnad->reglen = len << 2;
  290. rb = bfa_ioc_bar0(ioc);
  291. addr &= BFA_REG_ADDRMSK(ioc);
  292. /* offset and len sanity check */
  293. rc = bna_reg_offset_check(ioc, addr, len);
  294. if (rc) {
  295. netdev_warn(bnad->netdev, "failed reg offset check\n");
  296. kfree(bnad->regdata);
  297. bnad->regdata = NULL;
  298. bnad->reglen = 0;
  299. return -EINVAL;
  300. }
  301. reg_addr = rb + addr;
  302. regbuf = (u32 *)bnad->regdata;
  303. spin_lock_irqsave(&bnad->bna_lock, flags);
  304. for (i = 0; i < len; i++) {
  305. *regbuf = readl(reg_addr);
  306. regbuf++;
  307. reg_addr += sizeof(u32);
  308. }
  309. spin_unlock_irqrestore(&bnad->bna_lock, flags);
  310. return nbytes;
  311. }
  312. static ssize_t
  313. bnad_debugfs_write_regwr(struct file *file, const char __user *buf,
  314. size_t nbytes, loff_t *ppos)
  315. {
  316. struct bnad_debug_info *debug = file->private_data;
  317. struct bnad *bnad = (struct bnad *)debug->i_private;
  318. struct bfa_ioc *ioc = &bnad->bna.ioceth.ioc;
  319. int rc;
  320. u32 addr, val;
  321. void __iomem *reg_addr;
  322. unsigned long flags;
  323. void *kern_buf;
  324. /* Copy the user space buf */
  325. kern_buf = memdup_user(buf, nbytes);
  326. if (IS_ERR(kern_buf))
  327. return PTR_ERR(kern_buf);
  328. rc = sscanf(kern_buf, "%x:%x", &addr, &val);
  329. if (rc < 2) {
  330. netdev_warn(bnad->netdev, "failed to read user buffer\n");
  331. kfree(kern_buf);
  332. return -EINVAL;
  333. }
  334. kfree(kern_buf);
  335. addr &= BFA_REG_ADDRMSK(ioc); /* offset only 17 bit and word align */
  336. /* offset and len sanity check */
  337. rc = bna_reg_offset_check(ioc, addr, 1);
  338. if (rc) {
  339. netdev_warn(bnad->netdev, "failed reg offset check\n");
  340. return -EINVAL;
  341. }
  342. reg_addr = (bfa_ioc_bar0(ioc)) + addr;
  343. spin_lock_irqsave(&bnad->bna_lock, flags);
  344. writel(val, reg_addr);
  345. spin_unlock_irqrestore(&bnad->bna_lock, flags);
  346. return nbytes;
  347. }
  348. static int
  349. bnad_debugfs_release(struct inode *inode, struct file *file)
  350. {
  351. struct bnad_debug_info *debug = file->private_data;
  352. if (!debug)
  353. return 0;
  354. file->private_data = NULL;
  355. kfree(debug);
  356. return 0;
  357. }
  358. static int
  359. bnad_debugfs_buffer_release(struct inode *inode, struct file *file)
  360. {
  361. struct bnad_debug_info *debug = file->private_data;
  362. if (!debug)
  363. return 0;
  364. kfree(debug->debug_buffer);
  365. file->private_data = NULL;
  366. kfree(debug);
  367. debug = NULL;
  368. return 0;
  369. }
  370. static const struct file_operations bnad_debugfs_op_fwtrc = {
  371. .owner = THIS_MODULE,
  372. .open = bnad_debugfs_open_fwtrc,
  373. .llseek = bnad_debugfs_lseek,
  374. .read = bnad_debugfs_read,
  375. .release = bnad_debugfs_buffer_release,
  376. };
  377. static const struct file_operations bnad_debugfs_op_fwsave = {
  378. .owner = THIS_MODULE,
  379. .open = bnad_debugfs_open_fwsave,
  380. .llseek = bnad_debugfs_lseek,
  381. .read = bnad_debugfs_read,
  382. .release = bnad_debugfs_buffer_release,
  383. };
  384. static const struct file_operations bnad_debugfs_op_regrd = {
  385. .owner = THIS_MODULE,
  386. .open = bnad_debugfs_open_reg,
  387. .llseek = bnad_debugfs_lseek,
  388. .read = bnad_debugfs_read_regrd,
  389. .write = bnad_debugfs_write_regrd,
  390. .release = bnad_debugfs_release,
  391. };
  392. static const struct file_operations bnad_debugfs_op_regwr = {
  393. .owner = THIS_MODULE,
  394. .open = bnad_debugfs_open_reg,
  395. .llseek = bnad_debugfs_lseek,
  396. .write = bnad_debugfs_write_regwr,
  397. .release = bnad_debugfs_release,
  398. };
  399. static const struct file_operations bnad_debugfs_op_drvinfo = {
  400. .owner = THIS_MODULE,
  401. .open = bnad_debugfs_open_drvinfo,
  402. .llseek = bnad_debugfs_lseek,
  403. .read = bnad_debugfs_read,
  404. .release = bnad_debugfs_buffer_release,
  405. };
  406. struct bnad_debugfs_entry {
  407. const char *name;
  408. umode_t mode;
  409. const struct file_operations *fops;
  410. };
  411. static const struct bnad_debugfs_entry bnad_debugfs_files[] = {
  412. { "fwtrc", S_IFREG|S_IRUGO, &bnad_debugfs_op_fwtrc, },
  413. { "fwsave", S_IFREG|S_IRUGO, &bnad_debugfs_op_fwsave, },
  414. { "regrd", S_IFREG|S_IRUGO|S_IWUSR, &bnad_debugfs_op_regrd, },
  415. { "regwr", S_IFREG|S_IWUSR, &bnad_debugfs_op_regwr, },
  416. { "drvinfo", S_IFREG|S_IRUGO, &bnad_debugfs_op_drvinfo, },
  417. };
  418. static struct dentry *bna_debugfs_root;
  419. static atomic_t bna_debugfs_port_count;
  420. /* Initialize debugfs interface for BNA */
  421. void
  422. bnad_debugfs_init(struct bnad *bnad)
  423. {
  424. const struct bnad_debugfs_entry *file;
  425. char name[64];
  426. int i;
  427. /* Setup the BNA debugfs root directory*/
  428. if (!bna_debugfs_root) {
  429. bna_debugfs_root = debugfs_create_dir("bna", NULL);
  430. atomic_set(&bna_debugfs_port_count, 0);
  431. if (!bna_debugfs_root) {
  432. netdev_warn(bnad->netdev,
  433. "debugfs root dir creation failed\n");
  434. return;
  435. }
  436. }
  437. /* Setup the pci_dev debugfs directory for the port */
  438. snprintf(name, sizeof(name), "pci_dev:%s", pci_name(bnad->pcidev));
  439. if (!bnad->port_debugfs_root) {
  440. bnad->port_debugfs_root =
  441. debugfs_create_dir(name, bna_debugfs_root);
  442. if (!bnad->port_debugfs_root) {
  443. netdev_warn(bnad->netdev,
  444. "debugfs root dir creation failed\n");
  445. return;
  446. }
  447. atomic_inc(&bna_debugfs_port_count);
  448. for (i = 0; i < ARRAY_SIZE(bnad_debugfs_files); i++) {
  449. file = &bnad_debugfs_files[i];
  450. bnad->bnad_dentry_files[i] =
  451. debugfs_create_file(file->name,
  452. file->mode,
  453. bnad->port_debugfs_root,
  454. bnad,
  455. file->fops);
  456. if (!bnad->bnad_dentry_files[i]) {
  457. netdev_warn(bnad->netdev,
  458. "create %s entry failed\n",
  459. file->name);
  460. return;
  461. }
  462. }
  463. }
  464. }
  465. /* Uninitialize debugfs interface for BNA */
  466. void
  467. bnad_debugfs_uninit(struct bnad *bnad)
  468. {
  469. int i;
  470. for (i = 0; i < ARRAY_SIZE(bnad_debugfs_files); i++) {
  471. if (bnad->bnad_dentry_files[i]) {
  472. debugfs_remove(bnad->bnad_dentry_files[i]);
  473. bnad->bnad_dentry_files[i] = NULL;
  474. }
  475. }
  476. /* Remove the pci_dev debugfs directory for the port */
  477. if (bnad->port_debugfs_root) {
  478. debugfs_remove(bnad->port_debugfs_root);
  479. bnad->port_debugfs_root = NULL;
  480. atomic_dec(&bna_debugfs_port_count);
  481. }
  482. /* Remove the BNA debugfs root directory */
  483. if (atomic_read(&bna_debugfs_port_count) == 0) {
  484. debugfs_remove(bna_debugfs_root);
  485. bna_debugfs_root = NULL;
  486. }
  487. }