Skip to content

Commit a419f47

Browse files
Wei Fanggregkh
Wei Fang
authored andcommitted
net: enetc: disable Tx BD rings after they are empty
commit 0a93f2c upstream. The Tx BD rings are disabled first in enetc_stop() and the driver waits for them to become empty. This operation is not safe while the ring is actively transmitting frames, and will cause the ring to not be empty and hardware exception. As described in the NETC block guide, software should only disable an active Tx ring after all pending ring entries have been consumed (i.e. when PI = CI). Disabling a transmit ring that is actively processing BDs risks a HW-SW race hazard whereby a hardware resource becomes assigned to work on one or more ring entries only to have those entries be removed due to the ring becoming disabled. When testing XDP_REDIRECT feautre, although all frames were blocked from being put into Tx rings during ring reconfiguration, the similar warning log was still encountered: fsl_enetc 0000:00:00.2 eno2: timeout for tx ring #6 clear fsl_enetc 0000:00:00.2 eno2: timeout for tx ring #7 clear The reason is that when there are still unsent frames in the Tx ring, disabling the Tx ring causes the remaining frames to be unable to be sent out. And the Tx ring cannot be restored, which means that even if the xdp program is uninstalled, the Tx frames cannot be sent out anymore. Therefore, correct the operation order in enect_start() and enect_stop(). Fixes: ff58fda ("net: enetc: prioritize ability to go down over packet processing") Cc: [email protected] Signed-off-by: Wei Fang <[email protected]> Reviewed-by: Vladimir Oltean <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 3718434 commit a419f47

File tree

1 file changed

+26
-10
lines changed
  • drivers/net/ethernet/freescale/enetc

1 file changed

+26
-10
lines changed

drivers/net/ethernet/freescale/enetc/enetc.c

+26-10
Original file line numberDiff line numberDiff line change
@@ -2236,18 +2236,24 @@ static void enetc_enable_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
22362236
enetc_rxbdr_wr(hw, idx, ENETC_RBMR, rbmr);
22372237
}
22382238

2239-
static void enetc_enable_bdrs(struct enetc_ndev_priv *priv)
2239+
static void enetc_enable_rx_bdrs(struct enetc_ndev_priv *priv)
22402240
{
22412241
struct enetc_hw *hw = &priv->si->hw;
22422242
int i;
22432243

2244-
for (i = 0; i < priv->num_tx_rings; i++)
2245-
enetc_enable_txbdr(hw, priv->tx_ring[i]);
2246-
22472244
for (i = 0; i < priv->num_rx_rings; i++)
22482245
enetc_enable_rxbdr(hw, priv->rx_ring[i]);
22492246
}
22502247

2248+
static void enetc_enable_tx_bdrs(struct enetc_ndev_priv *priv)
2249+
{
2250+
struct enetc_hw *hw = &priv->si->hw;
2251+
int i;
2252+
2253+
for (i = 0; i < priv->num_tx_rings; i++)
2254+
enetc_enable_txbdr(hw, priv->tx_ring[i]);
2255+
}
2256+
22512257
static void enetc_disable_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
22522258
{
22532259
int idx = rx_ring->index;
@@ -2264,18 +2270,24 @@ static void enetc_disable_txbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
22642270
enetc_txbdr_wr(hw, idx, ENETC_TBMR, 0);
22652271
}
22662272

2267-
static void enetc_disable_bdrs(struct enetc_ndev_priv *priv)
2273+
static void enetc_disable_rx_bdrs(struct enetc_ndev_priv *priv)
22682274
{
22692275
struct enetc_hw *hw = &priv->si->hw;
22702276
int i;
22712277

2272-
for (i = 0; i < priv->num_tx_rings; i++)
2273-
enetc_disable_txbdr(hw, priv->tx_ring[i]);
2274-
22752278
for (i = 0; i < priv->num_rx_rings; i++)
22762279
enetc_disable_rxbdr(hw, priv->rx_ring[i]);
22772280
}
22782281

2282+
static void enetc_disable_tx_bdrs(struct enetc_ndev_priv *priv)
2283+
{
2284+
struct enetc_hw *hw = &priv->si->hw;
2285+
int i;
2286+
2287+
for (i = 0; i < priv->num_tx_rings; i++)
2288+
enetc_disable_txbdr(hw, priv->tx_ring[i]);
2289+
}
2290+
22792291
static void enetc_wait_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring)
22802292
{
22812293
int delay = 8, timeout = 100;
@@ -2465,6 +2477,8 @@ void enetc_start(struct net_device *ndev)
24652477

24662478
enetc_setup_interrupts(priv);
24672479

2480+
enetc_enable_tx_bdrs(priv);
2481+
24682482
for (i = 0; i < priv->bdr_int_num; i++) {
24692483
int irq = pci_irq_vector(priv->si->pdev,
24702484
ENETC_BDR_INT_BASE_IDX + i);
@@ -2473,7 +2487,7 @@ void enetc_start(struct net_device *ndev)
24732487
enable_irq(irq);
24742488
}
24752489

2476-
enetc_enable_bdrs(priv);
2490+
enetc_enable_rx_bdrs(priv);
24772491

24782492
netif_tx_start_all_queues(ndev);
24792493

@@ -2539,7 +2553,7 @@ void enetc_stop(struct net_device *ndev)
25392553

25402554
netif_tx_stop_all_queues(ndev);
25412555

2542-
enetc_disable_bdrs(priv);
2556+
enetc_disable_rx_bdrs(priv);
25432557

25442558
for (i = 0; i < priv->bdr_int_num; i++) {
25452559
int irq = pci_irq_vector(priv->si->pdev,
@@ -2552,6 +2566,8 @@ void enetc_stop(struct net_device *ndev)
25522566

25532567
enetc_wait_bdrs(priv);
25542568

2569+
enetc_disable_tx_bdrs(priv);
2570+
25552571
enetc_clear_interrupts(priv);
25562572
}
25572573
EXPORT_SYMBOL_GPL(enetc_stop);

0 commit comments

Comments
 (0)