treewide: remove redundant IS_ERR() before error code check
[linux/fpc-iii.git] / drivers / net / dsa / sja1105 / sja1105_ethtool.c
blob064301cc7d5b280fd70d1ec6a0370f5195065423
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
3 */
4 #include "sja1105.h"
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 */
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;
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;
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 */
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;
72 static void
73 sja1105_port_status_mac_unpack(void *buf,
74 struct sja1105_port_status_mac *status)
76 /* Make pointer arithmetic work on 4 bytes */
77 u32 *p = buf;
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);
105 static void
106 sja1105_port_status_hl1_unpack(void *buf,
107 struct sja1105_port_status_hl1 *status)
109 /* Make pointer arithmetic work on 4 bytes */
110 u32 *p = buf;
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;
134 static void
135 sja1105_port_status_hl2_unpack(void *buf,
136 struct sja1105_port_status_hl2 *status)
138 /* Make pointer arithmetic work on 4 bytes */
139 u32 *p = buf;
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);
147 static void
148 sja1105pqrs_port_status_qlevel_unpack(void *buf,
149 struct sja1105_port_status_hl2 *status)
151 /* Make pointer arithmetic work on 4 bytes */
152 u32 *p = buf;
153 int i;
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);
161 static int sja1105_port_status_get_mac(struct sja1105_private *priv,
162 struct sja1105_port_status_mac *status,
163 int port)
165 const struct sja1105_regs *regs = priv->info->regs;
166 u8 packed_buf[SJA1105_SIZE_MAC_AREA] = {0};
167 int rc;
169 /* MAC area */
170 rc = sja1105_xfer_buf(priv, SPI_READ, regs->mac[port], packed_buf,
171 SJA1105_SIZE_MAC_AREA);
172 if (rc < 0)
173 return rc;
175 sja1105_port_status_mac_unpack(packed_buf, status);
177 return 0;
180 static int sja1105_port_status_get_hl1(struct sja1105_private *priv,
181 struct sja1105_port_status_hl1 *status,
182 int port)
184 const struct sja1105_regs *regs = priv->info->regs;
185 u8 packed_buf[SJA1105_SIZE_HL1_AREA] = {0};
186 int rc;
188 rc = sja1105_xfer_buf(priv, SPI_READ, regs->mac_hl1[port], packed_buf,
189 SJA1105_SIZE_HL1_AREA);
190 if (rc < 0)
191 return rc;
193 sja1105_port_status_hl1_unpack(packed_buf, status);
195 return 0;
198 static int sja1105_port_status_get_hl2(struct sja1105_private *priv,
199 struct sja1105_port_status_hl2 *status,
200 int port)
202 const struct sja1105_regs *regs = priv->info->regs;
203 u8 packed_buf[SJA1105_SIZE_QLEVEL_AREA] = {0};
204 int rc;
206 rc = sja1105_xfer_buf(priv, SPI_READ, regs->mac_hl2[port], packed_buf,
207 SJA1105_SIZE_HL2_AREA);
208 if (rc < 0)
209 return rc;
211 sja1105_port_status_hl2_unpack(packed_buf, status);
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;
218 rc = sja1105_xfer_buf(priv, SPI_READ, regs->qlevel[port], packed_buf,
219 SJA1105_SIZE_QLEVEL_AREA);
220 if (rc < 0)
221 return rc;
223 sja1105pqrs_port_status_qlevel_unpack(packed_buf, status);
225 return 0;
228 static int sja1105_port_status_get(struct sja1105_private *priv,
229 struct sja1105_port_status *status,
230 int port)
232 int rc;
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;
244 return 0;
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",
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",
313 void sja1105_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data)
315 struct sja1105_private *priv = ds->priv;
316 struct sja1105_port_status status;
317 int rc, i, k = 0;
319 memset(&status, 0, sizeof(status));
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;
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;
369 if (priv->info->device_id == SJA1105E_DEVICE_ID ||
370 priv->info->device_id == SJA1105T_DEVICE_ID)
371 return;
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];
381 void sja1105_get_strings(struct dsa_switch *ds, int port,
382 u32 stringset, u8 *data)
384 struct sja1105_private *priv = ds->priv;
385 u8 *p = data;
386 int i;
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;
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;
402 break;
406 int sja1105_get_sset_count(struct dsa_switch *ds, int port, int sset)
408 int count = ARRAY_SIZE(sja1105_port_stats);
409 struct sja1105_private *priv = ds->priv;
411 if (sset != ETH_SS_STATS)
412 return -EOPNOTSUPP;
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);
418 return count;