aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2010-12-31 14:03:14 -0500
committerDavid S. Miller <davem@davemloft.net>2010-12-31 14:03:14 -0500
commita29ba9d2d84889686a3af1c5a6023f28be75ccba (patch)
tree46506c127a2d37ef00dca9752cc93e15e2f7b727
parent0438a1b24437cf007ed0e0f5f6b414d5b49468dc (diff)
bnx2: Free IRQ before freeing status block memory
When changing ring size, we free all memory including status block memory. If we're in INTA mode and sharing IRQ, the IRQ handler can be called and it will reference the NULL status block pointer. Because of the lockless design of the IRQ handler, there is no simple way to synchronize and prevent this. So we avoid this problem by freeing the IRQ handler before freeing the status block memory. Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/bnx2.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 6fa798468ad4..44aed3b0da60 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -6096,7 +6096,7 @@ bnx2_request_irq(struct bnx2 *bp)
6096} 6096}
6097 6097
6098static void 6098static void
6099bnx2_free_irq(struct bnx2 *bp) 6099__bnx2_free_irq(struct bnx2 *bp)
6100{ 6100{
6101 struct bnx2_irq *irq; 6101 struct bnx2_irq *irq;
6102 int i; 6102 int i;
@@ -6107,6 +6107,13 @@ bnx2_free_irq(struct bnx2 *bp)
6107 free_irq(irq->vector, &bp->bnx2_napi[i]); 6107 free_irq(irq->vector, &bp->bnx2_napi[i]);
6108 irq->requested = 0; 6108 irq->requested = 0;
6109 } 6109 }
6110}
6111
6112static void
6113bnx2_free_irq(struct bnx2 *bp)
6114{
6115
6116 __bnx2_free_irq(bp);
6110 if (bp->flags & BNX2_FLAG_USING_MSI) 6117 if (bp->flags & BNX2_FLAG_USING_MSI)
6111 pci_disable_msi(bp->pdev); 6118 pci_disable_msi(bp->pdev);
6112 else if (bp->flags & BNX2_FLAG_USING_MSIX) 6119 else if (bp->flags & BNX2_FLAG_USING_MSIX)
@@ -7092,6 +7099,7 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
7092 7099
7093 bnx2_netif_stop(bp, true); 7100 bnx2_netif_stop(bp, true);
7094 bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET); 7101 bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET);
7102 __bnx2_free_irq(bp);
7095 bnx2_free_skbs(bp); 7103 bnx2_free_skbs(bp);
7096 bnx2_free_mem(bp); 7104 bnx2_free_mem(bp);
7097 } 7105 }
@@ -7104,6 +7112,9 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
7104 7112
7105 rc = bnx2_alloc_mem(bp); 7113 rc = bnx2_alloc_mem(bp);
7106 if (!rc) 7114 if (!rc)
7115 rc = bnx2_request_irq(bp);
7116
7117 if (!rc)
7107 rc = bnx2_init_nic(bp, 0); 7118 rc = bnx2_init_nic(bp, 0);
7108 7119
7109 if (rc) { 7120 if (rc) {