Commit 63a664b7 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

net/mlx4_en: fix tx_dropped bug

1) mlx4_en_xmit() can increment priv->stats.tx_dropped, but this variable
is overwritten in mlx4_en_DUMP_ETH_STATS().

2) This increment was not SMP safe, as a port might have many TX queues.

Add a per TX ring tx_dropped to fix these issues.

This is u32 as mlx4_en_DUMP_ETH_STATS() will add a 32bit field.

So lets avoid bugs with SNMP agents having to cope with partial
overwraps. (One of these agents being bond_fold_stats())
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reported-by: default avatarWillem de Bruijn <willemb@google.com>
Cc: Eugenia Emantayev <eugenia@mellanox.com>
Acked-by: default avatarAlexei Starovoitov <ast@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent bed187b5
...@@ -1892,6 +1892,7 @@ static void mlx4_en_clear_stats(struct net_device *dev) ...@@ -1892,6 +1892,7 @@ static void mlx4_en_clear_stats(struct net_device *dev)
priv->tx_ring[i]->bytes = 0; priv->tx_ring[i]->bytes = 0;
priv->tx_ring[i]->packets = 0; priv->tx_ring[i]->packets = 0;
priv->tx_ring[i]->tx_csum = 0; priv->tx_ring[i]->tx_csum = 0;
priv->tx_ring[i]->tx_dropped = 0;
} }
for (i = 0; i < priv->rx_ring_num; i++) { for (i = 0; i < priv->rx_ring_num; i++) {
priv->rx_ring[i]->bytes = 0; priv->rx_ring[i]->bytes = 0;
......
...@@ -188,6 +188,7 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset) ...@@ -188,6 +188,7 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
} }
stats->tx_packets = 0; stats->tx_packets = 0;
stats->tx_bytes = 0; stats->tx_bytes = 0;
stats->tx_dropped = 0;
priv->port_stats.tx_chksum_offload = 0; priv->port_stats.tx_chksum_offload = 0;
priv->port_stats.queue_stopped = 0; priv->port_stats.queue_stopped = 0;
priv->port_stats.wake_queue = 0; priv->port_stats.wake_queue = 0;
...@@ -199,6 +200,7 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset) ...@@ -199,6 +200,7 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
stats->tx_packets += ring->packets; stats->tx_packets += ring->packets;
stats->tx_bytes += ring->bytes; stats->tx_bytes += ring->bytes;
stats->tx_dropped += ring->tx_dropped;
priv->port_stats.tx_chksum_offload += ring->tx_csum; priv->port_stats.tx_chksum_offload += ring->tx_csum;
priv->port_stats.queue_stopped += ring->queue_stopped; priv->port_stats.queue_stopped += ring->queue_stopped;
priv->port_stats.wake_queue += ring->wake_queue; priv->port_stats.wake_queue += ring->wake_queue;
...@@ -251,7 +253,7 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset) ...@@ -251,7 +253,7 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
stats->tx_fifo_errors = 0; stats->tx_fifo_errors = 0;
stats->tx_heartbeat_errors = 0; stats->tx_heartbeat_errors = 0;
stats->tx_window_errors = 0; stats->tx_window_errors = 0;
stats->tx_dropped = be32_to_cpu(mlx4_en_stats->TDROP); stats->tx_dropped += be32_to_cpu(mlx4_en_stats->TDROP);
/* RX stats */ /* RX stats */
priv->pkstats.rx_multicast_packets = stats->multicast; priv->pkstats.rx_multicast_packets = stats->multicast;
......
...@@ -726,12 +726,12 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -726,12 +726,12 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
bool inline_ok; bool inline_ok;
u32 ring_cons; u32 ring_cons;
if (!priv->port_up)
goto tx_drop;
tx_ind = skb_get_queue_mapping(skb); tx_ind = skb_get_queue_mapping(skb);
ring = priv->tx_ring[tx_ind]; ring = priv->tx_ring[tx_ind];
if (!priv->port_up)
goto tx_drop;
/* fetch ring->cons far ahead before needing it to avoid stall */ /* fetch ring->cons far ahead before needing it to avoid stall */
ring_cons = ACCESS_ONCE(ring->cons); ring_cons = ACCESS_ONCE(ring->cons);
...@@ -1030,7 +1030,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1030,7 +1030,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
tx_drop: tx_drop:
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
priv->stats.tx_dropped++; ring->tx_dropped++;
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
...@@ -270,6 +270,7 @@ struct mlx4_en_tx_ring { ...@@ -270,6 +270,7 @@ struct mlx4_en_tx_ring {
unsigned long tx_csum; unsigned long tx_csum;
unsigned long tso_packets; unsigned long tso_packets;
unsigned long xmit_more; unsigned long xmit_more;
unsigned int tx_dropped;
struct mlx4_bf bf; struct mlx4_bf bf;
unsigned long queue_stopped; unsigned long queue_stopped;
......
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