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

Commit d81db240 authored by Netanel Belgazal's avatar Netanel Belgazal Committed by David S. Miller
Browse files

net/ena: refactor ena_get_stats64 to be atomic context safe



ndo_get_stat64() can be called from atomic context, but the current
implementation sends an admin command to retrieve the statistics from
the device. This admin command can sleep.

This patch re-factors the implementation of ena_get_stats64() to use
the {rx,tx}bytes/count from the driver's inner counters, and to obtain
the rx drop counter from the asynchronous keep alive (heart bit)
event.

Signed-off-by: default avatarNetanel Belgazal <netanel@annapurnalabs.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 22b331c9
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -873,6 +873,14 @@ struct ena_admin_aenq_link_change_desc {
	u32 flags;
};

struct ena_admin_aenq_keep_alive_desc {
	struct ena_admin_aenq_common_desc aenq_common_desc;

	u32 rx_drops_low;

	u32 rx_drops_high;
};

struct ena_admin_ena_mmio_req_read_less_resp {
	u16 req_id;

+33 −15
Original line number Diff line number Diff line
@@ -2169,28 +2169,46 @@ static void ena_get_stats64(struct net_device *netdev,
			    struct rtnl_link_stats64 *stats)
{
	struct ena_adapter *adapter = netdev_priv(netdev);
	struct ena_admin_basic_stats ena_stats;
	int rc;
	struct ena_ring *rx_ring, *tx_ring;
	unsigned int start;
	u64 rx_drops;
	int i;

	if (!test_bit(ENA_FLAG_DEV_UP, &adapter->flags))
		return;

	rc = ena_com_get_dev_basic_stats(adapter->ena_dev, &ena_stats);
	if (rc)
		return;
	for (i = 0; i < adapter->num_queues; i++) {
		u64 bytes, packets;

		tx_ring = &adapter->tx_ring[i];

		do {
			start = u64_stats_fetch_begin_irq(&tx_ring->syncp);
			packets = tx_ring->tx_stats.cnt;
			bytes = tx_ring->tx_stats.bytes;
		} while (u64_stats_fetch_retry_irq(&tx_ring->syncp, start));

		stats->tx_packets += packets;
		stats->tx_bytes += bytes;

		rx_ring = &adapter->rx_ring[i];

	stats->tx_bytes = ((u64)ena_stats.tx_bytes_high << 32) |
		ena_stats.tx_bytes_low;
	stats->rx_bytes = ((u64)ena_stats.rx_bytes_high << 32) |
		ena_stats.rx_bytes_low;
		do {
			start = u64_stats_fetch_begin_irq(&rx_ring->syncp);
			packets = rx_ring->rx_stats.cnt;
			bytes = rx_ring->rx_stats.bytes;
		} while (u64_stats_fetch_retry_irq(&rx_ring->syncp, start));

		stats->rx_packets += packets;
		stats->rx_bytes += bytes;
	}

	stats->rx_packets = ((u64)ena_stats.rx_pkts_high << 32) |
		ena_stats.rx_pkts_low;
	stats->tx_packets = ((u64)ena_stats.tx_pkts_high << 32) |
		ena_stats.tx_pkts_low;
	do {
		start = u64_stats_fetch_begin_irq(&adapter->syncp);
		rx_drops = adapter->dev_stats.rx_drops;
	} while (u64_stats_fetch_retry_irq(&adapter->syncp, start));

	stats->rx_dropped = ((u64)ena_stats.rx_drops_high << 32) |
		ena_stats.rx_drops_low;
	stats->rx_dropped = rx_drops;

	stats->multicast = 0;
	stats->collisions = 0;
+1 −0
Original line number Diff line number Diff line
@@ -241,6 +241,7 @@ struct ena_stats_dev {
	u64 interface_up;
	u64 interface_down;
	u64 admin_q_pause;
	u64 rx_drops;
};

enum ena_flags_t {