Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/522598/?format=api
{ "id": 522598, "url": "http://patchwork.ozlabs.org/api/patches/522598/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/1443132795-139834-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": "<1443132795-139834-1-git-send-email-catherine.sullivan@intel.com>", "list_archive_url": null, "date": "2015-09-24T22:13:15", "name": "[next,S,2/2,v3] i40e/i40evf: refactor tx timeout logic", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "9471077f41bc479843541f965b6e4522f5a51660", "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/1443132795-139834-1-git-send-email-catherine.sullivan@intel.com/mbox/", "series": [], "comments": "http://patchwork.ozlabs.org/api/patches/522598/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/522598/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 whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138])\n\tby ozlabs.org (Postfix) with ESMTP id BC021140775\n\tfor <incoming@patchwork.ozlabs.org>;\n\tFri, 25 Sep 2015 08:13:10 +1000 (AEST)", "from localhost (localhost [127.0.0.1])\n\tby whitealder.osuosl.org (Postfix) with ESMTP id 0E0B38D818;\n\tThu, 24 Sep 2015 22:13:10 +0000 (UTC)", "from whitealder.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id Ik-RWiDjWN5s; Thu, 24 Sep 2015 22:13:06 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby whitealder.osuosl.org (Postfix) with ESMTP id 5C89B8D841;\n\tThu, 24 Sep 2015 22:13:06 +0000 (UTC)", "from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137])\n\tby ash.osuosl.org (Postfix) with ESMTP id E32E11C1207\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 24 Sep 2015 22:13:04 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id DC1E88B1DA\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 24 Sep 2015 22:13:04 +0000 (UTC)", "from fraxinus.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id pfQRzLyB7ohE for <intel-wired-lan@lists.osuosl.org>;\n\tThu, 24 Sep 2015 22:13:03 +0000 (UTC)", "from mga01.intel.com (mga01.intel.com [192.55.52.88])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id F02EF8B1EA\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 24 Sep 2015 22:13:02 +0000 (UTC)", "from orsmga003.jf.intel.com ([10.7.209.27])\n\tby fmsmga101.fm.intel.com with ESMTP; 24 Sep 2015 15:13:03 -0700", "from catheri1-tigger.jf.intel.com ([134.134.176.92])\n\tby orsmga003.jf.intel.com with ESMTP; 24 Sep 2015 15:13:02 -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,583,1437462000\"; d=\"scan'208\";a=\"651796343\"", "From": "Catherine Sullivan <catherine.sullivan@intel.com>", "To": "intel-wired-lan@lists.osuosl.org", "Date": "Thu, 24 Sep 2015 18:13:15 -0400", "Message-Id": "<1443132795-139834-1-git-send-email-catherine.sullivan@intel.com>", "X-Mailer": "git-send-email 1.9.3", "Subject": "[Intel-wired-lan] [next PATCH S 2/2 v3] 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---\nv3: Made i40evf_force_wb static.\n\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 e87d967..0ed6506 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 ccefab8..f6c8ee2 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@@ -4314,6 +4323,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@@ -5951,68 +6062,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@@ -6031,7 +6080,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@@ -6995,6 +7043,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@@ -10334,7 +10383,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 7dbe264..99f464f 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 cff9b47..5d3a8bd 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+static 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 \tif (!clean_complete) {\n tx_only:\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", "S", "2/2", "v3" ] }