X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fhns3%2Fhns3_ethdev.c;h=7d37004972bf28a8d9f6a4e3ff13dcfefc7e7655;hb=ed2ffccdc1c862a24361f67dcf470428be142418;hp=d4561ffd90a8874d5f8414731c488c6f4c693e47;hpb=5b96963f9d121cee0eaaa19c19eca0ddbeee73b7;p=dpdk.git diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c index d4561ffd90..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) @@ -253,8 +254,8 @@ static void hns3_clear_all_event_cause(struct hns3_hw *hw) { uint32_t vector0_int_stats; - vector0_int_stats = hns3_read_dev(hw, HNS3_VECTOR0_OTHER_INT_STS_REG); + vector0_int_stats = hns3_read_dev(hw, HNS3_VECTOR0_OTHER_INT_STS_REG); if (BIT(HNS3_VECTOR0_IMPRESET_INT_B) & vector0_int_stats) hns3_warn(hw, "Probe during IMP reset interrupt"); @@ -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) { @@ -3127,7 +3203,6 @@ hns3_parse_cfg(struct hns3_cfg *cfg, struct hns3_cmd_desc *desc) ext_rss_size_max = hns3_get_field(rte_le_to_cpu_32(req->param[2]), HNS3_CFG_EXT_RSS_SIZE_M, HNS3_CFG_EXT_RSS_SIZE_S); - /* * Field ext_rss_size_max obtained from firmware will be more flexible * for future changes and expansions, which is an exponent of 2, instead @@ -3318,6 +3393,7 @@ hns3_get_capability(struct hns3_hw *hw) pf->tqp_config_mode = HNS3_FIXED_MAX_TQP_NUM_MODE; hw->rss_info.ipv6_sctp_offload_supported = false; hw->udp_cksum_mode = HNS3_SPECIAL_PORT_SW_CKSUM_MODE; + pf->support_multi_tc_pause = false; return 0; } @@ -3338,6 +3414,7 @@ hns3_get_capability(struct hns3_hw *hw) pf->tqp_config_mode = HNS3_FLEX_MAX_TQP_NUM_MODE; hw->rss_info.ipv6_sctp_offload_supported = true; hw->udp_cksum_mode = HNS3_SPECIAL_PORT_HW_CKSUM_MODE; + pf->support_multi_tc_pause = true; return 0; } @@ -3846,7 +3923,6 @@ hns3_drop_nopfc_buf_till_fit(struct hns3_hw *hw, for (i = HNS3_MAX_TC_NUM - 1; i >= 0; i--) { priv = &buf_alloc->priv_buf[i]; mask = BIT((uint8_t)i); - if (hw->hw_tc_map & mask && !(hw->dcb_info.hw_pfc_map & mask)) { /* Clear the no pfc TC private buffer */ @@ -3932,7 +4008,6 @@ hns3_only_alloc_priv_buff(struct hns3_hw *hw, COMPENSATE_HALF_MPS_NUM * half_mps; min_rx_priv = roundup(min_rx_priv, HNS3_BUF_SIZE_UNIT); rx_priv = rounddown(rx_priv, HNS3_BUF_SIZE_UNIT); - if (rx_priv < min_rx_priv) return false; @@ -5177,6 +5252,8 @@ hns3_init_pf(struct rte_eth_dev *eth_dev) goto err_cmd_init; } + hns3_tx_push_init(eth_dev); + /* * To ensure that the hardware environment is clean during * initialization, the driver actively clear the hardware environment @@ -5298,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); @@ -5518,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); } @@ -5578,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); @@ -5602,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; @@ -5733,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(); @@ -5742,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; @@ -5803,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); @@ -5921,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); @@ -5940,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); @@ -6104,6 +6190,7 @@ static int hns3_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) { struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct hns3_pf *pf = HNS3_DEV_PRIVATE_TO_PF(dev->data->dev_private); int ret; if (fc_conf->high_water || fc_conf->low_water || @@ -6133,7 +6220,7 @@ hns3_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) return -EOPNOTSUPP; } - if (hw->num_tc > 1) { + if (hw->num_tc > 1 && !pf->support_multi_tc_pause) { hns3_err(hw, "in multi-TC scenarios, MAC pause is not supported."); return -EOPNOTSUPP; } @@ -6297,7 +6384,6 @@ hns3_is_reset_pending(struct hns3_adapter *hns) hns3_check_event_cause(hns, NULL); reset = hns3_get_reset_level(hns, &hw->reset.pending); - if (reset != HNS3_NONE_RESET && hw->reset.level != HNS3_NONE_RESET && hw->reset.level < reset) { hns3_warn(hw, "High level reset %d is pending", reset); @@ -7352,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, @@ -7401,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); @@ -7422,8 +7501,8 @@ hns3_dev_init(struct rte_eth_dev *eth_dev) "process, ret = %d", ret); goto err_mp_init_secondary; } - hw->secondary_cnt++; + hns3_tx_push_init(eth_dev); return 0; } @@ -7513,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; } @@ -7526,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);