@@ -43,6 +43,8 @@ static const char gve_gstrings_main_stats[][ETH_GSTRING_LEN] = {
4343static const char gve_gstrings_rx_stats [][ETH_GSTRING_LEN ] = {
4444 "rx_posted_desc[%u]" , "rx_completed_desc[%u]" , "rx_bytes[%u]" ,
4545 "rx_dropped_pkt[%u]" , "rx_copybreak_pkt[%u]" , "rx_copied_pkt[%u]" ,
46+ "rx_queue_drop_cnt[%u]" , "rx_no_buffers_posted[%u]" ,
47+ "rx_drops_packet_over_mru[%u]" , "rx_drops_invalid_checksum[%u]" ,
4648};
4749
4850static const char gve_gstrings_tx_stats [][ETH_GSTRING_LEN ] = {
@@ -138,14 +140,30 @@ gve_get_ethtool_stats(struct net_device *netdev,
138140 tmp_rx_desc_err_dropped_pkt , tmp_tx_pkts , tmp_tx_bytes ;
139141 u64 rx_buf_alloc_fail , rx_desc_err_dropped_pkt , rx_pkts ,
140142 rx_skb_alloc_fail , rx_bytes , tx_pkts , tx_bytes ;
143+ int stats_idx , base_stats_idx , max_stats_idx ;
144+ struct stats * report_stats ;
145+ int * rx_qid_to_stats_idx ;
146+ int * tx_qid_to_stats_idx ;
141147 struct gve_priv * priv ;
148+ bool skip_nic_stats ;
142149 unsigned int start ;
143150 int ring ;
144- int i ;
151+ int i , j ;
145152
146153 ASSERT_RTNL ();
147154
148155 priv = netdev_priv (netdev );
156+ report_stats = priv -> stats_report -> stats ;
157+ rx_qid_to_stats_idx = kmalloc_array (priv -> rx_cfg .num_queues ,
158+ sizeof (int ), GFP_KERNEL );
159+ if (!rx_qid_to_stats_idx )
160+ return ;
161+ tx_qid_to_stats_idx = kmalloc_array (priv -> tx_cfg .num_queues ,
162+ sizeof (int ), GFP_KERNEL );
163+ if (!tx_qid_to_stats_idx ) {
164+ kfree (rx_qid_to_stats_idx );
165+ return ;
166+ }
149167 for (rx_pkts = 0 , rx_bytes = 0 , rx_skb_alloc_fail = 0 ,
150168 rx_buf_alloc_fail = 0 , rx_desc_err_dropped_pkt = 0 , ring = 0 ;
151169 ring < priv -> rx_cfg .num_queues ; ring ++ ) {
@@ -208,6 +226,25 @@ gve_get_ethtool_stats(struct net_device *netdev,
208226 data [i ++ ] = priv -> stats_report_trigger_cnt ;
209227 i = GVE_MAIN_STATS_LEN ;
210228
229+ /* For rx cross-reporting stats, start from nic rx stats in report */
230+ base_stats_idx = GVE_TX_STATS_REPORT_NUM * priv -> tx_cfg .num_queues +
231+ GVE_RX_STATS_REPORT_NUM * priv -> rx_cfg .num_queues ;
232+ max_stats_idx = NIC_RX_STATS_REPORT_NUM * priv -> rx_cfg .num_queues +
233+ base_stats_idx ;
234+ /* Preprocess the stats report for rx, map queue id to start index */
235+ skip_nic_stats = false;
236+ for (stats_idx = base_stats_idx ; stats_idx < max_stats_idx ;
237+ stats_idx += NIC_RX_STATS_REPORT_NUM ) {
238+ u32 stat_name = be32_to_cpu (report_stats [stats_idx ].stat_name );
239+ u32 queue_id = be32_to_cpu (report_stats [stats_idx ].queue_id );
240+
241+ if (stat_name == 0 ) {
242+ /* no stats written by NIC yet */
243+ skip_nic_stats = true;
244+ break ;
245+ }
246+ rx_qid_to_stats_idx [queue_id ] = stats_idx ;
247+ }
211248 /* walk RX rings */
212249 if (priv -> rx ) {
213250 for (ring = 0 ; ring < priv -> rx_cfg .num_queues ; ring ++ ) {
@@ -232,10 +269,41 @@ gve_get_ethtool_stats(struct net_device *netdev,
232269 tmp_rx_desc_err_dropped_pkt ;
233270 data [i ++ ] = rx -> rx_copybreak_pkt ;
234271 data [i ++ ] = rx -> rx_copied_pkt ;
272+ /* stats from NIC */
273+ if (skip_nic_stats ) {
274+ /* skip NIC rx stats */
275+ i += NIC_RX_STATS_REPORT_NUM ;
276+ continue ;
277+ }
278+ for (j = 0 ; j < NIC_RX_STATS_REPORT_NUM ; j ++ ) {
279+ u64 value =
280+ be64_to_cpu (report_stats [rx_qid_to_stats_idx [ring ] + j ].value );
281+
282+ data [i ++ ] = value ;
283+ }
235284 }
236285 } else {
237286 i += priv -> rx_cfg .num_queues * NUM_GVE_RX_CNTS ;
238287 }
288+
289+ /* For tx cross-reporting stats, start from nic tx stats in report */
290+ base_stats_idx = max_stats_idx ;
291+ max_stats_idx = NIC_TX_STATS_REPORT_NUM * priv -> tx_cfg .num_queues +
292+ max_stats_idx ;
293+ /* Preprocess the stats report for tx, map queue id to start index */
294+ skip_nic_stats = false;
295+ for (stats_idx = base_stats_idx ; stats_idx < max_stats_idx ;
296+ stats_idx += NIC_TX_STATS_REPORT_NUM ) {
297+ u32 stat_name = be32_to_cpu (report_stats [stats_idx ].stat_name );
298+ u32 queue_id = be32_to_cpu (report_stats [stats_idx ].queue_id );
299+
300+ if (stat_name == 0 ) {
301+ /* no stats written by NIC yet */
302+ skip_nic_stats = true;
303+ break ;
304+ }
305+ tx_qid_to_stats_idx [queue_id ] = stats_idx ;
306+ }
239307 /* walk TX rings */
240308 if (priv -> tx ) {
241309 for (ring = 0 ; ring < priv -> tx_cfg .num_queues ; ring ++ ) {
@@ -254,10 +322,24 @@ gve_get_ethtool_stats(struct net_device *netdev,
254322 data [i ++ ] = tx -> stop_queue ;
255323 data [i ++ ] = be32_to_cpu (gve_tx_load_event_counter (priv ,
256324 tx ));
325+ /* stats from NIC */
326+ if (skip_nic_stats ) {
327+ /* skip NIC tx stats */
328+ i += NIC_TX_STATS_REPORT_NUM ;
329+ continue ;
330+ }
331+ for (j = 0 ; j < NIC_TX_STATS_REPORT_NUM ; j ++ ) {
332+ u64 value =
333+ be64_to_cpu (report_stats [tx_qid_to_stats_idx [ring ] + j ].value );
334+ data [i ++ ] = value ;
335+ }
257336 }
258337 } else {
259338 i += priv -> tx_cfg .num_queues * NUM_GVE_TX_CNTS ;
260339 }
340+
341+ kfree (rx_qid_to_stats_idx );
342+ kfree (tx_qid_to_stats_idx );
261343 /* AQ Stats */
262344 data [i ++ ] = priv -> adminq_prod_cnt ;
263345 data [i ++ ] = priv -> adminq_cmd_fail ;
0 commit comments