Commit f43995bd authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'qed-qede-add-support-for-new-operating-modes'

Alexander Lobakin says:

====================
qed, qede: add support for new operating modes

This series covers the support for the following:
 - new port modes;
 - loopback modes, previously missing;
 - new speed/link modes;
 - several FEC modes;
 - multi-rate transceivers;

and also cleans up and optimizes several related parts of code.

v3 (from [2]):
 - dropped custom link mode declaration; qed, qede and qedf switched to
   Ethtool link modes and definitions (#0001, #0002, per Andrew Lunn's
   suggestion);
 - exchange more .text size to .initconst and .ro_after_init in qede
   (#0003).

v2 (from [1]):
 - added a patch (#0010) that drops discussed dead struct member;
 - addressed checkpatch complaints on #0014 (former #0013);
 - rebased on top of latest net-next;
 - no other changes.

[1] https://lore.kernel.org/netdev/20200716115446.994-1-alobakin@marvell.com/
[2] https://lore.kernel.org/netdev/20200719201453.3648-1-alobakin@marvell.com/


====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents cfd69201 99785a87
Loading
Loading
Loading
Loading
+56 −69
Original line number Diff line number Diff line
@@ -245,20 +245,6 @@ enum QED_FEATURE {
	QED_MAX_FEATURES,
};

enum QED_PORT_MODE {
	QED_PORT_MODE_DE_2X40G,
	QED_PORT_MODE_DE_2X50G,
	QED_PORT_MODE_DE_1X100G,
	QED_PORT_MODE_DE_4X10G_F,
	QED_PORT_MODE_DE_4X10G_E,
	QED_PORT_MODE_DE_4X20G,
	QED_PORT_MODE_DE_1X40G,
	QED_PORT_MODE_DE_2X25G,
	QED_PORT_MODE_DE_1X25G,
	QED_PORT_MODE_DE_4X25G,
	QED_PORT_MODE_DE_2X10G,
};

enum qed_dev_cap {
	QED_DEV_CAP_ETH,
	QED_DEV_CAP_FCOE,
@@ -302,12 +288,12 @@ struct qed_hw_info {
	/* Resource Allocation scheme results */
	u32				resc_start[QED_MAX_RESC];
	u32				resc_num[QED_MAX_RESC];
	u32				feat_num[QED_MAX_FEATURES];

#define RESC_START(_p_hwfn, resc)	((_p_hwfn)->hw_info.resc_start[resc])
#define RESC_NUM(_p_hwfn, resc)		((_p_hwfn)->hw_info.resc_num[resc])
#define RESC_END(_p_hwfn, resc)		(RESC_START(_p_hwfn, resc) +	\
					 RESC_NUM(_p_hwfn, resc))

	u32				feat_num[QED_MAX_FEATURES];
#define FEAT_NUM(_p_hwfn, resc)		((_p_hwfn)->hw_info.feat_num[resc])

	/* Amount of traffic classes HW supports */
@@ -317,11 +303,12 @@ struct qed_hw_info {
	 * layer driver configuration.
	 */
	u8				num_active_tc;

	u8				offload_tc;
	bool				offload_tc_set;

	bool				multi_tc_roce_en;
#define IS_QED_MULTI_TC_ROCE(p_hwfn) (((p_hwfn)->hw_info.multi_tc_roce_en))
#define IS_QED_MULTI_TC_ROCE(p_hwfn)	((p_hwfn)->hw_info.multi_tc_roce_en)

	u32				concrete_fid;
	u16				opaque_fid;
@@ -336,7 +323,6 @@ struct qed_hw_info {

	struct qed_igu_info		*p_igu_info;

	u32				port_mode;
	u32				hw_mode;
	unsigned long			device_capabilities;
	u16				mtu;
@@ -722,17 +708,18 @@ struct qed_dev {
	enum qed_dev_type		type;
	/* Translate type/revision combo into the proper conditions */
#define QED_IS_BB(dev)			((dev)->type == QED_DEV_TYPE_BB)
#define QED_IS_BB_B0(dev)       (QED_IS_BB(dev) && \
				 CHIP_REV_IS_B0(dev))
#define QED_IS_BB_B0(dev)		(QED_IS_BB(dev) && CHIP_REV_IS_B0(dev))
#define QED_IS_AH(dev)			((dev)->type == QED_DEV_TYPE_AH)
#define QED_IS_K2(dev)			QED_IS_AH(dev)
#define QED_IS_E4(dev)			(QED_IS_BB(dev) || QED_IS_AH(dev))
#define QED_IS_E5(dev)			((dev)->type == QED_DEV_TYPE_E5)

	u16				vendor_id;

	u16				device_id;
#define QED_DEV_ID_MASK			0xff00
#define QED_DEV_ID_MASK_BB		0x1600
#define QED_DEV_ID_MASK_AH		0x8000
#define QED_IS_E4(dev)  (QED_IS_BB(dev) || QED_IS_AH(dev))

	u16				chip_num;
#define CHIP_NUM_MASK			0xffff
+130 −42
Original line number Diff line number Diff line
@@ -3968,8 +3968,9 @@ static int qed_hw_get_resc(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)

static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
{
	u32 port_cfg_addr, link_temp, nvm_cfg_addr, device_capabilities;
	u32 port_cfg_addr, link_temp, nvm_cfg_addr, device_capabilities, fld;
	u32 nvm_cfg1_offset, mf_mode, addr, generic_cont0, core_cfg;
	struct qed_mcp_link_speed_params *ext_speed;
	struct qed_mcp_link_capabilities *p_caps;
	struct qed_mcp_link_params *link;

@@ -3994,37 +3995,21 @@ static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
	switch ((core_cfg & NVM_CFG1_GLOB_NETWORK_PORT_MODE_MASK) >>
		NVM_CFG1_GLOB_NETWORK_PORT_MODE_OFFSET) {
	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_2X40G:
		p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_2X40G;
		break;
	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_2X50G:
		p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_2X50G;
		break;
	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_1X100G:
		p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_1X100G;
		break;
	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_4X10G_F:
		p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_4X10G_F;
		break;
	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_4X10G_E:
		p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_4X10G_E;
		break;
	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_4X20G:
		p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_4X20G;
		break;
	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_1X40G:
		p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_1X40G;
		break;
	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_2X25G:
		p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_2X25G;
		break;
	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_2X10G:
		p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_2X10G;
		break;
	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_1X25G:
		p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_1X25G;
		break;
	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_4X25G:
		p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_4X25G;
	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_AHP_2X50G_R1:
	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_AHP_4X50G_R1:
	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_AHP_1X100G_R2:
	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_AHP_2X100G_R2:
	case NVM_CFG1_GLOB_NETWORK_PORT_MODE_AHP_1X100G_R4:
		break;
	default:
		DP_NOTICE(p_hwfn, "Unknown port mode in 0x%08x\n", core_cfg);
@@ -4042,8 +4027,7 @@ static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
	link_temp &= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_MASK;
	link->speed.advertised_speeds = link_temp;

	link_temp = link->speed.advertised_speeds;
	p_hwfn->mcp_info->link_capabilities.speed_capabilities = link_temp;
	p_caps->speed_capabilities = link->speed.advertised_speeds;

	link_temp = qed_rd(p_hwfn, p_ptt,
			   port_cfg_addr +
@@ -4078,19 +4062,40 @@ static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
		DP_NOTICE(p_hwfn, "Unknown Speed in 0x%08x\n", link_temp);
	}

	p_hwfn->mcp_info->link_capabilities.default_speed_autoneg =
		link->speed.autoneg;
	p_caps->default_speed_autoneg = link->speed.autoneg;

	link_temp &= NVM_CFG1_PORT_DRV_FLOW_CONTROL_MASK;
	link_temp >>= NVM_CFG1_PORT_DRV_FLOW_CONTROL_OFFSET;
	link->pause.autoneg = !!(link_temp &
				 NVM_CFG1_PORT_DRV_FLOW_CONTROL_AUTONEG);
	link->pause.forced_rx = !!(link_temp &
				   NVM_CFG1_PORT_DRV_FLOW_CONTROL_RX);
	link->pause.forced_tx = !!(link_temp &
				   NVM_CFG1_PORT_DRV_FLOW_CONTROL_TX);
	fld = GET_MFW_FIELD(link_temp, NVM_CFG1_PORT_DRV_FLOW_CONTROL);
	link->pause.autoneg = !!(fld & NVM_CFG1_PORT_DRV_FLOW_CONTROL_AUTONEG);
	link->pause.forced_rx = !!(fld & NVM_CFG1_PORT_DRV_FLOW_CONTROL_RX);
	link->pause.forced_tx = !!(fld & NVM_CFG1_PORT_DRV_FLOW_CONTROL_TX);
	link->loopback_mode = 0;

	if (p_hwfn->mcp_info->capabilities &
	    FW_MB_PARAM_FEATURE_SUPPORT_FEC_CONTROL) {
		switch (GET_MFW_FIELD(link_temp,
				      NVM_CFG1_PORT_FEC_FORCE_MODE)) {
		case NVM_CFG1_PORT_FEC_FORCE_MODE_NONE:
			p_caps->fec_default |= QED_FEC_MODE_NONE;
			break;
		case NVM_CFG1_PORT_FEC_FORCE_MODE_FIRECODE:
			p_caps->fec_default |= QED_FEC_MODE_FIRECODE;
			break;
		case NVM_CFG1_PORT_FEC_FORCE_MODE_RS:
			p_caps->fec_default |= QED_FEC_MODE_RS;
			break;
		case NVM_CFG1_PORT_FEC_FORCE_MODE_AUTO:
			p_caps->fec_default |= QED_FEC_MODE_AUTO;
			break;
		default:
			DP_VERBOSE(p_hwfn, NETIF_MSG_LINK,
				   "unknown FEC mode in 0x%08x\n", link_temp);
		}
	} else {
		p_caps->fec_default = QED_FEC_MODE_UNSUPPORTED;
	}

	link->fec = p_caps->fec_default;

	if (p_hwfn->mcp_info->capabilities & FW_MB_PARAM_FEATURE_SUPPORT_EEE) {
		link_temp = qed_rd(p_hwfn, p_ptt, port_cfg_addr +
				   offsetof(struct nvm_cfg1_port, ext_phy));
@@ -4122,14 +4127,97 @@ static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
		p_caps->default_eee = QED_MCP_EEE_UNSUPPORTED;
	}

	DP_VERBOSE(p_hwfn,
		   NETIF_MSG_LINK,
		   "Read default link: Speed 0x%08x, Adv. Speed 0x%08x, AN: 0x%02x, PAUSE AN: 0x%02x EEE: %02x [%08x usec]\n",
		   link->speed.forced_speed,
		   link->speed.advertised_speeds,
		   link->speed.autoneg,
		   link->pause.autoneg,
		   p_caps->default_eee, p_caps->eee_lpi_timer);
	if (p_hwfn->mcp_info->capabilities &
	    FW_MB_PARAM_FEATURE_SUPPORT_EXT_SPEED_FEC_CONTROL) {
		ext_speed = &link->ext_speed;

		link_temp = qed_rd(p_hwfn, p_ptt,
				   port_cfg_addr +
				   offsetof(struct nvm_cfg1_port,
					    extended_speed));

		fld = GET_MFW_FIELD(link_temp, NVM_CFG1_PORT_EXTENDED_SPEED);
		if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_AN)
			ext_speed->autoneg = true;

		ext_speed->forced_speed = 0;
		if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_1G)
			ext_speed->forced_speed |= QED_EXT_SPEED_1G;
		if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_10G)
			ext_speed->forced_speed |= QED_EXT_SPEED_10G;
		if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_20G)
			ext_speed->forced_speed |= QED_EXT_SPEED_20G;
		if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_25G)
			ext_speed->forced_speed |= QED_EXT_SPEED_25G;
		if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_40G)
			ext_speed->forced_speed |= QED_EXT_SPEED_40G;
		if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_50G_R)
			ext_speed->forced_speed |= QED_EXT_SPEED_50G_R;
		if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_50G_R2)
			ext_speed->forced_speed |= QED_EXT_SPEED_50G_R2;
		if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_100G_R2)
			ext_speed->forced_speed |= QED_EXT_SPEED_100G_R2;
		if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_100G_R4)
			ext_speed->forced_speed |= QED_EXT_SPEED_100G_R4;
		if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_100G_P4)
			ext_speed->forced_speed |= QED_EXT_SPEED_100G_P4;

		fld = GET_MFW_FIELD(link_temp,
				    NVM_CFG1_PORT_EXTENDED_SPEED_CAP);

		ext_speed->advertised_speeds = 0;
		if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_RESERVED)
			ext_speed->advertised_speeds |= QED_EXT_SPEED_MASK_RES;
		if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_1G)
			ext_speed->advertised_speeds |= QED_EXT_SPEED_MASK_1G;
		if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_10G)
			ext_speed->advertised_speeds |= QED_EXT_SPEED_MASK_10G;
		if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_20G)
			ext_speed->advertised_speeds |= QED_EXT_SPEED_MASK_20G;
		if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_25G)
			ext_speed->advertised_speeds |= QED_EXT_SPEED_MASK_25G;
		if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_40G)
			ext_speed->advertised_speeds |= QED_EXT_SPEED_MASK_40G;
		if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_50G_R)
			ext_speed->advertised_speeds |=
				QED_EXT_SPEED_MASK_50G_R;
		if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_50G_R2)
			ext_speed->advertised_speeds |=
				QED_EXT_SPEED_MASK_50G_R2;
		if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_100G_R2)
			ext_speed->advertised_speeds |=
				QED_EXT_SPEED_MASK_100G_R2;
		if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_100G_R4)
			ext_speed->advertised_speeds |=
				QED_EXT_SPEED_MASK_100G_R4;
		if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_100G_P4)
			ext_speed->advertised_speeds |=
				QED_EXT_SPEED_MASK_100G_P4;

		link_temp = qed_rd(p_hwfn, p_ptt,
				   port_cfg_addr +
				   offsetof(struct nvm_cfg1_port,
					    extended_fec_mode));
		link->ext_fec_mode = link_temp;

		p_caps->default_ext_speed_caps = ext_speed->advertised_speeds;
		p_caps->default_ext_speed = ext_speed->forced_speed;
		p_caps->default_ext_autoneg = ext_speed->autoneg;
		p_caps->default_ext_fec = link->ext_fec_mode;

		DP_VERBOSE(p_hwfn, NETIF_MSG_LINK,
			   "Read default extended link config: Speed 0x%08x, Adv. Speed 0x%08x, AN: 0x%02x, FEC: 0x%02x\n",
			   ext_speed->forced_speed,
			   ext_speed->advertised_speeds, ext_speed->autoneg,
			   p_caps->default_ext_fec);
	}

	DP_VERBOSE(p_hwfn, NETIF_MSG_LINK,
		   "Read default link: Speed 0x%08x, Adv. Speed 0x%08x, AN: 0x%02x, PAUSE AN: 0x%02x, EEE: 0x%02x [0x%08x usec], FEC: 0x%02x\n",
		   link->speed.forced_speed, link->speed.advertised_speeds,
		   link->speed.autoneg, link->pause.autoneg,
		   p_caps->default_eee, p_caps->eee_lpi_timer,
		   p_caps->fec_default);

	if (IS_LEAD_HWFN(p_hwfn)) {
		struct qed_dev *cdev = p_hwfn->cdev;
+458 −328

File changed.

Preview size limit exceeded, changes collapsed.

+592 −173

File changed.

Preview size limit exceeded, changes collapsed.

+115 −11
Original line number Diff line number Diff line
@@ -1446,6 +1446,25 @@ static void qed_mcp_handle_link_change(struct qed_hwfn *p_hwfn,
	if (p_hwfn->mcp_info->capabilities & FW_MB_PARAM_FEATURE_SUPPORT_EEE)
		qed_mcp_read_eee_config(p_hwfn, p_ptt, p_link);

	if (p_hwfn->mcp_info->capabilities &
	    FW_MB_PARAM_FEATURE_SUPPORT_FEC_CONTROL) {
		switch (status & LINK_STATUS_FEC_MODE_MASK) {
		case LINK_STATUS_FEC_MODE_NONE:
			p_link->fec_active = QED_FEC_MODE_NONE;
			break;
		case LINK_STATUS_FEC_MODE_FIRECODE_CL74:
			p_link->fec_active = QED_FEC_MODE_FIRECODE;
			break;
		case LINK_STATUS_FEC_MODE_RS_CL91:
			p_link->fec_active = QED_FEC_MODE_RS;
			break;
		default:
			p_link->fec_active = QED_FEC_MODE_AUTO;
		}
	} else {
		p_link->fec_active = QED_FEC_MODE_UNSUPPORTED;
	}

	qed_link_update(p_hwfn, p_ptt);
out:
	spin_unlock_bh(&p_hwfn->mcp_info->link_lock);
@@ -1456,8 +1475,9 @@ int qed_mcp_set_link(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, bool b_up)
	struct qed_mcp_link_params *params = &p_hwfn->mcp_info->link_input;
	struct qed_mcp_mb_params mb_params;
	struct eth_phy_cfg phy_cfg;
	u32 cmd, fec_bit = 0;
	u32 val, ext_speed;
	int rc = 0;
	u32 cmd;

	/* Set the shmem configuration according to params */
	memset(&phy_cfg, 0, sizeof(phy_cfg));
@@ -1489,19 +1509,91 @@ int qed_mcp_set_link(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, bool b_up)
				   EEE_TX_TIMER_USEC_MASK;
	}

	if (p_hwfn->mcp_info->capabilities &
	    FW_MB_PARAM_FEATURE_SUPPORT_FEC_CONTROL) {
		if (params->fec & QED_FEC_MODE_NONE)
			fec_bit |= FEC_FORCE_MODE_NONE;
		else if (params->fec & QED_FEC_MODE_FIRECODE)
			fec_bit |= FEC_FORCE_MODE_FIRECODE;
		else if (params->fec & QED_FEC_MODE_RS)
			fec_bit |= FEC_FORCE_MODE_RS;
		else if (params->fec & QED_FEC_MODE_AUTO)
			fec_bit |= FEC_FORCE_MODE_AUTO;

		SET_MFW_FIELD(phy_cfg.fec_mode, FEC_FORCE_MODE, fec_bit);
	}

	if (p_hwfn->mcp_info->capabilities &
	    FW_MB_PARAM_FEATURE_SUPPORT_EXT_SPEED_FEC_CONTROL) {
		ext_speed = 0;
		if (params->ext_speed.autoneg)
			ext_speed |= ETH_EXT_SPEED_AN;

		val = params->ext_speed.forced_speed;
		if (val & QED_EXT_SPEED_1G)
			ext_speed |= ETH_EXT_SPEED_1G;
		if (val & QED_EXT_SPEED_10G)
			ext_speed |= ETH_EXT_SPEED_10G;
		if (val & QED_EXT_SPEED_20G)
			ext_speed |= ETH_EXT_SPEED_20G;
		if (val & QED_EXT_SPEED_25G)
			ext_speed |= ETH_EXT_SPEED_25G;
		if (val & QED_EXT_SPEED_40G)
			ext_speed |= ETH_EXT_SPEED_40G;
		if (val & QED_EXT_SPEED_50G_R)
			ext_speed |= ETH_EXT_SPEED_50G_BASE_R;
		if (val & QED_EXT_SPEED_50G_R2)
			ext_speed |= ETH_EXT_SPEED_50G_BASE_R2;
		if (val & QED_EXT_SPEED_100G_R2)
			ext_speed |= ETH_EXT_SPEED_100G_BASE_R2;
		if (val & QED_EXT_SPEED_100G_R4)
			ext_speed |= ETH_EXT_SPEED_100G_BASE_R4;
		if (val & QED_EXT_SPEED_100G_P4)
			ext_speed |= ETH_EXT_SPEED_100G_BASE_P4;

		SET_MFW_FIELD(phy_cfg.extended_speed, ETH_EXT_SPEED,
			      ext_speed);

		ext_speed = 0;

		val = params->ext_speed.advertised_speeds;
		if (val & QED_EXT_SPEED_MASK_1G)
			ext_speed |= ETH_EXT_ADV_SPEED_1G;
		if (val & QED_EXT_SPEED_MASK_10G)
			ext_speed |= ETH_EXT_ADV_SPEED_10G;
		if (val & QED_EXT_SPEED_MASK_20G)
			ext_speed |= ETH_EXT_ADV_SPEED_20G;
		if (val & QED_EXT_SPEED_MASK_25G)
			ext_speed |= ETH_EXT_ADV_SPEED_25G;
		if (val & QED_EXT_SPEED_MASK_40G)
			ext_speed |= ETH_EXT_ADV_SPEED_40G;
		if (val & QED_EXT_SPEED_MASK_50G_R)
			ext_speed |= ETH_EXT_ADV_SPEED_50G_BASE_R;
		if (val & QED_EXT_SPEED_MASK_50G_R2)
			ext_speed |= ETH_EXT_ADV_SPEED_50G_BASE_R2;
		if (val & QED_EXT_SPEED_MASK_100G_R2)
			ext_speed |= ETH_EXT_ADV_SPEED_100G_BASE_R2;
		if (val & QED_EXT_SPEED_MASK_100G_R4)
			ext_speed |= ETH_EXT_ADV_SPEED_100G_BASE_R4;
		if (val & QED_EXT_SPEED_MASK_100G_P4)
			ext_speed |= ETH_EXT_ADV_SPEED_100G_BASE_P4;

		phy_cfg.extended_speed |= ext_speed;

		SET_MFW_FIELD(phy_cfg.fec_mode, FEC_EXTENDED_MODE,
			      params->ext_fec_mode);
	}

	p_hwfn->b_drv_link_init = b_up;

	if (b_up) {
		DP_VERBOSE(p_hwfn, NETIF_MSG_LINK,
			   "Configuring Link: Speed 0x%08x, Pause 0x%08x, adv_speed 0x%08x, loopback 0x%08x, features 0x%08x\n",
			   phy_cfg.speed,
			   phy_cfg.pause,
			   phy_cfg.adv_speed,
			   phy_cfg.loopback_mode,
			   phy_cfg.feature_config_flags);
			   "Configuring Link: Speed 0x%08x, Pause 0x%08x, Adv. Speed 0x%08x, Loopback 0x%08x, FEC 0x%08x, Ext. Speed 0x%08x\n",
			   phy_cfg.speed, phy_cfg.pause, phy_cfg.adv_speed,
			   phy_cfg.loopback_mode, phy_cfg.fec_mode,
			   phy_cfg.extended_speed);
	} else {
		DP_VERBOSE(p_hwfn, NETIF_MSG_LINK,
			   "Resetting link\n");
		DP_VERBOSE(p_hwfn, NETIF_MSG_LINK, "Resetting link\n");
	}

	memset(&mb_params, 0, sizeof(mb_params));
