|
@@ -359,6 +359,37 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
|
|
|
return n;
|
|
|
}
|
|
|
|
|
|
+static size_t efx_describe_per_queue_stats(struct efx_nic *efx, u8 *strings)
|
|
|
+{
|
|
|
+ size_t n_stats = 0;
|
|
|
+ struct efx_channel *channel;
|
|
|
+
|
|
|
+ efx_for_each_channel(channel, efx) {
|
|
|
+ if (efx_channel_has_tx_queues(channel)) {
|
|
|
+ n_stats++;
|
|
|
+ if (strings != NULL) {
|
|
|
+ snprintf(strings, ETH_GSTRING_LEN,
|
|
|
+ "tx-%u.tx_packets",
|
|
|
+ channel->tx_queue[0].queue /
|
|
|
+ EFX_TXQ_TYPES);
|
|
|
+
|
|
|
+ strings += ETH_GSTRING_LEN;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ efx_for_each_channel(channel, efx) {
|
|
|
+ if (efx_channel_has_rx_queue(channel)) {
|
|
|
+ n_stats++;
|
|
|
+ if (strings != NULL) {
|
|
|
+ snprintf(strings, ETH_GSTRING_LEN,
|
|
|
+ "rx-%d.rx_packets", channel->channel);
|
|
|
+ strings += ETH_GSTRING_LEN;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return n_stats;
|
|
|
+}
|
|
|
+
|
|
|
static int efx_ethtool_get_sset_count(struct net_device *net_dev,
|
|
|
int string_set)
|
|
|
{
|
|
@@ -367,8 +398,9 @@ static int efx_ethtool_get_sset_count(struct net_device *net_dev,
|
|
|
switch (string_set) {
|
|
|
case ETH_SS_STATS:
|
|
|
return efx->type->describe_stats(efx, NULL) +
|
|
|
- EFX_ETHTOOL_SW_STAT_COUNT +
|
|
|
- efx_ptp_describe_stats(efx, NULL);
|
|
|
+ EFX_ETHTOOL_SW_STAT_COUNT +
|
|
|
+ efx_describe_per_queue_stats(efx, NULL) +
|
|
|
+ efx_ptp_describe_stats(efx, NULL);
|
|
|
case ETH_SS_TEST:
|
|
|
return efx_ethtool_fill_self_tests(efx, NULL, NULL, NULL);
|
|
|
default:
|
|
@@ -390,6 +422,8 @@ static void efx_ethtool_get_strings(struct net_device *net_dev,
|
|
|
strlcpy(strings + i * ETH_GSTRING_LEN,
|
|
|
efx_sw_stat_desc[i].name, ETH_GSTRING_LEN);
|
|
|
strings += EFX_ETHTOOL_SW_STAT_COUNT * ETH_GSTRING_LEN;
|
|
|
+ strings += (efx_describe_per_queue_stats(efx, strings) *
|
|
|
+ ETH_GSTRING_LEN);
|
|
|
efx_ptp_describe_stats(efx, strings);
|
|
|
break;
|
|
|
case ETH_SS_TEST:
|
|
@@ -409,6 +443,7 @@ static void efx_ethtool_get_stats(struct net_device *net_dev,
|
|
|
const struct efx_sw_stat_desc *stat;
|
|
|
struct efx_channel *channel;
|
|
|
struct efx_tx_queue *tx_queue;
|
|
|
+ struct efx_rx_queue *rx_queue;
|
|
|
int i;
|
|
|
|
|
|
spin_lock_bh(&efx->stats_lock);
|
|
@@ -444,6 +479,25 @@ static void efx_ethtool_get_stats(struct net_device *net_dev,
|
|
|
|
|
|
spin_unlock_bh(&efx->stats_lock);
|
|
|
|
|
|
+ efx_for_each_channel(channel, efx) {
|
|
|
+ if (efx_channel_has_tx_queues(channel)) {
|
|
|
+ *data = 0;
|
|
|
+ efx_for_each_channel_tx_queue(tx_queue, channel) {
|
|
|
+ *data += tx_queue->tx_packets;
|
|
|
+ }
|
|
|
+ data++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ efx_for_each_channel(channel, efx) {
|
|
|
+ if (efx_channel_has_rx_queue(channel)) {
|
|
|
+ *data = 0;
|
|
|
+ efx_for_each_channel_rx_queue(rx_queue, channel) {
|
|
|
+ *data += rx_queue->rx_packets;
|
|
|
+ }
|
|
|
+ data++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
efx_ptp_update_stats(efx, data);
|
|
|
}
|
|
|
|