From patchwork Tue Dec 3 07:56:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksij Rempel X-Patchwork-Id: 13891833 X-Patchwork-Delegate: kuba@kernel.org Received: from metis.whiteo.stw.pengutronix.de (metis.whiteo.stw.pengutronix.de [185.203.201.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DCEFF1DC182 for ; Tue, 3 Dec 2024 07:56:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.201.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733212607; cv=none; b=NYhS60OzkYUkTNklnfgez10r92mX3xHMga57ZWorDGucZdBJC67YCYgS8FuO6nTwmzvWj06yLoCJSdglyhZr9xAKOu2ETIJ+02gi6zGBpFRZJIoIV55XVuEqNL+8aQ2rQhQy2+qyUgO1RPOuNwS5iOKjHxwfkFS6AWpLonb4MpA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733212607; c=relaxed/simple; bh=fNDJiRjSIpBTI2wShbwaQxYzIQAT0tah72XFz2vi4KU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Hh91leI/aoxICtxkX7ulSyvdGjIHJi69YkdylR9DOcrllULrwRGVO0/3o71+AycWOQv+oelmg4CqGhzUqN6i3ZCwicsfqEQobvN2tQBvrALY1n3fWs0mrlH1sJv+j1Hc8K/t1GJONquhgOq6EOeBsRNsp05sOeRm+tfeUipfT+Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.201.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.whiteo.stw.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1tINlj-000393-Kj; Tue, 03 Dec 2024 08:56:27 +0100 Received: from dude04.red.stw.pengutronix.de ([2a0a:edc0:0:1101:1d::ac]) by drehscheibe.grey.stw.pengutronix.de with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1tINle-001R8v-0V; Tue, 03 Dec 2024 08:56:22 +0100 Received: from ore by dude04.red.stw.pengutronix.de with local (Exim 4.96) (envelope-from ) id 1tINle-00AHvo-2l; Tue, 03 Dec 2024 08:56:22 +0100 From: Oleksij Rempel To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Heiner Kallweit , Jonathan Corbet Cc: Oleksij Rempel , kernel@pengutronix.de, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Simon Horman , Russell King , Maxime Chevallier , linux-doc@vger.kernel.org Subject: [PATCH net-next v1 1/7] net: ethtool: plumb PHY stats to PHY drivers Date: Tue, 3 Dec 2024 08:56:15 +0100 Message-Id: <20241203075622.2452169-2-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241203075622.2452169-1-o.rempel@pengutronix.de> References: <20241203075622.2452169-1-o.rempel@pengutronix.de> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org From: Jakub Kicinski Feed the existing IEEE PHY counter struct (which currently only has one entry) and link stats into the PHY driver. The MAC driver can override the value if it somehow has a better idea of PHY stats. Since the stats are "undefined" at input the drivers can't += the values, so we should be safe from double-counting. Signed-off-by: Jakub Kicinski Signed-off-by: Oleksij Rempel --- include/linux/phy.h | 10 ++++++++++ net/ethtool/linkstate.c | 25 ++++++++++++++++++++++--- net/ethtool/stats.c | 19 +++++++++++++++++++ 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/include/linux/phy.h b/include/linux/phy.h index 563c46205685..523195c724b5 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1090,6 +1090,16 @@ struct phy_driver { int (*cable_test_get_status)(struct phy_device *dev, bool *finished); /* Get statistics from the PHY using ethtool */ + /** + * @get_phy_stats: Get well known statistics. + * @get_link_stats: Get well known link statistics. + * The input structure is not zero-initialized and the implementation + * must only set statistics which are actually collected by the device. + */ + void (*get_phy_stats)(struct phy_device *dev, + struct ethtool_eth_phy_stats *eth_stats); + void (*get_link_stats)(struct phy_device *dev, + struct ethtool_link_ext_stats *link_stats); /** @get_sset_count: Number of statistic counters */ int (*get_sset_count)(struct phy_device *dev); /** @get_strings: Names of the statistic counters */ diff --git a/net/ethtool/linkstate.c b/net/ethtool/linkstate.c index 34d76e87847d..8d3a38cc3d48 100644 --- a/net/ethtool/linkstate.c +++ b/net/ethtool/linkstate.c @@ -94,6 +94,27 @@ static int linkstate_get_link_ext_state(struct net_device *dev, return 0; } +static void +ethtool_get_phydev_stats(struct net_device *dev, + struct linkstate_reply_data *data) +{ + struct phy_device *phydev = dev->phydev; + + if (!phydev) + return; + + if (dev->phydev) + data->link_stats.link_down_events = + READ_ONCE(dev->phydev->link_down_events); + + if (!phydev->drv || !phydev->drv->get_link_stats) + return; + + mutex_lock(&phydev->lock); + phydev->drv->get_link_stats(phydev, &data->link_stats); + mutex_unlock(&phydev->lock); +} + static int linkstate_prepare_data(const struct ethnl_req_info *req_base, struct ethnl_reply_data *reply_base, const struct genl_info *info) @@ -127,9 +148,7 @@ static int linkstate_prepare_data(const struct ethnl_req_info *req_base, sizeof(data->link_stats) / 8); if (req_base->flags & ETHTOOL_FLAG_STATS) { - if (dev->phydev) - data->link_stats.link_down_events = - READ_ONCE(dev->phydev->link_down_events); + ethtool_get_phydev_stats(dev, data); if (dev->ethtool_ops->get_link_ext_stats) dev->ethtool_ops->get_link_ext_stats(dev, diff --git a/net/ethtool/stats.c b/net/ethtool/stats.c index 912f0c4fff2f..cf802b1cda6f 100644 --- a/net/ethtool/stats.c +++ b/net/ethtool/stats.c @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only +#include + #include "netlink.h" #include "common.h" #include "bitset.h" @@ -112,6 +114,19 @@ static int stats_parse_request(struct ethnl_req_info *req_base, return 0; } +static void +ethtool_get_phydev_stats(struct net_device *dev, struct stats_reply_data *data) +{ + struct phy_device *phydev = dev->phydev; + + if (!phydev || !phydev->drv || !phydev->drv->get_phy_stats) + return; + + mutex_lock(&phydev->lock); + phydev->drv->get_phy_stats(phydev, &data->phy_stats); + mutex_unlock(&phydev->lock); +} + static int stats_prepare_data(const struct ethnl_req_info *req_base, struct ethnl_reply_data *reply_base, const struct genl_info *info) @@ -145,6 +160,10 @@ static int stats_prepare_data(const struct ethnl_req_info *req_base, data->ctrl_stats.src = src; data->rmon_stats.src = src; + if (test_bit(ETHTOOL_STATS_ETH_PHY, req_info->stat_mask) && + src == ETHTOOL_MAC_STATS_SRC_AGGREGATE) + ethtool_get_phydev_stats(dev, data); + if (test_bit(ETHTOOL_STATS_ETH_PHY, req_info->stat_mask) && dev->ethtool_ops->get_eth_phy_stats) dev->ethtool_ops->get_eth_phy_stats(dev, &data->phy_stats); From patchwork Tue Dec 3 07:56:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksij Rempel X-Patchwork-Id: 13891834 X-Patchwork-Delegate: kuba@kernel.org Received: from metis.whiteo.stw.pengutronix.de (metis.whiteo.stw.pengutronix.de [185.203.201.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D1E991DF73D for ; Tue, 3 Dec 2024 07:56:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.201.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733212608; cv=none; b=nfyuhDvNs1m5F89WAh8/URkF5hGSAvJeuVs2WWKfrlbYW1bC8IMujCWe+fZuSsCEyU1TfxqRXqqHR2IXtBJYgLPTEIWM3OsEYJjg+u/6Ozos6X5oJrJLAMXyzHUcY+tKgXzvDPOB2sJj1V/AQbpEE5u4yRBGIoHoYKX2W8OVFjE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733212608; c=relaxed/simple; bh=IJz3BTVVUVHjJPI4ChFZs5cSm+d66rR2ttqqpJVqLko=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Y6JswmX54O4wllFhPbP5WQQJWfNhR95ir+mswArGkW039Y603ZOv4V3ljX8SlDlqbbpfNLmRtFCeWZiHM4rzoBsvzA9po6Xuu0NxEywxrC19NZ5vjIGjzDJ6Hktx6PFTeRdmbkTVlLpj7KY1LsjLryfN2WUAbAjoshswc7KNWuE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.201.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.whiteo.stw.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1tINlj-000394-Ki; Tue, 03 Dec 2024 08:56:27 +0100 Received: from dude04.red.stw.pengutronix.de ([2a0a:edc0:0:1101:1d::ac]) by drehscheibe.grey.stw.pengutronix.de with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1tINle-001R8w-0a; Tue, 03 Dec 2024 08:56:22 +0100 Received: from ore by dude04.red.stw.pengutronix.de with local (Exim 4.96) (envelope-from ) id 1tINle-00AHvy-2q; Tue, 03 Dec 2024 08:56:22 +0100 From: Oleksij Rempel To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Heiner Kallweit , Jonathan Corbet Cc: Oleksij Rempel , kernel@pengutronix.de, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Simon Horman , Russell King , Maxime Chevallier , linux-doc@vger.kernel.org Subject: [PATCH net-next v1 2/7] net: ethtool: add support for structured PHY statistics Date: Tue, 3 Dec 2024 08:56:16 +0100 Message-Id: <20241203075622.2452169-3-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241203075622.2452169-1-o.rempel@pengutronix.de> References: <20241203075622.2452169-1-o.rempel@pengutronix.de> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org From: Jakub Kicinski Introduce a new way to report PHY statistics in a structured and standardized format using the netlink API. This new method does not replace the old driver-specific stats, which can still be accessed with `ethtool -S `. The structured stats are available with `ethtool -S --all-groups`. This new method makes it easier to diagnose problems by organizing stats in a consistent and documented way. Signed-off-by: Jakub Kicinski Signed-off-by: Oleksij Rempel --- Documentation/networking/ethtool-netlink.rst | 1 + include/linux/ethtool.h | 23 +++++++++++ include/linux/phy.h | 3 +- include/uapi/linux/ethtool.h | 2 + include/uapi/linux/ethtool_netlink.h | 15 +++++++ net/ethtool/netlink.h | 1 + net/ethtool/stats.c | 43 +++++++++++++++++++- net/ethtool/strset.c | 5 +++ 8 files changed, 90 insertions(+), 3 deletions(-) diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst index b25926071ece..3bc6003185a1 100644 --- a/Documentation/networking/ethtool-netlink.rst +++ b/Documentation/networking/ethtool-netlink.rst @@ -1611,6 +1611,7 @@ the ``ETHTOOL_A_STATS_GROUPS`` bitset. Currently defined values are: ETHTOOL_STATS_ETH_PHY eth-phy Basic IEEE 802.3 PHY statistics (30.3.2.1.*) ETHTOOL_STATS_ETH_CTRL eth-ctrl Basic IEEE 802.3 MAC Ctrl statistics (30.3.3.*) ETHTOOL_STATS_RMON rmon RMON (RFC 2819) statistics + ETHTOOL_STATS_PHY phy Additional PHY statistics, not defined by IEEE ====================== ======== =============================================== Each group should have a corresponding ``ETHTOOL_A_STATS_GRP`` in the reply. diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index b8b935b52603..b0ed740ca749 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -412,6 +412,29 @@ struct ethtool_eth_phy_stats { ); }; +/** + * struct ethtool_phy_stats - PHY-level statistics counters + * @rx_packets: Total successfully received frames + * @rx_bytes: Total successfully received bytes + * @rx_errors: Total received frames with errors (e.g., CRC errors) + * @tx_packets: Total successfully transmitted frames + * @tx_bytes: Total successfully transmitted bytes + * @tx_errors: Total transmitted frames with errors + * + * This structure provides a standardized interface for reporting + * PHY-level statistics counters. It is designed to expose statistics + * commonly provided by PHYs but not explicitly defined in the IEEE + * 802.3 standard. + */ +struct ethtool_phy_stats { + u64 rx_packets; + u64 rx_bytes; + u64 rx_errors; + u64 tx_packets; + u64 tx_bytes; + u64 tx_errors; +}; + /* Basic IEEE 802.3 MAC Ctrl statistics (30.3.3.*), not otherwise exposed * via a more targeted API. */ diff --git a/include/linux/phy.h b/include/linux/phy.h index 523195c724b5..20a0d43ab5d4 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1097,7 +1097,8 @@ struct phy_driver { * must only set statistics which are actually collected by the device. */ void (*get_phy_stats)(struct phy_device *dev, - struct ethtool_eth_phy_stats *eth_stats); + struct ethtool_eth_phy_stats *eth_stats, + struct ethtool_phy_stats *stats); void (*get_link_stats)(struct phy_device *dev, struct ethtool_link_ext_stats *link_stats); /** @get_sset_count: Number of statistic counters */ diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index 7e1b3820f91f..d1089b88efc7 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -681,6 +681,7 @@ enum ethtool_link_ext_substate_module { * @ETH_SS_STATS_ETH_MAC: names of IEEE 802.3 MAC statistics * @ETH_SS_STATS_ETH_CTRL: names of IEEE 802.3 MAC Control statistics * @ETH_SS_STATS_RMON: names of RMON statistics + * @ETH_SS_STATS_PHY: names of PHY(dev) statistics * * @ETH_SS_COUNT: number of defined string sets */ @@ -706,6 +707,7 @@ enum ethtool_stringset { ETH_SS_STATS_ETH_MAC, ETH_SS_STATS_ETH_CTRL, ETH_SS_STATS_RMON, + ETH_SS_STATS_PHY, /* add new constants above here */ ETH_SS_COUNT diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h index 283305f6b063..dc332f8aa3a6 100644 --- a/include/uapi/linux/ethtool_netlink.h +++ b/include/uapi/linux/ethtool_netlink.h @@ -820,6 +820,7 @@ enum { ETHTOOL_STATS_ETH_MAC, ETHTOOL_STATS_ETH_CTRL, ETHTOOL_STATS_RMON, + ETHTOOL_STATS_PHY, /* add new constants above here */ __ETHTOOL_STATS_CNT @@ -935,6 +936,20 @@ enum { ETHTOOL_A_STATS_RMON_MAX = (__ETHTOOL_A_STATS_RMON_CNT - 1) }; +enum { + /* Basic packet counters if PHY has separate counters from the MAC */ + ETHTOOL_A_STATS_PHY_RX_PKTS, + ETHTOOL_A_STATS_PHY_RX_BYTES, + ETHTOOL_A_STATS_PHY_RX_ERRORS, + ETHTOOL_A_STATS_PHY_TX_PKTS, + ETHTOOL_A_STATS_PHY_TX_BYTES, + ETHTOOL_A_STATS_PHY_TX_ERRORS, + + /* add new constants above here */ + __ETHTOOL_A_STATS_PHY_CNT, + ETHTOOL_A_STATS_PHY_MAX = (__ETHTOOL_A_STATS_PHY_CNT - 1) +}; + /* MODULE */ enum { diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h index 203b08eb6c6f..3a6ecdcb5b8c 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -505,5 +505,6 @@ extern const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING extern const char stats_eth_mac_names[__ETHTOOL_A_STATS_ETH_MAC_CNT][ETH_GSTRING_LEN]; extern const char stats_eth_ctrl_names[__ETHTOOL_A_STATS_ETH_CTRL_CNT][ETH_GSTRING_LEN]; extern const char stats_rmon_names[__ETHTOOL_A_STATS_RMON_CNT][ETH_GSTRING_LEN]; +extern const char stats_phy_names[__ETHTOOL_A_STATS_PHY_CNT][ETH_GSTRING_LEN]; #endif /* _NET_ETHTOOL_NETLINK_H */ diff --git a/net/ethtool/stats.c b/net/ethtool/stats.c index cf802b1cda6f..ec3b0a2e01e8 100644 --- a/net/ethtool/stats.c +++ b/net/ethtool/stats.c @@ -22,6 +22,7 @@ struct stats_reply_data { struct ethtool_eth_mac_stats mac_stats; struct ethtool_eth_ctrl_stats ctrl_stats; struct ethtool_rmon_stats rmon_stats; + struct ethtool_phy_stats phydev_stats; ); const struct ethtool_rmon_hist_range *rmon_ranges; }; @@ -34,6 +35,7 @@ const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN] = { [ETHTOOL_STATS_ETH_MAC] = "eth-mac", [ETHTOOL_STATS_ETH_CTRL] = "eth-ctrl", [ETHTOOL_STATS_RMON] = "rmon", + [ETHTOOL_STATS_PHY] = "phydev", }; const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN] = { @@ -78,6 +80,15 @@ const char stats_rmon_names[__ETHTOOL_A_STATS_RMON_CNT][ETH_GSTRING_LEN] = { [ETHTOOL_A_STATS_RMON_JABBER] = "etherStatsJabbers", }; +const char stats_phy_names[__ETHTOOL_A_STATS_PHY_CNT][ETH_GSTRING_LEN] = { + [ETHTOOL_A_STATS_PHY_RX_PKTS] = "RxFrames", + [ETHTOOL_A_STATS_PHY_RX_BYTES] = "RxOctets", + [ETHTOOL_A_STATS_PHY_RX_ERRORS] = "RxErrors", + [ETHTOOL_A_STATS_PHY_TX_PKTS] = "TxFrames", + [ETHTOOL_A_STATS_PHY_TX_BYTES] = "TxOctets", + [ETHTOOL_A_STATS_PHY_TX_ERRORS] = "TxErrors", +}; + const struct nla_policy ethnl_stats_get_policy[ETHTOOL_A_STATS_SRC + 1] = { [ETHTOOL_A_STATS_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy), @@ -123,7 +134,8 @@ ethtool_get_phydev_stats(struct net_device *dev, struct stats_reply_data *data) return; mutex_lock(&phydev->lock); - phydev->drv->get_phy_stats(phydev, &data->phy_stats); + phydev->drv->get_phy_stats(phydev, &data->phy_stats, + &data->phydev_stats); mutex_unlock(&phydev->lock); } @@ -160,7 +172,8 @@ static int stats_prepare_data(const struct ethnl_req_info *req_base, data->ctrl_stats.src = src; data->rmon_stats.src = src; - if (test_bit(ETHTOOL_STATS_ETH_PHY, req_info->stat_mask) && + if ((test_bit(ETHTOOL_STATS_PHY, req_info->stat_mask) || + test_bit(ETHTOOL_STATS_ETH_PHY, req_info->stat_mask)) && src == ETHTOOL_MAC_STATS_SRC_AGGREGATE) ethtool_get_phydev_stats(dev, data); @@ -213,6 +226,10 @@ static int stats_reply_size(const struct ethnl_req_info *req_base, nla_total_size(4)) * /* _A_STATS_GRP_HIST_BKT_HI */ ETHTOOL_RMON_HIST_MAX * 2; } + if (test_bit(ETHTOOL_STATS_PHY, req_info->stat_mask)) { + n_stats += sizeof(struct ethtool_phy_stats) / sizeof(u64); + n_grps++; + } len += n_grps * (nla_total_size(0) + /* _A_STATS_GRP */ nla_total_size(4) + /* _A_STATS_GRP_ID */ @@ -266,6 +283,25 @@ static int stats_put_phy_stats(struct sk_buff *skb, return 0; } +static int stats_put_phydev_stats(struct sk_buff *skb, + const struct stats_reply_data *data) +{ + if (stat_put(skb, ETHTOOL_A_STATS_PHY_RX_PKTS, + data->phydev_stats.rx_packets) || + stat_put(skb, ETHTOOL_A_STATS_PHY_RX_BYTES, + data->phydev_stats.rx_bytes) || + stat_put(skb, ETHTOOL_A_STATS_PHY_RX_ERRORS, + data->phydev_stats.rx_errors) || + stat_put(skb, ETHTOOL_A_STATS_PHY_TX_PKTS, + data->phydev_stats.tx_packets) || + stat_put(skb, ETHTOOL_A_STATS_PHY_TX_BYTES, + data->phydev_stats.tx_bytes) || + stat_put(skb, ETHTOOL_A_STATS_PHY_TX_ERRORS, + data->phydev_stats.tx_errors)) + return -EMSGSIZE; + return 0; +} + static int stats_put_mac_stats(struct sk_buff *skb, const struct stats_reply_data *data) { @@ -442,6 +478,9 @@ static int stats_fill_reply(struct sk_buff *skb, if (!ret && test_bit(ETHTOOL_STATS_RMON, req_info->stat_mask)) ret = stats_put_stats(skb, data, ETHTOOL_STATS_RMON, ETH_SS_STATS_RMON, stats_put_rmon_stats); + if (!ret && test_bit(ETHTOOL_STATS_PHY, req_info->stat_mask)) + ret = stats_put_stats(skb, data, ETHTOOL_STATS_PHY, + ETH_SS_STATS_PHY, stats_put_phydev_stats); return ret; } diff --git a/net/ethtool/strset.c b/net/ethtool/strset.c index b3382b3cf325..818cf01f0911 100644 --- a/net/ethtool/strset.c +++ b/net/ethtool/strset.c @@ -105,6 +105,11 @@ static const struct strset_info info_template[] = { .count = __ETHTOOL_A_STATS_RMON_CNT, .strings = stats_rmon_names, }, + [ETH_SS_STATS_PHY] = { + .per_dev = false, + .count = __ETHTOOL_A_STATS_PHY_CNT, + .strings = stats_phy_names, + }, }; struct strset_req_info { From patchwork Tue Dec 3 07:56:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksij Rempel X-Patchwork-Id: 13891827 X-Patchwork-Delegate: kuba@kernel.org Received: from metis.whiteo.stw.pengutronix.de (metis.whiteo.stw.pengutronix.de [185.203.201.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A40121A01B9 for ; Tue, 3 Dec 2024 07:56:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.201.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733212603; cv=none; b=K7oWOrYLfuB0M21xCBw0ku7TierIzcPNmjUuBJCNb+opeEsjUo0ftnkPs0LMI+1A51aCL03MRCkTFcTVU1WIcZX7bH9tlfxYIp72s2C6h2pQiqyOlLK+4xekITgZdZDxs8qlnk9i/pKhJQLlIbSc7J2ahE9G0kKNX67gdMkJc1M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733212603; c=relaxed/simple; bh=h2wq29K/7BN/z+SVjji4cLJS5r3QL0WZHvFT9zzVm1Y=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Vk0ch59SnUmmrCD3aFgGSHj8YyPhStn6CFSxDqDFxw4E3pOAaPloYVsHLcJ5SwlI/EudEFF4ArPyUHSdWFL4G6KjYT7LeG5YsLsgXSnbxYGxM4O/yPrUzIPN/m6sIp3Nxce4/33GkgqTkxqZVMN+X0yEzsCNs7s66FTCVqv9zqg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.201.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.whiteo.stw.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1tINlj-000395-Kl; Tue, 03 Dec 2024 08:56:27 +0100 Received: from dude04.red.stw.pengutronix.de ([2a0a:edc0:0:1101:1d::ac]) by drehscheibe.grey.stw.pengutronix.de with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1tINle-001R8x-0h; Tue, 03 Dec 2024 08:56:22 +0100 Received: from ore by dude04.red.stw.pengutronix.de with local (Exim 4.96) (envelope-from ) id 1tINle-00AHw8-2v; Tue, 03 Dec 2024 08:56:22 +0100 From: Oleksij Rempel To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Heiner Kallweit , Jonathan Corbet Cc: Oleksij Rempel , kernel@pengutronix.de, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Simon Horman , Russell King , Maxime Chevallier , linux-doc@vger.kernel.org Subject: [PATCH net-next v1 3/7] phy: replace bitwise flag definitions with BIT() macro Date: Tue, 3 Dec 2024 08:56:17 +0100 Message-Id: <20241203075622.2452169-4-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241203075622.2452169-1-o.rempel@pengutronix.de> References: <20241203075622.2452169-1-o.rempel@pengutronix.de> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Convert the PHY flag definitions to use the BIT() macro instead of hexadecimal values. This improves readability and maintainability. No functional changes are introduced by this modification. Signed-off-by: Oleksij Rempel Reviewed-by: Russell King (Oracle) --- include/linux/phy.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/linux/phy.h b/include/linux/phy.h index 20a0d43ab5d4..a6c47b0675af 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -86,11 +86,11 @@ extern const int phy_10gbit_features_array[1]; #define PHY_POLL -1 #define PHY_MAC_INTERRUPT -2 -#define PHY_IS_INTERNAL 0x00000001 -#define PHY_RST_AFTER_CLK_EN 0x00000002 -#define PHY_POLL_CABLE_TEST 0x00000004 -#define PHY_ALWAYS_CALL_SUSPEND 0x00000008 -#define MDIO_DEVICE_IS_PHY 0x80000000 +#define PHY_IS_INTERNAL BIT(0) +#define PHY_RST_AFTER_CLK_EN BIT(1) +#define PHY_POLL_CABLE_TEST BIT(2) +#define PHY_ALWAYS_CALL_SUSPEND BIT(3) +#define MDIO_DEVICE_IS_PHY BIT(31) /** * enum phy_interface_t - Interface Mode definitions From patchwork Tue Dec 3 07:56:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksij Rempel X-Patchwork-Id: 13891830 X-Patchwork-Delegate: kuba@kernel.org Received: from metis.whiteo.stw.pengutronix.de (metis.whiteo.stw.pengutronix.de [185.203.201.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A64AD1D9A6E for ; Tue, 3 Dec 2024 07:56:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.201.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733212605; cv=none; b=GXM2oCPrJ4oE3FKHaO0MNO2ZnViPxr+G0cOzRM3GSTKB3FwG/rBU5mb+Zizj0q0zOlRitTB2Vc/fmYy5nnzMtF/rq0R5MnBIic0NmqGe4hwak8OxcNOwQYI19Xw0xdS5sf4THgDhX+GWzq00R7hHJJcGc09vH3S5ewWfJIW5+ns= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733212605; c=relaxed/simple; bh=hVd5tnauehki0EC7uyVUjToNlUh6nLbMFADO/U21EQY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=LUuUPD79An98for86z2dg2U73G8SJ7B2r68UFkyEKAGcx/PzIfS19ewCRpkh/UJWuFbNhR6nfUxNNmS+uWeAWBhl8QN6bTLAOU2kij0VkYRHuFMOkfjfm+xC7Vgt3p956qQ5MI/TCARkG+0kzUfqac2uneYOK7dtBPKhc/EBZ6o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.201.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.whiteo.stw.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1tINlj-000396-Kk; Tue, 03 Dec 2024 08:56:27 +0100 Received: from dude04.red.stw.pengutronix.de ([2a0a:edc0:0:1101:1d::ac]) by drehscheibe.grey.stw.pengutronix.de with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1tINle-001R8z-0k; Tue, 03 Dec 2024 08:56:23 +0100 Received: from ore by dude04.red.stw.pengutronix.de with local (Exim 4.96) (envelope-from ) id 1tINle-00AHwI-2z; Tue, 03 Dec 2024 08:56:22 +0100 From: Oleksij Rempel To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Heiner Kallweit , Jonathan Corbet Cc: Oleksij Rempel , kernel@pengutronix.de, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Simon Horman , Russell King , Maxime Chevallier , linux-doc@vger.kernel.org Subject: [PATCH net-next v1 4/7] phy: introduce optional polling interface for PHY statistics Date: Tue, 3 Dec 2024 08:56:18 +0100 Message-Id: <20241203075622.2452169-5-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241203075622.2452169-1-o.rempel@pengutronix.de> References: <20241203075622.2452169-1-o.rempel@pengutronix.de> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Add an optional polling interface for PHY statistics to simplify driver implementation. Drivers can request the PHYlib to handle the polling task by explicitly setting the `PHY_POLL_STATS` flag in their driver configuration. Signed-off-by: Oleksij Rempel --- drivers/net/phy/phy.c | 15 +++++++++++++++ include/linux/phy.h | 6 ++++++ 2 files changed, 21 insertions(+) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 0d20b534122b..b10ee9223fc9 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -1346,6 +1346,18 @@ static int phy_enable_interrupts(struct phy_device *phydev) return phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED); } +/** + * phy_update_stats - update the PHY statistics + * @phydev: target phy_device struct + */ +static int phy_update_stats(struct phy_device *phydev) +{ + if (!phydev->drv->update_stats) + return 0; + + return phydev->drv->update_stats(phydev); +} + /** * phy_request_interrupt - request and enable interrupt for a PHY device * @phydev: target phy_device struct @@ -1415,6 +1427,9 @@ static enum phy_state_work _phy_state_machine(struct phy_device *phydev) case PHY_RUNNING: err = phy_check_link_status(phydev); func = &phy_check_link_status; + + if (!err) + err = phy_update_stats(phydev); break; case PHY_CABLETEST: err = phydev->drv->cable_test_get_status(phydev, &finished); diff --git a/include/linux/phy.h b/include/linux/phy.h index a6c47b0675af..21cd44d177d2 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -90,6 +90,7 @@ extern const int phy_10gbit_features_array[1]; #define PHY_RST_AFTER_CLK_EN BIT(1) #define PHY_POLL_CABLE_TEST BIT(2) #define PHY_ALWAYS_CALL_SUSPEND BIT(3) +#define PHY_POLL_STATS BIT(4) #define MDIO_DEVICE_IS_PHY BIT(31) /** @@ -1101,6 +1102,8 @@ struct phy_driver { struct ethtool_phy_stats *stats); void (*get_link_stats)(struct phy_device *dev, struct ethtool_link_ext_stats *link_stats); + int (*update_stats)(struct phy_device *dev); + /** @get_sset_count: Number of statistic counters */ int (*get_sset_count)(struct phy_device *dev); /** @get_strings: Names of the statistic counters */ @@ -1591,6 +1594,9 @@ static inline bool phy_polling_mode(struct phy_device *phydev) if (phydev->drv->flags & PHY_POLL_CABLE_TEST) return true; + if (phydev->drv->update_stats && phydev->drv->flags & PHY_POLL_STATS) + return true; + return phydev->irq == PHY_POLL; } From patchwork Tue Dec 3 07:56:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksij Rempel X-Patchwork-Id: 13891829 X-Patchwork-Delegate: kuba@kernel.org Received: from metis.whiteo.stw.pengutronix.de (metis.whiteo.stw.pengutronix.de [185.203.201.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 325F61B85CB for ; Tue, 3 Dec 2024 07:56:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.201.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733212604; cv=none; b=Gqa0PaLc3QstySWnkgi43qpngQUQkX5HYY7OX9jr/p8f1o2lARcXZIDjx+hqRsuyW3D1ZHm2SpMYQb1Jt5imHPR/Tqj2qPpWzkxXFg5yAbRl2A5ZnBpYIBQddY4Sx5++k4/+SyiVM7AhACZqhQ23WhdjScnaWj9NhdW32HvEk6s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733212604; c=relaxed/simple; bh=oSPdpmoBlXHFSd4Hu5Dq7Ep5kgm70t61USTk5+qm7rs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=LN825M58u58RINZ9Q0krCiKfDY0wcUz4X987d7mKWy0Kv/BBRombWTxPhETVm5lljmSrhZ/kevGmMa/j62uRXcxG1JF9xBKqg2sbns8cT+iz1K3SD9MKaLaFwYHzBl4vmuDWOZLfElm7cLdKXt3ZOIRW6fo77u8vp7WzRAOBdyI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.201.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.whiteo.stw.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1tINlj-000397-Kk; Tue, 03 Dec 2024 08:56:27 +0100 Received: from dude04.red.stw.pengutronix.de ([2a0a:edc0:0:1101:1d::ac]) by drehscheibe.grey.stw.pengutronix.de with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1tINle-001R92-0r; Tue, 03 Dec 2024 08:56:23 +0100 Received: from ore by dude04.red.stw.pengutronix.de with local (Exim 4.96) (envelope-from ) id 1tINle-00AHwS-33; Tue, 03 Dec 2024 08:56:22 +0100 From: Oleksij Rempel To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Heiner Kallweit , Jonathan Corbet Cc: Oleksij Rempel , kernel@pengutronix.de, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Simon Horman , Russell King , Maxime Chevallier , linux-doc@vger.kernel.org Subject: [PATCH net-next v1 5/7] ethtool: add helper to prevent invalid statistics exposure to userspace Date: Tue, 3 Dec 2024 08:56:19 +0100 Message-Id: <20241203075622.2452169-6-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241203075622.2452169-1-o.rempel@pengutronix.de> References: <20241203075622.2452169-1-o.rempel@pengutronix.de> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Introduce a new helper function, `ethtool_stat_add`, to update 64-bit statistics with proper handling of the reserved value `ETHTOOL_STAT_NOT_SET`. This ensures that statistics remain valid and are always reported to userspace, even if the driver accidentally sets `ETHTOOL_STAT_NOT_SET` during an update. Signed-off-by: Oleksij Rempel Reviewed-by: Mateusz Polchlopek --- include/linux/ethtool.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index b0ed740ca749..657bd69ddaf7 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -371,6 +371,22 @@ static inline void ethtool_stats_init(u64 *stats, unsigned int n) stats[n] = ETHTOOL_STAT_NOT_SET; } +/** + * ethtool_stat_add - Add a value to a u64 statistic with wraparound handling + * @stat: Pointer to the statistic to update + * @value: Value to add to the statistic + * + * Adds the specified value to a u64 statistic. If the result of the addition + * equals the reserved value (`ETHTOOL_STAT_NOT_SET`), it increments the result + * by 1 to avoid the reserved value. + */ +static inline void ethtool_stat_add(u64 *stat, u64 value) +{ + *stat += value; + if (*stat == ETHTOOL_STAT_NOT_SET) + (*stat)++; +} + /* Basic IEEE 802.3 MAC statistics (30.3.1.1.*), not otherwise exposed * via a more targeted API. */ From patchwork Tue Dec 3 07:56:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksij Rempel X-Patchwork-Id: 13891832 X-Patchwork-Delegate: kuba@kernel.org Received: from metis.whiteo.stw.pengutronix.de (metis.whiteo.stw.pengutronix.de [185.203.201.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 684E01DD9AD for ; Tue, 3 Dec 2024 07:56:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.201.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733212606; cv=none; b=cfKQqm6aZ4SqLdavjK/lgIncjZhev6BrjR9MTrXAQktvDehMLIl6DzgEA5X/bYmlSn7n/DH9eLLYIvBy+I93J/t4jMRRSSBxhlxJzLQo5/5LqJaJj1e2HDNxC+3VGiotVb2AuipduIfF8jqUczeotpq+WL5tN8krMLPTWKywFG4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733212606; c=relaxed/simple; bh=KvgKfIw/lL22aGiulcuLraD/URWJ60B/wcfyKrnFy2o=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=G8sDPZK+EBvyKfohHg9WAKEympK3m7bo2BhFtwEi4YEWjIsmHYh1HVT/PWYOrw1J/ryTQw2XCgyEtVe8jhov3VPYyW6dMwVd8WiayP/ArC1Izi/8QyPfKU6RpevlAZWN8sYl3sUFirVo/OtdMGfQUiuxKEgECafvkBoq40KugOw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.201.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.whiteo.stw.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1tINlj-000398-Kl; Tue, 03 Dec 2024 08:56:27 +0100 Received: from dude04.red.stw.pengutronix.de ([2a0a:edc0:0:1101:1d::ac]) by drehscheibe.grey.stw.pengutronix.de with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1tINle-001R94-0v; Tue, 03 Dec 2024 08:56:23 +0100 Received: from ore by dude04.red.stw.pengutronix.de with local (Exim 4.96) (envelope-from ) id 1tINle-00AHwd-37; Tue, 03 Dec 2024 08:56:22 +0100 From: Oleksij Rempel To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Heiner Kallweit , Jonathan Corbet Cc: Oleksij Rempel , kernel@pengutronix.de, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Simon Horman , Russell King , Maxime Chevallier , linux-doc@vger.kernel.org Subject: [PATCH net-next v1 6/7] phy: dp83td510: add statistics support Date: Tue, 3 Dec 2024 08:56:20 +0100 Message-Id: <20241203075622.2452169-7-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241203075622.2452169-1-o.rempel@pengutronix.de> References: <20241203075622.2452169-1-o.rempel@pengutronix.de> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Add support for reporting PHY statistics in the DP83TD510 driver. This includes cumulative tracking of transmit/receive packet counts, and error counts. Implemented functions to update and provide statistics via ethtool, with optional polling support enabled through `PHY_POLL_STATS`. Signed-off-by: Oleksij Rempel --- drivers/net/phy/dp83td510.c | 98 ++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/dp83td510.c b/drivers/net/phy/dp83td510.c index 92aa3a2b9744..08d61a6a8c61 100644 --- a/drivers/net/phy/dp83td510.c +++ b/drivers/net/phy/dp83td510.c @@ -34,6 +34,24 @@ #define DP83TD510E_CTRL_HW_RESET BIT(15) #define DP83TD510E_CTRL_SW_RESET BIT(14) +#define DP83TD510E_PKT_STAT_1 0x12b +#define DP83TD510E_TX_PKT_CNT_15_0_MASK GENMASK(15, 0) + +#define DP83TD510E_PKT_STAT_2 0x12c +#define DP83TD510E_TX_PKT_CNT_31_16_MASK GENMASK(15, 0) + +#define DP83TD510E_PKT_STAT_3 0x12d +#define DP83TD510E_TX_ERR_PKT_CNT_MASK GENMASK(15, 0) + +#define DP83TD510E_PKT_STAT_4 0x12e +#define DP83TD510E_RX_PKT_CNT_15_0_MASK GENMASK(15, 0) + +#define DP83TD510E_PKT_STAT_5 0x12f +#define DP83TD510E_RX_PKT_CNT_31_16_MASK GENMASK(15, 0) + +#define DP83TD510E_PKT_STAT_6 0x130 +#define DP83TD510E_RX_ERR_PKT_CNT_MASK GENMASK(15, 0) + #define DP83TD510E_AN_STAT_1 0x60c #define DP83TD510E_MASTER_SLAVE_RESOL_FAIL BIT(15) @@ -58,8 +76,16 @@ static const u16 dp83td510_mse_sqi_map[] = { 0x0000 /* 24dB =< SNR */ }; +struct dp83td510_stats { + u64 tx_pkt_cnt; + u64 tx_err_pkt_cnt; + u64 rx_pkt_cnt; + u64 rx_err_pkt_cnt; +}; + struct dp83td510_priv { bool alcd_test_active; + struct dp83td510_stats stats; }; /* Time Domain Reflectometry (TDR) Functionality of DP83TD510 PHY @@ -177,6 +203,74 @@ struct dp83td510_priv { #define DP83TD510E_ALCD_COMPLETE BIT(15) #define DP83TD510E_ALCD_CABLE_LENGTH GENMASK(10, 0) +/** + * dp83td510_update_stats - Update the PHY statistics for the DP83TD510 PHY. + * @phydev: Pointer to the phy_device structure. + * + * The function reads the PHY statistics registers and updates the statistics + * structure. + * + * Returns: 0 on success or a negative error code on failure. + */ +static int dp83td510_update_stats(struct phy_device *phydev) +{ + struct dp83td510_priv *priv = phydev->priv; + u64 count; + int ret; + + /* DP83TD510E_PKT_STAT_1 to DP83TD510E_PKT_STAT_6 registers are cleared + * after reading them in a sequence. A reading of this register not in + * sequence will prevent them from being cleared. + */ + ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_PKT_STAT_1); + if (ret < 0) + return ret; + count = FIELD_GET(DP83TD510E_TX_PKT_CNT_15_0_MASK, ret); + + ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_PKT_STAT_2); + if (ret < 0) + return ret; + count |= (u64)FIELD_GET(DP83TD510E_TX_PKT_CNT_31_16_MASK, ret) << 16; + ethtool_stat_add(&priv->stats.tx_pkt_cnt, count); + + ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_PKT_STAT_3); + if (ret < 0) + return ret; + count = FIELD_GET(DP83TD510E_TX_ERR_PKT_CNT_MASK, ret); + ethtool_stat_add(&priv->stats.tx_err_pkt_cnt, count); + + ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_PKT_STAT_4); + if (ret < 0) + return ret; + count = FIELD_GET(DP83TD510E_RX_PKT_CNT_15_0_MASK, ret); + + ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_PKT_STAT_5); + if (ret < 0) + return ret; + count |= (u64)FIELD_GET(DP83TD510E_RX_PKT_CNT_31_16_MASK, ret) << 16; + ethtool_stat_add(&priv->stats.rx_pkt_cnt, count); + + ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_PKT_STAT_6); + if (ret < 0) + return ret; + count = FIELD_GET(DP83TD510E_RX_ERR_PKT_CNT_MASK, ret); + ethtool_stat_add(&priv->stats.rx_err_pkt_cnt, count); + + return 0; +} + +static void dp83td510_get_phy_stats(struct phy_device *phydev, + struct ethtool_eth_phy_stats *eth_stats, + struct ethtool_phy_stats *stats) +{ + struct dp83td510_priv *priv = phydev->priv; + + stats->tx_packets = priv->stats.tx_pkt_cnt; + stats->tx_errors = priv->stats.tx_err_pkt_cnt; + stats->rx_packets = priv->stats.rx_pkt_cnt; + stats->rx_errors = priv->stats.rx_err_pkt_cnt; +} + static int dp83td510_config_intr(struct phy_device *phydev) { int ret; @@ -588,7 +682,7 @@ static struct phy_driver dp83td510_driver[] = { PHY_ID_MATCH_MODEL(DP83TD510E_PHY_ID), .name = "TI DP83TD510E", - .flags = PHY_POLL_CABLE_TEST, + .flags = PHY_POLL_CABLE_TEST | PHY_POLL_STATS, .probe = dp83td510_probe, .config_aneg = dp83td510_config_aneg, .read_status = dp83td510_read_status, @@ -599,6 +693,8 @@ static struct phy_driver dp83td510_driver[] = { .get_sqi_max = dp83td510_get_sqi_max, .cable_test_start = dp83td510_cable_test_start, .cable_test_get_status = dp83td510_cable_test_get_status, + .get_phy_stats = dp83td510_get_phy_stats, + .update_stats = dp83td510_update_stats, .suspend = genphy_suspend, .resume = genphy_resume, From patchwork Tue Dec 3 07:56:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksij Rempel X-Patchwork-Id: 13891831 X-Patchwork-Delegate: kuba@kernel.org Received: from metis.whiteo.stw.pengutronix.de (metis.whiteo.stw.pengutronix.de [185.203.201.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A65051DA0F5 for ; Tue, 3 Dec 2024 07:56:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.201.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733212605; cv=none; b=jy92I8zpaFIQRoYiIG36GTguJvCbDo2nI4L5cHdRwVBJBFmv+4HHjUpxAwYhsffSbQAI62DK/zBO3fMRqdwTqCaMm7ykHz48BOVvu90DkrDDsr477BXSoVS/9HMEQgCLPgj8LCJKkD7afw3G3nKM2AaEG8atTpfjTcewrQSMeVY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733212605; c=relaxed/simple; bh=wTzVvBK9ZqqOjjJmDbIv+42orF5YbDmWRRRAy8fF99I=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=FT5wc1SZZiU9xnJuhDaYJ9E1IFXOyekRNDr8KWy3jpwykDVcE2jLp1cigpEvM3sU+nCLQKJeZ7gydmWXIvBevuT616AW/nuBOlP0d8K1IbaAUpmsionLrC923XqVAkUOcSuSVCEhAjgMmucNm2Zmi6MQ9FGw7Pf8Mw+gXUNHZZ4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.201.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.whiteo.stw.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1tINlj-000399-Kl; Tue, 03 Dec 2024 08:56:27 +0100 Received: from dude04.red.stw.pengutronix.de ([2a0a:edc0:0:1101:1d::ac]) by drehscheibe.grey.stw.pengutronix.de with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1tINle-001R96-0t; Tue, 03 Dec 2024 08:56:23 +0100 Received: from ore by dude04.red.stw.pengutronix.de with local (Exim 4.96) (envelope-from ) id 1tINle-00AHwo-3A; Tue, 03 Dec 2024 08:56:22 +0100 From: Oleksij Rempel To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Heiner Kallweit , Jonathan Corbet Cc: Oleksij Rempel , kernel@pengutronix.de, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Simon Horman , Russell King , Maxime Chevallier , linux-doc@vger.kernel.org Subject: [PATCH net-next v1 7/7] phy: dp83tg720: add statistics support Date: Tue, 3 Dec 2024 08:56:21 +0100 Message-Id: <20241203075622.2452169-8-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241203075622.2452169-1-o.rempel@pengutronix.de> References: <20241203075622.2452169-1-o.rempel@pengutronix.de> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Add support for reporting PHY statistics in the DP83TG720 driver. This includes cumulative tracking of link loss events, transmit/receive packet counts, and error counts. Implemented functions to update and provide statistics via ethtool, with optional polling support enabled through `PHY_POLL_STATS`. Signed-off-by: Oleksij Rempel --- drivers/net/phy/dp83tg720.c | 147 +++++++++++++++++++++++++++++++++++- 1 file changed, 146 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/dp83tg720.c b/drivers/net/phy/dp83tg720.c index 0ef4d7dba065..f56659d41b31 100644 --- a/drivers/net/phy/dp83tg720.c +++ b/drivers/net/phy/dp83tg720.c @@ -51,6 +51,9 @@ /* Register 0x0405: Unknown Register */ #define DP83TG720S_UNKNOWN_0405 0x405 +#define DP83TG720S_LINK_QUAL_3 0x547 +#define DP83TG720S_LINK_LOSS_CNT_MASK GENMASK(15, 10) + /* Register 0x0576: TDR Master Link Down Control */ #define DP83TG720S_TDR_MASTER_LINK_DOWN 0x576 @@ -60,6 +63,24 @@ /* In RGMII mode, Enable or disable the internal delay for TXD */ #define DP83TG720S_RGMII_TX_CLK_SEL BIT(0) +#define DP83TG720S_PKT_STAT_1 0x639 +#define DP83TG720S_TX_PKT_CNT_15_0_MASK GENMASK(15, 0) + +#define DP83TG720S_PKT_STAT_2 0x63a +#define DP83TG720S_TX_PKT_CNT_31_16_MASK GENMASK(15, 0) + +#define DP83TG720S_PKT_STAT_3 0x63b +#define DP83TG720S_TX_ERR_PKT_CNT_MASK GENMASK(15, 0) + +#define DP83TG720S_PKT_STAT_4 0x63c +#define DP83TG720S_RX_PKT_CNT_15_0_MASK GENMASK(15, 0) + +#define DP83TG720S_PKT_STAT_5 0x63d +#define DP83TG720S_RX_PKT_CNT_31_16_MASK GENMASK(15, 0) + +#define DP83TG720S_PKT_STAT_6 0x63e +#define DP83TG720S_RX_ERR_PKT_CNT_MASK GENMASK(15, 0) + /* Register 0x083F: Unknown Register */ #define DP83TG720S_UNKNOWN_083F 0x83f @@ -69,6 +90,102 @@ #define DP83TG720_SQI_MAX 7 +struct dp83tg720_stats { + u64 link_loss_cnt; + u64 tx_pkt_cnt; + u64 tx_err_pkt_cnt; + u64 rx_pkt_cnt; + u64 rx_err_pkt_cnt; +}; + +struct dp83tg720_priv { + struct dp83tg720_stats stats; +}; + +/** + * dp83tg720_update_stats - Update the PHY statistics for the DP83TD510 PHY. + * @phydev: Pointer to the phy_device structure. + * + * The function reads the PHY statistics registers and updates the statistics + * structure. + * + * Returns: 0 on success or a negative error code on failure. + */ +static int dp83tg720_update_stats(struct phy_device *phydev) +{ + struct dp83tg720_priv *priv = phydev->priv; + u64 count; + int ret; + + /* Read the link loss count */ + ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_LINK_QUAL_3); + if (ret < 0) + return ret; + count = FIELD_GET(DP83TG720S_LINK_LOSS_CNT_MASK, ret); + ethtool_stat_add(&priv->stats.link_loss_cnt, count); + + /* Read frame statistics */ + /* DP83TG720S_PKT_STAT_1 to DP83TG720S_PKT_STAT_6 registers are cleared + * after reading them in a sequence. A reading of this register not in + * sequence will prevent them from being cleared. + */ + ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_PKT_STAT_1); + if (ret < 0) + return ret; + count = FIELD_GET(DP83TG720S_TX_PKT_CNT_15_0_MASK, ret); + + ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_PKT_STAT_2); + if (ret < 0) + return ret; + count |= (u64)FIELD_GET(DP83TG720S_TX_PKT_CNT_31_16_MASK, ret) << 16; + ethtool_stat_add(&priv->stats.tx_pkt_cnt, count); + + ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_PKT_STAT_3); + if (ret < 0) + return ret; + count = FIELD_GET(DP83TG720S_TX_ERR_PKT_CNT_MASK, ret); + ethtool_stat_add(&priv->stats.tx_err_pkt_cnt, count); + + ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_PKT_STAT_4); + if (ret < 0) + return ret; + count = FIELD_GET(DP83TG720S_RX_PKT_CNT_15_0_MASK, ret); + + ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_PKT_STAT_5); + if (ret < 0) + return ret; + count |= (u64)FIELD_GET(DP83TG720S_RX_PKT_CNT_31_16_MASK, ret) << 16; + ethtool_stat_add(&priv->stats.rx_pkt_cnt, count); + + ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_PKT_STAT_6); + if (ret < 0) + return ret; + count = FIELD_GET(DP83TG720S_RX_ERR_PKT_CNT_MASK, ret); + ethtool_stat_add(&priv->stats.rx_err_pkt_cnt, count); + + return 0; +} + +static void dp83tg720_get_link_stats(struct phy_device *phydev, + struct ethtool_link_ext_stats *link_stats) +{ + struct dp83tg720_priv *priv = phydev->priv; + + link_stats->link_down_events = priv->stats.link_loss_cnt; +} + +static void dp83tg720_get_phy_stats(struct phy_device *phydev, + struct ethtool_eth_phy_stats *eth_stats, + struct ethtool_phy_stats *stats) +{ + struct dp83tg720_priv *priv = phydev->priv; + + stats->tx_packets = priv->stats.tx_pkt_cnt; + stats->tx_errors = priv->stats.tx_err_pkt_cnt; + stats->rx_packets = priv->stats.rx_pkt_cnt; + stats->rx_errors = priv->stats.rx_err_pkt_cnt; +} + /** * dp83tg720_cable_test_start - Start the cable test for the DP83TG720 PHY. * @phydev: Pointer to the phy_device structure. @@ -182,6 +299,11 @@ static int dp83tg720_cable_test_get_status(struct phy_device *phydev, ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, stat); + /* save the current stats before resetting the PHY */ + ret = dp83tg720_update_stats(phydev); + if (ret) + return ret; + return phy_init_hw(phydev); } @@ -217,6 +339,11 @@ static int dp83tg720_read_status(struct phy_device *phydev) phy_sts = phy_read(phydev, DP83TG720S_MII_REG_10); phydev->link = !!(phy_sts & DP83TG720S_LINK_STATUS); if (!phydev->link) { + /* save the current stats before resetting the PHY */ + ret = dp83tg720_update_stats(phydev); + if (ret) + return ret; + /* According to the "DP83TC81x, DP83TG72x Software * Implementation Guide", the PHY needs to be reset after a * link loss or if no link is created after at least 100ms. @@ -341,12 +468,27 @@ static int dp83tg720_config_init(struct phy_device *phydev) return genphy_c45_pma_baset1_read_master_slave(phydev); } +static int dp83tg720_probe(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + struct dp83tg720_priv *priv; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + phydev->priv = priv; + + return 0; +} + static struct phy_driver dp83tg720_driver[] = { { PHY_ID_MATCH_MODEL(DP83TG720S_PHY_ID), .name = "TI DP83TG720S", - .flags = PHY_POLL_CABLE_TEST, + .flags = PHY_POLL_CABLE_TEST | PHY_POLL_STATS, + .probe = dp83tg720_probe, .config_aneg = dp83tg720_config_aneg, .read_status = dp83tg720_read_status, .get_features = genphy_c45_pma_read_ext_abilities, @@ -355,6 +497,9 @@ static struct phy_driver dp83tg720_driver[] = { .get_sqi_max = dp83tg720_get_sqi_max, .cable_test_start = dp83tg720_cable_test_start, .cable_test_get_status = dp83tg720_cable_test_get_status, + .get_link_stats = dp83tg720_get_link_stats, + .get_phy_stats = dp83tg720_get_phy_stats, + .update_stats = dp83tg720_update_stats, .suspend = genphy_suspend, .resume = genphy_resume,