DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 0/3] net/cxgbe: rework link config and add FEC support
@ 2020-12-20 22:47 Rahul Lakkireddy
  2020-12-20 22:47 ` [dpdk-dev] [PATCH 1/3] net/cxgbe: remove legacy 16-bit link capabilities Rahul Lakkireddy
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Rahul Lakkireddy @ 2020-12-20 22:47 UTC (permalink / raw)
  To: dev; +Cc: kaara.satwik

This series of patches rework link handling and add support to
configure Forward Error Correction (FEC) capability.

Patch 1 removes legacy 16-bit link capabilities infrastructure
and always enables 32-bit link capabilities in firmware.

Patch 2 simplifies link handling in preparation for FEC support.

Patch 3 adds support to configure link FEC when supported.

Thanks,
Rahul

Karra Satwik (3):
  net/cxgbe: remove legacy 16-bit link capabilities
  net/cxgbe: rework and simplify link handling code
  net/cxgbe: implement ethdev ops to configure link FEC

 doc/guides/nics/cxgbe.rst               |  14 +-
 drivers/net/cxgbe/base/adapter.h        |  10 -
 drivers/net/cxgbe/base/common.h         |  71 +--
 drivers/net/cxgbe/base/t4_hw.c          | 648 +++++++++++-------------
 drivers/net/cxgbe/base/t4fw_interface.h |  87 +---
 drivers/net/cxgbe/base/t4vf_hw.c        |  86 +---
 drivers/net/cxgbe/cxgbe_ethdev.c        | 201 +++++++-
 drivers/net/cxgbe/cxgbe_main.c          |  21 +-
 8 files changed, 565 insertions(+), 573 deletions(-)

-- 
2.24.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [dpdk-dev] [PATCH 1/3] net/cxgbe: remove legacy 16-bit link capabilities
  2020-12-20 22:47 [dpdk-dev] [PATCH 0/3] net/cxgbe: rework link config and add FEC support Rahul Lakkireddy
@ 2020-12-20 22:47 ` Rahul Lakkireddy
  2020-12-20 22:47 ` [dpdk-dev] [PATCH 2/3] net/cxgbe: rework and simplify link handling code Rahul Lakkireddy
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Rahul Lakkireddy @ 2020-12-20 22:47 UTC (permalink / raw)
  To: dev; +Cc: kaara.satwik

From: Karra Satwik <kaara.satwik@chelsio.com>

Remove legacy 16-bit link capabilities and always request for the
32-bit link capabilities from firmware.

Signed-off-by: Karra Satwik <kaara.satwik@chelsio.com>
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
---
 doc/guides/nics/cxgbe.rst               |  14 +-
 drivers/net/cxgbe/base/common.h         |   9 -
 drivers/net/cxgbe/base/t4_hw.c          | 233 +++++-------------------
 drivers/net/cxgbe/base/t4fw_interface.h |  70 +------
 drivers/net/cxgbe/base/t4vf_hw.c        |  79 +++-----
 5 files changed, 78 insertions(+), 327 deletions(-)

diff --git a/doc/guides/nics/cxgbe.rst b/doc/guides/nics/cxgbe.rst
index f01cd6560..4b9913669 100644
--- a/doc/guides/nics/cxgbe.rst
+++ b/doc/guides/nics/cxgbe.rst
@@ -70,7 +70,7 @@ in :ref:`t5-nics` and :ref:`t6-nics`.
 Prerequisites
 -------------
 
-- Requires firmware version **1.24.11.0** and higher. Visit
+- Requires firmware version **1.24.17.0** and higher. Visit
   `Chelsio Download Center <http://service.chelsio.com>`_ to get latest firmware
   bundled with the latest Chelsio Unified Wire package.
 
@@ -404,7 +404,7 @@ Unified Wire package for Linux operating system are as follows:
 
    .. code-block:: console
 
-      firmware-version: 1.24.11.0, TP 0.1.23.2
+      firmware-version: 1.24.17.0, TP 0.1.23.2
 
 Running testpmd
 ~~~~~~~~~~~~~~~
@@ -462,7 +462,7 @@ devices managed by librte_net_cxgbe in Linux operating system.
       EAL:   PCI memory mapped at 0x7fd7c0200000
       EAL:   PCI memory mapped at 0x7fd77cdfd000
       EAL:   PCI memory mapped at 0x7fd7c10b7000
-      PMD: rte_cxgbe_pmd: fw: 1.24.11.0, TP: 0.1.23.2
+      PMD: rte_cxgbe_pmd: fw: 1.24.17.0, TP: 0.1.23.2
       PMD: rte_cxgbe_pmd: Coming up as MASTER: Initializing adapter
       Interactive-mode selected
       Configuring Port 0 (socket 0)
@@ -568,7 +568,7 @@ virtual functions.
       [...]
       EAL: PCI device 0000:02:01.0 on NUMA socket 0
       EAL:   probe driver: 1425:5803 net_cxgbevf
-      PMD: rte_cxgbe_pmd: Firmware version: 1.24.11.0
+      PMD: rte_cxgbe_pmd: Firmware version: 1.24.17.0
       PMD: rte_cxgbe_pmd: TP Microcode version: 0.1.23.2
       PMD: rte_cxgbe_pmd: Chelsio rev 0
       PMD: rte_cxgbe_pmd: No bootstrap loaded
@@ -576,7 +576,7 @@ virtual functions.
       PMD: rte_cxgbe_pmd:  0000:02:01.0 Chelsio rev 0 1G/10GBASE-SFP
       EAL: PCI device 0000:02:01.1 on NUMA socket 0
       EAL:   probe driver: 1425:5803 net_cxgbevf
-      PMD: rte_cxgbe_pmd: Firmware version: 1.24.11.0
+      PMD: rte_cxgbe_pmd: Firmware version: 1.24.17.0
       PMD: rte_cxgbe_pmd: TP Microcode version: 0.1.23.2
       PMD: rte_cxgbe_pmd: Chelsio rev 0
       PMD: rte_cxgbe_pmd: No bootstrap loaded
@@ -654,7 +654,7 @@ Unified Wire package for FreeBSD operating system are as follows:
 
    .. code-block:: console
 
-      dev.t5nex.0.firmware_version: 1.24.11.0
+      dev.t5nex.0.firmware_version: 1.24.17.0
 
 Running testpmd
 ~~~~~~~~~~~~~~~
@@ -772,7 +772,7 @@ devices managed by librte_net_cxgbe in FreeBSD operating system.
       EAL:   PCI memory mapped at 0x8007ec000
       EAL:   PCI memory mapped at 0x842800000
       EAL:   PCI memory mapped at 0x80086c000
-      PMD: rte_cxgbe_pmd: fw: 1.24.11.0, TP: 0.1.23.2
+      PMD: rte_cxgbe_pmd: fw: 1.24.17.0, TP: 0.1.23.2
       PMD: rte_cxgbe_pmd: Coming up as MASTER: Initializing adapter
       Interactive-mode selected
       Configuring Port 0 (socket 0)
