0001
0002
0003
0004 #include "sja1105.h"
0005
0006 enum sja1105_counter_index {
0007 __SJA1105_COUNTER_UNUSED,
0008
0009 N_RUNT,
0010 N_SOFERR,
0011 N_ALIGNERR,
0012 N_MIIERR,
0013 TYPEERR,
0014 SIZEERR,
0015 TCTIMEOUT,
0016 PRIORERR,
0017 NOMASTER,
0018 MEMOV,
0019 MEMERR,
0020 INVTYP,
0021 INTCYOV,
0022 DOMERR,
0023 PCFBAGDROP,
0024 SPCPRIOR,
0025 AGEPRIOR,
0026 PORTDROP,
0027 LENDROP,
0028 BAGDROP,
0029 POLICEERR,
0030 DRPNONA664ERR,
0031 SPCERR,
0032 AGEDRP,
0033
0034 N_N664ERR,
0035 N_VLANERR,
0036 N_UNRELEASED,
0037 N_SIZEERR,
0038 N_CRCERR,
0039 N_VLNOTFOUND,
0040 N_CTPOLERR,
0041 N_POLERR,
0042 N_RXFRM,
0043 N_RXBYTE,
0044 N_TXFRM,
0045 N_TXBYTE,
0046
0047 N_QFULL,
0048 N_PART_DROP,
0049 N_EGR_DISABLED,
0050 N_NOT_REACH,
0051 __MAX_SJA1105ET_PORT_COUNTER,
0052
0053
0054 N_DROPS_NOLEARN = __MAX_SJA1105ET_PORT_COUNTER,
0055 N_DROPS_NOROUTE,
0056 N_DROPS_ILL_DTAG,
0057 N_DROPS_DTAG,
0058 N_DROPS_SOTAG,
0059 N_DROPS_SITAG,
0060 N_DROPS_UTAG,
0061 N_TX_BYTES_1024_2047,
0062 N_TX_BYTES_512_1023,
0063 N_TX_BYTES_256_511,
0064 N_TX_BYTES_128_255,
0065 N_TX_BYTES_65_127,
0066 N_TX_BYTES_64,
0067 N_TX_MCAST,
0068 N_TX_BCAST,
0069 N_RX_BYTES_1024_2047,
0070 N_RX_BYTES_512_1023,
0071 N_RX_BYTES_256_511,
0072 N_RX_BYTES_128_255,
0073 N_RX_BYTES_65_127,
0074 N_RX_BYTES_64,
0075 N_RX_MCAST,
0076 N_RX_BCAST,
0077 __MAX_SJA1105PQRS_PORT_COUNTER,
0078 };
0079
0080 struct sja1105_port_counter {
0081 enum sja1105_stats_area area;
0082 const char name[ETH_GSTRING_LEN];
0083 int offset;
0084 int start;
0085 int end;
0086 bool is_64bit;
0087 };
0088
0089 static const struct sja1105_port_counter sja1105_port_counters[] = {
0090
0091 [N_RUNT] = {
0092 .area = MAC,
0093 .name = "n_runt",
0094 .offset = 0,
0095 .start = 31,
0096 .end = 24,
0097 },
0098 [N_SOFERR] = {
0099 .area = MAC,
0100 .name = "n_soferr",
0101 .offset = 0x0,
0102 .start = 23,
0103 .end = 16,
0104 },
0105 [N_ALIGNERR] = {
0106 .area = MAC,
0107 .name = "n_alignerr",
0108 .offset = 0x0,
0109 .start = 15,
0110 .end = 8,
0111 },
0112 [N_MIIERR] = {
0113 .area = MAC,
0114 .name = "n_miierr",
0115 .offset = 0x0,
0116 .start = 7,
0117 .end = 0,
0118 },
0119
0120 [TYPEERR] = {
0121 .area = MAC,
0122 .name = "typeerr",
0123 .offset = 0x1,
0124 .start = 27,
0125 .end = 27,
0126 },
0127 [SIZEERR] = {
0128 .area = MAC,
0129 .name = "sizeerr",
0130 .offset = 0x1,
0131 .start = 26,
0132 .end = 26,
0133 },
0134 [TCTIMEOUT] = {
0135 .area = MAC,
0136 .name = "tctimeout",
0137 .offset = 0x1,
0138 .start = 25,
0139 .end = 25,
0140 },
0141 [PRIORERR] = {
0142 .area = MAC,
0143 .name = "priorerr",
0144 .offset = 0x1,
0145 .start = 24,
0146 .end = 24,
0147 },
0148 [NOMASTER] = {
0149 .area = MAC,
0150 .name = "nomaster",
0151 .offset = 0x1,
0152 .start = 23,
0153 .end = 23,
0154 },
0155 [MEMOV] = {
0156 .area = MAC,
0157 .name = "memov",
0158 .offset = 0x1,
0159 .start = 22,
0160 .end = 22,
0161 },
0162 [MEMERR] = {
0163 .area = MAC,
0164 .name = "memerr",
0165 .offset = 0x1,
0166 .start = 21,
0167 .end = 21,
0168 },
0169 [INVTYP] = {
0170 .area = MAC,
0171 .name = "invtyp",
0172 .offset = 0x1,
0173 .start = 19,
0174 .end = 19,
0175 },
0176 [INTCYOV] = {
0177 .area = MAC,
0178 .name = "intcyov",
0179 .offset = 0x1,
0180 .start = 18,
0181 .end = 18,
0182 },
0183 [DOMERR] = {
0184 .area = MAC,
0185 .name = "domerr",
0186 .offset = 0x1,
0187 .start = 17,
0188 .end = 17,
0189 },
0190 [PCFBAGDROP] = {
0191 .area = MAC,
0192 .name = "pcfbagdrop",
0193 .offset = 0x1,
0194 .start = 16,
0195 .end = 16,
0196 },
0197 [SPCPRIOR] = {
0198 .area = MAC,
0199 .name = "spcprior",
0200 .offset = 0x1,
0201 .start = 15,
0202 .end = 12,
0203 },
0204 [AGEPRIOR] = {
0205 .area = MAC,
0206 .name = "ageprior",
0207 .offset = 0x1,
0208 .start = 11,
0209 .end = 8,
0210 },
0211 [PORTDROP] = {
0212 .area = MAC,
0213 .name = "portdrop",
0214 .offset = 0x1,
0215 .start = 6,
0216 .end = 6,
0217 },
0218 [LENDROP] = {
0219 .area = MAC,
0220 .name = "lendrop",
0221 .offset = 0x1,
0222 .start = 5,
0223 .end = 5,
0224 },
0225 [BAGDROP] = {
0226 .area = MAC,
0227 .name = "bagdrop",
0228 .offset = 0x1,
0229 .start = 4,
0230 .end = 4,
0231 },
0232 [POLICEERR] = {
0233 .area = MAC,
0234 .name = "policeerr",
0235 .offset = 0x1,
0236 .start = 3,
0237 .end = 3,
0238 },
0239 [DRPNONA664ERR] = {
0240 .area = MAC,
0241 .name = "drpnona664err",
0242 .offset = 0x1,
0243 .start = 2,
0244 .end = 2,
0245 },
0246 [SPCERR] = {
0247 .area = MAC,
0248 .name = "spcerr",
0249 .offset = 0x1,
0250 .start = 1,
0251 .end = 1,
0252 },
0253 [AGEDRP] = {
0254 .area = MAC,
0255 .name = "agedrp",
0256 .offset = 0x1,
0257 .start = 0,
0258 .end = 0,
0259 },
0260
0261 [N_N664ERR] = {
0262 .area = HL1,
0263 .name = "n_n664err",
0264 .offset = 0xF,
0265 .start = 31,
0266 .end = 0,
0267 },
0268 [N_VLANERR] = {
0269 .area = HL1,
0270 .name = "n_vlanerr",
0271 .offset = 0xE,
0272 .start = 31,
0273 .end = 0,
0274 },
0275 [N_UNRELEASED] = {
0276 .area = HL1,
0277 .name = "n_unreleased",
0278 .offset = 0xD,
0279 .start = 31,
0280 .end = 0,
0281 },
0282 [N_SIZEERR] = {
0283 .area = HL1,
0284 .name = "n_sizeerr",
0285 .offset = 0xC,
0286 .start = 31,
0287 .end = 0,
0288 },
0289 [N_CRCERR] = {
0290 .area = HL1,
0291 .name = "n_crcerr",
0292 .offset = 0xB,
0293 .start = 31,
0294 .end = 0,
0295 },
0296 [N_VLNOTFOUND] = {
0297 .area = HL1,
0298 .name = "n_vlnotfound",
0299 .offset = 0xA,
0300 .start = 31,
0301 .end = 0,
0302 },
0303 [N_CTPOLERR] = {
0304 .area = HL1,
0305 .name = "n_ctpolerr",
0306 .offset = 0x9,
0307 .start = 31,
0308 .end = 0,
0309 },
0310 [N_POLERR] = {
0311 .area = HL1,
0312 .name = "n_polerr",
0313 .offset = 0x8,
0314 .start = 31,
0315 .end = 0,
0316 },
0317 [N_RXFRM] = {
0318 .area = HL1,
0319 .name = "n_rxfrm",
0320 .offset = 0x6,
0321 .start = 31,
0322 .end = 0,
0323 .is_64bit = true,
0324 },
0325 [N_RXBYTE] = {
0326 .area = HL1,
0327 .name = "n_rxbyte",
0328 .offset = 0x4,
0329 .start = 31,
0330 .end = 0,
0331 .is_64bit = true,
0332 },
0333 [N_TXFRM] = {
0334 .area = HL1,
0335 .name = "n_txfrm",
0336 .offset = 0x2,
0337 .start = 31,
0338 .end = 0,
0339 .is_64bit = true,
0340 },
0341 [N_TXBYTE] = {
0342 .area = HL1,
0343 .name = "n_txbyte",
0344 .offset = 0x0,
0345 .start = 31,
0346 .end = 0,
0347 .is_64bit = true,
0348 },
0349 [N_QFULL] = {
0350 .area = HL2,
0351 .name = "n_qfull",
0352 .offset = 0x3,
0353 .start = 31,
0354 .end = 0,
0355 },
0356 [N_PART_DROP] = {
0357 .area = HL2,
0358 .name = "n_part_drop",
0359 .offset = 0x2,
0360 .start = 31,
0361 .end = 0,
0362 },
0363 [N_EGR_DISABLED] = {
0364 .area = HL2,
0365 .name = "n_egr_disabled",
0366 .offset = 0x1,
0367 .start = 31,
0368 .end = 0,
0369 },
0370 [N_NOT_REACH] = {
0371 .area = HL2,
0372 .name = "n_not_reach",
0373 .offset = 0x0,
0374 .start = 31,
0375 .end = 0,
0376 },
0377
0378 [N_DROPS_NOLEARN] = {
0379 .area = ETHER,
0380 .name = "n_drops_nolearn",
0381 .offset = 0x16,
0382 .start = 31,
0383 .end = 0,
0384 },
0385 [N_DROPS_NOROUTE] = {
0386 .area = ETHER,
0387 .name = "n_drops_noroute",
0388 .offset = 0x15,
0389 .start = 31,
0390 .end = 0,
0391 },
0392 [N_DROPS_ILL_DTAG] = {
0393 .area = ETHER,
0394 .name = "n_drops_ill_dtag",
0395 .offset = 0x14,
0396 .start = 31,
0397 .end = 0,
0398 },
0399 [N_DROPS_DTAG] = {
0400 .area = ETHER,
0401 .name = "n_drops_dtag",
0402 .offset = 0x13,
0403 .start = 31,
0404 .end = 0,
0405 },
0406 [N_DROPS_SOTAG] = {
0407 .area = ETHER,
0408 .name = "n_drops_sotag",
0409 .offset = 0x12,
0410 .start = 31,
0411 .end = 0,
0412 },
0413 [N_DROPS_SITAG] = {
0414 .area = ETHER,
0415 .name = "n_drops_sitag",
0416 .offset = 0x11,
0417 .start = 31,
0418 .end = 0,
0419 },
0420 [N_DROPS_UTAG] = {
0421 .area = ETHER,
0422 .name = "n_drops_utag",
0423 .offset = 0x10,
0424 .start = 31,
0425 .end = 0,
0426 },
0427 [N_TX_BYTES_1024_2047] = {
0428 .area = ETHER,
0429 .name = "n_tx_bytes_1024_2047",
0430 .offset = 0x0F,
0431 .start = 31,
0432 .end = 0,
0433 },
0434 [N_TX_BYTES_512_1023] = {
0435 .area = ETHER,
0436 .name = "n_tx_bytes_512_1023",
0437 .offset = 0x0E,
0438 .start = 31,
0439 .end = 0,
0440 },
0441 [N_TX_BYTES_256_511] = {
0442 .area = ETHER,
0443 .name = "n_tx_bytes_256_511",
0444 .offset = 0x0D,
0445 .start = 31,
0446 .end = 0,
0447 },
0448 [N_TX_BYTES_128_255] = {
0449 .area = ETHER,
0450 .name = "n_tx_bytes_128_255",
0451 .offset = 0x0C,
0452 .start = 31,
0453 .end = 0,
0454 },
0455 [N_TX_BYTES_65_127] = {
0456 .area = ETHER,
0457 .name = "n_tx_bytes_65_127",
0458 .offset = 0x0B,
0459 .start = 31,
0460 .end = 0,
0461 },
0462 [N_TX_BYTES_64] = {
0463 .area = ETHER,
0464 .name = "n_tx_bytes_64",
0465 .offset = 0x0A,
0466 .start = 31,
0467 .end = 0,
0468 },
0469 [N_TX_MCAST] = {
0470 .area = ETHER,
0471 .name = "n_tx_mcast",
0472 .offset = 0x09,
0473 .start = 31,
0474 .end = 0,
0475 },
0476 [N_TX_BCAST] = {
0477 .area = ETHER,
0478 .name = "n_tx_bcast",
0479 .offset = 0x08,
0480 .start = 31,
0481 .end = 0,
0482 },
0483 [N_RX_BYTES_1024_2047] = {
0484 .area = ETHER,
0485 .name = "n_rx_bytes_1024_2047",
0486 .offset = 0x07,
0487 .start = 31,
0488 .end = 0,
0489 },
0490 [N_RX_BYTES_512_1023] = {
0491 .area = ETHER,
0492 .name = "n_rx_bytes_512_1023",
0493 .offset = 0x06,
0494 .start = 31,
0495 .end = 0,
0496 },
0497 [N_RX_BYTES_256_511] = {
0498 .area = ETHER,
0499 .name = "n_rx_bytes_256_511",
0500 .offset = 0x05,
0501 .start = 31,
0502 .end = 0,
0503 },
0504 [N_RX_BYTES_128_255] = {
0505 .area = ETHER,
0506 .name = "n_rx_bytes_128_255",
0507 .offset = 0x04,
0508 .start = 31,
0509 .end = 0,
0510 },
0511 [N_RX_BYTES_65_127] = {
0512 .area = ETHER,
0513 .name = "n_rx_bytes_65_127",
0514 .offset = 0x03,
0515 .start = 31,
0516 .end = 0,
0517 },
0518 [N_RX_BYTES_64] = {
0519 .area = ETHER,
0520 .name = "n_rx_bytes_64",
0521 .offset = 0x02,
0522 .start = 31,
0523 .end = 0,
0524 },
0525 [N_RX_MCAST] = {
0526 .area = ETHER,
0527 .name = "n_rx_mcast",
0528 .offset = 0x01,
0529 .start = 31,
0530 .end = 0,
0531 },
0532 [N_RX_BCAST] = {
0533 .area = ETHER,
0534 .name = "n_rx_bcast",
0535 .offset = 0x00,
0536 .start = 31,
0537 .end = 0,
0538 },
0539 };
0540
0541 static int sja1105_port_counter_read(struct sja1105_private *priv, int port,
0542 enum sja1105_counter_index idx, u64 *ctr)
0543 {
0544 const struct sja1105_port_counter *c = &sja1105_port_counters[idx];
0545 size_t size = c->is_64bit ? 8 : 4;
0546 u8 buf[8] = {0};
0547 u64 regs;
0548 int rc;
0549
0550 regs = priv->info->regs->stats[c->area][port];
0551
0552 rc = sja1105_xfer_buf(priv, SPI_READ, regs + c->offset, buf, size);
0553 if (rc)
0554 return rc;
0555
0556 sja1105_unpack(buf, ctr, c->start, c->end, size);
0557
0558 return 0;
0559 }
0560
0561 void sja1105_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data)
0562 {
0563 struct sja1105_private *priv = ds->priv;
0564 enum sja1105_counter_index max_ctr, i;
0565 int rc, k = 0;
0566
0567 if (priv->info->device_id == SJA1105E_DEVICE_ID ||
0568 priv->info->device_id == SJA1105T_DEVICE_ID)
0569 max_ctr = __MAX_SJA1105ET_PORT_COUNTER;
0570 else
0571 max_ctr = __MAX_SJA1105PQRS_PORT_COUNTER;
0572
0573 for (i = 0; i < max_ctr; i++) {
0574 rc = sja1105_port_counter_read(priv, port, i, &data[k++]);
0575 if (rc) {
0576 dev_err(ds->dev,
0577 "Failed to read port %d counters: %d\n",
0578 port, rc);
0579 break;
0580 }
0581 }
0582 }
0583
0584 void sja1105_get_strings(struct dsa_switch *ds, int port,
0585 u32 stringset, u8 *data)
0586 {
0587 struct sja1105_private *priv = ds->priv;
0588 enum sja1105_counter_index max_ctr, i;
0589 char *p = data;
0590
0591 if (stringset != ETH_SS_STATS)
0592 return;
0593
0594 if (priv->info->device_id == SJA1105E_DEVICE_ID ||
0595 priv->info->device_id == SJA1105T_DEVICE_ID)
0596 max_ctr = __MAX_SJA1105ET_PORT_COUNTER;
0597 else
0598 max_ctr = __MAX_SJA1105PQRS_PORT_COUNTER;
0599
0600 for (i = 0; i < max_ctr; i++) {
0601 strscpy(p, sja1105_port_counters[i].name, ETH_GSTRING_LEN);
0602 p += ETH_GSTRING_LEN;
0603 }
0604 }
0605
0606 int sja1105_get_sset_count(struct dsa_switch *ds, int port, int sset)
0607 {
0608 struct sja1105_private *priv = ds->priv;
0609 enum sja1105_counter_index max_ctr, i;
0610 int sset_count = 0;
0611
0612 if (sset != ETH_SS_STATS)
0613 return -EOPNOTSUPP;
0614
0615 if (priv->info->device_id == SJA1105E_DEVICE_ID ||
0616 priv->info->device_id == SJA1105T_DEVICE_ID)
0617 max_ctr = __MAX_SJA1105ET_PORT_COUNTER;
0618 else
0619 max_ctr = __MAX_SJA1105PQRS_PORT_COUNTER;
0620
0621 for (i = 0; i < max_ctr; i++) {
0622 if (!strlen(sja1105_port_counters[i].name))
0623 continue;
0624
0625 sset_count++;
0626 }
0627
0628 return sset_count;
0629 }