2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-05 11:54:01 +08:00

bnx2x: Change DCB context handling

After notification that DCBX configuration has ended arrived to the driver,
the driver configured the FW/HW in sleepless context.
As a result, it was possible to reach a race (mostly with CNIC registration)
in which the configuration will return a timeout, failing to set the DCBX
results correctly.

This patch moves the configuration following the DCBX end into the slowpath
RTNL task (i.e., sleepless context protected by the RTNL lock), allowing the
configuration to cope with such races.

Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com>
Signed-off-by: Yuval Mintz <yuvalmin@broadcom.com>
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>
This commit is contained in:
Dmitry Kravkov 2013-08-19 09:11:57 +03:00 committed by David S. Miller
parent 9156b30b33
commit 07b4eb3b53
4 changed files with 43 additions and 8 deletions

View File

@ -1333,6 +1333,8 @@ enum {
BNX2X_SP_RTNL_VFPF_CHANNEL_DOWN,
BNX2X_SP_RTNL_VFPF_STORM_RX_MODE,
BNX2X_SP_RTNL_HYPERVISOR_VLAN,
BNX2X_SP_RTNL_TX_STOP,
BNX2X_SP_RTNL_TX_RESUME,
};
struct bnx2x_prev_path_list {

View File

@ -30,10 +30,8 @@
#include "bnx2x_dcb.h"
/* forward declarations of dcbx related functions */
static int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp);
static void bnx2x_pfc_set_pfc(struct bnx2x *bp);
static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp);
static int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp);
static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
u32 *set_configuration_ets_pg,
u32 *pri_pg_tbl);
@ -425,30 +423,52 @@ static void bnx2x_pfc_set_pfc(struct bnx2x *bp)
bnx2x_pfc_clear(bp);
}
static int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp)
int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp)
{
struct bnx2x_func_state_params func_params = {NULL};
int rc;
func_params.f_obj = &bp->func_obj;
func_params.cmd = BNX2X_F_CMD_TX_STOP;
__set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
__set_bit(RAMROD_RETRY, &func_params.ramrod_flags);
DP(BNX2X_MSG_DCB, "STOP TRAFFIC\n");
return bnx2x_func_state_change(bp, &func_params);
rc = bnx2x_func_state_change(bp, &func_params);
if (rc) {
BNX2X_ERR("Unable to hold traffic for HW configuration\n");
bnx2x_panic();
}
return rc;
}
static int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp)
int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp)
{
struct bnx2x_func_state_params func_params = {NULL};
struct bnx2x_func_tx_start_params *tx_params =
&func_params.params.tx_start;
int rc;
func_params.f_obj = &bp->func_obj;
func_params.cmd = BNX2X_F_CMD_TX_START;
__set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
__set_bit(RAMROD_RETRY, &func_params.ramrod_flags);
bnx2x_dcbx_fw_struct(bp, tx_params);
DP(BNX2X_MSG_DCB, "START TRAFFIC\n");
return bnx2x_func_state_change(bp, &func_params);
rc = bnx2x_func_state_change(bp, &func_params);
if (rc) {
BNX2X_ERR("Unable to resume traffic after HW configuration\n");
bnx2x_panic();
}
return rc;
}
static void bnx2x_dcbx_2cos_limit_update_ets_config(struct bnx2x *bp)
@ -744,7 +764,9 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
if (IS_MF(bp))
bnx2x_link_sync_notify(bp);
bnx2x_dcbx_stop_hw_tx(bp);
set_bit(BNX2X_SP_RTNL_TX_STOP, &bp->sp_rtnl_state);
schedule_delayed_work(&bp->sp_rtnl_task, 0);
return;
}
@ -757,7 +779,9 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
/* ets may affect cmng configuration: reinit it in hw */
bnx2x_set_local_cmng(bp);
bnx2x_dcbx_resume_hw_tx(bp);
set_bit(BNX2X_SP_RTNL_TX_RESUME, &bp->sp_rtnl_state);
schedule_delayed_work(&bp->sp_rtnl_task, 0);
return;
case BNX2X_DCBX_STATE_TX_RELEASED:

View File

@ -199,4 +199,7 @@ extern const struct dcbnl_rtnl_ops bnx2x_dcbnl_ops;
int bnx2x_dcbnl_update_applist(struct bnx2x *bp, bool delall);
#endif /* BCM_DCBNL */
int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp);
int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp);
#endif /* BNX2X_DCB_H */

View File

@ -9655,6 +9655,12 @@ sp_rtnl_not_reset:
&bp->sp_rtnl_state))
bnx2x_pf_set_vfs_vlan(bp);
if (test_and_clear_bit(BNX2X_SP_RTNL_TX_STOP, &bp->sp_rtnl_state))
bnx2x_dcbx_stop_hw_tx(bp);
if (test_and_clear_bit(BNX2X_SP_RTNL_TX_RESUME, &bp->sp_rtnl_state))
bnx2x_dcbx_resume_hw_tx(bp);
/* work which needs rtnl lock not-taken (as it takes the lock itself and
* can be called from other contexts as well)
*/