aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2014-09-20 19:53:23 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2014-09-23 06:59:22 -0400
commit7461fd913afe3a830b47cf133a6ad53e49a5db8b (patch)
tree85a8a68d661e31eae18909b826d6d5462d24e523
parent9f801abc3d4fe1e770268ae4e610556e79be6fca (diff)
fm10k: Add support for debugfs
This patch adds limited debugfs support for the driver. Most of the functionality needed for dumping registers is already provided via ethtool. The only thing we saw that we really neeed was the ability to dump the descriptor rings so as such this patch will add a fm10k directory containing a listing of directories each one with a unique PCI Bus, Device, and Function number. Each of those BDF directories will have a list of q_vectors, and the q_vectors will contain a file for each of the Rx/Tx rings that are a part of the vector. For example: # ls -RD /sys/kernel/debug/fm10k/ /sys/kernel/debug/fm10k/: 0000:01:00.0 /sys/kernel/debug/fm10k/0000:01:00.0: q_vector.000 q_vector.001 q_vector.002 q_vector.003 /sys/kernel/debug/fm10k/0000:01:00.0/q_vector.000: rx_ring.000 tx_ring.000 /sys/kernel/debug/fm10k/0000:01:00.0/q_vector.001: rx_ring.001 tx_ring.001 /sys/kernel/debug/fm10k/0000:01:00.0/q_vector.002: rx_ring.002 tx_ring.002 /sys/kernel/debug/fm10k/0000:01:00.0/q_vector.003: rx_ring.003 tx_ring.003 # cat /sys/kernel/debug/fm10k/0000:01:00.0/q_vector.000/rx_ring.000 DES DATA RSS STATERR LENGTH VLAN DGLORT SGLORT TIMESTAMP --------------------------------------------------------------------------- 000 0x00000000 0x00000000 0x00000003 0x002a 0x0000 0x0000 0x0000 0x13951807dc4fedf0 001 0x00000000 0x00000000 0x00000003 0x002a 0x0000 0x0000 0x0000 0x1395180906c9f2c8 002 0x3731c000 0x00000000 0x00000000 0x0000 0x0000 0x0000 0x0000 0x0000000000000000 003 0x3731d000 0x00000000 0x00000000 0x0000 0x0000 0x0000 0x0000 0x0000000000000000 004 0xaab3a000 0x00000000 0x00000000 0x0000 0x0000 0x0000 0x0000 0x0000000000000000 ... # cat /sys/kernel/debug/fm10k/0000:01:00.0/q_vector.000/tx_ring.000 DES BUFFER_ADDRESS LENGTH VLAN MSS HDRLEN FLAGS --------------------------------------------------------- 000 0x00000000aa8a1002 0x005a 0x0000 0x0000 0x0000 0xc0 001 0x00000000aa8a2002 0x005a 0x0000 0x0000 0x0000 0xc0 002 0x000000006bc13202 0x004e 0x0000 0x0000 0x0000 0xc0 003 0x000000006bc13c02 0x002a 0x0000 0x0000 0x0000 0xe1 004 0x000000006bc13602 0x0062 0x0000 0x0000 0x0000 0xc0 Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r--drivers/net/ethernet/intel/fm10k/Makefile2
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k.h24
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c259
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_main.c8
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_pci.c6
5 files changed, 298 insertions, 1 deletions
diff --git a/drivers/net/ethernet/intel/fm10k/Makefile b/drivers/net/ethernet/intel/fm10k/Makefile
index 502362584165..fbc0e092077c 100644
--- a/drivers/net/ethernet/intel/fm10k/Makefile
+++ b/drivers/net/ethernet/intel/fm10k/Makefile
@@ -30,4 +30,4 @@ obj-$(CONFIG_FM10K) += fm10k.o
30fm10k-objs := fm10k_main.o fm10k_common.o fm10k_pci.o \ 30fm10k-objs := fm10k_main.o fm10k_common.o fm10k_pci.o \
31 fm10k_netdev.o fm10k_ethtool.o fm10k_pf.o fm10k_vf.o \ 31 fm10k_netdev.o fm10k_ethtool.o fm10k_pf.o fm10k_vf.o \
32 fm10k_mbx.o fm10k_iov.o fm10k_tlv.o \ 32 fm10k_mbx.o fm10k_iov.o fm10k_tlv.o \
33 fm10k_dcbnl.o 33 fm10k_debugfs.o fm10k_dcbnl.o
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k.h b/drivers/net/ethernet/intel/fm10k/fm10k.h
index 33a59493094c..10454834176a 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k.h
+++ b/drivers/net/ethernet/intel/fm10k/fm10k.h
@@ -199,6 +199,9 @@ struct fm10k_q_vector {
199 struct napi_struct napi; 199 struct napi_struct napi;
200 char name[IFNAMSIZ + 9]; 200 char name[IFNAMSIZ + 9];
201 201
202#ifdef CONFIG_DEBUG_FS
203 struct dentry *dbg_q_vector;
204#endif /* CONFIG_DEBUG_FS */
202 struct rcu_head rcu; /* to avoid race with update stats on free */ 205 struct rcu_head rcu; /* to avoid race with update stats on free */
203 206
204 /* for dynamic allocation of rings associated with this q_vector */ 207 /* for dynamic allocation of rings associated with this q_vector */
@@ -307,6 +310,10 @@ struct fm10k_intfc {
307 /* VXLAN port tracking information */ 310 /* VXLAN port tracking information */
308 struct list_head vxlan_port; 311 struct list_head vxlan_port;
309 312
313#ifdef CONFIG_DEBUG_FS
314 struct dentry *dbg_intfc;
315
316#endif /* CONFIG_DEBUG_FS */
310#ifdef CONFIG_DCB 317#ifdef CONFIG_DCB
311 u8 pfc_en; 318 u8 pfc_en;
312#endif 319#endif
@@ -468,6 +475,23 @@ int fm10k_ndo_set_vf_bw(struct net_device *netdev, int vf_idx, int rate,
468int fm10k_ndo_get_vf_config(struct net_device *netdev, 475int fm10k_ndo_get_vf_config(struct net_device *netdev,
469 int vf_idx, struct ifla_vf_info *ivi); 476 int vf_idx, struct ifla_vf_info *ivi);
470 477
478/* DebugFS */
479#ifdef CONFIG_DEBUG_FS
480void fm10k_dbg_q_vector_init(struct fm10k_q_vector *q_vector);
481void fm10k_dbg_q_vector_exit(struct fm10k_q_vector *q_vector);
482void fm10k_dbg_intfc_init(struct fm10k_intfc *interface);
483void fm10k_dbg_intfc_exit(struct fm10k_intfc *interface);
484void fm10k_dbg_init(void);
485void fm10k_dbg_exit(void);
486#else
487static inline void fm10k_dbg_q_vector_init(struct fm10k_q_vector *q_vector) {}
488static inline void fm10k_dbg_q_vector_exit(struct fm10k_q_vector *q_vector) {}
489static inline void fm10k_dbg_intfc_init(struct fm10k_intfc *interface) {}
490static inline void fm10k_dbg_intfc_exit(struct fm10k_intfc *interface) {}
491static inline void fm10k_dbg_init(void) {}
492static inline void fm10k_dbg_exit(void) {}
493#endif /* CONFIG_DEBUG_FS */
494
471/* DCB */ 495/* DCB */
472void fm10k_dcbnl_set_ops(struct net_device *dev); 496void fm10k_dcbnl_set_ops(struct net_device *dev);
473#endif /* _FM10K_H_ */ 497#endif /* _FM10K_H_ */
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c b/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c
new file mode 100644
index 000000000000..4327f86218b9
--- /dev/null
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c
@@ -0,0 +1,259 @@
1/* Intel Ethernet Switch Host Interface Driver
2 * Copyright(c) 2013 - 2014 Intel Corporation.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * The full GNU General Public License is included in this distribution in
14 * the file called "COPYING".
15 *
16 * Contact Information:
17 * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
18 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
19 */
20
21#ifdef CONFIG_DEBUG_FS
22
23#include "fm10k.h"
24
25#include <linux/debugfs.h>
26#include <linux/seq_file.h>
27
28static struct dentry *dbg_root;
29
30/* Descriptor Seq Functions */
31
32static void *fm10k_dbg_desc_seq_start(struct seq_file *s, loff_t *pos)
33{
34 struct fm10k_ring *ring = s->private;
35
36 return (*pos < ring->count) ? pos : NULL;
37}
38
39static void *fm10k_dbg_desc_seq_next(struct seq_file *s, void *v, loff_t *pos)
40{
41 struct fm10k_ring *ring = s->private;
42
43 return (++(*pos) < ring->count) ? pos : NULL;
44}
45
46static void fm10k_dbg_desc_seq_stop(struct seq_file *s, void *v)
47{
48 /* Do nothing. */
49}
50
51static void fm10k_dbg_desc_break(struct seq_file *s, int i)
52{
53 while (i--)
54 seq_puts(s, "-");
55
56 seq_puts(s, "\n");
57}
58
59static int fm10k_dbg_tx_desc_seq_show(struct seq_file *s, void *v)
60{
61 struct fm10k_ring *ring = s->private;
62 int i = *(loff_t *)v;
63 static const char tx_desc_hdr[] =
64 "DES BUFFER_ADDRESS LENGTH VLAN MSS HDRLEN FLAGS\n";
65
66 /* Generate header */
67 if (!i) {
68 seq_printf(s, tx_desc_hdr);
69 fm10k_dbg_desc_break(s, sizeof(tx_desc_hdr) - 1);
70 }
71
72 /* Validate descriptor allocation */
73 if (!ring->desc) {
74 seq_printf(s, "%03X Descriptor ring not allocated.\n", i);
75 } else {
76 struct fm10k_tx_desc *txd = FM10K_TX_DESC(ring, i);
77
78 seq_printf(s, "%03X %#018llx %#06x %#06x %#06x %#06x %#04x\n",
79 i, txd->buffer_addr, txd->buflen, txd->vlan,
80 txd->mss, txd->hdrlen, txd->flags);
81 }
82
83 return 0;
84}
85
86static int fm10k_dbg_rx_desc_seq_show(struct seq_file *s, void *v)
87{
88 struct fm10k_ring *ring = s->private;
89 int i = *(loff_t *)v;
90 static const char rx_desc_hdr[] =
91 "DES DATA RSS STATERR LENGTH VLAN DGLORT SGLORT TIMESTAMP\n";
92
93 /* Generate header */
94 if (!i) {
95 seq_printf(s, rx_desc_hdr);
96 fm10k_dbg_desc_break(s, sizeof(rx_desc_hdr) - 1);
97 }
98
99 /* Validate descriptor allocation */
100 if (!ring->desc) {
101 seq_printf(s, "%03X Descriptor ring not allocated.\n", i);
102 } else {
103 union fm10k_rx_desc *rxd = FM10K_RX_DESC(ring, i);
104
105 seq_printf(s,
106 "%03X %#010x %#010x %#010x %#06x %#06x %#06x %#06x %#018llx\n",
107 i, rxd->d.data, rxd->d.rss, rxd->d.staterr,
108 rxd->w.length, rxd->w.vlan, rxd->w.dglort,
109 rxd->w.sglort, rxd->q.timestamp);
110 }
111
112 return 0;
113}
114
115static const struct seq_operations fm10k_dbg_tx_desc_seq_ops = {
116 .start = fm10k_dbg_desc_seq_start,
117 .next = fm10k_dbg_desc_seq_next,
118 .stop = fm10k_dbg_desc_seq_stop,
119 .show = fm10k_dbg_tx_desc_seq_show,
120};
121
122static const struct seq_operations fm10k_dbg_rx_desc_seq_ops = {
123 .start = fm10k_dbg_desc_seq_start,
124 .next = fm10k_dbg_desc_seq_next,
125 .stop = fm10k_dbg_desc_seq_stop,
126 .show = fm10k_dbg_rx_desc_seq_show,
127};
128
129static int fm10k_dbg_desc_open(struct inode *inode, struct file *filep)
130{
131 struct fm10k_ring *ring = inode->i_private;
132 struct fm10k_q_vector *q_vector = ring->q_vector;
133 const struct seq_operations *desc_seq_ops;
134 int err;
135
136 if (ring < q_vector->rx.ring)
137 desc_seq_ops = &fm10k_dbg_tx_desc_seq_ops;
138 else
139 desc_seq_ops = &fm10k_dbg_rx_desc_seq_ops;
140
141 err = seq_open(filep, desc_seq_ops);
142 if (err)
143 return err;
144
145 ((struct seq_file *)filep->private_data)->private = ring;
146
147 return 0;
148}
149
150static const struct file_operations fm10k_dbg_desc_fops = {
151 .owner = THIS_MODULE,
152 .open = fm10k_dbg_desc_open,
153 .read = seq_read,
154 .llseek = seq_lseek,
155 .release = seq_release,
156};
157
158/**
159 * fm10k_dbg_q_vector_init - setup debugfs for the q_vectors
160 * @q_vector: q_vector to allocate directories for
161 *
162 * A folder is created for each q_vector found. In each q_vector
163 * folder, a debugfs file is created for each tx and rx ring
164 * allocated to the q_vector.
165 **/
166void fm10k_dbg_q_vector_init(struct fm10k_q_vector *q_vector)
167{
168 struct fm10k_intfc *interface = q_vector->interface;
169 char name[16];
170 int i;
171
172 if (!interface->dbg_intfc)
173 return;
174
175 /* Generate a folder for each q_vector */
176 sprintf(name, "q_vector.%03d", q_vector->v_idx);
177
178 q_vector->dbg_q_vector = debugfs_create_dir(name, interface->dbg_intfc);
179 if (!q_vector->dbg_q_vector)
180 return;
181
182 /* Generate a file for each rx ring in the q_vector */
183 for (i = 0; i < q_vector->tx.count; i++) {
184 struct fm10k_ring *ring = &q_vector->tx.ring[i];
185
186 sprintf(name, "tx_ring.%03d", ring->queue_index);
187
188 debugfs_create_file(name, 0600,
189 q_vector->dbg_q_vector, ring,
190 &fm10k_dbg_desc_fops);
191 }
192
193 /* Generate a file for each rx ring in the q_vector */
194 for (i = 0; i < q_vector->rx.count; i++) {
195 struct fm10k_ring *ring = &q_vector->rx.ring[i];
196
197 sprintf(name, "rx_ring.%03d", ring->queue_index);
198
199 debugfs_create_file(name, 0600,
200 q_vector->dbg_q_vector, ring,
201 &fm10k_dbg_desc_fops);
202 }
203}
204
205/**
206 * fm10k_dbg_free_q_vector_dir - setup debugfs for the q_vectors
207 * @q_vector: q_vector to allocate directories for
208 **/
209void fm10k_dbg_q_vector_exit(struct fm10k_q_vector *q_vector)
210{
211 struct fm10k_intfc *interface = q_vector->interface;
212
213 if (interface->dbg_intfc)
214 debugfs_remove_recursive(q_vector->dbg_q_vector);
215 q_vector->dbg_q_vector = NULL;
216}
217
218/**
219 * fm10k_dbg_intfc_init - setup the debugfs directory for the intferface
220 * @interface: the interface that is starting up
221 **/
222
223void fm10k_dbg_intfc_init(struct fm10k_intfc *interface)
224{
225 const char *name = pci_name(interface->pdev);
226
227 if (dbg_root)
228 interface->dbg_intfc = debugfs_create_dir(name, dbg_root);
229}
230
231/**
232 * fm10k_dbg_intfc_exit - clean out the interface's debugfs entries
233 * @interface: the interface that is stopping
234 **/
235void fm10k_dbg_intfc_exit(struct fm10k_intfc *interface)
236{
237 if (dbg_root)
238 debugfs_remove_recursive(interface->dbg_intfc);
239 interface->dbg_intfc = NULL;
240}
241
242/**
243 * fm10k_dbg_init - start up debugfs for the driver
244 **/
245void fm10k_dbg_init(void)
246{
247 dbg_root = debugfs_create_dir(fm10k_driver_name, NULL);
248}
249
250/**
251 * fm10k_dbg_exit - clean out the driver's debugfs entries
252 **/
253void fm10k_dbg_exit(void)
254{
255 debugfs_remove_recursive(dbg_root);
256 dbg_root = NULL;
257}
258
259#endif /* CONFIG_DEBUG_FS */
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c
index d2c189b037b5..d9987331387e 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c
@@ -52,6 +52,8 @@ static int __init fm10k_init_module(void)
52 pr_info("%s - version %s\n", fm10k_driver_string, fm10k_driver_version); 52 pr_info("%s - version %s\n", fm10k_driver_string, fm10k_driver_version);
53 pr_info("%s\n", fm10k_copyright); 53 pr_info("%s\n", fm10k_copyright);
54 54
55 fm10k_dbg_init();
56
55 return fm10k_register_pci_driver(); 57 return fm10k_register_pci_driver();
56} 58}
57module_init(fm10k_init_module); 59module_init(fm10k_init_module);
@@ -65,6 +67,8 @@ module_init(fm10k_init_module);
65static void __exit fm10k_exit_module(void) 67static void __exit fm10k_exit_module(void)
66{ 68{
67 fm10k_unregister_pci_driver(); 69 fm10k_unregister_pci_driver();
70
71 fm10k_dbg_exit();
68} 72}
69module_exit(fm10k_exit_module); 73module_exit(fm10k_exit_module);
70 74
@@ -1617,6 +1621,8 @@ static int fm10k_alloc_q_vector(struct fm10k_intfc *interface,
1617 ring++; 1621 ring++;
1618 } 1622 }
1619 1623
1624 fm10k_dbg_q_vector_init(q_vector);
1625
1620 return 0; 1626 return 0;
1621} 1627}
1622 1628
@@ -1634,6 +1640,8 @@ static void fm10k_free_q_vector(struct fm10k_intfc *interface, int v_idx)
1634 struct fm10k_q_vector *q_vector = interface->q_vector[v_idx]; 1640 struct fm10k_q_vector *q_vector = interface->q_vector[v_idx];
1635 struct fm10k_ring *ring; 1641 struct fm10k_ring *ring;
1636 1642
1643 fm10k_dbg_q_vector_exit(q_vector);
1644
1637 fm10k_for_each_ring(ring, q_vector->tx) 1645 fm10k_for_each_ring(ring, q_vector->tx)
1638 interface->tx_ring[ring->queue_index] = NULL; 1646 interface->tx_ring[ring->queue_index] = NULL;
1639 1647
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
index 04ca7f2ab385..74d7d473d113 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
@@ -1690,6 +1690,9 @@ static int fm10k_probe(struct pci_dev *pdev,
1690 if (err) 1690 if (err)
1691 goto err_sw_init; 1691 goto err_sw_init;
1692 1692
1693 /* enable debugfs support */
1694 fm10k_dbg_intfc_init(interface);
1695
1693 err = fm10k_init_queueing_scheme(interface); 1696 err = fm10k_init_queueing_scheme(interface);
1694 if (err) 1697 if (err)
1695 goto err_sw_init; 1698 goto err_sw_init;
@@ -1786,6 +1789,9 @@ static void fm10k_remove(struct pci_dev *pdev)
1786 /* free interrupts */ 1789 /* free interrupts */
1787 fm10k_clear_queueing_scheme(interface); 1790 fm10k_clear_queueing_scheme(interface);
1788 1791
1792 /* remove any debugfs interfaces */
1793 fm10k_dbg_intfc_exit(interface);
1794
1789 iounmap(interface->uc_addr); 1795 iounmap(interface->uc_addr);
1790 1796
1791 free_netdev(netdev); 1797 free_netdev(netdev);