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 (!nfp_net_running(nn
))
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
;
133 if (debugfs_real_fops(file
->file
) == &nfp_tx_q_fops
)
134 tx_ring
= r_vec
->tx_ring
;
136 tx_ring
= r_vec
->xdp_ring
;
137 if (!r_vec
->nfp_net
|| !tx_ring
)
140 if (!nfp_net_running(nn
))
143 txd_cnt
= tx_ring
->cnt
;
145 d_rd_p
= nfp_qcp_rd_ptr_read(tx_ring
->qcp_q
);
146 d_wr_p
= nfp_qcp_wr_ptr_read(tx_ring
->qcp_q
);
148 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",
149 tx_ring
->idx
, tx_ring
->qcidx
,
150 tx_ring
== r_vec
->tx_ring
? "" : "xdp",
151 tx_ring
->cnt
, &tx_ring
->dma
, tx_ring
->txds
,
152 tx_ring
->rd_p
, tx_ring
->wr_p
, d_rd_p
, d_wr_p
);
154 for (i
= 0; i
< txd_cnt
; i
++) {
155 txd
= &tx_ring
->txds
[i
];
156 seq_printf(file
, "%04d: 0x%08x 0x%08x 0x%08x 0x%08x", i
,
157 txd
->vals
[0], txd
->vals
[1],
158 txd
->vals
[2], txd
->vals
[3]);
160 if (tx_ring
== r_vec
->tx_ring
) {
161 struct sk_buff
*skb
= READ_ONCE(tx_ring
->txbufs
[i
].skb
);
164 seq_printf(file
, " skb->head=%p skb->data=%p",
165 skb
->head
, skb
->data
);
167 seq_printf(file
, " frag=%p",
168 READ_ONCE(tx_ring
->txbufs
[i
].frag
));
171 if (tx_ring
->txbufs
[i
].dma_addr
)
172 seq_printf(file
, " dma_addr=%pad",
173 &tx_ring
->txbufs
[i
].dma_addr
);
175 if (i
== tx_ring
->rd_p
% txd_cnt
)
176 seq_puts(file
, " H_RD");
177 if (i
== tx_ring
->wr_p
% txd_cnt
)
178 seq_puts(file
, " H_WR");
179 if (i
== d_rd_p
% txd_cnt
)
180 seq_puts(file
, " D_RD");
181 if (i
== d_wr_p
% txd_cnt
)
182 seq_puts(file
, " D_WR");
184 seq_putc(file
, '\n');
191 static int nfp_net_debugfs_tx_q_open(struct inode
*inode
, struct file
*f
)
193 return single_open(f
, nfp_net_debugfs_tx_q_read
, inode
->i_private
);
196 static const struct file_operations nfp_xdp_q_fops
= {
197 .owner
= THIS_MODULE
,
198 .open
= nfp_net_debugfs_tx_q_open
,
199 .release
= single_release
,
204 void nfp_net_debugfs_vnic_add(struct nfp_net
*nn
, struct dentry
*ddir
, int id
)
206 struct dentry
*queues
, *tx
, *rx
, *xdp
;
210 if (IS_ERR_OR_NULL(nfp_dir
))
213 if (nfp_net_is_data_vnic(nn
))
214 sprintf(name
, "vnic%d", id
);
216 strcpy(name
, "ctrl-vnic");
217 nn
->debugfs_dir
= debugfs_create_dir(name
, ddir
);
218 if (IS_ERR_OR_NULL(nn
->debugfs_dir
))
221 /* Create queue debugging sub-tree */
222 queues
= debugfs_create_dir("queue", nn
->debugfs_dir
);
223 if (IS_ERR_OR_NULL(queues
))
226 rx
= debugfs_create_dir("rx", queues
);
227 tx
= debugfs_create_dir("tx", queues
);
228 xdp
= debugfs_create_dir("xdp", queues
);
229 if (IS_ERR_OR_NULL(rx
) || IS_ERR_OR_NULL(tx
) || IS_ERR_OR_NULL(xdp
))
232 for (i
= 0; i
< min(nn
->max_rx_rings
, nn
->max_r_vecs
); i
++) {
233 sprintf(name
, "%d", i
);
234 debugfs_create_file(name
, S_IRUSR
, rx
,
235 &nn
->r_vecs
[i
], &nfp_rx_q_fops
);
236 debugfs_create_file(name
, S_IRUSR
, xdp
,
237 &nn
->r_vecs
[i
], &nfp_xdp_q_fops
);
240 for (i
= 0; i
< min(nn
->max_tx_rings
, nn
->max_r_vecs
); i
++) {
241 sprintf(name
, "%d", i
);
242 debugfs_create_file(name
, S_IRUSR
, tx
,
243 &nn
->r_vecs
[i
], &nfp_tx_q_fops
);
247 struct dentry
*nfp_net_debugfs_device_add(struct pci_dev
*pdev
)
249 struct dentry
*dev_dir
;
251 if (IS_ERR_OR_NULL(nfp_dir
))
254 dev_dir
= debugfs_create_dir(pci_name(pdev
), nfp_dir
);
255 if (IS_ERR_OR_NULL(dev_dir
))
261 void nfp_net_debugfs_dir_clean(struct dentry
**dir
)
263 debugfs_remove_recursive(*dir
);
267 void nfp_net_debugfs_create(void)
269 nfp_dir
= debugfs_create_dir("nfp_net", NULL
);
272 void nfp_net_debugfs_destroy(void)
274 debugfs_remove_recursive(nfp_dir
);