Skip to content

Commit 0913ec3

Browse files
tanstafelPaolo Abeni
authored andcommitted
net: ks8851: Fix deadlock with the SPI chip variant
When SMP is enabled and spinlocks are actually functional then there is a deadlock with the 'statelock' spinlock between ks8851_start_xmit_spi and ks8851_irq: watchdog: BUG: soft lockup - CPU#0 stuck for 27s! call trace: queued_spin_lock_slowpath+0x100/0x284 do_raw_spin_lock+0x34/0x44 ks8851_start_xmit_spi+0x30/0xb8 ks8851_start_xmit+0x14/0x20 netdev_start_xmit+0x40/0x6c dev_hard_start_xmit+0x6c/0xbc sch_direct_xmit+0xa4/0x22c __qdisc_run+0x138/0x3fc qdisc_run+0x24/0x3c net_tx_action+0xf8/0x130 handle_softirqs+0x1ac/0x1f0 __do_softirq+0x14/0x20 ____do_softirq+0x10/0x1c call_on_irq_stack+0x3c/0x58 do_softirq_own_stack+0x1c/0x28 __irq_exit_rcu+0x54/0x9c irq_exit_rcu+0x10/0x1c el1_interrupt+0x38/0x50 el1h_64_irq_handler+0x18/0x24 el1h_64_irq+0x64/0x68 __netif_schedule+0x6c/0x80 netif_tx_wake_queue+0x38/0x48 ks8851_irq+0xb8/0x2c8 irq_thread_fn+0x2c/0x74 irq_thread+0x10c/0x1b0 kthread+0xc8/0xd8 ret_from_fork+0x10/0x20 This issue has not been identified earlier because tests were done on a device with SMP disabled and so spinlocks were actually NOPs. Now use spin_(un)lock_bh for TX queue related locking to avoid execution of softirq work synchronously that would lead to a deadlock. Fixes: 3dc5d44 ("net: ks8851: Fix TX stall caused by TX buffer overrun") Cc: "David S. Miller" <[email protected]> Cc: Eric Dumazet <[email protected]> Cc: Jakub Kicinski <[email protected]> Cc: Paolo Abeni <[email protected]> Cc: Simon Horman <[email protected]> Cc: [email protected] Cc: [email protected] # 5.10+ Signed-off-by: Ronald Wahl <[email protected]> Reviewed-by: Simon Horman <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
1 parent 442e26a commit 0913ec3

File tree

2 files changed

+6
-6
lines changed

2 files changed

+6
-6
lines changed

drivers/net/ethernet/micrel/ks8851_common.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -352,11 +352,11 @@ static irqreturn_t ks8851_irq(int irq, void *_ks)
352352
netif_dbg(ks, intr, ks->netdev,
353353
"%s: txspace %d\n", __func__, tx_space);
354354

355-
spin_lock(&ks->statelock);
355+
spin_lock_bh(&ks->statelock);
356356
ks->tx_space = tx_space;
357357
if (netif_queue_stopped(ks->netdev))
358358
netif_wake_queue(ks->netdev);
359-
spin_unlock(&ks->statelock);
359+
spin_unlock_bh(&ks->statelock);
360360
}
361361

362362
if (status & IRQ_SPIBEI) {
@@ -635,14 +635,14 @@ static void ks8851_set_rx_mode(struct net_device *dev)
635635

636636
/* schedule work to do the actual set of the data if needed */
637637

638-
spin_lock(&ks->statelock);
638+
spin_lock_bh(&ks->statelock);
639639

640640
if (memcmp(&rxctrl, &ks->rxctrl, sizeof(rxctrl)) != 0) {
641641
memcpy(&ks->rxctrl, &rxctrl, sizeof(ks->rxctrl));
642642
schedule_work(&ks->rxctrl_work);
643643
}
644644

645-
spin_unlock(&ks->statelock);
645+
spin_unlock_bh(&ks->statelock);
646646
}
647647

648648
static int ks8851_set_mac_address(struct net_device *dev, void *addr)

drivers/net/ethernet/micrel/ks8851_spi.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,10 +340,10 @@ static void ks8851_tx_work(struct work_struct *work)
340340

341341
tx_space = ks8851_rdreg16_spi(ks, KS_TXMIR);
342342

343-
spin_lock(&ks->statelock);
343+
spin_lock_bh(&ks->statelock);
344344
ks->queued_len -= dequeued_len;
345345
ks->tx_space = tx_space;
346-
spin_unlock(&ks->statelock);
346+
spin_unlock_bh(&ks->statelock);
347347

348348
ks8851_unlock_spi(ks, &flags);
349349
}

0 commit comments

Comments
 (0)