Show a patch.

GET /api/patches/391/
Content-Type: application/json
Vary: Accept

    "id": 391,
    "url": "",
    "web_url": "",
    "project": {
        "id": 1,
        "url": "",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "",
        "list_email": "",
        "web_url": "",
        "scm_url": "git://",
        "webscm_url": ""
    "msgid": "<>",
    "date": "2014-09-17T07:54:21",
    "name": "[dpdk-dev,3/3] i40e: fix of interrupt based link status change",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "e5d39be172360cb68461b6ad229612a734a1b7e8",
    "submitter": {
        "id": 14,
        "url": "",
        "name": "Helin Zhang",
        "email": ""
    "delegate": null,
    "mbox": "",
    "series": [],
    "comments": "",
    "check": "pending",
    "checks": "",
    "tags": {},
    "headers": {
        "Return-Path": "<>",
        "References": "<>",
        "X-Mailman-Version": "2.1.15",
        "X-IronPort-AV": "E=Sophos;i=\"5.04,539,1406617200\"; d=\"scan'208\";a=\"478067643\"",
        "Date": "Wed, 17 Sep 2014 15:54:21 +0800",
        "List-Help": "<>",
        "X-BeenThere": "",
        "Message-Id": "<>",
        "X-Original-To": "",
        "Received": [
            "from [] (localhost [IPv6:::1])\n\tby (Postfix) with ESMTP id 5F56CB3AB;\n\tWed, 17 Sep 2014 09:49:02 +0200 (CEST)",
            "from ( [])\n\tby (Postfix) with ESMTP id 1666BAFD1\n\tfor <>; Wed, 17 Sep 2014 09:48:58 +0200 (CEST)",
            "from ([])\n\tby with ESMTP; 17 Sep 2014 00:45:43 -0700",
            "from ([])\n\tby with ESMTP; 17 Sep 2014 00:54:32 -0700",
            "from (\n\t[])\n\tby with ESMTP id s8H7sVvX024956;\n\tWed, 17 Sep 2014 15:54:31 +0800",
            "from (localhost [])\n\tby (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP\n\tid s8H7sT4Q017566; Wed, 17 Sep 2014 15:54:31 +0800",
            "(from hzhan75@localhost)\n\tby (8.13.6/8.13.6/Submit) id s8H7sTIb017562; \n\tWed, 17 Sep 2014 15:54:29 +0800"
        "List-Post": "<>",
        "Subject": "[dpdk-dev] [PATCH 3/3] i40e: fix of interrupt based link status\n\tchange",
        "Sender": "\"dev\" <>",
        "X-Mailer": "git-send-email",
        "Precedence": "list",
        "From": "Helin Zhang <>",
        "List-Archive": "<>",
        "X-ExtLoop1": "1",
        "List-Subscribe": "<>,\n\t<>",
        "List-Id": "patches and discussions about DPDK <>",
        "Delivered-To": "",
        "In-Reply-To": "<>",
        "List-Unsubscribe": "<>,\n\t<>",
        "To": "",
        "Errors-To": ""
    "content": "As driver flag of 'RTE_PCI_DRV_INTR_LSC' was introduced\nrecently, it must be added in i40e. One second waiting\nis needed for link up event, to wait the hardware into a\nstable state, so the interrupt could be processed in two\nparts. In addition, it should finally call the callback\nfunction registered by application.\n\nSigned-off-by: Helin Zhang <>\nReviewed-by: Jing Chen <>\nReviewed-by: Jijiang Liu <>\n---\n lib/librte_pmd_i40e/i40e_ethdev.c | 88 +++++++++++++++++++++++++++++++++++----\n 1 file changed, 80 insertions(+), 8 deletions(-)",
    "diff": "diff --git a/lib/librte_pmd_i40e/i40e_ethdev.c b/lib/librte_pmd_i40e/i40e_ethdev.c\nindex 6df41ea..e223d3a 100644\n--- a/lib/librte_pmd_i40e/i40e_ethdev.c\n+++ b/lib/librte_pmd_i40e/i40e_ethdev.c\n@@ -47,6 +47,7 @@\n #include <rte_memzone.h>\n #include <rte_malloc.h>\n #include <rte_memcpy.h>\n+#include <rte_alarm.h>\n #include <rte_dev.h>\n \n #include \"i40e_logs.h\"\n@@ -275,7 +276,7 @@ static struct eth_driver rte_i40e_pmd = {\n \t{\n \t\ = \"rte_i40e_pmd\",\n \t\t.id_table = pci_id_i40e_map,\n-\t\t.drv_flags = RTE_PCI_DRV_NEED_MAPPING,\n+\t\t.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,\n \t},\n \t.eth_dev_init = eth_i40e_dev_init,\n \t.dev_private_size = sizeof(struct i40e_adapter),\n@@ -3371,6 +3372,58 @@ i40e_dev_handle_aq_msg(struct rte_eth_dev *dev)\n \trte_free(info.msg_buf);\n }\n \n+/*\n+ * Interrupt handler is registered as the alarm callback for handling LSC\n+ * interrupt in a definite of time, in order to wait the NIC into a stable\n+ * state. Currently it waits 1 sec in i40e for the link up interrupt, and\n+ * no need for link down interrupt.\n+ */\n+static void\n+i40e_dev_interrupt_delayed_handler(void *param)\n+{\n+\tstruct rte_eth_dev *dev = (struct rte_eth_dev *)param;\n+\tstruct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\tuint32_t icr0;\n+\n+\t/* read interrupt causes again */\n+\ticr0 = I40E_READ_REG(hw, I40E_PFINT_ICR0);\n+\n+#ifdef RTE_LIBRTE_I40E_DEBUG_DRIVER\n+\tif (icr0 & I40E_PFINT_ICR0_ECC_ERR_MASK)\n+\t\tPMD_DRV_LOG(ERR, \"ICR0: unrecoverable ECC error\\n\");\n+\tif (icr0 & I40E_PFINT_ICR0_MAL_DETECT_MASK)\n+\t\tPMD_DRV_LOG(ERR, \"ICR0: malicious programming detected\\n\");\n+\tif (icr0 & I40E_PFINT_ICR0_GRST_MASK)\n+\t\tPMD_DRV_LOG(INFO, \"ICR0: global reset requested\\n\");\n+\tif (icr0 & I40E_PFINT_ICR0_PCI_EXCEPTION_MASK)\n+\t\tPMD_DRV_LOG(INFO, \"ICR0: PCI exception\\n activated\\n\");\n+\tif (icr0 & I40E_PFINT_ICR0_STORM_DETECT_MASK)\n+\t\tPMD_DRV_LOG(INFO, \"ICR0: a change in the storm control \"\n+\t\t\t\t\t\t\t\t\"state\\n\");\n+\tif (icr0 & I40E_PFINT_ICR0_HMC_ERR_MASK)\n+\t\tPMD_DRV_LOG(ERR, \"ICR0: HMC error\\n\");\n+\tif (icr0 & I40E_PFINT_ICR0_PE_CRITERR_MASK)\n+\t\tPMD_DRV_LOG(ERR, \"ICR0: protocol engine critical error\\n\");\n+#endif /* RTE_LIBRTE_I40E_DEBUG_DRIVER */\n+\n+\tif (icr0 & I40E_PFINT_ICR0_VFLR_MASK) {\n+\t\tPMD_DRV_LOG(INFO, \"INT:VF reset detected\\n\");\n+\t\ti40e_dev_handle_vfr_event(dev);\n+\t}\n+\tif (icr0 & I40E_PFINT_ICR0_ADMINQ_MASK) {\n+\t\tPMD_DRV_LOG(INFO, \"INT:ADMINQ event\\n\");\n+\t\ti40e_dev_handle_aq_msg(dev);\n+\t}\n+\n+\t/* handle the link up interrupt in an alarm callback */\n+\ti40e_dev_link_update(dev, 0);\n+\t_rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC);\n+\n+\tI40E_WRITE_REG(hw, I40E_PFINT_ICR0_ENA, I40E_PFINT_ICR0_ENA_MASK);\n+\ti40e_pf_enable_irq0(hw);\n+\trte_intr_enable(&(dev->pci_dev->intr_handle));\n+}\n+\n /**\n  * Interrupt handler triggered by NIC  for handling\n  * specific interrupt.\n@@ -3389,19 +3442,20 @@ i40e_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle,\n {\n \tstruct rte_eth_dev *dev = (struct rte_eth_dev *)param;\n \tstruct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n-\tuint32_t icr0, icr0_ena;\n+\tuint32_t icr0;\n \n+\t/* Disable interrupt */\n \ti40e_pf_disable_irq0(hw);\n+\tI40E_WRITE_REG(hw, I40E_PFINT_ICR0_ENA, 0);\n \n+\t/* read out interrupt causes */\n \ticr0 = I40E_READ_REG(hw, I40E_PFINT_ICR0);\n-\ticr0_ena = I40E_READ_REG(hw, I40E_PFINT_ICR0_ENA);\n \n \t/* No interrupt event indicated */\n \tif (!(icr0 & I40E_PFINT_ICR0_INTEVENT_MASK)) {\n \t\tPMD_DRV_LOG(INFO, \"No interrupt event\\n\");\n \t\tgoto done;\n \t}\n-\n #ifdef RTE_LIBRTE_I40E_DEBUG_DRIVER\n \tif (icr0 & I40E_PFINT_ICR0_ECC_ERR_MASK)\n \t\tPMD_DRV_LOG(ERR, \"ICR0: unrecoverable ECC error\\n\");\n@@ -3429,16 +3483,34 @@ i40e_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle,\n \t\ti40e_dev_handle_aq_msg(dev);\n \t}\n \n+\t/* Link Status Change interrupt */\n \tif (icr0 & I40E_PFINT_ICR0_LINK_STAT_CHANGE_MASK) {\n-\t\tPMD_DRV_LOG(INFO, \"INT:Link status changed\\n\");\n+#define I40E_US_PER_SECOND 1000000\n+\t\tstruct rte_eth_link link;\n+\n+\t\tPMD_DRV_LOG(INFO, \"ICR0: link status changed\\n\");\n+\t\tmemset(&link, 0, sizeof(link));\n+\t\trte_i40e_dev_atomic_read_link_status(dev, &link);\n \t\ti40e_dev_link_update(dev, 0);\n+\n+\t\t/*\n+\t\t * For link up interrupt, it needs to wait 1 second to let the\n+\t\t * hardware be a stable state. Otherwise several consecutive\n+\t\t * interrupts can be observed.\n+\t\t * For link down interrupt, no need to wait.\n+\t\t */\n+\t\tif (!link.link_status && rte_eal_alarm_set(I40E_US_PER_SECOND,\n+\t\t\ti40e_dev_interrupt_delayed_handler, (void *)dev) >= 0)\n+\t\t\treturn;\n+\t\telse\n+\t\t\t_rte_eth_dev_callback_process(dev,\n+\t\t\t\tRTE_ETH_EVENT_INTR_LSC);\n \t}\n \n done:\n-\tI40E_WRITE_REG(hw, I40E_PFINT_ICR0_ENA, icr0_ena);\n-\t/* Re-enable interrupt from device side */\n+\t/* Enable interrupt */\n+\tI40E_WRITE_REG(hw, I40E_PFINT_ICR0_ENA, I40E_PFINT_ICR0_ENA_MASK);\n \ti40e_pf_enable_irq0(hw);\n-\t/* Re-enable interrupt from host side */\n \trte_intr_enable(&(dev->pci_dev->intr_handle));\n }\n \n",
    "prefixes": [