GNU Linux-libre 4.19.264-gnu1
[releases.git] / drivers / net / ethernet / netronome / nfp / nfp_net_debugfs.c
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
37 #include "nfp_net.h"
38
39 static struct dentry *nfp_dir;
40
41 static 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         }
94 out:
95         rtnl_unlock();
96         return 0;
97 }
98
99 static 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
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,
108         .read = seq_read,
109         .llseek = seq_lseek
110 };
111
112 static int nfp_net_debugfs_tx_q_open(struct inode *inode, struct file *f);
113
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,
118         .read = seq_read,
119         .llseek = seq_lseek
120 };
121
122 static 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         }
186 out:
187         rtnl_unlock();
188         return 0;
189 }
190
191 static 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
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,
200         .read = seq_read,
201         .llseek = seq_lseek
202 };
203
204 void nfp_net_debugfs_vnic_add(struct nfp_net *nn, struct dentry *ddir)
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", nn->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         /* Create queue debugging sub-tree */
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, 0400, rx,
235                                     &nn->r_vecs[i], &nfp_rx_q_fops);
236                 debugfs_create_file(name, 0400, 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, 0400, tx,
243                                     &nn->r_vecs[i], &nfp_tx_q_fops);
244         }
245 }
246
247 struct 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
261 void nfp_net_debugfs_dir_clean(struct dentry **dir)
262 {
263         debugfs_remove_recursive(*dir);
264         *dir = NULL;
265 }
266
267 void nfp_net_debugfs_create(void)
268 {
269         nfp_dir = debugfs_create_dir("nfp_net", NULL);
270 }
271
272 void nfp_net_debugfs_destroy(void)
273 {
274         debugfs_remove_recursive(nfp_dir);
275         nfp_dir = NULL;
276 }