Commit 6debea87 authored by Dmitry Kravkov's avatar Dmitry Kravkov Committed by David S. Miller

bnx2x: DCB rework

create DCB related states in function state-machine
allow handling of DCB errors from FW
allow disablement of DCB in FW, when peer disappears or error
clean up unused functions/variables as pointed by
David Binderman <dcb314@hotmail.com>
Reported-by: default avatarDavid Binderman <dcb314@hotmail.com>
Signed-off-by: default avatarDmitry Kravkov <dmitry@broadcom.com>
Signed-off-by: default avatarEilon Greenstein <eilong@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f13ac41f
...@@ -966,6 +966,8 @@ struct bnx2x_slowpath { ...@@ -966,6 +966,8 @@ struct bnx2x_slowpath {
union { union {
struct function_start_data func_start; struct function_start_data func_start;
/* pfc configuration for DCBX ramrod */
struct flow_control_configuration pfc_config;
} func_rdata; } func_rdata;
/* used by dmae command executer */ /* used by dmae command executer */
...@@ -980,8 +982,6 @@ struct bnx2x_slowpath { ...@@ -980,8 +982,6 @@ struct bnx2x_slowpath {
u32 wb_comp; u32 wb_comp;
u32 wb_data[4]; u32 wb_data[4];
/* pfc configuration for DCBX ramrod */
struct flow_control_configuration pfc_config;
}; };
#define bnx2x_sp(bp, var) (&bp->slowpath->var) #define bnx2x_sp(bp, var) (&bp->slowpath->var)
...@@ -1417,9 +1417,6 @@ struct bnx2x { ...@@ -1417,9 +1417,6 @@ struct bnx2x {
char fw_ver[32]; char fw_ver[32];
const struct firmware *firmware; const struct firmware *firmware;
/* LLDP params */
struct bnx2x_config_lldp_params lldp_config_params;
/* DCB support on/off */ /* DCB support on/off */
u16 dcb_state; u16 dcb_state;
#define BNX2X_DCB_STATE_OFF 0 #define BNX2X_DCB_STATE_OFF 0
......
...@@ -29,10 +29,10 @@ ...@@ -29,10 +29,10 @@
#endif #endif
/* forward declarations of dcbx related functions */ /* forward declarations of dcbx related functions */
static void bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp); static int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp);
static void bnx2x_pfc_set_pfc(struct bnx2x *bp); static void bnx2x_pfc_set_pfc(struct bnx2x *bp);
static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp); static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp);
static void bnx2x_dcbx_resume_hw_tx(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, static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
u32 *set_configuration_ets_pg, u32 *set_configuration_ets_pg,
u32 *pri_pg_tbl); u32 *pri_pg_tbl);
...@@ -47,8 +47,25 @@ static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp, ...@@ -47,8 +47,25 @@ static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp,
struct cos_help_data *cos_data, struct cos_help_data *cos_data,
u32 *pg_pri_orginal_spread, u32 *pg_pri_orginal_spread,
struct dcbx_ets_feature *ets); struct dcbx_ets_feature *ets);
static void bnx2x_dcbx_fw_struct(struct bnx2x *bp); static void bnx2x_dcbx_fw_struct(struct bnx2x *bp,
struct bnx2x_func_tx_start_params*);
/* helpers: read/write len bytes from addr into buff by REG_RD/REG_WR */
static void bnx2x_read_data(struct bnx2x *bp, u32 *buff,
u32 addr, u32 len)
{
int i;
for (i = 0; i < len; i += 4, buff++)
*buff = REG_RD(bp, addr + i);
}
static void bnx2x_write_data(struct bnx2x *bp, u32 *buff,
u32 addr, u32 len)
{
int i;
for (i = 0; i < len; i += 4, buff++)
REG_WR(bp, addr + i, *buff);
}
static void bnx2x_pfc_set(struct bnx2x *bp) static void bnx2x_pfc_set(struct bnx2x *bp)
{ {
...@@ -205,7 +222,11 @@ static void bnx2x_dcbx_get_ap_feature(struct bnx2x *bp, ...@@ -205,7 +222,11 @@ static void bnx2x_dcbx_get_ap_feature(struct bnx2x *bp,
if (GET_FLAGS(error, DCBX_LOCAL_APP_ERROR)) if (GET_FLAGS(error, DCBX_LOCAL_APP_ERROR))
DP(NETIF_MSG_LINK, "DCBX_LOCAL_APP_ERROR\n"); DP(NETIF_MSG_LINK, "DCBX_LOCAL_APP_ERROR\n");
if (app->enabled && !GET_FLAGS(error, DCBX_LOCAL_APP_ERROR)) { if (GET_FLAGS(error, DCBX_LOCAL_APP_MISMATCH))
DP(NETIF_MSG_LINK, "DCBX_LOCAL_APP_MISMATCH\n");
if (app->enabled &&
!GET_FLAGS(error, DCBX_LOCAL_APP_ERROR | DCBX_LOCAL_APP_MISMATCH)) {
bp->dcbx_port_params.app.enabled = true; bp->dcbx_port_params.app.enabled = true;
...@@ -300,7 +321,7 @@ static void bnx2x_dcbx_get_pfc_feature(struct bnx2x *bp, ...@@ -300,7 +321,7 @@ static void bnx2x_dcbx_get_pfc_feature(struct bnx2x *bp,
DP(NETIF_MSG_LINK, "DCBX_LOCAL_PFC_ERROR\n"); DP(NETIF_MSG_LINK, "DCBX_LOCAL_PFC_ERROR\n");
if (bp->dcbx_port_params.app.enabled && if (bp->dcbx_port_params.app.enabled &&
!GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR) && !GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR | DCBX_LOCAL_PFC_MISMATCH) &&
pfc->enabled) { pfc->enabled) {
bp->dcbx_port_params.pfc.enabled = true; bp->dcbx_port_params.pfc.enabled = true;
bp->dcbx_port_params.pfc.priority_non_pauseable_mask = bp->dcbx_port_params.pfc.priority_non_pauseable_mask =
...@@ -329,8 +350,8 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp, ...@@ -329,8 +350,8 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp,
u32 offset, u32 offset,
int read_mib_type) int read_mib_type)
{ {
int max_try_read = 0, i; int max_try_read = 0;
u32 *buff, mib_size, prefix_seq_num, suffix_seq_num; u32 mib_size, prefix_seq_num, suffix_seq_num;
struct lldp_remote_mib *remote_mib ; struct lldp_remote_mib *remote_mib ;
struct lldp_local_mib *local_mib; struct lldp_local_mib *local_mib;
...@@ -349,9 +370,7 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp, ...@@ -349,9 +370,7 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp,
offset += BP_PORT(bp) * mib_size; offset += BP_PORT(bp) * mib_size;
do { do {
buff = base_mib_addr; bnx2x_read_data(bp, base_mib_addr, offset, mib_size);
for (i = 0; i < mib_size; i += 4, buff++)
*buff = REG_RD(bp, offset + i);
max_try_read++; max_try_read++;
...@@ -382,12 +401,8 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp, ...@@ -382,12 +401,8 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp,
static void bnx2x_pfc_set_pfc(struct bnx2x *bp) static void bnx2x_pfc_set_pfc(struct bnx2x *bp)
{ {
if (BP_PORT(bp)) { if (bp->dcbx_port_params.pfc.enabled &&
BNX2X_ERR("4 port mode is not supported"); !(bp->dcbx_error & DCBX_REMOTE_MIB_ERROR))
return;
}
if (bp->dcbx_port_params.pfc.enabled)
/* /*
* 1. Fills up common PFC structures if required * 1. Fills up common PFC structures if required
* 2. Configure NIG, MAC and BRB via the elink * 2. Configure NIG, MAC and BRB via the elink
...@@ -397,25 +412,30 @@ static void bnx2x_pfc_set_pfc(struct bnx2x *bp) ...@@ -397,25 +412,30 @@ static void bnx2x_pfc_set_pfc(struct bnx2x *bp)
bnx2x_pfc_clear(bp); bnx2x_pfc_clear(bp);
} }
static void bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp) static int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp)
{ {
DP(NETIF_MSG_LINK, "sending STOP TRAFFIC\n"); struct bnx2x_func_state_params func_params = {0};
bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STOP_TRAFFIC,
0 /* connectionless */, func_params.f_obj = &bp->func_obj;
0 /* dataHi is zero */, func_params.cmd = BNX2X_F_CMD_TX_STOP;
0 /* dataLo is zero */,
NONE_CONNECTION_TYPE); DP(NETIF_MSG_LINK, "STOP TRAFFIC\n");
return bnx2x_func_state_change(bp, &func_params);
} }
static void bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp) static int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp)
{ {
bnx2x_dcbx_fw_struct(bp); struct bnx2x_func_state_params func_params = {0};
DP(NETIF_MSG_LINK, "sending START TRAFFIC\n"); struct bnx2x_func_tx_start_params *tx_params =
bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_START_TRAFFIC, &func_params.params.tx_start;
0, /* connectionless */
U64_HI(bnx2x_sp_mapping(bp, pfc_config)), func_params.f_obj = &bp->func_obj;
U64_LO(bnx2x_sp_mapping(bp, pfc_config)), func_params.cmd = BNX2X_F_CMD_TX_START;
NONE_CONNECTION_TYPE);
bnx2x_dcbx_fw_struct(bp, tx_params);
DP(NETIF_MSG_LINK, "START TRAFFIC\n");
return bnx2x_func_state_change(bp, &func_params);
} }
static void bnx2x_dcbx_2cos_limit_update_ets_config(struct bnx2x *bp) static void bnx2x_dcbx_2cos_limit_update_ets_config(struct bnx2x *bp)
...@@ -522,7 +542,8 @@ static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp) ...@@ -522,7 +542,8 @@ static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp)
{ {
bnx2x_ets_disabled(&bp->link_params, &bp->link_vars); bnx2x_ets_disabled(&bp->link_params, &bp->link_vars);
if (!bp->dcbx_port_params.ets.enabled) if (!bp->dcbx_port_params.ets.enabled ||
(bp->dcbx_error & DCBX_REMOTE_MIB_ERROR))
return; return;
if (CHIP_IS_E3B0(bp)) if (CHIP_IS_E3B0(bp))
...@@ -739,61 +760,14 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state) ...@@ -739,61 +760,14 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
} }
} }
#define LLDP_STATS_OFFSET(bp) (BP_PORT(bp)*\
sizeof(struct lldp_dcbx_stat))
/* calculate struct offset in array according to chip information */
#define LLDP_PARAMS_OFFSET(bp) (BP_PORT(bp)*sizeof(struct lldp_params))
#define LLDP_ADMIN_MIB_OFFSET(bp) (PORT_MAX*sizeof(struct lldp_params) + \ #define LLDP_ADMIN_MIB_OFFSET(bp) (PORT_MAX*sizeof(struct lldp_params) + \
BP_PORT(bp)*sizeof(struct lldp_admin_mib)) BP_PORT(bp)*sizeof(struct lldp_admin_mib))
static void bnx2x_dcbx_lldp_updated_params(struct bnx2x *bp,
u32 dcbx_lldp_params_offset)
{
struct lldp_params lldp_params = {0};
u32 i = 0, *buff = NULL;
u32 offset = dcbx_lldp_params_offset + LLDP_PARAMS_OFFSET(bp);
DP(NETIF_MSG_LINK, "lldp_offset 0x%x\n", offset);
if ((bp->lldp_config_params.overwrite_settings ==
BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE)) {
/* Read the data first */
buff = (u32 *)&lldp_params;
for (i = 0; i < sizeof(struct lldp_params); i += 4, buff++)
*buff = REG_RD(bp, (offset + i));
lldp_params.msg_tx_hold =
(u8)bp->lldp_config_params.msg_tx_hold;
lldp_params.msg_fast_tx_interval =
(u8)bp->lldp_config_params.msg_fast_tx;
lldp_params.tx_crd_max =
(u8)bp->lldp_config_params.tx_credit_max;
lldp_params.msg_tx_interval =
(u8)bp->lldp_config_params.msg_tx_interval;
lldp_params.tx_fast =
(u8)bp->lldp_config_params.tx_fast;
/* Write the data.*/
buff = (u32 *)&lldp_params;
for (i = 0; i < sizeof(struct lldp_params); i += 4, buff++)
REG_WR(bp, (offset + i) , *buff);
} else if (BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE ==
bp->lldp_config_params.overwrite_settings)
bp->lldp_config_params.overwrite_settings =
BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID;
}
static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp, static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp,
u32 dcbx_lldp_params_offset) u32 dcbx_lldp_params_offset)
{ {
struct lldp_admin_mib admin_mib; struct lldp_admin_mib admin_mib;
u32 i, other_traf_type = PREDEFINED_APP_IDX_MAX, traf_type = 0; u32 i, other_traf_type = PREDEFINED_APP_IDX_MAX, traf_type = 0;
u32 *buff;
u32 offset = dcbx_lldp_params_offset + LLDP_ADMIN_MIB_OFFSET(bp); u32 offset = dcbx_lldp_params_offset + LLDP_ADMIN_MIB_OFFSET(bp);
/*shortcuts*/ /*shortcuts*/
...@@ -801,18 +775,18 @@ static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp, ...@@ -801,18 +775,18 @@ static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp,
struct bnx2x_config_dcbx_params *dp = &bp->dcbx_config_params; struct bnx2x_config_dcbx_params *dp = &bp->dcbx_config_params;
memset(&admin_mib, 0, sizeof(struct lldp_admin_mib)); memset(&admin_mib, 0, sizeof(struct lldp_admin_mib));
buff = (u32 *)&admin_mib;
/* Read the data first */ /* Read the data first */
for (i = 0; i < sizeof(struct lldp_admin_mib); i += 4, buff++) bnx2x_read_data(bp, (u32 *)&admin_mib, offset,
*buff = REG_RD(bp, (offset + i)); sizeof(struct lldp_admin_mib));
if (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_ON) if (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_ON)
SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED); SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED);
else else
RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED); RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED);
if ((BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE == if (dp->overwrite_settings == BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE) {
dp->overwrite_settings)) {
RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_CEE_VERSION_MASK); RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_CEE_VERSION_MASK);
admin_mib.ver_cfg_flags |= admin_mib.ver_cfg_flags |=
(dp->admin_dcbx_version << DCBX_CEE_VERSION_SHIFT) & (dp->admin_dcbx_version << DCBX_CEE_VERSION_SHIFT) &
...@@ -908,19 +882,17 @@ static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp, ...@@ -908,19 +882,17 @@ static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp,
af->app.default_pri = (u8)dp->admin_default_priority; af->app.default_pri = (u8)dp->admin_default_priority;
} else if (BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE == }
dp->overwrite_settings)
dp->overwrite_settings = BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID;
/* Write the data. */ /* Write the data. */
buff = (u32 *)&admin_mib; bnx2x_write_data(bp, (u32 *)&admin_mib, offset,
for (i = 0; i < sizeof(struct lldp_admin_mib); i += 4, buff++) sizeof(struct lldp_admin_mib));
REG_WR(bp, (offset + i), *buff);
} }
void bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled) void bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled)
{ {
if (!CHIP_IS_E1x(bp) && !CHIP_MODE_IS_4_PORT(bp)) { if (!CHIP_IS_E1x(bp)) {
bp->dcb_state = dcb_on; bp->dcb_state = dcb_on;
bp->dcbx_enabled = dcbx_enabled; bp->dcbx_enabled = dcbx_enabled;
} else { } else {
...@@ -1029,9 +1001,6 @@ void bnx2x_dcbx_init(struct bnx2x *bp) ...@@ -1029,9 +1001,6 @@ void bnx2x_dcbx_init(struct bnx2x *bp)
bnx2x_update_drv_flags(bp, DRV_FLAGS_DCB_CONFIGURED, 0); bnx2x_update_drv_flags(bp, DRV_FLAGS_DCB_CONFIGURED, 0);
if (SHMEM_LLDP_DCBX_PARAMS_NONE != dcbx_lldp_params_offset) { if (SHMEM_LLDP_DCBX_PARAMS_NONE != dcbx_lldp_params_offset) {
bnx2x_dcbx_lldp_updated_params(bp,
dcbx_lldp_params_offset);
bnx2x_dcbx_admin_mib_updated_params(bp, bnx2x_dcbx_admin_mib_updated_params(bp,
dcbx_lldp_params_offset); dcbx_lldp_params_offset);
...@@ -1043,7 +1012,7 @@ void bnx2x_dcbx_init(struct bnx2x *bp) ...@@ -1043,7 +1012,7 @@ void bnx2x_dcbx_init(struct bnx2x *bp)
} }
static void static void
bnx2x_dcbx_print_cos_params(struct bnx2x *bp, bnx2x_dcbx_print_cos_params(struct bnx2x *bp,
struct flow_control_configuration *pfc_fw_cfg) struct bnx2x_func_tx_start_params *pfc_fw_cfg)
{ {
u8 pri = 0; u8 pri = 0;
u8 cos = 0; u8 cos = 0;
...@@ -1821,17 +1790,19 @@ static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp, ...@@ -1821,17 +1790,19 @@ static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
} }
} }
static void bnx2x_dcbx_fw_struct(struct bnx2x *bp) static void bnx2x_dcbx_fw_struct(struct bnx2x *bp,
struct bnx2x_func_tx_start_params *pfc_fw_cfg)
{ {
struct flow_control_configuration *pfc_fw_cfg = NULL;
u16 pri_bit = 0; u16 pri_bit = 0;
u8 cos = 0, pri = 0; u8 cos = 0, pri = 0;
struct priority_cos *tt2cos; struct priority_cos *tt2cos;
u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority; u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
pfc_fw_cfg = (struct flow_control_configuration *) memset(pfc_fw_cfg, 0, sizeof(*pfc_fw_cfg));
bnx2x_sp(bp, pfc_config);
memset(pfc_fw_cfg, 0, sizeof(struct flow_control_configuration)); /* to disable DCB - the structure must be zeroed */
if (bp->dcbx_error & DCBX_REMOTE_MIB_ERROR)
return;
/*shortcut*/ /*shortcut*/
tt2cos = pfc_fw_cfg->traffic_type_to_priority_cos; tt2cos = pfc_fw_cfg->traffic_type_to_priority_cos;
......
...@@ -1834,6 +1834,7 @@ struct lldp_local_mib { ...@@ -1834,6 +1834,7 @@ struct lldp_local_mib {
#define DCBX_LOCAL_APP_ERROR 0x00000004 #define DCBX_LOCAL_APP_ERROR 0x00000004
#define DCBX_LOCAL_PFC_MISMATCH 0x00000010 #define DCBX_LOCAL_PFC_MISMATCH 0x00000010
#define DCBX_LOCAL_APP_MISMATCH 0x00000020 #define DCBX_LOCAL_APP_MISMATCH 0x00000020
#define DCBX_REMOTE_MIB_ERROR 0x00000040
struct dcbx_features features; struct dcbx_features features;
u32 suffix_seq_num; u32 suffix_seq_num;
}; };
......
...@@ -4403,11 +4403,17 @@ static void bnx2x_eq_int(struct bnx2x *bp) ...@@ -4403,11 +4403,17 @@ static void bnx2x_eq_int(struct bnx2x *bp)
case EVENT_RING_OPCODE_STOP_TRAFFIC: case EVENT_RING_OPCODE_STOP_TRAFFIC:
DP(NETIF_MSG_IFUP, "got STOP TRAFFIC\n"); DP(NETIF_MSG_IFUP, "got STOP TRAFFIC\n");
if (f_obj->complete_cmd(bp, f_obj,
BNX2X_F_CMD_TX_STOP))
break;
bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_PAUSED); bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_PAUSED);
goto next_spqe; goto next_spqe;
case EVENT_RING_OPCODE_START_TRAFFIC: case EVENT_RING_OPCODE_START_TRAFFIC:
DP(NETIF_MSG_IFUP, "got START TRAFFIC\n"); DP(NETIF_MSG_IFUP, "got START TRAFFIC\n");
if (f_obj->complete_cmd(bp, f_obj,
BNX2X_F_CMD_TX_START))
break;
bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_RELEASED); bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_RELEASED);
goto next_spqe; goto next_spqe;
case EVENT_RING_OPCODE_FUNCTION_START: case EVENT_RING_OPCODE_FUNCTION_START:
...@@ -7536,6 +7542,71 @@ void bnx2x_send_unload_done(struct bnx2x *bp) ...@@ -7536,6 +7542,71 @@ void bnx2x_send_unload_done(struct bnx2x *bp)
bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0); bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
} }
static inline int bnx2x_func_wait_started(struct bnx2x *bp)
{
int tout = 50;
int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
if (!bp->port.pmf)
return 0;
/*
* (assumption: No Attention from MCP at this stage)
* PMF probably in the middle of TXdisable/enable transaction
* 1. Sync IRS for default SB
* 2. Sync SP queue - this guarantes us that attention handling started
* 3. Wait, that TXdisable/enable transaction completes
*
* 1+2 guranty that if DCBx attention was scheduled it already changed
* pending bit of transaction from STARTED-->TX_STOPPED, if we alredy
* received complettion for the transaction the state is TX_STOPPED.
* State will return to STARTED after completion of TX_STOPPED-->STARTED
* transaction.
*/
/* make sure default SB ISR is done */
if (msix)
synchronize_irq(bp->msix_table[0].vector);
else
synchronize_irq(bp->pdev->irq);
flush_workqueue(bnx2x_wq);
while (bnx2x_func_get_state(bp, &bp->func_obj) !=
BNX2X_F_STATE_STARTED && tout--)
msleep(20);
if (bnx2x_func_get_state(bp, &bp->func_obj) !=
BNX2X_F_STATE_STARTED) {
#ifdef BNX2X_STOP_ON_ERROR
return -EBUSY;
#else
/*
* Failed to complete the transaction in a "good way"
* Force both transactions with CLR bit
*/
struct bnx2x_func_state_params func_params = {0};
DP(BNX2X_MSG_SP, "Hmmm... unexpected function state! "
"Forcing STARTED-->TX_ST0PPED-->STARTED\n");
func_params.f_obj = &bp->func_obj;
__set_bit(RAMROD_DRV_CLR_ONLY,
&func_params.ramrod_flags);
/* STARTED-->TX_ST0PPED */
func_params.cmd = BNX2X_F_CMD_TX_STOP;
bnx2x_func_state_change(bp, &func_params);
/* TX_ST0PPED-->STARTED */
func_params.cmd = BNX2X_F_CMD_TX_START;
return bnx2x_func_state_change(bp, &func_params);
#endif
}
return 0;
}
void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode) void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
{ {
int port = BP_PORT(bp); int port = BP_PORT(bp);
...@@ -7595,6 +7666,26 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode) ...@@ -7595,6 +7666,26 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
netif_addr_unlock_bh(bp->dev); netif_addr_unlock_bh(bp->dev);
/*
* Send the UNLOAD_REQUEST to the MCP. This will return if
* this function should perform FUNC, PORT or COMMON HW
* reset.
*/
reset_code = bnx2x_send_unload_req(bp, unload_mode);
/*
* (assumption: No Attention from MCP at this stage)
* PMF probably in the middle of TXdisable/enable transaction
*/
rc = bnx2x_func_wait_started(bp);
if (rc) {
BNX2X_ERR("bnx2x_func_wait_started failed\n");
#ifdef BNX2X_STOP_ON_ERROR
return;
#endif
}
/* Close multi and leading connections /* Close multi and leading connections
* Completions for ramrods are collected in a synchronous way * Completions for ramrods are collected in a synchronous way
*/ */
...@@ -7622,13 +7713,6 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode) ...@@ -7622,13 +7713,6 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
#endif #endif
} }
/*
* Send the UNLOAD_REQUEST to the MCP. This will return if
* this function should perform FUNC, PORT or COMMON HW
* reset.
*/
reset_code = bnx2x_send_unload_req(bp, unload_mode);
/* Disable HW interrupts, NAPI */ /* Disable HW interrupts, NAPI */
bnx2x_netif_stop(bp, 1); bnx2x_netif_stop(bp, 1);
......
...@@ -4874,6 +4874,22 @@ static int bnx2x_queue_chk_transition(struct bnx2x *bp, ...@@ -4874,6 +4874,22 @@ static int bnx2x_queue_chk_transition(struct bnx2x *bp,
&params->params.update; &params->params.update;
u8 next_tx_only = o->num_tx_only; u8 next_tx_only = o->num_tx_only;
/*
* Forget all pending for completion commands if a driver only state
* transition has been requested.
*/
if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
o->pending = 0;
o->next_state = BNX2X_Q_STATE_MAX;
}
/*
* Don't allow a next state transition if we are in the middle of
* the previous one.
*/
if (o->pending)
return -EBUSY;
switch (state) { switch (state) {
case BNX2X_Q_STATE_RESET: case BNX2X_Q_STATE_RESET:
if (cmd == BNX2X_Q_CMD_INIT) if (cmd == BNX2X_Q_CMD_INIT)
...@@ -5053,6 +5069,21 @@ void bnx2x_queue_set_cos_cid(struct bnx2x *bp, ...@@ -5053,6 +5069,21 @@ void bnx2x_queue_set_cos_cid(struct bnx2x *bp,
} }
/********************** Function state object *********************************/ /********************** Function state object *********************************/
enum bnx2x_func_state bnx2x_func_get_state(struct bnx2x *bp,
struct bnx2x_func_sp_obj *o)
{
/* in the middle of transaction - return INVALID state */
if (o->pending)
return BNX2X_F_STATE_MAX;
/*
* unsure the order of reading of o->pending and o->state
* o->pending should be read first
*/
rmb();
return o->state;
}
static int bnx2x_func_wait_comp(struct bnx2x *bp, static int bnx2x_func_wait_comp(struct bnx2x *bp,
struct bnx2x_func_sp_obj *o, struct bnx2x_func_sp_obj *o,
...@@ -5143,6 +5174,22 @@ static int bnx2x_func_chk_transition(struct bnx2x *bp, ...@@ -5143,6 +5174,22 @@ static int bnx2x_func_chk_transition(struct bnx2x *bp,
enum bnx2x_func_state state = o->state, next_state = BNX2X_F_STATE_MAX; enum bnx2x_func_state state = o->state, next_state = BNX2X_F_STATE_MAX;
enum bnx2x_func_cmd cmd = params->cmd; enum bnx2x_func_cmd cmd = params->cmd;
/*
* Forget all pending for completion commands if a driver only state
* transition has been requested.
*/
if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
o->pending = 0;
o->next_state = BNX2X_F_STATE_MAX;
}
/*
* Don't allow a next state transition if we are in the middle of
* the previous one.
*/
if (o->pending)
return -EBUSY;
switch (state) { switch (state) {
case BNX2X_F_STATE_RESET: case BNX2X_F_STATE_RESET:
if (cmd == BNX2X_F_CMD_HW_INIT) if (cmd == BNX2X_F_CMD_HW_INIT)
...@@ -5160,6 +5207,13 @@ static int bnx2x_func_chk_transition(struct bnx2x *bp, ...@@ -5160,6 +5207,13 @@ static int bnx2x_func_chk_transition(struct bnx2x *bp,
case BNX2X_F_STATE_STARTED: case BNX2X_F_STATE_STARTED:
if (cmd == BNX2X_F_CMD_STOP) if (cmd == BNX2X_F_CMD_STOP)
next_state = BNX2X_F_STATE_INITIALIZED; next_state = BNX2X_F_STATE_INITIALIZED;
else if (cmd == BNX2X_F_CMD_TX_STOP)
next_state = BNX2X_F_STATE_TX_STOPPED;
break;
case BNX2X_F_STATE_TX_STOPPED:
if (cmd == BNX2X_F_CMD_TX_START)
next_state = BNX2X_F_STATE_STARTED;
break; break;
default: default:
...@@ -5444,6 +5498,38 @@ static inline int bnx2x_func_send_stop(struct bnx2x *bp, ...@@ -5444,6 +5498,38 @@ static inline int bnx2x_func_send_stop(struct bnx2x *bp,
NONE_CONNECTION_TYPE); NONE_CONNECTION_TYPE);
} }
static inline int bnx2x_func_send_tx_stop(struct bnx2x *bp,
struct bnx2x_func_state_params *params)
{
return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STOP_TRAFFIC, 0, 0, 0,
NONE_CONNECTION_TYPE);
}
static inline int bnx2x_func_send_tx_start(struct bnx2x *bp,
struct bnx2x_func_state_params *params)
{
struct bnx2x_func_sp_obj *o = params->f_obj;
struct flow_control_configuration *rdata =
(struct flow_control_configuration *)o->rdata;
dma_addr_t data_mapping = o->rdata_mapping;
struct bnx2x_func_tx_start_params *tx_start_params =
&params->params.tx_start;
int i;
memset(rdata, 0, sizeof(*rdata));
rdata->dcb_enabled = tx_start_params->dcb_enabled;
rdata->dcb_version = tx_start_params->dcb_version;
rdata->dont_add_pri_0_en = tx_start_params->dont_add_pri_0_en;
for (i = 0; i < ARRAY_SIZE(rdata->traffic_type_to_priority_cos); i++)
rdata->traffic_type_to_priority_cos[i] =
tx_start_params->traffic_type_to_priority_cos[i];
return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_START_TRAFFIC, 0,
U64_HI(data_mapping),
U64_LO(data_mapping), NONE_CONNECTION_TYPE);
}
static int bnx2x_func_send_cmd(struct bnx2x *bp, static int bnx2x_func_send_cmd(struct bnx2x *bp,
struct bnx2x_func_state_params *params) struct bnx2x_func_state_params *params)
{ {
...@@ -5456,6 +5542,10 @@ static int bnx2x_func_send_cmd(struct bnx2x *bp, ...@@ -5456,6 +5542,10 @@ static int bnx2x_func_send_cmd(struct bnx2x *bp,
return bnx2x_func_send_stop(bp, params); return bnx2x_func_send_stop(bp, params);
case BNX2X_F_CMD_HW_RESET: case BNX2X_F_CMD_HW_RESET:
return bnx2x_func_hw_reset(bp, params); return bnx2x_func_hw_reset(bp, params);
case BNX2X_F_CMD_TX_STOP:
return bnx2x_func_send_tx_stop(bp, params);
case BNX2X_F_CMD_TX_START:
return bnx2x_func_send_tx_start(bp, params);
default: default:
BNX2X_ERR("Unknown command: %d\n", params->cmd); BNX2X_ERR("Unknown command: %d\n", params->cmd);
return -EINVAL; return -EINVAL;
......
...@@ -996,6 +996,7 @@ enum bnx2x_func_state { ...@@ -996,6 +996,7 @@ enum bnx2x_func_state {
BNX2X_F_STATE_RESET, BNX2X_F_STATE_RESET,
BNX2X_F_STATE_INITIALIZED, BNX2X_F_STATE_INITIALIZED,
BNX2X_F_STATE_STARTED, BNX2X_F_STATE_STARTED,
BNX2X_F_STATE_TX_STOPPED,
BNX2X_F_STATE_MAX, BNX2X_F_STATE_MAX,
}; };
...@@ -1005,6 +1006,8 @@ enum bnx2x_func_cmd { ...@@ -1005,6 +1006,8 @@ enum bnx2x_func_cmd {
BNX2X_F_CMD_START, BNX2X_F_CMD_START,
BNX2X_F_CMD_STOP, BNX2X_F_CMD_STOP,
BNX2X_F_CMD_HW_RESET, BNX2X_F_CMD_HW_RESET,
BNX2X_F_CMD_TX_STOP,
BNX2X_F_CMD_TX_START,
BNX2X_F_CMD_MAX, BNX2X_F_CMD_MAX,
}; };
...@@ -1047,6 +1050,13 @@ struct bnx2x_func_start_params { ...@@ -1047,6 +1050,13 @@ struct bnx2x_func_start_params {
u8 network_cos_mode; u8 network_cos_mode;
}; };
struct bnx2x_func_tx_start_params {
struct priority_cos traffic_type_to_priority_cos[MAX_TRAFFIC_TYPES];
u8 dcb_enabled;
u8 dcb_version;
u8 dont_add_pri_0_en;
};
struct bnx2x_func_state_params { struct bnx2x_func_state_params {
struct bnx2x_func_sp_obj *f_obj; struct bnx2x_func_sp_obj *f_obj;
...@@ -1061,6 +1071,7 @@ struct bnx2x_func_state_params { ...@@ -1061,6 +1071,7 @@ struct bnx2x_func_state_params {
struct bnx2x_func_hw_init_params hw_init; struct bnx2x_func_hw_init_params hw_init;
struct bnx2x_func_hw_reset_params hw_reset; struct bnx2x_func_hw_reset_params hw_reset;
struct bnx2x_func_start_params start; struct bnx2x_func_start_params start;
struct bnx2x_func_tx_start_params tx_start;
} params; } params;
}; };
...@@ -1152,6 +1163,8 @@ void bnx2x_init_func_obj(struct bnx2x *bp, ...@@ -1152,6 +1163,8 @@ void bnx2x_init_func_obj(struct bnx2x *bp,
int bnx2x_func_state_change(struct bnx2x *bp, int bnx2x_func_state_change(struct bnx2x *bp,
struct bnx2x_func_state_params *params); struct bnx2x_func_state_params *params);
enum bnx2x_func_state bnx2x_func_get_state(struct bnx2x *bp,
struct bnx2x_func_sp_obj *o);
/******************* Queue State **************/ /******************* Queue State **************/
void bnx2x_init_queue_obj(struct bnx2x *bp, void bnx2x_init_queue_obj(struct bnx2x *bp,
struct bnx2x_queue_sp_obj *obj, u8 cl_id, u32 *cids, struct bnx2x_queue_sp_obj *obj, u8 cl_id, u32 *cids,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment