* Rx interrupt.
*/
vec = hw->num_msi - 1; /* vector 0 for misc interrupt, not for queue */
- hw->intr_tqps_num = vec - 1; /* the last interrupt is reserved */
+ /* vec - 1: the last interrupt is reserved */
+ hw->intr_tqps_num = vec > hw->tqps_num ? hw->tqps_num : vec - 1;
for (i = 0; i < hw->intr_tqps_num; i++) {
/*
* Set gap limiter and rate limiter configuration of queue's
/* When RSS is not configured, redirect the packet queue 0 */
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;
if (rss_conf.rss_key == NULL) {
rss_conf.rss_key = rss_cfg->key;
DEV_RX_OFFLOAD_KEEP_CRC |
DEV_RX_OFFLOAD_SCATTER |
DEV_RX_OFFLOAD_VLAN_STRIP |
- DEV_RX_OFFLOAD_QINQ_STRIP |
DEV_RX_OFFLOAD_VLAN_FILTER |
- DEV_RX_OFFLOAD_JUMBO_FRAME);
+ DEV_RX_OFFLOAD_JUMBO_FRAME |
+ DEV_RX_OFFLOAD_RSS_HASH);
info->tx_queue_offload_capa = DEV_TX_OFFLOAD_MBUF_FAST_FREE;
info->tx_offload_capa = (DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM |
DEV_TX_OFFLOAD_IPV4_CKSUM |
return -EINVAL;
}
- hw->num_msi = (num_msi > hw->tqps_num + 1) ? hw->tqps_num + 1 : num_msi;
+ hw->num_msi = num_msi;
return 0;
}
goto err_init_hardware;
}
+ /*
+ * In the initialization clearing the all hardware mapping relationship
+ * configurations between queues and interrupt vectors is needed, so
+ * some error caused by the residual configurations, such as the
+ * unexpected interrupt, can be avoid.
+ */
+ ret = hns3vf_init_ring_with_vector(hw);
+ if (ret) {
+ PMD_INIT_LOG(ERR, "Failed to init ring intr vector: %d", ret);
+ goto err_init_hardware;
+ }
+
ret = hns3vf_set_alive(hw, true);
if (ret) {
PMD_INIT_LOG(ERR, "Failed to VF send alive to PF: %d", ret);
hns3_set_default_rss_args(hw);
- /*
- * In the initialization clearing the all hardware mapping relationship
- * configurations between queues and interrupt vectors is needed, so
- * some error caused by the residual configurations, such as the
- * unexpected interrupt, can be avoid.
- */
- ret = hns3vf_init_ring_with_vector(hw);
- if (ret)
- goto err_get_config;
-
return 0;
err_get_config:
rte_spinlock_lock(&hw->lock);
if (rte_atomic16_read(&hw->reset.resetting) == 0) {
hns3vf_do_stop(hns);
+ hns3vf_unmap_rx_interrupt(dev);
hns3_dev_release_mbufs(hns);
hw->adapter_state = HNS3_NIC_CONFIGURED;
}
rte_eal_alarm_cancel(hns3vf_service_handler, dev);
rte_spinlock_unlock(&hw->lock);
-
- hns3vf_unmap_rx_interrupt(dev);
}
static void
hns3_warn(hw, "Close port %d finished", hw->data->port_id);
}
+static int
+hns3vf_fw_version_get(struct rte_eth_dev *eth_dev, char *fw_version,
+ size_t fw_size)
+{
+ struct hns3_adapter *hns = eth_dev->data->dev_private;
+ struct hns3_hw *hw = &hns->hw;
+ uint32_t version = hw->fw_version;
+ int ret;
+
+ ret = snprintf(fw_version, fw_size, "%lu.%lu.%lu.%lu",
+ hns3_get_field(version, HNS3_FW_VERSION_BYTE3_M,
+ HNS3_FW_VERSION_BYTE3_S),
+ hns3_get_field(version, HNS3_FW_VERSION_BYTE2_M,
+ HNS3_FW_VERSION_BYTE2_S),
+ hns3_get_field(version, HNS3_FW_VERSION_BYTE1_M,
+ HNS3_FW_VERSION_BYTE1_S),
+ hns3_get_field(version, HNS3_FW_VERSION_BYTE0_M,
+ HNS3_FW_VERSION_BYTE0_S));
+ ret += 1; /* add the size of '\0' */
+ if (fw_size < (uint32_t)ret)
+ return ret;
+ else
+ return 0;
+}
+
static int
hns3vf_dev_link_update(struct rte_eth_dev *eth_dev,
__rte_unused int wait_to_complete)
return ret;
}
+static int
+hns3vf_restore_rx_interrupt(struct hns3_hw *hw)
+{
+ struct rte_eth_dev *dev = &rte_eth_devices[hw->data->port_id];
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+ struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+ uint16_t q_id;
+ int ret;
+
+ if (dev->data->dev_conf.intr_conf.rxq == 0)
+ return 0;
+
+ if (rte_intr_dp_is_en(intr_handle)) {
+ for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
+ ret = hns3vf_bind_ring_with_vector(hw,
+ intr_handle->intr_vec[q_id], true,
+ HNS3_RING_TYPE_RX, q_id);
+ if (ret)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
static void
hns3vf_restore_filter(struct rte_eth_dev *dev)
{
rte_spinlock_unlock(&hw->lock);
return ret;
}
+ ret = hns3vf_map_rx_interrupt(dev);
+ if (ret) {
+ hw->adapter_state = HNS3_NIC_CONFIGURED;
+ rte_spinlock_unlock(&hw->lock);
+ return ret;
+ }
hw->adapter_state = HNS3_NIC_STARTED;
rte_spinlock_unlock(&hw->lock);
- ret = hns3vf_map_rx_interrupt(dev);
- if (ret)
- return ret;
hns3_set_rxtx_function(dev);
hns3_mp_req_start_rxtx(dev);
rte_eal_alarm_set(HNS3VF_SERVICE_INTERVAL, hns3vf_service_handler, dev);
hns3vf_restore_filter(dev);
+ /* 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.
+ */
+ hns3_enable_all_queues(hw, true);
+
return ret;
}
eth_dev = &rte_eth_devices[hw->data->port_id];
hns3_set_rxtx_function(eth_dev);
hns3_mp_req_start_rxtx(eth_dev);
- if (hw->adapter_state == HNS3_NIC_STARTED)
+ if (hw->adapter_state == HNS3_NIC_STARTED) {
hns3vf_service_handler(eth_dev);
+ /* 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
+ * and transmit packets.
+ */
+ hns3_enable_all_queues(hw, true);
+ }
+
return 0;
}
if (ret)
goto err_vlan_table;
+ ret = hns3vf_restore_rx_interrupt(hw);
+ if (ret)
+ goto err_vlan_table;
+
if (hw->adapter_state == HNS3_NIC_STARTED) {
ret = hns3vf_do_start(hns, false);
if (ret)
.xstats_get_by_id = hns3_dev_xstats_get_by_id,
.xstats_get_names_by_id = hns3_dev_xstats_get_names_by_id,
.dev_infos_get = hns3vf_dev_infos_get,
+ .fw_version_get = hns3vf_fw_version_get,
.rx_queue_setup = hns3_rx_queue_setup,
.tx_queue_setup = hns3_tx_queue_setup,
.rx_queue_release = hns3_dev_rx_queue_release,
static int
hns3vf_dev_init(struct rte_eth_dev *eth_dev)
{
+ struct rte_device *dev = eth_dev->device;
+ struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev);
struct hns3_adapter *hns = eth_dev->data->dev_private;
struct hns3_hw *hw = &hns->hw;
+ uint8_t revision;
int ret;
PMD_INIT_FUNC_TRACE();
+ /* Get PCI revision id */
+ ret = rte_pci_read_config(pci_dev, &revision, HNS3_PCI_REVISION_ID_LEN,
+ HNS3_PCI_REVISION_ID);
+ if (ret != HNS3_PCI_REVISION_ID_LEN) {
+ PMD_INIT_LOG(ERR, "Failed to read pci revision id, ret = %d",
+ ret);
+ return -EIO;
+ }
+ hw->revision = revision;
+
eth_dev->process_private = (struct hns3_process_private *)
rte_zmalloc_socket("hns3_filter_list",
sizeof(struct hns3_process_private),