Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S965056AbbLCMwj (ORCPT ); Thu, 3 Dec 2015 07:52:39 -0500 Received: from mail-by2on0145.outbound.protection.outlook.com ([207.46.100.145]:11520 "EHLO na01-by2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1760066AbbLCMwd (ORCPT ); Thu, 3 Dec 2015 07:52:33 -0500 Authentication-Results: spf=permerror (sender IP is 192.88.168.50) smtp.mailfrom=freescale.com; freescale.mail.onmicrosoft.com; dkim=none (message not signed) header.d=none;freescale.mail.onmicrosoft.com; dmarc=none action=none header.from=freescale.com; From: Madalin Bucur To: CC: , , , , , , , , , , Madalin Bucur , Ioana Ciornei Subject: [net-next v5 6/8] dpaa_eth: add ethtool statistics Date: Thu, 3 Dec 2015 15:49:47 +0200 Message-ID: <1449150589-26253-7-git-send-email-madalin.bucur@freescale.com> X-Mailer: git-send-email 1.5.6.5 In-Reply-To: <1449150589-26253-1-git-send-email-madalin.bucur@freescale.com> References: <1449150589-26253-1-git-send-email-madalin.bucur@freescale.com> Reply-To: X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1;BN1BFFO11FD018;1:erZzbZXOG0muabQGCjzpPHD8XE8BIT8SxR2aAmXgitIHvA4ZerIt6+QjYE/25gjU5Y6RfGoGErnXswEHDzzdNHEX1MlT73HL8Qveq23DiKHrePq464gXzepEoLGRCBhY6O7R9mz8x/o3KM5B8274JcbFklQfKhVMBgkJHi1c5RuQ1DsiiFd/nXfmtoKfzdC4b6em8S8QBh4/U6N/L+1nB355vNAkvVbv0EJAiRTDo5bbLU1GIdNERKrXoySYLfcNdwJfHB+zWxFNysWQqNrk1mXh2U7VjMrSuhb+fTTKNqVPtkKNlJxFGkjLYmkZeCxPtCqKc+W66EzQrVuz1KP18SHkMVatJkVOejhYlYv6w1ouT5drjtHdXmqtzunSYbf2gBGkOiNT1aP4CoxINu3+W0i5du+ylQuw6VPrAuYQ0WY= X-Forefront-Antispam-Report: CIP:192.88.168.50;CTRY:US;IPV:NLI;EFV:NLI;SFV:NSPM;SFS:(10019020)(6009001)(2980300002)(448002)(199003)(189002)(575784001)(50466002)(19580405001)(48376002)(586003)(50986999)(86362001)(1220700001)(106466001)(49486002)(87936001)(81156007)(43066003)(110136002)(107886002)(189998001)(5001960100002)(76176999)(2950100001)(6806005)(53806999)(85326001)(19580395003)(1096002)(97736004)(50226001)(4001430100002)(33646002)(104016004)(5008740100001)(47776003)(36756003)(2351001)(229853001)(5003940100001)(77096005);DIR:OUT;SFP:1102;SCL:1;SRVR:BY2PR03MB506;H:tx30smr01.am.freescale.net;FPR:;SPF:PermError;PTR:InfoDomainNonexistent;A:1;MX:1;LANG:en; MIME-Version: 1.0 Content-Type: text/plain X-Microsoft-Exchange-Diagnostics: 1;BY2PR03MB506;2:8KelIsi6/bTAzKZBjLQIugjep8TDrqCPBw97vlNbmi9PsC26ANdEPOFYz0qbfOcqf+FLkr4/7qDV+FG24b8WtsyibK8kA3lzQgMr6zkQq3fuzTi3karbNtPgmG/i/jLxe18waxNVcYD1p5b2RTrh5Q==;3:RNsNqqpB62iJrx2WlfDePlPHrlvP3l7ip2K2EcWCi2pWtCsIExaIv7H3G3JlyrtMfEoD/TZqGfKyuAPnn1p0jw5H2ILmXcffxqxC0xMslMSETrKsm/sFGnE2qiJ5IEJA4q3Z1F7hY/xoMq5hFPdgmGTLPsTH6vV60f882IIxzG8UDCH4f66Z0KEs5Cu1GryzNPZ0xSpZK9JPtdXZKiByNREHhn+VjV1+EK8Wy4O3c28=;25:YPFtAiSalfG1XmwipKF3jOupGbG0yfa0OlaL9YJL4gORLRJ8d85GoaBjQvDuLbvtK0uYoANWsBmEZcm+V4l2AJMQ5Jhm/deS2qxB3mZ4ah14npTQ2aa0aguvXWL4IviOc+n2T1O1tQnnAG/9RU69Vt3eKQNuK4+fa+DGIRv+p0a8DpvD/NOlKp7Rne7RwEWJbkW4yMOXIIFZkbGJL6OaHl7X9ChTNkE0mLQYRZdWurzSqSoLxcVm8Jz+nfYl1B+GSRZs8BDcjdYCzHdz1ofR9Q== X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BY2PR03MB506; X-Microsoft-Exchange-Diagnostics: 1;BY2PR03MB506;20:ssZASAl5rrtpuGxXOSqH/EX7r1IgGPP+FFYtzWfQSMYUJfo+vyH3CkKwgFq33t1puYg6z+GUx05/W36opWugb7016GYYjen9Xe2+aEz/ve4IxB/3udUD7P2aUPEyuiAA5PamJwnaSITVA2XhOvdjj6HKSZlsCSvr2JGpRAMTu2vq6R0CrXKQyarjNT+mqrCZLM2K7A/T291ok4apDFA9gwyVNUr0nSQgsOymgn9JMePBkPh3jiBqIGYZ8svRGz8JC/L4bt/SfBXMA85Ewb6B/Gqdw2dG9ztBn3NXnP9QjsOIQDh/nAjwx2/YXYSJuHdYZftx6wljinEqoKtngv0uqqw5g5aCfH5YdtOpXmLWNs8=;4:YmYW9J3icELol+FIphQabFK0eYyC6LQ02VjIYteFd0MMAyU69xHmF5i9qrwQIet2nHw+XeTVpXKGFEMFFUYxUpGNr6V9149oxi3mofHTNk+HiqAyjr4mSzrLGSmolQn/9W33AsZwZ2Ph9vAOF+TJ3zdKAXnJz8i//D2FNNiqIlOuYpD+6ErQJjnxCM5g07b4FQ9Okj81bgU7ZtL+iYVKyZR+HLGHfDnk8zpmoTcBP6ZvnOZJWQ7CH7P3w1/H/7pg0Cl8lXrv4gMR2sxmv6qoX3cDltP02NC865oHma9uzgAmP4XVgb9/IR7vcAcsm9cXILueni3fZVLjBUzMAJqVztZsVhbiHx0yNUQWr3DUvrGk5vwiQuR0amsHCex/2JiDbV0AkKPw/0TIaNBB9aLfh1bC3k48EXl1cWrjy1H6ItUu/xhM1AOT0N8S4sx8/DTz X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(101931422205132); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(2401047)(8121501046)(520078)(5005006)(10201501046)(3002001);SRVR:BY2PR03MB506;BCL:0;PCL:0;RULEID:;SRVR:BY2PR03MB506; X-Forefront-PRVS: 077929D941 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BY2PR03MB506;23:ITJn/IDIjG+gzJDYmBuMOx4WxeF1Ir026HXvHT7Dcm?= =?us-ascii?Q?7e1VSNiuLTbkVkEfOuT1DZ0fnaE8vHVwCygRBUUU395g2++YSklIVJwyOCiG?= =?us-ascii?Q?/q2rbdqaVYiDwH6b+ZBFhShOrUNpgtPyyd+to5ZX4ZVIq4RvGHWAXhAsSUvf?= =?us-ascii?Q?2IM2G/iPXXYF80PelGSTvhK2/4K9KW9/SJW5CIviP4oYndahBzDMCyjh+vLZ?= =?us-ascii?Q?08CNEox+Q5OfaMRTanCRPU5d0mUYyOipsUeJFpWzja6sSj6ErAV5mVakaXML?= =?us-ascii?Q?KnGLxYn8woDzxMrK3MnwU66rJJGJA5i1tHxpAjTmqAhAyC2NseCA4HIA5jmS?= =?us-ascii?Q?PKhdTsD6dU2AN9lUXpud0wLNWIWriwzt7MrVmaG49ZWX2yyqcIP/h5P8OLhN?= =?us-ascii?Q?FXid+p5VUSbgeJRzo+g/pXr7T9xglf12aKaKMSYI2L+/BOH5prwPRkggLw0L?= =?us-ascii?Q?rqN5IeTnxx4vwa7BXdJon0Vt2bRF9efk/ACGJWxE9XbrsWb3ZzZwonwjowJj?= =?us-ascii?Q?hfsccVkrj/pJsQ2/NpQG7HGHzIkwDM8r6UNgtjU8nAMLW38TurNfIS8D4aRL?= =?us-ascii?Q?EkiePHRzVTKqZ8J85HCyp2KW4t4X8nZU0/iGdYGKiF/hBRjrS4aKLjMSupk3?= =?us-ascii?Q?r1hEB6rzfThxirKNZ0mZxca9QIk1cqiMlPHFjVI4xRvFINnHF0a2X6W9DO41?= =?us-ascii?Q?0VbALozJsMZ9GuduDC06oBGKzSnh4ykGwxyrhJC8BBo4sdR/mD1VU14bwLVW?= =?us-ascii?Q?GIxofHKO9JDu/7ISorPDo1cWDINWiy5QIWmRzw5UgZEs72LxifOcOS+kr2/v?= =?us-ascii?Q?YepAdHn5kDAtycpNKAx2IAKJqgm3sqhrKYzy0/aEemtYCJ3YgjLDFgSACI00?= =?us-ascii?Q?QgHR8VtPVlEAUZURMlPz4fmEritNFE7bSu1gFUxYGS2r0/AnOPqrGui5gbUj?= =?us-ascii?Q?64Bq4LG5uziDBkKVSMS8xF79UcdRcpdMl1ByNQhh9cqBtEq7Dq8sL2K1J3Sn?= =?us-ascii?Q?3f1cnXACumh+lURWDlvFA4K+YjspVoUr4+4AtP0s5/69s6Lfwpm0HkChZwsN?= =?us-ascii?Q?t7cDKuQtF7l9e3dfH7LjfQ/0R5bMobCCxesSRFvGhndypYrQ=3D=3D?= X-Microsoft-Exchange-Diagnostics: 1;BY2PR03MB506;5:o+ZGzj+xiOIoyf8Gn4r4mgW2x72OhJqUv39Uwqm+ipvrcVU6ho8GdhlJP5TtXxlq15gF+O6Z5+BbozdtZDZr32Rrf1hpoGO+5AGig9UAuYQ6QUjB6+FuLIAJ0pPIxchqN7HR2p22aO/G/MpbdzhYzw==;24:PQPjpfVyXOoW85DyYSO+y2XGo4IKcSRzCPhTq/6FbxkIhHtH1sABYN/IUV96iVw/yF75LVU/uCeC4fC7ULTxMAqUUJyfYXEOvDS5ft9YSrU= X-OriginatorOrg: freescale.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 03 Dec 2015 12:52:25.4684 (UTC) X-MS-Exchange-CrossTenant-Id: 710a03f5-10f6-4d38-9ff4-a80b81da590d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=710a03f5-10f6-4d38-9ff4-a80b81da590d;Ip=[192.88.168.50];Helo=[tx30smr01.am.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY2PR03MB506 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 14332 Lines: 423 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 | 12 ++ drivers/net/ethernet/freescale/dpaa/dpaa_eth.h | 34 ++++ .../net/ethernet/freescale/dpaa/dpaa_eth_common.c | 40 ++++- .../net/ethernet/freescale/dpaa/dpaa_eth_common.h | 2 + drivers/net/ethernet/freescale/dpaa/dpaa_eth_sg.c | 1 + drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c | 184 +++++++++++++++++++++ 6 files changed, 271 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index 6c16ddd..f71a0d2 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -93,6 +93,15 @@ static void dpa_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++; + dpa_fd_release(net_dev, fd); } @@ -158,6 +167,8 @@ static void dpa_tx_conf(struct net_device *net_dev, percpu_priv->stats.tx_errors++; } + percpu_priv->tx_confirm++; + skb = dpa_cleanup_tx_fd(priv, fd); dev_kfree_skb(skb); @@ -287,6 +298,7 @@ static void priv_ern(struct qman_portal *portal, percpu_priv->stats.tx_dropped++; percpu_priv->stats.tx_fifo_errors++; + count_ern(percpu_priv, msg); /* If we intended this buffer to go into the pool * when the FM was done, we need to put it in diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h index a990c7b..076d66a 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h @@ -183,6 +183,25 @@ struct dpa_bp { void (*free_buf_cb)(void *addr); }; +struct dpa_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 dpa_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 dpa_napi_portal { struct napi_struct napi; struct qman_portal *p; @@ -192,7 +211,13 @@ struct dpa_napi_portal { struct dpa_percpu_priv { struct net_device *net_dev; struct dpa_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 dpa_rx_errors rx_errors; + struct dpa_ern_cnt ern_cnt; }; struct dpa_priv { @@ -219,6 +244,14 @@ struct dpa_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; @@ -276,6 +309,7 @@ static inline int dpaa_eth_napi_schedule(struct dpa_percpu_priv *percpu_priv, np->p = portal; napi_schedule(&np->napi); + percpu_priv->in_interrupt++; return 1; } } diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c index 656c5a8..2a7cff2 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c @@ -767,10 +767,15 @@ static void dpaa_eth_cgscn(struct qman_portal *qm, struct qman_cgr *cgr, struct dpa_priv *priv = (struct dpa_priv *)container_of(cgr, struct dpa_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); + } } int dpaa_eth_cgr_init(struct dpa_priv *priv) @@ -1274,6 +1279,37 @@ void dpa_fd_release(const struct net_device *net_dev, const struct qm_fd *fd) cpu_relax(); } +void count_ern(struct dpa_percpu_priv *percpu_priv, + const struct 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. diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.h b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.h index 8564bfa..93b4717 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.h +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.h @@ -99,6 +99,8 @@ void dpaa_eth_init_ports(struct mac_device *mac_dev, struct device *dev); void dpa_release_sgt(struct qm_sg_entry *sgt); void dpa_fd_release(const struct net_device *net_dev, const struct qm_fd *fd); +void count_ern(struct dpa_percpu_priv *percpu_priv, + const struct qm_mr_entry *msg); int dpa_enable_tx_csum(struct dpa_priv *priv, struct sk_buff *skb, struct qm_fd *fd, diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sg.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sg.c index 5fbc167..436e277 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sg.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sg.c @@ -653,6 +653,7 @@ int dpa_tx(struct sk_buff *skb, struct net_device *net_dev) likely(skb_shinfo(skb)->nr_frags < DPA_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. diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c index ebf049f..274c484 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c @@ -37,6 +37,43 @@ #include "mac.h" #include "dpaa_eth_common.h" +static const char dpa_stats_percpu[][ETH_GSTRING_LEN] = { + "interrupts", + "rx packets", + "tx packets", + "tx confirm", + "tx S/G", + "tx error", + "rx error", + "bp count" +}; + +static char dpa_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 DPA_STATS_PERCPU_LEN ARRAY_SIZE(dpa_stats_percpu) +#define DPA_STATS_GLOBAL_LEN ARRAY_SIZE(dpa_stats_global) + static int dpa_get_settings(struct net_device *net_dev, struct ethtool_cmd *et_cmd) { @@ -217,6 +254,150 @@ static int dpa_set_pauseparam(struct net_device *net_dev, return err; } +static int dpa_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 * DPA_STATS_PERCPU_LEN + DPA_STATS_GLOBAL_LEN; + + switch (type) { + case ETH_SS_STATS: + return total_stats; + default: + return -EOPNOTSUPP; + } +} + +static void copy_stats(struct dpa_percpu_priv *percpu_priv, int num_cpus, + int crr_cpu, u64 bp_count, u64 *data) +{ + int num_values = num_cpus + 1; + int crr = 0; + + /* 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; + + data[crr * num_values + crr_cpu] = bp_count; + data[crr++ * num_values + num_cpus] += bp_count; +} + +static void dpa_get_ethtool_stats(struct net_device *net_dev, + struct ethtool_stats *stats, u64 *data) +{ + u64 bp_count, cg_time, cg_num, cg_status; + struct dpa_percpu_priv *percpu_priv; + struct qm_mcr_querycgr query_cgr; + struct dpa_rx_errors rx_errors; + struct dpa_ern_cnt ern_cnt; + struct dpa_priv *priv; + unsigned int num_cpus, offset; + struct dpa_bp *dpa_bp; + int total_stats, i; + + total_stats = dpa_get_sset_count(net_dev, ETH_SS_STATS); + priv = netdev_priv(net_dev); + dpa_bp = priv->dpa_bp; + num_cpus = num_online_cpus(); + bp_count = 0; + + memset(&rx_errors, 0, sizeof(struct dpa_rx_errors)); + memset(&ern_cnt, 0, sizeof(struct dpa_ern_cnt)); + memset(data, 0, total_stats * sizeof(u64)); + + for_each_online_cpu(i) { + percpu_priv = per_cpu_ptr(priv->percpu_priv, i); + + if (dpa_bp->percpu_count) + bp_count = *(per_cpu_ptr(dpa_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) * DPA_STATS_PERCPU_LEN; + memcpy(data + offset, &rx_errors, sizeof(struct dpa_rx_errors)); + + offset += sizeof(struct dpa_rx_errors) / sizeof(u64); + memcpy(data + offset, &ern_cnt, sizeof(struct dpa_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(&priv->cgr_data.cgr, &query_cgr) == 0) { + cg_num = priv->cgr_data.cgr_congested_count; + cg_status = query_cgr.cgr.cs; + + /* reset congestion stats (like QMan API does */ + priv->cgr_data.congested_jiffies = 0; + priv->cgr_data.cgr_congested_count = 0; + } + + offset += sizeof(struct dpa_ern_cnt) / sizeof(u64); + data[offset++] = cg_time; + data[offset++] = cg_num; + data[offset++] = cg_status; +} + +static void dpa_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 = DPA_STATS_GLOBAL_LEN * ETH_GSTRING_LEN; + + for (i = 0; i < DPA_STATS_PERCPU_LEN; i++) { + for (j = 0; j < num_cpus; j++) { + snprintf(string_cpu, ETH_GSTRING_LEN, "%s [CPU %d]", + dpa_stats_percpu[i], j); + memcpy(strings, string_cpu, ETH_GSTRING_LEN); + strings += ETH_GSTRING_LEN; + } + snprintf(string_cpu, ETH_GSTRING_LEN, "%s [TOTAL]", + dpa_stats_percpu[i]); + memcpy(strings, string_cpu, ETH_GSTRING_LEN); + strings += ETH_GSTRING_LEN; + } + memcpy(strings, dpa_stats_global, size); +} + const struct ethtool_ops dpa_ethtool_ops = { .get_settings = dpa_get_settings, .set_settings = dpa_set_settings, @@ -227,4 +408,7 @@ const struct ethtool_ops dpa_ethtool_ops = { .get_pauseparam = dpa_get_pauseparam, .set_pauseparam = dpa_set_pauseparam, .get_link = ethtool_op_get_link, + .get_sset_count = dpa_get_sset_count, + .get_ethtool_stats = dpa_get_ethtool_stats, + .get_strings = dpa_get_strings, }; -- 1.7.11.7 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/