aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/sfc/ef10.c2
-rw-r--r--drivers/net/ethernet/sfc/efx.c11
-rw-r--r--drivers/net/ethernet/sfc/falcon.c10
-rw-r--r--drivers/net/ethernet/sfc/mcdi.h1
-rw-r--r--drivers/net/ethernet/sfc/mcdi_port.c49
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h5
-rw-r--r--drivers/net/ethernet/sfc/nic.c12
-rw-r--r--drivers/net/ethernet/sfc/nic.h1
-rw-r--r--drivers/net/ethernet/sfc/siena.c3
9 files changed, 83 insertions, 11 deletions
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index e9c546bdbdfe..c1b85edcb204 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -902,6 +902,7 @@ static int efx_ef10_try_update_nic_stats(struct efx_nic *efx)
902 return -EAGAIN; 902 return -EAGAIN;
903 903
904 /* Update derived statistics */ 904 /* Update derived statistics */
905 efx_nic_fix_nodesc_drop_stat(efx, &stats[EF10_STAT_rx_nodesc_drops]);
905 stats[EF10_STAT_rx_good_bytes] = 906 stats[EF10_STAT_rx_good_bytes] =
906 stats[EF10_STAT_rx_bytes] - 907 stats[EF10_STAT_rx_bytes] -
907 stats[EF10_STAT_rx_bytes_minus_good_bytes]; 908 stats[EF10_STAT_rx_bytes_minus_good_bytes];
@@ -3423,6 +3424,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
3423 .describe_stats = efx_ef10_describe_stats, 3424 .describe_stats = efx_ef10_describe_stats,
3424 .update_stats = efx_ef10_update_stats, 3425 .update_stats = efx_ef10_update_stats,
3425 .start_stats = efx_mcdi_mac_start_stats, 3426 .start_stats = efx_mcdi_mac_start_stats,
3427 .pull_stats = efx_mcdi_mac_pull_stats,
3426 .stop_stats = efx_mcdi_mac_stop_stats, 3428 .stop_stats = efx_mcdi_mac_stop_stats,
3427 .set_id_led = efx_mcdi_set_id_led, 3429 .set_id_led = efx_mcdi_set_id_led,
3428 .push_irq_moderation = efx_ef10_push_irq_moderation, 3430 .push_irq_moderation = efx_ef10_push_irq_moderation,
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 5e2454d07137..c734fba8c99c 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1684,6 +1684,10 @@ static void efx_start_all(struct efx_nic *efx)
1684 } 1684 }
1685 1685
1686 efx->type->start_stats(efx); 1686 efx->type->start_stats(efx);
1687 efx->type->pull_stats(efx);
1688 spin_lock_bh(&efx->stats_lock);
1689 efx->type->update_stats(efx, NULL, NULL);
1690 spin_unlock_bh(&efx->stats_lock);
1687} 1691}
1688 1692
1689/* Flush all delayed work. Should only be called when no more delayed work 1693/* Flush all delayed work. Should only be called when no more delayed work
@@ -1711,6 +1715,13 @@ static void efx_stop_all(struct efx_nic *efx)
1711 if (!efx->port_enabled) 1715 if (!efx->port_enabled)
1712 return; 1716 return;
1713 1717
1718 /* update stats before we go down so we can accurately count
1719 * rx_nodesc_drops
1720 */
1721 efx->type->pull_stats(efx);
1722 spin_lock_bh(&efx->stats_lock);
1723 efx->type->update_stats(efx, NULL, NULL);
1724 spin_unlock_bh(&efx->stats_lock);
1714 efx->type->stop_stats(efx); 1725 efx->type->stop_stats(efx);
1715 efx_stop_port(efx); 1726 efx_stop_port(efx);
1716 1727
diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c
index ff5d322b9b49..4a9e05c82e2a 100644
--- a/drivers/net/ethernet/sfc/falcon.c
+++ b/drivers/net/ethernet/sfc/falcon.c
@@ -2593,6 +2593,14 @@ void falcon_start_nic_stats(struct efx_nic *efx)
2593 spin_unlock_bh(&efx->stats_lock); 2593 spin_unlock_bh(&efx->stats_lock);
2594} 2594}
2595 2595
2596/* We don't acutally pull stats on falcon. Wait 10ms so that
2597 * they arrive when we call this just after start_stats
2598 */
2599void falcon_pull_nic_stats(struct efx_nic *efx)
2600{
2601 msleep(10);
2602}
2603
2596void falcon_stop_nic_stats(struct efx_nic *efx) 2604void falcon_stop_nic_stats(struct efx_nic *efx)
2597{ 2605{
2598 struct falcon_nic_data *nic_data = efx->nic_data; 2606 struct falcon_nic_data *nic_data = efx->nic_data;
@@ -2672,6 +2680,7 @@ const struct efx_nic_type falcon_a1_nic_type = {
2672 .describe_stats = falcon_describe_nic_stats, 2680 .describe_stats = falcon_describe_nic_stats,
2673 .update_stats = falcon_update_nic_stats, 2681 .update_stats = falcon_update_nic_stats,
2674 .start_stats = falcon_start_nic_stats, 2682 .start_stats = falcon_start_nic_stats,
2683 .pull_stats = falcon_pull_nic_stats,
2675 .stop_stats = falcon_stop_nic_stats, 2684 .stop_stats = falcon_stop_nic_stats,
2676 .set_id_led = falcon_set_id_led, 2685 .set_id_led = falcon_set_id_led,
2677 .push_irq_moderation = falcon_push_irq_moderation, 2686 .push_irq_moderation = falcon_push_irq_moderation,
@@ -2765,6 +2774,7 @@ const struct efx_nic_type falcon_b0_nic_type = {
2765 .describe_stats = falcon_describe_nic_stats, 2774 .describe_stats = falcon_describe_nic_stats,
2766 .update_stats = falcon_update_nic_stats, 2775 .update_stats = falcon_update_nic_stats,
2767 .start_stats = falcon_start_nic_stats, 2776 .start_stats = falcon_start_nic_stats,
2777 .pull_stats = falcon_pull_nic_stats,
2768 .stop_stats = falcon_stop_nic_stats, 2778 .stop_stats = falcon_stop_nic_stats,
2769 .set_id_led = falcon_set_id_led, 2779 .set_id_led = falcon_set_id_led,
2770 .push_irq_moderation = falcon_push_irq_moderation, 2780 .push_irq_moderation = falcon_push_irq_moderation,
diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h
index 15816cacb548..d861628b7ee6 100644
--- a/drivers/net/ethernet/sfc/mcdi.h
+++ b/drivers/net/ethernet/sfc/mcdi.h
@@ -301,6 +301,7 @@ int efx_mcdi_set_mac(struct efx_nic *efx);
301#define EFX_MC_STATS_GENERATION_INVALID ((__force __le64)(-1)) 301#define EFX_MC_STATS_GENERATION_INVALID ((__force __le64)(-1))
302void efx_mcdi_mac_start_stats(struct efx_nic *efx); 302void efx_mcdi_mac_start_stats(struct efx_nic *efx);
303void efx_mcdi_mac_stop_stats(struct efx_nic *efx); 303void efx_mcdi_mac_stop_stats(struct efx_nic *efx);
304void efx_mcdi_mac_pull_stats(struct efx_nic *efx);
304bool efx_mcdi_mac_check_fault(struct efx_nic *efx); 305bool efx_mcdi_mac_check_fault(struct efx_nic *efx);
305enum reset_type efx_mcdi_map_reset_reason(enum reset_type reason); 306enum reset_type efx_mcdi_map_reset_reason(enum reset_type reason);
306int efx_mcdi_reset(struct efx_nic *efx, enum reset_type method); 307int efx_mcdi_reset(struct efx_nic *efx, enum reset_type method);
diff --git a/drivers/net/ethernet/sfc/mcdi_port.c b/drivers/net/ethernet/sfc/mcdi_port.c
index 7b6be61d549f..7288aefc2877 100644
--- a/drivers/net/ethernet/sfc/mcdi_port.c
+++ b/drivers/net/ethernet/sfc/mcdi_port.c
@@ -927,12 +927,23 @@ bool efx_mcdi_mac_check_fault(struct efx_nic *efx)
927 return MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT) != 0; 927 return MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT) != 0;
928} 928}
929 929
930static int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr, 930enum efx_stats_action {
931 u32 dma_len, int enable, int clear) 931 EFX_STATS_ENABLE,
932 EFX_STATS_DISABLE,
933 EFX_STATS_PULL,
934};
935
936static int efx_mcdi_mac_stats(struct efx_nic *efx,
937 enum efx_stats_action action, int clear)
932{ 938{
933 MCDI_DECLARE_BUF(inbuf, MC_CMD_MAC_STATS_IN_LEN); 939 MCDI_DECLARE_BUF(inbuf, MC_CMD_MAC_STATS_IN_LEN);
934 int rc; 940 int rc;
935 int period = enable ? 1000 : 0; 941 int change = action == EFX_STATS_PULL ? 0 : 1;
942 int enable = action == EFX_STATS_ENABLE ? 1 : 0;
943 int period = action == EFX_STATS_ENABLE ? 1000 : 0;
944 dma_addr_t dma_addr = efx->stats_buffer.dma_addr;
945 u32 dma_len = action != EFX_STATS_DISABLE ?
946 MC_CMD_MAC_NSTATS * sizeof(u64) : 0;
936 947
937 BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_DMA_LEN != 0); 948 BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_DMA_LEN != 0);
938 949
@@ -940,8 +951,8 @@ static int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr,
940 MCDI_POPULATE_DWORD_7(inbuf, MAC_STATS_IN_CMD, 951 MCDI_POPULATE_DWORD_7(inbuf, MAC_STATS_IN_CMD,
941 MAC_STATS_IN_DMA, !!enable, 952 MAC_STATS_IN_DMA, !!enable,
942 MAC_STATS_IN_CLEAR, clear, 953 MAC_STATS_IN_CLEAR, clear,
943 MAC_STATS_IN_PERIODIC_CHANGE, 1, 954 MAC_STATS_IN_PERIODIC_CHANGE, change,
944 MAC_STATS_IN_PERIODIC_ENABLE, !!enable, 955 MAC_STATS_IN_PERIODIC_ENABLE, enable,
945 MAC_STATS_IN_PERIODIC_CLEAR, 0, 956 MAC_STATS_IN_PERIODIC_CLEAR, 0,
946 MAC_STATS_IN_PERIODIC_NOEVENT, 1, 957 MAC_STATS_IN_PERIODIC_NOEVENT, 1,
947 MAC_STATS_IN_PERIOD_MS, period); 958 MAC_STATS_IN_PERIOD_MS, period);
@@ -955,8 +966,8 @@ static int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr,
955 return 0; 966 return 0;
956 967
957fail: 968fail:
958 netif_err(efx, hw, efx->net_dev, "%s: %s failed rc=%d\n", 969 netif_err(efx, hw, efx->net_dev, "%s: action %d failed rc=%d\n",
959 __func__, enable ? "enable" : "disable", rc); 970 __func__, action, rc);
960 return rc; 971 return rc;
961} 972}
962 973
@@ -966,13 +977,29 @@ void efx_mcdi_mac_start_stats(struct efx_nic *efx)
966 977
967 dma_stats[MC_CMD_MAC_GENERATION_END] = EFX_MC_STATS_GENERATION_INVALID; 978 dma_stats[MC_CMD_MAC_GENERATION_END] = EFX_MC_STATS_GENERATION_INVALID;
968 979
969 efx_mcdi_mac_stats(efx, efx->stats_buffer.dma_addr, 980 efx_mcdi_mac_stats(efx, EFX_STATS_ENABLE, 0);
970 MC_CMD_MAC_NSTATS * sizeof(u64), 1, 0);
971} 981}
972 982
973void efx_mcdi_mac_stop_stats(struct efx_nic *efx) 983void efx_mcdi_mac_stop_stats(struct efx_nic *efx)
974{ 984{
975 efx_mcdi_mac_stats(efx, efx->stats_buffer.dma_addr, 0, 0, 0); 985 efx_mcdi_mac_stats(efx, EFX_STATS_DISABLE, 0);
986}
987
988#define EFX_MAC_STATS_WAIT_US 100
989#define EFX_MAC_STATS_WAIT_ATTEMPTS 10
990
991void efx_mcdi_mac_pull_stats(struct efx_nic *efx)
992{
993 __le64 *dma_stats = efx->stats_buffer.addr;
994 int attempts = EFX_MAC_STATS_WAIT_ATTEMPTS;
995
996 dma_stats[MC_CMD_MAC_GENERATION_END] = EFX_MC_STATS_GENERATION_INVALID;
997 efx_mcdi_mac_stats(efx, EFX_STATS_PULL, 0);
998
999 while (dma_stats[MC_CMD_MAC_GENERATION_END] ==
1000 EFX_MC_STATS_GENERATION_INVALID &&
1001 attempts-- != 0)
1002 udelay(EFX_MAC_STATS_WAIT_US);
976} 1003}
977 1004
978int efx_mcdi_port_probe(struct efx_nic *efx) 1005int efx_mcdi_port_probe(struct efx_nic *efx)
@@ -1003,7 +1030,7 @@ int efx_mcdi_port_probe(struct efx_nic *efx)
1003 efx->stats_buffer.addr, 1030 efx->stats_buffer.addr,
1004 (u64)virt_to_phys(efx->stats_buffer.addr)); 1031 (u64)virt_to_phys(efx->stats_buffer.addr));
1005 1032
1006 efx_mcdi_mac_stats(efx, efx->stats_buffer.dma_addr, 0, 0, 1); 1033 efx_mcdi_mac_stats(efx, EFX_STATS_DISABLE, 1);
1007 1034
1008 return 0; 1035 return 0;
1009} 1036}
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index d98b3f031ab5..f47bac78b92c 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -857,6 +857,9 @@ struct efx_nic {
857 struct net_device *net_dev; 857 struct net_device *net_dev;
858 858
859 struct efx_buffer stats_buffer; 859 struct efx_buffer stats_buffer;
860 u64 rx_nodesc_drops_total;
861 u64 rx_nodesc_drops_while_down;
862 bool rx_nodesc_drops_prev_state;
860 863
861 unsigned int phy_type; 864 unsigned int phy_type;
862 const struct efx_phy_operations *phy_op; 865 const struct efx_phy_operations *phy_op;
@@ -960,6 +963,7 @@ struct efx_mtd_partition {
960 * @update_stats: Update statistics not provided by event handling. 963 * @update_stats: Update statistics not provided by event handling.
961 * Either argument may be %NULL. 964 * Either argument may be %NULL.
962 * @start_stats: Start the regular fetching of statistics 965 * @start_stats: Start the regular fetching of statistics
966 * @pull_stats: Pull stats from the NIC and wait until they arrive.
963 * @stop_stats: Stop the regular fetching of statistics 967 * @stop_stats: Stop the regular fetching of statistics
964 * @set_id_led: Set state of identifying LED or revert to automatic function 968 * @set_id_led: Set state of identifying LED or revert to automatic function
965 * @push_irq_moderation: Apply interrupt moderation value 969 * @push_irq_moderation: Apply interrupt moderation value
@@ -1078,6 +1082,7 @@ struct efx_nic_type {
1078 size_t (*update_stats)(struct efx_nic *efx, u64 *full_stats, 1082 size_t (*update_stats)(struct efx_nic *efx, u64 *full_stats,
1079 struct rtnl_link_stats64 *core_stats); 1083 struct rtnl_link_stats64 *core_stats);
1080 void (*start_stats)(struct efx_nic *efx); 1084 void (*start_stats)(struct efx_nic *efx);
1085 void (*pull_stats)(struct efx_nic *efx);
1081 void (*stop_stats)(struct efx_nic *efx); 1086 void (*stop_stats)(struct efx_nic *efx);
1082 void (*set_id_led)(struct efx_nic *efx, enum efx_led_mode mode); 1087 void (*set_id_led)(struct efx_nic *efx, enum efx_led_mode mode);
1083 void (*push_irq_moderation)(struct efx_channel *channel); 1088 void (*push_irq_moderation)(struct efx_channel *channel);
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index 9c90bf56090f..79226b19e3c4 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -519,3 +519,15 @@ void efx_nic_update_stats(const struct efx_hw_stat_desc *desc, size_t count,
519 } 519 }
520 } 520 }
521} 521}
522
523void efx_nic_fix_nodesc_drop_stat(struct efx_nic *efx, u64 *rx_nodesc_drops)
524{
525 /* if down, or this is the first update after coming up */
526 if (!(efx->net_dev->flags & IFF_UP) || !efx->rx_nodesc_drops_prev_state)
527 efx->rx_nodesc_drops_while_down +=
528 *rx_nodesc_drops - efx->rx_nodesc_drops_total;
529 efx->rx_nodesc_drops_total = *rx_nodesc_drops;
530 efx->rx_nodesc_drops_prev_state = !!(efx->net_dev->flags & IFF_UP);
531 *rx_nodesc_drops -= efx->rx_nodesc_drops_while_down;
532}
533
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index fe71e81ee8bf..7ac9c000696f 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -775,6 +775,7 @@ size_t efx_nic_describe_stats(const struct efx_hw_stat_desc *desc, size_t count,
775void efx_nic_update_stats(const struct efx_hw_stat_desc *desc, size_t count, 775void efx_nic_update_stats(const struct efx_hw_stat_desc *desc, size_t count,
776 const unsigned long *mask, u64 *stats, 776 const unsigned long *mask, u64 *stats,
777 const void *dma_buf, bool accumulate); 777 const void *dma_buf, bool accumulate);
778void efx_nic_fix_nodesc_drop_stat(struct efx_nic *efx, u64 *stat);
778 779
779#define EFX_MAX_FLUSH_TIME 5000 780#define EFX_MAX_FLUSH_TIME 5000
780 781
diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c
index d034bcd124ef..f2a7ad4c76aa 100644
--- a/drivers/net/ethernet/sfc/siena.c
+++ b/drivers/net/ethernet/sfc/siena.c
@@ -458,6 +458,8 @@ static int siena_try_update_nic_stats(struct efx_nic *efx)
458 return -EAGAIN; 458 return -EAGAIN;
459 459
460 /* Update derived statistics */ 460 /* Update derived statistics */
461 efx_nic_fix_nodesc_drop_stat(efx,
462 &stats[SIENA_STAT_rx_nodesc_drop_cnt]);
461 efx_update_diff_stat(&stats[SIENA_STAT_tx_good_bytes], 463 efx_update_diff_stat(&stats[SIENA_STAT_tx_good_bytes],
462 stats[SIENA_STAT_tx_bytes] - 464 stats[SIENA_STAT_tx_bytes] -
463 stats[SIENA_STAT_tx_bad_bytes]); 465 stats[SIENA_STAT_tx_bad_bytes]);
@@ -878,6 +880,7 @@ const struct efx_nic_type siena_a0_nic_type = {
878 .describe_stats = siena_describe_nic_stats, 880 .describe_stats = siena_describe_nic_stats,
879 .update_stats = siena_update_nic_stats, 881 .update_stats = siena_update_nic_stats,
880 .start_stats = efx_mcdi_mac_start_stats, 882 .start_stats = efx_mcdi_mac_start_stats,
883 .pull_stats = efx_mcdi_mac_pull_stats,
881 .stop_stats = efx_mcdi_mac_stop_stats, 884 .stop_stats = efx_mcdi_mac_stop_stats,
882 .set_id_led = efx_mcdi_set_id_led, 885 .set_id_led = efx_mcdi_set_id_led,
883 .push_irq_moderation = siena_push_irq_moderation, 886 .push_irq_moderation = siena_push_irq_moderation,