@@ -3833,11 +3833,145 @@ static void rocker_port_get_drvinfo(struct net_device *dev,
38333833 strlcpy (drvinfo -> version , UTS_RELEASE , sizeof (drvinfo -> version ));
38343834}
38353835
3836+ static struct rocker_port_stats {
3837+ char str [ETH_GSTRING_LEN ];
3838+ int type ;
3839+ } rocker_port_stats [] = {
3840+ { "rx_packets" , ROCKER_TLV_CMD_PORT_STATS_RX_PKTS , },
3841+ { "rx_bytes" , ROCKER_TLV_CMD_PORT_STATS_RX_BYTES , },
3842+ { "rx_dropped" , ROCKER_TLV_CMD_PORT_STATS_RX_DROPPED , },
3843+ { "rx_errors" , ROCKER_TLV_CMD_PORT_STATS_RX_ERRORS , },
3844+
3845+ { "tx_packets" , ROCKER_TLV_CMD_PORT_STATS_TX_PKTS , },
3846+ { "tx_bytes" , ROCKER_TLV_CMD_PORT_STATS_TX_BYTES , },
3847+ { "tx_dropped" , ROCKER_TLV_CMD_PORT_STATS_TX_DROPPED , },
3848+ { "tx_errors" , ROCKER_TLV_CMD_PORT_STATS_TX_ERRORS , },
3849+ };
3850+
3851+ #define ROCKER_PORT_STATS_LEN ARRAY_SIZE(rocker_port_stats)
3852+
3853+ static void rocker_port_get_strings (struct net_device * netdev , u32 stringset ,
3854+ u8 * data )
3855+ {
3856+ u8 * p = data ;
3857+ int i ;
3858+
3859+ switch (stringset ) {
3860+ case ETH_SS_STATS :
3861+ for (i = 0 ; i < ARRAY_SIZE (rocker_port_stats ); i ++ ) {
3862+ memcpy (p , rocker_port_stats [i ].str , ETH_GSTRING_LEN );
3863+ p += ETH_GSTRING_LEN ;
3864+ }
3865+ break ;
3866+ }
3867+ }
3868+
3869+ static int
3870+ rocker_cmd_get_port_stats_prep (struct rocker * rocker ,
3871+ struct rocker_port * rocker_port ,
3872+ struct rocker_desc_info * desc_info ,
3873+ void * priv )
3874+ {
3875+ struct rocker_tlv * cmd_stats ;
3876+
3877+ if (rocker_tlv_put_u16 (desc_info , ROCKER_TLV_CMD_TYPE ,
3878+ ROCKER_TLV_CMD_TYPE_GET_PORT_STATS ))
3879+ return - EMSGSIZE ;
3880+
3881+ cmd_stats = rocker_tlv_nest_start (desc_info , ROCKER_TLV_CMD_INFO );
3882+ if (!cmd_stats )
3883+ return - EMSGSIZE ;
3884+
3885+ if (rocker_tlv_put_u32 (desc_info , ROCKER_TLV_CMD_PORT_STATS_LPORT ,
3886+ rocker_port -> lport ))
3887+ return - EMSGSIZE ;
3888+
3889+ rocker_tlv_nest_end (desc_info , cmd_stats );
3890+
3891+ return 0 ;
3892+ }
3893+
3894+ static int
3895+ rocker_cmd_get_port_stats_ethtool_proc (struct rocker * rocker ,
3896+ struct rocker_port * rocker_port ,
3897+ struct rocker_desc_info * desc_info ,
3898+ void * priv )
3899+ {
3900+ struct rocker_tlv * attrs [ROCKER_TLV_CMD_MAX + 1 ];
3901+ struct rocker_tlv * stats_attrs [ROCKER_TLV_CMD_PORT_STATS_MAX + 1 ];
3902+ struct rocker_tlv * pattr ;
3903+ u32 lport ;
3904+ u64 * data = priv ;
3905+ int i ;
3906+
3907+ rocker_tlv_parse_desc (attrs , ROCKER_TLV_CMD_MAX , desc_info );
3908+
3909+ if (!attrs [ROCKER_TLV_CMD_INFO ])
3910+ return - EIO ;
3911+
3912+ rocker_tlv_parse_nested (stats_attrs , ROCKER_TLV_CMD_PORT_STATS_MAX ,
3913+ attrs [ROCKER_TLV_CMD_INFO ]);
3914+
3915+ if (!stats_attrs [ROCKER_TLV_CMD_PORT_STATS_LPORT ])
3916+ return - EIO ;
3917+
3918+ lport = rocker_tlv_get_u32 (stats_attrs [ROCKER_TLV_CMD_PORT_STATS_LPORT ]);
3919+ if (lport != rocker_port -> lport )
3920+ return - EIO ;
3921+
3922+ for (i = 0 ; i < ARRAY_SIZE (rocker_port_stats ); i ++ ) {
3923+ pattr = stats_attrs [rocker_port_stats [i ].type ];
3924+ if (!pattr )
3925+ continue ;
3926+
3927+ data [i ] = rocker_tlv_get_u64 (pattr );
3928+ }
3929+
3930+ return 0 ;
3931+ }
3932+
3933+ static int rocker_cmd_get_port_stats_ethtool (struct rocker_port * rocker_port ,
3934+ void * priv )
3935+ {
3936+ return rocker_cmd_exec (rocker_port -> rocker , rocker_port ,
3937+ rocker_cmd_get_port_stats_prep , NULL ,
3938+ rocker_cmd_get_port_stats_ethtool_proc ,
3939+ priv , false);
3940+ }
3941+
3942+ static void rocker_port_get_stats (struct net_device * dev ,
3943+ struct ethtool_stats * stats , u64 * data )
3944+ {
3945+ struct rocker_port * rocker_port = netdev_priv (dev );
3946+
3947+ if (rocker_cmd_get_port_stats_ethtool (rocker_port , data ) != 0 ) {
3948+ int i ;
3949+
3950+ for (i = 0 ; i < ARRAY_SIZE (rocker_port_stats ); ++ i )
3951+ data [i ] = 0 ;
3952+ }
3953+
3954+ return ;
3955+ }
3956+
3957+ static int rocker_port_get_sset_count (struct net_device * netdev , int sset )
3958+ {
3959+ switch (sset ) {
3960+ case ETH_SS_STATS :
3961+ return ROCKER_PORT_STATS_LEN ;
3962+ default :
3963+ return - EOPNOTSUPP ;
3964+ }
3965+ }
3966+
38363967static const struct ethtool_ops rocker_port_ethtool_ops = {
38373968 .get_settings = rocker_port_get_settings ,
38383969 .set_settings = rocker_port_set_settings ,
38393970 .get_drvinfo = rocker_port_get_drvinfo ,
38403971 .get_link = ethtool_op_get_link ,
3972+ .get_strings = rocker_port_get_strings ,
3973+ .get_ethtool_stats = rocker_port_get_stats ,
3974+ .get_sset_count = rocker_port_get_sset_count ,
38413975};
38423976
38433977/*****************
0 commit comments