Skip to content

Commit 858430d

Browse files
Sean Andersonkuba-moo
authored andcommitted
net: xilinx: axienet: Fix race in axienet_stop
axienet_dma_err_handler can race with axienet_stop in the following manner: CPU 1 CPU 2 ====================== ================== axienet_stop() napi_disable() axienet_dma_stop() axienet_dma_err_handler() napi_disable() axienet_dma_stop() axienet_dma_start() napi_enable() cancel_work_sync() free_irq() Fix this by setting a flag in axienet_stop telling axienet_dma_err_handler not to bother doing anything. I chose not to use disable_work_sync to allow for easier backporting. Signed-off-by: Sean Anderson <[email protected]> Fixes: 8a3b7a2 ("drivers/net/ethernet/xilinx: added Xilinx AXI Ethernet driver") Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent bee2ef9 commit 858430d

File tree

2 files changed

+11
-0
lines changed

2 files changed

+11
-0
lines changed

drivers/net/ethernet/xilinx/xilinx_axienet.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,8 @@ struct skbuf_dma_descriptor {
436436
* @tx_bytes: TX byte count for statistics
437437
* @tx_stat_sync: Synchronization object for TX stats
438438
* @dma_err_task: Work structure to process Axi DMA errors
439+
* @stopping: Set when @dma_err_task shouldn't do anything because we are
440+
* about to stop the device.
439441
* @tx_irq: Axidma TX IRQ number
440442
* @rx_irq: Axidma RX IRQ number
441443
* @eth_irq: Ethernet core IRQ number
@@ -507,6 +509,7 @@ struct axienet_local {
507509
struct u64_stats_sync tx_stat_sync;
508510

509511
struct work_struct dma_err_task;
512+
bool stopping;
510513

511514
int tx_irq;
512515
int rx_irq;

drivers/net/ethernet/xilinx/xilinx_axienet_main.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1460,6 +1460,7 @@ static int axienet_init_legacy_dma(struct net_device *ndev)
14601460
struct axienet_local *lp = netdev_priv(ndev);
14611461

14621462
/* Enable worker thread for Axi DMA error handling */
1463+
lp->stopping = false;
14631464
INIT_WORK(&lp->dma_err_task, axienet_dma_err_handler);
14641465

14651466
napi_enable(&lp->napi_rx);
@@ -1580,6 +1581,9 @@ static int axienet_stop(struct net_device *ndev)
15801581
dev_dbg(&ndev->dev, "axienet_close()\n");
15811582

15821583
if (!lp->use_dmaengine) {
1584+
WRITE_ONCE(lp->stopping, true);
1585+
flush_work(&lp->dma_err_task);
1586+
15831587
napi_disable(&lp->napi_tx);
15841588
napi_disable(&lp->napi_rx);
15851589
}
@@ -2154,6 +2158,10 @@ static void axienet_dma_err_handler(struct work_struct *work)
21542158
dma_err_task);
21552159
struct net_device *ndev = lp->ndev;
21562160

2161+
/* Don't bother if we are going to stop anyway */
2162+
if (READ_ONCE(lp->stopping))
2163+
return;
2164+
21572165
napi_disable(&lp->napi_tx);
21582166
napi_disable(&lp->napi_rx);
21592167

0 commit comments

Comments
 (0)