summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2015-12-10 03:35:43 +0300
committerDavid S. Miller <davem@davemloft.net>2015-12-12 07:34:06 +0300
commit4cebdcec0933bf39c0ab42e8ce8c9d72f803fbe9 (patch)
treeb80eaa62f21b2f8a804475d79092930af02ee4f2 /drivers/net/ethernet
parentcaefe526d7b5af11d9b5977b2862eb144fa45537 (diff)
downloadlinux-4cebdcec0933bf39c0ab42e8ce8c9d72f803fbe9.tar.xz
bnxt_en: Don't cancel sp_task from bnxt_close_nic().
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>
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.c13
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.h1
2 files changed, 12 insertions, 2 deletions
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index fd89e9d70ab6..f5f448959ee2 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -4679,7 +4679,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);
@@ -5080,8 +5082,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);
@@ -5107,6 +5113,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)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index a8b688151e0c..f199f4cc8ffe 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -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];