From patchwork Thu Sep 7 09:23: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: 13376518 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9A24229B4 for ; Thu, 7 Sep 2023 15:35:35 +0000 (UTC) Received: from mslow1.mail.gandi.net (mslow1.mail.gandi.net [217.70.178.240]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2DC691BFA; Thu, 7 Sep 2023 08:35:19 -0700 (PDT) Received: from relay2-d.mail.gandi.net (unknown [217.70.183.194]) by mslow1.mail.gandi.net (Postfix) with ESMTP id D6F0BD6694; Thu, 7 Sep 2023 09:24:35 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPSA id 63D5B40004; Thu, 7 Sep 2023 09:24:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1694078653; 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=omfLr8sHaUj1FxSEZuFWzZWjI2Jn7oLXwE8BQG3Uhp8=; b=oHYORDdIfpnMH3f6Ld4RU9ozCfffa0NmjANliebtJ6ZZSgX/hhg+YakgBM0eY6AXN8hGSE phtGfAYfHjnoH6PfbAQuSm+gegpE+ZHAgELFetifhoCLj/auGRHpGhWiJV5LTVzlIxuVwy RaWIO5EeFQYgU48hIkAoPc4HtXeZAvxYgWdfsIURx8U0qkU1sKiP48v21yMLYh+fHQZsOX 0TTbmQT0WJb+OZsf26bNRoM/kou/RLVKd92/xEjUzDNbS9Lbwk+0R+l89q1HuAGSzXJ221 0+3AeSclcTWtjfUj17lo2r8KFM3Vc8G92WKYUfzk4q5KDQDmzJfGP3AVSNE0zA== From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Florian Fainelli , Heiner Kallweit , Russell King , Vladimir Oltean , Oleksij Rempel , =?utf-8?q?Nicol=C3=B2_Veronese?= , thomas.petazzoni@bootlin.com, Christophe Leroy Subject: [RFC PATCH net-next 1/7] net: phy: introduce phy numbering and phy namespaces Date: Thu, 7 Sep 2023 11:23:59 +0200 Message-ID: <20230907092407.647139-2-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230907092407.647139-1-maxime.chevallier@bootlin.com> References: <20230907092407.647139-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-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_BLOCKED, SPF_HELO_PASS,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net 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, hence the notion of PHY namespaces. 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 --- drivers/net/phy/Makefile | 2 +- drivers/net/phy/phy_device.c | 13 ++++++++ drivers/net/phy/phy_ns.c | 65 ++++++++++++++++++++++++++++++++++++ include/linux/netdevice.h | 2 ++ include/linux/phy.h | 4 +++ include/linux/phy_ns.h | 30 +++++++++++++++++ net/core/dev.c | 3 ++ 7 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 drivers/net/phy/phy_ns.c create mode 100644 include/linux/phy_ns.h diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index c945ed9bd14b..baa95d9f24e4 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_ns.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 2ce74593d6e4..0c029ae5130a 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_namespace *phy_get_ns(struct phy_device *phydev) +{ + if (phydev->attached_dev) + return &phydev->attached_dev->phy_ns; + + return NULL; +} + static LIST_HEAD(phy_fixup_list); static DEFINE_MUTEX(phy_fixup_lock); @@ -677,6 +686,7 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, u32 phy_id, dev->state = PHY_DOWN; INIT_LIST_HEAD(&dev->leds); + INIT_LIST_HEAD(&dev->node); mutex_init(&dev->lock); INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine); @@ -1489,6 +1499,8 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, if (phydev->sfp_bus_attached) dev->sfp_bus = phydev->sfp_bus; + + phy_ns_add_phy(&dev->phy_ns, phydev); } /* Some Ethernet drivers try to connect to a PHY device before @@ -1814,6 +1826,7 @@ void phy_detach(struct phy_device *phydev) if (dev) { phydev->attached_dev->phydev = NULL; phydev->attached_dev = NULL; + phy_ns_del_phy(&dev->phy_ns, phydev); } phydev->phylink = NULL; diff --git a/drivers/net/phy/phy_ns.c b/drivers/net/phy/phy_ns.c new file mode 100644 index 000000000000..d7865028ab20 --- /dev/null +++ b/drivers/net/phy/phy_ns.c @@ -0,0 +1,65 @@ +// 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 + +static int phy_ns_next_phyindex(struct phy_namespace *phy_ns) +{ + int phyindex = phy_ns->last_attributed_index; + + for (;;) { + if (++phyindex <= 0) + phyindex = 1; + if (!phy_ns_get_by_index(phy_ns, phyindex)) + return phy_ns->last_attributed_index = phyindex; + } +} + +struct phy_device *phy_ns_get_by_index(struct phy_namespace *phy_ns, + int phyindex) +{ + struct phy_device *phy; + + mutex_lock(&phy_ns->ns_lock); + list_for_each_entry(phy, &phy_ns->phys, node) + if (phy->phyindex == phyindex) + goto unlock; + + phy = NULL; +unlock: + mutex_unlock(&phy_ns->ns_lock); + return phy; +} +EXPORT_SYMBOL_GPL(phy_ns_get_by_index); + +void phy_ns_add_phy(struct phy_namespace *phy_ns, struct phy_device *phy) +{ + /* PHYs can be attached and detached, they will keep their id */ + if (!phy->phyindex) + phy->phyindex = phy_ns_next_phyindex(phy_ns); + + mutex_lock(&phy_ns->ns_lock); + list_add(&phy->node, &phy_ns->phys); + mutex_unlock(&phy_ns->ns_lock); +} +EXPORT_SYMBOL_GPL(phy_ns_add_phy); + +void phy_ns_del_phy(struct phy_namespace *phy_ns, struct phy_device *phy) +{ + mutex_lock(&phy_ns->ns_lock); + list_del(&phy->node); + mutex_unlock(&phy_ns->ns_lock); +} +EXPORT_SYMBOL_GPL(phy_ns_del_phy); + +void phy_ns_init(struct phy_namespace *phy_ns) +{ + INIT_LIST_HEAD(&phy_ns->phys); + mutex_init(&phy_ns->ns_lock); +} diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 0896aaa91dd7..ef86cb87a38a 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -43,6 +43,7 @@ #include #include +#include #include #include #include @@ -2380,6 +2381,7 @@ struct net_device { struct netprio_map __rcu *priomap; #endif struct phy_device *phydev; + struct phy_namespace phy_ns; struct sfp_bus *sfp_bus; struct lock_class_key *qdisc_tx_busylock; bool proto_down; diff --git a/include/linux/phy.h b/include/linux/phy.h index 1351b802ffcf..b12fd33aa84a 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -543,6 +543,8 @@ 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. It's never recycled. * @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 +642,7 @@ struct phy_device { struct device_link *devlink; + int phyindex; u32 phy_id; struct phy_c45_device_ids c45_ids; @@ -761,6 +764,7 @@ struct phy_device { /* MACsec management functions */ const struct macsec_ops *macsec_ops; #endif + struct list_head node; }; /* Generic phy_device::dev_flags */ diff --git a/include/linux/phy_ns.h b/include/linux/phy_ns.h new file mode 100644 index 000000000000..ae173e637c62 --- /dev/null +++ b/include/linux/phy_ns.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * PHY device namespaces 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_NS_H +#define __PHY_NS_H + +struct mutex; + +struct phy_namespace { + struct list_head phys; + int last_attributed_index; + + /* Protects the .phys list */ + struct mutex ns_lock; +}; + +struct phy_device *phy_ns_get_by_index(struct phy_namespace *phy_ns, + int phyindex); +void phy_ns_add_phy(struct phy_namespace *phy_ns, struct phy_device *phy); +void phy_ns_del_phy(struct phy_namespace *phy_ns, struct phy_device *phy); +void phy_ns_init(struct phy_namespace *phy_ns); + +#endif /* __PHY_NS_H */ diff --git a/net/core/dev.c b/net/core/dev.c index ccff2b6ef958..aa8b924269d7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -10729,6 +10729,9 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, INIT_LIST_HEAD(&dev->net_notifier_list); #ifdef CONFIG_NET_SCHED hash_init(dev->qdisc_hash); +#endif +#ifdef CONFIG_PHYLIB + phy_ns_init(&dev->phy_ns); #endif dev->priv_flags = IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM; setup(dev); From patchwork Thu Sep 7 09:24: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: 13376579 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2574A33FA for ; Thu, 7 Sep 2023 15:53:31 +0000 (UTC) Received: from mslow1.mail.gandi.net (mslow1.mail.gandi.net [IPv6:2001:4b98:dc4:8::240]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C327B6186; Thu, 7 Sep 2023 08:53:02 -0700 (PDT) Received: from relay2-d.mail.gandi.net (unknown [IPv6:2001:4b98:dc4:8::222]) by mslow1.mail.gandi.net (Postfix) with ESMTP id 42C44D6698; Thu, 7 Sep 2023 09:24:36 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPSA id 02F3B40026; Thu, 7 Sep 2023 09:24:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1694078655; 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=ST8KCiLU18FjuUXI8eVuo27uXYnock5GYqmWCIa1nR4=; b=B2uw1Xqtxyilb1NMs7Uhht7byGCRw7f08saTX5jUXL6y5d0gY7TKxRGBqLUAPoaBf6YwDi 7pjdAbtXIqssI1GJYFCjf7QtruKngEEstFCK/IivQYK40uqf18v9lXf0UhCLKparrCGcZ9 wB0JqLFK3oAiloALLvPY6zWfqVX/cPoQTlurkR6P8N+RwxE5LEsrPt5LUcueQ+a2KllPu+ abxq7tOVJXTscBXSVh6bXXZh7NZNz0Ol+8rowJBNoQK4uVqIpav6+w/RDWp4mcpbQNvlPC fJ4oKTcfxharYTBg8OyXDE2ZrGT5zHikDt7A/Lt1/qmbYNEq5Y0GyNw10rGEyw== From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Florian Fainelli , Heiner Kallweit , Russell King , Vladimir Oltean , Oleksij Rempel , =?utf-8?q?Nicol=C3=B2_Veronese?= , thomas.petazzoni@bootlin.com, Christophe Leroy Subject: [RFC PATCH net-next 2/7] net: sfp: pass the phy_device when disconnecting an sfp module's PHY Date: Thu, 7 Sep 2023 11:24:00 +0200 Message-ID: <20230907092407.647139-3-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230907092407.647139-1-maxime.chevallier@bootlin.com> References: <20230907092407.647139-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-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_BLOCKED, SPF_HELO_PASS,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net 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 --- 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 0d7354955d62..97e8019adad8 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -3325,7 +3325,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 208a9393c2df..f42e9a082935 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 Thu Sep 7 09:24: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: 13376513 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0E50312B77 for ; Thu, 7 Sep 2023 15:32:53 +0000 (UTC) Received: from mslow1.mail.gandi.net (mslow1.mail.gandi.net [IPv6:2001:4b98:dc4:8::240]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AEC071FD3; Thu, 7 Sep 2023 08:32:38 -0700 (PDT) Received: from relay2-d.mail.gandi.net (unknown [IPv6:2001:4b98:dc4:8::222]) by mslow1.mail.gandi.net (Postfix) with ESMTP id 34722D677E; Thu, 7 Sep 2023 09:24:39 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPSA id B486940006; Thu, 7 Sep 2023 09:24:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1694078657; 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=NKYGfipofVWW/3g1qYBUmoAQ/1wK2Hf5hr6dKrL514M=; b=ijshBAXsDikrGSk8aI0z3FKVhqzPN3TK04DROLA3/+t4b1AKJrZe0UuyKGZ1uQSs6fXZna lVM95zVnuFR3Hthj9/bdFg7uL3OC95yALhcmjHUI5SgZm0kq9ngmcR2XezdoM9HaJYdCf6 o58wI4ByYcZ4QrXOs8kfX4pek+BDZN3lf/x0nRfdJjajdU8ze1qbT+E0g5ri/YSDczdYIr kv5TQCkfnp4uHuopvMb1M7z3PHoNlGc6uPUw6qLBHRU/ioCj+zTOJrnaXXxSakRCdt7obK p6HWPFaedVdZ3rr/OKZ2apACl8tz6DcbMPlQA9tYHki55WthAAMTecHzCHcIbg== From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Florian Fainelli , Heiner Kallweit , Russell King , Vladimir Oltean , Oleksij Rempel , =?utf-8?q?Nicol=C3=B2_Veronese?= , thomas.petazzoni@bootlin.com, Christophe Leroy Subject: [RFC PATCH net-next 3/7] net: phy: add helpers to handle sfp phy connect/disconnect Date: Thu, 7 Sep 2023 11:24:01 +0200 Message-ID: <20230907092407.647139-4-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230907092407.647139-1-maxime.chevallier@bootlin.com> References: <20230907092407.647139-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-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_BLOCKED, SPF_HELO_PASS,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net 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 --- 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 0c029ae5130a..090c5b14a7b8 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1362,6 +1362,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_namespace *phy_ns = phy_get_ns(phydev); + + if (phy_ns) + phy_ns_add_phy(phy_ns, phy); + + 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_namespace *phy_ns = phy_get_ns(phydev); + + if (phy_ns) + phy_ns_del_phy(phy_ns, 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 b12fd33aa84a..02fdf5075f31 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1720,6 +1720,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 Thu Sep 7 09:24: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: 13376512 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 82C9829AB for ; Thu, 7 Sep 2023 15:32:53 +0000 (UTC) Received: from mslow1.mail.gandi.net (mslow1.mail.gandi.net [217.70.178.240]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2BEAF1BFA; Thu, 7 Sep 2023 08:32:38 -0700 (PDT) Received: from relay2-d.mail.gandi.net (unknown [217.70.183.194]) by mslow1.mail.gandi.net (Postfix) with ESMTP id 32F5BD669E; Thu, 7 Sep 2023 09:24:39 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPSA id 495504002E; Thu, 7 Sep 2023 09:24:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1694078658; 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=cwg8Q82/Dfui3G+s3HaJDAFCq+dngbenMf800j20jak=; b=mFjP3Joj5HVzyaKR4ON3GSwzwwcm2MKoKTz5SmtY/0bReNzaAF0leBWBkAJC3vtqka7n2F 3rzUMtqMO4byuxu6yeBooQSordPKIbn2YvLiHorvIBoeM5787lbty+LpaztbKdDaNvRQO9 rIA2kfEoYXwyNJdP/JX7Hc8LIIF4WkQJc8iW6sh/H9/UXR/eLSN8fWkTjYArJ+BtArd5fg 0hbJ9sgFvsBa1mwbAltErYpttALhi6i72O9QAVMs8Z7QwhFBPQHdeZCB85G/M+2fHb9QPN URa9LNsMYv/AO9Dbdeyzc7EWe4sg9JgyFtyVKAFbZt3mbRe7n92FlcJ+R+Voaw== From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Florian Fainelli , Heiner Kallweit , Russell King , Vladimir Oltean , Oleksij Rempel , =?utf-8?q?Nicol=C3=B2_Veronese?= , thomas.petazzoni@bootlin.com, Christophe Leroy Subject: [RFC PATCH net-next 4/7] net: ethtool: add a netlink command to list PHYs Date: Thu, 7 Sep 2023 11:24:02 +0200 Message-ID: <20230907092407.647139-5-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230907092407.647139-1-maxime.chevallier@bootlin.com> References: <20230907092407.647139-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-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_BLOCKED, SPF_HELO_PASS,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Introduce a new netlink message that lists all PHYs on a given interface at a given time. Signed-off-by: Maxime Chevallier --- include/uapi/linux/ethtool_netlink.h | 13 ++++ net/ethtool/Makefile | 2 +- net/ethtool/netlink.c | 10 +++ net/ethtool/netlink.h | 2 + net/ethtool/phy_list.c | 99 ++++++++++++++++++++++++++++ 5 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 net/ethtool/phy_list.c diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h index 73e2c10dc2cc..b2a0d21fdd8e 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_LIST_GET, /* add new constants above here */ __ETHTOOL_MSG_USER_CNT, @@ -109,6 +110,7 @@ enum { ETHTOOL_MSG_PLCA_NTF, ETHTOOL_MSG_MM_GET_REPLY, ETHTOOL_MSG_MM_NTF, + ETHTOOL_MSG_PHY_LIST_GET_REPLY, /* add new constants above here */ __ETHTOOL_MSG_KERNEL_CNT, @@ -975,6 +977,17 @@ enum { ETHTOOL_A_MM_MAX = (__ETHTOOL_A_MM_CNT - 1) }; +enum { + ETHTOOL_A_PHY_LIST_UNSPEC, + ETHTOOL_A_PHY_LIST_HEADER, /* nest - _A_HEADER_* */ + ETHTOOL_A_PHY_LIST_COUNT, /* u8 */ + ETHTOOL_A_PHY_LIST_INDEX, /* array, u32 */ + + /* add new constants above here */ + __ETHTOOL_A_PHY_LIST_CNT, + ETHTOOL_A_PHY_LIST_MAX = (__ETHTOOL_A_PHY_LIST_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..a182c0dbbb9d 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_list.o diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index 3bbd5afb7b31..60b66b78055e 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -306,6 +306,7 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = { [ETHTOOL_MSG_PLCA_GET_STATUS] = ðnl_plca_status_request_ops, [ETHTOOL_MSG_MM_GET] = ðnl_mm_request_ops, [ETHTOOL_MSG_MM_SET] = ðnl_mm_request_ops, + [ETHTOOL_MSG_PHY_LIST_GET] = ðnl_phy_list_request_ops, }; static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb) @@ -1128,6 +1129,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_LIST_GET, + .doit = ethnl_default_doit, + .start = ethnl_default_start, + .dumpit = ethnl_default_dumpit, + .done = ethnl_default_done, + .policy = ethnl_phy_list_get_policy, + .maxattr = ARRAY_SIZE(ethnl_phy_list_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 9a333a8d04c1..76859d8fbce0 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -395,6 +395,7 @@ 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_list_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]; @@ -441,6 +442,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_list_get_policy[ETHTOOL_A_PHY_LIST_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); diff --git a/net/ethtool/phy_list.c b/net/ethtool/phy_list.c new file mode 100644 index 000000000000..689d08637391 --- /dev/null +++ b/net/ethtool/phy_list.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2023 Bootlin + * + * Ethtool netlink operations for Ethernet PHY specific operations + */ +#include "common.h" +#include "netlink.h" + +#include +#include + +struct phy_list_req_info { + struct ethnl_req_info base; +}; + +#define PHY_MAX_ENTRIES 16 + +struct phy_list_reply_data { + struct ethnl_reply_data base; + u8 n_phys; + u32 phy_indices[PHY_MAX_ENTRIES]; +}; + +#define PHY_LIST_REPDATA(__reply_base) \ + container_of(__reply_base, struct phy_list_reply_data, base) + +const struct nla_policy ethnl_phy_list_get_policy[ETHTOOL_A_PHY_LIST_HEADER + 1] = { + [ETHTOOL_A_PHY_LIST_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy_stats), +}; + +static int phy_list_prepare_data(const struct ethnl_req_info *req_base, + struct ethnl_reply_data *reply_base, + struct genl_info *info) +{ + struct phy_list_reply_data *data = PHY_LIST_REPDATA(reply_base); + struct net_device *dev = reply_base->dev; + struct phy_namespace *phy_ns = &dev->phy_ns; + struct phy_device *phydev; + int ret; + + ret = ethnl_ops_begin(dev); + if (ret < 0) + return ret; + + data->n_phys = 0; + + mutex_lock(&phy_ns->ns_lock); + list_for_each_entry(phydev, &phy_ns->phys, node) + data->phy_indices[data->n_phys++] = phydev->phyindex; + mutex_unlock(&phy_ns->ns_lock); + + ethnl_ops_complete(dev); + + return ret; +} + +static int phy_list_reply_size(const struct ethnl_req_info *req_base, + const struct ethnl_reply_data *reply_base) +{ + const struct phy_list_reply_data *data = PHY_LIST_REPDATA(reply_base); + int len = 0; + + len += nla_total_size(sizeof(u8)); /* _PHY_LIST_COUNT */ + len += nla_total_size(data->n_phys * sizeof(u32)); /* Array of _PHY_LIST_INDEX */ + + return len; +} + +static int phy_list_fill_reply(struct sk_buff *skb, + const struct ethnl_req_info *req_base, + const struct ethnl_reply_data *reply_base) +{ + const struct phy_list_reply_data *data = PHY_LIST_REPDATA(reply_base); + + if (nla_put_u8(skb, ETHTOOL_A_PHY_LIST_COUNT, data->n_phys)) + return -EMSGSIZE; + + if (!data->n_phys) + return 0; + + if (nla_put(skb, ETHTOOL_A_PHY_LIST_INDEX, sizeof(u32) * data->n_phys, + data->phy_indices)) + return -EMSGSIZE; + + return 0; +} + +const struct ethnl_request_ops ethnl_phy_list_request_ops = { + .request_cmd = ETHTOOL_MSG_PHY_LIST_GET, + .reply_cmd = ETHTOOL_MSG_PHY_LIST_GET_REPLY, + .hdr_attr = ETHTOOL_A_PHY_LIST_HEADER, + .req_info_size = sizeof(struct phy_list_req_info), + .reply_data_size = sizeof(struct phy_list_reply_data), + + .prepare_data = phy_list_prepare_data, + .reply_size = phy_list_reply_size, + .fill_reply = phy_list_fill_reply, +}; From patchwork Thu Sep 7 09:24: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: 13376517 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8865629B4 for ; Thu, 7 Sep 2023 15:35:00 +0000 (UTC) Received: from mslow1.mail.gandi.net (mslow1.mail.gandi.net [IPv6:2001:4b98:dc4:8::240]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1F7411A8; Thu, 7 Sep 2023 08:34:28 -0700 (PDT) Received: from relay2-d.mail.gandi.net (unknown [IPv6:2001:4b98:dc4:8::222]) by mslow1.mail.gandi.net (Postfix) with ESMTP id 7D7CDD6781; Thu, 7 Sep 2023 09:24:42 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPSA id E6E1140032; Thu, 7 Sep 2023 09:24:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1694078660; 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=da+6NJOJEm++PNss5/CyJhpocrTl9IbiBTOkyc0NiIU=; b=D0xm9lzpjQN6rJaPPDGdOkBud3WdI0MIuYRbaLyVf5gp172r+LKVbuWciVT4M/JyuowyO6 vD/nTBVDCAnfLiqAn3VwquNxtIW1CGcVGSihG6AS/+rCew0l4SkNe2RrUaMnfwvVs47W4D yYybwNxT84Pw9OSEGIjvu9Ll9uEqxo5hg1uWjaHlo3nuY9/0eq7Xy9pFGgNLsNV0VdP7SM LDj5KyXstKCg5XgEbIuIjveeOWb7wBdoKRgx3n3LXfhBDBKv3QryU7dMcn2AFr58yW3OfZ Lg1xHroyNPE2rZIe73zTtSzCaGwYTa8RDP3FREM7WdvV1Vd/C6uHxH+0tT5Yfw== From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Florian Fainelli , Heiner Kallweit , Russell King , Vladimir Oltean , Oleksij Rempel , =?utf-8?q?Nicol=C3=B2_Veronese?= , thomas.petazzoni@bootlin.com, Christophe Leroy Subject: [RFC PATCH net-next 5/7] netlink: specs: add phy_list command Date: Thu, 7 Sep 2023 11:24:03 +0200 Message-ID: <20230907092407.647139-6-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230907092407.647139-1-maxime.chevallier@bootlin.com> References: <20230907092407.647139-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-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_BLOCKED, SPF_HELO_PASS,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Add a new command allowing to list PHYs that are present on a netdevice's link. The list is an array of phyindex, per-netdevice unique numbers that describe a PHY device. Example messages : - No PHY on the link (Pure SFP interface) : ./cli.py --spec specs/ethtool.yaml --schema genetlink-legacy.yaml \ --do phy-list-get --json '{"header" : {"dev-name" : "eth3"}}' {'header': {'dev-index': 5, 'dev-name': 'eth3'}, 'phy-count': 0} - One PHY on the link : ./cli.py --spec specs/ethtool.yaml --schema genetlink-legacy.yaml \ --do phy-list-get --json '{"header" : {"dev-name" : "eth2"}}' {'header': {'dev-index': 4, 'dev-name': 'eth2'}, 'phy-count': 1, 'phy-indices': b'\x01\x00\x00\x00'} - 2 PHYs on the link (MAC - PHY - SFP[PHY]) : ./cli.py --spec specs/ethtool.yaml --schema genetlink-legacy.yaml \ --do phy-list-get --json '{"header" : {"dev-name" : "eth0"}}' {'header': {'dev-index': 2, 'dev-name': 'eth0'}, 'phy-count': 2, 'phy-indices': b'\x02\x00\x00\x00\x01\x00\x00\x00'} This PHY inddices can then be used by other netlink commands that would target PHYs. Signed-off-by: Maxime Chevallier --- Documentation/netlink/specs/ethtool.yaml | 28 ++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Documentation/netlink/specs/ethtool.yaml b/Documentation/netlink/specs/ethtool.yaml index 837b565577ca..1139c88ed65c 100644 --- a/Documentation/netlink/specs/ethtool.yaml +++ b/Documentation/netlink/specs/ethtool.yaml @@ -942,6 +942,19 @@ attribute-sets: - name: burst-tmr type: u32 + - + name: phy-list + attributes: + - + name: header + type: nest + nested-attributes: header + - + name: phy-count + type: u8 + - + name: phy-indices + type: binary operations: enum-model: directional @@ -1692,3 +1705,18 @@ operations: name: mm-ntf doc: Notification for change in MAC Merge configuration. notify: mm-get + - + name: phy-list-get + doc: Get list of PHY devices attached to an interface + + attribute-set: phy-list + + do: &phy-list-get-op + request: + attributes: + - header + reply: + attributes: + - header + - phy-count + - phy-indices From patchwork Thu Sep 7 09:24:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Chevallier X-Patchwork-Id: 13376511 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 28D1C12B71 for ; Thu, 7 Sep 2023 15:29:57 +0000 (UTC) Received: from mslow1.mail.gandi.net (mslow1.mail.gandi.net [217.70.178.240]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 017031739; Thu, 7 Sep 2023 08:29:29 -0700 (PDT) Received: from relay2-d.mail.gandi.net (unknown [217.70.183.194]) by mslow1.mail.gandi.net (Postfix) with ESMTP id C4FA1D67AE; Thu, 7 Sep 2023 09:24:45 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPSA id C392A40030; Thu, 7 Sep 2023 09:24:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1694078662; 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=CaBZk7bZ3a0MTep+V5x+r8Tk/H8dUevKifh4/mfa3xg=; b=XNr0/jJpEiPbjfwSDKbDIAKNH5cSr8wsxFW5LNAogGeGXF1orubjCDYBKEKmcJjjVB3O5X sI02HI5EQ0NSMqNWHCV3DGg2ks6ittd37BRDy3Aa78jXSKWy5QavoRZ+c08Oru2PouPPlO ZPtVRjaxXre0x8B9uuPq04FCpP1snp9lFo1vwDvqL9kdk154WEM3LvoIufHfjZV/PxbeNm P81F3c681kx8Exxi+HyjBeLDs39qiLjnQp+wNXiX8fnBjuymBD4m7rVuAsvRt4fSKlFW+b tOrqqE/ZksTCSBH062DcVGJ93/iA83W9vsnJ3PBfnxkAVt3BnbjjpP4qGPi05g== From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Florian Fainelli , Heiner Kallweit , Russell King , Vladimir Oltean , Oleksij Rempel , =?utf-8?q?Nicol=C3=B2_Veronese?= , thomas.petazzoni@bootlin.com, Christophe Leroy Subject: [RFC PATCH net-next 6/7] net: ethtool: add a netlink command to get PHY information Date: Thu, 7 Sep 2023 11:24:04 +0200 Message-ID: <20230907092407.647139-7-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230907092407.647139-1-maxime.chevallier@bootlin.com> References: <20230907092407.647139-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-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_BLOCKED, SPF_HELO_PASS,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Now that we can list PHYs belonging to a netdevice, add a command to get PHY-specific information, that we can extend as needed to get more data such as link info, offloading support, etc. Signed-off-by: Maxime Chevallier --- include/uapi/linux/ethtool.h | 7 ++ include/uapi/linux/ethtool_netlink.h | 14 +++ net/ethtool/Makefile | 2 +- net/ethtool/netlink.c | 10 +++ net/ethtool/netlink.h | 2 + net/ethtool/phy.c | 124 +++++++++++++++++++++++++++ 6 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 net/ethtool/phy.c diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index f7fba0dc87e5..d74f839ad32c 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -2205,4 +2205,11 @@ struct ethtool_link_settings { * __u32 map_lp_advertising[link_mode_masks_nwords]; */ }; + +enum phy_upstream_type { + PHY_UPSTREAM_MAC, + PHY_UPSTREAM_SFP, + PHY_UPSTREAM_PHY, +}; + #endif /* _UAPI_LINUX_ETHTOOL_H */ diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h index b2a0d21fdd8e..ec96e816d564 100644 --- a/include/uapi/linux/ethtool_netlink.h +++ b/include/uapi/linux/ethtool_netlink.h @@ -58,6 +58,7 @@ enum { ETHTOOL_MSG_MM_GET, ETHTOOL_MSG_MM_SET, ETHTOOL_MSG_PHY_LIST_GET, + ETHTOOL_MSG_PHY_GET, /* add new constants above here */ __ETHTOOL_MSG_USER_CNT, @@ -111,6 +112,7 @@ enum { ETHTOOL_MSG_MM_GET_REPLY, ETHTOOL_MSG_MM_NTF, ETHTOOL_MSG_PHY_LIST_GET_REPLY, + ETHTOOL_MSG_PHY_GET_REPLY, /* add new constants above here */ __ETHTOOL_MSG_KERNEL_CNT, @@ -988,6 +990,18 @@ enum { ETHTOOL_A_PHY_LIST_MAX = (__ETHTOOL_A_PHY_LIST_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_UPSTREAM_TYPE, /* u8 */ + ETHTOOL_A_PHY_ID, /* u32 */ + + __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 a182c0dbbb9d..e6ef280431d6 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 phy_list.o + module.o pse-pd.o plca.o mm.o phy_list.o phy.o diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index 60b66b78055e..88a60fbb8806 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -307,6 +307,7 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = { [ETHTOOL_MSG_MM_GET] = ðnl_mm_request_ops, [ETHTOOL_MSG_MM_SET] = ðnl_mm_request_ops, [ETHTOOL_MSG_PHY_LIST_GET] = ðnl_phy_list_request_ops, + [ETHTOOL_MSG_PHY_GET] = ðnl_phy_request_ops, }; static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb) @@ -1138,6 +1139,15 @@ static const struct genl_ops ethtool_genl_ops[] = { .policy = ethnl_phy_list_get_policy, .maxattr = ARRAY_SIZE(ethnl_phy_list_get_policy) - 1, }, + { + .cmd = ETHTOOL_MSG_PHY_GET, + .doit = ethnl_default_doit, + .start = ethnl_default_start, + .dumpit = ethnl_default_dumpit, + .done = ethnl_default_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 76859d8fbce0..15f75fd211fc 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -396,6 +396,7 @@ 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_list_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]; @@ -443,6 +444,7 @@ extern const struct nla_policy ethnl_plca_get_status_policy[ETHTOOL_A_PLCA_HEADE 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_list_get_policy[ETHTOOL_A_PHY_LIST_HEADER + 1]; +extern const struct nla_policy ethnl_phy_get_policy[ETHTOOL_A_PHY_INDEX + 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); diff --git a/net/ethtool/phy.c b/net/ethtool/phy.c new file mode 100644 index 000000000000..0f646bec946b --- /dev/null +++ b/net/ethtool/phy.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2023 Bootlin + * + */ +#include "common.h" +#include "netlink.h" + +#include +#include + +struct phy_req_info { + struct ethnl_req_info base; + u32 phyindex; +}; + +struct phy_reply_data { + struct ethnl_reply_data base; + u32 phyindex; + const char *drvname; + enum phy_upstream_type upstream; + u32 id; +}; + +#define PHY_REQINFO(__req_base) \ + container_of(__req_base, struct phy_req_info, base) +#define PHY_REPDATA(__reply_base) \ + container_of(__reply_base, struct phy_reply_data, base) + +const struct nla_policy ethnl_phy_get_policy[ETHTOOL_A_PHY_INDEX + 1] = { + [ETHTOOL_A_PHY_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy), + [ETHTOOL_A_PHY_INDEX] = NLA_POLICY_MAX(NLA_U32, 255), +}; + +static int phy_parse_request(struct ethnl_req_info *req_base, + struct nlattr **tb, + struct netlink_ext_ack *extack) +{ + struct phy_req_info *req_info = PHY_REQINFO(req_base); + + if (!tb[ETHTOOL_A_PHY_INDEX]) + return -EINVAL; + + req_info->phyindex = nla_get_u32(tb[ETHTOOL_A_PHY_INDEX]); + + return 0; +} + +static int phy_prepare_data(const struct ethnl_req_info *req_base, + struct ethnl_reply_data *reply_base, + struct genl_info *info) +{ + struct phy_req_info *req_info = PHY_REQINFO(req_base); + struct phy_reply_data *data = PHY_REPDATA(reply_base); + struct net_device *dev = reply_base->dev; + struct phy_namespace *phy_ns = &dev->phy_ns; + struct phy_device *phydev; + int ret; + + phydev = phy_ns_get_by_index(phy_ns, req_info->phyindex); + if (!phydev) + return -ENODEV; + + ret = ethnl_ops_begin(dev); + if (ret < 0) + return ret; + + data->phyindex = req_info->phyindex; + data->drvname = phydev->drv->name; + if (phydev->is_on_sfp_module) + data->upstream = PHY_UPSTREAM_SFP; + else if (phydev->attached_dev) + data->upstream = PHY_UPSTREAM_MAC; + else + data->upstream = PHY_UPSTREAM_PHY; + + data->id = phydev->phy_id; + + ethnl_ops_complete(dev); + + return ret; +} + +static int phy_reply_size(const struct ethnl_req_info *req_base, + const struct ethnl_reply_data *reply_base) +{ + const struct phy_reply_data *data = PHY_REPDATA(reply_base); + int len = 0; + + len += nla_total_size(sizeof(u32)); /* ETHTOOL_A_PHY_INDEX */ + len += ethnl_strz_size(data->drvname); /* ETHTOOL_A_DRVNAME */ + len += nla_total_size(sizeof(u8)); /* ETHTOOL_A_PHY_UPSTREAM_TYPE */ + len += nla_total_size(sizeof(u32)); /* ETHTOOL_A_PHY_ID */ + + return len; +} + +static int phy_fill_reply(struct sk_buff *skb, + const struct ethnl_req_info *req_base, + const struct ethnl_reply_data *reply_base) +{ + const struct phy_reply_data *data = PHY_REPDATA(reply_base); + + if (nla_put_u32(skb, ETHTOOL_A_PHY_INDEX, data->phyindex) || + ethnl_put_strz(skb, ETHTOOL_A_PHY_DRVNAME, data->drvname) || + nla_put_u8(skb, ETHTOOL_A_PHY_UPSTREAM_TYPE, data->upstream) || + nla_put_u32(skb, ETHTOOL_A_PHY_ID, data->id)) + return -EMSGSIZE; + + return 0; +} + +const struct ethnl_request_ops ethnl_phy_request_ops = { + .request_cmd = ETHTOOL_MSG_PHY_GET, + .reply_cmd = ETHTOOL_MSG_PHY_GET_REPLY, + .hdr_attr = ETHTOOL_A_PHY_HEADER, + .req_info_size = sizeof(struct phy_req_info), + .reply_data_size = sizeof(struct phy_reply_data), + + .parse_request = phy_parse_request, + .prepare_data = phy_prepare_data, + .reply_size = phy_reply_size, + .fill_reply = phy_fill_reply, +}; From patchwork Thu Sep 7 09:24:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Chevallier X-Patchwork-Id: 13376510 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 467B329B4 for ; Thu, 7 Sep 2023 15:29:32 +0000 (UTC) Received: from mslow1.mail.gandi.net (mslow1.mail.gandi.net [217.70.178.240]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 32769CC; Thu, 7 Sep 2023 08:29:07 -0700 (PDT) Received: from relay2-d.mail.gandi.net (unknown [IPv6:2001:4b98:dc4:8::222]) by mslow1.mail.gandi.net (Postfix) with ESMTP id C6D36D67E2; Thu, 7 Sep 2023 09:24:45 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPSA id 85E5140033; Thu, 7 Sep 2023 09:24:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1694078664; 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=PP4qFU6v/2wbsuMME7GJXKWzRSZTU8obLf77vj2Y764=; b=KqPlFH8SpLqr71N8Xu1HKLtjul2/9Zjh9V+XSbwUv+4bkMcaaxQgyK/zWNqrQmmEC1U31r oTwSSBadbMkgeIe6Kh6NIuP0EFiQEAqDyCltAn3BwaSw6PBeTspPkn8PGURCXoMaOiA8LY Ey0h4PsgDjnehE0cddYMXLOMwq0aTr+ww4YJCBh3LGcjm5vZy2WuHidQqEPKoFkYmVV+v1 Lu1VVhJWMBweukhP35zrcRzSzg7vhzDJGnbTy64T/Ugz4GPp6kgBAJg807ss4BF8njg8MV M5DC0oH9L1hZlu/AgD8wbrRYn/cOwCWlG19EAEQ+uygoee5FhVGexPNyEXVh9w== From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Florian Fainelli , Heiner Kallweit , Russell King , Vladimir Oltean , Oleksij Rempel , =?utf-8?q?Nicol=C3=B2_Veronese?= , thomas.petazzoni@bootlin.com, Christophe Leroy Subject: [RFC PATCH net-next 7/7] netlink: specs: add command to show individual phy information Date: Thu, 7 Sep 2023 11:24:05 +0200 Message-ID: <20230907092407.647139-8-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230907092407.647139-1-maxime.chevallier@bootlin.com> References: <20230907092407.647139-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-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_BLOCKED, SPF_HELO_PASS,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC With the ETHTOOL_CMD_PHY_LIST_GET command, we can obtain a list of PHYs on a link, addressable through their phyindex. This index can be used to issue PHY-specific commands. The phy_get command allows querying per-PHY information. The information reported so-far is minimal (driver name, phy id (for C22), upstream PHY type (real PHY, SFP phy), but we can imagine extending this in the future to report PHY offloading capabilities, status, and much more. Example usage : ./cli.py --spec specs/ethtool.yaml --schema genetlink-legacy.yaml \ --do phy-list-get --json '{"header" : {"dev-name" : "eth0"}}' {'header': {'dev-index': 2, 'dev-name': 'eth0'}, 'phy-count': 2, 'phy-indices': b'\x02\x00\x00\x00\x01\x00\x00\x00'} ./cli.py --spec specs/ethtool.yaml --schema genetlink-legacy.yaml \ --do phy-get \ --json '{"header" : {"dev-name" : "eth0"}, "phy-index" : 1}' {'drvname': 'mv88x3310', 'header': {'dev-index': 2, 'dev-name': 'eth0'}, 'phy-id': 0, 'phy-index': 1, 'phy-upstream-type': 0} ./cli.py --spec specs/ethtool.yaml --schema genetlink-legacy.yaml \ --do phy-get \ --json '{"header" : {"dev-name" : "eth0"}, "phy-index" : 2}' {'drvname': 'Marvell 88E1111', 'header': {'dev-index': 2, 'dev-name': 'eth0'}, 'phy-id': 21040322, 'phy-index': 2, 'phy-upstream-type': 2} Signed-off-by: Maxime Chevallier --- Documentation/netlink/specs/ethtool.yaml | 37 ++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/Documentation/netlink/specs/ethtool.yaml b/Documentation/netlink/specs/ethtool.yaml index 1139c88ed65c..708a77423286 100644 --- a/Documentation/netlink/specs/ethtool.yaml +++ b/Documentation/netlink/specs/ethtool.yaml @@ -955,6 +955,25 @@ attribute-sets: - name: phy-indices type: binary + - + name: phy + attributes: + - + name: header + type: nest + nested-attributes: header + - + name: phy-index + type: u32 + - + name: drvname + type: string + - + name: phy-upstream-type + type: u8 + - + name: phy-id + type: u32 operations: enum-model: directional @@ -1720,3 +1739,21 @@ operations: - header - phy-count - phy-indices + - + name: phy-get + doc: Get a PHY's information + + attribute-set: phy + + do: &phy-get-op + request: + attributes: + - header + - phy-index + reply: + attributes: + - header + - phy-index + - drvname + - phy-upstream-type + - phy-id