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>
This commit is contained in:
parent
87b200e11b
commit
8ccf3800db
@ -359,6 +359,37 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
|
|||||||
return n;
|
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,
|
static int efx_ethtool_get_sset_count(struct net_device *net_dev,
|
||||||
int string_set)
|
int string_set)
|
||||||
{
|
{
|
||||||
@ -367,8 +398,9 @@ static int efx_ethtool_get_sset_count(struct net_device *net_dev,
|
|||||||
switch (string_set) {
|
switch (string_set) {
|
||||||
case ETH_SS_STATS:
|
case ETH_SS_STATS:
|
||||||
return efx->type->describe_stats(efx, NULL) +
|
return efx->type->describe_stats(efx, NULL) +
|
||||||
EFX_ETHTOOL_SW_STAT_COUNT +
|
EFX_ETHTOOL_SW_STAT_COUNT +
|
||||||
efx_ptp_describe_stats(efx, NULL);
|
efx_describe_per_queue_stats(efx, NULL) +
|
||||||
|
efx_ptp_describe_stats(efx, NULL);
|
||||||
case ETH_SS_TEST:
|
case ETH_SS_TEST:
|
||||||
return efx_ethtool_fill_self_tests(efx, NULL, NULL, NULL);
|
return efx_ethtool_fill_self_tests(efx, NULL, NULL, NULL);
|
||||||
default:
|
default:
|
||||||
@ -390,6 +422,8 @@ static void efx_ethtool_get_strings(struct net_device *net_dev,
|
|||||||
strlcpy(strings + i * ETH_GSTRING_LEN,
|
strlcpy(strings + i * ETH_GSTRING_LEN,
|
||||||
efx_sw_stat_desc[i].name, ETH_GSTRING_LEN);
|
efx_sw_stat_desc[i].name, ETH_GSTRING_LEN);
|
||||||
strings += EFX_ETHTOOL_SW_STAT_COUNT * 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);
|
efx_ptp_describe_stats(efx, strings);
|
||||||
break;
|
break;
|
||||||
case ETH_SS_TEST:
|
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;
|
const struct efx_sw_stat_desc *stat;
|
||||||
struct efx_channel *channel;
|
struct efx_channel *channel;
|
||||||
struct efx_tx_queue *tx_queue;
|
struct efx_tx_queue *tx_queue;
|
||||||
|
struct efx_rx_queue *rx_queue;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
spin_lock_bh(&efx->stats_lock);
|
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);
|
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);
|
efx_ptp_update_stats(efx, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,6 +249,8 @@ struct efx_tx_queue {
|
|||||||
unsigned int tso_packets;
|
unsigned int tso_packets;
|
||||||
unsigned int pushes;
|
unsigned int pushes;
|
||||||
unsigned int pio_packets;
|
unsigned int pio_packets;
|
||||||
|
/* Statistics to supplement MAC stats */
|
||||||
|
unsigned long tx_packets;
|
||||||
|
|
||||||
/* Members shared between paths and sometimes updated */
|
/* Members shared between paths and sometimes updated */
|
||||||
unsigned int empty_read_count ____cacheline_aligned_in_smp;
|
unsigned int empty_read_count ____cacheline_aligned_in_smp;
|
||||||
@ -358,6 +360,8 @@ struct efx_rx_queue {
|
|||||||
unsigned int recycle_count;
|
unsigned int recycle_count;
|
||||||
struct timer_list slow_fill;
|
struct timer_list slow_fill;
|
||||||
unsigned int slow_fill_count;
|
unsigned int slow_fill_count;
|
||||||
|
/* Statistics to supplement MAC stats */
|
||||||
|
unsigned long rx_packets;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum efx_sync_events_state {
|
enum efx_sync_events_state {
|
||||||
|
@ -530,6 +530,8 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
|
|||||||
struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
|
struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
|
||||||
struct efx_rx_buffer *rx_buf;
|
struct efx_rx_buffer *rx_buf;
|
||||||
|
|
||||||
|
rx_queue->rx_packets++;
|
||||||
|
|
||||||
rx_buf = efx_rx_buffer(rx_queue, index);
|
rx_buf = efx_rx_buffer(rx_queue, index);
|
||||||
rx_buf->flags |= flags;
|
rx_buf->flags |= flags;
|
||||||
|
|
||||||
|
@ -452,6 +452,8 @@ finish_packet:
|
|||||||
/* Pass off to hardware */
|
/* Pass off to hardware */
|
||||||
efx_nic_push_buffers(tx_queue);
|
efx_nic_push_buffers(tx_queue);
|
||||||
|
|
||||||
|
tx_queue->tx_packets++;
|
||||||
|
|
||||||
efx_tx_maybe_stop_queue(tx_queue);
|
efx_tx_maybe_stop_queue(tx_queue);
|
||||||
|
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
@ -1245,6 +1247,8 @@ static int tso_start_new_packet(struct efx_tx_queue *tx_queue,
|
|||||||
|
|
||||||
++tx_queue->tso_packets;
|
++tx_queue->tso_packets;
|
||||||
|
|
||||||
|
++tx_queue->tx_packets;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user