| From f048fa9c8686119c3858a463cab6121dced7c0bf Mon Sep 17 00:00:00 2001 |
| From: Michael Chan <mchan@broadcom.com> |
| Date: Tue, 1 Jun 2010 15:05:36 +0000 |
| Subject: bnx2: Fix hang during rmmod bnx2. |
| |
| From: Michael Chan <mchan@broadcom.com> |
| |
| commit f048fa9c8686119c3858a463cab6121dced7c0bf upstream. |
| |
| The regression is caused by: |
| |
| commit 4327ba435a56ada13eedf3eb332e583c7a0586a9 |
| bnx2: Fix netpoll crash. |
| |
| If ->open() and ->close() are called multiple times, the same napi structs |
| will be added to dev->napi_list multiple times, corrupting the dev->napi_list. |
| This causes free_netdev() to hang during rmmod. |
| |
| We fix this by calling netif_napi_del() during ->close(). |
| |
| Also, bnx2_init_napi() must not be in the __devinit section since it is |
| called by ->open(). |
| |
| Signed-off-by: Michael Chan <mchan@broadcom.com> |
| Signed-off-by: Benjamin Li <benli@broadcom.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| drivers/net/bnx2.c | 14 +++++++++++++- |
| 1 file changed, 13 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/net/bnx2.c |
| +++ b/drivers/net/bnx2.c |
| @@ -248,6 +248,7 @@ static const struct flash_spec flash_570 |
| MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl); |
| |
| static void bnx2_init_napi(struct bnx2 *bp); |
| +static void bnx2_del_napi(struct bnx2 *bp); |
| |
| static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_tx_ring_info *txr) |
| { |
| @@ -6237,6 +6238,7 @@ open_err: |
| bnx2_free_skbs(bp); |
| bnx2_free_irq(bp); |
| bnx2_free_mem(bp); |
| + bnx2_del_napi(bp); |
| return rc; |
| } |
| |
| @@ -6444,6 +6446,7 @@ bnx2_close(struct net_device *dev) |
| bnx2_free_irq(bp); |
| bnx2_free_skbs(bp); |
| bnx2_free_mem(bp); |
| + bnx2_del_napi(bp); |
| bp->link_up = 0; |
| netif_carrier_off(bp->dev); |
| bnx2_set_power_state(bp, PCI_D3hot); |
| @@ -8019,7 +8022,16 @@ bnx2_bus_string(struct bnx2 *bp, char *s |
| return str; |
| } |
| |
| -static void __devinit |
| +static void |
| +bnx2_del_napi(struct bnx2 *bp) |
| +{ |
| + int i; |
| + |
| + for (i = 0; i < bp->irq_nvecs; i++) |
| + netif_napi_del(&bp->bnx2_napi[i].napi); |
| +} |
| + |
| +static void |
| bnx2_init_napi(struct bnx2 *bp) |
| { |
| int i; |