1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2015-2018 Netronome Systems, Inc. */
3 #include <linux/debugfs.h>
4 #include <linux/module.h>
5 #include <linux/rtnetlink.h>
9 static struct dentry
*nfp_dir
;
11 static int nfp_rx_q_show(struct seq_file
*file
, void *data
)
13 struct nfp_net_r_vector
*r_vec
= file
->private;
14 struct nfp_net_rx_ring
*rx_ring
;
15 int fl_rd_p
, fl_wr_p
, rxd_cnt
;
16 struct nfp_net_rx_desc
*rxd
;
23 if (!r_vec
->nfp_net
|| !r_vec
->rx_ring
)
26 rx_ring
= r_vec
->rx_ring
;
27 if (!nfp_net_running(nn
))
30 rxd_cnt
= rx_ring
->cnt
;
32 fl_rd_p
= nfp_qcp_rd_ptr_read(rx_ring
->qcp_fl
);
33 fl_wr_p
= nfp_qcp_wr_ptr_read(rx_ring
->qcp_fl
);
35 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",
36 rx_ring
->idx
, rx_ring
->fl_qcidx
,
37 rx_ring
->cnt
, &rx_ring
->dma
, rx_ring
->rxds
,
38 rx_ring
->rd_p
, rx_ring
->wr_p
, fl_rd_p
, fl_wr_p
);
40 for (i
= 0; i
< rxd_cnt
; i
++) {
41 rxd
= &rx_ring
->rxds
[i
];
42 seq_printf(file
, "%04d: 0x%08x 0x%08x", i
,
43 rxd
->vals
[0], rxd
->vals
[1]);
45 frag
= READ_ONCE(rx_ring
->rxbufs
[i
].frag
);
47 seq_printf(file
, " frag=%p", frag
);
49 if (rx_ring
->rxbufs
[i
].dma_addr
)
50 seq_printf(file
, " dma_addr=%pad",
51 &rx_ring
->rxbufs
[i
].dma_addr
);
53 if (i
== rx_ring
->rd_p
% rxd_cnt
)
54 seq_puts(file
, " H_RD ");
55 if (i
== rx_ring
->wr_p
% rxd_cnt
)
56 seq_puts(file
, " H_WR ");
57 if (i
== fl_rd_p
% rxd_cnt
)
58 seq_puts(file
, " FL_RD");
59 if (i
== fl_wr_p
% rxd_cnt
)
60 seq_puts(file
, " FL_WR");
68 DEFINE_SHOW_ATTRIBUTE(nfp_rx_q
);
70 static int nfp_tx_q_show(struct seq_file
*file
, void *data
);
71 DEFINE_SHOW_ATTRIBUTE(nfp_tx_q
);
73 static int nfp_tx_q_show(struct seq_file
*file
, void *data
)
75 struct nfp_net_r_vector
*r_vec
= file
->private;
76 struct nfp_net_tx_ring
*tx_ring
;
77 struct nfp_net_tx_desc
*txd
;
78 int d_rd_p
, d_wr_p
, txd_cnt
;
84 if (debugfs_real_fops(file
->file
) == &nfp_tx_q_fops
)
85 tx_ring
= r_vec
->tx_ring
;
87 tx_ring
= r_vec
->xdp_ring
;
88 if (!r_vec
->nfp_net
|| !tx_ring
)
91 if (!nfp_net_running(nn
))
94 txd_cnt
= tx_ring
->cnt
;
96 d_rd_p
= nfp_qcp_rd_ptr_read(tx_ring
->qcp_q
);
97 d_wr_p
= nfp_qcp_wr_ptr_read(tx_ring
->qcp_q
);
99 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",
100 tx_ring
->idx
, tx_ring
->qcidx
,
101 tx_ring
== r_vec
->tx_ring
? "" : "xdp",
102 tx_ring
->cnt
, &tx_ring
->dma
, tx_ring
->txds
,
103 tx_ring
->rd_p
, tx_ring
->wr_p
, d_rd_p
, d_wr_p
);
105 for (i
= 0; i
< txd_cnt
; i
++) {
106 txd
= &tx_ring
->txds
[i
];
107 seq_printf(file
, "%04d: 0x%08x 0x%08x 0x%08x 0x%08x", i
,
108 txd
->vals
[0], txd
->vals
[1],
109 txd
->vals
[2], txd
->vals
[3]);
111 if (tx_ring
== r_vec
->tx_ring
) {
112 struct sk_buff
*skb
= READ_ONCE(tx_ring
->txbufs
[i
].skb
);
115 seq_printf(file
, " skb->head=%p skb->data=%p",
116 skb
->head
, skb
->data
);
118 seq_printf(file
, " frag=%p",
119 READ_ONCE(tx_ring
->txbufs
[i
].frag
));
122 if (tx_ring
->txbufs
[i
].dma_addr
)
123 seq_printf(file
, " dma_addr=%pad",
124 &tx_ring
->txbufs
[i
].dma_addr
);
126 if (i
== tx_ring
->rd_p
% txd_cnt
)
127 seq_puts(file
, " H_RD");
128 if (i
== tx_ring
->wr_p
% txd_cnt
)
129 seq_puts(file
, " H_WR");
130 if (i
== d_rd_p
% txd_cnt
)
131 seq_puts(file
, " D_RD");
132 if (i
== d_wr_p
% txd_cnt
)
133 seq_puts(file
, " D_WR");
135 seq_putc(file
, '\n');
142 static int nfp_xdp_q_show(struct seq_file
*file
, void *data
)
144 return nfp_tx_q_show(file
, data
);
146 DEFINE_SHOW_ATTRIBUTE(nfp_xdp_q
);
148 void nfp_net_debugfs_vnic_add(struct nfp_net
*nn
, struct dentry
*ddir
)
150 struct dentry
*queues
, *tx
, *rx
, *xdp
;
154 if (IS_ERR_OR_NULL(nfp_dir
))
157 if (nfp_net_is_data_vnic(nn
))
158 sprintf(name
, "vnic%d", nn
->id
);
160 strcpy(name
, "ctrl-vnic");
161 nn
->debugfs_dir
= debugfs_create_dir(name
, ddir
);
163 /* Create queue debugging sub-tree */
164 queues
= debugfs_create_dir("queue", nn
->debugfs_dir
);
166 rx
= debugfs_create_dir("rx", queues
);
167 tx
= debugfs_create_dir("tx", queues
);
168 xdp
= debugfs_create_dir("xdp", queues
);
170 for (i
= 0; i
< min(nn
->max_rx_rings
, nn
->max_r_vecs
); i
++) {
171 sprintf(name
, "%d", i
);
172 debugfs_create_file(name
, 0400, rx
,
173 &nn
->r_vecs
[i
], &nfp_rx_q_fops
);
174 debugfs_create_file(name
, 0400, xdp
,
175 &nn
->r_vecs
[i
], &nfp_xdp_q_fops
);
178 for (i
= 0; i
< min(nn
->max_tx_rings
, nn
->max_r_vecs
); i
++) {
179 sprintf(name
, "%d", i
);
180 debugfs_create_file(name
, 0400, tx
,
181 &nn
->r_vecs
[i
], &nfp_tx_q_fops
);
185 struct dentry
*nfp_net_debugfs_device_add(struct pci_dev
*pdev
)
187 return debugfs_create_dir(pci_name(pdev
), nfp_dir
);
190 void nfp_net_debugfs_dir_clean(struct dentry
**dir
)
192 debugfs_remove_recursive(*dir
);
196 void nfp_net_debugfs_create(void)
198 nfp_dir
= debugfs_create_dir("nfp_net", NULL
);
201 void nfp_net_debugfs_destroy(void)
203 debugfs_remove_recursive(nfp_dir
);