Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/960025/?format=api
{ "id": 960025, "url": "http://patchwork.ozlabs.org/api/patches/960025/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20180820151233.14629-2-alice.michael@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": "<20180820151233.14629-2-alice.michael@intel.com>", "list_archive_url": null, "date": "2018-08-20T15:12:23", "name": "[next,S95,02/12] i40e: convert queue stats to i40e_stats array", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "b07afd64f3754d364f20ee8bc5f234b795172982", "submitter": { "id": 71123, "url": "http://patchwork.ozlabs.org/api/people/71123/?format=api", "name": "Michael, Alice", "email": "alice.michael@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/20180820151233.14629-2-alice.michael@intel.com/mbox/", "series": [ { "id": 61649, "url": "http://patchwork.ozlabs.org/api/series/61649/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=61649", "date": "2018-08-20T15:12:30", "name": null, "version": 1, "mbox": "http://patchwork.ozlabs.org/series/61649/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/960025/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/960025/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<intel-wired-lan-bounces@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" ], "Authentication-Results": [ "ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=osuosl.org\n\t(client-ip=140.211.166.133; helo=hemlock.osuosl.org;\n\tenvelope-from=intel-wired-lan-bounces@osuosl.org;\n\treceiver=<UNKNOWN>)", "ozlabs.org;\n\tdmarc=fail (p=none dis=none) header.from=intel.com" ], "Received": [ "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\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 41vVHh3769z9s5b\n\tfor <incoming@patchwork.ozlabs.org>;\n\tTue, 21 Aug 2018 09:24:00 +1000 (AEST)", "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 167B6871D9;\n\tMon, 20 Aug 2018 23:23:59 +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 rFJsgEbzENhu; Mon, 20 Aug 2018 23:23:58 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 1EBC087398;\n\tMon, 20 Aug 2018 23:23:58 +0000 (UTC)", "from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136])\n\tby ash.osuosl.org (Postfix) with ESMTP id 70BAE1C16D3\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tMon, 20 Aug 2018 23:23:48 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby silver.osuosl.org (Postfix) with ESMTP id 6EC1121561\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tMon, 20 Aug 2018 23:23:48 +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 yxhZ+VTvnP8I for <intel-wired-lan@lists.osuosl.org>;\n\tMon, 20 Aug 2018 23:23:45 +0000 (UTC)", "from mga02.intel.com (mga02.intel.com [134.134.136.20])\n\tby silver.osuosl.org (Postfix) with ESMTPS id A49432155C\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tMon, 20 Aug 2018 23:23:45 +0000 (UTC)", "from orsmga001.jf.intel.com ([10.7.209.18])\n\tby orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t20 Aug 2018 16:23:45 -0700", "from alicemic-2.jf.intel.com ([10.166.16.121])\n\tby orsmga001.jf.intel.com with ESMTP; 20 Aug 2018 16:23:32 -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-Amp-Result": "SKIPPED(no attachment in message)", "X-Amp-File-Uploaded": "False", "X-ExtLoop1": "1", "X-IronPort-AV": "E=Sophos;i=\"5.53,267,1531810800\"; d=\"scan'208\";a=\"83446368\"", "From": "Alice Michael <alice.michael@intel.com>", "To": "alice.michael@intel.com,\n\tintel-wired-lan@lists.osuosl.org", "Date": "Mon, 20 Aug 2018 08:12:23 -0700", "Message-Id": "<20180820151233.14629-2-alice.michael@intel.com>", "X-Mailer": "git-send-email 2.9.5", "In-Reply-To": "<20180820151233.14629-1-alice.michael@intel.com>", "References": "<20180820151233.14629-1-alice.michael@intel.com>", "Subject": "[Intel-wired-lan] [next PATCH S95 02/12] i40e: convert queue stats\n\tto i40e_stats array", "X-BeenThere": "intel-wired-lan@osuosl.org", "X-Mailman-Version": "2.1.24", "Precedence": "list", "List-Id": "Intel Wired Ethernet Linux Kernel Driver Development\n\t<intel-wired-lan.osuosl.org>", "List-Unsubscribe": "<https://lists.osuosl.org/mailman/options/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=unsubscribe>", "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>", "List-Post": "<mailto:intel-wired-lan@osuosl.org>", "List-Help": "<mailto:intel-wired-lan-request@osuosl.org?subject=help>", "List-Subscribe": "<https://lists.osuosl.org/mailman/listinfo/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@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@osuosl.org", "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@osuosl.org>" }, "content": "From: Jacob Keller <jacob.e.keller@intel.com>\n\nUse an i40e_stats array to handle the queue stats, instead of coding\nsimilar functionality separately. Because of how the queue stats are\naccessed on some kernels, we can't easily use i40e_add_ethtool_stats.\n\nInstead, implement a separate helper, i40e_add_queue_stats, which we'll\nuse instead. This helper will correctly implement the\nu64_stats_fetch_begin_irq logic and allow retries until successful. We\nshare the most complex code by re-using i40e_add_one_ethtool_stat.\n\nThis logic additionally easily supports skipping disabled rings by using\na ternary operator before calling the u64_stats_fetch_begin_irq()\nfunction, so that we correctly zero-out the stats values without having\nto perform two separate sections of code.\n\nThis significantly reduces the boiler plate code in\ni40e_get_ethtool_stats, and helps keep the complex logic contained to as\nfew functions as possible.\n\nWith this patch, we've finally converted all the statistics to use the\nhelpers and the i40e_stats function.\n\nSigned-off-by: Jacob Keller <jacob.e.keller@intel.com>\n---\n drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 148 +++++++++++++++----------\n 1 file changed, 89 insertions(+), 59 deletions(-)", "diff": "diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c\nindex 19606a2..9ac41c8 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c\n@@ -33,6 +33,8 @@ struct i40e_stats {\n \tI40E_STAT(struct i40e_veb, _name, _stat)\n #define I40E_PFC_STAT(_name, _stat) \\\n \tI40E_STAT(struct i40e_pfc_stats, _name, _stat)\n+#define I40E_QUEUE_STAT(_name, _stat) \\\n+\tI40E_STAT(struct i40e_ring, _name, _stat)\n \n static const struct i40e_stats i40e_gstrings_net_stats[] = {\n \tI40E_NETDEV_STAT(rx_packets),\n@@ -171,20 +173,16 @@ static const struct i40e_stats i40e_gstrings_pfc_stats[] = {\n \tI40E_PFC_STAT(\"port.rx_priority_%u_xon_2_xoff\", priority_xon_2_xoff),\n };\n \n-/* We use num_tx_queues here as a proxy for the maximum number of queues\n- * available because we always allocate queues symmetrically.\n- */\n-#define I40E_MAX_NUM_QUEUES(n) ((n)->num_tx_queues)\n-#define I40E_QUEUE_STATS_LEN(n) \\\n-\t (I40E_MAX_NUM_QUEUES(n) \\\n-\t * 2 /* Tx and Rx together */ \\\n-\t * (sizeof(struct i40e_queue_stats) / sizeof(u64)))\n-#define I40E_GLOBAL_STATS_LEN\tARRAY_SIZE(i40e_gstrings_stats)\n+static const struct i40e_stats i40e_gstrings_queue_stats[] = {\n+\tI40E_QUEUE_STAT(\"%s-%u.packets\", stats.packets),\n+\tI40E_QUEUE_STAT(\"%s-%u.bytes\", stats.bytes),\n+};\n+\n #define I40E_NETDEV_STATS_LEN\tARRAY_SIZE(i40e_gstrings_net_stats)\n+\n #define I40E_MISC_STATS_LEN\tARRAY_SIZE(i40e_gstrings_misc_stats)\n-#define I40E_VSI_STATS_LEN(n)\t(I40E_NETDEV_STATS_LEN + \\\n-\t\t\t\t I40E_MISC_STATS_LEN + \\\n-\t\t\t\t I40E_QUEUE_STATS_LEN((n)))\n+\n+#define I40E_VSI_STATS_LEN\t(I40E_NETDEV_STATS_LEN + I40E_MISC_STATS_LEN)\n \n #define I40E_PFC_STATS_LEN\t(ARRAY_SIZE(i40e_gstrings_pfc_stats) * \\\n \t\t\t\t I40E_MAX_USER_PRIORITY)\n@@ -193,10 +191,15 @@ static const struct i40e_stats i40e_gstrings_pfc_stats[] = {\n \t\t\t\t (ARRAY_SIZE(i40e_gstrings_veb_tc_stats) * \\\n \t\t\t\t I40E_MAX_TRAFFIC_CLASS))\n \n-#define I40E_PF_STATS_LEN(n)\t(I40E_GLOBAL_STATS_LEN + \\\n+#define I40E_GLOBAL_STATS_LEN\tARRAY_SIZE(i40e_gstrings_stats)\n+\n+#define I40E_PF_STATS_LEN\t(I40E_GLOBAL_STATS_LEN + \\\n \t\t\t\t I40E_PFC_STATS_LEN + \\\n \t\t\t\t I40E_VEB_STATS_LEN + \\\n-\t\t\t\t I40E_VSI_STATS_LEN((n)))\n+\t\t\t\t I40E_VSI_STATS_LEN)\n+\n+/* Length of stats for a single queue */\n+#define I40E_QUEUE_STATS_LEN\tARRAY_SIZE(i40e_gstrings_queue_stats)\n \n enum i40e_ethtool_test_id {\n \tI40E_ETH_TEST_REG = 0,\n@@ -1701,11 +1704,30 @@ static int i40e_get_stats_count(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+\tint stats_len;\n \n \tif (vsi == pf->vsi[pf->lan_vsi] && pf->hw.partition_id == 1)\n-\t\treturn I40E_PF_STATS_LEN(netdev);\n+\t\tstats_len = I40E_PF_STATS_LEN;\n \telse\n-\t\treturn I40E_VSI_STATS_LEN(netdev);\n+\t\tstats_len = I40E_VSI_STATS_LEN;\n+\n+\t/* The number of stats reported for a given net_device must remain\n+\t * constant throughout the life of that device.\n+\t *\n+\t * This is because the API for obtaining the size, strings, and stats\n+\t * is spread out over three separate ethtool ioctls. There is no safe\n+\t * way to lock the number of stats across these calls, so we must\n+\t * assume that they will never change.\n+\t *\n+\t * Due to this, we report the maximum number of queues, even if not\n+\t * every queue is currently configured. Since we always allocate\n+\t * queues in pairs, we'll just use netdev->num_tx_queues * 2. This\n+\t * works because the num_tx_queues is set at device creation and never\n+\t * changes.\n+\t */\n+\tstats_len += I40E_QUEUE_STATS_LEN * 2 * netdev->num_tx_queues;\n+\n+\treturn stats_len;\n }\n \n static int i40e_get_sset_count(struct net_device *netdev, int sset)\n@@ -1734,8 +1756,8 @@ static int i40e_get_sset_count(struct net_device *netdev, int sset)\n * @stat: the stat definition\n *\n * Copies the stat data defined by the pointer and stat structure pair into\n- * the memory supplied as data. Used to implement i40e_add_ethtool_stats.\n- * If the pointer is null, data will be zero'd.\n+ * the memory supplied as data. Used to implement i40e_add_ethtool_stats and\n+ * i40e_add_queue_stats. If the pointer is null, data will be zero'd.\n */\n static inline void\n i40e_add_one_ethtool_stat(u64 *data, void *pointer,\n@@ -1811,6 +1833,45 @@ __i40e_add_ethtool_stats(u64 **data, void *pointer,\n \t__i40e_add_ethtool_stats(data, pointer, stats, ARRAY_SIZE(stats))\n \n /**\n+ * i40e_add_queue_stats - copy queue statistics into supplied buffer\n+ * @data: ethtool stats buffer\n+ * @ring: the ring to copy\n+ *\n+ * Queue statistics must be copied while protected by\n+ * u64_stats_fetch_begin_irq, so we can't directly use i40e_add_ethtool_stats.\n+ * Assumes that queue stats are defined in i40e_gstrings_queue_stats. If the\n+ * ring pointer is null, zero out the queue stat values and update the data\n+ * pointer. Otherwise safely copy the stats from the ring into the supplied\n+ * buffer and update the data pointer when finished.\n+ *\n+ * This function expects to be called while under rcu_read_lock().\n+ **/\n+static inline void\n+i40e_add_queue_stats(u64 **data, struct i40e_ring *ring)\n+{\n+\tconst unsigned int size = ARRAY_SIZE(i40e_gstrings_queue_stats);\n+\tconst struct i40e_stats *stats = i40e_gstrings_queue_stats;\n+\tunsigned int start;\n+\tunsigned int i;\n+\n+\t/* To avoid invalid statistics values, ensure that we keep retrying\n+\t * the copy until we get a consistent value according to\n+\t * u64_stats_fetch_retry_irq. But first, make sure our ring is\n+\t * non-null before attempting to access its syncp.\n+\t */\n+\tdo {\n+\t\tstart = !ring ? 0 : u64_stats_fetch_begin_irq(&ring->syncp);\n+\t\tfor (i = 0; i < size; i++) {\n+\t\t\ti40e_add_one_ethtool_stat(&(*data)[i], ring,\n+\t\t\t\t\t\t &stats[i]);\n+\t\t}\n+\t} while (ring && u64_stats_fetch_retry_irq(&ring->syncp, start));\n+\n+\t/* Once we successfully copy the stats in, update the data pointer */\n+\tdata += size;\n+}\n+\n+/**\n * i40e_get_pfc_stats - copy HW PFC statistics to formatted structure\n * @pf: the PF device structure\n * @i: the priority value to copy\n@@ -1853,12 +1914,10 @@ static void i40e_get_ethtool_stats(struct net_device *netdev,\n \t\t\t\t struct ethtool_stats *stats, u64 *data)\n {\n \tstruct i40e_netdev_priv *np = netdev_priv(netdev);\n-\tstruct i40e_ring *tx_ring, *rx_ring;\n \tstruct i40e_vsi *vsi = np->vsi;\n \tstruct i40e_pf *pf = vsi->back;\n \tstruct i40e_veb *veb = pf->veb[pf->lan_veb];\n \tunsigned int i;\n-\tunsigned int start;\n \tbool veb_stats;\n \tu64 *p = data;\n \n@@ -1870,38 +1929,12 @@ static void i40e_get_ethtool_stats(struct net_device *netdev,\n \ti40e_add_ethtool_stats(&data, vsi, i40e_gstrings_misc_stats);\n \n \trcu_read_lock();\n-\tfor (i = 0; i < I40E_MAX_NUM_QUEUES(netdev) ; i++) {\n-\t\ttx_ring = READ_ONCE(vsi->tx_rings[i]);\n-\n-\t\tif (!tx_ring) {\n-\t\t\t/* Bump the stat counter to skip these stats, and make\n-\t\t\t * sure the memory is zero'd\n-\t\t\t */\n-\t\t\t*(data++) = 0;\n-\t\t\t*(data++) = 0;\n-\t\t\t*(data++) = 0;\n-\t\t\t*(data++) = 0;\n-\t\t\tcontinue;\n-\t\t}\n-\n-\t\t/* process Tx ring statistics */\n-\t\tdo {\n-\t\t\tstart = u64_stats_fetch_begin_irq(&tx_ring->syncp);\n-\t\t\tdata[0] = tx_ring->stats.packets;\n-\t\t\tdata[1] = tx_ring->stats.bytes;\n-\t\t} while (u64_stats_fetch_retry_irq(&tx_ring->syncp, start));\n-\t\tdata += 2;\n-\n-\t\t/* Rx ring is the 2nd half of the queue pair */\n-\t\trx_ring = &tx_ring[1];\n-\t\tdo {\n-\t\t\tstart = u64_stats_fetch_begin_irq(&rx_ring->syncp);\n-\t\t\tdata[0] = rx_ring->stats.packets;\n-\t\t\tdata[1] = rx_ring->stats.bytes;\n-\t\t} while (u64_stats_fetch_retry_irq(&rx_ring->syncp, start));\n-\t\tdata += 2;\n+\tfor (i = 0; i < netdev->num_tx_queues; i++) {\n+\t\ti40e_add_queue_stats(&data, READ_ONCE(vsi->tx_rings[i]));\n+\t\ti40e_add_queue_stats(&data, READ_ONCE(vsi->rx_rings[i]));\n \t}\n \trcu_read_unlock();\n+\n \tif (vsi != pf->vsi[pf->lan_vsi] || pf->hw.partition_id != 1)\n \t\tgoto check_data_pointer;\n \n@@ -1990,16 +2023,13 @@ static void i40e_get_stat_strings(struct net_device *netdev, u8 *data)\n \n \ti40e_add_stat_strings(&data, i40e_gstrings_misc_stats);\n \n-\tfor (i = 0; i < I40E_MAX_NUM_QUEUES(netdev); i++) {\n-\t\tsnprintf(data, ETH_GSTRING_LEN, \"tx-%u.tx_packets\", i);\n-\t\tdata += ETH_GSTRING_LEN;\n-\t\tsnprintf(data, ETH_GSTRING_LEN, \"tx-%u.tx_bytes\", i);\n-\t\tdata += ETH_GSTRING_LEN;\n-\t\tsnprintf(data, ETH_GSTRING_LEN, \"rx-%u.rx_packets\", i);\n-\t\tdata += ETH_GSTRING_LEN;\n-\t\tsnprintf(data, ETH_GSTRING_LEN, \"rx-%u.rx_bytes\", i);\n-\t\tdata += ETH_GSTRING_LEN;\n+\tfor (i = 0; i < netdev->num_tx_queues; i++) {\n+\t\ti40e_add_stat_strings(&data, i40e_gstrings_queue_stats,\n+\t\t\t\t \"tx\", i);\n+\t\ti40e_add_stat_strings(&data, i40e_gstrings_queue_stats,\n+\t\t\t\t \"rx\", i);\n \t}\n+\n \tif (vsi != pf->vsi[pf->lan_vsi] || pf->hw.partition_id != 1)\n \t\treturn;\n \n", "prefixes": [ "next", "S95", "02/12" ] }