aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Rybchenko <Andrew.Rybchenko@oktetlabs.ru>2014-07-17 07:10:43 -0400
committerDavid S. Miller <davem@davemloft.net>2014-07-17 19:48:36 -0400
commit8ccf3800dbdeaf26bcdefa471c9c8e0da7e6ec7a (patch)
treee88c2ea06aaed738991c1f3336c088f1eb9181c2
parent87b200e11bb50e90471a69fe1af01e8fce8995aa (diff)
sfc: Add per-queue statistics in ethtool
Implement per channel software TX and RX packet counters accessed as ethtool statistics. This allows confirmation with MAC statistics. Signed-off-by: Shradha Shah <sshah@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/sfc/ethtool.c58
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h4
-rw-r--r--drivers/net/ethernet/sfc/rx.c2
-rw-r--r--drivers/net/ethernet/sfc/tx.c4
4 files changed, 66 insertions, 2 deletions
diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c
index 03fe4e715024..cad258a78708 100644
--- a/drivers/net/ethernet/sfc/ethtool.c
+++ b/drivers/net/ethernet/sfc/ethtool.c
@@ -359,6 +359,37 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
359 return n; 359 return n;
360} 360}
361 361
362static size_t efx_describe_per_queue_stats(struct efx_nic *efx, u8 *strings)
363{
364 size_t n_stats = 0;
365 struct efx_channel *channel;
366
367 efx_for_each_channel(channel, efx) {
368 if (efx_channel_has_tx_queues(channel)) {
369 n_stats++;
370 if (strings != NULL) {
371 snprintf(strings, ETH_GSTRING_LEN,
372 "tx-%u.tx_packets",
373 channel->tx_queue[0].queue /
374 EFX_TXQ_TYPES);
375
376 strings += ETH_GSTRING_LEN;
377 }
378 }
379 }
380 efx_for_each_channel(channel, efx) {
381 if (efx_channel_has_rx_queue(channel)) {
382 n_stats++;
383 if (strings != NULL) {
384 snprintf(strings, ETH_GSTRING_LEN,
385 "rx-%d.rx_packets", channel->channel);
386 strings += ETH_GSTRING_LEN;
387 }
388 }
389 }
390 return n_stats;
391}
392
362static int efx_ethtool_get_sset_count(struct net_device *net_dev, 393static int efx_ethtool_get_sset_count(struct net_device *net_dev,
363 int string_set) 394 int string_set)
364{ 395{
@@ -367,8 +398,9 @@ static int efx_ethtool_get_sset_count(struct net_device *net_dev,
367 switch (string_set) { 398 switch (string_set) {
368 case ETH_SS_STATS: 399 case ETH_SS_STATS:
369 return efx->type->describe_stats(efx, NULL) + 400 return efx->type->describe_stats(efx, NULL) +
370 EFX_ETHTOOL_SW_STAT_COUNT + 401 EFX_ETHTOOL_SW_STAT_COUNT +
371 efx_ptp_describe_stats(efx, NULL); 402 efx_describe_per_queue_stats(efx, NULL) +
403 efx_ptp_describe_stats(efx, NULL);
372 case ETH_SS_TEST: 404 case ETH_SS_TEST:
373 return efx_ethtool_fill_self_tests(efx, NULL, NULL, NULL); 405 return efx_ethtool_fill_self_tests(efx, NULL, NULL, NULL);
374 default: 406 default:
@@ -390,6 +422,8 @@ static void efx_ethtool_get_strings(struct net_device *net_dev,
390 strlcpy(strings + i * ETH_GSTRING_LEN, 422 strlcpy(strings + i * ETH_GSTRING_LEN,
391 efx_sw_stat_desc[i].name, ETH_GSTRING_LEN); 423 efx_sw_stat_desc[i].name, ETH_GSTRING_LEN);
392 strings += EFX_ETHTOOL_SW_STAT_COUNT * ETH_GSTRING_LEN; 424 strings += EFX_ETHTOOL_SW_STAT_COUNT * ETH_GSTRING_LEN;
425 strings += (efx_describe_per_queue_stats(efx, strings) *
426 ETH_GSTRING_LEN);
393 efx_ptp_describe_stats(efx, strings); 427 efx_ptp_describe_stats(efx, strings);
394 break; 428 break;
395 case ETH_SS_TEST: 429 case ETH_SS_TEST:
@@ -409,6 +443,7 @@ static void efx_ethtool_get_stats(struct net_device *net_dev,
409 const struct efx_sw_stat_desc *stat; 443 const struct efx_sw_stat_desc *stat;
410 struct efx_channel *channel; 444 struct efx_channel *channel;
411 struct efx_tx_queue *tx_queue; 445 struct efx_tx_queue *tx_queue;
446 struct efx_rx_queue *rx_queue;
412 int i; 447 int i;
413 448
414 spin_lock_bh(&efx->stats_lock); 449 spin_lock_bh(&efx->stats_lock);
@@ -444,6 +479,25 @@ static void efx_ethtool_get_stats(struct net_device *net_dev,
444 479
445 spin_unlock_bh(&efx->stats_lock); 480 spin_unlock_bh(&efx->stats_lock);
446 481
482 efx_for_each_channel(channel, efx) {
483 if (efx_channel_has_tx_queues(channel)) {
484 *data = 0;
485 efx_for_each_channel_tx_queue(tx_queue, channel) {
486 *data += tx_queue->tx_packets;
487 }
488 data++;
489 }
490 }
491 efx_for_each_channel(channel, efx) {
492 if (efx_channel_has_rx_queue(channel)) {
493 *data = 0;
494 efx_for_each_channel_rx_queue(rx_queue, channel) {
495 *data += rx_queue->rx_packets;
496 }
497 data++;
498 }
499 }
500
447 efx_ptp_update_stats(efx, data); 501 efx_ptp_update_stats(efx, data);
448} 502}
449 503
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 8a02d45ed667..fb2e3bfeb2c2 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -249,6 +249,8 @@ struct efx_tx_queue {
249 unsigned int tso_packets; 249 unsigned int tso_packets;
250 unsigned int pushes; 250 unsigned int pushes;
251 unsigned int pio_packets; 251 unsigned int pio_packets;
252 /* Statistics to supplement MAC stats */
253 unsigned long tx_packets;
252 254
253 /* Members shared between paths and sometimes updated */ 255 /* Members shared between paths and sometimes updated */
254 unsigned int empty_read_count ____cacheline_aligned_in_smp; 256 unsigned int empty_read_count ____cacheline_aligned_in_smp;
@@ -358,6 +360,8 @@ struct efx_rx_queue {
358 unsigned int recycle_count; 360 unsigned int recycle_count;
359 struct timer_list slow_fill; 361 struct timer_list slow_fill;
360 unsigned int slow_fill_count; 362 unsigned int slow_fill_count;
363 /* Statistics to supplement MAC stats */
364 unsigned long rx_packets;
361}; 365};
362 366
363enum efx_sync_events_state { 367enum efx_sync_events_state {
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index bf537a2a901f..a7bb63a7a521 100644
--- a/drivers/net/ethernet/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -530,6 +530,8 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
530 struct efx_channel *channel = efx_rx_queue_channel(rx_queue); 530 struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
531 struct efx_rx_buffer *rx_buf; 531 struct efx_rx_buffer *rx_buf;
532 532
533 rx_queue->rx_packets++;
534
533 rx_buf = efx_rx_buffer(rx_queue, index); 535 rx_buf = efx_rx_buffer(rx_queue, index);
534 rx_buf->flags |= flags; 536 rx_buf->flags |= flags;
535 537
diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c
index ede8dcca0ff3..283e5f87b09f 100644
--- a/drivers/net/ethernet/sfc/tx.c
+++ b/drivers/net/ethernet/sfc/tx.c
@@ -452,6 +452,8 @@ finish_packet:
452 /* Pass off to hardware */ 452 /* Pass off to hardware */
453 efx_nic_push_buffers(tx_queue); 453 efx_nic_push_buffers(tx_queue);
454 454
455 tx_queue->tx_packets++;
456
455 efx_tx_maybe_stop_queue(tx_queue); 457 efx_tx_maybe_stop_queue(tx_queue);
456 458
457 return NETDEV_TX_OK; 459 return NETDEV_TX_OK;
@@ -1245,6 +1247,8 @@ static int tso_start_new_packet(struct efx_tx_queue *tx_queue,
1245 1247
1246 ++tx_queue->tso_packets; 1248 ++tx_queue->tso_packets;
1247 1249
1250 ++tx_queue->tx_packets;
1251
1248 return 0; 1252 return 0;
1249} 1253}
1250 1254