get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 522527,
    "url": "http://patchwork.ozlabs.org/api/patches/522527/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/1443123983-86865-1-git-send-email-catherine.sullivan@intel.com/",
    "project": {
        "id": 46,
        "url": "http://patchwork.ozlabs.org/api/projects/46/?format=api",
        "name": "Intel Wired Ethernet development",
        "link_name": "intel-wired-lan",
        "list_id": "intel-wired-lan.osuosl.org",
        "list_email": "intel-wired-lan@osuosl.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<1443123983-86865-1-git-send-email-catherine.sullivan@intel.com>",
    "list_archive_url": null,
    "date": "2015-09-24T19:46:23",
    "name": "[next,2/2,v2] i40e/i40evf: refactor tx timeout logic",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "aead891086bcc68617e03a3aa1d4d61c00dc1dfe",
    "submitter": {
        "id": 13931,
        "url": "http://patchwork.ozlabs.org/api/people/13931/?format=api",
        "name": "Catherine Sullivan",
        "email": "catherine.sullivan@intel.com"
    },
    "delegate": {
        "id": 68,
        "url": "http://patchwork.ozlabs.org/api/users/68/?format=api",
        "username": "jtkirshe",
        "first_name": "Jeff",
        "last_name": "Kirsher",
        "email": "jeffrey.t.kirsher@intel.com"
    },
    "mbox": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/1443123983-86865-1-git-send-email-catherine.sullivan@intel.com/mbox/",
    "series": [],
    "comments": "http://patchwork.ozlabs.org/api/patches/522527/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/522527/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<intel-wired-lan-bounces@lists.osuosl.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "intel-wired-lan@lists.osuosl.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@bilbo.ozlabs.org",
            "intel-wired-lan@lists.osuosl.org"
        ],
        "Received": [
            "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\tby ozlabs.org (Postfix) with ESMTP id 6BF02140775\n\tfor <incoming@patchwork.ozlabs.org>;\n\tFri, 25 Sep 2015 05:46:57 +1000 (AEST)",
            "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id BE18F95674;\n\tThu, 24 Sep 2015 19:46:56 +0000 (UTC)",
            "from hemlock.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id cIUuciGZhddB; Thu, 24 Sep 2015 19:46:55 +0000 (UTC)",
            "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 713F795648;\n\tThu, 24 Sep 2015 19:46:55 +0000 (UTC)",
            "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\tby ash.osuosl.org (Postfix) with ESMTP id 72D191C15FC\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 24 Sep 2015 19:46:53 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 6D13A9566A\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 24 Sep 2015 19:46:53 +0000 (UTC)",
            "from hemlock.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id MGYQdy2jQfLw for <intel-wired-lan@lists.osuosl.org>;\n\tThu, 24 Sep 2015 19:46:51 +0000 (UTC)",
            "from mga14.intel.com (mga14.intel.com [192.55.52.115])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id AEA9395648\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 24 Sep 2015 19:46:51 +0000 (UTC)",
            "from fmsmga001.fm.intel.com ([10.253.24.23])\n\tby fmsmga103.fm.intel.com with ESMTP; 24 Sep 2015 12:46:29 -0700",
            "from catheri1-tigger.jf.intel.com ([134.134.176.92])\n\tby fmsmga001.fm.intel.com with ESMTP; 24 Sep 2015 12:46:29 -0700"
        ],
        "X-Virus-Scanned": [
            "amavisd-new at osuosl.org",
            "amavisd-new at osuosl.org"
        ],
        "X-Greylist": "domain auto-whitelisted by SQLgrey-1.7.6",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.17,582,1437462000\"; d=\"scan'208\";a=\"796684515\"",
        "From": "Catherine Sullivan <catherine.sullivan@intel.com>",
        "To": "intel-wired-lan@lists.osuosl.org",
        "Date": "Thu, 24 Sep 2015 15:46:23 -0400",
        "Message-Id": "<1443123983-86865-1-git-send-email-catherine.sullivan@intel.com>",
        "X-Mailer": "git-send-email 1.9.3",
        "Subject": "[Intel-wired-lan] [next PATCH 2/2 v2] i40e/i40evf: refactor tx\n\ttimeout logic",
        "X-BeenThere": "intel-wired-lan@lists.osuosl.org",
        "X-Mailman-Version": "2.1.18-1",
        "Precedence": "list",
        "List-Id": "Intel Wired Ethernet Linux Kernel Driver Development\n\t<intel-wired-lan.lists.osuosl.org>",
        "List-Unsubscribe": "<http://lists.osuosl.org/mailman/options/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@lists.osuosl.org?subject=unsubscribe>",
        "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>",
        "List-Post": "<mailto:intel-wired-lan@lists.osuosl.org>",
        "List-Help": "<mailto:intel-wired-lan-request@lists.osuosl.org?subject=help>",
        "List-Subscribe": "<http://lists.osuosl.org/mailman/listinfo/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@lists.osuosl.org?subject=subscribe>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Errors-To": "intel-wired-lan-bounces@lists.osuosl.org",
        "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@lists.osuosl.org>"
    },
    "content": "From: Kiran Patil <kiran.patil@intel.com>\n\nThis patch modifies the driver timeout logic by issuing a writeback\nrequest via a software interrupt to the hardware the first time the\ndriver detects a hang. The driver was too agrressive in resetting a hung\nqueue, so back that off by removing logic to down the netdevice after\ntoo many hangs, and move the function to the service task.\n\nSigned-off-by: Kiran Patil <kiran.patil@intel.com>\nSigned-off-by: Shannon Nelson <shannon.nelson@intel.com>\nSigned-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>\nChange-ID: Ife100b9d124cd08cbdb81ab659008c1b9abbedea\n\n---\nv2: Fix author to Kiran.\n\nHSD-number: 5644407,5644501,5644189,5644320,5644525,5644616,5645042\n drivers/net/ethernet/intel/i40e/i40e.h        |   1 -\n drivers/net/ethernet/intel/i40e/i40e_main.c   | 274 +++++++++++++++-----------\n drivers/net/ethernet/intel/i40e/i40e_txrx.c   |  75 +------\n drivers/net/ethernet/intel/i40e/i40e_txrx.h   |  10 +-\n drivers/net/ethernet/intel/i40evf/i40e_txrx.c |  96 +--------\n drivers/net/ethernet/intel/i40evf/i40e_txrx.h |   8 -\n 6 files changed, 173 insertions(+), 291 deletions(-)",
    "diff": "diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h\nindex e1cd8ac..ad18f99 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e.h\n+++ b/drivers/net/ethernet/intel/i40e/i40e.h\n@@ -246,7 +246,6 @@ struct i40e_pf {\n \tstruct pci_dev *pdev;\n \tstruct i40e_hw hw;\n \tunsigned long state;\n-\tunsigned long link_check_timeout;\n \tstruct msix_entry *msix_entries;\n \tbool fc_autoneg_status;\n \ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c\nindex f048002..e47afbe 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_main.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c\n@@ -302,25 +302,69 @@ static void i40e_tx_timeout(struct net_device *netdev)\n \tstruct i40e_netdev_priv *np = netdev_priv(netdev);\n \tstruct i40e_vsi *vsi = np->vsi;\n \tstruct i40e_pf *pf = vsi->back;\n+\tstruct i40e_ring *tx_ring = NULL;\n+\tunsigned int i, hung_queue = 0;\n+\tu32 head, val;\n \n \tpf->tx_timeout_count++;\n \n+\t/* find the stopped queue the same way the stack does */\n+\tfor (i = 0; i < netdev->num_tx_queues; i++) {\n+\t\tstruct netdev_queue *q;\n+\t\tunsigned long trans_start;\n+\n+\t\tq = netdev_get_tx_queue(netdev, i);\n+\t\ttrans_start = q->trans_start ? : netdev->trans_start;\n+\t\tif (netif_xmit_stopped(q) &&\n+\t\t    time_after(jiffies,\n+\t\t\t       (trans_start + netdev->watchdog_timeo))) {\n+\t\t\thung_queue = i;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tif (i == netdev->num_tx_queues) {\n+\t\tnetdev_info(netdev, \"tx_timeout: no netdev hung queue found\\n\");\n+\t} else {\n+\t\t/* now that we have an index, find the tx_ring struct */\n+\t\tfor (i = 0; i < vsi->num_queue_pairs; i++) {\n+\t\t\tif (vsi->tx_rings[i] && vsi->tx_rings[i]->desc) {\n+\t\t\t\tif (hung_queue ==\n+\t\t\t\t\t\tvsi->tx_rings[i]->queue_index) {\n+\t\t\t\t\ttx_ring = vsi->tx_rings[i];\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n+\n \tif (time_after(jiffies, (pf->tx_timeout_last_recovery + HZ*20)))\n-\t\tpf->tx_timeout_recovery_level = 1;\n+\t\tpf->tx_timeout_recovery_level = 1;  /* reset after some time */\n+\telse if (time_before(jiffies,\n+\t\t      (pf->tx_timeout_last_recovery + netdev->watchdog_timeo)))\n+\t\treturn;   /* don't do any new action before the next timeout */\n+\n+\tif (tx_ring) {\n+\t\thead = i40e_get_head(tx_ring);\n+\t\t/* Read interrupt register */\n+\t\tif (pf->flags & I40E_FLAG_MSIX_ENABLED)\n+\t\t\tval = rd32(&pf->hw,\n+\t\t\t     I40E_PFINT_DYN_CTLN(tx_ring->q_vector->v_idx +\n+\t\t\t\t\ttx_ring->vsi->base_vector - 1));\n+\t\telse\n+\t\t\tval = rd32(&pf->hw, I40E_PFINT_DYN_CTL0);\n+\n+\t\tnetdev_info(netdev, \"tx_timeout: VSI_seid: %d, Q %d, NTC: 0x%x, HWB: 0x%x, NTU: 0x%x, TAIL: 0x%x, INT: 0x%x\\n\",\n+\t\t\t    vsi->seid, hung_queue, tx_ring->next_to_clean,\n+\t\t\t    head, tx_ring->next_to_use,\n+\t\t\t    readl(tx_ring->tail), val);\n+\t}\n+\n \tpf->tx_timeout_last_recovery = jiffies;\n-\tnetdev_info(netdev, \"tx_timeout recovery level %d\\n\",\n-\t\t    pf->tx_timeout_recovery_level);\n+\tnetdev_info(netdev, \"tx_timeout recovery level %d, hung_queue %d\\n\",\n+\t\t    pf->tx_timeout_recovery_level, hung_queue);\n \n \tswitch (pf->tx_timeout_recovery_level) {\n-\tcase 0:\n-\t\t/* disable and re-enable queues for the VSI */\n-\t\tif (in_interrupt()) {\n-\t\t\tset_bit(__I40E_REINIT_REQUESTED, &pf->state);\n-\t\t\tset_bit(__I40E_REINIT_REQUESTED, &vsi->state);\n-\t\t} else {\n-\t\t\ti40e_vsi_reinit_locked(vsi);\n-\t\t}\n-\t\tbreak;\n \tcase 1:\n \t\tset_bit(__I40E_PF_RESET_REQUESTED, &pf->state);\n \t\tbreak;\n@@ -332,10 +376,9 @@ static void i40e_tx_timeout(struct net_device *netdev)\n \t\tbreak;\n \tdefault:\n \t\tnetdev_err(netdev, \"tx_timeout recovery unsuccessful\\n\");\n-\t\tset_bit(__I40E_DOWN_REQUESTED, &pf->state);\n-\t\tset_bit(__I40E_DOWN_REQUESTED, &vsi->state);\n \t\tbreak;\n \t}\n+\n \ti40e_service_event_schedule(pf);\n \tpf->tx_timeout_recovery_level++;\n }\n@@ -758,7 +801,6 @@ static void i40e_update_link_xoff_rx(struct i40e_pf *pf)\n \tstruct i40e_hw_port_stats *nsd = &pf->stats;\n \tstruct i40e_hw *hw = &pf->hw;\n \tu64 xoff = 0;\n-\tu16 i, v;\n \n \tif ((hw->fc.current_mode != I40E_FC_FULL) &&\n \t    (hw->fc.current_mode != I40E_FC_RX_PAUSE))\n@@ -772,20 +814,6 @@ static void i40e_update_link_xoff_rx(struct i40e_pf *pf)\n \t/* No new LFC xoff rx */\n \tif (!(nsd->link_xoff_rx - xoff))\n \t\treturn;\n-\n-\t/* Clear the __I40E_HANG_CHECK_ARMED bit for all Tx rings */\n-\tfor (v = 0; v < pf->num_alloc_vsi; v++) {\n-\t\tstruct i40e_vsi *vsi = pf->vsi[v];\n-\n-\t\tif (!vsi || !vsi->tx_rings[0])\n-\t\t\tcontinue;\n-\n-\t\tfor (i = 0; i < vsi->num_queue_pairs; i++) {\n-\t\t\tstruct i40e_ring *ring = vsi->tx_rings[i];\n-\n-\t\t\tclear_bit(__I40E_HANG_CHECK_ARMED, &ring->state);\n-\t\t}\n-\t}\n }\n \n /**\n@@ -801,7 +829,7 @@ static void i40e_update_prio_xoff_rx(struct i40e_pf *pf)\n \tbool xoff[I40E_MAX_TRAFFIC_CLASS] = {false};\n \tstruct i40e_dcbx_config *dcb_cfg;\n \tstruct i40e_hw *hw = &pf->hw;\n-\tu16 i, v;\n+\tu16 i;\n \tu8 tc;\n \n \tdcb_cfg = &hw->local_dcbx_config;\n@@ -827,23 +855,6 @@ static void i40e_update_prio_xoff_rx(struct i40e_pf *pf)\n \t\ttc = dcb_cfg->etscfg.prioritytable[i];\n \t\txoff[tc] = true;\n \t}\n-\n-\t/* Clear the __I40E_HANG_CHECK_ARMED bit for Tx rings */\n-\tfor (v = 0; v < pf->num_alloc_vsi; v++) {\n-\t\tstruct i40e_vsi *vsi = pf->vsi[v];\n-\n-\t\tif (!vsi || !vsi->tx_rings[0])\n-\t\t\tcontinue;\n-\n-\t\tfor (i = 0; i < vsi->num_queue_pairs; i++) {\n-\t\t\tstruct i40e_ring *ring = vsi->tx_rings[i];\n-\n-\t\t\ttc = ring->dcb_tc;\n-\t\t\tif (xoff[tc])\n-\t\t\t\tclear_bit(__I40E_HANG_CHECK_ARMED,\n-\t\t\t\t\t  &ring->state);\n-\t\t}\n-\t}\n }\n \n /**\n@@ -2803,8 +2814,6 @@ static int i40e_configure_tx_ring(struct i40e_ring *ring)\n \twr32(hw, I40E_QTX_CTL(pf_q), qtx_ctl);\n \ti40e_flush(hw);\n \n-\tclear_bit(__I40E_HANG_CHECK_ARMED, &ring->state);\n-\n \t/* cache tail off for easier writes later */\n \tring->tail = hw->hw_addr + I40E_QTX_TAIL(pf_q);\n \n@@ -4316,6 +4325,108 @@ static int i40e_pf_wait_txq_disabled(struct i40e_pf *pf)\n }\n \n #endif\n+\n+/**\n+ * i40e_detect_recover_hung_queue - Function to detect and recover hung_queue\n+ * @q_idx: TX queue number\n+ * @vsi: Pointer to VSI struct\n+ *\n+ * This function checks specified queue for given VSI. Detects hung condition.\n+ * Sets hung bit since it is two step process. Before next run of service task\n+ * if napi_poll runs, it reset 'hung' bit for respective q_vector. If not,\n+ * hung condition remain unchanged and during subsequent run, this function\n+ * issues SW interrupt to recover from hung condition.\n+ **/\n+static void i40e_detect_recover_hung_queue(int q_idx, struct i40e_vsi *vsi)\n+{\n+\tstruct i40e_ring *tx_ring = NULL;\n+\tstruct i40e_pf\t*pf;\n+\tu32 head, val, tx_pending;\n+\tint i;\n+\n+\tpf = vsi->back;\n+\n+\t/* now that we have an index, find the tx_ring struct */\n+\tfor (i = 0; i < vsi->num_queue_pairs; i++) {\n+\t\tif (vsi->tx_rings[i] && vsi->tx_rings[i]->desc) {\n+\t\t\tif (q_idx == vsi->tx_rings[i]->queue_index) {\n+\t\t\t\ttx_ring = vsi->tx_rings[i];\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tif (!tx_ring)\n+\t\treturn;\n+\n+\t/* Read interrupt register */\n+\tif (pf->flags & I40E_FLAG_MSIX_ENABLED)\n+\t\tval = rd32(&pf->hw,\n+\t\t\t   I40E_PFINT_DYN_CTLN(tx_ring->q_vector->v_idx +\n+\t\t\t\t\t       tx_ring->vsi->base_vector - 1));\n+\telse\n+\t\tval = rd32(&pf->hw, I40E_PFINT_DYN_CTL0);\n+\n+\thead = i40e_get_head(tx_ring);\n+\n+\ttx_pending = i40e_get_tx_pending(tx_ring);\n+\n+\t/* Interrupts are disabled and TX pending is non-zero,\n+\t * trigger the SW interrupt (don't wait). Worst case\n+\t * there will be one extra interrupt which may result\n+\t * into not cleaning any queues because queues are cleaned.\n+\t */\n+\tif (tx_pending && (!(val & I40E_PFINT_DYN_CTLN_INTENA_MASK)))\n+\t\ti40e_force_wb(vsi, tx_ring->q_vector);\n+}\n+\n+/**\n+ * i40e_detect_recover_hung - Function to detect and recover hung_queues\n+ * @pf:  pointer to PF struct\n+ *\n+ * LAN VSI has netdev and netdev has TX queues. This function is to check\n+ * each of those TX queues if they are hung, trigger recovery by issuing\n+ * SW interrupt.\n+ **/\n+static void i40e_detect_recover_hung(struct i40e_pf *pf)\n+{\n+\tstruct net_device *netdev;\n+\tstruct i40e_vsi *vsi;\n+\tint i;\n+\n+\t/* Only for LAN VSI */\n+\tvsi = pf->vsi[pf->lan_vsi];\n+\n+\tif (!vsi)\n+\t\treturn;\n+\n+\t/* Make sure, VSI state is not DOWN/RECOVERY_PENDING */\n+\tif (test_bit(__I40E_DOWN, &vsi->back->state) ||\n+\t    test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state))\n+\t\treturn;\n+\n+\t/* Make sure type is MAIN VSI */\n+\tif (vsi->type != I40E_VSI_MAIN)\n+\t\treturn;\n+\n+\tnetdev = vsi->netdev;\n+\tif (!netdev)\n+\t\treturn;\n+\n+\t/* Bail out if netif_carrier is not OK */\n+\tif (!netif_carrier_ok(netdev))\n+\t\treturn;\n+\n+\t/* Go thru' TX queues for netdev */\n+\tfor (i = 0; i < netdev->num_tx_queues; i++) {\n+\t\tstruct netdev_queue *q;\n+\n+\t\tq = netdev_get_tx_queue(netdev, i);\n+\t\tif (q)\n+\t\t\ti40e_detect_recover_hung_queue(i, vsi);\n+\t}\n+}\n+\n /**\n  * i40e_get_iscsi_tc_map - Return TC map for iSCSI APP\n  * @pf: pointer to PF\n@@ -5949,68 +6060,6 @@ static void i40e_link_event(struct i40e_pf *pf)\n }\n \n /**\n- * i40e_check_hang_subtask - Check for hung queues and dropped interrupts\n- * @pf: board private structure\n- *\n- * Set the per-queue flags to request a check for stuck queues in the irq\n- * clean functions, then force interrupts to be sure the irq clean is called.\n- **/\n-static void i40e_check_hang_subtask(struct i40e_pf *pf)\n-{\n-\tint i, v;\n-\n-\t/* If we're down or resetting, just bail */\n-\tif (test_bit(__I40E_DOWN, &pf->state) ||\n-\t    test_bit(__I40E_CONFIG_BUSY, &pf->state))\n-\t\treturn;\n-\n-\t/* for each VSI/netdev\n-\t *     for each Tx queue\n-\t *         set the check flag\n-\t *     for each q_vector\n-\t *         force an interrupt\n-\t */\n-\tfor (v = 0; v < pf->num_alloc_vsi; v++) {\n-\t\tstruct i40e_vsi *vsi = pf->vsi[v];\n-\t\tint armed = 0;\n-\n-\t\tif (!pf->vsi[v] ||\n-\t\t    test_bit(__I40E_DOWN, &vsi->state) ||\n-\t\t    (vsi->netdev && !netif_carrier_ok(vsi->netdev)))\n-\t\t\tcontinue;\n-\n-\t\tfor (i = 0; i < vsi->num_queue_pairs; i++) {\n-\t\t\tset_check_for_tx_hang(vsi->tx_rings[i]);\n-\t\t\tif (test_bit(__I40E_HANG_CHECK_ARMED,\n-\t\t\t\t     &vsi->tx_rings[i]->state))\n-\t\t\t\tarmed++;\n-\t\t}\n-\n-\t\tif (armed) {\n-\t\t\tif (!(pf->flags & I40E_FLAG_MSIX_ENABLED)) {\n-\t\t\t\twr32(&vsi->back->hw, I40E_PFINT_DYN_CTL0,\n-\t\t\t\t     (I40E_PFINT_DYN_CTL0_INTENA_MASK |\n-\t\t\t\t      I40E_PFINT_DYN_CTL0_SWINT_TRIG_MASK |\n-\t\t\t\t      I40E_PFINT_DYN_CTL0_ITR_INDX_MASK |\n-\t\t\t\t      I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK |\n-\t\t\t\t      I40E_PFINT_DYN_CTL0_SW_ITR_INDX_MASK));\n-\t\t\t} else {\n-\t\t\t\tu16 vec = vsi->base_vector - 1;\n-\t\t\t\tu32 val = (I40E_PFINT_DYN_CTLN_INTENA_MASK |\n-\t\t\t\t      I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK |\n-\t\t\t\t      I40E_PFINT_DYN_CTLN_ITR_INDX_MASK |\n-\t\t\t\t      I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK |\n-\t\t\t\t      I40E_PFINT_DYN_CTLN_SW_ITR_INDX_MASK);\n-\t\t\t\tfor (i = 0; i < vsi->num_q_vectors; i++, vec++)\n-\t\t\t\t\twr32(&vsi->back->hw,\n-\t\t\t\t\t     I40E_PFINT_DYN_CTLN(vec), val);\n-\t\t\t}\n-\t\t\ti40e_flush(&vsi->back->hw);\n-\t\t}\n-\t}\n-}\n-\n-/**\n  * i40e_watchdog_subtask - periodic checks not using event driven response\n  * @pf: board private structure\n  **/\n@@ -6029,7 +6078,6 @@ static void i40e_watchdog_subtask(struct i40e_pf *pf)\n \t\treturn;\n \tpf->service_timer_previous = jiffies;\n \n-\ti40e_check_hang_subtask(pf);\n \tif (pf->flags & I40E_FLAG_LINK_POLLING_ENABLED)\n \t\ti40e_link_event(pf);\n \n@@ -6993,6 +7041,7 @@ static void i40e_service_task(struct work_struct *work)\n \t\treturn;\n \t}\n \n+\ti40e_detect_recover_hung(pf);\n \ti40e_reset_subtask(pf);\n \ti40e_handle_mdd_event(pf);\n \ti40e_vc_process_vflr_event(pf);\n@@ -10332,7 +10381,6 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)\n \tINIT_WORK(&pf->service_task, i40e_service_task);\n \tclear_bit(__I40E_SERVICE_SCHED, &pf->state);\n \tpf->flags |= I40E_FLAG_NEED_LINK_UPDATE;\n-\tpf->link_check_timeout = jiffies;\n \n \t/* NVM bit on means WoL disabled for the port */\n \ti40e_read_nvm_word(hw, I40E_SR_NVM_WAKE_ON_LAN, &wol_nvm_bits);\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c\nindex 6b78df3..6b935d6c 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c\n@@ -601,7 +601,6 @@ void i40e_free_tx_resources(struct i40e_ring *tx_ring)\n \t}\n }\n \n-\n /**\n  * i40e_get_tx_pending - how many tx descriptors not processed\n  * @tx_ring: the ring of descriptors\n@@ -609,7 +608,7 @@ void i40e_free_tx_resources(struct i40e_ring *tx_ring)\n  * Since there is no access to the ring head register\n  * in XL710, we need to use our local copies\n  **/\n-static u32 i40e_get_tx_pending(struct i40e_ring *ring)\n+u32 i40e_get_tx_pending(struct i40e_ring *ring)\n {\n \tu32 head, tail;\n \n@@ -623,50 +622,6 @@ static u32 i40e_get_tx_pending(struct i40e_ring *ring)\n \treturn 0;\n }\n \n-/**\n- * i40e_check_tx_hang - Is there a hang in the Tx queue\n- * @tx_ring: the ring of descriptors\n- **/\n-static bool i40e_check_tx_hang(struct i40e_ring *tx_ring)\n-{\n-\tu32 tx_done = tx_ring->stats.packets;\n-\tu32 tx_done_old = tx_ring->tx_stats.tx_done_old;\n-\tu32 tx_pending = i40e_get_tx_pending(tx_ring);\n-\tstruct i40e_pf *pf = tx_ring->vsi->back;\n-\tbool ret = false;\n-\n-\tclear_check_for_tx_hang(tx_ring);\n-\n-\t/* Check for a hung queue, but be thorough. This verifies\n-\t * that a transmit has been completed since the previous\n-\t * check AND there is at least one packet pending. The\n-\t * ARMED bit is set to indicate a potential hang. The\n-\t * bit is cleared if a pause frame is received to remove\n-\t * false hang detection due to PFC or 802.3x frames. By\n-\t * requiring this to fail twice we avoid races with\n-\t * PFC clearing the ARMED bit and conditions where we\n-\t * run the check_tx_hang logic with a transmit completion\n-\t * pending but without time to complete it yet.\n-\t */\n-\tif ((tx_done_old == tx_done) && tx_pending) {\n-\t\t/* make sure it is true for two checks in a row */\n-\t\tret = test_and_set_bit(__I40E_HANG_CHECK_ARMED,\n-\t\t\t\t       &tx_ring->state);\n-\t} else if (tx_done_old == tx_done &&\n-\t\t   (tx_pending < I40E_MIN_DESC_PENDING) && (tx_pending > 0)) {\n-\t\tif (I40E_DEBUG_FLOW & pf->hw.debug_mask)\n-\t\t\tdev_info(tx_ring->dev, \"HW needs some more descs to do a cacheline flush. tx_pending %d, queue %d\",\n-\t\t\t\t tx_pending, tx_ring->queue_index);\n-\t\tpf->tx_sluggish_count++;\n-\t} else {\n-\t\t/* update completed stats and disarm the hang check */\n-\t\ttx_ring->tx_stats.tx_done_old = tx_done;\n-\t\tclear_bit(__I40E_HANG_CHECK_ARMED, &tx_ring->state);\n-\t}\n-\n-\treturn ret;\n-}\n-\n #define WB_STRIDE 0x3\n \n /**\n@@ -782,32 +737,6 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)\n \t    (I40E_DESC_UNUSED(tx_ring) != tx_ring->count))\n \t\ttx_ring->arm_wb = true;\n \n-\tif (check_for_tx_hang(tx_ring) && i40e_check_tx_hang(tx_ring)) {\n-\t\t/* schedule immediate reset if we believe we hung */\n-\t\tdev_info(tx_ring->dev, \"Detected Tx Unit Hang\\n\"\n-\t\t\t \"  VSI                  <%d>\\n\"\n-\t\t\t \"  Tx Queue             <%d>\\n\"\n-\t\t\t \"  next_to_use          <%x>\\n\"\n-\t\t\t \"  next_to_clean        <%x>\\n\",\n-\t\t\t tx_ring->vsi->seid,\n-\t\t\t tx_ring->queue_index,\n-\t\t\t tx_ring->next_to_use, i);\n-\n-\t\tnetif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);\n-\n-\t\tdev_info(tx_ring->dev,\n-\t\t\t \"tx hang detected on queue %d, reset requested\\n\",\n-\t\t\t tx_ring->queue_index);\n-\n-\t\t/* do not fire the reset immediately, wait for the stack to\n-\t\t * decide we are truly stuck, also prevents every queue from\n-\t\t * simultaneously requesting a reset\n-\t\t */\n-\n-\t\t/* the adapter is about to reset, no point in enabling polling */\n-\t\tbudget = 1;\n-\t}\n-\n \tnetdev_tx_completed_queue(netdev_get_tx_queue(tx_ring->netdev,\n \t\t\t\t\t\t      tx_ring->queue_index),\n \t\t\t\t  total_packets, total_bytes);\n@@ -837,7 +766,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)\n  * @q_vector: the vector  on which to force writeback\n  *\n  **/\n-static void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)\n+void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)\n {\n \tu16 flags = q_vector->tx.ring[0].flags;\n \ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h\nindex f67f8cf..c8a7cb4 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h\n+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h\n@@ -201,8 +201,6 @@ struct i40e_rx_queue_stats {\n enum i40e_ring_state_t {\n \t__I40E_TX_FDIR_INIT_DONE,\n \t__I40E_TX_XPS_INIT_DONE,\n-\t__I40E_TX_DETECT_HANG,\n-\t__I40E_HANG_CHECK_ARMED,\n \t__I40E_RX_PS_ENABLED,\n \t__I40E_RX_16BYTE_DESC_ENABLED,\n };\n@@ -213,12 +211,6 @@ enum i40e_ring_state_t {\n \tset_bit(__I40E_RX_PS_ENABLED, &(ring)->state)\n #define clear_ring_ps_enabled(ring) \\\n \tclear_bit(__I40E_RX_PS_ENABLED, &(ring)->state)\n-#define check_for_tx_hang(ring) \\\n-\ttest_bit(__I40E_TX_DETECT_HANG, &(ring)->state)\n-#define set_check_for_tx_hang(ring) \\\n-\tset_bit(__I40E_TX_DETECT_HANG, &(ring)->state)\n-#define clear_check_for_tx_hang(ring) \\\n-\tclear_bit(__I40E_TX_DETECT_HANG, &(ring)->state)\n #define ring_is_16byte_desc_enabled(ring) \\\n \ttest_bit(__I40E_RX_16BYTE_DESC_ENABLED, &(ring)->state)\n #define set_ring_16byte_desc_enabled(ring) \\\n@@ -328,6 +320,8 @@ int i40e_xmit_descriptor_count(struct sk_buff *skb, struct i40e_ring *tx_ring);\n int i40e_tx_prepare_vlan_flags(struct sk_buff *skb,\n \t\t\t       struct i40e_ring *tx_ring, u32 *flags);\n #endif\n+void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector);\n+u32 i40e_get_tx_pending(struct i40e_ring *ring);\n \n /**\n  * i40e_get_head - Retrieve head from head writeback\ndiff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c\nindex 7b20f53..ef79db6 100644\n--- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c\n+++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c\n@@ -140,67 +140,6 @@ static inline u32 i40e_get_head(struct i40e_ring *tx_ring)\n \treturn le32_to_cpu(*(volatile __le32 *)head);\n }\n \n-/**\n- * i40e_get_tx_pending - how many tx descriptors not processed\n- * @tx_ring: the ring of descriptors\n- *\n- * Since there is no access to the ring head register\n- * in XL710, we need to use our local copies\n- **/\n-static u32 i40e_get_tx_pending(struct i40e_ring *ring)\n-{\n-\tu32 head, tail;\n-\n-\thead = i40e_get_head(ring);\n-\ttail = readl(ring->tail);\n-\n-\tif (head != tail)\n-\t\treturn (head < tail) ?\n-\t\t\ttail - head : (tail + ring->count - head);\n-\n-\treturn 0;\n-}\n-\n-/**\n- * i40e_check_tx_hang - Is there a hang in the Tx queue\n- * @tx_ring: the ring of descriptors\n- **/\n-static bool i40e_check_tx_hang(struct i40e_ring *tx_ring)\n-{\n-\tu32 tx_done = tx_ring->stats.packets;\n-\tu32 tx_done_old = tx_ring->tx_stats.tx_done_old;\n-\tu32 tx_pending = i40e_get_tx_pending(tx_ring);\n-\tbool ret = false;\n-\n-\tclear_check_for_tx_hang(tx_ring);\n-\n-\t/* Check for a hung queue, but be thorough. This verifies\n-\t * that a transmit has been completed since the previous\n-\t * check AND there is at least one packet pending. The\n-\t * ARMED bit is set to indicate a potential hang. The\n-\t * bit is cleared if a pause frame is received to remove\n-\t * false hang detection due to PFC or 802.3x frames. By\n-\t * requiring this to fail twice we avoid races with\n-\t * PFC clearing the ARMED bit and conditions where we\n-\t * run the check_tx_hang logic with a transmit completion\n-\t * pending but without time to complete it yet.\n-\t */\n-\tif ((tx_done_old == tx_done) && tx_pending) {\n-\t\t/* make sure it is true for two checks in a row */\n-\t\tret = test_and_set_bit(__I40E_HANG_CHECK_ARMED,\n-\t\t\t\t       &tx_ring->state);\n-\t} else if (tx_done_old == tx_done &&\n-\t\t   (tx_pending < I40E_MIN_DESC_PENDING) && (tx_pending > 0)) {\n-\t\t/* do nothing */\n-\t} else {\n-\t\t/* update completed stats and disarm the hang check */\n-\t\ttx_ring->tx_stats.tx_done_old = tx_done;\n-\t\tclear_bit(__I40E_HANG_CHECK_ARMED, &tx_ring->state);\n-\t}\n-\n-\treturn ret;\n-}\n-\n #define WB_STRIDE 0x3\n \n /**\n@@ -306,35 +245,16 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)\n \ttx_ring->q_vector->tx.total_bytes += total_bytes;\n \ttx_ring->q_vector->tx.total_packets += total_packets;\n \n+\t/* check to see if there are any non-cache aligned descriptors\n+\t * waiting to be written back, and kick the hardware to force\n+\t * them to be written back in case of napi polling\n+\t */\n \tif (budget &&\n \t    !((i & WB_STRIDE) == WB_STRIDE) &&\n \t    !test_bit(__I40E_DOWN, &tx_ring->vsi->state) &&\n \t    (I40E_DESC_UNUSED(tx_ring) != tx_ring->count))\n \t\ttx_ring->arm_wb = true;\n \n-\tif (check_for_tx_hang(tx_ring) && i40e_check_tx_hang(tx_ring)) {\n-\t\t/* schedule immediate reset if we believe we hung */\n-\t\tdev_info(tx_ring->dev, \"Detected Tx Unit Hang\\n\"\n-\t\t\t \"  VSI                  <%d>\\n\"\n-\t\t\t \"  Tx Queue             <%d>\\n\"\n-\t\t\t \"  next_to_use          <%x>\\n\"\n-\t\t\t \"  next_to_clean        <%x>\\n\",\n-\t\t\t tx_ring->vsi->seid,\n-\t\t\t tx_ring->queue_index,\n-\t\t\t tx_ring->next_to_use, i);\n-\n-\t\tnetif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);\n-\n-\t\tdev_info(tx_ring->dev,\n-\t\t\t \"tx hang detected on queue %d, resetting adapter\\n\",\n-\t\t\t tx_ring->queue_index);\n-\n-\t\ttx_ring->netdev->netdev_ops->ndo_tx_timeout(tx_ring->netdev);\n-\n-\t\t/* the adapter is about to reset, no point in enabling stuff */\n-\t\treturn true;\n-\t}\n-\n \tnetdev_tx_completed_queue(netdev_get_tx_queue(tx_ring->netdev,\n \t\t\t\t\t\t      tx_ring->queue_index),\n \t\t\t\t  total_packets, total_bytes);\n@@ -355,16 +275,16 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)\n \t\t}\n \t}\n \n-\treturn budget > 0;\n+\treturn !!budget;\n }\n \n /**\n- * i40e_force_wb -Arm hardware to do a wb on noncache aligned descriptors\n+ * i40evf_force_wb -Arm hardware to do a wb on noncache aligned descriptors\n  * @vsi: the VSI we care about\n  * @q_vector: the vector  on which to force writeback\n  *\n  **/\n-static void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)\n+void i40evf_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)\n {\n \tu16 flags = q_vector->tx.ring[0].flags;\n \n@@ -1384,7 +1304,7 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget)\n \t/* If work not completed, return budget and polling will return */\n \tif (!clean_complete) {\n \t\tif (arm_wb)\n-\t\t\ti40e_force_wb(vsi, q_vector);\n+\t\t\ti40evf_force_wb(vsi, q_vector);\n \t\treturn budget;\n \t}\n \ndiff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h\nindex 26fc85f..0c13ece 100644\n--- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h\n+++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h\n@@ -200,8 +200,6 @@ struct i40e_rx_queue_stats {\n enum i40e_ring_state_t {\n \t__I40E_TX_FDIR_INIT_DONE,\n \t__I40E_TX_XPS_INIT_DONE,\n-\t__I40E_TX_DETECT_HANG,\n-\t__I40E_HANG_CHECK_ARMED,\n \t__I40E_RX_PS_ENABLED,\n \t__I40E_RX_16BYTE_DESC_ENABLED,\n };\n@@ -212,12 +210,6 @@ enum i40e_ring_state_t {\n \tset_bit(__I40E_RX_PS_ENABLED, &(ring)->state)\n #define clear_ring_ps_enabled(ring) \\\n \tclear_bit(__I40E_RX_PS_ENABLED, &(ring)->state)\n-#define check_for_tx_hang(ring) \\\n-\ttest_bit(__I40E_TX_DETECT_HANG, &(ring)->state)\n-#define set_check_for_tx_hang(ring) \\\n-\tset_bit(__I40E_TX_DETECT_HANG, &(ring)->state)\n-#define clear_check_for_tx_hang(ring) \\\n-\tclear_bit(__I40E_TX_DETECT_HANG, &(ring)->state)\n #define ring_is_16byte_desc_enabled(ring) \\\n \ttest_bit(__I40E_RX_16BYTE_DESC_ENABLED, &(ring)->state)\n #define set_ring_16byte_desc_enabled(ring) \\\n",
    "prefixes": [
        "next",
        "2/2",
        "v2"
    ]
}