aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAriel Elior <ariele@broadcom.com>2012-01-26 01:01:51 -0500
committerDavid S. Miller <davem@davemloft.net>2012-01-26 13:39:52 -0500
commit889b9af34f986138eebebfe781567cb950b3a22b (patch)
tree06c17cb0605aa0bdeacd4e3f3c70f264f725d9cd
parentf16da43b5df947cef427f19b8f5c4b2f5d566231 (diff)
bnx2x: Track active PFs with bitmap
The recovery register (to which a hardware lock has been added in previous patch) is used amongst other things to track the active PFs. The old implementation which used a per path counter is not viable in a virtualized environment where a pf may increment the counter and then have the kernel crash around it preventing the counter from ever reaching zero. In the new implementation the scenario described will result in the PF timing out against the mcp, which will clear the PF's bit in the bitmask allowing recovery process to proceed. Signed-off-by: Ariel Elior <ariele@broadcom.com> Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c8
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h4
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c56
3 files changed, 35 insertions, 33 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index b75c8eab095c..15db2d679a14 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -1767,6 +1767,9 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
1767 1767
1768 bnx2x_napi_enable(bp); 1768 bnx2x_napi_enable(bp);
1769 1769
1770 /* set pf load just before approaching the MCP */
1771 bnx2x_set_pf_load(bp);
1772
1770 /* Send LOAD_REQUEST command to MCP 1773 /* Send LOAD_REQUEST command to MCP
1771 * Returns the type of LOAD command: 1774 * Returns the type of LOAD command:
1772 * if it is the first port to be initialized 1775 * if it is the first port to be initialized
@@ -1972,7 +1975,6 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
1972 if (bp->state == BNX2X_STATE_OPEN) 1975 if (bp->state == BNX2X_STATE_OPEN)
1973 bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD); 1976 bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD);
1974#endif 1977#endif
1975 bnx2x_inc_load_cnt(bp);
1976 1978
1977 /* Wait for all pending SP commands to complete */ 1979 /* Wait for all pending SP commands to complete */
1978 if (!bnx2x_wait_sp_comp(bp, ~0x0UL)) { 1980 if (!bnx2x_wait_sp_comp(bp, ~0x0UL)) {
@@ -2012,6 +2014,8 @@ load_error2:
2012 bp->port.pmf = 0; 2014 bp->port.pmf = 0;
2013load_error1: 2015load_error1:
2014 bnx2x_napi_disable(bp); 2016 bnx2x_napi_disable(bp);
2017 /* clear pf_load status, as it was already set */
2018 bnx2x_clear_pf_load(bp);
2015load_error0: 2019load_error0:
2016 bnx2x_free_mem(bp); 2020 bnx2x_free_mem(bp);
2017 2021
@@ -2132,7 +2136,7 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
2132 /* The last driver must disable a "close the gate" if there is no 2136 /* The last driver must disable a "close the gate" if there is no
2133 * parity attention or "process kill" pending. 2137 * parity attention or "process kill" pending.
2134 */ 2138 */
2135 if (!bnx2x_dec_load_cnt(bp) && bnx2x_reset_is_done(bp, BP_PATH(bp))) 2139 if (!bnx2x_clear_pf_load(bp) && bnx2x_reset_is_done(bp, BP_PATH(bp)))
2136 bnx2x_disable_close_the_gate(bp); 2140 bnx2x_disable_close_the_gate(bp);
2137 2141
2138 return 0; 2142 return 0;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index bd990c2e5d1b..a6ef3ef85e51 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -379,8 +379,8 @@ void bnx2x_set_q_rx_mode(struct bnx2x *bp, u8 cl_id,
379 unsigned long ramrod_flags); 379 unsigned long ramrod_flags);
380 380
381/* Parity errors related */ 381/* Parity errors related */
382void bnx2x_inc_load_cnt(struct bnx2x *bp); 382void bnx2x_set_pf_load(struct bnx2x *bp);
383u32 bnx2x_dec_load_cnt(struct bnx2x *bp); 383bool bnx2x_clear_pf_load(struct bnx2x *bp);
384bool bnx2x_chk_parity_attn(struct bnx2x *bp, bool *global, bool print); 384bool bnx2x_chk_parity_attn(struct bnx2x *bp, bool *global, bool print);
385bool bnx2x_reset_is_done(struct bnx2x *bp, int engine); 385bool bnx2x_reset_is_done(struct bnx2x *bp, int engine);
386void bnx2x_set_reset_in_progress(struct bnx2x *bp); 386void bnx2x_set_reset_in_progress(struct bnx2x *bp);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 4824b0f8bd23..f7f167a0f85a 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -3812,11 +3812,11 @@ bool bnx2x_reset_is_done(struct bnx2x *bp, int engine)
3812} 3812}
3813 3813
3814/* 3814/*
3815 * Increment the load counter for the current engine. 3815 * set pf load for the current pf.
3816 * 3816 *
3817 * should be run under rtnl lock 3817 * should be run under rtnl lock
3818 */ 3818 */
3819void bnx2x_inc_load_cnt(struct bnx2x *bp) 3819void bnx2x_set_pf_load(struct bnx2x *bp)
3820{ 3820{
3821 u32 val1, val; 3821 u32 val1, val;
3822 u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK : 3822 u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
@@ -3832,8 +3832,8 @@ void bnx2x_inc_load_cnt(struct bnx2x *bp)
3832 /* get the current counter value */ 3832 /* get the current counter value */
3833 val1 = (val & mask) >> shift; 3833 val1 = (val & mask) >> shift;
3834 3834
3835 /* increment... */ 3835 /* set bit of that PF */
3836 val1++; 3836 val1 |= (1 << bp->pf_num);
3837 3837
3838 /* clear the old value */ 3838 /* clear the old value */
3839 val &= ~mask; 3839 val &= ~mask;
@@ -3846,15 +3846,15 @@ void bnx2x_inc_load_cnt(struct bnx2x *bp)
3846} 3846}
3847 3847
3848/** 3848/**
3849 * bnx2x_dec_load_cnt - decrement the load counter 3849 * bnx2x_clear_pf_load - clear pf load mark
3850 * 3850 *
3851 * @bp: driver handle 3851 * @bp: driver handle
3852 * 3852 *
3853 * Should be run under rtnl lock. 3853 * Should be run under rtnl lock.
3854 * Decrements the load counter for the current engine. Returns 3854 * Decrements the load counter for the current engine. Returns
3855 * the new counter value. 3855 * whether other functions are still loaded
3856 */ 3856 */
3857u32 bnx2x_dec_load_cnt(struct bnx2x *bp) 3857bool bnx2x_clear_pf_load(struct bnx2x *bp)
3858{ 3858{
3859 u32 val1, val; 3859 u32 val1, val;
3860 u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK : 3860 u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
@@ -3869,8 +3869,8 @@ u32 bnx2x_dec_load_cnt(struct bnx2x *bp)
3869 /* get the current counter value */ 3869 /* get the current counter value */
3870 val1 = (val & mask) >> shift; 3870 val1 = (val & mask) >> shift;
3871 3871
3872 /* decrement... */ 3872 /* clear bit of that PF */
3873 val1--; 3873 val1 &= ~(1 << bp->pf_num);
3874 3874
3875 /* clear the old value */ 3875 /* clear the old value */
3876 val &= ~mask; 3876 val &= ~mask;
@@ -3884,11 +3884,11 @@ u32 bnx2x_dec_load_cnt(struct bnx2x *bp)
3884} 3884}
3885 3885
3886/* 3886/*
3887 * Read the load counter for the current engine. 3887 * Read the load status for the current engine.
3888 * 3888 *
3889 * should be run under rtnl lock 3889 * should be run under rtnl lock
3890 */ 3890 */
3891static inline u32 bnx2x_get_load_cnt(struct bnx2x *bp, int engine) 3891static inline bool bnx2x_get_load_status(struct bnx2x *bp, int engine)
3892{ 3892{
3893 u32 mask = (engine ? BNX2X_PATH1_LOAD_CNT_MASK : 3893 u32 mask = (engine ? BNX2X_PATH1_LOAD_CNT_MASK :
3894 BNX2X_PATH0_LOAD_CNT_MASK); 3894 BNX2X_PATH0_LOAD_CNT_MASK);
@@ -3900,17 +3900,15 @@ static inline u32 bnx2x_get_load_cnt(struct bnx2x *bp, int engine)
3900 3900
3901 val = (val & mask) >> shift; 3901 val = (val & mask) >> shift;
3902 3902
3903 DP(NETIF_MSG_HW, "load_cnt for engine %d = %d\n", engine, val); 3903 DP(NETIF_MSG_HW, "load mask for engine %d = 0x%x\n", engine, val);
3904 3904
3905 return val; 3905 return val != 0;
3906} 3906}
3907 3907
3908/* 3908/*
3909 * Reset the load counter for the current engine. 3909 * Reset the load status for the current engine.
3910 *
3911 * should be run under rtnl lock
3912 */ 3910 */
3913static inline void bnx2x_clear_load_cnt(struct bnx2x *bp) 3911static inline void bnx2x_clear_load_status(struct bnx2x *bp)
3914{ 3912{
3915 u32 val; 3913 u32 val;
3916 u32 mask = (BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK : 3914 u32 mask = (BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
@@ -8582,10 +8580,10 @@ static void bnx2x_parity_recover(struct bnx2x *bp)
8582 DP(NETIF_MSG_HW, "State is BNX2X_RECOVERY_WAIT\n"); 8580 DP(NETIF_MSG_HW, "State is BNX2X_RECOVERY_WAIT\n");
8583 if (bp->is_leader) { 8581 if (bp->is_leader) {
8584 int other_engine = BP_PATH(bp) ? 0 : 1; 8582 int other_engine = BP_PATH(bp) ? 0 : 1;
8585 u32 other_load_counter = 8583 bool other_load_status =
8586 bnx2x_get_load_cnt(bp, other_engine); 8584 bnx2x_get_load_status(bp, other_engine);
8587 u32 load_counter = 8585 bool load_status =
8588 bnx2x_get_load_cnt(bp, BP_PATH(bp)); 8586 bnx2x_get_load_status(bp, BP_PATH(bp));
8589 global = bnx2x_reset_is_global(bp); 8587 global = bnx2x_reset_is_global(bp);
8590 8588
8591 /* 8589 /*
@@ -8596,8 +8594,8 @@ static void bnx2x_parity_recover(struct bnx2x *bp)
8596 * the the gates will remain closed for that 8594 * the the gates will remain closed for that
8597 * engine. 8595 * engine.
8598 */ 8596 */
8599 if (load_counter || 8597 if (load_status ||
8600 (global && other_load_counter)) { 8598 (global && other_load_status)) {
8601 /* Wait until all other functions get 8599 /* Wait until all other functions get
8602 * down. 8600 * down.
8603 */ 8601 */
@@ -10206,14 +10204,14 @@ static int bnx2x_open(struct net_device *dev)
10206 struct bnx2x *bp = netdev_priv(dev); 10204 struct bnx2x *bp = netdev_priv(dev);
10207 bool global = false; 10205 bool global = false;
10208 int other_engine = BP_PATH(bp) ? 0 : 1; 10206 int other_engine = BP_PATH(bp) ? 0 : 1;
10209 u32 other_load_counter, load_counter; 10207 bool other_load_status, load_status;
10210 10208
10211 netif_carrier_off(dev); 10209 netif_carrier_off(dev);
10212 10210
10213 bnx2x_set_power_state(bp, PCI_D0); 10211 bnx2x_set_power_state(bp, PCI_D0);
10214 10212
10215 other_load_counter = bnx2x_get_load_cnt(bp, other_engine); 10213 other_load_status = bnx2x_get_load_status(bp, other_engine);
10216 load_counter = bnx2x_get_load_cnt(bp, BP_PATH(bp)); 10214 load_status = bnx2x_get_load_status(bp, BP_PATH(bp));
10217 10215
10218 /* 10216 /*
10219 * If parity had happen during the unload, then attentions 10217 * If parity had happen during the unload, then attentions
@@ -10239,8 +10237,8 @@ static int bnx2x_open(struct net_device *dev)
10239 * global blocks only the first in the chip should try 10237 * global blocks only the first in the chip should try
10240 * to recover. 10238 * to recover.
10241 */ 10239 */
10242 if ((!load_counter && 10240 if ((!load_status &&
10243 (!global || !other_load_counter)) && 10241 (!global || !other_load_status)) &&
10244 bnx2x_trylock_leader_lock(bp) && 10242 bnx2x_trylock_leader_lock(bp) &&
10245 !bnx2x_leader_reset(bp)) { 10243 !bnx2x_leader_reset(bp)) {
10246 netdev_info(bp->dev, "Recovered in open\n"); 10244 netdev_info(bp->dev, "Recovered in open\n");
@@ -10680,7 +10678,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
10680 REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1); 10678 REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1);
10681 10679
10682 /* Reset the load counter */ 10680 /* Reset the load counter */
10683 bnx2x_clear_load_cnt(bp); 10681 bnx2x_clear_load_status(bp);
10684 10682
10685 dev->watchdog_timeo = TX_TIMEOUT; 10683 dev->watchdog_timeo = TX_TIMEOUT;
10686 10684