From nobody Thu Sep 18 12:53:45 2025 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 B5532C4708E for ; Tue, 6 Dec 2022 12:52:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234350AbiLFMwl (ORCPT ); Tue, 6 Dec 2022 07:52:41 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56450 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234390AbiLFMwf (ORCPT ); Tue, 6 Dec 2022 07:52:35 -0500 Received: from mail-ed1-x52c.google.com (mail-ed1-x52c.google.com [IPv6:2a00:1450:4864:20::52c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B6E9E1839C; Tue, 6 Dec 2022 04:52:24 -0800 (PST) Received: by mail-ed1-x52c.google.com with SMTP id m19so20084347edj.8; Tue, 06 Dec 2022 04:52:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=in-reply-to:content-transfer-encoding:content-disposition :mime-version:references:message-id:subject:cc:to:from:date:from:to :cc:subject:date:message-id:reply-to; bh=74BFqwUTcgpc/7zsTZVAsiQmX/jMtMmjSZEV7hyDC7M=; b=DTgB7WMVy1PTMRcvpYCqzjztI4ZyizUfgp3jdquAxGQnMCC8UiH1iEMBTlFyNb93Hl ZXJzjJV0y4PXKmCfWT/XlOK1lDi4skQ9psq65XLy6d6dolwxqlZNGUWK2ItfIUDkbS7i YE97Gj7d1jsiAAadTiX29KhybQxVNYURKsZFvypT3VZHlL7P/OZtm9LfM8TcwKc5xtmI 2ou5uFhiBPx8WYcjTLZyQ5zSiaxWbVJwIvLsfOXDR62NdNJTQiggYVFXf6YmCQQPe9Xb CiwnpZN+AXvXRFonV9sJZSVH9yzHz6sKlXbkm4e6V6kESSDJKfj1zITFZDH9fxS9RemP ObSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=in-reply-to:content-transfer-encoding:content-disposition :mime-version:references:message-id:subject:cc:to:from:date :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=74BFqwUTcgpc/7zsTZVAsiQmX/jMtMmjSZEV7hyDC7M=; b=QULeiZTpr41lD+u51PGk6yP9uGJTlKqkq625HmUg/LKerZIGtV+J9gV/kbXJYiPi4J 8yqJ+RYIKGQIX4Tyd5qDe9auXvB+YEpOK1Y9jgY7OLuydDgq4ok+s52S2Ap6EX7RkbwP 8YeuQylFxDVH/dRaes8NEekjCsWST0oHu6vn5LkliC59BVvidTh82K3sbIE8737/EqmJ K75Ybde+jWYk7ZYbvvY1brHOEpBgAp3aROBHUXqfKrqviQHNO0WQIWS4pfrLDNZ7gfjQ HS3kFNjvDTZHhIbQfgII26gbnIju4Hf/RTXdklkjlXygBPdT8DqA7UB/yqHFW3R2Ra01 cZiw== X-Gm-Message-State: ANoB5pm6sDGs5FJek7aEn0KdmxgNbjJTEil3BRHwWHMtrpL1MldAW0mJ ScKKILZzAEikpLUDkcGorns= X-Google-Smtp-Source: AA0mqf4cNKmGVTeRAT/vACEY88Ya7lYQfi3wqhpRSpjsMKUL1h/+ujgbgajdLID9CyIcdvYBYIMkOQ== X-Received: by 2002:aa7:cc8d:0:b0:461:15f0:a574 with SMTP id p13-20020aa7cc8d000000b0046115f0a574mr21537041edt.187.1670331142866; Tue, 06 Dec 2022 04:52:22 -0800 (PST) Received: from gvm01 (net-2-45-26-236.cust.vodafonedsl.it. [2.45.26.236]) by smtp.gmail.com with ESMTPSA id tj13-20020a170907c24d00b00780b1979adesm7365886ejc.218.2022.12.06.04.52.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Dec 2022 04:52:22 -0800 (PST) Date: Tue, 6 Dec 2022 13:52:32 +0100 From: Piergiorgio Beruto To: Andrew Lunn , Heiner Kallweit , Russell King , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Oleksij Rempel Subject: [PATCH v4 net-next 1/5] net/ethtool: add netlink interface for the PLCA RS Message-ID: <6ac7b9b950c732b8d7d9005b716e23cea1d6463f.1670329232.git.piergiorgio.beruto@gmail.com> References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Disposition: inline Content-Transfer-Encoding: quoted-printable In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add support for configuring the PLCA Reconciliation Sublayer on multi-drop PHYs that support IEEE802.3cg-2019 Clause 148 (e.g., 10BASE-T1S). This patch adds the appropriate netlink interface to ethtool. Signed-off-by: Piergiorgio Beruto --- Documentation/networking/ethtool-netlink.rst | 133 +++++++++ MAINTAINERS | 6 + include/linux/ethtool.h | 11 + include/linux/phy.h | 64 ++++ include/uapi/linux/ethtool_netlink.h | 25 ++ net/ethtool/Makefile | 2 +- net/ethtool/netlink.c | 30 ++ net/ethtool/netlink.h | 6 + net/ethtool/plca.c | 290 +++++++++++++++++++ 9 files changed, 566 insertions(+), 1 deletion(-) create mode 100644 net/ethtool/plca.c diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/n= etworking/ethtool-netlink.rst index bede24ef44fd..044c20a52e24 100644 --- a/Documentation/networking/ethtool-netlink.rst +++ b/Documentation/networking/ethtool-netlink.rst @@ -1687,6 +1687,136 @@ to control PoDL PSE Admin functions. This option is= implementing ``IEEE 802.3-2018`` 30.15.1.2.1 acPoDLPSEAdminControl. See ``ETHTOOL_A_PODL_PSE_ADMIN_STATE`` for supported values. =20 +PLCA_GET_CFG +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Gets PLCA RS 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_PLCA_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=3D=3D= =3D + ``ETHTOOL_A_PLCA_HEADER`` nested reply header + ``ETHTOOL_A_PLCA_VERSION`` u16 Supported PLCA management + interface standard/versi= on + ``ETHTOOL_A_PLCA_ENABLED`` u8 PLCA Admin State + ``ETHTOOL_A_PLCA_NODE_ID`` u8 PLCA unique local node ID + ``ETHTOOL_A_PLCA_NODE_CNT`` u8 Number of PLCA nodes on = the + netkork, including the + coordinator + ``ETHTOOL_A_PLCA_TO_TMR`` u8 Transmit Opportunity Tim= er + value in bit-times (BT) + ``ETHTOOL_A_PLCA_BURST_CNT`` u8 Number of additional pac= kets + the node is allowed to s= end + within a single TO + ``ETHTOOL_A_PLCA_BURST_TMR`` u8 Time to wait for the MAC= to + transmit a new frame bef= ore + terminating the burst + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D =3D=3D=3D= =3D=3D=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_PLCA_VERSION`` attribute indicates which +standard and version the PLCA management interface complies to. When not s= et, +the interface is vendor-specific and (possibly) supplied by the driver. +The OPEN Alliance SIG specifies a standard register map for 10BASE-T1S PHYs +embedding the PLCA Reconcialiation Sublayer. See "10BASE-T1S PLCA Manageme= nt +Registers" at https://www.opensig.org/about/specifications/. When this sta= ndard +is supported, ETHTOOL_A_PLCA_VERSION is reported as 0Axx where 'xx' denote= s the +map version (see Table A.1.0 =E2=80=94 IDVER bits assignment). + +When set, the optional ``ETHTOOL_A_PLCA_ENABLED`` attribute indicates the +administrative state of the PLCA RS. When not set, the node operates in "p= lain" +CSMA/CD mode. This option is corresponding to ``IEEE 802.3cg-2019`` 30.16.= 1.1.1 +aPLCAAdminState / 30.16.1.2.1 acPLCAAdminControl. + +When set, the optional ``ETHTOOL_A_PLCA_NODE_ID`` attribute indicates the +configured local node ID of the PHY. This ID determines which transmit +opportunity (TO) is reserved for the node to transmit into. This option is +corresponding to ``IEEE 802.3cg-2019`` 30.16.1.1.4 aPLCALocalNodeID. + +When set, the optional ``ETHTOOL_A_PLCA_NODE_CNT`` attribute indicates the +configured maximum number of PLCA nodes on the mixing-segment. This number +determines the total number of transmit opportunities generated during a +PLCA cycle. This attribute is relevant only for the PLCA coordinator, whic= h is +the node with aPLCALocalNodeID set to 0. Follower nodes ignore this settin= g. +This option is corresponding to ``IEEE 802.3cg-2019`` 30.16.1.1.3 +aPLCANodeCount. + +When set, the optional ``ETHTOOL_A_PLCA_TO_TMR`` attribute indicates the +configured value of the transmit opportunity timer in bit-times. This value +must be set equal across all nodes sharing the medium for PLCA to work +correctly. This option is corresponding to ``IEEE 802.3cg-2019`` 30.16.1.1= .5 +aPLCATransmitOpportunityTimer. + +When set, the optional ``ETHTOOL_A_PLCA_BURST_CNT`` attribute indicates the +configured number of extra packets that the node is allowed to send during= a +single transmit opportunity. By default, this attribute is 0, meaning that +the node can only send a sigle frame per TO. When greater than 0, the PLCA= RS +keeps the TO after any transmission, waiting for the MAC to send a new fra= me +for up to aPLCABurstTimer BTs. This can only happen a number of times per = PLCA +cycle up to the value of this parameter. After that, the burst is over and= the +normal counting of TOs resumes. This option is corresponding to +``IEEE 802.3cg-2019`` 30.16.1.1.6 aPLCAMaxBurstCount. + +When set, the optional ``ETHTOOL_A_PLCA_BURST_TMR`` attribute indicates how +many bit-times the PLCA RS waits for the MAC to initiate a new transmission +when aPLCAMaxBurstCount is greater than 0. If the MAC fails to send a new +frame within this time, the burst ends and the counting of TOs resumes. +Otherwise, the new frame is sent as part of the current burst. This option +is corresponding to ``IEEE 802.3cg-2019`` 30.16.1.1.7 aPLCABurstTimer. + +PLCA_SET_CFG +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Sets PLCA RS 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=3D=3D= =3D + ``ETHTOOL_A_PLCA_HEADER`` nested request header + ``ETHTOOL_A_PLCA_ENABLED`` u8 PLCA Admin State + ``ETHTOOL_A_PLCA_NODE_ID`` u8 PLCA unique local node ID + ``ETHTOOL_A_PLCA_NODE_CNT`` u8 Number of PLCA nodes on = the + netkork, including the + coordinator + ``ETHTOOL_A_PLCA_TO_TMR`` u8 Transmit Opportunity Tim= er + value in bit-times (BT) + ``ETHTOOL_A_PLCA_BURST_CNT`` u8 Number of additional pac= kets + the node is allowed to s= end + within a single TO + ``ETHTOOL_A_PLCA_BURST_TMR`` u8 Time to wait for the MAC= to + transmit a new frame bef= ore + terminating the burst + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D =3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D + +For a description of each attribute, see ``PLCA_GET_CFG``. + +PLCA_GET_STATUS +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Gets PLCA RS status information. + +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_PLCA_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=3D=3D= =3D + ``ETHTOOL_A_PLCA_HEADER`` nested reply header + ``ETHTOOL_A_PLCA_STATUS`` u8 PLCA RS operational stat= us + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D =3D=3D=3D= =3D=3D=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 ``ETHTOOL_A_PLCA_STATUS`` attribute indicates whether the no= de is +detecting the presence of the BEACON on the network. This flag is +corresponding to ``IEEE 802.3cg-2019`` 30.16.1.1.2 aPLCAStatus. + Request translation =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 @@ -1788,4 +1918,7 @@ are netlink only. n/a ``ETHTOOL_MSG_PHC_VCLOCKS_GET`` n/a ``ETHTOOL_MSG_MODULE_GET`` n/a ``ETHTOOL_MSG_MODULE_SET`` + n/a ``ETHTOOL_MSG_PLCA_GET_CFG`` + n/a ``ETHTOOL_MSG_PLCA_SET_CFG`` + n/a ``ETHTOOL_MSG_PLCA_GET_STATUS`` =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D diff --git a/MAINTAINERS b/MAINTAINERS index 955c1be1efb2..7952243e4b43 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16396,6 +16396,12 @@ S: Maintained F: Documentation/devicetree/bindings/iio/chemical/plantower,pms7003.yaml F: drivers/iio/chemical/pms7003.c =20 +PLCA RECONCILIATION SUBLAYER (IEEE802.3 Clause 148) +M: Piergiorgio Beruto +L: netdev@vger.kernel.org +S: Maintained +F: net/ethtool/plca.c + PLDMFW LIBRARY M: Jacob Keller S: Maintained diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 9e0a76fc7de9..4bfe95ec1f0a 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -802,12 +802,16 @@ int ethtool_virtdev_set_link_ksettings(struct net_dev= ice *dev, =20 struct phy_device; struct phy_tdr_config; +struct phy_plca_cfg; +struct phy_plca_status; =20 /** * struct ethtool_phy_ops - Optional PHY device options * @get_sset_count: Get number of strings that @get_strings will write. * @get_strings: Return a set of strings that describe the requested objec= ts * @get_stats: Return extended statistics about the PHY device. + * @get_plca_cfg: Return PLCA configuration. + * @set_plca_cfg: Set PLCA configuration. * @start_cable_test: Start a cable test * @start_cable_test_tdr: Start a Time Domain Reflectometry cable test * @@ -819,6 +823,13 @@ struct ethtool_phy_ops { int (*get_strings)(struct phy_device *dev, u8 *data); int (*get_stats)(struct phy_device *dev, struct ethtool_stats *stats, u64 *data); + int (*get_plca_cfg)(struct phy_device *dev, + struct phy_plca_cfg *plca_cfg); + int (*set_plca_cfg)(struct phy_device *dev, + struct netlink_ext_ack *extack, + const struct phy_plca_cfg *plca_cfg); + int (*get_plca_status)(struct phy_device *dev, + struct phy_plca_status *plca_st); int (*start_cable_test)(struct phy_device *phydev, struct netlink_ext_ack *extack); int (*start_cable_test_tdr)(struct phy_device *phydev, diff --git a/include/linux/phy.h b/include/linux/phy.h index 71eeb4e3b1fd..f3ecc9a86e67 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -765,6 +765,63 @@ struct phy_tdr_config { }; #define PHY_PAIR_ALL -1 =20 +/** + * struct phy_plca_cfg - Configuration of the PLCA (Physical Layer Collisi= on + * Avoidance) Reconciliation Sublayer. + * + * @version: read-only PLCA register map version. 0 =3D not available. Ign= ored + * when setting the configuration. Format is the same as reported by the= PLCA + * IDVER register (31.CA00). -1 =3D not available. + * @enabled: PLCA configured mode (enabled/disabled). -1 =3D not available= / don't + * set. 0 =3D disabled, anything else =3D enabled. + * @node_id: the PLCA local node identifier. -1 =3D not available / don't = set. + * Allowed values [0 .. 254]. 255 =3D node disabled. + * @node_cnt: the PLCA node count (maximum number of nodes having a TO). O= nly + * meaningful for the coordinator (node_id =3D 0). -1 =3D not available = / don't + * set. Allowed values [0 .. 255]. + * @to_tmr: The value of the PLCA to_timer in bit-times, which determines = the + * PLCA transmit opportunity window opening. See IEEE802.3 Clause 148 for + * more details. The to_timer shall be set equal over all nodes. + * -1 =3D not available / don't set. Allowed values [0 .. 255]. + * @burst_cnt: controls how many additional frames a node is allowed to se= nd in + * single transmit opportunity (TO). The default value of 0 means that t= he + * node is allowed exactly one frame per TO. A value of 1 allows two fra= mes + * per TO, and so on. -1 =3D not available / don't set. + * Allowed values [0 .. 255]. + * @burst_tmr: controls how many bit times to wait for the MAC to send a n= ew + * frame before interrupting the burst. This value should be set to a va= lue + * greater than the MAC inter-packet gap (which is typically 96 bits). + * -1 =3D not available / don't set. Allowed values [0 .. 255]. + * + * A structure containing configuration parameters for setting/getting the= PLCA + * RS configuration. The driver does not need to implement all the paramet= ers, + * but should report what is actually used. + */ +struct phy_plca_cfg { + s32 version; + s16 enabled; + s16 node_id; + s16 node_cnt; + s16 to_tmr; + s16 burst_cnt; + s16 burst_tmr; +}; + +/** + * struct phy_plca_status - Status of the PLCA (Physical Layer Collision + * Avoidance) Reconciliation Sublayer. + * + * @pst: The PLCA status as reported by the PST bit in the PLCA STATUS + * register(31.CA03), indicating BEACON activity. + * + * A structure containing status information of the PLCA RS configuration. + * The driver does not need to implement all the parameters, but should re= port + * what is actually used. + */ +struct phy_plca_status { + bool pst; +}; + /** * struct phy_driver - Driver structure for a particular PHY type * @@ -1775,6 +1832,13 @@ int phy_ethtool_get_strings(struct phy_device *phyde= v, u8 *data); int phy_ethtool_get_sset_count(struct phy_device *phydev); int phy_ethtool_get_stats(struct phy_device *phydev, struct ethtool_stats *stats, u64 *data); +int phy_ethtool_get_plca_cfg(struct phy_device *phydev, + struct phy_plca_cfg *plca_cfg); +int phy_ethtool_set_plca_cfg(struct phy_device *phydev, + struct netlink_ext_ack *extack, + const struct phy_plca_cfg *plca_cfg); +int phy_ethtool_get_plca_status(struct phy_device *phydev, + struct phy_plca_status *plca_st); =20 static inline int phy_package_read(struct phy_device *phydev, u32 regnum) { diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/etht= ool_netlink.h index aaf7c6963d61..81e3d7b42d0f 100644 --- a/include/uapi/linux/ethtool_netlink.h +++ b/include/uapi/linux/ethtool_netlink.h @@ -51,6 +51,9 @@ enum { ETHTOOL_MSG_MODULE_SET, ETHTOOL_MSG_PSE_GET, ETHTOOL_MSG_PSE_SET, + ETHTOOL_MSG_PLCA_GET_CFG, + ETHTOOL_MSG_PLCA_SET_CFG, + ETHTOOL_MSG_PLCA_GET_STATUS, =20 /* add new constants above here */ __ETHTOOL_MSG_USER_CNT, @@ -97,6 +100,9 @@ enum { ETHTOOL_MSG_MODULE_GET_REPLY, ETHTOOL_MSG_MODULE_NTF, ETHTOOL_MSG_PSE_GET_REPLY, + ETHTOOL_MSG_PLCA_GET_CFG_REPLY, + ETHTOOL_MSG_PLCA_GET_STATUS_REPLY, + ETHTOOL_MSG_PLCA_NTF, =20 /* add new constants above here */ __ETHTOOL_MSG_KERNEL_CNT, @@ -880,6 +886,25 @@ enum { ETHTOOL_A_PSE_MAX =3D (__ETHTOOL_A_PSE_CNT - 1) }; =20 +/* PLCA */ + +enum { + ETHTOOL_A_PLCA_UNSPEC, + ETHTOOL_A_PLCA_HEADER, /* nest - _A_HEADER_* */ + ETHTOOL_A_PLCA_VERSION, /* u16 */ + ETHTOOL_A_PLCA_ENABLED, /* u8 */ + ETHTOOL_A_PLCA_STATUS, /* u8 */ + ETHTOOL_A_PLCA_NODE_CNT, /* u8 */ + ETHTOOL_A_PLCA_NODE_ID, /* u8 */ + ETHTOOL_A_PLCA_TO_TMR, /* u8 */ + ETHTOOL_A_PLCA_BURST_CNT, /* u8 */ + ETHTOOL_A_PLCA_BURST_TMR, /* u8 */ + + /* add new constants above here */ + __ETHTOOL_A_PLCA_CNT, + ETHTOOL_A_PLCA_MAX =3D (__ETHTOOL_A_PLCA_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 72ab0944262a..b18930e2ce9a 100644 --- a/net/ethtool/Makefile +++ b/net/ethtool/Makefile @@ -8,4 +8,4 @@ ethtool_nl-y :=3D netlink.o bitset.o strset.o linkinfo.o li= nkmodes.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 \ - pse-pd.o + pse-pd.o plca.o diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index 1a4c11356c96..eb044f48cb24 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -287,6 +287,8 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] =3D { [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, + [ETHTOOL_MSG_PLCA_GET_CFG] =3D ðnl_plca_cfg_request_ops, + [ETHTOOL_MSG_PLCA_GET_STATUS] =3D ðnl_plca_status_request_ops, }; =20 static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *= cb) @@ -602,6 +604,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_PLCA_NTF] =3D ðnl_plca_cfg_request_ops, }; =20 /* default notification handler */ @@ -695,6 +698,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_PLCA_NTF] =3D ethnl_default_notify, }; =20 void ethtool_notify(struct net_device *dev, unsigned int cmd, const void *= data) @@ -1040,6 +1044,32 @@ static const struct genl_ops ethtool_genl_ops[] =3D { .policy =3D ethnl_pse_set_policy, .maxattr =3D ARRAY_SIZE(ethnl_pse_set_policy) - 1, }, + { + .cmd =3D ETHTOOL_MSG_PLCA_GET_CFG, + .doit =3D ethnl_default_doit, + .start =3D ethnl_default_start, + .dumpit =3D ethnl_default_dumpit, + .done =3D ethnl_default_done, + .policy =3D ethnl_plca_get_cfg_policy, + .maxattr =3D ARRAY_SIZE(ethnl_plca_get_cfg_policy) - 1, + }, + { + .cmd =3D ETHTOOL_MSG_PLCA_SET_CFG, + .flags =3D GENL_UNS_ADMIN_PERM, + .doit =3D ethnl_set_plca_cfg, + .policy =3D ethnl_plca_set_cfg_policy, + .maxattr =3D ARRAY_SIZE(ethnl_plca_set_cfg_policy) - 1, + }, + { + .cmd =3D ETHTOOL_MSG_PLCA_GET_STATUS, + .doit =3D ethnl_default_doit, + .start =3D ethnl_default_start, + .dumpit =3D ethnl_default_dumpit, + .done =3D ethnl_default_done, + .policy =3D ethnl_plca_get_status_policy, + .maxattr =3D ARRAY_SIZE(ethnl_plca_get_status_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 1bfd374f9718..c0ed1a6d0833 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -346,6 +346,8 @@ extern const struct ethnl_request_ops ethnl_stats_reque= st_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; +extern const struct ethnl_request_ops ethnl_plca_cfg_request_ops; +extern const struct ethnl_request_ops ethnl_plca_status_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]; @@ -386,6 +388,9 @@ extern const struct nla_policy ethnl_module_get_policy[= ETHTOOL_A_MODULE_HEADER + 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]; +extern const struct nla_policy ethnl_plca_get_cfg_policy[ETHTOOL_A_PLCA_HE= ADER + 1]; +extern const struct nla_policy ethnl_plca_set_cfg_policy[ETHTOOL_A_PLCA_MA= X + 1]; +extern const struct nla_policy ethnl_plca_get_status_policy[ETHTOOL_A_PLCA= _HEADER + 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); @@ -406,6 +411,7 @@ int ethnl_tunnel_info_dumpit(struct sk_buff *skb, struc= t 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); +int ethnl_set_plca_cfg(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/plca.c b/net/ethtool/plca.c new file mode 100644 index 000000000000..0282acab1c4d --- /dev/null +++ b/net/ethtool/plca.c @@ -0,0 +1,290 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include + +#include "netlink.h" +#include "common.h" + +struct plca_req_info { + struct ethnl_req_info base; +}; + +struct plca_reply_data { + struct ethnl_reply_data base; + struct phy_plca_cfg plca_cfg; + struct phy_plca_status plca_st; +}; + +#define PLCA_REPDATA(__reply_base) \ + container_of(__reply_base, struct plca_reply_data, base) + +// PLCA get configuration message ----------------------------------------= --- // + +const struct nla_policy ethnl_plca_get_cfg_policy[] =3D { + [ETHTOOL_A_PLCA_HEADER] =3D + NLA_POLICY_NESTED(ethnl_header_policy), +}; + +static int plca_get_cfg_prepare_data(const struct ethnl_req_info *req_base, + struct ethnl_reply_data *reply_base, + struct genl_info *info) +{ + struct plca_reply_data *data =3D PLCA_REPDATA(reply_base); + struct net_device *dev =3D reply_base->dev; + const struct ethtool_phy_ops *ops; + int ret; + + // check that the PHY device is available and connected + if (!dev->phydev) { + ret =3D -EOPNOTSUPP; + goto out; + } + + // note: rtnl_lock is held already by ethnl_default_doit + ops =3D ethtool_phy_ops; + if (!ops || !ops->get_plca_cfg) { + ret =3D -EOPNOTSUPP; + goto out; + } + + ret =3D ethnl_ops_begin(dev); + if (ret < 0) + goto out; + + ret =3D ops->get_plca_cfg(dev->phydev, &data->plca_cfg); + if (ret < 0) + goto out; + + ethnl_ops_complete(dev); + +out: + return ret; +} + +static int plca_get_cfg_reply_size(const struct ethnl_req_info *req_base, + const struct ethnl_reply_data *reply_base) +{ + return nla_total_size(sizeof(u16)) + /* _VERSION */ + nla_total_size(sizeof(u8)) + /* _ENABLED */ + nla_total_size(sizeof(u8)) + /* _STATUS */ + nla_total_size(sizeof(u8)) + /* _NODE_CNT */ + nla_total_size(sizeof(u8)) + /* _NODE_ID */ + nla_total_size(sizeof(u8)) + /* _TO_TIMER */ + nla_total_size(sizeof(u8)) + /* _BURST_COUNT */ + nla_total_size(sizeof(u8)); /* _BURST_TIMER */ +} + +static int plca_get_cfg_fill_reply(struct sk_buff *skb, + const struct ethnl_req_info *req_base, + const struct ethnl_reply_data *reply_base) +{ + const struct plca_reply_data *data =3D PLCA_REPDATA(reply_base); + const struct phy_plca_cfg *plca =3D &data->plca_cfg; + + if ((plca->version >=3D 0 && + nla_put_u16(skb, ETHTOOL_A_PLCA_VERSION, (u16)plca->version)) || + (plca->enabled >=3D 0 && + nla_put_u8(skb, ETHTOOL_A_PLCA_ENABLED, !!plca->enabled)) || + (plca->node_id >=3D 0 && + nla_put_u8(skb, ETHTOOL_A_PLCA_NODE_ID, (u8)plca->node_id)) || + (plca->node_cnt >=3D 0 && + nla_put_u8(skb, ETHTOOL_A_PLCA_NODE_CNT, (u8)plca->node_cnt)) || + (plca->to_tmr >=3D 0 && + nla_put_u8(skb, ETHTOOL_A_PLCA_TO_TMR, (u8)plca->to_tmr)) || + (plca->burst_cnt >=3D 0 && + nla_put_u8(skb, ETHTOOL_A_PLCA_BURST_CNT, (u8)plca->burst_cnt)) || + (plca->burst_tmr >=3D 0 && + nla_put_u8(skb, ETHTOOL_A_PLCA_BURST_TMR, (u8)plca->burst_tmr))) + return -EMSGSIZE; + + return 0; +}; + +const struct ethnl_request_ops ethnl_plca_cfg_request_ops =3D { + .request_cmd =3D ETHTOOL_MSG_PLCA_GET_CFG, + .reply_cmd =3D ETHTOOL_MSG_PLCA_GET_CFG_REPLY, + .hdr_attr =3D ETHTOOL_A_PLCA_HEADER, + .req_info_size =3D sizeof(struct plca_req_info), + .reply_data_size =3D sizeof(struct plca_reply_data), + + .prepare_data =3D plca_get_cfg_prepare_data, + .reply_size =3D plca_get_cfg_reply_size, + .fill_reply =3D plca_get_cfg_fill_reply, +}; + +// PLCA set configuration message ----------------------------------------= --- // + +const struct nla_policy ethnl_plca_set_cfg_policy[] =3D { + [ETHTOOL_A_PLCA_HEADER] =3D + NLA_POLICY_NESTED(ethnl_header_policy), + [ETHTOOL_A_PLCA_ENABLED] =3D { .type =3D NLA_U8 }, + [ETHTOOL_A_PLCA_NODE_ID] =3D { .type =3D NLA_U8 }, + [ETHTOOL_A_PLCA_NODE_CNT] =3D { .type =3D NLA_U8 }, + [ETHTOOL_A_PLCA_TO_TMR] =3D { .type =3D NLA_U8 }, + [ETHTOOL_A_PLCA_BURST_CNT] =3D { .type =3D NLA_U8 }, + [ETHTOOL_A_PLCA_BURST_TMR] =3D { .type =3D NLA_U8 }, +}; + +int ethnl_set_plca_cfg(struct sk_buff *skb, struct genl_info *info) +{ + struct ethnl_req_info req_info =3D {}; + struct nlattr **tb =3D info->attrs; + const struct ethtool_phy_ops *ops; + struct phy_plca_cfg plca_cfg; + struct net_device *dev; + + bool mod =3D false; + int ret; + + ret =3D ethnl_parse_header_dev_get(&req_info, + tb[ETHTOOL_A_PLCA_HEADER], + genl_info_net(info), info->extack, + true); + if (ret < 0) + return ret; + + dev =3D req_info.dev; + + // check that the PHY device is available and connected + rtnl_lock(); + + if (!dev->phydev) { + ret =3D -EOPNOTSUPP; + goto out_rtnl; + } + + ops =3D ethtool_phy_ops; + if (!ops || !ops->set_plca_cfg) { + ret =3D -EOPNOTSUPP; + goto out_rtnl; + } + + ret =3D ethnl_ops_begin(dev); + if (ret < 0) + goto out_rtnl; + + memset(&plca_cfg, 0xFF, sizeof(plca_cfg)); + + if (tb[ETHTOOL_A_PLCA_ENABLED]) { + plca_cfg.enabled =3D !!nla_get_u8(tb[ETHTOOL_A_PLCA_ENABLED]); + mod =3D true; + } + + if (tb[ETHTOOL_A_PLCA_NODE_ID]) { + plca_cfg.node_id =3D nla_get_u8(tb[ETHTOOL_A_PLCA_NODE_ID]); + mod =3D true; + } + + if (tb[ETHTOOL_A_PLCA_NODE_CNT]) { + plca_cfg.node_cnt =3D nla_get_u8(tb[ETHTOOL_A_PLCA_NODE_CNT]); + mod =3D true; + } + + if (tb[ETHTOOL_A_PLCA_TO_TMR]) { + plca_cfg.to_tmr =3D nla_get_u8(tb[ETHTOOL_A_PLCA_TO_TMR]); + mod =3D true; + } + + if (tb[ETHTOOL_A_PLCA_BURST_CNT]) { + plca_cfg.burst_cnt =3D nla_get_u8(tb[ETHTOOL_A_PLCA_BURST_CNT]); + mod =3D true; + } + + if (tb[ETHTOOL_A_PLCA_BURST_TMR]) { + plca_cfg.burst_tmr =3D nla_get_u8(tb[ETHTOOL_A_PLCA_BURST_TMR]); + mod =3D true; + } + + ret =3D 0; + if (!mod) + goto out_ops; + + ret =3D ops->set_plca_cfg(dev->phydev, info->extack, &plca_cfg); + + if (ret < 0) + goto out_ops; + + ethtool_notify(dev, ETHTOOL_MSG_PLCA_NTF, NULL); + +out_ops: + ethnl_ops_complete(dev); +out_rtnl: + rtnl_unlock(); + ethnl_parse_header_dev_put(&req_info); + + return ret; +} + +// PLCA get status message -----------------------------------------------= --- // + +const struct nla_policy ethnl_plca_get_status_policy[] =3D { + [ETHTOOL_A_PLCA_HEADER] =3D + NLA_POLICY_NESTED(ethnl_header_policy), +}; + +static int plca_get_status_prepare_data(const struct ethnl_req_info *req_b= ase, + struct ethnl_reply_data *reply_base, + struct genl_info *info) +{ + struct plca_reply_data *data =3D PLCA_REPDATA(reply_base); + struct net_device *dev =3D reply_base->dev; + const struct ethtool_phy_ops *ops; + int ret; + + // check that the PHY device is available and connected + if (!dev->phydev) { + ret =3D -EOPNOTSUPP; + goto out; + } + + // note: rtnl_lock is held already by ethnl_default_doit + ops =3D ethtool_phy_ops; + if (!ops || !ops->get_plca_status) { + ret =3D -EOPNOTSUPP; + goto out; + } + + ret =3D ethnl_ops_begin(dev); + if (ret < 0) + goto out; + + ret =3D ops->get_plca_status(dev->phydev, &data->plca_st); + if (ret < 0) + goto out; + + ethnl_ops_complete(dev); +out: + return ret; +} + +static int plca_get_status_reply_size(const struct ethnl_req_info *req_bas= e, + const struct ethnl_reply_data *reply_base) +{ + return nla_total_size(sizeof(u8)); /* _STATUS */ +} + +static int plca_get_status_fill_reply(struct sk_buff *skb, + const struct ethnl_req_info *req_base, + const struct ethnl_reply_data *reply_base) +{ + const struct plca_reply_data *data =3D PLCA_REPDATA(reply_base); + const u8 status =3D data->plca_st.pst; + + if (nla_put_u8(skb, ETHTOOL_A_PLCA_STATUS, !!status)) + return -EMSGSIZE; + + return 0; +}; + +const struct ethnl_request_ops ethnl_plca_status_request_ops =3D { + .request_cmd =3D ETHTOOL_MSG_PLCA_GET_STATUS, + .reply_cmd =3D ETHTOOL_MSG_PLCA_GET_STATUS_REPLY, + .hdr_attr =3D ETHTOOL_A_PLCA_HEADER, + .req_info_size =3D sizeof(struct plca_req_info), + .reply_data_size =3D sizeof(struct plca_reply_data), + + .prepare_data =3D plca_get_status_prepare_data, + .reply_size =3D plca_get_status_reply_size, + .fill_reply =3D plca_get_status_fill_reply, +}; --=20 2.35.1