bool gro_en;
int ret;
+ hw->cfg_max_queues = RTE_MAX(nb_rx_q, nb_tx_q);
+
/*
- * Hardware does not support individually enable/disable/reset the Tx or
- * Rx queue in hns3 network engine. Driver must enable/disable/reset Tx
- * and Rx queues at the same time. When the numbers of Tx queues
- * allocated by upper applications are not equal to the numbers of Rx
- * queues, driver needs to setup fake Tx or Rx queues to adjust numbers
- * of Tx/Rx queues. otherwise, network engine can not work as usual. But
- * these fake queues are imperceptible, and can not be used by upper
- * applications.
+ * Some versions of hardware network engine does not support
+ * individually enable/disable/reset the Tx or Rx queue. These devices
+ * must enable/disable/reset Tx and Rx queues at the same time. When the
+ * numbers of Tx queues allocated by upper applications are not equal to
+ * the numbers of Rx queues, driver needs to setup fake Tx or Rx queues
+ * to adjust numbers of Tx/Rx queues. otherwise, network engine can not
+ * work as usual. But these fake queues are imperceptible, and can not
+ * be used by upper applications.
*/
- ret = hns3_set_fake_rx_or_tx_queues(dev, nb_rx_q, nb_tx_q);
- if (ret) {
- hns3_err(hw, "Failed to set rx/tx fake queues: %d", ret);
- return ret;
+ if (!hns3_dev_indep_txrx_supported(hw)) {
+ ret = hns3_set_fake_rx_or_tx_queues(dev, nb_rx_q, nb_tx_q);
+ if (ret) {
+ hns3_err(hw, "fail to set Rx/Tx fake queues, ret = %d.",
+ ret);
+ return ret;
+ }
}
hw->adapter_state = HNS3_NIC_CONFIGURING;
if ((uint32_t)mq_mode & ETH_MQ_RX_RSS_FLAG) {
conf->rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH;
rss_conf = conf->rx_adv_conf.rss_conf;
+ hw->rss_dis_flag = false;
if (rss_conf.rss_key == NULL) {
rss_conf.rss_key = rss_cfg->key;
rss_conf.rss_key_len = HNS3_RSS_KEY_SIZE;
DEV_TX_OFFLOAD_MBUF_FAST_FREE |
hns3_txvlan_cap_get(hw));
+ if (hns3_dev_indep_txrx_supported(hw))
+ info->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
+ RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
+
info->rx_desc_lim = (struct rte_eth_desc_lim) {
.nb_max = HNS3_MAX_RING_DESC,
.nb_min = HNS3_MIN_RING_DESC,
return hns3_parse_func_status(hw, req);
}
+static int
+hns3_get_pf_max_tqp_num(struct hns3_hw *hw)
+{
+ struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+ struct hns3_pf *pf = &hns->pf;
+
+ if (pf->tqp_config_mode == HNS3_FLEX_MAX_TQP_NUM_MODE) {
+ /*
+ * The total_tqps_num obtained from firmware is maximum tqp
+ * numbers of this port, which should be used for PF and VFs.
+ * There is no need for pf to have so many tqp numbers in
+ * most cases. RTE_LIBRTE_HNS3_MAX_TQP_NUM_PER_PF,
+ * coming from config file, is assigned to maximum queue number
+ * for the PF of this port by user. So users can modify the
+ * maximum queue number of PF according to their own application
+ * scenarios, which is more flexible to use. In addition, many
+ * memories can be saved due to allocating queue statistics
+ * room according to the actual number of queues required. The
+ * maximum queue number of PF for network engine with
+ * revision_id greater than 0x30 is assigned by config file.
+ */
+ if (RTE_LIBRTE_HNS3_MAX_TQP_NUM_PER_PF <= 0) {
+ hns3_err(hw, "RTE_LIBRTE_HNS3_MAX_TQP_NUM_PER_PF(%d) "
+ "must be greater than 0.",
+ RTE_LIBRTE_HNS3_MAX_TQP_NUM_PER_PF);
+ return -EINVAL;
+ }
+
+ hw->tqps_num = RTE_MIN(RTE_LIBRTE_HNS3_MAX_TQP_NUM_PER_PF,
+ hw->total_tqps_num);
+ } else {
+ /*
+ * Due to the limitation on the number of PF interrupts
+ * available, the maximum queue number assigned to PF on
+ * the network engine with revision_id 0x21 is 64.
+ */
+ hw->tqps_num = RTE_MIN(hw->total_tqps_num,
+ HNS3_MAX_TQP_NUM_HIP08_PF);
+ }
+
+ return 0;
+}
+
static int
hns3_query_pf_resource(struct hns3_hw *hw)
{
}
req = (struct hns3_pf_res_cmd *)desc.data;
- hw->total_tqps_num = rte_le_to_cpu_16(req->tqp_num);
+ hw->total_tqps_num = rte_le_to_cpu_16(req->tqp_num) +
+ rte_le_to_cpu_16(req->ext_tqp_num);
+ ret = hns3_get_pf_max_tqp_num(hw);
+ if (ret)
+ return ret;
+
pf->pkt_buf_size = rte_le_to_cpu_16(req->buf_size) << HNS3_BUF_UNIT_S;
- hw->tqps_num = RTE_MIN(hw->total_tqps_num, HNS3_MAX_TQP_NUM_PER_FUNC);
pf->func_num = rte_le_to_cpu_16(req->pf_own_fun_number);
if (req->tx_buf_size)
{
struct hns3_cfg_param_cmd *req;
uint64_t mac_addr_tmp_high;
+ uint8_t ext_rss_size_max;
uint64_t mac_addr_tmp;
uint32_t i;
HNS3_CFG_UMV_TBL_SPACE_S);
if (!cfg->umv_space)
cfg->umv_space = HNS3_DEFAULT_UMV_SPACE_PER_PF;
+
+ 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
+ * of reading out directly. If this field is not zero, hns3 PF PMD
+ * driver uses it as rss_size_max under one TC. Device, whose revision
+ * id is greater than or equal to PCI_REVISION_ID_HIP09_A, obtains the
+ * maximum number of queues supported under a TC through this field.
+ */
+ if (ext_rss_size_max)
+ cfg->rss_size_max = 1U << ext_rss_size_max;
}
/* hns3_get_board_cfg: query the static parameter from NCL_config file in flash
static int
hns3_get_capability(struct hns3_hw *hw)
{
+ struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
struct rte_pci_device *pci_dev;
+ struct hns3_pf *pf = &hns->pf;
struct rte_eth_dev *eth_dev;
uint16_t device_id;
uint8_t revision;
hw->intr.mapping_mode = HNS3_INTR_MAPPING_VEC_RSV_ONE;
hw->intr.coalesce_mode = HNS3_INTR_COALESCE_NON_QL;
hw->intr.gl_unit = HNS3_INTR_COALESCE_GL_UINT_2US;
+ hw->tso_mode = HNS3_TSO_SW_CAL_PSEUDO_H_CSUM;
hw->vlan_mode = HNS3_SW_SHIFT_AND_DISCARD_MODE;
hw->min_tx_pkt_len = HNS3_HIP08_MIN_TX_PKT_LEN;
+ pf->tqp_config_mode = HNS3_FIXED_MAX_TQP_NUM_MODE;
return 0;
}
hw->intr.mapping_mode = HNS3_INTR_MAPPING_VEC_ALL;
hw->intr.coalesce_mode = HNS3_INTR_COALESCE_QL;
hw->intr.gl_unit = HNS3_INTR_COALESCE_GL_UINT_1US;
+ hw->tso_mode = HNS3_TSO_HW_CAL_PSEUDO_H_CSUM;
hw->vlan_mode = HNS3_HW_SHIFT_AND_DISCARD_MODE;
hw->min_tx_pkt_len = HNS3_HIP09_MIN_TX_PKT_LEN;
+ pf->tqp_config_mode = HNS3_FLEX_MAX_TQP_NUM_MODE;
return 0;
}
ret = hns3_get_board_configuration(hw);
if (ret)
- PMD_INIT_LOG(ERR, "Failed to get board configuration: %d", ret);
+ PMD_INIT_LOG(ERR, "failed to get board configuration: %d", ret);
return ret;
}
static int
hns3_map_tqp(struct hns3_hw *hw)
{
- uint16_t tqps_num = hw->total_tqps_num;
- uint16_t func_id;
- uint16_t tqp_id;
- bool is_pf;
- int num;
int ret;
int i;
/*
- * In current version VF is not supported when PF is driven by DPDK
- * driver, so we allocate tqps to PF as much as possible.
+ * In current version, VF is not supported when PF is driven by DPDK
+ * driver, so we assign total tqps_num tqps allocated to this port
+ * to PF.
*/
- tqp_id = 0;
- num = DIV_ROUND_UP(hw->total_tqps_num, HNS3_MAX_TQP_NUM_PER_FUNC);
- for (func_id = HNS3_PF_FUNC_ID; func_id < num; func_id++) {
- is_pf = func_id == HNS3_PF_FUNC_ID ? true : false;
- for (i = 0;
- i < HNS3_MAX_TQP_NUM_PER_FUNC && tqp_id < tqps_num; i++) {
- ret = hns3_map_tqps_to_func(hw, func_id, tqp_id++, i,
- is_pf);
- if (ret)
- return ret;
- }
+ for (i = 0; i < hw->total_tqps_num; i++) {
+ ret = hns3_map_tqps_to_func(hw, HNS3_PF_FUNC_ID, i, i, true);
+ if (ret)
+ return ret;
}
return 0;
goto err_get_config;
}
+ ret = hns3_tqp_stats_init(hw);
+ if (ret)
+ goto err_get_config;
+
ret = hns3_init_hardware(hns);
if (ret) {
PMD_INIT_LOG(ERR, "Failed to init hardware: %d", ret);
- goto err_get_config;
+ goto err_init_hw;
}
/* Initialize flow director filter list & hash */
ret = hns3_fdir_filter_init(hns);
if (ret) {
PMD_INIT_LOG(ERR, "Failed to alloc hashmap for fdir: %d", ret);
- goto err_hw_init;
+ goto err_fdir;
}
hns3_set_default_rss_args(hw);
if (ret) {
PMD_INIT_LOG(ERR, "fail to enable hw error interrupts: %d",
ret);
- goto err_fdir;
+ goto err_enable_intr;
}
return 0;
-err_fdir:
+err_enable_intr:
hns3_fdir_filter_uninit(hns);
-err_hw_init:
+err_fdir:
hns3_uninit_umv_space(hw);
-
+err_init_hw:
+ hns3_tqp_stats_uninit(hw);
err_get_config:
hns3_pf_disable_irq0(hw);
rte_intr_disable(&pci_dev->intr_handle);
hns3_promisc_uninit(hw);
hns3_fdir_filter_uninit(hns);
hns3_uninit_umv_space(hw);
+ hns3_tqp_stats_uninit(hw);
hns3_pf_disable_irq0(hw);
rte_intr_disable(&pci_dev->intr_handle);
hns3_intr_unregister(&pci_dev->intr_handle, hns3_interrupt_handler,
if (ret)
return ret;
- /* Enable queues */
- ret = hns3_start_queues(hns, reset_queue);
+ ret = hns3_init_queues(hns, reset_queue);
if (ret) {
- PMD_INIT_LOG(ERR, "Failed to start queues: %d", ret);
+ PMD_INIT_LOG(ERR, "failed to init queues, ret = %d.", ret);
return ret;
}
- /* Enable MAC */
ret = hns3_cfg_mac_mode(hw, true);
if (ret) {
- PMD_INIT_LOG(ERR, "Failed to enable MAC: %d", ret);
+ PMD_INIT_LOG(ERR, "failed to enable MAC, ret = %d", ret);
goto err_config_mac_mode;
}
return 0;
err_config_mac_mode:
- hns3_stop_queues(hns, true);
+ hns3_dev_release_mbufs(hns);
+ hns3_reset_all_tqps(hns);
return ret;
}
return ret;
}
+ /*
+ * There are three register used to control the status of a TQP
+ * (contains a pair of Tx queue and Rx queue) in the new version network
+ * engine. One is used to control the enabling of Tx queue, the other is
+ * used to control the enabling of Rx queue, and the last is the master
+ * switch used to control the enabling of the tqp. The Tx register and
+ * TQP register must be enabled at the same time to enable a Tx queue.
+ * The same applies to the Rx queue. For the older network engine, this
+ * function only refresh the enabled flag, and it is used to update the
+ * status of queue in the dpdk framework.
+ */
+ ret = hns3_start_all_txqs(dev);
+ if (ret) {
+ hw->adapter_state = HNS3_NIC_CONFIGURED;
+ rte_spinlock_unlock(&hw->lock);
+ return ret;
+ }
+
+ ret = hns3_start_all_rxqs(dev);
+ if (ret) {
+ hns3_stop_all_txqs(dev);
+ hw->adapter_state = HNS3_NIC_CONFIGURED;
+ rte_spinlock_unlock(&hw->lock);
+ return ret;
+ }
+
hw->adapter_state = HNS3_NIC_STARTED;
rte_spinlock_unlock(&hw->lock);
/* Enable interrupt of all rx queues before enabling queues */
hns3_dev_all_rx_queue_intr_enable(hw, true);
+
/*
- * When finished the initialization, enable queues to receive/transmit
- * packets.
+ * After finished the initialization, enable tqps to receive/transmit
+ * packets and refresh all queue status.
*/
- hns3_enable_all_queues(hw, true);
+ hns3_start_tqps(hw);
hns3_info(hw, "hns3 dev start successful!");
return 0;
hns3_do_stop(struct hns3_adapter *hns)
{
struct hns3_hw *hw = &hns->hw;
- bool reset_queue;
int ret;
ret = hns3_cfg_mac_mode(hw, false);
if (rte_atomic16_read(&hw->reset.disable_cmd) == 0) {
hns3_configure_all_mac_addr(hns, true);
- reset_queue = true;
- } else
- reset_queue = false;
+ ret = hns3_reset_all_tqps(hns);
+ if (ret) {
+ hns3_err(hw, "failed to reset all queues ret = %d.",
+ ret);
+ return ret;
+ }
+ }
hw->mac.default_addr_setted = false;
- return hns3_stop_queues(hns, reset_queue);
+ return 0;
}
static void
rte_spinlock_lock(&hw->lock);
if (rte_atomic16_read(&hw->reset.resetting) == 0) {
+ hns3_stop_tqps(hw);
hns3_do_stop(hns);
hns3_unmap_rx_interrupt(dev);
hns3_dev_release_mbufs(hns);
rte_spinlock_unlock(&hw->lock);
}
-static void
+static int
hns3_dev_close(struct rte_eth_dev *eth_dev)
{
struct hns3_adapter *hns = eth_dev->data->dev_private;
if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
rte_free(eth_dev->process_private);
eth_dev->process_private = NULL;
- return;
+ return 0;
}
if (hw->adapter_state == HNS3_NIC_STARTED)
eth_dev->process_private = NULL;
hns3_mp_uninit_primary();
hns3_warn(hw, "Close port %d finished", hw->data->port_id);
+
+ return 0;
}
static int
return ret;
}
- ret = hns3_reset_all_queues(hns);
+ ret = hns3_reset_all_tqps(hns);
if (ret) {
hns3_err(hw, "Failed to reset all queues: %d", ret);
return ret;
rte_spinlock_lock(&hw->lock);
if (hns->hw.adapter_state == HNS3_NIC_STARTED ||
hw->adapter_state == HNS3_NIC_STOPPING) {
+ hns3_enable_all_queues(hw, false);
hns3_do_stop(hns);
hw->reset.mbuf_deferred_free = true;
} else
.tx_queue_setup = hns3_tx_queue_setup,
.rx_queue_release = hns3_dev_rx_queue_release,
.tx_queue_release = hns3_dev_tx_queue_release,
+ .rx_queue_start = hns3_dev_rx_queue_start,
+ .rx_queue_stop = hns3_dev_rx_queue_stop,
+ .tx_queue_start = hns3_dev_tx_queue_start,
+ .tx_queue_stop = hns3_dev_tx_queue_stop,
.rx_queue_intr_enable = hns3_dev_rx_queue_intr_enable,
.rx_queue_intr_disable = hns3_dev_rx_queue_intr_disable,
.rxq_info_get = hns3_rxq_info_get,
ð_dev->data->mac_addrs[0]);
hw->adapter_state = HNS3_NIC_INITIALIZED;
- /*
- * Pass the information to the rte_eth_dev_close() that it should also
- * release the private port resources.
- */
- eth_dev->data->dev_flags |= RTE_ETH_DEV_CLOSE_REMOVE;
if (rte_atomic16_read(&hns->hw.reset.schedule) == SCHEDULE_PENDING) {
hns3_err(hw, "Reschedule reset service after dev_init");