From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 02997C2BBCA for ; Thu, 17 Dec 2020 07:54:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BBB97238A0 for ; Thu, 17 Dec 2020 07:54:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727738AbgLQHxu (ORCPT ); Thu, 17 Dec 2020 02:53:50 -0500 Received: from esa.microchip.iphmx.com ([68.232.154.123]:62476 "EHLO esa.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727151AbgLQHxs (ORCPT ); Thu, 17 Dec 2020 02:53:48 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1608191625; x=1639727625; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=aFbjaDH9EXbm/Bi3gK+vbc8GnyrplszqMPX9sG16bN4=; b=e1ZroX1rnt/yQWwGvNfvjkjYsDI8WzZvJI9J07rk2LsJVb+x+HNmUGoA L5yS8hrHqZ0QUvw23qCzPk19jWNyP2uyDsvWI6RJFGzcUK/7Kjs3DgIgS 3piK3NAEcsX39XSJxwsjWsqVZeQBuA3+5tA9h8gQzorWIg9XSzZXoF1jP MJkNkdNaGLrxmUM+hxkS2V32IvM9dzslQiUuYvvjt/8VebkqWwC6rhF98 zWS6YzbCbb4rIL1k+c3iKLWw4aX0UTBEmfL/9lZjUcm3YcSRP19lYpNWS DDgLJ5OFdexcPl75yk+EHJt1fdnjB38RW49Dz2BB34wmvqJiXfYJ0orKD w==; IronPort-SDR: pXJTc6yHSA/cdnMx5K/tT9gtj1DCsTPWyihyCfWWB12eP9DDsOo06vbSKUdZcwIkYgMSVHaP2l laeFTp6miANxR8cTlwm4ZfXt4q/n7CLQTNXj2nwYVUy/WbcBdHhmou2IwC9pIHk92rAKABRz4J 1rwa+GRR0XWjzSlZVOihbs+TGdxUDbP3lc5EaTEYNP5jb+vM6/Higx0o6n4DcKrrIyvyE4oqEJ y+Fpws3prLlOqlXGqRTa9kIq2YiW/XscCs0l4DozS3GCWUAXu9URye5+oBitJLvwgSG51qMy0d 74I= X-IronPort-AV: E=Sophos;i="5.78,426,1599548400"; d="scan'208";a="97422906" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa4.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 17 Dec 2020 00:52:13 -0700 Received: from chn-vm-ex03.mchp-main.com (10.10.85.151) by chn-vm-ex03.mchp-main.com (10.10.85.151) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1979.3; Thu, 17 Dec 2020 00:52:12 -0700 Received: from mchp-dev-shegelun.microchip.com (10.10.115.15) by chn-vm-ex03.mchp-main.com (10.10.85.151) with Microsoft SMTP Server id 15.1.1979.3 via Frontend Transport; Thu, 17 Dec 2020 00:52:09 -0700 From: Steen Hegelund To: "David S. Miller" , Jakub Kicinski CC: Steen Hegelund , Andrew Lunn , Russell King , Lars Povlsen , Bjarni Jonasson , Microchip Linux Driver Support , Alexandre Belloni , Madalin Bucur , Nicolas Ferre , Mark Einon , Masahiro Yamada , Arnd Bergmann , , , Subject: [RFC PATCH v2 7/8] net: sparx5: add ethtool configuration and statistics support Date: Thu, 17 Dec 2020 08:51:33 +0100 Message-ID: <20201217075134.919699-8-steen.hegelund@microchip.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201217075134.919699-1-steen.hegelund@microchip.com> References: <20201217075134.919699-1-steen.hegelund@microchip.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This adds statistic counters for the network interfaces provided by the driver. It also adds CPU port counters (which are not exposed by ethtool). This also adds support for configuring the network interface parameters via ethtool: speed, duplex, aneg etc. Signed-off-by: Steen Hegelund Signed-off-by: Bjarni Jonasson Signed-off-by: Lars Povlsen --- .../net/ethernet/microchip/sparx5/Makefile | 3 +- .../microchip/sparx5/sparx5_ethtool.c | 979 ++++++++++++++++++ .../ethernet/microchip/sparx5/sparx5_main.c | 5 + .../ethernet/microchip/sparx5/sparx5_main.h | 17 +- .../ethernet/microchip/sparx5/sparx5_netdev.c | 2 + 5 files changed, 1001 insertions(+), 5 deletions(-) create mode 100644 drivers/net/ethernet/microchip/sparx5/sparx5_ethtool.c diff --git a/drivers/net/ethernet/microchip/sparx5/Makefile b/drivers/net/ethernet/microchip/sparx5/Makefile index 17654ab90ce1..de3155cd582c 100644 --- a/drivers/net/ethernet/microchip/sparx5/Makefile +++ b/drivers/net/ethernet/microchip/sparx5/Makefile @@ -7,4 +7,5 @@ obj-$(CONFIG_SPARX5_SWITCH) += sparx5-switch.o sparx5-switch-objs := sparx5_main.o sparx5_switchdev.o \ sparx5_vlan.o sparx5_mactable.o sparx5_packet.o \ - sparx5_netdev.o sparx5_port.o sparx5_phylink.o sparx5_calendar.o + sparx5_ethtool.o sparx5_netdev.o sparx5_port.o \ + sparx5_phylink.o sparx5_calendar.o diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_ethtool.c b/drivers/net/ethernet/microchip/sparx5/sparx5_ethtool.c new file mode 100644 index 000000000000..f72f2126fea2 --- /dev/null +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_ethtool.c @@ -0,0 +1,979 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* Microchip Sparx5 Switch driver + * + * Copyright (c) 2020 Microchip Technology Inc. and its subsidiaries. + */ + +#include + +#include "sparx5_main.h" +#include "sparx5_port.h" + +/* Add a potentially wrapping 32 bit value to a 64 bit counter */ +static void sparx5_update_counter(u64 *cnt, u32 val) +{ + if (val < (*cnt & U32_MAX)) + *cnt += (u64)1 << 32; /* value has wrapped */ + + *cnt = (*cnt & ~(u64)U32_MAX) + val; +} + +/* Get a set of Queue System statistics */ +static void sparx5_xqs_prio_stats(struct sparx5 *sparx5, + u32 addr, + u64 *stats) +{ + int idx; + + for (idx = 0; idx < 2 * SPX5_PRIOS; ++idx, ++addr, ++stats) + sparx5_update_counter(stats, spx5_rd(sparx5, XQS_CNT(addr))); +} + +#define SPX5_STAT_GET(sname) portstats[spx5_stats_##sname] +#define SPX5_STAT_SUM(sname) (portstats[spx5_stats_##sname] + \ + portstats[spx5_stats_pmac_##sname]) +#define SPX5_STAT_XQS_PRIOS_COUNTER_SUM(sname) \ + (portstats[spx5_stats_green_p0_##sname] + \ + portstats[spx5_stats_green_p1_##sname] + \ + portstats[spx5_stats_green_p2_##sname] + \ + portstats[spx5_stats_green_p3_##sname] + \ + portstats[spx5_stats_green_p4_##sname] + \ + portstats[spx5_stats_green_p5_##sname] + \ + portstats[spx5_stats_green_p6_##sname] + \ + portstats[spx5_stats_green_p7_##sname] + \ + portstats[spx5_stats_yellow_p0_##sname] + \ + portstats[spx5_stats_yellow_p1_##sname] + \ + portstats[spx5_stats_yellow_p2_##sname] + \ + portstats[spx5_stats_yellow_p3_##sname] + \ + portstats[spx5_stats_yellow_p4_##sname] + \ + portstats[spx5_stats_yellow_p5_##sname] + \ + portstats[spx5_stats_yellow_p6_##sname] + \ + portstats[spx5_stats_yellow_p7_##sname]) + +enum sparx5_stats_entry { + spx5_stats_rx_in_bytes, + spx5_stats_rx_symbol_err, + spx5_stats_rx_pause, + spx5_stats_rx_unsup_opcode, + spx5_stats_rx_ok_bytes, + spx5_stats_rx_bad_bytes, + spx5_stats_rx_unicast, + spx5_stats_rx_multicast, + spx5_stats_rx_broadcast, + spx5_stats_rx_crc_err, + spx5_stats_rx_undersize, + spx5_stats_rx_fragments, + spx5_stats_rx_inrangelen_err, + spx5_stats_rx_outofrangelen_err, + spx5_stats_rx_oversize, + spx5_stats_rx_jabbers, + spx5_stats_rx_size64, + spx5_stats_rx_size65_127, + spx5_stats_rx_size128_255, + spx5_stats_rx_size256_511, + spx5_stats_rx_size512_1023, + spx5_stats_rx_size1024_1518, + spx5_stats_rx_size1519_max, + spx5_stats_pmac_rx_symbol_err, + spx5_stats_pmac_rx_pause, + spx5_stats_pmac_rx_unsup_opcode, + spx5_stats_pmac_rx_ok_bytes, + spx5_stats_pmac_rx_bad_bytes, + spx5_stats_pmac_rx_unicast, + spx5_stats_pmac_rx_multicast, + spx5_stats_pmac_rx_broadcast, + spx5_stats_pmac_rx_crc_err, + spx5_stats_pmac_rx_undersize, + spx5_stats_pmac_rx_fragments, + spx5_stats_pmac_rx_inrangelen_err, + spx5_stats_pmac_rx_outofrangelen_err, + spx5_stats_pmac_rx_oversize, + spx5_stats_pmac_rx_jabbers, + spx5_stats_pmac_rx_size64, + spx5_stats_pmac_rx_size65_127, + spx5_stats_pmac_rx_size128_255, + spx5_stats_pmac_rx_size256_511, + spx5_stats_pmac_rx_size512_1023, + spx5_stats_pmac_rx_size1024_1518, + spx5_stats_pmac_rx_size1519_max, + spx5_stats_green_p0_rx_fwd, + spx5_stats_green_p1_rx_fwd, + spx5_stats_green_p2_rx_fwd, + spx5_stats_green_p3_rx_fwd, + spx5_stats_green_p4_rx_fwd, + spx5_stats_green_p5_rx_fwd, + spx5_stats_green_p6_rx_fwd, + spx5_stats_green_p7_rx_fwd, + spx5_stats_yellow_p0_rx_fwd, + spx5_stats_yellow_p1_rx_fwd, + spx5_stats_yellow_p2_rx_fwd, + spx5_stats_yellow_p3_rx_fwd, + spx5_stats_yellow_p4_rx_fwd, + spx5_stats_yellow_p5_rx_fwd, + spx5_stats_yellow_p6_rx_fwd, + spx5_stats_yellow_p7_rx_fwd, + spx5_stats_green_p0_rx_port_drop, + spx5_stats_green_p1_rx_port_drop, + spx5_stats_green_p2_rx_port_drop, + spx5_stats_green_p3_rx_port_drop, + spx5_stats_green_p4_rx_port_drop, + spx5_stats_green_p5_rx_port_drop, + spx5_stats_green_p6_rx_port_drop, + spx5_stats_green_p7_rx_port_drop, + spx5_stats_yellow_p0_rx_port_drop, + spx5_stats_yellow_p1_rx_port_drop, + spx5_stats_yellow_p2_rx_port_drop, + spx5_stats_yellow_p3_rx_port_drop, + spx5_stats_yellow_p4_rx_port_drop, + spx5_stats_yellow_p5_rx_port_drop, + spx5_stats_yellow_p6_rx_port_drop, + spx5_stats_yellow_p7_rx_port_drop, + spx5_stats_rx_local_drop, + spx5_stats_rx_port_policer_drop, + spx5_stats_tx_out_bytes, + spx5_stats_tx_pause, + spx5_stats_tx_ok_bytes, + spx5_stats_tx_unicast, + spx5_stats_tx_multicast, + spx5_stats_tx_broadcast, + spx5_stats_tx_size64, + spx5_stats_tx_size65_127, + spx5_stats_tx_size128_255, + spx5_stats_tx_size256_511, + spx5_stats_tx_size512_1023, + spx5_stats_tx_size1024_1518, + spx5_stats_tx_size1519_max, + spx5_stats_tx_multi_coll, + spx5_stats_tx_late_coll, + spx5_stats_tx_xcoll, + spx5_stats_tx_defer, + spx5_stats_tx_xdefer, + spx5_stats_tx_backoff1, + spx5_stats_pmac_tx_pause, + spx5_stats_pmac_tx_ok_bytes, + spx5_stats_pmac_tx_unicast, + spx5_stats_pmac_tx_multicast, + spx5_stats_pmac_tx_broadcast, + spx5_stats_pmac_tx_size64, + spx5_stats_pmac_tx_size65_127, + spx5_stats_pmac_tx_size128_255, + spx5_stats_pmac_tx_size256_511, + spx5_stats_pmac_tx_size512_1023, + spx5_stats_pmac_tx_size1024_1518, + spx5_stats_pmac_tx_size1519_max, + spx5_stats_green_p0_tx_port, + spx5_stats_green_p1_tx_port, + spx5_stats_green_p2_tx_port, + spx5_stats_green_p3_tx_port, + spx5_stats_green_p4_tx_port, + spx5_stats_green_p5_tx_port, + spx5_stats_green_p6_tx_port, + spx5_stats_green_p7_tx_port, + spx5_stats_yellow_p0_tx_port, + spx5_stats_yellow_p1_tx_port, + spx5_stats_yellow_p2_tx_port, + spx5_stats_yellow_p3_tx_port, + spx5_stats_yellow_p4_tx_port, + spx5_stats_yellow_p5_tx_port, + spx5_stats_yellow_p6_tx_port, + spx5_stats_yellow_p7_tx_port, + spx5_stats_tx_local_drop, +}; + +static const char *const sparx5_stats_layout[] = { + "rx_in_bytes", + "rx_symbol_err", + "rx_pause", + "rx_unsup_opcode", + "rx_ok_bytes", + "rx_bad_bytes", + "rx_unicast", + "rx_multicast", + "rx_broadcast", + "rx_crc_err", + "rx_undersize", + "rx_fragments", + "rx_inrangelen_err", + "rx_outofrangelen_err", + "rx_oversize", + "rx_jabbers", + "rx_size64", + "rx_size65_127", + "rx_size128_255", + "rx_size256_511", + "rx_size512_1023", + "rx_size1024_1518", + "rx_size1519_max", + "pmac_rx_symbol_err", + "pmac_rx_pause", + "pmac_rx_unsup_opcode", + "pmac_rx_ok_bytes", + "pmac_rx_bad_bytes", + "pmac_rx_unicast", + "pmac_rx_multicast", + "pmac_rx_broadcast", + "pmac_rx_crc_err", + "pmac_rx_undersize", + "pmac_rx_fragments", + "pmac_rx_inrangelen_err", + "pmac_rx_outofrangelen_err", + "pmac_rx_oversize", + "pmac_rx_jabbers", + "pmac_rx_size64", + "pmac_rx_size65_127", + "pmac_rx_size128_255", + "pmac_rx_size256_511", + "pmac_rx_size512_1023", + "pmac_rx_size1024_1518", + "pmac_rx_size1519_max", + "rx_fwd_green_p0_q", + "rx_fwd_green_p1_q", + "rx_fwd_green_p2_q", + "rx_fwd_green_p3_q", + "rx_fwd_green_p4_q", + "rx_fwd_green_p5_q", + "rx_fwd_green_p6_q", + "rx_fwd_green_p7_q", + "rx_fwd_yellow_p0_q", + "rx_fwd_yellow_p1_q", + "rx_fwd_yellow_p2_q", + "rx_fwd_yellow_p3_q", + "rx_fwd_yellow_p4_q", + "rx_fwd_yellow_p5_q", + "rx_fwd_yellow_p6_q", + "rx_fwd_yellow_p7_q", + "rx_port_drop_green_p0_q", + "rx_port_drop_green_p1_q", + "rx_port_drop_green_p2_q", + "rx_port_drop_green_p3_q", + "rx_port_drop_green_p4_q", + "rx_port_drop_green_p5_q", + "rx_port_drop_green_p6_q", + "rx_port_drop_green_p7_q", + "rx_port_drop_yellow_p0_q", + "rx_port_drop_yellow_p1_q", + "rx_port_drop_yellow_p2_q", + "rx_port_drop_yellow_p3_q", + "rx_port_drop_yellow_p4_q", + "rx_port_drop_yellow_p5_q", + "rx_port_drop_yellow_p6_q", + "rx_port_drop_yellow_p7_q", + "rx_local_drop", + "rx_port_policer_drop", + "tx_out_bytes", + "tx_pause", + "tx_ok_bytes", + "tx_unicast", + "tx_multicast", + "tx_broadcast", + "tx_size64", + "tx_size65_127", + "tx_size128_255", + "tx_size256_511", + "tx_size512_1023", + "tx_size1024_1518", + "tx_size1519_max", + "tx_multi_coll", + "tx_late_coll", + "tx_xcoll", + "tx_defer", + "tx_xdefer", + "tx_backoff1", + "pmac_tx_pause", + "pmac_tx_ok_bytes", + "pmac_tx_unicast", + "pmac_tx_multicast", + "pmac_tx_broadcast", + "pmac_tx_size64", + "pmac_tx_size65_127", + "pmac_tx_size128_255", + "pmac_tx_size256_511", + "pmac_tx_size512_1023", + "pmac_tx_size1024_1518", + "pmac_tx_size1519_max", + "tx_port_green_p0_q", + "tx_port_green_p1_q", + "tx_port_green_p2_q", + "tx_port_green_p3_q", + "tx_port_green_p4_q", + "tx_port_green_p5_q", + "tx_port_green_p6_q", + "tx_port_green_p7_q", + "tx_port_yellow_p0_q", + "tx_port_yellow_p1_q", + "tx_port_yellow_p2_q", + "tx_port_yellow_p3_q", + "tx_port_yellow_p4_q", + "tx_port_yellow_p5_q", + "tx_port_yellow_p6_q", + "tx_port_yellow_p7_q", + "tx_local_drop", +}; + +/* Device Statistics */ +static void sparx5_get_device_stats(struct sparx5 *sparx5, int portno) +{ + u64 *portstats = &sparx5->stats[portno * sparx5->num_stats]; + u32 dev = sparx5_to_high_dev(portno); + u32 tinst = sparx5_port_dev_index(portno); + void __iomem *inst = spx5_inst_get(sparx5, dev, tinst); + + sparx5_update_counter(&portstats[spx5_stats_rx_in_bytes], + spx5_inst_rd(inst, + DEV5G_RX_IN_BYTES_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_symbol_err], + spx5_inst_rd(inst, + DEV5G_RX_SYMBOL_ERR_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_pause], + spx5_inst_rd(inst, + DEV5G_RX_PAUSE_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_unsup_opcode], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_UNSUP_OPCODE_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_ok_bytes], + spx5_inst_rd(inst, + DEV5G_RX_OK_BYTES_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_bad_bytes], + spx5_inst_rd(inst, + DEV5G_RX_BAD_BYTES_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_unicast], + spx5_inst_rd(inst, + DEV5G_RX_UC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_multicast], + spx5_inst_rd(inst, + DEV5G_RX_MC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_broadcast], + spx5_inst_rd(inst, + DEV5G_RX_BC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_crc_err], + spx5_inst_rd(inst, + DEV5G_RX_CRC_ERR_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_undersize], + spx5_inst_rd(inst, + DEV5G_RX_UNDERSIZE_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_fragments], + spx5_inst_rd(inst, + DEV5G_RX_FRAGMENTS_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_inrangelen_err], + spx5_inst_rd(inst, + DEV5G_RX_IN_RANGE_LEN_ERR_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_outofrangelen_err], + spx5_inst_rd(inst, + DEV5G_RX_OUT_OF_RANGE_LEN_ERR_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_oversize], + spx5_inst_rd(inst, + DEV5G_RX_OVERSIZE_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_jabbers], + spx5_inst_rd(inst, + DEV5G_RX_JABBERS_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_size64], + spx5_inst_rd(inst, + DEV5G_RX_SIZE64_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_size65_127], + spx5_inst_rd(inst, + DEV5G_RX_SIZE65TO127_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_size128_255], + spx5_inst_rd(inst, + DEV5G_RX_SIZE128TO255_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_size256_511], + spx5_inst_rd(inst, + DEV5G_RX_SIZE256TO511_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_size512_1023], + spx5_inst_rd(inst, + DEV5G_RX_SIZE512TO1023_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_size1024_1518], + spx5_inst_rd(inst, + DEV5G_RX_SIZE1024TO1518_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_size1519_max], + spx5_inst_rd(inst, + DEV5G_RX_SIZE1519TOMAX_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_symbol_err], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_SYMBOL_ERR_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_pause], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_PAUSE_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_unsup_opcode], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_UNSUP_OPCODE_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_ok_bytes], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_OK_BYTES_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_bad_bytes], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_BAD_BYTES_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_unicast], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_UC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_multicast], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_MC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_broadcast], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_BC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_crc_err], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_CRC_ERR_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_undersize], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_UNDERSIZE_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_fragments], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_FRAGMENTS_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_inrangelen_err], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_IN_RANGE_LEN_ERR_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_outofrangelen_err], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_OUT_OF_RANGE_LEN_ERR_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_oversize], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_OVERSIZE_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_jabbers], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_JABBERS_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size64], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_SIZE64_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size65_127], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_SIZE65TO127_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size128_255], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_SIZE128TO255_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size256_511], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_SIZE256TO511_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size512_1023], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_SIZE512TO1023_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size1024_1518], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_SIZE1024TO1518_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size1519_max], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_SIZE1519TOMAX_CNT(tinst))); + sparx5_xqs_prio_stats(sparx5, + 0, + &portstats[spx5_stats_green_p0_rx_fwd]); + sparx5_xqs_prio_stats(sparx5, + 16, + &portstats[spx5_stats_green_p0_rx_port_drop]); + sparx5_update_counter(&portstats[spx5_stats_rx_local_drop], + spx5_rd(sparx5, XQS_CNT(32))); + sparx5_update_counter(&portstats[spx5_stats_rx_port_policer_drop], + spx5_rd(sparx5, + ANA_AC_PORT_STAT_LSB_CNT(portno, 1))); + sparx5_update_counter(&portstats[spx5_stats_tx_out_bytes], + spx5_inst_rd(inst, + DEV5G_TX_OUT_BYTES_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_pause], + spx5_inst_rd(inst, + DEV5G_TX_PAUSE_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_ok_bytes], + spx5_inst_rd(inst, + DEV5G_TX_OK_BYTES_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_unicast], + spx5_inst_rd(inst, + DEV5G_TX_UC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_multicast], + spx5_inst_rd(inst, + DEV5G_TX_MC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_broadcast], + spx5_inst_rd(inst, + DEV5G_TX_BC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_size64], + spx5_inst_rd(inst, + DEV5G_TX_SIZE64_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_size65_127], + spx5_inst_rd(inst, + DEV5G_TX_SIZE65TO127_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_size128_255], + spx5_inst_rd(inst, + DEV5G_TX_SIZE128TO255_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_size256_511], + spx5_inst_rd(inst, + DEV5G_TX_SIZE256TO511_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_size512_1023], + spx5_inst_rd(inst, + DEV5G_TX_SIZE512TO1023_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_size1024_1518], + spx5_inst_rd(inst, + DEV5G_TX_SIZE1024TO1518_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_size1519_max], + spx5_inst_rd(inst, + DEV5G_TX_SIZE1519TOMAX_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_pause], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_PAUSE_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_ok_bytes], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_OK_BYTES_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_unicast], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_UC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_multicast], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_MC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_broadcast], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_BC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size64], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_SIZE64_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size65_127], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_SIZE65TO127_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size128_255], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_SIZE128TO255_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size256_511], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_SIZE256TO511_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size512_1023], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_SIZE512TO1023_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size1024_1518], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_SIZE1024TO1518_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size1519_max], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_SIZE1519TOMAX_CNT(tinst))); + sparx5_xqs_prio_stats(sparx5, + 256, + &portstats[spx5_stats_green_p0_tx_port]); + sparx5_update_counter(&portstats[spx5_stats_tx_local_drop], + spx5_rd(sparx5, XQS_CNT(272))); +} + +/* ASM Statistics */ +static void sparx5_get_asm_stats(struct sparx5 *sparx5, int portno) +{ + u64 *portstats = &sparx5->stats[portno * sparx5->num_stats]; + u32 dev = TARGET_ASM; + void __iomem *inst = spx5_inst_get(sparx5, dev, 0); + + sparx5_update_counter(&portstats[spx5_stats_rx_in_bytes], + spx5_inst_rd(inst, + ASM_RX_IN_BYTES_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_symbol_err], + spx5_inst_rd(inst, + ASM_RX_SYMBOL_ERR_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_pause], + spx5_inst_rd(inst, + ASM_RX_PAUSE_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_unsup_opcode], + spx5_inst_rd(inst, + ASM_PMAC_RX_UNSUP_OPCODE_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_ok_bytes], + spx5_inst_rd(inst, + ASM_RX_OK_BYTES_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_bad_bytes], + spx5_inst_rd(inst, + ASM_RX_BAD_BYTES_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_unicast], + spx5_inst_rd(inst, + ASM_RX_UC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_multicast], + spx5_inst_rd(inst, + ASM_RX_MC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_broadcast], + spx5_inst_rd(inst, + ASM_RX_BC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_crc_err], + spx5_inst_rd(inst, + ASM_RX_CRC_ERR_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_undersize], + spx5_inst_rd(inst, + ASM_RX_UNDERSIZE_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_fragments], + spx5_inst_rd(inst, + ASM_RX_FRAGMENTS_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_inrangelen_err], + spx5_inst_rd(inst, + ASM_RX_IN_RANGE_LEN_ERR_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_outofrangelen_err], + spx5_inst_rd(inst, + ASM_RX_OUT_OF_RANGE_LEN_ERR_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_oversize], + spx5_inst_rd(inst, + ASM_RX_OVERSIZE_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_jabbers], + spx5_inst_rd(inst, + ASM_RX_JABBERS_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_size64], + spx5_inst_rd(inst, + ASM_RX_SIZE64_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_size65_127], + spx5_inst_rd(inst, + ASM_RX_SIZE65TO127_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_size128_255], + spx5_inst_rd(inst, + ASM_RX_SIZE128TO255_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_size256_511], + spx5_inst_rd(inst, + ASM_RX_SIZE256TO511_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_size512_1023], + spx5_inst_rd(inst, + ASM_RX_SIZE512TO1023_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_size1024_1518], + spx5_inst_rd(inst, + ASM_RX_SIZE1024TO1518_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_size1519_max], + spx5_inst_rd(inst, + ASM_RX_SIZE1519TOMAX_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_symbol_err], + spx5_inst_rd(inst, + ASM_PMAC_RX_SYMBOL_ERR_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_pause], + spx5_inst_rd(inst, + ASM_PMAC_RX_PAUSE_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_unsup_opcode], + spx5_inst_rd(inst, + ASM_PMAC_RX_UNSUP_OPCODE_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_ok_bytes], + spx5_inst_rd(inst, + ASM_PMAC_RX_OK_BYTES_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_bad_bytes], + spx5_inst_rd(inst, + ASM_PMAC_RX_BAD_BYTES_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_unicast], + spx5_inst_rd(inst, + ASM_PMAC_RX_UC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_multicast], + spx5_inst_rd(inst, + ASM_PMAC_RX_MC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_broadcast], + spx5_inst_rd(inst, + ASM_PMAC_RX_BC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_crc_err], + spx5_inst_rd(inst, + ASM_PMAC_RX_CRC_ERR_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_undersize], + spx5_inst_rd(inst, + ASM_PMAC_RX_UNDERSIZE_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_fragments], + spx5_inst_rd(inst, + ASM_PMAC_RX_FRAGMENTS_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_inrangelen_err], + spx5_inst_rd(inst, + ASM_PMAC_RX_IN_RANGE_LEN_ERR_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_outofrangelen_err], + spx5_inst_rd(inst, + ASM_PMAC_RX_OUT_OF_RANGE_LEN_ERR_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_oversize], + spx5_inst_rd(inst, + ASM_PMAC_RX_OVERSIZE_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_jabbers], + spx5_inst_rd(inst, + ASM_PMAC_RX_JABBERS_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size64], + spx5_inst_rd(inst, + ASM_PMAC_RX_SIZE64_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size65_127], + spx5_inst_rd(inst, + ASM_PMAC_RX_SIZE65TO127_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size128_255], + spx5_inst_rd(inst, + ASM_PMAC_RX_SIZE128TO255_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size256_511], + spx5_inst_rd(inst, + ASM_PMAC_RX_SIZE256TO511_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size512_1023], + spx5_inst_rd(inst, + ASM_PMAC_RX_SIZE512TO1023_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size1024_1518], + spx5_inst_rd(inst, + ASM_PMAC_RX_SIZE1024TO1518_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size1519_max], + spx5_inst_rd(inst, + ASM_PMAC_RX_SIZE1519TOMAX_CNT(portno))); + sparx5_xqs_prio_stats(sparx5, + 0, + &portstats[spx5_stats_green_p0_rx_fwd]); + sparx5_xqs_prio_stats(sparx5, + 16, + &portstats[spx5_stats_green_p0_rx_port_drop]); + sparx5_update_counter(&portstats[spx5_stats_rx_local_drop], + spx5_rd(sparx5, XQS_CNT(32))); + sparx5_update_counter(&portstats[spx5_stats_rx_port_policer_drop], + spx5_rd(sparx5, + ANA_AC_PORT_STAT_LSB_CNT(portno, 1))); + sparx5_update_counter(&portstats[spx5_stats_tx_out_bytes], + spx5_inst_rd(inst, + ASM_TX_OUT_BYTES_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_pause], + spx5_inst_rd(inst, + ASM_TX_PAUSE_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_ok_bytes], + spx5_inst_rd(inst, + ASM_TX_OK_BYTES_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_unicast], + spx5_inst_rd(inst, + ASM_TX_UC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_multicast], + spx5_inst_rd(inst, + ASM_TX_MC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_broadcast], + spx5_inst_rd(inst, + ASM_TX_BC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_size64], + spx5_inst_rd(inst, + ASM_TX_SIZE64_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_size65_127], + spx5_inst_rd(inst, + ASM_TX_SIZE65TO127_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_size128_255], + spx5_inst_rd(inst, + ASM_TX_SIZE128TO255_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_size256_511], + spx5_inst_rd(inst, + ASM_TX_SIZE256TO511_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_size512_1023], + spx5_inst_rd(inst, + ASM_TX_SIZE512TO1023_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_size1024_1518], + spx5_inst_rd(inst, + ASM_TX_SIZE1024TO1518_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_size1519_max], + spx5_inst_rd(inst, + ASM_TX_SIZE1519TOMAX_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_multi_coll], + spx5_inst_rd(inst, + ASM_TX_MULTI_COLL_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_late_coll], + spx5_inst_rd(inst, + ASM_TX_LATE_COLL_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_xcoll], + spx5_inst_rd(inst, + ASM_TX_XCOLL_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_defer], + spx5_inst_rd(inst, + ASM_TX_DEFER_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_xdefer], + spx5_inst_rd(inst, + ASM_TX_XDEFER_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_backoff1], + spx5_inst_rd(inst, + ASM_TX_BACKOFF1_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_pause], + spx5_inst_rd(inst, + ASM_PMAC_TX_PAUSE_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_ok_bytes], + spx5_inst_rd(inst, + ASM_PMAC_TX_OK_BYTES_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_unicast], + spx5_inst_rd(inst, + ASM_PMAC_TX_UC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_multicast], + spx5_inst_rd(inst, + ASM_PMAC_TX_MC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_broadcast], + spx5_inst_rd(inst, + ASM_PMAC_TX_BC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size64], + spx5_inst_rd(inst, + ASM_PMAC_TX_SIZE64_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size65_127], + spx5_inst_rd(inst, + ASM_PMAC_TX_SIZE65TO127_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size128_255], + spx5_inst_rd(inst, + ASM_PMAC_TX_SIZE128TO255_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size256_511], + spx5_inst_rd(inst, + ASM_PMAC_TX_SIZE256TO511_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size512_1023], + spx5_inst_rd(inst, + ASM_PMAC_TX_SIZE512TO1023_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size1024_1518], + spx5_inst_rd(inst, + ASM_PMAC_TX_SIZE1024TO1518_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size1519_max], + spx5_inst_rd(inst, + ASM_PMAC_TX_SIZE1519TOMAX_CNT(portno))); + sparx5_xqs_prio_stats(sparx5, + 256, + &portstats[spx5_stats_green_p0_tx_port]); + sparx5_update_counter(&portstats[spx5_stats_tx_local_drop], + spx5_rd(sparx5, XQS_CNT(272))); +} + +static void sparx5_update_port_stats(struct sparx5 *sparx5, int portno) +{ + bool high_speed_dev = sparx5_is_high_speed_device(&sparx5->ports[portno]->conf); + + /* Set XQS port number */ + spx5_wr(XQS_STAT_CFG_STAT_VIEW_SET(portno), sparx5, XQS_STAT_CFG); + if (high_speed_dev) + sparx5_get_device_stats(sparx5, portno); + else + sparx5_get_asm_stats(sparx5, portno); +} + +static void sparx5_update_stats(struct sparx5 *sparx5) +{ + int idx; + + mutex_lock(&sparx5->stats_lock); + for (idx = 0; idx < SPX5_PORTS; idx++) + if (sparx5->ports[idx]) + sparx5_update_port_stats(sparx5, idx); + mutex_unlock(&sparx5->stats_lock); +} + +static void sparx5_check_stats_work(struct work_struct *work) +{ + struct delayed_work *dwork = to_delayed_work(work); + struct sparx5 *sparx5 = container_of(dwork, struct sparx5, + stats_work); + + sparx5_update_stats(sparx5); + + queue_delayed_work(sparx5->stats_queue, &sparx5->stats_work, + SPX5_STATS_CHECK_DELAY); +} + +static int sparx5_get_sset_count(struct net_device *ndev, int sset) +{ + struct sparx5_port *port = netdev_priv(ndev); + struct sparx5 *sparx5 = port->sparx5; + + if (sset != ETH_SS_STATS) + return -EOPNOTSUPP; + return sparx5->num_stats; +} + +static void sparx5_get_sset_strings(struct net_device *ndev, u32 sset, u8 *data) +{ + struct sparx5_port *port = netdev_priv(ndev); + struct sparx5 *sparx5 = port->sparx5; + int idx; + + if (sset != ETH_SS_STATS) + return; + + for (idx = 0; idx < sparx5->num_stats; idx++) + strncpy(data + idx * ETH_GSTRING_LEN, + sparx5->stats_layout[idx], ETH_GSTRING_LEN); +} + +static void sparx5_get_stats(struct net_device *ndev, + struct ethtool_stats *stats, u64 *data) +{ + struct sparx5_port *port = netdev_priv(ndev); + struct sparx5 *sparx5 = port->sparx5; + u64 *portstats = &sparx5->stats[port->portno * sparx5->num_stats]; + int idx; + + /* check and update now (all ports) */ + sparx5_update_stats(sparx5); + + /* Copy port counters to the ethtool buffer */ + for (idx = 0; idx < sparx5->num_stats; idx++) + *data++ = portstats[idx]; +} + +void sparx5_get_stats64(struct net_device *ndev, + struct rtnl_link_stats64 *stats) +{ + struct sparx5_port *port = netdev_priv(ndev); + struct sparx5 *sparx5 = port->sparx5; + u64 *portstats; + + if (!sparx5->stats) + return; /* Not initialized yet */ + + portstats = &sparx5->stats[port->portno * sparx5->num_stats]; + + mutex_lock(&sparx5->stats_lock); + + stats->rx_errors = SPX5_STAT_SUM(rx_crc_err) + + SPX5_STAT_SUM(rx_undersize) + SPX5_STAT_SUM(rx_oversize) + + SPX5_STAT_SUM(rx_outofrangelen_err) + + SPX5_STAT_SUM(rx_symbol_err) + SPX5_STAT_SUM(rx_jabbers) + + SPX5_STAT_SUM(rx_fragments); + + stats->rx_bytes = SPX5_STAT_SUM(rx_ok_bytes) + + SPX5_STAT_SUM(rx_bad_bytes); + + stats->rx_packets = SPX5_STAT_SUM(rx_unicast) + + SPX5_STAT_SUM(rx_multicast) + SPX5_STAT_SUM(rx_broadcast) + + stats->rx_errors; + + stats->multicast = SPX5_STAT_SUM(rx_unicast); + + stats->rx_dropped = SPX5_STAT_GET(rx_port_policer_drop) + + SPX5_STAT_XQS_PRIOS_COUNTER_SUM(rx_port_drop); + + /* Get Tx stats */ + stats->tx_bytes = SPX5_STAT_SUM(tx_ok_bytes); + + stats->tx_packets = SPX5_STAT_SUM(tx_unicast) + + SPX5_STAT_SUM(tx_multicast) + SPX5_STAT_SUM(tx_broadcast); + + stats->tx_dropped = SPX5_STAT_GET(tx_local_drop); + + stats->collisions = SPX5_STAT_GET(tx_multi_coll) + + SPX5_STAT_GET(tx_late_coll) + + SPX5_STAT_GET(tx_xcoll) + + SPX5_STAT_GET(tx_backoff1); + + mutex_unlock(&sparx5->stats_lock); +} + +static int sparx5_get_link_settings(struct net_device *ndev, + struct ethtool_link_ksettings *cmd) +{ + struct sparx5_port *port = netdev_priv(ndev); + + return phylink_ethtool_ksettings_get(port->phylink, cmd); +} + +static int sparx5_set_link_settings(struct net_device *ndev, + const struct ethtool_link_ksettings *cmd) +{ + struct sparx5_port *port = netdev_priv(ndev); + + return phylink_ethtool_ksettings_set(port->phylink, cmd); +} + +const struct ethtool_ops sparx5_ethtool_ops = { + .get_sset_count = sparx5_get_sset_count, + .get_strings = sparx5_get_sset_strings, + .get_ethtool_stats = sparx5_get_stats, + .get_link_ksettings = sparx5_get_link_settings, + .set_link_ksettings = sparx5_set_link_settings, + .get_link = ethtool_op_get_link, +}; + +int sparx_stats_init(struct sparx5 *sparx5) +{ + char queue_name[32]; + int portno; + + sparx5->stats_layout = sparx5_stats_layout; + sparx5->num_stats = ARRAY_SIZE(sparx5_stats_layout); + sparx5->stats = devm_kcalloc(sparx5->dev, + SPX5_PORTS_ALL * sparx5->num_stats, + sizeof(u64), GFP_KERNEL); + if (!sparx5->stats) + return -ENOMEM; + + for (portno = 0; portno < SPX5_PORTS; portno++) + if (sparx5->ports[portno]) { + /* Clear Queue System counters */ + spx5_wr(XQS_STAT_CFG_STAT_VIEW_SET(portno) | + XQS_STAT_CFG_STAT_CLEAR_SHOT_SET(3), sparx5, XQS_STAT_CFG); + } + + mutex_init(&sparx5->stats_lock); + snprintf(queue_name, sizeof(queue_name), "%s-stats", + dev_name(sparx5->dev)); + sparx5->stats_queue = create_singlethread_workqueue(queue_name); + INIT_DELAYED_WORK(&sparx5->stats_work, sparx5_check_stats_work); + queue_delayed_work(sparx5->stats_queue, &sparx5->stats_work, + SPX5_STATS_CHECK_DELAY); + + return 0; +} diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c index 2b42c72dac72..e1e2384512bc 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c @@ -751,6 +751,11 @@ static int mchp_sparx5_probe(struct platform_device *pdev) if (err) goto cleanup_ports; + /* Init stats */ + err = sparx_stats_init(sparx5); + if (err) + goto cleanup_ports; + /* Init mact_sw struct */ mutex_init(&sparx5->mact_lock); INIT_LIST_HEAD(&sparx5->mact_entries); diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h index e59e1962f7d4..1d1b3b516244 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h @@ -130,6 +130,14 @@ struct sparx5 { /* port structures are in net device */ struct sparx5_port *ports[SPX5_PORTS]; enum sparx5_core_clockfreq coreclock; + /* Statistics */ + u32 num_stats; + const char * const *stats_layout; + u64 *stats; + /* Workqueue for reading stats */ + struct mutex stats_lock; + struct delayed_work stats_work; + struct workqueue_struct *stats_queue; /* Notifiers */ struct notifier_block netdevice_nb; struct notifier_block switchdev_nb; @@ -153,10 +161,6 @@ struct sparx5 { bool sd_sgpio_remapping; }; -/* sparx5_main.c */ -void sparx5_update_cpuport_stats(struct sparx5 *sparx5, int portno); -bool sparx5_is_cpuport_stat(struct sparx5 *sparx5, int idx); - /* sparx5_switchdev.c */ int sparx5_register_notifier_blocks(struct sparx5 *sparx5); void sparx5_unregister_notifier_blocks(struct sparx5 *sparx5); @@ -199,6 +203,10 @@ void sparx5_vlan_port_apply(struct sparx5 *sparx5, struct sparx5_port *port); int sparx5_config_auto_calendar(struct sparx5 *sparx5); int sparx5_config_dsm_calendar(struct sparx5 *sparx5); +/* sparx5_ethtool.c */ +void sparx5_get_stats64(struct net_device *ndev, struct rtnl_link_stats64 *stats); +int sparx_stats_init(struct sparx5 *sparx5); + /* sparx5_netdev.c */ bool sparx5_netdevice_check(const struct net_device *dev); struct net_device *sparx5_create_netdev(struct sparx5 *sparx5, u32 portno); @@ -226,6 +234,7 @@ static inline u32 sparx5_clk_period(enum sparx5_core_clockfreq cclock) } extern const struct phylink_mac_ops sparx5_phylink_mac_ops; +extern const struct ethtool_ops sparx5_ethtool_ops; /* Calculate raw offset */ static inline __pure int spx5_offset(int id, int tinst, int tcnt, diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c b/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c index a0992443ab9f..3b7cfbb14f2e 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c @@ -176,6 +176,7 @@ static const struct net_device_ops sparx5_port_netdev_ops = { .ndo_get_phys_port_name = sparx5_port_get_phys_port_name, .ndo_set_mac_address = sparx5_set_mac_address, .ndo_validate_addr = eth_validate_addr, + .ndo_get_stats64 = sparx5_get_stats64, .ndo_get_port_parent_id = sparx5_get_port_parent_id, }; @@ -203,6 +204,7 @@ struct net_device *sparx5_create_netdev(struct sparx5 *sparx5, u32 portno) ether_setup(ndev); ndev->netdev_ops = &sparx5_port_netdev_ops; + ndev->ethtool_ops = &sparx5_ethtool_ops; ndev->features |= NETIF_F_LLTX; /* software tx */ ether_addr_copy(ndev->dev_addr, sparx5->base_mac); -- 2.29.2 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A49C6C2BB48 for ; Thu, 17 Dec 2020 07:54:18 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2A7A923434 for ; Thu, 17 Dec 2020 07:54:18 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2A7A923434 Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=microchip.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-ID:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=HEGf4Pp8Ucg2ZaXmzHtr49AHbOnvCtPbCedro4cbdZ4=; b=RZS8DFvOqhKCZePnqh/vFg30X JdkIavHxSgTlz8x9FPu14RGEykhliPzpr/RYA/1pVduvFPTAtvOZupntC+AqmwYACuwjYKvIaVQi0 EYJ+8YiyXSFf1hWeOHoToWZzOL07jGwdkdmh02FJHl7B+A29/V5CRSdSPw6aggM1yzPqmRya5KmdN jBsFdpVsFX/fWn+feTsmoSV38wET/OftuRzUKPw8IdU3FOFAGxr3+A0rPZwO9p/UKTNh9iDg+fQke v2rG5I9sFMHbVADj6WjLWhh00yKT4oLc4pB+7I5pL7pIZqF0atPFQUU5e6OpCUtKA1we4W2dLL+eT wEwEhJN/g==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kpo5k-0006qA-6N; Thu, 17 Dec 2020 07:52:52 +0000 Received: from esa.microchip.iphmx.com ([68.232.154.123]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kpo58-0006dW-5W for linux-arm-kernel@lists.infradead.org; Thu, 17 Dec 2020 07:52:20 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1608191534; x=1639727534; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=aFbjaDH9EXbm/Bi3gK+vbc8GnyrplszqMPX9sG16bN4=; b=h1HmK2OII5Zac/60UlO9Z33cf3e0raqFUU3kv66Croi1EFLYczv6dAOF BV9O3tS9VBdml9Qw5t6U5ychm0B8/LNCW7GXORO8MxeNnA9/9dI/89eUj mkh78cfv56D3YkjFSi44n7ouLPydZuOlJuCexhEPfPD6zxaCEriHemntp E9ooB16N3M3N1xiu/sqG0PfVIfsoWpaQnXWMD9Si45xRDf5whWnzM9oDn BqNGyvWJjBh5bWtL2JS4HtZUkbGgp7PUAs7c9kPF3ZZv8hF1xe1p37I8/ JfYWJlFiOBxmjxef2M3VoYXfXIEhwWjEwBnOdETkAQapaRC88l8F9dHwN Q==; IronPort-SDR: pXJTc6yHSA/cdnMx5K/tT9gtj1DCsTPWyihyCfWWB12eP9DDsOo06vbSKUdZcwIkYgMSVHaP2l laeFTp6miANxR8cTlwm4ZfXt4q/n7CLQTNXj2nwYVUy/WbcBdHhmou2IwC9pIHk92rAKABRz4J 1rwa+GRR0XWjzSlZVOihbs+TGdxUDbP3lc5EaTEYNP5jb+vM6/Higx0o6n4DcKrrIyvyE4oqEJ y+Fpws3prLlOqlXGqRTa9kIq2YiW/XscCs0l4DozS3GCWUAXu9URye5+oBitJLvwgSG51qMy0d 74I= X-IronPort-AV: E=Sophos;i="5.78,426,1599548400"; d="scan'208";a="97422906" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa4.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 17 Dec 2020 00:52:13 -0700 Received: from chn-vm-ex03.mchp-main.com (10.10.85.151) by chn-vm-ex03.mchp-main.com (10.10.85.151) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1979.3; Thu, 17 Dec 2020 00:52:12 -0700 Received: from mchp-dev-shegelun.microchip.com (10.10.115.15) by chn-vm-ex03.mchp-main.com (10.10.85.151) with Microsoft SMTP Server id 15.1.1979.3 via Frontend Transport; Thu, 17 Dec 2020 00:52:09 -0700 From: Steen Hegelund To: "David S. Miller" , Jakub Kicinski Subject: [RFC PATCH v2 7/8] net: sparx5: add ethtool configuration and statistics support Date: Thu, 17 Dec 2020 08:51:33 +0100 Message-ID: <20201217075134.919699-8-steen.hegelund@microchip.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201217075134.919699-1-steen.hegelund@microchip.com> References: <20201217075134.919699-1-steen.hegelund@microchip.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201217_025214_689149_A70D2E8D X-CRM114-Status: GOOD ( 18.71 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Andrew Lunn , Alexandre Belloni , linux-kernel@vger.kernel.org, Arnd Bergmann , Bjarni Jonasson , Madalin Bucur , netdev@vger.kernel.org, Steen Hegelund , Russell King , Microchip Linux Driver Support , linux-arm-kernel@lists.infradead.org, Mark Einon , Masahiro Yamada , Lars Povlsen Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org This adds statistic counters for the network interfaces provided by the driver. It also adds CPU port counters (which are not exposed by ethtool). This also adds support for configuring the network interface parameters via ethtool: speed, duplex, aneg etc. Signed-off-by: Steen Hegelund Signed-off-by: Bjarni Jonasson Signed-off-by: Lars Povlsen --- .../net/ethernet/microchip/sparx5/Makefile | 3 +- .../microchip/sparx5/sparx5_ethtool.c | 979 ++++++++++++++++++ .../ethernet/microchip/sparx5/sparx5_main.c | 5 + .../ethernet/microchip/sparx5/sparx5_main.h | 17 +- .../ethernet/microchip/sparx5/sparx5_netdev.c | 2 + 5 files changed, 1001 insertions(+), 5 deletions(-) create mode 100644 drivers/net/ethernet/microchip/sparx5/sparx5_ethtool.c diff --git a/drivers/net/ethernet/microchip/sparx5/Makefile b/drivers/net/ethernet/microchip/sparx5/Makefile index 17654ab90ce1..de3155cd582c 100644 --- a/drivers/net/ethernet/microchip/sparx5/Makefile +++ b/drivers/net/ethernet/microchip/sparx5/Makefile @@ -7,4 +7,5 @@ obj-$(CONFIG_SPARX5_SWITCH) += sparx5-switch.o sparx5-switch-objs := sparx5_main.o sparx5_switchdev.o \ sparx5_vlan.o sparx5_mactable.o sparx5_packet.o \ - sparx5_netdev.o sparx5_port.o sparx5_phylink.o sparx5_calendar.o + sparx5_ethtool.o sparx5_netdev.o sparx5_port.o \ + sparx5_phylink.o sparx5_calendar.o diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_ethtool.c b/drivers/net/ethernet/microchip/sparx5/sparx5_ethtool.c new file mode 100644 index 000000000000..f72f2126fea2 --- /dev/null +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_ethtool.c @@ -0,0 +1,979 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* Microchip Sparx5 Switch driver + * + * Copyright (c) 2020 Microchip Technology Inc. and its subsidiaries. + */ + +#include + +#include "sparx5_main.h" +#include "sparx5_port.h" + +/* Add a potentially wrapping 32 bit value to a 64 bit counter */ +static void sparx5_update_counter(u64 *cnt, u32 val) +{ + if (val < (*cnt & U32_MAX)) + *cnt += (u64)1 << 32; /* value has wrapped */ + + *cnt = (*cnt & ~(u64)U32_MAX) + val; +} + +/* Get a set of Queue System statistics */ +static void sparx5_xqs_prio_stats(struct sparx5 *sparx5, + u32 addr, + u64 *stats) +{ + int idx; + + for (idx = 0; idx < 2 * SPX5_PRIOS; ++idx, ++addr, ++stats) + sparx5_update_counter(stats, spx5_rd(sparx5, XQS_CNT(addr))); +} + +#define SPX5_STAT_GET(sname) portstats[spx5_stats_##sname] +#define SPX5_STAT_SUM(sname) (portstats[spx5_stats_##sname] + \ + portstats[spx5_stats_pmac_##sname]) +#define SPX5_STAT_XQS_PRIOS_COUNTER_SUM(sname) \ + (portstats[spx5_stats_green_p0_##sname] + \ + portstats[spx5_stats_green_p1_##sname] + \ + portstats[spx5_stats_green_p2_##sname] + \ + portstats[spx5_stats_green_p3_##sname] + \ + portstats[spx5_stats_green_p4_##sname] + \ + portstats[spx5_stats_green_p5_##sname] + \ + portstats[spx5_stats_green_p6_##sname] + \ + portstats[spx5_stats_green_p7_##sname] + \ + portstats[spx5_stats_yellow_p0_##sname] + \ + portstats[spx5_stats_yellow_p1_##sname] + \ + portstats[spx5_stats_yellow_p2_##sname] + \ + portstats[spx5_stats_yellow_p3_##sname] + \ + portstats[spx5_stats_yellow_p4_##sname] + \ + portstats[spx5_stats_yellow_p5_##sname] + \ + portstats[spx5_stats_yellow_p6_##sname] + \ + portstats[spx5_stats_yellow_p7_##sname]) + +enum sparx5_stats_entry { + spx5_stats_rx_in_bytes, + spx5_stats_rx_symbol_err, + spx5_stats_rx_pause, + spx5_stats_rx_unsup_opcode, + spx5_stats_rx_ok_bytes, + spx5_stats_rx_bad_bytes, + spx5_stats_rx_unicast, + spx5_stats_rx_multicast, + spx5_stats_rx_broadcast, + spx5_stats_rx_crc_err, + spx5_stats_rx_undersize, + spx5_stats_rx_fragments, + spx5_stats_rx_inrangelen_err, + spx5_stats_rx_outofrangelen_err, + spx5_stats_rx_oversize, + spx5_stats_rx_jabbers, + spx5_stats_rx_size64, + spx5_stats_rx_size65_127, + spx5_stats_rx_size128_255, + spx5_stats_rx_size256_511, + spx5_stats_rx_size512_1023, + spx5_stats_rx_size1024_1518, + spx5_stats_rx_size1519_max, + spx5_stats_pmac_rx_symbol_err, + spx5_stats_pmac_rx_pause, + spx5_stats_pmac_rx_unsup_opcode, + spx5_stats_pmac_rx_ok_bytes, + spx5_stats_pmac_rx_bad_bytes, + spx5_stats_pmac_rx_unicast, + spx5_stats_pmac_rx_multicast, + spx5_stats_pmac_rx_broadcast, + spx5_stats_pmac_rx_crc_err, + spx5_stats_pmac_rx_undersize, + spx5_stats_pmac_rx_fragments, + spx5_stats_pmac_rx_inrangelen_err, + spx5_stats_pmac_rx_outofrangelen_err, + spx5_stats_pmac_rx_oversize, + spx5_stats_pmac_rx_jabbers, + spx5_stats_pmac_rx_size64, + spx5_stats_pmac_rx_size65_127, + spx5_stats_pmac_rx_size128_255, + spx5_stats_pmac_rx_size256_511, + spx5_stats_pmac_rx_size512_1023, + spx5_stats_pmac_rx_size1024_1518, + spx5_stats_pmac_rx_size1519_max, + spx5_stats_green_p0_rx_fwd, + spx5_stats_green_p1_rx_fwd, + spx5_stats_green_p2_rx_fwd, + spx5_stats_green_p3_rx_fwd, + spx5_stats_green_p4_rx_fwd, + spx5_stats_green_p5_rx_fwd, + spx5_stats_green_p6_rx_fwd, + spx5_stats_green_p7_rx_fwd, + spx5_stats_yellow_p0_rx_fwd, + spx5_stats_yellow_p1_rx_fwd, + spx5_stats_yellow_p2_rx_fwd, + spx5_stats_yellow_p3_rx_fwd, + spx5_stats_yellow_p4_rx_fwd, + spx5_stats_yellow_p5_rx_fwd, + spx5_stats_yellow_p6_rx_fwd, + spx5_stats_yellow_p7_rx_fwd, + spx5_stats_green_p0_rx_port_drop, + spx5_stats_green_p1_rx_port_drop, + spx5_stats_green_p2_rx_port_drop, + spx5_stats_green_p3_rx_port_drop, + spx5_stats_green_p4_rx_port_drop, + spx5_stats_green_p5_rx_port_drop, + spx5_stats_green_p6_rx_port_drop, + spx5_stats_green_p7_rx_port_drop, + spx5_stats_yellow_p0_rx_port_drop, + spx5_stats_yellow_p1_rx_port_drop, + spx5_stats_yellow_p2_rx_port_drop, + spx5_stats_yellow_p3_rx_port_drop, + spx5_stats_yellow_p4_rx_port_drop, + spx5_stats_yellow_p5_rx_port_drop, + spx5_stats_yellow_p6_rx_port_drop, + spx5_stats_yellow_p7_rx_port_drop, + spx5_stats_rx_local_drop, + spx5_stats_rx_port_policer_drop, + spx5_stats_tx_out_bytes, + spx5_stats_tx_pause, + spx5_stats_tx_ok_bytes, + spx5_stats_tx_unicast, + spx5_stats_tx_multicast, + spx5_stats_tx_broadcast, + spx5_stats_tx_size64, + spx5_stats_tx_size65_127, + spx5_stats_tx_size128_255, + spx5_stats_tx_size256_511, + spx5_stats_tx_size512_1023, + spx5_stats_tx_size1024_1518, + spx5_stats_tx_size1519_max, + spx5_stats_tx_multi_coll, + spx5_stats_tx_late_coll, + spx5_stats_tx_xcoll, + spx5_stats_tx_defer, + spx5_stats_tx_xdefer, + spx5_stats_tx_backoff1, + spx5_stats_pmac_tx_pause, + spx5_stats_pmac_tx_ok_bytes, + spx5_stats_pmac_tx_unicast, + spx5_stats_pmac_tx_multicast, + spx5_stats_pmac_tx_broadcast, + spx5_stats_pmac_tx_size64, + spx5_stats_pmac_tx_size65_127, + spx5_stats_pmac_tx_size128_255, + spx5_stats_pmac_tx_size256_511, + spx5_stats_pmac_tx_size512_1023, + spx5_stats_pmac_tx_size1024_1518, + spx5_stats_pmac_tx_size1519_max, + spx5_stats_green_p0_tx_port, + spx5_stats_green_p1_tx_port, + spx5_stats_green_p2_tx_port, + spx5_stats_green_p3_tx_port, + spx5_stats_green_p4_tx_port, + spx5_stats_green_p5_tx_port, + spx5_stats_green_p6_tx_port, + spx5_stats_green_p7_tx_port, + spx5_stats_yellow_p0_tx_port, + spx5_stats_yellow_p1_tx_port, + spx5_stats_yellow_p2_tx_port, + spx5_stats_yellow_p3_tx_port, + spx5_stats_yellow_p4_tx_port, + spx5_stats_yellow_p5_tx_port, + spx5_stats_yellow_p6_tx_port, + spx5_stats_yellow_p7_tx_port, + spx5_stats_tx_local_drop, +}; + +static const char *const sparx5_stats_layout[] = { + "rx_in_bytes", + "rx_symbol_err", + "rx_pause", + "rx_unsup_opcode", + "rx_ok_bytes", + "rx_bad_bytes", + "rx_unicast", + "rx_multicast", + "rx_broadcast", + "rx_crc_err", + "rx_undersize", + "rx_fragments", + "rx_inrangelen_err", + "rx_outofrangelen_err", + "rx_oversize", + "rx_jabbers", + "rx_size64", + "rx_size65_127", + "rx_size128_255", + "rx_size256_511", + "rx_size512_1023", + "rx_size1024_1518", + "rx_size1519_max", + "pmac_rx_symbol_err", + "pmac_rx_pause", + "pmac_rx_unsup_opcode", + "pmac_rx_ok_bytes", + "pmac_rx_bad_bytes", + "pmac_rx_unicast", + "pmac_rx_multicast", + "pmac_rx_broadcast", + "pmac_rx_crc_err", + "pmac_rx_undersize", + "pmac_rx_fragments", + "pmac_rx_inrangelen_err", + "pmac_rx_outofrangelen_err", + "pmac_rx_oversize", + "pmac_rx_jabbers", + "pmac_rx_size64", + "pmac_rx_size65_127", + "pmac_rx_size128_255", + "pmac_rx_size256_511", + "pmac_rx_size512_1023", + "pmac_rx_size1024_1518", + "pmac_rx_size1519_max", + "rx_fwd_green_p0_q", + "rx_fwd_green_p1_q", + "rx_fwd_green_p2_q", + "rx_fwd_green_p3_q", + "rx_fwd_green_p4_q", + "rx_fwd_green_p5_q", + "rx_fwd_green_p6_q", + "rx_fwd_green_p7_q", + "rx_fwd_yellow_p0_q", + "rx_fwd_yellow_p1_q", + "rx_fwd_yellow_p2_q", + "rx_fwd_yellow_p3_q", + "rx_fwd_yellow_p4_q", + "rx_fwd_yellow_p5_q", + "rx_fwd_yellow_p6_q", + "rx_fwd_yellow_p7_q", + "rx_port_drop_green_p0_q", + "rx_port_drop_green_p1_q", + "rx_port_drop_green_p2_q", + "rx_port_drop_green_p3_q", + "rx_port_drop_green_p4_q", + "rx_port_drop_green_p5_q", + "rx_port_drop_green_p6_q", + "rx_port_drop_green_p7_q", + "rx_port_drop_yellow_p0_q", + "rx_port_drop_yellow_p1_q", + "rx_port_drop_yellow_p2_q", + "rx_port_drop_yellow_p3_q", + "rx_port_drop_yellow_p4_q", + "rx_port_drop_yellow_p5_q", + "rx_port_drop_yellow_p6_q", + "rx_port_drop_yellow_p7_q", + "rx_local_drop", + "rx_port_policer_drop", + "tx_out_bytes", + "tx_pause", + "tx_ok_bytes", + "tx_unicast", + "tx_multicast", + "tx_broadcast", + "tx_size64", + "tx_size65_127", + "tx_size128_255", + "tx_size256_511", + "tx_size512_1023", + "tx_size1024_1518", + "tx_size1519_max", + "tx_multi_coll", + "tx_late_coll", + "tx_xcoll", + "tx_defer", + "tx_xdefer", + "tx_backoff1", + "pmac_tx_pause", + "pmac_tx_ok_bytes", + "pmac_tx_unicast", + "pmac_tx_multicast", + "pmac_tx_broadcast", + "pmac_tx_size64", + "pmac_tx_size65_127", + "pmac_tx_size128_255", + "pmac_tx_size256_511", + "pmac_tx_size512_1023", + "pmac_tx_size1024_1518", + "pmac_tx_size1519_max", + "tx_port_green_p0_q", + "tx_port_green_p1_q", + "tx_port_green_p2_q", + "tx_port_green_p3_q", + "tx_port_green_p4_q", + "tx_port_green_p5_q", + "tx_port_green_p6_q", + "tx_port_green_p7_q", + "tx_port_yellow_p0_q", + "tx_port_yellow_p1_q", + "tx_port_yellow_p2_q", + "tx_port_yellow_p3_q", + "tx_port_yellow_p4_q", + "tx_port_yellow_p5_q", + "tx_port_yellow_p6_q", + "tx_port_yellow_p7_q", + "tx_local_drop", +}; + +/* Device Statistics */ +static void sparx5_get_device_stats(struct sparx5 *sparx5, int portno) +{ + u64 *portstats = &sparx5->stats[portno * sparx5->num_stats]; + u32 dev = sparx5_to_high_dev(portno); + u32 tinst = sparx5_port_dev_index(portno); + void __iomem *inst = spx5_inst_get(sparx5, dev, tinst); + + sparx5_update_counter(&portstats[spx5_stats_rx_in_bytes], + spx5_inst_rd(inst, + DEV5G_RX_IN_BYTES_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_symbol_err], + spx5_inst_rd(inst, + DEV5G_RX_SYMBOL_ERR_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_pause], + spx5_inst_rd(inst, + DEV5G_RX_PAUSE_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_unsup_opcode], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_UNSUP_OPCODE_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_ok_bytes], + spx5_inst_rd(inst, + DEV5G_RX_OK_BYTES_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_bad_bytes], + spx5_inst_rd(inst, + DEV5G_RX_BAD_BYTES_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_unicast], + spx5_inst_rd(inst, + DEV5G_RX_UC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_multicast], + spx5_inst_rd(inst, + DEV5G_RX_MC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_broadcast], + spx5_inst_rd(inst, + DEV5G_RX_BC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_crc_err], + spx5_inst_rd(inst, + DEV5G_RX_CRC_ERR_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_undersize], + spx5_inst_rd(inst, + DEV5G_RX_UNDERSIZE_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_fragments], + spx5_inst_rd(inst, + DEV5G_RX_FRAGMENTS_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_inrangelen_err], + spx5_inst_rd(inst, + DEV5G_RX_IN_RANGE_LEN_ERR_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_outofrangelen_err], + spx5_inst_rd(inst, + DEV5G_RX_OUT_OF_RANGE_LEN_ERR_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_oversize], + spx5_inst_rd(inst, + DEV5G_RX_OVERSIZE_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_jabbers], + spx5_inst_rd(inst, + DEV5G_RX_JABBERS_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_size64], + spx5_inst_rd(inst, + DEV5G_RX_SIZE64_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_size65_127], + spx5_inst_rd(inst, + DEV5G_RX_SIZE65TO127_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_size128_255], + spx5_inst_rd(inst, + DEV5G_RX_SIZE128TO255_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_size256_511], + spx5_inst_rd(inst, + DEV5G_RX_SIZE256TO511_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_size512_1023], + spx5_inst_rd(inst, + DEV5G_RX_SIZE512TO1023_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_size1024_1518], + spx5_inst_rd(inst, + DEV5G_RX_SIZE1024TO1518_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_rx_size1519_max], + spx5_inst_rd(inst, + DEV5G_RX_SIZE1519TOMAX_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_symbol_err], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_SYMBOL_ERR_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_pause], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_PAUSE_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_unsup_opcode], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_UNSUP_OPCODE_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_ok_bytes], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_OK_BYTES_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_bad_bytes], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_BAD_BYTES_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_unicast], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_UC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_multicast], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_MC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_broadcast], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_BC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_crc_err], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_CRC_ERR_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_undersize], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_UNDERSIZE_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_fragments], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_FRAGMENTS_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_inrangelen_err], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_IN_RANGE_LEN_ERR_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_outofrangelen_err], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_OUT_OF_RANGE_LEN_ERR_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_oversize], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_OVERSIZE_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_jabbers], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_JABBERS_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size64], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_SIZE64_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size65_127], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_SIZE65TO127_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size128_255], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_SIZE128TO255_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size256_511], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_SIZE256TO511_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size512_1023], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_SIZE512TO1023_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size1024_1518], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_SIZE1024TO1518_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size1519_max], + spx5_inst_rd(inst, + DEV5G_PMAC_RX_SIZE1519TOMAX_CNT(tinst))); + sparx5_xqs_prio_stats(sparx5, + 0, + &portstats[spx5_stats_green_p0_rx_fwd]); + sparx5_xqs_prio_stats(sparx5, + 16, + &portstats[spx5_stats_green_p0_rx_port_drop]); + sparx5_update_counter(&portstats[spx5_stats_rx_local_drop], + spx5_rd(sparx5, XQS_CNT(32))); + sparx5_update_counter(&portstats[spx5_stats_rx_port_policer_drop], + spx5_rd(sparx5, + ANA_AC_PORT_STAT_LSB_CNT(portno, 1))); + sparx5_update_counter(&portstats[spx5_stats_tx_out_bytes], + spx5_inst_rd(inst, + DEV5G_TX_OUT_BYTES_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_pause], + spx5_inst_rd(inst, + DEV5G_TX_PAUSE_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_ok_bytes], + spx5_inst_rd(inst, + DEV5G_TX_OK_BYTES_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_unicast], + spx5_inst_rd(inst, + DEV5G_TX_UC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_multicast], + spx5_inst_rd(inst, + DEV5G_TX_MC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_broadcast], + spx5_inst_rd(inst, + DEV5G_TX_BC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_size64], + spx5_inst_rd(inst, + DEV5G_TX_SIZE64_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_size65_127], + spx5_inst_rd(inst, + DEV5G_TX_SIZE65TO127_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_size128_255], + spx5_inst_rd(inst, + DEV5G_TX_SIZE128TO255_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_size256_511], + spx5_inst_rd(inst, + DEV5G_TX_SIZE256TO511_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_size512_1023], + spx5_inst_rd(inst, + DEV5G_TX_SIZE512TO1023_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_size1024_1518], + spx5_inst_rd(inst, + DEV5G_TX_SIZE1024TO1518_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_tx_size1519_max], + spx5_inst_rd(inst, + DEV5G_TX_SIZE1519TOMAX_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_pause], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_PAUSE_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_ok_bytes], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_OK_BYTES_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_unicast], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_UC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_multicast], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_MC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_broadcast], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_BC_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size64], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_SIZE64_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size65_127], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_SIZE65TO127_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size128_255], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_SIZE128TO255_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size256_511], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_SIZE256TO511_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size512_1023], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_SIZE512TO1023_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size1024_1518], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_SIZE1024TO1518_CNT(tinst))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size1519_max], + spx5_inst_rd(inst, + DEV5G_PMAC_TX_SIZE1519TOMAX_CNT(tinst))); + sparx5_xqs_prio_stats(sparx5, + 256, + &portstats[spx5_stats_green_p0_tx_port]); + sparx5_update_counter(&portstats[spx5_stats_tx_local_drop], + spx5_rd(sparx5, XQS_CNT(272))); +} + +/* ASM Statistics */ +static void sparx5_get_asm_stats(struct sparx5 *sparx5, int portno) +{ + u64 *portstats = &sparx5->stats[portno * sparx5->num_stats]; + u32 dev = TARGET_ASM; + void __iomem *inst = spx5_inst_get(sparx5, dev, 0); + + sparx5_update_counter(&portstats[spx5_stats_rx_in_bytes], + spx5_inst_rd(inst, + ASM_RX_IN_BYTES_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_symbol_err], + spx5_inst_rd(inst, + ASM_RX_SYMBOL_ERR_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_pause], + spx5_inst_rd(inst, + ASM_RX_PAUSE_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_unsup_opcode], + spx5_inst_rd(inst, + ASM_PMAC_RX_UNSUP_OPCODE_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_ok_bytes], + spx5_inst_rd(inst, + ASM_RX_OK_BYTES_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_bad_bytes], + spx5_inst_rd(inst, + ASM_RX_BAD_BYTES_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_unicast], + spx5_inst_rd(inst, + ASM_RX_UC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_multicast], + spx5_inst_rd(inst, + ASM_RX_MC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_broadcast], + spx5_inst_rd(inst, + ASM_RX_BC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_crc_err], + spx5_inst_rd(inst, + ASM_RX_CRC_ERR_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_undersize], + spx5_inst_rd(inst, + ASM_RX_UNDERSIZE_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_fragments], + spx5_inst_rd(inst, + ASM_RX_FRAGMENTS_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_inrangelen_err], + spx5_inst_rd(inst, + ASM_RX_IN_RANGE_LEN_ERR_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_outofrangelen_err], + spx5_inst_rd(inst, + ASM_RX_OUT_OF_RANGE_LEN_ERR_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_oversize], + spx5_inst_rd(inst, + ASM_RX_OVERSIZE_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_jabbers], + spx5_inst_rd(inst, + ASM_RX_JABBERS_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_size64], + spx5_inst_rd(inst, + ASM_RX_SIZE64_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_size65_127], + spx5_inst_rd(inst, + ASM_RX_SIZE65TO127_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_size128_255], + spx5_inst_rd(inst, + ASM_RX_SIZE128TO255_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_size256_511], + spx5_inst_rd(inst, + ASM_RX_SIZE256TO511_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_size512_1023], + spx5_inst_rd(inst, + ASM_RX_SIZE512TO1023_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_size1024_1518], + spx5_inst_rd(inst, + ASM_RX_SIZE1024TO1518_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_rx_size1519_max], + spx5_inst_rd(inst, + ASM_RX_SIZE1519TOMAX_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_symbol_err], + spx5_inst_rd(inst, + ASM_PMAC_RX_SYMBOL_ERR_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_pause], + spx5_inst_rd(inst, + ASM_PMAC_RX_PAUSE_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_unsup_opcode], + spx5_inst_rd(inst, + ASM_PMAC_RX_UNSUP_OPCODE_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_ok_bytes], + spx5_inst_rd(inst, + ASM_PMAC_RX_OK_BYTES_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_bad_bytes], + spx5_inst_rd(inst, + ASM_PMAC_RX_BAD_BYTES_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_unicast], + spx5_inst_rd(inst, + ASM_PMAC_RX_UC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_multicast], + spx5_inst_rd(inst, + ASM_PMAC_RX_MC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_broadcast], + spx5_inst_rd(inst, + ASM_PMAC_RX_BC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_crc_err], + spx5_inst_rd(inst, + ASM_PMAC_RX_CRC_ERR_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_undersize], + spx5_inst_rd(inst, + ASM_PMAC_RX_UNDERSIZE_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_fragments], + spx5_inst_rd(inst, + ASM_PMAC_RX_FRAGMENTS_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_inrangelen_err], + spx5_inst_rd(inst, + ASM_PMAC_RX_IN_RANGE_LEN_ERR_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_outofrangelen_err], + spx5_inst_rd(inst, + ASM_PMAC_RX_OUT_OF_RANGE_LEN_ERR_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_oversize], + spx5_inst_rd(inst, + ASM_PMAC_RX_OVERSIZE_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_jabbers], + spx5_inst_rd(inst, + ASM_PMAC_RX_JABBERS_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size64], + spx5_inst_rd(inst, + ASM_PMAC_RX_SIZE64_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size65_127], + spx5_inst_rd(inst, + ASM_PMAC_RX_SIZE65TO127_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size128_255], + spx5_inst_rd(inst, + ASM_PMAC_RX_SIZE128TO255_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size256_511], + spx5_inst_rd(inst, + ASM_PMAC_RX_SIZE256TO511_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size512_1023], + spx5_inst_rd(inst, + ASM_PMAC_RX_SIZE512TO1023_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size1024_1518], + spx5_inst_rd(inst, + ASM_PMAC_RX_SIZE1024TO1518_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size1519_max], + spx5_inst_rd(inst, + ASM_PMAC_RX_SIZE1519TOMAX_CNT(portno))); + sparx5_xqs_prio_stats(sparx5, + 0, + &portstats[spx5_stats_green_p0_rx_fwd]); + sparx5_xqs_prio_stats(sparx5, + 16, + &portstats[spx5_stats_green_p0_rx_port_drop]); + sparx5_update_counter(&portstats[spx5_stats_rx_local_drop], + spx5_rd(sparx5, XQS_CNT(32))); + sparx5_update_counter(&portstats[spx5_stats_rx_port_policer_drop], + spx5_rd(sparx5, + ANA_AC_PORT_STAT_LSB_CNT(portno, 1))); + sparx5_update_counter(&portstats[spx5_stats_tx_out_bytes], + spx5_inst_rd(inst, + ASM_TX_OUT_BYTES_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_pause], + spx5_inst_rd(inst, + ASM_TX_PAUSE_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_ok_bytes], + spx5_inst_rd(inst, + ASM_TX_OK_BYTES_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_unicast], + spx5_inst_rd(inst, + ASM_TX_UC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_multicast], + spx5_inst_rd(inst, + ASM_TX_MC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_broadcast], + spx5_inst_rd(inst, + ASM_TX_BC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_size64], + spx5_inst_rd(inst, + ASM_TX_SIZE64_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_size65_127], + spx5_inst_rd(inst, + ASM_TX_SIZE65TO127_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_size128_255], + spx5_inst_rd(inst, + ASM_TX_SIZE128TO255_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_size256_511], + spx5_inst_rd(inst, + ASM_TX_SIZE256TO511_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_size512_1023], + spx5_inst_rd(inst, + ASM_TX_SIZE512TO1023_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_size1024_1518], + spx5_inst_rd(inst, + ASM_TX_SIZE1024TO1518_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_size1519_max], + spx5_inst_rd(inst, + ASM_TX_SIZE1519TOMAX_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_multi_coll], + spx5_inst_rd(inst, + ASM_TX_MULTI_COLL_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_late_coll], + spx5_inst_rd(inst, + ASM_TX_LATE_COLL_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_xcoll], + spx5_inst_rd(inst, + ASM_TX_XCOLL_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_defer], + spx5_inst_rd(inst, + ASM_TX_DEFER_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_xdefer], + spx5_inst_rd(inst, + ASM_TX_XDEFER_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_tx_backoff1], + spx5_inst_rd(inst, + ASM_TX_BACKOFF1_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_pause], + spx5_inst_rd(inst, + ASM_PMAC_TX_PAUSE_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_ok_bytes], + spx5_inst_rd(inst, + ASM_PMAC_TX_OK_BYTES_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_unicast], + spx5_inst_rd(inst, + ASM_PMAC_TX_UC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_multicast], + spx5_inst_rd(inst, + ASM_PMAC_TX_MC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_broadcast], + spx5_inst_rd(inst, + ASM_PMAC_TX_BC_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size64], + spx5_inst_rd(inst, + ASM_PMAC_TX_SIZE64_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size65_127], + spx5_inst_rd(inst, + ASM_PMAC_TX_SIZE65TO127_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size128_255], + spx5_inst_rd(inst, + ASM_PMAC_TX_SIZE128TO255_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size256_511], + spx5_inst_rd(inst, + ASM_PMAC_TX_SIZE256TO511_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size512_1023], + spx5_inst_rd(inst, + ASM_PMAC_TX_SIZE512TO1023_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size1024_1518], + spx5_inst_rd(inst, + ASM_PMAC_TX_SIZE1024TO1518_CNT(portno))); + sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size1519_max], + spx5_inst_rd(inst, + ASM_PMAC_TX_SIZE1519TOMAX_CNT(portno))); + sparx5_xqs_prio_stats(sparx5, + 256, + &portstats[spx5_stats_green_p0_tx_port]); + sparx5_update_counter(&portstats[spx5_stats_tx_local_drop], + spx5_rd(sparx5, XQS_CNT(272))); +} + +static void sparx5_update_port_stats(struct sparx5 *sparx5, int portno) +{ + bool high_speed_dev = sparx5_is_high_speed_device(&sparx5->ports[portno]->conf); + + /* Set XQS port number */ + spx5_wr(XQS_STAT_CFG_STAT_VIEW_SET(portno), sparx5, XQS_STAT_CFG); + if (high_speed_dev) + sparx5_get_device_stats(sparx5, portno); + else + sparx5_get_asm_stats(sparx5, portno); +} + +static void sparx5_update_stats(struct sparx5 *sparx5) +{ + int idx; + + mutex_lock(&sparx5->stats_lock); + for (idx = 0; idx < SPX5_PORTS; idx++) + if (sparx5->ports[idx]) + sparx5_update_port_stats(sparx5, idx); + mutex_unlock(&sparx5->stats_lock); +} + +static void sparx5_check_stats_work(struct work_struct *work) +{ + struct delayed_work *dwork = to_delayed_work(work); + struct sparx5 *sparx5 = container_of(dwork, struct sparx5, + stats_work); + + sparx5_update_stats(sparx5); + + queue_delayed_work(sparx5->stats_queue, &sparx5->stats_work, + SPX5_STATS_CHECK_DELAY); +} + +static int sparx5_get_sset_count(struct net_device *ndev, int sset) +{ + struct sparx5_port *port = netdev_priv(ndev); + struct sparx5 *sparx5 = port->sparx5; + + if (sset != ETH_SS_STATS) + return -EOPNOTSUPP; + return sparx5->num_stats; +} + +static void sparx5_get_sset_strings(struct net_device *ndev, u32 sset, u8 *data) +{ + struct sparx5_port *port = netdev_priv(ndev); + struct sparx5 *sparx5 = port->sparx5; + int idx; + + if (sset != ETH_SS_STATS) + return; + + for (idx = 0; idx < sparx5->num_stats; idx++) + strncpy(data + idx * ETH_GSTRING_LEN, + sparx5->stats_layout[idx], ETH_GSTRING_LEN); +} + +static void sparx5_get_stats(struct net_device *ndev, + struct ethtool_stats *stats, u64 *data) +{ + struct sparx5_port *port = netdev_priv(ndev); + struct sparx5 *sparx5 = port->sparx5; + u64 *portstats = &sparx5->stats[port->portno * sparx5->num_stats]; + int idx; + + /* check and update now (all ports) */ + sparx5_update_stats(sparx5); + + /* Copy port counters to the ethtool buffer */ + for (idx = 0; idx < sparx5->num_stats; idx++) + *data++ = portstats[idx]; +} + +void sparx5_get_stats64(struct net_device *ndev, + struct rtnl_link_stats64 *stats) +{ + struct sparx5_port *port = netdev_priv(ndev); + struct sparx5 *sparx5 = port->sparx5; + u64 *portstats; + + if (!sparx5->stats) + return; /* Not initialized yet */ + + portstats = &sparx5->stats[port->portno * sparx5->num_stats]; + + mutex_lock(&sparx5->stats_lock); + + stats->rx_errors = SPX5_STAT_SUM(rx_crc_err) + + SPX5_STAT_SUM(rx_undersize) + SPX5_STAT_SUM(rx_oversize) + + SPX5_STAT_SUM(rx_outofrangelen_err) + + SPX5_STAT_SUM(rx_symbol_err) + SPX5_STAT_SUM(rx_jabbers) + + SPX5_STAT_SUM(rx_fragments); + + stats->rx_bytes = SPX5_STAT_SUM(rx_ok_bytes) + + SPX5_STAT_SUM(rx_bad_bytes); + + stats->rx_packets = SPX5_STAT_SUM(rx_unicast) + + SPX5_STAT_SUM(rx_multicast) + SPX5_STAT_SUM(rx_broadcast) + + stats->rx_errors; + + stats->multicast = SPX5_STAT_SUM(rx_unicast); + + stats->rx_dropped = SPX5_STAT_GET(rx_port_policer_drop) + + SPX5_STAT_XQS_PRIOS_COUNTER_SUM(rx_port_drop); + + /* Get Tx stats */ + stats->tx_bytes = SPX5_STAT_SUM(tx_ok_bytes); + + stats->tx_packets = SPX5_STAT_SUM(tx_unicast) + + SPX5_STAT_SUM(tx_multicast) + SPX5_STAT_SUM(tx_broadcast); + + stats->tx_dropped = SPX5_STAT_GET(tx_local_drop); + + stats->collisions = SPX5_STAT_GET(tx_multi_coll) + + SPX5_STAT_GET(tx_late_coll) + + SPX5_STAT_GET(tx_xcoll) + + SPX5_STAT_GET(tx_backoff1); + + mutex_unlock(&sparx5->stats_lock); +} + +static int sparx5_get_link_settings(struct net_device *ndev, + struct ethtool_link_ksettings *cmd) +{ + struct sparx5_port *port = netdev_priv(ndev); + + return phylink_ethtool_ksettings_get(port->phylink, cmd); +} + +static int sparx5_set_link_settings(struct net_device *ndev, + const struct ethtool_link_ksettings *cmd) +{ + struct sparx5_port *port = netdev_priv(ndev); + + return phylink_ethtool_ksettings_set(port->phylink, cmd); +} + +const struct ethtool_ops sparx5_ethtool_ops = { + .get_sset_count = sparx5_get_sset_count, + .get_strings = sparx5_get_sset_strings, + .get_ethtool_stats = sparx5_get_stats, + .get_link_ksettings = sparx5_get_link_settings, + .set_link_ksettings = sparx5_set_link_settings, + .get_link = ethtool_op_get_link, +}; + +int sparx_stats_init(struct sparx5 *sparx5) +{ + char queue_name[32]; + int portno; + + sparx5->stats_layout = sparx5_stats_layout; + sparx5->num_stats = ARRAY_SIZE(sparx5_stats_layout); + sparx5->stats = devm_kcalloc(sparx5->dev, + SPX5_PORTS_ALL * sparx5->num_stats, + sizeof(u64), GFP_KERNEL); + if (!sparx5->stats) + return -ENOMEM; + + for (portno = 0; portno < SPX5_PORTS; portno++) + if (sparx5->ports[portno]) { + /* Clear Queue System counters */ + spx5_wr(XQS_STAT_CFG_STAT_VIEW_SET(portno) | + XQS_STAT_CFG_STAT_CLEAR_SHOT_SET(3), sparx5, XQS_STAT_CFG); + } + + mutex_init(&sparx5->stats_lock); + snprintf(queue_name, sizeof(queue_name), "%s-stats", + dev_name(sparx5->dev)); + sparx5->stats_queue = create_singlethread_workqueue(queue_name); + INIT_DELAYED_WORK(&sparx5->stats_work, sparx5_check_stats_work); + queue_delayed_work(sparx5->stats_queue, &sparx5->stats_work, + SPX5_STATS_CHECK_DELAY); + + return 0; +} diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c index 2b42c72dac72..e1e2384512bc 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c @@ -751,6 +751,11 @@ static int mchp_sparx5_probe(struct platform_device *pdev) if (err) goto cleanup_ports; + /* Init stats */ + err = sparx_stats_init(sparx5); + if (err) + goto cleanup_ports; + /* Init mact_sw struct */ mutex_init(&sparx5->mact_lock); INIT_LIST_HEAD(&sparx5->mact_entries); diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h index e59e1962f7d4..1d1b3b516244 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h @@ -130,6 +130,14 @@ struct sparx5 { /* port structures are in net device */ struct sparx5_port *ports[SPX5_PORTS]; enum sparx5_core_clockfreq coreclock; + /* Statistics */ + u32 num_stats; + const char * const *stats_layout; + u64 *stats; + /* Workqueue for reading stats */ + struct mutex stats_lock; + struct delayed_work stats_work; + struct workqueue_struct *stats_queue; /* Notifiers */ struct notifier_block netdevice_nb; struct notifier_block switchdev_nb; @@ -153,10 +161,6 @@ struct sparx5 { bool sd_sgpio_remapping; }; -/* sparx5_main.c */ -void sparx5_update_cpuport_stats(struct sparx5 *sparx5, int portno); -bool sparx5_is_cpuport_stat(struct sparx5 *sparx5, int idx); - /* sparx5_switchdev.c */ int sparx5_register_notifier_blocks(struct sparx5 *sparx5); void sparx5_unregister_notifier_blocks(struct sparx5 *sparx5); @@ -199,6 +203,10 @@ void sparx5_vlan_port_apply(struct sparx5 *sparx5, struct sparx5_port *port); int sparx5_config_auto_calendar(struct sparx5 *sparx5); int sparx5_config_dsm_calendar(struct sparx5 *sparx5); +/* sparx5_ethtool.c */ +void sparx5_get_stats64(struct net_device *ndev, struct rtnl_link_stats64 *stats); +int sparx_stats_init(struct sparx5 *sparx5); + /* sparx5_netdev.c */ bool sparx5_netdevice_check(const struct net_device *dev); struct net_device *sparx5_create_netdev(struct sparx5 *sparx5, u32 portno); @@ -226,6 +234,7 @@ static inline u32 sparx5_clk_period(enum sparx5_core_clockfreq cclock) } extern const struct phylink_mac_ops sparx5_phylink_mac_ops; +extern const struct ethtool_ops sparx5_ethtool_ops; /* Calculate raw offset */ static inline __pure int spx5_offset(int id, int tinst, int tcnt, diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c b/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c index a0992443ab9f..3b7cfbb14f2e 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c @@ -176,6 +176,7 @@ static const struct net_device_ops sparx5_port_netdev_ops = { .ndo_get_phys_port_name = sparx5_port_get_phys_port_name, .ndo_set_mac_address = sparx5_set_mac_address, .ndo_validate_addr = eth_validate_addr, + .ndo_get_stats64 = sparx5_get_stats64, .ndo_get_port_parent_id = sparx5_get_port_parent_id, }; @@ -203,6 +204,7 @@ struct net_device *sparx5_create_netdev(struct sparx5 *sparx5, u32 portno) ether_setup(ndev); ndev->netdev_ops = &sparx5_port_netdev_ops; + ndev->ethtool_ops = &sparx5_ethtool_ops; ndev->features |= NETIF_F_LLTX; /* software tx */ ether_addr_copy(ndev->dev_addr, sparx5->base_mac); -- 2.29.2 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel