Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+2 −5
Original line number Diff line number Diff line
@@ -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
+71 −100
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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;
};
+91 −7
Original line number Diff line number Diff line
@@ -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 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
#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);

+90 −0
Original line number Diff line number Diff line
@@ -4874,6 +4874,22 @@ static int bnx2x_queue_chk_transition(struct bnx2x *bp,
		 &params->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, &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) {
	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, &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) {
	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 =
		&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,
			       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;
Loading