diff --git a/drivers/net/cxgbe/base/common.h b/drivers/net/cxgbe/base/common.h
index 8fe8e2a36..86f3dc80b 100644
--- a/drivers/net/cxgbe/base/common.h
+++ b/drivers/net/cxgbe/base/common.h
@@ -274,7 +274,6 @@ struct adapter_params {
 	struct arch_specific_params arch; /* chip specific params */
 
 	bool ulptx_memwrite_dsgl;          /* use of T5 DSGL allowed */
-	u8 fw_caps_support;		  /* 32-bit Port Capabilities */
 	u8 filter2_wr_support;            /* FW support for FILTER2_WR */
 	u32 viid_smt_extn_support:1;	  /* FW returns vin and smt index */
 	u32 max_tx_coalesce_num; /* Max # of Tx packets that can be coalesced */
@@ -282,15 +281,8 @@ struct adapter_params {
 
 /* Firmware Port Capabilities types.
  */
-typedef u16 fw_port_cap16_t;    /* 16-bit Port Capabilities integral value */
 typedef u32 fw_port_cap32_t;    /* 32-bit Port Capabilities integral value */
 
-enum fw_caps {
-	FW_CAPS_UNKNOWN = 0,    /* 0'ed out initial state */
-	FW_CAPS16       = 1,    /* old Firmware: 16-bit Port Capabilities */
-	FW_CAPS32       = 2,    /* new Firmware: 32-bit Port Capabilities */
-};
-
 struct link_config {
 	fw_port_cap32_t pcaps;          /* link capabilities */
 	fw_port_cap32_t acaps;          /* advertised capabilities */
@@ -552,5 +544,4 @@ static inline int t4_memory_rw(struct adapter *adap, int win,
 {
 	return t4_memory_rw_mtype(adap, win, mtype, maddr, len, hbuf, dir);
 }
-fw_port_cap32_t fwcaps16_to_caps32(fw_port_cap16_t caps16);
 #endif /* __CHELSIO_COMMON_H */
diff --git a/drivers/net/cxgbe/base/t4_hw.c b/drivers/net/cxgbe/base/t4_hw.c
index 9217956b4..44227740c 100644
--- a/drivers/net/cxgbe/base/t4_hw.c
+++ b/drivers/net/cxgbe/base/t4_hw.c
@@ -2811,81 +2811,6 @@ void t4_dump_version_info(struct adapter *adapter)
 
 #define ADVERT_MASK (V_FW_PORT_CAP32_SPEED(M_FW_PORT_CAP32_SPEED) | \
 		     FW_PORT_CAP32_ANEG)
-/**
- *     fwcaps16_to_caps32 - convert 16-bit Port Capabilities to 32-bits
- *     @caps16: a 16-bit Port Capabilities value
- *
- *     Returns the equivalent 32-bit Port Capabilities value.
- */
-fw_port_cap32_t fwcaps16_to_caps32(fw_port_cap16_t caps16)
-{
-	fw_port_cap32_t caps32 = 0;
-
-#define CAP16_TO_CAP32(__cap) \
-	do { \
-		if (caps16 & FW_PORT_CAP_##__cap) \
-			caps32 |= FW_PORT_CAP32_##__cap; \
-	} while (0)
-
-	CAP16_TO_CAP32(SPEED_100M);
-	CAP16_TO_CAP32(SPEED_1G);
-	CAP16_TO_CAP32(SPEED_25G);
-	CAP16_TO_CAP32(SPEED_10G);
-	CAP16_TO_CAP32(SPEED_40G);
-	CAP16_TO_CAP32(SPEED_100G);
-	CAP16_TO_CAP32(FC_RX);
-	CAP16_TO_CAP32(FC_TX);
-	CAP16_TO_CAP32(ANEG);
-	CAP16_TO_CAP32(MDIX);
-	CAP16_TO_CAP32(MDIAUTO);
-	CAP16_TO_CAP32(FEC_RS);
-	CAP16_TO_CAP32(FEC_BASER_RS);
-	CAP16_TO_CAP32(802_3_PAUSE);
-	CAP16_TO_CAP32(802_3_ASM_DIR);
-
-#undef CAP16_TO_CAP32
-
-	return caps32;
-}
-
-/**
- *     fwcaps32_to_caps16 - convert 32-bit Port Capabilities to 16-bits
- *     @caps32: a 32-bit Port Capabilities value
- *
- *     Returns the equivalent 16-bit Port Capabilities value.  Note that
- *     not all 32-bit Port Capabilities can be represented in the 16-bit
- *     Port Capabilities and some fields/values may not make it.
- */
-static fw_port_cap16_t fwcaps32_to_caps16(fw_port_cap32_t caps32)
-{
-	fw_port_cap16_t caps16 = 0;
-
-#define CAP32_TO_CAP16(__cap) \
-	do { \
-		if (caps32 & FW_PORT_CAP32_##__cap) \
-			caps16 |= FW_PORT_CAP_##__cap; \
-	} while (0)
-
-	CAP32_TO_CAP16(SPEED_100M);
-	CAP32_TO_CAP16(SPEED_1G);
-	CAP32_TO_CAP16(SPEED_10G);
-	CAP32_TO_CAP16(SPEED_25G);
-	CAP32_TO_CAP16(SPEED_40G);
-	CAP32_TO_CAP16(SPEED_100G);
-	CAP32_TO_CAP16(FC_RX);
-	CAP32_TO_CAP16(FC_TX);
-	CAP32_TO_CAP16(802_3_PAUSE);
-	CAP32_TO_CAP16(802_3_ASM_DIR);
-	CAP32_TO_CAP16(ANEG);
-	CAP32_TO_CAP16(MDIX);
-	CAP32_TO_CAP16(MDIAUTO);
-	CAP32_TO_CAP16(FEC_RS);
-	CAP32_TO_CAP16(FEC_BASER_RS);
-
-#undef CAP32_TO_CAP16
-
-	return caps16;
-}
 
 /* Translate Firmware Pause specification to Common Code */
 static inline enum cc_pause fwcap_to_cc_pause(fw_port_cap32_t fw_pause)
@@ -2957,7 +2882,6 @@ int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
 		  struct link_config *lc)
 {
 	unsigned int fw_mdi = V_FW_PORT_CAP32_MDI(FW_PORT_CAP32_MDI_AUTO);
-	unsigned int fw_caps = adap->params.fw_caps_support;
 	fw_port_cap32_t fw_fc, cc_fec, fw_fec, rcap;
 	struct fw_port_cmd cmd;
 
@@ -2999,15 +2923,10 @@ int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
 				       F_FW_CMD_REQUEST | F_FW_CMD_EXEC |
 				       V_FW_PORT_CMD_PORTID(port));
 	cmd.action_to_len16 =
-		cpu_to_be32(V_FW_PORT_CMD_ACTION(fw_caps == FW_CAPS16 ?
-						 FW_PORT_ACTION_L1_CFG :
-						 FW_PORT_ACTION_L1_CFG32) |
+		cpu_to_be32(V_FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG32) |
 			    FW_LEN16(cmd));
 
-	if (fw_caps == FW_CAPS16)
-		cmd.u.l1cfg.rcap = cpu_to_be32(fwcaps32_to_caps16(rcap));
-	else
-		cmd.u.l1cfg32.rcap32 = cpu_to_be32(rcap);
+	cmd.u.l1cfg32.rcap32 = cpu_to_be32(rcap);
 
 	return t4_wr_mbox(adap, mbox, &cmd, sizeof(cmd), NULL);
 }
@@ -4539,73 +4458,31 @@ static unsigned int fwcap_to_speed(fw_port_cap32_t caps)
 static void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
 {
 	const struct fw_port_cmd *cmd = (const void *)rpl;
-	int action = G_FW_PORT_CMD_ACTION(be32_to_cpu(cmd->action_to_len16));
-	fw_port_cap32_t pcaps, acaps, linkattr;
+	u8 link_ok, link_down_rc, mod_type, port_type;
+	u32 action, pcaps, acaps, linkattr, lstatus;
 	struct link_config *lc = &pi->link_cfg;
 	struct adapter *adapter = pi->adapter;
-	enum fw_port_module_type mod_type;
-	enum fw_port_type port_type;
 	unsigned int speed, fc, fec;
-	int link_ok, linkdnrc;
 
 	/* Extract the various fields from the Port Information message.
 	 */
-	switch (action) {
-	case FW_PORT_ACTION_GET_PORT_INFO: {
-		u32 lstatus = be32_to_cpu(cmd->u.info.lstatus_to_modtype);
-
-		link_ok = (lstatus & F_FW_PORT_CMD_LSTATUS) != 0;
-		linkdnrc = G_FW_PORT_CMD_LINKDNRC(lstatus);
-		port_type = G_FW_PORT_CMD_PTYPE(lstatus);
-		mod_type = G_FW_PORT_CMD_MODTYPE(lstatus);
-		pcaps = fwcaps16_to_caps32(be16_to_cpu(cmd->u.info.pcap));
-		acaps = fwcaps16_to_caps32(be16_to_cpu(cmd->u.info.acap));
-
-		/* Unfortunately the format of the Link Status in the old
-		 * 16-bit Port Information message isn't the same as the
-		 * 16-bit Port Capabilities bitfield used everywhere else ...
-		 */
-		linkattr = 0;
-		if (lstatus & F_FW_PORT_CMD_RXPAUSE)
-			linkattr |= FW_PORT_CAP32_FC_RX;
-		if (lstatus & F_FW_PORT_CMD_TXPAUSE)
-			linkattr |= FW_PORT_CAP32_FC_TX;
-		if (lstatus & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_100M))
-			linkattr |= FW_PORT_CAP32_SPEED_100M;
-		if (lstatus & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_1G))
-			linkattr |= FW_PORT_CAP32_SPEED_1G;
-		if (lstatus & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_10G))
-			linkattr |= FW_PORT_CAP32_SPEED_10G;
-		if (lstatus & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_25G))
-			linkattr |= FW_PORT_CAP32_SPEED_25G;
-		if (lstatus & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_40G))
-			linkattr |= FW_PORT_CAP32_SPEED_40G;
-		if (lstatus & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_100G))
-			linkattr |= FW_PORT_CAP32_SPEED_100G;
-
-		break;
-		}
-
-	case FW_PORT_ACTION_GET_PORT_INFO32: {
-		u32 lstatus32 =
-			be32_to_cpu(cmd->u.info32.lstatus32_to_cbllen32);
-
-		link_ok = (lstatus32 & F_FW_PORT_CMD_LSTATUS32) != 0;
-		linkdnrc = G_FW_PORT_CMD_LINKDNRC32(lstatus32);
-		port_type = G_FW_PORT_CMD_PORTTYPE32(lstatus32);
-		mod_type = G_FW_PORT_CMD_MODTYPE32(lstatus32);
-		pcaps = be32_to_cpu(cmd->u.info32.pcaps32);
-		acaps = be32_to_cpu(cmd->u.info32.acaps32);
-		linkattr = be32_to_cpu(cmd->u.info32.linkattr32);
-		break;
-		}
-
-	default:
+	action = be32_to_cpu(cmd->action_to_len16);
+	if (G_FW_PORT_CMD_ACTION(action) != FW_PORT_ACTION_GET_PORT_INFO32) {
 		dev_warn(adapter, "Handle Port Information: Bad Command/Action %#x\n",
-			 be32_to_cpu(cmd->action_to_len16));
+			 action);
 		return;
 	}
 
+	lstatus = be32_to_cpu(cmd->u.info32.lstatus32_to_cbllen32);
+	link_ok = (lstatus & F_FW_PORT_CMD_LSTATUS32) ? 1 : 0;
+	link_down_rc = G_FW_PORT_CMD_LINKDNRC32(lstatus);
+	port_type = G_FW_PORT_CMD_PORTTYPE32(lstatus);
+	mod_type = G_FW_PORT_CMD_MODTYPE32(lstatus);
+
+	pcaps = be32_to_cpu(cmd->u.info32.pcaps32);
+	acaps = be32_to_cpu(cmd->u.info32.acaps32);
+	linkattr = be32_to_cpu(cmd->u.info32.linkattr32);
+
 	fec = fwcap_to_cc_fec(acaps);
 
 	fc = fwcap_to_cc_pause(linkattr);
@@ -4620,9 +4497,10 @@ static void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
 	if (link_ok != lc->link_ok || speed != lc->speed ||
 	    fc != lc->fc || fec != lc->fec) { /* something changed */
 		if (!link_ok && lc->link_ok) {
-			lc->link_down_rc = linkdnrc;
+			lc->link_down_rc = link_down_rc;
 			dev_warn(adap, "Port %d link down, reason: %s\n",
-				 pi->tx_chan, t4_link_down_rc_str(linkdnrc));
+				 pi->port_id,
+				 t4_link_down_rc_str(link_down_rc));
 		}
 		lc->link_ok = link_ok;
 		lc->speed = speed;
@@ -4691,9 +4569,7 @@ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl)
 	unsigned int action =
 		G_FW_PORT_CMD_ACTION(be32_to_cpu(p->action_to_len16));
 
-	if (opcode == FW_PORT_CMD &&
-	    (action == FW_PORT_ACTION_GET_PORT_INFO ||
-	     action == FW_PORT_ACTION_GET_PORT_INFO32)) {
+	if (opcode == FW_PORT_CMD && action == FW_PORT_ACTION_GET_PORT_INFO32) {
 		/* link/module state change message */
 		int chan = G_FW_PORT_CMD_PORTID(be32_to_cpu(p->op_to_portid));
 		struct port_info *pi = NULL;
@@ -5395,81 +5271,54 @@ int t4_init_rss_mode(struct adapter *adap, int mbox)
 
 int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
 {
-	unsigned int fw_caps = adap->params.fw_caps_support;
 	fw_port_cap32_t pcaps, acaps;
 	enum fw_port_type port_type;
 	struct fw_port_cmd cmd;
 	u8 vivld = 0, vin = 0;
 	int ret, i, j = 0;
+	u32 param, val;
 	int mdio_addr;
-	u32 action;
 	u8 addr[6];
 
+	param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) |
+		 V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_PORT_CAPS32));
+	val = 1;
+	ret = t4_set_params(adap, mbox, pf, vf, 1, &param, &val);
+	if (ret < 0)
+		return ret;
+
 	memset(&cmd, 0, sizeof(cmd));
 
 	for_each_port(adap, i) {
 		struct port_info *pi = adap2pinfo(adap, i);
 		unsigned int rss_size = 0;
+		u32 lstatus32;
 
 		while ((adap->params.portvec & (1 << j)) == 0)
 			j++;
 
-		/* If we haven't yet determined whether we're talking to
-		 * Firmware which knows the new 32-bit Port Capabilities, it's
-		 * time to find out now.  This will also tell new Firmware to
-		 * send us Port Status Updates using the new 32-bit Port
-		 * Capabilities version of the Port Information message.
-		 */
-		if (fw_caps == FW_CAPS_UNKNOWN) {
-			u32 param, val, caps;
-
-			caps = FW_PARAMS_PARAM_PFVF_PORT_CAPS32;
-			param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) |
-				 V_FW_PARAMS_PARAM_X(caps));
-			val = 1;
-			ret = t4_set_params(adap, mbox, pf, vf, 1, &param,
-					    &val);
-			fw_caps = ret == 0 ? FW_CAPS32 : FW_CAPS16;
-			adap->params.fw_caps_support = fw_caps;
-		}
-
 		memset(&cmd, 0, sizeof(cmd));
 		cmd.op_to_portid = cpu_to_be32(V_FW_CMD_OP(FW_PORT_CMD) |
 					       F_FW_CMD_REQUEST |
 					       F_FW_CMD_READ |
 					       V_FW_PORT_CMD_PORTID(j));
