88#include "gve.h"
99#include "gve_adminq.h"
1010#include "gve_dqo.h"
11+ #include "gve_utils.h"
1112
1213static void gve_get_drvinfo (struct net_device * netdev ,
1314 struct ethtool_drvinfo * info )
@@ -165,6 +166,8 @@ gve_get_ethtool_stats(struct net_device *netdev,
165166 struct stats * report_stats ;
166167 int * rx_qid_to_stats_idx ;
167168 int * tx_qid_to_stats_idx ;
169+ int num_stopped_rxqs = 0 ;
170+ int num_stopped_txqs = 0 ;
168171 struct gve_priv * priv ;
169172 bool skip_nic_stats ;
170173 unsigned int start ;
@@ -181,12 +184,23 @@ gve_get_ethtool_stats(struct net_device *netdev,
181184 sizeof (int ), GFP_KERNEL );
182185 if (!rx_qid_to_stats_idx )
183186 return ;
187+ for (ring = 0 ; ring < priv -> rx_cfg .num_queues ; ring ++ ) {
188+ rx_qid_to_stats_idx [ring ] = -1 ;
189+ if (!gve_rx_was_added_to_block (priv , ring ))
190+ num_stopped_rxqs ++ ;
191+ }
184192 tx_qid_to_stats_idx = kmalloc_array (num_tx_queues ,
185193 sizeof (int ), GFP_KERNEL );
186194 if (!tx_qid_to_stats_idx ) {
187195 kfree (rx_qid_to_stats_idx );
188196 return ;
189197 }
198+ for (ring = 0 ; ring < num_tx_queues ; ring ++ ) {
199+ tx_qid_to_stats_idx [ring ] = -1 ;
200+ if (!gve_tx_was_added_to_block (priv , ring ))
201+ num_stopped_txqs ++ ;
202+ }
203+
190204 for (rx_pkts = 0 , rx_bytes = 0 , rx_hsplit_pkt = 0 ,
191205 rx_skb_alloc_fail = 0 , rx_buf_alloc_fail = 0 ,
192206 rx_desc_err_dropped_pkt = 0 , rx_hsplit_unsplit_pkt = 0 ,
@@ -260,7 +274,13 @@ gve_get_ethtool_stats(struct net_device *netdev,
260274 /* For rx cross-reporting stats, start from nic rx stats in report */
261275 base_stats_idx = GVE_TX_STATS_REPORT_NUM * num_tx_queues +
262276 GVE_RX_STATS_REPORT_NUM * priv -> rx_cfg .num_queues ;
263- max_stats_idx = NIC_RX_STATS_REPORT_NUM * priv -> rx_cfg .num_queues +
277+ /* The boundary between driver stats and NIC stats shifts if there are
278+ * stopped queues.
279+ */
280+ base_stats_idx += NIC_RX_STATS_REPORT_NUM * num_stopped_rxqs +
281+ NIC_TX_STATS_REPORT_NUM * num_stopped_txqs ;
282+ max_stats_idx = NIC_RX_STATS_REPORT_NUM *
283+ (priv -> rx_cfg .num_queues - num_stopped_rxqs ) +
264284 base_stats_idx ;
265285 /* Preprocess the stats report for rx, map queue id to start index */
266286 skip_nic_stats = false;
@@ -274,6 +294,10 @@ gve_get_ethtool_stats(struct net_device *netdev,
274294 skip_nic_stats = true;
275295 break ;
276296 }
297+ if (queue_id < 0 || queue_id >= priv -> rx_cfg .num_queues ) {
298+ net_err_ratelimited ("Invalid rxq id in NIC stats\n" );
299+ continue ;
300+ }
277301 rx_qid_to_stats_idx [queue_id ] = stats_idx ;
278302 }
279303 /* walk RX rings */
@@ -308,11 +332,11 @@ gve_get_ethtool_stats(struct net_device *netdev,
308332 data [i ++ ] = rx -> rx_copybreak_pkt ;
309333 data [i ++ ] = rx -> rx_copied_pkt ;
310334 /* stats from NIC */
311- if (skip_nic_stats ) {
335+ stats_idx = rx_qid_to_stats_idx [ring ];
336+ if (skip_nic_stats || stats_idx < 0 ) {
312337 /* skip NIC rx stats */
313338 i += NIC_RX_STATS_REPORT_NUM ;
314339 } else {
315- stats_idx = rx_qid_to_stats_idx [ring ];
316340 for (j = 0 ; j < NIC_RX_STATS_REPORT_NUM ; j ++ ) {
317341 u64 value =
318342 be64_to_cpu (report_stats [stats_idx + j ].value );
@@ -338,7 +362,8 @@ gve_get_ethtool_stats(struct net_device *netdev,
338362
339363 /* For tx cross-reporting stats, start from nic tx stats in report */
340364 base_stats_idx = max_stats_idx ;
341- max_stats_idx = NIC_TX_STATS_REPORT_NUM * num_tx_queues +
365+ max_stats_idx = NIC_TX_STATS_REPORT_NUM *
366+ (num_tx_queues - num_stopped_txqs ) +
342367 max_stats_idx ;
343368 /* Preprocess the stats report for tx, map queue id to start index */
344369 skip_nic_stats = false;
@@ -352,6 +377,10 @@ gve_get_ethtool_stats(struct net_device *netdev,
352377 skip_nic_stats = true;
353378 break ;
354379 }
380+ if (queue_id < 0 || queue_id >= num_tx_queues ) {
381+ net_err_ratelimited ("Invalid txq id in NIC stats\n" );
382+ continue ;
383+ }
355384 tx_qid_to_stats_idx [queue_id ] = stats_idx ;
356385 }
357386 /* walk TX rings */
@@ -383,11 +412,11 @@ gve_get_ethtool_stats(struct net_device *netdev,
383412 data [i ++ ] = gve_tx_load_event_counter (priv , tx );
384413 data [i ++ ] = tx -> dma_mapping_error ;
385414 /* stats from NIC */
386- if (skip_nic_stats ) {
415+ stats_idx = tx_qid_to_stats_idx [ring ];
416+ if (skip_nic_stats || stats_idx < 0 ) {
387417 /* skip NIC tx stats */
388418 i += NIC_TX_STATS_REPORT_NUM ;
389419 } else {
390- stats_idx = tx_qid_to_stats_idx [ring ];
391420 for (j = 0 ; j < NIC_TX_STATS_REPORT_NUM ; j ++ ) {
392421 u64 value =
393422 be64_to_cpu (report_stats [stats_idx + j ].value );
0 commit comments