From patchwork Fri Dec 1 16:36:51 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Chevallier X-Patchwork-Id: 13476143 X-Patchwork-Delegate: kuba@kernel.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="cL5SrG93" Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 058D112A; Fri, 1 Dec 2023 08:37:10 -0800 (PST) Received: by mail.gandi.net (Postfix) with ESMTPSA id 7C050C000A; Fri, 1 Dec 2023 16:37:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1701448629; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=bInECG3ekdSZHD0C1gyU0O7zrvVagdDlEMEJ8pz0EWc=; b=cL5SrG93zvdWqzqFGJfxyr6uWKHUTgUP1oeQsNwFF1X3NR3rFVg1nVQQoIlA6B+yt8RROI sbzw5wzuZyiYwF2tL0DHhYSoVUF8tGuinni75YSH09C4YYvMg7mNYRG/NC1MfrkpD1Dlq7 9jZnK0Zu0sf9/JNvHg3FZLHcdaXpuHCVFlUUDTbaRryS8DZp8u0tsoFCZJ/NEFHEMG/Bly bRc8ZNrIVOPQjqNgmhO6Oyz+CQWDfgYGxtSdxfWjuMITsQnc4aSHrFQMmtZXEgaKxxPeFt kGhKvTy8YdsnubcsHxGpSuUAW2tB2SPs7WUV5PZz5xtQkFZS3/MNx4IfKy1HSw== From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Russell King , linux-arm-kernel@lists.infradead.org, Christophe Leroy , Herve Codina , Florian Fainelli , Heiner Kallweit , Vladimir Oltean , =?utf-8?q?K=C3=B6ry_Maincent?= , Jesse Brandeburg , Jonathan Corbet , =?utf-8?q?Marek_Beh=C3=BAn?= , Piergiorgio Beruto , Oleksij Rempel , =?utf-8?q?Nicol=C3=B2_Veronese?= Subject: [RFC PATCH net-next v3 01/13] net: phy: Introduce ethernet link topology representation Date: Fri, 1 Dec 2023 17:36:51 +0100 Message-ID: <20231201163704.1306431-2-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> References: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: maxime.chevallier@bootlin.com X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Link topologies containing multiple network PHYs attached to the same net_device can be found when using a PHY as a media converter for use with an SFP connector, on which an SFP transceiver containing a PHY can be used. With the current model, the transceiver's PHY can't be used for operations such as cable testing, timestamping, macsec offload, etc. The reason being that most of the logic for these configuration, coming from either ethtool netlink or ioctls tend to use netdev->phydev, which in multi-phy systems will reference the PHY closest to the MAC. Introduce a numbering scheme allowing to enumerate PHY devices that belong to any netdev, which can in turn allow userspace to take more precise decisions with regard to each PHY's configuration. The numbering is maintained per-netdev, in a phy_device_list. The numbering works similarly to a netdevice's ifindex, with identifiers that are only recycled once INT_MAX has been reached. This prevents races that could occur between PHY listing and SFP transceiver removal/insertion. The identifiers are assigned at phy_attach time, as the numbering depends on the netdevice the phy is attached to. Signed-off-by: Maxime Chevallier --- V3: - Renamed to phy_link_topology - Added assertions for RTNL - Various cleanups of leftover, unused test code - Made the PHY index u32 MAINTAINERS | 2 + drivers/net/phy/Makefile | 2 +- drivers/net/phy/phy_device.c | 15 +++++ drivers/net/phy/phy_link_topology.c | 85 ++++++++++++++++++++++++++ include/linux/netdevice.h | 4 +- include/linux/phy.h | 4 ++ include/linux/phy_link_topology.h | 64 +++++++++++++++++++ include/linux/phy_link_topology_core.h | 15 +++++ include/uapi/linux/ethtool.h | 16 +++++ net/core/dev.c | 3 + 10 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 drivers/net/phy/phy_link_topology.c create mode 100644 include/linux/phy_link_topology.h create mode 100644 include/linux/phy_link_topology_core.h diff --git a/MAINTAINERS b/MAINTAINERS index 509281e9e169..54d50510c299 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7922,6 +7922,8 @@ F: include/linux/mii.h F: include/linux/of_net.h F: include/linux/phy.h F: include/linux/phy_fixed.h +F: include/linux/phy_link_topology.h +F: include/linux/phy_link_topology_core.h F: include/linux/phylib_stubs.h F: include/linux/platform_data/mdio-bcm-unimac.h F: include/linux/platform_data/mdio-gpio.h diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index f65e85c91fc1..3cf7774df57e 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -2,7 +2,7 @@ # Makefile for Linux PHY drivers libphy-y := phy.o phy-c45.o phy-core.o phy_device.o \ - linkmode.o + linkmode.o phy_link_topology.o mdio-bus-y += mdio_bus.o mdio_device.o ifdef CONFIG_MDIO_DEVICE diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 478126f6b5bc..b921a091d636 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -265,6 +266,14 @@ static void phy_mdio_device_remove(struct mdio_device *mdiodev) static struct phy_driver genphy_driver; +static struct phy_link_topology *phy_get_link_topology(struct phy_device *phydev) +{ + if (phydev->attached_dev) + return &phydev->attached_dev->link_topo; + + return NULL; +} + static LIST_HEAD(phy_fixup_list); static DEFINE_MUTEX(phy_fixup_lock); @@ -1488,6 +1497,11 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, if (phydev->sfp_bus_attached) dev->sfp_bus = phydev->sfp_bus; + + err = phy_link_topo_add_phy(&dev->link_topo, phydev, + PHY_UPSTREAM_MAC, dev); + if (err) + goto error; } /* Some Ethernet drivers try to connect to a PHY device before @@ -1813,6 +1827,7 @@ void phy_detach(struct phy_device *phydev) if (dev) { phydev->attached_dev->phydev = NULL; phydev->attached_dev = NULL; + phy_link_topo_del_phy(&dev->link_topo, phydev); } phydev->phylink = NULL; diff --git a/drivers/net/phy/phy_link_topology.c b/drivers/net/phy/phy_link_topology.c new file mode 100644 index 000000000000..4bb8b1eb7df6 --- /dev/null +++ b/drivers/net/phy/phy_link_topology.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Infrastructure to handle all PHY devices connected to a given netdev, + * either directly or indirectly attached. + * + * Copyright (c) 2023 Maxime Chevallier + */ + +#include +#include +#include +#include +#include + +struct phy_device *phy_link_topo_get_phy(struct phy_link_topology *topo, + u32 phyindex) +{ + struct phy_device_node *pdn = xa_load(&topo->phys, phyindex); + + if (pdn) + return pdn->phy; + + return NULL; +} +EXPORT_SYMBOL_GPL(phy_link_topo_get_phy); + +int phy_link_topo_add_phy(struct phy_link_topology *topo, + struct phy_device *phy, + enum phy_upstream upt, void *upstream) +{ + struct phy_device_node *pdn; + int ret; + + /* Protects phy and upstream */ + ASSERT_RTNL(); + + pdn = kzalloc(sizeof(*pdn), GFP_KERNEL); + if (!pdn) + return -ENOMEM; + + pdn->phy = phy; + switch (upt) { + case PHY_UPSTREAM_MAC: + pdn->upstream.netdev = (struct net_device *)upstream; + if (phy_on_sfp(phy)) + pdn->parent_sfp_bus = pdn->upstream.netdev->sfp_bus; + break; + case PHY_UPSTREAM_PHY: + pdn->upstream.phydev = (struct phy_device *)upstream; + if (phy_on_sfp(phy)) + pdn->parent_sfp_bus = pdn->upstream.phydev->sfp_bus; + break; + default: + ret = -EINVAL; + goto err; + } + pdn->upstream_type = upt; + + ret = xa_alloc_cyclic(&topo->phys, &phy->phyindex, pdn, xa_limit_32b, + &topo->next_phy_index, GFP_KERNEL); + if (ret) + goto err; + + return 0; + +err: + kfree(pdn); + return ret; +} +EXPORT_SYMBOL_GPL(phy_link_topo_add_phy); + +void phy_link_topo_del_phy(struct phy_link_topology *topo, + struct phy_device *phy) +{ + struct phy_device_node *pdn = xa_erase(&topo->phys, phy->phyindex); + + kfree(pdn); +} +EXPORT_SYMBOL_GPL(phy_link_topo_del_phy); + +void phy_link_topo_init(struct phy_link_topology *topo) +{ + xa_init_flags(&topo->phys, XA_FLAGS_ALLOC1); + topo->next_phy_index = 1; +} diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index e87caa81f70c..6ebb37375d39 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -40,7 +40,6 @@ #include #endif #include - #include #include #include @@ -52,6 +51,7 @@ #include #include #include +#include struct netpoll_info; struct device; @@ -2035,6 +2035,7 @@ enum netdev_stat_type { * @fcoe_ddp_xid: Max exchange id for FCoE LRO by ddp * * @priomap: XXX: need comments on this one + * @link_topo: Physical link topology tracking attached PHYs * @phydev: Physical device may attach itself * for hardware timestamping * @sfp_bus: attached &struct sfp_bus structure. @@ -2417,6 +2418,7 @@ struct net_device { #if IS_ENABLED(CONFIG_CGROUP_NET_PRIO) struct netprio_map __rcu *priomap; #endif + struct phy_link_topology link_topo; struct phy_device *phydev; struct sfp_bus *sfp_bus; struct lock_class_key *qdisc_tx_busylock; diff --git a/include/linux/phy.h b/include/linux/phy.h index e5f1f41e399c..4cee9c05183f 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -543,6 +543,9 @@ struct macsec_ops; * @drv: Pointer to the driver for this PHY instance * @devlink: Create a link between phy dev and mac dev, if the external phy * used by current mac interface is managed by another mac interface. + * @phyindex: Unique id across the phy's parent tree of phys to address the PHY + * from userspace, similar to ifindex. A zero index means the PHY + * wasn't assigned an id yet. * @phy_id: UID for this device found during discovery * @c45_ids: 802.3-c45 Device Identifiers if is_c45. * @is_c45: Set to true if this PHY uses clause 45 addressing. @@ -640,6 +643,7 @@ struct phy_device { struct device_link *devlink; + u32 phyindex; u32 phy_id; struct phy_c45_device_ids c45_ids; diff --git a/include/linux/phy_link_topology.h b/include/linux/phy_link_topology.h new file mode 100644 index 000000000000..44013a3cff50 --- /dev/null +++ b/include/linux/phy_link_topology.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * PHY device list allow maintaining a list of PHY devices that are + * part of a netdevice's link topology. PHYs can for example be chained, + * as is the case when using a PHY that exposes an SFP module, on which an + * SFP transceiver that embeds a PHY is connected. + * + * This list can then be used by userspace to leverage individual PHY + * capabilities. + */ +#ifndef __PHY_LINK_TOPOLOGY_H +#define __PHY_LINK_TOPOLOGY_H + +#include +#include + +struct xarray; +struct phy_device; +struct net_device; +struct sfp_bus; + +struct phy_device_node { + enum phy_upstream upstream_type; + + union { + struct net_device *netdev; + struct phy_device *phydev; + } upstream; + + struct sfp_bus *parent_sfp_bus; + + struct phy_device *phy; +}; + +#if IS_ENABLED(CONFIG_PHYLIB) +struct phy_device *phy_link_topo_get_phy(struct phy_link_topology *topo, + u32 phyindex); +int phy_link_topo_add_phy(struct phy_link_topology *topo, + struct phy_device *phy, + enum phy_upstream upt, void *upstream); + +void phy_link_topo_del_phy(struct phy_link_topology *lt, struct phy_device *phy); + +#else +static struct phy_device *phy_link_topo_get_phy(struct phy_link_topology *topo, + u32 phyindex) +{ + return NULL; +} + +static int phy_link_topo_add_phy(struct phy_link_topology *topo, + struct phy_device *phy, + enum phy_upstream upt, void *upstream) +{ + return 0; +} + +static void phy_link_topo_del_phy(struct phy_link_topology *topo, + struct phy_device *phy) +{ +} +#endif + +#endif /* __PHY_LINK_TOPOLOGY_H */ diff --git a/include/linux/phy_link_topology_core.h b/include/linux/phy_link_topology_core.h new file mode 100644 index 000000000000..7aee9718d305 --- /dev/null +++ b/include/linux/phy_link_topology_core.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __PHY_LINK_TOPOLOGY_CORE_H +#define __PHY_LINK_TOPOLOGY_CORE_H + +struct xarray; + +struct phy_link_topology { + struct xarray phys; + + u32 next_phy_index; +}; + +void phy_link_topo_init(struct phy_link_topology *topo); + +#endif /* __PHY_LINK_TOPOLOGY_CORE_H */ diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index f7fba0dc87e5..f3a8b582b8d4 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -2205,4 +2205,20 @@ struct ethtool_link_settings { * __u32 map_lp_advertising[link_mode_masks_nwords]; */ }; + +/** + * enum phy_upstream - Represents the upstream component a given PHY device + * is connected to, as in what is on the other end of the MII bus. Most PHYs + * will be attached to an Ethernet MAC controller, but in some cases, there's + * an intermediate PHY used as a media-converter, which will driver another + * MII interface as its output. + * @PHY_UPSTREAM_MAC: Upstream component is a MAC (a switch port, + * or ethernet controller) + * @PHY_UPSTREAM_PHY: Upstream component is a PHY (likely a media converter) + */ +enum phy_upstream { + PHY_UPSTREAM_MAC, + PHY_UPSTREAM_PHY, +}; + #endif /* _UAPI_LINUX_ETHTOOL_H */ diff --git a/net/core/dev.c b/net/core/dev.c index 3950ced396b5..64b0fda64033 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -153,6 +153,7 @@ #include #include #include +#include #include "dev.h" #include "net-sysfs.h" @@ -10832,6 +10833,8 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, #ifdef CONFIG_NET_SCHED hash_init(dev->qdisc_hash); #endif + phy_link_topo_init(&dev->link_topo); + dev->priv_flags = IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM; setup(dev); From patchwork Fri Dec 1 16:36:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Chevallier X-Patchwork-Id: 13476144 X-Patchwork-Delegate: kuba@kernel.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="ga6NHPE1" Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::226]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 60924FF; Fri, 1 Dec 2023 08:37:12 -0800 (PST) Received: by mail.gandi.net (Postfix) with ESMTPSA id B5BF8C0002; Fri, 1 Dec 2023 16:37:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1701448630; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=lHDZfNw32Cu/7HGNJf2PAJcLVsMIJGgKgWqUxlmjNrE=; b=ga6NHPE151pjq/wQ80fA0OzrdmfwqdFlY10KdQw3Rsh1ijfwTHC6AhuLAqyJq9iXLFbYki P79rhs6HJ3NqqK67JcivWjQV0CNaMYOQ4eTboU8UY8dR0t8kwevdC8EnyjG5qZSQ11alcJ 1mOwTdP5puRKSObiE/VAhqumPSgJy5TEwigCDkfhVpqOuX+dx3ec6mc34wszrVJQuu7I1o j6t4tF58OuaXxqYy1ZqwZKmtEqwnk8yTEKanVpOfGCMX+NQaCOxABXCiAMxN0EeBzVE8gL Unh9Ss6+WNnJ7fqxKs/4QCFHNi5MS8mkkyn03Nt/QBIn7P5euNYl8NPeYAxCcQ== From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Russell King , linux-arm-kernel@lists.infradead.org, Christophe Leroy , Herve Codina , Florian Fainelli , Heiner Kallweit , Vladimir Oltean , =?utf-8?q?K=C3=B6ry_Maincent?= , Jesse Brandeburg , Jonathan Corbet , =?utf-8?q?Marek_Beh=C3=BAn?= , Piergiorgio Beruto , Oleksij Rempel , =?utf-8?q?Nicol=C3=B2_Veronese?= Subject: [RFC PATCH net-next v3 02/13] net: sfp: pass the phy_device when disconnecting an sfp module's PHY Date: Fri, 1 Dec 2023 17:36:52 +0100 Message-ID: <20231201163704.1306431-3-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> References: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: maxime.chevallier@bootlin.com X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Pass the phy_device as a parameter to the sfp upstream .disconnect_phy operation. This is preparatory work to help track phy devices across a net_device's link. Signed-off-by: Maxime Chevallier --- V3: No changes drivers/net/phy/phylink.c | 3 ++- drivers/net/phy/sfp-bus.c | 4 ++-- include/linux/sfp.h | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index c276f9482f78..788785335fca 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -3309,7 +3309,8 @@ static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy) return ret; } -static void phylink_sfp_disconnect_phy(void *upstream) +static void phylink_sfp_disconnect_phy(void *upstream, + struct phy_device *phydev) { phylink_disconnect_phy(upstream); } diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c index 6fa679b36290..3a86c41e1235 100644 --- a/drivers/net/phy/sfp-bus.c +++ b/drivers/net/phy/sfp-bus.c @@ -486,7 +486,7 @@ static void sfp_unregister_bus(struct sfp_bus *bus) bus->socket_ops->stop(bus->sfp); bus->socket_ops->detach(bus->sfp); if (bus->phydev && ops && ops->disconnect_phy) - ops->disconnect_phy(bus->upstream); + ops->disconnect_phy(bus->upstream, bus->phydev); } bus->registered = false; } @@ -742,7 +742,7 @@ void sfp_remove_phy(struct sfp_bus *bus) const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus); if (ops && ops->disconnect_phy) - ops->disconnect_phy(bus->upstream); + ops->disconnect_phy(bus->upstream, bus->phydev); bus->phydev = NULL; } EXPORT_SYMBOL_GPL(sfp_remove_phy); diff --git a/include/linux/sfp.h b/include/linux/sfp.h index 9346cd44814d..0573e53b0c11 100644 --- a/include/linux/sfp.h +++ b/include/linux/sfp.h @@ -544,7 +544,7 @@ struct sfp_upstream_ops { void (*link_down)(void *priv); void (*link_up)(void *priv); int (*connect_phy)(void *priv, struct phy_device *); - void (*disconnect_phy)(void *priv); + void (*disconnect_phy)(void *priv, struct phy_device *); }; #if IS_ENABLED(CONFIG_SFP) From patchwork Fri Dec 1 16:36:53 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Chevallier X-Patchwork-Id: 13476145 X-Patchwork-Delegate: kuba@kernel.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="ddV9Snkb" Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 74A3CA6; Fri, 1 Dec 2023 08:37:13 -0800 (PST) Received: by mail.gandi.net (Postfix) with ESMTPSA id 02050C0008; Fri, 1 Dec 2023 16:37:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1701448632; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=sXpDXkkD3ikt6WqoaDXyXCU8qzMrGQc4F7n0ARxk3O4=; b=ddV9Snkbf0tVTSbersPvQxpgDW4UOqQBtjgAvBLy177yRPcoMxFw4wnsKegP34Vx+EhueY 6jaOBKH/MLbetYTTrGCDbKRC+kbyN+YLVmxtuWkwqq6ctI5d72RryLezoMukOS4Nr84ByI BUB0xEL2kAkoNf2dziyx4g5em7ERU6WXU4XNh+in8nJ6/bdNAtTOsNDiyKcHkfYwxaUt0P qiVjycowzWaU+/GNUyUY6OepOTbDKtQpfDFynOGhWCvDsladZcifBRc8yNYmVLyBRdy2HO UpASRyJcGxnzwSGn2BbQ+TT2EEcqHl1JJSY39ymk8XXXaL19B6gRD2MuwHhq/g== From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Russell King , linux-arm-kernel@lists.infradead.org, Christophe Leroy , Herve Codina , Florian Fainelli , Heiner Kallweit , Vladimir Oltean , =?utf-8?q?K=C3=B6ry_Maincent?= , Jesse Brandeburg , Jonathan Corbet , =?utf-8?q?Marek_Beh=C3=BAn?= , Piergiorgio Beruto , Oleksij Rempel , =?utf-8?q?Nicol=C3=B2_Veronese?= Subject: [RFC PATCH net-next v3 03/13] net: phy: add helpers to handle sfp phy connect/disconnect Date: Fri, 1 Dec 2023 17:36:53 +0100 Message-ID: <20231201163704.1306431-4-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> References: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: maxime.chevallier@bootlin.com X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC There are a few PHY drivers that can handle SFP modules through their sfp_upstream_ops. Introduce Phylib helpers to keep track of connected SFP PHYs in a netdevice's namespace, by adding the SFP PHY to the upstream PHY's netdev's namespace. By doing so, these SFP PHYs can be enumerated and exposed to users, which will be able to use their capabilities. Signed-off-by: Maxime Chevallier --- V3: Renaming V2: Renaming drivers/net/phy/at803x.c | 2 ++ drivers/net/phy/marvell-88x2222.c | 2 ++ drivers/net/phy/marvell.c | 2 ++ drivers/net/phy/marvell10g.c | 2 ++ drivers/net/phy/phy_device.c | 40 +++++++++++++++++++++++++++++++ include/linux/phy.h | 2 ++ 6 files changed, 50 insertions(+) diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index 37fb033e1c29..9b1659b03aa5 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -730,6 +730,8 @@ static const struct sfp_upstream_ops at803x_sfp_ops = { .attach = phy_sfp_attach, .detach = phy_sfp_detach, .module_insert = at803x_sfp_insert, + .connect_phy = phy_sfp_connect_phy, + .disconnect_phy = phy_sfp_disconnect_phy, }; static int at803x_parse_dt(struct phy_device *phydev) diff --git a/drivers/net/phy/marvell-88x2222.c b/drivers/net/phy/marvell-88x2222.c index e3aa30dad2e6..3f77bbc7e04f 100644 --- a/drivers/net/phy/marvell-88x2222.c +++ b/drivers/net/phy/marvell-88x2222.c @@ -555,6 +555,8 @@ static const struct sfp_upstream_ops sfp_phy_ops = { .link_down = mv2222_sfp_link_down, .attach = phy_sfp_attach, .detach = phy_sfp_detach, + .connect_phy = phy_sfp_connect_phy, + .disconnect_phy = phy_sfp_disconnect_phy, }; static int mv2222_probe(struct phy_device *phydev) diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index eba652a4c1d8..674e29bce2cc 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -3254,6 +3254,8 @@ static const struct sfp_upstream_ops m88e1510_sfp_ops = { .module_remove = m88e1510_sfp_remove, .attach = phy_sfp_attach, .detach = phy_sfp_detach, + .connect_phy = phy_sfp_connect_phy, + .disconnect_phy = phy_sfp_disconnect_phy, }; static int m88e1510_probe(struct phy_device *phydev) diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index d4bb90d76881..a88ebc0a6be5 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -496,6 +496,8 @@ static int mv3310_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) static const struct sfp_upstream_ops mv3310_sfp_ops = { .attach = phy_sfp_attach, .detach = phy_sfp_detach, + .connect_phy = phy_sfp_connect_phy, + .disconnect_phy = phy_sfp_disconnect_phy, .module_insert = mv3310_sfp_insert, }; diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index b921a091d636..675b9afdc66c 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1360,6 +1360,46 @@ phy_standalone_show(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RO(phy_standalone); +/** + * phy_sfp_connect_phy - Connect the SFP module's PHY to the upstream PHY + * @upstream: pointer to the upstream phy device + * @phy: pointer to the SFP module's phy device + * + * This helper allows keeping track of PHY devices on the link. It adds the + * SFP module's phy to the phy namespace of the upstream phy + */ +int phy_sfp_connect_phy(void *upstream, struct phy_device *phy) +{ + struct phy_device *phydev = upstream; + struct phy_link_topology *topo = phy_get_link_topology(phydev); + + if (topo) + return phy_link_topo_add_phy(topo, phy, PHY_UPSTREAM_PHY, phydev); + + return 0; +} +EXPORT_SYMBOL(phy_sfp_connect_phy); + +/** + * phy_sfp_disconnect_phy - Disconnect the SFP module's PHY from the upstream PHY + * @upstream: pointer to the upstream phy device + * @phy: pointer to the SFP module's phy device + * + * This helper allows keeping track of PHY devices on the link. It removes the + * SFP module's phy to the phy namespace of the upstream phy. As the module phy + * will be destroyed, re-inserting the same module will add a new phy with a + * new index. + */ +void phy_sfp_disconnect_phy(void *upstream, struct phy_device *phy) +{ + struct phy_device *phydev = upstream; + struct phy_link_topology *topo = phy_get_link_topology(phydev); + + if (topo) + phy_link_topo_del_phy(topo, phy); +} +EXPORT_SYMBOL(phy_sfp_disconnect_phy); + /** * phy_sfp_attach - attach the SFP bus to the PHY upstream network device * @upstream: pointer to the phy device diff --git a/include/linux/phy.h b/include/linux/phy.h index 4cee9c05183f..d1fe51e8ba93 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1722,6 +1722,8 @@ int phy_suspend(struct phy_device *phydev); int phy_resume(struct phy_device *phydev); int __phy_resume(struct phy_device *phydev); int phy_loopback(struct phy_device *phydev, bool enable); +int phy_sfp_connect_phy(void *upstream, struct phy_device *phy); +void phy_sfp_disconnect_phy(void *upstream, struct phy_device *phy); void phy_sfp_attach(void *upstream, struct sfp_bus *bus); void phy_sfp_detach(void *upstream, struct sfp_bus *bus); int phy_sfp_probe(struct phy_device *phydev, From patchwork Fri Dec 1 16:36:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Chevallier X-Patchwork-Id: 13476146 X-Patchwork-Delegate: kuba@kernel.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="LSXijdMo" Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3999EDD; Fri, 1 Dec 2023 08:37:15 -0800 (PST) Received: by mail.gandi.net (Postfix) with ESMTPSA id 4067FC000B; Fri, 1 Dec 2023 16:37:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1701448634; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/UJgbGqCn4KZ8wgN6ydYKFmmc8NcXDI2Sqt+FJcDgT4=; b=LSXijdMo86F0stdaNqeqqp6yLoIB8nLvjr9ivnTXr0FSEQW2siVYiwb489yXvByvKj+P7X fA1qjbluaAS1Q0aAJCZKsUuMW9cpLne5hIrVCT9Nvp3X4zwp80n/t0G5mSfWfOOoJbKPO2 Qz5WPtXxc9Q+OWyb2YXKNPY2rP7V6MgAnQszNazXYWIDuQ5lq21L2AJzUiKrpucgJ+xBRz XObRKwYhXS52P2MhIWZFjUVJBeRw+r7PHcGpZ15+gcCxrzzk/zuFUB1zsPZVdwBIq1tU5R R0jbni+eCAAb333yyIoXCxIvp3E1KWL8Ki0IUwN7DhabTvnMdxBbPYFSZlZVnw== From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Russell King , linux-arm-kernel@lists.infradead.org, Christophe Leroy , Herve Codina , Florian Fainelli , Heiner Kallweit , Vladimir Oltean , =?utf-8?q?K=C3=B6ry_Maincent?= , Jesse Brandeburg , Jonathan Corbet , =?utf-8?q?Marek_Beh=C3=BAn?= , Piergiorgio Beruto , Oleksij Rempel , =?utf-8?q?Nicol=C3=B2_Veronese?= Subject: [RFC PATCH net-next v3 04/13] net: sfp: Add helper to return the SFP bus name Date: Fri, 1 Dec 2023 17:36:54 +0100 Message-ID: <20231201163704.1306431-5-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> References: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: maxime.chevallier@bootlin.com X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Knowing the bus name is helpful when we want to expose the link topology to userspace, add a helper to return the SFP bus name. Signed-off-by: Maxime Chevallier --- V3: - Added RTNL assert - Made the stub inline V2: New patch drivers/net/phy/sfp-bus.c | 11 +++++++++++ include/linux/sfp.h | 6 ++++++ 2 files changed, 17 insertions(+) diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c index 3a86c41e1235..fb1c102714b5 100644 --- a/drivers/net/phy/sfp-bus.c +++ b/drivers/net/phy/sfp-bus.c @@ -859,3 +859,14 @@ void sfp_unregister_socket(struct sfp_bus *bus) sfp_bus_put(bus); } EXPORT_SYMBOL_GPL(sfp_unregister_socket); + +const char *sfp_get_name(struct sfp_bus *bus) +{ + ASSERT_RTNL(); + + if (bus->sfp_dev) + return dev_name(bus->sfp_dev); + + return NULL; +} +EXPORT_SYMBOL_GPL(sfp_get_name); diff --git a/include/linux/sfp.h b/include/linux/sfp.h index 0573e53b0c11..55c0ab17c9e2 100644 --- a/include/linux/sfp.h +++ b/include/linux/sfp.h @@ -570,6 +570,7 @@ struct sfp_bus *sfp_bus_find_fwnode(const struct fwnode_handle *fwnode); int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream, const struct sfp_upstream_ops *ops); void sfp_bus_del_upstream(struct sfp_bus *bus); +const char *sfp_get_name(struct sfp_bus *bus); #else static inline int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id, @@ -648,6 +649,11 @@ static inline int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream, static inline void sfp_bus_del_upstream(struct sfp_bus *bus) { } + +static inline const char *sfp_get_name(struct sfp_bus *bus) +{ + return NULL; +} #endif #endif From patchwork Fri Dec 1 16:36:55 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Chevallier X-Patchwork-Id: 13476147 X-Patchwork-Delegate: kuba@kernel.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="N1L9mi8t" Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::226]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9E2A2F1; Fri, 1 Dec 2023 08:37:16 -0800 (PST) Received: by mail.gandi.net (Postfix) with ESMTPSA id 22231C000C; Fri, 1 Dec 2023 16:37:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1701448635; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=rICygNfVggVNd10TEZiZNclHAZ+8n31mfU867S2s8jU=; b=N1L9mi8tqG+qrdeByZJ95b/cMJykUodLSVJfkLmIYa2BtO8MUy1MVmU070i+dkyXwFNzQx eLRFSfmGLW4WbZN9BV1j4dy7+HJBVvCOUN2TBZOaJlZfkM2zDf1ZgC/xiSI6SwFwupbHfZ TwcNTSuCHWfEnCuRCWJKgDU5LD8or9Fy0tzMqHmRBQKhnIclLvQE33vxEpb9pm9FHQSyRD NLcXdIvf9qSLxgn1v3gguCfmcS2X6PALU2rlBSPRbcaeyz4tAPvw/SeYFIIObx5QX3sfDs loxTNaJneEPYlzc/wK+FFD4Yusx8KZ8ALI8fBjyuQ+y5aS+g50gGy88OAIkFKA== From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Russell King , linux-arm-kernel@lists.infradead.org, Christophe Leroy , Herve Codina , Florian Fainelli , Heiner Kallweit , Vladimir Oltean , =?utf-8?q?K=C3=B6ry_Maincent?= , Jesse Brandeburg , Jonathan Corbet , =?utf-8?q?Marek_Beh=C3=BAn?= , Piergiorgio Beruto , Oleksij Rempel , =?utf-8?q?Nicol=C3=B2_Veronese?= Subject: [RFC PATCH net-next v3 05/13] net: ethtool: Allow passing a phy index for some commands Date: Fri, 1 Dec 2023 17:36:55 +0100 Message-ID: <20231201163704.1306431-6-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> References: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: maxime.chevallier@bootlin.com X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Some netlink commands are target towards ethernet PHYs, to control some of their features. As there's several such commands, add the ability to pass a PHY index in the ethnl request, which will populate the generic ethnl_req_info with the relevant phydev when the command targets a PHY. Signed-off-by: Maxime Chevallier --- V3: - Fixed the documentation V2: - New patch Documentation/networking/ethtool-netlink.rst | 7 ++++++ include/uapi/linux/ethtool_netlink.h | 1 + net/ethtool/netlink.c | 24 ++++++++++++++++++++ net/ethtool/netlink.h | 7 ++++-- 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst index 2540c70952ff..8f6390a85895 100644 --- a/Documentation/networking/ethtool-netlink.rst +++ b/Documentation/networking/ethtool-netlink.rst @@ -57,6 +57,7 @@ Structure of this header is ``ETHTOOL_A_HEADER_DEV_INDEX`` u32 device ifindex ``ETHTOOL_A_HEADER_DEV_NAME`` string device name ``ETHTOOL_A_HEADER_FLAGS`` u32 flags common for all requests + ``ETHTOOL_A_HEADER_PHY_INDEX`` u32 phy device index ============================== ====== ============================= ``ETHTOOL_A_HEADER_DEV_INDEX`` and ``ETHTOOL_A_HEADER_DEV_NAME`` identify the @@ -81,6 +82,12 @@ the behaviour is backward compatible, i.e. requests from old clients not aware of the flag should be interpreted the way the client expects. A client must not set flags it does not understand. +``ETHTOOL_A_HEADER_PHY_INDEX`` identify the ethernet PHY the message relates to. +As there are numerous commands that are related to PHY configuration, and because +we can have more than one PHY on the link, the PHY index can be passed in the +request for the commands that needs it. It is however not mandatory, and if it +is not passed for commands that target a PHY, the net_device.phydev pointer +is used, as a fallback that keeps the legacy behaviour. Bit sets ======== diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h index 73e2c10dc2cc..e557cf35250e 100644 --- a/include/uapi/linux/ethtool_netlink.h +++ b/include/uapi/linux/ethtool_netlink.h @@ -133,6 +133,7 @@ enum { ETHTOOL_A_HEADER_DEV_INDEX, /* u32 */ ETHTOOL_A_HEADER_DEV_NAME, /* string */ ETHTOOL_A_HEADER_FLAGS, /* u32 - ETHTOOL_FLAG_* */ + ETHTOOL_A_HEADER_PHY_INDEX, /* u32 */ /* add new constants above here */ __ETHTOOL_A_HEADER_CNT, diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index 3bbd5afb7b31..b8faab3a92e8 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -4,6 +4,7 @@ #include #include #include "netlink.h" +#include static struct genl_family ethtool_genl_family; @@ -20,6 +21,7 @@ const struct nla_policy ethnl_header_policy[] = { .len = ALTIFNAMSIZ - 1 }, [ETHTOOL_A_HEADER_FLAGS] = NLA_POLICY_MASK(NLA_U32, ETHTOOL_FLAGS_BASIC), + [ETHTOOL_A_HEADER_PHY_INDEX] = NLA_POLICY_MIN(NLA_U32, 1), }; const struct nla_policy ethnl_header_policy_stats[] = { @@ -28,6 +30,7 @@ const struct nla_policy ethnl_header_policy_stats[] = { .len = ALTIFNAMSIZ - 1 }, [ETHTOOL_A_HEADER_FLAGS] = NLA_POLICY_MASK(NLA_U32, ETHTOOL_FLAGS_STATS), + [ETHTOOL_A_HEADER_PHY_INDEX] = NLA_POLICY_MIN(NLA_U32, 1), }; int ethnl_ops_begin(struct net_device *dev) @@ -91,6 +94,7 @@ int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info, { struct nlattr *tb[ARRAY_SIZE(ethnl_header_policy)]; const struct nlattr *devname_attr; + struct phy_device *phydev = NULL; struct net_device *dev = NULL; u32 flags = 0; int ret; @@ -145,6 +149,26 @@ int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info, return -EINVAL; } + if (dev) { + if (tb[ETHTOOL_A_HEADER_PHY_INDEX]) { + u32 phy_index = nla_get_u32(tb[ETHTOOL_A_HEADER_PHY_INDEX]); + + phydev = phy_link_topo_get_phy(&dev->link_topo, + phy_index); + if (!phydev) { + NL_SET_ERR_MSG_ATTR(extack, header, + "no phy matches phy index"); + return -EINVAL; + } + } else { + /* If we need a PHY but no phy index is specified, fallback + * to dev->phydev + */ + phydev = dev->phydev; + } + } + + req_info->phydev = phydev; req_info->dev = dev; req_info->flags = flags; return 0; diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h index 9a333a8d04c1..def84e2def9e 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -250,6 +250,7 @@ static inline unsigned int ethnl_reply_header_size(void) * @dev: network device the request is for (may be null) * @dev_tracker: refcount tracker for @dev reference * @flags: request flags common for all request types + * @phydev: phy_device connected to @dev this request is for (may be null) * * This is a common base for request specific structures holding data from * parsed userspace request. These always embed struct ethnl_req_info at @@ -259,6 +260,7 @@ struct ethnl_req_info { struct net_device *dev; netdevice_tracker dev_tracker; u32 flags; + struct phy_device *phydev; }; static inline void ethnl_parse_header_dev_put(struct ethnl_req_info *req_info) @@ -395,9 +397,10 @@ extern const struct ethnl_request_ops ethnl_rss_request_ops; extern const struct ethnl_request_ops ethnl_plca_cfg_request_ops; extern const struct ethnl_request_ops ethnl_plca_status_request_ops; extern const struct ethnl_request_ops ethnl_mm_request_ops; +extern const struct ethnl_request_ops ethnl_phy_request_ops; -extern const struct nla_policy ethnl_header_policy[ETHTOOL_A_HEADER_FLAGS + 1]; -extern const struct nla_policy ethnl_header_policy_stats[ETHTOOL_A_HEADER_FLAGS + 1]; +extern const struct nla_policy ethnl_header_policy[ETHTOOL_A_HEADER_PHY_INDEX + 1]; +extern const struct nla_policy ethnl_header_policy_stats[ETHTOOL_A_HEADER_PHY_INDEX + 1]; extern const struct nla_policy ethnl_strset_get_policy[ETHTOOL_A_STRSET_COUNTS_ONLY + 1]; extern const struct nla_policy ethnl_linkinfo_get_policy[ETHTOOL_A_LINKINFO_HEADER + 1]; extern const struct nla_policy ethnl_linkinfo_set_policy[ETHTOOL_A_LINKINFO_TP_MDIX_CTRL + 1]; From patchwork Fri Dec 1 16:36:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Chevallier X-Patchwork-Id: 13476148 X-Patchwork-Delegate: kuba@kernel.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="i1x2casJ" Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::226]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 03E96A6; Fri, 1 Dec 2023 08:37:17 -0800 (PST) Received: by mail.gandi.net (Postfix) with ESMTPSA id 7160FC0003; Fri, 1 Dec 2023 16:37:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1701448636; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=TpQ2Lq1/07PThiXwqtF6vKr0dTACC1pOrJXucEn5IXw=; b=i1x2casJcKzjprF16OADCP4Tl7KvUnOGNz3Gbunzulg0Vxcr1z48gFP1HyYjH0zTk7ZkCT EQ3cFQUipC9DAMIc5Twt7ApUTRUy40KMw5phY4m8SAVgVB89EzjL8RT9wPL85C76cgw7XZ +L5idGNx3bJBGheiAPO12Lu0AaNHwLB9wKR1fIjrCzX5CIiyGcFzwFIW7EYJ45shK6KsZQ HbufO1XG9zlhc8vUyvaHq9+QpSy3NJqD9n5/oilFhqar9/6A5bG7ArI8hMbFMYuUqrqN7F CqOnQ25XJfywEv+a4gDiy133DgcTfln7cfQtAe9nwO+hT4baY1yKh2R9T7PWfg== From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Russell King , linux-arm-kernel@lists.infradead.org, Christophe Leroy , Herve Codina , Florian Fainelli , Heiner Kallweit , Vladimir Oltean , =?utf-8?q?K=C3=B6ry_Maincent?= , Jesse Brandeburg , Jonathan Corbet , =?utf-8?q?Marek_Beh=C3=BAn?= , Piergiorgio Beruto , Oleksij Rempel , =?utf-8?q?Nicol=C3=B2_Veronese?= Subject: [RFC PATCH net-next v3 06/13] netlink: specs: add phy-index as a header parameter Date: Fri, 1 Dec 2023 17:36:56 +0100 Message-ID: <20231201163704.1306431-7-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> References: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: maxime.chevallier@bootlin.com X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Update the spec to take the newly introduced phy-index as a generic request parameter, and bump the generated ethtool-user.c|h accordingly. Signed-off-by: Maxime Chevallier --- V3: New patch Documentation/netlink/specs/ethtool.yaml | 3 + tools/net/ynl/generated/ethtool-user.c | 8 + tools/net/ynl/generated/ethtool-user.h | 530 +++++++++++++++++++++++ 3 files changed, 541 insertions(+) diff --git a/Documentation/netlink/specs/ethtool.yaml b/Documentation/netlink/specs/ethtool.yaml index 5c7a65b009b4..4e0790648913 100644 --- a/Documentation/netlink/specs/ethtool.yaml +++ b/Documentation/netlink/specs/ethtool.yaml @@ -30,6 +30,9 @@ attribute-sets: - name: flags type: u32 + - + name: phy-index + type: u32 - name: bitset-bit diff --git a/tools/net/ynl/generated/ethtool-user.c b/tools/net/ynl/generated/ethtool-user.c index 74b883a14958..295661eb3a3e 100644 --- a/tools/net/ynl/generated/ethtool-user.c +++ b/tools/net/ynl/generated/ethtool-user.c @@ -96,6 +96,7 @@ struct ynl_policy_attr ethtool_header_policy[ETHTOOL_A_HEADER_MAX + 1] = { [ETHTOOL_A_HEADER_DEV_INDEX] = { .name = "dev-index", .type = YNL_PT_U32, }, [ETHTOOL_A_HEADER_DEV_NAME] = { .name = "dev-name", .type = YNL_PT_NUL_STR, }, [ETHTOOL_A_HEADER_FLAGS] = { .name = "flags", .type = YNL_PT_U32, }, + [ETHTOOL_A_HEADER_PHY_INDEX] = { .name = "phy-index", .type = YNL_PT_U32, }, }; struct ynl_policy_nest ethtool_header_nest = { @@ -684,6 +685,8 @@ int ethtool_header_put(struct nlmsghdr *nlh, unsigned int attr_type, mnl_attr_put_strz(nlh, ETHTOOL_A_HEADER_DEV_NAME, obj->dev_name); if (obj->_present.flags) mnl_attr_put_u32(nlh, ETHTOOL_A_HEADER_FLAGS, obj->flags); + if (obj->_present.phy_index) + mnl_attr_put_u32(nlh, ETHTOOL_A_HEADER_PHY_INDEX, obj->phy_index); mnl_attr_nest_end(nlh, nest); return 0; @@ -719,6 +722,11 @@ int ethtool_header_parse(struct ynl_parse_arg *yarg, return MNL_CB_ERROR; dst->_present.flags = 1; dst->flags = mnl_attr_get_u32(attr); + } else if (type == ETHTOOL_A_HEADER_PHY_INDEX) { + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + dst->_present.phy_index = 1; + dst->phy_index = mnl_attr_get_u32(attr); } } diff --git a/tools/net/ynl/generated/ethtool-user.h b/tools/net/ynl/generated/ethtool-user.h index ca0ec5fd7798..97c079c0f332 100644 --- a/tools/net/ynl/generated/ethtool-user.h +++ b/tools/net/ynl/generated/ethtool-user.h @@ -27,11 +27,13 @@ struct ethtool_header { __u32 dev_index:1; __u32 dev_name_len; __u32 flags:1; + __u32 phy_index:1; } _present; __u32 dev_index; char *dev_name; __u32 flags; + __u32 phy_index; }; struct ethtool_pause_stat { @@ -253,6 +255,14 @@ ethtool_strset_get_req_set_header_flags(struct ethtool_strset_get_req *req, req->header.flags = flags; } static inline void +ethtool_strset_get_req_set_header_phy_index(struct ethtool_strset_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} +static inline void __ethtool_strset_get_req_set_stringsets_stringset(struct ethtool_strset_get_req *req, struct ethtool_stringset_ *stringset, unsigned int n_stringset) @@ -331,6 +341,14 @@ ethtool_strset_get_req_dump_set_header_flags(struct ethtool_strset_get_req_dump req->header.flags = flags; } static inline void +ethtool_strset_get_req_dump_set_header_phy_index(struct ethtool_strset_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} +static inline void __ethtool_strset_get_req_dump_set_stringsets_stringset(struct ethtool_strset_get_req_dump *req, struct ethtool_stringset_ *stringset, unsigned int n_stringset) @@ -399,6 +417,14 @@ ethtool_linkinfo_get_req_set_header_flags(struct ethtool_linkinfo_get_req *req, req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_linkinfo_get_req_set_header_phy_index(struct ethtool_linkinfo_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_linkinfo_get_rsp { struct { @@ -469,6 +495,14 @@ ethtool_linkinfo_get_req_dump_set_header_flags(struct ethtool_linkinfo_get_req_d req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_linkinfo_get_req_dump_set_header_phy_index(struct ethtool_linkinfo_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_linkinfo_get_list { struct ethtool_linkinfo_get_list *next; @@ -546,6 +580,14 @@ ethtool_linkinfo_set_req_set_header_flags(struct ethtool_linkinfo_set_req *req, req->header.flags = flags; } static inline void +ethtool_linkinfo_set_req_set_header_phy_index(struct ethtool_linkinfo_set_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} +static inline void ethtool_linkinfo_set_req_set_port(struct ethtool_linkinfo_set_req *req, __u8 port) { @@ -630,6 +672,14 @@ ethtool_linkmodes_get_req_set_header_flags(struct ethtool_linkmodes_get_req *req req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_linkmodes_get_req_set_header_phy_index(struct ethtool_linkmodes_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_linkmodes_get_rsp { struct { @@ -709,6 +759,14 @@ ethtool_linkmodes_get_req_dump_set_header_flags(struct ethtool_linkmodes_get_req req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_linkmodes_get_req_dump_set_header_phy_index(struct ethtool_linkmodes_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_linkmodes_get_list { struct ethtool_linkmodes_get_list *next; @@ -794,6 +852,14 @@ ethtool_linkmodes_set_req_set_header_flags(struct ethtool_linkmodes_set_req *req req->header.flags = flags; } static inline void +ethtool_linkmodes_set_req_set_header_phy_index(struct ethtool_linkmodes_set_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} +static inline void ethtool_linkmodes_set_req_set_autoneg(struct ethtool_linkmodes_set_req *req, __u8 autoneg) { @@ -938,6 +1004,14 @@ ethtool_linkstate_get_req_set_header_flags(struct ethtool_linkstate_get_req *req req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_linkstate_get_req_set_header_phy_index(struct ethtool_linkstate_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_linkstate_get_rsp { struct { @@ -1011,6 +1085,14 @@ ethtool_linkstate_get_req_dump_set_header_flags(struct ethtool_linkstate_get_req req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_linkstate_get_req_dump_set_header_phy_index(struct ethtool_linkstate_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_linkstate_get_list { struct ethtool_linkstate_get_list *next; @@ -1065,6 +1147,14 @@ ethtool_debug_get_req_set_header_flags(struct ethtool_debug_get_req *req, req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_debug_get_req_set_header_phy_index(struct ethtool_debug_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_debug_get_rsp { struct { @@ -1126,6 +1216,14 @@ ethtool_debug_get_req_dump_set_header_flags(struct ethtool_debug_get_req_dump *r req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_debug_get_req_dump_set_header_phy_index(struct ethtool_debug_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_debug_get_list { struct ethtool_debug_get_list *next; @@ -1194,6 +1292,14 @@ ethtool_debug_set_req_set_header_flags(struct ethtool_debug_set_req *req, req->header.flags = flags; } static inline void +ethtool_debug_set_req_set_header_phy_index(struct ethtool_debug_set_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} +static inline void ethtool_debug_set_req_set_msgmask_nomask(struct ethtool_debug_set_req *req) { req->_present.msgmask = 1; @@ -1264,6 +1370,14 @@ ethtool_wol_get_req_set_header_flags(struct ethtool_wol_get_req *req, req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_wol_get_req_set_header_phy_index(struct ethtool_wol_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_wol_get_rsp { struct { @@ -1327,6 +1441,14 @@ ethtool_wol_get_req_dump_set_header_flags(struct ethtool_wol_get_req_dump *req, req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_wol_get_req_dump_set_header_phy_index(struct ethtool_wol_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_wol_get_list { struct ethtool_wol_get_list *next; @@ -1396,6 +1518,14 @@ ethtool_wol_set_req_set_header_flags(struct ethtool_wol_set_req *req, req->header.flags = flags; } static inline void +ethtool_wol_set_req_set_header_phy_index(struct ethtool_wol_set_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} +static inline void ethtool_wol_set_req_set_modes_nomask(struct ethtool_wol_set_req *req) { req->_present.modes = 1; @@ -1475,6 +1605,14 @@ ethtool_features_get_req_set_header_flags(struct ethtool_features_get_req *req, req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_features_get_req_set_header_phy_index(struct ethtool_features_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_features_get_rsp { struct { @@ -1543,6 +1681,14 @@ ethtool_features_get_req_dump_set_header_flags(struct ethtool_features_get_req_d req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_features_get_req_dump_set_header_phy_index(struct ethtool_features_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_features_get_list { struct ethtool_features_get_list *next; @@ -1618,6 +1764,14 @@ ethtool_features_set_req_set_header_flags(struct ethtool_features_set_req *req, req->header.flags = flags; } static inline void +ethtool_features_set_req_set_header_phy_index(struct ethtool_features_set_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} +static inline void ethtool_features_set_req_set_hw_nomask(struct ethtool_features_set_req *req) { req->_present.hw = 1; @@ -1777,6 +1931,14 @@ ethtool_privflags_get_req_set_header_flags(struct ethtool_privflags_get_req *req req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_privflags_get_req_set_header_phy_index(struct ethtool_privflags_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_privflags_get_rsp { struct { @@ -1840,6 +2002,14 @@ ethtool_privflags_get_req_dump_set_header_flags(struct ethtool_privflags_get_req req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_privflags_get_req_dump_set_header_phy_index(struct ethtool_privflags_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_privflags_get_list { struct ethtool_privflags_get_list *next; @@ -1909,6 +2079,14 @@ ethtool_privflags_set_req_set_header_flags(struct ethtool_privflags_set_req *req req->header.flags = flags; } static inline void +ethtool_privflags_set_req_set_header_phy_index(struct ethtool_privflags_set_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} +static inline void ethtool_privflags_set_req_set_flags_nomask(struct ethtool_privflags_set_req *req) { req->_present.flags = 1; @@ -1980,6 +2158,14 @@ ethtool_rings_get_req_set_header_flags(struct ethtool_rings_get_req *req, req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_rings_get_req_set_header_phy_index(struct ethtool_rings_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_rings_get_rsp { struct { @@ -2069,6 +2255,14 @@ ethtool_rings_get_req_dump_set_header_flags(struct ethtool_rings_get_req_dump *r req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_rings_get_req_dump_set_header_phy_index(struct ethtool_rings_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_rings_get_list { struct ethtool_rings_get_list *next; @@ -2165,6 +2359,14 @@ ethtool_rings_set_req_set_header_flags(struct ethtool_rings_set_req *req, req->header.flags = flags; } static inline void +ethtool_rings_set_req_set_header_phy_index(struct ethtool_rings_set_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} +static inline void ethtool_rings_set_req_set_rx_max(struct ethtool_rings_set_req *req, __u32 rx_max) { @@ -2316,6 +2518,14 @@ ethtool_channels_get_req_set_header_flags(struct ethtool_channels_get_req *req, req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_channels_get_req_set_header_phy_index(struct ethtool_channels_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_channels_get_rsp { struct { @@ -2392,6 +2602,14 @@ ethtool_channels_get_req_dump_set_header_flags(struct ethtool_channels_get_req_d req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_channels_get_req_dump_set_header_phy_index(struct ethtool_channels_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_channels_get_list { struct ethtool_channels_get_list *next; @@ -2475,6 +2693,14 @@ ethtool_channels_set_req_set_header_flags(struct ethtool_channels_set_req *req, req->header.flags = flags; } static inline void +ethtool_channels_set_req_set_header_phy_index(struct ethtool_channels_set_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} +static inline void ethtool_channels_set_req_set_rx_max(struct ethtool_channels_set_req *req, __u32 rx_max) { @@ -2580,6 +2806,14 @@ ethtool_coalesce_get_req_set_header_flags(struct ethtool_coalesce_get_req *req, req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_coalesce_get_req_set_header_phy_index(struct ethtool_coalesce_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_coalesce_get_rsp { struct { @@ -2694,6 +2928,14 @@ ethtool_coalesce_get_req_dump_set_header_flags(struct ethtool_coalesce_get_req_d req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_coalesce_get_req_dump_set_header_phy_index(struct ethtool_coalesce_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_coalesce_get_list { struct ethtool_coalesce_get_list *next; @@ -2815,6 +3057,14 @@ ethtool_coalesce_set_req_set_header_flags(struct ethtool_coalesce_set_req *req, req->header.flags = flags; } static inline void +ethtool_coalesce_set_req_set_header_phy_index(struct ethtool_coalesce_set_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} +static inline void ethtool_coalesce_set_req_set_rx_usecs(struct ethtool_coalesce_set_req *req, __u32 rx_usecs) { @@ -3052,6 +3302,14 @@ ethtool_pause_get_req_set_header_flags(struct ethtool_pause_get_req *req, req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_pause_get_req_set_header_phy_index(struct ethtool_pause_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_pause_get_rsp { struct { @@ -3121,6 +3379,14 @@ ethtool_pause_get_req_dump_set_header_flags(struct ethtool_pause_get_req_dump *r req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_pause_get_req_dump_set_header_phy_index(struct ethtool_pause_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_pause_get_list { struct ethtool_pause_get_list *next; @@ -3197,6 +3463,14 @@ ethtool_pause_set_req_set_header_flags(struct ethtool_pause_set_req *req, req->header.flags = flags; } static inline void +ethtool_pause_set_req_set_header_phy_index(struct ethtool_pause_set_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} +static inline void ethtool_pause_set_req_set_autoneg(struct ethtool_pause_set_req *req, __u8 autoneg) { @@ -3286,6 +3560,14 @@ ethtool_eee_get_req_set_header_flags(struct ethtool_eee_get_req *req, req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_eee_get_req_set_header_phy_index(struct ethtool_eee_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_eee_get_rsp { struct { @@ -3357,6 +3639,14 @@ ethtool_eee_get_req_dump_set_header_flags(struct ethtool_eee_get_req_dump *req, req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_eee_get_req_dump_set_header_phy_index(struct ethtool_eee_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_eee_get_list { struct ethtool_eee_get_list *next; @@ -3434,6 +3724,14 @@ ethtool_eee_set_req_set_header_flags(struct ethtool_eee_set_req *req, req->header.flags = flags; } static inline void +ethtool_eee_set_req_set_header_phy_index(struct ethtool_eee_set_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} +static inline void ethtool_eee_set_req_set_modes_ours_nomask(struct ethtool_eee_set_req *req) { req->_present.modes_ours = 1; @@ -3553,6 +3851,14 @@ ethtool_tsinfo_get_req_set_header_flags(struct ethtool_tsinfo_get_req *req, req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_tsinfo_get_req_set_header_phy_index(struct ethtool_tsinfo_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_tsinfo_get_rsp { struct { @@ -3620,6 +3926,14 @@ ethtool_tsinfo_get_req_dump_set_header_flags(struct ethtool_tsinfo_get_req_dump req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_tsinfo_get_req_dump_set_header_phy_index(struct ethtool_tsinfo_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_tsinfo_get_list { struct ethtool_tsinfo_get_list *next; @@ -3675,6 +3989,14 @@ ethtool_cable_test_act_req_set_header_flags(struct ethtool_cable_test_act_req *r req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_cable_test_act_req_set_header_phy_index(struct ethtool_cable_test_act_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} /* * Cable test. @@ -3726,6 +4048,14 @@ ethtool_cable_test_tdr_act_req_set_header_flags(struct ethtool_cable_test_tdr_ac req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_cable_test_tdr_act_req_set_header_phy_index(struct ethtool_cable_test_tdr_act_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} /* * Cable test TDR. @@ -3776,6 +4106,14 @@ ethtool_tunnel_info_get_req_set_header_flags(struct ethtool_tunnel_info_get_req req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_tunnel_info_get_req_set_header_phy_index(struct ethtool_tunnel_info_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_tunnel_info_get_rsp { struct { @@ -3839,6 +4177,14 @@ ethtool_tunnel_info_get_req_dump_set_header_flags(struct ethtool_tunnel_info_get req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_tunnel_info_get_req_dump_set_header_phy_index(struct ethtool_tunnel_info_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_tunnel_info_get_list { struct ethtool_tunnel_info_get_list *next; @@ -3894,6 +4240,14 @@ ethtool_fec_get_req_set_header_flags(struct ethtool_fec_get_req *req, req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_fec_get_req_set_header_phy_index(struct ethtool_fec_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_fec_get_rsp { struct { @@ -3961,6 +4315,14 @@ ethtool_fec_get_req_dump_set_header_flags(struct ethtool_fec_get_req_dump *req, req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_fec_get_req_dump_set_header_phy_index(struct ethtool_fec_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_fec_get_list { struct ethtool_fec_get_list *next; @@ -4034,6 +4396,14 @@ ethtool_fec_set_req_set_header_flags(struct ethtool_fec_set_req *req, req->header.flags = flags; } static inline void +ethtool_fec_set_req_set_header_phy_index(struct ethtool_fec_set_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} +static inline void ethtool_fec_set_req_set_modes_nomask(struct ethtool_fec_set_req *req) { req->_present.modes = 1; @@ -4144,6 +4514,14 @@ ethtool_module_eeprom_get_req_set_header_flags(struct ethtool_module_eeprom_get_ req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_module_eeprom_get_req_set_header_phy_index(struct ethtool_module_eeprom_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_module_eeprom_get_rsp { struct { @@ -4218,6 +4596,14 @@ ethtool_module_eeprom_get_req_dump_set_header_flags(struct ethtool_module_eeprom req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_module_eeprom_get_req_dump_set_header_phy_index(struct ethtool_module_eeprom_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_module_eeprom_get_list { struct ethtool_module_eeprom_get_list *next; @@ -4274,6 +4660,14 @@ ethtool_phc_vclocks_get_req_set_header_flags(struct ethtool_phc_vclocks_get_req req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_phc_vclocks_get_req_set_header_phy_index(struct ethtool_phc_vclocks_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_phc_vclocks_get_rsp { struct { @@ -4337,6 +4731,14 @@ ethtool_phc_vclocks_get_req_dump_set_header_flags(struct ethtool_phc_vclocks_get req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_phc_vclocks_get_req_dump_set_header_phy_index(struct ethtool_phc_vclocks_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_phc_vclocks_get_list { struct ethtool_phc_vclocks_get_list *next; @@ -4392,6 +4794,14 @@ ethtool_module_get_req_set_header_flags(struct ethtool_module_get_req *req, req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_module_get_req_set_header_phy_index(struct ethtool_module_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_module_get_rsp { struct { @@ -4455,6 +4865,14 @@ ethtool_module_get_req_dump_set_header_flags(struct ethtool_module_get_req_dump req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_module_get_req_dump_set_header_phy_index(struct ethtool_module_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_module_get_list { struct ethtool_module_get_list *next; @@ -4525,6 +4943,14 @@ ethtool_module_set_req_set_header_flags(struct ethtool_module_set_req *req, req->header.flags = flags; } static inline void +ethtool_module_set_req_set_header_phy_index(struct ethtool_module_set_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} +static inline void ethtool_module_set_req_set_power_mode_policy(struct ethtool_module_set_req *req, __u8 power_mode_policy) { @@ -4586,6 +5012,14 @@ ethtool_pse_get_req_set_header_flags(struct ethtool_pse_get_req *req, req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_pse_get_req_set_header_phy_index(struct ethtool_pse_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_pse_get_rsp { struct { @@ -4651,6 +5085,14 @@ ethtool_pse_get_req_dump_set_header_flags(struct ethtool_pse_get_req_dump *req, req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_pse_get_req_dump_set_header_phy_index(struct ethtool_pse_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_pse_get_list { struct ethtool_pse_get_list *next; @@ -4711,6 +5153,14 @@ ethtool_pse_set_req_set_header_flags(struct ethtool_pse_set_req *req, req->header.flags = flags; } static inline void +ethtool_pse_set_req_set_header_phy_index(struct ethtool_pse_set_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} +static inline void ethtool_pse_set_req_set_admin_state(struct ethtool_pse_set_req *req, __u32 admin_state) { @@ -4779,6 +5229,14 @@ ethtool_rss_get_req_set_header_flags(struct ethtool_rss_get_req *req, req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_rss_get_req_set_header_phy_index(struct ethtool_rss_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_rss_get_rsp { struct { @@ -4846,6 +5304,14 @@ ethtool_rss_get_req_dump_set_header_flags(struct ethtool_rss_get_req_dump *req, req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_rss_get_req_dump_set_header_phy_index(struct ethtool_rss_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_rss_get_list { struct ethtool_rss_get_list *next; @@ -4900,6 +5366,14 @@ ethtool_plca_get_cfg_req_set_header_flags(struct ethtool_plca_get_cfg_req *req, req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_plca_get_cfg_req_set_header_phy_index(struct ethtool_plca_get_cfg_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_plca_get_cfg_rsp { struct { @@ -4976,6 +5450,14 @@ ethtool_plca_get_cfg_req_dump_set_header_flags(struct ethtool_plca_get_cfg_req_d req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_plca_get_cfg_req_dump_set_header_phy_index(struct ethtool_plca_get_cfg_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_plca_get_cfg_list { struct ethtool_plca_get_cfg_list *next; @@ -5059,6 +5541,14 @@ ethtool_plca_set_cfg_req_set_header_flags(struct ethtool_plca_set_cfg_req *req, req->header.flags = flags; } static inline void +ethtool_plca_set_cfg_req_set_header_phy_index(struct ethtool_plca_set_cfg_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} +static inline void ethtool_plca_set_cfg_req_set_version(struct ethtool_plca_set_cfg_req *req, __u16 version) { @@ -5164,6 +5654,14 @@ ethtool_plca_get_status_req_set_header_flags(struct ethtool_plca_get_status_req req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_plca_get_status_req_set_header_phy_index(struct ethtool_plca_get_status_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_plca_get_status_rsp { struct { @@ -5241,6 +5739,14 @@ ethtool_plca_get_status_req_dump_set_header_flags(struct ethtool_plca_get_status req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_plca_get_status_req_dump_set_header_phy_index(struct ethtool_plca_get_status_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_plca_get_status_list { struct ethtool_plca_get_status_list *next; @@ -5296,6 +5802,14 @@ ethtool_mm_get_req_set_header_flags(struct ethtool_mm_get_req *req, req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_mm_get_req_set_header_phy_index(struct ethtool_mm_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_mm_get_rsp { struct { @@ -5373,6 +5887,14 @@ ethtool_mm_get_req_dump_set_header_flags(struct ethtool_mm_get_req_dump *req, req->header._present.flags = 1; req->header.flags = flags; } +static inline void +ethtool_mm_get_req_dump_set_header_phy_index(struct ethtool_mm_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} struct ethtool_mm_get_list { struct ethtool_mm_get_list *next; @@ -5448,6 +5970,14 @@ ethtool_mm_set_req_set_header_flags(struct ethtool_mm_set_req *req, req->header.flags = flags; } static inline void +ethtool_mm_set_req_set_header_phy_index(struct ethtool_mm_set_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} +static inline void ethtool_mm_set_req_set_verify_enabled(struct ethtool_mm_set_req *req, __u8 verify_enabled) { From patchwork Fri Dec 1 16:36:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Chevallier X-Patchwork-Id: 13476152 X-Patchwork-Delegate: kuba@kernel.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="J3nU3bNV" Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 27AD6D67; Fri, 1 Dec 2023 08:37:19 -0800 (PST) Received: by mail.gandi.net (Postfix) with ESMTPSA id BA40DC0002; Fri, 1 Dec 2023 16:37:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1701448637; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MnWFoctM5dCxNvjtj1tJfSyq/yYsvd8LiNxVjJtV4vs=; b=J3nU3bNV/U2kNgKoQVPDOWfAyiUyvqq4iDU2uz0Bpn4VGKvdYp6Qwy716VIlYrn00ISkET RYKDieuOekMZ99yTIBXr6gz2YY2ckiGXGkqklqC8VGAtZyVs57yQrJdoUVah5N/9FL8b0Z nPGgv8XPyglMhQ0bMNL2o/ZBFnQz7ZdtPienj5paD5sZnPPE1ng+Ars/LERcHuE0pLZPNp u7u9pDJMrvD5bgqvhBcDU56xE4659zQSJaWdk8gagpgLwMSV0mOJ9pOJRczDSvhTllUgYK W9QkCCX06tG1b9DgKSqKtaKNm6z9IKaGPJRDzQp+HSD84SqYtXRutGGwtC3XLA== From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Russell King , linux-arm-kernel@lists.infradead.org, Christophe Leroy , Herve Codina , Florian Fainelli , Heiner Kallweit , Vladimir Oltean , =?utf-8?q?K=C3=B6ry_Maincent?= , Jesse Brandeburg , Jonathan Corbet , =?utf-8?q?Marek_Beh=C3=BAn?= , Piergiorgio Beruto , Oleksij Rempel , =?utf-8?q?Nicol=C3=B2_Veronese?= Subject: [RFC PATCH net-next v3 07/13] net: ethtool: Introduce a command to list PHYs on an interface Date: Fri, 1 Dec 2023 17:36:57 +0100 Message-ID: <20231201163704.1306431-8-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> References: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: maxime.chevallier@bootlin.com X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC As we have the ability to track the PHYs connected to a net_device through the link_topology, we can expose this list to userspace. This allows userspace to use these identifiers for phy-specific commands and take the decision of which PHY to target by knowing the link topology. Add PHY_GET and PHY_DUMP, which can be a filtered DUMP operation to list devices on only one interface. Signed-off-by: Maxime Chevallier --- V3: - Fixed the documentation - Fixed the DUMP implementation V2: New patch Documentation/networking/ethtool-netlink.rst | 44 +++ include/uapi/linux/ethtool_netlink.h | 29 ++ net/ethtool/Makefile | 2 +- net/ethtool/netlink.c | 9 + net/ethtool/netlink.h | 5 + net/ethtool/phy.c | 292 +++++++++++++++++++ 6 files changed, 380 insertions(+), 1 deletion(-) create mode 100644 net/ethtool/phy.c diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst index 8f6390a85895..d9b8cc256e71 100644 --- a/Documentation/networking/ethtool-netlink.rst +++ b/Documentation/networking/ethtool-netlink.rst @@ -2001,6 +2001,49 @@ The attributes are propagated to the driver through the following structure: .. kernel-doc:: include/linux/ethtool.h :identifiers: ethtool_mm_cfg +PHY_GET +======= + +Retrieve information about a given Ethernet PHY sitting on the link. As there +can be more than one PHY, the DUMP operation can be used to list the PHYs +present on a given interface, by passing an interface index or name in +the dump request + +Request contents: + + ==================================== ====== ========================== + ``ETHTOOL_A_PHY_HEADER`` nested request header + ==================================== ====== ========================== + +Kernel response contents: + + ===================================== ====== ========================== + ``ETHTOOL_A_PHY_HEADER`` nested request header + ``ETHTOOL_A_PHY_INDEX`` u32 the phy's unique index, that can + be used for phy-specific requests + ``ETHTOOL_A_PHY_DRVNAME`` string the phy driver name + ``ETHTOOL_A_PHY_NAME`` string the phy device name + ``ETHTOOL_A_PHY_UPSTREAM_TYPE`` u32 the type of device this phy is + connected to + ``ETHTOOL_A_PHY_UPSTREAM_PHY`` nested if the phy is connected to another + phy, this nest contains info on + that connection + ``ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME`` string if the phy controls an sfp bus, + the name of the sfp bus + ``ETHTOOL_A_PHY_ID`` u32 the phy id if the phy is C22 + ===================================== ====== ========================== + +When ``ETHTOOL_A_PHY_UPSTREAM_TYPE`` is PHY_UPSTREAM_PHY, the PHY's parent is +another PHY. Information on the parent PHY will be set in the +``ETHTOOL_A_PHY_UPSTREAM_PHY`` nest, which has the following structure : + + =================================== ====== ========================== + ``ETHTOOL_A_PHY_UPSTREAM_INDEX`` u32 the PHY index of the upstream PHY + ``ETHTOOL_A_PHY_UPSTREAM_SFP_NAME`` string if this PHY is connected to it's + parent PHY through an SFP bus, the + name of this sfp bus + =================================== ====== ========================== + Request translation =================== @@ -2107,4 +2150,5 @@ are netlink only. n/a ``ETHTOOL_MSG_PLCA_GET_STATUS`` n/a ``ETHTOOL_MSG_MM_GET`` n/a ``ETHTOOL_MSG_MM_SET`` + n/a ``ETHTOOL_MSG_PHY_GET`` =================================== ===================================== diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h index e557cf35250e..7d621963698a 100644 --- a/include/uapi/linux/ethtool_netlink.h +++ b/include/uapi/linux/ethtool_netlink.h @@ -57,6 +57,7 @@ enum { ETHTOOL_MSG_PLCA_GET_STATUS, ETHTOOL_MSG_MM_GET, ETHTOOL_MSG_MM_SET, + ETHTOOL_MSG_PHY_GET, /* add new constants above here */ __ETHTOOL_MSG_USER_CNT, @@ -109,6 +110,8 @@ enum { ETHTOOL_MSG_PLCA_NTF, ETHTOOL_MSG_MM_GET_REPLY, ETHTOOL_MSG_MM_NTF, + ETHTOOL_MSG_PHY_GET_REPLY, + ETHTOOL_MSG_PHY_NTF, /* add new constants above here */ __ETHTOOL_MSG_KERNEL_CNT, @@ -976,6 +979,32 @@ enum { ETHTOOL_A_MM_MAX = (__ETHTOOL_A_MM_CNT - 1) }; +enum { + ETHTOOL_A_PHY_UPSTREAM_UNSPEC, + ETHTOOL_A_PHY_UPSTREAM_INDEX, /* u32 */ + ETHTOOL_A_PHY_UPSTREAM_SFP_NAME, /* string */ + + /* add new constants above here */ + __ETHTOOL_A_PHY_UPSTREAM_CNT, + ETHTOOL_A_PHY_UPSTREAM_MAX = (__ETHTOOL_A_PHY_UPSTREAM_CNT - 1) +}; + +enum { + ETHTOOL_A_PHY_UNSPEC, + ETHTOOL_A_PHY_HEADER, /* nest - _A_HEADER_* */ + ETHTOOL_A_PHY_INDEX, /* u32 */ + ETHTOOL_A_PHY_DRVNAME, /* string */ + ETHTOOL_A_PHY_NAME, /* string */ + ETHTOOL_A_PHY_UPSTREAM_TYPE, /* u8 */ + ETHTOOL_A_PHY_UPSTREAM, /* nest - _A_PHY_UPSTREAM_* */ + ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME, /* string */ + ETHTOOL_A_PHY_ID, /* u32 */ + + /* add new constants above here */ + __ETHTOOL_A_PHY_CNT, + ETHTOOL_A_PHY_MAX = (__ETHTOOL_A_PHY_CNT - 1) +}; + /* generic netlink info */ #define ETHTOOL_GENL_NAME "ethtool" #define ETHTOOL_GENL_VERSION 1 diff --git a/net/ethtool/Makefile b/net/ethtool/Makefile index 504f954a1b28..0ccd0e9afd3f 100644 --- a/net/ethtool/Makefile +++ b/net/ethtool/Makefile @@ -8,4 +8,4 @@ ethtool_nl-y := netlink.o bitset.o strset.o linkinfo.o linkmodes.o rss.o \ linkstate.o debug.o wol.o features.o privflags.o rings.o \ channels.o coalesce.o pause.o eee.o tsinfo.o cabletest.o \ tunnels.o fec.o eeprom.o stats.o phc_vclocks.o mm.o \ - module.o pse-pd.o plca.o mm.o + module.o pse-pd.o plca.o mm.o phy.o diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index b8faab3a92e8..ebc481f2cf39 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -1152,6 +1152,15 @@ static const struct genl_ops ethtool_genl_ops[] = { .policy = ethnl_mm_set_policy, .maxattr = ARRAY_SIZE(ethnl_mm_set_policy) - 1, }, + { + .cmd = ETHTOOL_MSG_PHY_GET, + .doit = ethnl_phy_doit, + .start = ethnl_phy_start, + .dumpit = ethnl_phy_dumpit, + .done = ethnl_phy_done, + .policy = ethnl_phy_get_policy, + .maxattr = ARRAY_SIZE(ethnl_phy_get_policy) - 1, + }, }; static const struct genl_multicast_group ethtool_nl_mcgrps[] = { diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h index def84e2def9e..5e6a43e35a09 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -444,6 +444,7 @@ extern const struct nla_policy ethnl_plca_set_cfg_policy[ETHTOOL_A_PLCA_MAX + 1] extern const struct nla_policy ethnl_plca_get_status_policy[ETHTOOL_A_PLCA_HEADER + 1]; extern const struct nla_policy ethnl_mm_get_policy[ETHTOOL_A_MM_HEADER + 1]; extern const struct nla_policy ethnl_mm_set_policy[ETHTOOL_A_MM_MAX + 1]; +extern const struct nla_policy ethnl_phy_get_policy[ETHTOOL_A_PHY_HEADER + 1]; int ethnl_set_features(struct sk_buff *skb, struct genl_info *info); int ethnl_act_cable_test(struct sk_buff *skb, struct genl_info *info); @@ -451,6 +452,10 @@ int ethnl_act_cable_test_tdr(struct sk_buff *skb, struct genl_info *info); int ethnl_tunnel_info_doit(struct sk_buff *skb, struct genl_info *info); int ethnl_tunnel_info_start(struct netlink_callback *cb); int ethnl_tunnel_info_dumpit(struct sk_buff *skb, struct netlink_callback *cb); +int ethnl_phy_start(struct netlink_callback *cb); +int ethnl_phy_doit(struct sk_buff *skb, struct genl_info *info); +int ethnl_phy_dumpit(struct sk_buff *skb, struct netlink_callback *cb); +int ethnl_phy_done(struct netlink_callback *cb); extern const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN]; extern const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN]; diff --git a/net/ethtool/phy.c b/net/ethtool/phy.c new file mode 100644 index 000000000000..e25ac405e46c --- /dev/null +++ b/net/ethtool/phy.c @@ -0,0 +1,292 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2023 Bootlin + * + */ +#include "common.h" +#include "netlink.h" + +#include +#include +#include + +struct phy_req_info { + struct ethnl_req_info base; + struct phy_device_node pdn; +}; + +#define PHY_REQINFO(__req_base) \ + container_of(__req_base, struct phy_req_info, base) + +const struct nla_policy ethnl_phy_get_policy[ETHTOOL_A_PHY_HEADER + 1] = { + [ETHTOOL_A_PHY_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy), +}; + +/* Caller holds rtnl */ +static ssize_t +ethnl_phy_reply_size(const struct ethnl_req_info *req_base, + struct netlink_ext_ack *extack) +{ + struct phy_link_topology *topo; + struct phy_device_node *pdn; + struct phy_device *phydev; + unsigned long index; + size_t size; + + ASSERT_RTNL(); + + topo = &req_base->dev->link_topo; + + size = nla_total_size(0); + + xa_for_each(&topo->phys, index, pdn) { + phydev = pdn->phy; + + /* ETHTOOL_A_PHY_INDEX */ + size += nla_total_size(sizeof(u32)); + + /* ETHTOOL_A_DRVNAME */ + size += nla_total_size(strlen(phydev->drv->name)); + + /* ETHTOOL_A_NAME */ + size += nla_total_size(strlen(dev_name(&phydev->mdio.dev))); + + /* ETHTOOL_A_PHY_UPSTREAM_TYPE */ + size += nla_total_size(sizeof(u8)); + + /* ETHTOOL_A_PHY_ID */ + size += nla_total_size(sizeof(u32)); + + if (phy_on_sfp(phydev)) { + /* ETHTOOL_A_PHY_UPSTREAM_SFP_NAME */ + if (sfp_get_name(pdn->parent_sfp_bus)) + size += nla_total_size(strlen(sfp_get_name(pdn->parent_sfp_bus))); + + /* ETHTOOL_A_PHY_UPSTREAM_INDEX */ + size += nla_total_size(sizeof(u32)); + } + + /* ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME */ + if (phydev->sfp_bus) + size += nla_total_size(strlen(sfp_get_name(phydev->sfp_bus))); + } + + return size; +} + +static int +ethnl_phy_fill_reply(const struct ethnl_req_info *req_base, struct sk_buff *skb) +{ + struct phy_req_info *req_info = PHY_REQINFO(req_base); + struct phy_device_node *pdn = &req_info->pdn; + struct phy_device *phydev = pdn->phy; + enum phy_upstream ptype; + struct nlattr *nest; + + ptype = pdn->upstream_type; + + if (nla_put_u32(skb, ETHTOOL_A_PHY_INDEX, phydev->phyindex) || + nla_put_string(skb, ETHTOOL_A_PHY_DRVNAME, phydev->drv->name) || + nla_put_string(skb, ETHTOOL_A_PHY_NAME, dev_name(&phydev->mdio.dev)) || + nla_put_u8(skb, ETHTOOL_A_PHY_UPSTREAM_TYPE, ptype) || + nla_put_u32(skb, ETHTOOL_A_PHY_ID, phydev->phy_id)) + return -EMSGSIZE; + + if (ptype == PHY_UPSTREAM_PHY) { + struct phy_device *upstream = pdn->upstream.phydev; + + nest = nla_nest_start(skb, ETHTOOL_A_PHY_UPSTREAM); + if (!nest) + return -EMSGSIZE; + + /* Parent index */ + if (nla_put_u32(skb, ETHTOOL_A_PHY_UPSTREAM_INDEX, upstream->phyindex)) + return -EMSGSIZE; + + if (pdn->parent_sfp_bus && sfp_get_name(pdn->parent_sfp_bus) && + nla_put_string(skb, ETHTOOL_A_PHY_UPSTREAM_SFP_NAME, + sfp_get_name(pdn->parent_sfp_bus))) + return -EMSGSIZE; + + nla_nest_end(skb, nest); + } + + if (phydev->sfp_bus && + nla_put_string(skb, ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME, + sfp_get_name(phydev->sfp_bus))) + return -EMSGSIZE; + + return 0; +} + +static int ethnl_phy_parse_request(struct ethnl_req_info *req_base, + struct nlattr **tb) +{ + struct phy_req_info *req_info = PHY_REQINFO(req_base); + struct phy_link_topology *topo = &req_base->dev->link_topo; + struct phy_device_node *pdn; + + if (!req_base->phydev) + return 0; + + pdn = xa_load(&topo->phys, req_base->phydev->phyindex); + memcpy(&req_info->pdn, pdn, sizeof(*pdn)); + + return 0; +} + +int ethnl_phy_doit(struct sk_buff *skb, struct genl_info *info) +{ + struct phy_req_info req_info = {}; + struct nlattr **tb = info->attrs; + struct sk_buff *rskb; + void *reply_payload; + int reply_len; + int ret; + + ret = ethnl_parse_header_dev_get(&req_info.base, + tb[ETHTOOL_A_PHY_HEADER], + genl_info_net(info), info->extack, + true); + if (ret < 0) + return ret; + + rtnl_lock(); + + ret = ethnl_phy_parse_request(&req_info.base, tb); + if (ret < 0) + goto err_unlock_rtnl; + + /* No PHY, return early */ + if (!req_info.pdn.phy) + goto err_unlock_rtnl; + + ret = ethnl_phy_reply_size(&req_info.base, info->extack); + if (ret < 0) + goto err_unlock_rtnl; + reply_len = ret + ethnl_reply_header_size(); + + rskb = ethnl_reply_init(reply_len, req_info.base.dev, + ETHTOOL_MSG_PHY_GET_REPLY, + ETHTOOL_A_PHY_HEADER, + info, &reply_payload); + if (!rskb) { + ret = -ENOMEM; + goto err_unlock_rtnl; + } + + ret = ethnl_phy_fill_reply(&req_info.base, rskb); + if (ret) + goto err_free_msg; + + rtnl_unlock(); + ethnl_parse_header_dev_put(&req_info.base); + genlmsg_end(rskb, reply_payload); + + return genlmsg_reply(rskb, info); + +err_free_msg: + nlmsg_free(rskb); +err_unlock_rtnl: + rtnl_unlock(); + ethnl_parse_header_dev_put(&req_info.base); + return ret; +} + +struct ethnl_phy_dump_ctx { + struct phy_req_info *phy_req_info; +}; + +int ethnl_phy_start(struct netlink_callback *cb) +{ + const struct genl_dumpit_info *info = genl_dumpit_info(cb); + struct ethnl_phy_dump_ctx *ctx = (void *)cb->ctx; + struct nlattr **tb = info->info.attrs; + int ret; + + BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx)); + + ctx->phy_req_info = kzalloc(sizeof(*ctx->phy_req_info), GFP_KERNEL); + if (!ctx->phy_req_info) + return -ENOMEM; + + ret = ethnl_parse_header_dev_get(&ctx->phy_req_info->base, + tb[ETHTOOL_A_PHY_HEADER], + sock_net(cb->skb->sk), cb->extack, + false); + return ret; +} + +int ethnl_phy_done(struct netlink_callback *cb) +{ + struct ethnl_phy_dump_ctx *ctx = (void *)cb->ctx; + + kfree(ctx->phy_req_info); + + return 0; +} + +static int ethnl_phy_dump_one_dev(struct sk_buff *skb, struct net_device *dev, + struct netlink_callback *cb) +{ + struct ethnl_phy_dump_ctx *ctx = (void *)cb->ctx; + struct phy_req_info *pri = ctx->phy_req_info; + struct phy_device_node *pdn; + unsigned long index = 1; + void *ehdr; + int ret; + + pri->base.dev = dev; + + xa_for_each(&dev->link_topo.phys, index, pdn) { + ehdr = ethnl_dump_put(skb, cb, + ETHTOOL_MSG_PHY_GET_REPLY); + if (!ehdr) { + ret = -EMSGSIZE; + break; + } + + ret = ethnl_fill_reply_header(skb, dev, + ETHTOOL_A_PHY_HEADER); + if (ret < 0) { + genlmsg_cancel(skb, ehdr); + break; + } + + memcpy(&pri->pdn, pdn, sizeof(*pdn)); + ret = ethnl_phy_fill_reply(&pri->base, skb); + + genlmsg_end(skb, ehdr); + } + + return ret; +} + +int ethnl_phy_dumpit(struct sk_buff *skb, struct netlink_callback *cb) +{ + struct ethnl_phy_dump_ctx *ctx = (void *)cb->ctx; + struct net *net = sock_net(skb->sk); + unsigned long ifindex = 1; + struct net_device *dev; + int ret = 0; + + rtnl_lock(); + + if (ctx->phy_req_info->base.dev) { + ret = ethnl_phy_dump_one_dev(skb, ctx->phy_req_info->base.dev, cb); + ethnl_parse_header_dev_put(&ctx->phy_req_info->base); + ctx->phy_req_info->base.dev = NULL; + } else { + for_each_netdev_dump(net, dev, ifindex) { + ret = ethnl_phy_dump_one_dev(skb, dev, cb); + if (ret) + break; + } + } + rtnl_unlock(); + + if (ret == -EMSGSIZE && skb->len) + return skb->len; + return ret; +} + From patchwork Fri Dec 1 16:36:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Chevallier X-Patchwork-Id: 13476150 X-Patchwork-Delegate: kuba@kernel.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="WIv8nj2Z" Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::226]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 900111713; Fri, 1 Dec 2023 08:37:20 -0800 (PST) Received: by mail.gandi.net (Postfix) with ESMTPSA id 0BD2DC0008; Fri, 1 Dec 2023 16:37:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1701448639; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UUPrERWVmZXfJBxo+Ko10zUTpdUI1iWcuWQHSDOYj1w=; b=WIv8nj2ZV2CZjYIhBAxYUu/IOA8Kx2/sL3iIPGhlNOJhAmmi8q1Zke4hJKrnt0XhuVI1nj E9NS8SSDORWSOkCbnwb22kS+RwcE7J/YHAIWiHm8GeVsj2jG/UPiyA8gKKstAeTPCPXxQB Nbdr+C8lam3L17dAw6gmJKSKW7OPpShOXfFvSx+TCIBQ6AoBaWxPQ1pdiHuH23usOLdZGs 2O/TqFC89hEVak1t1Xo+G5+yOvhHv1TZKPWRXnWjGeqXRpquIQWuVch4l4y1GUDnUgZEpo aIVxgHobgw/gjaFUoRuWVGUhtPKOu2H+v7tsCjJah7OyQRBIrN5lduJ7EM3VfA== From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Russell King , linux-arm-kernel@lists.infradead.org, Christophe Leroy , Herve Codina , Florian Fainelli , Heiner Kallweit , Vladimir Oltean , =?utf-8?q?K=C3=B6ry_Maincent?= , Jesse Brandeburg , Jonathan Corbet , =?utf-8?q?Marek_Beh=C3=BAn?= , Piergiorgio Beruto , Oleksij Rempel , =?utf-8?q?Nicol=C3=B2_Veronese?= Subject: [RFC PATCH net-next v3 08/13] netlink: specs: add ethnl PHY_GET command set Date: Fri, 1 Dec 2023 17:36:58 +0100 Message-ID: <20231201163704.1306431-9-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> References: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: maxime.chevallier@bootlin.com X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC The PHY_GET command, supporting both DUMP and GET operations, is used to retrieve the list of PHYs connected to a netdevice, and get topology information to know where exactly it sits on the physical link. Add the netlink specs corresponding to that command, and bump the ethtool-user.c|h autogenerated files. Signed-off-by: Maxime Chevallier --- V3: New patch Documentation/netlink/specs/ethtool.yaml | 65 ++++++ tools/net/ynl/generated/ethtool-user.c | 257 +++++++++++++++++++++++ tools/net/ynl/generated/ethtool-user.h | 153 ++++++++++++++ 3 files changed, 475 insertions(+) diff --git a/Documentation/netlink/specs/ethtool.yaml b/Documentation/netlink/specs/ethtool.yaml index 4e0790648913..280b090b5f7c 100644 --- a/Documentation/netlink/specs/ethtool.yaml +++ b/Documentation/netlink/specs/ethtool.yaml @@ -16,6 +16,11 @@ definitions: name: stringset type: enum entries: [] + - + name: phy-upstream-type + enum-name: + type: enum + entries: [ mac, phy ] attribute-sets: - @@ -942,6 +947,45 @@ attribute-sets: - name: burst-tmr type: u32 + - + name: phy-upstream + attributes: + - + name: index + type: u32 + - + name: sfp-name + type: string + - + name: phy + attributes: + - + name: header + type: nest + nested-attributes: header + - + name: index + type: u32 + - + name: drvname + type: string + - + name: name + type: string + - + name: upstream-type + type: u8 + enum: phy-upstream-type + - + name: upstream + type: nest + nested-attributes: phy-upstream + - + name: downstream-sfp-name + type: string + - + name: id + type: u32 operations: enum-model: directional @@ -1692,3 +1736,24 @@ operations: name: mm-ntf doc: Notification for change in MAC Merge configuration. notify: mm-get + - + name: phy-get + doc: Get PHY devices attached to an interface + + attribute-set: phy + + do: &phy-get-op + request: + attributes: + - header + reply: + attributes: + - header + - index + - drvname + - name + - upstream-type + - upstream + - downstream-sfp-name + - id + dump: *phy-get-op diff --git a/tools/net/ynl/generated/ethtool-user.c b/tools/net/ynl/generated/ethtool-user.c index 295661eb3a3e..b63ba2d2e25e 100644 --- a/tools/net/ynl/generated/ethtool-user.c +++ b/tools/net/ynl/generated/ethtool-user.c @@ -59,6 +59,7 @@ static const char * const ethtool_op_strmap[] = { [41] = "plca-ntf", [ETHTOOL_MSG_MM_GET] = "mm-get", [43] = "mm-ntf", + [ETHTOOL_MSG_PHY_GET] = "phy-get", }; const char *ethtool_op_str(int op) @@ -91,6 +92,18 @@ const char *ethtool_stringset_str(enum ethtool_stringset value) return ethtool_stringset_strmap[value]; } +static const char * const ethtool_phy_upstream_type_strmap[] = { + [0] = "mac", + [1] = "phy", +}; + +const char *ethtool_phy_upstream_type_str(int value) +{ + if (value < 0 || value >= (int)MNL_ARRAY_SIZE(ethtool_phy_upstream_type_strmap)) + return NULL; + return ethtool_phy_upstream_type_strmap[value]; +} + /* Policies */ struct ynl_policy_attr ethtool_header_policy[ETHTOOL_A_HEADER_MAX + 1] = { [ETHTOOL_A_HEADER_DEV_INDEX] = { .name = "dev-index", .type = YNL_PT_U32, }, @@ -154,6 +167,16 @@ struct ynl_policy_nest ethtool_mm_stat_nest = { .table = ethtool_mm_stat_policy, }; +struct ynl_policy_attr ethtool_phy_upstream_policy[ETHTOOL_A_PHY_UPSTREAM_MAX + 1] = { + [ETHTOOL_A_PHY_UPSTREAM_INDEX] = { .name = "index", .type = YNL_PT_U32, }, + [ETHTOOL_A_PHY_UPSTREAM_SFP_NAME] = { .name = "sfp-name", .type = YNL_PT_NUL_STR, }, +}; + +struct ynl_policy_nest ethtool_phy_upstream_nest = { + .max_attr = ETHTOOL_A_PHY_UPSTREAM_MAX, + .table = ethtool_phy_upstream_policy, +}; + struct ynl_policy_attr ethtool_cable_result_policy[ETHTOOL_A_CABLE_RESULT_MAX + 1] = { [ETHTOOL_A_CABLE_RESULT_PAIR] = { .name = "pair", .type = YNL_PT_U8, }, [ETHTOOL_A_CABLE_RESULT_CODE] = { .name = "code", .type = YNL_PT_U8, }, @@ -667,6 +690,22 @@ struct ynl_policy_nest ethtool_mm_nest = { .table = ethtool_mm_policy, }; +struct ynl_policy_attr ethtool_phy_policy[ETHTOOL_A_PHY_MAX + 1] = { + [ETHTOOL_A_PHY_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = ðtool_header_nest, }, + [ETHTOOL_A_PHY_INDEX] = { .name = "index", .type = YNL_PT_U32, }, + [ETHTOOL_A_PHY_DRVNAME] = { .name = "drvname", .type = YNL_PT_NUL_STR, }, + [ETHTOOL_A_PHY_NAME] = { .name = "name", .type = YNL_PT_NUL_STR, }, + [ETHTOOL_A_PHY_UPSTREAM_TYPE] = { .name = "upstream-type", .type = YNL_PT_U8, }, + [ETHTOOL_A_PHY_UPSTREAM] = { .name = "upstream", .type = YNL_PT_NEST, .nest = ðtool_phy_upstream_nest, }, + [ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME] = { .name = "downstream-sfp-name", .type = YNL_PT_NUL_STR, }, + [ETHTOOL_A_PHY_ID] = { .name = "id", .type = YNL_PT_U32, }, +}; + +struct ynl_policy_nest ethtool_phy_nest = { + .max_attr = ETHTOOL_A_PHY_MAX, + .table = ethtool_phy_policy, +}; + /* Common nested types */ void ethtool_header_free(struct ethtool_header *obj) { @@ -899,6 +938,42 @@ int ethtool_mm_stat_parse(struct ynl_parse_arg *yarg, return 0; } +void ethtool_phy_upstream_free(struct ethtool_phy_upstream *obj) +{ + free(obj->sfp_name); +} + +int ethtool_phy_upstream_parse(struct ynl_parse_arg *yarg, + const struct nlattr *nested) +{ + struct ethtool_phy_upstream *dst = yarg->data; + const struct nlattr *attr; + + mnl_attr_for_each_nested(attr, nested) { + unsigned int type = mnl_attr_get_type(attr); + + if (type == ETHTOOL_A_PHY_UPSTREAM_INDEX) { + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + dst->_present.index = 1; + dst->index = mnl_attr_get_u32(attr); + } else if (type == ETHTOOL_A_PHY_UPSTREAM_SFP_NAME) { + unsigned int len; + + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + + len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr)); + dst->_present.sfp_name_len = len; + dst->sfp_name = malloc(len + 1); + memcpy(dst->sfp_name, mnl_attr_get_str(attr), len); + dst->sfp_name[len] = 0; + } + } + + return 0; +} + void ethtool_cable_result_free(struct ethtool_cable_result *obj) { } @@ -6158,6 +6233,188 @@ int ethtool_mm_set(struct ynl_sock *ys, struct ethtool_mm_set_req *req) return 0; } +/* ============== ETHTOOL_MSG_PHY_GET ============== */ +/* ETHTOOL_MSG_PHY_GET - do */ +void ethtool_phy_get_req_free(struct ethtool_phy_get_req *req) +{ + ethtool_header_free(&req->header); + free(req); +} + +void ethtool_phy_get_rsp_free(struct ethtool_phy_get_rsp *rsp) +{ + ethtool_header_free(&rsp->header); + free(rsp->drvname); + free(rsp->name); + ethtool_phy_upstream_free(&rsp->upstream); + free(rsp->downstream_sfp_name); + free(rsp); +} + +int ethtool_phy_get_rsp_parse(const struct nlmsghdr *nlh, void *data) +{ + struct ynl_parse_arg *yarg = data; + struct ethtool_phy_get_rsp *dst; + const struct nlattr *attr; + struct ynl_parse_arg parg; + + dst = yarg->data; + parg.ys = yarg->ys; + + mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) { + unsigned int type = mnl_attr_get_type(attr); + + if (type == ETHTOOL_A_PHY_HEADER) { + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + dst->_present.header = 1; + + parg.rsp_policy = ðtool_header_nest; + parg.data = &dst->header; + if (ethtool_header_parse(&parg, attr)) + return MNL_CB_ERROR; + } else if (type == ETHTOOL_A_PHY_INDEX) { + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + dst->_present.index = 1; + dst->index = mnl_attr_get_u32(attr); + } else if (type == ETHTOOL_A_PHY_DRVNAME) { + unsigned int len; + + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + + len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr)); + dst->_present.drvname_len = len; + dst->drvname = malloc(len + 1); + memcpy(dst->drvname, mnl_attr_get_str(attr), len); + dst->drvname[len] = 0; + } else if (type == ETHTOOL_A_PHY_NAME) { + unsigned int len; + + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + + len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr)); + dst->_present.name_len = len; + dst->name = malloc(len + 1); + memcpy(dst->name, mnl_attr_get_str(attr), len); + dst->name[len] = 0; + } else if (type == ETHTOOL_A_PHY_UPSTREAM_TYPE) { + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + dst->_present.upstream_type = 1; + dst->upstream_type = mnl_attr_get_u8(attr); + } else if (type == ETHTOOL_A_PHY_UPSTREAM) { + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + dst->_present.upstream = 1; + + parg.rsp_policy = ðtool_phy_upstream_nest; + parg.data = &dst->upstream; + if (ethtool_phy_upstream_parse(&parg, attr)) + return MNL_CB_ERROR; + } else if (type == ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME) { + unsigned int len; + + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + + len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr)); + dst->_present.downstream_sfp_name_len = len; + dst->downstream_sfp_name = malloc(len + 1); + memcpy(dst->downstream_sfp_name, mnl_attr_get_str(attr), len); + dst->downstream_sfp_name[len] = 0; + } else if (type == ETHTOOL_A_PHY_ID) { + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + dst->_present.id = 1; + dst->id = mnl_attr_get_u32(attr); + } + } + + return MNL_CB_OK; +} + +struct ethtool_phy_get_rsp * +ethtool_phy_get(struct ynl_sock *ys, struct ethtool_phy_get_req *req) +{ + struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; + struct ethtool_phy_get_rsp *rsp; + struct nlmsghdr *nlh; + int err; + + nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_PHY_GET, 1); + ys->req_policy = ðtool_phy_nest; + yrs.yarg.rsp_policy = ðtool_phy_nest; + + if (req->_present.header) + ethtool_header_put(nlh, ETHTOOL_A_PHY_HEADER, &req->header); + + rsp = calloc(1, sizeof(*rsp)); + yrs.yarg.data = rsp; + yrs.cb = ethtool_phy_get_rsp_parse; + yrs.rsp_cmd = ETHTOOL_MSG_PHY_GET; + + err = ynl_exec(ys, nlh, &yrs); + if (err < 0) + goto err_free; + + return rsp; + +err_free: + ethtool_phy_get_rsp_free(rsp); + return NULL; +} + +/* ETHTOOL_MSG_PHY_GET - dump */ +void ethtool_phy_get_list_free(struct ethtool_phy_get_list *rsp) +{ + struct ethtool_phy_get_list *next = rsp; + + while ((void *)next != YNL_LIST_END) { + rsp = next; + next = rsp->next; + + ethtool_header_free(&rsp->obj.header); + free(rsp->obj.drvname); + free(rsp->obj.name); + ethtool_phy_upstream_free(&rsp->obj.upstream); + free(rsp->obj.downstream_sfp_name); + free(rsp); + } +} + +struct ethtool_phy_get_list * +ethtool_phy_get_dump(struct ynl_sock *ys, struct ethtool_phy_get_req_dump *req) +{ + struct ynl_dump_state yds = {}; + struct nlmsghdr *nlh; + int err; + + yds.ys = ys; + yds.alloc_sz = sizeof(struct ethtool_phy_get_list); + yds.cb = ethtool_phy_get_rsp_parse; + yds.rsp_cmd = ETHTOOL_MSG_PHY_GET; + yds.rsp_policy = ðtool_phy_nest; + + nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_PHY_GET, 1); + ys->req_policy = ðtool_phy_nest; + + if (req->_present.header) + ethtool_header_put(nlh, ETHTOOL_A_PHY_HEADER, &req->header); + + err = ynl_exec_dump(ys, nlh, &yds); + if (err < 0) + goto free_list; + + return yds.first; + +free_list: + ethtool_phy_get_list_free(yds.first); + return NULL; +} + /* ETHTOOL_MSG_CABLE_TEST_NTF - event */ int ethtool_cable_test_ntf_rsp_parse(const struct nlmsghdr *nlh, void *data) { diff --git a/tools/net/ynl/generated/ethtool-user.h b/tools/net/ynl/generated/ethtool-user.h index 97c079c0f332..59ebb0a1a09f 100644 --- a/tools/net/ynl/generated/ethtool-user.h +++ b/tools/net/ynl/generated/ethtool-user.h @@ -20,6 +20,7 @@ extern const struct ynl_family ynl_ethtool_family; const char *ethtool_op_str(int op); const char *ethtool_udp_tunnel_type_str(int value); const char *ethtool_stringset_str(enum ethtool_stringset value); +const char *ethtool_phy_upstream_type_str(int value); /* Common nested types */ struct ethtool_header { @@ -90,6 +91,16 @@ struct ethtool_mm_stat { __u64 hold_count; }; +struct ethtool_phy_upstream { + struct { + __u32 index:1; + __u32 sfp_name_len; + } _present; + + __u32 index; + char *sfp_name; +}; + struct ethtool_cable_result { struct { __u32 pair:1; @@ -6018,6 +6029,148 @@ ethtool_mm_set_req_set_tx_min_frag_size(struct ethtool_mm_set_req *req, */ int ethtool_mm_set(struct ynl_sock *ys, struct ethtool_mm_set_req *req); +/* ============== ETHTOOL_MSG_PHY_GET ============== */ +/* ETHTOOL_MSG_PHY_GET - do */ +struct ethtool_phy_get_req { + struct { + __u32 header:1; + } _present; + + struct ethtool_header header; +}; + +static inline struct ethtool_phy_get_req *ethtool_phy_get_req_alloc(void) +{ + return calloc(1, sizeof(struct ethtool_phy_get_req)); +} +void ethtool_phy_get_req_free(struct ethtool_phy_get_req *req); + +static inline void +ethtool_phy_get_req_set_header_dev_index(struct ethtool_phy_get_req *req, + __u32 dev_index) +{ + req->_present.header = 1; + req->header._present.dev_index = 1; + req->header.dev_index = dev_index; +} +static inline void +ethtool_phy_get_req_set_header_dev_name(struct ethtool_phy_get_req *req, + const char *dev_name) +{ + free(req->header.dev_name); + req->header._present.dev_name_len = strlen(dev_name); + req->header.dev_name = malloc(req->header._present.dev_name_len + 1); + memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len); + req->header.dev_name[req->header._present.dev_name_len] = 0; +} +static inline void +ethtool_phy_get_req_set_header_flags(struct ethtool_phy_get_req *req, + __u32 flags) +{ + req->_present.header = 1; + req->header._present.flags = 1; + req->header.flags = flags; +} +static inline void +ethtool_phy_get_req_set_header_phy_index(struct ethtool_phy_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} + +struct ethtool_phy_get_rsp { + struct { + __u32 header:1; + __u32 index:1; + __u32 drvname_len; + __u32 name_len; + __u32 upstream_type:1; + __u32 upstream:1; + __u32 downstream_sfp_name_len; + __u32 id:1; + } _present; + + struct ethtool_header header; + __u32 index; + char *drvname; + char *name; + __u8 upstream_type; + struct ethtool_phy_upstream upstream; + char *downstream_sfp_name; + __u32 id; +}; + +void ethtool_phy_get_rsp_free(struct ethtool_phy_get_rsp *rsp); + +/* + * Get PHY devices attached to an interface + */ +struct ethtool_phy_get_rsp * +ethtool_phy_get(struct ynl_sock *ys, struct ethtool_phy_get_req *req); + +/* ETHTOOL_MSG_PHY_GET - dump */ +struct ethtool_phy_get_req_dump { + struct { + __u32 header:1; + } _present; + + struct ethtool_header header; +}; + +static inline struct ethtool_phy_get_req_dump * +ethtool_phy_get_req_dump_alloc(void) +{ + return calloc(1, sizeof(struct ethtool_phy_get_req_dump)); +} +void ethtool_phy_get_req_dump_free(struct ethtool_phy_get_req_dump *req); + +static inline void +ethtool_phy_get_req_dump_set_header_dev_index(struct ethtool_phy_get_req_dump *req, + __u32 dev_index) +{ + req->_present.header = 1; + req->header._present.dev_index = 1; + req->header.dev_index = dev_index; +} +static inline void +ethtool_phy_get_req_dump_set_header_dev_name(struct ethtool_phy_get_req_dump *req, + const char *dev_name) +{ + free(req->header.dev_name); + req->header._present.dev_name_len = strlen(dev_name); + req->header.dev_name = malloc(req->header._present.dev_name_len + 1); + memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len); + req->header.dev_name[req->header._present.dev_name_len] = 0; +} +static inline void +ethtool_phy_get_req_dump_set_header_flags(struct ethtool_phy_get_req_dump *req, + __u32 flags) +{ + req->_present.header = 1; + req->header._present.flags = 1; + req->header.flags = flags; +} +static inline void +ethtool_phy_get_req_dump_set_header_phy_index(struct ethtool_phy_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} + +struct ethtool_phy_get_list { + struct ethtool_phy_get_list *next; + struct ethtool_phy_get_rsp obj __attribute__((aligned(8))); +}; + +void ethtool_phy_get_list_free(struct ethtool_phy_get_list *rsp); + +struct ethtool_phy_get_list * +ethtool_phy_get_dump(struct ynl_sock *ys, struct ethtool_phy_get_req_dump *req); + /* ETHTOOL_MSG_CABLE_TEST_NTF - event */ struct ethtool_cable_test_ntf_rsp { struct { From patchwork Fri Dec 1 16:36:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Chevallier X-Patchwork-Id: 13476149 X-Patchwork-Delegate: kuba@kernel.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="UA1HpYof" Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::226]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0FA741720; Fri, 1 Dec 2023 08:37:21 -0800 (PST) Received: by mail.gandi.net (Postfix) with ESMTPSA id 58161C000A; Fri, 1 Dec 2023 16:37:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1701448640; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=2tgWKDF7KvzEfYVSrBqsu+zgRG5hS2mMQT/44TU8PoA=; b=UA1HpYofn7CvVW1jmM9rDVxW4KmPR9Z26Y4X3G6WvpkQQl2tXn1GnogxZzYQv9L/reEgLK sZdBjXs1QOy3yVo7a0wYCEYlu9UwHvuQl01hzZO0W6gNCZbiG+iJcjMdW3luIVLnTPDAB1 CfieVJVvwNxMaaq5jJxewiTtCKyESPDKxfRwH5k487OuXqgPe2/k2CqI81EydjGxZmULDR 7neV7UZ6oTHSmkKgbqDg4XwJFjROPE7AdpI43n1Zf3uDC1zFDajWDB7MYmJJlSz3A21lCM Ty5zGelhS7j1QUUun6c8e5zrhhvWDiSr/yCaxHquPczbhCcRERbaAbWwrOeidg== From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Russell King , linux-arm-kernel@lists.infradead.org, Christophe Leroy , Herve Codina , Florian Fainelli , Heiner Kallweit , Vladimir Oltean , =?utf-8?q?K=C3=B6ry_Maincent?= , Jesse Brandeburg , Jonathan Corbet , =?utf-8?q?Marek_Beh=C3=BAn?= , Piergiorgio Beruto , Oleksij Rempel , =?utf-8?q?Nicol=C3=B2_Veronese?= Subject: [RFC PATCH net-next v3 09/13] net: ethtool: plca: Target the command to the requested PHY Date: Fri, 1 Dec 2023 17:36:59 +0100 Message-ID: <20231201163704.1306431-10-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> References: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: maxime.chevallier@bootlin.com X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC PLCA is a PHY-specific command. Instead of targeting the command towards dev->phydev, use the request to pick the targeted PHY. Signed-off-by: Maxime Chevallier --- V3: No changes V2: New patch net/ethtool/plca.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/net/ethtool/plca.c b/net/ethtool/plca.c index b1e2e3b5027f..2b3e419f4dc2 100644 --- a/net/ethtool/plca.c +++ b/net/ethtool/plca.c @@ -61,7 +61,7 @@ static int plca_get_cfg_prepare_data(const struct ethnl_req_info *req_base, int ret; // check that the PHY device is available and connected - if (!dev->phydev) { + if (!req_base->phydev) { ret = -EOPNOTSUPP; goto out; } @@ -80,7 +80,7 @@ static int plca_get_cfg_prepare_data(const struct ethnl_req_info *req_base, memset(&data->plca_cfg, 0xff, sizeof_field(struct plca_reply_data, plca_cfg)); - ret = ops->get_plca_cfg(dev->phydev, &data->plca_cfg); + ret = ops->get_plca_cfg(req_base->phydev, &data->plca_cfg); ethnl_ops_complete(dev); out: @@ -141,7 +141,6 @@ const struct nla_policy ethnl_plca_set_cfg_policy[] = { static int ethnl_set_plca(struct ethnl_req_info *req_info, struct genl_info *info) { - struct net_device *dev = req_info->dev; const struct ethtool_phy_ops *ops; struct nlattr **tb = info->attrs; struct phy_plca_cfg plca_cfg; @@ -149,7 +148,7 @@ ethnl_set_plca(struct ethnl_req_info *req_info, struct genl_info *info) int ret; // check that the PHY device is available and connected - if (!dev->phydev) + if (!req_info->phydev) return -EOPNOTSUPP; ops = ethtool_phy_ops; @@ -168,7 +167,7 @@ ethnl_set_plca(struct ethnl_req_info *req_info, struct genl_info *info) if (!mod) return 0; - ret = ops->set_plca_cfg(dev->phydev, &plca_cfg, info->extack); + ret = ops->set_plca_cfg(req_info->phydev, &plca_cfg, info->extack); return ret < 0 ? ret : 1; } @@ -204,7 +203,7 @@ static int plca_get_status_prepare_data(const struct ethnl_req_info *req_base, int ret; // check that the PHY device is available and connected - if (!dev->phydev) { + if (!req_base->phydev) { ret = -EOPNOTSUPP; goto out; } @@ -223,7 +222,7 @@ static int plca_get_status_prepare_data(const struct ethnl_req_info *req_base, memset(&data->plca_st, 0xff, sizeof_field(struct plca_reply_data, plca_st)); - ret = ops->get_plca_status(dev->phydev, &data->plca_st); + ret = ops->get_plca_status(req_base->phydev, &data->plca_st); ethnl_ops_complete(dev); out: return ret; From patchwork Fri Dec 1 16:37:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Chevallier X-Patchwork-Id: 13476151 X-Patchwork-Delegate: kuba@kernel.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="mCogDkwR" Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::226]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3251F1729; Fri, 1 Dec 2023 08:37:23 -0800 (PST) Received: by mail.gandi.net (Postfix) with ESMTPSA id A9F93C0009; Fri, 1 Dec 2023 16:37:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1701448641; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=b2iCt+luKYahOq6OV4Eg/c860F9iD1WGePLyjS+PCBc=; b=mCogDkwRw9OjEg7OeiqqEdRtmZhsqFny2PFW4D6ReZSd2JxleqkLbcSdjWbLgTQzw77duq jimPjPo5TAdThkJU1M1rZ2WgiqGkm7/WhNroXN+HSOnApVUP7AuVIOZgvvlCmZkdy3PzlD jrXHrfwquKCNy62ZrMi1TA/W4P9jFHxA5pIDWupJnQnKKuhVT2DyF/FPGi8RugzERWaAYu CDO3WW8fJJPFOMCXQIJbM5+POjyi5GP8G6RN5vdrc7JFPiLQXkVJxLnhXxw+7u+uGzXqdT pf7feHg5B5pxplETU1DozHmqJoTLCnkLlib5V4adErR4MPdmwl81BLirc2l/lQ== From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Russell King , linux-arm-kernel@lists.infradead.org, Christophe Leroy , Herve Codina , Florian Fainelli , Heiner Kallweit , Vladimir Oltean , =?utf-8?q?K=C3=B6ry_Maincent?= , Jesse Brandeburg , Jonathan Corbet , =?utf-8?q?Marek_Beh=C3=BAn?= , Piergiorgio Beruto , Oleksij Rempel , =?utf-8?q?Nicol=C3=B2_Veronese?= Subject: [RFC PATCH net-next v3 10/13] net: ethtool: pse-pd: Target the command to the requested PHY Date: Fri, 1 Dec 2023 17:37:00 +0100 Message-ID: <20231201163704.1306431-11-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> References: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: maxime.chevallier@bootlin.com X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC PSE and PD configuration is a PHY-specific command. Instead of targeting the command towards dev->phydev, use the request to pick the targeted PHY device. Signed-off-by: Maxime Chevallier --- V3: No changes V2: New patch net/ethtool/pse-pd.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/net/ethtool/pse-pd.c b/net/ethtool/pse-pd.c index cc478af77111..0d9cd9c87104 100644 --- a/net/ethtool/pse-pd.c +++ b/net/ethtool/pse-pd.c @@ -31,17 +31,10 @@ const struct nla_policy ethnl_pse_get_policy[ETHTOOL_A_PSE_HEADER + 1] = { [ETHTOOL_A_PSE_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy), }; -static int pse_get_pse_attributes(struct net_device *dev, +static int pse_get_pse_attributes(struct phy_device *phydev, struct netlink_ext_ack *extack, struct pse_reply_data *data) { - struct phy_device *phydev = dev->phydev; - - if (!phydev) { - NL_SET_ERR_MSG(extack, "No PHY is attached"); - return -EOPNOTSUPP; - } - if (!phydev->psec) { NL_SET_ERR_MSG(extack, "No PSE is attached"); return -EOPNOTSUPP; @@ -64,7 +57,7 @@ static int pse_prepare_data(const struct ethnl_req_info *req_base, if (ret < 0) return ret; - ret = pse_get_pse_attributes(dev, info->extack, data); + ret = pse_get_pse_attributes(req_base->phydev, info->extack, data); ethnl_ops_complete(dev); @@ -124,7 +117,6 @@ ethnl_set_pse_validate(struct ethnl_req_info *req_info, struct genl_info *info) static int ethnl_set_pse(struct ethnl_req_info *req_info, struct genl_info *info) { - struct net_device *dev = req_info->dev; struct pse_control_config config = {}; struct nlattr **tb = info->attrs; struct phy_device *phydev; @@ -132,7 +124,7 @@ ethnl_set_pse(struct ethnl_req_info *req_info, struct genl_info *info) /* this values are already validated by the ethnl_pse_set_policy */ config.admin_cotrol = nla_get_u32(tb[ETHTOOL_A_PODL_PSE_ADMIN_CONTROL]); - phydev = dev->phydev; + phydev = req_info->phydev; if (!phydev) { NL_SET_ERR_MSG(info->extack, "No PHY is attached"); return -EOPNOTSUPP; From patchwork Fri Dec 1 16:37:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Chevallier X-Patchwork-Id: 13476153 X-Patchwork-Delegate: kuba@kernel.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="DowcDovD" Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 74B21173A; Fri, 1 Dec 2023 08:37:24 -0800 (PST) Received: by mail.gandi.net (Postfix) with ESMTPSA id E913EC000E; Fri, 1 Dec 2023 16:37:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1701448643; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=IrIqVHTv4OFpjH8swPAPtlm1OVsBZBIxDm7JNwM2hes=; b=DowcDovDfXhbCr83jjB6+e7vCvtHLWw+3yqvIj8oZU1U0KnCUh8eJ6SZcQv1B80liC7gQ4 VnIikbXDRGHTlL/9OIYmyydIer/u5RE8jXn+MPtZ96JT0ROkwyAjy87cGAfWTmtbPmAzgZ SkZ2hjw5KQS+rbXvQLZzG2uTuevCsaWMj1kApe609ZFEyJp2T9tTes0lAI/PJS0w3VY1jT 7sFcU5hqDulKniBa3Z93qCjqFWrusADdrMNHUEWgSzYWO9Wl3nKZx0C9F7KrjWnqNXrhxS J7Q3oRa+nZC0l4LgqafpwL2DywD3wPRM/QEpWfrsWGW3FKJYjEws4sN8/I5ELg== From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Russell King , linux-arm-kernel@lists.infradead.org, Christophe Leroy , Herve Codina , Florian Fainelli , Heiner Kallweit , Vladimir Oltean , =?utf-8?q?K=C3=B6ry_Maincent?= , Jesse Brandeburg , Jonathan Corbet , =?utf-8?q?Marek_Beh=C3=BAn?= , Piergiorgio Beruto , Oleksij Rempel , =?utf-8?q?Nicol=C3=B2_Veronese?= Subject: [RFC PATCH net-next v3 11/13] net: ethtool: cable-test: Target the command to the requested PHY Date: Fri, 1 Dec 2023 17:37:01 +0100 Message-ID: <20231201163704.1306431-12-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> References: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: maxime.chevallier@bootlin.com X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Cable testing is a PHY-specific command. Instead of targeting the command towards dev->phydev, use the request to pick the targeted PHY. Signed-off-by: Maxime Chevallier --- V3: No changes V2: New patch net/ethtool/cabletest.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/net/ethtool/cabletest.c b/net/ethtool/cabletest.c index 06a151165c31..6b00d0800f23 100644 --- a/net/ethtool/cabletest.c +++ b/net/ethtool/cabletest.c @@ -69,7 +69,7 @@ int ethnl_act_cable_test(struct sk_buff *skb, struct genl_info *info) return ret; dev = req_info.dev; - if (!dev->phydev) { + if (!req_info.phydev) { ret = -EOPNOTSUPP; goto out_dev_put; } @@ -85,12 +85,12 @@ int ethnl_act_cable_test(struct sk_buff *skb, struct genl_info *info) if (ret < 0) goto out_rtnl; - ret = ops->start_cable_test(dev->phydev, info->extack); + ret = ops->start_cable_test(req_info.phydev, info->extack); ethnl_ops_complete(dev); if (!ret) - ethnl_cable_test_started(dev->phydev, + ethnl_cable_test_started(req_info.phydev, ETHTOOL_MSG_CABLE_TEST_NTF); out_rtnl: @@ -321,7 +321,7 @@ int ethnl_act_cable_test_tdr(struct sk_buff *skb, struct genl_info *info) return ret; dev = req_info.dev; - if (!dev->phydev) { + if (!req_info.phydev) { ret = -EOPNOTSUPP; goto out_dev_put; } @@ -342,12 +342,12 @@ int ethnl_act_cable_test_tdr(struct sk_buff *skb, struct genl_info *info) if (ret < 0) goto out_rtnl; - ret = ops->start_cable_test_tdr(dev->phydev, info->extack, &cfg); + ret = ops->start_cable_test_tdr(req_info.phydev, info->extack, &cfg); ethnl_ops_complete(dev); if (!ret) - ethnl_cable_test_started(dev->phydev, + ethnl_cable_test_started(req_info.phydev, ETHTOOL_MSG_CABLE_TEST_TDR_NTF); out_rtnl: From patchwork Fri Dec 1 16:37:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Chevallier X-Patchwork-Id: 13476154 X-Patchwork-Delegate: kuba@kernel.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="HV8EfGS9" Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AED881986; Fri, 1 Dec 2023 08:37:25 -0800 (PST) Received: by mail.gandi.net (Postfix) with ESMTPSA id 37CBEC0011; Fri, 1 Dec 2023 16:37:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1701448644; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=qP/8ocJ/dqKsRX12Co8UhuKkpSAILqQvsIAG4JFJivY=; b=HV8EfGS9wM/gOZEFEKMlraKNu+2YD9V7H4ldYc8vosNV28+YFXs73h5JIYoNsOeSDf8u2W ksDAF5Rp5nf2e4hOOSWH9a+dnizwnvAGYbIEjygeAwSLPOer7olFQmTICbyoZNKQ761XIu Y27AW0SWZav3FUqchfQUpA571ysXXhfOlg5YZfV1ixTh8qh2HFWELNTK771UZtxrb2HORi 20691dNwP23xU9rZs/NH/baBiryYSnmhYJdM0WichEzpYORMG+cutfvBKhTZlOhU8Ts2rp sEaMQJaryhauKnsmun3liC6ZuXgKKZPmTkw107rkWlGNNLKGFr646aFXdrwz1g== From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Russell King , linux-arm-kernel@lists.infradead.org, Christophe Leroy , Herve Codina , Florian Fainelli , Heiner Kallweit , Vladimir Oltean , =?utf-8?q?K=C3=B6ry_Maincent?= , Jesse Brandeburg , Jonathan Corbet , =?utf-8?q?Marek_Beh=C3=BAn?= , Piergiorgio Beruto , Oleksij Rempel , =?utf-8?q?Nicol=C3=B2_Veronese?= Subject: [RFC PATCH net-next v3 12/13] net: ethtool: strset: Allow querying phy stats by index Date: Fri, 1 Dec 2023 17:37:02 +0100 Message-ID: <20231201163704.1306431-13-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> References: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: maxime.chevallier@bootlin.com X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC The ETH_SS_PHY_STATS command gets PHY statistics. Use the phydev pointer from the ethnl request to allow query phy stats from each PHY on the link. Signed-off-by: Maxime Chevallier --- V3: No changes V2: New patch net/ethtool/strset.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/net/ethtool/strset.c b/net/ethtool/strset.c index c678b484a079..70c00631c51f 100644 --- a/net/ethtool/strset.c +++ b/net/ethtool/strset.c @@ -233,17 +233,18 @@ static void strset_cleanup_data(struct ethnl_reply_data *reply_base) } static int strset_prepare_set(struct strset_info *info, struct net_device *dev, - unsigned int id, bool counts_only) + struct phy_device *phydev, unsigned int id, + bool counts_only) { const struct ethtool_phy_ops *phy_ops = ethtool_phy_ops; const struct ethtool_ops *ops = dev->ethtool_ops; void *strings; int count, ret; - if (id == ETH_SS_PHY_STATS && dev->phydev && + if (id == ETH_SS_PHY_STATS && phydev && !ops->get_ethtool_phy_stats && phy_ops && phy_ops->get_sset_count) - ret = phy_ops->get_sset_count(dev->phydev); + ret = phy_ops->get_sset_count(phydev); else if (ops->get_sset_count && ops->get_strings) ret = ops->get_sset_count(dev, id); else @@ -258,10 +259,10 @@ static int strset_prepare_set(struct strset_info *info, struct net_device *dev, strings = kcalloc(count, ETH_GSTRING_LEN, GFP_KERNEL); if (!strings) return -ENOMEM; - if (id == ETH_SS_PHY_STATS && dev->phydev && + if (id == ETH_SS_PHY_STATS && phydev && !ops->get_ethtool_phy_stats && phy_ops && phy_ops->get_strings) - phy_ops->get_strings(dev->phydev, strings); + phy_ops->get_strings(phydev, strings); else ops->get_strings(dev, id, strings); info->strings = strings; @@ -305,8 +306,8 @@ static int strset_prepare_data(const struct ethnl_req_info *req_base, !data->sets[i].per_dev) continue; - ret = strset_prepare_set(&data->sets[i], dev, i, - req_info->counts_only); + ret = strset_prepare_set(&data->sets[i], dev, req_base->phydev, + i, req_info->counts_only); if (ret < 0) goto err_ops; } From patchwork Fri Dec 1 16:37:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Chevallier X-Patchwork-Id: 13476155 X-Patchwork-Delegate: kuba@kernel.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="JFMrE9ig" Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 601C019B9; Fri, 1 Dec 2023 08:37:27 -0800 (PST) Received: by mail.gandi.net (Postfix) with ESMTPSA id 7CAA1C0005; Fri, 1 Dec 2023 16:37:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1701448645; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Zkn3WcoWgpmwL6HOZQplo2JHjoZL6UnLU3cm1imhSbo=; b=JFMrE9igbAfRsBHjn2eHGVHiMZar+QKPiWyK9OTG3p75DXV1HarHSHpQmhsiC+DxHlGO7Y EFPQkl1ICPsdMdGysAGOXOmgy5Ez8pavrFYCuuBTrgFYEbQECjrghK/qXSOvruVZMVvOUj tAOlSc/eMCexhkirlfEdYgETbEu008DT8cYlflnKTk2I6ZLwi0w89m/s9gYLCcIeV7QikB F5Dw8M+TUarzW0meKb7WUVlltV05b/umQIVHXd4PMF7ypDnPcj6iNLfb0l18TQaUUBUIv4 K4Dvyn1c0wJnOe+hB4udi4esNdBqHVrEjPTUFNFZp1SKN6DZhf2Uk4kz7ImoPw== From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Russell King , linux-arm-kernel@lists.infradead.org, Christophe Leroy , Herve Codina , Florian Fainelli , Heiner Kallweit , Vladimir Oltean , =?utf-8?q?K=C3=B6ry_Maincent?= , Jesse Brandeburg , Jonathan Corbet , =?utf-8?q?Marek_Beh=C3=BAn?= , Piergiorgio Beruto , Oleksij Rempel , =?utf-8?q?Nicol=C3=B2_Veronese?= Subject: [RFC PATCH net-next v3 13/13] Documentation: networking: document phy_link_topology Date: Fri, 1 Dec 2023 17:37:03 +0100 Message-ID: <20231201163704.1306431-14-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> References: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: maxime.chevallier@bootlin.com X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC The newly introduced phy_link_topology tracks all ethernet PHYs that are attached to a netdevice. Document the base principle, internal and external APIs. As the phy_link_topology is expected to be extended, this documentation will hold any further improvements and additions made relative to topology handling. Signed-off-by: Maxime Chevallier --- V3: New patch Documentation/networking/index.rst | 1 + .../networking/phy-link-topology.rst | 121 ++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 Documentation/networking/phy-link-topology.rst diff --git a/Documentation/networking/index.rst b/Documentation/networking/index.rst index cb435c141794..e472d53f933a 100644 --- a/Documentation/networking/index.rst +++ b/Documentation/networking/index.rst @@ -87,6 +87,7 @@ Contents: operstates packet_mmap phonet + phy-link-topology pktgen plip ppp_generic diff --git a/Documentation/networking/phy-link-topology.rst b/Documentation/networking/phy-link-topology.rst new file mode 100644 index 000000000000..d66ee9711ac1 --- /dev/null +++ b/Documentation/networking/phy-link-topology.rst @@ -0,0 +1,121 @@ +.. SPDX-License-Identifier: GPL-2.0 + +================= +PHY link topology +================= + +Overview +======== + +The PHY link topology representation in the networking stack aims at representing +the hardware layout for any given Ethernet link. + +An Ethernet Interface from userspace's poing of view is nothing but a +:c:type:`struct net_device `, which exposes configuration options +trough the legacy ioctls and the ethool netlink commands. The base assumption +when designing these configuration channels were that the link looked +something like this :: + + +-----------------------+ +----------+ +--------------+ + | Ethernet Controller / | | Ethernet | | Connector / | + | MAC | ------ | PHY | ---- | Port | ---... to LP + +-----------------------+ +----------+ +--------------+ + struct net_device struct phy_device + +Commands that needs to configure the PHY will go through the net_device.phydev +field to reach the PHY and perform the relevant configuration. + +This assumption falls appart in more complex topologies that can arise when, +for example, using SFP transceivers (although that's not the only specific case). + +Here, we have 2 basic scenarios. Either the MAC is able to output a serialized +interface, that can directly be fed to an SFP cage, such as SGMII, 1000BaseX, +10GBaseR, etc. + +The link topology then looks like this (when an SFP module is inserted) :: + + +-----+ SGMII +------------+ + | MAC | ------- | SFP Module | + +-----+ +------------+ + +Knowing that some modules embed a PHY, the actual link is more like :: + + +-----+ SGMII +--------------+ + | MAC | -------- | PHY (on SFP) | + +-----+ +--------------+ + +In this case, the SFP PHY is handled by phylib, and registered by phylink through +its SFP upstream ops. + +Now some Ethernet controllers aren't able to output a serialized interface, so +we can't directly connect them to an SFP cage. However, some PHYs can be used +as media-converters, to translate the non-serialized MAC MII interface to a +serialized MII interface fed to the SFP :: + + +-----+ RGMII +-----------------------+ SGMII +--------------+ + | MAC | ------- | PHY (media converter) | ------- | PHY (on SFP) | + +-----+ +-----------------------+ +--------------+ + +This is where the model of having a single net_device.phydev pointer shows its +limitations, as we now have 2 PHYs on the link. + +The phy_link topology framework aims at providing a way to keep track of every +PHY on the link, for use by both kernel drivers and subsystems, but also to +report the topology to userspace, allowing to target individual PHYs in configuration +commands. + +API +=== + +The :c:type:`struct phy_link_topology ` is a per-netdevice +resource, that gets initialized at netdevice creation. Once it's initialized, +it is then possible to register PHYs to the topology through : + +:c:func:`phy_link_topo_add_phy` + +Besides registering the PHY to the topology, this call will also assign a unique +index to the PHY, which can then be reported to userspace to refer to this PHY +(akin to the ifindex). This index is a u32, ranging from 1 to U32_MAX. The value +0 is reserved to indicate the PHY doesn't belong to any topology yet. + +The PHY can then be removed from the topology through + +:c:func:`phy_link_topo_del_phy` + +These function are already hooked into the phylib subsystem, so all PHYs that +are linked to a net_device through :c:func:`phy_attach_direct` will automatically +join the netdev's topology. + +PHYs that are on a SFP module will also be automatically registered IF the SFP +upstream is phylink (so, no media-converter). + +PHY drivers that can be used as SFP upstream need to call :c:func:`phy_sfp_attach_phy` +and :c:func:`phy_sfp_detach_phy`, which can be used as a +.attach_phy / .detach_phy implementation for the +:c:type:`struct sfp_upstream_ops `. + +UAPI +==== + +There exist a set of netlink commands to query the link topology from userspace, +see ``Documentation/networking/ethtool-netlink.rst``. + +The whole point of having a topology representation is to assign the phyindex +field in :c:type:`struct phy_device `. This index is reported to +userspace using the ``ETHTOOL_MSG_PHY_GET`` ethtnl command. Performing a DUMP operation +will result in all PHYs from all net_device being listed. The DUMP command +accepts either a ``ETHTOOL_A_HEADER_DEV_INDEX`` or ``ETHTOOL_A_HEADER_DEV_NAME`` +to be passed in the request to filter the DUMP to a single net_device. + +The retrieved index can then be passed as a request parameter using the +``ETHTOOL_A_HEADER_PHY_INDEX`` field in the following ethnl commands : + +* ``ETHTOOL_MSG_STRSET_GET`` to get the stats strig set from a given PHY +* ``ETHTOOL_MSG_CABLE_TEST_ACT`` and ``ETHTOOL_MSG_CABLE_TEST_ACT``, to perform + cable testing on a given PHY on the link (most likely the outermost PHY) +* ``ETHTOOL_MSG_PSE_SET`` and ``ETHTOOL_MSG_PSE_GET`` for PHY-controlled PoE and PSE settings +* ``ETHTOOL_MSG_PLCA_GET_CFG``, ``ETHTOOL_MSG_PLCA_SET_CFG`` and ``ETHTOOL_MSG_PLCA_GET_STATUS`` + to set the PLCA (Physical Layer Collision Avoidance) parameters + +Note that the PHY index can be passed to other requests, which will silently +ignore it if present and irrelevant.