Commit 6fcd2735 authored by Eran Ben Elisha's avatar Eran Ben Elisha Committed by David S. Miller

net/mlx4_en: Support general selective view of ethtool statistics

The driver uses a bitmask to indicate which statistics should be
displayed to the user in ethtool. The bitmask is u64, therefore we are
limited for a selective view of up to 64 statistics. Extend the bitmap
in order to show more than 64 statistics.

In addition, add packet statistics to the ethtool display for PF.
Signed-off-by: default avatarEran Ben Elisha <eranbe@mellanox.com>
Signed-off-by: default avatarHadar Hen Zion <hadarh@mellanox.com>
Signed-off-by: default avatarOr Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ffa88f37
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <linux/mlx4/device.h> #include <linux/mlx4/device.h>
#include <linux/in.h> #include <linux/in.h>
#include <net/ip.h> #include <net/ip.h>
#include <linux/bitmap.h>
#include "mlx4_en.h" #include "mlx4_en.h"
#include "en_port.h" #include "en_port.h"
...@@ -104,6 +105,7 @@ static const char mlx4_en_priv_flags[][ETH_GSTRING_LEN] = { ...@@ -104,6 +105,7 @@ static const char mlx4_en_priv_flags[][ETH_GSTRING_LEN] = {
}; };
static const char main_strings[][ETH_GSTRING_LEN] = { static const char main_strings[][ETH_GSTRING_LEN] = {
/* main statistics */
"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
"tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
"rx_length_errors", "rx_over_errors", "rx_crc_errors", "rx_length_errors", "rx_over_errors", "rx_crc_errors",
...@@ -222,14 +224,50 @@ static int mlx4_en_set_wol(struct net_device *netdev, ...@@ -222,14 +224,50 @@ static int mlx4_en_set_wol(struct net_device *netdev,
return err; return err;
} }
struct bitmap_iterator {
unsigned long *stats_bitmap;
unsigned int count;
unsigned int iterator;
bool advance_array; /* if set, force no increments */
};
static inline void bitmap_iterator_init(struct bitmap_iterator *h,
unsigned long *stats_bitmap,
int count)
{
h->iterator = 0;
h->advance_array = !bitmap_empty(stats_bitmap, count);
h->count = h->advance_array ? bitmap_weight(stats_bitmap, count)
: count;
h->stats_bitmap = stats_bitmap;
}
static inline int bitmap_iterator_test(struct bitmap_iterator *h)
{
return !h->advance_array ? 1 : test_bit(h->iterator, h->stats_bitmap);
}
static inline int bitmap_iterator_inc(struct bitmap_iterator *h)
{
return h->iterator++;
}
static inline unsigned int
bitmap_iterator_count(struct bitmap_iterator *h)
{
return h->count;
}
static int mlx4_en_get_sset_count(struct net_device *dev, int sset) static int mlx4_en_get_sset_count(struct net_device *dev, int sset)
{ {
struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_priv *priv = netdev_priv(dev);
int bit_count = hweight64(priv->stats_bitmap); struct bitmap_iterator it;
bitmap_iterator_init(&it, priv->stats_bitmap, NUM_ALL_STATS);
switch (sset) { switch (sset) {
case ETH_SS_STATS: case ETH_SS_STATS:
return (priv->stats_bitmap ? bit_count : NUM_ALL_STATS) + return bitmap_iterator_count(&it) +
(priv->tx_ring_num * 2) + (priv->tx_ring_num * 2) +
#ifdef CONFIG_NET_RX_BUSY_POLL #ifdef CONFIG_NET_RX_BUSY_POLL
(priv->rx_ring_num * 5); (priv->rx_ring_num * 5);
...@@ -251,34 +289,25 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev, ...@@ -251,34 +289,25 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev,
{ {
struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_priv *priv = netdev_priv(dev);
int index = 0; int index = 0;
int i, j = 0; int i;
struct bitmap_iterator it;
bitmap_iterator_init(&it, priv->stats_bitmap, NUM_ALL_STATS);
spin_lock_bh(&priv->stats_lock); spin_lock_bh(&priv->stats_lock);
if (!(priv->stats_bitmap)) { for (i = 0; i < NUM_MAIN_STATS; i++, bitmap_iterator_inc(&it))
for (i = 0; i < NUM_MAIN_STATS; i++) if (bitmap_iterator_test(&it))
data[index++] = data[index++] = ((unsigned long *)&priv->stats)[i];
((unsigned long *) &priv->stats)[i];
for (i = 0; i < NUM_PORT_STATS; i++) for (i = 0; i < NUM_PORT_STATS; i++, bitmap_iterator_inc(&it))
data[index++] = if (bitmap_iterator_test(&it))
((unsigned long *) &priv->port_stats)[i]; data[index++] = ((unsigned long *)&priv->port_stats)[i];
for (i = 0; i < NUM_PKT_STATS; i++)
data[index++] = for (i = 0; i < NUM_PKT_STATS; i++, bitmap_iterator_inc(&it))
((unsigned long *) &priv->pkstats)[i]; if (bitmap_iterator_test(&it))
} else { data[index++] = ((unsigned long *)&priv->pkstats)[i];
for (i = 0; i < NUM_MAIN_STATS; i++) {
if ((priv->stats_bitmap >> j) & 1)
data[index++] =
((unsigned long *) &priv->stats)[i];
j++;
}
for (i = 0; i < NUM_PORT_STATS; i++) {
if ((priv->stats_bitmap >> j) & 1)
data[index++] =
((unsigned long *) &priv->port_stats)[i];
j++;
}
}
for (i = 0; i < priv->tx_ring_num; i++) { for (i = 0; i < priv->tx_ring_num; i++) {
data[index++] = priv->tx_ring[i]->packets; data[index++] = priv->tx_ring[i]->packets;
data[index++] = priv->tx_ring[i]->bytes; data[index++] = priv->tx_ring[i]->bytes;
...@@ -307,7 +336,10 @@ static void mlx4_en_get_strings(struct net_device *dev, ...@@ -307,7 +336,10 @@ static void mlx4_en_get_strings(struct net_device *dev,
{ {
struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_priv *priv = netdev_priv(dev);
int index = 0; int index = 0;
int i; int i, strings = 0;
struct bitmap_iterator it;
bitmap_iterator_init(&it, priv->stats_bitmap, NUM_ALL_STATS);
switch (stringset) { switch (stringset) {
case ETH_SS_TEST: case ETH_SS_TEST:
...@@ -320,29 +352,24 @@ static void mlx4_en_get_strings(struct net_device *dev, ...@@ -320,29 +352,24 @@ static void mlx4_en_get_strings(struct net_device *dev,
case ETH_SS_STATS: case ETH_SS_STATS:
/* Add main counters */ /* Add main counters */
if (!priv->stats_bitmap) { for (i = 0; i < NUM_MAIN_STATS; i++, strings++,
for (i = 0; i < NUM_MAIN_STATS; i++) bitmap_iterator_inc(&it))
if (bitmap_iterator_test(&it))
strcpy(data + (index++) * ETH_GSTRING_LEN, strcpy(data + (index++) * ETH_GSTRING_LEN,
main_strings[i]); main_strings[strings]);
for (i = 0; i < NUM_PORT_STATS; i++)
for (i = 0; i < NUM_PORT_STATS; i++, strings++,
bitmap_iterator_inc(&it))
if (bitmap_iterator_test(&it))
strcpy(data + (index++) * ETH_GSTRING_LEN, strcpy(data + (index++) * ETH_GSTRING_LEN,
main_strings[i + main_strings[strings]);
NUM_MAIN_STATS]);
for (i = 0; i < NUM_PKT_STATS; i++) for (i = 0; i < NUM_PKT_STATS; i++, strings++,
bitmap_iterator_inc(&it))
if (bitmap_iterator_test(&it))
strcpy(data + (index++) * ETH_GSTRING_LEN, strcpy(data + (index++) * ETH_GSTRING_LEN,
main_strings[i + main_strings[strings]);
NUM_MAIN_STATS +
NUM_PORT_STATS]);
} else
for (i = 0; i < NUM_MAIN_STATS + NUM_PORT_STATS; i++) {
if ((priv->stats_bitmap >> i) & 1) {
strcpy(data +
(index++) * ETH_GSTRING_LEN,
main_strings[i]);
}
if (!(priv->stats_bitmap >> i))
break;
}
for (i = 0; i < priv->tx_ring_num; i++) { for (i = 0; i < priv->tx_ring_num; i++) {
sprintf(data + (index++) * ETH_GSTRING_LEN, sprintf(data + (index++) * ETH_GSTRING_LEN,
"tx%d_packets", i); "tx%d_packets", i);
......
...@@ -49,11 +49,6 @@ ...@@ -49,11 +49,6 @@
#include "mlx4_en.h" #include "mlx4_en.h"
#include "en_port.h" #include "en_port.h"
#define MLX4_STATS_TRAFFIC_COUNTERS_MASK 0xfULL
#define MLX4_STATS_TRAFFIC_DROPS_MASK 0xc0ULL
#define MLX4_STATS_ERROR_COUNTERS_MASK 0x1ffc30ULL
#define MLX4_STATS_PORT_COUNTERS_MASK 0x7fe00000ULL
int mlx4_en_setup_tc(struct net_device *dev, u8 up) int mlx4_en_setup_tc(struct net_device *dev, u8 up)
{ {
struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_priv *priv = netdev_priv(dev);
...@@ -2653,19 +2648,36 @@ int mlx4_en_netdev_event(struct notifier_block *this, ...@@ -2653,19 +2648,36 @@ int mlx4_en_netdev_event(struct notifier_block *this,
return NOTIFY_DONE; return NOTIFY_DONE;
} }
void mlx4_en_set_stats_bitmap(struct mlx4_dev *dev, u64 *stats_bitmap) void mlx4_en_set_stats_bitmap(struct mlx4_dev *dev,
unsigned long *stats_bitmap)
{ {
if (!mlx4_is_mfunc(dev)) { int last_i = 0;
*stats_bitmap = 0;
return; bitmap_zero(stats_bitmap, NUM_ALL_STATS);
if (mlx4_is_slave(dev)) {
bitmap_set(stats_bitmap, last_i +
MLX4_FIND_NETDEV_STAT(rx_packets), 1);
bitmap_set(stats_bitmap, last_i +
MLX4_FIND_NETDEV_STAT(tx_packets), 1);
bitmap_set(stats_bitmap, last_i +
MLX4_FIND_NETDEV_STAT(rx_bytes), 1);
bitmap_set(stats_bitmap, last_i +
MLX4_FIND_NETDEV_STAT(tx_bytes), 1);
bitmap_set(stats_bitmap, last_i +
MLX4_FIND_NETDEV_STAT(rx_dropped), 1);
bitmap_set(stats_bitmap, last_i +
MLX4_FIND_NETDEV_STAT(tx_dropped), 1);
} else {
bitmap_set(stats_bitmap, last_i, NUM_MAIN_STATS);
} }
last_i += NUM_MAIN_STATS;
*stats_bitmap = (MLX4_STATS_TRAFFIC_COUNTERS_MASK | bitmap_set(stats_bitmap, last_i, NUM_PORT_STATS);
MLX4_STATS_TRAFFIC_DROPS_MASK | last_i += NUM_PORT_STATS;
MLX4_STATS_PORT_COUNTERS_MASK);
if (mlx4_is_master(dev)) if (!mlx4_is_slave(dev))
*stats_bitmap |= MLX4_STATS_ERROR_COUNTERS_MASK; bitmap_set(stats_bitmap, last_i, NUM_PKT_STATS);
} }
int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
...@@ -2901,7 +2913,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, ...@@ -2901,7 +2913,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
queue_delayed_work(mdev->workqueue, &priv->service_task, queue_delayed_work(mdev->workqueue, &priv->service_task,
SERVICE_TASK_DELAY); SERVICE_TASK_DELAY);
mlx4_en_set_stats_bitmap(mdev->dev, &priv->stats_bitmap); mlx4_en_set_stats_bitmap(mdev->dev, priv->stats_bitmap);
return 0; return 0;
......
...@@ -561,7 +561,7 @@ struct mlx4_en_priv { ...@@ -561,7 +561,7 @@ struct mlx4_en_priv {
struct mlx4_en_perf_stats pstats; struct mlx4_en_perf_stats pstats;
struct mlx4_en_pkt_stats pkstats; struct mlx4_en_pkt_stats pkstats;
struct mlx4_en_port_stats port_stats; struct mlx4_en_port_stats port_stats;
u64 stats_bitmap; DECLARE_BITMAP(stats_bitmap, NUM_ALL_STATS);
struct list_head mc_list; struct list_head mc_list;
struct list_head curr_list; struct list_head curr_list;
u64 broadcast_id; u64 broadcast_id;
...@@ -730,7 +730,8 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, ...@@ -730,7 +730,8 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
int mlx4_en_start_port(struct net_device *dev); int mlx4_en_start_port(struct net_device *dev);
void mlx4_en_stop_port(struct net_device *dev, int detach); void mlx4_en_stop_port(struct net_device *dev, int detach);
void mlx4_en_set_stats_bitmap(struct mlx4_dev *dev, u64 *stats_bitmap); void mlx4_en_set_stats_bitmap(struct mlx4_dev *dev,
unsigned long *stats_bitmap);
void mlx4_en_free_resources(struct mlx4_en_priv *priv); void mlx4_en_free_resources(struct mlx4_en_priv *priv);
int mlx4_en_alloc_resources(struct mlx4_en_priv *priv); int mlx4_en_alloc_resources(struct mlx4_en_priv *priv);
......
...@@ -44,4 +44,8 @@ struct mlx4_en_perf_stats { ...@@ -44,4 +44,8 @@ struct mlx4_en_perf_stats {
#define NUM_MAIN_STATS 21 #define NUM_MAIN_STATS 21
#define NUM_ALL_STATS (NUM_MAIN_STATS + NUM_PORT_STATS + NUM_PKT_STATS + \ #define NUM_ALL_STATS (NUM_MAIN_STATS + NUM_PORT_STATS + NUM_PKT_STATS + \
NUM_PERF_STATS) NUM_PERF_STATS)
#define MLX4_FIND_NETDEV_STAT(n) (offsetof(struct net_device_stats, n) / \
sizeof(((struct net_device_stats *)0)->n))
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment