All of lore.kernel.org
 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 related	[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 related	[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 related	[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:03 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.