From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932639AbcKBUVq (ORCPT ); Wed, 2 Nov 2016 16:21:46 -0400 Received: from mail-bl2nam02on0052.outbound.protection.outlook.com ([104.47.38.52]:10336 "EHLO NAM02-BL2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1756318AbcKBUR4 (ORCPT ); Wed, 2 Nov 2016 16:17:56 -0400 Authentication-Results: spf=fail (sender IP is 192.88.158.2) smtp.mailfrom=nxp.com; transmode.se; dkim=none (message not signed) header.d=none;transmode.se; dmarc=fail action=none header.from=nxp.com; From: Madalin Bucur To: CC: , , , , , , , Subject: [PATCH net-next v6 05/10] dpaa_eth: add ethtool statistics Date: Wed, 2 Nov 2016 22:17:29 +0200 Message-ID: <1478117854-8952-6-git-send-email-madalin.bucur@nxp.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1478117854-8952-1-git-send-email-madalin.bucur@nxp.com> References: <1478117854-8952-1-git-send-email-madalin.bucur@nxp.com> Reply-To: X-EOPAttributedMessage: 0 X-Matching-Connectors: 131225914738411615;(91ab9b29-cfa4-454e-5278-08d120cd25b8);() X-Forefront-Antispam-Report: CIP:192.88.158.2;IPV:NLI;CTRY:US;EFV:NLI;SFV:NSPM;SFS:(10009020)(6009001)(7916002)(2980300002)(1110001)(1109001)(339900001)(189002)(199003)(7846002)(2906002)(229853001)(81156014)(81166006)(305945005)(19580405001)(110136003)(8676002)(8936002)(2950100002)(4326007)(36756003)(5003940100001)(86362001)(47776003)(3450700001)(356003)(5660300001)(85426001)(50226002)(43066003)(87936001)(33646002)(6916009)(77096005)(626004)(19580395003)(97736004)(50466002)(69596002)(11100500001)(189998001)(6666003)(2351001)(104016004)(106466001)(105606002)(68736007)(586003)(53806999)(76176999)(50986999)(48376002);DIR:OUT;SFP:1101;SCL:1;SRVR:BN3PR03MB2369;H:az84smr01.freescale.net;FPR:;SPF:Fail;PTR:InfoDomainNonexistent;MX:1;A:1;LANG:en; X-Microsoft-Exchange-Diagnostics: 1;BL2FFO11FD057;1:NQ6CMfYC/yhDawId5k27DEGbmrENSQW6sLPekGGRNiSU/EU5WP4RKuUR15ga3a/FwUhcPNe2IaJuErKfliCEfPzGgM+8Z7cOOlyecKFRFkYzdKqRzF022JmzoLkgeo/BrgINwl1M9Z55dmclc8bT+hIN5ReZkrUPcB24rVeQvUodrz9HY9CJp6ekbuJ+Fb0YD/H2o6cdpCNGYbD8NsnTefk2+PvqdXzCViO0tgWd5EzQ5IxktTg6xs4EFLTHS4uknfVJVGtNt278/Wg1QwOgRrEp1xMGIi5rLrjYXNhXhwpI7Z8SJI621eu7vvpfz7KfV0pV0BoYV3h95I+FeZRQ1EQNY0IcbNAAqyqlEiNSzveVfpuu/G3mjg0G7PD+0r7GZbTMegaA/dtq8x1SZNrLuID9S5jN0MFbSPA8LJARN13MaF7jHBz93ghOnKKZ+TKueEhn/nP5lVp4jinY2AGA0z9+wSiMf0aI6NehdPyi7xSIb90VZg6zvwEGxE1sgEbNJuFa5SH2277muVi1TaSo8i945q4nJBX3hWphry0gKR6RtVEjuLlGMZpNHwYSoDx4fu3JCXCEpeZ4QdViH2br1IV518RnNwkSGPuIna2fo0lT5p5KQmF6LNDWwCk6raby MIME-Version: 1.0 Content-Type: text/plain X-MS-Office365-Filtering-Correlation-Id: df2e1aab-8b9a-4447-fd4f-08d4035d53b2 X-Microsoft-Exchange-Diagnostics: 1;BN3PR03MB2369;2:uDqc+3oyMOLNdgK8aQLTGEtjUK/VQC1/IStejPeABzQvDw8mss3sZQSt+ah9zGpHGtvi3CXLbcmazQDr7eVoK6WnOQUXCOp9MijJkUQU21av6xMgOTzWO4uCTwUuSQpnjnDqdvv7jHOeyeYRuv6NfufHFVFQ3C5fdgSZra75fpodUAdXQHaaMlEtMqndps57L0HBNPANeJsgVjFhjaQLEQ==;3:H/Xnwn+wug6IQ2+WRVssa6GQ7YX54QPVw7MQAoyMCuTdOLlBmAIe8/3HcpPxxApqNP6j5sEEyj3epklaYj35/Thbqsz/dILGIeNEdfuNMtTyFBmmkGj2wZ9Ua0oadQMFxfDFAgLNaIp2dEkPjzs1NcjIVh5BJOjYfb92NeGZYI4ATQR3NvO5QMtdj+TwOMvjjYW5RY8qtVlHHIwfByBjb21H6nS1fnit93qegHGIjkmuBfIspQqLvb7NQIvNI0FU X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BN3PR03MB2369; X-Microsoft-Exchange-Diagnostics: 1;BN3PR03MB2369;25:KvHQGdR9o0K6QTL5CTXT7AGIh5TgdJGqYe2HOqU+jcA4QHYBTuy9QpZRWacgQhMISKphjv/T6lcmc0H1EN5G8qkrtQ5W2IBUvvAg8/xhrEL8fZulYUwEXcaZHxD1+0hGMFnil6hGp1k3Efoq1QD7Srrg4oRLZAO9mj+Z0J6OshF7U8c2167ETNzhj9w+WtTxnawJoQq4XQTdFgw7IQ+oWLahkP1Ol7+u45EtMujta/k5Uf8tsKblPt0QvhFVAILKbeYSO4KTX/37crtQwgzFe6fqin3I1Gg6xD2FCHJKtk0U0iVGhAeQaXV5wUJ1b1wKMVHHSvOT5Kqab8iqwznwZWYnGaE0zNMwyqh/98LDW2l8hctaotBQtsrZlYYlb8fUwmSrNc18kSuEQXKgYQZsK8m90iLZ2uQScLdpSTLfT3TSSrycbADcQGSkTwZk2zqxxqLJVufRX1e1WgyO5m01MpMnmaLnsNJi4ljEMQp38wVLimvxExWI5urVIdzeD6uAojE44DkoX53wtfcR6XNUd0Dr9t7M3dphG6UieCVOGhdoCJoETx8Ppeom2ozx+H7LlOUe4RUBJvykBFQxzLtCOVnGcxrbPntanvPN0kUllJcpbg5Hi54MShOsomt0O/y+Yc31XvMbqbk9vKfgAo//8NuvS15i+IaoA2DuPpthM8wEiRDkc78H4FgBSstYPeU1h7pNe/AExC1hnm6iXKBXwYrjVcEhvLSMDmAp/l4pc0laf0fGe+ewbQfL8OeMwZC1rKLATEVDGvT/O0sEglU4DRIln9yKVloPpl4ojVlVM+ZfKwLXcumKRUnLddW0dIYQ X-Microsoft-Exchange-Diagnostics: 1;BN3PR03MB2369;31:HjxqVZhk2l1H3rVR+7OwDVHNpgkPiEk5F4L6nb3BZr+Glfc46DT7pCgKNbsygZHBAClmY1bp2LVCAWOq17svEmZt4iaOW/OeJem8DTInnFGgkhQ01ywmJSEv9aCfluCdMsgaOF2xlWZ74vXPqzNpJthz4aCraXyg/e57SRzJjnBxX1kW5YC+BntCDVL0JGSwVkb51Yn4ziezSppPSec2Sn53bT1+muiqANfPtUdLNMj0UbcS/ndKM/Y5AwEAJowQro3Me11BpeEdZTl10h4MGw==;4:x0dWPH4V2Cr/tYY/Jk+6zC2FBsG/tV6aRMPVSnCHGKB0qCDCMvFrMP6EB9SMz4el/FLrje2yagHoFOSo4gFVAFHlZxpcy+h1aIl9Vk0W2FY46MHBxr0TmIUXn3Cm9GFsd23gKd3hdgTsI/TR04cWCOyvwyO8MMntq1JFcgLS6nu8wuRVk4RL/TvrAD9eJ1XV7nPs3GGxty2q5mwAr60qAbp6pWP+DUcxLGU/gjhSRY0aBIeouCOUvsBYH28esWVE1i9mb+vd/IQDgfPai5EWwVG+d9P6/RGzAaU8JaeWf9kSfELwlIfcDXWXAhgw5pU6RohHw3OGAJ/1Jt0lpkBs6kv/6jfYZeBuFIYj+UoVzf4j12q2xsNt9FsMw3kW1TUQtpljVqyVjbwyxiSNRH4EOUkqg6brX0mHpPuXkZyD7fQi+aZvJcyD9vTlC/zbrnywjVYBg7b6Ei+7ICO0oLrM6tf+9IaTnGC3tnGHbv60mS1CLrrzTb2NLyyFUDpIC8/OdnNpxTa0qhG1umRBigJoapG3nVtg5ueLCD/Q4zUPZ+L3LkTpTgd8dl6BBYqpa307I1vjuzrvvypC65K+A+YfCQ== X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(185117386973197)(275809806118684); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6040176)(601004)(2401047)(13024025)(13015025)(13023025)(13017025)(13018025)(8121501046)(5005006)(3002001)(10201501046)(6055026);SRVR:BN3PR03MB2369;BCL:0;PCL:0;RULEID:(400006);SRVR:BN3PR03MB2369; X-Forefront-PRVS: 0114FF88F6 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BN3PR03MB2369;23:LOpU7rGNatZH1qDbeeQXXk3wf7qFZwVBYus3p5mG2?= =?us-ascii?Q?PrEQ5ydQOtKMpO/avto0Ch0F50L0Wfpm6W4N3owpUYF7vrCDqwlGgNntghGY?= =?us-ascii?Q?S4IVkbRIR23Ak6pRUrB4nc/fcJkzMF9FsKL19XHmAJJtDWpRfR0FD+DLFk2I?= =?us-ascii?Q?ES64Y2YgAGCg2UuoteZTCvbeXclqREqLhdikafqfOMENoEzzFipsrXzY24SX?= =?us-ascii?Q?WY1pYbVKAmyfsCr9JbwEdSY9RZlg6LrsMBIVYqOvLD4xOBE/p6xVA/XpL4AZ?= =?us-ascii?Q?dRJn6/cJrKultIEwlaJ74orXK6y1nDAaX9HnoAnTWDLxCY32UbZQsTfBIx9r?= =?us-ascii?Q?PuH7srGMpAtLm4VFoWFj8Nd1ZcIzbHmjjo6NLexIY4DCfAa6FsrBDh3grHLI?= =?us-ascii?Q?08qMICHnFJS9wtgVNWyZxturnI/pnQcQD08afsnpOjFEoQ1I/9mWfjH3byDx?= =?us-ascii?Q?QFz/EwPZGtkPa3rdk/nIT/u0vYp/gQQx8UPRF0Rc6iqGF2U93s6LuW+Smi5e?= =?us-ascii?Q?RZBML5WIRoqrv2d2k1X0/+EaSyxXeTLSHi9uyJcMvn4OOH1qHZP4EqpjrX9n?= =?us-ascii?Q?Y40N444g1SsA1iw/cOkF/suPc2CvTDkiVNo1tNg0QZrPS1O6J1y0+0ymmui/?= =?us-ascii?Q?6XiJcTtYj+Iem/K84FQztoM/5qt2wYolLslUiYbIVKD3DL9NJfJWk7mKxmRD?= =?us-ascii?Q?qHDg9n8ApD6/HDpFE9SXOE7uF2xqZegcraC8AOsAviWdmI1OqrdFT9cxIfe6?= =?us-ascii?Q?Mu0bBVstAkJhz9XSkZQzoW5wf2xhy3zbZiXtuZRW/Gb46spTEMYxrEtW9+6+?= =?us-ascii?Q?7mXiZUoPe7oCIpNhRW0G09vsXrtHN+rqovR1OOW7RtC+FjPDLwyCJL7kqzzz?= =?us-ascii?Q?woKrad4yKqS4nkcpes9bsAd0LRRNZGWBLsjWY/1vAgP98/QqOwwx34iy9fhD?= =?us-ascii?Q?Cg+F6MeMm8Ewz7amWlNOaRn6+wT/QoErGr5QYOvlYv0UYHy2H/P18E+p1BgA?= =?us-ascii?Q?byV+6iOoVLkBo6ewHMilqnAXSjJcamzD+kwZF/uN+NrvLAgnZAI/cvcO0UBi?= =?us-ascii?Q?Jxds1Sppyai+CSXMcujLdqDHntMinkehBz+CEo5NPuvc8P6JAVAzb4EP9Ukd?= =?us-ascii?Q?2GsSyN/i1ed381VtHZuXwkzZEUBLATliUYpkyteM5Yb4dBGkSDHC/IWN/+bM?= =?us-ascii?Q?NftBV8rhmPFSgE3fksNtHjJmdts05SivNGXZHsoBoN1LY3XTcEwQJX+Maat+?= =?us-ascii?Q?BBry14Vt6u5ayhfxwE=3D?= X-Microsoft-Exchange-Diagnostics: 1;BN3PR03MB2369;6:lDL/BlklONpg6PvreVe8Xv+luAMUSWL8yEFhc4V2UYAQqFAFSbNx7aHAe3n8Ch9E46sDGE9wPZ83sitfmBXtlf3gkF+ERDG/IXXn/Sx4aFisuLAnkjLCm5hcui0CGIUrbWc2cZJxsfJVuRWugc4d5wU4sin1FFZpC10F/nSPWvKEXHCLogU0mJzjNWXi8TiNRSaawFd5KIYZivJFvHjIFjNOK7iyW4d6HHHMB6ppbazLYxO9DljZfKlycIzQZ/2VpbCz7irdQrJksbhrZXlD06kLyGlDfvObzI6+81yncltFAjVVkhdVXfl2DkqSX2IP;5:gOMOgrysyoQG6LqEbcDaaZM4Wty8sqVUd7ckfI4K3KcuTVhCxYa+6oHqVwxanXhuIJStJ/seBxDeC04oAdIo0u4KCojrcizUNpLZV+OkyUeq4SNPwfm3Hvk2pp/EYDtk41xbNGs/BdGLu0NXEjhdjNU4mtmSSFB8PIja9mGDUxAE4iEnPDcLQddpiGvGyiib;24:Vq+3Iv8ggqEYluf4dZcvIUnNh5XyXRe7npiQdvc0I5okzCOBSI2XZ1iQxbeCl4MhSfXzqREYMM0WdSoJgvolGmMjRI43eh3NWwz5tiyFwv0= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;BN3PR03MB2369;7:gckNepG3SB672AtuHLU9sFHexKLDwx2TXZa9U/1u5mxygCfRaOBSVdcu1LfIsBi19JzH3y5KX+EME/TP7ubKsGDE1yAGMxheYf0VpCUo9Tp/HTdQpIyiRiZnSgnZ7HJ2aLlusIrQKcXv5C3gcD/d4q1JnTxkJher0urAYUCwOerl5Mx2hHX9NbMVhz0fS4eOTvnRTJi325dGnI4vHy0lbRcQu2V1G7PD9NSAq+iJEt+kQ1GFkoEomnFWenqq296ZsNg44H5vRjvqZMKUw44UUiT2KwynGr7IE+Z/xHVbZYR6vE+XtmCAFs/sVy/wKAsH7Man7woUL2/H5cnVaxB7e1a8dpNUOrxk+GuJCr1AaLE= X-MS-Exchange-CrossTenant-OriginalArrivalTime: 02 Nov 2016 20:17:53.4823 (UTC) X-MS-Exchange-CrossTenant-Id: 5afe0b00-7697-4969-b663-5eab37d5f47e X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=5afe0b00-7697-4969-b663-5eab37d5f47e;Ip=[192.88.158.2];Helo=[az84smr01.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN3PR03MB2369 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add a series of counters to be exported through ethtool: - add detailed counters for reception errors; - add detailed counters for QMan enqueue reject events; - count the number of fragmented skbs received from the stack; - count all frames received on the Tx confirmation path; - add congestion group statistics; - count the number of interrupts for each CPU. Signed-off-by: Ioana Ciornei Signed-off-by: Madalin Bucur --- drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 54 +++++- drivers/net/ethernet/freescale/dpaa/dpaa_eth.h | 33 ++++ drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c | 199 +++++++++++++++++++++ 3 files changed, 284 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index 681abf1..3deb240 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -755,10 +755,15 @@ static void dpaa_eth_cgscn(struct qman_portal *qm, struct qman_cgr *cgr, struct dpaa_priv *priv = (struct dpaa_priv *)container_of(cgr, struct dpaa_priv, cgr_data.cgr); - if (congested) + if (congested) { + priv->cgr_data.congestion_start_jiffies = jiffies; netif_tx_stop_all_queues(priv->net_dev); - else + priv->cgr_data.cgr_congested_count++; + } else { + priv->cgr_data.congested_jiffies += + (jiffies - priv->cgr_data.congestion_start_jiffies); netif_tx_wake_all_queues(priv->net_dev); + } } static int dpaa_eth_cgr_init(struct dpaa_priv *priv) @@ -1273,6 +1278,37 @@ static void dpaa_fd_release(const struct net_device *net_dev, dpaa_bman_release(dpaa_bp, &bmb, 1); } +static void count_ern(struct dpaa_percpu_priv *percpu_priv, + const union qm_mr_entry *msg) +{ + switch (msg->ern.rc & QM_MR_RC_MASK) { + case QM_MR_RC_CGR_TAILDROP: + percpu_priv->ern_cnt.cg_tdrop++; + break; + case QM_MR_RC_WRED: + percpu_priv->ern_cnt.wred++; + break; + case QM_MR_RC_ERROR: + percpu_priv->ern_cnt.err_cond++; + break; + case QM_MR_RC_ORPWINDOW_EARLY: + percpu_priv->ern_cnt.early_window++; + break; + case QM_MR_RC_ORPWINDOW_LATE: + percpu_priv->ern_cnt.late_window++; + break; + case QM_MR_RC_FQ_TAILDROP: + percpu_priv->ern_cnt.fq_tdrop++; + break; + case QM_MR_RC_ORPWINDOW_RETIRED: + percpu_priv->ern_cnt.fq_retired++; + break; + case QM_MR_RC_ORP_ZERO: + percpu_priv->ern_cnt.orp_zero++; + break; + } +} + /* Turn on HW checksum computation for this outgoing frame. * If the current protocol is not something we support in this regard * (or if the stack has already computed the SW checksum), we do nothing. @@ -1937,6 +1973,7 @@ static int dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev) likely(skb_shinfo(skb)->nr_frags < DPAA_SGT_MAX_ENTRIES)) { /* Just create a S/G fd based on the skb */ err = skb_to_sg_fd(priv, skb, &fd); + percpu_priv->tx_frag_skbuffs++; } else { /* If the egress skb contains more fragments than we support * we have no choice but to linearize it ourselves. @@ -1973,6 +2010,15 @@ static void dpaa_rx_error(struct net_device *net_dev, percpu_priv->stats.rx_errors++; + if (fd->status & FM_FD_ERR_DMA) + percpu_priv->rx_errors.dme++; + if (fd->status & FM_FD_ERR_PHYSICAL) + percpu_priv->rx_errors.fpe++; + if (fd->status & FM_FD_ERR_SIZE) + percpu_priv->rx_errors.fse++; + if (fd->status & FM_FD_ERR_PRS_HDR_ERR) + percpu_priv->rx_errors.phe++; + dpaa_fd_release(net_dev, fd); } @@ -2028,6 +2074,8 @@ static void dpaa_tx_conf(struct net_device *net_dev, percpu_priv->stats.tx_errors++; } + percpu_priv->tx_confirm++; + skb = dpaa_cleanup_tx_fd(priv, fd); consume_skb(skb); @@ -2042,6 +2090,7 @@ static inline int dpaa_eth_napi_schedule(struct dpaa_percpu_priv *percpu_priv, percpu_priv->np.p = portal; napi_schedule(&percpu_priv->np.napi); + percpu_priv->in_interrupt++; return 1; } return 0; @@ -2225,6 +2274,7 @@ static void egress_ern(struct qman_portal *portal, percpu_priv->stats.tx_dropped++; percpu_priv->stats.tx_fifo_errors++; + count_ern(percpu_priv, msg); skb = dpaa_cleanup_tx_fd(priv, fd); dev_kfree_skb_any(skb); diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h index d6ab335..711fb06 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h @@ -95,6 +95,25 @@ struct dpaa_bp { atomic_t refs; }; +struct dpaa_rx_errors { + u64 dme; /* DMA Error */ + u64 fpe; /* Frame Physical Error */ + u64 fse; /* Frame Size Error */ + u64 phe; /* Header Error */ +}; + +/* Counters for QMan ERN frames - one counter per rejection code */ +struct dpaa_ern_cnt { + u64 cg_tdrop; /* Congestion group taildrop */ + u64 wred; /* WRED congestion */ + u64 err_cond; /* Error condition */ + u64 early_window; /* Order restoration, frame too early */ + u64 late_window; /* Order restoration, frame too late */ + u64 fq_tdrop; /* FQ taildrop */ + u64 fq_retired; /* FQ is retired */ + u64 orp_zero; /* ORP disabled */ +}; + struct dpaa_napi_portal { struct napi_struct napi; struct qman_portal *p; @@ -104,7 +123,13 @@ struct dpaa_napi_portal { struct dpaa_percpu_priv { struct net_device *net_dev; struct dpaa_napi_portal np; + u64 in_interrupt; + u64 tx_confirm; + /* fragmented (non-linear) skbuffs received from the stack */ + u64 tx_frag_skbuffs; struct rtnl_link_stats64 stats; + struct dpaa_rx_errors rx_errors; + struct dpaa_ern_cnt ern_cnt; }; struct dpaa_buffer_layout { @@ -133,6 +158,14 @@ struct dpaa_priv { * (and the same) congestion group. */ struct qman_cgr cgr; + /* If congested, when it began. Used for performance stats. */ + u32 congestion_start_jiffies; + /* Number of jiffies the Tx port was congested. */ + u32 congested_jiffies; + /* Counter for the number of times the CGR + * entered congestion state + */ + u32 cgr_congested_count; } cgr_data; /* Use a per-port CGR for ingress traffic. */ bool use_ingress_cgr; diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c index f97f563..71ffe16 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c @@ -36,6 +36,42 @@ #include "dpaa_eth.h" #include "mac.h" +static const char dpaa_stats_percpu[][ETH_GSTRING_LEN] = { + "interrupts", + "rx packets", + "tx packets", + "tx confirm", + "tx S/G", + "tx error", + "rx error", +}; + +static char dpaa_stats_global[][ETH_GSTRING_LEN] = { + /* dpa rx errors */ + "rx dma error", + "rx frame physical error", + "rx frame size error", + "rx header error", + + /* demultiplexing errors */ + "qman cg_tdrop", + "qman wred", + "qman error cond", + "qman early window", + "qman late window", + "qman fq tdrop", + "qman fq retired", + "qman orp disabled", + + /* congestion related stats */ + "congestion time (ms)", + "entered congestion", + "congested (0/1)" +}; + +#define DPAA_STATS_PERCPU_LEN ARRAY_SIZE(dpaa_stats_percpu) +#define DPAA_STATS_GLOBAL_LEN ARRAY_SIZE(dpaa_stats_global) + static int dpaa_get_settings(struct net_device *net_dev, struct ethtool_cmd *et_cmd) { @@ -205,6 +241,166 @@ static int dpaa_set_pauseparam(struct net_device *net_dev, return err; } +static int dpaa_get_sset_count(struct net_device *net_dev, int type) +{ + unsigned int total_stats, num_stats; + + num_stats = num_online_cpus() + 1; + total_stats = num_stats * (DPAA_STATS_PERCPU_LEN + DPAA_BPS_NUM) + + DPAA_STATS_GLOBAL_LEN; + + switch (type) { + case ETH_SS_STATS: + return total_stats; + default: + return -EOPNOTSUPP; + } +} + +static void copy_stats(struct dpaa_percpu_priv *percpu_priv, int num_cpus, + int crr_cpu, u64 *bp_count, u64 *data) +{ + int num_values = num_cpus + 1; + int crr = 0, j; + + /* update current CPU's stats and also add them to the total values */ + data[crr * num_values + crr_cpu] = percpu_priv->in_interrupt; + data[crr++ * num_values + num_cpus] += percpu_priv->in_interrupt; + + data[crr * num_values + crr_cpu] = percpu_priv->stats.rx_packets; + data[crr++ * num_values + num_cpus] += percpu_priv->stats.rx_packets; + + data[crr * num_values + crr_cpu] = percpu_priv->stats.tx_packets; + data[crr++ * num_values + num_cpus] += percpu_priv->stats.tx_packets; + + data[crr * num_values + crr_cpu] = percpu_priv->tx_confirm; + data[crr++ * num_values + num_cpus] += percpu_priv->tx_confirm; + + data[crr * num_values + crr_cpu] = percpu_priv->tx_frag_skbuffs; + data[crr++ * num_values + num_cpus] += percpu_priv->tx_frag_skbuffs; + + data[crr * num_values + crr_cpu] = percpu_priv->stats.tx_errors; + data[crr++ * num_values + num_cpus] += percpu_priv->stats.tx_errors; + + data[crr * num_values + crr_cpu] = percpu_priv->stats.rx_errors; + data[crr++ * num_values + num_cpus] += percpu_priv->stats.rx_errors; + + for (j = 0; j < DPAA_BPS_NUM; j++) { + data[crr * num_values + crr_cpu] = bp_count[j]; + data[crr++ * num_values + num_cpus] += bp_count[j]; + } +} + +static void dpaa_get_ethtool_stats(struct net_device *net_dev, + struct ethtool_stats *stats, u64 *data) +{ + u64 bp_count[DPAA_BPS_NUM], cg_time, cg_num; + struct dpaa_percpu_priv *percpu_priv; + struct dpaa_rx_errors rx_errors; + struct dpaa_ern_cnt ern_cnt; + struct dpaa_priv *priv; + unsigned int num_cpus, offset; + struct dpaa_bp *dpaa_bp; + int total_stats, i, j; + bool cg_status; + + total_stats = dpaa_get_sset_count(net_dev, ETH_SS_STATS); + priv = netdev_priv(net_dev); + num_cpus = num_online_cpus(); + + memset(&bp_count, 0, sizeof(bp_count)); + memset(&rx_errors, 0, sizeof(struct dpaa_rx_errors)); + memset(&ern_cnt, 0, sizeof(struct dpaa_ern_cnt)); + memset(data, 0, total_stats * sizeof(u64)); + + for_each_online_cpu(i) { + percpu_priv = per_cpu_ptr(priv->percpu_priv, i); + for (j = 0; j < DPAA_BPS_NUM; j++) { + dpaa_bp = priv->dpaa_bps[j]; + if (!dpaa_bp->percpu_count) + continue; + bp_count[j] = *(per_cpu_ptr(dpaa_bp->percpu_count, i)); + } + rx_errors.dme += percpu_priv->rx_errors.dme; + rx_errors.fpe += percpu_priv->rx_errors.fpe; + rx_errors.fse += percpu_priv->rx_errors.fse; + rx_errors.phe += percpu_priv->rx_errors.phe; + + ern_cnt.cg_tdrop += percpu_priv->ern_cnt.cg_tdrop; + ern_cnt.wred += percpu_priv->ern_cnt.wred; + ern_cnt.err_cond += percpu_priv->ern_cnt.err_cond; + ern_cnt.early_window += percpu_priv->ern_cnt.early_window; + ern_cnt.late_window += percpu_priv->ern_cnt.late_window; + ern_cnt.fq_tdrop += percpu_priv->ern_cnt.fq_tdrop; + ern_cnt.fq_retired += percpu_priv->ern_cnt.fq_retired; + ern_cnt.orp_zero += percpu_priv->ern_cnt.orp_zero; + + copy_stats(percpu_priv, num_cpus, i, bp_count, data); + } + + offset = (num_cpus + 1) * (DPAA_STATS_PERCPU_LEN + DPAA_BPS_NUM); + memcpy(data + offset, &rx_errors, sizeof(struct dpaa_rx_errors)); + + offset += sizeof(struct dpaa_rx_errors) / sizeof(u64); + memcpy(data + offset, &ern_cnt, sizeof(struct dpaa_ern_cnt)); + + /* gather congestion related counters */ + cg_num = 0; + cg_status = 0; + cg_time = jiffies_to_msecs(priv->cgr_data.congested_jiffies); + if (qman_query_cgr_congested(&priv->cgr_data.cgr, &cg_status) == 0) { + cg_num = priv->cgr_data.cgr_congested_count; + + /* reset congestion stats (like QMan API does */ + priv->cgr_data.congested_jiffies = 0; + priv->cgr_data.cgr_congested_count = 0; + } + + offset += sizeof(struct dpaa_ern_cnt) / sizeof(u64); + data[offset++] = cg_time; + data[offset++] = cg_num; + data[offset++] = cg_status; +} + +static void dpaa_get_strings(struct net_device *net_dev, u32 stringset, + u8 *data) +{ + unsigned int i, j, num_cpus, size; + char string_cpu[ETH_GSTRING_LEN]; + u8 *strings; + + memset(string_cpu, 0, sizeof(string_cpu)); + strings = data; + num_cpus = num_online_cpus(); + size = DPAA_STATS_GLOBAL_LEN * ETH_GSTRING_LEN; + + for (i = 0; i < DPAA_STATS_PERCPU_LEN; i++) { + for (j = 0; j < num_cpus; j++) { + snprintf(string_cpu, ETH_GSTRING_LEN, "%s [CPU %d]", + dpaa_stats_percpu[i], j); + memcpy(strings, string_cpu, ETH_GSTRING_LEN); + strings += ETH_GSTRING_LEN; + } + snprintf(string_cpu, ETH_GSTRING_LEN, "%s [TOTAL]", + dpaa_stats_percpu[i]); + memcpy(strings, string_cpu, ETH_GSTRING_LEN); + strings += ETH_GSTRING_LEN; + } + for (i = 0; i < DPAA_BPS_NUM; i++) { + for (j = 0; j < num_cpus; j++) { + snprintf(string_cpu, ETH_GSTRING_LEN, + "bpool %c [CPU %d]", 'a' + i, j); + memcpy(strings, string_cpu, ETH_GSTRING_LEN); + strings += ETH_GSTRING_LEN; + } + snprintf(string_cpu, ETH_GSTRING_LEN, "bpool %c [TOTAL]", + 'a' + i); + memcpy(strings, string_cpu, ETH_GSTRING_LEN); + strings += ETH_GSTRING_LEN; + } + memcpy(strings, dpaa_stats_global, size); +} + const struct ethtool_ops dpaa_ethtool_ops = { .get_settings = dpaa_get_settings, .set_settings = dpaa_set_settings, @@ -215,4 +411,7 @@ const struct ethtool_ops dpaa_ethtool_ops = { .get_pauseparam = dpaa_get_pauseparam, .set_pauseparam = dpaa_set_pauseparam, .get_link = ethtool_op_get_link, + .get_sset_count = dpaa_get_sset_count, + .get_ethtool_stats = dpaa_get_ethtool_stats, + .get_strings = dpaa_get_strings, }; -- 2.1.0