Patch "net/ncsi: Avoid channel_monitor hrtimer deadlock" has been added to the 4.14-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/ncsi: Avoid channel_monitor hrtimer deadlock

to the 4.14-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-ncsi-avoid-channel_monitor-hrtimer-deadlock.patch
and it can be found in the queue-4.14 subdirectory.

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



commit 86a2441dd24df95ccf777fddfe1a64ebedb2971b
Author: Milton Miller <miltonm@xxxxxxxxxx>
Date:   Mon Mar 29 10:20:39 2021 -0500

    net/ncsi: Avoid channel_monitor hrtimer deadlock
    
    [ Upstream commit 03cb4d05b4ea9a3491674ca40952adb708d549fa ]
    
    Calling ncsi_stop_channel_monitor from channel_monitor is a guaranteed
    deadlock on SMP because stop calls del_timer_sync on the timer that
    invoked channel_monitor as its timer function.
    
    Recognise the inherent race of marking the monitor disabled before
    deleting the timer by just returning if enable was cleared.  After
    a timeout (the default case -- reset to START when response received)
    just mark the monitor.enabled false.
    
    If the channel has an entry on the channel_queue list, or if the
    state is not ACTIVE or INACTIVE, then warn and mark the timer stopped
    and don't restart, as the locking is broken somehow.
    
    Fixes: 0795fb2021f0 ("net/ncsi: Stop monitor if channel times out or is inactive")
    Signed-off-by: Milton Miller <miltonm@xxxxxxxxxx>
    Signed-off-by: Eddie James <eajames@xxxxxxxxxxxxx>
    Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
index 28c42b22b748..6b7f9e1f64d3 100644
--- a/net/ncsi/ncsi-manage.c
+++ b/net/ncsi/ncsi-manage.c
@@ -203,13 +203,20 @@ static void ncsi_channel_monitor(unsigned long data)
 	monitor_state = nc->monitor.state;
 	spin_unlock_irqrestore(&nc->lock, flags);
 
-	if (!enabled || chained) {
-		ncsi_stop_channel_monitor(nc);
-		return;
-	}
+	if (!enabled)
+		return;		/* expected race disabling timer */
+	if (WARN_ON_ONCE(chained))
+		goto bad_state;
+
 	if (state != NCSI_CHANNEL_INACTIVE &&
 	    state != NCSI_CHANNEL_ACTIVE) {
-		ncsi_stop_channel_monitor(nc);
+bad_state:
+		netdev_warn(ndp->ndev.dev,
+			    "Bad NCSI monitor state channel %d 0x%x %s queue\n",
+			    nc->id, state, chained ? "on" : "off");
+		spin_lock_irqsave(&nc->lock, flags);
+		nc->monitor.enabled = false;
+		spin_unlock_irqrestore(&nc->lock, flags);
 		return;
 	}
 
@@ -234,10 +241,9 @@ static void ncsi_channel_monitor(unsigned long data)
 			ndp->flags |= NCSI_DEV_RESHUFFLE;
 		}
 
-		ncsi_stop_channel_monitor(nc);
-
 		ncm = &nc->modes[NCSI_MODE_LINK];
 		spin_lock_irqsave(&nc->lock, flags);
+		nc->monitor.enabled = false;
 		nc->state = NCSI_CHANNEL_INVISIBLE;
 		ncm->data[2] &= ~0x1;
 		spin_unlock_irqrestore(&nc->lock, flags);



[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