Skip to content

Commit e086363

Browse files
Marek Vasutkuba-moo
authored andcommitted
net: ks8851: Queue RX packets in IRQ handler instead of disabling BHs
Currently the driver uses local_bh_disable()/local_bh_enable() in its IRQ handler to avoid triggering net_rx_action() softirq on exit from netif_rx(). The net_rx_action() could trigger this driver .start_xmit callback, which is protected by the same lock as the IRQ handler, so calling the .start_xmit from netif_rx() from the IRQ handler critical section protected by the lock could lead to an attempt to claim the already claimed lock, and a hang. The local_bh_disable()/local_bh_enable() approach works only in case the IRQ handler is protected by a spinlock, but does not work if the IRQ handler is protected by mutex, i.e. this works for KS8851 with Parallel bus interface, but not for KS8851 with SPI bus interface. Remove the BH manipulation and instead of calling netif_rx() inside the IRQ handler code protected by the lock, queue all the received SKBs in the IRQ handler into a queue first, and once the IRQ handler exits the critical section protected by the lock, dequeue all the queued SKBs and push them all into netif_rx(). At this point, it is safe to trigger the net_rx_action() softirq, since the netif_rx() call is outside of the lock that protects the IRQ handler. Fixes: be0384b ("net: ks8851: Handle softirqs at the end of IRQ thread to fix hang") Tested-by: Ronald Wahl <[email protected]> # KS8851 SPI Signed-off-by: Marek Vasut <[email protected]> Reviewed-by: Eric Dumazet <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent f2db723 commit e086363

File tree

1 file changed

+10
-6
lines changed

1 file changed

+10
-6
lines changed

drivers/net/ethernet/micrel/ks8851_common.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -234,12 +234,13 @@ static void ks8851_dbg_dumpkkt(struct ks8851_net *ks, u8 *rxpkt)
234234
/**
235235
* ks8851_rx_pkts - receive packets from the host
236236
* @ks: The device information.
237+
* @rxq: Queue of packets received in this function.
237238
*
238239
* This is called from the IRQ work queue when the system detects that there
239240
* are packets in the receive queue. Find out how many packets there are and
240241
* read them from the FIFO.
241242
*/
242-
static void ks8851_rx_pkts(struct ks8851_net *ks)
243+
static void ks8851_rx_pkts(struct ks8851_net *ks, struct sk_buff_head *rxq)
243244
{
244245
struct sk_buff *skb;
245246
unsigned rxfc;
@@ -299,7 +300,7 @@ static void ks8851_rx_pkts(struct ks8851_net *ks)
299300
ks8851_dbg_dumpkkt(ks, rxpkt);
300301

301302
skb->protocol = eth_type_trans(skb, ks->netdev);
302-
__netif_rx(skb);
303+
__skb_queue_tail(rxq, skb);
303304

304305
ks->netdev->stats.rx_packets++;
305306
ks->netdev->stats.rx_bytes += rxlen;
@@ -326,11 +327,11 @@ static void ks8851_rx_pkts(struct ks8851_net *ks)
326327
static irqreturn_t ks8851_irq(int irq, void *_ks)
327328
{
328329
struct ks8851_net *ks = _ks;
330+
struct sk_buff_head rxq;
329331
unsigned handled = 0;
330332
unsigned long flags;
331333
unsigned int status;
332-
333-
local_bh_disable();
334+
struct sk_buff *skb;
334335

335336
ks8851_lock(ks, &flags);
336337

@@ -384,7 +385,8 @@ static irqreturn_t ks8851_irq(int irq, void *_ks)
384385
* from the device so do not bother masking just the RX
385386
* from the device. */
386387

387-
ks8851_rx_pkts(ks);
388+
__skb_queue_head_init(&rxq);
389+
ks8851_rx_pkts(ks, &rxq);
388390
}
389391

390392
/* if something stopped the rx process, probably due to wanting
@@ -408,7 +410,9 @@ static irqreturn_t ks8851_irq(int irq, void *_ks)
408410
if (status & IRQ_LCI)
409411
mii_check_link(&ks->mii);
410412

411-
local_bh_enable();
413+
if (status & IRQ_RXI)
414+
while ((skb = __skb_dequeue(&rxq)))
415+
netif_rx(skb);
412416

413417
return IRQ_HANDLED;
414418
}

0 commit comments

Comments
 (0)