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 struct nfp_net_r_vector
*r_vec
= file
->private;
44 struct nfp_net_rx_ring
*rx_ring
;
45 int fl_rd_p
, fl_wr_p
, rxd_cnt
;
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
->dp
.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
);
65 seq_printf(file
, "RX[%02d,%02d]: cnt=%u dma=%pad host=%p H_RD=%u H_WR=%u FL_RD=%u FL_WR=%u\n",
66 rx_ring
->idx
, rx_ring
->fl_qcidx
,
67 rx_ring
->cnt
, &rx_ring
->dma
, rx_ring
->rxds
,
68 rx_ring
->rd_p
, rx_ring
->wr_p
, fl_rd_p
, fl_wr_p
);
70 for (i
= 0; i
< rxd_cnt
; i
++) {
71 rxd
= &rx_ring
->rxds
[i
];
72 seq_printf(file
, "%04d: 0x%08x 0x%08x", i
,
73 rxd
->vals
[0], rxd
->vals
[1]);
75 frag
= READ_ONCE(rx_ring
->rxbufs
[i
].frag
);
77 seq_printf(file
, " frag=%p", frag
);
79 if (rx_ring
->rxbufs
[i
].dma_addr
)
80 seq_printf(file
, " dma_addr=%pad",
81 &rx_ring
->rxbufs
[i
].dma_addr
);
83 if (i
== rx_ring
->rd_p
% rxd_cnt
)
84 seq_puts(file
, " H_RD ");
85 if (i
== rx_ring
->wr_p
% rxd_cnt
)
86 seq_puts(file
, " H_WR ");
87 if (i
== fl_rd_p
% rxd_cnt
)
88 seq_puts(file
, " FL_RD");
89 if (i
== fl_wr_p
% rxd_cnt
)
90 seq_puts(file
, " FL_WR");
99 static int nfp_net_debugfs_rx_q_open(struct inode
*inode
, struct file
*f
)
101 return single_open(f
, nfp_net_debugfs_rx_q_read
, inode
->i_private
);
104 static const struct file_operations nfp_rx_q_fops
= {
105 .owner
= THIS_MODULE
,
106 .open
= nfp_net_debugfs_rx_q_open
,
107 .release
= single_release
,
112 static int nfp_net_debugfs_tx_q_open(struct inode
*inode
, struct file
*f
);
114 static const struct file_operations nfp_tx_q_fops
= {
115 .owner
= THIS_MODULE
,
116 .open
= nfp_net_debugfs_tx_q_open
,
117 .release
= single_release
,
122 static int nfp_net_debugfs_tx_q_read(struct seq_file
*file
, void *data
)
124 struct nfp_net_r_vector
*r_vec
= file
->private;
125 struct nfp_net_tx_ring
*tx_ring
;
126 struct nfp_net_tx_desc
*txd
;
127 int d_rd_p
, d_wr_p
, txd_cnt
;
134 if (debugfs_real_fops(file
->file
) == &nfp_tx_q_fops
)
135 tx_ring
= r_vec
->tx_ring
;
137 tx_ring
= r_vec
->xdp_ring
;
138 if (!r_vec
->nfp_net
|| !tx_ring
)
141 if (!netif_running(nn
->dp
.netdev
))
144 txd_cnt
= tx_ring
->cnt
;
146 d_rd_p
= nfp_qcp_rd_ptr_read(tx_ring
->qcp_q
);
147 d_wr_p
= nfp_qcp_wr_ptr_read(tx_ring
->qcp_q
);
149 seq_printf(file
, "TX[%02d,%02d%s]: cnt=%u dma=%pad host=%p H_RD=%u H_WR=%u D_RD=%u D_WR=%u\n",
150 tx_ring
->idx
, tx_ring
->qcidx
,
151 tx_ring
== r_vec
->tx_ring
? "" : "xdp",
152 tx_ring
->cnt
, &tx_ring
->dma
, tx_ring
->txds
,
153 tx_ring
->rd_p
, tx_ring
->wr_p
, d_rd_p
, d_wr_p
);
155 for (i
= 0; i
< txd_cnt
; i
++) {
156 txd
= &tx_ring
->txds
[i
];
157 seq_printf(file
, "%04d: 0x%08x 0x%08x 0x%08x 0x%08x", i
,
158 txd
->vals
[0], txd
->vals
[1],
159 txd
->vals
[2], txd
->vals
[3]);
161 skb
= READ_ONCE(tx_ring
->txbufs
[i
].skb
);
163 if (tx_ring
== r_vec
->tx_ring
)
164 seq_printf(file
, " skb->head=%p skb->data=%p",
165 skb
->head
, skb
->data
);
167 seq_printf(file
, " frag=%p", skb
);
170 if (tx_ring
->txbufs
[i
].dma_addr
)
171 seq_printf(file
, " dma_addr=%pad",
172 &tx_ring
->txbufs
[i
].dma_addr
);
174 if (i
== tx_ring
->rd_p
% txd_cnt
)
175 seq_puts(file
, " H_RD");
176 if (i
== tx_ring
->wr_p
% txd_cnt
)
177 seq_puts(file
, " H_WR");
178 if (i
== d_rd_p
% txd_cnt
)
179 seq_puts(file
, " D_RD");
180 if (i
== d_wr_p
% txd_cnt
)
181 seq_puts(file
, " D_WR");
183 seq_putc(file
, '\n');
190 static int nfp_net_debugfs_tx_q_open(struct inode
*inode
, struct file
*f
)
192 return single_open(f
, nfp_net_debugfs_tx_q_read
, inode
->i_private
);
195 static const struct file_operations nfp_xdp_q_fops
= {
196 .owner
= THIS_MODULE
,
197 .open
= nfp_net_debugfs_tx_q_open
,
198 .release
= single_release
,
203 void nfp_net_debugfs_vnic_add(struct nfp_net
*nn
, struct dentry
*ddir
, int id
)
205 struct dentry
*queues
, *tx
, *rx
, *xdp
;
209 if (IS_ERR_OR_NULL(nfp_dir
))
212 sprintf(name
, "vnic%d", id
);
213 nn
->debugfs_dir
= debugfs_create_dir(name
, ddir
);
214 if (IS_ERR_OR_NULL(nn
->debugfs_dir
))
217 /* Create queue debugging sub-tree */
218 queues
= debugfs_create_dir("queue", nn
->debugfs_dir
);
219 if (IS_ERR_OR_NULL(queues
))
222 rx
= debugfs_create_dir("rx", queues
);
223 tx
= debugfs_create_dir("tx", queues
);
224 xdp
= debugfs_create_dir("xdp", queues
);
225 if (IS_ERR_OR_NULL(rx
) || IS_ERR_OR_NULL(tx
) || IS_ERR_OR_NULL(xdp
))
228 for (i
= 0; i
< min(nn
->max_rx_rings
, nn
->max_r_vecs
); i
++) {
229 sprintf(name
, "%d", i
);
230 debugfs_create_file(name
, S_IRUSR
, rx
,
231 &nn
->r_vecs
[i
], &nfp_rx_q_fops
);
232 debugfs_create_file(name
, S_IRUSR
, xdp
,
233 &nn
->r_vecs
[i
], &nfp_xdp_q_fops
);
236 for (i
= 0; i
< min(nn
->max_tx_rings
, nn
->max_r_vecs
); i
++) {
237 sprintf(name
, "%d", i
);
238 debugfs_create_file(name
, S_IRUSR
, tx
,
239 &nn
->r_vecs
[i
], &nfp_tx_q_fops
);
243 struct dentry
*nfp_net_debugfs_device_add(struct pci_dev
*pdev
)
245 struct dentry
*dev_dir
;
247 if (IS_ERR_OR_NULL(nfp_dir
))
250 dev_dir
= debugfs_create_dir(pci_name(pdev
), nfp_dir
);
251 if (IS_ERR_OR_NULL(dev_dir
))
257 void nfp_net_debugfs_dir_clean(struct dentry
**dir
)
259 debugfs_remove_recursive(*dir
);
263 void nfp_net_debugfs_create(void)
265 nfp_dir
= debugfs_create_dir("nfp_net", NULL
);
268 void nfp_net_debugfs_destroy(void)
270 debugfs_remove_recursive(nfp_dir
);