630 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			630 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0
 | |
| /* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
 | |
|  */
 | |
| #include "sja1105.h"
 | |
| 
 | |
| enum sja1105_counter_index {
 | |
| 	__SJA1105_COUNTER_UNUSED,
 | |
| 	/* MAC */
 | |
| 	N_RUNT,
 | |
| 	N_SOFERR,
 | |
| 	N_ALIGNERR,
 | |
| 	N_MIIERR,
 | |
| 	TYPEERR,
 | |
| 	SIZEERR,
 | |
| 	TCTIMEOUT,
 | |
| 	PRIORERR,
 | |
| 	NOMASTER,
 | |
| 	MEMOV,
 | |
| 	MEMERR,
 | |
| 	INVTYP,
 | |
| 	INTCYOV,
 | |
| 	DOMERR,
 | |
| 	PCFBAGDROP,
 | |
| 	SPCPRIOR,
 | |
| 	AGEPRIOR,
 | |
| 	PORTDROP,
 | |
| 	LENDROP,
 | |
| 	BAGDROP,
 | |
| 	POLICEERR,
 | |
| 	DRPNONA664ERR,
 | |
| 	SPCERR,
 | |
| 	AGEDRP,
 | |
| 	/* HL1 */
 | |
| 	N_N664ERR,
 | |
| 	N_VLANERR,
 | |
| 	N_UNRELEASED,
 | |
| 	N_SIZEERR,
 | |
| 	N_CRCERR,
 | |
| 	N_VLNOTFOUND,
 | |
| 	N_CTPOLERR,
 | |
| 	N_POLERR,
 | |
| 	N_RXFRM,
 | |
| 	N_RXBYTE,
 | |
| 	N_TXFRM,
 | |
| 	N_TXBYTE,
 | |
| 	/* HL2 */
 | |
| 	N_QFULL,
 | |
| 	N_PART_DROP,
 | |
| 	N_EGR_DISABLED,
 | |
| 	N_NOT_REACH,
 | |
| 	__MAX_SJA1105ET_PORT_COUNTER,
 | |
| 	/* P/Q/R/S only */
 | |
| 	/* ETHER */
 | |
| 	N_DROPS_NOLEARN = __MAX_SJA1105ET_PORT_COUNTER,
 | |
| 	N_DROPS_NOROUTE,
 | |
| 	N_DROPS_ILL_DTAG,
 | |
| 	N_DROPS_DTAG,
 | |
| 	N_DROPS_SOTAG,
 | |
| 	N_DROPS_SITAG,
 | |
| 	N_DROPS_UTAG,
 | |
| 	N_TX_BYTES_1024_2047,
 | |
| 	N_TX_BYTES_512_1023,
 | |
| 	N_TX_BYTES_256_511,
 | |
| 	N_TX_BYTES_128_255,
 | |
| 	N_TX_BYTES_65_127,
 | |
| 	N_TX_BYTES_64,
 | |
| 	N_TX_MCAST,
 | |
| 	N_TX_BCAST,
 | |
| 	N_RX_BYTES_1024_2047,
 | |
| 	N_RX_BYTES_512_1023,
 | |
| 	N_RX_BYTES_256_511,
 | |
| 	N_RX_BYTES_128_255,
 | |
| 	N_RX_BYTES_65_127,
 | |
| 	N_RX_BYTES_64,
 | |
| 	N_RX_MCAST,
 | |
| 	N_RX_BCAST,
 | |
| 	__MAX_SJA1105PQRS_PORT_COUNTER,
 | |
| };
 | |
| 
 | |
| struct sja1105_port_counter {
 | |
| 	enum sja1105_stats_area area;
 | |
| 	const char name[ETH_GSTRING_LEN];
 | |
| 	int offset;
 | |
| 	int start;
 | |
| 	int end;
 | |
| 	bool is_64bit;
 | |
| };
 | |
| 
 | |
