net/hns3: support Rx interrupt
authorHao Chen <chenhao164@huawei.com>
Sat, 21 Dec 2019 10:32:45 +0000 (18:32 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Fri, 17 Jan 2020 18:46:01 +0000 (19:46 +0100)
This patch adds supports of receive packets through interrupt mode for
hns3 PF/VF driver. The following ops functions should be implemented
defined in the struct eth_dev_ops:
rx_queue_intr_enable
rx_queue_intr_disable

Signed-off-by: Hao Chen <chenhao164@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
doc/guides/nics/features/hns3.ini
doc/guides/nics/features/hns3_vf.ini
doc/guides/nics/hns3.rst
doc/guides/rel_notes/release_20_02.rst
drivers/net/hns3/hns3_cmd.h
drivers/net/hns3/hns3_ethdev.c
drivers/net/hns3/hns3_ethdev_vf.c
drivers/net/hns3/hns3_mbx.h
drivers/net/hns3/hns3_regs.h
drivers/net/hns3/hns3_rxtx.c
drivers/net/hns3/hns3_rxtx.h

index 6df789e..cd5c08a 100644 (file)
@@ -5,6 +5,7 @@
 ;
 [Features]
 Link status          = Y
+Rx interrupt         = Y
 MTU update           = Y
 Jumbo frame          = Y
 Promiscuous mode     = Y
index 41497c4..fd00ac3 100644 (file)
@@ -5,6 +5,7 @@
 ;
 [Features]
 Link status          = Y
+Rx interrupt         = Y
 MTU update           = Y
 Jumbo frame          = Y
 Unicast MAC filter   = Y
index 505488b..8d19f48 100644 (file)
@@ -22,6 +22,7 @@ Features of the HNS3 PMD are:
 - Port hardware statistics
 - Jumbo frames
 - Link state information
+- Interrupt mode for RX
 - VLAN stripping
 - NUMA support
 
index ea156e6..4c27f45 100644 (file)
@@ -61,6 +61,12 @@ New Features
   A new API has been added to wait for a memory location to be updated with a
   16-bit, 32-bit, 64-bit value.
 
+* **Updated Hisilicon hns3 driver.**
+
+  Updated Hisilicon hns3 driver with new features and improvements, including:
+
+  * Added support for Rx interrupt.
+
 * **Updated Mellanox mlx5 driver.**
 
   Updated Mellanox mlx5 driver with new features and improvements, including:
index be0ecbe..897dc14 100644 (file)
@@ -209,6 +209,10 @@ enum hns3_opcode_type {
        /* SFP command */
        HNS3_OPC_SFP_GET_SPEED          = 0x7104,
 
+       /* Interrupts commands */
+       HNS3_OPC_ADD_RING_TO_VECTOR     = 0x1503,
+       HNS3_OPC_DEL_RING_TO_VECTOR     = 0x1504,
+
        /* Error INT commands */
        HNS3_QUERY_MSIX_INT_STS_BD_NUM          = 0x1513,
        HNS3_QUERY_CLEAR_ALL_MPF_MSIX_INT       = 0x1514,
@@ -673,6 +677,30 @@ struct hns3_tqp_map_cmd {
        uint8_t rsv[18];
 };
 
+#define HNS3_RING_TYPE_B       0
+#define HNS3_RING_TYPE_TX      0
+#define HNS3_RING_TYPE_RX      1
+#define HNS3_RING_GL_IDX_S     0
+#define HNS3_RING_GL_IDX_M     GENMASK(1, 0)
+#define HNS3_RING_GL_RX                0
+#define HNS3_RING_GL_TX                1
+
+#define HNS3_VECTOR_ELEMENTS_PER_CMD   10
+
+#define HNS3_INT_TYPE_S                0
+#define HNS3_INT_TYPE_M                GENMASK(1, 0)
+#define HNS3_TQP_ID_S          2
+#define HNS3_TQP_ID_M          GENMASK(12, 2)
+#define HNS3_INT_GL_IDX_S      13
+#define HNS3_INT_GL_IDX_M      GENMASK(14, 13)
+struct hns3_ctrl_vector_chain_cmd {
+       uint8_t int_vector_id;
+       uint8_t int_cause_num;
+       uint16_t tqp_type_and_id[HNS3_VECTOR_ELEMENTS_PER_CMD];
+       uint8_t vfid;
+       uint8_t rsv;
+};
+
 struct hns3_config_max_frm_size_cmd {
        uint16_t max_frm_size;
        uint8_t min_frm_size;
index 7231571..8243ade 100644 (file)
@@ -2021,6 +2021,40 @@ hns3_check_dcb_cfg(struct rte_eth_dev *dev)
        return hns3_check_mq_mode(dev);
 }
 
+static int
+hns3_bind_ring_with_vector(struct rte_eth_dev *dev, uint8_t vector_id,
+                          bool mmap, uint16_t queue_id)
+{
+       struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       struct hns3_cmd_desc desc;
+       struct hns3_ctrl_vector_chain_cmd *req =
+               (struct hns3_ctrl_vector_chain_cmd *)desc.data;
+       enum hns3_cmd_status status;
+       enum hns3_opcode_type op;
+       uint16_t tqp_type_and_id = 0;
+
+       op = mmap ? HNS3_OPC_ADD_RING_TO_VECTOR : HNS3_OPC_DEL_RING_TO_VECTOR;
+       hns3_cmd_setup_basic_desc(&desc, op, false);
+       req->int_vector_id = vector_id;
+
+       hns3_set_field(tqp_type_and_id, HNS3_INT_TYPE_M, HNS3_INT_TYPE_S,
+                      HNS3_RING_TYPE_RX);
+       hns3_set_field(tqp_type_and_id, HNS3_TQP_ID_M, HNS3_TQP_ID_S, queue_id);
+       hns3_set_field(tqp_type_and_id, HNS3_INT_GL_IDX_M, HNS3_INT_GL_IDX_S,
+                      HNS3_RING_GL_RX);
+       req->tqp_type_and_id[0] = rte_cpu_to_le_16(tqp_type_and_id);
+
+       req->int_cause_num = 1;
+       status = hns3_cmd_send(hw, &desc, 1);
+       if (status) {
+               hns3_err(hw, "Map TQP %d fail, vector_id is %d, status is %d.",
+                        queue_id, vector_id, status);
+               return -EIO;
+       }
+
+       return 0;
+}
+
 static int
 hns3_dev_configure(struct rte_eth_dev *dev)
 {
@@ -4020,15 +4054,83 @@ err_config_mac_mode:
 }
 
 static int
-hns3_dev_start(struct rte_eth_dev *eth_dev)
+hns3_map_rx_interrupt(struct rte_eth_dev *dev)
 {
-       struct hns3_adapter *hns = eth_dev->data->dev_private;
-       struct hns3_hw *hw = &hns->hw;
+       struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+       struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint32_t intr_vector;
+       uint8_t base = 0;
+       uint8_t vec = 0;
+       uint16_t q_id;
        int ret;
 
+       if (dev->data->dev_conf.intr_conf.rxq == 0)
+               return 0;
+
+       /* disable uio/vfio intr/eventfd mapping */
+       rte_intr_disable(intr_handle);
+
+       /* check and configure queue intr-vector mapping */
+       if (rte_intr_cap_multiple(intr_handle) ||
+           !RTE_ETH_DEV_SRIOV(dev).active) {
+               intr_vector = dev->data->nb_rx_queues;
+               /* creates event fd for each intr vector when MSIX is used */
+               if (rte_intr_efd_enable(intr_handle, intr_vector))
+                       return -EINVAL;
+       }
+       if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
+               intr_handle->intr_vec =
+                       rte_zmalloc("intr_vec",
+                                   dev->data->nb_rx_queues * sizeof(int), 0);
+               if (intr_handle->intr_vec == NULL) {
+                       hns3_err(hw, "Failed to allocate %d rx_queues"
+                                    " intr_vec", dev->data->nb_rx_queues);
+                       ret = -ENOMEM;
+                       goto alloc_intr_vec_error;
+               }
+       }
+
+       if (rte_intr_allow_others(intr_handle)) {
+               vec = RTE_INTR_VEC_RXTX_OFFSET;
+               base = RTE_INTR_VEC_RXTX_OFFSET;
+       }
+       if (rte_intr_dp_is_en(intr_handle)) {
+               for (q_id = 0; q_id < dev->data->nb_rx_queues; q_id++) {
+                       ret = hns3_bind_ring_with_vector(dev, vec, true, q_id);
+                       if (ret)
+                               goto bind_vector_error;
+                       intr_handle->intr_vec[q_id] = vec;
+                       if (vec < base + intr_handle->nb_efd - 1)
+                               vec++;
+               }
+       }
+       rte_intr_enable(intr_handle);
+       return 0;
+
+bind_vector_error:
+       rte_intr_efd_disable(intr_handle);
+       if (intr_handle->intr_vec) {
+               free(intr_handle->intr_vec);
+               intr_handle->intr_vec = NULL;
+       }
+       return ret;
+alloc_intr_vec_error:
+       rte_intr_efd_disable(intr_handle);
+       return ret;
+}
+
+static int
+hns3_dev_start(struct rte_eth_dev *dev)
+{
+       struct hns3_adapter *hns = dev->data->dev_private;
+       struct hns3_hw *hw = &hns->hw;
+       int ret = 0;
+
        PMD_INIT_FUNC_TRACE();
        if (rte_atomic16_read(&hw->reset.resetting))
                return -EBUSY;
+
        rte_spinlock_lock(&hw->lock);
        hw->adapter_state = HNS3_NIC_STARTING;
 
@@ -4041,8 +4143,12 @@ hns3_dev_start(struct rte_eth_dev *eth_dev)
 
        hw->adapter_state = HNS3_NIC_STARTED;
        rte_spinlock_unlock(&hw->lock);
-       hns3_set_rxtx_function(eth_dev);
-       hns3_mp_req_start_rxtx(eth_dev);
+
+       ret = hns3_map_rx_interrupt(dev);
+       if (ret)
+               return ret;
+       hns3_set_rxtx_function(dev);
+       hns3_mp_req_start_rxtx(dev);
 
        hns3_info(hw, "hns3 dev start successful!");
        return 0;
@@ -4070,18 +4176,50 @@ hns3_do_stop(struct hns3_adapter *hns)
 }
 
 static void
-hns3_dev_stop(struct rte_eth_dev *eth_dev)
+hns3_unmap_rx_interrupt(struct rte_eth_dev *dev)
 {
-       struct hns3_adapter *hns = eth_dev->data->dev_private;
+       struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+       uint8_t base = 0;
+       uint8_t vec = 0;
+       uint16_t q_id;
+
+       if (dev->data->dev_conf.intr_conf.rxq == 0)
+               return;
+
+       /* unmap the ring with vector */
+       if (rte_intr_allow_others(intr_handle)) {
+               vec = RTE_INTR_VEC_RXTX_OFFSET;
+               base = RTE_INTR_VEC_RXTX_OFFSET;
+       }
+       if (rte_intr_dp_is_en(intr_handle)) {
+               for (q_id = 0; q_id < dev->data->nb_rx_queues; q_id++) {
+                       (void)hns3_bind_ring_with_vector(dev, vec, false, q_id);
+                       if (vec < base + intr_handle->nb_efd - 1)
+                               vec++;
+               }
+       }
+       /* Clean datapath event and queue/vec mapping */
+       rte_intr_efd_disable(intr_handle);
+       if (intr_handle->intr_vec) {
+               rte_free(intr_handle->intr_vec);
+               intr_handle->intr_vec = NULL;
+       }
+}
+
+static void
+hns3_dev_stop(struct rte_eth_dev *dev)
+{
+       struct hns3_adapter *hns = dev->data->dev_private;
        struct hns3_hw *hw = &hns->hw;
 
        PMD_INIT_FUNC_TRACE();
 
        hw->adapter_state = HNS3_NIC_STOPPING;
-       hns3_set_rxtx_function(eth_dev);
+       hns3_set_rxtx_function(dev);
        rte_wmb();
        /* Disable datapath on secondary process. */
-       hns3_mp_req_stop_rxtx(eth_dev);
+       hns3_mp_req_stop_rxtx(dev);
        /* Prevent crashes when queues are still in use. */
        rte_delay_ms(hw->tqps_num);
 
@@ -4092,6 +4230,7 @@ hns3_dev_stop(struct rte_eth_dev *eth_dev)
                hw->adapter_state = HNS3_NIC_CONFIGURED;
        }
        rte_spinlock_unlock(&hw->lock);
+       hns3_unmap_rx_interrupt(dev);
 }
 
 static void
