1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#include <linux/debugfs.h>
34#include <linux/module.h>
35#include <linux/rtnetlink.h>
36
37#include "nfp_net.h"
38
39static struct dentry *nfp_dir;
40
41static int nfp_net_debugfs_rx_q_read(struct seq_file *file, void *data)
42{
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;
47 struct nfp_net *nn;
48 void *frag;
49 int i;
50
51 rtnl_lock();
52
53 if (!r_vec->nfp_net || !r_vec->rx_ring)
54 goto out;
55 nn = r_vec->nfp_net;
56 rx_ring = r_vec->rx_ring;
57 if (!nfp_net_running(nn))
58 goto out;
59
60 rxd_cnt = rx_ring->cnt;
61
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
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);
69
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]);
74
75 frag = READ_ONCE(rx_ring->rxbufs[i].frag);
76 if (frag)
77 seq_printf(file, " frag=%p", frag);
78
79 if (rx_ring->rxbufs[i].dma_addr)
80 seq_printf(file, " dma_addr=%pad",
81 &rx_ring->rxbufs[i].dma_addr);
82
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");
91
92 seq_putc(file, '\n');
93 }
94out:
95 rtnl_unlock();
96 return 0;
97}
98
99static int nfp_net_debugfs_rx_q_open(struct inode *inode, struct file *f)
100{
101 return single_open(f, nfp_net_debugfs_rx_q_read, inode->i_private);
102}
103
104static const struct file_operations nfp_rx_q_fops = {
105 .owner = THIS_MODULE,
106 .open = nfp_net_debugfs_rx_q_open,
107 .release = single_release,
108 .read = seq_read,
109 .llseek = seq_lseek
110};
111
112static int nfp_net_debugfs_tx_q_open(struct inode *inode, struct file *f);
113
114static const struct file_operations nfp_tx_q_fops = {
115 .owner = THIS_MODULE,
116 .open = nfp_net_debugfs_tx_q_open,
117 .release = single_release,
118 .read = seq_read,
119 .llseek = seq_lseek
120};
121
122static int nfp_net_debugfs_tx_q_read(struct seq_file *file, void *data)
123{
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;
128 struct nfp_net *nn;
129 int i;
130
131 rtnl_lock();
132
133 if (debugfs_real_fops(file->file) == &nfp_tx_q_fops)
134 tx_ring = r_vec->tx_ring;
135 else
136 tx_ring = r_vec->xdp_ring;
137 if (!r_vec->nfp_net || !tx_ring)
138 goto out;
139 nn = r_vec->nfp_net;
140 if (!nfp_net_running(nn))
141 goto out;
142
143 txd_cnt = tx_ring->cnt;
144
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);
147
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);
153
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]);
159
160 if (tx_ring == r_vec->tx_ring) {
161 struct sk_buff *skb = READ_ONCE(tx_ring->txbufs[i].skb);
162
163 if (skb)
164 seq_printf(file, " skb->head=%p skb->data=%p",
165 skb->head, skb->data);
166 } else {
167 seq_printf(file, " frag=%p",
168 READ_ONCE(tx_ring->txbufs[i].frag));
169 }
170
171 if (tx_ring->txbufs[i].dma_addr)
172 seq_printf(file, " dma_addr=%pad",
173 &tx_ring->txbufs[i].dma_addr);
174
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");
183
184 seq_putc(file, '\n');
185 }
186out:
187 rtnl_unlock();
188 return 0;
189}
190
191static int nfp_net_debugfs_tx_q_open(struct inode *inode, struct file *f)
192{
193 return single_open(f, nfp_net_debugfs_tx_q_read, inode->i_private);
194}
195
196static const struct file_operations nfp_xdp_q_fops = {
197 .owner = THIS_MODULE,
198 .open = nfp_net_debugfs_tx_q_open,
199 .release = single_release,
200 .read = seq_read,
201 .llseek = seq_lseek
202};
203
204void nfp_net_debugfs_vnic_add(struct nfp_net *nn, struct dentry *ddir, int id)
205{
206 struct dentry *queues, *tx, *rx, *xdp;
207 char name[20];
208 int i;
209
210 if (IS_ERR_OR_NULL(nfp_dir))
211 return;
212
213 if (nfp_net_is_data_vnic(nn))
214 sprintf(name, "vnic%d", id);
215 else
216 strcpy(name, "ctrl-vnic");
217 nn->debugfs_dir = debugfs_create_dir(name, ddir);
218 if (IS_ERR_OR_NULL(nn->debugfs_dir))
219 return;
220
221
222 queues = debugfs_create_dir("queue", nn->debugfs_dir);
223 if (IS_ERR_OR_NULL(queues))
224 return;
225
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))
230 return;
231
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);
238 }
239
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);
244 }
245}
246
247struct dentry *nfp_net_debugfs_device_add(struct pci_dev *pdev)
248{
249 struct dentry *dev_dir;
250
251 if (IS_ERR_OR_NULL(nfp_dir))
252 return NULL;
253
254 dev_dir = debugfs_create_dir(pci_name(pdev), nfp_dir);
255 if (IS_ERR_OR_NULL(dev_dir))
256 return NULL;
257
258 return dev_dir;
259}
260
261void nfp_net_debugfs_dir_clean(struct dentry **dir)
262{
263 debugfs_remove_recursive(*dir);
264 *dir = NULL;
265}
266
267void nfp_net_debugfs_create(void)
268{
269 nfp_dir = debugfs_create_dir("nfp_net", NULL);
270}
271
272void nfp_net_debugfs_destroy(void)
273{
274 debugfs_remove_recursive(nfp_dir);
275 nfp_dir = NULL;
276}
277