diff options
author | Dmitry Kravkov <dmitry@broadcom.com> | 2011-07-19 05:42:04 +0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-07-19 20:57:48 +0400 |
commit | 6debea870a66be4aac2e28be0e3952dad6c7fcdb (patch) | |
tree | 60bf7bed2d6350ada4f0802f6d59d73c2ca6b372 /drivers/net/bnx2x | |
parent | f13ac41f5165c0ac0441f9d42f7d6f6f9ee7c075 (diff) | |
download | linux-6debea870a66be4aac2e28be0e3952dad6c7fcdb.tar.xz |
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: David Binderman <dcb314@hotmail.com>
Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bnx2x')
-rw-r--r-- | drivers/net/bnx2x/bnx2x.h | 7 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_dcb.c | 171 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_hsi.h | 1 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_main.c | 98 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_sp.c | 90 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_sp.h | 13 |
6 files changed, 268 insertions, 112 deletions
diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h index 53fa8ea983e9..333f5d6c6b81 100644 --- a/drivers/net/bnx2x/bnx2x.h +++ b/drivers/net/bnx2x/bnx2x.h @@ -966,6 +966,8 @@ struct bnx2x_slowpath { union { struct function_start_data func_start; + /* pfc configuration for DCBX ramrod */ + struct flow_control_configuration pfc_config; } func_rdata; /* used by dmae command executer */ @@ -980,8 +982,6 @@ struct bnx2x_slowpath { u32 wb_comp; u32 wb_data[4]; - /* pfc configuration for DCBX ramrod */ - struct flow_control_configuration pfc_config; }; #define bnx2x_sp(bp, var) (&bp->slowpath->var) @@ -1417,9 +1417,6 @@ struct bnx2x { char fw_ver[32]; const struct firmware *firmware; - /* LLDP params */ - struct bnx2x_config_lldp_params lldp_config_params; - /* DCB support on/off */ u16 dcb_state; #define BNX2X_DCB_STATE_OFF 0 diff --git a/drivers/net/bnx2x/bnx2x_dcb.c b/drivers/net/bnx2x/bnx2x_dcb.c index 3bfba44961d3..d028794a2298 100644 --- a/drivers/net/bnx2x/bnx2x_dcb.c +++ b/drivers/net/bnx2x/bnx2x_dcb.c @@ -29,10 +29,10 @@ #endif /* 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_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, u32 *set_configuration_ets_pg, u32 *pri_pg_tbl); @@ -47,8 +47,25 @@ static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp, struct cos_help_data *cos_data, u32 *pg_pri_orginal_spread, 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) { @@ -205,7 +222,11 @@ static void bnx2x_dcbx_get_ap_feature(struct bnx2x *bp, if (GET_FLAGS(error, DCBX_LOCAL_APP_ERROR)) 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; @@ -300,7 +321,7 @@ static void bnx2x_dcbx_get_pfc_feature(struct bnx2x *bp, DP(NETIF_MSG_LINK, "DCBX_LOCAL_PFC_ERROR\n"); 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) { bp->dcbx_port_params.pfc.enabled = true; bp->dcbx_port_params.pfc.priority_non_pauseable_mask = @@ -329,8 +350,8 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp, u32 offset, int read_mib_type) { - int max_try_read = 0, i; - u32 *buff, mib_size, prefix_seq_num, suffix_seq_num; + int max_try_read = 0; + u32 mib_size, prefix_seq_num, suffix_seq_num; struct lldp_remote_mib *remote_mib ; struct lldp_local_mib *local_mib; @@ -349,9 +370,7 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp, offset += BP_PORT(bp) * mib_size; do { - buff = base_mib_addr; - for (i = 0; i < mib_size; i += 4, buff++) - *buff = REG_RD(bp, offset + i); + bnx2x_read_data(bp, base_mib_addr, offset, mib_size); max_try_read++; @@ -382,12 +401,8 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp, static void bnx2x_pfc_set_pfc(struct bnx2x *bp) { - if (BP_PORT(bp)) { - BNX2X_ERR("4 port mode is not supported"); - return; - } - - if (bp->dcbx_port_params.pfc.enabled) + if (bp->dcbx_port_params.pfc.enabled && + !(bp->dcbx_error & DCBX_REMOTE_MIB_ERROR)) /* * 1. Fills up common PFC structures if required * 2. Configure NIG, MAC and BRB via the elink @@ -397,25 +412,30 @@ static void bnx2x_pfc_set_pfc(struct bnx2x *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"); - bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STOP_TRAFFIC, - 0 /* connectionless */, - 0 /* dataHi is zero */, - 0 /* dataLo is zero */, - NONE_CONNECTION_TYPE); + struct bnx2x_func_state_params func_params = {0}; + + func_params.f_obj = &bp->func_obj; + func_params.cmd = BNX2X_F_CMD_TX_STOP; + + 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); - DP(NETIF_MSG_LINK, "sending START TRAFFIC\n"); - bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_START_TRAFFIC, - 0, /* connectionless */ - U64_HI(bnx2x_sp_mapping(bp, pfc_config)), - U64_LO(bnx2x_sp_mapping(bp, pfc_config)), - NONE_CONNECTION_TYPE); + struct bnx2x_func_state_params func_params = {0}; + struct bnx2x_func_tx_start_params *tx_params = + &func_params.params.tx_start; + + func_params.f_obj = &bp->func_obj; + func_params.cmd = BNX2X_F_CMD_TX_START; + + 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) @@ -522,7 +542,8 @@ static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp) { 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; if (CHIP_IS_E3B0(bp)) @@ -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) + \ 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, u32 dcbx_lldp_params_offset) { struct lldp_admin_mib admin_mib; 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); /*shortcuts*/ @@ -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; memset(&admin_mib, 0, sizeof(struct lldp_admin_mib)); - buff = (u32 *)&admin_mib; + /* Read the data first */ - for (i = 0; i < sizeof(struct lldp_admin_mib); i += 4, buff++) - *buff = REG_RD(bp, (offset + i)); + bnx2x_read_data(bp, (u32 *)&admin_mib, offset, + sizeof(struct lldp_admin_mib)); if (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_ON) SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED); else RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED); - if ((BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE == - dp->overwrite_settings)) { + if (dp->overwrite_settings == BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE) { + RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_CEE_VERSION_MASK); admin_mib.ver_cfg_flags |= (dp->admin_dcbx_version << DCBX_CEE_VERSION_SHIFT) & @@ -908,19 +882,17 @@ static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp, 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. */ - buff = (u32 *)&admin_mib; - for (i = 0; i < sizeof(struct lldp_admin_mib); i += 4, buff++) - REG_WR(bp, (offset + i), *buff); + bnx2x_write_data(bp, (u32 *)&admin_mib, offset, + sizeof(struct lldp_admin_mib)); + } 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->dcbx_enabled = dcbx_enabled; } else { @@ -1029,9 +1001,6 @@ void bnx2x_dcbx_init(struct bnx2x *bp) bnx2x_update_drv_flags(bp, DRV_FLAGS_DCB_CONFIGURED, 0); 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, dcbx_lldp_params_offset); @@ -1043,7 +1012,7 @@ void bnx2x_dcbx_init(struct bnx2x *bp) } static void 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 cos = 0; @@ -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; u8 cos = 0, pri = 0; struct priority_cos *tt2cos; u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority; - pfc_fw_cfg = (struct flow_control_configuration *) - bnx2x_sp(bp, pfc_config); - memset(pfc_fw_cfg, 0, sizeof(struct flow_control_configuration)); + memset(pfc_fw_cfg, 0, sizeof(*pfc_fw_cfg)); + + /* to disable DCB - the structure must be zeroed */ + if (bp->dcbx_error & DCBX_REMOTE_MIB_ERROR) + return; /*shortcut*/ tt2cos = pfc_fw_cfg->traffic_type_to_priority_cos; diff --git a/drivers/net/bnx2x/bnx2x_hsi.h b/drivers/net/bnx2x/bnx2x_hsi.h index ce3b5662ca5a..06727f32e505 100644 --- a/drivers/net/bnx2x/bnx2x_hsi.h +++ b/drivers/net/bnx2x/bnx2x_hsi.h @@ -1834,6 +1834,7 @@ struct lldp_local_mib { #define DCBX_LOCAL_APP_ERROR 0x00000004 #define DCBX_LOCAL_PFC_MISMATCH 0x00000010 #define DCBX_LOCAL_APP_MISMATCH 0x00000020 + #define DCBX_REMOTE_MIB_ERROR 0x00000040 struct dcbx_features features; u32 suffix_seq_num; }; diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 8a374a77cdc9..a86517cffd4a 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -4403,11 +4403,17 @@ static void bnx2x_eq_int(struct bnx2x *bp) case EVENT_RING_OPCODE_STOP_TRAFFIC: 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); goto next_spqe; case EVENT_RING_OPCODE_START_TRAFFIC: 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); goto next_spqe; case EVENT_RING_OPCODE_FUNCTION_START: @@ -7536,6 +7542,71 @@ void bnx2x_send_unload_done(struct bnx2x *bp) 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) { int port = BP_PORT(bp); @@ -7595,6 +7666,26 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode) 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 * Completions for ramrods are collected in a synchronous way */ @@ -7622,13 +7713,6 @@ unload_error: #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 */ bnx2x_netif_stop(bp, 1); diff --git a/drivers/net/bnx2x/bnx2x_sp.c b/drivers/net/bnx2x/bnx2x_sp.c index 358c33997536..6306ff59de0c 100644 --- a/drivers/net/bnx2x/bnx2x_sp.c +++ b/drivers/net/bnx2x/bnx2x_sp.c @@ -4874,6 +4874,22 @@ static int bnx2x_queue_chk_transition(struct bnx2x *bp, ¶ms->params.update; 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, ¶ms->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) { case BNX2X_Q_STATE_RESET: if (cmd == BNX2X_Q_CMD_INIT) @@ -5053,6 +5069,21 @@ void bnx2x_queue_set_cos_cid(struct bnx2x *bp, } /********************** 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, struct bnx2x_func_sp_obj *o, @@ -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_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, ¶ms->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) { case BNX2X_F_STATE_RESET: if (cmd == BNX2X_F_CMD_HW_INIT) @@ -5160,6 +5207,13 @@ static int bnx2x_func_chk_transition(struct bnx2x *bp, case BNX2X_F_STATE_STARTED: if (cmd == BNX2X_F_CMD_STOP) 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; default: @@ -5444,6 +5498,38 @@ static inline int bnx2x_func_send_stop(struct bnx2x *bp, 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 = + ¶ms->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, struct bnx2x_func_state_params *params) { @@ -5456,6 +5542,10 @@ static int bnx2x_func_send_cmd(struct bnx2x *bp, return bnx2x_func_send_stop(bp, params); case BNX2X_F_CMD_HW_RESET: 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: BNX2X_ERR("Unknown command: %d\n", params->cmd); return -EINVAL; diff --git a/drivers/net/bnx2x/bnx2x_sp.h b/drivers/net/bnx2x/bnx2x_sp.h index 83f3b0b44211..73400dd77b2f 100644 --- a/drivers/net/bnx2x/bnx2x_sp.h +++ b/drivers/net/bnx2x/bnx2x_sp.h @@ -996,6 +996,7 @@ enum bnx2x_func_state { BNX2X_F_STATE_RESET, BNX2X_F_STATE_INITIALIZED, BNX2X_F_STATE_STARTED, + BNX2X_F_STATE_TX_STOPPED, BNX2X_F_STATE_MAX, }; @@ -1005,6 +1006,8 @@ enum bnx2x_func_cmd { BNX2X_F_CMD_START, BNX2X_F_CMD_STOP, BNX2X_F_CMD_HW_RESET, + BNX2X_F_CMD_TX_STOP, + BNX2X_F_CMD_TX_START, BNX2X_F_CMD_MAX, }; @@ -1047,6 +1050,13 @@ struct bnx2x_func_start_params { 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_sp_obj *f_obj; @@ -1061,6 +1071,7 @@ struct bnx2x_func_state_params { struct bnx2x_func_hw_init_params hw_init; struct bnx2x_func_hw_reset_params hw_reset; struct bnx2x_func_start_params start; + struct bnx2x_func_tx_start_params tx_start; } params; }; @@ -1152,6 +1163,8 @@ void bnx2x_init_func_obj(struct bnx2x *bp, int bnx2x_func_state_change(struct bnx2x *bp, 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 **************/ void bnx2x_init_queue_obj(struct bnx2x *bp, struct bnx2x_queue_sp_obj *obj, u8 cl_id, u32 *cids, |