linux/drivers/net/dsa/sja1105/sja1105_ethtool.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
   3 */
   4#include "sja1105.h"
   5
   6enum sja1105_counter_index {
   7        __SJA1105_COUNTER_UNUSED,
   8        /* MAC */
   9        N_RUNT,
  10        N_SOFERR,
  11        N_ALIGNERR,
  12        N_MIIERR,
  13        TYPEERR,
  14        SIZEERR,
  15        TCTIMEOUT,
  16        PRIORERR,
  17        NOMASTER,
  18        MEMOV,
  19        MEMERR,
  20        INVTYP,
  21        INTCYOV,
  22        DOMERR,
  23        PCFBAGDROP,
  24        SPCPRIOR,
  25        AGEPRIOR,
  26        PORTDROP,
  27        LENDROP,
  28        BAGDROP,
  29        POLICEERR,
  30        DRPNONA664ERR,
  31        SPCERR,
  32        AGEDRP,
  33        /* HL1 */
  34        N_N664ERR,
  35        N_VLANERR,
  36        N_UNRELEASED,
  37        N_SIZEERR,
  38        N_CRCERR,
  39        N_VLNOTFOUND,
  40        N_CTPOLERR,
  41        N_POLERR,
  42        N_RXFRM,
  43        N_RXBYTE,
  44        N_TXFRM,
  45        N_TXBYTE,
  46        /* HL2 */
  47        N_QFULL,
  48        N_PART_DROP,
  49        N_EGR_DISABLED,
  50        N_NOT_REACH,
  51        __MAX_SJA1105ET_PORT_COUNTER,
  52        /* P/Q/R/S only */
  53        /* ETHER */
  54        N_DROPS_NOLEARN = __MAX_SJA1105ET_PORT_COUNTER,
  55        N_DROPS_NOROUTE,
  56        N_DROPS_ILL_DTAG,
  57        N_DROPS_DTAG,
  58        N_DROPS_SOTAG,
  59        N_DROPS_SITAG,
  60        N_DROPS_UTAG,
  61        N_TX_BYTES_1024_2047,
  62        N_TX_BYTES_512_1023,
  63        N_TX_BYTES_256_511,
  64        N_TX_BYTES_128_255,
  65        N_TX_BYTES_65_127,
  66        N_TX_BYTES_64,
  67        N_TX_MCAST,
  68        N_TX_BCAST,
  69        N_RX_BYTES_1024_2047,
  70        N_RX_BYTES_512_1023,
  71        N_RX_BYTES_256_511,
  72        N_RX_BYTES_128_255,
  73        N_RX_BYTES_65_127,
  74        N_RX_BYTES_64,
  75        N_RX_MCAST,
  76        N_RX_BCAST,
  77        __MAX_SJA1105PQRS_PORT_COUNTER,
  78};
  79
  80struct sja1105_port_counter {
  81        enum sja1105_stats_area area;
  82        const char name[ETH_GSTRING_LEN];
  83        int offset;
  84        int start;
  85        int end;
  86        bool is_64bit;
  87};
  88
  89static const struct sja1105_port_counter sja1105_port_counters[] = {
  90        /* MAC-Level Diagnostic Counters */
  91        [N_RUNT] = {
  92                .area = MAC,
  93                .name = "n_runt",
  94                .offset = 0,
  95                .start = 31,
  96                .end = 24,
  97        },
  98        [N_SOFERR] = {
  99                .area = MAC,
 100                .name = "n_soferr",
 101                .offset = 0x0,
 102                .start = 23,
 103                .end = 16,
 104        },
 105        [N_ALIGNERR] = {
 106                .area = MAC,
 107                .name = "n_alignerr",
 108                .offset = 0x0,
 109                .start = 15,
 110                .end = 8,
 111        },
 112        [N_MIIERR] = {
 113                .area = MAC,
 114                .name = "n_miierr",
 115                .offset = 0x0,
 116                .start = 7,
 117                .end = 0,
 118        },
 119        /* MAC-Level Diagnostic Flags */
 120        [TYPEERR] = {
 121                .area = MAC,
 122                .name = "typeerr",
 123                .offset = 0x1,
 124                .start = 27,
 125                .end = 27,
 126        },
 127        [SIZEERR] = {
 128                .area = MAC,
 129                .name = "sizeerr",
 130                .offset = 0x1,
 131                .start = 26,
 132                .end = 26,
 133        },
 134        [TCTIMEOUT] = {
 135                .area = MAC,
 136                .name = "tctimeout",
 137                .offset = 0x1,
 138                .start = 25,
 139                .end = 25,
 140        },
 141        [PRIORERR] = {
 142                .area = MAC,
 143                .name = "priorerr",
 144                .offset = 0x1,
 145                .start = 24,
 146                .end = 24,
 147        },
 148        [NOMASTER] = {
 149                .area = MAC,
 150                .name = "nomaster",
 151                .offset = 0x1,
 152                .start = 23,
 153                .end = 23,
 154        },
 155        [MEMOV] = {
 156                .area = MAC,
 157                .name = "memov",
 158                .offset = 0x1,
 159                .start = 22,
 160                .end = 22,
 161        },
 162        [MEMERR] = {
 163                .area = MAC,
 164                .name = "memerr",
 165                .offset = 0x1,
 166                .start = 21,
 167                .end = 21,
 168        },
 169        [INVTYP] = {
 170                .area = MAC,
 171                .name = "invtyp",
 172                .offset = 0x1,
 173                .start = 19,
 174                .end = 19,
 175        },
 176        [INTCYOV] = {
 177                .area = MAC,
 178                .name = "intcyov",
 179                .offset = 0x1,
 180                .start = 18,
 181                .end = 18,
 182        },
 183        [DOMERR] = {
 184                .area = MAC,
 185                .name = "domerr",
 186                .offset = 0x1,
 187                .start = 17,
 188                .end = 17,
 189        },
 190        [PCFBAGDROP] = {
 191                .area = MAC,
 192                .name = "pcfbagdrop",
 193                .offset = 0x1,
 194                .start = 16,
 195                .end = 16,
 196        },
 197        [SPCPRIOR] = {
 198                .area = MAC,
 199                .name = "spcprior",
 200                .offset = 0x1,
 201                .start = 15,
 202                .end = 12,
 203        },
 204        [AGEPRIOR] = {
 205                .area = MAC,
 206                .name = "ageprior",
 207                .offset = 0x1,
 208                .start = 11,
 209                .end = 8,
 210        },
 211        [PORTDROP] = {
 212                .area = MAC,
 213                .name = "portdrop",
 214                .offset = 0x1,
 215                .start = 6,
 216                .end = 6,
 217        },
 218        [LENDROP] = {
 219                .area = MAC,
 220                .name = "lendrop",
 221                .offset = 0x1,
 222                .start = 5,
 223                .end = 5,
 224        },
 225        [BAGDROP] = {
 226                .area = MAC,
 227                .name = "bagdrop",
 228                .offset = 0x1,
 229                .start = 4,
 230                .end = 4,
 231        },
 232        [POLICEERR] = {
 233                .area = MAC,
 234                .name = "policeerr",
 235                .offset = 0x1,
 236                .start = 3,
 237                .end = 3,
 238        },
 239        [DRPNONA664ERR] = {
 240                .area = MAC,
 241                .name = "drpnona664err",
 242                .offset = 0x1,
 243                .start = 2,
 244                .end = 2,
 245        },
 246        [SPCERR] = {
 247                .area = MAC,
 248                .name = "spcerr",
 249                .offset = 0x1,
 250                .start = 1,
 251                .end = 1,
 252        },
 253        [AGEDRP] = {
 254                .area = MAC,
 255                .name = "agedrp",
 256                .offset = 0x1,
 257                .start = 0,
 258                .end = 0,
 259        },
 260        /* High-Level Diagnostic Counters */
 261        [N_N664ERR] = {
 262                .area = HL1,
 263                .name = "n_n664err",
 264                .offset = 0xF,
 265                .start = 31,
 266                .end = 0,
 267        },
 268        [N_VLANERR] = {
 269                .area = HL1,
 270                .name = "n_vlanerr",
 271                .offset = 0xE,
 272                .start = 31,
 273                .end = 0,
 274        },
 275        [N_UNRELEASED] = {
 276                .area = HL1,
 277                .name = "n_unreleased",
 278                .offset = 0xD,
 279                .start = 31,
 280                .end = 0,
 281        },
 282        [N_SIZEERR] = {
 283                .area = HL1,
 284                .name = "n_sizeerr",
 285                .offset = 0xC,
 286                .start = 31,
 287                .end = 0,
 288        },
 289        [N_CRCERR] = {
 290                .area = HL1,
 291                .name = "n_crcerr",
 292                .offset = 0xB,
 293                .start = 31,
 294                .end = 0,
 295        },
 296        [N_VLNOTFOUND] = {
 297                .area = HL1,
 298                .name = "n_vlnotfound",
 299                .offset = 0xA,
 300                .start = 31,
 301                .end = 0,
 302        },
 303        [N_CTPOLERR] = {
 304                .area = HL1,
 305                .name = "n_ctpolerr",
 306                .offset = 0x9,
 307                .start = 31,
 308                .end = 0,
 309        },
 310        [N_POLERR] = {
 311                .area = HL1,
 312                .name = "n_polerr",
 313                .offset = 0x8,
 314                .start = 31,
 315                .end = 0,
 316        },
 317        [N_RXFRM] = {
 318                .area = HL1,
 319                .name = "n_rxfrm",
 320                .offset = 0x6,
 321                .start = 31,
 322                .end = 0,
 323                .is_64bit = true,
 324        },
 325        [N_RXBYTE] = {
 326                .area = HL1,
 327                .name = "n_rxbyte",
 328                .offset = 0x4,
 329                .start = 31,
 330                .end = 0,
 331                .is_64bit = true,
 332        },
 333        [N_TXFRM] = {
 334                .area = HL1,
 335                .name = "n_txfrm",
 336                .offset = 0x2,
 337                .start = 31,
 338                .end = 0,
 339                .is_64bit = true,
 340        },
 341        [N_TXBYTE] = {
 342                .area = HL1,
 343                .name = "n_txbyte",
 344                .offset = 0x0,
 345                .start = 31,
 346                .end = 0,
 347                .is_64bit = true,
 348        },
 349        [N_QFULL] = {
 350                .area = HL2,
 351                .name = "n_qfull",
 352                .offset = 0x3,
 353                .start = 31,
 354                .end = 0,
 355        },
 356        [N_PART_DROP] = {
 357                .area = HL2,
 358                .name = "n_part_drop",
 359                .offset = 0x2,
 360                .start = 31,
 361                .end = 0,
 362        },
 363        [N_EGR_DISABLED] = {
 364                .area = HL2,
 365                .name = "n_egr_disabled",
 366                .offset = 0x1,
 367                .start = 31,
 368                .end = 0,
 369        },
 370        [N_NOT_REACH] = {
 371                .area = HL2,
 372                .name = "n_not_reach",
 373                .offset = 0x0,
 374                .start = 31,
 375                .end = 0,
 376        },
 377        /* Ether Stats */
 378        [N_DROPS_NOLEARN] = {
 379                .area = ETHER,
 380                .name = "n_drops_nolearn",
 381                .offset = 0x16,
 382                .start = 31,
 383                .end = 0,
 384        },
 385        [N_DROPS_NOROUTE] = {
 386                .area = ETHER,
 387                .name = "n_drops_noroute",
 388                .offset = 0x15,
 389                .start = 31,
 390                .end = 0,
 391        },
 392        [N_DROPS_ILL_DTAG] = {
 393                .area = ETHER,
 394                .name = "n_drops_ill_dtag",
 395                .offset = 0x14,
 396                .start = 31,
 397                .end = 0,
 398        },
 399        [N_DROPS_DTAG] = {
 400                .area = ETHER,
 401                .name = "n_drops_dtag",
 402                .offset = 0x13,
 403                .start = 31,
 404                .end = 0,
 405        },
 406        [N_DROPS_SOTAG] = {
 407                .area = ETHER,
 408                .name = "n_drops_sotag",
 409                .offset = 0x12,
 410                .start = 31,
 411                .end = 0,
 412        },
 413        [N_DROPS_SITAG] = {
 414                .area = ETHER,
 415                .name = "n_drops_sitag",
 416                .offset = 0x11,
 417                .start = 31,
 418                .end = 0,
 419        },
 420        [N_DROPS_UTAG] = {
 421                .area = ETHER,
 422                .name = "n_drops_utag",
 423                .offset = 0x10,
 424                .start = 31,
 425                .end = 0,
 426        },
 427        [N_TX_BYTES_1024_2047] = {
 428                .area = ETHER,
 429                .name = "n_tx_bytes_1024_2047",
 430                .offset = 0x0F,
 431                .start = 31,
 432                .end = 0,
 433        },
 434        [N_TX_BYTES_512_1023] = {
 435                .area = ETHER,
 436                .name = "n_tx_bytes_512_1023",
 437                .offset = 0x0E,
 438                .start = 31,
 439                .end = 0,
 440        },
 441        [N_TX_BYTES_256_511] = {
 442                .area = ETHER,
 443                .name = "n_tx_bytes_256_511",
 444                .offset = 0x0D,
 445                .start = 31,
 446                .end = 0,
 447        },
 448        [N_TX_BYTES_128_255] = {
 449                .area = ETHER,
 450                .name = "n_tx_bytes_128_255",
 451                .offset = 0x0C,
 452                .start = 31,
 453                .end = 0,
 454        },
 455        [N_TX_BYTES_65_127] = {
 456                .area = ETHER,
 457                .name = "n_tx_bytes_65_127",
 458                .offset = 0x0B,
 459                .start = 31,
 460                .end = 0,
 461        },
 462        [N_TX_BYTES_64] = {
 463                .area = ETHER,
 464                .name = "n_tx_bytes_64",
 465                .offset = 0x0A,
 466                .start = 31,
 467                .end = 0,
 468        },
 469        [N_TX_MCAST] = {
 470                .area = ETHER,
 471                .name = "n_tx_mcast",
 472                .offset = 0x09,
 473                .start = 31,
 474                .end = 0,
 475        },
 476        [N_TX_BCAST] = {
 477                .area = ETHER,
 478                .name = "n_tx_bcast",
 479                .offset = 0x08,
 480                .start = 31,
 481                .end = 0,
 482        },
 483        [N_RX_BYTES_1024_2047] = {
 484                .area = ETHER,
 485                .name = "n_rx_bytes_1024_2047",
 486                .offset = 0x07,
 487                .start = 31,
 488                .end = 0,
 489        },
 490        [N_RX_BYTES_512_1023] = {
 491                .area = ETHER,
 492                .name = "n_rx_bytes_512_1023",
 493                .offset = 0x06,
 494                .start = 31,
 495                .end = 0,
 496        },
 497        [N_RX_BYTES_256_511] = {
 498                .area = ETHER,
 499                .name = "n_rx_bytes_256_511",
 500                .offset = 0x05,
 501                .start = 31,
 502                .end = 0,
 503        },
 504        [N_RX_BYTES_128_255] = {
 505                .area = ETHER,
 506                .name = "n_rx_bytes_128_255",
 507                .offset = 0x04,
 508                .start = 31,
 509                .end = 0,
 510        },
 511        [N_RX_BYTES_65_127] = {
 512                .area = ETHER,
 513                .name = "n_rx_bytes_65_127",
 514                .offset = 0x03,
 515                .start = 31,
 516                .end = 0,
 517        },
 518        [N_RX_BYTES_64] = {
 519                .area = ETHER,
 520                .name = "n_rx_bytes_64",
 521                .offset = 0x02,
 522                .start = 31,
 523                .end = 0,
 524        },
 525        [N_RX_MCAST] = {
 526                .area = ETHER,
 527                .name = "n_rx_mcast",
 528                .offset = 0x01,
 529                .start = 31,
 530                .end = 0,
 531        },
 532        [N_RX_BCAST] = {
 533                .area = ETHER,
 534                .name = "n_rx_bcast",
 535                .offset = 0x00,
 536                .start = 31,
 537                .end = 0,
 538        },
 539};
 540
 541static int sja1105_port_counter_read(struct sja1105_private *priv, int port,
 542                                     enum sja1105_counter_index idx, u64 *ctr)
 543{
 544        const struct sja1105_port_counter *c = &sja1105_port_counters[idx];
 545        size_t size = c->is_64bit ? 8 : 4;
 546        u8 buf[8] = {0};
 547        u64 regs;
 548        int rc;
 549
 550        regs = priv->info->regs->stats[c->area][port];
 551
 552        rc = sja1105_xfer_buf(priv, SPI_READ, regs + c->offset, buf, size);
 553        if (rc)
 554                return rc;
 555
 556        sja1105_unpack(buf, ctr, c->start, c->end, size);
 557
 558        return 0;
 559}
 560
 561void sja1105_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data)
 562{
 563        struct sja1105_private *priv = ds->priv;
 564        enum sja1105_counter_index max_ctr, i;
 565        int rc, k = 0;
 566
 567        if (priv->info->device_id == SJA1105E_DEVICE_ID ||
 568            priv->info->device_id == SJA1105T_DEVICE_ID)
 569                max_ctr = __MAX_SJA1105ET_PORT_COUNTER;
 570        else
 571                max_ctr = __MAX_SJA1105PQRS_PORT_COUNTER;
 572
 573        for (i = 0; i < max_ctr; i++) {
 574                rc = sja1105_port_counter_read(priv, port, i, &data[k++]);
 575                if (rc) {
 576                        dev_err(ds->dev,
 577                                "Failed to read port %d counters: %d\n",
 578                                port, rc);
 579                        break;
 580                }
 581        }
 582}
 583
 584void sja1105_get_strings(struct dsa_switch *ds, int port,
 585                         u32 stringset, u8 *data)
 586{
 587        struct sja1105_private *priv = ds->priv;
 588        enum sja1105_counter_index max_ctr, i;
 589        char *p = data;
 590
 591        if (stringset != ETH_SS_STATS)
 592                return;
 593
 594        if (priv->info->device_id == SJA1105E_DEVICE_ID ||
 595            priv->info->device_id == SJA1105T_DEVICE_ID)
 596                max_ctr = __MAX_SJA1105ET_PORT_COUNTER;
 597        else
 598                max_ctr = __MAX_SJA1105PQRS_PORT_COUNTER;
 599
 600        for (i = 0; i < max_ctr; i++) {
 601                strscpy(p, sja1105_port_counters[i].name, ETH_GSTRING_LEN);
 602                p += ETH_GSTRING_LEN;
 603        }
 604}
 605
 606int sja1105_get_sset_count(struct dsa_switch *ds, int port, int sset)
 607{
 608        struct sja1105_private *priv = ds->priv;
 609        enum sja1105_counter_index max_ctr, i;
 610        int sset_count = 0;
 611
 612        if (sset != ETH_SS_STATS)
 613                return -EOPNOTSUPP;
 614
 615        if (priv->info->device_id == SJA1105E_DEVICE_ID ||
 616            priv->info->device_id == SJA1105T_DEVICE_ID)
 617                max_ctr = __MAX_SJA1105ET_PORT_COUNTER;
 618        else
 619                max_ctr = __MAX_SJA1105PQRS_PORT_COUNTER;
 620
 621        for (i = 0; i < max_ctr; i++) {
 622                if (!strlen(sja1105_port_counters[i].name))
 623                        continue;
 624
 625                sset_count++;
 626        }
 627
 628        return sset_count;
 629}
 630