nfp_net_debugfs.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /*
  2. * Copyright (C) 2015-2017 Netronome Systems, Inc.
  3. *
  4. * This software is dual licensed under the GNU General License Version 2,
  5. * June 1991 as shown in the file COPYING in the top-level directory of this
  6. * source tree or the BSD 2-Clause License provided below. You have the
  7. * option to license this software under the complete terms of either license.
  8. *
  9. * The BSD 2-Clause License:
  10. *
  11. * Redistribution and use in source and binary forms, with or
  12. * without modification, are permitted provided that the following
  13. * conditions are met:
  14. *
  15. * 1. Redistributions of source code must retain the above
  16. * copyright notice, this list of conditions and the following
  17. * disclaimer.
  18. *
  19. * 2. Redistributions in binary form must reproduce the above
  20. * copyright notice, this list of conditions and the following
  21. * disclaimer in the documentation and/or other materials
  22. * provided with the distribution.
  23. *
  24. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  25. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  26. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  27. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  28. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  29. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  30. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  31. * SOFTWARE.
  32. */
  33. #include <linux/debugfs.h>
  34. #include <linux/module.h>
  35. #include <linux/rtnetlink.h>
  36. #include "nfp_net.h"
  37. static struct dentry *nfp_dir;
  38. static int nfp_net_debugfs_rx_q_read(struct seq_file *file, void *data)
  39. {
  40. struct nfp_net_r_vector *r_vec = file->private;
  41. struct nfp_net_rx_ring *rx_ring;
  42. int fl_rd_p, fl_wr_p, rxd_cnt;
  43. struct nfp_net_rx_desc *rxd;
  44. struct nfp_net *nn;
  45. void *frag;
  46. int i;
  47. rtnl_lock();
  48. if (!r_vec->nfp_net || !r_vec->rx_ring)
  49. goto out;
  50. nn = r_vec->nfp_net;
  51. rx_ring = r_vec->rx_ring;
  52. if (!netif_running(nn->dp.netdev))
  53. goto out;
  54. rxd_cnt = rx_ring->cnt;
  55. fl_rd_p = nfp_qcp_rd_ptr_read(rx_ring->qcp_fl);
  56. fl_wr_p = nfp_qcp_wr_ptr_read(rx_ring->qcp_fl);
  57. seq_printf(file, "RX[%02d,%02d]: cnt=%d dma=%pad host=%p H_RD=%d H_WR=%d FL_RD=%d FL_WR=%d\n",
  58. rx_ring->idx, rx_ring->fl_qcidx,
  59. rx_ring->cnt, &rx_ring->dma, rx_ring->rxds,
  60. rx_ring->rd_p, rx_ring->wr_p, fl_rd_p, fl_wr_p);
  61. for (i = 0; i < rxd_cnt; i++) {
  62. rxd = &rx_ring->rxds[i];
  63. seq_printf(file, "%04d: 0x%08x 0x%08x", i,
  64. rxd->vals[0], rxd->vals[1]);
  65. frag = READ_ONCE(rx_ring->rxbufs[i].frag);
  66. if (frag)
  67. seq_printf(file, " frag=%p", frag);
  68. if (rx_ring->rxbufs[i].dma_addr)
  69. seq_printf(file, " dma_addr=%pad",
  70. &rx_ring->rxbufs[i].dma_addr);
  71. if (i == rx_ring->rd_p % rxd_cnt)
  72. seq_puts(file, " H_RD ");
  73. if (i == rx_ring->wr_p % rxd_cnt)
  74. seq_puts(file, " H_WR ");
  75. if (i == fl_rd_p % rxd_cnt)
  76. seq_puts(file, " FL_RD");
  77. if (i == fl_wr_p % rxd_cnt)
  78. seq_puts(file, " FL_WR");
  79. seq_putc(file, '\n');
  80. }
  81. out:
  82. rtnl_unlock();
  83. return 0;
  84. }
  85. static int nfp_net_debugfs_rx_q_open(struct inode *inode, struct file *f)
  86. {
  87. return single_open(f, nfp_net_debugfs_rx_q_read, inode->i_private);
  88. }
  89. static const struct file_operations nfp_rx_q_fops = {
  90. .owner = THIS_MODULE,
  91. .open = nfp_net_debugfs_rx_q_open,
  92. .release = single_release,
  93. .read = seq_read,
  94. .llseek = seq_lseek
  95. };
  96. static int nfp_net_debugfs_tx_q_open(struct inode *inode, struct file *f);
  97. static const struct file_operations nfp_tx_q_fops = {
  98. .owner = THIS_MODULE,
  99. .open = nfp_net_debugfs_tx_q_open,
  100. .release = single_release,
  101. .read = seq_read,
  102. .llseek = seq_lseek
  103. };
  104. static int nfp_net_debugfs_tx_q_read(struct seq_file *file, void *data)
  105. {
  106. struct nfp_net_r_vector *r_vec = file->private;
  107. struct nfp_net_tx_ring *tx_ring;
  108. struct nfp_net_tx_desc *txd;
  109. int d_rd_p, d_wr_p, txd_cnt;
  110. struct sk_buff *skb;
  111. struct nfp_net *nn;
  112. int i;
  113. rtnl_lock();
  114. if (debugfs_real_fops(file->file) == &nfp_tx_q_fops)
  115. tx_ring = r_vec->tx_ring;
  116. else
  117. tx_ring = r_vec->xdp_ring;
  118. if (!r_vec->nfp_net || !tx_ring)
  119. goto out;
  120. nn = r_vec->nfp_net;
  121. if (!netif_running(nn->dp.netdev))
  122. goto out;
  123. txd_cnt = tx_ring->cnt;
  124. d_rd_p = nfp_qcp_rd_ptr_read(tx_ring->qcp_q);
  125. d_wr_p = nfp_qcp_wr_ptr_read(tx_ring->qcp_q);
  126. seq_printf(file, "TX[%02d,%02d%s]: cnt=%d dma=%pad host=%p H_RD=%d H_WR=%d D_RD=%d D_WR=%d\n",
  127. tx_ring->idx, tx_ring->qcidx,
  128. tx_ring == r_vec->tx_ring ? "" : "xdp",
  129. tx_ring->cnt, &tx_ring->dma, tx_ring->txds,
  130. tx_ring->rd_p, tx_ring->wr_p, d_rd_p, d_wr_p);
  131. for (i = 0; i < txd_cnt; i++) {
  132. txd = &tx_ring->txds[i];
  133. seq_printf(file, "%04d: 0x%08x 0x%08x 0x%08x 0x%08x", i,
  134. txd->vals[0], txd->vals[1],
  135. txd->vals[2], txd->vals[3]);
  136. skb = READ_ONCE(tx_ring->txbufs[i].skb);
  137. if (skb) {
  138. if (tx_ring == r_vec->tx_ring)
  139. seq_printf(file, " skb->head=%p skb->data=%p",
  140. skb->head, skb->data);
  141. else
  142. seq_printf(file, " frag=%p", skb);
  143. }
  144. if (tx_ring->txbufs[i].dma_addr)
  145. seq_printf(file, " dma_addr=%pad",
  146. &tx_ring->txbufs[i].dma_addr);
  147. if (i == tx_ring->rd_p % txd_cnt)
  148. seq_puts(file, " H_RD");
  149. if (i == tx_ring->wr_p % txd_cnt)
  150. seq_puts(file, " H_WR");
  151. if (i == d_rd_p % txd_cnt)
  152. seq_puts(file, " D_RD");
  153. if (i == d_wr_p % txd_cnt)
  154. seq_puts(file, " D_WR");
  155. seq_putc(file, '\n');
  156. }
  157. out:
  158. rtnl_unlock();
  159. return 0;
  160. }
  161. static int nfp_net_debugfs_tx_q_open(struct inode *inode, struct file *f)
  162. {
  163. return single_open(f, nfp_net_debugfs_tx_q_read, inode->i_private);
  164. }
  165. static const struct file_operations nfp_xdp_q_fops = {
  166. .owner = THIS_MODULE,
  167. .open = nfp_net_debugfs_tx_q_open,
  168. .release = single_release,
  169. .read = seq_read,
  170. .llseek = seq_lseek
  171. };
  172. void nfp_net_debugfs_port_add(struct nfp_net *nn, struct dentry *ddir, int id)
  173. {
  174. struct dentry *queues, *tx, *rx, *xdp;
  175. char name[20];
  176. int i;
  177. if (IS_ERR_OR_NULL(nfp_dir))
  178. return;
  179. sprintf(name, "port%d", id);
  180. nn->debugfs_dir = debugfs_create_dir(name, ddir);
  181. if (IS_ERR_OR_NULL(nn->debugfs_dir))
  182. return;
  183. /* Create queue debugging sub-tree */
  184. queues = debugfs_create_dir("queue", nn->debugfs_dir);
  185. if (IS_ERR_OR_NULL(queues))
  186. return;
  187. rx = debugfs_create_dir("rx", queues);
  188. tx = debugfs_create_dir("tx", queues);
  189. xdp = debugfs_create_dir("xdp", queues);
  190. if (IS_ERR_OR_NULL(rx) || IS_ERR_OR_NULL(tx) || IS_ERR_OR_NULL(xdp))
  191. return;
  192. for (i = 0; i < min(nn->max_rx_rings, nn->max_r_vecs); i++) {
  193. sprintf(name, "%d", i);
  194. debugfs_create_file(name, S_IRUSR, rx,
  195. &nn->r_vecs[i], &nfp_rx_q_fops);
  196. debugfs_create_file(name, S_IRUSR, xdp,
  197. &nn->r_vecs[i], &nfp_xdp_q_fops);
  198. }
  199. for (i = 0; i < min(nn->max_tx_rings, nn->max_r_vecs); i++) {
  200. sprintf(name, "%d", i);
  201. debugfs_create_file(name, S_IRUSR, tx,
  202. &nn->r_vecs[i], &nfp_tx_q_fops);
  203. }
  204. }
  205. struct dentry *nfp_net_debugfs_device_add(struct pci_dev *pdev)
  206. {
  207. struct dentry *dev_dir;
  208. if (IS_ERR_OR_NULL(nfp_dir))
  209. return NULL;
  210. dev_dir = debugfs_create_dir(pci_name(pdev), nfp_dir);
  211. if (IS_ERR_OR_NULL(dev_dir))
  212. return NULL;
  213. return dev_dir;
  214. }
  215. void nfp_net_debugfs_dir_clean(struct dentry **dir)
  216. {
  217. debugfs_remove_recursive(*dir);
  218. *dir = NULL;
  219. }
  220. void nfp_net_debugfs_create(void)
  221. {
  222. nfp_dir = debugfs_create_dir("nfp_net", NULL);
  223. }
  224. void nfp_net_debugfs_destroy(void)
  225. {
  226. debugfs_remove_recursive(nfp_dir);
  227. nfp_dir = NULL;
  228. }