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        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}
 526