linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ioana Radulescu <ruxandra.radulescu@nxp.com>
To: <gregkh@linuxfoundation.org>
Cc: <devel@driverdev.osuosl.org>, <linux-kernel@vger.kernel.org>,
	<agraf@suse.de>, <arnd@arndb.de>,
	<linux-arm-kernel@lists.infradead.org>,
	<alexandru.marginean@nxp.com>, <bogdan.hamciuc@nxp.com>,
	<stuyoder@gmail.com>, <laurentiu.tudor@nxp.com>,
	<ruxandra.radulescu@nxp.com>, <roy.pledge@nxp.com>,
	<haiying.wang@nxp.com>
Subject: [PATCH v2 6/9] staging: fsl-dpaa2/eth: Add driver specific stats
Date: Wed, 12 Apr 2017 11:25:35 -0500	[thread overview]
Message-ID: <20170412162538.25302-7-ruxandra.radulescu@nxp.com> (raw)
In-Reply-To: <20170412162538.25302-1-ruxandra.radulescu@nxp.com>

Add custom statistics to be reported via ethtool -S. These include
driver specific per-cpu statistics as well as queue and channel
counters.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@nxp.com>
---
v2: no changes

 drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c     | 42 ++++++++++++++++++-
 drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h     | 36 ++++++++++++++++
 drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c | 49 +++++++++++++++++++++-
 3 files changed, 123 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
index f13f72f3dd9a..67f007bdbe79 100644
--- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
@@ -208,6 +208,7 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
 	void *vaddr;
 	struct sk_buff *skb;
 	struct rtnl_link_stats64 *percpu_stats;
+	struct dpaa2_eth_drv_stats *percpu_extras;
 	struct device *dev = priv->net_dev->dev.parent;
 	struct dpaa2_fas *fas;
 	u32 status = 0;
@@ -219,6 +220,7 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
 	prefetch(vaddr + dpaa2_fd_get_offset(fd));
 
 	percpu_stats = this_cpu_ptr(priv->percpu_stats);
