Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1892,6 +1892,7 @@ static void mlx4_en_clear_stats(struct net_device *dev)
		priv->tx_ring[i]->bytes = 0;
		priv->tx_ring[i]->packets = 0;
		priv->tx_ring[i]->tx_csum = 0;
		priv->tx_ring[i]->tx_dropped = 0;
	}
	for (i = 0; i < priv->rx_ring_num; i++) {
		priv->rx_ring[i]->bytes = 0;
+3 −1
Original line number Diff line number Diff line
@@ -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_bytes = 0;
	stats->tx_dropped = 0;
	priv->port_stats.tx_chksum_offload = 0;
	priv->port_stats.queue_stopped = 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)

		stats->tx_packets += ring->packets;
		stats->tx_bytes += ring->bytes;
		stats->tx_dropped += ring->tx_dropped;
		priv->port_stats.tx_chksum_offload += ring->tx_csum;
		priv->port_stats.queue_stopped     += ring->queue_stopped;
		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)
	stats->tx_fifo_errors = 0;
	stats->tx_heartbeat_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 */
	priv->pkstats.rx_multicast_packets = stats->multicast;
+4 −4
Original line number Diff line number Diff line
@@ -726,12 +726,12 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
	bool inline_ok;
	u32 ring_cons;

	if (!priv->port_up)
		goto tx_drop;

	tx_ind = skb_get_queue_mapping(skb);
	ring = priv->tx_ring[tx_ind];

	if (!priv->port_up)
		goto tx_drop;

	/* fetch ring->cons far ahead before needing it to avoid stall */
	ring_cons = ACCESS_ONCE(ring->cons);

@@ -1030,7 +1030,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)

tx_drop:
	dev_kfree_skb_any(skb);
	priv->stats.tx_dropped++;
	ring->tx_dropped++;
	return NETDEV_TX_OK;
}
+1 −0
Original line number Diff line number Diff line
@@ -270,6 +270,7 @@ struct mlx4_en_tx_ring {
	unsigned long		tx_csum;
	unsigned long		tso_packets;
	unsigned long		xmit_more;
	unsigned int		tx_dropped;
	struct mlx4_bf		bf;
	unsigned long		queue_stopped;