xgbe-debugfs.c (16365B)
1/* 2 * AMD 10Gb Ethernet driver 3 * 4 * This file is available to you under your choice of the following two 5 * licenses: 6 * 7 * License 1: GPLv2 8 * 9 * Copyright (c) 2014 Advanced Micro Devices, Inc. 10 * 11 * This file is free software; you may copy, redistribute and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation, either version 2 of the License, or (at 14 * your option) any later version. 15 * 16 * This file is distributed in the hope that it will be useful, but 17 * WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 * General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program. If not, see <http://www.gnu.org/licenses/>. 23 * 24 * This file incorporates work covered by the following copyright and 25 * permission notice: 26 * The Synopsys DWC ETHER XGMAC Software Driver and documentation 27 * (hereinafter "Software") is an unsupported proprietary work of Synopsys, 28 * Inc. unless otherwise expressly agreed to in writing between Synopsys 29 * and you. 30 * 31 * The Software IS NOT an item of Licensed Software or Licensed Product 32 * under any End User Software License Agreement or Agreement for Licensed 33 * Product with Synopsys or any supplement thereto. Permission is hereby 34 * granted, free of charge, to any person obtaining a copy of this software 35 * annotated with this license and the Software, to deal in the Software 36 * without restriction, including without limitation the rights to use, 37 * copy, modify, merge, publish, distribute, sublicense, and/or sell copies 38 * of the Software, and to permit persons to whom the Software is furnished 39 * to do so, subject to the following conditions: 40 * 41 * The above copyright notice and this permission notice shall be included 42 * in all copies or substantial portions of the Software. 43 * 44 * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" 45 * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 46 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 47 * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 48 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 49 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 50 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 51 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 52 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 53 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 54 * THE POSSIBILITY OF SUCH DAMAGE. 55 * 56 * 57 * License 2: Modified BSD 58 * 59 * Copyright (c) 2014 Advanced Micro Devices, Inc. 60 * All rights reserved. 61 * 62 * Redistribution and use in source and binary forms, with or without 63 * modification, are permitted provided that the following conditions are met: 64 * * Redistributions of source code must retain the above copyright 65 * notice, this list of conditions and the following disclaimer. 66 * * Redistributions in binary form must reproduce the above copyright 67 * notice, this list of conditions and the following disclaimer in the 68 * documentation and/or other materials provided with the distribution. 69 * * Neither the name of Advanced Micro Devices, Inc. nor the 70 * names of its contributors may be used to endorse or promote products 71 * derived from this software without specific prior written permission. 72 * 73 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 74 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 75 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 76 * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY 77 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 78 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 79 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 80 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 81 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 82 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 83 * 84 * This file incorporates work covered by the following copyright and 85 * permission notice: 86 * The Synopsys DWC ETHER XGMAC Software Driver and documentation 87 * (hereinafter "Software") is an unsupported proprietary work of Synopsys, 88 * Inc. unless otherwise expressly agreed to in writing between Synopsys 89 * and you. 90 * 91 * The Software IS NOT an item of Licensed Software or Licensed Product 92 * under any End User Software License Agreement or Agreement for Licensed 93 * Product with Synopsys or any supplement thereto. Permission is hereby 94 * granted, free of charge, to any person obtaining a copy of this software 95 * annotated with this license and the Software, to deal in the Software 96 * without restriction, including without limitation the rights to use, 97 * copy, modify, merge, publish, distribute, sublicense, and/or sell copies 98 * of the Software, and to permit persons to whom the Software is furnished 99 * to do so, subject to the following conditions: 100 * 101 * The above copyright notice and this permission notice shall be included 102 * in all copies or substantial portions of the Software. 103 * 104 * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" 105 * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 106 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 107 * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 108 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 109 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 110 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 111 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 112 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 113 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 114 * THE POSSIBILITY OF SUCH DAMAGE. 115 */ 116 117#include <linux/debugfs.h> 118#include <linux/module.h> 119#include <linux/slab.h> 120 121#include "xgbe.h" 122#include "xgbe-common.h" 123 124static ssize_t xgbe_common_read(char __user *buffer, size_t count, 125 loff_t *ppos, unsigned int value) 126{ 127 char *buf; 128 ssize_t len; 129 130 if (*ppos != 0) 131 return 0; 132 133 buf = kasprintf(GFP_KERNEL, "0x%08x\n", value); 134 if (!buf) 135 return -ENOMEM; 136 137 if (count < strlen(buf)) { 138 kfree(buf); 139 return -ENOSPC; 140 } 141 142 len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf)); 143 kfree(buf); 144 145 return len; 146} 147 148static ssize_t xgbe_common_write(const char __user *buffer, size_t count, 149 loff_t *ppos, unsigned int *value) 150{ 151 char workarea[32]; 152 ssize_t len; 153 int ret; 154 155 if (*ppos != 0) 156 return -EINVAL; 157 158 if (count >= sizeof(workarea)) 159 return -ENOSPC; 160 161 len = simple_write_to_buffer(workarea, sizeof(workarea) - 1, ppos, 162 buffer, count); 163 if (len < 0) 164 return len; 165 166 workarea[len] = '\0'; 167 ret = kstrtouint(workarea, 16, value); 168 if (ret) 169 return -EIO; 170 171 return len; 172} 173 174static ssize_t xgmac_reg_addr_read(struct file *filp, char __user *buffer, 175 size_t count, loff_t *ppos) 176{ 177 struct xgbe_prv_data *pdata = filp->private_data; 178 179 return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xgmac_reg); 180} 181 182static ssize_t xgmac_reg_addr_write(struct file *filp, 183 const char __user *buffer, 184 size_t count, loff_t *ppos) 185{ 186 struct xgbe_prv_data *pdata = filp->private_data; 187 188 return xgbe_common_write(buffer, count, ppos, 189 &pdata->debugfs_xgmac_reg); 190} 191 192static ssize_t xgmac_reg_value_read(struct file *filp, char __user *buffer, 193 size_t count, loff_t *ppos) 194{ 195 struct xgbe_prv_data *pdata = filp->private_data; 196 unsigned int value; 197 198 value = XGMAC_IOREAD(pdata, pdata->debugfs_xgmac_reg); 199 200 return xgbe_common_read(buffer, count, ppos, value); 201} 202 203static ssize_t xgmac_reg_value_write(struct file *filp, 204 const char __user *buffer, 205 size_t count, loff_t *ppos) 206{ 207 struct xgbe_prv_data *pdata = filp->private_data; 208 unsigned int value; 209 ssize_t len; 210 211 len = xgbe_common_write(buffer, count, ppos, &value); 212 if (len < 0) 213 return len; 214 215 XGMAC_IOWRITE(pdata, pdata->debugfs_xgmac_reg, value); 216 217 return len; 218} 219 220static const struct file_operations xgmac_reg_addr_fops = { 221 .owner = THIS_MODULE, 222 .open = simple_open, 223 .read = xgmac_reg_addr_read, 224 .write = xgmac_reg_addr_write, 225}; 226 227static const struct file_operations xgmac_reg_value_fops = { 228 .owner = THIS_MODULE, 229 .open = simple_open, 230 .read = xgmac_reg_value_read, 231 .write = xgmac_reg_value_write, 232}; 233 234static ssize_t xpcs_mmd_read(struct file *filp, char __user *buffer, 235 size_t count, loff_t *ppos) 236{ 237 struct xgbe_prv_data *pdata = filp->private_data; 238 239 return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xpcs_mmd); 240} 241 242static ssize_t xpcs_mmd_write(struct file *filp, const char __user *buffer, 243 size_t count, loff_t *ppos) 244{ 245 struct xgbe_prv_data *pdata = filp->private_data; 246 247 return xgbe_common_write(buffer, count, ppos, 248 &pdata->debugfs_xpcs_mmd); 249} 250 251static ssize_t xpcs_reg_addr_read(struct file *filp, char __user *buffer, 252 size_t count, loff_t *ppos) 253{ 254 struct xgbe_prv_data *pdata = filp->private_data; 255 256 return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xpcs_reg); 257} 258 259static ssize_t xpcs_reg_addr_write(struct file *filp, const char __user *buffer, 260 size_t count, loff_t *ppos) 261{ 262 struct xgbe_prv_data *pdata = filp->private_data; 263 264 return xgbe_common_write(buffer, count, ppos, 265 &pdata->debugfs_xpcs_reg); 266} 267 268static ssize_t xpcs_reg_value_read(struct file *filp, char __user *buffer, 269 size_t count, loff_t *ppos) 270{ 271 struct xgbe_prv_data *pdata = filp->private_data; 272 unsigned int value; 273 274 value = XMDIO_READ(pdata, pdata->debugfs_xpcs_mmd, 275 pdata->debugfs_xpcs_reg); 276 277 return xgbe_common_read(buffer, count, ppos, value); 278} 279 280static ssize_t xpcs_reg_value_write(struct file *filp, 281 const char __user *buffer, 282 size_t count, loff_t *ppos) 283{ 284 struct xgbe_prv_data *pdata = filp->private_data; 285 unsigned int value; 286 ssize_t len; 287 288 len = xgbe_common_write(buffer, count, ppos, &value); 289 if (len < 0) 290 return len; 291 292 XMDIO_WRITE(pdata, pdata->debugfs_xpcs_mmd, pdata->debugfs_xpcs_reg, 293 value); 294 295 return len; 296} 297 298static const struct file_operations xpcs_mmd_fops = { 299 .owner = THIS_MODULE, 300 .open = simple_open, 301 .read = xpcs_mmd_read, 302 .write = xpcs_mmd_write, 303}; 304 305static const struct file_operations xpcs_reg_addr_fops = { 306 .owner = THIS_MODULE, 307 .open = simple_open, 308 .read = xpcs_reg_addr_read, 309 .write = xpcs_reg_addr_write, 310}; 311 312static const struct file_operations xpcs_reg_value_fops = { 313 .owner = THIS_MODULE, 314 .open = simple_open, 315 .read = xpcs_reg_value_read, 316 .write = xpcs_reg_value_write, 317}; 318 319static ssize_t xprop_reg_addr_read(struct file *filp, char __user *buffer, 320 size_t count, loff_t *ppos) 321{ 322 struct xgbe_prv_data *pdata = filp->private_data; 323 324 return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xprop_reg); 325} 326 327static ssize_t xprop_reg_addr_write(struct file *filp, 328 const char __user *buffer, 329 size_t count, loff_t *ppos) 330{ 331 struct xgbe_prv_data *pdata = filp->private_data; 332 333 return xgbe_common_write(buffer, count, ppos, 334 &pdata->debugfs_xprop_reg); 335} 336 337static ssize_t xprop_reg_value_read(struct file *filp, char __user *buffer, 338 size_t count, loff_t *ppos) 339{ 340 struct xgbe_prv_data *pdata = filp->private_data; 341 unsigned int value; 342 343 value = XP_IOREAD(pdata, pdata->debugfs_xprop_reg); 344 345 return xgbe_common_read(buffer, count, ppos, value); 346} 347 348static ssize_t xprop_reg_value_write(struct file *filp, 349 const char __user *buffer, 350 size_t count, loff_t *ppos) 351{ 352 struct xgbe_prv_data *pdata = filp->private_data; 353 unsigned int value; 354 ssize_t len; 355 356 len = xgbe_common_write(buffer, count, ppos, &value); 357 if (len < 0) 358 return len; 359 360 XP_IOWRITE(pdata, pdata->debugfs_xprop_reg, value); 361 362 return len; 363} 364 365static const struct file_operations xprop_reg_addr_fops = { 366 .owner = THIS_MODULE, 367 .open = simple_open, 368 .read = xprop_reg_addr_read, 369 .write = xprop_reg_addr_write, 370}; 371 372static const struct file_operations xprop_reg_value_fops = { 373 .owner = THIS_MODULE, 374 .open = simple_open, 375 .read = xprop_reg_value_read, 376 .write = xprop_reg_value_write, 377}; 378 379static ssize_t xi2c_reg_addr_read(struct file *filp, char __user *buffer, 380 size_t count, loff_t *ppos) 381{ 382 struct xgbe_prv_data *pdata = filp->private_data; 383 384 return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xi2c_reg); 385} 386 387static ssize_t xi2c_reg_addr_write(struct file *filp, 388 const char __user *buffer, 389 size_t count, loff_t *ppos) 390{ 391 struct xgbe_prv_data *pdata = filp->private_data; 392 393 return xgbe_common_write(buffer, count, ppos, 394 &pdata->debugfs_xi2c_reg); 395} 396 397static ssize_t xi2c_reg_value_read(struct file *filp, char __user *buffer, 398 size_t count, loff_t *ppos) 399{ 400 struct xgbe_prv_data *pdata = filp->private_data; 401 unsigned int value; 402 403 value = XI2C_IOREAD(pdata, pdata->debugfs_xi2c_reg); 404 405 return xgbe_common_read(buffer, count, ppos, value); 406} 407 408static ssize_t xi2c_reg_value_write(struct file *filp, 409 const char __user *buffer, 410 size_t count, loff_t *ppos) 411{ 412 struct xgbe_prv_data *pdata = filp->private_data; 413 unsigned int value; 414 ssize_t len; 415 416 len = xgbe_common_write(buffer, count, ppos, &value); 417 if (len < 0) 418 return len; 419 420 XI2C_IOWRITE(pdata, pdata->debugfs_xi2c_reg, value); 421 422 return len; 423} 424 425static const struct file_operations xi2c_reg_addr_fops = { 426 .owner = THIS_MODULE, 427 .open = simple_open, 428 .read = xi2c_reg_addr_read, 429 .write = xi2c_reg_addr_write, 430}; 431 432static const struct file_operations xi2c_reg_value_fops = { 433 .owner = THIS_MODULE, 434 .open = simple_open, 435 .read = xi2c_reg_value_read, 436 .write = xi2c_reg_value_write, 437}; 438 439void xgbe_debugfs_init(struct xgbe_prv_data *pdata) 440{ 441 char *buf; 442 443 /* Set defaults */ 444 pdata->debugfs_xgmac_reg = 0; 445 pdata->debugfs_xpcs_mmd = 1; 446 pdata->debugfs_xpcs_reg = 0; 447 448 buf = kasprintf(GFP_KERNEL, "amd-xgbe-%s", pdata->netdev->name); 449 if (!buf) 450 return; 451 452 pdata->xgbe_debugfs = debugfs_create_dir(buf, NULL); 453 454 debugfs_create_file("xgmac_register", 0600, pdata->xgbe_debugfs, pdata, 455 &xgmac_reg_addr_fops); 456 457 debugfs_create_file("xgmac_register_value", 0600, pdata->xgbe_debugfs, 458 pdata, &xgmac_reg_value_fops); 459 460 debugfs_create_file("xpcs_mmd", 0600, pdata->xgbe_debugfs, pdata, 461 &xpcs_mmd_fops); 462 463 debugfs_create_file("xpcs_register", 0600, pdata->xgbe_debugfs, pdata, 464 &xpcs_reg_addr_fops); 465 466 debugfs_create_file("xpcs_register_value", 0600, pdata->xgbe_debugfs, 467 pdata, &xpcs_reg_value_fops); 468 469 if (pdata->xprop_regs) { 470 debugfs_create_file("xprop_register", 0600, pdata->xgbe_debugfs, 471 pdata, &xprop_reg_addr_fops); 472 473 debugfs_create_file("xprop_register_value", 0600, 474 pdata->xgbe_debugfs, pdata, 475 &xprop_reg_value_fops); 476 } 477 478 if (pdata->xi2c_regs) { 479 debugfs_create_file("xi2c_register", 0600, pdata->xgbe_debugfs, 480 pdata, &xi2c_reg_addr_fops); 481 482 debugfs_create_file("xi2c_register_value", 0600, 483 pdata->xgbe_debugfs, pdata, 484 &xi2c_reg_value_fops); 485 } 486 487 if (pdata->vdata->an_cdr_workaround) { 488 debugfs_create_bool("an_cdr_workaround", 0600, 489 pdata->xgbe_debugfs, 490 &pdata->debugfs_an_cdr_workaround); 491 492 debugfs_create_bool("an_cdr_track_early", 0600, 493 pdata->xgbe_debugfs, 494 &pdata->debugfs_an_cdr_track_early); 495 } 496 497 kfree(buf); 498} 499 500void xgbe_debugfs_exit(struct xgbe_prv_data *pdata) 501{ 502 debugfs_remove_recursive(pdata->xgbe_debugfs); 503 pdata->xgbe_debugfs = NULL; 504} 505 506void xgbe_debugfs_rename(struct xgbe_prv_data *pdata) 507{ 508 char *buf; 509 510 if (!pdata->xgbe_debugfs) 511 return; 512 513 buf = kasprintf(GFP_KERNEL, "amd-xgbe-%s", pdata->netdev->name); 514 if (!buf) 515 return; 516 517 if (!strcmp(pdata->xgbe_debugfs->d_name.name, buf)) 518 goto out; 519 520 debugfs_rename(pdata->xgbe_debugfs->d_parent, pdata->xgbe_debugfs, 521 pdata->xgbe_debugfs->d_parent, buf); 522 523out: 524 kfree(buf); 525}