| static const struct sja1105_port_counter sja1105_port_counters[] = {
 | |
| 	/* MAC-Level Diagnostic Counters */
 | |
| 	[N_RUNT] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "n_runt",
 | |
| 		.offset = 0,
 | |
| 		.start = 31,
 | |
| 		.end = 24,
 | |
| 	},
 | |
| 	[N_SOFERR] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "n_soferr",
 | |
| 		.offset = 0x0,
 | |
| 		.start = 23,
 | |
| 		.end = 16,
 | |
| 	},
 | |
| 	[N_ALIGNERR] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "n_alignerr",
 | |
| 		.offset = 0x0,
 | |
| 		.start = 15,
 | |
| 		.end = 8,
 | |
| 	},
 | |
| 	[N_MIIERR] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "n_miierr",
 | |
| 		.offset = 0x0,
 | |
| 		.start = 7,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	/* MAC-Level Diagnostic Flags */
 | |
| 	[TYPEERR] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "typeerr",
 | |
| 		.offset = 0x1,
 | |
| 		.start = 27,
 | |
| 		.end = 27,
 | |
| 	},
 | |
| 	[SIZEERR] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "sizeerr",
 | |
| 		.offset = 0x1,
 | |
| 		.start = 26,
 | |
| 		.end = 26,
 | |
| 	},
 | |
| 	[TCTIMEOUT] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "tctimeout",
 | |
| 		.offset = 0x1,
 | |
| 		.start = 25,
 | |
| 		.end = 25,
 | |
| 	},
 | |
| 	[PRIORERR] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "priorerr",
 | |
| 		.offset = 0x1,
 | |
| 		.start = 24,
 | |
| 		.end = 24,
 | |
| 	},
 | |
| 	[NOMASTER] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "nomaster",
 | |
| 		.offset = 0x1,
 | |
| 		.start = 23,
 | |
| 		.end = 23,
 | |
| 	},
 | |
| 	[MEMOV] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "memov",
 | |
| 		.offset = 0x1,
 | |
| 		.start = 22,
 | |
| 		.end = 22,
 | |
| 	},
 | |
| 	[MEMERR] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "memerr",
 | |
| 		.offset = 0x1,
 | |
| 		.start = 21,
 | |
| 		.end = 21,
 | |
| 	},
 | |
| 	[INVTYP] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "invtyp",
 | |
| 		.offset = 0x1,
 | |
| 		.start = 19,
 | |
| 		.end = 19,
 | |
| 	},
 | |
| 	[INTCYOV] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "intcyov",
 | |
| 		.offset = 0x1,
 | |
| 		.start = 18,
 | |
| 		.end = 18,
 | |
| 	},
 | |
| 	[DOMERR] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "domerr",
 | |
| 		.offset = 0x1,
 | |
| 		.start = 17,
 | |
| 		.end = 17,
 | |
| 	},
 | |
| 	[PCFBAGDROP] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "pcfbagdrop",
 | |
| 		.offset = 0x1,
 | |
| 		.start = 16,
 | |
| 		.end = 16,
 | |
| 	},
 | |
| 	[SPCPRIOR] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "spcprior",
 | |
| 		.offset = 0x1,
 | |
| 		.start = 15,
 | |
| 		.end = 12,
 | |
| 	},
 | |
| 	[AGEPRIOR] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "ageprior",
 | |
| 		.offset = 0x1,
 | |
| 		.start = 11,
 | |
| 		.end = 8,
 | |
| 	},
 | |
| 	[PORTDROP] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "portdrop",
 | |
| 		.offset = 0x1,
 | |
| 		.start = 6,
 | |
| 		.end = 6,
 | |
| 	},
 | |
| 	[LENDROP] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "lendrop",
 | |
| 		.offset = 0x1,
 | |
| 		.start = 5,
 | |
| 		.end = 5,
 | |
| 	},
 | |
| 	[BAGDROP] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "bagdrop",
 | |
| 		.offset = 0x1,
 | |
| 		.start = 4,
 | |
| 		.end = 4,
 | |
| 	},
 | |
| 	[POLICEERR] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "policeerr",
 | |
| 		.offset = 0x1,
 | |
