Commit 0af8c8ae authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'net-enetc-fix-some-issues-of-xdp'

Wei Fang says:

====================
net: enetc: fix some issues of XDP

We found some bugs when testing the XDP function of enetc driver,
and these bugs are easy to reproduce. This is not only causes XDP
to not work, but also the network cannot be restored after exiting
the XDP program. So the patch set is mainly to fix these bugs. For
details, please see the commit message of each patch.

v1: https://lore.kernel.org/bpf/20240919084104.661180-1-wei.fang@nxp.com/
v2: https://lore.kernel.org/netdev/20241008224806.2onzkt3gbslw5jxb@skbuf/
v3: https://lore.kernel.org/imx/20241009090327.146461-1-wei.fang@nxp.com/
====================

Link: https://patch.msgid.link/20241010092056.298128-1-wei.fang@nxp.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 8a6be4bd 6b58fadd
Loading
Loading
Loading
Loading
+43 −13
Original line number Diff line number Diff line
@@ -902,6 +902,7 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)

	if (unlikely(tx_frm_cnt && netif_carrier_ok(ndev) &&
		     __netif_subqueue_stopped(ndev, tx_ring->index) &&
		     !test_bit(ENETC_TX_DOWN, &priv->flags) &&
		     (enetc_bd_unused(tx_ring) >= ENETC_TXBDS_MAX_NEEDED))) {
		netif_wake_subqueue(ndev, tx_ring->index);
	}
@@ -1377,6 +1378,9 @@ int enetc_xdp_xmit(struct net_device *ndev, int num_frames,
	int xdp_tx_bd_cnt, i, k;
	int xdp_tx_frm_cnt = 0;

	if (unlikely(test_bit(ENETC_TX_DOWN, &priv->flags)))
		return -ENETDOWN;

	enetc_lock_mdio();

	tx_ring = priv->xdp_tx_ring[smp_processor_id()];
@@ -1521,7 +1525,6 @@ static void enetc_xdp_drop(struct enetc_bdr *rx_ring, int rx_ring_first,
				  &rx_ring->rx_swbd[rx_ring_first]);
		enetc_bdr_idx_inc(rx_ring, &rx_ring_first);
	}
	rx_ring->stats.xdp_drops++;
}

static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring,
@@ -1586,6 +1589,7 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring,
			fallthrough;
		case XDP_DROP:
			enetc_xdp_drop(rx_ring, orig_i, i);
			rx_ring->stats.xdp_drops++;
			break;
		case XDP_PASS:
			rxbd = orig_rxbd;
@@ -1602,6 +1606,12 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring,
			break;
		case XDP_TX:
			tx_ring = priv->xdp_tx_ring[rx_ring->index];
			if (unlikely(test_bit(ENETC_TX_DOWN, &priv->flags))) {
				enetc_xdp_drop(rx_ring, orig_i, i);
				tx_ring->stats.xdp_tx_drops++;
				break;
			}

			xdp_tx_bd_cnt = enetc_rx_swbd_to_xdp_tx_swbd(xdp_tx_arr,
								     rx_ring,
								     orig_i, i);
@@ -2223,18 +2233,24 @@ static void enetc_enable_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
	enetc_rxbdr_wr(hw, idx, ENETC_RBMR, rbmr);
}

static void enetc_enable_bdrs(struct enetc_ndev_priv *priv)
static void enetc_enable_rx_bdrs(struct enetc_ndev_priv *priv)
{
	struct enetc_hw *hw = &priv->si->hw;
	int i;

	for (i = 0; i < priv->num_tx_rings; i++)
		enetc_enable_txbdr(hw, priv->tx_ring[i]);

	for (i = 0; i < priv->num_rx_rings; i++)
		enetc_enable_rxbdr(hw, priv->rx_ring[i]);
}

static void enetc_enable_tx_bdrs(struct enetc_ndev_priv *priv)
{
	struct enetc_hw *hw = &priv->si->hw;
	int i;

	for (i = 0; i < priv->num_tx_rings; i++)
		enetc_enable_txbdr(hw, priv->tx_ring[i]);
}

static void enetc_disable_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
{
	int idx = rx_ring->index;
@@ -2251,18 +2267,24 @@ static void enetc_disable_txbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
	enetc_txbdr_wr(hw, idx, ENETC_TBMR, 0);
}

static void enetc_disable_bdrs(struct enetc_ndev_priv *priv)
static void enetc_disable_rx_bdrs(struct enetc_ndev_priv *priv)
{
	struct enetc_hw *hw = &priv->si->hw;
	int i;

	for (i = 0; i < priv->num_tx_rings; i++)
		enetc_disable_txbdr(hw, priv->tx_ring[i]);

	for (i = 0; i < priv->num_rx_rings; i++)
		enetc_disable_rxbdr(hw, priv->rx_ring[i]);
}

static void enetc_disable_tx_bdrs(struct enetc_ndev_priv *priv)
{
	struct enetc_hw *hw = &priv->si->hw;
	int i;

	for (i = 0; i < priv->num_tx_rings; i++)
		enetc_disable_txbdr(hw, priv->tx_ring[i]);
}

static void enetc_wait_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring)
{
	int delay = 8, timeout = 100;
@@ -2460,9 +2482,13 @@ void enetc_start(struct net_device *ndev)
		enable_irq(irq);
	}

	enetc_enable_bdrs(priv);
	enetc_enable_tx_bdrs(priv);

	enetc_enable_rx_bdrs(priv);

	netif_tx_start_all_queues(ndev);

	clear_bit(ENETC_TX_DOWN, &priv->flags);
}
EXPORT_SYMBOL_GPL(enetc_start);

@@ -2520,9 +2546,15 @@ void enetc_stop(struct net_device *ndev)
	struct enetc_ndev_priv *priv = netdev_priv(ndev);
	int i;

	set_bit(ENETC_TX_DOWN, &priv->flags);

	netif_tx_stop_all_queues(ndev);

	enetc_disable_bdrs(priv);
	enetc_disable_rx_bdrs(priv);

	enetc_wait_bdrs(priv);

	enetc_disable_tx_bdrs(priv);

	for (i = 0; i < priv->bdr_int_num; i++) {
		int irq = pci_irq_vector(priv->si->pdev,
@@ -2533,8 +2565,6 @@ void enetc_stop(struct net_device *ndev)
		napi_disable(&priv->int_vector[i]->napi);
	}

	enetc_wait_bdrs(priv);

	enetc_clear_interrupts(priv);
}
EXPORT_SYMBOL_GPL(enetc_stop);
+1 −0
Original line number Diff line number Diff line
@@ -325,6 +325,7 @@ enum enetc_active_offloads {

enum enetc_flags_bit {
	ENETC_TX_ONESTEP_TSTAMP_IN_PROGRESS = 0,
	ENETC_TX_DOWN,
};

/* interrupt coalescing modes */