Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/669017/?format=api
{ "id": 669017, "url": "http://patchwork.ozlabs.org/api/patches/669017/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/1473715124-31296-9-git-send-email-bimmy.pujari@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": "<1473715124-31296-9-git-send-email-bimmy.pujari@intel.com>", "list_archive_url": null, "date": "2016-09-12T21:18:44", "name": "[next,S46,8/8] i40evf: support queue-specific settings for interrupt moderation", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "800f55a7c7265c5db51036ca78d234caeaf77e22", "submitter": { "id": 68919, "url": "http://patchwork.ozlabs.org/api/people/68919/?format=api", "name": "Pujari, Bimmy", "email": "bimmy.pujari@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/1473715124-31296-9-git-send-email-bimmy.pujari@intel.com/mbox/", "series": [], "comments": "http://patchwork.ozlabs.org/api/patches/669017/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/669017/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 fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137])\n\t(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3sY10q5LlLz9sdg\n\tfor <incoming@patchwork.ozlabs.org>;\n\tTue, 13 Sep 2016 07:19:55 +1000 (AEST)", "from localhost (localhost [127.0.0.1])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id 42B168911B;\n\tMon, 12 Sep 2016 21:19:54 +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 m-2lTMvHUaIq; Mon, 12 Sep 2016 21:19:52 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id 7CA6889030;\n\tMon, 12 Sep 2016 21:19:37 +0000 (UTC)", "from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136])\n\tby ash.osuosl.org (Postfix) with ESMTP id F2E061C2D64\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tMon, 12 Sep 2016 21:19:35 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby silver.osuosl.org (Postfix) with ESMTP id EB0B131510\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tMon, 12 Sep 2016 21:19:35 +0000 (UTC)", "from silver.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id 3UUR8QpBvvX3 for <intel-wired-lan@lists.osuosl.org>;\n\tMon, 12 Sep 2016 21:19:18 +0000 (UTC)", "from mga07.intel.com (mga07.intel.com [134.134.136.100])\n\tby silver.osuosl.org (Postfix) with ESMTPS id BFBE131617\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tMon, 12 Sep 2016 21:19:17 +0000 (UTC)", "from orsmga003.jf.intel.com ([10.7.209.27])\n\tby orsmga105.jf.intel.com with ESMTP; 12 Sep 2016 14:19:16 -0700", "from bimmy.jf.intel.com (HELO bimmy.linux1.jf.intel.com)\n\t([134.134.2.177])\n\tby orsmga003.jf.intel.com with ESMTP; 12 Sep 2016 14:19:17 -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.30,324,1470726000\"; d=\"scan'208\";a=\"877982166\"", "From": "Bimmy Pujari <bimmy.pujari@intel.com>", "To": "intel-wired-lan@lists.osuosl.org", "Date": "Mon, 12 Sep 2016 14:18:44 -0700", "Message-Id": "<1473715124-31296-9-git-send-email-bimmy.pujari@intel.com>", "X-Mailer": "git-send-email 2.4.11", "In-Reply-To": "<1473715124-31296-1-git-send-email-bimmy.pujari@intel.com>", "References": "<1473715124-31296-1-git-send-email-bimmy.pujari@intel.com>", "Subject": "[Intel-wired-lan] [next PATCH S46 8/8] i40evf: support\n\tqueue-specific settings for interrupt moderation", "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: Jacob Keller <jacob.e.keller@intel.com>\n\nIn commit a75e8005d506f3 (\"i40e: queue-specific settings for interrupt\nmoderation\") the i40e driver gained support for setting interrupt\nmoderation values per queue. This patch adds support for this feature\nto the i40evf driver as well. In addition, a few changes are made to\nthe i40e implementation to add function header documentation comments,\nas well.\n\nThis behaves in a similar fashion to the implementation in i40e. Thus,\nrequesting the moderation value when no queue is provided will report\nqueue 0 value, while setting the value without a queue will set all\nqueues at once.\n\nSigned-off-by: Jacob Keller <jacob.e.keller@intel.com>\nChange-ID: I1f310a57c8e6c84a8524c178d44d1b7a6d3a848e\n---\n drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 72 ++++++-\n drivers/net/ethernet/intel/i40e/i40e_txrx.c | 21 ++-\n drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 26 ++-\n drivers/net/ethernet/intel/i40evf/i40e_txrx.h | 8 +\n drivers/net/ethernet/intel/i40evf/i40evf.h | 7 -\n drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c | 206 ++++++++++++++++-----\n drivers/net/ethernet/intel/i40evf/i40evf_main.c | 10 +-\n 7 files changed, 280 insertions(+), 70 deletions(-)", "diff": "diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c\nindex e842628..c1c0775 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c\n@@ -1970,11 +1970,22 @@ static int i40e_set_phys_id(struct net_device *netdev,\n * 125us (8000 interrupts per second) == ITR(62)\n */\n \n+/**\n+ * __i40e_get_coalesce - get per-queue coalesce settings\n+ * @netdev: the netdev to check\n+ * @ec: ethtool coalesce data structure\n+ * @queue: which queue to pick\n+ *\n+ * Gets the per-queue settings for coalescence. Specifically rx and tx usecs\n+ * are per queue. If queue is <0 then we default to queue 0 as the\n+ * representative value.\n+ **/\n static int __i40e_get_coalesce(struct net_device *netdev,\n \t\t\t struct ethtool_coalesce *ec,\n \t\t\t int queue)\n {\n \tstruct i40e_netdev_priv *np = netdev_priv(netdev);\n+\tstruct i40e_ring *rx_ring, *tx_ring;\n \tstruct i40e_vsi *vsi = np->vsi;\n \n \tec->tx_max_coalesced_frames_irq = vsi->work_limit;\n@@ -1989,14 +2000,18 @@ static int __i40e_get_coalesce(struct net_device *netdev,\n \t\treturn -EINVAL;\n \t}\n \n-\tif (ITR_IS_DYNAMIC(vsi->rx_rings[queue]->rx_itr_setting))\n+\trx_ring = vsi->rx_rings[queue];\n+\ttx_ring = vsi->tx_rings[queue];\n+\n+\tif (ITR_IS_DYNAMIC(rx_ring->rx_itr_setting))\n \t\tec->use_adaptive_rx_coalesce = 1;\n \n-\tif (ITR_IS_DYNAMIC(vsi->tx_rings[queue]->tx_itr_setting))\n+\tif (ITR_IS_DYNAMIC(tx_ring->tx_itr_setting))\n \t\tec->use_adaptive_tx_coalesce = 1;\n \n-\tec->rx_coalesce_usecs = vsi->rx_rings[queue]->rx_itr_setting & ~I40E_ITR_DYNAMIC;\n-\tec->tx_coalesce_usecs = vsi->tx_rings[queue]->tx_itr_setting & ~I40E_ITR_DYNAMIC;\n+\tec->rx_coalesce_usecs = rx_ring->rx_itr_setting & ~I40E_ITR_DYNAMIC;\n+\tec->tx_coalesce_usecs = tx_ring->tx_itr_setting & ~I40E_ITR_DYNAMIC;\n+\n \n \t/* we use the _usecs_high to store/set the interrupt rate limit\n \t * that the hardware supports, that almost but not quite\n@@ -2010,18 +2025,44 @@ static int __i40e_get_coalesce(struct net_device *netdev,\n \treturn 0;\n }\n \n+/**\n+ * i40e_get_coalesce - get a netdev's coalesce settings\n+ * @netdev: the netdev to check\n+ * @ec: ethtool coalesce data structure\n+ *\n+ * Gets the coalesce settings for a particular netdev. Note that if user has\n+ * modified per-queue settings, this only guarantees to represent queue 0. See\n+ * __i40e_get_coalesce for more details.\n+ **/\n static int i40e_get_coalesce(struct net_device *netdev,\n \t\t\t struct ethtool_coalesce *ec)\n {\n \treturn __i40e_get_coalesce(netdev, ec, -1);\n }\n \n+/**\n+ * i40e_get_per_queue_coalesce - gets coalesce settings for particular queue\n+ * @netdev: netdev structure\n+ * @ec: ethtool's coalesce settings\n+ * @queue: the particular queue to read\n+ *\n+ * Will read a specific queue's coalesce settings\n+ **/\n static int i40e_get_per_queue_coalesce(struct net_device *netdev, u32 queue,\n \t\t\t\t struct ethtool_coalesce *ec)\n {\n \treturn __i40e_get_coalesce(netdev, ec, queue);\n }\n \n+/**\n+ * i40e_set_itr_per_queue - set ITR values for specific queue\n+ * @vsi: the vsi to set values for\n+ * @ec: coalesce settings from ethtool\n+ * @queue: the queue to modify\n+ *\n+ * Change the ITR settings for a specific queue.\n+ **/\n+\n static void i40e_set_itr_per_queue(struct i40e_vsi *vsi,\n \t\t\t\t struct ethtool_coalesce *ec,\n \t\t\t\t int queue)\n@@ -2060,6 +2101,14 @@ static void i40e_set_itr_per_queue(struct i40e_vsi *vsi,\n \ti40e_flush(hw);\n }\n \n+/**\n+ * __i40e_set_coalesce - set coalesce settings for particular queue\n+ * @netdev: the netdev to change\n+ * @ec: ethtool coalesce settings\n+ * @queue: the queue to change\n+ *\n+ * Sets the coalesce settings for a particular queue.\n+ **/\n static int __i40e_set_coalesce(struct net_device *netdev,\n \t\t\t struct ethtool_coalesce *ec,\n \t\t\t int queue)\n@@ -2120,12 +2169,27 @@ static int __i40e_set_coalesce(struct net_device *netdev,\n \treturn 0;\n }\n \n+/**\n+ * i40e_set_coalesce - set coalesce settings for every queue on the netdev\n+ * @netdev: the netdev to change\n+ * @ec: ethtool coalesce settings\n+ *\n+ * This will set each queue to the same coalesce settings.\n+ **/\n static int i40e_set_coalesce(struct net_device *netdev,\n \t\t\t struct ethtool_coalesce *ec)\n {\n \treturn __i40e_set_coalesce(netdev, ec, -1);\n }\n \n+/**\n+ * i40e_set_per_queue_coalesce - set specific queue's coalesce settings\n+ * @netdev: the netdev to change\n+ * @ec: ethtool's coalesce settings\n+ * @queue: the queue to change\n+ *\n+ * Sets the specified queue's coalesce settings.\n+ **/\n static int i40e_set_per_queue_coalesce(struct net_device *netdev, u32 queue,\n \t\t\t\t struct ethtool_coalesce *ec)\n {\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c\nindex e94e4e1..9b82240 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c\n@@ -1877,6 +1877,15 @@ static u32 i40e_buildreg_itr(const int type, const u16 itr)\n \n /* a small macro to shorten up some long lines */\n #define INTREG I40E_PFINT_DYN_CTLN\n+static inline int get_rx_itr_enabled(struct i40e_vsi *vsi, int idx)\n+{\n+\treturn !!(vsi->rx_rings[idx]->rx_itr_setting);\n+}\n+\n+static inline int get_tx_itr_enabled(struct i40e_vsi *vsi, int idx)\n+{\n+\treturn !!(vsi->tx_rings[idx]->tx_itr_setting);\n+}\n \n /**\n * i40e_update_enable_itr - Update itr and re-enable MSIX interrupt\n@@ -1892,6 +1901,7 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,\n \tu32 rxval, txval;\n \tint vector;\n \tint idx = q_vector->v_idx;\n+\tint rx_itr_setting, tx_itr_setting;\n \n \tvector = (q_vector->v_idx + vsi->base_vector);\n \n@@ -1900,18 +1910,21 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,\n \t */\n \trxval = txval = i40e_buildreg_itr(I40E_ITR_NONE, 0);\n \n+\trx_itr_setting = get_rx_itr_enabled(vsi, idx);\n+\ttx_itr_setting = get_tx_itr_enabled(vsi, idx);\n+\n \tif (q_vector->itr_countdown > 0 ||\n-\t (!ITR_IS_DYNAMIC(vsi->rx_rings[idx]->rx_itr_setting) &&\n-\t !ITR_IS_DYNAMIC(vsi->tx_rings[idx]->tx_itr_setting))) {\n+\t (!ITR_IS_DYNAMIC(rx_itr_setting) &&\n+\t !ITR_IS_DYNAMIC(tx_itr_setting))) {\n \t\tgoto enable_int;\n \t}\n \n-\tif (ITR_IS_DYNAMIC(vsi->rx_rings[idx]->rx_itr_setting)) {\n+\tif (ITR_IS_DYNAMIC(tx_itr_setting)) {\n \t\trx = i40e_set_new_dynamic_itr(&q_vector->rx);\n \t\trxval = i40e_buildreg_itr(I40E_RX_ITR, q_vector->rx.itr);\n \t}\n \n-\tif (ITR_IS_DYNAMIC(vsi->tx_rings[idx]->tx_itr_setting)) {\n+\tif (ITR_IS_DYNAMIC(tx_itr_setting)) {\n \t\ttx = i40e_set_new_dynamic_itr(&q_vector->tx);\n \t\ttxval = i40e_buildreg_itr(I40E_TX_ITR, q_vector->tx.itr);\n \t}\ndiff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c\nindex d4c6a76..75f2a2c 100644\n--- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c\n+++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c\n@@ -1311,6 +1311,19 @@ static u32 i40e_buildreg_itr(const int type, const u16 itr)\n \n /* a small macro to shorten up some long lines */\n #define INTREG I40E_VFINT_DYN_CTLN1\n+static inline int get_rx_itr_enabled(struct i40e_vsi *vsi, int idx)\n+{\n+\tstruct i40evf_adapter *adapter = vsi->back;\n+\n+\treturn !!(adapter->rx_rings[idx].rx_itr_setting);\n+}\n+\n+static inline int get_tx_itr_enabled(struct i40e_vsi *vsi, int idx)\n+{\n+\tstruct i40evf_adapter *adapter = vsi->back;\n+\n+\treturn !!(adapter->tx_rings[idx].tx_itr_setting);\n+}\n \n /**\n * i40e_update_enable_itr - Update itr and re-enable MSIX interrupt\n@@ -1325,6 +1338,8 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,\n \tbool rx = false, tx = false;\n \tu32 rxval, txval;\n \tint vector;\n+\tint idx = q_vector->v_idx;\n+\tint rx_itr_setting, tx_itr_setting;\n \n \tvector = (q_vector->v_idx + vsi->base_vector);\n \n@@ -1333,18 +1348,21 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,\n \t */\n \trxval = txval = i40e_buildreg_itr(I40E_ITR_NONE, 0);\n \n+\trx_itr_setting = get_rx_itr_enabled(vsi, idx);\n+\ttx_itr_setting = get_tx_itr_enabled(vsi, idx);\n+\n \tif (q_vector->itr_countdown > 0 ||\n-\t (!ITR_IS_DYNAMIC(vsi->rx_itr_setting) &&\n-\t !ITR_IS_DYNAMIC(vsi->tx_itr_setting))) {\n+\t (!ITR_IS_DYNAMIC(rx_itr_setting) &&\n+\t !ITR_IS_DYNAMIC(tx_itr_setting))) {\n \t\tgoto enable_int;\n \t}\n \n-\tif (ITR_IS_DYNAMIC(vsi->rx_itr_setting)) {\n+\tif (ITR_IS_DYNAMIC(rx_itr_setting)) {\n \t\trx = i40e_set_new_dynamic_itr(&q_vector->rx);\n \t\trxval = i40e_buildreg_itr(I40E_RX_ITR, q_vector->rx.itr);\n \t}\n \n-\tif (ITR_IS_DYNAMIC(vsi->tx_itr_setting)) {\n+\tif (ITR_IS_DYNAMIC(tx_itr_setting)) {\n \t\ttx = i40e_set_new_dynamic_itr(&q_vector->tx);\n \t\ttxval = i40e_buildreg_itr(I40E_TX_ITR, q_vector->tx.itr);\n \t}\ndiff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h\nindex 7f72ee7..1bc5b99 100644\n--- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h\n+++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h\n@@ -287,6 +287,14 @@ struct i40e_ring {\n \tu8 dcb_tc;\t\t\t/* Traffic class of ring */\n \tu8 __iomem *tail;\n \n+\t/* high bit set means dynamic, use accessor routines to read/write.\n+\t * hardware only supports 2us resolution for the ITR registers.\n+\t * these values always store the USER setting, and must be converted\n+\t * before programming to a register.\n+\t */\n+\tu16 rx_itr_setting;\n+\tu16 tx_itr_setting;\n+\n \tu16 count;\t\t\t/* Number of descriptors */\n \tu16 reg_idx;\t\t\t/* HW register index of the ring */\n \tu16 rx_buf_len;\ndiff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h\nindex dc00aaf..c5fd724 100644\n--- a/drivers/net/ethernet/intel/i40evf/i40evf.h\n+++ b/drivers/net/ethernet/intel/i40evf/i40evf.h\n@@ -59,13 +59,6 @@ struct i40e_vsi {\n \tunsigned long state;\n \tint base_vector;\n \tu16 work_limit;\n-\t/* high bit set means dynamic, use accessor routines to read/write.\n-\t * hardware only supports 2us resolution for the ITR registers.\n-\t * these values always store the USER setting, and must be converted\n-\t * before programming to a register.\n-\t */\n-\tu16 rx_itr_setting;\n-\tu16 tx_itr_setting;\n \tu16 qs_handle;\n };\n \ndiff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c\nindex e17a154..6d15a71 100644\n--- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c\n+++ b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c\n@@ -296,93 +296,207 @@ static int i40evf_set_ringparam(struct net_device *netdev,\n }\n \n /**\n- * i40evf_get_coalesce - Get interrupt coalescing settings\n- * @netdev: network interface device structure\n- * @ec: ethtool coalesce structure\n+ * __i40evf_get_coalesce - get per-queue coalesce settings\n+ * @netdev: the netdev to check\n+ * @ec: ethtool coalesce data structure\n+ * @queue: which queue to pick\n *\n- * Returns current coalescing settings. This is referred to elsewhere in the\n- * driver as Interrupt Throttle Rate, as this is how the hardware describes\n- * this functionality.\n+ * Gets the per-queue settings for coalescence. Specifically rx and tx usecs\n+ * are per queue. If queue is <0 then we default to queue 0 as the\n+ * representative value.\n **/\n-static int i40evf_get_coalesce(struct net_device *netdev,\n-\t\t\t struct ethtool_coalesce *ec)\n+static int __i40evf_get_coalesce(struct net_device *netdev,\n+\t\t\t\t struct ethtool_coalesce *ec,\n+\t\t\t\t int queue)\n {\n \tstruct i40evf_adapter *adapter = netdev_priv(netdev);\n \tstruct i40e_vsi *vsi = &adapter->vsi;\n+\tstruct i40e_ring *rx_ring, *tx_ring;\n \n \tec->tx_max_coalesced_frames = vsi->work_limit;\n \tec->rx_max_coalesced_frames = vsi->work_limit;\n \n-\tif (ITR_IS_DYNAMIC(vsi->rx_itr_setting))\n+\t/* rx and tx usecs per queue value. If user doesn't specify the\n+\t * queue, return queue 0's value to represent.\n+\t */\n+\tif (queue < 0)\n+\t\tqueue = 0;\n+\telse if (queue >= adapter->num_active_queues)\n+\t\treturn -EINVAL;\n+\n+\trx_ring = &adapter->rx_rings[queue];\n+\ttx_ring = &adapter->tx_rings[queue];\n+\n+\tif (ITR_IS_DYNAMIC(rx_ring->rx_itr_setting))\n \t\tec->use_adaptive_rx_coalesce = 1;\n \n-\tif (ITR_IS_DYNAMIC(vsi->tx_itr_setting))\n+\tif (ITR_IS_DYNAMIC(tx_ring->tx_itr_setting))\n \t\tec->use_adaptive_tx_coalesce = 1;\n \n-\tec->rx_coalesce_usecs = vsi->rx_itr_setting & ~I40E_ITR_DYNAMIC;\n-\tec->tx_coalesce_usecs = vsi->tx_itr_setting & ~I40E_ITR_DYNAMIC;\n+\tec->rx_coalesce_usecs = rx_ring->rx_itr_setting & ~I40E_ITR_DYNAMIC;\n+\tec->tx_coalesce_usecs = tx_ring->tx_itr_setting & ~I40E_ITR_DYNAMIC;\n \n \treturn 0;\n }\n \n /**\n- * i40evf_set_coalesce - Set interrupt coalescing settings\n+ * i40evf_get_coalesce - Get interrupt coalescing settings\n * @netdev: network interface device structure\n * @ec: ethtool coalesce structure\n *\n- * Change current coalescing settings.\n+ * Returns current coalescing settings. This is referred to elsewhere in the\n+ * driver as Interrupt Throttle Rate, as this is how the hardware describes\n+ * this functionality. Note that if per-queue settings have been modified this\n+ * only represents the settings of queue 0.\n **/\n-static int i40evf_set_coalesce(struct net_device *netdev,\n+static int i40evf_get_coalesce(struct net_device *netdev,\n \t\t\t struct ethtool_coalesce *ec)\n {\n-\tstruct i40evf_adapter *adapter = netdev_priv(netdev);\n-\tstruct i40e_hw *hw = &adapter->hw;\n+\treturn __i40evf_get_coalesce(netdev, ec, -1);\n+}\n+\n+/**\n+ * i40evf_get_per_queue_coalesce - get coalesce values for specific queue\n+ * @netdev: netdev to read\n+ * @ec: coalesce settings from ethtool\n+ * @queue: the queue to read\n+ *\n+ * Read specific queue's coalesce settings.\n+ **/\n+static int i40evf_get_per_queue_coalesce(struct net_device *netdev,\n+\t\t\t\t\t u32 queue,\n+\t\t\t\t\t struct ethtool_coalesce *ec)\n+{\n+\treturn __i40evf_get_coalesce(netdev, ec, queue);\n+}\n+\n+/**\n+ * i40evf_set_itr_per_queue - set ITR values for specific queue\n+ * @vsi: the vsi to set values for\n+ * @ec: coalesce settings from ethtool\n+ * @queue: the queue to modify\n+ *\n+ * Change the ITR settings for a specific queue.\n+ **/\n+static void i40evf_set_itr_per_queue(struct i40evf_adapter *adapter,\n+\t\t\t\t struct ethtool_coalesce *ec,\n+\t\t\t\t int queue)\n+{\n \tstruct i40e_vsi *vsi = &adapter->vsi;\n+\tstruct i40e_hw *hw = &adapter->hw;\n \tstruct i40e_q_vector *q_vector;\n+\tu16 vector;\n+\n+\tadapter->rx_rings[queue].rx_itr_setting = ec->rx_coalesce_usecs;\n+\tadapter->tx_rings[queue].tx_itr_setting = ec->tx_coalesce_usecs;\n+\n+\tif (ec->use_adaptive_rx_coalesce)\n+\t\tadapter->rx_rings[queue].rx_itr_setting |= I40E_ITR_DYNAMIC;\n+\telse\n+\t\tadapter->rx_rings[queue].rx_itr_setting &= ~I40E_ITR_DYNAMIC;\n+\n+\tif (ec->use_adaptive_tx_coalesce)\n+\t\tadapter->tx_rings[queue].tx_itr_setting |= I40E_ITR_DYNAMIC;\n+\telse\n+\t\tadapter->tx_rings[queue].tx_itr_setting &= ~I40E_ITR_DYNAMIC;\n+\n+\tq_vector = adapter->rx_rings[queue].q_vector;\n+\tq_vector->rx.itr = ITR_TO_REG(adapter->rx_rings[queue].rx_itr_setting);\n+\tvector = vsi->base_vector + q_vector->v_idx;\n+\twr32(hw, I40E_VFINT_ITRN1(I40E_RX_ITR, vector - 1), q_vector->rx.itr);\n+\n+\tq_vector = adapter->tx_rings[queue].q_vector;\n+\tq_vector->tx.itr = ITR_TO_REG(adapter->tx_rings[queue].tx_itr_setting);\n+\tvector = vsi->base_vector + q_vector->v_idx;\n+\twr32(hw, I40E_VFINT_ITRN1(I40E_TX_ITR, vector - 1), q_vector->tx.itr);\n+\n+\ti40e_flush(hw);\n+}\n+\n+/**\n+ * __i40evf_set_coalesce - set coalesce settings for particular queue\n+ * @netdev: the netdev to change\n+ * @ec: ethtool coalesce settings\n+ * @queue: the queue to change\n+ *\n+ * Sets the coalesce settings for a particular queue.\n+ **/\n+static int __i40evf_set_coalesce(struct net_device *netdev,\n+\t\t\t\t struct ethtool_coalesce *ec,\n+\t\t\t\t int queue)\n+{\n+\tstruct i40evf_adapter *adapter = netdev_priv(netdev);\n+\tstruct i40e_vsi *vsi = &adapter->vsi;\n \tint i;\n \n \tif (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq)\n \t\tvsi->work_limit = ec->tx_max_coalesced_frames_irq;\n \n-\tif ((ec->rx_coalesce_usecs >= (I40E_MIN_ITR << 1)) &&\n-\t (ec->rx_coalesce_usecs <= (I40E_MAX_ITR << 1)))\n-\t\tvsi->rx_itr_setting = ec->rx_coalesce_usecs;\n-\n-\telse\n+\tif (ec->rx_coalesce_usecs == 0) {\n+\t\tif (ec->use_adaptive_rx_coalesce)\n+\t\t\tnetif_info(adapter, drv, netdev, \"rx-usecs=0, need to disable adaptive-rx for a complete disable\\n\");\n+\t} else if ((ec->rx_coalesce_usecs < (I40E_MIN_ITR << 1)) ||\n+\t\t (ec->rx_coalesce_usecs > (I40E_MAX_ITR << 1))) {\n+\t\tnetif_info(adapter, drv, netdev, \"Invalid value, rx-usecs range is 0-8160\\n\");\n \t\treturn -EINVAL;\n+\t}\n \n-\tif ((ec->tx_coalesce_usecs >= (I40E_MIN_ITR << 1)) &&\n-\t (ec->tx_coalesce_usecs <= (I40E_MAX_ITR << 1)))\n-\t\tvsi->tx_itr_setting = ec->tx_coalesce_usecs;\n-\telse if (ec->use_adaptive_tx_coalesce)\n-\t\tvsi->tx_itr_setting = (I40E_ITR_DYNAMIC |\n-\t\t\t\t ITR_REG_TO_USEC(I40E_ITR_RX_DEF));\n \telse\n+\tif (ec->tx_coalesce_usecs == 0) {\n+\t\tif (ec->use_adaptive_tx_coalesce)\n+\t\t\tnetif_info(adapter, drv, netdev, \"tx-usecs=0, need to disable adaptive-tx for a complete disable\\n\");\n+\t} else if ((ec->tx_coalesce_usecs < (I40E_MIN_ITR << 1)) ||\n+\t\t (ec->tx_coalesce_usecs > (I40E_MAX_ITR << 1))) {\n+\t\tnetif_info(adapter, drv, netdev, \"Invalid value, tx-usecs range is 0-8160\\n\");\n \t\treturn -EINVAL;\n+\t}\n \n-\tif (ec->use_adaptive_rx_coalesce)\n-\t\tvsi->rx_itr_setting |= I40E_ITR_DYNAMIC;\n-\telse\n-\t\tvsi->rx_itr_setting &= ~I40E_ITR_DYNAMIC;\n-\n-\tif (ec->use_adaptive_tx_coalesce)\n-\t\tvsi->tx_itr_setting |= I40E_ITR_DYNAMIC;\n-\telse\n-\t\tvsi->tx_itr_setting &= ~I40E_ITR_DYNAMIC;\n-\n-\tfor (i = 0; i < adapter->num_msix_vectors - NONQ_VECS; i++) {\n-\t\tq_vector = &adapter->q_vectors[i];\n-\t\tq_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting);\n-\t\twr32(hw, I40E_VFINT_ITRN1(0, i), q_vector->rx.itr);\n-\t\tq_vector->tx.itr = ITR_TO_REG(vsi->tx_itr_setting);\n-\t\twr32(hw, I40E_VFINT_ITRN1(1, i), q_vector->tx.itr);\n-\t\ti40e_flush(hw);\n+\t/* rx and tx usecs has per queue value. If user doesn't specify the\n+\t * queue, apply to all queues.\n+\t */\n+\tif (queue < 0) {\n+\t\tfor (i = 0; i < adapter->num_active_queues; i++)\n+\t\t\ti40evf_set_itr_per_queue(adapter, ec, i);\n+\t} else if (queue < adapter->num_active_queues) {\n+\t\ti40evf_set_itr_per_queue(adapter, ec, queue);\n+\t} else {\n+\t\tnetif_info(adapter, drv, netdev, \"Invalid queue value, queue range is 0 - %d\\n\",\n+\t\t\t adapter->num_active_queues - 1);\n+\t\treturn -EINVAL;\n \t}\n \n \treturn 0;\n }\n \n /**\n+ * i40evf_set_coalesce - Set interrupt coalescing settings\n+ * @netdev: network interface device structure\n+ * @ec: ethtool coalesce structure\n+ *\n+ * Change current coalescing settings for every queue.\n+ **/\n+static int i40evf_set_coalesce(struct net_device *netdev,\n+\t\t\t struct ethtool_coalesce *ec)\n+{\n+\treturn __i40evf_set_coalesce(netdev, ec, -1);\n+}\n+\n+/**\n+ * i40evf_set_per_queue_coalesce - set specific queue's coalesce settings\n+ * @netdev: the netdev to change\n+ * @ec: ethtool's coalesce settings\n+ * @queue: the queue to modify\n+ *\n+ * Modifies a specific queue's coalesce settings.\n+ */\n+static int i40evf_set_per_queue_coalesce(struct net_device *netdev,\n+\t\t\t\t\t u32 queue,\n+\t\t\t\t\t struct ethtool_coalesce *ec)\n+{\n+\treturn __i40evf_set_coalesce(netdev, ec, queue);\n+}\n+\n+/**\n * i40evf_get_rxnfc - command to get RX flow classification rules\n * @netdev: network interface device structure\n * @cmd: ethtool rxnfc command\n@@ -533,6 +647,8 @@ static const struct ethtool_ops i40evf_ethtool_ops = {\n \t.set_msglevel\t\t= i40evf_set_msglevel,\n \t.get_coalesce\t\t= i40evf_get_coalesce,\n \t.set_coalesce\t\t= i40evf_set_coalesce,\n+\t.get_per_queue_coalesce = i40evf_get_per_queue_coalesce,\n+\t.set_per_queue_coalesce = i40evf_set_per_queue_coalesce,\n \t.get_rxnfc\t\t= i40evf_get_rxnfc,\n \t.get_rxfh_indir_size\t= i40evf_get_rxfh_indir_size,\n \t.get_rxfh\t\t= i40evf_get_rxfh,\ndiff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c\nindex 302c974..1437281 100644\n--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c\n+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c\n@@ -370,7 +370,6 @@ i40evf_map_vector_to_rxq(struct i40evf_adapter *adapter, int v_idx, int r_idx)\n {\n \tstruct i40e_q_vector *q_vector = &adapter->q_vectors[v_idx];\n \tstruct i40e_ring *rx_ring = &adapter->rx_rings[r_idx];\n-\tstruct i40e_vsi *vsi = &adapter->vsi;\n \tstruct i40e_hw *hw = &adapter->hw;\n \n \trx_ring->q_vector = q_vector;\n@@ -379,7 +378,7 @@ i40evf_map_vector_to_rxq(struct i40evf_adapter *adapter, int v_idx, int r_idx)\n \tq_vector->rx.ring = rx_ring;\n \tq_vector->rx.count++;\n \tq_vector->rx.latency_range = I40E_LOW_LATENCY;\n-\tq_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting);\n+\tq_vector->rx.itr = ITR_TO_REG(rx_ring->rx_itr_setting);\n \tq_vector->ring_mask |= BIT(r_idx);\n \tq_vector->itr_countdown = ITR_COUNTDOWN_START;\n \twr32(hw, I40E_VFINT_ITRN1(I40E_RX_ITR, v_idx - 1), q_vector->rx.itr);\n@@ -396,7 +395,6 @@ i40evf_map_vector_to_txq(struct i40evf_adapter *adapter, int v_idx, int t_idx)\n {\n \tstruct i40e_q_vector *q_vector = &adapter->q_vectors[v_idx];\n \tstruct i40e_ring *tx_ring = &adapter->tx_rings[t_idx];\n-\tstruct i40e_vsi *vsi = &adapter->vsi;\n \tstruct i40e_hw *hw = &adapter->hw;\n \n \ttx_ring->q_vector = q_vector;\n@@ -405,7 +403,7 @@ i40evf_map_vector_to_txq(struct i40evf_adapter *adapter, int v_idx, int t_idx)\n \tq_vector->tx.ring = tx_ring;\n \tq_vector->tx.count++;\n \tq_vector->tx.latency_range = I40E_LOW_LATENCY;\n-\tq_vector->tx.itr = ITR_TO_REG(vsi->tx_itr_setting);\n+\tq_vector->tx.itr = ITR_TO_REG(tx_ring->tx_itr_setting);\n \tq_vector->itr_countdown = ITR_COUNTDOWN_START;\n \tq_vector->num_ringpairs++;\n \twr32(hw, I40E_VFINT_ITRN1(I40E_TX_ITR, v_idx - 1), q_vector->tx.itr);\n@@ -1162,6 +1160,7 @@ static int i40evf_alloc_queues(struct i40evf_adapter *adapter)\n \t\ttx_ring->netdev = adapter->netdev;\n \t\ttx_ring->dev = &adapter->pdev->dev;\n \t\ttx_ring->count = adapter->tx_desc_count;\n+\t\ttx_ring->tx_itr_setting = (I40E_ITR_DYNAMIC | I40E_ITR_TX_DEF);\n \t\tif (adapter->flags & I40E_FLAG_WB_ON_ITR_CAPABLE)\n \t\t\ttx_ring->flags |= I40E_TXR_FLAGS_WB_ON_ITR;\n \n@@ -1170,6 +1169,7 @@ static int i40evf_alloc_queues(struct i40evf_adapter *adapter)\n \t\trx_ring->netdev = adapter->netdev;\n \t\trx_ring->dev = &adapter->pdev->dev;\n \t\trx_ring->count = adapter->rx_desc_count;\n+\t\trx_ring->rx_itr_setting = (I40E_ITR_DYNAMIC | I40E_ITR_RX_DEF);\n \t}\n \n \treturn 0;\n@@ -2277,8 +2277,6 @@ int i40evf_process_config(struct i40evf_adapter *adapter)\n \tadapter->vsi.back = adapter;\n \tadapter->vsi.base_vector = 1;\n \tadapter->vsi.work_limit = I40E_DEFAULT_IRQ_WORK;\n-\tadapter->vsi.rx_itr_setting = (I40E_ITR_DYNAMIC | I40E_ITR_RX_DEF);\n-\tadapter->vsi.tx_itr_setting = (I40E_ITR_DYNAMIC | I40E_ITR_TX_DEF);\n \tvsi->netdev = adapter->netdev;\n \tvsi->qs_handle = adapter->vsi_res->qset_handle;\n \tif (vfres->vf_offload_flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF) {\n", "prefixes": [ "next", "S46", "8/8" ] }