@@ -107,32 +107,29 @@ struct virtnet_rq_stats {
107107 u64_stats_t kicks ;
108108};
109109
110- #define VIRTNET_SQ_STAT (m ) offsetof(struct virtnet_sq_stats, m)
111- #define VIRTNET_RQ_STAT (m ) offsetof(struct virtnet_rq_stats, m)
110+ #define VIRTNET_SQ_STAT (name , m ) {name, offsetof(struct virtnet_sq_stats, m)}
111+ #define VIRTNET_RQ_STAT (name , m ) {name, offsetof(struct virtnet_rq_stats, m)}
112112
113113static const struct virtnet_stat_desc virtnet_sq_stats_desc [] = {
114- { "packets" , VIRTNET_SQ_STAT ( packets ) } ,
115- { "bytes" , VIRTNET_SQ_STAT ( bytes ) } ,
116- { "xdp_tx" , VIRTNET_SQ_STAT ( xdp_tx ) } ,
117- { "xdp_tx_drops" , VIRTNET_SQ_STAT ( xdp_tx_drops ) } ,
118- { "kicks" , VIRTNET_SQ_STAT ( kicks ) } ,
119- { "tx_timeouts" , VIRTNET_SQ_STAT ( tx_timeouts ) } ,
114+ VIRTNET_SQ_STAT ( "packets" , packets ),
115+ VIRTNET_SQ_STAT ( "bytes" , bytes ),
116+ VIRTNET_SQ_STAT ( "xdp_tx" , xdp_tx ),
117+ VIRTNET_SQ_STAT ( "xdp_tx_drops" , xdp_tx_drops ),
118+ VIRTNET_SQ_STAT ( "kicks" , kicks ),
119+ VIRTNET_SQ_STAT ( "tx_timeouts" , tx_timeouts ),
120120};
121121
122122static const struct virtnet_stat_desc virtnet_rq_stats_desc [] = {
123- { "packets" , VIRTNET_RQ_STAT ( packets ) } ,
124- { "bytes" , VIRTNET_RQ_STAT ( bytes ) } ,
125- { "drops" , VIRTNET_RQ_STAT ( drops ) } ,
126- { "xdp_packets" , VIRTNET_RQ_STAT ( xdp_packets ) } ,
127- { "xdp_tx" , VIRTNET_RQ_STAT ( xdp_tx ) } ,
128- { "xdp_redirects" , VIRTNET_RQ_STAT ( xdp_redirects ) } ,
129- { "xdp_drops" , VIRTNET_RQ_STAT ( xdp_drops ) } ,
130- { "kicks" , VIRTNET_RQ_STAT ( kicks ) } ,
123+ VIRTNET_RQ_STAT ( "packets" , packets ),
124+ VIRTNET_RQ_STAT ( "bytes" , bytes ),
125+ VIRTNET_RQ_STAT ( "drops" , drops ),
126+ VIRTNET_RQ_STAT ( "xdp_packets" , xdp_packets ),
127+ VIRTNET_RQ_STAT ( "xdp_tx" , xdp_tx ),
128+ VIRTNET_RQ_STAT ( "xdp_redirects" , xdp_redirects ),
129+ VIRTNET_RQ_STAT ( "xdp_drops" , xdp_drops ),
130+ VIRTNET_RQ_STAT ( "kicks" , kicks ),
131131};
132132
133- #define VIRTNET_SQ_STATS_LEN ARRAY_SIZE(virtnet_sq_stats_desc)
134- #define VIRTNET_RQ_STATS_LEN ARRAY_SIZE(virtnet_rq_stats_desc)
135-
136133#define VIRTNET_STATS_DESC_CQ (name ) \
137134 {#name, offsetof(struct virtio_net_stats_cvq, name)}
138135
@@ -2210,7 +2207,7 @@ static int virtnet_receive(struct receive_queue *rq, int budget,
22102207
22112208 u64_stats_set (& stats .packets , packets );
22122209 u64_stats_update_begin (& rq -> stats .syncp );
2213- for (i = 0 ; i < VIRTNET_RQ_STATS_LEN ; i ++ ) {
2210+ for (i = 0 ; i < ARRAY_SIZE ( virtnet_rq_stats_desc ) ; i ++ ) {
22142211 size_t offset = virtnet_rq_stats_desc [i ].offset ;
22152212 u64_stats_t * item , * src ;
22162213
@@ -3386,16 +3383,13 @@ static void virtnet_stats_sprintf(u8 **p, const char *fmt, const char *noq_fmt,
33863383 }
33873384}
33883385
3389- static void virtnet_get_hw_stats_string (struct virtnet_info * vi , int type , int qid , u8 * * data )
3386+ static void virtnet_get_stats_string (struct virtnet_info * vi , int type , int qid , u8 * * data )
33903387{
33913388 const struct virtnet_stat_desc * desc ;
33923389 const char * fmt , * noq_fmt ;
33933390 u8 * p = * data ;
33943391 u32 num = 0 ;
33953392
3396- if (!virtio_has_feature (vi -> vdev , VIRTIO_NET_F_DEVICE_STATS ))
3397- return ;
3398-
33993393 if (type == VIRTNET_Q_TYPE_CQ ) {
34003394 noq_fmt = "cq_hw_%s" ;
34013395
@@ -3408,6 +3402,13 @@ static void virtnet_get_hw_stats_string(struct virtnet_info *vi, int type, int q
34083402 }
34093403
34103404 if (type == VIRTNET_Q_TYPE_RX ) {
3405+ fmt = "rx%u_%s" ;
3406+
3407+ desc = & virtnet_rq_stats_desc [0 ];
3408+ num = ARRAY_SIZE (virtnet_rq_stats_desc );
3409+
3410+ virtnet_stats_sprintf (& p , fmt , NULL , num , qid , desc );
3411+
34113412 fmt = "rx%u_hw_%s" ;
34123413
34133414 if (vi -> device_stats_cap & VIRTIO_NET_STATS_TYPE_RX_BASIC ) {
@@ -3433,6 +3434,13 @@ static void virtnet_get_hw_stats_string(struct virtnet_info *vi, int type, int q
34333434 }
34343435
34353436 if (type == VIRTNET_Q_TYPE_TX ) {
3437+ fmt = "tx%u_%s" ;
3438+
3439+ desc = & virtnet_sq_stats_desc [0 ];
3440+ num = ARRAY_SIZE (virtnet_sq_stats_desc );
3441+
3442+ virtnet_stats_sprintf (& p , fmt , NULL , num , qid , desc );
3443+
34363444 fmt = "tx%u_hw_%s" ;
34373445
34383446 if (vi -> device_stats_cap & VIRTIO_NET_STATS_TYPE_TX_BASIC ) {
@@ -3482,6 +3490,9 @@ static void virtnet_stats_ctx_init(struct virtnet_info *vi,
34823490
34833491 ctx -> data = data ;
34843492
3493+ ctx -> desc_num [VIRTNET_Q_TYPE_RX ] = ARRAY_SIZE (virtnet_rq_stats_desc );
3494+ ctx -> desc_num [VIRTNET_Q_TYPE_TX ] = ARRAY_SIZE (virtnet_sq_stats_desc );
3495+
34853496 if (vi -> device_stats_cap & VIRTIO_NET_STATS_TYPE_CVQ ) {
34863497 queue_type = VIRTNET_Q_TYPE_CQ ;
34873498
@@ -3532,37 +3543,55 @@ static void virtnet_stats_ctx_init(struct virtnet_info *vi,
35323543}
35333544
35343545/* virtnet_fill_stats - copy the stats to ethtool -S
3535- * The stats source is the device.
3546+ * The stats source is the device or the driver .
35363547 *
35373548 * @vi: virtio net info
35383549 * @qid: the vq id
35393550 * @ctx: stats ctx (initiated by virtnet_stats_ctx_init())
3540- * @base: pointer to the device reply.
3541- * @type: the type of the device reply
3551+ * @base: pointer to the device reply or the driver stats structure.
3552+ * @drv_stats: designate the base type (device reply, driver stats)
3553+ * @type: the type of the device reply (if drv_stats is true, this must be zero)
35423554 */
35433555static void virtnet_fill_stats (struct virtnet_info * vi , u32 qid ,
35443556 struct virtnet_stats_ctx * ctx ,
3545- const u8 * base , u8 reply_type )
3557+ const u8 * base , bool drv_stats , u8 reply_type )
35463558{
35473559 u32 queue_type , num_rx , num_tx , num_cq ;
35483560 const struct virtnet_stat_desc * desc ;
3561+ const u64_stats_t * v_stat ;
35493562 u64 offset , bitmap ;
35503563 const __le64 * v ;
35513564 int i , num ;
35523565
3553- num_rx = VIRTNET_RQ_STATS_LEN + ctx -> desc_num [VIRTNET_Q_TYPE_RX ];
3554- num_tx = VIRTNET_SQ_STATS_LEN + ctx -> desc_num [VIRTNET_Q_TYPE_TX ];
35553566 num_cq = ctx -> desc_num [VIRTNET_Q_TYPE_CQ ];
3567+ num_rx = ctx -> desc_num [VIRTNET_Q_TYPE_RX ];
3568+ num_tx = ctx -> desc_num [VIRTNET_Q_TYPE_TX ];
35563569
35573570 queue_type = vq_type (vi , qid );
35583571 bitmap = ctx -> bitmap [queue_type ];
35593572 offset = 0 ;
35603573
35613574 if (queue_type == VIRTNET_Q_TYPE_TX ) {
3562- offset = num_cq + num_rx * vi -> curr_queue_pairs + num_tx * (qid / 2 );
3563- offset += VIRTNET_SQ_STATS_LEN ;
3575+ offset += num_cq + num_rx * vi -> curr_queue_pairs + num_tx * (qid / 2 );
3576+
3577+ num = ARRAY_SIZE (virtnet_sq_stats_desc );
3578+ if (drv_stats ) {
3579+ desc = & virtnet_sq_stats_desc [0 ];
3580+ goto drv_stats ;
3581+ }
3582+
3583+ offset += num ;
3584+
35643585 } else if (queue_type == VIRTNET_Q_TYPE_RX ) {
3565- offset = num_cq + num_rx * (qid / 2 ) + VIRTNET_RQ_STATS_LEN ;
3586+ offset += num_cq + num_rx * (qid / 2 );
3587+
3588+ num = ARRAY_SIZE (virtnet_rq_stats_desc );
3589+ if (drv_stats ) {
3590+ desc = & virtnet_rq_stats_desc [0 ];
3591+ goto drv_stats ;
3592+ }
3593+
3594+ offset += num ;
35663595 }
35673596
35683597 if (bitmap & VIRTIO_NET_STATS_TYPE_CVQ ) {
@@ -3635,6 +3664,14 @@ static void virtnet_fill_stats(struct virtnet_info *vi, u32 qid,
36353664 v = (const __le64 * )(base + desc [i ].offset );
36363665 ctx -> data [offset + i ] = le64_to_cpu (* v );
36373666 }
3667+
3668+ return ;
3669+
3670+ drv_stats :
3671+ for (i = 0 ; i < num ; ++ i ) {
3672+ v_stat = (const u64_stats_t * )(base + desc [i ].offset );
3673+ ctx -> data [offset + i ] = u64_stats_read (v_stat );
3674+ }
36383675}
36393676
36403677static int __virtnet_get_hw_stats (struct virtnet_info * vi ,
@@ -3661,7 +3698,7 @@ static int __virtnet_get_hw_stats(struct virtnet_info *vi,
36613698 for (p = reply ; p - reply < res_size ; p += le16_to_cpu (hdr -> size )) {
36623699 hdr = p ;
36633700 qid = le16_to_cpu (hdr -> vq_index );
3664- virtnet_fill_stats (vi , qid , ctx , p , hdr -> type );
3701+ virtnet_fill_stats (vi , qid , ctx , p , false, hdr -> type );
36653702 }
36663703
36673704 return 0 ;
@@ -3738,28 +3775,18 @@ static int virtnet_get_hw_stats(struct virtnet_info *vi,
37383775static void virtnet_get_strings (struct net_device * dev , u32 stringset , u8 * data )
37393776{
37403777 struct virtnet_info * vi = netdev_priv (dev );
3741- unsigned int i , j ;
3778+ unsigned int i ;
37423779 u8 * p = data ;
37433780
37443781 switch (stringset ) {
37453782 case ETH_SS_STATS :
3746- virtnet_get_hw_stats_string (vi , VIRTNET_Q_TYPE_CQ , 0 , & p );
3747-
3748- for (i = 0 ; i < vi -> curr_queue_pairs ; i ++ ) {
3749- for (j = 0 ; j < VIRTNET_RQ_STATS_LEN ; j ++ )
3750- ethtool_sprintf (& p , "rx%u_%s" , i ,
3751- virtnet_rq_stats_desc [j ].desc );
3783+ virtnet_get_stats_string (vi , VIRTNET_Q_TYPE_CQ , 0 , & p );
37523784
3753- virtnet_get_hw_stats_string ( vi , VIRTNET_Q_TYPE_RX , i , & p );
3754- }
3785+ for ( i = 0 ; i < vi -> curr_queue_pairs ; ++ i )
3786+ virtnet_get_stats_string ( vi , VIRTNET_Q_TYPE_RX , i , & p );
37553787
3756- for (i = 0 ; i < vi -> curr_queue_pairs ; i ++ ) {
3757- for (j = 0 ; j < VIRTNET_SQ_STATS_LEN ; j ++ )
3758- ethtool_sprintf (& p , "tx%u_%s" , i ,
3759- virtnet_sq_stats_desc [j ].desc );
3760-
3761- virtnet_get_hw_stats_string (vi , VIRTNET_Q_TYPE_TX , i , & p );
3762- }
3788+ for (i = 0 ; i < vi -> curr_queue_pairs ; ++ i )
3789+ virtnet_get_stats_string (vi , VIRTNET_Q_TYPE_TX , i , & p );
37633790 break ;
37643791 }
37653792}
@@ -3774,8 +3801,7 @@ static int virtnet_get_sset_count(struct net_device *dev, int sset)
37743801 case ETH_SS_STATS :
37753802 virtnet_stats_ctx_init (vi , & ctx , NULL );
37763803
3777- pair_count = VIRTNET_RQ_STATS_LEN + VIRTNET_SQ_STATS_LEN ;
3778- pair_count += ctx .desc_num [VIRTNET_Q_TYPE_RX ] + ctx .desc_num [VIRTNET_Q_TYPE_TX ];
3804+ pair_count = ctx .desc_num [VIRTNET_Q_TYPE_RX ] + ctx .desc_num [VIRTNET_Q_TYPE_TX ];
37793805
37803806 return ctx .desc_num [VIRTNET_Q_TYPE_CQ ] + vi -> curr_queue_pairs * pair_count ;
37813807 default :
@@ -3788,47 +3814,28 @@ static void virtnet_get_ethtool_stats(struct net_device *dev,
37883814{
37893815 struct virtnet_info * vi = netdev_priv (dev );
37903816 struct virtnet_stats_ctx ctx = {0 };
3791- unsigned int idx , start , i , j ;
3817+ unsigned int start , i ;
37923818 const u8 * stats_base ;
3793- const u64_stats_t * p ;
3794- size_t offset ;
37953819
37963820 virtnet_stats_ctx_init (vi , & ctx , data );
37973821 if (virtnet_get_hw_stats (vi , & ctx ))
37983822 dev_warn (& vi -> dev -> dev , "Failed to get hw stats.\n" );
37993823
3800- idx = ctx .desc_num [VIRTNET_Q_TYPE_CQ ];
3801-
38023824 for (i = 0 ; i < vi -> curr_queue_pairs ; i ++ ) {
38033825 struct receive_queue * rq = & vi -> rq [i ];
3826+ struct send_queue * sq = & vi -> sq [i ];
38043827
38053828 stats_base = (const u8 * )& rq -> stats ;
38063829 do {
38073830 start = u64_stats_fetch_begin (& rq -> stats .syncp );
3808- for (j = 0 ; j < VIRTNET_RQ_STATS_LEN ; j ++ ) {
3809- offset = virtnet_rq_stats_desc [j ].offset ;
3810- p = (const u64_stats_t * )(stats_base + offset );
3811- data [idx + j ] = u64_stats_read (p );
3812- }
3831+ virtnet_fill_stats (vi , i * 2 , & ctx , stats_base , true, 0 );
38133832 } while (u64_stats_fetch_retry (& rq -> stats .syncp , start ));
3814- idx += VIRTNET_RQ_STATS_LEN ;
3815- idx += ctx .desc_num [VIRTNET_Q_TYPE_RX ];
3816- }
3817-
3818- for (i = 0 ; i < vi -> curr_queue_pairs ; i ++ ) {
3819- struct send_queue * sq = & vi -> sq [i ];
38203833
38213834 stats_base = (const u8 * )& sq -> stats ;
38223835 do {
38233836 start = u64_stats_fetch_begin (& sq -> stats .syncp );
3824- for (j = 0 ; j < VIRTNET_SQ_STATS_LEN ; j ++ ) {
3825- offset = virtnet_sq_stats_desc [j ].offset ;
3826- p = (const u64_stats_t * )(stats_base + offset );
3827- data [idx + j ] = u64_stats_read (p );
3828- }
3837+ virtnet_fill_stats (vi , i * 2 + 1 , & ctx , stats_base , true, 0 );
38293838 } while (u64_stats_fetch_retry (& sq -> stats .syncp , start ));
3830- idx += VIRTNET_SQ_STATS_LEN ;
3831- idx += ctx .desc_num [VIRTNET_Q_TYPE_TX ];
38323839 }
38333840}
38343841
0 commit comments