@@ -4748,6 +4887,8 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
        .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_intr_enable   = hns3_dev_rx_queue_intr_enable,
+       .rx_queue_intr_disable  = hns3_dev_rx_queue_intr_disable,
        .dev_configure          = hns3_dev_configure,
        .flow_ctrl_get          = hns3_flow_ctrl_get,
        .flow_ctrl_set          = hns3_flow_ctrl_set,
index b1736e7..bd52e19 100644 (file)
@@ -1208,6 +1208,36 @@ hns3vf_uninit_vf(struct rte_eth_dev *eth_dev)
        hw->io_base = NULL;
 }
 
+static int
+hns3vf_bind_ring_with_vector(struct rte_eth_dev *dev, uint8_t vector_id,
+                            bool mmap, uint16_t queue_id)
+
+{
+       struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       struct hns3_vf_bind_vector_msg bind_msg;
+       uint16_t code;
+       int ret;
+
+       memset(&bind_msg, 0, sizeof(bind_msg));
+       code = mmap ? HNS3_MBX_MAP_RING_TO_VECTOR :
+               HNS3_MBX_UNMAP_RING_TO_VECTOR;
+       bind_msg.vector_id = vector_id;
+       bind_msg.ring_num = 1;
+       bind_msg.param[0].ring_type = HNS3_RING_TYPE_RX;
+       bind_msg.param[0].tqp_index = queue_id;
+       bind_msg.param[0].int_gl_index = HNS3_RING_GL_RX;
+
+       ret = hns3_send_mbx_msg(hw, code, 0, (uint8_t *)&bind_msg,
+                               sizeof(bind_msg), false, NULL, 0);
+       if (ret) {
+               hns3_err(hw, "Map TQP %d fail, vector_id is %d, ret is %d.",
+                        queue_id, vector_id, ret);
+               return ret;
+       }
+
+       return 0;
+}
+
 static int
 hns3vf_do_stop(struct hns3_adapter *hns)
 {
@@ -1225,18 +1255,51 @@ hns3vf_do_stop(struct hns3_adapter *hns)
 }
 
 static void
