xref: /OK3568_Linux_fs/kernel/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /* Copyright(c) 1999 - 2018 Intel Corporation. */
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun #include <linux/debugfs.h>
5*4882a593Smuzhiyun #include <linux/module.h>
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include "ixgbe.h"
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun static struct dentry *ixgbe_dbg_root;
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun static char ixgbe_dbg_reg_ops_buf[256] = "";
12*4882a593Smuzhiyun 
ixgbe_dbg_common_ops_read(struct file * filp,char __user * buffer,size_t count,loff_t * ppos,char * dbg_buf)13*4882a593Smuzhiyun static ssize_t ixgbe_dbg_common_ops_read(struct file *filp, char __user *buffer,
14*4882a593Smuzhiyun 					 size_t count, loff_t *ppos,
15*4882a593Smuzhiyun 					 char *dbg_buf)
16*4882a593Smuzhiyun {
17*4882a593Smuzhiyun 	struct ixgbe_adapter *adapter = filp->private_data;
18*4882a593Smuzhiyun 	char *buf;
19*4882a593Smuzhiyun 	int len;
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun 	/* don't allow partial reads */
22*4882a593Smuzhiyun 	if (*ppos != 0)
23*4882a593Smuzhiyun 		return 0;
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun 	buf = kasprintf(GFP_KERNEL, "%s: %s\n",
26*4882a593Smuzhiyun 			adapter->netdev->name, dbg_buf);
27*4882a593Smuzhiyun 	if (!buf)
28*4882a593Smuzhiyun 		return -ENOMEM;
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun 	if (count < strlen(buf)) {
31*4882a593Smuzhiyun 		kfree(buf);
32*4882a593Smuzhiyun 		return -ENOSPC;
33*4882a593Smuzhiyun 	}
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun 	len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun 	kfree(buf);
38*4882a593Smuzhiyun 	return len;
39*4882a593Smuzhiyun }
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun /**
42*4882a593Smuzhiyun  * ixgbe_dbg_reg_ops_read - read for reg_ops datum
43*4882a593Smuzhiyun  * @filp: the opened file
44*4882a593Smuzhiyun  * @buffer: where to write the data for the user to read
45*4882a593Smuzhiyun  * @count: the size of the user's buffer
46*4882a593Smuzhiyun  * @ppos: file position offset
47*4882a593Smuzhiyun  **/
ixgbe_dbg_reg_ops_read(struct file * filp,char __user * buffer,size_t count,loff_t * ppos)48*4882a593Smuzhiyun static ssize_t ixgbe_dbg_reg_ops_read(struct file *filp, char __user *buffer,
49*4882a593Smuzhiyun 				      size_t count, loff_t *ppos)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun 	return ixgbe_dbg_common_ops_read(filp, buffer, count, ppos,
52*4882a593Smuzhiyun 					 ixgbe_dbg_reg_ops_buf);
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun /**
56*4882a593Smuzhiyun  * ixgbe_dbg_reg_ops_write - write into reg_ops datum
57*4882a593Smuzhiyun  * @filp: the opened file
58*4882a593Smuzhiyun  * @buffer: where to find the user's data
59*4882a593Smuzhiyun  * @count: the length of the user's data
60*4882a593Smuzhiyun  * @ppos: file position offset
61*4882a593Smuzhiyun  **/
ixgbe_dbg_reg_ops_write(struct file * filp,const char __user * buffer,size_t count,loff_t * ppos)62*4882a593Smuzhiyun static ssize_t ixgbe_dbg_reg_ops_write(struct file *filp,
63*4882a593Smuzhiyun 				     const char __user *buffer,
64*4882a593Smuzhiyun 				     size_t count, loff_t *ppos)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun 	struct ixgbe_adapter *adapter = filp->private_data;
67*4882a593Smuzhiyun 	int len;
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	/* don't allow partial writes */
70*4882a593Smuzhiyun 	if (*ppos != 0)
71*4882a593Smuzhiyun 		return 0;
72*4882a593Smuzhiyun 	if (count >= sizeof(ixgbe_dbg_reg_ops_buf))
73*4882a593Smuzhiyun 		return -ENOSPC;
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	len = simple_write_to_buffer(ixgbe_dbg_reg_ops_buf,
76*4882a593Smuzhiyun 				     sizeof(ixgbe_dbg_reg_ops_buf)-1,
77*4882a593Smuzhiyun 				     ppos,
78*4882a593Smuzhiyun 				     buffer,
79*4882a593Smuzhiyun 				     count);
80*4882a593Smuzhiyun 	if (len < 0)
81*4882a593Smuzhiyun 		return len;
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	ixgbe_dbg_reg_ops_buf[len] = '\0';
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	if (strncmp(ixgbe_dbg_reg_ops_buf, "write", 5) == 0) {
86*4882a593Smuzhiyun 		u32 reg, value;
87*4882a593Smuzhiyun 		int cnt;
88*4882a593Smuzhiyun 		cnt = sscanf(&ixgbe_dbg_reg_ops_buf[5], "%x %x", &reg, &value);
89*4882a593Smuzhiyun 		if (cnt == 2) {
90*4882a593Smuzhiyun 			IXGBE_WRITE_REG(&adapter->hw, reg, value);
91*4882a593Smuzhiyun 			value = IXGBE_READ_REG(&adapter->hw, reg);
92*4882a593Smuzhiyun 			e_dev_info("write: 0x%08x = 0x%08x\n", reg, value);
93*4882a593Smuzhiyun 		} else {
94*4882a593Smuzhiyun 			e_dev_info("write <reg> <value>\n");
95*4882a593Smuzhiyun 		}
96*4882a593Smuzhiyun 	} else if (strncmp(ixgbe_dbg_reg_ops_buf, "read", 4) == 0) {
97*4882a593Smuzhiyun 		u32 reg, value;
98*4882a593Smuzhiyun 		int cnt;
99*4882a593Smuzhiyun 		cnt = sscanf(&ixgbe_dbg_reg_ops_buf[4], "%x", &reg);
100*4882a593Smuzhiyun 		if (cnt == 1) {
101*4882a593Smuzhiyun 			value = IXGBE_READ_REG(&adapter->hw, reg);
102*4882a593Smuzhiyun 			e_dev_info("read 0x%08x = 0x%08x\n", reg, value);
103*4882a593Smuzhiyun 		} else {
104*4882a593Smuzhiyun 			e_dev_info("read <reg>\n");
105*4882a593Smuzhiyun 		}
106*4882a593Smuzhiyun 	} else {
107*4882a593Smuzhiyun 		e_dev_info("Unknown command %s\n", ixgbe_dbg_reg_ops_buf);
108*4882a593Smuzhiyun 		e_dev_info("Available commands:\n");
109*4882a593Smuzhiyun 		e_dev_info("   read <reg>\n");
110*4882a593Smuzhiyun 		e_dev_info("   write <reg> <value>\n");
111*4882a593Smuzhiyun 	}
112*4882a593Smuzhiyun 	return count;
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun static const struct file_operations ixgbe_dbg_reg_ops_fops = {
116*4882a593Smuzhiyun 	.owner = THIS_MODULE,
117*4882a593Smuzhiyun 	.open = simple_open,
118*4882a593Smuzhiyun 	.read =  ixgbe_dbg_reg_ops_read,
119*4882a593Smuzhiyun 	.write = ixgbe_dbg_reg_ops_write,
120*4882a593Smuzhiyun };
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun static char ixgbe_dbg_netdev_ops_buf[256] = "";
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun /**
125*4882a593Smuzhiyun  * ixgbe_dbg_netdev_ops_read - read for netdev_ops datum
126*4882a593Smuzhiyun  * @filp: the opened file
127*4882a593Smuzhiyun  * @buffer: where to write the data for the user to read
128*4882a593Smuzhiyun  * @count: the size of the user's buffer
129*4882a593Smuzhiyun  * @ppos: file position offset
130*4882a593Smuzhiyun  **/
ixgbe_dbg_netdev_ops_read(struct file * filp,char __user * buffer,size_t count,loff_t * ppos)131*4882a593Smuzhiyun static ssize_t ixgbe_dbg_netdev_ops_read(struct file *filp, char __user *buffer,
132*4882a593Smuzhiyun 					 size_t count, loff_t *ppos)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun 	return ixgbe_dbg_common_ops_read(filp, buffer, count, ppos,
135*4882a593Smuzhiyun 					 ixgbe_dbg_netdev_ops_buf);
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun /**
139*4882a593Smuzhiyun  * ixgbe_dbg_netdev_ops_write - write into netdev_ops datum
140*4882a593Smuzhiyun  * @filp: the opened file
141*4882a593Smuzhiyun  * @buffer: where to find the user's data
142*4882a593Smuzhiyun  * @count: the length of the user's data
143*4882a593Smuzhiyun  * @ppos: file position offset
144*4882a593Smuzhiyun  **/
ixgbe_dbg_netdev_ops_write(struct file * filp,const char __user * buffer,size_t count,loff_t * ppos)145*4882a593Smuzhiyun static ssize_t ixgbe_dbg_netdev_ops_write(struct file *filp,
146*4882a593Smuzhiyun 					  const char __user *buffer,
147*4882a593Smuzhiyun 					  size_t count, loff_t *ppos)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun 	struct ixgbe_adapter *adapter = filp->private_data;
150*4882a593Smuzhiyun 	int len;
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	/* don't allow partial writes */
153*4882a593Smuzhiyun 	if (*ppos != 0)
154*4882a593Smuzhiyun 		return 0;
155*4882a593Smuzhiyun 	if (count >= sizeof(ixgbe_dbg_netdev_ops_buf))
156*4882a593Smuzhiyun 		return -ENOSPC;
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	len = simple_write_to_buffer(ixgbe_dbg_netdev_ops_buf,
159*4882a593Smuzhiyun 				     sizeof(ixgbe_dbg_netdev_ops_buf)-1,
160*4882a593Smuzhiyun 				     ppos,
161*4882a593Smuzhiyun 				     buffer,
162*4882a593Smuzhiyun 				     count);
163*4882a593Smuzhiyun 	if (len < 0)
164*4882a593Smuzhiyun 		return len;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	ixgbe_dbg_netdev_ops_buf[len] = '\0';
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 	if (strncmp(ixgbe_dbg_netdev_ops_buf, "tx_timeout", 10) == 0) {
169*4882a593Smuzhiyun 		/* TX Queue number below is wrong, but ixgbe does not use it */
170*4882a593Smuzhiyun 		adapter->netdev->netdev_ops->ndo_tx_timeout(adapter->netdev,
171*4882a593Smuzhiyun 							    UINT_MAX);
172*4882a593Smuzhiyun 		e_dev_info("tx_timeout called\n");
173*4882a593Smuzhiyun 	} else {
174*4882a593Smuzhiyun 		e_dev_info("Unknown command: %s\n", ixgbe_dbg_netdev_ops_buf);
175*4882a593Smuzhiyun 		e_dev_info("Available commands:\n");
176*4882a593Smuzhiyun 		e_dev_info("    tx_timeout\n");
177*4882a593Smuzhiyun 	}
178*4882a593Smuzhiyun 	return count;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun static const struct file_operations ixgbe_dbg_netdev_ops_fops = {
182*4882a593Smuzhiyun 	.owner = THIS_MODULE,
183*4882a593Smuzhiyun 	.open = simple_open,
184*4882a593Smuzhiyun 	.read = ixgbe_dbg_netdev_ops_read,
185*4882a593Smuzhiyun 	.write = ixgbe_dbg_netdev_ops_write,
186*4882a593Smuzhiyun };
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun /**
189*4882a593Smuzhiyun  * ixgbe_dbg_adapter_init - setup the debugfs directory for the adapter
190*4882a593Smuzhiyun  * @adapter: the adapter that is starting up
191*4882a593Smuzhiyun  **/
ixgbe_dbg_adapter_init(struct ixgbe_adapter * adapter)192*4882a593Smuzhiyun void ixgbe_dbg_adapter_init(struct ixgbe_adapter *adapter)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun 	const char *name = pci_name(adapter->pdev);
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	adapter->ixgbe_dbg_adapter = debugfs_create_dir(name, ixgbe_dbg_root);
197*4882a593Smuzhiyun 	debugfs_create_file("reg_ops", 0600, adapter->ixgbe_dbg_adapter,
198*4882a593Smuzhiyun 			    adapter, &ixgbe_dbg_reg_ops_fops);
199*4882a593Smuzhiyun 	debugfs_create_file("netdev_ops", 0600, adapter->ixgbe_dbg_adapter,
200*4882a593Smuzhiyun 			    adapter, &ixgbe_dbg_netdev_ops_fops);
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun /**
204*4882a593Smuzhiyun  * ixgbe_dbg_adapter_exit - clear out the adapter's debugfs entries
205*4882a593Smuzhiyun  * @adapter: the adapter that is exiting
206*4882a593Smuzhiyun  **/
ixgbe_dbg_adapter_exit(struct ixgbe_adapter * adapter)207*4882a593Smuzhiyun void ixgbe_dbg_adapter_exit(struct ixgbe_adapter *adapter)
208*4882a593Smuzhiyun {
209*4882a593Smuzhiyun 	debugfs_remove_recursive(adapter->ixgbe_dbg_adapter);
210*4882a593Smuzhiyun 	adapter->ixgbe_dbg_adapter = NULL;
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun /**
214*4882a593Smuzhiyun  * ixgbe_dbg_init - start up debugfs for the driver
215*4882a593Smuzhiyun  **/
ixgbe_dbg_init(void)216*4882a593Smuzhiyun void ixgbe_dbg_init(void)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun 	ixgbe_dbg_root = debugfs_create_dir(ixgbe_driver_name, NULL);
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun /**
222*4882a593Smuzhiyun  * ixgbe_dbg_exit - clean out the driver's debugfs entries
223*4882a593Smuzhiyun  **/
ixgbe_dbg_exit(void)224*4882a593Smuzhiyun void ixgbe_dbg_exit(void)
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun 	debugfs_remove_recursive(ixgbe_dbg_root);
227*4882a593Smuzhiyun }
228