+	percpu_extras = this_cpu_ptr(priv->percpu_extras);
 
 	if (fd_format == dpaa2_fd_single) {
 		skb = build_linear_skb(priv, ch, fd, vaddr);
@@ -227,6 +229,8 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
 				vaddr + dpaa2_fd_get_offset(fd);
 		skb = build_frag_skb(priv, ch, sgt);
 		skb_free_frag(vaddr);
+		percpu_extras->rx_sg_frames++;
+		percpu_extras->rx_sg_bytes += dpaa2_fd_get_len(fd);
 	} else {
 		/* We don't support any other format */
 		goto err_frame_format;
@@ -291,6 +295,7 @@ static int consume_frames(struct dpaa2_eth_channel *ch)
 
 		fd = dpaa2_dq_fd(dq);
 		fq = (struct dpaa2_eth_fq *)dpaa2_dq_fqd_ctx(dq);
+		fq->stats.frames++;
 
 		fq->consume(priv, ch, fd, &ch->napi);
 		cleaned++;
@@ -532,11 +537,13 @@ static int dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
 	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
 	struct dpaa2_fd fd;
 	struct rtnl_link_stats64 *percpu_stats;
+	struct dpaa2_eth_drv_stats *percpu_extras;
 	struct dpaa2_eth_fq *fq;
 	u16 queue_mapping;
 	int err, i;
 
 	percpu_stats = this_cpu_ptr(priv->percpu_stats);
+	percpu_extras = this_cpu_ptr(priv->percpu_extras);
 
 	if (unlikely(skb_headroom(skb) < DPAA2_ETH_NEEDED_HEADROOM(priv))) {
 		struct sk_buff *ns;
@@ -563,10 +570,14 @@ static int dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
 	/* Setup the FD fields */
 	memset(&fd, 0, sizeof(fd));
 
-	if (skb_is_nonlinear(skb))
+	if (skb_is_nonlinear(skb)) {
 		err = build_sg_fd(priv, skb, &fd);
-	else
+		percpu_extras->tx_sg_frames++;
+		percpu_extras->tx_sg_bytes += skb->len;
+	} else {
 		err = build_single_fd(priv, skb, &fd);
+	}
+
 	if (unlikely(err)) {
 		percpu_stats->tx_dropped++;
 		goto err_build_fd;
@@ -583,6 +594,7 @@ static int dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
 		if (err != -EBUSY)
 			break;
 	}
+	percpu_extras->tx_portal_busy += i;
 	if (unlikely(err < 0)) {
 		percpu_stats->tx_errors++;
 		/* Clean up everything, including freeing the skb */
@@ -608,8 +620,13 @@ static void dpaa2_eth_tx_conf(struct dpaa2_eth_priv *priv,
 			      struct napi_struct *napi __always_unused)
 {
 	struct rtnl_link_stats64 *percpu_stats;
+	struct dpaa2_eth_drv_stats *percpu_extras;
 	u32 status = 0;
 
+	percpu_extras = this_cpu_ptr(priv->percpu_extras);
+	percpu_extras->tx_conf_frames++;
+	percpu_extras->tx_conf_bytes += dpaa2_fd_get_len(fd);
+
 	free_tx_fd(priv, fd, &status);
 
 	if (unlikely(status & DPAA2_ETH_TXCONF_ERR_MASK)) {
@@ -814,13 +831,19 @@ static int refill_pool(struct dpaa2_eth_priv *priv,
 static int pull_channel(struct dpaa2_eth_channel *ch)
 {
 	int err;
+	int dequeues = -1;
 
 	/* Retry while portal is busy */
 	do {
 		err = dpaa2_io_service_pull_channel(NULL, ch->ch_id, ch->store);
+		dequeues++;
 		cpu_relax();
 	} while (err == -EBUSY);
 
+	ch->stats.dequeue_portal_busy += dequeues;
+	if (unlikely(err))
+		ch->stats.pull_err++;
+
 	return err;
 }
 
@@ -868,6 +891,8 @@ static int dpaa2_eth_poll(struct napi_struct *napi, int budget)
 		} while (err == -EBUSY);
 	}
 
+	ch->stats.frames += cleaned;
+
 	return cleaned;
 }
 
@@ -1320,6 +1345,10 @@ static void cdan_cb(struct dpaa2_io_notification_ctx *ctx)
 	struct dpaa2_eth_channel *ch;
 
 	ch = container_of(ctx, struct dpaa2_eth_channel, nctx);
+
+	/* Update NAPI statistics */
+	ch->stats.cdan++;
+
 	napi_schedule_irqoff(&ch->napi);
 }
 
@@ -2345,6 +2374,12 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
 		err = -ENOMEM;
 		goto err_alloc_percpu_stats;
 	}
+	priv->percpu_extras = alloc_percpu(*priv->percpu_extras);
+	if (!priv->percpu_extras) {
+		dev_err(dev, "alloc_percpu(percpu_extras) failed\n");
+		err = -ENOMEM;
+		goto err_alloc_percpu_extras;
+	}
 
 	err = netdev_init(net_dev);
 	if (err)
@@ -2387,6 +2422,8 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
 err_csum:
 	unregister_netdev(net_dev);
 err_netdev_init:
+	free_percpu(priv->percpu_extras);
+err_alloc_percpu_extras:
 	free_percpu(priv->percpu_stats);
 err_alloc_percpu_stats:
 	del_ch_napi(priv);
@@ -2425,6 +2462,7 @@ static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev)
 
 	free_rings(priv);
 	free_percpu(priv->percpu_stats);
+	free_percpu(priv->percpu_extras);
 
 	del_ch_napi(priv);
 	free_dpbp(priv);
