Patch "net: ks8851: Queue RX packets in IRQ handler instead of disabling BHs" has been added to the 6.1-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    net: ks8851: Queue RX packets in IRQ handler instead of disabling BHs

to the 6.1-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     net-ks8851-queue-rx-packets-in-irq-handler-instead-o.patch
and it can be found in the queue-6.1 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit ce6fdf185bc8b86d0a000f09d54427282407d6c2
Author: Marek Vasut <marex@xxxxxxx>
Date:   Thu May 2 20:32:59 2024 +0200

    net: ks8851: Queue RX packets in IRQ handler instead of disabling BHs
    
    [ Upstream commit e0863634bf9f7cf36291ebb5bfa2d16632f79c49 ]
    
    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: be0384bf599c ("net: ks8851: Handle softirqs at the end of IRQ thread to fix hang")
    Tested-by: Ronald Wahl <ronald.wahl@xxxxxxxxxxx> # KS8851 SPI
    Signed-off-by: Marek Vasut <marex@xxxxxxx>
    Reviewed-by: Eric Dumazet <edumazet@xxxxxxxxxx>
    Link: https://lore.kernel.org/r/20240502183436.117117-1-marex@xxxxxxx
    Signed-off-by: Jakub Kicinski <kuba@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/net/ethernet/micrel/ks8851_common.c b/drivers/net/ethernet/micrel/ks8851_common.c
index d4cdf3d4f5525..502518cdb4618 100644
--- a/drivers/net/ethernet/micrel/ks8851_common.c
+++ b/drivers/net/ethernet/micrel/ks8851_common.c
@@ -234,12 +234,13 @@ static void ks8851_dbg_dumpkkt(struct ks8851_net *ks, u8 *rxpkt)
 /**
  * ks8851_rx_pkts - receive packets from the host
  * @ks: The device information.
+ * @rxq: Queue of packets received in this function.
  *
  * This is called from the IRQ work queue when the system detects that there
  * are packets in the receive queue. Find out how many packets there are and
  * read them from the FIFO.
  */
-static void ks8851_rx_pkts(struct ks8851_net *ks)
+static void ks8851_rx_pkts(struct ks8851_net *ks, struct sk_buff_head *rxq)
 {
 	struct sk_buff *skb;
 	unsigned rxfc;
@@ -299,7 +300,7 @@ static void ks8851_rx_pkts(struct ks8851_net *ks)
 					ks8851_dbg_dumpkkt(ks, rxpkt);
 
 				skb->protocol = eth_type_trans(skb, ks->netdev);
-				__netif_rx(skb);
+				__skb_queue_tail(rxq, skb);
 
 				ks->netdev->stats.rx_packets++;
 				ks->netdev->stats.rx_bytes += rxlen;
@@ -326,11 +327,11 @@ static void ks8851_rx_pkts(struct ks8851_net *ks)
 static irqreturn_t ks8851_irq(int irq, void *_ks)
 {
 	struct ks8851_net *ks = _ks;
+	struct sk_buff_head rxq;
 	unsigned handled = 0;
 	unsigned long flags;
 	unsigned int status;
-
-	local_bh_disable();
+	struct sk_buff *skb;
 
 	ks8851_lock(ks, &flags);
 
@@ -384,7 +385,8 @@ static irqreturn_t ks8851_irq(int irq, void *_ks)
 		 * from the device so do not bother masking just the RX
 		 * from the device. */
 
-		ks8851_rx_pkts(ks);
+		__skb_queue_head_init(&rxq);
+		ks8851_rx_pkts(ks, &rxq);
 	}
 
 	/* if something stopped the rx process, probably due to wanting
@@ -408,7 +410,9 @@ static irqreturn_t ks8851_irq(int irq, void *_ks)
 	if (status & IRQ_LCI)
 		mii_check_link(&ks->mii);
 
-	local_bh_enable();
+	if (status & IRQ_RXI)
+		while ((skb = __skb_dequeue(&rxq)))
+			netif_rx(skb);
 
 	return IRQ_HANDLED;
 }




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux