diff options
| -rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 71 |
1 files changed, 59 insertions, 12 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 0a3bb53f3eee..13f814485a36 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | |||
| @@ -12721,17 +12721,11 @@ init_one_exit: | |||
| 12721 | return rc; | 12721 | return rc; |
| 12722 | } | 12722 | } |
| 12723 | 12723 | ||
| 12724 | static void bnx2x_remove_one(struct pci_dev *pdev) | 12724 | static void __bnx2x_remove(struct pci_dev *pdev, |
| 12725 | struct net_device *dev, | ||
| 12726 | struct bnx2x *bp, | ||
| 12727 | bool remove_netdev) | ||
| 12725 | { | 12728 | { |
| 12726 | struct net_device *dev = pci_get_drvdata(pdev); | ||
| 12727 | struct bnx2x *bp; | ||
| 12728 | |||
| 12729 | if (!dev) { | ||
| 12730 | dev_err(&pdev->dev, "BAD net device from bnx2x_init_one\n"); | ||
| 12731 | return; | ||
| 12732 | } | ||
| 12733 | bp = netdev_priv(dev); | ||
| 12734 | |||
| 12735 | /* Delete storage MAC address */ | 12729 | /* Delete storage MAC address */ |
| 12736 | if (!NO_FCOE(bp)) { | 12730 | if (!NO_FCOE(bp)) { |
| 12737 | rtnl_lock(); | 12731 | rtnl_lock(); |
| @@ -12744,7 +12738,15 @@ static void bnx2x_remove_one(struct pci_dev *pdev) | |||
| 12744 | bnx2x_dcbnl_update_applist(bp, true); | 12738 | bnx2x_dcbnl_update_applist(bp, true); |
| 12745 | #endif | 12739 | #endif |
| 12746 | 12740 | ||
| 12747 | unregister_netdev(dev); | 12741 | /* Close the interface - either directly or implicitly */ |
| 12742 | if (remove_netdev) { | ||
| 12743 | unregister_netdev(dev); | ||
| 12744 | } else { | ||
| 12745 | rtnl_lock(); | ||
| 12746 | if (netif_running(dev)) | ||
| 12747 | bnx2x_close(dev); | ||
| 12748 | rtnl_unlock(); | ||
| 12749 | } | ||
| 12748 | 12750 | ||
| 12749 | /* Power on: we can't let PCI layer write to us while we are in D3 */ | 12751 | /* Power on: we can't let PCI layer write to us while we are in D3 */ |
| 12750 | if (IS_PF(bp)) | 12752 | if (IS_PF(bp)) |
| @@ -12766,6 +12768,12 @@ static void bnx2x_remove_one(struct pci_dev *pdev) | |||
| 12766 | if (IS_VF(bp)) | 12768 | if (IS_VF(bp)) |
| 12767 | bnx2x_vfpf_release(bp); | 12769 | bnx2x_vfpf_release(bp); |
| 12768 | 12770 | ||
| 12771 | /* Assumes no further PCIe PM changes will occur */ | ||
| 12772 | if (system_state == SYSTEM_POWER_OFF) { | ||
| 12773 | pci_wake_from_d3(pdev, bp->wol); | ||
| 12774 | pci_set_power_state(pdev, PCI_D3hot); | ||
| 12775 | } | ||
| 12776 | |||
| 12769 | if (bp->regview) | 12777 | if (bp->regview) |
| 12770 | iounmap(bp->regview); | 12778 | iounmap(bp->regview); |
| 12771 | 12779 | ||
| @@ -12780,7 +12788,8 @@ static void bnx2x_remove_one(struct pci_dev *pdev) | |||
| 12780 | } | 12788 | } |
| 12781 | bnx2x_free_mem_bp(bp); | 12789 | bnx2x_free_mem_bp(bp); |
| 12782 | 12790 | ||
| 12783 | free_netdev(dev); | 12791 | if (remove_netdev) |
| 12792 | free_netdev(dev); | ||
| 12784 | 12793 | ||
| 12785 | if (atomic_read(&pdev->enable_cnt) == 1) | 12794 | if (atomic_read(&pdev->enable_cnt) == 1) |
| 12786 | pci_release_regions(pdev); | 12795 | pci_release_regions(pdev); |
| @@ -12789,6 +12798,20 @@ static void bnx2x_remove_one(struct pci_dev *pdev) | |||
| 12789 | pci_set_drvdata(pdev, NULL); | 12798 | pci_set_drvdata(pdev, NULL); |
| 12790 | } | 12799 | } |
| 12791 | 12800 | ||
| 12801 | static void bnx2x_remove_one(struct pci_dev *pdev) | ||
| 12802 | { | ||
| 12803 | struct net_device *dev = pci_get_drvdata(pdev); | ||
| 12804 | struct bnx2x *bp; | ||
| 12805 | |||
| 12806 | if (!dev) { | ||
| 12807 | dev_err(&pdev->dev, "BAD net device from bnx2x_init_one\n"); | ||
| 12808 | return; | ||
| 12809 | } | ||
| 12810 | bp = netdev_priv(dev); | ||
| 12811 | |||
| 12812 | __bnx2x_remove(pdev, dev, bp, true); | ||
| 12813 | } | ||
| 12814 | |||
| 12792 | static int bnx2x_eeh_nic_unload(struct bnx2x *bp) | 12815 | static int bnx2x_eeh_nic_unload(struct bnx2x *bp) |
| 12793 | { | 12816 | { |
| 12794 | bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT; | 12817 | bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT; |
| @@ -12968,6 +12991,29 @@ static const struct pci_error_handlers bnx2x_err_handler = { | |||
| 12968 | .resume = bnx2x_io_resume, | 12991 | .resume = bnx2x_io_resume, |
| 12969 | }; | 12992 | }; |
| 12970 | 12993 | ||
| 12994 | static void bnx2x_shutdown(struct pci_dev *pdev) | ||
| 12995 | { | ||
| 12996 | struct net_device *dev = pci_get_drvdata(pdev); | ||
| 12997 | struct bnx2x *bp; | ||
| 12998 | |||
| 12999 | if (!dev) | ||
| 13000 | return; | ||
| 13001 | |||
| 13002 | bp = netdev_priv(dev); | ||
| 13003 | if (!bp) | ||
| 13004 | return; | ||
| 13005 | |||
| 13006 | rtnl_lock(); | ||
| 13007 | netif_device_detach(dev); | ||
| 13008 | rtnl_unlock(); | ||
| 13009 | |||
| 13010 | /* Don't remove the netdevice, as there are scenarios which will cause | ||
| 13011 | * the kernel to hang, e.g., when trying to remove bnx2i while the | ||
| 13012 | * rootfs is mounted from SAN. | ||
| 13013 | */ | ||
| 13014 | __bnx2x_remove(pdev, dev, bp, false); | ||
| 13015 | } | ||
| 13016 | |||
| 12971 | static struct pci_driver bnx2x_pci_driver = { | 13017 | static struct pci_driver bnx2x_pci_driver = { |
| 12972 | .name = DRV_MODULE_NAME, | 13018 | .name = DRV_MODULE_NAME, |
| 12973 | .id_table = bnx2x_pci_tbl, | 13019 | .id_table = bnx2x_pci_tbl, |
| @@ -12979,6 +13025,7 @@ static struct pci_driver bnx2x_pci_driver = { | |||
| 12979 | #ifdef CONFIG_BNX2X_SRIOV | 13025 | #ifdef CONFIG_BNX2X_SRIOV |
| 12980 | .sriov_configure = bnx2x_sriov_configure, | 13026 | .sriov_configure = bnx2x_sriov_configure, |
| 12981 | #endif | 13027 | #endif |
| 13028 | .shutdown = bnx2x_shutdown, | ||
| 12982 | }; | 13029 | }; |
| 12983 | 13030 | ||
| 12984 | static int __init bnx2x_init(void) | 13031 | static int __init bnx2x_init(void) |