-		action = fw_caps == FW_CAPS16 ? FW_PORT_ACTION_GET_PORT_INFO :
-						FW_PORT_ACTION_GET_PORT_INFO32;
-		cmd.action_to_len16 = cpu_to_be32(V_FW_PORT_CMD_ACTION(action) |
+		val = FW_PORT_ACTION_GET_PORT_INFO32;
+		cmd.action_to_len16 = cpu_to_be32(V_FW_PORT_CMD_ACTION(val) |
 						  FW_LEN16(cmd));
 		ret = t4_wr_mbox(pi->adapter, mbox, &cmd, sizeof(cmd), &cmd);
 		if (ret)
 			return ret;
 
-		/* Extract the various fields from the Port Information message.
+		/* Extract the various fields from the Port Information
+		 * message.
 		 */
-		if (fw_caps == FW_CAPS16) {
-			u32 lstatus =
-				be32_to_cpu(cmd.u.info.lstatus_to_modtype);
-
-			port_type = G_FW_PORT_CMD_PTYPE(lstatus);
-			mdio_addr = (lstatus & F_FW_PORT_CMD_MDIOCAP) ?
-				    (int)G_FW_PORT_CMD_MDIOADDR(lstatus) : -1;
-			pcaps = be16_to_cpu(cmd.u.info.pcap);
-			acaps = be16_to_cpu(cmd.u.info.acap);
-			pcaps = fwcaps16_to_caps32(pcaps);
-			acaps = fwcaps16_to_caps32(acaps);
-		} else {
-			u32 lstatus32 =
-				be32_to_cpu(cmd.u.info32.lstatus32_to_cbllen32);
-
-			port_type = G_FW_PORT_CMD_PORTTYPE32(lstatus32);
-			mdio_addr = (lstatus32 & F_FW_PORT_CMD_MDIOCAP32) ?
-				    (int)G_FW_PORT_CMD_MDIOADDR32(lstatus32) :
-				    -1;
-			pcaps = be32_to_cpu(cmd.u.info32.pcaps32);
-			acaps = be32_to_cpu(cmd.u.info32.acaps32);
-		}
+		lstatus32 = be32_to_cpu(cmd.u.info32.lstatus32_to_cbllen32);
+
+		port_type = G_FW_PORT_CMD_PORTTYPE32(lstatus32);
+		mdio_addr = (lstatus32 & F_FW_PORT_CMD_MDIOCAP32) ?
+			    (int)G_FW_PORT_CMD_MDIOADDR32(lstatus32) : -1;
+		pcaps = be32_to_cpu(cmd.u.info32.pcaps32);
+		acaps = be32_to_cpu(cmd.u.info32.acaps32);
 
 		ret = t4_alloc_vi(adap, mbox, j, pf, vf, 1, addr, &rss_size,
 				  &vivld, &vin);
diff --git a/drivers/net/cxgbe/base/t4fw_interface.h b/drivers/net/cxgbe/base/t4fw_interface.h
index 109273a39..153141247 100644
--- a/drivers/net/cxgbe/base/t4fw_interface.h
+++ b/drivers/net/cxgbe/base/t4fw_interface.h
@@ -1598,41 +1598,6 @@ struct fw_vi_stats_cmd {
 #define S_FW_VI_STATS_CMD_IX		0
 #define V_FW_VI_STATS_CMD_IX(x)		((x) << S_FW_VI_STATS_CMD_IX)
 
-/* old 16-bit port capabilities bitmap */
-enum fw_port_cap {
-	FW_PORT_CAP_SPEED_100M		= 0x0001,
-	FW_PORT_CAP_SPEED_1G		= 0x0002,
-	FW_PORT_CAP_SPEED_25G		= 0x0004,
-	FW_PORT_CAP_SPEED_10G		= 0x0008,
-	FW_PORT_CAP_SPEED_40G		= 0x0010,
-	FW_PORT_CAP_SPEED_100G		= 0x0020,
-	FW_PORT_CAP_FC_RX		= 0x0040,
-	FW_PORT_CAP_FC_TX		= 0x0080,
-	FW_PORT_CAP_ANEG		= 0x0100,
-	FW_PORT_CAP_MDIX		= 0x0200,
-	FW_PORT_CAP_MDIAUTO		= 0x0400,
-	FW_PORT_CAP_FEC_RS              = 0x0800,
-	FW_PORT_CAP_FEC_BASER_RS        = 0x1000,
-	FW_PORT_CAP_FEC_RESERVED        = 0x2000,
-	FW_PORT_CAP_802_3_PAUSE		= 0x4000,
-	FW_PORT_CAP_802_3_ASM_DIR	= 0x8000,
-};
-
-#define S_FW_PORT_CAP_SPEED     0
-#define M_FW_PORT_CAP_SPEED     0x3f
-#define V_FW_PORT_CAP_SPEED(x)  ((x) << S_FW_PORT_CAP_SPEED)
-#define G_FW_PORT_CAP_SPEED(x) \
-	(((x) >> S_FW_PORT_CAP_SPEED) & M_FW_PORT_CAP_SPEED)
-
-enum fw_port_mdi {
-	FW_PORT_CAP_MDI_AUTO,
-};
-
-#define S_FW_PORT_CAP_MDI 9
-#define M_FW_PORT_CAP_MDI 3
-#define V_FW_PORT_CAP_MDI(x) ((x) << S_FW_PORT_CAP_MDI)
-#define G_FW_PORT_CAP_MDI(x) (((x) >> S_FW_PORT_CAP_MDI) & M_FW_PORT_CAP_MDI)
-
 /* new 32-bit port capabilities bitmap (fw_port_cap32_t) */
 #define FW_PORT_CAP32_SPEED_100M        0x00000001UL
 #define FW_PORT_CAP32_SPEED_1G          0x00000002UL
@@ -1668,8 +1633,6 @@ enum fw_port_mdi32 {
 	(((x) >> S_FW_PORT_CAP32_MDI) & M_FW_PORT_CAP32_MDI)
 
 enum fw_port_action {
-	FW_PORT_ACTION_L1_CFG		= 0x0001,
-	FW_PORT_ACTION_GET_PORT_INFO	= 0x0003,
 	FW_PORT_ACTION_L1_CFG32         = 0x0009,
 	FW_PORT_ACTION_GET_PORT_INFO32  = 0x000a,
 };
@@ -1814,37 +1777,12 @@ struct fw_port_cmd {
 	(((x) >> S_FW_PORT_CMD_RXPAUSE) & M_FW_PORT_CMD_RXPAUSE)
 #define F_FW_PORT_CMD_RXPAUSE	V_FW_PORT_CMD_RXPAUSE(1U)
 
-#define S_FW_PORT_CMD_MDIOCAP		21
-#define M_FW_PORT_CMD_MDIOCAP		0x1
-#define V_FW_PORT_CMD_MDIOCAP(x)	((x) << S_FW_PORT_CMD_MDIOCAP)
-#define G_FW_PORT_CMD_MDIOCAP(x)	\
-	(((x) >> S_FW_PORT_CMD_MDIOCAP) & M_FW_PORT_CMD_MDIOCAP)
-#define F_FW_PORT_CMD_MDIOCAP	V_FW_PORT_CMD_MDIOCAP(1U)
-
-#define S_FW_PORT_CMD_MDIOADDR		16
-#define M_FW_PORT_CMD_MDIOADDR		0x1f
-#define V_FW_PORT_CMD_MDIOADDR(x)	((x) << S_FW_PORT_CMD_MDIOADDR)
-#define G_FW_PORT_CMD_MDIOADDR(x)	\
-	(((x) >> S_FW_PORT_CMD_MDIOADDR) & M_FW_PORT_CMD_MDIOADDR)
-
 #define S_FW_PORT_CMD_PTYPE	8
 #define M_FW_PORT_CMD_PTYPE	0x1f
 #define V_FW_PORT_CMD_PTYPE(x)	((x) << S_FW_PORT_CMD_PTYPE)
 #define G_FW_PORT_CMD_PTYPE(x)	\
 	(((x) >> S_FW_PORT_CMD_PTYPE) & M_FW_PORT_CMD_PTYPE)
 
-#define S_FW_PORT_CMD_LINKDNRC		5
-#define M_FW_PORT_CMD_LINKDNRC		0x7
-#define V_FW_PORT_CMD_LINKDNRC(x)	((x) << S_FW_PORT_CMD_LINKDNRC)
-#define G_FW_PORT_CMD_LINKDNRC(x)	\
-	(((x) >> S_FW_PORT_CMD_LINKDNRC) & M_FW_PORT_CMD_LINKDNRC)
-
-#define S_FW_PORT_CMD_MODTYPE		0
-#define M_FW_PORT_CMD_MODTYPE		0x1f
-#define V_FW_PORT_CMD_MODTYPE(x)	((x) << S_FW_PORT_CMD_MODTYPE)
-#define G_FW_PORT_CMD_MODTYPE(x)	\
-	(((x) >> S_FW_PORT_CMD_MODTYPE) & M_FW_PORT_CMD_MODTYPE)
-
 #define S_FW_PORT_CMD_LSTATUS32                31
 #define M_FW_PORT_CMD_LSTATUS32                0x1
 #define V_FW_PORT_CMD_LSTATUS32(x)     ((x) << S_FW_PORT_CMD_LSTATUS32)
@@ -1924,10 +1862,10 @@ enum fw_port_module_type {
 	FW_PORT_MOD_TYPE_TWINAX_PASSIVE	= 0x4,
 	FW_PORT_MOD_TYPE_TWINAX_ACTIVE	= 0x5,
 	FW_PORT_MOD_TYPE_LRM		= 0x6,
-	FW_PORT_MOD_TYPE_ERROR		= M_FW_PORT_CMD_MODTYPE - 3,
-	FW_PORT_MOD_TYPE_UNKNOWN	= M_FW_PORT_CMD_MODTYPE - 2,
-	FW_PORT_MOD_TYPE_NOTSUPPORTED	= M_FW_PORT_CMD_MODTYPE - 1,
-	FW_PORT_MOD_TYPE_NONE		= M_FW_PORT_CMD_MODTYPE
+	FW_PORT_MOD_TYPE_ERROR		= M_FW_PORT_CMD_MODTYPE32 - 3,
+	FW_PORT_MOD_TYPE_UNKNOWN	= M_FW_PORT_CMD_MODTYPE32 - 2,
+	FW_PORT_MOD_TYPE_NOTSUPPORTED	= M_FW_PORT_CMD_MODTYPE32 - 1,
+	FW_PORT_MOD_TYPE_NONE		= M_FW_PORT_CMD_MODTYPE32
 };
 
 /* used by FW and tools may use this to generate VPD */
diff --git a/drivers/net/cxgbe/base/t4vf_hw.c b/drivers/net/cxgbe/base/t4vf_hw.c
index 649bacfb2..6454029aa 100644
--- a/drivers/net/cxgbe/base/t4vf_hw.c
+++ b/drivers/net/cxgbe/base/t4vf_hw.c
@@ -766,35 +766,24 @@ static int t4vf_alloc_vi(struct adapter *adapter, int port_id)
 
 int t4vf_port_init(struct adapter *adapter)
 {
-	unsigned int fw_caps = adapter->params.fw_caps_support;
-	struct fw_port_cmd port_cmd, port_rpl;
+	struct fw_port_cmd port_cmd, port_rpl, rpl;
 	struct fw_vi_cmd vi_cmd, vi_rpl;
 	fw_port_cap32_t pcaps, acaps;
 	enum fw_port_type port_type;
+	u32 param, val;
 	int mdio_addr;
 	int ret, i;
 
+	param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) |
+		 V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_PORT_CAPS32));
+	val = 1;
+	ret = t4vf_set_params(adapter, 1, &param, &val);
+	if (ret < 0)
+		return ret;
+
 	for_each_port(adapter, i) {
 		struct port_info *p = adap2pinfo(adapter, i);
-
-		/*
-		 * If we haven't yet determined if we're talking to Firmware
-		 * which knows the new 32-bit Port Caps, it's time to find
-		 * out now.  This will also tell new Firmware to send us Port
-		 * Status Updates using the new 32-bit Port Capabilities
-		 * version of the Port Information message.
-		 */
-		if (fw_caps == FW_CAPS_UNKNOWN) {
-			u32 param, val;
-
-			param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) |
-				 V_FW_PARAMS_PARAM_X
-					 (FW_PARAMS_PARAM_PFVF_PORT_CAPS32));
-			val = 1;
-			ret = t4vf_set_params(adapter, 1, &param, &val);
-			fw_caps = (ret == 0 ? FW_CAPS32 : FW_CAPS16);
-			adapter->params.fw_caps_support = fw_caps;
-		}
+		u32 lstatus32;
 
 		ret = t4vf_alloc_vi(adapter, p->port_id);
 		if (ret < 0) {
@@ -830,15 +819,14 @@ int t4vf_port_init(struct adapter *adapter)
 			return 0;
 
 		memset(&port_cmd, 0, sizeof(port_cmd));
-		port_cmd.op_to_portid = cpu_to_be32
-				(V_FW_CMD_OP(FW_PORT_CMD) | F_FW_CMD_REQUEST |
-				F_FW_CMD_READ |
-				V_FW_PORT_CMD_PORTID(p->port_id));
-		port_cmd.action_to_len16 = cpu_to_be32
-				(V_FW_PORT_CMD_ACTION(fw_caps == FW_CAPS16 ?
-					FW_PORT_ACTION_GET_PORT_INFO :
-					FW_PORT_ACTION_GET_PORT_INFO32) |
-					FW_LEN16(port_cmd));
+		port_cmd.op_to_portid =
+			cpu_to_be32(V_FW_CMD_OP(FW_PORT_CMD) |
+				    F_FW_CMD_REQUEST | F_FW_CMD_READ |
+				    V_FW_PORT_CMD_PORTID(p->port_id));
+		val = FW_PORT_ACTION_GET_PORT_INFO32;
+		port_cmd.action_to_len16 =
+			cpu_to_be32(V_FW_PORT_CMD_ACTION(val) |
+				    FW_LEN16(port_cmd));
 		ret = t4vf_wr_mbox(adapter, &port_cmd, sizeof(port_cmd),
 				   &port_rpl);
 		if (ret != FW_SUCCESS)
@@ -847,29 +835,14 @@ int t4vf_port_init(struct adapter *adapter)
 		/*
 		 * Extract the various fields from the Port Information message.
 		 */
-		if (fw_caps == FW_CAPS16) {
-			u32 lstatus = be32_to_cpu
-					(port_rpl.u.info.lstatus_to_modtype);
-
-			port_type = G_FW_PORT_CMD_PTYPE(lstatus);
-			mdio_addr = ((lstatus & F_FW_PORT_CMD_MDIOCAP) ?
-				      (int)G_FW_PORT_CMD_MDIOADDR(lstatus) :
-				      -1);
-			pcaps = fwcaps16_to_caps32
-					(be16_to_cpu(port_rpl.u.info.pcap));
-			acaps = fwcaps16_to_caps32
-					(be16_to_cpu(port_rpl.u.info.acap));
-		} else {
-			u32 lstatus32 = be32_to_cpu
-				(port_rpl.u.info32.lstatus32_to_cbllen32);
-
-			port_type = G_FW_PORT_CMD_PORTTYPE32(lstatus32);
-			mdio_addr = ((lstatus32 & F_FW_PORT_CMD_MDIOCAP32) ?
-				      (int)G_FW_PORT_CMD_MDIOADDR32(lstatus32) :
-				      -1);
-			pcaps = be32_to_cpu(port_rpl.u.info32.pcaps32);
-			acaps = be32_to_cpu(port_rpl.u.info32.acaps32);
-		}
+		rpl = port_rpl;
+		lstatus32 = be32_to_cpu(rpl.u.info32.lstatus32_to_cbllen32);
+
+		port_type = G_FW_PORT_CMD_PORTTYPE32(lstatus32);
+		mdio_addr = (lstatus32 & F_FW_PORT_CMD_MDIOCAP32) ?
+			    (int)G_FW_PORT_CMD_MDIOADDR32(lstatus32) : -1;
+		pcaps = be32_to_cpu(port_rpl.u.info32.pcaps32);
+		acaps = be32_to_cpu(port_rpl.u.info32.acaps32);
 
 		p->port_type = port_type;
 		p->mdio_addr = mdio_addr;
-- 
2.24.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [dpdk-dev] [PATCH 2/3] net/cxgbe: rework and simplify link handling code
  2020-12-20 22:47 [dpdk-dev] [PATCH 0/3] net/cxgbe: rework link config and add FEC support Rahul Lakkireddy
  2020-12-20 22:47 ` [dpdk-dev] [PATCH 1/3] net/cxgbe: remove legacy 16-bit link capabilities Rahul Lakkireddy
@ 2020-12-20 22:47 ` Rahul Lakkireddy
  2020-12-20 22:47 ` [dpdk-dev] [PATCH 3/3] net/cxgbe: implement ethdev ops to configure link FEC Rahul Lakkireddy
  2021-01-15 15:02 ` [dpdk-dev] [PATCH 0/3] net/cxgbe: rework link config and add FEC support Ferruh Yigit
  3 siblings, 0 replies; 5+ messages in thread
From: Rahul Lakkireddy @ 2020-12-20 22:47 UTC (permalink / raw)
  To: dev; +Cc: kaara.satwik

From: Karra Satwik <kaara.satwik@chelsio.com>

Rework and simplify link handling code. Remove redundant
variables in link configuration structure and directly
extract information from the 32-bit link capabilities.

Signed-off-by: Karra Satwik <kaara.satwik@chelsio.com>
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
---
 drivers/net/cxgbe/base/adapter.h        |  10 -
 drivers/net/cxgbe/base/common.h         |  60 ++--
 drivers/net/cxgbe/base/t4_hw.c          | 350 +++++++++++++-----------
 drivers/net/cxgbe/base/t4fw_interface.h |  11 +-
 drivers/net/cxgbe/base/t4vf_hw.c        |   9 +-
 drivers/net/cxgbe/cxgbe_ethdev.c        |  68 +++--
 drivers/net/cxgbe/cxgbe_main.c          |  21 +-
 7 files changed, 275 insertions(+), 254 deletions(-)

diff --git a/drivers/net/cxgbe/base/adapter.h b/drivers/net/cxgbe/base/adapter.h
index 6ff009a5f..a5a3313c2 100644
--- a/drivers/net/cxgbe/base/adapter.h
+++ b/drivers/net/cxgbe/base/adapter.h
@@ -39,9 +39,6 @@ struct port_info {
 	short int xact_addr_filt;       /* index of exact MAC address filter */
 
 	u16    viid;                    /* associated virtual interface id */
-	s8     mdio_addr;               /* address of the PHY */
-	u8     port_type;               /* firmware port type */
-	u8     mod_type;                /* firmware module type */
 	u8     port_id;                 /* physical port ID */
 	u8     pidx;			/* port index for this PF */
 	u8     tx_chan;                 /* associated channel */
@@ -63,12 +60,6 @@ struct port_info {
 	u8 vivld;
 };
 
-/* Enable or disable autonegotiation.  If this is set to enable,
- * the forced link modes above are completely ignored.
- */
-#define AUTONEG_DISABLE         0x00
-#define AUTONEG_ENABLE          0x01
-
 enum {                                 /* adapter flags */
 	FULL_INIT_DONE     = (1 << 0),
 	USING_MSI          = (1 << 1),
@@ -801,7 +792,6 @@ void t4_free_mem(void *addr);
 #define t4_os_free(_ptr)       t4_free_mem((_ptr))
 
 void t4_os_portmod_changed(const struct adapter *adap, int port_id);
-void t4_os_link_changed(struct adapter *adap, int port_id, int link_stat);
 
 void reclaim_completed_tx(struct sge_txq *q);
 void t4_free_sge_resources(struct adapter *adap);
diff --git a/drivers/net/cxgbe/base/common.h b/drivers/net/cxgbe/base/common.h
index 86f3dc80b..a244df7a0 100644
--- a/drivers/net/cxgbe/base/common.h
+++ b/drivers/net/cxgbe/base/common.h
@@ -38,18 +38,6 @@ enum dev_master { MASTER_CANT, MASTER_MAY, MASTER_MUST };
 
 enum dev_state { DEV_STATE_UNINIT, DEV_STATE_INIT, DEV_STATE_ERR };
 
-enum cc_pause {
-	PAUSE_RX      = 1 << 0,
-	PAUSE_TX      = 1 << 1,
-	PAUSE_AUTONEG = 1 << 2
-};
-
-enum cc_fec {
-	FEC_AUTO     = 1 << 0,    /* IEEE 802.3 "automatic" */
-	FEC_RS       = 1 << 1,    /* Reed-Solomon */
-	FEC_BASER_RS = 1 << 2,    /* BaseR/Reed-Solomon */
-};
-
 enum { MEM_EDC0, MEM_EDC1, MEM_MC, MEM_MC0 = MEM_MC, MEM_MC1 };
 
 struct port_stats {
@@ -281,28 +269,19 @@ struct adapter_params {
 
 /* Firmware Port Capabilities types.
  */
-typedef u32 fw_port_cap32_t;    /* 32-bit Port Capabilities integral value */
-
 struct link_config {
-	fw_port_cap32_t pcaps;          /* link capabilities */
-	fw_port_cap32_t acaps;          /* advertised capabilities */
-
-	u32 requested_speed;            /* speed (Mb/s) user has requested */
-	u32 speed;                      /* actual link speed (Mb/s) */
-
-	enum cc_pause requested_fc;     /* flow control user has requested */
-	enum cc_pause fc;               /* actual link flow control */
+	u32 pcaps;         /* Physically supported link caps */
+	u32 acaps;         /* Advertised link caps */
 
-	enum cc_fec auto_fec;           /* Forward Error Correction
-					 * "automatic" (IEEE 802.3)
-					 */
-	enum cc_fec requested_fec;      /* Forward Error Correction requested */
-	enum cc_fec fec;                /* Forward Error Correction actual */
+	u32 link_caps;     /* Current link caps */
+	u32 admin_caps;    /* Admin configured link caps  */
 
-	unsigned char autoneg;          /* autonegotiating? */
+	u8 mdio_addr;      /* Address of the PHY */
+	u8 port_type;      /* Firmware port type */
+	u8 mod_type;       /* Firmware module type */
 
-	unsigned char link_ok;          /* link up? */
-	unsigned char link_down_rc;     /* link down reason */
+	u8 link_ok;        /* Link up? */
+	u8 link_down_rc;   /* Link down reason */
 };
 
 #include "adapter.h"
@@ -338,8 +317,21 @@ void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr,
 			    unsigned int mask, unsigned int val);
 void t4_intr_enable(struct adapter *adapter);
 void t4_intr_disable(struct adapter *adapter);
-int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
-		  struct link_config *lc);
+int t4_link_l1cfg_core(struct port_info *pi, u32 caps, u8 sleep_ok);
+static inline int t4_link_l1cfg(struct port_info *pi, u32 caps)
+{
+	return t4_link_l1cfg_core(pi, caps, true);
+}
+
+static inline int t4_link_l1cfg_ns(struct port_info *pi, u32 caps)
+{
+	return t4_link_l1cfg_core(pi, caps, false);
+}
+
+int t4_set_link_speed(struct port_info *pi, u32 speed, u32 *new_caps);
+int t4_set_link_pause(struct port_info *pi, u8 autoneg, u8 pause_tx,
+		      u8 pause_rx, u32 *new_caps);
+unsigned int t4_fwcap_to_speed(u32 caps);
 void t4_load_mtus(struct adapter *adap, const unsigned short *mtus,
 		  const unsigned short *alpha, const unsigned short *beta);
 int t4_fw_hello(struct adapter *adap, unsigned int mbox, unsigned int evt_mbox,
@@ -496,8 +488,8 @@ void t4_get_port_stats_offset(struct adapter *adap, int idx,
 			      struct port_stats *stats,
 			      struct port_stats *offset);
 void t4_clr_port_stats(struct adapter *adap, int idx);
-void init_link_config(struct link_config *lc, fw_port_cap32_t pcaps,
-		      fw_port_cap32_t acaps);
+void t4_init_link_config(struct port_info *pi, u32 pcaps, u32 acaps,
+			 u8 mdio_addr, u8 port_type, u8 mod_type);
 void t4_reset_link_config(struct adapter *adap, int idx);
 int t4_get_version_info(struct adapter *adapter);
 void t4_dump_version_info(struct adapter *adapter);
diff --git a/drivers/net/cxgbe/base/t4_hw.c b/drivers/net/cxgbe/base/t4_hw.c
index 44227740c..3c0990cb3 100644
--- a/drivers/net/cxgbe/base/t4_hw.c
+++ b/drivers/net/cxgbe/base/t4_hw.c
@@ -2809,67 +2809,11 @@ void t4_dump_version_info(struct adapter *adapter)
 			 G_FW_HDR_FW_VER_BUILD(adapter->params.er_vers));
 }
 
-#define ADVERT_MASK (V_FW_PORT_CAP32_SPEED(M_FW_PORT_CAP32_SPEED) | \
-		     FW_PORT_CAP32_ANEG)
-
-/* Translate Firmware Pause specification to Common Code */
-static inline enum cc_pause fwcap_to_cc_pause(fw_port_cap32_t fw_pause)
-{
-	enum cc_pause cc_pause = 0;
-
-	if (fw_pause & FW_PORT_CAP32_FC_RX)
-		cc_pause |= PAUSE_RX;
-	if (fw_pause & FW_PORT_CAP32_FC_TX)
-		cc_pause |= PAUSE_TX;
-
-	return cc_pause;
-}
-
-/* Translate Common Code Pause Frame specification into Firmware */
-static inline fw_port_cap32_t cc_to_fwcap_pause(enum cc_pause cc_pause)
-{
-	fw_port_cap32_t fw_pause = 0;
-
-	if (cc_pause & PAUSE_RX)
-		fw_pause |= FW_PORT_CAP32_FC_RX;
-	if (cc_pause & PAUSE_TX)
-		fw_pause |= FW_PORT_CAP32_FC_TX;
-
-	return fw_pause;
-}
-
-/* Translate Firmware Forward Error Correction specification to Common Code */
-static inline enum cc_fec fwcap_to_cc_fec(fw_port_cap32_t fw_fec)
-{
-	enum cc_fec cc_fec = 0;
-
-	if (fw_fec & FW_PORT_CAP32_FEC_RS)
-		cc_fec |= FEC_RS;
-	if (fw_fec & FW_PORT_CAP32_FEC_BASER_RS)
-		cc_fec |= FEC_BASER_RS;
-
-	return cc_fec;
-}
-
-/* Translate Common Code Forward Error Correction specification to Firmware */
-static inline fw_port_cap32_t cc_to_fwcap_fec(enum cc_fec cc_fec)
-{
-	fw_port_cap32_t fw_fec = 0;
-
-	if (cc_fec & FEC_RS)
-		fw_fec |= FW_PORT_CAP32_FEC_RS;
-	if (cc_fec & FEC_BASER_RS)
-		fw_fec |= FW_PORT_CAP32_FEC_BASER_RS;
-
-	return fw_fec;
-}
-
 /**
- * t4_link_l1cfg - apply link configuration to MAC/PHY
- * @adapter: the adapter
- * @mbox: the Firmware Mailbox to use
- * @port: the Port ID
- * @lc: the Port's Link Configuration
+ * t4_link_l1cfg_core - apply link configuration to MAC/PHY
+ * @pi: the port info
+ * @caps: link capabilities to configure
+ * @sleep_ok: if true we may sleep while awaiting command completion
  *
  * Set up a port's MAC and PHY according to a desired link configuration.
  * - If the PHY can auto-negotiate first decide what to advertise, then
@@ -2878,57 +2822,38 @@ static inline fw_port_cap32_t cc_to_fwcap_fec(enum cc_fec cc_fec)
  * - If auto-negotiation is off set the MAC to the proper speed/duplex/FC,
  *   otherwise do it later based on the outcome of auto-negotiation.
  */
-int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
-		  struct link_config *lc)
+int t4_link_l1cfg_core(struct port_info *pi, u32 caps, u8 sleep_ok)
 {
-	unsigned int fw_mdi = V_FW_PORT_CAP32_MDI(FW_PORT_CAP32_MDI_AUTO);
-	fw_port_cap32_t fw_fc, cc_fec, fw_fec, rcap;
+	struct link_config *lc = &pi->link_cfg;
+	struct adapter *adap = pi->adapter;
 	struct fw_port_cmd cmd;
+	int ret;
 
-	lc->link_ok = 0;
-
-	fw_fc = cc_to_fwcap_pause(lc->requested_fc);
-
-	/* Convert Common Code Forward Error Control settings into the
-	 * Firmware's API.  If the current Requested FEC has "Automatic"
-	 * (IEEE 802.3) specified, then we use whatever the Firmware
-	 * sent us as part of it's IEEE 802.3-based interpratation of
-	 * the Transceiver Module EPROM FEC parameters.  Otherwise we
-	 * use whatever is in the current Requested FEC settings.
-	 */
-	if (lc->requested_fec & FEC_AUTO)
-		cc_fec = lc->auto_fec;
-	else
-		cc_fec = lc->requested_fec;
-	fw_fec = cc_to_fwcap_fec(cc_fec);
-
-	/* Figure out what our Requested Port Capabilities are going to be.
-	 */
-	if (!(lc->pcaps & FW_PORT_CAP32_ANEG)) {
-		rcap = (lc->pcaps & ADVERT_MASK) | fw_fc | fw_fec;
-		lc->fc = lc->requested_fc & ~PAUSE_AUTONEG;
-		lc->fec = cc_fec;
-	} else if (lc->autoneg == AUTONEG_DISABLE) {
-		rcap = lc->requested_speed | fw_fc | fw_fec | fw_mdi;
-		lc->fc = lc->requested_fc & ~PAUSE_AUTONEG;
-		lc->fec = cc_fec;
-	} else {
-		rcap = lc->acaps | fw_fc | fw_fec | fw_mdi;
-	}
-
-	/* And send that on to the Firmware ...
-	 */
 	memset(&cmd, 0, sizeof(cmd));
 	cmd.op_to_portid = cpu_to_be32(V_FW_CMD_OP(FW_PORT_CMD) |
 				       F_FW_CMD_REQUEST | F_FW_CMD_EXEC |
-				       V_FW_PORT_CMD_PORTID(port));
+				       V_FW_PORT_CMD_PORTID(pi->port_id));
 	cmd.action_to_len16 =
 		cpu_to_be32(V_FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG32) |
 			    FW_LEN16(cmd));
 
