From nobody Fri Apr 10 20:21:46 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6A49BC3F6B0 for ; Fri, 19 Aug 2022 12:01:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348782AbiHSMBh (ORCPT ); Fri, 19 Aug 2022 08:01:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48564 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347592AbiHSMBe (ORCPT ); Fri, 19 Aug 2022 08:01:34 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D3EB3E2C43 for ; Fri, 19 Aug 2022 05:01:32 -0700 (PDT) Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1oP0ge-0007mg-NM; Fri, 19 Aug 2022 14:01:16 +0200 Received: from [2a0a:edc0:0:1101:1d::ac] (helo=dude04.red.stw.pengutronix.de) by drehscheibe.grey.stw.pengutronix.de with esmtp (Exim 4.94.2) (envelope-from ) id 1oP0gc-000hbU-AV; Fri, 19 Aug 2022 14:01:14 +0200 Received: from ore by dude04.red.stw.pengutronix.de with local (Exim 4.94.2) (envelope-from ) id 1oP0ga-00GBah-81; Fri, 19 Aug 2022 14:01:12 +0200 From: Oleksij Rempel To: Andrew Lunn , Heiner Kallweit , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Russell King , Rob Herring , Krzysztof Kozlowski , Jonathan Corbet Cc: Oleksij Rempel , kernel@pengutronix.de, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-doc@vger.kernel.org, David Jander Subject: [PATCH net-next v1 1/7] dt-bindings: net: pse-dt: add bindings for generic PSE controller Date: Fri, 19 Aug 2022 14:01:03 +0200 Message-Id: <20220819120109.3857571-2-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220819120109.3857571-1-o.rempel@pengutronix.de> References: <20220819120109.3857571-1-o.rempel@pengutronix.de> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-kernel@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Add binding for generic Ethernet PSE controller. Signed-off-by: Oleksij Rempel --- .../bindings/net/pse-pd/generic-pse.yaml | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/pse-pd/generic-ps= e.yaml diff --git a/Documentation/devicetree/bindings/net/pse-pd/generic-pse.yaml = b/Documentation/devicetree/bindings/net/pse-pd/generic-pse.yaml new file mode 100644 index 0000000000000..64f91efa79a56 --- /dev/null +++ b/Documentation/devicetree/bindings/net/pse-pd/generic-pse.yaml @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/pse-pd/generic-pse.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Generic Power Sourcing Equipment + +maintainers: + - Oleksij Rempel + +description: | + Generic PSE controller. The device must be referenced by the PHY node + to control power injection to the Ethernet cable. + +properties: + compatible: + const: ieee802.3-podl-pse-generic + + '#pse-cells': + const: 0 + + ieee802.3-podl-pse-supply: + description: | + Power supply for the PSE controller + +additionalProperties: false + +required: + - compatible + - '#pse-cells' + - ieee802.3-podl-pse-supply + +examples: + - | + ethernet-pse-1 { + compatible =3D "ieee802.3-podl-pse-generic"; + ieee802.3-podl-pse-supply =3D <®_t1l1>; + #pse-cells =3D <0>; + }; --=20 2.30.2 From nobody Fri Apr 10 20:21:46 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0EA28C32792 for ; Fri, 19 Aug 2022 12:02:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348815AbiHSMCA (ORCPT ); Fri, 19 Aug 2022 08:02:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48690 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1348741AbiHSMBj (ORCPT ); Fri, 19 Aug 2022 08:01:39 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CE01EE3C20 for ; Fri, 19 Aug 2022 05:01:38 -0700 (PDT) Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1oP0ge-0007mi-NM; Fri, 19 Aug 2022 14:01:16 +0200 Received: from [2a0a:edc0:0:1101:1d::ac] (helo=dude04.red.stw.pengutronix.de) by drehscheibe.grey.stw.pengutronix.de with esmtp (Exim 4.94.2) (envelope-from ) id 1oP0gc-000hbX-Dd; Fri, 19 Aug 2022 14:01:14 +0200 Received: from ore by dude04.red.stw.pengutronix.de with local (Exim 4.94.2) (envelope-from ) id 1oP0ga-00GBaq-8k; Fri, 19 Aug 2022 14:01:12 +0200 From: Oleksij Rempel To: Andrew Lunn , Heiner Kallweit , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Russell King , Rob Herring , Krzysztof Kozlowski , Jonathan Corbet Cc: Oleksij Rempel , kernel@pengutronix.de, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-doc@vger.kernel.org, David Jander Subject: [PATCH net-next v1 2/7] dt-bindings: net: phy: add PoDL PSE property Date: Fri, 19 Aug 2022 14:01:04 +0200 Message-Id: <20220819120109.3857571-3-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220819120109.3857571-1-o.rempel@pengutronix.de> References: <20220819120109.3857571-1-o.rempel@pengutronix.de> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-kernel@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Add property to reference node representing a PoDL Power Sourcing Equipment. Signed-off-by: Oleksij Rempel --- Documentation/devicetree/bindings/net/ethernet-phy.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/net/ethernet-phy.yaml b/Docu= mentation/devicetree/bindings/net/ethernet-phy.yaml index ed1415a4381f2..49c74e177c788 100644 --- a/Documentation/devicetree/bindings/net/ethernet-phy.yaml +++ b/Documentation/devicetree/bindings/net/ethernet-phy.yaml @@ -144,6 +144,12 @@ properties: Mark the corresponding energy efficient ethernet mode as broken and request the ethernet to stop advertising it. =20 + ieee802.3-podl-pse: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Specifies a reference to a node representing a Power over Data Lines + Power Sourcing Equipment. + phy-is-integrated: $ref: /schemas/types.yaml#/definitions/flag description: --=20 2.30.2 From nobody Fri Apr 10 20:21:46 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0DBD2C32771 for ; Fri, 19 Aug 2022 12:02:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348877AbiHSMCE (ORCPT ); Fri, 19 Aug 2022 08:02:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48716 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1348829AbiHSMBl (ORCPT ); Fri, 19 Aug 2022 08:01:41 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 42F1FE42F6 for ; Fri, 19 Aug 2022 05:01:39 -0700 (PDT) Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1oP0ge-0007mq-NK; Fri, 19 Aug 2022 14:01:16 +0200 Received: from [2a0a:edc0:0:1101:1d::ac] (helo=dude04.red.stw.pengutronix.de) by drehscheibe.grey.stw.pengutronix.de with esmtp (Exim 4.94.2) (envelope-from ) id 1oP0gc-000hbf-LC; Fri, 19 Aug 2022 14:01:14 +0200 Received: from ore by dude04.red.stw.pengutronix.de with local (Exim 4.94.2) (envelope-from ) id 1oP0ga-00GBaz-9P; Fri, 19 Aug 2022 14:01:12 +0200 From: Oleksij Rempel To: Andrew Lunn , Heiner Kallweit , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Russell King , Rob Herring , Krzysztof Kozlowski , Jonathan Corbet Cc: Oleksij Rempel , kernel@pengutronix.de, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-doc@vger.kernel.org, David Jander Subject: [PATCH net-next v1 3/7] net: add framework to support Ethernet PSE and PDs devices Date: Fri, 19 Aug 2022 14:01:05 +0200 Message-Id: <20220819120109.3857571-4-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220819120109.3857571-1-o.rempel@pengutronix.de> References: <20220819120109.3857571-1-o.rempel@pengutronix.de> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-kernel@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" This framework was create with intention to provide support for Ethernet PSE (Power Sourcing Equipment) and PDs (Powered Device). At current step this patch implements generic PSE support for PoDL (Power o= ver Data Lines 802.3bu) specification with reserving name space for PD devices = as well. This framework can be extended to support 802.3af and 802.3at "Power via the Media Dependent Interface" (or PoE/Power over Ethernet) Signed-off-by: Oleksij Rempel --- drivers/net/Kconfig | 2 + drivers/net/Makefile | 1 + drivers/net/pse-pd/Kconfig | 11 + drivers/net/pse-pd/Makefile | 4 + drivers/net/pse-pd/pse-core.c | 387 ++++++++++++++++++++++++++++++++++ include/linux/pse-pd/pse.h | 134 ++++++++++++ 6 files changed, 539 insertions(+) create mode 100644 drivers/net/pse-pd/Kconfig create mode 100644 drivers/net/pse-pd/Makefile create mode 100644 drivers/net/pse-pd/pse-core.c create mode 100644 include/linux/pse-pd/pse.h diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 94c889802566a..15d4a38b1351d 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -500,6 +500,8 @@ config NET_SB1000 =20 source "drivers/net/phy/Kconfig" =20 +source "drivers/net/pse-pd/Kconfig" + source "drivers/net/can/Kconfig" =20 source "drivers/net/mctp/Kconfig" diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 3f1192d3c52d3..6ce076462dbfd 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_NET) +=3D loopback.o obj-$(CONFIG_NETDEV_LEGACY_INIT) +=3D Space.o obj-$(CONFIG_NETCONSOLE) +=3D netconsole.o obj-y +=3D phy/ +obj-y +=3D pse-pd/ obj-y +=3D mdio/ obj-y +=3D pcs/ obj-$(CONFIG_RIONET) +=3D rionet.o diff --git a/drivers/net/pse-pd/Kconfig b/drivers/net/pse-pd/Kconfig new file mode 100644 index 0000000000000..49c7f0bcff526 --- /dev/null +++ b/drivers/net/pse-pd/Kconfig @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Ethernet Power Sourcing Equipment drivers +# + +menuconfig PSE_CONTROLLER + bool "Ethernet Power Sourcing Equipment Support" + help + Generic Power Sourcing Equipment Controller support. + + If unsure, say no. diff --git a/drivers/net/pse-pd/Makefile b/drivers/net/pse-pd/Makefile new file mode 100644 index 0000000000000..cbb79fc2e2706 --- /dev/null +++ b/drivers/net/pse-pd/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Makefile for Linux PSE drivers + +obj-$(CONFIG_PSE_CONTROLLER) +=3D pse-core.o diff --git a/drivers/net/pse-pd/pse-core.c b/drivers/net/pse-pd/pse-core.c new file mode 100644 index 0000000000000..a0b42dc46d029 --- /dev/null +++ b/drivers/net/pse-pd/pse-core.c @@ -0,0 +1,387 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Framework for Ethernet Power Sourcing Equipment +// +// Copyright (c) 2022 Pengutronix, Oleksij Rempel +// + +#include +#include +#include + +static DEFINE_MUTEX(pse_list_mutex); +static LIST_HEAD(pse_controller_list); + +/** + * struct pse_control - a PSE control + * @pcdev: a pointer to the PSE controller device + * this PSE control belongs to + * @list: list entry for the pcdev's PSE controller list + * @id: ID of the PSE line in the PSE controller device + * @refcnt: Number of gets of this pse_control + */ +struct pse_control { + struct pse_controller_dev *pcdev; + struct list_head list; + unsigned int id; + struct kref refcnt; +}; + +/** + * of_pse_zero_xlate - dummy function for controllers with one only control + * @pcdev: a pointer to the PSE controller device + * @pse_spec: PSE line specifier as found in the device tree + * + * This static translation function is used by default if of_xlate in + * :c:type:`pse_controller_dev` is not set. It is useful for all PSE + * controllers with #pse-cells =3D <0>. + */ +static int of_pse_zero_xlate(struct pse_controller_dev *pcdev, + const struct of_phandle_args *pse_spec) +{ + return 0; +} + +/** + * of_pse_simple_xlate - translate pse_spec to the PSE line number + * @pcdev: a pointer to the PSE controller device + * @pse_spec: PSE line specifier as found in the device tree + * + * This static translation function is used by default if of_xlate in + * :c:type:`pse_controller_dev` is not set. It is useful for all PSE + * controllers with 1:1 mapping, where PSE lines can be indexed by number + * without gaps. + */ +static int of_pse_simple_xlate(struct pse_controller_dev *pcdev, + const struct of_phandle_args *pse_spec) +{ + if (pse_spec->args[0] >=3D pcdev->nr_lines) + return -EINVAL; + + return pse_spec->args[0]; +} + +/** + * pse_controller_register - register a PSE controller device + * @pcdev: a pointer to the initialized PSE controller device + */ +int pse_controller_register(struct pse_controller_dev *pcdev) +{ + if (!pcdev->of_xlate) { + if (pcdev->of_pse_n_cells =3D=3D 0) + pcdev->of_xlate =3D of_pse_zero_xlate; + else if (pcdev->of_pse_n_cells =3D=3D 1) + pcdev->of_xlate =3D of_pse_simple_xlate; + } + + INIT_LIST_HEAD(&pcdev->pse_control_head); + + mutex_lock(&pse_list_mutex); + list_add(&pcdev->list, &pse_controller_list); + mutex_unlock(&pse_list_mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(pse_controller_register); + +/** + * pse_controller_unregister - unregister a PSE controller device + * @pcdev: a pointer to the PSE controller device + */ +void pse_controller_unregister(struct pse_controller_dev *pcdev) +{ + mutex_lock(&pse_list_mutex); + list_del(&pcdev->list); + mutex_unlock(&pse_list_mutex); +} +EXPORT_SYMBOL_GPL(pse_controller_unregister); + +static void devm_pse_controller_release(struct device *dev, void *res) +{ + pse_controller_unregister(*(struct pse_controller_dev **)res); +} + +/** + * devm_pse_controller_register - resource managed pse_controller_register= () + * @dev: device that is registering this PSE controller + * @pcdev: a pointer to the initialized PSE controller device + * + * Managed pse_controller_register(). For PSE controllers registered by + * this function, pse_controller_unregister() is automatically called on + * driver detach. See pse_controller_register() for more information. + */ +int devm_pse_controller_register(struct device *dev, + struct pse_controller_dev *pcdev) +{ + struct pse_controller_dev **pcdevp; + int ret; + + pcdevp =3D devres_alloc(devm_pse_controller_release, sizeof(*pcdevp), + GFP_KERNEL); + if (!pcdevp) + return -ENOMEM; + + ret =3D pse_controller_register(pcdev); + if (ret) { + devres_free(pcdevp); + return ret; + } + + *pcdevp =3D pcdev; + devres_add(dev, pcdevp); + + return 0; +} +EXPORT_SYMBOL_GPL(devm_pse_controller_register); + +/* PSE control section */ + +static void __pse_control_release(struct kref *kref) +{ + struct pse_control *psec =3D container_of(kref, struct pse_control, + refcnt); + + lockdep_assert_held(&pse_list_mutex); + + module_put(psec->pcdev->owner); + + list_del(&psec->list); + kfree(psec); +} + +static void __pse_control_put_internal(struct pse_control *psec) +{ + lockdep_assert_held(&pse_list_mutex); + + kref_put(&psec->refcnt, __pse_control_release); +} + +/** + * pse_control_put - free the PSE control + * @psec: PSE control pointer + */ +void pse_control_put(struct pse_control *psec) +{ + if (IS_ERR_OR_NULL(psec)) + return; + + mutex_lock(&pse_list_mutex); + __pse_control_put_internal(psec); + mutex_unlock(&pse_list_mutex); +} +EXPORT_SYMBOL_GPL(pse_control_put); + +static struct pse_control * +pse_control_get_internal(struct pse_controller_dev *pcdev, unsigned int in= dex) +{ + struct pse_control *psec; + + lockdep_assert_held(&pse_list_mutex); + + list_for_each_entry(psec, &pcdev->pse_control_head, list) { + if (psec->id =3D=3D index) { + kref_get(&psec->refcnt); + return psec; + } + } + + psec =3D kzalloc(sizeof(*psec), GFP_KERNEL); + if (!psec) + return ERR_PTR(-ENOMEM); + + if (!try_module_get(pcdev->owner)) { + kfree(psec); + return ERR_PTR(-ENODEV); + } + + psec->pcdev =3D pcdev; + list_add(&psec->list, &pcdev->pse_control_head); + psec->id =3D index; + kref_init(&psec->refcnt); + + return psec; +} + +struct pse_control * +of_pse_control_get(struct device_node *node) +{ + struct pse_controller_dev *r, *pcdev; + struct of_phandle_args args; + struct pse_control *psec; + int psec_id; + int ret; + + if (!node) + return ERR_PTR(-EINVAL); + + ret =3D of_parse_phandle_with_args(node, "ieee802.3-podl-pse", + "#pse-cells", 0, &args); + if (ret) + return ERR_PTR(ret); + + mutex_lock(&pse_list_mutex); + pcdev =3D NULL; + list_for_each_entry(r, &pse_controller_list, list) { + if (args.np =3D=3D r->dev->of_node) { + pcdev =3D r; + break; + } + } + + if (!pcdev) { + psec =3D ERR_PTR(-EPROBE_DEFER); + goto out; + } + + if (WARN_ON(args.args_count !=3D pcdev->of_pse_n_cells)) { + psec =3D ERR_PTR(-EINVAL); + goto out; + } + + psec_id =3D pcdev->of_xlate(pcdev, &args); + if (psec_id < 0) { + psec =3D ERR_PTR(psec_id); + goto out; + } + + /* pse_list_mutex also protects the pcdev's pse_control list */ + psec =3D pse_control_get_internal(pcdev, psec_id); + +out: + mutex_unlock(&pse_list_mutex); + of_node_put(args.np); + + return psec; +} +EXPORT_SYMBOL_GPL(of_pse_control_get); + +struct pse_control *pse_control_get(struct device *dev) +{ + if (!dev->of_node) + return ERR_PTR(-ENODEV); + + return of_pse_control_get(dev->of_node); +} +EXPORT_SYMBOL_GPL(pse_control_get); + +static void devm_pse_control_release(struct device *dev, void *res) +{ + pse_control_put(*(struct pse_control **)res); +} + +struct pse_control * +devm_pse_control_get(struct device *dev) +{ + struct pse_control **ptr, *psec; + + ptr =3D devres_alloc(devm_pse_control_release, sizeof(*ptr), + GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + psec =3D pse_control_get(dev); + if (IS_ERR_OR_NULL(psec)) { + devres_free(ptr); + return psec; + } + + *ptr =3D psec; + devres_add(dev, ptr); + + return psec; +} +EXPORT_SYMBOL_GPL(devm_pse_control_get); + +/** + * pse_podl_get_admin_sate - get operational state of the PoDL PSE functio= ns. + * @pcdev: a pointer to the PSE controller device + * + * IEEE 802.3-2018 30.15.1.1.2 aPoDLPSEAdminState: + * A read-only value that identifies the operational state of the PoDL PSE + * functions. + * + * Return values: + * see enum ethtool_podl_pse_admin_state + * Negative value is an error. + */ +int pse_podl_get_admin_sate(struct pse_control *psec) +{ + const struct pse_control_ops *ops; + + if (!psec) + return 0; + + if (WARN_ON(IS_ERR(psec))) + return -EINVAL; + + ops =3D psec->pcdev->ops; + + if (!ops->get_podl_pse_admin_sate) + return -ENOTSUPP; + + return ops->get_podl_pse_admin_sate(psec->pcdev, psec->id); +} +EXPORT_SYMBOL_GPL(pse_podl_get_admin_sate); + +/** + * pse_podl_set_admin_control - set operational state of the PoDL PSE func= tions. + * @pcdev: a pointer to the PSE controller device + * + * IEEE 802.3-2018 30.15.1.2.1 acPoDLPSEAdminControl + * This action provides a means to alter aPoDLPSEAdminState. + * + * Return values: + * Negative value is an error. + */ +int pse_podl_set_admin_control(struct pse_control *psec, + enum ethtool_podl_pse_admin_state state) +{ + const struct pse_control_ops *ops; + + if (!psec) + return 0; + + if (WARN_ON(IS_ERR(psec))) + return -EINVAL; + + ops =3D psec->pcdev->ops; + + if (!ops->set_podl_pse_admin_control) + return -ENOTSUPP; + + if (state >=3D ETHTOOL_PODL_PSE_ADMIN_STATE_COUNT) + return -ENOTSUPP; + + return ops->set_podl_pse_admin_control(psec->pcdev, psec->id, state); +} +EXPORT_SYMBOL_GPL(pse_podl_set_admin_control); + +/** + * pse_podl_get_pw_d_status - get a PoDL PSE power detection status + * @pcdev: a pointer to the PSE controller device + * + * IEEE 802.3-2018 30.15.1.1.3 aPoDLPSEPowerDetectionStatus: + * A read-only value that indicates the current status of the PoDL PSE. + * + * Return values: + * see enum ethtool_podl_pse_pw_d_status + * Negative value is an error. + */ +int pse_podl_get_pw_d_status(struct pse_control *psec) +{ + const struct pse_control_ops *ops; + + if (!psec) + return 0; + + if (WARN_ON(IS_ERR(psec))) + return -EINVAL; + + ops =3D psec->pcdev->ops; + + if (!ops->get_podl_pse_pw_d_status) + return -ENOTSUPP; + + return ops->get_podl_pse_pw_d_status(psec->pcdev, psec->id); +} +EXPORT_SYMBOL_GPL(pse_podl_get_pw_d_status); diff --git a/include/linux/pse-pd/pse.h b/include/linux/pse-pd/pse.h new file mode 100644 index 0000000000000..77d1d64f3e831 --- /dev/null +++ b/include/linux/pse-pd/pse.h @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +// Copyright (c) 2022 Pengutronix, Oleksij Rempel + */ +#ifndef _LINUX_PSE_CONTROLLER_H +#define _LINUX_PSE_CONTROLLER_H + +#include +#include + +struct phy_device; +struct pse_controller_dev; + +/** + * struct pse_control_ops - PSE controller driver callbacks + * + * @get_podl_pse_admin_sate: return a PoDL PSE admin state as described in + * IEEE 802.3-2018 30.15.1.1.2 aPoDLPSEAdminState + * @set_podl_pse_admin_control: set PoDL PSE admin control as described in + * IEEE 802.3-2018 30.15.1.2.1 acPoDLPSEAdminControl + * @get_podl_pse_pw_d_status: return a PoDL PSE power detection status as + * described in: IEEE 802.3-2018 30.15.1.1.3 aPoDLPSEPowerDetectionStatus + */ +struct pse_control_ops { + int (*get_podl_pse_admin_sate)(struct pse_controller_dev *pcdev, + unsigned long id); + int (*set_podl_pse_admin_control)(struct pse_controller_dev *pcdev, + unsigned long id, enum ethtool_podl_pse_admin_state state); + int (*get_podl_pse_pw_d_status)(struct pse_controller_dev *pcdev, + unsigned long id); +}; + +struct module; +struct device_node; +struct of_phandle_args; +struct pse_control; + +/** + * struct pse_controller_dev - PSE controller entity that might + * provide multiple PSE controls + * @ops: a pointer to device specific struct pse_control_ops + * @owner: kernel module of the PSE controller driver + * @list: internal list of PSE controller devices + * @pse_control_head: head of internal list of requested PSE controls + * @dev: corresponding driver model device struct + * @of_pse_n_cells: number of cells in PSE line specifiers + * @of_xlate: translation function to translate from specifier as found in= the + * device tree to id as given to the PSE control ops + * @nr_lines: number of PSE controls in this controller device + */ +struct pse_controller_dev { + const struct pse_control_ops *ops; + struct module *owner; + struct list_head list; + struct list_head pse_control_head; + struct device *dev; + int of_pse_n_cells; + int (*of_xlate)(struct pse_controller_dev *pcdev, + const struct of_phandle_args *pse_spec); + unsigned int nr_lines; +}; + +#if IS_ENABLED(CONFIG_PSE_CONTROLLER) +int pse_controller_register(struct pse_controller_dev *pcdev); +void pse_controller_unregister(struct pse_controller_dev *pcdev); +struct device; +int devm_pse_controller_register(struct device *dev, + struct pse_controller_dev *pcdev); + +struct pse_control *pse_control_get(struct device *dev); +struct pse_control *devm_pse_control_get( struct device *dev); +struct pse_control *of_pse_control_get(struct device_node *node); +void pse_control_put(struct pse_control *psec); +int pse_podl_get_admin_sate(struct pse_control *psec); +int pse_podl_set_admin_control(struct pse_control *psec, + enum ethtool_podl_pse_admin_state state); +int pse_podl_get_pw_d_status(struct pse_control *psec); + +#else + +static inline int pse_controller_register(struct pse_controller_dev *pcdev) +{ + return -ENOTSUPP; +} + +static inline void pse_controller_unregister(struct pse_controller_dev *pc= dev) +{ +} + +static inline int devm_pse_controller_register(struct device *dev, + struct pse_controller_dev *pcdev) +{ + return -ENOTSUPP; +} + +static inline struct pse_control *pse_control_get(struct device *dev) +{ + return ERR_PTR(-ENOTSUPP); +} + +static inline struct pse_control *devm_pse_control_get( struct device *dev) +{ + return ERR_PTR(-ENOTSUPP); +} + +static inline struct pse_control *of_pse_control_get(struct device_node *n= ode) +{ + return ERR_PTR(-ENOTSUPP); +} + +static inline void pse_control_put(struct pse_control *psec) +{ +} + +static inline int pse_podl_get_admin_sate(struct pse_control *psec) +{ + return -ENOTSUPP; +} + +static inline int +pse_podl_set_admin_control(struct pse_control *psec, + enum ethtool_podl_pse_admin_state state) +{ + return -ENOTSUPP; +} + +static inline int pse_podl_get_pw_d_status(struct pse_control *psec) +{ + return -ENOTSUPP; +} + +#endif + +#endif --=20 2.30.2 From nobody Fri Apr 10 20:21:46 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A2C14C32771 for ; Fri, 19 Aug 2022 12:01:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348665AbiHSMBt (ORCPT ); Fri, 19 Aug 2022 08:01:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48596 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1348544AbiHSMBe (ORCPT ); Fri, 19 Aug 2022 08:01:34 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 76B46E3990 for ; Fri, 19 Aug 2022 05:01:33 -0700 (PDT) Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1oP0ge-0007ml-NN; Fri, 19 Aug 2022 14:01:16 +0200 Received: from [2a0a:edc0:0:1101:1d::ac] (helo=dude04.red.stw.pengutronix.de) by drehscheibe.grey.stw.pengutronix.de with esmtp (Exim 4.94.2) (envelope-from ) id 1oP0gc-000hba-G9; Fri, 19 Aug 2022 14:01:14 +0200 Received: from ore by dude04.red.stw.pengutronix.de with local (Exim 4.94.2) (envelope-from ) id 1oP0ga-00GBb8-AE; Fri, 19 Aug 2022 14:01:12 +0200 From: Oleksij Rempel To: Andrew Lunn , Heiner Kallweit , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Russell King , Rob Herring , Krzysztof Kozlowski , Jonathan Corbet Cc: Oleksij Rempel , kernel@pengutronix.de, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-doc@vger.kernel.org, David Jander Subject: [PATCH net-next v1 4/7] net: pse-pd: add generic PSE driver Date: Fri, 19 Aug 2022 14:01:06 +0200 Message-Id: <20220819120109.3857571-5-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220819120109.3857571-1-o.rempel@pengutronix.de> References: <20220819120109.3857571-1-o.rempel@pengutronix.de> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-kernel@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Add generic driver to support simple Power Sourcing Equipment without automatic classification support. This driver was tested on 10Bast-T1L switch with regulator based PoDL PSE. Signed-off-by: Oleksij Rempel --- drivers/net/pse-pd/Kconfig | 11 +++ drivers/net/pse-pd/Makefile | 2 + drivers/net/pse-pd/pse_generic.c | 146 +++++++++++++++++++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 drivers/net/pse-pd/pse_generic.c diff --git a/drivers/net/pse-pd/Kconfig b/drivers/net/pse-pd/Kconfig index 49c7f0bcff526..a804c9f1af2bc 100644 --- a/drivers/net/pse-pd/Kconfig +++ b/drivers/net/pse-pd/Kconfig @@ -9,3 +9,14 @@ menuconfig PSE_CONTROLLER Generic Power Sourcing Equipment Controller support. =20 If unsure, say no. + +if PSE_CONTROLLER + +config PSE_GENERIC + tristate "Generic PSE driver" + help + This module provides support for simple Ethernet Power Sourcing + Equipment without automatic classification support. For example for + PoDL (802.3bu) specification. + +endif diff --git a/drivers/net/pse-pd/Makefile b/drivers/net/pse-pd/Makefile index cbb79fc2e2706..80ef39ad68f10 100644 --- a/drivers/net/pse-pd/Makefile +++ b/drivers/net/pse-pd/Makefile @@ -2,3 +2,5 @@ # Makefile for Linux PSE drivers =20 obj-$(CONFIG_PSE_CONTROLLER) +=3D pse-core.o + +obj-$(CONFIG_PSE_GENERIC) +=3D pse_generic.o diff --git a/drivers/net/pse-pd/pse_generic.c b/drivers/net/pse-pd/pse_gene= ric.c new file mode 100644 index 0000000000000..f264d4d589f59 --- /dev/null +++ b/drivers/net/pse-pd/pse_generic.c @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Driver for the Generic Ethernet Power Sourcing Equipment, without +// auto classification support. +// +// Copyright (c) 2022 Pengutronix, Oleksij Rempel +// + +#include +#include +#include +#include +#include + +struct gen_pse_priv { + struct pse_controller_dev pcdev; + struct regulator *ps; /*power source */ + enum ethtool_podl_pse_admin_state admin_state; +}; + +static struct gen_pse_priv *to_gen_pse(struct pse_controller_dev *pcdev) +{ + return container_of(pcdev, struct gen_pse_priv, pcdev); +} + +static int +gen_pse_podl_get_admin_sate(struct pse_controller_dev *pcdev, unsigned lon= g id) +{ + struct gen_pse_priv *priv =3D to_gen_pse(pcdev); + + /* aPoDLPSEAdminState can be different to aPoDLPSEPowerDetectionStatus + * which is provided by the regulator. + */ + return priv->admin_state; +} + +static int +gen_pse_podl_set_admin_control(struct pse_controller_dev *pcdev, + unsigned long id, + enum ethtool_podl_pse_admin_state state) +{ + struct gen_pse_priv *priv =3D to_gen_pse(pcdev); + int ret; + + if (priv->admin_state =3D=3D state) + goto set_state; + + switch (state) { + case ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED: + ret =3D regulator_enable(priv->ps); + break; + case ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED: + ret =3D regulator_disable(priv->ps); + break; + default: + dev_err(pcdev->dev, "Unknown admin state %i\n", state); + ret =3D -ENOTSUPP; + } + + if (ret) + return ret; + +set_state: + priv->admin_state =3D state; + + return 0; +} + +static int +gen_pse_podl_get_pw_d_status(struct pse_controller_dev *pcdev, unsigned lo= ng id) +{ + struct gen_pse_priv *priv =3D to_gen_pse(pcdev); + int ret; + + ret =3D regulator_is_enabled(priv->ps); + if (ret < 0) + return ret; + + if (!ret) + return ETHTOOL_PODL_PSE_PW_D_STATUS_DISABLED; + + return ETHTOOL_PODL_PSE_PW_D_STATUS_DELIVERING; +} + +static const struct pse_control_ops gen_pse_ops =3D { + .get_podl_pse_admin_sate =3D gen_pse_podl_get_admin_sate, + .set_podl_pse_admin_control =3D gen_pse_podl_set_admin_control, + .get_podl_pse_pw_d_status =3D gen_pse_podl_get_pw_d_status, +}; + +static int +gen_pse_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct gen_pse_priv *priv; + int ret; + + priv =3D devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + if (!pdev->dev.of_node) + return -ENOENT; + + priv->ps =3D devm_regulator_get(dev, "ieee802.3-podl-pse"); + if (IS_ERR(priv->ps)) { + dev_err(dev, "failed to get PSE regulator (%pe)\n", priv->ps); + return PTR_ERR(priv->ps); + } + + platform_set_drvdata(pdev, priv); + + priv->admin_state =3D ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED; + + priv->pcdev.owner =3D THIS_MODULE; + priv->pcdev.ops =3D &gen_pse_ops; + priv->pcdev.dev =3D dev; + ret =3D devm_pse_controller_register(dev, &priv->pcdev); + if (ret) { + dev_err(dev, "failed to register PSE controller (%pe)\n", + ERR_PTR(ret)); + return ret; + } + + return 0; +} + +static const struct of_device_id gen_pse_of_match[] =3D { + { .compatible =3D "ieee802.3-podl-pse-generic", }, + { }, +}; +MODULE_DEVICE_TABLE(of, gen_pse_of_match); + +static struct platform_driver gen_pse_driver =3D { + .probe =3D gen_pse_probe, + .driver =3D { + .name =3D "PSE Generic", + .of_match_table =3D of_match_ptr(gen_pse_of_match), + }, +}; +module_platform_driver(gen_pse_driver); + +MODULE_AUTHOR("Oleksij Rempel "); +MODULE_DESCRIPTION("Generic Ethernet Power Sourcing Equipment"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:pse-generic"); --=20 2.30.2 From nobody Fri Apr 10 20:21:46 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A3190C32773 for ; Fri, 19 Aug 2022 12:01:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348848AbiHSMBw (ORCPT ); Fri, 19 Aug 2022 08:01:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48672 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1348818AbiHSMBj (ORCPT ); Fri, 19 Aug 2022 08:01:39 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7CD61E398B for ; Fri, 19 Aug 2022 05:01:38 -0700 (PDT) Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1oP0ge-0007mT-NL; Fri, 19 Aug 2022 14:01:16 +0200 Received: from [2a0a:edc0:0:1101:1d::ac] (helo=dude04.red.stw.pengutronix.de) by drehscheibe.grey.stw.pengutronix.de with esmtp (Exim 4.94.2) (envelope-from ) id 1oP0gb-000hbL-7j; Fri, 19 Aug 2022 14:01:13 +0200 Received: from ore by dude04.red.stw.pengutronix.de with local (Exim 4.94.2) (envelope-from ) id 1oP0ga-00GBbH-Ar; Fri, 19 Aug 2022 14:01:12 +0200 From: Oleksij Rempel To: Andrew Lunn , Heiner Kallweit , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Russell King , Rob Herring , Krzysztof Kozlowski , Jonathan Corbet Cc: Oleksij Rempel , kernel@pengutronix.de, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-doc@vger.kernel.org, David Jander Subject: [PATCH net-next v1 5/7] net: mdiobus: fwnode_mdiobus_register_phy() rework error handling Date: Fri, 19 Aug 2022 14:01:07 +0200 Message-Id: <20220819120109.3857571-6-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220819120109.3857571-1-o.rempel@pengutronix.de> References: <20220819120109.3857571-1-o.rempel@pengutronix.de> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-kernel@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Rework error handling as preparation for PSE patch. This patch should make it easier to extend this function. Signed-off-by: Oleksij Rempel --- drivers/net/mdio/fwnode_mdio.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/net/mdio/fwnode_mdio.c b/drivers/net/mdio/fwnode_mdio.c index 3e79c2c519298..e78ad55c0e091 100644 --- a/drivers/net/mdio/fwnode_mdio.c +++ b/drivers/net/mdio/fwnode_mdio.c @@ -108,8 +108,8 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus, else phy =3D phy_device_create(bus, addr, phy_id, 0, NULL); if (IS_ERR(phy)) { - unregister_mii_timestamper(mii_ts); - return PTR_ERR(phy); + rc =3D PTR_ERR(phy); + goto clean_mii_ts; } =20 if (is_acpi_node(child)) { @@ -123,17 +123,13 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus, /* All data is now stored in the phy struct, so register it */ rc =3D phy_device_register(phy); if (rc) { - phy_device_free(phy); fwnode_handle_put(phy->mdio.dev.fwnode); - return rc; + goto clean_phy; } } else if (is_of_node(child)) { rc =3D fwnode_mdiobus_phy_device_register(bus, phy, child, addr); - if (rc) { - unregister_mii_timestamper(mii_ts); - phy_device_free(phy); - return rc; - } + if (rc) + goto clean_phy; } =20 /* phy->mii_ts may already be defined by the PHY driver. A @@ -143,5 +139,12 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus, if (mii_ts) phy->mii_ts =3D mii_ts; return 0; + +clean_phy: + phy_device_free(phy); +clean_mii_ts: + unregister_mii_timestamper(mii_ts); + + return rc; } EXPORT_SYMBOL(fwnode_mdiobus_register_phy); --=20 2.30.2 From nobody Fri Apr 10 20:21:46 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AB4A5C32792 for ; Fri, 19 Aug 2022 12:01:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348761AbiHSMBq (ORCPT ); Fri, 19 Aug 2022 08:01:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48588 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1348461AbiHSMBe (ORCPT ); Fri, 19 Aug 2022 08:01:34 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 76BB6E39BD for ; Fri, 19 Aug 2022 05:01:33 -0700 (PDT) Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1oP0ge-0007mp-NL; Fri, 19 Aug 2022 14:01:16 +0200 Received: from [2a0a:edc0:0:1101:1d::ac] (helo=dude04.red.stw.pengutronix.de) by drehscheibe.grey.stw.pengutronix.de with esmtp (Exim 4.94.2) (envelope-from ) id 1oP0gc-000hbd-KD; Fri, 19 Aug 2022 14:01:14 +0200 Received: from ore by dude04.red.stw.pengutronix.de with local (Exim 4.94.2) (envelope-from ) id 1oP0ga-00GBbQ-BR; Fri, 19 Aug 2022 14:01:12 +0200 From: Oleksij Rempel To: Andrew Lunn , Heiner Kallweit , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Russell King , Rob Herring , Krzysztof Kozlowski , Jonathan Corbet Cc: Oleksij Rempel , kernel@pengutronix.de, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-doc@vger.kernel.org, David Jander Subject: [PATCH net-next v1 6/7] net: mdiobus: search for PSE nodes by parsing PHY nodes. Date: Fri, 19 Aug 2022 14:01:08 +0200 Message-Id: <20220819120109.3857571-7-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220819120109.3857571-1-o.rempel@pengutronix.de> References: <20220819120109.3857571-1-o.rempel@pengutronix.de> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-kernel@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Some PHYs can be linked with PSE (Power Sourcing Equipment), so search for related nodes and attach it to the phydev. Signed-off-by: Oleksij Rempel --- drivers/net/mdio/fwnode_mdio.c | 37 ++++++++++++++++++++++++++++++++-- drivers/net/phy/phy_device.c | 2 ++ include/linux/phy.h | 2 ++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/drivers/net/mdio/fwnode_mdio.c b/drivers/net/mdio/fwnode_mdio.c index e78ad55c0e091..1e775c449f5db 100644 --- a/drivers/net/mdio/fwnode_mdio.c +++ b/drivers/net/mdio/fwnode_mdio.c @@ -10,10 +10,31 @@ #include #include #include +#include =20 MODULE_AUTHOR("Calvin Johnson "); MODULE_LICENSE("GPL"); =20 +static struct pse_control * +fwnode_find_pse_control(struct fwnode_handle *fwnode) +{ + struct pse_control *psec; + struct device_node *np; + + if (is_acpi_node(fwnode)) + return NULL; + + np =3D to_of_node(fwnode); + if (!np) + return NULL; + + psec =3D of_pse_control_get(np); + if (IS_ERR_OR_NULL(psec)) + return NULL; + + return psec; +} + static struct mii_timestamper * fwnode_find_mii_timestamper(struct fwnode_handle *fwnode) { @@ -89,14 +110,21 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus, struct fwnode_handle *child, u32 addr) { struct mii_timestamper *mii_ts =3D NULL; + struct pse_control *psec =3D NULL; struct phy_device *phy; bool is_c45 =3D false; u32 phy_id; int rc; =20 + psec =3D fwnode_find_pse_control(child); + if (IS_ERR(psec)) + return PTR_ERR(psec); + mii_ts =3D fwnode_find_mii_timestamper(child); - if (IS_ERR(mii_ts)) - return PTR_ERR(mii_ts); + if (IS_ERR(mii_ts)) { + rc =3D PTR_ERR(mii_ts); + goto clean_pse; + } =20 rc =3D fwnode_property_match_string(child, "compatible", "ethernet-phy-ieee802.3-c45"); @@ -132,18 +160,23 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus, goto clean_phy; } =20 + phy->psec =3D psec; + /* phy->mii_ts may already be defined by the PHY driver. A * mii_timestamper probed via the device tree will still have * precedence. */ if (mii_ts) phy->mii_ts =3D mii_ts; + return 0; =20 clean_phy: phy_device_free(phy); clean_mii_ts: unregister_mii_timestamper(mii_ts); +clean_pse: + pse_control_put(psec); =20 return rc; } diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 0c6efd7926907..221bc872ee2fb 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -988,6 +989,7 @@ EXPORT_SYMBOL(phy_device_register); */ void phy_device_remove(struct phy_device *phydev) { + pse_control_put(phydev->psec); unregister_mii_timestamper(phydev->mii_ts); =20 device_del(&phydev->mdio.dev); diff --git a/include/linux/phy.h b/include/linux/phy.h index 87638c55d8442..0c91870b82582 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -588,6 +588,7 @@ struct macsec_ops; * @master_slave_get: Current master/slave advertisement * @master_slave_state: Current master/slave configuration * @mii_ts: Pointer to time stamper callbacks + * @psec: Pointer to Power Sourcing Equipment control struct * @lock: Mutex for serialization access to PHY * @state_queue: Work queue for state machine * @shared: Pointer to private data shared by phys in one package @@ -701,6 +702,7 @@ struct phy_device { struct phylink *phylink; struct net_device *attached_dev; struct mii_timestamper *mii_ts; + struct pse_control *psec; =20 u8 mdix; u8 mdix_ctrl; --=20 2.30.2 From nobody Fri Apr 10 20:21:46 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A736AC32789 for ; Fri, 19 Aug 2022 12:01:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348867AbiHSMB4 (ORCPT ); Fri, 19 Aug 2022 08:01:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48700 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1348823AbiHSMBk (ORCPT ); Fri, 19 Aug 2022 08:01:40 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B3A55E3990 for ; Fri, 19 Aug 2022 05:01:38 -0700 (PDT) Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1oP0ge-0007mV-NL; Fri, 19 Aug 2022 14:01:16 +0200 Received: from [2a0a:edc0:0:1101:1d::ac] (helo=dude04.red.stw.pengutronix.de) by drehscheibe.grey.stw.pengutronix.de with esmtp (Exim 4.94.2) (envelope-from ) id 1oP0gb-000hbN-AN; Fri, 19 Aug 2022 14:01:13 +0200 Received: from ore by dude04.red.stw.pengutronix.de with local (Exim 4.94.2) (envelope-from ) id 1oP0ga-00GBbZ-C4; Fri, 19 Aug 2022 14:01:12 +0200 From: Oleksij Rempel To: Andrew Lunn , Heiner Kallweit , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Russell King , Rob Herring , Krzysztof Kozlowski , Jonathan Corbet Cc: Oleksij Rempel , kernel@pengutronix.de, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-doc@vger.kernel.org, David Jander Subject: [PATCH net-next v1 7/7] ethtool: add interface to interact with Ethernet Power Equipment Date: Fri, 19 Aug 2022 14:01:09 +0200 Message-Id: <20220819120109.3857571-8-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220819120109.3857571-1-o.rempel@pengutronix.de> References: <20220819120109.3857571-1-o.rempel@pengutronix.de> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-kernel@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add interface to support Power Sourcing Equipment. At current step it provides generic way to address all variants of PSE devices as defined in IEEE 802.3-2018 but support only objects specified for IEEE 802.3-2018 1= 04.4 PoDL Power Sourcing Equipment (PSE). Currently supported and mandatory objects are: IEEE 802.3-2018 30.15.1.1.3 aPoDLPSEPowerDetectionStatus IEEE 802.3-2018 30.15.1.1.2 aPoDLPSEAdminState IEEE 802.3-2018 30.15.1.2.1 acPoDLPSEAdminControl This is minimal interface needed to control PSE on each separate ethernet port but it provides not all mandatory objects specified in IEEE 802.3-2018. Since "PoDL PSE" and "PSE" have similar names, but some different values I decide to not merge them and keep separate naming schema. This should allow as to be as close to IEEE 802.3 spec as possible and avoid name conflicts in the future. This implementation is connected to PHYs instead of MACs because PSE auto classification can potentially interfere with PHY auto negotiation. So, may be some extra PHY related initialization will be needed. With WIP version of ethtools interaction with PSE capable link looks as following: $ ip l ... 5: t1l1@eth0: .. ... $ ethtool --show-pse t1l1 PSE attributs for t1l1: PoDL PSE Admin State: disabled PoDL PSE Power Detection Status: disabled $ ethtool --set-pse t1l1 podl-pse-admin-control enable $ ethtool --show-pse t1l1 PSE attributs for t1l1: PoDL PSE Admin State: enabled PoDL PSE Power Detection Status: delivering power Signed-off-by: Oleksij Rempel Reported-by: kernel test robot --- Documentation/networking/ethtool-netlink.rst | 60 ++++++ include/uapi/linux/ethtool.h | 50 +++++ include/uapi/linux/ethtool_netlink.h | 17 ++ net/ethtool/Makefile | 3 +- net/ethtool/netlink.c | 19 ++ net/ethtool/netlink.h | 4 + net/ethtool/pse-pd.c | 194 +++++++++++++++++++ 7 files changed, 346 insertions(+), 1 deletion(-) create mode 100644 net/ethtool/pse-pd.c diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/n= etworking/ethtool-netlink.rst index dbca3e9ec782f..c8b09b57bd65e 100644 --- a/Documentation/networking/ethtool-netlink.rst +++ b/Documentation/networking/ethtool-netlink.rst @@ -220,6 +220,8 @@ Userspace to kernel: ``ETHTOOL_MSG_PHC_VCLOCKS_GET`` get PHC virtual clocks info ``ETHTOOL_MSG_MODULE_SET`` set transceiver module parameters ``ETHTOOL_MSG_MODULE_GET`` get transceiver module parameters + ``ETHTOOL_MSG_PSE_SET`` set PSE parameters + ``ETHTOOL_MSG_PSE_GET`` get PSE parameters =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 Kernel to userspace: @@ -260,6 +262,7 @@ Kernel to userspace: ``ETHTOOL_MSG_STATS_GET_REPLY`` standard statistics ``ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY`` PHC virtual clocks info ``ETHTOOL_MSG_MODULE_GET_REPLY`` transceiver module parameters + ``ETHTOOL_MSG_PSE_GET_REPLY`` PSE parameters =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 ``GET`` requests are sent by userspace applications to retrieve device @@ -1625,6 +1628,63 @@ For SFF-8636 modules, low power mode is forced by th= e host according to table For CMIS modules, low power mode is forced by the host according to table = 6-12 in revision 5.0 of the specification. =20 +PSE_GET +=3D=3D=3D=3D=3D=3D=3D + +Gets PSE attributes. + +Request contents: + + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D =3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + ``ETHTOOL_A_PSE_HEADER`` nested request header + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D =3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Kernel response contents: + + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D =3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + ``ETHTOOL_A_PSE_HEADER`` nested reply header + ``ETHTOOL_A_PODL_PSE_ADMIN_STATE`` u8 Operational state of the= PoDL + PSE functions + ``ETHTOOL_A_PODL_PSE_PW_D_STATUS`` u8 power detection status o= f the + PoDL PSE. + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D =3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +The ``ETHTOOL_A_PODL_PSE_ADMIN_STATE`` identifies the operational state of= the +PoDL PSE functions. The operational state of the PSE function can be chan= ged +using the ``ETHTOOL_A_PODL_PSE_ADMIN_CONTROL`` action. This option is +corresponding to IEEE 802.3-2018 30.15.1.1.2 aPoDLPSEAdminState. Possible = values +are: + +.. kernel-doc:: include/uapi/linux/ethtool.h + :identifiers: ethtool_podl_pse_admin_state + +The ``ETHTOOL_A_PODL_PSE_PW_D_STATUS`` identifies the power detection stat= us of the +PoDL PSE. The status depend on internal PSE state machine and automatic +PD classification support. This option is corresponding to IEEE 802.3-2018 +30.15.1.1.3 aPoDLPSEPowerDetectionStatus. Possible values are: + +.. kernel-doc:: include/uapi/linux/ethtool.h + :identifiers: ethtool_podl_pse_admin_state + +PSE_SET +=3D=3D=3D=3D=3D=3D=3D + +Sets PSE parameters. + +Request contents: + + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D =3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + ``ETHTOOL_A_PSE_HEADER`` nested request header + ``ETHTOOL_A_PODL_PSE_ADMIN_CONTROL`` u8 Control PoDL PSE Admin s= tate + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D =3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +When set, the optional ``ETHTOOL_A_PODL_PSE_ADMIN_CONTROL`` attribute is u= sed +to control PoDL PSE Admin functions. This option is implementing +IEEE 802.3-2018 30.15.1.2.1 acPoDLPSEAdminControl. Possible values are: + +.. kernel-doc:: include/uapi/linux/ethtool.h + :identifiers: ethtool_podl_pse_admin_state + Request translation =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index 2d5741fd44bbc..783f19f78c633 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -736,6 +736,56 @@ enum ethtool_module_power_mode { ETHTOOL_MODULE_POWER_MODE_HIGH, }; =20 +/** + * enum ethtool_podl_pse_admin_state - operational state of the PoDL PSE + * functions. IEEE 802.3-2018 30.15.1.1.2 aPoDLPSEAdminState + * @ETHTOOL_PSE_MODE_POLICY_UNKNOWN: state of PoDL PSE functions are unkno= wn + * @ETHTOOL_PSE_MODE_POLICY_HIGH: PoDL PSE functions are disabled + * @ETHTOOL_PSE_MODE_POLICY_AUTO: PoDL PSE functions are enabled + */ +enum ethtool_podl_pse_admin_state { + ETHTOOL_PODL_PSE_ADMIN_STATE_UNKNOWN =3D 1, + ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED, + ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED, + + /* add new constants above here */ + ETHTOOL_PODL_PSE_ADMIN_STATE_COUNT +}; + +/** + * enum ethtool_podl_pse_pw_d_status - power detection status of the PoDL = PSE. + * IEEE 802.3-2018 30.15.1.1.3 aPoDLPSEPowerDetectionStatus: + * @ETHTOOL_PODL_PSE_PW_D_STATUS_UNKNOWN: PoDL PSE + * @ETHTOOL_PODL_PSE_PW_D_STATUS_DISABLED: "The enumeration =E2=80=9Cdisab= led=E2=80=9D is + * asserted true when the PoDL PSE state diagram variable mr_pse_enable is + * false" + * @ETHTOOL_PODL_PSE_PW_D_STATUS_SEARCHING: "The enumeration =E2=80=9Csear= ching=E2=80=9D is + * asserted true when either of the PSE state diagram variables + * pi_detecting or pi_classifying is true." + * @ETHTOOL_PODL_PSE_PW_D_STATUS_DELIVERING: "The enumeration =E2=80=9Cdel= iveringPower=E2=80=9D + * is asserted true when the PoDL PSE state diagram variable pi_powered is + * true." + * @ETHTOOL_PODL_PSE_PW_D_STATUS_SLEEP: "The enumeration =E2=80=9Csleep=E2= =80=9D is asserted + * true when the PoDL PSE state diagram variable pi_sleeping is true." + * @ETHTOOL_PODL_PSE_PW_D_STATUS_IDLE: "The enumeration =E2=80=9Cidle=E2= =80=9D is asserted true + * when the logical combination of the PoDL PSE state diagram variables + * pi_prebiased*!pi_sleeping is true." + * @ETHTOOL_PODL_PSE_PW_D_STATUS_ERROR: "The enumeration =E2=80=9Cerror=E2= =80=9D is asserted + * true when the PoDL PSE state diagram variable overload_held is true." + */ +enum ethtool_podl_pse_pw_d_status { + ETHTOOL_PODL_PSE_PW_D_STATUS_UNKNOWN =3D 1, + ETHTOOL_PODL_PSE_PW_D_STATUS_DISABLED, + ETHTOOL_PODL_PSE_PW_D_STATUS_SEARCHING, + ETHTOOL_PODL_PSE_PW_D_STATUS_DELIVERING, + ETHTOOL_PODL_PSE_PW_D_STATUS_SLEEP, + ETHTOOL_PODL_PSE_PW_D_STATUS_IDLE, + ETHTOOL_PODL_PSE_PW_D_STATUS_ERROR, + + /* add new constants above here */ + ETHTOOL_PODL_PSE_PW_D_STATUS_COUNT +}; + /** * struct ethtool_gstrings - string set for data tagging * @cmd: Command number =3D %ETHTOOL_GSTRINGS diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/etht= ool_netlink.h index d2fb4f7be61b2..1c890a37a35b5 100644 --- a/include/uapi/linux/ethtool_netlink.h +++ b/include/uapi/linux/ethtool_netlink.h @@ -49,6 +49,8 @@ enum { ETHTOOL_MSG_PHC_VCLOCKS_GET, ETHTOOL_MSG_MODULE_GET, ETHTOOL_MSG_MODULE_SET, + ETHTOOL_MSG_PSE_GET, + ETHTOOL_MSG_PSE_SET, =20 /* add new constants above here */ __ETHTOOL_MSG_USER_CNT, @@ -94,6 +96,8 @@ enum { ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY, ETHTOOL_MSG_MODULE_GET_REPLY, ETHTOOL_MSG_MODULE_NTF, + ETHTOOL_MSG_PSE_GET_REPLY, + ETHTOOL_MSG_PSE_NTF, =20 /* add new constants above here */ __ETHTOOL_MSG_KERNEL_CNT, @@ -862,6 +866,19 @@ enum { ETHTOOL_A_MODULE_MAX =3D (__ETHTOOL_A_MODULE_CNT - 1) }; =20 +/* Power Sourcing Equipment */ +enum { + ETHTOOL_A_PSE_UNSPEC, + ETHTOOL_A_PSE_HEADER, /* nest - _A_HEADER_* */ + ETHTOOL_A_PODL_PSE_ADMIN_STATE, /* u8 */ + ETHTOOL_A_PODL_PSE_ADMIN_CONTROL, /* u8 */ + ETHTOOL_A_PODL_PSE_PW_D_STATUS, /* u8 */ + + /* add new constants above here */ + __ETHTOOL_A_PSE_CNT, + ETHTOOL_A_PSE_MAX =3D (__ETHTOOL_A_PSE_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 b76432e70e6ba..7247769829641 100644 --- a/net/ethtool/Makefile +++ b/net/ethtool/Makefile @@ -7,4 +7,5 @@ obj-$(CONFIG_ETHTOOL_NETLINK) +=3D ethtool_nl.o ethtool_nl-y :=3D netlink.o bitset.o strset.o linkinfo.o linkmodes.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 module.o + tunnels.o fec.o eeprom.o stats.o phc_vclocks.o module.o \ + pse.o diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index e26079e11835c..ec84a12ba4918 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -286,6 +286,7 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] =3D { [ETHTOOL_MSG_STATS_GET] =3D ðnl_stats_request_ops, [ETHTOOL_MSG_PHC_VCLOCKS_GET] =3D ðnl_phc_vclocks_request_ops, [ETHTOOL_MSG_MODULE_GET] =3D ðnl_module_request_ops, + [ETHTOOL_MSG_PSE_GET] =3D ðnl_pse_request_ops, }; =20 static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *= cb) @@ -598,6 +599,7 @@ ethnl_default_notify_ops[ETHTOOL_MSG_KERNEL_MAX + 1] = =3D { [ETHTOOL_MSG_EEE_NTF] =3D ðnl_eee_request_ops, [ETHTOOL_MSG_FEC_NTF] =3D ðnl_fec_request_ops, [ETHTOOL_MSG_MODULE_NTF] =3D ðnl_module_request_ops, + [ETHTOOL_MSG_PSE_NTF] =3D ðnl_pse_request_ops, }; =20 /* default notification handler */ @@ -691,6 +693,7 @@ static const ethnl_notify_handler_t ethnl_notify_handle= rs[] =3D { [ETHTOOL_MSG_EEE_NTF] =3D ethnl_default_notify, [ETHTOOL_MSG_FEC_NTF] =3D ethnl_default_notify, [ETHTOOL_MSG_MODULE_NTF] =3D ethnl_default_notify, + [ETHTOOL_MSG_PSE_NTF] =3D ethnl_default_notify, }; =20 void ethtool_notify(struct net_device *dev, unsigned int cmd, const void *= data) @@ -1020,6 +1023,22 @@ static const struct genl_ops ethtool_genl_ops[] =3D { .policy =3D ethnl_module_set_policy, .maxattr =3D ARRAY_SIZE(ethnl_module_set_policy) - 1, }, + { + .cmd =3D ETHTOOL_MSG_PSE_GET, + .doit =3D ethnl_default_doit, + .start =3D ethnl_default_start, + .dumpit =3D ethnl_default_dumpit, + .done =3D ethnl_default_done, + .policy =3D ethnl_pse_get_policy, + .maxattr =3D ARRAY_SIZE(ethnl_pse_get_policy) - 1, + }, + { + .cmd =3D ETHTOOL_MSG_PSE_SET, + .flags =3D GENL_UNS_ADMIN_PERM, + .doit =3D ethnl_set_pse, + .policy =3D ethnl_pse_set_policy, + .maxattr =3D ARRAY_SIZE(ethnl_pse_set_policy) - 1, + }, }; =20 static const struct genl_multicast_group ethtool_nl_mcgrps[] =3D { diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h index c0d5876118546..1bfd374f97188 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -345,6 +345,7 @@ extern const struct ethnl_request_ops ethnl_module_eepr= om_request_ops; extern const struct ethnl_request_ops ethnl_stats_request_ops; extern const struct ethnl_request_ops ethnl_phc_vclocks_request_ops; extern const struct ethnl_request_ops ethnl_module_request_ops; +extern const struct ethnl_request_ops ethnl_pse_request_ops; =20 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]; @@ -383,6 +384,8 @@ extern const struct nla_policy ethnl_stats_get_policy[E= THTOOL_A_STATS_GROUPS + 1 extern const struct nla_policy ethnl_phc_vclocks_get_policy[ETHTOOL_A_PHC_= VCLOCKS_HEADER + 1]; extern const struct nla_policy ethnl_module_get_policy[ETHTOOL_A_MODULE_HE= ADER + 1]; extern const struct nla_policy ethnl_module_set_policy[ETHTOOL_A_MODULE_PO= WER_MODE_POLICY + 1]; +extern const struct nla_policy ethnl_pse_get_policy[ETHTOOL_A_PSE_HEADER += 1]; +extern const struct nla_policy ethnl_pse_set_policy[ETHTOOL_A_PSE_MAX + 1]; =20 int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info); int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info); @@ -402,6 +405,7 @@ int ethnl_tunnel_info_start(struct netlink_callback *cb= ); int ethnl_tunnel_info_dumpit(struct sk_buff *skb, struct netlink_callback = *cb); int ethnl_set_fec(struct sk_buff *skb, struct genl_info *info); int ethnl_set_module(struct sk_buff *skb, struct genl_info *info); +int ethnl_set_pse(struct sk_buff *skb, struct genl_info *info); =20 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_G= STRING_LEN]; diff --git a/net/ethtool/pse-pd.c b/net/ethtool/pse-pd.c new file mode 100644 index 0000000000000..216c6b0d327b5 --- /dev/null +++ b/net/ethtool/pse-pd.c @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// ethtool interface for for Ethernet PSE (Power Sourcing Equipment) +// and PD (Powered Device) +// +// Copyright (c) 2022 Pengutronix, Oleksij Rempel +// + +#include "netlink.h" +#include "common.h" +#include +#include "linux/pse-pd/pse.h" + +struct pse_req_info { + struct ethnl_req_info base; +}; + +struct pse_reply_data { + struct ethnl_reply_data base; + int podl_pse_admin_state; + int podl_pse_pw_d_status; +}; + +#define PSE_REPDATA(__reply_base) \ + container_of(__reply_base, struct pse_reply_data, base) + +/* PSE_GET */ + +const struct nla_policy ethnl_pse_get_policy[ETHTOOL_A_PSE_HEADER + 1] =3D= { + [ETHTOOL_A_PSE_HEADER] =3D NLA_POLICY_NESTED(ethnl_header_policy), +}; + +static int pse_get_pse_attributs(struct net_device *dev, + struct pse_reply_data *data) +{ + struct phy_device *phydev =3D dev->phydev; + int ret; + + if (!phydev) + return -EOPNOTSUPP; + + mutex_lock(&phydev->lock); + if (!phydev->psec) { + ret =3D -EOPNOTSUPP; + goto error_unlock; + } + + ret =3D pse_podl_get_admin_sate(phydev->psec); + if (ret < 0) + goto error_unlock; + + data->podl_pse_admin_state =3D ret; + + ret =3D pse_podl_get_pw_d_status(phydev->psec); + if (ret < 0) + goto error_unlock; + + data->podl_pse_pw_d_status =3D ret; + +error_unlock: + mutex_unlock(&phydev->lock); + + return ret; +} + +static int pse_prepare_data(const struct ethnl_req_info *req_base, + struct ethnl_reply_data *reply_base, + struct genl_info *info) +{ + struct pse_reply_data *data =3D PSE_REPDATA(reply_base); + struct net_device *dev =3D reply_base->dev; + int ret; + + ret =3D ethnl_ops_begin(dev); + if (ret < 0) + return ret; + + ret =3D pse_get_pse_attributs(dev, data); + + ethnl_ops_complete(dev); + + return ret; +} + +static int pse_reply_size(const struct ethnl_req_info *req_base, + const struct ethnl_reply_data *reply_base) +{ + struct pse_reply_data *data =3D PSE_REPDATA(reply_base); + int len =3D 0; + + if (data->podl_pse_admin_state >=3D 0) + len +=3D nla_total_size(sizeof(u8)); /* _PODL_PSE_ADMIN_STATE */ + if (data->podl_pse_pw_d_status >=3D 0) + len +=3D nla_total_size(sizeof(u8)); /* _PODL_PSE_PW_D_STATUS */ + + return len; +} + +static int pse_fill_reply(struct sk_buff *skb, + const struct ethnl_req_info *req_base, + const struct ethnl_reply_data *reply_base) +{ + const struct pse_reply_data *data =3D PSE_REPDATA(reply_base); + + if (data->podl_pse_admin_state >=3D 0 && + nla_put_u8(skb, ETHTOOL_A_PODL_PSE_ADMIN_STATE, + data->podl_pse_admin_state)) + return -EMSGSIZE; + + if (data->podl_pse_pw_d_status >=3D 0 && + nla_put_u8(skb, ETHTOOL_A_PODL_PSE_PW_D_STATUS, + data->podl_pse_pw_d_status)) + return -EMSGSIZE; + + return 0; +} + +const struct ethnl_request_ops ethnl_pse_request_ops =3D { + .request_cmd =3D ETHTOOL_MSG_PSE_GET, + .reply_cmd =3D ETHTOOL_MSG_PSE_GET_REPLY, + .hdr_attr =3D ETHTOOL_A_PSE_HEADER, + .req_info_size =3D sizeof(struct pse_req_info), + .reply_data_size =3D sizeof(struct pse_reply_data), + + .prepare_data =3D pse_prepare_data, + .reply_size =3D pse_reply_size, + .fill_reply =3D pse_fill_reply, +}; + +/* PSE_SET */ + +const struct nla_policy ethnl_pse_set_policy[ETHTOOL_A_PSE_MAX + 1] =3D { + [ETHTOOL_A_PSE_HEADER] =3D NLA_POLICY_NESTED(ethnl_header_policy), + [ETHTOOL_A_PODL_PSE_ADMIN_CONTROL] =3D + NLA_POLICY_RANGE(NLA_U8, ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED, + ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED), +}; + +static int pse_set_pse_mode(struct net_device *dev, struct nlattr **tb) +{ + enum ethtool_podl_pse_admin_state state; + struct phy_device *phydev =3D dev->phydev; + int ret; + + if (!tb[ETHTOOL_A_PODL_PSE_ADMIN_CONTROL]) + return 0; + + state =3D nla_get_u8(tb[ETHTOOL_A_PODL_PSE_ADMIN_CONTROL]); + + if (!phydev) + return -EOPNOTSUPP; + + mutex_lock(&phydev->lock); + if (!phydev->psec) + ret =3D -EOPNOTSUPP; + else + ret =3D pse_podl_set_admin_control(phydev->psec, state); + mutex_unlock(&phydev->lock); + + return ret; +} + +int ethnl_set_pse(struct sk_buff *skb, struct genl_info *info) +{ + struct ethnl_req_info req_info =3D {}; + struct nlattr **tb =3D info->attrs; + struct net_device *dev; + int ret; + + ret =3D ethnl_parse_header_dev_get(&req_info, tb[ETHTOOL_A_PSE_HEADER], + genl_info_net(info), info->extack, + true); + if (ret < 0) + return ret; + dev =3D req_info.dev; + + rtnl_lock(); + ret =3D ethnl_ops_begin(dev); + if (ret < 0) + goto out_rtnl; + + ret =3D pse_set_pse_mode(dev, tb); + if (ret < 0) + goto out_ops; + + ethtool_notify(dev, ETHTOOL_MSG_PSE_NTF, NULL); + +out_ops: + ethnl_ops_complete(dev); +out_rtnl: + rtnl_unlock(); + ethnl_parse_header_dev_put(&req_info); + return ret; +} --=20 2.30.2