-hns3vf_dev_stop(struct rte_eth_dev *eth_dev)
+hns3vf_unmap_rx_interrupt(struct rte_eth_dev *dev)
 {
-       struct hns3_adapter *hns = eth_dev->data->dev_private;
+       struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+       uint8_t base = 0;
+       uint8_t vec = 0;
+       uint16_t q_id;
+
+       if (dev->data->dev_conf.intr_conf.rxq == 0)
+               return;
+
+       /* unmap the ring with vector */
+       if (rte_intr_allow_others(intr_handle)) {
+               vec = RTE_INTR_VEC_RXTX_OFFSET;
+               base = RTE_INTR_VEC_RXTX_OFFSET;
+       }
+       if (rte_intr_dp_is_en(intr_handle)) {
+               for (q_id = 0; q_id < dev->data->nb_rx_queues; q_id++) {
+                       (void)hns3vf_bind_ring_with_vector(dev, vec, false,
+                                                          q_id);
+                       if (vec < base + intr_handle->nb_efd - 1)
+                               vec++;
+               }
+       }
+       /* Clean datapath event and queue/vec mapping */
+       rte_intr_efd_disable(intr_handle);
+       if (intr_handle->intr_vec) {
+               rte_free(intr_handle->intr_vec);
+               intr_handle->intr_vec = NULL;
+       }
+}
+
+static void
+hns3vf_dev_stop(struct rte_eth_dev *dev)
+{
+       struct hns3_adapter *hns = dev->data->dev_private;
        struct hns3_hw *hw = &hns->hw;
 
        PMD_INIT_FUNC_TRACE();
 
        hw->adapter_state = HNS3_NIC_STOPPING;
-       hns3_set_rxtx_function(eth_dev);
+       hns3_set_rxtx_function(dev);
        rte_wmb();
        /* Disable datapath on secondary process. */
-       hns3_mp_req_stop_rxtx(eth_dev);
+       hns3_mp_req_stop_rxtx(dev);
        /* Prevent crashes when queues are still in use. */
        rte_delay_ms(hw->tqps_num);
 
@@ -1246,8 +1309,10 @@ hns3vf_dev_stop(struct rte_eth_dev *eth_dev)
                hns3_dev_release_mbufs(hns);
                hw->adapter_state = HNS3_NIC_CONFIGURED;
        }
