Patch "tg3: Fix soft lockup when tg3_reset_task() fails." has been added to the 5.4-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

    tg3: Fix soft lockup when tg3_reset_task() fails.

to the 5.4-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:
     tg3-fix-soft-lockup-when-tg3_reset_task-fails.patch
and it can be found in the queue-5.4 subdirectory.

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



commit db6e84afb80188a7a9e226964ea285ede92415d7
Author: Michael Chan <michael.chan@xxxxxxxxxxxx>
Date:   Thu Sep 3 14:28:54 2020 -0400

    tg3: Fix soft lockup when tg3_reset_task() fails.
    
    [ Upstream commit 556699341efa98243e08e34401b3f601da91f5a3 ]
    
    If tg3_reset_task() fails, the device state is left in an inconsistent
    state with IFF_RUNNING still set but NAPI state not enabled.  A
    subsequent operation, such as ifdown or AER error can cause it to
    soft lock up when it tries to disable NAPI state.
    
    Fix it by bringing down the device to !IFF_RUNNING state when
    tg3_reset_task() fails.  tg3_reset_task() running from workqueue
    will now call tg3_close() when the reset fails.  We need to
    modify tg3_reset_task_cancel() slightly to avoid tg3_close()
    calling cancel_work_sync() to cancel tg3_reset_task().  Otherwise
    cancel_work_sync() will wait forever for tg3_reset_task() to
    finish.
    
    Reported-by: David Christensen <drc@xxxxxxxxxxxxxxxxxx>
    Reported-by: Baptiste Covolato <baptiste@xxxxxxxxxx>
    Fixes: db2199737990 ("tg3: Schedule at most one tg3_reset_task run")
    Signed-off-by: Michael Chan <michael.chan@xxxxxxxxxxxx>
    Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index e12ba81288e64..70bd79dc43f2e 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -7227,8 +7227,8 @@ static inline void tg3_reset_task_schedule(struct tg3 *tp)
 
 static inline void tg3_reset_task_cancel(struct tg3 *tp)
 {
-	cancel_work_sync(&tp->reset_task);
-	tg3_flag_clear(tp, RESET_TASK_PENDING);
+	if (test_and_clear_bit(TG3_FLAG_RESET_TASK_PENDING, tp->tg3_flags))
+		cancel_work_sync(&tp->reset_task);
 	tg3_flag_clear(tp, TX_RECOVERY_PENDING);
 }
 
@@ -11219,18 +11219,27 @@ static void tg3_reset_task(struct work_struct *work)
 
 	tg3_halt(tp, RESET_KIND_SHUTDOWN, 0);
 	err = tg3_init_hw(tp, true);
-	if (err)
+	if (err) {
+		tg3_full_unlock(tp);
+		tp->irq_sync = 0;
+		tg3_napi_enable(tp);
+		/* Clear this flag so that tg3_reset_task_cancel() will not
+		 * call cancel_work_sync() and wait forever.
+		 */
+		tg3_flag_clear(tp, RESET_TASK_PENDING);
+		dev_close(tp->dev);
 		goto out;
+	}
 
 	tg3_netif_start(tp);
 
-out:
 	tg3_full_unlock(tp);
 
 	if (!err)
 		tg3_phy_start(tp);
 
 	tg3_flag_clear(tp, RESET_TASK_PENDING);
+out:
 	rtnl_unlock();
 }
 



[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