diff --git a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
index b30231891eef..f2b0a60795fe 100644
--- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
@@ -197,6 +197,38 @@ struct dpaa2_fas {
  */
 #define DPAA2_ETH_ENQUEUE_RETRIES	10
 
+/* Driver statistics, other than those in struct rtnl_link_stats64.
+ * These are usually collected per-CPU and aggregated by ethtool.
+ */
+struct dpaa2_eth_drv_stats {
+	__u64	tx_conf_frames;
+	__u64	tx_conf_bytes;
+	__u64	tx_sg_frames;
+	__u64	tx_sg_bytes;
+	__u64	rx_sg_frames;
+	__u64	rx_sg_bytes;
+	/* Enqueues retried due to portal busy */
+	__u64	tx_portal_busy;
+};
+
+/* Per-FQ statistics */
+struct dpaa2_eth_fq_stats {
+	/* Number of frames received on this queue */
+	__u64 frames;
+};
+
+/* Per-channel statistics */
+struct dpaa2_eth_ch_stats {
+	/* Volatile dequeues retried due to portal busy */
+	__u64 dequeue_portal_busy;
+	/* Number of CDANs; useful to estimate avg NAPI len */
+	__u64 cdan;
+	/* Number of frames received on queues from this channel */
+	__u64 frames;
+	/* Pull errors */
+	__u64 pull_err;
+};
+
 /* Maximum number of queues associated with a DPNI */
 #define DPAA2_ETH_MAX_RX_QUEUES		16
 #define DPAA2_ETH_MAX_TX_QUEUES		NR_CPUS
@@ -224,6 +256,7 @@ struct dpaa2_eth_fq {
 			struct dpaa2_eth_channel *,
 			const struct dpaa2_fd *,
 			struct napi_struct *);
+	struct dpaa2_eth_fq_stats stats;
 };
 
 struct dpaa2_eth_channel {
@@ -236,6 +269,7 @@ struct dpaa2_eth_channel {
 	struct dpaa2_io_store *store;
 	struct dpaa2_eth_priv *priv;
 	int buf_count;
+	struct dpaa2_eth_ch_stats stats;
 };
 
 struct dpaa2_eth_hash_fields {
@@ -275,6 +309,8 @@ struct dpaa2_eth_priv {
 
 	/* Standard statistics */
 	struct rtnl_link_stats64 __percpu *percpu_stats;
+	/* Extra stats, in addition to the ones known by the kernel */
+	struct dpaa2_eth_drv_stats __percpu *percpu_extras;
 
 	u16 mc_token;
 
diff --git a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c
index 4378956a5527..dd0cffa908ef 100644
--- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c
@@ -56,6 +56,23 @@ char dpaa2_ethtool_stats[][ETH_GSTRING_LEN] = {
 
 #define DPAA2_ETH_NUM_STATS	ARRAY_SIZE(dpaa2_ethtool_stats)
 
+char dpaa2_ethtool_extras[][ETH_GSTRING_LEN] = {
+	/* per-cpu stats */
+	"tx conf frames",
+	"tx conf bytes",
+	"tx sg frames",
+	"tx sg bytes",
+	"rx sg frames",
+	"rx sg bytes",
+	"enqueue portal busy",
+	/* Channel stats */
+	"dequeue portal busy",
+	"channel pull errors",
+	"cdan",
+};
+
+#define DPAA2_ETH_NUM_EXTRA_STATS	ARRAY_SIZE(dpaa2_ethtool_extras)
+
 static void dpaa2_eth_get_drvinfo(struct net_device *net_dev,
 				  struct ethtool_drvinfo *drvinfo)
 {
@@ -147,6 +164,10 @@ static void dpaa2_eth_get_strings(struct net_device *netdev, u32 stringset,
 			strlcpy(p, dpaa2_ethtool_stats[i], ETH_GSTRING_LEN);
 			p += ETH_GSTRING_LEN;
 		}
+		for (i = 0; i < DPAA2_ETH_NUM_EXTRA_STATS; i++) {
+			strlcpy(p, dpaa2_ethtool_extras[i], ETH_GSTRING_LEN);
+			p += ETH_GSTRING_LEN;
+		}
 		break;
 	}
 }
@@ -155,7 +176,7 @@ static int dpaa2_eth_get_sset_count(struct net_device *net_dev, int sset)
 {
 	switch (sset) {
 	case ETH_SS_STATS: /* ethtool_get_stats(), ethtool_get_drvinfo() */
-		return DPAA2_ETH_NUM_STATS;
+		return DPAA2_ETH_NUM_STATS + DPAA2_ETH_NUM_EXTRA_STATS;
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -171,9 +192,14 @@ static void dpaa2_eth_get_ethtool_stats(struct net_device *net_dev,
 	int j, k, err;
 	int num_cnt;
 	union dpni_statistics dpni_stats;
+	u64 cdan = 0;
+	u64 portal_busy = 0, pull_err = 0;
 	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+	struct dpaa2_eth_drv_stats *extras;
+	struct dpaa2_eth_ch_stats *ch_stats;
 
-	memset(data, 0, sizeof(u64) * DPAA2_ETH_NUM_STATS);
+	memset(data, 0,
+	       sizeof(u64) * (DPAA2_ETH_NUM_STATS + DPAA2_ETH_NUM_EXTRA_STATS));
 
 	/* Print standard counters, from DPNI statistics */
 	for (j = 0; j <= 2; j++) {
@@ -197,6 +223,25 @@ static void dpaa2_eth_get_ethtool_stats(struct net_device *net_dev,
 		for (k = 0; k < num_cnt; k++)
 			*(data + i++) = dpni_stats.raw.counter[k];
 	}
+
+	/* Print per-cpu extra stats */
+	for_each_online_cpu(k) {
+		extras = per_cpu_ptr(priv->percpu_extras, k);
+		for (j = 0; j < sizeof(*extras) / sizeof(__u64); j++)
+			*((__u64 *)data + i + j) += *((__u64 *)extras + j);
+	}
+	i += j;
+
+	for (j = 0; j < priv->num_channels; j++) {
+		ch_stats = &priv->channel[j]->stats;
+		cdan += ch_stats->cdan;
+		portal_busy += ch_stats->dequeue_portal_busy;
+		pull_err += ch_stats->pull_err;
+	}
+
+	*(data + i++) = portal_busy;
+	*(data + i++) = pull_err;
+	*(data + i++) = cdan;
 }
 
 static int dpaa2_eth_get_rxnfc(struct net_device *net_dev,
-- 
2.11.0

  parent reply	other threads:[~2017-04-12 16:28 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-12 16:25 [PATCH v2 0/9] staging: Introduce the DPAA2 Ethernet driver Ioana Radulescu
2017-04-12 16:25 ` [PATCH v2 1/9] bus: fsl-mc: add DPCON object APIs Ioana Radulescu
2017-04-12 16:25 ` [PATCH v2 2/9] staging: fsl-dpaa2/eth: Add Ethernet driver overview document Ioana Radulescu
2017-04-12 16:25 ` [PATCH v2 3/9] staging: fsl-dpaa2/eth: Add APIs for DPNI objects Ioana Radulescu
2017-04-12 16:25 ` [PATCH v2 4/9] staging: fsl-dpaa2/eth: Add Freescale DPAA2 Ethernet driver Ioana Radulescu
2017-04-12 16:25 ` [PATCH v2 5/9] staging: fsl-dpaa2/eth: Add ethtool support Ioana Radulescu
2017-04-12 16:25 ` Ioana Radulescu [this message]
2017-04-12 16:25 ` [PATCH v2 7/9] staging: fsl-dpaa2/eth: Add trace points Ioana Radulescu
2017-04-12 16:25 ` [PATCH v2 8/9] staging: fsl-dpaa2/eth: Add TODO file Ioana Radulescu
2017-04-19  3:44   ` Stuart Yoder
2017-04-20  8:31     ` Ruxandra Ioana Radulescu
2017-04-12 16:25 ` [PATCH v2 9/9] staging: fsl-dpaa2/eth: Add maintainer for Ethernet driver Ioana Radulescu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170412162538.25302-7-ruxandra.radulescu@nxp.com \
    --to=ruxandra.radulescu@nxp.com \
    --cc=agraf@suse.de \
    --cc=alexandru.marginean@nxp.com \
    --cc=arnd@arndb.de \
    --cc=bogdan.hamciuc@nxp.com \
    --cc=devel@driverdev.osuosl.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=haiying.wang@nxp.com \
    --cc=laurentiu.tudor@nxp.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=roy.pledge@nxp.com \
    --cc=stuyoder@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).