-	cmd.u.l1cfg32.rcap32 = cpu_to_be32(rcap);
+	cmd.u.l1cfg32.rcap32 = cpu_to_be32(caps);
 
-	return t4_wr_mbox(adap, mbox, &cmd, sizeof(cmd), NULL);
+	if (sleep_ok)
+		ret = t4_wr_mbox(adap, adap->mbox, &cmd, sizeof(cmd), NULL);
+	else
+		ret = t4_wr_mbox_ns(adap, adap->mbox, &cmd, sizeof(cmd), NULL);
+
+	if (ret == FW_SUCCESS) {
+		lc->link_ok = 0;
+		lc->link_caps = caps;
+	} else {
+		dev_err(adap,
+			"Requested Port Capabilities %#x rejected, error %d\n",
+			caps, ret);
+	}
+
+	return ret;
 }
 
 /**
@@ -4426,8 +4351,32 @@ static const char *t4_link_down_rc_str(unsigned char link_down_rc)
 	return reason[link_down_rc];
 }
 
+static u32 t4_speed_to_fwcap(u32 speed)
+{
+	switch (speed) {
+	case 100000:
+		return FW_PORT_CAP32_SPEED_100G;
+	case 50000:
+		return FW_PORT_CAP32_SPEED_50G;
+	case 40000:
+		return FW_PORT_CAP32_SPEED_40G;
+	case 25000:
+		return FW_PORT_CAP32_SPEED_25G;
+	case 10000:
+		return FW_PORT_CAP32_SPEED_10G;
+	case 1000:
+		return FW_PORT_CAP32_SPEED_1G;
+	case 100:
+		return FW_PORT_CAP32_SPEED_100M;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
 /* Return the highest speed set in the port capabilities, in Mb/s. */
