]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
bnxt_en: Don't cancel sp_task from bnxt_close_nic().
authorMichael Chan <mchan@broadcom.com>
Thu, 10 Dec 2015 00:35:43 +0000 (19:35 -0500)
committerChuck Anderson <chuck.anderson@oracle.com>
Thu, 7 Jul 2016 00:36:36 +0000 (17:36 -0700)
Orabug: 23221795

When implementing driver reset from tx_timeout in the next patch,
bnxt_close_nic() will be called from the sp_task workqueue.  Calling
cancel_work() on sp_task will hang the workqueue.

Instead, set a new bit BNXT_STATE_IN_SP_TASK when bnxt_sp_task() is running.
bnxt_close_nic() will wait for BNXT_STATE_IN_SP_TASK to clear before
proceeding.

Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
(cherry picked from commit 4cebdcec0933bf39c0ab42e8ce8c9d72f803fbe9)
Signed-off-by: Brian Maly <brian.maly@oracle.com>
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h

index fcbd3df7b087b875c96888554285415a9d2d263c..e1874196666b96bb19d29a102d21db796e487e14 100644 (file)
@@ -4696,7 +4696,9 @@ int bnxt_close_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
        bnxt_tx_disable(bp);
 
        clear_bit(BNXT_STATE_OPEN, &bp->state);
-       cancel_work_sync(&bp->sp_task);
+       smp_mb__after_atomic();
+       while (test_bit(BNXT_STATE_IN_SP_TASK, &bp->state))
+               msleep(20);
 
        /* Flush rings before disabling interrupts */
        bnxt_shutdown_nic(bp, irq_re_init);
@@ -5097,8 +5099,12 @@ static void bnxt_sp_task(struct work_struct *work)
        struct bnxt *bp = container_of(work, struct bnxt, sp_task);
        int rc;
 
-       if (!test_bit(BNXT_STATE_OPEN, &bp->state))
+       set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+       smp_mb__after_atomic();
+       if (!test_bit(BNXT_STATE_OPEN, &bp->state)) {
+               clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
                return;
+       }
 
        if (test_and_clear_bit(BNXT_RX_MASK_SP_EVENT, &bp->sp_event))
                bnxt_cfg_rx_mode(bp);
@@ -5124,6 +5130,9 @@ static void bnxt_sp_task(struct work_struct *work)
        }
        if (test_and_clear_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event))
                bnxt_reset_task(bp);
+
+       smp_mb__before_atomic();
+       clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
 }
 
 static int bnxt_init_board(struct pci_dev *pdev, struct net_device *dev)
index a8b688151e0c8343da0acff8cd9f12b589cb5624..f199f4cc8ffe05e7c5580dcc8b14b29ab1b8f3e9 100644 (file)
@@ -927,6 +927,7 @@ struct bnxt {
 
        unsigned long           state;
 #define BNXT_STATE_OPEN                0
+#define BNXT_STATE_IN_SP_TASK  1
 
        struct bnxt_irq *irq_tbl;
        u8                      mac_addr[ETH_ALEN];