-       rte_eal_alarm_cancel(hns3vf_service_handler, eth_dev);
+       rte_eal_alarm_cancel(hns3vf_service_handler, dev);
        rte_spinlock_unlock(&hw->lock);
+
+       hns3vf_unmap_rx_interrupt(dev);
 }
 
 static void
@@ -1329,15 +1394,84 @@ hns3vf_do_start(struct hns3_adapter *hns, bool reset_queue)
 }
 
 static int
-hns3vf_dev_start(struct rte_eth_dev *eth_dev)
+hns3vf_map_rx_interrupt(struct rte_eth_dev *dev)
 {
-       struct hns3_adapter *hns = eth_dev->data->dev_private;
-       struct hns3_hw *hw = &hns->hw;
+       struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+       struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint32_t intr_vector;
+       uint8_t base = 0;
+       uint8_t vec = 0;
+       uint16_t q_id;
        int ret;
 
+       if (dev->data->dev_conf.intr_conf.rxq == 0)
+               return 0;
+
+       /* disable uio/vfio intr/eventfd mapping */
+       rte_intr_disable(intr_handle);
+
+       /* check and configure queue intr-vector mapping */
+       if (rte_intr_cap_multiple(intr_handle) ||
+               !RTE_ETH_DEV_SRIOV(dev).active) {
+               intr_vector = dev->data->nb_rx_queues;
+               /* It creates event fd for each intr vector when MSIX is used */
+               if (rte_intr_efd_enable(intr_handle, intr_vector))
+                       return -EINVAL;
+       }
+       if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
+               intr_handle->intr_vec =
+                       rte_zmalloc("intr_vec",
+                                   dev->data->nb_rx_queues * sizeof(int), 0);
+               if (intr_handle->intr_vec == NULL) {
+                       hns3_err(hw, "Failed to allocate %d rx_queues"
+                                    " intr_vec", dev->data->nb_rx_queues);
+                       ret = -ENOMEM;
+                       goto vf_alloc_intr_vec_error;
+               }
+       }
+
+       if (rte_intr_allow_others(intr_handle)) {
+               vec = RTE_INTR_VEC_RXTX_OFFSET;
+               base = RTE_INTR_VEC_RXTX_OFFSET;
+       }
+       if (rte_intr_dp_is_en(intr_handle)) {
+               for (q_id = 0; q_id < dev->data->nb_rx_queues; q_id++) {
+                       ret = hns3vf_bind_ring_with_vector(dev, vec, true,
+                                                          q_id);
+                       if (ret)
+                               goto vf_bind_vector_error;
+                       intr_handle->intr_vec[q_id] = vec;
+                       if (vec < base + intr_handle->nb_efd - 1)
+                               vec++;
+               }
+       }
+       rte_intr_enable(intr_handle);
+       return 0;
+
+vf_bind_vector_error:
+       rte_intr_efd_disable(intr_handle);
+       if (intr_handle->intr_vec) {
+               free(intr_handle->intr_vec);
+               intr_handle->intr_vec = NULL;
+       }
+       return ret;
+vf_alloc_intr_vec_error:
+       rte_intr_efd_disable(intr_handle);
+       return ret;
+}
+
+static int
+hns3vf_dev_start(struct rte_eth_dev *dev)
+{
+       struct hns3_adapter *hns = dev->data->dev_private;
+       struct hns3_hw *hw = &hns->hw;
+       int ret = 0;
+
        PMD_INIT_FUNC_TRACE();
        if (rte_atomic16_read(&hw->reset.resetting))
                return -EBUSY;
+
        rte_spinlock_lock(&hw->lock);
        hw->adapter_state = HNS3_NIC_STARTING;
        ret = hns3vf_do_start(hns, true);
@@ -1348,11 +1482,14 @@ hns3vf_dev_start(struct rte_eth_dev *eth_dev)
        }
        hw->adapter_state = HNS3_NIC_STARTED;
        rte_spinlock_unlock(&hw->lock);