-static unsigned int fwcap_to_speed(fw_port_cap32_t caps)
+unsigned int t4_fwcap_to_speed(u32 caps)
 {
 #define TEST_SPEED_RETURN(__caps_speed, __speed) \
 	do { \
@@ -4448,6 +4397,84 @@ static unsigned int fwcap_to_speed(fw_port_cap32_t caps)
 	return 0;
 }
 
+static void t4_set_link_autoneg_speed(struct port_info *pi, u32 *new_caps)
+{
+	struct link_config *lc = &pi->link_cfg;
+	u32 caps = *new_caps;
+
+	caps &= ~V_FW_PORT_CAP32_SPEED(M_FW_PORT_CAP32_SPEED);
+	caps |= G_FW_PORT_CAP32_SPEED(lc->acaps);
+
+	*new_caps = caps;
+}
+
+int t4_set_link_speed(struct port_info *pi, u32 speed, u32 *new_caps)
+{
+	u32 fw_speed_cap = t4_speed_to_fwcap(speed);
+	struct link_config *lc = &pi->link_cfg;
+	u32 caps = *new_caps;
+
+	if (!(lc->pcaps & fw_speed_cap))
+		return -EOPNOTSUPP;
+
+	caps &= ~V_FW_PORT_CAP32_SPEED(M_FW_PORT_CAP32_SPEED);
+	caps |= fw_speed_cap;
+
+	*new_caps = caps;
+
+	return 0;
+}
+
+int t4_set_link_pause(struct port_info *pi, u8 autoneg, u8 pause_tx,
+		      u8 pause_rx, u32 *new_caps)
+{
+	struct link_config *lc = &pi->link_cfg;
+	u32 caps = *new_caps;
+	u32 max_speed;
+
+	max_speed = t4_fwcap_to_speed(lc->link_caps);
+
+	if (autoneg) {
+		if (!(lc->pcaps & FW_PORT_CAP32_ANEG))
+			return -EINVAL;
+
+		caps |= FW_PORT_CAP32_ANEG;
+		t4_set_link_autoneg_speed(pi, &caps);
+	} else {
+		if (!max_speed)
+			max_speed = t4_fwcap_to_speed(lc->acaps);
+
+		caps &= ~FW_PORT_CAP32_ANEG;
+		t4_set_link_speed(pi, max_speed, &caps);
+	}
+
+	if (lc->pcaps & FW_PORT_CAP32_MDIAUTO)
+		caps |= V_FW_PORT_CAP32_MDI(FW_PORT_CAP32_MDI_AUTO);
+
+	caps &= ~V_FW_PORT_CAP32_FC(M_FW_PORT_CAP32_FC);
+	caps &= ~V_FW_PORT_CAP32_802_3(M_FW_PORT_CAP32_802_3);
+	if (pause_tx && pause_rx) {
+		caps |= FW_PORT_CAP32_FC_TX | FW_PORT_CAP32_FC_RX;
+		if (lc->pcaps & FW_PORT_CAP32_802_3_PAUSE)
+			caps |= FW_PORT_CAP32_802_3_PAUSE;
+	} else if (pause_tx) {
+		caps |= FW_PORT_CAP32_FC_TX;
+		if (lc->pcaps & FW_PORT_CAP32_802_3_ASM_DIR)
+			caps |= FW_PORT_CAP32_802_3_ASM_DIR;
+	} else if (pause_rx) {
+		caps |= FW_PORT_CAP32_FC_RX;
+		if (lc->pcaps & FW_PORT_CAP32_802_3_PAUSE)
+			caps |= FW_PORT_CAP32_802_3_PAUSE;
+
+		if (lc->pcaps & FW_PORT_CAP32_802_3_ASM_DIR)
+			caps |= FW_PORT_CAP32_802_3_ASM_DIR;
+	}
+
+	*new_caps = caps;
+
+	return 0;
+}
+
 /**
  * t4_handle_get_port_info - process a FW reply message
  * @pi: the port info
@@ -4459,10 +4486,10 @@ static void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
 {
 	const struct fw_port_cmd *cmd = (const void *)rpl;
 	u8 link_ok, link_down_rc, mod_type, port_type;
-	u32 action, pcaps, acaps, linkattr, lstatus;
+	u32 action, pcaps, acaps, link_caps, lstatus;
 	struct link_config *lc = &pi->link_cfg;
 	struct adapter *adapter = pi->adapter;
-	unsigned int speed, fc, fec;
+	u8 mod_changed = 0;
 
 	/* Extract the various fields from the Port Information message.
 	 */
@@ -4481,21 +4508,16 @@ static void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
 
 	pcaps = be32_to_cpu(cmd->u.info32.pcaps32);
 	acaps = be32_to_cpu(cmd->u.info32.acaps32);
-	linkattr = be32_to_cpu(cmd->u.info32.linkattr32);
-
-	fec = fwcap_to_cc_fec(acaps);
-
-	fc = fwcap_to_cc_pause(linkattr);
-	speed = fwcap_to_speed(linkattr);
+	link_caps = be32_to_cpu(cmd->u.info32.linkattr32);
 
-	if (mod_type != pi->mod_type) {
-		lc->auto_fec = fec;
-		pi->port_type = port_type;
-		pi->mod_type = mod_type;
+	if (mod_type != lc->mod_type) {
+		t4_init_link_config(pi, pcaps, acaps, lc->mdio_addr,
+				    port_type, mod_type);
 		t4_os_portmod_changed(adapter, pi->pidx);
+		mod_changed = 1;
 	}
-	if (link_ok != lc->link_ok || speed != lc->speed ||
-	    fc != lc->fc || fec != lc->fec) { /* something changed */
+	if (link_ok != lc->link_ok || acaps != lc->acaps ||
+	    link_caps != lc->link_caps) { /* something changed */
 		if (!link_ok && lc->link_ok) {
 			lc->link_down_rc = link_down_rc;
 			dev_warn(adap, "Port %d link down, reason: %s\n",
@@ -4503,23 +4525,19 @@ static void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
 				 t4_link_down_rc_str(link_down_rc));
 		}
 		lc->link_ok = link_ok;
-		lc->speed = speed;
-		lc->fc = fc;
-		lc->fec = fec;
-		lc->pcaps = pcaps;
-		lc->acaps = acaps & ADVERT_MASK;
-
-		if (lc->acaps & FW_PORT_CAP32_ANEG) {
-			lc->autoneg = AUTONEG_ENABLE;
-		} else {
-			/* When Autoneg is disabled, user needs to set
-			 * single speed.
-			 * Similar to cxgb4_ethtool.c: set_link_ksettings
-			 */
-			lc->acaps = 0;
-			lc->requested_speed = fwcap_to_speed(acaps);
-			lc->autoneg = AUTONEG_DISABLE;
-		}
+		lc->acaps = acaps;
+		lc->link_caps = link_caps;
+	}
+
+	if (mod_changed) {
+		u32 mod_caps = lc->admin_caps;
+		int ret;
+
+		ret = t4_link_l1cfg_ns(pi, mod_caps);
+		if (ret != FW_SUCCESS)
+			dev_warn(adapter,
+				 "Attempt to update new Transceiver Module settings %#x failed with error: %d\n",
+				 mod_caps, ret);
 	}
 }
 
@@ -4595,45 +4613,49 @@ void t4_reset_link_config(struct adapter *adap, int idx)
 	struct link_config *lc = &pi->link_cfg;
 
 	lc->link_ok = 0;
-	lc->requested_speed = 0;
-	lc->requested_fc = 0;
-	lc->speed = 0;
-	lc->fc = 0;
+	lc->link_down_rc = 0;
+	lc->link_caps = 0;
 }
 
 /**
- * init_link_config - initialize a link's SW state
- * @lc: structure holding the link state
+ * t4_init_link_config - initialize a link's SW state
+ * @pi: the port info
  * @pcaps: link Port Capabilities
  * @acaps: link current Advertised Port Capabilities
+ * @mdio_addr : address of the PHY
+ * @port_type : firmware port type
+ * @mod_type  : firmware module type
  *
  * Initializes the SW state maintained for each link, including the link's
  * capabilities and default speed/flow-control/autonegotiation settings.
  */
-void init_link_config(struct link_config *lc, fw_port_cap32_t pcaps,
-		      fw_port_cap32_t acaps)
+void t4_init_link_config(struct port_info *pi, u32 pcaps, u32 acaps,
+			 u8 mdio_addr, u8 port_type, u8 mod_type)
 {
+	struct link_config *lc = &pi->link_cfg;
+
 	lc->pcaps = pcaps;
-	lc->requested_speed = 0;
-	lc->speed = 0;
-	lc->requested_fc = 0;
-	lc->fc = 0;
+	lc->acaps = acaps;
+	lc->admin_caps = acaps;
+	lc->link_caps = 0;
 
-	/**
-	 * For Forward Error Control, we default to whatever the Firmware
-	 * tells us the Link is currently advertising.
-	 */
-	lc->auto_fec = fwcap_to_cc_fec(acaps);
-	lc->requested_fec = FEC_AUTO;
-	lc->fec = lc->auto_fec;
-
-	if (lc->pcaps & FW_PORT_CAP32_ANEG) {
-		lc->acaps = lc->pcaps & ADVERT_MASK;
-		lc->autoneg = AUTONEG_ENABLE;
-		lc->requested_fc |= PAUSE_AUTONEG;
-	} else {
-		lc->acaps = 0;
-		lc->autoneg = AUTONEG_DISABLE;
+	lc->mdio_addr = mdio_addr;
+	lc->port_type = port_type;
+	lc->mod_type = mod_type;
+
+	lc->link_ok = 0;
+	lc->link_down_rc = 0;
+
+	/* Turn Tx and Rx pause off by default */
+	lc->admin_caps &= ~V_FW_PORT_CAP32_FC(M_FW_PORT_CAP32_FC);
+	lc->admin_caps &= ~V_FW_PORT_CAP32_802_3(M_FW_PORT_CAP32_802_3);
+	if (lc->pcaps & FW_PORT_CAP32_FORCE_PAUSE)
+		lc->admin_caps &= ~FW_PORT_CAP32_FORCE_PAUSE;
+
+	/* Reset MDI to AUTO */
+	if (lc->pcaps & FW_PORT_CAP32_MDIAUTO) {
+		lc->admin_caps &= ~V_FW_PORT_CAP32_MDI(M_FW_PORT_CAP32_MDI);
+		lc->admin_caps |= V_FW_PORT_CAP32_MDI(FW_PORT_CAP32_MDI_AUTO);
 	}
 }
 
@@ -5271,12 +5293,11 @@ int t4_init_rss_mode(struct adapter *adap, int mbox)
 
 int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
 {
-	fw_port_cap32_t pcaps, acaps;
+	u32 param, val, pcaps, acaps;
 	enum fw_port_type port_type;
 	struct fw_port_cmd cmd;
 	u8 vivld = 0, vin = 0;
 	int ret, i, j = 0;
-	u32 param, val;
 	int mdio_addr;
 	u8 addr[6];
 
@@ -5342,11 +5363,8 @@ int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
 			pi->vin =  G_FW_VIID_VIN(pi->viid);
 		}
 
-		pi->port_type = port_type;
-		pi->mdio_addr = mdio_addr;
-		pi->mod_type = FW_PORT_MOD_TYPE_NA;
-
-		init_link_config(&pi->link_cfg, pcaps, acaps);
+		t4_init_link_config(pi, pcaps, acaps, mdio_addr, port_type,
+				    FW_PORT_MOD_TYPE_NA);
 		j++;
 	}
 	return 0;
diff --git a/drivers/net/cxgbe/base/t4fw_interface.h b/drivers/net/cxgbe/base/t4fw_interface.h
index 153141247..cfd03cf34 100644
--- a/drivers/net/cxgbe/base/t4fw_interface.h
+++ b/drivers/net/cxgbe/base/t4fw_interface.h
@@ -1615,6 +1615,7 @@ struct fw_vi_stats_cmd {
 #define FW_PORT_CAP32_MDIAUTO           0x00400000UL
 #define FW_PORT_CAP32_FEC_RS            0x00800000UL
 #define FW_PORT_CAP32_FEC_BASER_RS      0x01000000UL
+#define FW_PORT_CAP32_FORCE_PAUSE       0x10000000UL
 
 #define S_FW_PORT_CAP32_SPEED           0
 #define M_FW_PORT_CAP32_SPEED           0xfff
@@ -1622,8 +1623,16 @@ struct fw_vi_stats_cmd {
 #define G_FW_PORT_CAP32_SPEED(x) \
 	(((x) >> S_FW_PORT_CAP32_SPEED) & M_FW_PORT_CAP32_SPEED)
 
+#define S_FW_PORT_CAP32_FC             16
+#define M_FW_PORT_CAP32_FC             0x3
+#define V_FW_PORT_CAP32_FC(x)          ((x) << S_FW_PORT_CAP32_FC)
+
+#define S_FW_PORT_CAP32_802_3          18
+#define M_FW_PORT_CAP32_802_3          0x3
+#define V_FW_PORT_CAP32_802_3(x)       ((x) << S_FW_PORT_CAP32_802_3)
+
 enum fw_port_mdi32 {
-	FW_PORT_CAP32_MDI_AUTO,
+	FW_PORT_CAP32_MDI_AUTO = 1,
 };
 
 #define S_FW_PORT_CAP32_MDI 21
diff --git a/drivers/net/cxgbe/base/t4vf_hw.c b/drivers/net/cxgbe/base/t4vf_hw.c
index 6454029aa..cd011bc1b 100644
--- a/drivers/net/cxgbe/base/t4vf_hw.c
+++ b/drivers/net/cxgbe/base/t4vf_hw.c
@@ -768,9 +768,8 @@ int t4vf_port_init(struct adapter *adapter)
 {
 	struct fw_port_cmd port_cmd, port_rpl, rpl;
 	struct fw_vi_cmd vi_cmd, vi_rpl;
-	fw_port_cap32_t pcaps, acaps;
+	u32 param, val, pcaps, acaps;
 	enum fw_port_type port_type;
-	u32 param, val;
 	int mdio_addr;
 	int ret, i;
 
@@ -844,10 +843,8 @@ int t4vf_port_init(struct adapter *adapter)
 		pcaps = be32_to_cpu(port_rpl.u.info32.pcaps32);
 		acaps = be32_to_cpu(port_rpl.u.info32.acaps32);
 
-		p->port_type = port_type;
-		p->mdio_addr = mdio_addr;
-		p->mod_type = FW_PORT_MOD_TYPE_NA;
-		init_link_config(&p->link_cfg, pcaps, acaps);
+		t4_init_link_config(p, pcaps, acaps, mdio_addr, port_type,
+				    FW_PORT_MOD_TYPE_NA);
 	}
 	return 0;
 }
diff --git a/drivers/net/cxgbe/cxgbe_ethdev.c b/drivers/net/cxgbe/cxgbe_ethdev.c
index 98d0362fa..c58e63918 100644
--- a/drivers/net/cxgbe/cxgbe_ethdev.c
+++ b/drivers/net/cxgbe/cxgbe_ethdev.c
@@ -193,11 +193,12 @@ int cxgbe_dev_link_update(struct rte_eth_dev *eth_dev,
 			  int wait_to_complete)
 {
 	struct port_info *pi = eth_dev->data->dev_private;
+	unsigned int i, work_done, budget = 32;
+	struct link_config *lc = &pi->link_cfg;
 	struct adapter *adapter = pi->adapter;
-	struct sge *s = &adapter->sge;
 	struct rte_eth_link new_link = { 0 };
-	unsigned int i, work_done, budget = 32;
 	u8 old_link = pi->link_cfg.link_ok;
+	struct sge *s = &adapter->sge;
 
 	for (i = 0; i < CXGBE_LINK_STATUS_POLL_CNT; i++) {
 		if (!s->fw_evtq.desc)
@@ -218,9 +219,9 @@ int cxgbe_dev_link_update(struct rte_eth_dev *eth_dev,
 
 	new_link.link_status = cxgbe_force_linkup(adapter) ?
 			       ETH_LINK_UP : pi->link_cfg.link_ok;
-	new_link.link_autoneg = pi->link_cfg.autoneg;
+	new_link.link_autoneg = (lc->link_caps & FW_PORT_CAP32_ANEG) ? 1 : 0;
 	new_link.link_duplex = ETH_LINK_FULL_DUPLEX;
-	new_link.link_speed = pi->link_cfg.speed;
+	new_link.link_speed = t4_fwcap_to_speed(lc->link_caps);
 
 	return rte_eth_linkstatus_set(eth_dev, &new_link);
 }
@@ -787,11 +788,17 @@ static int cxgbe_flow_ctrl_get(struct rte_eth_dev *eth_dev,
 {
 	struct port_info *pi = eth_dev->data->dev_private;
 	struct link_config *lc = &pi->link_cfg;
-	int rx_pause, tx_pause;
+	u8 rx_pause = 0, tx_pause = 0;
+	u32 caps = lc->link_caps;
 
-	fc_conf->autoneg = lc->fc & PAUSE_AUTONEG;
-	rx_pause = lc->fc & PAUSE_RX;
-	tx_pause = lc->fc & PAUSE_TX;
+	if (caps & FW_PORT_CAP32_ANEG)
+		fc_conf->autoneg = 1;
+
+	if (caps & FW_PORT_CAP32_FC_TX)
+		tx_pause = 1;
+
+	if (caps & FW_PORT_CAP32_FC_RX)
+		rx_pause = 1;
 
 	if (rx_pause && tx_pause)
 		fc_conf->mode = RTE_FC_FULL;
@@ -808,30 +815,39 @@ static int cxgbe_flow_ctrl_set(struct rte_eth_dev *eth_dev,
 			       struct rte_eth_fc_conf *fc_conf)
 {
 	struct port_info *pi = eth_dev->data->dev_private;
-	struct adapter *adapter = pi->adapter;
 	struct link_config *lc = &pi->link_cfg;
+	u32 new_caps = lc->admin_caps;
+	u8 tx_pause = 0, rx_pause = 0;
+	int ret;
 
-	if (lc->pcaps & FW_PORT_CAP32_ANEG) {
-		if (fc_conf->autoneg)
-			lc->requested_fc |= PAUSE_AUTONEG;
-		else
-			lc->requested_fc &= ~PAUSE_AUTONEG;
+	if (fc_conf->mode == RTE_FC_FULL) {
+		tx_pause = 1;
+		rx_pause = 1;
+	} else if (fc_conf->mode == RTE_FC_TX_PAUSE) {
+		tx_pause = 1;
+	} else if (fc_conf->mode == RTE_FC_RX_PAUSE) {
+		rx_pause = 1;
 	}
 
-	if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
-	    (fc_conf->mode & RTE_FC_RX_PAUSE))
-		lc->requested_fc |= PAUSE_RX;
-	else
-		lc->requested_fc &= ~PAUSE_RX;
+	ret = t4_set_link_pause(pi, fc_conf->autoneg, tx_pause,
+				rx_pause, &new_caps);
+	if (ret != 0)
+		return ret;
 
-	if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
-	    (fc_conf->mode & RTE_FC_TX_PAUSE))
-		lc->requested_fc |= PAUSE_TX;
-	else
-		lc->requested_fc &= ~PAUSE_TX;
+	if (!fc_conf->autoneg) {
+		if (lc->pcaps & FW_PORT_CAP32_FORCE_PAUSE)
+			new_caps |= FW_PORT_CAP32_FORCE_PAUSE;
+	} else {
+		new_caps &= ~FW_PORT_CAP32_FORCE_PAUSE;
+	}
+
+	if (new_caps != lc->admin_caps) {
+		ret = t4_link_l1cfg(pi, new_caps);
+		if (ret == 0)
+			lc->admin_caps = new_caps;
+	}
 
-	return t4_link_l1cfg(adapter, adapter->mbox, pi->tx_chan,
-			     &pi->link_cfg);
+	return ret;
 }
 
 const uint32_t *
diff --git a/drivers/net/cxgbe/cxgbe_main.c b/drivers/net/cxgbe/cxgbe_main.c
index 53b08a64a..3b56eccfb 100644
--- a/drivers/net/cxgbe/cxgbe_main.c
+++ b/drivers/net/cxgbe/cxgbe_main.c
@@ -732,7 +732,7 @@ void cxgbe_print_port_info(struct adapter *adap)
 			--bufp;
 		sprintf(bufp, "BASE-%s",
 			t4_get_port_type_description(
-					(enum fw_port_type)pi->port_type));
+				(enum fw_port_type)pi->link_cfg.port_type));
 
 		dev_info(adap,
 			 " " PCI_PRI_FMT " Chelsio rev %d %s %s\n",
@@ -1575,23 +1575,23 @@ void t4_os_portmod_changed(const struct adapter *adap, int port_id)
 
 	const struct port_info *pi = adap2pinfo(adap, port_id);
 
-	if (pi->mod_type == FW_PORT_MOD_TYPE_NONE)
+	if (pi->link_cfg.mod_type == FW_PORT_MOD_TYPE_NONE)
 		dev_info(adap, "Port%d: port module unplugged\n", pi->port_id);
-	else if (pi->mod_type < ARRAY_SIZE(mod_str))
+	else if (pi->link_cfg.mod_type < ARRAY_SIZE(mod_str))
 		dev_info(adap, "Port%d: %s port module inserted\n", pi->port_id,
-			 mod_str[pi->mod_type]);
-	else if (pi->mod_type == FW_PORT_MOD_TYPE_NOTSUPPORTED)
+			 mod_str[pi->link_cfg.mod_type]);
+	else if (pi->link_cfg.mod_type == FW_PORT_MOD_TYPE_NOTSUPPORTED)
 		dev_info(adap, "Port%d: unsupported port module inserted\n",
 			 pi->port_id);
-	else if (pi->mod_type == FW_PORT_MOD_TYPE_UNKNOWN)
+	else if (pi->link_cfg.mod_type == FW_PORT_MOD_TYPE_UNKNOWN)
 		dev_info(adap, "Port%d: unknown port module inserted\n",
 			 pi->port_id);
-	else if (pi->mod_type == FW_PORT_MOD_TYPE_ERROR)
+	else if (pi->link_cfg.mod_type == FW_PORT_MOD_TYPE_ERROR)
 		dev_info(adap, "Port%d: transceiver module error\n",
 			 pi->port_id);
 	else
 		dev_info(adap, "Port%d: unknown module type %d inserted\n",
-			 pi->port_id, pi->mod_type);
+			 pi->port_id, pi->link_cfg.mod_type);
 }
 
 bool cxgbe_force_linkup(struct adapter *adap)
@@ -1636,8 +1636,7 @@ int cxgbe_link_start(struct port_info *pi)
 		}
 	}
 	if (ret == 0 && is_pf4(adapter))
