root/drivers/net/dsa/sja1105/sja1105_ethtool.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sja1105_port_status_mac_unpack
  2. sja1105_port_status_hl1_unpack
  3. sja1105_port_status_hl2_unpack
  4. sja1105pqrs_port_status_qlevel_unpack
  5. sja1105_port_status_get_mac
  6. sja1105_port_status_get_hl1
  7. sja1105_port_status_get_hl2
  8. sja1105_port_status_get
  9. sja1105_get_ethtool_stats
  10. sja1105_get_strings
  11. sja1105_get_sset_count

   1 // SPDX-License-Identifier: GPL-2.0
   2 /* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
   3  */
   4 #include "sja1105.h"
   5 
   6 #define SJA1105_SIZE_MAC_AREA           (0x02 * 4)
   7 #define SJA1105_SIZE_HL1_AREA           (0x10 * 4)
   8 #define SJA1105_SIZE_HL2_AREA           (0x4 * 4)
   9 #define SJA1105_SIZE_QLEVEL_AREA        (0x8 * 4) /* 0x4 to 0xB */
  10 
  11 struct sja1105_port_status_mac {
  12         u64 n_runt;
  13         u64 n_soferr;
  14         u64 n_alignerr;
  15         u64 n_miierr;
  16         u64 typeerr;
  17         u64 sizeerr;
  18         u64 tctimeout;
  19         u64 priorerr;
  20         u64 nomaster;
  21         u64 memov;
  22         u64 memerr;
  23         u64 invtyp;
  24         u64 intcyov;
  25         u64 domerr;
  26         u64 pcfbagdrop;
  27         u64 spcprior;
  28         u64 ageprior;
  29         u64 portdrop;
  30         u64 lendrop;
  31         u64 bagdrop;
  32         u64 policeerr;
  33         u64 drpnona664err;
  34         u64 spcerr;
  35         u64 agedrp;
  36 };
  37 
  38 struct sja1105_port_status_hl1 {
  39         u64 n_n664err;
  40         u64 n_vlanerr;
  41         u64 n_unreleased;
  42         u64 n_sizeerr;
  43         u64 n_crcerr;
  44         u64 n_vlnotfound;
  45         u64 n_ctpolerr;
  46         u64 n_polerr;
  47         u64 n_rxfrmsh;
  48         u64 n_rxfrm;
  49         u64 n_rxbytesh;
  50         u64 n_rxbyte;
  51         u64 n_txfrmsh;
  52         u64 n_txfrm;
  53         u64 n_txbytesh;
  54         u64 n_txbyte;
  55 };
  56 
  57 struct sja1105_port_status_hl2 {
  58         u64 n_qfull;
  59         u64 n_part_drop;
  60         u64 n_egr_disabled;
  61         u64 n_not_reach;
  62         u64 qlevel_hwm[8]; /* Only for P/Q/R/S */
  63         u64 qlevel[8];     /* Only for P/Q/R/S */
  64 };
  65 
  66 struct sja1105_port_status {
  67         struct sja1105_port_status_mac mac;
  68         struct sja1105_port_status_hl1 hl1;
  69         struct sja1105_port_status_hl2 hl2;
  70 };
  71 
  72 static void
  73 sja1105_port_status_mac_unpack(void *buf,
  74                                struct sja1105_port_status_mac *status)
  75 {
  76         /* Make pointer arithmetic work on 4 bytes */
  77         u32 *p = buf;
  78 
  79         sja1105_unpack(p + 0x0, &status->n_runt,       31, 24, 4);
  80         sja1105_unpack(p + 0x0, &status->n_soferr,     23, 16, 4);
  81         sja1105_unpack(p + 0x0, &status->n_alignerr,   15,  8, 4);
  82         sja1105_unpack(p + 0x0, &status->n_miierr,      7,  0, 4);
  83         sja1105_unpack(p + 0x1, &status->typeerr,      27, 27, 4);
  84         sja1105_unpack(p + 0x1, &status->sizeerr,      26, 26, 4);
  85         sja1105_unpack(p + 0x1, &status->tctimeout,    25, 25, 4);
  86         sja1105_unpack(p + 0x1, &status->priorerr,     24, 24, 4);
  87         sja1105_unpack(p + 0x1, &status->nomaster,     23, 23, 4);
  88         sja1105_unpack(p + 0x1, &status->memov,        22, 22, 4);
  89         sja1105_unpack(p + 0x1, &status->memerr,       21, 21, 4);
  90         sja1105_unpack(p + 0x1, &status->invtyp,       19, 19, 4);
  91         sja1105_unpack(p + 0x1, &status->intcyov,      18, 18, 4);
  92         sja1105_unpack(p + 0x1, &status->domerr,       17, 17, 4);
  93         sja1105_unpack(p + 0x1, &status->pcfbagdrop,   16, 16, 4);
  94         sja1105_unpack(p + 0x1, &status->spcprior,     15, 12, 4);
  95         sja1105_unpack(p + 0x1, &status->ageprior,     11,  8, 4);
  96         sja1105_unpack(p + 0x1, &status->portdrop,      6,  6, 4);
  97         sja1105_unpack(p + 0x1, &status->lendrop,       5,  5, 4);
  98         sja1105_unpack(p + 0x1, &status->bagdrop,       4,  4, 4);
  99         sja1105_unpack(p + 0x1, &status->policeerr,     3,  3, 4);
 100         sja1105_unpack(p + 0x1, &status->drpnona664err, 2,  2, 4);
 101         sja1105_unpack(p + 0x1, &status->spcerr,        1,  1, 4);
 102         sja1105_unpack(p + 0x1, &status->agedrp,        0,  0, 4);
 103 }
 104 
 105 static void
 106 sja1105_port_status_hl1_unpack(void *buf,
 107                                struct sja1105_port_status_hl1 *status)
 108 {
 109         /* Make pointer arithmetic work on 4 bytes */
 110         u32 *p = buf;
 111 
 112         sja1105_unpack(p + 0xF, &status->n_n664err,    31,  0, 4);
 113         sja1105_unpack(p + 0xE, &status->n_vlanerr,    31,  0, 4);
 114         sja1105_unpack(p + 0xD, &status->n_unreleased, 31,  0, 4);
 115         sja1105_unpack(p + 0xC, &status->n_sizeerr,    31,  0, 4);
 116         sja1105_unpack(p + 0xB, &status->n_crcerr,     31,  0, 4);
 117         sja1105_unpack(p + 0xA, &status->n_vlnotfound, 31,  0, 4);
 118         sja1105_unpack(p + 0x9, &status->n_ctpolerr,   31,  0, 4);
 119         sja1105_unpack(p + 0x8, &status->n_polerr,     31,  0, 4);
 120         sja1105_unpack(p + 0x7, &status->n_rxfrmsh,    31,  0, 4);
 121         sja1105_unpack(p + 0x6, &status->n_rxfrm,      31,  0, 4);
 122         sja1105_unpack(p + 0x5, &status->n_rxbytesh,   31,  0, 4);
 123         sja1105_unpack(p + 0x4, &status->n_rxbyte,     31,  0, 4);
 124         sja1105_unpack(p + 0x3, &status->n_txfrmsh,    31,  0, 4);
 125         sja1105_unpack(p + 0x2, &status->n_txfrm,      31,  0, 4);
 126         sja1105_unpack(p + 0x1, &status->n_txbytesh,   31,  0, 4);
 127         sja1105_unpack(p + 0x0, &status->n_txbyte,     31,  0, 4);
 128         status->n_rxfrm  += status->n_rxfrmsh  << 32;
 129         status->n_rxbyte += status->n_rxbytesh << 32;
 130         status->n_txfrm  += status->n_txfrmsh  << 32;
 131         status->n_txbyte += status->n_txbytesh << 32;
 132 }
 133 
 134 static void
 135 sja1105_port_status_hl2_unpack(void *buf,
 136                                struct sja1105_port_status_hl2 *status)
 137 {
 138         /* Make pointer arithmetic work on 4 bytes */
 139         u32 *p = buf;
 140 
 141         sja1105_unpack(p + 0x3, &status->n_qfull,        31,  0, 4);
 142         sja1105_unpack(p + 0x2, &status->n_part_drop,    31,  0, 4);
 143         sja1105_unpack(p + 0x1, &status->n_egr_disabled, 31,  0, 4);
 144         sja1105_unpack(p + 0x0, &status->n_not_reach,    31,  0, 4);
 145 }
 146 
 147 static void
 148 sja1105pqrs_port_status_qlevel_unpack(void *buf,
 149                                       struct sja1105_port_status_hl2 *status)
 150 {
 151         /* Make pointer arithmetic work on 4 bytes */
 152         u32 *p = buf;
 153         int i;
 154 
 155         for (i = 0; i < 8; i++) {
 156                 sja1105_unpack(p + i, &status->qlevel_hwm[i], 24, 16, 4);
 157                 sja1105_unpack(p + i, &status->qlevel[i],      8,  0, 4);
 158         }
 159 }
 160 
 161 static int sja1105_port_status_get_mac(struct sja1105_private *priv,
 162                                        struct sja1105_port_status_mac *status,
 163                                        int port)
 164 {
 165         const struct sja1105_regs *regs = priv->info->regs;
 166         u8 packed_buf[SJA1105_SIZE_MAC_AREA] = {0};
 167         int rc;
 168 
 169         /* MAC area */
 170         rc = sja1105_spi_send_packed_buf(priv, SPI_READ, regs->mac[port],
 171                                          packed_buf, SJA1105_SIZE_MAC_AREA);
 172         if (rc < 0)
 173                 return rc;
 174 
 175         sja1105_port_status_mac_unpack(packed_buf, status);
 176 
 177         return 0;
 178 }
 179 
 180 static int sja1105_port_status_get_hl1(struct sja1105_private *priv,
 181                                        struct sja1105_port_status_hl1 *status,
 182                                        int port)
 183 {
 184         const struct sja1105_regs *regs = priv->info->regs;
 185         u8 packed_buf[SJA1105_SIZE_HL1_AREA] = {0};
 186         int rc;
 187 
 188         rc = sja1105_spi_send_packed_buf(priv, SPI_READ, regs->mac_hl1[port],
 189                                          packed_buf, SJA1105_SIZE_HL1_AREA);
 190         if (rc < 0)
 191                 return rc;
 192 
 193         sja1105_port_status_hl1_unpack(packed_buf, status);
 194 
 195         return 0;
 196 }
 197 
 198 static int sja1105_port_status_get_hl2(struct sja1105_private *priv,
 199                                        struct sja1105_port_status_hl2 *status,
 200                                        int port)
 201 {
 202         const struct sja1105_regs *regs = priv->info->regs;
 203         u8 packed_buf[SJA1105_SIZE_QLEVEL_AREA] = {0};
 204         int rc;
 205 
 206         rc = sja1105_spi_send_packed_buf(priv, SPI_READ, regs->mac_hl2[port],
 207                                          packed_buf, SJA1105_SIZE_HL2_AREA);
 208         if (rc < 0)
 209                 return rc;
 210 
 211         sja1105_port_status_hl2_unpack(packed_buf, status);
 212 
 213         /* Code below is strictly P/Q/R/S specific. */
 214         if (priv->info->device_id == SJA1105E_DEVICE_ID ||
 215             priv->info->device_id == SJA1105T_DEVICE_ID)
 216                 return 0;
 217 
 218         rc = sja1105_spi_send_packed_buf(priv, SPI_READ, regs->qlevel[port],
 219                                          packed_buf, SJA1105_SIZE_QLEVEL_AREA);
 220         if (rc < 0)
 221                 return rc;
 222 
 223         sja1105pqrs_port_status_qlevel_unpack(packed_buf, status);
 224 
 225         return 0;
 226 }
 227 
 228 static int sja1105_port_status_get(struct sja1105_private *priv,
 229                                    struct sja1105_port_status *status,
 230                                    int port)
 231 {
 232         int rc;
 233 
 234         rc = sja1105_port_status_get_mac(priv, &status->mac, port);
 235         if (rc < 0)
 236                 return rc;
 237         rc = sja1105_port_status_get_hl1(priv, &status->hl1, port);
 238         if (rc < 0)
 239                 return rc;
 240         rc = sja1105_port_status_get_hl2(priv, &status->hl2, port);
 241         if (rc < 0)
 242                 return rc;
 243 
 244         return 0;
 245 }
 246 
 247 static char sja1105_port_stats[][ETH_GSTRING_LEN] = {
 248         /* MAC-Level Diagnostic Counters */
 249         "n_runt",
 250         "n_soferr",
 251         "n_alignerr",
 252         "n_miierr",
 253         /* MAC-Level Diagnostic Flags */
 254         "typeerr",
 255         "sizeerr",
 256         "tctimeout",
 257         "priorerr",
 258         "nomaster",
 259         "memov",
 260         "memerr",
 261         "invtyp",
 262         "intcyov",
 263         "domerr",
 264         "pcfbagdrop",
 265         "spcprior",
 266         "ageprior",
 267         "portdrop",
 268         "lendrop",
 269         "bagdrop",
 270         "policeerr",
 271         "drpnona664err",
 272         "spcerr",
 273         "agedrp",
 274         /* High-Level Diagnostic Counters */
 275         "n_n664err",
 276         "n_vlanerr",
 277         "n_unreleased",
 278         "n_sizeerr",
 279         "n_crcerr",
 280         "n_vlnotfound",
 281         "n_ctpolerr",
 282         "n_polerr",
 283         "n_rxfrm",
 284         "n_rxbyte",
 285         "n_txfrm",
 286         "n_txbyte",
 287         "n_qfull",
 288         "n_part_drop",
 289         "n_egr_disabled",
 290         "n_not_reach",
 291 };
 292 
 293 static char sja1105pqrs_extra_port_stats[][ETH_GSTRING_LEN] = {
 294         /* Queue Levels */
 295         "qlevel_hwm_0",
 296         "qlevel_hwm_1",
 297         "qlevel_hwm_2",
 298         "qlevel_hwm_3",
 299         "qlevel_hwm_4",
 300         "qlevel_hwm_5",
 301         "qlevel_hwm_6",
 302         "qlevel_hwm_7",
 303         "qlevel_0",
 304         "qlevel_1",
 305         "qlevel_2",
 306         "qlevel_3",
 307         "qlevel_4",
 308         "qlevel_5",
 309         "qlevel_6",
 310         "qlevel_7",
 311 };
 312 
 313 void sja1105_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data)
 314 {
 315         struct sja1105_private *priv = ds->priv;
 316         struct sja1105_port_status status;
 317         int rc, i, k = 0;
 318 
 319         memset(&status, 0, sizeof(status));
 320 
 321         rc = sja1105_port_status_get(priv, &status, port);
 322         if (rc < 0) {
 323                 dev_err(ds->dev, "Failed to read port %d counters: %d\n",
 324                         port, rc);
 325                 return;
 326         }
 327         memset(data, 0, ARRAY_SIZE(sja1105_port_stats) * sizeof(u64));
 328         data[k++] = status.mac.n_runt;
 329         data[k++] = status.mac.n_soferr;
 330         data[k++] = status.mac.n_alignerr;
 331         data[k++] = status.mac.n_miierr;
 332         data[k++] = status.mac.typeerr;
 333         data[k++] = status.mac.sizeerr;
 334         data[k++] = status.mac.tctimeout;
 335         data[k++] = status.mac.priorerr;
 336         data[k++] = status.mac.nomaster;
 337         data[k++] = status.mac.memov;
 338         data[k++] = status.mac.memerr;
 339         data[k++] = status.mac.invtyp;
 340         data[k++] = status.mac.intcyov;
 341         data[k++] = status.mac.domerr;
 342         data[k++] = status.mac.pcfbagdrop;
 343         data[k++] = status.mac.spcprior;
 344         data[k++] = status.mac.ageprior;
 345         data[k++] = status.mac.portdrop;
 346         data[k++] = status.mac.lendrop;
 347         data[k++] = status.mac.bagdrop;
 348         data[k++] = status.mac.policeerr;
 349         data[k++] = status.mac.drpnona664err;
 350         data[k++] = status.mac.spcerr;
 351         data[k++] = status.mac.agedrp;
 352         data[k++] = status.hl1.n_n664err;
 353         data[k++] = status.hl1.n_vlanerr;
 354         data[k++] = status.hl1.n_unreleased;
 355         data[k++] = status.hl1.n_sizeerr;
 356         data[k++] = status.hl1.n_crcerr;
 357         data[k++] = status.hl1.n_vlnotfound;
 358         data[k++] = status.hl1.n_ctpolerr;
 359         data[k++] = status.hl1.n_polerr;
 360         data[k++] = status.hl1.n_rxfrm;
 361         data[k++] = status.hl1.n_rxbyte;
 362         data[k++] = status.hl1.n_txfrm;
 363         data[k++] = status.hl1.n_txbyte;
 364         data[k++] = status.hl2.n_qfull;
 365         data[k++] = status.hl2.n_part_drop;
 366         data[k++] = status.hl2.n_egr_disabled;
 367         data[k++] = status.hl2.n_not_reach;
 368 
 369         if (priv->info->device_id == SJA1105E_DEVICE_ID ||
 370             priv->info->device_id == SJA1105T_DEVICE_ID)
 371                 return;
 372 
 373         memset(data + k, 0, ARRAY_SIZE(sja1105pqrs_extra_port_stats) *
 374                         sizeof(u64));
 375         for (i = 0; i < 8; i++) {
 376                 data[k++] = status.hl2.qlevel_hwm[i];
 377                 data[k++] = status.hl2.qlevel[i];
 378         }
 379 }
 380 
 381 void sja1105_get_strings(struct dsa_switch *ds, int port,
 382                          u32 stringset, u8 *data)
 383 {
 384         struct sja1105_private *priv = ds->priv;
 385         u8 *p = data;
 386         int i;
 387 
 388         switch (stringset) {
 389         case ETH_SS_STATS:
 390                 for (i = 0; i < ARRAY_SIZE(sja1105_port_stats); i++) {
 391                         strlcpy(p, sja1105_port_stats[i], ETH_GSTRING_LEN);
 392                         p += ETH_GSTRING_LEN;
 393                 }
 394                 if (priv->info->device_id == SJA1105E_DEVICE_ID ||
 395                     priv->info->device_id == SJA1105T_DEVICE_ID)
 396                         return;
 397                 for (i = 0; i < ARRAY_SIZE(sja1105pqrs_extra_port_stats); i++) {
 398                         strlcpy(p, sja1105pqrs_extra_port_stats[i],
 399                                 ETH_GSTRING_LEN);
 400                         p += ETH_GSTRING_LEN;
 401                 }
 402                 break;
 403         }
 404 }
 405 
 406 int sja1105_get_sset_count(struct dsa_switch *ds, int port, int sset)
 407 {
 408         int count = ARRAY_SIZE(sja1105_port_stats);
 409         struct sja1105_private *priv = ds->priv;
 410 
 411         if (sset != ETH_SS_STATS)
 412                 return -EOPNOTSUPP;
 413 
 414         if (priv->info->device_id == SJA1105PR_DEVICE_ID ||
 415             priv->info->device_id == SJA1105QS_DEVICE_ID)
 416                 count += ARRAY_SIZE(sja1105pqrs_extra_port_stats);
 417 
 418         return count;
 419 }

/* [<][>][^][v][top][bottom][index][help] */