X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fhns3%2Fhns3_ethdev.c;h=7d37004972bf28a8d9f6a4e3ff13dcfefc7e7655;hb=bd7b62d7e05daea20b81da3e26d8210b4dacf9ba;hp=17b995af1501fd8bbb747d20a4255b12a1324bf0;hpb=fafa81dece7fe22369073235b636c2fc6cda6601;p=dpdk.git diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c index 17b995af15..7d37004972 100644 --- a/drivers/net/hns3/hns3_ethdev.c +++ b/drivers/net/hns3/hns3_ethdev.c @@ -103,6 +103,7 @@ static int hns3_restore_fec(struct hns3_hw *hw); static int hns3_query_dev_fec_info(struct hns3_hw *hw); static int hns3_do_stop(struct hns3_adapter *hns); static int hns3_check_port_speed(struct hns3_hw *hw, uint32_t link_speeds); +static int hns3_cfg_mac_mode(struct hns3_hw *hw, bool enable); void hns3_ether_format_addr(char *buf, uint16_t size, const struct rte_ether_addr *ether_addr) @@ -317,6 +318,7 @@ hns3_interrupt_handler(void *param) vector0_int = hns3_read_dev(hw, HNS3_VECTOR0_OTHER_INT_STS_REG); ras_int = hns3_read_dev(hw, HNS3_RAS_PF_OTHER_INT_STS_REG); cmdq_int = hns3_read_dev(hw, HNS3_VECTOR0_CMDQ_SRC_REG); + hns3_clear_event_cause(hw, event_cause, clearval); /* vector 0 interrupt is shared with reset and mailbox source events. */ if (event_cause == HNS3_VECTOR0_EVENT_ERR) { hns3_warn(hw, "received interrupt: vector0_int_stat:0x%x " @@ -335,7 +337,6 @@ hns3_interrupt_handler(void *param) vector0_int, ras_int, cmdq_int); } - hns3_clear_event_cause(hw, event_cause, clearval); /* Enable interrupt if it is not cause by reset */ hns3_pf_enable_irq0(hw); } @@ -1748,7 +1749,6 @@ hns3_set_default_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *oaddr; char mac_str[RTE_ETHER_ADDR_FMT_SIZE]; bool default_addr_setted; - bool rm_succes = false; int ret, ret_val; /* @@ -1768,9 +1768,10 @@ hns3_set_default_mac_addr(struct rte_eth_dev *dev, oaddr); hns3_warn(hw, "Remove old uc mac address(%s) fail: %d", mac_str, ret); - rm_succes = false; - } else - rm_succes = true; + + rte_spinlock_unlock(&hw->lock); + return ret; + } } ret = hns3_add_uc_addr_common(hw, mac_addr); @@ -1805,16 +1806,12 @@ err_pause_addr_cfg: } err_add_uc_addr: - if (rm_succes) { - ret_val = hns3_add_uc_addr_common(hw, oaddr); - if (ret_val) { - hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE, - oaddr); - hns3_warn(hw, - "Failed to restore old uc mac addr(%s): %d", + ret_val = hns3_add_uc_addr_common(hw, oaddr); + if (ret_val) { + hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE, oaddr); + hns3_warn(hw, "Failed to restore old uc mac addr(%s): %d", mac_str, ret_val); - hw->mac.default_addr_setted = false; - } + hw->mac.default_addr_setted = false; } rte_spinlock_unlock(&hw->lock); @@ -2441,14 +2438,11 @@ hns3_check_link_speed(struct hns3_hw *hw, uint32_t link_speeds) /* * Some hardware doesn't support auto-negotiation, but users may not * configure link_speeds (default 0), which means auto-negotiation. - * In this case, a warning message need to be printed, instead of - * an error. + * In this case, it should return success. */ if (link_speeds == ETH_LINK_SPEED_AUTONEG && - hw->mac.support_autoneg == 0) { - hns3_warn(hw, "auto-negotiation is not supported, use default fixed speed!"); + hw->mac.support_autoneg == 0) return 0; - } if (link_speeds != ETH_LINK_SPEED_AUTONEG) { ret = hns3_check_port_speed(hw, link_speeds); @@ -2930,6 +2924,88 @@ out: return rte_eth_linkstatus_set(eth_dev, &new_link); } +static int +hns3_dev_set_link_up(struct rte_eth_dev *dev) +{ + struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); + int ret; + + /* + * The "tx_pkt_burst" will be restored. But the secondary process does + * not support the mechanism for notifying the primary process. + */ + if (rte_eal_process_type() != RTE_PROC_PRIMARY) { + hns3_err(hw, "secondary process does not support to set link up."); + return -ENOTSUP; + } + + /* + * If device isn't started Rx/Tx function is still disabled, setting + * link up is not allowed. But it is probably better to return success + * to reduce the impact on the upper layer. + */ + if (hw->adapter_state != HNS3_NIC_STARTED) { + hns3_info(hw, "device isn't started, can't set link up."); + return 0; + } + + if (!hw->set_link_down) + return 0; + + rte_spinlock_lock(&hw->lock); + ret = hns3_cfg_mac_mode(hw, true); + if (ret) { + rte_spinlock_unlock(&hw->lock); + hns3_err(hw, "failed to set link up, ret = %d", ret); + return ret; + } + + hw->set_link_down = false; + hns3_start_tx_datapath(dev); + rte_spinlock_unlock(&hw->lock); + + return 0; +} + +static int +hns3_dev_set_link_down(struct rte_eth_dev *dev) +{ + struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); + int ret; + + /* + * The "tx_pkt_burst" will be set to dummy function. But the secondary + * process does not support the mechanism for notifying the primary + * process. + */ + if (rte_eal_process_type() != RTE_PROC_PRIMARY) { + hns3_err(hw, "secondary process does not support to set link down."); + return -ENOTSUP; + } + + /* + * If device isn't started or the API has been called, link status is + * down, return success. + */ + if (hw->adapter_state != HNS3_NIC_STARTED || hw->set_link_down) + return 0; + + rte_spinlock_lock(&hw->lock); + hns3_stop_tx_datapath(dev); + ret = hns3_cfg_mac_mode(hw, false); + if (ret) { + hns3_start_tx_datapath(dev); + rte_spinlock_unlock(&hw->lock); + hns3_err(hw, "failed to set link down, ret = %d", ret); + return ret; + } + + hw->set_link_down = true; + rte_spinlock_unlock(&hw->lock); + + return 0; +} + static int hns3_parse_func_status(struct hns3_hw *hw, struct hns3_func_status_cmd *status) { @@ -5299,6 +5375,7 @@ hns3_uninit_pf(struct rte_eth_dev *eth_dev) hns3_rss_uninit(hns); (void)hns3_config_gro(hw, false); hns3_promisc_uninit(hw); + hns3_flow_uninit(eth_dev); hns3_fdir_filter_uninit(hns); hns3_uninit_umv_space(hw); hns3_tqp_stats_uninit(hw); @@ -5519,10 +5596,13 @@ hns3_set_fiber_port_link_speed(struct hns3_hw *hw, /* * Some hardware doesn't support auto-negotiation, but users may not * configure link_speeds (default 0), which means auto-negotiation. - * In this case, it should return success. + * In this case, a warning message need to be printed, instead of + * an error. */ - if (cfg->autoneg) + if (cfg->autoneg) { + hns3_warn(hw, "auto-negotiation is not supported, use default fixed speed!"); return 0; + } return hns3_cfg_mac_speed_dup(hw, cfg->speed, cfg->duplex); } @@ -5579,6 +5659,7 @@ static int hns3_do_start(struct hns3_adapter *hns, bool reset_queue) { struct hns3_hw *hw = &hns->hw; + bool link_en; int ret; ret = hns3_update_queue_map_configure(hns); @@ -5603,7 +5684,8 @@ hns3_do_start(struct hns3_adapter *hns, bool reset_queue) return ret; } - ret = hns3_cfg_mac_mode(hw, true); + link_en = hw->set_link_down ? false : true; + ret = hns3_cfg_mac_mode(hw, link_en); if (ret) { PMD_INIT_LOG(ERR, "failed to enable MAC, ret = %d", ret); goto err_config_mac_mode; @@ -5734,6 +5816,7 @@ hns3_dev_start(struct rte_eth_dev *dev) { struct hns3_adapter *hns = dev->data->dev_private; struct hns3_hw *hw = &hns->hw; + bool old_state = hw->set_link_down; int ret; PMD_INIT_FUNC_TRACE(); @@ -5743,12 +5826,17 @@ hns3_dev_start(struct rte_eth_dev *dev) rte_spinlock_lock(&hw->lock); hw->adapter_state = HNS3_NIC_STARTING; + /* + * If the dev_set_link_down() API has been called, the "set_link_down" + * flag can be cleared by dev_start() API. In addition, the flag should + * also be cleared before calling hns3_do_start() so that MAC can be + * enabled in dev_start stage. + */ + hw->set_link_down = false; ret = hns3_do_start(hns, true); - if (ret) { - hw->adapter_state = HNS3_NIC_CONFIGURED; - rte_spinlock_unlock(&hw->lock); - return ret; - } + if (ret) + goto do_start_fail; + ret = hns3_map_rx_interrupt(dev); if (ret) goto map_rx_inter_err; @@ -5804,6 +5892,8 @@ start_all_rxqs_fail: hns3_stop_all_txqs(dev); map_rx_inter_err: (void)hns3_do_stop(hns); +do_start_fail: + hw->set_link_down = old_state; hw->adapter_state = HNS3_NIC_CONFIGURED; rte_spinlock_unlock(&hw->lock); @@ -5922,11 +6012,8 @@ hns3_dev_close(struct rte_eth_dev *eth_dev) struct hns3_hw *hw = &hns->hw; int ret = 0; - if (rte_eal_process_type() != RTE_PROC_PRIMARY) { - rte_free(eth_dev->process_private); - eth_dev->process_private = NULL; + if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; - } if (hw->adapter_state == HNS3_NIC_STARTED) ret = hns3_dev_stop(eth_dev); @@ -5941,8 +6028,6 @@ hns3_dev_close(struct rte_eth_dev *eth_dev) hns3_uninit_pf(eth_dev); hns3_free_all_queues(eth_dev); rte_free(hw->reset.wait_data); - rte_free(eth_dev->process_private); - eth_dev->process_private = NULL; hns3_mp_uninit_primary(); hns3_warn(hw, "Close port %u finished", hw->data->port_id); @@ -7353,6 +7438,8 @@ static const struct eth_dev_ops hns3_eth_dev_ops = { .mac_addr_set = hns3_set_default_mac_addr, .set_mc_addr_list = hns3_set_mc_mac_addr_list, .link_update = hns3_dev_link_update, + .dev_set_link_up = hns3_dev_set_link_up, + .dev_set_link_down = hns3_dev_set_link_down, .rss_hash_update = hns3_dev_rss_hash_update, .rss_hash_conf_get = hns3_dev_rss_hash_conf_get, .reta_update = hns3_dev_rss_reta_update, @@ -7402,15 +7489,6 @@ hns3_dev_init(struct rte_eth_dev *eth_dev) PMD_INIT_FUNC_TRACE(); - eth_dev->process_private = (struct hns3_process_private *) - rte_zmalloc_socket("hns3_filter_list", - sizeof(struct hns3_process_private), - RTE_CACHE_LINE_SIZE, eth_dev->device->numa_node); - if (eth_dev->process_private == NULL) { - PMD_INIT_LOG(ERR, "Failed to alloc memory for process private"); - return -ENOMEM; - } - hns3_flow_init(eth_dev); hns3_set_rxtx_function(eth_dev); @@ -7514,8 +7592,6 @@ err_mp_init_secondary: eth_dev->tx_pkt_burst = NULL; eth_dev->tx_pkt_prepare = NULL; eth_dev->tx_descriptor_status = NULL; - rte_free(eth_dev->process_private); - eth_dev->process_private = NULL; return ret; } @@ -7527,11 +7603,8 @@ hns3_dev_uninit(struct rte_eth_dev *eth_dev) PMD_INIT_FUNC_TRACE(); - if (rte_eal_process_type() != RTE_PROC_PRIMARY) { - rte_free(eth_dev->process_private); - eth_dev->process_private = NULL; + if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; - } if (hw->adapter_state < HNS3_NIC_CLOSING) hns3_dev_close(eth_dev);