From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id A9009A04B7; Mon, 21 Sep 2020 08:16:47 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 164FF1C0DB; Mon, 21 Sep 2020 08:16:38 +0200 (CEST) Received: from huawei.com (szxga07-in.huawei.com [45.249.212.35]) by dpdk.org (Postfix) with ESMTP id 7EF551D93F for ; Mon, 21 Sep 2020 08:16:34 +0200 (CEST) Received: from DGGEMS405-HUB.china.huawei.com (unknown [172.30.72.60]) by Forcepoint Email with ESMTP id C82EF9E986400E489458; Mon, 21 Sep 2020 14:16:32 +0800 (CST) Received: from localhost.localdomain (10.69.192.56) by DGGEMS405-HUB.china.huawei.com (10.3.19.205) with Microsoft SMTP Server id 14.3.487.0; Mon, 21 Sep 2020 14:16:24 +0800 From: "Min Hu (Connor)" To: CC: , , , , Date: Mon, 21 Sep 2020 14:13:57 +0800 Message-ID: <1600668838-31498-3-git-send-email-humin29@huawei.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1600668838-31498-1-git-send-email-humin29@huawei.com> References: <1599534347-20430-1-git-send-email-humin29@huawei.com> <1600668838-31498-1-git-send-email-humin29@huawei.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.69.192.56] X-CFilter-Loop: Reflected Subject: [dpdk-dev] [PATCH V9 2/3] net/hns3: support 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" Forward error correction (FEC) is a bit error correction mode. It adds error correction information to data packets at the transmit end, and uses the error correction information to correct the bit errors generated during data packet transmission at the receive end. This improves signal quality but also brings a delay to signals. This function can be enabled or disabled as required. This patch adds FEC support for ethdev.Introduce ethdev operations which support query and config FEC information in hardware. Signed-off-by: Min Hu (Connor) Reviewed-by: Wei Hu (Xavier) Reviewed-by: Chengwen Feng Reviewed-by: Chengchang Tang --- v7->v8: FEC mode order defined in hns3 hardware is inconsistend with that defined in the ethdev library. So the sequence needs to be converted. --- v5->v6: fixed code styles according to DPDK coding style. added _eth prefix. --- v4->v5: Data type for fec_cap is changed from uint8_t to uint32_t for possible future expansion. --- v2->v3: adjust the return value of function. --- drivers/net/hns3/hns3_cmd.h | 19 ++++- drivers/net/hns3/hns3_ethdev.c | 183 +++++++++++++++++++++++++++++++++++++++++ drivers/net/hns3/hns3_ethdev.h | 1 + 3 files changed, 202 insertions(+), 1 deletion(-) diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h index d70f42e..8b80353 100644 --- a/drivers/net/hns3/hns3_cmd.h +++ b/drivers/net/hns3/hns3_cmd.h @@ -99,6 +99,7 @@ enum hns3_opcode_type { HNS3_OPC_CONFIG_MAX_FRM_SIZE = 0x0308, HNS3_OPC_CONFIG_SPEED_DUP = 0x0309, HNS3_MAC_COMMON_INT_EN = 0x030E, + HNS3_OPC_CONFIG_FEC_MODE = 0x031A, /* PFC/Pause commands */ HNS3_OPC_CFG_MAC_PAUSE_EN = 0x0701, @@ -653,9 +654,25 @@ struct hns3_config_auto_neg_cmd { uint8_t rsv[20]; }; +#define HNS3_MAC_CFG_FEC_AUTO_EN_B 0 +#define HNS3_MAC_CFG_FEC_MODE_S 1 +#define HNS3_MAC_CFG_FEC_MODE_M GENMASK(3, 1) +#define HNS3_MAC_FEC_OFF 0 +#define HNS3_MAC_FEC_BASER 1 +#define HNS3_MAC_FEC_RS 2 + struct hns3_sfp_speed_cmd { uint32_t sfp_speed; - uint32_t rsv[5]; + uint8_t query_type; /* 0: sfp speed, 1: active fec */ + uint8_t active_fec; /* current FEC mode */ + uint16_t rsv1; + uint32_t rsv2[4]; +}; + +/* Configure FEC mode, opcode:0x031A */ +struct hns3_config_fec_cmd { + uint8_t fec_mode; + uint8_t rsv[23]; }; #define HNS3_MAC_MGR_MASK_VLAN_B BIT(0) diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c index 81e7730..3fc2525 100644 --- a/drivers/net/hns3/hns3_ethdev.c +++ b/drivers/net/hns3/hns3_ethdev.c @@ -60,6 +60,11 @@ #define HNS3_RESET_WAIT_MS 100 #define HNS3_RESET_WAIT_CNT 200 +/* FEC mode order defined in HNS3 hardware */ +#define HNS3_HW_FEC_MODE_NOFEC 0 +#define HNS3_HW_FEC_MODE_BASER 1 +#define HNS3_HW_FEC_MODE_RS 2 + enum hns3_evt_cause { HNS3_VECTOR0_EVENT_RST, HNS3_VECTOR0_EVENT_MBX, @@ -78,6 +83,8 @@ static int hns3_add_mc_addr(struct hns3_hw *hw, struct rte_ether_addr *mac_addr); static int hns3_remove_mc_addr(struct hns3_hw *hw, struct rte_ether_addr *mac_addr); +static int hns3_restore_fec(struct hns3_hw *hw); +static int hns3_query_dev_fec_info(struct rte_eth_dev *dev); static void hns3_pf_disable_irq0(struct hns3_hw *hw) @@ -2819,6 +2826,13 @@ hns3_get_capability(struct hns3_hw *hw) device_id == HNS3_DEV_ID_200G_RDMA) hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_DCB_B, 1); + ret = hns3_query_dev_fec_info(eth_dev); + if (ret) { + PMD_INIT_LOG(ERR, + "failed to query FEC information, ret = %d", ret); + return ret; + } + /* Get PCI revision id */ ret = rte_pci_read_config(pci_dev, &revision, HNS3_PCI_REVISION_ID_LEN, HNS3_PCI_REVISION_ID); @@ -5311,6 +5325,10 @@ hns3_restore_conf(struct hns3_adapter *hns) if (ret) goto err_promisc; + ret = hns3_restore_fec(hw); + if (ret) + goto err_promisc; + if (hns->hw.adapter_state == HNS3_NIC_STARTED) { ret = hns3_do_start(hns, false); if (ret) @@ -5389,6 +5407,168 @@ hns3_reset_service(void *param) hns3_msix_process(hns, reset_level); } +static int +hns3_fec_get_capability(struct rte_eth_dev *dev, uint32_t *fec_cap) +{ + struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct hns3_mac *mac = &hw->mac; + uint32_t mode; + + switch (mac->link_speed) { + case ETH_SPEED_NUM_10G: + case ETH_SPEED_NUM_40G: + mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_BASER | + RTE_ETH_FEC_CAPA_AUTO; + break; + case ETH_SPEED_NUM_25G: + case ETH_SPEED_NUM_50G: + mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_BASER | + RTE_ETH_FEC_CAPA_RS | RTE_ETH_FEC_CAPA_AUTO; + break; + case ETH_SPEED_NUM_100G: + case ETH_SPEED_NUM_200G: + mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_RS | + RTE_ETH_FEC_CAPA_AUTO; + break; + default: + mode = 0; + break; + } + + *fec_cap = mode; + return 0; +} + +static int +hns3_fec_get(struct rte_eth_dev *dev, enum rte_eth_fec_mode *mode) +{ +#define QUERY_ACTIVE_SPEED 1 + struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct hns3_sfp_speed_cmd *resp; + enum rte_eth_fec_mode tmp_mode; + struct hns3_cmd_desc desc; + int ret; + + hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_SFP_GET_SPEED, true); + resp = (struct hns3_sfp_speed_cmd *)desc.data; + resp->query_type = QUERY_ACTIVE_SPEED; + + ret = hns3_cmd_send(hw, &desc, 1); + if (ret == -EOPNOTSUPP) { + hns3_err(hw, "IMP do not support get FEC, ret = %d", ret); + return ret; + } else if (ret) { + hns3_err(hw, "get FEC failed, ret = %d", ret); + return ret; + } + + /* + * FEC mode order defined in hns3 hardware is inconsistend with + * that defined in the ethdev library. So the sequence needs + * to be converted. + */ + switch (resp->active_fec) { + case HNS3_HW_FEC_MODE_NOFEC: + tmp_mode = RTE_ETH_FEC_NOFEC; + break; + case HNS3_HW_FEC_MODE_BASER: + tmp_mode = RTE_ETH_FEC_BASER; + break; + case HNS3_HW_FEC_MODE_RS: + tmp_mode = RTE_ETH_FEC_RS; + break; + default: + tmp_mode = RTE_ETH_FEC_NOFEC; + break; + } + + *mode = tmp_mode; + return 0; +} + +static int +hns3_set_fec_hw(struct hns3_hw *hw, enum rte_eth_fec_mode mode) +{ + struct hns3_config_fec_cmd *req; + struct hns3_cmd_desc desc; + int ret; + + hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CONFIG_FEC_MODE, false); + + req = (struct hns3_config_fec_cmd *)desc.data; + switch (mode) { + case RTE_ETH_FEC_NOFEC: + hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M, + HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_OFF); + break; + case RTE_ETH_FEC_BASER: + hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M, + HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_BASER); + break; + case RTE_ETH_FEC_RS: + hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M, + HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_RS); + break; + case RTE_ETH_FEC_AUTO: + hns3_set_bit(req->fec_mode, HNS3_MAC_CFG_FEC_AUTO_EN_B, 1); + break; + default: + return 0; + } + ret = hns3_cmd_send(hw, &desc, 1); + if (ret) + hns3_err(hw, "set fec mode failed, ret = %d", ret); + + return ret; +} + +static int +hns3_fec_set(struct rte_eth_dev *dev, enum rte_eth_fec_mode mode) +{ + struct hns3_adapter *hns = dev->data->dev_private; + struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns); + struct hns3_pf *pf = &hns->pf; + int ret; + + ret = hns3_set_fec_hw(hw, mode); + if (ret) + return ret; + + pf->fec_mode = mode; + return 0; +} + +static int +hns3_restore_fec(struct hns3_hw *hw) +{ + struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw); + struct hns3_pf *pf = &hns->pf; + enum rte_eth_fec_mode mode = pf->fec_mode; + int ret; + + ret = hns3_set_fec_hw(hw, mode); + if (ret) + hns3_err(hw, "restore fec mode(%d) failed, ret = %d", + mode, ret); + + return ret; +} + +static int +hns3_query_dev_fec_info(struct rte_eth_dev *dev) +{ + struct hns3_adapter *hns = dev->data->dev_private; + struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns); + struct hns3_pf *pf = &hns->pf; + int ret; + + ret = hns3_fec_get(dev, &pf->fec_mode); + if (ret) + hns3_err(hw, "query device FEC info failed, ret = %d", ret); + + return ret; +} + static const struct eth_dev_ops hns3_eth_dev_ops = { .dev_start = hns3_dev_start, .dev_stop = hns3_dev_stop, @@ -5434,6 +5614,9 @@ static const struct eth_dev_ops hns3_eth_dev_ops = { .get_reg = hns3_get_regs, .get_dcb_info = hns3_get_dcb_info, .dev_supported_ptypes_get = hns3_dev_supported_ptypes_get, + .fec_get_capability = hns3_fec_get_capability, + .fec_get = hns3_fec_get, + .fec_set = hns3_fec_set, }; static const struct hns3_reset_ops hns3_reset_ops = { diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h index 0e665e5..2435668 100644 --- a/drivers/net/hns3/hns3_ethdev.h +++ b/drivers/net/hns3/hns3_ethdev.h @@ -510,6 +510,7 @@ struct hns3_pf { struct hns3_err_msix_intr_stats abn_int_stats; bool support_sfp_query; + enum rte_eth_fec_mode fec_mode; /* current FEC mode for ethdev */ struct hns3_vtag_cfg vtag_config; LIST_HEAD(vlan_tbl, hns3_user_vlan_table) vlan_list; -- 2.7.4