@@ -2193,6 +2285,11 @@ int qed_mcp_trans_speed_mask(struct qed_hwfn *p_hwfn,
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G |
		    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
		break;
	case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_25G_SR:
	case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_25G_LR:
		*p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G |
				NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
		break;
	case ETH_TRANSCEIVER_TYPE_40G_CR4:
	case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_CR:
		*p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G |
@@ -2223,6 +2320,8 @@ int qed_mcp_trans_speed_mask(struct qed_hwfn *p_hwfn,
		*p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G;
		break;
	case ETH_TRANSCEIVER_TYPE_10G_BASET:
	case ETH_TRANSCEIVER_TYPE_MULTI_RATE_1G_10G_SR:
	case ETH_TRANSCEIVER_TYPE_MULTI_RATE_1G_10G_LR:
		*p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G |
				NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
		break;
@@ -3798,7 +3897,12 @@ int qed_mcp_set_capabilities(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
	u32 mcp_resp, mcp_param, features;

	features = DRV_MB_PARAM_FEATURE_SUPPORT_PORT_EEE |
		   DRV_MB_PARAM_FEATURE_SUPPORT_FUNC_VLINK;
		   DRV_MB_PARAM_FEATURE_SUPPORT_FUNC_VLINK |
		   DRV_MB_PARAM_FEATURE_SUPPORT_PORT_FEC_CONTROL;

	if (QED_IS_E5(p_hwfn->cdev))
		features |=
		    DRV_MB_PARAM_FEATURE_SUPPORT_PORT_EXT_SPEED_FEC_CONTROL;

	return qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_FEATURE_SUPPORT,
			   features, &mcp_resp, &mcp_param);
Loading