| 		.start = 3,
 | |
| 		.end = 3,
 | |
| 	},
 | |
| 	[DRPNONA664ERR] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "drpnona664err",
 | |
| 		.offset = 0x1,
 | |
| 		.start = 2,
 | |
| 		.end = 2,
 | |
| 	},
 | |
| 	[SPCERR] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "spcerr",
 | |
| 		.offset = 0x1,
 | |
| 		.start = 1,
 | |
| 		.end = 1,
 | |
| 	},
 | |
| 	[AGEDRP] = {
 | |
| 		.area = MAC,
 | |
| 		.name = "agedrp",
 | |
| 		.offset = 0x1,
 | |
| 		.start = 0,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	/* High-Level Diagnostic Counters */
 | |
| 	[N_N664ERR] = {
 | |
| 		.area = HL1,
 | |
| 		.name = "n_n664err",
 | |
| 		.offset = 0xF,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_VLANERR] = {
 | |
| 		.area = HL1,
 | |
| 		.name = "n_vlanerr",
 | |
| 		.offset = 0xE,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_UNRELEASED] = {
 | |
| 		.area = HL1,
 | |
| 		.name = "n_unreleased",
 | |
| 		.offset = 0xD,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_SIZEERR] = {
 | |
| 		.area = HL1,
 | |
| 		.name = "n_sizeerr",
 | |
| 		.offset = 0xC,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_CRCERR] = {
 | |
| 		.area = HL1,
 | |
| 		.name = "n_crcerr",
 | |
| 		.offset = 0xB,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_VLNOTFOUND] = {
 | |
| 		.area = HL1,
 | |
| 		.name = "n_vlnotfound",
 | |
| 		.offset = 0xA,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_CTPOLERR] = {
 | |
| 		.area = HL1,
 | |
| 		.name = "n_ctpolerr",
 | |
| 		.offset = 0x9,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_POLERR] = {
 | |
| 		.area = HL1,
 | |
| 		.name = "n_polerr",
 | |
| 		.offset = 0x8,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_RXFRM] = {
 | |
| 		.area = HL1,
 | |
| 		.name = "n_rxfrm",
 | |
| 		.offset = 0x6,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 		.is_64bit = true,
 | |
| 	},
 | |
| 	[N_RXBYTE] = {
 | |
| 		.area = HL1,
 | |
| 		.name = "n_rxbyte",
 | |
| 		.offset = 0x4,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 		.is_64bit = true,
 | |
| 	},
 | |
| 	[N_TXFRM] = {
 | |
| 		.area = HL1,
 | |
| 		.name = "n_txfrm",
 | |
| 		.offset = 0x2,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 		.is_64bit = true,
 | |
| 	},
 | |
| 	[N_TXBYTE] = {
 | |
| 		.area = HL1,
 | |
| 		.name = "n_txbyte",
 | |
| 		.offset = 0x0,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 		.is_64bit = true,
 | |
| 	},
 | |
| 	[N_QFULL] = {
 | |
| 		.area = HL2,
 | |
| 		.name = "n_qfull",
 | |
| 		.offset = 0x3,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_PART_DROP] = {
 | |
| 		.area = HL2,
 | |
| 		.name = "n_part_drop",
 | |
| 		.offset = 0x2,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_EGR_DISABLED] = {
 | |
| 		.area = HL2,
 | |
| 		.name = "n_egr_disabled",
 | |
| 		.offset = 0x1,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_NOT_REACH] = {
 | |
| 		.area = HL2,
 | |
| 		.name = "n_not_reach",
 | |
| 		.offset = 0x0,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	/* Ether Stats */
 | |
| 	[N_DROPS_NOLEARN] = {
 | |
| 		.area = ETHER,
 | |
| 		.name = "n_drops_nolearn",
 | |
| 		.offset = 0x16,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_DROPS_NOROUTE] = {
 | |
| 		.area = ETHER,
 | |
| 		.name = "n_drops_noroute",
 | |
| 		.offset = 0x15,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_DROPS_ILL_DTAG] = {
 | |
| 		.area = ETHER,
 | |
| 		.name = "n_drops_ill_dtag",
 | |
| 		.offset = 0x14,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_DROPS_DTAG] = {
 | |
| 		.area = ETHER,
 | |
| 		.name = "n_drops_dtag",
 | |
| 		.offset = 0x13,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_DROPS_SOTAG] = {
 | |
| 		.area = ETHER,
 | |
| 		.name = "n_drops_sotag",
 | |
| 		.offset = 0x12,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_DROPS_SITAG] = {
 | |
| 		.area = ETHER,
 | |
| 		.name = "n_drops_sitag",
 | |
| 		.offset = 0x11,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_DROPS_UTAG] = {
 | |
| 		.area = ETHER,
 | |
| 		.name = "n_drops_utag",
 | |
| 		.offset = 0x10,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_TX_BYTES_1024_2047] = {
 | |
| 		.area = ETHER,
 | |
| 		.name = "n_tx_bytes_1024_2047",
 | |
| 		.offset = 0x0F,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_TX_BYTES_512_1023] = {
 | |
| 		.area = ETHER,
 | |
| 		.name = "n_tx_bytes_512_1023",
 | |
| 		.offset = 0x0E,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_TX_BYTES_256_511] = {
 | |
| 		.area = ETHER,
 | |
| 		.name = "n_tx_bytes_256_511",
 | |
| 		.offset = 0x0D,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_TX_BYTES_128_255] = {
 | |
| 		.area = ETHER,
 | |
| 		.name = "n_tx_bytes_128_255",
 | |
| 		.offset = 0x0C,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_TX_BYTES_65_127] = {
 | |
| 		.area = ETHER,
 | |
| 		.name = "n_tx_bytes_65_127",
 | |
| 		.offset = 0x0B,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_TX_BYTES_64] = {
 | |
| 		.area = ETHER,
 | |
| 		.name = "n_tx_bytes_64",
 | |
| 		.offset = 0x0A,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_TX_MCAST] = {
 | |
| 		.area = ETHER,
 | |
| 		.name = "n_tx_mcast",
 | |
| 		.offset = 0x09,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_TX_BCAST] = {
 | |
| 		.area = ETHER,
 | |
| 		.name = "n_tx_bcast",
 | |
| 		.offset = 0x08,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_RX_BYTES_1024_2047] = {
 | |
| 		.area = ETHER,
 | |
| 		.name = "n_rx_bytes_1024_2047",
 | |
| 		.offset = 0x07,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_RX_BYTES_512_1023] = {
 | |
| 		.area = ETHER,
 | |
| 		.name = "n_rx_bytes_512_1023",
 | |
| 		.offset = 0x06,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_RX_BYTES_256_511] = {
 | |
| 		.area = ETHER,
 | |
| 		.name = "n_rx_bytes_256_511",
 | |
| 		.offset = 0x05,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_RX_BYTES_128_255] = {
 | |
| 		.area = ETHER,
 | |
| 		.name = "n_rx_bytes_128_255",
 | |
| 		.offset = 0x04,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_RX_BYTES_65_127] = {
 | |
| 		.area = ETHER,
 | |
| 		.name = "n_rx_bytes_65_127",
 | |
| 		.offset = 0x03,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_RX_BYTES_64] = {
 | |
| 		.area = ETHER,
 | |
| 		.name = "n_rx_bytes_64",
 | |
| 		.offset = 0x02,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_RX_MCAST] = {
 | |
| 		.area = ETHER,
 | |
| 		.name = "n_rx_mcast",
 | |
| 		.offset = 0x01,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| 	[N_RX_BCAST] = {
 | |
| 		.area = ETHER,
 | |
| 		.name = "n_rx_bcast",
 | |
| 		.offset = 0x00,
 | |
| 		.start = 31,
 | |
| 		.end = 0,
 | |
| 	},
 | |
| };
 | |
| 
 | |
| static int sja1105_port_counter_read(struct sja1105_private *priv, int port,
 | |
| 				     enum sja1105_counter_index idx, u64 *ctr)
 | |
| {
 | |
| 	const struct sja1105_port_counter *c = &sja1105_port_counters[idx];
 | |
| 	size_t size = c->is_64bit ? 8 : 4;
 | |
| 	u8 buf[8] = {0};
 | |
| 	u64 regs;
 | |
| 	int rc;
 | |
| 
 | |
| 	regs = priv->info->regs->stats[c->area][port];
 | |
| 
 | |
| 	rc = sja1105_xfer_buf(priv, SPI_READ, regs + c->offset, buf, size);
 | |
| 	if (rc)
 | |
| 		return rc;
 | |
| 
 | |
| 	sja1105_unpack(buf, ctr, c->start, c->end, size);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| void sja1105_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data)
 | |
| {
 | |
| 	struct sja1105_private *priv = ds->priv;
 | |
| 	enum sja1105_counter_index max_ctr, i;
 | |
| 	int rc, k = 0;
 | |
| 
 | |
| 	if (priv->info->device_id == SJA1105E_DEVICE_ID ||
 | |
| 	    priv->info->device_id == SJA1105T_DEVICE_ID)
 | |
| 		max_ctr = __MAX_SJA1105ET_PORT_COUNTER;
 | |
| 	else
 | |
| 		max_ctr = __MAX_SJA1105PQRS_PORT_COUNTER;
 | |
| 
 | |
| 	for (i = 0; i < max_ctr; i++) {
 | |
| 		rc = sja1105_port_counter_read(priv, port, i, &data[k++]);
 | |
| 		if (rc) {
 | |
| 			dev_err(ds->dev,
 | |
| 				"Failed to read port %d counters: %d\n",
 | |
| 				port, rc);
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void sja1105_get_strings(struct dsa_switch *ds, int port,
 | |
| 			 u32 stringset, u8 *data)
 | |
| {
 | |
| 	struct sja1105_private *priv = ds->priv;
 | |
| 	enum sja1105_counter_index max_ctr, i;
 | |
| 	char *p = data;
 | |
| 
 | |
| 	if (stringset != ETH_SS_STATS)
 | |
| 		return;
 | |
| 
 | |
| 	if (priv->info->device_id == SJA1105E_DEVICE_ID ||
 | |
| 	    priv->info->device_id == SJA1105T_DEVICE_ID)
 | |
| 		max_ctr = __MAX_SJA1105ET_PORT_COUNTER;
 | |
| 	else
 | |
| 		max_ctr = __MAX_SJA1105PQRS_PORT_COUNTER;
 | |
| 
 | |
| 	for (i = 0; i < max_ctr; i++) {
 | |
| 		strscpy(p, sja1105_port_counters[i].name, ETH_GSTRING_LEN);
 | |
| 		p += ETH_GSTRING_LEN;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| int sja1105_get_sset_count(struct dsa_switch *ds, int port, int sset)
 | |
| {
 | |
| 	struct sja1105_private *priv = ds->priv;
 | |
| 	enum sja1105_counter_index max_ctr, i;
 | |
| 	int sset_count = 0;
 | |
| 
 | |
| 	if (sset != ETH_SS_STATS)
 | |
| 		return -EOPNOTSUPP;
 | |
| 
 | |
| 	if (priv->info->device_id == SJA1105E_DEVICE_ID ||
 | |
| 	    priv->info->device_id == SJA1105T_DEVICE_ID)
 | |
| 		max_ctr = __MAX_SJA1105ET_PORT_COUNTER;
 | |
| 	else
 | |
| 		max_ctr = __MAX_SJA1105PQRS_PORT_COUNTER;
 | |
| 
 | |
| 	for (i = 0; i < max_ctr; i++) {
 | |
| 		if (!strlen(sja1105_port_counters[i].name))
 | |
| 			continue;
 | |
| 
 | |
| 		sset_count++;
 | |
| 	}
 | |
| 
 | |
| 	return sset_count;
 | |
| }
 |