-       hns3_set_rxtx_function(eth_dev);
-       hns3_mp_req_start_rxtx(eth_dev);
-       rte_eal_alarm_set(HNS3VF_SERVICE_INTERVAL, hns3vf_service_handler,
-                         eth_dev);
-       return 0;
+
+       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);
+       return ret;
 }
 
 static bool
@@ -1685,6 +1822,8 @@ static const struct eth_dev_ops hns3vf_eth_dev_ops = {
        .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_intr_enable   = hns3_dev_rx_queue_intr_enable,
+       .rx_queue_intr_disable  = hns3_dev_rx_queue_intr_disable,
        .dev_configure      = hns3vf_dev_configure,
        .mac_addr_add       = hns3vf_add_mac_addr,
        .mac_addr_remove    = hns3vf_remove_mac_addr,
index 01eddb8..d1a6bfe 100644 (file)
@@ -104,6 +104,19 @@ struct hns3_mbx_pf_to_vf_cmd {
        uint16_t msg[8];
 };
 
+struct hns3_ring_chain_param {
+       uint8_t ring_type;
+       uint8_t tqp_index;
+       uint8_t int_gl_index;
+};
+
+#define HNS3_MBX_MAX_RING_CHAIN_PARAM_NUM      4
+struct hns3_vf_bind_vector_msg {
+       uint8_t vector_id;
+       uint8_t ring_num;
+       struct hns3_ring_chain_param param[HNS3_MBX_MAX_RING_CHAIN_PARAM_NUM];
+};
+
 struct hns3_vf_rst_cmd {
        uint8_t dest_vfid;
        uint8_t vf_rst;
index 2f5faaf..42581df 100644 (file)
@@ -83,6 +83,9 @@
 
 #define HNS3_RING_EN_B                         0
 
+#define HNS3_VECTOR_REG_OFFSET                 0x4
+#define HNS3_VECTOR_VF_OFFSET                  0x100000
+
 #define HNS3_TQP_REG_OFFSET                    0x80000
 #define HNS3_TQP_REG_SIZE                      0x200
 
index 8166447..e1bdba9 100644 (file)
@@ -395,6 +395,47 @@ hns3_reset_all_queues(struct hns3_adapter *hns)
        return 0;
 }
 
+void
+hns3_tqp_intr_enable(struct hns3_hw *hw, uint16_t tpq_int_num, bool en)
+{
+       uint32_t addr, value;
+
+       addr = HNS3_TQP_INTR_CTRL_REG + tpq_int_num * HNS3_VECTOR_REG_OFFSET;
+       value = en ? 1 : 0;
+
+       hns3_write_dev(hw, addr, value);
+}
+
+int
+hns3_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+       struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+       struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+       if (dev->data->dev_conf.intr_conf.rxq == 0)
+               return -ENOTSUP;
+
+       /* enable the vectors */
+       hns3_tqp_intr_enable(hw, queue_id, true);
+
+       return rte_intr_ack(intr_handle);
+}
+
+int
+hns3_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+       struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+       if (dev->data->dev_conf.intr_conf.rxq == 0)
+               return -ENOTSUP;
+
+       /* disable the vectors */
+       hns3_tqp_intr_enable(hw, queue_id, false);
+
+       return 0;
+}
+
 static int
 hns3_dev_rx_queue_start(struct hns3_adapter *hns, uint16_t idx)
 {
index daf51f4..cc21026 100644 (file)
@@ -295,6 +295,8 @@ void hns3_dev_rx_queue_release(void *queue);
 void hns3_dev_tx_queue_release(void *queue);
 void hns3_free_all_queues(struct rte_eth_dev *dev);
 int hns3_reset_all_queues(struct hns3_adapter *hns);
+int hns3_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id);
+int hns3_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id);
 int hns3_start_queues(struct hns3_adapter *hns, bool reset_queue);
 int hns3_stop_queues(struct hns3_adapter *hns, bool reset_queue);
 void hns3_dev_release_mbufs(struct hns3_adapter *hns);
@@ -311,4 +313,5 @@ uint16_t hns3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
                        uint16_t nb_pkts);
 const uint32_t *hns3_dev_supported_ptypes_get(struct rte_eth_dev *dev);
 void hns3_set_rxtx_function(struct rte_eth_dev *eth_dev);
+void hns3_tqp_intr_enable(struct hns3_hw *hw, uint16_t tpq_int_num, bool en);
 #endif /* _HNS3_RXTX_H_ */