bnx2 EEH and WoL/PM patches
Subsystems (3)
cover bnx2 EEH and WoL/PM patches
First patch fixes EEH/AER error path. The rest of the patches modernize the driver to use latest APIs for WoL and power management.
Michael Chan (6):
bnx2: Handle error condition in ->slot_reset()
bnx2: Use kernel APIs for WoL and power state changes.
bnx2: Refactor WoL setup into a separate function.
bnx2: Use SIMPLE_DEV_PM_OPS.
bnx2: Add pci shutdown handler.
bnx2: Update version to 2.2.4
drivers/net/ethernet/broadcom/bnx2.c | 308 +++++++++++++++++----------------- drivers/net/ethernet/broadcom/bnx2.h | 2 +- 2 files changed, 158 insertions(+), 152 deletions(-)
PATCH 1/6 bnx2: Handle error condition in ->slot_reset()
by closing the device if necessary. Otherwise, since NAPI state is already disabled, a subsequent close will hang the system.
--- drivers/net/ethernet/broadcom/bnx2.c | 15 ++++++++++----- 1 files changed, 10 insertions(+), 5 deletions(-)
drivers/net/ethernet/broadcom/bnx2.c +10 -5
@@ -8694,14 +8694,13 @@ static pci_ers_result_t bnx2_io_slot_reset(struct pci_dev *pdev) {struct net_device *dev =pci_get_drvdata (pdev);struct bnx2 *bp =netdev_priv (dev); -pci_ers_result_t result; -int err; +pci_ers_result_t result =PCI_ERS_RESULT_DISCONNECT ; +int err =0 ;rtnl_lock ();if (pci_enable_device (pdev)) {dev_err (&pdev->dev,"Cannot re-enable PCI device after reset\n" ); - result =PCI_ERS_RESULT_DISCONNECT ; }else {pci_set_master (pdev);pci_restore_state (pdev);
@@ -8709,9 +8708,15 @@ static pci_ers_result_t bnx2_io_slot_reset(struct pci_dev *pdev)if (netif_running (dev)) {bnx2_set_power_state (bp,PCI_D0 ); -bnx2_init_nic (bp,1 ); + err =bnx2_init_nic (bp,1 ); } - result =PCI_ERS_RESULT_RECOVERED ; +if (!err) + result =PCI_ERS_RESULT_RECOVERED ; + } + +if (result !=PCI_ERS_RESULT_RECOVERED &&netif_running (dev)) { +bnx2_napi_enable (bp); +dev_close (dev); }rtnl_unlock ();
Signature · 1 line
1.7.1
PATCH 2/6 bnx2: Use kernel APIs for WoL and power state changes.
Simple API changes with no functional changes.
--- drivers/net/ethernet/broadcom/bnx2.c | 36 +++++++++++++-------------------- 1 files changed, 14 insertions(+), 22 deletions(-)
drivers/net/ethernet/broadcom/bnx2.c +14 -22
@@ -3911,21 +3911,12 @@ init_cpu_err:static int bnx2_set_power_state (struct bnx2 *bp,pci_power_t state) { -u16 pmcsr; - -pci_read_config_word (bp->pdev, bp->pm_cap +PCI_PM_CTRL , &pmcsr); -switch (state) {case PCI_D0 : {u32 val; -pci_write_config_word (bp->pdev, bp->pm_cap +PCI_PM_CTRL , - (pmcsr & ~PCI_PM_CTRL_STATE_MASK ) | -PCI_PM_CTRL_PME_STATUS ); - -if (pmcsr &PCI_PM_CTRL_STATE_MASK ) -/* delay required during transition out of D3hot */ -msleep (20 ); +pci_enable_wake (bp->pdev,PCI_D0 , false); +pci_set_power_state (bp->pdev,PCI_D0 ); val =BNX2_RD (bp,BNX2_EMAC_MODE ); val |=BNX2_EMAC_MODE_MPKT_RCVD |BNX2_EMAC_MODE_ACPI_RCVD ;
@@ -4018,26 +4009,19 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)bnx2_fw_sync (bp,BNX2_DRV_MSG_DATA_WAIT3 | wol_msg,1 ,0 ); - pmcsr &= ~PCI_PM_CTRL_STATE_MASK ; +pci_wake_from_d3 (bp->pdev, bp->wol);if ((BNX2_CHIP_ID (bp) ==BNX2_CHIP_ID_5706_A0 ) || (BNX2_CHIP_ID (bp) ==BNX2_CHIP_ID_5706_A1 )) {if (bp->wol) - pmcsr |=3 ; - } -else { - pmcsr |=3 ; - } -if (bp->wol) { - pmcsr |=PCI_PM_CTRL_PME_ENABLE ; +pci_set_power_state (bp->pdev, PCI_D3hot); + }else { +pci_set_power_state (bp->pdev, PCI_D3hot); } -pci_write_config_word (bp->pdev, bp->pm_cap +PCI_PM_CTRL , - pmcsr);/* No more memory access after this point until * device is brought back to D0. */ -udelay (50 );break ; }default :
@@ -7081,6 +7065,9 @@ bnx2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)else { bp->wol =0 ; } + +device_set_wakeup_enable (&bp->pdev->dev, bp->wol); +return 0 ; }
@@ -8369,6 +8356,11 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->wol =0 ; } +if (bp->flags &BNX2_FLAG_NO_WOL ) +device_set_wakeup_capable (&bp->pdev->dev, false); +else +device_set_wakeup_enable (&bp->pdev->dev, bp->wol); +if (BNX2_CHIP_ID (bp) ==BNX2_CHIP_ID_5706_A0 ) { bp->tx_quick_cons_trip_int = bp->tx_quick_cons_trip;
Signature · 1 line
1.7.1
PATCH 3/6 bnx2: Refactor WoL setup into a separate function.
Separate MAC and PHY WoL setup code into a separate function.
--- drivers/net/ethernet/broadcom/bnx2.c | 161 +++++++++++++++++----------------- 1 files changed, 81 insertions(+), 80 deletions(-)
drivers/net/ethernet/broadcom/bnx2.c +81 -80
@@ -3908,6 +3908,86 @@ init_cpu_err:return rc; } +static void +bnx2_setup_wol (struct bnx2 *bp) +{ +int i; +u32 val, wol_msg; + +if (bp->wol) { +u32 advertising; +u8 autoneg; + + autoneg = bp->autoneg; + advertising = bp->advertising; + +if (bp->phy_port ==PORT_TP ) { + bp->autoneg =AUTONEG_SPEED ; + bp->advertising = ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | + ADVERTISED_Autoneg; + } + +spin_lock_bh (&bp->phy_lock); +bnx2_setup_phy (bp, bp->phy_port); +spin_unlock_bh (&bp->phy_lock); + + bp->autoneg = autoneg; + bp->advertising = advertising; + +bnx2_set_mac_addr (bp, bp->dev->dev_addr,0 ); + + val =BNX2_RD (bp,BNX2_EMAC_MODE ); + +/* Enable port mode. */ + val &= ~BNX2_EMAC_MODE_PORT ; + val |=BNX2_EMAC_MODE_MPKT_RCVD | +BNX2_EMAC_MODE_ACPI_RCVD | +BNX2_EMAC_MODE_MPKT ; +if (bp->phy_port ==PORT_TP ) { + val |=BNX2_EMAC_MODE_PORT_MII ; + }else { + val |=BNX2_EMAC_MODE_PORT_GMII ; +if (bp->line_speed ==SPEED_2500 ) + val |=BNX2_EMAC_MODE_25G_MODE ; + } + +BNX2_WR (bp,BNX2_EMAC_MODE , val); + +/* receive all multicast */ +for (i =0 ; i <NUM_MC_HASH_REGISTERS ; i++) { +BNX2_WR (bp,BNX2_EMAC_MULTICAST_HASH0 + (i *4 ), +0xffffffff ); + } +BNX2_WR (bp,BNX2_EMAC_RX_MODE ,BNX2_EMAC_RX_MODE_SORT_MODE ); + + val =1 |BNX2_RPM_SORT_USER0_BC_EN |BNX2_RPM_SORT_USER0_MC_EN ; +BNX2_WR (bp,BNX2_RPM_SORT_USER0 ,0x0 ); +BNX2_WR (bp,BNX2_RPM_SORT_USER0 , val); +BNX2_WR (bp,BNX2_RPM_SORT_USER0 , val |BNX2_RPM_SORT_USER0_ENA ); + +/* Need to enable EMAC and RPM for WOL. */ +BNX2_WR (bp,BNX2_MISC_ENABLE_SET_BITS , +BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_MAC_ENABLE | +BNX2_MISC_ENABLE_SET_BITS_TX_HEADER_Q_ENABLE | +BNX2_MISC_ENABLE_SET_BITS_EMAC_ENABLE ); + + val =BNX2_RD (bp,BNX2_RPM_CONFIG ); + val &= ~BNX2_RPM_CONFIG_ACPI_ENA ; +BNX2_WR (bp,BNX2_RPM_CONFIG , val); + + wol_msg =BNX2_DRV_MSG_CODE_SUSPEND_WOL ; + }else { + wol_msg =BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL ; + } + +if (!(bp->flags &BNX2_FLAG_NO_WOL )) +bnx2_fw_sync (bp,BNX2_DRV_MSG_DATA_WAIT3 | wol_msg,1 ,0 ); + +} +static int bnx2_set_power_state (struct bnx2 *bp,pci_power_t state) {
@@ -3929,86 +4009,7 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)break ; }case PCI_D3hot: { -int i; -u32 val, wol_msg; - -if (bp->wol) { -u32 advertising; -u8 autoneg; - - autoneg = bp->autoneg; - advertising = bp->advertising; - -if (bp->phy_port ==PORT_TP ) { - bp->autoneg =AUTONEG_SPEED ; - bp->advertising = ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | - ADVERTISED_Autoneg; - } - -spin_lock_bh (&bp->phy_lock); -bnx2_setup_phy (bp, bp->phy_port); -spin_unlock_bh (&bp->phy_lock); - - bp->autoneg = autoneg; - bp->advertising = advertising; - -bnx2_set_mac_addr (bp, bp->dev->dev_addr,0 ); - - val =BNX2_RD (bp,BNX2_EMAC_MODE ); - -/* Enable port mode. */ - val &= ~BNX2_EMAC_MODE_PORT ; - val |=BNX2_EMAC_MODE_MPKT_RCVD | -BNX2_EMAC_MODE_ACPI_RCVD | -BNX2_EMAC_MODE_MPKT ; -if (bp->phy_port ==PORT_TP ) - val |=BNX2_EMAC_MODE_PORT_MII ; -else { - val |=BNX2_EMAC_MODE_PORT_GMII ; -if (bp->line_speed ==SPEED_2500 ) - val |=BNX2_EMAC_MODE_25G_MODE ; - } - -BNX2_WR (bp,BNX2_EMAC_MODE , val); - -/* receive all multicast */ -for (i =0 ; i <NUM_MC_HASH_REGISTERS ; i++) { -BNX2_WR (bp,BNX2_EMAC_MULTICAST_HASH0 + (i *4 ), -0xffffffff ); - } -BNX2_WR (bp,BNX2_EMAC_RX_MODE , -BNX2_EMAC_RX_MODE_SORT_MODE ); - - val =1 |BNX2_RPM_SORT_USER0_BC_EN | -BNX2_RPM_SORT_USER0_MC_EN ; -BNX2_WR (bp,BNX2_RPM_SORT_USER0 ,0x0 ); -BNX2_WR (bp,BNX2_RPM_SORT_USER0 , val); -BNX2_WR (bp,BNX2_RPM_SORT_USER0 , val | -BNX2_RPM_SORT_USER0_ENA ); - -/* Need to enable EMAC and RPM for WOL. */ -BNX2_WR (bp,BNX2_MISC_ENABLE_SET_BITS , -BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_MAC_ENABLE | -BNX2_MISC_ENABLE_SET_BITS_TX_HEADER_Q_ENABLE | -BNX2_MISC_ENABLE_SET_BITS_EMAC_ENABLE ); - - val =BNX2_RD (bp,BNX2_RPM_CONFIG ); - val &= ~BNX2_RPM_CONFIG_ACPI_ENA ; -BNX2_WR (bp,BNX2_RPM_CONFIG , val); - - wol_msg =BNX2_DRV_MSG_CODE_SUSPEND_WOL ; - } -else { - wol_msg =BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL ; - } - -if (!(bp->flags &BNX2_FLAG_NO_WOL )) -bnx2_fw_sync (bp,BNX2_DRV_MSG_DATA_WAIT3 | wol_msg, -1 ,0 ); - +bnx2_setup_wol (bp);pci_wake_from_d3 (bp->pdev, bp->wol);if ((BNX2_CHIP_ID (bp) ==BNX2_CHIP_ID_5706_A0 ) || (BNX2_CHIP_ID (bp) ==BNX2_CHIP_ID_5706_A1 )) {
Signature · 1 line
1.7.1
PATCH 4/6 bnx2: Use SIMPLE_DEV_PM_OPS.
This simplifies the suspend/resume code.
--- drivers/net/ethernet/broadcom/bnx2.c | 45 +++++++++++++++++++--------------- 1 files changed, 25 insertions(+), 20 deletions(-)
drivers/net/ethernet/broadcom/bnx2.c +25 -20
@@ -8602,46 +8602,52 @@ bnx2_remove_one(struct pci_dev *pdev) }static int -bnx2_suspend (struct pci_dev *pdev,pm_message_t state) +bnx2_suspend (struct device *device) { +struct pci_dev *pdev =to_pci_dev (device);struct net_device *dev =pci_get_drvdata (pdev);struct bnx2 *bp =netdev_priv (dev); -/* PCI register 4 needs to be saved whether netif_running() or not. -* MSI address and data need to be saved if using MSI and -* netif_running(). -*/ -pci_save_state (pdev); -if (!netif_running (dev)) -return 0 ; - -cancel_work_sync (&bp->reset_task); -bnx2_netif_stop (bp, true); -netif_device_detach (dev); -del_timer_sync (&bp->timer); -bnx2_shutdown_chip (bp); -bnx2_free_skbs (bp); -bnx2_set_power_state (bp,pci_choose_state (pdev, state)); +if (netif_running (dev)) { +cancel_work_sync (&bp->reset_task); +bnx2_netif_stop (bp, true); +netif_device_detach (dev); +del_timer_sync (&bp->timer); +bnx2_shutdown_chip (bp); +__bnx2_free_irq (bp); +bnx2_free_skbs (bp); + } +bnx2_setup_wol (bp);return 0 ; }static int -bnx2_resume (struct pci_dev *pdev) +bnx2_resume (struct device *device) { +struct pci_dev *pdev =to_pci_dev (device);struct net_device *dev =pci_get_drvdata (pdev);struct bnx2 *bp =netdev_priv (dev); -pci_restore_state (pdev);if (!netif_running (dev))return 0 ;bnx2_set_power_state (bp,PCI_D0 );netif_device_attach (dev); +bnx2_request_irq (bp);bnx2_init_nic (bp,1 );bnx2_netif_start (bp, true);return 0 ; } +#ifdef CONFIG_PM_SLEEP +static SIMPLE_DEV_PM_OPS(bnx2_pm_ops, bnx2_suspend, bnx2_resume); +#define BNX2_PM_OPS (&bnx2_pm_ops) + +#else + +#define BNX2_PM_OPS NULL + +#endif /* CONFIG_PM_SLEEP */ /** * bnx2_io_error_detected - called when PCI error is detected * @pdev: Pointer to PCI device
@@ -8757,8 +8763,7 @@ static struct pci_driver bnx2_pci_driver = { .id_table = bnx2_pci_tbl, .probe = bnx2_init_one, .remove = bnx2_remove_one, - .suspend = bnx2_suspend, - .resume = bnx2_resume, + .driver.pm = BNX2_PM_OPS, .err_handler = &bnx2_err_handler, };
Signature · 1 line
1.7.1
PATCH 5/6 bnx2: Add pci shutdown handler.
WoL and power state changes will now be done in the shutdown handler. open/close/ethtool will no longer change the power state. NVRAM operations can now be permitted whether the device is up or down.
--- drivers/net/ethernet/broadcom/bnx2.c | 47 ++++++++++++++++++---------------- 1 files changed, 25 insertions(+), 22 deletions(-)
drivers/net/ethernet/broadcom/bnx2.c +25 -22
@@ -6302,7 +6302,6 @@ bnx2_open(struct net_device *dev)netif_carrier_off (dev); -bnx2_set_power_state (bp,PCI_D0 );bnx2_disable_int (bp); rc =bnx2_setup_int_mode (bp, disable_msi);
@@ -6709,7 +6708,6 @@ bnx2_close(struct net_device *dev)bnx2_del_napi (bp); bp->link_up =0 ;netif_carrier_off (bp->dev); -bnx2_set_power_state (bp, PCI_D3hot);return 0 ; }
@@ -7144,9 +7142,6 @@ bnx2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,struct bnx2 *bp =netdev_priv (dev);int rc; -if (!netif_running (dev)) -return -EAGAIN ; -/* parameters already validated in ethtool_get_eeprom */ rc =bnx2_nvram_read (bp, eeprom->offset, eebuf, eeprom->len);
@@ -7161,9 +7156,6 @@ bnx2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,struct bnx2 *bp =netdev_priv (dev);int rc; -if (!netif_running (dev)) -return -EAGAIN ; -/* parameters already validated in ethtool_set_eeprom */ rc =bnx2_nvram_write (bp, eeprom->offset, eebuf, eeprom->len);
@@ -7523,8 +7515,6 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf) {struct bnx2 *bp =netdev_priv (dev); -bnx2_set_power_state (bp,PCI_D0 ); -memset (buf,0 ,sizeof (u64) *BNX2_NUM_TESTS );if (etest->flags Ð_TEST_FL_OFFLINE ) {int i;
@@ -7573,8 +7563,6 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf) etest->flags |=ETH_TEST_FL_FAILED ; } -if (!netif_running (bp->dev)) -bnx2_set_power_state (bp, PCI_D3hot); } static void
@@ -7646,8 +7634,6 @@ bnx2_set_phys_id(struct net_device *dev, enum ethtool_phys_id_state state)switch (state) {case ETHTOOL_ID_ACTIVE : -bnx2_set_power_state (bp,PCI_D0 ); - bp->leds_save =BNX2_RD (bp,BNX2_MISC_CFG );BNX2_WR (bp,BNX2_MISC_CFG ,BNX2_MISC_CFG_LEDMODE_MAC );return 1 ;/* cycle on/off once per second */
@@ -7668,9 +7654,6 @@ bnx2_set_phys_id(struct net_device *dev, enum ethtool_phys_id_state state)case ETHTOOL_ID_INACTIVE :BNX2_WR (bp,BNX2_EMAC_LED ,0 );BNX2_WR (bp,BNX2_MISC_CFG , bp->leds_save); - -if (!netif_running (dev)) -bnx2_set_power_state (bp, PCI_D3hot);break ; }
@@ -8118,8 +8101,6 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) goto err_out_release; } -bnx2_set_power_state (bp,PCI_D0 ); -/* Configure byte swap and enable write to the reg_window registers. * Rely on CPU to do target byte swapping on big endian systems * The chip's target access swapping will not swap all accesses
@@ -8705,10 +8686,9 @@ static pci_ers_result_t bnx2_io_slot_reset(struct pci_dev *pdev)pci_restore_state (pdev);pci_save_state (pdev); -if (netif_running (dev)) { -bnx2_set_power_state (bp,PCI_D0 ); +if (netif_running (dev)) err =bnx2_init_nic (bp,1 ); - } +if (!err) result =PCI_ERS_RESULT_RECOVERED ; }
@@ -8752,6 +8732,28 @@ static void bnx2_io_resume(struct pci_dev *pdev)rtnl_unlock (); } +static void bnx2_shutdown (struct pci_dev *pdev) +{ +struct net_device *dev =pci_get_drvdata (pdev); +struct bnx2 *bp; + +if (!dev) +return ; + + bp =netdev_priv (dev); +if (!bp) +return ; + +rtnl_lock (); +if (netif_running (dev)) +dev_close (bp->dev); + +if (system_state ==SYSTEM_POWER_OFF ) +bnx2_set_power_state (bp, PCI_D3hot); + +rtnl_unlock (); +} +static const struct pci_error_handlers bnx2_err_handler = { .error_detected = bnx2_io_error_detected, .slot_reset = bnx2_io_slot_reset,
@@ -8765,6 +8767,7 @@ static struct pci_driver bnx2_pci_driver = { .remove = bnx2_remove_one, .driver.pm = BNX2_PM_OPS, .err_handler = &bnx2_err_handler, + .shutdown = bnx2_shutdown, };module_pci_driver (bnx2_pci_driver);
Signature · 1 line
1.7.1
PATCH 6/6 bnx2: Update version to 2.2.4
and update copyright year.
--- drivers/net/ethernet/broadcom/bnx2.c | 6 +++--- drivers/net/ethernet/broadcom/bnx2.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-)
drivers/net/ethernet/broadcom/bnx2.c +3 -3
@@ -1,6 +1,6 @@/* bnx2.c: Broadcom NX2 network driver. * -* Copyright (c) 2004-2011 Broadcom Corporation +* Copyright (c) 2004-2013 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by
@@ -58,8 +58,8 @@#include "bnx2_fw.h" #define DRV_MODULE_NAME "bnx2" -#define DRV_MODULE_VERSION "2.2.3" -#define DRV_MODULE_RELDATE "June 27, 2012" +#define DRV_MODULE_VERSION "2.2.4" +#define DRV_MODULE_RELDATE "Aug 05, 2013"#define FW_MIPS_FILE_06 "bnx2/bnx2-mips-06-6.2.3.fw"#define FW_RV2P_FILE_06 "bnx2/bnx2-rv2p-06-6.0.15.fw"#define FW_MIPS_FILE_09 "bnx2/bnx2-mips-09-6.2.1b.fw"
drivers/net/ethernet/broadcom/bnx2.h +1 -1
@@ -1,6 +1,6 @@/* bnx2.h: Broadcom NX2 network driver. * -* Copyright (c) 2004-2011 Broadcom Corporation +* Copyright (c) 2004-2013 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by
Signature · 1 line
1.7.1
David Miller
maintainerFrom: "Michael Chan" <[email protected]>
Date: Tue, 6 Aug 2013 15:50:06 -0700
Quoted 2 lines
First patch fixes EEH/AER error path. The rest of the patches modernize the driver to use latest APIs for WoL and power management.
All applied, thank you.