-		ret = t4_link_l1cfg(adapter, adapter->mbox, pi->tx_chan,
-				    &pi->link_cfg);
+		ret = t4_link_l1cfg(pi, pi->link_cfg.admin_caps);
 	if (ret == 0) {
 		/*
 		 * Enabling a Virtual Interface can result in an interrupt
@@ -1905,7 +1904,7 @@ void cxgbe_get_speed_caps(struct port_info *pi, u32 *speed_caps)
 {
 	*speed_caps = 0;
 
-	fw_caps_to_speed_caps(pi->port_type, pi->link_cfg.pcaps,
+	fw_caps_to_speed_caps(pi->link_cfg.port_type, pi->link_cfg.pcaps,
 			      speed_caps);
 
 	if (!(pi->link_cfg.pcaps & FW_PORT_CAP32_ANEG))
-- 
2.24.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [dpdk-dev] [PATCH 3/3] net/cxgbe: implement ethdev ops to configure link FEC
  2020-12-20 22:47 [dpdk-dev] [PATCH 0/3] net/cxgbe: rework link config and add FEC support Rahul Lakkireddy
  2020-12-20 22:47 ` [dpdk-dev] [PATCH 1/3] net/cxgbe: remove legacy 16-bit link capabilities Rahul Lakkireddy
  2020-12-20 22:47 ` [dpdk-dev] [PATCH 2/3] net/cxgbe: rework and simplify link handling code Rahul Lakkireddy
@ 2020-12-20 22:47 ` Rahul Lakkireddy
  2021-01-15 15:02 ` [dpdk-dev] [PATCH 0/3] net/cxgbe: rework link config and add FEC support Ferruh Yigit
  3 siblings, 0 replies; 5+ messages in thread
From: Rahul Lakkireddy @ 2020-12-20 22:47 UTC (permalink / raw)
  To: dev; +Cc: kaara.satwik

From: Karra Satwik <kaara.satwik@chelsio.com>

Add ethdev ops to query and configure link FEC.

Signed-off-by: Karra Satwik <kaara.satwik@chelsio.com>
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
---
 drivers/net/cxgbe/base/common.h         |   2 +
 drivers/net/cxgbe/base/t4_hw.c          |  79 ++++++++++++++
 drivers/net/cxgbe/base/t4fw_interface.h |   6 ++
 drivers/net/cxgbe/cxgbe_ethdev.c        | 133 ++++++++++++++++++++++++
 4 files changed, 220 insertions(+)

diff --git a/drivers/net/cxgbe/base/common.h b/drivers/net/cxgbe/base/common.h
index a244df7a0..202a2f4ba 100644
--- a/drivers/net/cxgbe/base/common.h
+++ b/drivers/net/cxgbe/base/common.h
@@ -331,6 +331,8 @@ static inline int t4_link_l1cfg_ns(struct port_info *pi, u32 caps)
 int t4_set_link_speed(struct port_info *pi, u32 speed, u32 *new_caps);
 int t4_set_link_pause(struct port_info *pi, u8 autoneg, u8 pause_tx,
 		      u8 pause_rx, u32 *new_caps);
+int t4_set_link_fec(struct port_info *pi, u8 fec_rs, u8 fec_baser,
+		    u8 fec_none, u32 *new_caps);
 unsigned int t4_fwcap_to_speed(u32 caps);
 void t4_load_mtus(struct adapter *adap, const unsigned short *mtus,
 		  const unsigned short *alpha, const unsigned short *beta);
diff --git a/drivers/net/cxgbe/base/t4_hw.c b/drivers/net/cxgbe/base/t4_hw.c
index 3c0990cb3..e87823f8f 100644
--- a/drivers/net/cxgbe/base/t4_hw.c
+++ b/drivers/net/cxgbe/base/t4_hw.c
@@ -4475,6 +4475,76 @@ int t4_set_link_pause(struct port_info *pi, u8 autoneg, u8 pause_tx,
 	return 0;
 }
 
+int t4_set_link_fec(struct port_info *pi, u8 fec_rs, u8 fec_baser,
+		    u8 fec_none, u32 *new_caps)
+{
+	struct link_config *lc = &pi->link_cfg;
+	u32 max_speed, caps = *new_caps;
+
+	if (!(lc->pcaps & V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC)))
+		return -EOPNOTSUPP;
+
+	/* Link might be down. In that case consider the max
+	 * speed advertised
+	 */
+	max_speed = t4_fwcap_to_speed(lc->link_caps);
+	if (!max_speed)
+		max_speed = t4_fwcap_to_speed(lc->acaps);
+
+	caps &= ~V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC);
+	if (fec_rs) {
+		switch (max_speed) {
+		case 100000:
+		case 25000:
+			caps |= FW_PORT_CAP32_FEC_RS;
+			break;
+		default:
+			return -EOPNOTSUPP;
+		}
+	}
+
+	if (fec_baser) {
+		switch (max_speed) {
+		case 50000:
+		case 25000:
+			caps |= FW_PORT_CAP32_FEC_BASER_RS;
+			break;
+		default:
+			return -EOPNOTSUPP;
+		}
+	}
+
+	if (fec_none)
+		caps |= FW_PORT_CAP32_FEC_NO_FEC;
+
+	if (!(caps & V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC))) {
+		/* No explicit encoding is requested.
+		 * So, default back to AUTO.
+		 */
+		switch (max_speed) {
+		case 100000:
+			caps |= FW_PORT_CAP32_FEC_RS |
+				FW_PORT_CAP32_FEC_NO_FEC;
+			break;
+		case 50000:
+			caps |= FW_PORT_CAP32_FEC_BASER_RS |
+				FW_PORT_CAP32_FEC_NO_FEC;
+			break;
+		case 25000:
+			caps |= FW_PORT_CAP32_FEC_RS |
+				FW_PORT_CAP32_FEC_BASER_RS |
+				FW_PORT_CAP32_FEC_NO_FEC;
+			break;
+		default:
+			return -EOPNOTSUPP;
+		}
+	}
+
+	*new_caps = caps;
+
+	return 0;
+}
+
 /**
  * t4_handle_get_port_info - process a FW reply message
  * @pi: the port info
@@ -4652,6 +4722,15 @@ void t4_init_link_config(struct port_info *pi, u32 pcaps, u32 acaps,
 	if (lc->pcaps & FW_PORT_CAP32_FORCE_PAUSE)
 		lc->admin_caps &= ~FW_PORT_CAP32_FORCE_PAUSE;
 
+	/* Reset FEC caps to default values */
+	if (lc->pcaps & V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC)) {
+		lc->admin_caps &= ~V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC);
+		t4_set_link_fec(pi, 0, 0, 0, &lc->admin_caps);
+	}
+
+	if (lc->pcaps & FW_PORT_CAP32_FORCE_FEC)
+		lc->admin_caps &= ~FW_PORT_CAP32_FORCE_FEC;
+
 	/* Reset MDI to AUTO */
 	if (lc->pcaps & FW_PORT_CAP32_MDIAUTO) {
 		lc->admin_caps &= ~V_FW_PORT_CAP32_MDI(M_FW_PORT_CAP32_MDI);
diff --git a/drivers/net/cxgbe/base/t4fw_interface.h b/drivers/net/cxgbe/base/t4fw_interface.h
index cfd03cf34..240e0ee49 100644
--- a/drivers/net/cxgbe/base/t4fw_interface.h
+++ b/drivers/net/cxgbe/base/t4fw_interface.h
@@ -1615,7 +1615,9 @@ struct fw_vi_stats_cmd {
 #define FW_PORT_CAP32_MDIAUTO           0x00400000UL
 #define FW_PORT_CAP32_FEC_RS            0x00800000UL
 #define FW_PORT_CAP32_FEC_BASER_RS      0x01000000UL
+#define FW_PORT_CAP32_FEC_NO_FEC        0x02000000UL
 #define FW_PORT_CAP32_FORCE_PAUSE       0x10000000UL
+#define FW_PORT_CAP32_FORCE_FEC         0x20000000UL
 
 #define S_FW_PORT_CAP32_SPEED           0
 #define M_FW_PORT_CAP32_SPEED           0xfff
@@ -1641,6 +1643,10 @@ enum fw_port_mdi32 {
 #define G_FW_PORT_CAP32_MDI(x) \
 	(((x) >> S_FW_PORT_CAP32_MDI) & M_FW_PORT_CAP32_MDI)
 
+#define S_FW_PORT_CAP32_FEC     23
+#define M_FW_PORT_CAP32_FEC     0x1f
+#define V_FW_PORT_CAP32_FEC(x)  ((x) << S_FW_PORT_CAP32_FEC)
+
 enum fw_port_action {
 	FW_PORT_ACTION_L1_CFG32         = 0x0009,
 	FW_PORT_ACTION_GET_PORT_INFO32  = 0x000a,
diff --git a/drivers/net/cxgbe/cxgbe_ethdev.c b/drivers/net/cxgbe/cxgbe_ethdev.c
index c58e63918..6f481551d 100644
--- a/drivers/net/cxgbe/cxgbe_ethdev.c
+++ b/drivers/net/cxgbe/cxgbe_ethdev.c
@@ -1193,6 +1193,136 @@ int cxgbe_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *addr)
 	return 0;
 }
 
+static int cxgbe_fec_get_capa_speed_to_fec(struct link_config *lc,
+					   struct rte_eth_fec_capa *capa_arr)
+{
+	int num = 0;
+
+	if (lc->pcaps & FW_PORT_CAP32_SPEED_100G) {
+		if (capa_arr) {
+			capa_arr[num].speed = ETH_SPEED_NUM_100G;
+			capa_arr[num].capa = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+					     RTE_ETH_FEC_MODE_CAPA_MASK(RS);
+		}
+		num++;
+	}
+
+	if (lc->pcaps & FW_PORT_CAP32_SPEED_50G) {
+		if (capa_arr) {
+			capa_arr[num].speed = ETH_SPEED_NUM_50G;
+			capa_arr[num].capa = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+					     RTE_ETH_FEC_MODE_CAPA_MASK(BASER);
+		}
+		num++;
+	}
+
+	if (lc->pcaps & FW_PORT_CAP32_SPEED_25G) {
+		if (capa_arr) {
+			capa_arr[num].speed = ETH_SPEED_NUM_25G;
+			capa_arr[num].capa = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+					     RTE_ETH_FEC_MODE_CAPA_MASK(BASER) |
+					     RTE_ETH_FEC_MODE_CAPA_MASK(RS);
+		}
+		num++;
+	}
+
+	return num;
+}
+
+static int cxgbe_fec_get_capability(struct rte_eth_dev *dev,
+				    struct rte_eth_fec_capa *speed_fec_capa,
+				    unsigned int num)
+{
+	struct port_info *pi = dev->data->dev_private;
+	struct link_config *lc = &pi->link_cfg;
+	u8 num_entries;
+
+	if (!(lc->pcaps & V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC)))
+		return -EOPNOTSUPP;
+
+	num_entries = cxgbe_fec_get_capa_speed_to_fec(lc, NULL);
+	if (!speed_fec_capa || num < num_entries)
+		return num_entries;
+
+	return cxgbe_fec_get_capa_speed_to_fec(lc, speed_fec_capa);
+}
+
+static int cxgbe_fec_get(struct rte_eth_dev *dev, uint32_t *fec_capa)
+{
+	struct port_info *pi = dev->data->dev_private;
+	struct link_config *lc = &pi->link_cfg;
+	u32 fec_caps = 0, caps = lc->link_caps;
+
+	if (!(lc->pcaps & V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC)))
+		return -EOPNOTSUPP;
+
+	if (caps & FW_PORT_CAP32_FEC_NO_FEC) {
+		fec_caps = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
+		goto out;
+	}
+
+	if (caps & FW_PORT_CAP32_FEC_BASER_RS) {
+		fec_caps = RTE_ETH_FEC_MODE_CAPA_MASK(BASER);
+		goto out;
+	}
+
+	if (caps & FW_PORT_CAP32_FEC_RS) {
+		fec_caps = RTE_ETH_FEC_MODE_CAPA_MASK(RS);
+		goto out;
+	}
+
+	fec_caps = RTE_ETH_FEC_MODE_CAPA_MASK(AUTO);
+
+out:
+	*fec_capa = fec_caps;
+	return 0;
+}
+
+static int cxgbe_fec_set(struct rte_eth_dev *dev, uint32_t fec_capa)
+{
+	struct port_info *pi = dev->data->dev_private;
+	u8 fec_rs = 0, fec_baser = 0, fec_none = 0;
+	struct link_config *lc = &pi->link_cfg;
+	u32 new_caps = lc->admin_caps;
+	int ret;
+
+	if (!(lc->pcaps & V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC)))
+		return -EOPNOTSUPP;
+
+	if (!fec_capa)
+		return -EINVAL;
+
+	if (fec_capa & RTE_ETH_FEC_MODE_CAPA_MASK(AUTO))
+		goto set_fec;
+
+	if (fec_capa & RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC))
+		fec_none = 1;
+
+	if (fec_capa & RTE_ETH_FEC_MODE_CAPA_MASK(BASER))
+		fec_baser = 1;
+
+	if (fec_capa & RTE_ETH_FEC_MODE_CAPA_MASK(RS))
+		fec_rs = 1;
+
+set_fec:
+	ret = t4_set_link_fec(pi, fec_rs, fec_baser, fec_none, &new_caps);
+	if (ret != 0)
+		return ret;
+
+	if (lc->pcaps & FW_PORT_CAP32_FORCE_FEC)
+		new_caps |= FW_PORT_CAP32_FORCE_FEC;
+	else
+		new_caps &= ~FW_PORT_CAP32_FORCE_FEC;
+
+	if (new_caps != lc->admin_caps) {
+		ret = t4_link_l1cfg(pi, new_caps);
+		if (ret == 0)
+			lc->admin_caps = new_caps;
+	}
+
+	return ret;
+}
+
 static const struct eth_dev_ops cxgbe_eth_dev_ops = {
 	.dev_start		= cxgbe_dev_start,
 	.dev_stop		= cxgbe_dev_stop,
@@ -1230,6 +1360,9 @@ static const struct eth_dev_ops cxgbe_eth_dev_ops = {
 	.mac_addr_set		= cxgbe_mac_addr_set,
 	.reta_update            = cxgbe_dev_rss_reta_update,
 	.reta_query             = cxgbe_dev_rss_reta_query,
+	.fec_get_capability     = cxgbe_fec_get_capability,
+	.fec_get                = cxgbe_fec_get,
+	.fec_set                = cxgbe_fec_set,
 };
 
 /*
-- 
2.24.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [dpdk-dev] [PATCH 0/3] net/cxgbe: rework link config and add FEC support
  2020-12-20 22:47 [dpdk-dev] [PATCH 0/3] net/cxgbe: rework link config and add FEC support Rahul Lakkireddy
                   ` (2 preceding siblings ...)
  2020-12-20 22:47 ` [dpdk-dev] [PATCH 3/3] net/cxgbe: implement ethdev ops to configure link FEC Rahul Lakkireddy
@ 2021-01-15 15:02 ` Ferruh Yigit
  3 siblings, 0 replies; 5+ messages in thread
From: Ferruh Yigit @ 2021-01-15 15:02 UTC (permalink / raw)
  To: Rahul Lakkireddy, dev; +Cc: kaara.satwik

On 12/20/2020 10:47 PM, Rahul Lakkireddy wrote:
> This series of patches rework link handling and add support to
> configure Forward Error Correction (FEC) capability.
> 
> Patch 1 removes legacy 16-bit link capabilities infrastructure
> and always enables 32-bit link capabilities in firmware.
> 
> Patch 2 simplifies link handling in preparation for FEC support.
> 
> Patch 3 adds support to configure link FEC when supported.
> 
> Thanks,
> Rahul
> 
> Karra Satwik (3):
>    net/cxgbe: remove legacy 16-bit link capabilities
>    net/cxgbe: rework and simplify link handling code
>    net/cxgbe: implement ethdev ops to configure link FEC
> 

Series applied to dpdk-next-net/main, thanks.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-01-15 15:02 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-20 22:47 [dpdk-dev] [PATCH 0/3] net/cxgbe: rework link config and add FEC support Rahul Lakkireddy
2020-12-20 22:47 ` [dpdk-dev] [PATCH 1/3] net/cxgbe: remove legacy 16-bit link capabilities Rahul Lakkireddy
2020-12-20 22:47 ` [dpdk-dev] [PATCH 2/3] net/cxgbe: rework and simplify link handling code Rahul Lakkireddy
2020-12-20 22:47 ` [dpdk-dev] [PATCH 3/3] net/cxgbe: implement ethdev ops to configure link FEC Rahul Lakkireddy
2021-01-15 15:02 ` [dpdk-dev] [PATCH 0/3] net/cxgbe: rework link config and add FEC support Ferruh Yigit

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).