2 * Copyright (C) 2015-2017 Netronome Systems, Inc.
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.
9 * The BSD 2-Clause License:
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
15 * 1. Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
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.
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
33 #include <linux/debugfs.h>
34 #include <linux/module.h>
35 #include <linux/rtnetlink.h>
39 static struct dentry
*nfp_dir
;
41 static int nfp_net_debugfs_rx_q_read(struct seq_file
*file
, void *data
)
43 int fl_rd_p
, fl_wr_p
, rx_rd_p
, rx_wr_p
, rxd_cnt
;
44 struct nfp_net_r_vector
*r_vec
= file
->private;
45 struct nfp_net_rx_ring
*rx_ring
;
46 struct nfp_net_rx_desc
*rxd
;
53 if (!r_vec
->nfp_net
|| !r_vec
->rx_ring
)
56 rx_ring
= r_vec
->rx_ring
;
57 if (!netif_running(nn
->netdev
))
60 rxd_cnt
= rx_ring
->cnt
;
62 fl_rd_p
= nfp_qcp_rd_ptr_read(rx_ring
->qcp_fl
);
63 fl_wr_p
= nfp_qcp_wr_ptr_read(rx_ring
->qcp_fl
);
64 rx_rd_p
= nfp_qcp_rd_ptr_read(rx_ring
->qcp_rx
);
65 rx_wr_p
= nfp_qcp_wr_ptr_read(rx_ring
->qcp_rx
);
67 seq_printf(file
, "RX[%02d,%02d,%02d]: cnt=%d dma=%pad host=%p H_RD=%d H_WR=%d FL_RD=%d FL_WR=%d RX_RD=%d RX_WR=%d\n",
68 rx_ring
->idx
, rx_ring
->fl_qcidx
, rx_ring
->rx_qcidx
,
69 rx_ring
->cnt
, &rx_ring
->dma
, rx_ring
->rxds
,
70 rx_ring
->rd_p
, rx_ring
->wr_p
,
71 fl_rd_p
, fl_wr_p
, rx_rd_p
, rx_wr_p
);
73 for (i
= 0; i
< rxd_cnt
; i
++) {
74 rxd
= &rx_ring
->rxds
[i
];
75 seq_printf(file
, "%04d: 0x%08x 0x%08x", i
,
76 rxd
->vals
[0], rxd
->vals
[1]);
78 frag
= READ_ONCE(rx_ring
->rxbufs
[i
].frag
);
80 seq_printf(file
, " frag=%p", frag
);
82 if (rx_ring
->rxbufs
[i
].dma_addr
)
83 seq_printf(file
, " dma_addr=%pad",
84 &rx_ring
->rxbufs
[i
].dma_addr
);
86 if (i
== rx_ring
->rd_p
% rxd_cnt
)
87 seq_puts(file
, " H_RD ");
88 if (i
== rx_ring
->wr_p
% rxd_cnt
)
89 seq_puts(file
, " H_WR ");
90 if (i
== fl_rd_p
% rxd_cnt
)
91 seq_puts(file
, " FL_RD");
92 if (i
== fl_wr_p
% rxd_cnt
)
93 seq_puts(file
, " FL_WR");
94 if (i
== rx_rd_p
% rxd_cnt
)
95 seq_puts(file
, " RX_RD");
96 if (i
== rx_wr_p
% rxd_cnt
)
97 seq_puts(file
, " RX_WR");
106 static int nfp_net_debugfs_rx_q_open(struct inode
*inode
, struct file
*f
)
108 return single_open(f
, nfp_net_debugfs_rx_q_read
, inode
->i_private
);
111 static const struct file_operations nfp_rx_q_fops
= {
112 .owner
= THIS_MODULE
,
113 .open
= nfp_net_debugfs_rx_q_open
,
114 .release
= single_release
,
119 static int nfp_net_debugfs_tx_q_open(struct inode
*inode
, struct file
*f
);
121 static const struct file_operations nfp_tx_q_fops
= {
122 .owner
= THIS_MODULE
,
123 .open
= nfp_net_debugfs_tx_q_open
,
124 .release
= single_release
,
129 static int nfp_net_debugfs_tx_q_read(struct seq_file
*file
, void *data
)
131 struct nfp_net_r_vector
*r_vec
= file
->private;
132 struct nfp_net_tx_ring
*tx_ring
;
133 struct nfp_net_tx_desc
*txd
;
134 int d_rd_p
, d_wr_p
, txd_cnt
;
141 if (debugfs_real_fops(file
->file
) == &nfp_tx_q_fops
)
142 tx_ring
= r_vec
->tx_ring
;
144 tx_ring
= r_vec
->xdp_ring
;
145 if (!r_vec
->nfp_net
|| !tx_ring
)
148 if (!netif_running(nn
->netdev
))
151 txd_cnt
= tx_ring
->cnt
;
153 d_rd_p
= nfp_qcp_rd_ptr_read(tx_ring
->qcp_q
);
154 d_wr_p
= nfp_qcp_wr_ptr_read(tx_ring
->qcp_q
);
156 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",
157 tx_ring
->idx
, tx_ring
->qcidx
,
158 tx_ring
== r_vec
->tx_ring
? "" : "xdp",
159 tx_ring
->cnt
, &tx_ring
->dma
, tx_ring
->txds
,
160 tx_ring
->rd_p
, tx_ring
->wr_p
, d_rd_p
, d_wr_p
);
162 for (i
= 0; i
< txd_cnt
; i
++) {
163 txd
= &tx_ring
->txds
[i
];
164 seq_printf(file
, "%04d: 0x%08x 0x%08x 0x%08x 0x%08x", i
,
165 txd
->vals
[0], txd
->vals
[1],
166 txd
->vals
[2], txd
->vals
[3]);
168 skb
= READ_ONCE(tx_ring
->txbufs
[i
].skb
);
170 if (tx_ring
== r_vec
->tx_ring
)
171 seq_printf(file
, " skb->head=%p skb->data=%p",
172 skb
->head
, skb
->data
);
174 seq_printf(file
, " frag=%p", skb
);
177 if (tx_ring
->txbufs
[i
].dma_addr
)
178 seq_printf(file
, " dma_addr=%pad",
179 &tx_ring
->txbufs
[i
].dma_addr
);
181 if (i
== tx_ring
->rd_p
% txd_cnt
)
182 seq_puts(file
, " H_RD");
183 if (i
== tx_ring
->wr_p
% txd_cnt
)
184 seq_puts(file
, " H_WR");
185 if (i
== d_rd_p
% txd_cnt
)
186 seq_puts(file
, " D_RD");
187 if (i
== d_wr_p
% txd_cnt
)
188 seq_puts(file
, " D_WR");
190 seq_putc(file
, '\n');
197 static int nfp_net_debugfs_tx_q_open(struct inode
*inode
, struct file
*f
)
199 return single_open(f
, nfp_net_debugfs_tx_q_read
, inode
->i_private
);
202 static const struct file_operations nfp_xdp_q_fops
= {
203 .owner
= THIS_MODULE
,
204 .open
= nfp_net_debugfs_tx_q_open
,
205 .release
= single_release
,
210 void nfp_net_debugfs_port_add(struct nfp_net
*nn
, struct dentry
*ddir
, int id
)
212 struct dentry
*queues
, *tx
, *rx
, *xdp
;
216 if (IS_ERR_OR_NULL(nfp_dir
))
219 sprintf(name
, "port%d", id
);
220 nn
->debugfs_dir
= debugfs_create_dir(name
, ddir
);
221 if (IS_ERR_OR_NULL(nn
->debugfs_dir
))
224 /* Create queue debugging sub-tree */
225 queues
= debugfs_create_dir("queue", nn
->debugfs_dir
);
226 if (IS_ERR_OR_NULL(queues
))
229 rx
= debugfs_create_dir("rx", queues
);
230 tx
= debugfs_create_dir("tx", queues
);
231 xdp
= debugfs_create_dir("xdp", queues
);
232 if (IS_ERR_OR_NULL(rx
) || IS_ERR_OR_NULL(tx
) || IS_ERR_OR_NULL(xdp
))
235 for (i
= 0; i
< min(nn
->max_rx_rings
, nn
->max_r_vecs
); i
++) {
236 sprintf(name
, "%d", i
);
237 debugfs_create_file(name
, S_IRUSR
, rx
,
238 &nn
->r_vecs
[i
], &nfp_rx_q_fops
);
239 debugfs_create_file(name
, S_IRUSR
, xdp
,
240 &nn
->r_vecs
[i
], &nfp_xdp_q_fops
);
243 for (i
= 0; i
< min(nn
->max_tx_rings
, nn
->max_r_vecs
); i
++) {
244 sprintf(name
, "%d", i
);
245 debugfs_create_file(name
, S_IRUSR
, tx
,
246 &nn
->r_vecs
[i
], &nfp_tx_q_fops
);
250 struct dentry
*nfp_net_debugfs_device_add(struct pci_dev
*pdev
)
252 struct dentry
*dev_dir
;
254 if (IS_ERR_OR_NULL(nfp_dir
))
257 dev_dir
= debugfs_create_dir(pci_name(pdev
), nfp_dir
);
258 if (IS_ERR_OR_NULL(dev_dir
))
264 void nfp_net_debugfs_dir_clean(struct dentry
**dir
)
266 debugfs_remove_recursive(*dir
);
270 void nfp_net_debugfs_create(void)
272 nfp_dir
= debugfs_create_dir("nfp_net", NULL
);
275 void nfp_net_debugfs_destroy(void)
277 debugfs_remove_recursive(nfp_dir
);