bnx2: Free IRQ before freeing status block memory
authorMichael Chan <mchan@broadcom.com>
Fri, 31 Dec 2010 19:03:14 +0000 (11:03 -0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 31 Dec 2010 19:03:14 +0000 (11:03 -0800)
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>
drivers/net/bnx2.c

index 6fa798468ad466f8459dcde37f26e96021e713b4..44aed3b0da602cb487b16ea8df15ea8abe2dd195 100644 (file)
@@ -6096,7 +6096,7 @@ bnx2_request_irq(struct bnx2 *bp)
 }
 
 static void
-bnx2_free_irq(struct bnx2 *bp)
+__bnx2_free_irq(struct bnx2 *bp)
 {
        struct bnx2_irq *irq;
        int i;
@@ -6107,6 +6107,13 @@ bnx2_free_irq(struct bnx2 *bp)
                        free_irq(irq->vector, &bp->bnx2_napi[i]);
                irq->requested = 0;
        }
+}
+
+static void
+bnx2_free_irq(struct bnx2 *bp)
+{
+
+       __bnx2_free_irq(bp);
        if (bp->flags & BNX2_FLAG_USING_MSI)
                pci_disable_msi(bp->pdev);
        else if (bp->flags & BNX2_FLAG_USING_MSIX)
@@ -7092,6 +7099,7 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
 
                bnx2_netif_stop(bp, true);
                bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET);
+               __bnx2_free_irq(bp);
                bnx2_free_skbs(bp);
                bnx2_free_mem(bp);
        }
@@ -7103,6 +7111,9 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
                int rc;
 
                rc = bnx2_alloc_mem(bp);
+               if (!rc)
+                       rc = bnx2_request_irq(bp);
+
                if (!rc)
                        rc = bnx2_init_nic(bp, 0);