1/******************************************************************************* 2 3 Intel 10 Gigabit PCI Express Linux driver 4 Copyright(c) 1999 - 2013 Intel Corporation. 5 6 This program is free software; you can redistribute it and/or modify it 7 under the terms and conditions of the GNU General Public License, 8 version 2, as published by the Free Software Foundation. 9 10 This program is distributed in the hope it will be useful, but WITHOUT 11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 more details. 14 15 You should have received a copy of the GNU General Public License along with 16 this program; if not, write to the Free Software Foundation, Inc., 17 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 18 19 The full GNU General Public License is included in this distribution in 20 the file called "COPYING". 21 22 Contact Information: 23 Linux NICS <linux.nics@intel.com> 24 e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> 25 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 26 27*******************************************************************************/ 28#include <linux/debugfs.h> 29#include <linux/module.h> 30 31#include "ixgbe.h" 32 33static struct dentry *ixgbe_dbg_root; 34 35static char ixgbe_dbg_reg_ops_buf[256] = ""; 36 37/** 38 * ixgbe_dbg_reg_ops_read - read for reg_ops datum 39 * @filp: the opened file 40 * @buffer: where to write the data for the user to read 41 * @count: the size of the user's buffer 42 * @ppos: file position offset 43 **/ 44static ssize_t ixgbe_dbg_reg_ops_read(struct file *filp, char __user *buffer, 45 size_t count, loff_t *ppos) 46{ 47 struct ixgbe_adapter *adapter = filp->private_data; 48 char *buf; 49 int len; 50 51 /* don't allow partial reads */ 52 if (*ppos != 0) 53 return 0; 54 55 buf = kasprintf(GFP_KERNEL, "%s: %s\n", 56 adapter->netdev->name, 57 ixgbe_dbg_reg_ops_buf); 58 if (!buf) 59 return -ENOMEM; 60 61 if (count < strlen(buf)) { 62 kfree(buf); 63 return -ENOSPC; 64 } 65 66 len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf)); 67 68 kfree(buf); 69 return len; 70} 71 72/** 73 * ixgbe_dbg_reg_ops_write - write into reg_ops datum 74 * @filp: the opened file 75 * @buffer: where to find the user's data 76 * @count: the length of the user's data 77 * @ppos: file position offset 78 **/ 79static ssize_t ixgbe_dbg_reg_ops_write(struct file *filp, 80 const char __user *buffer, 81 size_t count, loff_t *ppos) 82{ 83 struct ixgbe_adapter *adapter = filp->private_data; 84 int len; 85 86 /* don't allow partial writes */ 87 if (*ppos != 0) 88 return 0; 89 if (count >= sizeof(ixgbe_dbg_reg_ops_buf)) 90 return -ENOSPC; 91 92 len = simple_write_to_buffer(ixgbe_dbg_reg_ops_buf, 93 sizeof(ixgbe_dbg_reg_ops_buf)-1, 94 ppos, 95 buffer, 96 count); 97 if (len < 0) 98 return len; 99 100 ixgbe_dbg_reg_ops_buf[len] = '\0'; 101 102 if (strncmp(ixgbe_dbg_reg_ops_buf, "write", 5) == 0) { 103 u32 reg, value; 104 int cnt; 105 cnt = sscanf(&ixgbe_dbg_reg_ops_buf[5], "%x %x", ®, &value); 106 if (cnt == 2) { 107 IXGBE_WRITE_REG(&adapter->hw, reg, value); 108 value = IXGBE_READ_REG(&adapter->hw, reg); 109 e_dev_info("write: 0x%08x = 0x%08x\n", reg, value); 110 } else { 111 e_dev_info("write <reg> <value>\n"); 112 } 113 } else if (strncmp(ixgbe_dbg_reg_ops_buf, "read", 4) == 0) { 114 u32 reg, value; 115 int cnt; 116 cnt = sscanf(&ixgbe_dbg_reg_ops_buf[4], "%x", ®); 117 if (cnt == 1) { 118 value = IXGBE_READ_REG(&adapter->hw, reg); 119 e_dev_info("read 0x%08x = 0x%08x\n", reg, value); 120 } else { 121 e_dev_info("read <reg>\n"); 122 } 123 } else { 124 e_dev_info("Unknown command %s\n", ixgbe_dbg_reg_ops_buf); 125 e_dev_info("Available commands:\n"); 126 e_dev_info(" read <reg>\n"); 127 e_dev_info(" write <reg> <value>\n"); 128 } 129 return count; 130} 131 132static const struct file_operations ixgbe_dbg_reg_ops_fops = { 133 .owner = THIS_MODULE, 134 .open = simple_open, 135 .read = ixgbe_dbg_reg_ops_read, 136 .write = ixgbe_dbg_reg_ops_write, 137}; 138 139static char ixgbe_dbg_netdev_ops_buf[256] = ""; 140 141/** 142 * ixgbe_dbg_netdev_ops_read - read for netdev_ops datum 143 * @filp: the opened file 144 * @buffer: where to write the data for the user to read 145 * @count: the size of the user's buffer 146 * @ppos: file position offset 147 **/ 148static ssize_t ixgbe_dbg_netdev_ops_read(struct file *filp, 149 char __user *buffer, 150 size_t count, loff_t *ppos) 151{ 152 struct ixgbe_adapter *adapter = filp->private_data; 153 char *buf; 154 int len; 155 156 /* don't allow partial reads */ 157 if (*ppos != 0) 158 return 0; 159 160 buf = kasprintf(GFP_KERNEL, "%s: %s\n", 161 adapter->netdev->name, 162 ixgbe_dbg_netdev_ops_buf); 163 if (!buf) 164 return -ENOMEM; 165 166 if (count < strlen(buf)) { 167 kfree(buf); 168 return -ENOSPC; 169 } 170 171 len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf)); 172 173 kfree(buf); 174 return len; 175} 176 177/** 178 * ixgbe_dbg_netdev_ops_write - write into netdev_ops datum 179 * @filp: the opened file 180 * @buffer: where to find the user's data 181 * @count: the length of the user's data 182 * @ppos: file position offset 183 **/ 184static ssize_t ixgbe_dbg_netdev_ops_write(struct file *filp, 185 const char __user *buffer, 186 size_t count, loff_t *ppos) 187{ 188 struct ixgbe_adapter *adapter = filp->private_data; 189 int len; 190 191 /* don't allow partial writes */ 192 if (*ppos != 0) 193 return 0; 194 if (count >= sizeof(ixgbe_dbg_netdev_ops_buf)) 195 return -ENOSPC; 196 197 len = simple_write_to_buffer(ixgbe_dbg_netdev_ops_buf, 198 sizeof(ixgbe_dbg_netdev_ops_buf)-1, 199 ppos, 200 buffer, 201 count); 202 if (len < 0) 203 return len; 204 205 ixgbe_dbg_netdev_ops_buf[len] = '\0'; 206 207 if (strncmp(ixgbe_dbg_netdev_ops_buf, "tx_timeout", 10) == 0) { 208 adapter->netdev->netdev_ops->ndo_tx_timeout(adapter->netdev); 209 e_dev_info("tx_timeout called\n"); 210 } else { 211 e_dev_info("Unknown command: %s\n", ixgbe_dbg_netdev_ops_buf); 212 e_dev_info("Available commands:\n"); 213 e_dev_info(" tx_timeout\n"); 214 } 215 return count; 216} 217 218static const struct file_operations ixgbe_dbg_netdev_ops_fops = { 219 .owner = THIS_MODULE, 220 .open = simple_open, 221 .read = ixgbe_dbg_netdev_ops_read, 222 .write = ixgbe_dbg_netdev_ops_write, 223}; 224 225/** 226 * ixgbe_dbg_adapter_init - setup the debugfs directory for the adapter 227 * @adapter: the adapter that is starting up 228 **/ 229void ixgbe_dbg_adapter_init(struct ixgbe_adapter *adapter) 230{ 231 const char *name = pci_name(adapter->pdev); 232 struct dentry *pfile; 233 adapter->ixgbe_dbg_adapter = debugfs_create_dir(name, ixgbe_dbg_root); 234 if (adapter->ixgbe_dbg_adapter) { 235 pfile = debugfs_create_file("reg_ops", 0600, 236 adapter->ixgbe_dbg_adapter, adapter, 237 &ixgbe_dbg_reg_ops_fops); 238 if (!pfile) 239 e_dev_err("debugfs reg_ops for %s failed\n", name); 240 pfile = debugfs_create_file("netdev_ops", 0600, 241 adapter->ixgbe_dbg_adapter, adapter, 242 &ixgbe_dbg_netdev_ops_fops); 243 if (!pfile) 244 e_dev_err("debugfs netdev_ops for %s failed\n", name); 245 } else { 246 e_dev_err("debugfs entry for %s failed\n", name); 247 } 248} 249 250/** 251 * ixgbe_dbg_adapter_exit - clear out the adapter's debugfs entries 252 * @pf: the pf that is stopping 253 **/ 254void ixgbe_dbg_adapter_exit(struct ixgbe_adapter *adapter) 255{ 256 debugfs_remove_recursive(adapter->ixgbe_dbg_adapter); 257 adapter->ixgbe_dbg_adapter = NULL; 258} 259 260/** 261 * ixgbe_dbg_init - start up debugfs for the driver 262 **/ 263void ixgbe_dbg_init(void) 264{ 265 ixgbe_dbg_root = debugfs_create_dir(ixgbe_driver_name, NULL); 266 if (ixgbe_dbg_root == NULL) 267 pr_err("init of debugfs failed\n"); 268} 269 270/** 271 * ixgbe_dbg_exit - clean out the driver's debugfs entries 272 **/ 273void ixgbe_dbg_exit(void) 274{ 275 debugfs_remove_recursive(ixgbe_dbg_root); 276} 277