diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2012-12-14 16:52:56 -0500 |
---|---|---|
committer | Ben Hutchings <bhutchings@solarflare.com> | 2013-08-27 17:25:55 -0400 |
commit | cd0ecc9a6d279c8c5c5336f576330c45f5c80939 (patch) | |
tree | db74cbf4e4e4e46e413d9d8cf53ce9f804670380 | |
parent | b681e57c38d81eee45f8bd7465d2a2af872800e3 (diff) |
sfc: Delegate MAC/NIC statistic description to efx_nic_type
Various hardware statistics that are available for Siena are
unavailable or meaningless for Falcon. Huntington adds further to the
NIC-type-specific statistics, as it has different MAC blocks from
Falcon/Siena.
All NIC types still provide most statistics by DMA, and use
little-endian byte order.
Therefore:
1. Add some general utility functions for reporting hardware statistics,
efx_nic_describe_stats() and efx_nic_update_stats().
2. Add an efx_nic_type::describe_stats operation to get the number and
names of statistics, implemented using efx_nic_describe_stats()
3. Change efx_nic_type::update_stats to store the core statistics
(struct rtnl_link_stats64) or full statistics (array of u64) in a
caller-provided buffer. Use efx_nic_update_stats() to aid in the
implementation.
4. Rename struct efx_ethtool_stat to struct efx_sw_stat_desc and
EFX_ETHTOOL_NUM_STATS to EFX_ETHTOOL_SW_STAT_COUNT.
5. Remove efx_nic::mac_stats and struct efx_mac_stats.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
-rw-r--r-- | drivers/net/ethernet/sfc/efx.c | 27 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/ethtool.c | 117 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/falcon.c | 212 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/mcdi.c | 13 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/net_driver.h | 96 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/nic.c | 83 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/nic.h | 124 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/siena.c | 215 |
8 files changed, 498 insertions, 389 deletions
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 1d4f38895b9f..9fe375f1710a 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c | |||
@@ -1920,34 +1920,9 @@ static struct rtnl_link_stats64 *efx_net_stats(struct net_device *net_dev, | |||
1920 | struct rtnl_link_stats64 *stats) | 1920 | struct rtnl_link_stats64 *stats) |
1921 | { | 1921 | { |
1922 | struct efx_nic *efx = netdev_priv(net_dev); | 1922 | struct efx_nic *efx = netdev_priv(net_dev); |
1923 | struct efx_mac_stats *mac_stats = &efx->mac_stats; | ||
1924 | 1923 | ||
1925 | spin_lock_bh(&efx->stats_lock); | 1924 | spin_lock_bh(&efx->stats_lock); |
1926 | 1925 | efx->type->update_stats(efx, NULL, stats); | |
1927 | efx->type->update_stats(efx); | ||
1928 | |||
1929 | stats->rx_packets = mac_stats->rx_packets; | ||
1930 | stats->tx_packets = mac_stats->tx_packets; | ||
1931 | stats->rx_bytes = mac_stats->rx_bytes; | ||
1932 | stats->tx_bytes = mac_stats->tx_bytes; | ||
1933 | stats->rx_dropped = efx->n_rx_nodesc_drop_cnt; | ||
1934 | stats->multicast = mac_stats->rx_multicast; | ||
1935 | stats->collisions = mac_stats->tx_collision; | ||
1936 | stats->rx_length_errors = (mac_stats->rx_gtjumbo + | ||
1937 | mac_stats->rx_length_error); | ||
1938 | stats->rx_crc_errors = mac_stats->rx_bad; | ||
1939 | stats->rx_frame_errors = mac_stats->rx_align_error; | ||
1940 | stats->rx_fifo_errors = mac_stats->rx_overflow; | ||
1941 | stats->rx_missed_errors = mac_stats->rx_missed; | ||
1942 | stats->tx_window_errors = mac_stats->tx_late_collision; | ||
1943 | |||
1944 | stats->rx_errors = (stats->rx_length_errors + | ||
1945 | stats->rx_crc_errors + | ||
1946 | stats->rx_frame_errors + | ||
1947 | mac_stats->rx_symbol_error); | ||
1948 | stats->tx_errors = (stats->tx_window_errors + | ||
1949 | mac_stats->tx_bad); | ||
1950 | |||
1951 | spin_unlock_bh(&efx->stats_lock); | 1926 | spin_unlock_bh(&efx->stats_lock); |
1952 | 1927 | ||
1953 | return stats; | 1928 | return stats; |
diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index 86b439185446..0b8ffdfba3d8 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c | |||
@@ -19,10 +19,9 @@ | |||
19 | #include "filter.h" | 19 | #include "filter.h" |
20 | #include "nic.h" | 20 | #include "nic.h" |
21 | 21 | ||
22 | struct efx_ethtool_stat { | 22 | struct efx_sw_stat_desc { |
23 | const char *name; | 23 | const char *name; |
24 | enum { | 24 | enum { |
25 | EFX_ETHTOOL_STAT_SOURCE_mac_stats, | ||
26 | EFX_ETHTOOL_STAT_SOURCE_nic, | 25 | EFX_ETHTOOL_STAT_SOURCE_nic, |
27 | EFX_ETHTOOL_STAT_SOURCE_channel, | 26 | EFX_ETHTOOL_STAT_SOURCE_channel, |
28 | EFX_ETHTOOL_STAT_SOURCE_tx_queue | 27 | EFX_ETHTOOL_STAT_SOURCE_tx_queue |
@@ -31,7 +30,7 @@ struct efx_ethtool_stat { | |||
31 | u64(*get_stat) (void *field); /* Reader function */ | 30 | u64(*get_stat) (void *field); /* Reader function */ |
32 | }; | 31 | }; |
33 | 32 | ||
34 | /* Initialiser for a struct #efx_ethtool_stat with type-checking */ | 33 | /* Initialiser for a struct efx_sw_stat_desc with type-checking */ |
35 | #define EFX_ETHTOOL_STAT(stat_name, source_name, field, field_type, \ | 34 | #define EFX_ETHTOOL_STAT(stat_name, source_name, field, field_type, \ |
36 | get_stat_function) { \ | 35 | get_stat_function) { \ |
37 | .name = #stat_name, \ | 36 | .name = #stat_name, \ |
@@ -48,24 +47,11 @@ static u64 efx_get_uint_stat(void *field) | |||
48 | return *(unsigned int *)field; | 47 | return *(unsigned int *)field; |
49 | } | 48 | } |
50 | 49 | ||
51 | static u64 efx_get_u64_stat(void *field) | ||
52 | { | ||
53 | return *(u64 *) field; | ||
54 | } | ||
55 | |||
56 | static u64 efx_get_atomic_stat(void *field) | 50 | static u64 efx_get_atomic_stat(void *field) |
57 | { | 51 | { |
58 | return atomic_read((atomic_t *) field); | 52 | return atomic_read((atomic_t *) field); |
59 | } | 53 | } |
60 | 54 | ||
61 | #define EFX_ETHTOOL_U64_MAC_STAT(field) \ | ||
62 | EFX_ETHTOOL_STAT(field, mac_stats, field, \ | ||
63 | u64, efx_get_u64_stat) | ||
64 | |||
65 | #define EFX_ETHTOOL_UINT_NIC_STAT(name) \ | ||
66 | EFX_ETHTOOL_STAT(name, nic, n_##name, \ | ||
67 | unsigned int, efx_get_uint_stat) | ||
68 | |||
69 | #define EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(field) \ | 55 | #define EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(field) \ |
70 | EFX_ETHTOOL_STAT(field, nic, field, \ | 56 | EFX_ETHTOOL_STAT(field, nic, field, \ |
71 | atomic_t, efx_get_atomic_stat) | 57 | atomic_t, efx_get_atomic_stat) |
@@ -78,72 +64,11 @@ static u64 efx_get_atomic_stat(void *field) | |||
78 | EFX_ETHTOOL_STAT(tx_##field, tx_queue, field, \ | 64 | EFX_ETHTOOL_STAT(tx_##field, tx_queue, field, \ |
79 | unsigned int, efx_get_uint_stat) | 65 | unsigned int, efx_get_uint_stat) |
80 | 66 | ||
81 | static const struct efx_ethtool_stat efx_ethtool_stats[] = { | 67 | static const struct efx_sw_stat_desc efx_sw_stat_desc[] = { |
82 | EFX_ETHTOOL_U64_MAC_STAT(tx_bytes), | ||
83 | EFX_ETHTOOL_U64_MAC_STAT(tx_good_bytes), | ||
84 | EFX_ETHTOOL_U64_MAC_STAT(tx_bad_bytes), | ||
85 | EFX_ETHTOOL_U64_MAC_STAT(tx_packets), | ||
86 | EFX_ETHTOOL_U64_MAC_STAT(tx_bad), | ||
87 | EFX_ETHTOOL_U64_MAC_STAT(tx_pause), | ||
88 | EFX_ETHTOOL_U64_MAC_STAT(tx_control), | ||
89 | EFX_ETHTOOL_U64_MAC_STAT(tx_unicast), | ||
90 | EFX_ETHTOOL_U64_MAC_STAT(tx_multicast), | ||
91 | EFX_ETHTOOL_U64_MAC_STAT(tx_broadcast), | ||
92 | EFX_ETHTOOL_U64_MAC_STAT(tx_lt64), | ||
93 | EFX_ETHTOOL_U64_MAC_STAT(tx_64), | ||
94 | EFX_ETHTOOL_U64_MAC_STAT(tx_65_to_127), | ||
95 | EFX_ETHTOOL_U64_MAC_STAT(tx_128_to_255), | ||
96 | EFX_ETHTOOL_U64_MAC_STAT(tx_256_to_511), | ||
97 | EFX_ETHTOOL_U64_MAC_STAT(tx_512_to_1023), | ||
98 | EFX_ETHTOOL_U64_MAC_STAT(tx_1024_to_15xx), | ||
99 | EFX_ETHTOOL_U64_MAC_STAT(tx_15xx_to_jumbo), | ||
100 | EFX_ETHTOOL_U64_MAC_STAT(tx_gtjumbo), | ||
101 | EFX_ETHTOOL_U64_MAC_STAT(tx_collision), | ||
102 | EFX_ETHTOOL_U64_MAC_STAT(tx_single_collision), | ||
103 | EFX_ETHTOOL_U64_MAC_STAT(tx_multiple_collision), | ||
104 | EFX_ETHTOOL_U64_MAC_STAT(tx_excessive_collision), | ||
105 | EFX_ETHTOOL_U64_MAC_STAT(tx_deferred), | ||
106 | EFX_ETHTOOL_U64_MAC_STAT(tx_late_collision), | ||
107 | EFX_ETHTOOL_U64_MAC_STAT(tx_excessive_deferred), | ||
108 | EFX_ETHTOOL_U64_MAC_STAT(tx_non_tcpudp), | ||
109 | EFX_ETHTOOL_U64_MAC_STAT(tx_mac_src_error), | ||
110 | EFX_ETHTOOL_U64_MAC_STAT(tx_ip_src_error), | ||
111 | EFX_ETHTOOL_UINT_TXQ_STAT(tso_bursts), | 68 | EFX_ETHTOOL_UINT_TXQ_STAT(tso_bursts), |
112 | EFX_ETHTOOL_UINT_TXQ_STAT(tso_long_headers), | 69 | EFX_ETHTOOL_UINT_TXQ_STAT(tso_long_headers), |
113 | EFX_ETHTOOL_UINT_TXQ_STAT(tso_packets), | 70 | EFX_ETHTOOL_UINT_TXQ_STAT(tso_packets), |
114 | EFX_ETHTOOL_UINT_TXQ_STAT(pushes), | 71 | EFX_ETHTOOL_UINT_TXQ_STAT(pushes), |
115 | EFX_ETHTOOL_U64_MAC_STAT(rx_bytes), | ||
116 | EFX_ETHTOOL_U64_MAC_STAT(rx_good_bytes), | ||
117 | EFX_ETHTOOL_U64_MAC_STAT(rx_bad_bytes), | ||
118 | EFX_ETHTOOL_U64_MAC_STAT(rx_packets), | ||
119 | EFX_ETHTOOL_U64_MAC_STAT(rx_good), | ||
120 | EFX_ETHTOOL_U64_MAC_STAT(rx_bad), | ||
121 | EFX_ETHTOOL_U64_MAC_STAT(rx_pause), | ||
122 | EFX_ETHTOOL_U64_MAC_STAT(rx_control), | ||
123 | EFX_ETHTOOL_U64_MAC_STAT(rx_unicast), | ||
124 | EFX_ETHTOOL_U64_MAC_STAT(rx_multicast), | ||
125 | EFX_ETHTOOL_U64_MAC_STAT(rx_broadcast), | ||
126 | EFX_ETHTOOL_U64_MAC_STAT(rx_lt64), | ||
127 | EFX_ETHTOOL_U64_MAC_STAT(rx_64), | ||
128 | EFX_ETHTOOL_U64_MAC_STAT(rx_65_to_127), | ||
129 | EFX_ETHTOOL_U64_MAC_STAT(rx_128_to_255), | ||
130 | EFX_ETHTOOL_U64_MAC_STAT(rx_256_to_511), | ||
131 | EFX_ETHTOOL_U64_MAC_STAT(rx_512_to_1023), | ||
132 | EFX_ETHTOOL_U64_MAC_STAT(rx_1024_to_15xx), | ||
133 | EFX_ETHTOOL_U64_MAC_STAT(rx_15xx_to_jumbo), | ||
134 | EFX_ETHTOOL_U64_MAC_STAT(rx_gtjumbo), | ||
135 | EFX_ETHTOOL_U64_MAC_STAT(rx_bad_lt64), | ||
136 | EFX_ETHTOOL_U64_MAC_STAT(rx_bad_64_to_15xx), | ||
137 | EFX_ETHTOOL_U64_MAC_STAT(rx_bad_15xx_to_jumbo), | ||
138 | EFX_ETHTOOL_U64_MAC_STAT(rx_bad_gtjumbo), | ||
139 | EFX_ETHTOOL_U64_MAC_STAT(rx_overflow), | ||
140 | EFX_ETHTOOL_U64_MAC_STAT(rx_missed), | ||
141 | EFX_ETHTOOL_U64_MAC_STAT(rx_false_carrier), | ||
142 | EFX_ETHTOOL_U64_MAC_STAT(rx_symbol_error), | ||
143 | EFX_ETHTOOL_U64_MAC_STAT(rx_align_error), | ||
144 | EFX_ETHTOOL_U64_MAC_STAT(rx_length_error), | ||
145 | EFX_ETHTOOL_U64_MAC_STAT(rx_internal_error), | ||
146 | EFX_ETHTOOL_UINT_NIC_STAT(rx_nodesc_drop_cnt), | ||
147 | EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(rx_reset), | 72 | EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(rx_reset), |
148 | EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tobe_disc), | 73 | EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tobe_disc), |
149 | EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_ip_hdr_chksum_err), | 74 | EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_ip_hdr_chksum_err), |
@@ -153,8 +78,7 @@ static const struct efx_ethtool_stat efx_ethtool_stats[] = { | |||
153 | EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_nodesc_trunc), | 78 | EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_nodesc_trunc), |
154 | }; | 79 | }; |
155 | 80 | ||
156 | /* Number of ethtool statistics */ | 81 | #define EFX_ETHTOOL_SW_STAT_COUNT ARRAY_SIZE(efx_sw_stat_desc) |
157 | #define EFX_ETHTOOL_NUM_STATS ARRAY_SIZE(efx_ethtool_stats) | ||
158 | 82 | ||
159 | #define EFX_ETHTOOL_EEPROM_MAGIC 0xEFAB | 83 | #define EFX_ETHTOOL_EEPROM_MAGIC 0xEFAB |
160 | 84 | ||
@@ -424,12 +348,14 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx, | |||
424 | static int efx_ethtool_get_sset_count(struct net_device *net_dev, | 348 | static int efx_ethtool_get_sset_count(struct net_device *net_dev, |
425 | int string_set) | 349 | int string_set) |
426 | { | 350 | { |
351 | struct efx_nic *efx = netdev_priv(net_dev); | ||
352 | |||
427 | switch (string_set) { | 353 | switch (string_set) { |
428 | case ETH_SS_STATS: | 354 | case ETH_SS_STATS: |
429 | return EFX_ETHTOOL_NUM_STATS; | 355 | return efx->type->describe_stats(efx, NULL) + |
356 | EFX_ETHTOOL_SW_STAT_COUNT; | ||
430 | case ETH_SS_TEST: | 357 | case ETH_SS_TEST: |
431 | return efx_ethtool_fill_self_tests(netdev_priv(net_dev), | 358 | return efx_ethtool_fill_self_tests(efx, NULL, NULL, NULL); |
432 | NULL, NULL, NULL); | ||
433 | default: | 359 | default: |
434 | return -EINVAL; | 360 | return -EINVAL; |
435 | } | 361 | } |
@@ -443,9 +369,11 @@ static void efx_ethtool_get_strings(struct net_device *net_dev, | |||
443 | 369 | ||
444 | switch (string_set) { | 370 | switch (string_set) { |
445 | case ETH_SS_STATS: | 371 | case ETH_SS_STATS: |
446 | for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++) | 372 | strings += (efx->type->describe_stats(efx, strings) * |
373 | ETH_GSTRING_LEN); | ||
374 | for (i = 0; i < EFX_ETHTOOL_SW_STAT_COUNT; i++) | ||
447 | strlcpy(strings + i * ETH_GSTRING_LEN, | 375 | strlcpy(strings + i * ETH_GSTRING_LEN, |
448 | efx_ethtool_stats[i].name, ETH_GSTRING_LEN); | 376 | efx_sw_stat_desc[i].name, ETH_GSTRING_LEN); |
449 | break; | 377 | break; |
450 | case ETH_SS_TEST: | 378 | case ETH_SS_TEST: |
451 | efx_ethtool_fill_self_tests(efx, NULL, strings, NULL); | 379 | efx_ethtool_fill_self_tests(efx, NULL, strings, NULL); |
@@ -461,27 +389,20 @@ static void efx_ethtool_get_stats(struct net_device *net_dev, | |||
461 | u64 *data) | 389 | u64 *data) |
462 | { | 390 | { |
463 | struct efx_nic *efx = netdev_priv(net_dev); | 391 | struct efx_nic *efx = netdev_priv(net_dev); |
464 | struct efx_mac_stats *mac_stats = &efx->mac_stats; | 392 | const struct efx_sw_stat_desc *stat; |
465 | const struct efx_ethtool_stat *stat; | ||
466 | struct efx_channel *channel; | 393 | struct efx_channel *channel; |
467 | struct efx_tx_queue *tx_queue; | 394 | struct efx_tx_queue *tx_queue; |
468 | int i; | 395 | int i; |
469 | 396 | ||
470 | EFX_BUG_ON_PARANOID(stats->n_stats != EFX_ETHTOOL_NUM_STATS); | ||
471 | |||
472 | spin_lock_bh(&efx->stats_lock); | 397 | spin_lock_bh(&efx->stats_lock); |
473 | 398 | ||
474 | /* Update MAC and NIC statistics */ | 399 | /* Get NIC statistics */ |
475 | efx->type->update_stats(efx); | 400 | data += efx->type->update_stats(efx, data, NULL); |
476 | 401 | ||
477 | /* Fill detailed statistics buffer */ | 402 | /* Get software statistics */ |
478 | for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++) { | 403 | for (i = 0; i < EFX_ETHTOOL_SW_STAT_COUNT; i++) { |
479 | stat = &efx_ethtool_stats[i]; | 404 | stat = &efx_sw_stat_desc[i]; |
480 | switch (stat->source) { | 405 | switch (stat->source) { |
481 | case EFX_ETHTOOL_STAT_SOURCE_mac_stats: | ||
482 | data[i] = stat->get_stat((void *)mac_stats + | ||
483 | stat->offset); | ||
484 | break; | ||
485 | case EFX_ETHTOOL_STAT_SOURCE_nic: | 406 | case EFX_ETHTOOL_STAT_SOURCE_nic: |
486 | data[i] = stat->get_stat((void *)efx + stat->offset); | 407 | data[i] = stat->get_stat((void *)efx + stat->offset); |
487 | break; | 408 | break; |
diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index 76a9e0dd2308..0be1f3711c89 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c | |||
@@ -31,7 +31,7 @@ | |||
31 | 31 | ||
32 | /************************************************************************** | 32 | /************************************************************************** |
33 | * | 33 | * |
34 | * MAC stats DMA format | 34 | * NIC stats |
35 | * | 35 | * |
36 | ************************************************************************** | 36 | ************************************************************************** |
37 | */ | 37 | */ |
@@ -134,27 +134,67 @@ | |||
134 | #define FALCON_XMAC_STATS_DMA_FLAG(efx) \ | 134 | #define FALCON_XMAC_STATS_DMA_FLAG(efx) \ |
135 | (*(u32 *)((efx)->stats_buffer.addr + XgDmaDone_offset)) | 135 | (*(u32 *)((efx)->stats_buffer.addr + XgDmaDone_offset)) |
136 | 136 | ||
137 | #define FALCON_STAT_OFFSET(falcon_stat) EFX_VAL(falcon_stat, offset) | 137 | #define FALCON_DMA_STAT(ext_name, hw_name) \ |
138 | #define FALCON_STAT_WIDTH(falcon_stat) EFX_VAL(falcon_stat, WIDTH) | 138 | [FALCON_STAT_ ## ext_name] = \ |
139 | 139 | { #ext_name, \ | |
140 | /* Retrieve statistic from statistics block */ | 140 | /* 48-bit stats are zero-padded to 64 on DMA */ \ |
141 | #define FALCON_STAT(efx, falcon_stat, efx_stat) do { \ | 141 | hw_name ## _ ## WIDTH == 48 ? 64 : hw_name ## _ ## WIDTH, \ |
142 | if (FALCON_STAT_WIDTH(falcon_stat) == 16) \ | 142 | hw_name ## _ ## offset } |
143 | (efx)->mac_stats.efx_stat += le16_to_cpu( \ | 143 | #define FALCON_OTHER_STAT(ext_name) \ |
144 | *((__force __le16 *) \ | 144 | [FALCON_STAT_ ## ext_name] = { #ext_name, 0, 0 } |
145 | (efx->stats_buffer.addr + \ | 145 | |
146 | FALCON_STAT_OFFSET(falcon_stat)))); \ | 146 | static const struct efx_hw_stat_desc falcon_stat_desc[FALCON_STAT_COUNT] = { |
147 | else if (FALCON_STAT_WIDTH(falcon_stat) == 32) \ | 147 | FALCON_DMA_STAT(tx_bytes, XgTxOctets), |
148 | (efx)->mac_stats.efx_stat += le32_to_cpu( \ | 148 | FALCON_DMA_STAT(tx_packets, XgTxPkts), |
149 | *((__force __le32 *) \ | 149 | FALCON_DMA_STAT(tx_pause, XgTxPausePkts), |
150 | (efx->stats_buffer.addr + \ | 150 | FALCON_DMA_STAT(tx_control, XgTxControlPkts), |
151 | FALCON_STAT_OFFSET(falcon_stat)))); \ | 151 | FALCON_DMA_STAT(tx_unicast, XgTxUnicastPkts), |
152 | else \ | 152 | FALCON_DMA_STAT(tx_multicast, XgTxMulticastPkts), |
153 | (efx)->mac_stats.efx_stat += le64_to_cpu( \ | 153 | FALCON_DMA_STAT(tx_broadcast, XgTxBroadcastPkts), |
154 | *((__force __le64 *) \ | 154 | FALCON_DMA_STAT(tx_lt64, XgTxUndersizePkts), |
155 | (efx->stats_buffer.addr + \ | 155 | FALCON_DMA_STAT(tx_64, XgTxPkts64Octets), |
156 | FALCON_STAT_OFFSET(falcon_stat)))); \ | 156 | FALCON_DMA_STAT(tx_65_to_127, XgTxPkts65to127Octets), |
157 | } while (0) | 157 | FALCON_DMA_STAT(tx_128_to_255, XgTxPkts128to255Octets), |
158 | FALCON_DMA_STAT(tx_256_to_511, XgTxPkts256to511Octets), | ||
159 | FALCON_DMA_STAT(tx_512_to_1023, XgTxPkts512to1023Octets), | ||
160 | FALCON_DMA_STAT(tx_1024_to_15xx, XgTxPkts1024to15xxOctets), | ||
161 | FALCON_DMA_STAT(tx_15xx_to_jumbo, XgTxPkts1519toMaxOctets), | ||
162 | FALCON_DMA_STAT(tx_gtjumbo, XgTxOversizePkts), | ||
163 | FALCON_DMA_STAT(tx_non_tcpudp, XgTxNonTcpUdpPkt), | ||
164 | FALCON_DMA_STAT(tx_mac_src_error, XgTxMacSrcErrPkt), | ||
165 | FALCON_DMA_STAT(tx_ip_src_error, XgTxIpSrcErrPkt), | ||
166 | FALCON_DMA_STAT(rx_bytes, XgRxOctets), | ||
167 | FALCON_DMA_STAT(rx_good_bytes, XgRxOctetsOK), | ||
168 | FALCON_OTHER_STAT(rx_bad_bytes), | ||
169 | FALCON_DMA_STAT(rx_packets, XgRxPkts), | ||
170 | FALCON_DMA_STAT(rx_good, XgRxPktsOK), | ||
171 | FALCON_DMA_STAT(rx_bad, XgRxFCSerrorPkts), | ||
172 | FALCON_DMA_STAT(rx_pause, XgRxPausePkts), | ||
173 | FALCON_DMA_STAT(rx_control, XgRxControlPkts), | ||
174 | FALCON_DMA_STAT(rx_unicast, XgRxUnicastPkts), | ||
175 | FALCON_DMA_STAT(rx_multicast, XgRxMulticastPkts), | ||
176 | FALCON_DMA_STAT(rx_broadcast, XgRxBroadcastPkts), | ||
177 | FALCON_DMA_STAT(rx_lt64, XgRxUndersizePkts), | ||
178 | FALCON_DMA_STAT(rx_64, XgRxPkts64Octets), | ||
179 | FALCON_DMA_STAT(rx_65_to_127, XgRxPkts65to127Octets), | ||
180 | FALCON_DMA_STAT(rx_128_to_255, XgRxPkts128to255Octets), | ||
181 | FALCON_DMA_STAT(rx_256_to_511, XgRxPkts256to511Octets), | ||
182 | FALCON_DMA_STAT(rx_512_to_1023, XgRxPkts512to1023Octets), | ||
183 | FALCON_DMA_STAT(rx_1024_to_15xx, XgRxPkts1024to15xxOctets), | ||
184 | FALCON_DMA_STAT(rx_15xx_to_jumbo, XgRxPkts15xxtoMaxOctets), | ||
185 | FALCON_DMA_STAT(rx_gtjumbo, XgRxOversizePkts), | ||
186 | FALCON_DMA_STAT(rx_bad_lt64, XgRxUndersizeFCSerrorPkts), | ||
187 | FALCON_DMA_STAT(rx_bad_gtjumbo, XgRxJabberPkts), | ||
188 | FALCON_DMA_STAT(rx_overflow, XgRxDropEvents), | ||
189 | FALCON_DMA_STAT(rx_symbol_error, XgRxSymbolError), | ||
190 | FALCON_DMA_STAT(rx_align_error, XgRxAlignError), | ||
191 | FALCON_DMA_STAT(rx_length_error, XgRxLengthError), | ||
192 | FALCON_DMA_STAT(rx_internal_error, XgRxInternalMACError), | ||
193 | FALCON_OTHER_STAT(rx_nodesc_drop_cnt), | ||
194 | }; | ||
195 | static const unsigned long falcon_stat_mask[] = { | ||
196 | [0 ... BITS_TO_LONGS(FALCON_STAT_COUNT) - 1] = ~0UL, | ||
197 | }; | ||
158 | 198 | ||
159 | /************************************************************************** | 199 | /************************************************************************** |
160 | * | 200 | * |
@@ -1159,66 +1199,6 @@ static int falcon_reconfigure_xmac(struct efx_nic *efx) | |||
1159 | return 0; | 1199 | return 0; |
1160 | } | 1200 | } |
1161 | 1201 | ||
1162 | static void falcon_update_stats_xmac(struct efx_nic *efx) | ||
1163 | { | ||
1164 | struct efx_mac_stats *mac_stats = &efx->mac_stats; | ||
1165 | |||
1166 | /* Update MAC stats from DMAed values */ | ||
1167 | FALCON_STAT(efx, XgRxOctets, rx_bytes); | ||
1168 | FALCON_STAT(efx, XgRxOctetsOK, rx_good_bytes); | ||
1169 | FALCON_STAT(efx, XgRxPkts, rx_packets); | ||
1170 | FALCON_STAT(efx, XgRxPktsOK, rx_good); | ||
1171 | FALCON_STAT(efx, XgRxBroadcastPkts, rx_broadcast); | ||
1172 | FALCON_STAT(efx, XgRxMulticastPkts, rx_multicast); | ||
1173 | FALCON_STAT(efx, XgRxUnicastPkts, rx_unicast); | ||
1174 | FALCON_STAT(efx, XgRxUndersizePkts, rx_lt64); | ||
1175 | FALCON_STAT(efx, XgRxOversizePkts, rx_gtjumbo); | ||
1176 | FALCON_STAT(efx, XgRxJabberPkts, rx_bad_gtjumbo); | ||
1177 | FALCON_STAT(efx, XgRxUndersizeFCSerrorPkts, rx_bad_lt64); | ||
1178 | FALCON_STAT(efx, XgRxDropEvents, rx_overflow); | ||
1179 | FALCON_STAT(efx, XgRxFCSerrorPkts, rx_bad); | ||
1180 | FALCON_STAT(efx, XgRxAlignError, rx_align_error); | ||
1181 | FALCON_STAT(efx, XgRxSymbolError, rx_symbol_error); | ||
1182 | FALCON_STAT(efx, XgRxInternalMACError, rx_internal_error); | ||
1183 | FALCON_STAT(efx, XgRxControlPkts, rx_control); | ||
1184 | FALCON_STAT(efx, XgRxPausePkts, rx_pause); | ||
1185 | FALCON_STAT(efx, XgRxPkts64Octets, rx_64); | ||
1186 | FALCON_STAT(efx, XgRxPkts65to127Octets, rx_65_to_127); | ||
1187 | FALCON_STAT(efx, XgRxPkts128to255Octets, rx_128_to_255); | ||
1188 | FALCON_STAT(efx, XgRxPkts256to511Octets, rx_256_to_511); | ||
1189 | FALCON_STAT(efx, XgRxPkts512to1023Octets, rx_512_to_1023); | ||
1190 | FALCON_STAT(efx, XgRxPkts1024to15xxOctets, rx_1024_to_15xx); | ||
1191 | FALCON_STAT(efx, XgRxPkts15xxtoMaxOctets, rx_15xx_to_jumbo); | ||
1192 | FALCON_STAT(efx, XgRxLengthError, rx_length_error); | ||
1193 | FALCON_STAT(efx, XgTxPkts, tx_packets); | ||
1194 | FALCON_STAT(efx, XgTxOctets, tx_bytes); | ||
1195 | FALCON_STAT(efx, XgTxMulticastPkts, tx_multicast); | ||
1196 | FALCON_STAT(efx, XgTxBroadcastPkts, tx_broadcast); | ||
1197 | FALCON_STAT(efx, XgTxUnicastPkts, tx_unicast); | ||
1198 | FALCON_STAT(efx, XgTxControlPkts, tx_control); | ||
1199 | FALCON_STAT(efx, XgTxPausePkts, tx_pause); | ||
1200 | FALCON_STAT(efx, XgTxPkts64Octets, tx_64); | ||
1201 | FALCON_STAT(efx, XgTxPkts65to127Octets, tx_65_to_127); | ||
1202 | FALCON_STAT(efx, XgTxPkts128to255Octets, tx_128_to_255); | ||
1203 | FALCON_STAT(efx, XgTxPkts256to511Octets, tx_256_to_511); | ||
1204 | FALCON_STAT(efx, XgTxPkts512to1023Octets, tx_512_to_1023); | ||
1205 | FALCON_STAT(efx, XgTxPkts1024to15xxOctets, tx_1024_to_15xx); | ||
1206 | FALCON_STAT(efx, XgTxPkts1519toMaxOctets, tx_15xx_to_jumbo); | ||
1207 | FALCON_STAT(efx, XgTxUndersizePkts, tx_lt64); | ||
1208 | FALCON_STAT(efx, XgTxOversizePkts, tx_gtjumbo); | ||
1209 | FALCON_STAT(efx, XgTxNonTcpUdpPkt, tx_non_tcpudp); | ||
1210 | FALCON_STAT(efx, XgTxMacSrcErrPkt, tx_mac_src_error); | ||
1211 | FALCON_STAT(efx, XgTxIpSrcErrPkt, tx_ip_src_error); | ||
1212 | |||
1213 | /* Update derived statistics */ | ||
1214 | efx_update_diff_stat(&mac_stats->tx_good_bytes, | ||
1215 | mac_stats->tx_bytes - mac_stats->tx_bad_bytes - | ||
1216 | mac_stats->tx_control * 64); | ||
1217 | efx_update_diff_stat(&mac_stats->rx_bad_bytes, | ||
1218 | mac_stats->rx_bytes - mac_stats->rx_good_bytes - | ||
1219 | mac_stats->rx_control * 64); | ||
1220 | } | ||
1221 | |||
1222 | static void falcon_poll_xmac(struct efx_nic *efx) | 1202 | static void falcon_poll_xmac(struct efx_nic *efx) |
1223 | { | 1203 | { |
1224 | struct falcon_nic_data *nic_data = efx->nic_data; | 1204 | struct falcon_nic_data *nic_data = efx->nic_data; |
@@ -1422,7 +1402,9 @@ static void falcon_stats_complete(struct efx_nic *efx) | |||
1422 | nic_data->stats_pending = false; | 1402 | nic_data->stats_pending = false; |
1423 | if (FALCON_XMAC_STATS_DMA_FLAG(efx)) { | 1403 | if (FALCON_XMAC_STATS_DMA_FLAG(efx)) { |
1424 | rmb(); /* read the done flag before the stats */ | 1404 | rmb(); /* read the done flag before the stats */ |
1425 | falcon_update_stats_xmac(efx); | 1405 | efx_nic_update_stats(falcon_stat_desc, FALCON_STAT_COUNT, |
1406 | falcon_stat_mask, nic_data->stats, | ||
1407 | efx->stats_buffer.addr, true); | ||
1426 | } else { | 1408 | } else { |
1427 | netif_err(efx, hw, efx->net_dev, | 1409 | netif_err(efx, hw, efx->net_dev, |
1428 | "timed out waiting for statistics\n"); | 1410 | "timed out waiting for statistics\n"); |
@@ -2538,23 +2520,65 @@ static void falcon_remove_nic(struct efx_nic *efx) | |||
2538 | efx->nic_data = NULL; | 2520 | efx->nic_data = NULL; |
2539 | } | 2521 | } |
2540 | 2522 | ||
2541 | static void falcon_update_nic_stats(struct efx_nic *efx) | 2523 | static size_t falcon_describe_nic_stats(struct efx_nic *efx, u8 *names) |
2524 | { | ||
2525 | return efx_nic_describe_stats(falcon_stat_desc, FALCON_STAT_COUNT, | ||
2526 | falcon_stat_mask, names); | ||
2527 | } | ||
2528 | |||
2529 | static size_t falcon_update_nic_stats(struct efx_nic *efx, u64 *full_stats, | ||
2530 | struct rtnl_link_stats64 *core_stats) | ||
2542 | { | 2531 | { |
2543 | struct falcon_nic_data *nic_data = efx->nic_data; | 2532 | struct falcon_nic_data *nic_data = efx->nic_data; |
2533 | u64 *stats = nic_data->stats; | ||
2544 | efx_oword_t cnt; | 2534 | efx_oword_t cnt; |
2545 | 2535 | ||
2546 | if (nic_data->stats_disable_count) | 2536 | if (!nic_data->stats_disable_count) { |
2547 | return; | 2537 | efx_reado(efx, &cnt, FR_AZ_RX_NODESC_DROP); |
2538 | stats[FALCON_STAT_rx_nodesc_drop_cnt] += | ||
2539 | EFX_OWORD_FIELD(cnt, FRF_AB_RX_NODESC_DROP_CNT); | ||
2540 | |||
2541 | if (nic_data->stats_pending && | ||
2542 | FALCON_XMAC_STATS_DMA_FLAG(efx)) { | ||
2543 | nic_data->stats_pending = false; | ||
2544 | rmb(); /* read the done flag before the stats */ | ||
2545 | efx_nic_update_stats( | ||
2546 | falcon_stat_desc, FALCON_STAT_COUNT, | ||
2547 | falcon_stat_mask, | ||
2548 | stats, efx->stats_buffer.addr, true); | ||
2549 | } | ||
2548 | 2550 | ||
2549 | efx_reado(efx, &cnt, FR_AZ_RX_NODESC_DROP); | 2551 | /* Update derived statistic */ |
2550 | efx->n_rx_nodesc_drop_cnt += | 2552 | efx_update_diff_stat(&stats[FALCON_STAT_rx_bad_bytes], |
2551 | EFX_OWORD_FIELD(cnt, FRF_AB_RX_NODESC_DROP_CNT); | 2553 | stats[FALCON_STAT_rx_bytes] - |
2554 | stats[FALCON_STAT_rx_good_bytes] - | ||
2555 | stats[FALCON_STAT_rx_control] * 64); | ||
2556 | } | ||
2552 | 2557 | ||
2553 | if (nic_data->stats_pending && FALCON_XMAC_STATS_DMA_FLAG(efx)) { | 2558 | if (full_stats) |
2554 | nic_data->stats_pending = false; | 2559 | memcpy(full_stats, stats, sizeof(u64) * FALCON_STAT_COUNT); |
2555 | rmb(); /* read the done flag before the stats */ | 2560 | |
2556 | falcon_update_stats_xmac(efx); | 2561 | if (core_stats) { |
2562 | core_stats->rx_packets = stats[FALCON_STAT_rx_packets]; | ||
2563 | core_stats->tx_packets = stats[FALCON_STAT_tx_packets]; | ||
2564 | core_stats->rx_bytes = stats[FALCON_STAT_rx_bytes]; | ||
2565 | core_stats->tx_bytes = stats[FALCON_STAT_tx_bytes]; | ||
2566 | core_stats->rx_dropped = stats[FALCON_STAT_rx_nodesc_drop_cnt]; | ||
2567 | core_stats->multicast = stats[FALCON_STAT_rx_multicast]; | ||
2568 | core_stats->rx_length_errors = | ||
2569 | stats[FALCON_STAT_rx_gtjumbo] + | ||
2570 | stats[FALCON_STAT_rx_length_error]; | ||
2571 | core_stats->rx_crc_errors = stats[FALCON_STAT_rx_bad]; | ||
2572 | core_stats->rx_frame_errors = stats[FALCON_STAT_rx_align_error]; | ||
2573 | core_stats->rx_fifo_errors = stats[FALCON_STAT_rx_overflow]; | ||
2574 | |||
2575 | core_stats->rx_errors = (core_stats->rx_length_errors + | ||
2576 | core_stats->rx_crc_errors + | ||
2577 | core_stats->rx_frame_errors + | ||
2578 | stats[FALCON_STAT_rx_symbol_error]); | ||
2557 | } | 2579 | } |
2580 | |||
2581 | return FALCON_STAT_COUNT; | ||
2558 | } | 2582 | } |
2559 | 2583 | ||
2560 | void falcon_start_nic_stats(struct efx_nic *efx) | 2584 | void falcon_start_nic_stats(struct efx_nic *efx) |
@@ -2643,6 +2667,7 @@ const struct efx_nic_type falcon_a1_nic_type = { | |||
2643 | .fini_dmaq = efx_farch_fini_dmaq, | 2667 | .fini_dmaq = efx_farch_fini_dmaq, |
2644 | .prepare_flush = falcon_prepare_flush, | 2668 | .prepare_flush = falcon_prepare_flush, |
2645 | .finish_flush = efx_port_dummy_op_void, | 2669 | .finish_flush = efx_port_dummy_op_void, |
2670 | .describe_stats = falcon_describe_nic_stats, | ||
2646 | .update_stats = falcon_update_nic_stats, | 2671 | .update_stats = falcon_update_nic_stats, |
2647 | .start_stats = falcon_start_nic_stats, | 2672 | .start_stats = falcon_start_nic_stats, |
2648 | .stop_stats = falcon_stop_nic_stats, | 2673 | .stop_stats = falcon_stop_nic_stats, |
@@ -2735,6 +2760,7 @@ const struct efx_nic_type falcon_b0_nic_type = { | |||
2735 | .fini_dmaq = efx_farch_fini_dmaq, | 2760 | .fini_dmaq = efx_farch_fini_dmaq, |
2736 | .prepare_flush = falcon_prepare_flush, | 2761 | .prepare_flush = falcon_prepare_flush, |
2737 | .finish_flush = efx_port_dummy_op_void, | 2762 | .finish_flush = efx_port_dummy_op_void, |
2763 | .describe_stats = falcon_describe_nic_stats, | ||
2738 | .update_stats = falcon_update_nic_stats, | 2764 | .update_stats = falcon_update_nic_stats, |
2739 | .start_stats = falcon_start_nic_stats, | 2765 | .start_stats = falcon_start_nic_stats, |
2740 | .stop_stats = falcon_stop_nic_stats, | 2766 | .stop_stats = falcon_stop_nic_stats, |
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index 67b07de2c599..ff90ebf51dbd 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c | |||
@@ -236,21 +236,10 @@ static int efx_mcdi_poll(struct efx_nic *efx) | |||
236 | */ | 236 | */ |
237 | int efx_mcdi_poll_reboot(struct efx_nic *efx) | 237 | int efx_mcdi_poll_reboot(struct efx_nic *efx) |
238 | { | 238 | { |
239 | int rc; | ||
240 | |||
241 | if (!efx->mcdi) | 239 | if (!efx->mcdi) |
242 | return 0; | 240 | return 0; |
243 | 241 | ||
244 | rc = efx->type->mcdi_poll_reboot(efx); | 242 | return efx->type->mcdi_poll_reboot(efx); |
245 | if (!rc) | ||
246 | return 0; | ||
247 | |||
248 | /* MAC statistics have been cleared on the NIC; clear our copy | ||
249 | * so that efx_update_diff_stat() can continue to work. | ||
250 | */ | ||
251 | memset(&efx->mac_stats, 0, sizeof(efx->mac_stats)); | ||
252 | |||
253 | return rc; | ||
254 | } | 243 | } |
255 | 244 | ||
256 | static void efx_mcdi_acquire(struct efx_mcdi_iface *mcdi) | 245 | static void efx_mcdi_acquire(struct efx_mcdi_iface *mcdi) |
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index fa881cdd9dcc..d33656bc4060 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h | |||
@@ -595,75 +595,17 @@ static inline bool efx_phy_mode_disabled(enum efx_phy_mode mode) | |||
595 | return !!(mode & ~PHY_MODE_TX_DISABLED); | 595 | return !!(mode & ~PHY_MODE_TX_DISABLED); |
596 | } | 596 | } |
597 | 597 | ||
598 | /* | 598 | /** |
599 | * Efx extended statistics | 599 | * struct efx_hw_stat_desc - Description of a hardware statistic |
600 | * | 600 | * @name: Name of the statistic as visible through ethtool, or %NULL if |
601 | * Not all statistics are provided by all supported MACs. The purpose | 601 | * it should not be exposed |
602 | * is this structure is to contain the raw statistics provided by each | 602 | * @dma_width: Width in bits (0 for non-DMA statistics) |
603 | * MAC. | 603 | * @offset: Offset within stats (ignored for non-DMA statistics) |
604 | */ | 604 | */ |
605 | struct efx_mac_stats { | 605 | struct efx_hw_stat_desc { |
606 | u64 tx_bytes; | 606 | const char *name; |
607 | u64 tx_good_bytes; | 607 | u16 dma_width; |
608 | u64 tx_bad_bytes; | 608 | u16 offset; |
609 | u64 tx_packets; | ||
610 | u64 tx_bad; | ||
611 | u64 tx_pause; | ||
612 | u64 tx_control; | ||
613 | u64 tx_unicast; | ||
614 | u64 tx_multicast; | ||
615 | u64 tx_broadcast; | ||
616 | u64 tx_lt64; | ||
617 | u64 tx_64; | ||
618 | u64 tx_65_to_127; | ||
619 | u64 tx_128_to_255; | ||
620 | u64 tx_256_to_511; | ||
621 | u64 tx_512_to_1023; | ||
622 | u64 tx_1024_to_15xx; | ||
623 | u64 tx_15xx_to_jumbo; | ||
624 | u64 tx_gtjumbo; | ||
625 | u64 tx_collision; | ||
626 | u64 tx_single_collision; | ||
627 | u64 tx_multiple_collision; | ||
628 | u64 tx_excessive_collision; | ||
629 | u64 tx_deferred; | ||
630 | u64 tx_late_collision; | ||
631 | u64 tx_excessive_deferred; | ||
632 | u64 tx_non_tcpudp; | ||
633 | u64 tx_mac_src_error; | ||
634 | u64 tx_ip_src_error; | ||
635 | u64 rx_bytes; | ||
636 | u64 rx_good_bytes; | ||
637 | u64 rx_bad_bytes; | ||
638 | u64 rx_packets; | ||
639 | u64 rx_good; | ||
640 | u64 rx_bad; | ||
641 | u64 rx_pause; | ||
642 | u64 rx_control; | ||
643 | u64 rx_unicast; | ||
644 | u64 rx_multicast; | ||
645 | u64 rx_broadcast; | ||
646 | u64 rx_lt64; | ||
647 | u64 rx_64; | ||
648 | u64 rx_65_to_127; | ||
649 | u64 rx_128_to_255; | ||
650 | u64 rx_256_to_511; | ||
651 | u64 rx_512_to_1023; | ||
652 | u64 rx_1024_to_15xx; | ||
653 | u64 rx_15xx_to_jumbo; | ||
654 | u64 rx_gtjumbo; | ||
655 | u64 rx_bad_lt64; | ||
656 | u64 rx_bad_64_to_15xx; | ||
657 | u64 rx_bad_15xx_to_jumbo; | ||
658 | u64 rx_bad_gtjumbo; | ||
659 | u64 rx_overflow; | ||
660 | u64 rx_missed; | ||
661 | u64 rx_false_carrier; | ||
662 | u64 rx_symbol_error; | ||
663 | u64 rx_align_error; | ||
664 | u64 rx_length_error; | ||
665 | u64 rx_internal_error; | ||
666 | u64 rx_good_lt64; | ||
667 | }; | 609 | }; |
668 | 610 | ||
669 | /* Number of bits used in a multicast filter hash address */ | 611 | /* Number of bits used in a multicast filter hash address */ |
@@ -795,12 +737,8 @@ struct vfdi_status; | |||
795 | * @last_irq_cpu: Last CPU to handle a possible test interrupt. This | 737 | * @last_irq_cpu: Last CPU to handle a possible test interrupt. This |
796 | * field is used by efx_test_interrupts() to verify that an | 738 | * field is used by efx_test_interrupts() to verify that an |
797 | * interrupt has occurred. | 739 | * interrupt has occurred. |
798 | * @n_rx_nodesc_drop_cnt: RX no descriptor drop count | 740 | * @stats_lock: Statistics update lock. Must be held when calling |
799 | * @mac_stats: MAC statistics. These include all statistics the MACs | 741 | * efx_nic_type::{update,start,stop}_stats. |
800 | * can provide. Generic code converts these into a standard | ||
801 | * &struct net_device_stats. | ||
802 | * @stats_lock: Statistics update lock. Serialises statistics fetches | ||
803 | * and access to @mac_stats. | ||
804 | * | 742 | * |
805 | * This is stored in the private area of the &struct net_device. | 743 | * This is stored in the private area of the &struct net_device. |
806 | */ | 744 | */ |
@@ -939,8 +877,6 @@ struct efx_nic { | |||
939 | struct delayed_work monitor_work ____cacheline_aligned_in_smp; | 877 | struct delayed_work monitor_work ____cacheline_aligned_in_smp; |
940 | spinlock_t biu_lock; | 878 | spinlock_t biu_lock; |
941 | int last_irq_cpu; | 879 | int last_irq_cpu; |
942 | unsigned n_rx_nodesc_drop_cnt; | ||
943 | struct efx_mac_stats mac_stats; | ||
944 | spinlock_t stats_lock; | 880 | spinlock_t stats_lock; |
945 | }; | 881 | }; |
946 | 882 | ||
@@ -984,7 +920,9 @@ struct efx_mtd_partition { | |||
984 | * (for Falcon architecture) | 920 | * (for Falcon architecture) |
985 | * @finish_flush: Clean up after flushing the DMA queues (for Falcon | 921 | * @finish_flush: Clean up after flushing the DMA queues (for Falcon |
986 | * architecture) | 922 | * architecture) |
987 | * @update_stats: Update statistics not provided by event handling | 923 | * @describe_stats: Describe statistics for ethtool |
924 | * @update_stats: Update statistics not provided by event handling. | ||
925 | * Either argument may be %NULL. | ||
988 | * @start_stats: Start the regular fetching of statistics | 926 | * @start_stats: Start the regular fetching of statistics |
989 | * @stop_stats: Stop the regular fetching of statistics | 927 | * @stop_stats: Stop the regular fetching of statistics |
990 | * @set_id_led: Set state of identifying LED or revert to automatic function | 928 | * @set_id_led: Set state of identifying LED or revert to automatic function |
@@ -1098,7 +1036,9 @@ struct efx_nic_type { | |||
1098 | int (*fini_dmaq)(struct efx_nic *efx); | 1036 | int (*fini_dmaq)(struct efx_nic *efx); |
1099 | void (*prepare_flush)(struct efx_nic *efx); | 1037 | void (*prepare_flush)(struct efx_nic *efx); |
1100 | void (*finish_flush)(struct efx_nic *efx); | 1038 | void (*finish_flush)(struct efx_nic *efx); |
1101 | void (*update_stats)(struct efx_nic *efx); | 1039 | size_t (*describe_stats)(struct efx_nic *efx, u8 *names); |
1040 | size_t (*update_stats)(struct efx_nic *efx, u64 *full_stats, | ||
1041 | struct rtnl_link_stats64 *core_stats); | ||
1102 | void (*start_stats)(struct efx_nic *efx); | 1042 | void (*start_stats)(struct efx_nic *efx); |
1103 | void (*stop_stats)(struct efx_nic *efx); | 1043 | void (*stop_stats)(struct efx_nic *efx); |
1104 | void (*set_id_led)(struct efx_nic *efx, enum efx_led_mode mode); | 1044 | void (*set_id_led)(struct efx_nic *efx, enum efx_led_mode mode); |
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c index 66c71ede3a98..b9b127743a07 100644 --- a/drivers/net/ethernet/sfc/nic.c +++ b/drivers/net/ethernet/sfc/nic.c | |||
@@ -429,3 +429,86 @@ void efx_nic_get_regs(struct efx_nic *efx, void *buf) | |||
429 | } | 429 | } |
430 | } | 430 | } |
431 | } | 431 | } |
432 | |||
433 | /** | ||
434 | * efx_nic_describe_stats - Describe supported statistics for ethtool | ||
435 | * @desc: Array of &struct efx_hw_stat_desc describing the statistics | ||
436 | * @count: Length of the @desc array | ||
437 | * @mask: Bitmask of which elements of @desc are enabled | ||
438 | * @names: Buffer to copy names to, or %NULL. The names are copied | ||
439 | * starting at intervals of %ETH_GSTRING_LEN bytes. | ||
440 | * | ||
441 | * Returns the number of visible statistics, i.e. the number of set | ||
442 | * bits in the first @count bits of @mask for which a name is defined. | ||
443 | */ | ||
444 | size_t efx_nic_describe_stats(const struct efx_hw_stat_desc *desc, size_t count, | ||
445 | const unsigned long *mask, u8 *names) | ||
446 | { | ||
447 | size_t visible = 0; | ||
448 | size_t index; | ||
449 | |||
450 | for_each_set_bit(index, mask, count) { | ||
451 | if (desc[index].name) { | ||
452 | if (names) { | ||
453 | strlcpy(names, desc[index].name, | ||
454 | ETH_GSTRING_LEN); | ||
455 | names += ETH_GSTRING_LEN; | ||
456 | } | ||
457 | ++visible; | ||
458 | } | ||
459 | } | ||
460 | |||
461 | return visible; | ||
462 | } | ||
463 | |||
464 | /** | ||
465 | * efx_nic_update_stats - Convert statistics DMA buffer to array of u64 | ||
466 | * @desc: Array of &struct efx_hw_stat_desc describing the DMA buffer | ||
467 | * layout. DMA widths of 0, 16, 32 and 64 are supported; where | ||
468 | * the width is specified as 0 the corresponding element of | ||
469 | * @stats is not updated. | ||
470 | * @count: Length of the @desc array | ||
471 | * @mask: Bitmask of which elements of @desc are enabled | ||
472 | * @stats: Buffer to update with the converted statistics. The length | ||
473 | * of this array must be at least the number of set bits in the | ||
474 | * first @count bits of @mask. | ||
475 | * @dma_buf: DMA buffer containing hardware statistics | ||
476 | * @accumulate: If set, the converted values will be added rather than | ||
477 | * directly stored to the corresponding elements of @stats | ||
478 | */ | ||
479 | void efx_nic_update_stats(const struct efx_hw_stat_desc *desc, size_t count, | ||
480 | const unsigned long *mask, | ||
481 | u64 *stats, const void *dma_buf, bool accumulate) | ||
482 | { | ||
483 | size_t index; | ||
484 | |||
485 | for_each_set_bit(index, mask, count) { | ||
486 | if (desc[index].dma_width) { | ||
487 | const void *addr = dma_buf + desc[index].offset; | ||
488 | u64 val; | ||
489 | |||
490 | switch (desc[index].dma_width) { | ||
491 | case 16: | ||
492 | val = le16_to_cpup((__le16 *)addr); | ||
493 | break; | ||
494 | case 32: | ||
495 | val = le32_to_cpup((__le32 *)addr); | ||
496 | break; | ||
497 | case 64: | ||
498 | val = le64_to_cpup((__le64 *)addr); | ||
499 | break; | ||
500 | default: | ||
501 | WARN_ON(1); | ||
502 | val = 0; | ||
503 | break; | ||
504 | } | ||
505 | |||
506 | if (accumulate) | ||
507 | *stats += val; | ||
508 | else | ||
509 | *stats = val; | ||
510 | } | ||
511 | |||
512 | ++stats; | ||
513 | } | ||
514 | } | ||
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index c3e0f1fd5047..9afbf3616b4b 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h | |||
@@ -191,10 +191,62 @@ static inline bool falcon_spi_present(const struct falcon_spi_device *spi) | |||
191 | return spi->size != 0; | 191 | return spi->size != 0; |
192 | } | 192 | } |
193 | 193 | ||
194 | enum { | ||
195 | FALCON_STAT_tx_bytes, | ||
196 | FALCON_STAT_tx_packets, | ||
197 | FALCON_STAT_tx_pause, | ||
198 | FALCON_STAT_tx_control, | ||
199 | FALCON_STAT_tx_unicast, | ||
200 | FALCON_STAT_tx_multicast, | ||
201 | FALCON_STAT_tx_broadcast, | ||
202 | FALCON_STAT_tx_lt64, | ||
203 | FALCON_STAT_tx_64, | ||
204 | FALCON_STAT_tx_65_to_127, | ||
205 | FALCON_STAT_tx_128_to_255, | ||
206 | FALCON_STAT_tx_256_to_511, | ||
207 | FALCON_STAT_tx_512_to_1023, | ||
208 | FALCON_STAT_tx_1024_to_15xx, | ||
209 | FALCON_STAT_tx_15xx_to_jumbo, | ||
210 | FALCON_STAT_tx_gtjumbo, | ||
211 | FALCON_STAT_tx_non_tcpudp, | ||
212 | FALCON_STAT_tx_mac_src_error, | ||
213 | FALCON_STAT_tx_ip_src_error, | ||
214 | FALCON_STAT_rx_bytes, | ||
215 | FALCON_STAT_rx_good_bytes, | ||
216 | FALCON_STAT_rx_bad_bytes, | ||
217 | FALCON_STAT_rx_packets, | ||
218 | FALCON_STAT_rx_good, | ||
219 | FALCON_STAT_rx_bad, | ||
220 | FALCON_STAT_rx_pause, | ||
221 | FALCON_STAT_rx_control, | ||
222 | FALCON_STAT_rx_unicast, | ||
223 | FALCON_STAT_rx_multicast, | ||
224 | FALCON_STAT_rx_broadcast, | ||
225 | FALCON_STAT_rx_lt64, | ||
226 | FALCON_STAT_rx_64, | ||
227 | FALCON_STAT_rx_65_to_127, | ||
228 | FALCON_STAT_rx_128_to_255, | ||
229 | FALCON_STAT_rx_256_to_511, | ||
230 | FALCON_STAT_rx_512_to_1023, | ||
231 | FALCON_STAT_rx_1024_to_15xx, | ||
232 | FALCON_STAT_rx_15xx_to_jumbo, | ||
233 | FALCON_STAT_rx_gtjumbo, | ||
234 | FALCON_STAT_rx_bad_lt64, | ||
235 | FALCON_STAT_rx_bad_gtjumbo, | ||
236 | FALCON_STAT_rx_overflow, | ||
237 | FALCON_STAT_rx_symbol_error, | ||
238 | FALCON_STAT_rx_align_error, | ||
239 | FALCON_STAT_rx_length_error, | ||
240 | FALCON_STAT_rx_internal_error, | ||
241 | FALCON_STAT_rx_nodesc_drop_cnt, | ||
242 | FALCON_STAT_COUNT | ||
243 | }; | ||
244 | |||
194 | /** | 245 | /** |
195 | * struct falcon_nic_data - Falcon NIC state | 246 | * struct falcon_nic_data - Falcon NIC state |
196 | * @pci_dev2: Secondary function of Falcon A | 247 | * @pci_dev2: Secondary function of Falcon A |
197 | * @board: Board state and functions | 248 | * @board: Board state and functions |
249 | * @stats: Hardware statistics | ||
198 | * @stats_disable_count: Nest count for disabling statistics fetches | 250 | * @stats_disable_count: Nest count for disabling statistics fetches |
199 | * @stats_pending: Is there a pending DMA of MAC statistics. | 251 | * @stats_pending: Is there a pending DMA of MAC statistics. |
200 | * @stats_timer: A timer for regularly fetching MAC statistics. | 252 | * @stats_timer: A timer for regularly fetching MAC statistics. |
@@ -207,6 +259,7 @@ static inline bool falcon_spi_present(const struct falcon_spi_device *spi) | |||
207 | struct falcon_nic_data { | 259 | struct falcon_nic_data { |
208 | struct pci_dev *pci_dev2; | 260 | struct pci_dev *pci_dev2; |
209 | struct falcon_board board; | 261 | struct falcon_board board; |
262 | u64 stats[FALCON_STAT_COUNT]; | ||
210 | unsigned int stats_disable_count; | 263 | unsigned int stats_disable_count; |
211 | bool stats_pending; | 264 | bool stats_pending; |
212 | struct timer_list stats_timer; | 265 | struct timer_list stats_timer; |
@@ -223,12 +276,75 @@ static inline struct falcon_board *falcon_board(struct efx_nic *efx) | |||
223 | return &data->board; | 276 | return &data->board; |
224 | } | 277 | } |
225 | 278 | ||
279 | enum { | ||
280 | SIENA_STAT_tx_bytes, | ||
281 | SIENA_STAT_tx_good_bytes, | ||
282 | SIENA_STAT_tx_bad_bytes, | ||
283 | SIENA_STAT_tx_packets, | ||
284 | SIENA_STAT_tx_bad, | ||
285 | SIENA_STAT_tx_pause, | ||
286 | SIENA_STAT_tx_control, | ||
287 | SIENA_STAT_tx_unicast, | ||
288 | SIENA_STAT_tx_multicast, | ||
289 | SIENA_STAT_tx_broadcast, | ||
290 | SIENA_STAT_tx_lt64, | ||
291 | SIENA_STAT_tx_64, | ||
292 | SIENA_STAT_tx_65_to_127, | ||
293 | SIENA_STAT_tx_128_to_255, | ||
294 | SIENA_STAT_tx_256_to_511, | ||
295 | SIENA_STAT_tx_512_to_1023, | ||
296 | SIENA_STAT_tx_1024_to_15xx, | ||
297 | SIENA_STAT_tx_15xx_to_jumbo, | ||
298 | SIENA_STAT_tx_gtjumbo, | ||
299 | SIENA_STAT_tx_collision, | ||
300 | SIENA_STAT_tx_single_collision, | ||
301 | SIENA_STAT_tx_multiple_collision, | ||
302 | SIENA_STAT_tx_excessive_collision, | ||
303 | SIENA_STAT_tx_deferred, | ||
304 | SIENA_STAT_tx_late_collision, | ||
305 | SIENA_STAT_tx_excessive_deferred, | ||
306 | SIENA_STAT_tx_non_tcpudp, | ||
307 | SIENA_STAT_tx_mac_src_error, | ||
308 | SIENA_STAT_tx_ip_src_error, | ||
309 | SIENA_STAT_rx_bytes, | ||
310 | SIENA_STAT_rx_good_bytes, | ||
311 | SIENA_STAT_rx_bad_bytes, | ||
312 | SIENA_STAT_rx_packets, | ||
313 | SIENA_STAT_rx_good, | ||
314 | SIENA_STAT_rx_bad, | ||
315 | SIENA_STAT_rx_pause, | ||
316 | SIENA_STAT_rx_control, | ||
317 | SIENA_STAT_rx_unicast, | ||
318 | SIENA_STAT_rx_multicast, | ||
319 | SIENA_STAT_rx_broadcast, | ||
320 | SIENA_STAT_rx_lt64, | ||
321 | SIENA_STAT_rx_64, | ||
322 | SIENA_STAT_rx_65_to_127, | ||
323 | SIENA_STAT_rx_128_to_255, | ||
324 | SIENA_STAT_rx_256_to_511, | ||
325 | SIENA_STAT_rx_512_to_1023, | ||
326 | SIENA_STAT_rx_1024_to_15xx, | ||
327 | SIENA_STAT_rx_15xx_to_jumbo, | ||
328 | SIENA_STAT_rx_gtjumbo, | ||
329 | SIENA_STAT_rx_bad_gtjumbo, | ||
330 | SIENA_STAT_rx_overflow, | ||
331 | SIENA_STAT_rx_false_carrier, | ||
332 | SIENA_STAT_rx_symbol_error, | ||
333 | SIENA_STAT_rx_align_error, | ||
334 | SIENA_STAT_rx_length_error, | ||
335 | SIENA_STAT_rx_internal_error, | ||
336 | SIENA_STAT_rx_nodesc_drop_cnt, | ||
337 | SIENA_STAT_COUNT | ||
338 | }; | ||
339 | |||
226 | /** | 340 | /** |
227 | * struct siena_nic_data - Siena NIC state | 341 | * struct siena_nic_data - Siena NIC state |
228 | * @wol_filter_id: Wake-on-LAN packet filter id | 342 | * @wol_filter_id: Wake-on-LAN packet filter id |
343 | * @stats: Hardware statistics | ||
229 | */ | 344 | */ |
230 | struct siena_nic_data { | 345 | struct siena_nic_data { |
231 | int wol_filter_id; | 346 | int wol_filter_id; |
347 | u64 stats[SIENA_STAT_COUNT]; | ||
232 | }; | 348 | }; |
233 | 349 | ||
234 | /* | 350 | /* |
@@ -533,6 +649,14 @@ extern int efx_farch_test_registers(struct efx_nic *efx, | |||
533 | extern size_t efx_nic_get_regs_len(struct efx_nic *efx); | 649 | extern size_t efx_nic_get_regs_len(struct efx_nic *efx); |
534 | extern void efx_nic_get_regs(struct efx_nic *efx, void *buf); | 650 | extern void efx_nic_get_regs(struct efx_nic *efx, void *buf); |
535 | 651 | ||
652 | extern size_t | ||
653 | efx_nic_describe_stats(const struct efx_hw_stat_desc *desc, size_t count, | ||
654 | const unsigned long *mask, u8 *names); | ||
655 | extern void | ||
656 | efx_nic_update_stats(const struct efx_hw_stat_desc *desc, size_t count, | ||
657 | const unsigned long *mask, | ||
658 | u64 *stats, const void *dma_buf, bool accumulate); | ||
659 | |||
536 | #define EFX_MAX_FLUSH_TIME 5000 | 660 | #define EFX_MAX_FLUSH_TIME 5000 |
537 | 661 | ||
538 | extern void efx_farch_generate_event(struct efx_nic *efx, unsigned int evq, | 662 | extern void efx_farch_generate_event(struct efx_nic *efx, unsigned int evq, |
diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index 11b4739b1705..a51d90c4c6cf 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c | |||
@@ -380,117 +380,160 @@ static void siena_remove_nic(struct efx_nic *efx) | |||
380 | efx_mcdi_fini(efx); | 380 | efx_mcdi_fini(efx); |
381 | } | 381 | } |
382 | 382 | ||
383 | #define SIENA_DMA_STAT(ext_name, mcdi_name) \ | ||
384 | [SIENA_STAT_ ## ext_name] = \ | ||
385 | { #ext_name, 64, 8 * MC_CMD_MAC_ ## mcdi_name } | ||
386 | #define SIENA_OTHER_STAT(ext_name) \ | ||
387 | [SIENA_STAT_ ## ext_name] = { #ext_name, 0, 0 } | ||
388 | |||
389 | static const struct efx_hw_stat_desc siena_stat_desc[SIENA_STAT_COUNT] = { | ||
390 | SIENA_DMA_STAT(tx_bytes, TX_BYTES), | ||
391 | SIENA_OTHER_STAT(tx_good_bytes), | ||
392 | SIENA_DMA_STAT(tx_bad_bytes, TX_BAD_BYTES), | ||
393 | SIENA_DMA_STAT(tx_packets, TX_PKTS), | ||
394 | SIENA_DMA_STAT(tx_bad, TX_BAD_FCS_PKTS), | ||
395 | SIENA_DMA_STAT(tx_pause, TX_PAUSE_PKTS), | ||
396 | SIENA_DMA_STAT(tx_control, TX_CONTROL_PKTS), | ||
397 | SIENA_DMA_STAT(tx_unicast, TX_UNICAST_PKTS), | ||
398 | SIENA_DMA_STAT(tx_multicast, TX_MULTICAST_PKTS), | ||
399 | SIENA_DMA_STAT(tx_broadcast, TX_BROADCAST_PKTS), | ||
400 | SIENA_DMA_STAT(tx_lt64, TX_LT64_PKTS), | ||
401 | SIENA_DMA_STAT(tx_64, TX_64_PKTS), | ||
402 | SIENA_DMA_STAT(tx_65_to_127, TX_65_TO_127_PKTS), | ||
403 | SIENA_DMA_STAT(tx_128_to_255, TX_128_TO_255_PKTS), | ||
404 | SIENA_DMA_STAT(tx_256_to_511, TX_256_TO_511_PKTS), | ||
405 | SIENA_DMA_STAT(tx_512_to_1023, TX_512_TO_1023_PKTS), | ||
406 | SIENA_DMA_STAT(tx_1024_to_15xx, TX_1024_TO_15XX_PKTS), | ||
407 | SIENA_DMA_STAT(tx_15xx_to_jumbo, TX_15XX_TO_JUMBO_PKTS), | ||
408 | SIENA_DMA_STAT(tx_gtjumbo, TX_GTJUMBO_PKTS), | ||
409 | SIENA_OTHER_STAT(tx_collision), | ||
410 | SIENA_DMA_STAT(tx_single_collision, TX_SINGLE_COLLISION_PKTS), | ||
411 | SIENA_DMA_STAT(tx_multiple_collision, TX_MULTIPLE_COLLISION_PKTS), | ||
412 | SIENA_DMA_STAT(tx_excessive_collision, TX_EXCESSIVE_COLLISION_PKTS), | ||
413 | SIENA_DMA_STAT(tx_deferred, TX_DEFERRED_PKTS), | ||
414 | SIENA_DMA_STAT(tx_late_collision, TX_LATE_COLLISION_PKTS), | ||
415 | SIENA_DMA_STAT(tx_excessive_deferred, TX_EXCESSIVE_DEFERRED_PKTS), | ||
416 | SIENA_DMA_STAT(tx_non_tcpudp, TX_NON_TCPUDP_PKTS), | ||
417 | SIENA_DMA_STAT(tx_mac_src_error, TX_MAC_SRC_ERR_PKTS), | ||
418 | SIENA_DMA_STAT(tx_ip_src_error, TX_IP_SRC_ERR_PKTS), | ||
419 | SIENA_DMA_STAT(rx_bytes, RX_BYTES), | ||
420 | SIENA_OTHER_STAT(rx_good_bytes), | ||
421 | SIENA_DMA_STAT(rx_bad_bytes, RX_BAD_BYTES), | ||
422 | SIENA_DMA_STAT(rx_packets, RX_PKTS), | ||
423 | SIENA_DMA_STAT(rx_good, RX_GOOD_PKTS), | ||
424 | SIENA_DMA_STAT(rx_bad, RX_BAD_FCS_PKTS), | ||
425 | SIENA_DMA_STAT(rx_pause, RX_PAUSE_PKTS), | ||
426 | SIENA_DMA_STAT(rx_control, RX_CONTROL_PKTS), | ||
427 | SIENA_DMA_STAT(rx_unicast, RX_UNICAST_PKTS), | ||
428 | SIENA_DMA_STAT(rx_multicast, RX_MULTICAST_PKTS), | ||
429 | SIENA_DMA_STAT(rx_broadcast, RX_BROADCAST_PKTS), | ||
430 | SIENA_DMA_STAT(rx_lt64, RX_UNDERSIZE_PKTS), | ||
431 | SIENA_DMA_STAT(rx_64, RX_64_PKTS), | ||
432 | SIENA_DMA_STAT(rx_65_to_127, RX_65_TO_127_PKTS), | ||
433 | SIENA_DMA_STAT(rx_128_to_255, RX_128_TO_255_PKTS), | ||
434 | SIENA_DMA_STAT(rx_256_to_511, RX_256_TO_511_PKTS), | ||
435 | SIENA_DMA_STAT(rx_512_to_1023, RX_512_TO_1023_PKTS), | ||
436 | SIENA_DMA_STAT(rx_1024_to_15xx, RX_1024_TO_15XX_PKTS), | ||
437 | SIENA_DMA_STAT(rx_15xx_to_jumbo, RX_15XX_TO_JUMBO_PKTS), | ||
438 | SIENA_DMA_STAT(rx_gtjumbo, RX_GTJUMBO_PKTS), | ||
439 | SIENA_DMA_STAT(rx_bad_gtjumbo, RX_JABBER_PKTS), | ||
440 | SIENA_DMA_STAT(rx_overflow, RX_OVERFLOW_PKTS), | ||
441 | SIENA_DMA_STAT(rx_false_carrier, RX_FALSE_CARRIER_PKTS), | ||
442 | SIENA_DMA_STAT(rx_symbol_error, RX_SYMBOL_ERROR_PKTS), | ||
443 | SIENA_DMA_STAT(rx_align_error, RX_ALIGN_ERROR_PKTS), | ||
444 | SIENA_DMA_STAT(rx_length_error, RX_LENGTH_ERROR_PKTS), | ||
445 | SIENA_DMA_STAT(rx_internal_error, RX_INTERNAL_ERROR_PKTS), | ||
446 | SIENA_DMA_STAT(rx_nodesc_drop_cnt, RX_NODESC_DROPS), | ||
447 | }; | ||
448 | static const unsigned long siena_stat_mask[] = { | ||
449 | [0 ... BITS_TO_LONGS(SIENA_STAT_COUNT) - 1] = ~0UL, | ||
450 | }; | ||
451 | |||
452 | static size_t siena_describe_nic_stats(struct efx_nic *efx, u8 *names) | ||
453 | { | ||
454 | return efx_nic_describe_stats(siena_stat_desc, SIENA_STAT_COUNT, | ||
455 | siena_stat_mask, names); | ||
456 | } | ||
457 | |||
383 | static int siena_try_update_nic_stats(struct efx_nic *efx) | 458 | static int siena_try_update_nic_stats(struct efx_nic *efx) |
384 | { | 459 | { |
460 | struct siena_nic_data *nic_data = efx->nic_data; | ||
461 | u64 *stats = nic_data->stats; | ||
385 | __le64 *dma_stats; | 462 | __le64 *dma_stats; |
386 | struct efx_mac_stats *mac_stats; | ||
387 | __le64 generation_start, generation_end; | 463 | __le64 generation_start, generation_end; |
388 | 464 | ||
389 | mac_stats = &efx->mac_stats; | ||
390 | dma_stats = efx->stats_buffer.addr; | 465 | dma_stats = efx->stats_buffer.addr; |
391 | 466 | ||
392 | generation_end = dma_stats[MC_CMD_MAC_GENERATION_END]; | 467 | generation_end = dma_stats[MC_CMD_MAC_GENERATION_END]; |
393 | if (generation_end == EFX_MC_STATS_GENERATION_INVALID) | 468 | if (generation_end == EFX_MC_STATS_GENERATION_INVALID) |
394 | return 0; | 469 | return 0; |
395 | rmb(); | 470 | rmb(); |
396 | 471 | efx_nic_update_stats(siena_stat_desc, SIENA_STAT_COUNT, siena_stat_mask, | |
397 | #define MAC_STAT(M, D) \ | 472 | stats, efx->stats_buffer.addr, false); |
398 | mac_stats->M = le64_to_cpu(dma_stats[MC_CMD_MAC_ ## D]) | ||
399 | |||
400 | MAC_STAT(tx_bytes, TX_BYTES); | ||
401 | MAC_STAT(tx_bad_bytes, TX_BAD_BYTES); | ||
402 | efx_update_diff_stat(&mac_stats->tx_good_bytes, | ||
403 | mac_stats->tx_bytes - mac_stats->tx_bad_bytes); | ||
404 | MAC_STAT(tx_packets, TX_PKTS); | ||
405 | MAC_STAT(tx_bad, TX_BAD_FCS_PKTS); | ||
406 | MAC_STAT(tx_pause, TX_PAUSE_PKTS); | ||
407 | MAC_STAT(tx_control, TX_CONTROL_PKTS); | ||
408 | MAC_STAT(tx_unicast, TX_UNICAST_PKTS); | ||
409 | MAC_STAT(tx_multicast, TX_MULTICAST_PKTS); | ||
410 | MAC_STAT(tx_broadcast, TX_BROADCAST_PKTS); | ||
411 | MAC_STAT(tx_lt64, TX_LT64_PKTS); | ||
412 | MAC_STAT(tx_64, TX_64_PKTS); | ||
413 | MAC_STAT(tx_65_to_127, TX_65_TO_127_PKTS); | ||
414 | MAC_STAT(tx_128_to_255, TX_128_TO_255_PKTS); | ||
415 | MAC_STAT(tx_256_to_511, TX_256_TO_511_PKTS); | ||
416 | MAC_STAT(tx_512_to_1023, TX_512_TO_1023_PKTS); | ||
417 | MAC_STAT(tx_1024_to_15xx, TX_1024_TO_15XX_PKTS); | ||
418 | MAC_STAT(tx_15xx_to_jumbo, TX_15XX_TO_JUMBO_PKTS); | ||
419 | MAC_STAT(tx_gtjumbo, TX_GTJUMBO_PKTS); | ||
420 | mac_stats->tx_collision = 0; | ||
421 | MAC_STAT(tx_single_collision, TX_SINGLE_COLLISION_PKTS); | ||
422 | MAC_STAT(tx_multiple_collision, TX_MULTIPLE_COLLISION_PKTS); | ||
423 | MAC_STAT(tx_excessive_collision, TX_EXCESSIVE_COLLISION_PKTS); | ||
424 | MAC_STAT(tx_deferred, TX_DEFERRED_PKTS); | ||
425 | MAC_STAT(tx_late_collision, TX_LATE_COLLISION_PKTS); | ||
426 | mac_stats->tx_collision = (mac_stats->tx_single_collision + | ||
427 | mac_stats->tx_multiple_collision + | ||
428 | mac_stats->tx_excessive_collision + | ||
429 | mac_stats->tx_late_collision); | ||
430 | MAC_STAT(tx_excessive_deferred, TX_EXCESSIVE_DEFERRED_PKTS); | ||
431 | MAC_STAT(tx_non_tcpudp, TX_NON_TCPUDP_PKTS); | ||
432 | MAC_STAT(tx_mac_src_error, TX_MAC_SRC_ERR_PKTS); | ||
433 | MAC_STAT(tx_ip_src_error, TX_IP_SRC_ERR_PKTS); | ||
434 | MAC_STAT(rx_bytes, RX_BYTES); | ||
435 | MAC_STAT(rx_bad_bytes, RX_BAD_BYTES); | ||
436 | efx_update_diff_stat(&mac_stats->rx_good_bytes, | ||
437 | mac_stats->rx_bytes - mac_stats->rx_bad_bytes); | ||
438 | MAC_STAT(rx_packets, RX_PKTS); | ||
439 | MAC_STAT(rx_good, RX_GOOD_PKTS); | ||
440 | MAC_STAT(rx_bad, RX_BAD_FCS_PKTS); | ||
441 | MAC_STAT(rx_pause, RX_PAUSE_PKTS); | ||
442 | MAC_STAT(rx_control, RX_CONTROL_PKTS); | ||
443 | MAC_STAT(rx_unicast, RX_UNICAST_PKTS); | ||
444 | MAC_STAT(rx_multicast, RX_MULTICAST_PKTS); | ||
445 | MAC_STAT(rx_broadcast, RX_BROADCAST_PKTS); | ||
446 | MAC_STAT(rx_lt64, RX_UNDERSIZE_PKTS); | ||
447 | MAC_STAT(rx_64, RX_64_PKTS); | ||
448 | MAC_STAT(rx_65_to_127, RX_65_TO_127_PKTS); | ||
449 | MAC_STAT(rx_128_to_255, RX_128_TO_255_PKTS); | ||
450 | MAC_STAT(rx_256_to_511, RX_256_TO_511_PKTS); | ||
451 | MAC_STAT(rx_512_to_1023, RX_512_TO_1023_PKTS); | ||
452 | MAC_STAT(rx_1024_to_15xx, RX_1024_TO_15XX_PKTS); | ||
453 | MAC_STAT(rx_15xx_to_jumbo, RX_15XX_TO_JUMBO_PKTS); | ||
454 | MAC_STAT(rx_gtjumbo, RX_GTJUMBO_PKTS); | ||
455 | mac_stats->rx_bad_lt64 = 0; | ||
456 | mac_stats->rx_bad_64_to_15xx = 0; | ||
457 | mac_stats->rx_bad_15xx_to_jumbo = 0; | ||
458 | MAC_STAT(rx_bad_gtjumbo, RX_JABBER_PKTS); | ||
459 | MAC_STAT(rx_overflow, RX_OVERFLOW_PKTS); | ||
460 | mac_stats->rx_missed = 0; | ||
461 | MAC_STAT(rx_false_carrier, RX_FALSE_CARRIER_PKTS); | ||
462 | MAC_STAT(rx_symbol_error, RX_SYMBOL_ERROR_PKTS); | ||
463 | MAC_STAT(rx_align_error, RX_ALIGN_ERROR_PKTS); | ||
464 | MAC_STAT(rx_length_error, RX_LENGTH_ERROR_PKTS); | ||
465 | MAC_STAT(rx_internal_error, RX_INTERNAL_ERROR_PKTS); | ||
466 | mac_stats->rx_good_lt64 = 0; | ||
467 | |||
468 | efx->n_rx_nodesc_drop_cnt = | ||
469 | le64_to_cpu(dma_stats[MC_CMD_MAC_RX_NODESC_DROPS]); | ||
470 | |||
471 | #undef MAC_STAT | ||
472 | |||
473 | rmb(); | 473 | rmb(); |
474 | generation_start = dma_stats[MC_CMD_MAC_GENERATION_START]; | 474 | generation_start = dma_stats[MC_CMD_MAC_GENERATION_START]; |
475 | if (generation_end != generation_start) | 475 | if (generation_end != generation_start) |
476 | return -EAGAIN; | 476 | return -EAGAIN; |
477 | 477 | ||
478 | /* Update derived statistics */ | ||
479 | efx_update_diff_stat(&stats[SIENA_STAT_tx_good_bytes], | ||
480 | stats[SIENA_STAT_tx_bytes] - | ||
481 | stats[SIENA_STAT_tx_bad_bytes]); | ||
482 | stats[SIENA_STAT_tx_collision] = | ||
483 | stats[SIENA_STAT_tx_single_collision] + | ||
484 | stats[SIENA_STAT_tx_multiple_collision] + | ||
485 | stats[SIENA_STAT_tx_excessive_collision] + | ||
486 | stats[SIENA_STAT_tx_late_collision]; | ||
487 | efx_update_diff_stat(&stats[SIENA_STAT_rx_good_bytes], | ||
488 | stats[SIENA_STAT_rx_bytes] - | ||
489 | stats[SIENA_STAT_rx_bad_bytes]); | ||
478 | return 0; | 490 | return 0; |
479 | } | 491 | } |
480 | 492 | ||
481 | static void siena_update_nic_stats(struct efx_nic *efx) | 493 | static size_t siena_update_nic_stats(struct efx_nic *efx, u64 *full_stats, |
494 | struct rtnl_link_stats64 *core_stats) | ||
482 | { | 495 | { |
496 | struct siena_nic_data *nic_data = efx->nic_data; | ||
497 | u64 *stats = nic_data->stats; | ||
483 | int retry; | 498 | int retry; |
484 | 499 | ||
485 | /* If we're unlucky enough to read statistics wduring the DMA, wait | 500 | /* If we're unlucky enough to read statistics wduring the DMA, wait |
486 | * up to 10ms for it to finish (typically takes <500us) */ | 501 | * up to 10ms for it to finish (typically takes <500us) */ |
487 | for (retry = 0; retry < 100; ++retry) { | 502 | for (retry = 0; retry < 100; ++retry) { |
488 | if (siena_try_update_nic_stats(efx) == 0) | 503 | if (siena_try_update_nic_stats(efx) == 0) |
489 | return; | 504 | break; |
490 | udelay(100); | 505 | udelay(100); |
491 | } | 506 | } |
492 | 507 | ||
493 | /* Use the old values instead */ | 508 | if (full_stats) |
509 | memcpy(full_stats, stats, sizeof(u64) * SIENA_STAT_COUNT); | ||
510 | |||
511 | if (core_stats) { | ||
512 | core_stats->rx_packets = stats[SIENA_STAT_rx_packets]; | ||
513 | core_stats->tx_packets = stats[SIENA_STAT_tx_packets]; | ||
514 | core_stats->rx_bytes = stats[SIENA_STAT_rx_bytes]; | ||
515 | core_stats->tx_bytes = stats[SIENA_STAT_tx_bytes]; | ||
516 | core_stats->rx_dropped = stats[SIENA_STAT_rx_nodesc_drop_cnt]; | ||
517 | core_stats->multicast = stats[SIENA_STAT_rx_multicast]; | ||
518 | core_stats->collisions = stats[SIENA_STAT_tx_collision]; | ||
519 | core_stats->rx_length_errors = | ||
520 | stats[SIENA_STAT_rx_gtjumbo] + | ||
521 | stats[SIENA_STAT_rx_length_error]; | ||
522 | core_stats->rx_crc_errors = stats[SIENA_STAT_rx_bad]; | ||
523 | core_stats->rx_frame_errors = stats[SIENA_STAT_rx_align_error]; | ||
524 | core_stats->rx_fifo_errors = stats[SIENA_STAT_rx_overflow]; | ||
525 | core_stats->tx_window_errors = | ||
526 | stats[SIENA_STAT_tx_late_collision]; | ||
527 | |||
528 | core_stats->rx_errors = (core_stats->rx_length_errors + | ||
529 | core_stats->rx_crc_errors + | ||
530 | core_stats->rx_frame_errors + | ||
531 | stats[SIENA_STAT_rx_symbol_error]); | ||
532 | core_stats->tx_errors = (core_stats->tx_window_errors + | ||
533 | stats[SIENA_STAT_tx_bad]); | ||
534 | } | ||
535 | |||
536 | return SIENA_STAT_COUNT; | ||
494 | } | 537 | } |
495 | 538 | ||
496 | static int siena_mac_reconfigure(struct efx_nic *efx) | 539 | static int siena_mac_reconfigure(struct efx_nic *efx) |
@@ -652,6 +695,7 @@ static void siena_mcdi_read_response(struct efx_nic *efx, efx_dword_t *outbuf, | |||
652 | 695 | ||
653 | static int siena_mcdi_poll_reboot(struct efx_nic *efx) | 696 | static int siena_mcdi_poll_reboot(struct efx_nic *efx) |
654 | { | 697 | { |
698 | struct siena_nic_data *nic_data = efx->nic_data; | ||
655 | unsigned int addr = FR_CZ_MC_TREG_SMEM + MCDI_STATUS(efx); | 699 | unsigned int addr = FR_CZ_MC_TREG_SMEM + MCDI_STATUS(efx); |
656 | efx_dword_t reg; | 700 | efx_dword_t reg; |
657 | u32 value; | 701 | u32 value; |
@@ -665,6 +709,12 @@ static int siena_mcdi_poll_reboot(struct efx_nic *efx) | |||
665 | EFX_ZERO_DWORD(reg); | 709 | EFX_ZERO_DWORD(reg); |
666 | efx_writed(efx, ®, addr); | 710 | efx_writed(efx, ®, addr); |
667 | 711 | ||
712 | /* MAC statistics have been cleared on the NIC; clear the local | ||
713 | * copies that we update with efx_update_diff_stat(). | ||
714 | */ | ||
715 | nic_data->stats[SIENA_STAT_tx_good_bytes] = 0; | ||
716 | nic_data->stats[SIENA_STAT_rx_good_bytes] = 0; | ||
717 | |||
668 | if (value == MC_STATUS_DWORD_ASSERT) | 718 | if (value == MC_STATUS_DWORD_ASSERT) |
669 | return -EINTR; | 719 | return -EINTR; |
670 | else | 720 | else |
@@ -830,6 +880,7 @@ const struct efx_nic_type siena_a0_nic_type = { | |||
830 | .fini_dmaq = efx_farch_fini_dmaq, | 880 | .fini_dmaq = efx_farch_fini_dmaq, |
831 | .prepare_flush = siena_prepare_flush, | 881 | .prepare_flush = siena_prepare_flush, |
832 | .finish_flush = siena_finish_flush, | 882 | .finish_flush = siena_finish_flush, |
883 | .describe_stats = siena_describe_nic_stats, | ||
833 | .update_stats = siena_update_nic_stats, | 884 | .update_stats = siena_update_nic_stats, |
834 | .start_stats = efx_mcdi_mac_start_stats, | 885 | .start_stats = efx_mcdi_mac_start_stats, |
835 | .stop_stats = efx_mcdi_mac_stop_stats, | 886 | .stop_stats = efx_mcdi_mac_stop_stats, |