151dce24bSJeff Kirsher // SPDX-License-Identifier: GPL-2.0
251dce24bSJeff Kirsher /* Copyright(c) 1999 - 2018 Intel Corporation. */
300949167SCatherine Sullivan
400949167SCatherine Sullivan #include <linux/debugfs.h>
500949167SCatherine Sullivan #include <linux/module.h>
600949167SCatherine Sullivan
700949167SCatherine Sullivan #include "ixgbe.h"
800949167SCatherine Sullivan
900949167SCatherine Sullivan static struct dentry *ixgbe_dbg_root;
1000949167SCatherine Sullivan
1191fbd8f0SCatherine Sullivan static char ixgbe_dbg_reg_ops_buf[256] = "";
1291fbd8f0SCatherine Sullivan
ixgbe_dbg_common_ops_read(struct file * filp,char __user * buffer,size_t count,loff_t * ppos,char * dbg_buf)13e9c72183SYueHaibing static ssize_t ixgbe_dbg_common_ops_read(struct file *filp, char __user *buffer,
14e9c72183SYueHaibing size_t count, loff_t *ppos,
15e9c72183SYueHaibing char *dbg_buf)
1691fbd8f0SCatherine Sullivan {
1791fbd8f0SCatherine Sullivan struct ixgbe_adapter *adapter = filp->private_data;
183288d735Sjoshua.a.hay@intel.com char *buf;
1991fbd8f0SCatherine Sullivan int len;
2091fbd8f0SCatherine Sullivan
2191fbd8f0SCatherine Sullivan /* don't allow partial reads */
2291fbd8f0SCatherine Sullivan if (*ppos != 0)
2391fbd8f0SCatherine Sullivan return 0;
2491fbd8f0SCatherine Sullivan
253288d735Sjoshua.a.hay@intel.com buf = kasprintf(GFP_KERNEL, "%s: %s\n",
26e9c72183SYueHaibing adapter->netdev->name, dbg_buf);
273288d735Sjoshua.a.hay@intel.com if (!buf)
283288d735Sjoshua.a.hay@intel.com return -ENOMEM;
2991fbd8f0SCatherine Sullivan
303288d735Sjoshua.a.hay@intel.com if (count < strlen(buf)) {
313288d735Sjoshua.a.hay@intel.com kfree(buf);
323288d735Sjoshua.a.hay@intel.com return -ENOSPC;
333288d735Sjoshua.a.hay@intel.com }
343288d735Sjoshua.a.hay@intel.com
353288d735Sjoshua.a.hay@intel.com len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
363288d735Sjoshua.a.hay@intel.com
373288d735Sjoshua.a.hay@intel.com kfree(buf);
3891fbd8f0SCatherine Sullivan return len;
3991fbd8f0SCatherine Sullivan }
4091fbd8f0SCatherine Sullivan
4191fbd8f0SCatherine Sullivan /**
42e9c72183SYueHaibing * ixgbe_dbg_reg_ops_read - read for reg_ops datum
43e9c72183SYueHaibing * @filp: the opened file
44e9c72183SYueHaibing * @buffer: where to write the data for the user to read
45e9c72183SYueHaibing * @count: the size of the user's buffer
46e9c72183SYueHaibing * @ppos: file position offset
47e9c72183SYueHaibing **/
ixgbe_dbg_reg_ops_read(struct file * filp,char __user * buffer,size_t count,loff_t * ppos)48e9c72183SYueHaibing static ssize_t ixgbe_dbg_reg_ops_read(struct file *filp, char __user *buffer,
49e9c72183SYueHaibing size_t count, loff_t *ppos)
50e9c72183SYueHaibing {
51e9c72183SYueHaibing return ixgbe_dbg_common_ops_read(filp, buffer, count, ppos,
52e9c72183SYueHaibing ixgbe_dbg_reg_ops_buf);
53e9c72183SYueHaibing }
54e9c72183SYueHaibing
55e9c72183SYueHaibing /**
5691fbd8f0SCatherine Sullivan * ixgbe_dbg_reg_ops_write - write into reg_ops datum
5791fbd8f0SCatherine Sullivan * @filp: the opened file
5891fbd8f0SCatherine Sullivan * @buffer: where to find the user's data
5991fbd8f0SCatherine Sullivan * @count: the length of the user's data
6091fbd8f0SCatherine Sullivan * @ppos: file position offset
6191fbd8f0SCatherine Sullivan **/
ixgbe_dbg_reg_ops_write(struct file * filp,const char __user * buffer,size_t count,loff_t * ppos)6291fbd8f0SCatherine Sullivan static ssize_t ixgbe_dbg_reg_ops_write(struct file *filp,
6391fbd8f0SCatherine Sullivan const char __user *buffer,
6491fbd8f0SCatherine Sullivan size_t count, loff_t *ppos)
6591fbd8f0SCatherine Sullivan {
6691fbd8f0SCatherine Sullivan struct ixgbe_adapter *adapter = filp->private_data;
673288d735Sjoshua.a.hay@intel.com int len;
6891fbd8f0SCatherine Sullivan
6991fbd8f0SCatherine Sullivan /* don't allow partial writes */
7091fbd8f0SCatherine Sullivan if (*ppos != 0)
7191fbd8f0SCatherine Sullivan return 0;
7291fbd8f0SCatherine Sullivan if (count >= sizeof(ixgbe_dbg_reg_ops_buf))
7391fbd8f0SCatherine Sullivan return -ENOSPC;
7491fbd8f0SCatherine Sullivan
753288d735Sjoshua.a.hay@intel.com len = simple_write_to_buffer(ixgbe_dbg_reg_ops_buf,
763288d735Sjoshua.a.hay@intel.com sizeof(ixgbe_dbg_reg_ops_buf)-1,
773288d735Sjoshua.a.hay@intel.com ppos,
783288d735Sjoshua.a.hay@intel.com buffer,
793288d735Sjoshua.a.hay@intel.com count);
803288d735Sjoshua.a.hay@intel.com if (len < 0)
813288d735Sjoshua.a.hay@intel.com return len;
823288d735Sjoshua.a.hay@intel.com
833288d735Sjoshua.a.hay@intel.com ixgbe_dbg_reg_ops_buf[len] = '\0';
8491fbd8f0SCatherine Sullivan
8591fbd8f0SCatherine Sullivan if (strncmp(ixgbe_dbg_reg_ops_buf, "write", 5) == 0) {
8691fbd8f0SCatherine Sullivan u32 reg, value;
8791fbd8f0SCatherine Sullivan int cnt;
8891fbd8f0SCatherine Sullivan cnt = sscanf(&ixgbe_dbg_reg_ops_buf[5], "%x %x", ®, &value);
8991fbd8f0SCatherine Sullivan if (cnt == 2) {
9091fbd8f0SCatherine Sullivan IXGBE_WRITE_REG(&adapter->hw, reg, value);
9191fbd8f0SCatherine Sullivan value = IXGBE_READ_REG(&adapter->hw, reg);
9291fbd8f0SCatherine Sullivan e_dev_info("write: 0x%08x = 0x%08x\n", reg, value);
9391fbd8f0SCatherine Sullivan } else {
9491fbd8f0SCatherine Sullivan e_dev_info("write <reg> <value>\n");
9591fbd8f0SCatherine Sullivan }
9691fbd8f0SCatherine Sullivan } else if (strncmp(ixgbe_dbg_reg_ops_buf, "read", 4) == 0) {
9791fbd8f0SCatherine Sullivan u32 reg, value;
9891fbd8f0SCatherine Sullivan int cnt;
9991fbd8f0SCatherine Sullivan cnt = sscanf(&ixgbe_dbg_reg_ops_buf[4], "%x", ®);
10091fbd8f0SCatherine Sullivan if (cnt == 1) {
10191fbd8f0SCatherine Sullivan value = IXGBE_READ_REG(&adapter->hw, reg);
10291fbd8f0SCatherine Sullivan e_dev_info("read 0x%08x = 0x%08x\n", reg, value);
10391fbd8f0SCatherine Sullivan } else {
10491fbd8f0SCatherine Sullivan e_dev_info("read <reg>\n");
10591fbd8f0SCatherine Sullivan }
10691fbd8f0SCatherine Sullivan } else {
10791fbd8f0SCatherine Sullivan e_dev_info("Unknown command %s\n", ixgbe_dbg_reg_ops_buf);
10891fbd8f0SCatherine Sullivan e_dev_info("Available commands:\n");
10991fbd8f0SCatherine Sullivan e_dev_info(" read <reg>\n");
11091fbd8f0SCatherine Sullivan e_dev_info(" write <reg> <value>\n");
11191fbd8f0SCatherine Sullivan }
11291fbd8f0SCatherine Sullivan return count;
11391fbd8f0SCatherine Sullivan }
11491fbd8f0SCatherine Sullivan
11591fbd8f0SCatherine Sullivan static const struct file_operations ixgbe_dbg_reg_ops_fops = {
11691fbd8f0SCatherine Sullivan .owner = THIS_MODULE,
11721cc57fbSWei Yongjun .open = simple_open,
11891fbd8f0SCatherine Sullivan .read = ixgbe_dbg_reg_ops_read,
11991fbd8f0SCatherine Sullivan .write = ixgbe_dbg_reg_ops_write,
12091fbd8f0SCatherine Sullivan };
12191fbd8f0SCatherine Sullivan
122826ff0deSCatherine Sullivan static char ixgbe_dbg_netdev_ops_buf[256] = "";
123826ff0deSCatherine Sullivan
124826ff0deSCatherine Sullivan /**
125826ff0deSCatherine Sullivan * ixgbe_dbg_netdev_ops_read - read for netdev_ops datum
126826ff0deSCatherine Sullivan * @filp: the opened file
127826ff0deSCatherine Sullivan * @buffer: where to write the data for the user to read
128826ff0deSCatherine Sullivan * @count: the size of the user's buffer
129826ff0deSCatherine Sullivan * @ppos: file position offset
130826ff0deSCatherine Sullivan **/
ixgbe_dbg_netdev_ops_read(struct file * filp,char __user * buffer,size_t count,loff_t * ppos)131e9c72183SYueHaibing static ssize_t ixgbe_dbg_netdev_ops_read(struct file *filp, char __user *buffer,
132826ff0deSCatherine Sullivan size_t count, loff_t *ppos)
133826ff0deSCatherine Sullivan {
134e9c72183SYueHaibing return ixgbe_dbg_common_ops_read(filp, buffer, count, ppos,
1353288d735Sjoshua.a.hay@intel.com ixgbe_dbg_netdev_ops_buf);
136826ff0deSCatherine Sullivan }
137826ff0deSCatherine Sullivan
138826ff0deSCatherine Sullivan /**
139826ff0deSCatherine Sullivan * ixgbe_dbg_netdev_ops_write - write into netdev_ops datum
140826ff0deSCatherine Sullivan * @filp: the opened file
141826ff0deSCatherine Sullivan * @buffer: where to find the user's data
142826ff0deSCatherine Sullivan * @count: the length of the user's data
143826ff0deSCatherine Sullivan * @ppos: file position offset
144826ff0deSCatherine Sullivan **/
ixgbe_dbg_netdev_ops_write(struct file * filp,const char __user * buffer,size_t count,loff_t * ppos)145826ff0deSCatherine Sullivan static ssize_t ixgbe_dbg_netdev_ops_write(struct file *filp,
146826ff0deSCatherine Sullivan const char __user *buffer,
147826ff0deSCatherine Sullivan size_t count, loff_t *ppos)
148826ff0deSCatherine Sullivan {
149826ff0deSCatherine Sullivan struct ixgbe_adapter *adapter = filp->private_data;
1503288d735Sjoshua.a.hay@intel.com int len;
151826ff0deSCatherine Sullivan
152826ff0deSCatherine Sullivan /* don't allow partial writes */
153826ff0deSCatherine Sullivan if (*ppos != 0)
154826ff0deSCatherine Sullivan return 0;
155826ff0deSCatherine Sullivan if (count >= sizeof(ixgbe_dbg_netdev_ops_buf))
156826ff0deSCatherine Sullivan return -ENOSPC;
157826ff0deSCatherine Sullivan
1583288d735Sjoshua.a.hay@intel.com len = simple_write_to_buffer(ixgbe_dbg_netdev_ops_buf,
1593288d735Sjoshua.a.hay@intel.com sizeof(ixgbe_dbg_netdev_ops_buf)-1,
1603288d735Sjoshua.a.hay@intel.com ppos,
1613288d735Sjoshua.a.hay@intel.com buffer,
1623288d735Sjoshua.a.hay@intel.com count);
1633288d735Sjoshua.a.hay@intel.com if (len < 0)
1643288d735Sjoshua.a.hay@intel.com return len;
1653288d735Sjoshua.a.hay@intel.com
1663288d735Sjoshua.a.hay@intel.com ixgbe_dbg_netdev_ops_buf[len] = '\0';
167826ff0deSCatherine Sullivan
168826ff0deSCatherine Sullivan if (strncmp(ixgbe_dbg_netdev_ops_buf, "tx_timeout", 10) == 0) {
169*0290bd29SMichael S. Tsirkin /* TX Queue number below is wrong, but ixgbe does not use it */
170*0290bd29SMichael S. Tsirkin adapter->netdev->netdev_ops->ndo_tx_timeout(adapter->netdev,
171*0290bd29SMichael S. Tsirkin UINT_MAX);
172826ff0deSCatherine Sullivan e_dev_info("tx_timeout called\n");
173826ff0deSCatherine Sullivan } else {
174826ff0deSCatherine Sullivan e_dev_info("Unknown command: %s\n", ixgbe_dbg_netdev_ops_buf);
175826ff0deSCatherine Sullivan e_dev_info("Available commands:\n");
176826ff0deSCatherine Sullivan e_dev_info(" tx_timeout\n");
177826ff0deSCatherine Sullivan }
178826ff0deSCatherine Sullivan return count;
179826ff0deSCatherine Sullivan }
180826ff0deSCatherine Sullivan
181826ff0deSCatherine Sullivan static const struct file_operations ixgbe_dbg_netdev_ops_fops = {
182826ff0deSCatherine Sullivan .owner = THIS_MODULE,
18321cc57fbSWei Yongjun .open = simple_open,
184826ff0deSCatherine Sullivan .read = ixgbe_dbg_netdev_ops_read,
185826ff0deSCatherine Sullivan .write = ixgbe_dbg_netdev_ops_write,
186826ff0deSCatherine Sullivan };
187826ff0deSCatherine Sullivan
18800949167SCatherine Sullivan /**
18900949167SCatherine Sullivan * ixgbe_dbg_adapter_init - setup the debugfs directory for the adapter
19000949167SCatherine Sullivan * @adapter: the adapter that is starting up
19100949167SCatherine Sullivan **/
ixgbe_dbg_adapter_init(struct ixgbe_adapter * adapter)19200949167SCatherine Sullivan void ixgbe_dbg_adapter_init(struct ixgbe_adapter *adapter)
19300949167SCatherine Sullivan {
19400949167SCatherine Sullivan const char *name = pci_name(adapter->pdev);
19535dc61ebSGreg Kroah-Hartman
19600949167SCatherine Sullivan adapter->ixgbe_dbg_adapter = debugfs_create_dir(name, ixgbe_dbg_root);
19735dc61ebSGreg Kroah-Hartman debugfs_create_file("reg_ops", 0600, adapter->ixgbe_dbg_adapter,
19835dc61ebSGreg Kroah-Hartman adapter, &ixgbe_dbg_reg_ops_fops);
19935dc61ebSGreg Kroah-Hartman debugfs_create_file("netdev_ops", 0600, adapter->ixgbe_dbg_adapter,
20035dc61ebSGreg Kroah-Hartman adapter, &ixgbe_dbg_netdev_ops_fops);
201826ff0deSCatherine Sullivan }
20200949167SCatherine Sullivan
20300949167SCatherine Sullivan /**
20400949167SCatherine Sullivan * ixgbe_dbg_adapter_exit - clear out the adapter's debugfs entries
2055ba643c6STony Nguyen * @adapter: the adapter that is exiting
20600949167SCatherine Sullivan **/
ixgbe_dbg_adapter_exit(struct ixgbe_adapter * adapter)20700949167SCatherine Sullivan void ixgbe_dbg_adapter_exit(struct ixgbe_adapter *adapter)
20800949167SCatherine Sullivan {
20900949167SCatherine Sullivan debugfs_remove_recursive(adapter->ixgbe_dbg_adapter);
21000949167SCatherine Sullivan adapter->ixgbe_dbg_adapter = NULL;
21100949167SCatherine Sullivan }
21200949167SCatherine Sullivan
21300949167SCatherine Sullivan /**
21400949167SCatherine Sullivan * ixgbe_dbg_init - start up debugfs for the driver
21500949167SCatherine Sullivan **/
ixgbe_dbg_init(void)21600949167SCatherine Sullivan void ixgbe_dbg_init(void)
21700949167SCatherine Sullivan {
21800949167SCatherine Sullivan ixgbe_dbg_root = debugfs_create_dir(ixgbe_driver_name, NULL);
21900949167SCatherine Sullivan }
22000949167SCatherine Sullivan
22100949167SCatherine Sullivan /**
22200949167SCatherine Sullivan * ixgbe_dbg_exit - clean out the driver's debugfs entries
22300949167SCatherine Sullivan **/
ixgbe_dbg_exit(void)22400949167SCatherine Sullivan void ixgbe_dbg_exit(void)
22500949167SCatherine Sullivan {
22600949167SCatherine Sullivan debugfs_remove_recursive(ixgbe_dbg_root);
22700949167SCatherine Sullivan }
228