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
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, ¶m, &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, ¶m, - &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, ¶m, &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, ¶m, &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
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
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
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.