linux/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
<<
>>
Prefs
   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        struct dentry *pfile;
 442        char *buf;
 443
 444        /* Set defaults */
 445        pdata->debugfs_xgmac_reg = 0;
 446        pdata->debugfs_xpcs_mmd = 1;
 447        pdata->debugfs_xpcs_reg = 0;
 448
 449        buf = kasprintf(GFP_KERNEL, "amd-xgbe-%s", pdata->netdev->name);
 450        if (!buf)
 451                return;
 452
 453        pdata->xgbe_debugfs = debugfs_create_dir(buf, NULL);
 454        if (!pdata->xgbe_debugfs) {
 455                netdev_err(pdata->netdev, "debugfs_create_dir failed\n");
 456                kfree(buf);
 457                return;
 458        }
 459
 460        pfile = debugfs_create_file("xgmac_register", 0600,
 461                                    pdata->xgbe_debugfs, pdata,
 462                                    &xgmac_reg_addr_fops);
 463        if (!pfile)
 464                netdev_err(pdata->netdev, "debugfs_create_file failed\n");
 465
 466        pfile = debugfs_create_file("xgmac_register_value", 0600,
 467                                    pdata->xgbe_debugfs, pdata,
 468                                    &xgmac_reg_value_fops);
 469        if (!pfile)
 470                netdev_err(pdata->netdev, "debugfs_create_file failed\n");
 471
 472        pfile = debugfs_create_file("xpcs_mmd", 0600,
 473                                    pdata->xgbe_debugfs, pdata,
 474                                    &xpcs_mmd_fops);
 475        if (!pfile)
 476                netdev_err(pdata->netdev, "debugfs_create_file failed\n");
 477
 478        pfile = debugfs_create_file("xpcs_register", 0600,
 479                                    pdata->xgbe_debugfs, pdata,
 480                                    &xpcs_reg_addr_fops);
 481        if (!pfile)
 482                netdev_err(pdata->netdev, "debugfs_create_file failed\n");
 483
 484        pfile = debugfs_create_file("xpcs_register_value", 0600,
 485                                    pdata->xgbe_debugfs, pdata,
 486                                    &xpcs_reg_value_fops);
 487        if (!pfile)
 488                netdev_err(pdata->netdev, "debugfs_create_file failed\n");
 489
 490        if (pdata->xprop_regs) {
 491                pfile = debugfs_create_file("xprop_register", 0600,
 492                                            pdata->xgbe_debugfs, pdata,
 493                                            &xprop_reg_addr_fops);
 494                if (!pfile)
 495                        netdev_err(pdata->netdev,
 496                                   "debugfs_create_file failed\n");
 497
 498                pfile = debugfs_create_file("xprop_register_value", 0600,
 499                                            pdata->xgbe_debugfs, pdata,
 500                                            &xprop_reg_value_fops);
 501                if (!pfile)
 502                        netdev_err(pdata->netdev,
 503                                   "debugfs_create_file failed\n");
 504        }
 505
 506        if (pdata->xi2c_regs) {
 507                pfile = debugfs_create_file("xi2c_register", 0600,
 508                                            pdata->xgbe_debugfs, pdata,
 509                                            &xi2c_reg_addr_fops);
 510                if (!pfile)
 511                        netdev_err(pdata->netdev,
 512                                   "debugfs_create_file failed\n");
 513
 514                pfile = debugfs_create_file("xi2c_register_value", 0600,
 515                                            pdata->xgbe_debugfs, pdata,
 516                                            &xi2c_reg_value_fops);
 517                if (!pfile)
 518                        netdev_err(pdata->netdev,
 519                                   "debugfs_create_file failed\n");
 520        }
 521
 522        if (pdata->vdata->an_cdr_workaround) {
 523                pfile = debugfs_create_bool("an_cdr_workaround", 0600,
 524                                            pdata->xgbe_debugfs,
 525                                            &pdata->debugfs_an_cdr_workaround);
 526                if (!pfile)
 527                        netdev_err(pdata->netdev,
 528                                   "debugfs_create_bool failed\n");
 529
 530                pfile = debugfs_create_bool("an_cdr_track_early", 0600,
 531                                            pdata->xgbe_debugfs,
 532                                            &pdata->debugfs_an_cdr_track_early);
 533                if (!pfile)
 534                        netdev_err(pdata->netdev,
 535                                   "debugfs_create_bool failed\n");
 536        }
 537
 538        kfree(buf);
 539}
 540
 541void xgbe_debugfs_exit(struct xgbe_prv_data *pdata)
 542{
 543        debugfs_remove_recursive(pdata->xgbe_debugfs);
 544        pdata->xgbe_debugfs = NULL;
 545}
 546
 547void xgbe_debugfs_rename(struct xgbe_prv_data *pdata)
 548{
 549        struct dentry *pfile;
 550        char *buf;
 551
 552        if (!pdata->xgbe_debugfs)
 553                return;
 554
 555        buf = kasprintf(GFP_KERNEL, "amd-xgbe-%s", pdata->netdev->name);
 556        if (!buf)
 557                return;
 558
 559        if (!strcmp(pdata->xgbe_debugfs->d_name.name, buf))
 560                goto out;
 561
 562        pfile = debugfs_rename(pdata->xgbe_debugfs->d_parent,
 563                               pdata->xgbe_debugfs,
 564                               pdata->xgbe_debugfs->d_parent, buf);
 565        if (!pfile)
 566                netdev_err(pdata->netdev, "debugfs_rename failed\n");
 567
 568out:
 569        kfree(buf);
 570}
 571