From patchwork Thu Sep 26 14:01:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Wei Hu (Xavier)" X-Patchwork-Id: 59886 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 9E2BA1BEB2; Thu, 26 Sep 2019 16:05:05 +0200 (CEST) Received: from huawei.com (szxga07-in.huawei.com [45.249.212.35]) by dpdk.org (Postfix) with ESMTP id DEABA1BE9F for ; Thu, 26 Sep 2019 16:04:55 +0200 (CEST) Received: from DGGEMS405-HUB.china.huawei.com (unknown [172.30.72.58]) by Forcepoint Email with ESMTP id 6A1BFB7C4D31FA934C91; Thu, 26 Sep 2019 22:04:53 +0800 (CST) Received: from localhost.localdomain (10.67.212.132) by DGGEMS405-HUB.china.huawei.com (10.3.19.205) with Microsoft SMTP Server id 14.3.439.0; Thu, 26 Sep 2019 22:04:44 +0800 From: "Wei Hu (Xavier)" To: CC: , , , Date: Thu, 26 Sep 2019 22:01:55 +0800 Message-ID: <1569506528-60464-10-git-send-email-xavier.huwei@huawei.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1569506528-60464-1-git-send-email-xavier.huwei@huawei.com> References: <1569506528-60464-1-git-send-email-xavier.huwei@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.67.212.132] X-CFilter-Loop: Reflected Subject: [dpdk-dev] [PATCH v3 09/22] net/hns3: add support for link_update operation 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" This patch adds link_update operation to hns3 PMD driver. Signed-off-by: Wei Hu (Xavier) Signed-off-by: Chunsong Feng Signed-off-by: Min Hu (Connor) Signed-off-by: Hao Chen Signed-off-by: Huisong Li --- v1 -> v2: Add Link status feature into hns3.ini file according to Ferruh Yigit's comments. --- doc/guides/nics/features/hns3.ini | 1 + drivers/net/hns3/hns3_ethdev.c | 162 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+) diff --git a/doc/guides/nics/features/hns3.ini b/doc/guides/nics/features/hns3.ini index 2eb78d0..caf1ef7 100644 --- a/doc/guides/nics/features/hns3.ini +++ b/doc/guides/nics/features/hns3.ini @@ -4,6 +4,7 @@ ; Refer to default.ini for the full list of available PMD features. ; [Features] +Link status = Y MTU update = Y Unicast MAC filter = Y Multicast MAC filter = Y diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c index 918a386..3c9bba4 100644 --- a/drivers/net/hns3/hns3_ethdev.c +++ b/drivers/net/hns3/hns3_ethdev.c @@ -28,6 +28,8 @@ #define HNS3_DEFAULT_PORT_CONF_BURST_SIZE 32 #define HNS3_DEFAULT_PORT_CONF_QUEUES_NUM 1 +#define HNS3_SERVICE_INTERVAL 1000000 /* us */ + int hns3_logtype_init; int hns3_logtype_driver; @@ -1050,6 +1052,40 @@ hns3_fw_version_get(struct rte_eth_dev *eth_dev, char *fw_version, } static int +hns3_dev_link_update(struct rte_eth_dev *eth_dev, + __rte_unused int wait_to_complete) +{ + struct hns3_adapter *hns = eth_dev->data->dev_private; + struct hns3_hw *hw = &hns->hw; + struct hns3_mac *mac = &hw->mac; + struct rte_eth_link new_link; + + memset(&new_link, 0, sizeof(new_link)); + switch (mac->link_speed) { + case ETH_SPEED_NUM_10M: + case ETH_SPEED_NUM_100M: + case ETH_SPEED_NUM_1G: + case ETH_SPEED_NUM_10G: + case ETH_SPEED_NUM_25G: + case ETH_SPEED_NUM_40G: + case ETH_SPEED_NUM_50G: + case ETH_SPEED_NUM_100G: + new_link.link_speed = mac->link_speed; + break; + default: + new_link.link_speed = ETH_SPEED_NUM_100M; + break; + } + + new_link.link_duplex = mac->link_duplex; + new_link.link_status = mac->link_status ? ETH_LINK_UP : ETH_LINK_DOWN; + new_link.link_autoneg = + !(eth_dev->data->dev_conf.link_speeds & ETH_LINK_SPEED_FIXED); + + return rte_eth_linkstatus_set(eth_dev, &new_link); +} + +static int hns3_parse_func_status(struct hns3_hw *hw, struct hns3_func_status_cmd *status) { struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw); @@ -2306,6 +2342,129 @@ hns3_set_promisc_mode(struct hns3_hw *hw, bool en_uc_pmc, bool en_mc_pmc) } static int +hns3_get_sfp_speed(struct hns3_hw *hw, uint32_t *speed) +{ + struct hns3_sfp_speed_cmd *resp; + 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; + ret = hns3_cmd_send(hw, &desc, 1); + if (ret == -EOPNOTSUPP) { + hns3_err(hw, "IMP do not support get SFP speed %d", ret); + return ret; + } else if (ret) { + hns3_err(hw, "get sfp speed failed %d", ret); + return ret; + } + + *speed = resp->sfp_speed; + + return 0; +} + +static uint8_t +hns3_check_speed_dup(uint8_t duplex, uint32_t speed) +{ + if (!(speed == ETH_SPEED_NUM_10M || speed == ETH_SPEED_NUM_100M)) + duplex = ETH_LINK_FULL_DUPLEX; + + return duplex; +} + +static int +hns3_cfg_mac_speed_dup(struct hns3_hw *hw, uint32_t speed, uint8_t duplex) +{ + struct hns3_mac *mac = &hw->mac; + int ret; + + duplex = hns3_check_speed_dup(duplex, speed); + if (mac->link_speed == speed && mac->link_duplex == duplex) + return 0; + + ret = hns3_cfg_mac_speed_dup_hw(hw, speed, duplex); + if (ret) + return ret; + + mac->link_speed = speed; + mac->link_duplex = duplex; + + return 0; +} + +static int +hns3_update_speed_duplex(struct rte_eth_dev *eth_dev) +{ + struct hns3_adapter *hns = eth_dev->data->dev_private; + struct hns3_hw *hw = &hns->hw; + struct hns3_pf *pf = &hns->pf; + uint32_t speed; + int ret; + + /* If IMP do not support get SFP/qSFP speed, return directly */ + if (!pf->support_sfp_query) + return 0; + + ret = hns3_get_sfp_speed(hw, &speed); + if (ret == -EOPNOTSUPP) { + pf->support_sfp_query = false; + return ret; + } else if (ret) + return ret; + + if (speed == ETH_SPEED_NUM_NONE) + return 0; /* do nothing if no SFP */ + + /* Config full duplex for SFP */ + return hns3_cfg_mac_speed_dup(hw, speed, ETH_LINK_FULL_DUPLEX); +} + +static int +hns3_get_mac_link_status(struct hns3_hw *hw) +{ + struct hns3_link_status_cmd *req; + struct hns3_cmd_desc desc; + int link_status; + int ret; + + hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_QUERY_LINK_STATUS, true); + ret = hns3_cmd_send(hw, &desc, 1); + if (ret) { + hns3_err(hw, "get link status cmd failed %d", ret); + return ret; + } + + req = (struct hns3_link_status_cmd *)desc.data; + link_status = req->status & HNS3_LINK_STATUS_UP_M; + + return !!link_status; +} + +static void +hns3_update_link_status(struct hns3_hw *hw) +{ + int state; + + state = hns3_get_mac_link_status(hw); + if (state != hw->mac.link_status) + hw->mac.link_status = state; +} + +static void +hns3_service_handler(void *param) +{ + struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)param; + struct hns3_adapter *hns = eth_dev->data->dev_private; + struct hns3_hw *hw = &hns->hw; + + hns3_update_speed_duplex(eth_dev); + hns3_update_link_status(hw); + + rte_eal_alarm_set(HNS3_SERVICE_INTERVAL, hns3_service_handler, eth_dev); +} + +static int hns3_init_hardware(struct hns3_adapter *hns) { struct hns3_hw *hw = &hns->hw; @@ -2435,6 +2594,7 @@ hns3_dev_close(struct rte_eth_dev *eth_dev) struct hns3_hw *hw = &hns->hw; hw->adapter_state = HNS3_NIC_CLOSING; + rte_eal_alarm_cancel(hns3_service_handler, eth_dev); hns3_configure_all_mc_mac_addr(hns, true); hns3_uninit_pf(eth_dev); @@ -2450,6 +2610,7 @@ static const struct eth_dev_ops hns3_eth_dev_ops = { .mac_addr_remove = hns3_remove_mac_addr, .mac_addr_set = hns3_set_default_mac_addr, .set_mc_addr_list = hns3_set_mc_mac_addr_list, + .link_update = hns3_dev_link_update, }; static int @@ -2504,6 +2665,7 @@ hns3_dev_init(struct rte_eth_dev *eth_dev) */ eth_dev->data->dev_flags |= RTE_ETH_DEV_CLOSE_REMOVE; + rte_eal_alarm_set(HNS3_SERVICE_INTERVAL, hns3_service_handler, eth_dev); hns3_info(hw, "hns3 dev initialization successful!"); return 0;