From patchwork Sun Dec 20 22:47:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rahul Lakkireddy X-Patchwork-Id: 85571 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 8CE17A09FD; Mon, 21 Dec 2020 00:05:00 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 7F58BCC33; Mon, 21 Dec 2020 00:04:14 +0100 (CET) Received: from stargate.chelsio.com (stargate.chelsio.com [12.32.117.8]) by dpdk.org (Postfix) with ESMTP id 570C9CC33 for ; Mon, 21 Dec 2020 00:04:13 +0100 (CET) Received: from localhost (scalar.blr.asicdesigners.com [10.193.185.94]) by stargate.chelsio.com (8.13.8/8.13.8) with ESMTP id 0BKN49EO011892; Sun, 20 Dec 2020 15:04:09 -0800 From: Rahul Lakkireddy To: dev@dpdk.org Cc: kaara.satwik@chelsio.com Date: Mon, 21 Dec 2020 04:17:42 +0530 Message-Id: <258c7004de1206e4d3bd4c4bca9f35ed318ebceb.1608504560.git.rahul.lakkireddy@chelsio.com> X-Mailer: git-send-email 2.5.3 In-Reply-To: References: In-Reply-To: References: Subject: [dpdk-dev] [PATCH 3/3] net/cxgbe: implement ethdev ops to configure link FEC X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Karra Satwik Add ethdev ops to query and configure link FEC. Signed-off-by: Karra Satwik Signed-off-by: Rahul Lakkireddy --- 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, }; /*