X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fhns3%2Fhns3_ethdev.c;h=fa01b588fd96557170fdc24799d3f1663e744cb2;hb=3b37cbe6179aeebc02b5e5cf3e39dfb2d5e69a01;hp=ca59a807bbaba7f0222e65d12c33b74c24fbd65e;hpb=d69b9dd854776b79049fda943ade2fb040484ea0;p=dpdk.git diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c index ca59a807bb..fa01b588fd 100644 --- a/drivers/net/hns3/hns3_ethdev.c +++ b/drivers/net/hns3/hns3_ethdev.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2018-2019 HiSilicon Limited. + * Copyright(c) 2018-2021 HiSilicon Limited. */ #include @@ -981,7 +981,7 @@ hns3_vlan_pvid_configure(struct hns3_adapter *hns, uint16_t pvid, int on) { struct hns3_hw *hw = &hns->hw; uint16_t port_base_vlan_state; - int ret; + int ret, err; if (on == 0 && pvid != hw->port_base_vlan_cfg.pvid) { if (hw->port_base_vlan_cfg.pvid != HNS3_INVALID_PVID) @@ -1004,7 +1004,7 @@ hns3_vlan_pvid_configure(struct hns3_adapter *hns, uint16_t pvid, int on) if (ret) { hns3_err(hw, "failed to config rx vlan strip for pvid, " "ret = %d", ret); - return ret; + goto pvid_vlan_strip_fail; } if (pvid == HNS3_INVALID_PVID) @@ -1013,13 +1013,27 @@ hns3_vlan_pvid_configure(struct hns3_adapter *hns, uint16_t pvid, int on) if (ret) { hns3_err(hw, "failed to update vlan filter entries, ret = %d", ret); - return ret; + goto vlan_filter_set_fail; } out: hw->port_base_vlan_cfg.state = port_base_vlan_state; hw->port_base_vlan_cfg.pvid = on ? pvid : HNS3_INVALID_PVID; return ret; + +vlan_filter_set_fail: + err = hns3_en_pvid_strip(hns, hw->port_base_vlan_cfg.state == + HNS3_PORT_BASE_VLAN_ENABLE); + if (err) + hns3_err(hw, "fail to rollback pvid strip, ret = %d", err); + +pvid_vlan_strip_fail: + err = hns3_vlan_txvlan_cfg(hns, hw->port_base_vlan_cfg.state, + hw->port_base_vlan_cfg.pvid); + if (err) + hns3_err(hw, "fail to rollback txvlan status, ret = %d", err); + + return ret; } static int @@ -2739,10 +2753,15 @@ static int hns3_update_port_link_info(struct rte_eth_dev *eth_dev) { struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); + int ret; (void)hns3_update_link_status(hw); - return hns3_update_link_info(eth_dev); + ret = hns3_update_link_info(eth_dev); + if (ret) + hw->mac.link_status = ETH_LINK_DOWN; + + return ret; } static void @@ -2793,7 +2812,6 @@ hns3_dev_link_update(struct rte_eth_dev *eth_dev, int wait_to_complete) do { ret = hns3_update_port_link_info(eth_dev); if (ret) { - mac->link_status = ETH_LINK_DOWN; hns3_err(hw, "failed to get port link info, ret = %d.", ret); break; @@ -4597,7 +4615,7 @@ hns3_update_fiber_link_info(struct hns3_hw *hw) } static void -hns3_parse_phy_params(struct hns3_cmd_desc *desc, struct hns3_mac *mac) +hns3_parse_copper_phy_params(struct hns3_cmd_desc *desc, struct hns3_mac *mac) { struct hns3_phy_params_bd0_cmd *req; @@ -4615,7 +4633,7 @@ hns3_parse_phy_params(struct hns3_cmd_desc *desc, struct hns3_mac *mac) } static int -hns3_get_phy_params(struct hns3_hw *hw, struct hns3_mac *mac) +hns3_get_copper_phy_params(struct hns3_hw *hw, struct hns3_mac *mac) { struct hns3_cmd_desc desc[HNS3_PHY_PARAM_CFG_BD_NUM]; uint16_t i; @@ -4634,20 +4652,20 @@ hns3_get_phy_params(struct hns3_hw *hw, struct hns3_mac *mac) return ret; } - hns3_parse_phy_params(desc, mac); + hns3_parse_copper_phy_params(desc, mac); return 0; } static int -hns3_update_phy_link_info(struct hns3_hw *hw) +hns3_update_copper_link_info(struct hns3_hw *hw) { struct hns3_mac *mac = &hw->mac; struct hns3_mac mac_info; int ret; memset(&mac_info, 0, sizeof(struct hns3_mac)); - ret = hns3_get_phy_params(hw, &mac_info); + ret = hns3_get_copper_phy_params(hw, &mac_info); if (ret) return ret; @@ -4676,7 +4694,7 @@ hns3_update_link_info(struct rte_eth_dev *eth_dev) int ret = 0; if (hw->mac.media_type == HNS3_MEDIA_TYPE_COPPER) - ret = hns3_update_phy_link_info(hw); + ret = hns3_update_copper_link_info(hw); else if (hw->mac.media_type == HNS3_MEDIA_TYPE_FIBER) ret = hns3_update_fiber_link_info(hw); @@ -4766,30 +4784,22 @@ hns3_update_link_status(struct hns3_hw *hw) return false; } -/* - * Current, the PF driver get link status by two ways: - * 1) Periodic polling in the intr thread context, driver call - * hns3_update_link_status to update link status. - * 2) Firmware report async interrupt, driver process the event in the intr - * thread context, and call hns3_update_link_status to update link status. - * - * If detect link status changed, driver need report LSE. One method is add the - * report LSE logic in hns3_update_link_status. - * - * But the PF driver ops(link_update) also call hns3_update_link_status to - * update link status. - * If we report LSE in hns3_update_link_status, it may lead to deadlock in the - * bonding application. - * - * So add the one new API which used only in intr thread context. - */ void -hns3_update_link_status_and_event(struct hns3_hw *hw) +hns3_update_linkstatus_and_event(struct hns3_hw *hw, bool query) { struct rte_eth_dev *dev = &rte_eth_devices[hw->data->port_id]; - bool changed = hns3_update_link_status(hw); - if (changed) - rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL); + struct rte_eth_link new_link; + int ret; + + if (query) + hns3_update_port_link_info(dev); + + memset(&new_link, 0, sizeof(new_link)); + hns3_setup_linkstatus(dev, &new_link); + + ret = rte_eth_linkstatus_set(dev, &new_link); + if (ret == 0 && dev->data->dev_conf.intr_conf.lsc != 0) + hns3_start_report_lse(dev); } static void @@ -4799,16 +4809,36 @@ hns3_service_handler(void *param) struct hns3_adapter *hns = eth_dev->data->dev_private; struct hns3_hw *hw = &hns->hw; - if (!hns3_is_reset_pending(hns)) { - hns3_update_link_status_and_event(hw); - hns3_update_link_info(eth_dev); - } else { + if (!hns3_is_reset_pending(hns)) + hns3_update_linkstatus_and_event(hw, true); + else hns3_warn(hw, "Cancel the query when reset is pending"); - } rte_eal_alarm_set(HNS3_SERVICE_INTERVAL, hns3_service_handler, eth_dev); } +static void +hns3_update_dev_lsc_cap(struct hns3_hw *hw, + int fw_compact_cmd_result) +{ + struct rte_eth_dev *dev = &rte_eth_devices[hw->data->port_id]; + + if (hw->adapter_state != HNS3_NIC_UNINITIALIZED) + return; + + if (fw_compact_cmd_result != 0) { + /* + * If fw_compact_cmd_result is not zero, it means firmware don't + * support link status change interrupt. + * Framework already set RTE_ETH_DEV_INTR_LSC bit because driver + * declared RTE_PCI_DRV_INTR_LSC in drv_flags. It need to clear + * the RTE_ETH_DEV_INTR_LSC capability when detect firmware + * don't support link status change interrupt. + */ + dev->data->dev_flags &= ~RTE_ETH_DEV_INTR_LSC; + } +} + static int hns3_init_hardware(struct hns3_adapter *hns) { @@ -4896,6 +4926,7 @@ hns3_init_hardware(struct hns3_adapter *hns) if (ret) PMD_INIT_LOG(WARNING, "firmware compatible features not " "supported, ret = %d.", ret); + hns3_update_dev_lsc_cap(hw, ret); return 0; @@ -5288,7 +5319,6 @@ hns3_dev_start(struct rte_eth_dev *dev) hns3_rx_scattered_calc(dev); hns3_set_rxtx_function(dev); hns3_mp_req_start_rxtx(dev); - rte_eal_alarm_set(HNS3_SERVICE_INTERVAL, hns3_service_handler, dev); hns3_restore_filter(dev); @@ -5303,6 +5333,10 @@ hns3_dev_start(struct rte_eth_dev *dev) hns3_tm_dev_start_proc(hw); + if (dev->data->dev_conf.intr_conf.lsc != 0) + hns3_dev_link_update(dev, 0); + rte_eal_alarm_set(HNS3_SERVICE_INTERVAL, hns3_service_handler, dev); + hns3_info(hw, "hns3 dev start successful!"); return 0; @@ -5416,6 +5450,7 @@ hns3_dev_stop(struct rte_eth_dev *dev) } hns3_rx_scattered_reset(dev); rte_eal_alarm_cancel(hns3_service_handler, dev); + hns3_stop_report_lse(dev); rte_spinlock_unlock(&hw->lock); return 0; @@ -5540,6 +5575,11 @@ hns3_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) return -EOPNOTSUPP; } + if (hw->num_tc > 1) { + hns3_err(hw, "in multi-TC scenarios, MAC pause is not supported."); + return -EOPNOTSUPP; + } + hns3_get_fc_mode(hw, fc_conf->mode); if (hw->requested_mode == hw->current_mode && pf->pause_time == fc_conf->pause_time) @@ -5914,11 +5954,11 @@ hns3_stop_service(struct hns3_adapter *hns) struct rte_eth_dev *eth_dev; eth_dev = &rte_eth_devices[hw->data->port_id]; + hw->mac.link_status = ETH_LINK_DOWN; if (hw->adapter_state == HNS3_NIC_STARTED) { rte_eal_alarm_cancel(hns3_service_handler, eth_dev); - hns3_update_link_status_and_event(hw); + hns3_update_linkstatus_and_event(hw, false); } - hw->mac.link_status = ETH_LINK_DOWN; hns3_set_rxtx_function(eth_dev); rte_wmb(); @@ -6920,7 +6960,7 @@ static const struct rte_pci_id pci_id_hns3_map[] = { static struct rte_pci_driver rte_hns3_pmd = { .id_table = pci_id_hns3_map, - .drv_flags = RTE_PCI_DRV_NEED_MAPPING, + .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, .probe = eth_hns3_pci_probe, .remove = eth_hns3_pci_remove, };