get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/2395/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2395,
    "url": "https://patches.dpdk.org/api/patches/2395/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1421747640-20978-6-git-send-email-danny.zhou@intel.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1421747640-20978-6-git-send-email-danny.zhou@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1421747640-20978-6-git-send-email-danny.zhou@intel.com",
    "date": "2015-01-20T09:54:00",
    "name": "[dpdk-dev,RFC,5/5] ixgbe: enable rx queue interrupts for VF",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "db6a038bb046d0632a69e063d785514875c6684f",
    "submitter": {
        "id": 29,
        "url": "https://patches.dpdk.org/api/people/29/?format=api",
        "name": "Zhou, Danny",
        "email": "danny.zhou@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1421747640-20978-6-git-send-email-danny.zhou@intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/2395/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/2395/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 75BE35AAB;\n\tTue, 20 Jan 2015 10:54:31 +0100 (CET)",
            "from mga09.intel.com (mga09.intel.com [134.134.136.24])\n\tby dpdk.org (Postfix) with ESMTP id 363285AA2\n\tfor <dev@dpdk.org>; Tue, 20 Jan 2015 10:54:27 +0100 (CET)",
            "from orsmga003.jf.intel.com ([10.7.209.27])\n\tby orsmga102.jf.intel.com with ESMTP; 20 Jan 2015 01:51:29 -0800",
            "from shvmail01.sh.intel.com ([10.239.29.42])\n\tby orsmga003.jf.intel.com with ESMTP; 20 Jan 2015 01:47:48 -0800",
            "from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com\n\t[10.239.29.89])\n\tby shvmail01.sh.intel.com with ESMTP id t0K9sN9c000492;\n\tTue, 20 Jan 2015 17:54:23 +0800",
            "from shecgisg004.sh.intel.com (localhost [127.0.0.1])\n\tby shecgisg004.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP\n\tid t0K9sJP2021049; Tue, 20 Jan 2015 17:54:21 +0800",
            "(from dyzhou@localhost)\n\tby shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id t0K9sJ4W021045; \n\tTue, 20 Jan 2015 17:54:19 +0800"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.09,433,1418112000\"; d=\"scan'208\";a=\"514752841\"",
        "From": "Danny Zhou <danny.zhou@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Tue, 20 Jan 2015 17:54:00 +0800",
        "Message-Id": "<1421747640-20978-6-git-send-email-danny.zhou@intel.com>",
        "X-Mailer": "git-send-email 1.7.4.1",
        "In-Reply-To": "<1421747640-20978-1-git-send-email-danny.zhou@intel.com>",
        "References": "<1421747640-20978-1-git-send-email-danny.zhou@intel.com>",
        "Subject": "[dpdk-dev] [RFC PATCH 5/5] ixgbe: enable rx queue interrupts for VF",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "This patch enables rx queue interrupt for ixgbevf with below changes:\n1) Configure ixgbevf rx queue interrupts\n2) Initialize ixgbevf devices in L3fwd-power appropriately\n3) Fix VFIO interrupt vector settings\n\nSigned-off-by: Yong Liu <yong.liu@intel.com>\nSigned-off-by: Danny Zhou <danny.zhou@intel.com>\n---\n examples/l3fwd-power/main.c                        |  46 +++++--\n lib/librte_eal/linuxapp/eal/eal_interrupts.c       |  83 ++++++-----\n .../linuxapp/eal/include/exec-env/rte_interrupts.h |   1 +\n lib/librte_pmd_ixgbe/ixgbe_ethdev.c                | 153 +++++++++++++++++++++\n lib/librte_pmd_ixgbe/ixgbe_ethdev.h                |   6 +\n 5 files changed, 233 insertions(+), 56 deletions(-)",
    "diff": "diff --git a/examples/l3fwd-power/main.c b/examples/l3fwd-power/main.c\nindex 71f1d90..3262db2 100644\n--- a/examples/l3fwd-power/main.c\n+++ b/examples/l3fwd-power/main.c\n@@ -237,7 +237,6 @@ static struct rte_eth_conf port_conf = {\n \t\t.mq_mode = ETH_MQ_TX_NONE,\n \t},\n \t.intr_conf = {\n-\t\t.lsc = 1,\n \t\t.rxq = 1, /**< rxq interrupt feature enabled */\n \t},\n };\n@@ -413,15 +412,19 @@ power_timer_cb(__attribute__((unused)) struct rte_timer *tim,\n \t/**\n \t * check whether need to scale down frequency a step if it sleep a lot.\n \t */\n-\tif (sleep_time_ratio >= SCALING_DOWN_TIME_RATIO_THRESHOLD)\n-\t\trte_power_freq_down(lcore_id);\n+\tif (sleep_time_ratio >= SCALING_DOWN_TIME_RATIO_THRESHOLD) {\n+\t\tif (rte_power_freq_down)\n+\t\t\trte_power_freq_down(lcore_id);\n+\t}\n \telse if ( (unsigned)(stats[lcore_id].nb_rx_processed /\n-\t\tstats[lcore_id].nb_iteration_looped) < MAX_PKT_BURST)\n+\t\tstats[lcore_id].nb_iteration_looped) < MAX_PKT_BURST) {\n \t\t/**\n \t\t * scale down a step if average packet per iteration less\n \t\t * than expectation.\n \t\t */\n-\t\trte_power_freq_down(lcore_id);\n+\t\tif (rte_power_freq_down)\n+\t\t\trte_power_freq_down(lcore_id);\n+\t}\n \n \t/**\n \t * initialize another timer according to current frequency to ensure\n@@ -946,10 +949,14 @@ start_rx:\n \t\t\t\t\t\trx_queue->freq_up_hint;\n \t\t\t}\n \n-\t\t\tif (lcore_scaleup_hint == FREQ_HIGHEST)\n-\t\t\t\trte_power_freq_max(lcore_id);\n-\t\t\telse if (lcore_scaleup_hint == FREQ_HIGHER)\n-\t\t\t\trte_power_freq_up(lcore_id);\n+\t\t\tif (lcore_scaleup_hint == FREQ_HIGHEST) {\n+\t\t\t\tif (rte_power_freq_max)\n+\t\t\t\t\trte_power_freq_max(lcore_id);\n+\t\t\t}\n+\t\t\telse if (lcore_scaleup_hint == FREQ_HIGHER) {\n+\t\t\t\tif (rte_power_freq_up)\n+\t\t\t\t\trte_power_freq_up(lcore_id);\n+\t\t\t}\n \t\t} else {\n \t\t\t/**\n \t\t\t * All Rx queues empty in recent consecutive polls,\n@@ -1546,6 +1553,7 @@ main(int argc, char **argv)\n \tunsigned lcore_id;\n \tuint64_t hz;\n \tuint32_t n_tx_queue, nb_lcores;\n+\tuint32_t dev_rxq_num, dev_txq_num;\n \tuint8_t portid, nb_rx_queue, queue, socketid;\n \n \t/* catch SIGINT and restore cpufreq governor to ondemand */\n@@ -1595,10 +1603,18 @@ main(int argc, char **argv)\n \t\tprintf(\"Initializing port %d ... \", portid );\n \t\tfflush(stdout);\n \n+\t\trte_eth_dev_info_get(portid, &dev_info);\n+\t\tdev_rxq_num = dev_info.max_rx_queues;\n+\t\tdev_txq_num = dev_info.max_tx_queues;\n+\n \t\tnb_rx_queue = get_port_n_rx_queues(portid);\n+\t\tif (nb_rx_queue > dev_rxq_num)\n+\t\t\trte_exit(EXIT_FAILURE, \"Cannot configure not existed rxq: \"\n+\t\t\t\t\t\"port=%d\\n\", portid);\n+\n \t\tn_tx_queue = nb_lcores;\n-\t\tif (n_tx_queue > MAX_TX_QUEUE_PER_PORT)\n-\t\t\tn_tx_queue = MAX_TX_QUEUE_PER_PORT;\n+\t\tif (n_tx_queue > dev_txq_num)\n+\t\t\tn_tx_queue = dev_txq_num;\n \t\tprintf(\"Creating queues: nb_rxq=%d nb_txq=%u... \",\n \t\t\tnb_rx_queue, (unsigned)n_tx_queue );\n \t\tret = rte_eth_dev_configure(portid, nb_rx_queue,\n@@ -1622,6 +1638,9 @@ main(int argc, char **argv)\n \t\t\tif (rte_lcore_is_enabled(lcore_id) == 0)\n \t\t\t\tcontinue;\n \n+\t\t\tif (queueid >= dev_txq_num)\n+\t\t\t\tcontinue;\n+\n \t\t\tif (numa_on)\n \t\t\t\tsocketid = \\\n \t\t\t\t(uint8_t)rte_lcore_to_socket_id(lcore_id);\n@@ -1656,8 +1675,9 @@ main(int argc, char **argv)\n \t\t/* init power management library */\n \t\tret = rte_power_init(lcore_id);\n \t\tif (ret)\n-\t\t\trte_exit(EXIT_FAILURE, \"Power management library \"\n-\t\t\t\t\"initialization failed on core%u\\n\", lcore_id);\n+\t\t\trte_log(RTE_LOG_ERR, RTE_LOGTYPE_POWER,\n+\t\t\t\t\"Power management library initialization \"\n+\t\t\t\t\"failed on core%u\", lcore_id);\n \n \t\t/* init timer structures for each enabled lcore */\n \t\trte_timer_init(&power_timers[lcore_id]);\ndiff --git a/lib/librte_eal/linuxapp/eal/eal_interrupts.c b/lib/librte_eal/linuxapp/eal/eal_interrupts.c\nindex 1be4ba7..e4de20e 100644\n--- a/lib/librte_eal/linuxapp/eal/eal_interrupts.c\n+++ b/lib/librte_eal/linuxapp/eal/eal_interrupts.c\n@@ -223,7 +223,7 @@ vfio_disable_intx(struct rte_intr_handle *intr_handle) {\n /* enable MSI-X interrupts */\n static int\n vfio_enable_msi(struct rte_intr_handle *intr_handle) {\n-\tint len, ret;\n+\tint len, ret, max_intr;\n \tchar irq_set_buf[IRQ_SET_BUF_LEN];\n \tstruct vfio_irq_set *irq_set;\n \tint *fd_ptr;\n@@ -232,12 +232,19 @@ vfio_enable_msi(struct rte_intr_handle *intr_handle) {\n \n \tirq_set = (struct vfio_irq_set *) irq_set_buf;\n \tirq_set->argsz = len;\n-\tirq_set->count = 1;\n+\tif ((!intr_handle->max_intr) ||\n+\t\t(intr_handle->max_intr > VFIO_MAX_QUEUE_ID))\n+\t\tmax_intr = VFIO_MAX_QUEUE_ID + 1;\n+\telse\n+\t\tmax_intr = intr_handle->max_intr;\n+\n+\tirq_set->count = max_intr;\n \tirq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER;\n \tirq_set->index = VFIO_PCI_MSI_IRQ_INDEX;\n \tirq_set->start = 0;\n \tfd_ptr = (int *) &irq_set->data;\n-\t*fd_ptr = intr_handle->fd;\n+\tmemcpy(fd_ptr, intr_handle->queue_fd, sizeof(intr_handle->queue_fd));\n+\tfd_ptr[max_intr - 1] = intr_handle->fd;\n \n \tret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);\n \n@@ -246,23 +253,6 @@ vfio_enable_msi(struct rte_intr_handle *intr_handle) {\n \t\t\t\t\t\tintr_handle->fd);\n \t\treturn -1;\n \t}\n-\n-\t/* manually trigger interrupt to enable it */\n-\tmemset(irq_set, 0, len);\n-\tlen = sizeof(struct vfio_irq_set);\n-\tirq_set->argsz = len;\n-\tirq_set->count = 1;\n-\tirq_set->flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER;\n-\tirq_set->index = VFIO_PCI_MSI_IRQ_INDEX;\n-\tirq_set->start = 0;\n-\n-\tret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);\n-\n-\tif (ret) {\n-\t\tRTE_LOG(ERR, EAL, \"Error triggering MSI interrupts for fd %d\\n\",\n-\t\t\t\t\t\tintr_handle->fd);\n-\t\treturn -1;\n-\t}\n \treturn 0;\n }\n \n@@ -294,7 +284,7 @@ vfio_disable_msi(struct rte_intr_handle *intr_handle) {\n /* enable MSI-X interrupts */\n static int\n vfio_enable_msix(struct rte_intr_handle *intr_handle) {\n-\tint len, ret;\n+\tint len, ret, max_intr;\n \tchar irq_set_buf[MSIX_IRQ_SET_BUF_LEN];\n \tstruct vfio_irq_set *irq_set;\n \tint *fd_ptr;\n@@ -303,13 +293,19 @@ vfio_enable_msix(struct rte_intr_handle *intr_handle) {\n \n \tirq_set = (struct vfio_irq_set *) irq_set_buf;\n \tirq_set->argsz = len;\n-\tirq_set->count = VFIO_MAX_QUEUE_ID + 1;\n+\tif ((!intr_handle->max_intr) ||\n+\t\t(intr_handle->max_intr > VFIO_MAX_QUEUE_ID))\n+\t\tmax_intr = VFIO_MAX_QUEUE_ID + 1;\n+\telse\n+\t\tmax_intr = intr_handle->max_intr;\n+\n+\tirq_set->count = max_intr;\n \tirq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER;\n \tirq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;\n \tirq_set->start = 0;\n \tfd_ptr = (int *) &irq_set->data;\n \tmemcpy(fd_ptr, intr_handle->queue_fd, sizeof(intr_handle->queue_fd));\n-\tfd_ptr[VFIO_MAX_QUEUE_ID] = intr_handle->fd;\n+\tfd_ptr[max_intr - 1] = intr_handle->fd;\n \n \tret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);\n \n@@ -319,23 +315,6 @@ vfio_enable_msix(struct rte_intr_handle *intr_handle) {\n \t\treturn -1;\n \t}\n \n-\t/* manually trigger interrupt to enable it */\n-\tmemset(irq_set, 0, len);\n-\tlen = sizeof(struct vfio_irq_set);\n-\tirq_set->argsz = len;\n-\tirq_set->count = 1;\n-\tirq_set->flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER;\n-\tirq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;\n-\tirq_set->start = VFIO_MAX_QUEUE_ID;\n-\n-\tret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);\n-\n-\tif (ret) {\n-\t\tRTE_LOG(ERR, EAL, \"Error triggering MSI-X interrupts for fd %d\\n\",\n-\t\t\t\t\t\tintr_handle->fd);\n-\t\treturn -1;\n-\t}\n-\n \treturn 0;\n }\n \n@@ -913,10 +892,28 @@ rte_eal_wait_rx_intr(uint8_t port_id, uint8_t queue_id)\n \trte_spinlock_lock(&intr_lock);\n \n \tev.events = EPOLLIN | EPOLLPRI;\n-\tev.data.fd = intr_handle.queue_fd[queue_id];\n+\tswitch (intr_handle.type) {\n+\tcase RTE_INTR_HANDLE_UIO:\n+\t\tev.data.fd = intr_handle.fd;\n+\t\tbreak;\n+#ifdef VFIO_PRESENT\n+        case RTE_INTR_HANDLE_VFIO_MSIX:\n+\t\tev.data.fd = intr_handle.queue_fd[queue_id];\n+                break;\n+        case RTE_INTR_HANDLE_VFIO_MSI:\n+\t\tev.data.fd = intr_handle.queue_fd[queue_id];\n+                break;\n+        case RTE_INTR_HANDLE_VFIO_LEGACY:\n+\t\tev.data.fd = intr_handle.queue_fd[queue_id];\n+                break;\n+#endif\n+\tdefault:\n+\t\tbreak;\n+\t\t\tclose(pfd);\n+\t\t\treturn -1;\n+\t}\n \n-\tif (epoll_ctl(pfd, EPOLL_CTL_ADD,\n-\t\t\t\tintr_handle.queue_fd[queue_id], &ev) < 0){\n+\tif (epoll_ctl(pfd, EPOLL_CTL_ADD, ev.data.fd, &ev) < 0){\n \t\trte_panic(\"Error adding fd %d epoll_ctl, %s\\n\",\n \t\t\t\tintr_handle.queue_fd[queue_id], strerror(errno));\n \t} else\ndiff --git a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h\nindex 83b717c..c6982cf 100644\n--- a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h\n+++ b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h\n@@ -54,6 +54,7 @@ enum rte_intr_handle_type {\n struct rte_intr_handle {\n \tint vfio_dev_fd;                 /**< VFIO device file descriptor */\n \tint fd;                          /**< file descriptor */\n+\tint max_intr;                    /**< max interrupt requested */\n \tint queue_fd[VFIO_MAX_QUEUE_ID]; /**< rx and tx queue interrupt file descriptor */\n \tenum rte_intr_handle_type type;  /**< handle type */\n };\ndiff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c\nindex 1d694c5..368e4db 100644\n--- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c\n+++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c\n@@ -187,11 +187,14 @@ static void ixgbe_dcb_init(struct ixgbe_hw *hw,struct ixgbe_dcb_config *dcb_conf\n /* For Virtual Function support */\n static int eth_ixgbevf_dev_init(struct eth_driver *eth_drv,\n \t\tstruct rte_eth_dev *eth_dev);\n+static int ixgbevf_dev_interrupt_get_status(struct rte_eth_dev *dev);\n+static int ixgbevf_dev_interrupt_action(struct rte_eth_dev *dev);\n static int  ixgbevf_dev_configure(struct rte_eth_dev *dev);\n static int  ixgbevf_dev_start(struct rte_eth_dev *dev);\n static void ixgbevf_dev_stop(struct rte_eth_dev *dev);\n static void ixgbevf_dev_close(struct rte_eth_dev *dev);\n static void ixgbevf_intr_disable(struct ixgbe_hw *hw);\n+static void ixgbevf_intr_enable(struct ixgbe_hw *hw);\n static void ixgbevf_dev_stats_get(struct rte_eth_dev *dev,\n \t\tstruct rte_eth_stats *stats);\n static void ixgbevf_dev_stats_reset(struct rte_eth_dev *dev);\n@@ -199,8 +202,15 @@ static int ixgbevf_vlan_filter_set(struct rte_eth_dev *dev,\n \t\tuint16_t vlan_id, int on);\n static void ixgbevf_vlan_strip_queue_set(struct rte_eth_dev *dev,\n \t\tuint16_t queue, int on);\n+static void ixgbevf_set_ivar(struct ixgbe_hw *hw, s8 direction, u8 queue, u8 msix_vector);\n static void ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask);\n static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on);\n+static void ixgbevf_dev_interrupt_handler(struct rte_intr_handle *handle,\n+\t\tvoid *param);\n+static int ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id);\n+static int ixgbevf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id);\n+static void ixgbevf_set_ivar(struct ixgbe_hw *hw, s8 direction, u8 queue, u8 msix_vector);\n+static void ixgbevf_configure_msix(struct  ixgbe_hw *hw);\n \n /* For Eth VMDQ APIs support */\n static int ixgbe_uc_hash_table_set(struct rte_eth_dev *dev, struct\n@@ -416,8 +426,11 @@ static struct eth_dev_ops ixgbevf_eth_dev_ops = {\n \t.vlan_offload_set     = ixgbevf_vlan_offload_set,\n \t.rx_queue_setup       = ixgbe_dev_rx_queue_setup,\n \t.rx_queue_release     = ixgbe_dev_rx_queue_release,\n+\t.rx_descriptor_done   = ixgbe_dev_rx_descriptor_done,\n \t.tx_queue_setup       = ixgbe_dev_tx_queue_setup,\n \t.tx_queue_release     = ixgbe_dev_tx_queue_release,\n+\t.rx_queue_intr_enable = ixgbevf_dev_rx_queue_intr_enable,\n+\t.rx_queue_intr_disable = ixgbevf_dev_rx_queue_intr_disable,\n \t.mac_addr_add         = ixgbevf_add_mac_addr,\n \t.mac_addr_remove      = ixgbevf_remove_mac_addr,\n };\n@@ -912,6 +925,9 @@ eth_ixgbe_dev_init(__attribute__((unused)) struct eth_driver *eth_drv,\n \t\t\teth_dev->data->port_id, pci_dev->id.vendor_id,\n \t\t\tpci_dev->id.device_id);\n \n+\t/* set max interrupt vfio request */\n+\tpci_dev->intr_handle.max_intr = hw->mac.max_rx_queues + IXGBE_MAX_OTHER_INTR;\n+\n \trte_intr_callback_register(&(pci_dev->intr_handle),\n \t\tixgbe_dev_interrupt_handler, (void *)eth_dev);\n \n@@ -1088,6 +1104,14 @@ eth_ixgbevf_dev_init(__attribute__((unused)) struct eth_driver *eth_drv,\n \t\t\treturn (-EIO);\n \t}\n \n+\t/* set max interrupt vfio request */\n+\tpci_dev->intr_handle.max_intr = hw->mac.max_rx_queues + IXGBEVF_MAX_OTHER_INTR;\n+\n+\trte_intr_callback_register(&(pci_dev->intr_handle),\n+\t\tixgbevf_dev_interrupt_handler, (void *)eth_dev);\n+\n+\trte_intr_enable(&(pci_dev->intr_handle));\n+\n \tPMD_INIT_LOG(DEBUG, \"port %d vendorID=0x%x deviceID=0x%x mac.type=%s\",\n \t\t     eth_dev->data->port_id, pci_dev->id.vendor_id,\n \t\t     pci_dev->id.device_id, \"ixgbe_mac_82599_vf\");\n@@ -2286,6 +2310,30 @@ ixgbe_dev_interrupt_get_status(struct rte_eth_dev *dev)\n \treturn 0;\n }\n \n+static int\n+ixgbevf_dev_interrupt_get_status(struct rte_eth_dev *dev)\n+{\n+\tuint32_t eicr;\n+\tstruct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\tstruct ixgbe_interrupt *intr =\n+\t\tIXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);\n+\n+\t/* clear all cause mask */\n+\tixgbevf_intr_disable(hw);\n+\n+\t/* read-on-clear nic registers here */\n+\teicr = IXGBE_READ_REG(hw, IXGBE_VTEICR);\n+\tPMD_DRV_LOG(INFO, \"eicr %x\", eicr);\n+\n+\tintr->flags = 0;\n+\n+\t/* set flag for async link update */\n+\tif (eicr & IXGBE_EICR_LSC)\n+\t\tintr->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;\n+\n+\treturn 0;\n+}\n+\n /**\n  * It gets and then prints the link status.\n  *\n@@ -2381,6 +2429,18 @@ ixgbe_dev_interrupt_action(struct rte_eth_dev *dev)\n \treturn 0;\n }\n \n+static int\n+ixgbevf_dev_interrupt_action(struct rte_eth_dev *dev)\n+{\n+\tstruct ixgbe_hw *hw =\n+\t\tIXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\n+\tPMD_DRV_LOG(DEBUG, \"enable intr immediately\");\n+\tixgbevf_intr_enable(hw);\n+\trte_intr_enable(&(dev->pci_dev->intr_handle));\n+\treturn 0;\n+}\n+\n /**\n  * Interrupt handler which shall be registered for alarm callback for delayed\n  * handling specific interrupt to wait for the stable nic state. As the\n@@ -2442,6 +2502,15 @@ ixgbe_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle,\n \tixgbe_dev_interrupt_action(dev);\n }\n \n+static void\n+ixgbevf_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle,\n+\t\t\t\t\t\t\tvoid *param)\n+{\n+\tstruct rte_eth_dev *dev = (struct rte_eth_dev *)param;\n+\tixgbevf_dev_interrupt_get_status(dev);\n+\tixgbevf_dev_interrupt_action(dev);\n+}\n+\n static int\n ixgbe_dev_led_on(struct rte_eth_dev *dev)\n {\n@@ -2940,6 +3009,19 @@ ixgbevf_intr_disable(struct ixgbe_hw *hw)\n \tIXGBE_WRITE_FLUSH(hw);\n }\n \n+static void\n+ixgbevf_intr_enable(struct ixgbe_hw *hw)\n+{\n+\tPMD_INIT_FUNC_TRACE();\n+\n+\t/* VF enable interrupt autoclean */\n+\tIXGBE_WRITE_REG(hw, IXGBE_VTEIAM, IXGBE_VF_IRQ_ENABLE_MASK);\n+\tIXGBE_WRITE_REG(hw, IXGBE_VTEIAC, IXGBE_VF_IRQ_ENABLE_MASK);\n+\tIXGBE_WRITE_REG(hw, IXGBE_VTEIMS, IXGBE_VF_IRQ_ENABLE_MASK);\n+\n+\tIXGBE_WRITE_FLUSH(hw);\n+}\n+\n static int\n ixgbevf_dev_configure(struct rte_eth_dev *dev)\n {\n@@ -3002,6 +3084,11 @@ ixgbevf_dev_start(struct rte_eth_dev *dev)\n \n \tixgbevf_dev_rxtx_start(dev);\n \n+\tixgbevf_configure_msix(hw);\n+\n+\t/* Re-enable interrupt for VF */\n+\tixgbevf_intr_enable(hw);\n+\n \treturn 0;\n }\n \n@@ -3539,6 +3626,33 @@ ixgbe_mirror_rule_reset(struct rte_eth_dev *dev, uint8_t rule_id)\n \treturn 0;\n }\n \n+\n+static int\n+ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)\n+{\n+\tuint32_t mask;\n+\tstruct ixgbe_hw *hw =\n+\t\tIXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\tmask = IXGBE_READ_REG(hw, IXGBE_VTEIMS);\n+\tmask |= ( 1 << queue_id);\n+\tIXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask);\n+\n+\treturn 0;\n+}\n+\n+static int\n+ixgbevf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)\n+{\n+\tuint32_t mask;\n+\tstruct ixgbe_hw *hw =\n+\t\tIXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\tmask = IXGBE_READ_REG(hw, IXGBE_VTEIMS);\n+\tmask &= ~( 1 << queue_id);\n+\tIXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask);\n+\n+\treturn 0;\n+}\n+\n static int\n ixgbe_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)\n {\n@@ -3591,6 +3705,29 @@ ixgbe_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)\n \treturn 0;\n }\n \n+static void\n+ixgbevf_set_ivar(struct ixgbe_hw *hw, s8 direction,\n+\t\t\tu8 queue, u8 msix_vector)\n+{\n+\tu32 ivar, index;\n+\tif (direction == -1) {\n+\t\t/* other causes */\n+\t\tmsix_vector |= IXGBE_IVAR_ALLOC_VAL;\n+\t\tivar = IXGBE_READ_REG(hw, IXGBE_VTIVAR_MISC);\n+\t\tivar &= ~0xFF;\n+\t\tivar |= msix_vector;\n+\t\tIXGBE_WRITE_REG(hw, IXGBE_VTIVAR_MISC, ivar);\n+\t} else {\n+\t\t/* tx or tx cause */\n+\t\tmsix_vector |= IXGBE_IVAR_ALLOC_VAL;\n+\t\tindex = ((16 * (queue & 1)) + (8 * direction));\n+\t\tivar = IXGBE_READ_REG(hw, IXGBE_VTIVAR(queue >> 1));\n+\t\tivar &= ~(0xFF << index);\n+\t\tivar |= (msix_vector << index);\n+\t\tIXGBE_WRITE_REG(hw, IXGBE_VTIVAR(queue >> 1), ivar);\n+\t}\n+}\n+\n /**\n  * ixgbe_set_ivar - set the IVAR registers, mapping interrupt causes to vectors\n  * @hw: pointer to ixgbe_hw struct\n@@ -3640,6 +3777,22 @@ ixgbe_set_ivar(struct ixgbe_hw *hw, s8 direction,\n \t}\n }\n \n+\n+static void\n+ixgbevf_configure_msix(struct ixgbe_hw *hw)\n+{\n+\tu32 queue_idx, vector_idx;\n+\t/* Configure all RX queues of VF */\n+\tfor (vector_idx = 0; vector_idx < IXGBE_VF_MAXMSIVECTOR; vector_idx ++)\n+\t{\n+\t\tfor (queue_idx = 0; queue_idx < (hw->mac.max_rx_queues - 1); queue_idx++)\n+\t\t\tixgbevf_set_ivar(hw, 0, queue_idx, vector_idx);\n+\t}\n+\n+\t/* Configure VF Rx queue ivar */\n+\tixgbevf_set_ivar(hw, -1, 1, vector_idx);\n+}\n+\n /**\n  * ixgbe_configure_msix - Configure MSI-X hardware\n  * @hw: board private structure\ndiff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h\nindex 730098d..b0221cf 100644\n--- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h\n+++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h\n@@ -98,6 +98,11 @@\n #define IXGBE_5TUPLE_MAX_PRI            7\n #define IXGBE_5TUPLE_MIN_PRI            1\n \n+#define IXGBE_VF_IRQ_ENABLE_MASK        3          /* vf interrupt enable mask */\n+#define IXGBE_VF_MAXMSIVECTOR\t\t\t1\n+/* maximum other interrupts besides rx&tx*/\n+#define IXGBE_MAX_OTHER_INTR\t\t1\n+#define IXGBEVF_MAX_OTHER_INTR\t\t1\n /*\n  * Information about the fdir mode.\n  */\n@@ -247,6 +252,7 @@ uint32_t ixgbe_dev_rx_queue_count(struct rte_eth_dev *dev,\n \t\tuint16_t rx_queue_id);\n \n int ixgbe_dev_rx_descriptor_done(void *rx_queue, uint16_t offset);\n+int ixgbevf_dev_rx_descriptor_done(void *rx_queue, uint16_t offset);\n \n int ixgbe_dev_rx_init(struct rte_eth_dev *dev);\n \n",
    "prefixes": [
        "dpdk-dev",
        "RFC",
        "5/5"
    ]
}