mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 06:02:05 +00:00
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: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
0af8c8ae34
@ -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,16 +2233,22 @@ 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_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]);
|
||||
|
||||
for (i = 0; i < priv->num_rx_rings; i++)
|
||||
enetc_enable_rxbdr(hw, priv->rx_ring[i]);
|
||||
}
|
||||
|
||||
static void enetc_disable_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
|
||||
@ -2251,16 +2267,22 @@ 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_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]);
|
||||
|
||||
for (i = 0; i < priv->num_rx_rings; i++)
|
||||
enetc_disable_rxbdr(hw, priv->rx_ring[i]);
|
||||
}
|
||||
|
||||
static void enetc_wait_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring)
|
||||
@ -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);
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user