From patchwork Mon Aug 9 10:21:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ido Schimmel X-Patchwork-Id: 494878 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F1508C4338F for ; Mon, 9 Aug 2021 10:22:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D71AA610A7 for ; Mon, 9 Aug 2021 10:22:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234328AbhHIKWj (ORCPT ); Mon, 9 Aug 2021 06:22:39 -0400 Received: from out3-smtp.messagingengine.com ([66.111.4.27]:53507 "EHLO out3-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233212AbhHIKWi (ORCPT ); Mon, 9 Aug 2021 06:22:38 -0400 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id 1184D5C00DB; Mon, 9 Aug 2021 06:22:18 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Mon, 09 Aug 2021 06:22:18 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=uPz4aoxh3Qb/1Wdqcpnf3PJu0/wbvAPeh4adwV4N0EM=; b=oSTKdiXy MKyL/0PZ1j/RsXeQe7RAsNZ+htqy/pzjdAtwuxuKfx2S9GX1UKrBtSDCg1J5U/Fo NZZOrABPnDPIYKuMLoXrB5BhuCIJd+y51bhRlcJcHRoKca6mBpkJGImQxelfn7s1 QAwIw2PKknGfCFVZCiofq6OKhWAgPGD/WbljTCeo3uCMkp1fgD0P6kYYohRrg5Ja xWM8zDQ8lqqGe+SWV0h9Rw0m1oJ4FBs/0J6QG6EyFPb05nKjYtiV1dASIL0Ihqa3 +5P84yy7BjTSoLWEZL7N10zPAwrYPKR6W9sskHT5Opjhu7LDETflT3y4jijmbp2Q 4oGHfiTQK4q8IQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrjeejgddvkecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffojghfggfgsedtkeertd ertddtnecuhfhrohhmpefkughoucfutghhihhmmhgvlhcuoehiughoshgthhesihguohhs tghhrdhorhhgqeenucggtffrrghtthgvrhhnpeduteeiveffffevleekleejffekhfekhe fgtdfftefhledvjefggfehgfevjeekhfenucevlhhushhtvghrufhiiigvpedtnecurfgr rhgrmhepmhgrihhlfhhrohhmpehiughoshgthhesihguohhstghhrdhorhhg X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 9 Aug 2021 06:22:15 -0400 (EDT) From: Ido Schimmel To: netdev@vger.kernel.org Cc: davem@davemloft.net, kuba@kernel.org, andrew@lunn.ch, mkubecek@suse.cz, pali@kernel.org, vadimp@nvidia.com, mlxsw@nvidia.com, Ido Schimmel Subject: [RFC PATCH net-next 1/8] ethtool: Add ability to control transceiver modules' low power mode Date: Mon, 9 Aug 2021 13:21:45 +0300 Message-Id: <20210809102152.719961-2-idosch@idosch.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210809102152.719961-1-idosch@idosch.org> References: <20210809102152.719961-1-idosch@idosch.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Ido Schimmel Add a pair of new ethtool messages, 'ETHTOOL_MSG_MODULE_SET' and 'ETHTOOL_MSG_MODULE_GET', that can be used to control transceiver modules parameters and retrieve their status. The first parameter to control is the low power mode of the module. It is only relevant for paged memory modules, as flat memory modules always operate in low power mode. When a paged memory module is in low power mode, its power consumption is reduced to the minimum, the management interface towards the host is available and the data path is deactivated. User space can choose to put modules that are not currently in use in low power mode and transition them to high power mode before putting the associated ports administratively up. Transitioning into low power mode means loss of carrier, so error is returned when the netdev is administratively up. The user API is designed to be generic enough so that it could be used for modules with different memory maps (e.g., SFF-8636, CMIS). The only implementation of the device driver API in this series is for a MAC driver (mlxsw) where the module is controlled by the device's firmware, but it is designed to be generic enough so that it could also be used by implementations where the module is controlled by the CPU. CMIS testing ============ # ethtool -m swp11 Identifier : 0x18 (QSFP-DD Double Density 8X Pluggable Transceiver (INF-8628)) ... Module State : 0x03 (ModuleReady) LowPwrAllowRequestHW : Off LowPwrRequestSW : Off The module is not in low power mode, as it is not forced by hardware (LowPwrAllowRequestHW is off) or by software (LowPwrRequestSW is off). The low power mode can be queried from the kernel. In case LowPwrAllowRequestHW was on, the kernel would need to take into account the state of the LowPwrRequestHW signal, which is not visible to user space. $ ethtool --show-module swp11 Module parameters for swp11: low-power false Turn on low power mode: # ethtool --set-module swp11 low-power on Query low power mode again: $ ethtool --show-module swp11 Module parameters for swp11: low-power true Verify with the data read from the EEPROM: # ethtool -m swp11 Identifier : 0x18 (QSFP-DD Double Density 8X Pluggable Transceiver (INF-8628)) ... Module State : 0x01 (ModuleLowPwr) LowPwrAllowRequestHW : Off LowPwrRequestSW : On Allow the module to transition out of low power mode: # ethtool --set-module swp11 low-power off Query low power mode again: $ ethtool --show-module swp11 Module parameters for swp11: low-power false Verify with the data read from the EEPROM: # ethtool -m swp11 Identifier : 0x18 (QSFP-DD Double Density 8X Pluggable Transceiver (INF-8628)) ... Module State : 0x03 (ModuleReady) LowPwrAllowRequestHW : Off LowPwrRequestSW : Off SFF-8636 testing ================ # ethtool -m swp13 Identifier : 0x11 (QSFP28) ... Extended identifier description : 5.0W max. Power consumption, High Power Class (> 3.5 W) enabled Power set : Off Power override : On ... Transmit avg optical power (Channel 1) : 0.7733 mW / -1.12 dBm Transmit avg optical power (Channel 2) : 0.7649 mW / -1.16 dBm Transmit avg optical power (Channel 3) : 0.7743 mW / -1.11 dBm Transmit avg optical power (Channel 4) : 0.7837 mW / -1.06 dBm Rcvr signal avg optical power(Channel 1) : 0.9186 mW / -0.37 dBm Rcvr signal avg optical power(Channel 2) : 0.9136 mW / -0.39 dBm Rcvr signal avg optical power(Channel 3) : 0.8986 mW / -0.46 dBm Rcvr signal avg optical power(Channel 4) : 0.8701 mW / -0.60 dBm The module is not in low power mode, as it is not forced by hardware (Power override is on) or by software (Power set is off). The low power mode can be queried from the kernel. In case Power override was off, the kernel would need to take into account the state of the LPMode signal, which is not visible to user space. $ ethtool --show-module swp13 Module parameters for swp13: low-power false Turn on low power mode: # ethtool --set-module swp13 low-power on Query low power mode again: $ ethtool --show-module swp13 Module parameters for swp13: low-power true Verify with the data read from the EEPROM: # ethtool -m swp13 Identifier : 0x11 (QSFP28) ... Extended identifier description : 5.0W max. Power consumption, High Power Class (> 3.5 W) not enabled Power set : On Power override : On ... Transmit avg optical power (Channel 1) : 0.0000 mW / -inf dBm Transmit avg optical power (Channel 2) : 0.0000 mW / -inf dBm Transmit avg optical power (Channel 3) : 0.0000 mW / -inf dBm Transmit avg optical power (Channel 4) : 0.0000 mW / -inf dBm Rcvr signal avg optical power(Channel 1) : 0.0000 mW / -inf dBm Rcvr signal avg optical power(Channel 2) : 0.0000 mW / -inf dBm Rcvr signal avg optical power(Channel 3) : 0.0000 mW / -inf dBm Rcvr signal avg optical power(Channel 4) : 0.0000 mW / -inf dBm Allow the module to transition out of low power mode: # ethtool --set-module swp13 low-power off Query low power mode again: $ ethtool --show-module swp13 Module parameters for swp13: low-power false Verify with the data read from the EEPROM: # ethtool -m swp13 Identifier : 0x11 (QSFP28) ... Extended identifier description : 5.0W max. Power consumption, High Power Class (> 3.5 W) enabled Power set : Off Power override : On ... Transmit avg optical power (Channel 1) : 0.7783 mW / -1.09 dBm Transmit avg optical power (Channel 2) : 0.7806 mW / -1.08 dBm Transmit avg optical power (Channel 3) : 0.7885 mW / -1.03 dBm Transmit avg optical power (Channel 4) : 0.7985 mW / -0.98 dBm Rcvr signal avg optical power(Channel 1) : 0.9124 mW / -0.40 dBm Rcvr signal avg optical power(Channel 2) : 0.9071 mW / -0.42 dBm Rcvr signal avg optical power(Channel 3) : 0.8993 mW / -0.46 dBm Rcvr signal avg optical power(Channel 4) : 0.8644 mW / -0.63 dBm Signed-off-by: Ido Schimmel --- Documentation/networking/ethtool-netlink.rst | 55 +++++- include/linux/ethtool.h | 9 + include/uapi/linux/ethtool_netlink.h | 16 ++ net/ethtool/Makefile | 2 +- net/ethtool/module.c | 184 +++++++++++++++++++ net/ethtool/netlink.c | 19 ++ net/ethtool/netlink.h | 4 + 7 files changed, 286 insertions(+), 3 deletions(-) create mode 100644 net/ethtool/module.c diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst index c86628e6a235..07eac5bc9cfc 100644 --- a/Documentation/networking/ethtool-netlink.rst +++ b/Documentation/networking/ethtool-netlink.rst @@ -179,7 +179,7 @@ according to message purpose: Userspace to kernel: - ===================================== ================================ + ===================================== ================================= ``ETHTOOL_MSG_STRSET_GET`` get string set ``ETHTOOL_MSG_LINKINFO_GET`` get link settings ``ETHTOOL_MSG_LINKINFO_SET`` set link settings @@ -213,7 +213,9 @@ Userspace to kernel: ``ETHTOOL_MSG_MODULE_EEPROM_GET`` read SFP module EEPROM ``ETHTOOL_MSG_STATS_GET`` get standard statistics ``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 + ===================================== ================================= Kernel to userspace: @@ -252,6 +254,7 @@ Kernel to userspace: ``ETHTOOL_MSG_MODULE_EEPROM_GET_REPLY`` read SFP module EEPROM ``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 ======================================== ================================= ``GET`` requests are sent by userspace applications to retrieve device @@ -1498,6 +1501,52 @@ Kernel response contents: ``ETHTOOL_A_PHC_VCLOCKS_INDEX`` s32 PHC index array ==================================== ====== ========================== +MODULE_GET +========== + +Gets transceiver module parameters. + +Request contents: + + ===================================== ====== ========================== + ``ETHTOOL_A_MODULE_HEADER`` nested request header + ===================================== ====== ========================== + +Kernel response contents: + + ====================================== ====== ========================== + ``ETHTOOL_A_MODULE_HEADER`` nested reply header + ``ETHTOOL_A_MODULE_LOW_POWER_ENABLED`` bool low power mode is enabled + ====================================== ====== ========================== + +The optional ``ETHTOOL_A_MODULE_LOW_POWER_ENABLED`` attribute encodes whether +low power mode is forced by the host. + +MODULE_SET +========== + +Sets transceiver module parameters. + +Request contents: + + ====================================== ====== ========================== + ``ETHTOOL_A_MODULE_HEADER`` nested request header + ``ETHTOOL_A_MODULE_LOW_POWER_ENABLED`` bool low power mode is enabled + ====================================== ====== ========================== + +When set, the optional ``ETHTOOL_A_MODULE_LOW_POWER_ENABLED`` attribute is used +to force the module to stay in low power mode or force it back into low power +mode. When cleared, capable modules can transition to high power mode. + +To avoid changes to the operational state of the device, low power mode can +only be set when the device is administratively down. + +For SFF-8636 modules, low power mode is forced by the host according to table +6-10 in revision 2.10a of the specification. + +For CMIS modules, low power mode is forced by the host according to table 6-12 +in revision 5.0 of the specification. + Request translation =================== @@ -1597,4 +1646,6 @@ are netlink only. n/a ``ETHTOOL_MSG_CABLE_TEST_TDR_ACT`` n/a ``ETHTOOL_MSG_TUNNEL_INFO_GET`` n/a ``ETHTOOL_MSG_PHC_VCLOCKS_GET`` + n/a ``ETHTOOL_MSG_MODULE_GET`` + n/a ``ETHTOOL_MSG_MODULE_SET`` =================================== ===================================== diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 4711b96dae0c..04286debdcdc 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -570,6 +570,10 @@ struct ethtool_module_eeprom { * @get_eth_ctrl_stats: Query some of the IEEE 802.3 MAC Ctrl statistics. * @get_rmon_stats: Query some of the RMON (RFC 2819) statistics. * Set %ranges to a pointer to zero-terminated array of byte ranges. + * @get_module_low_power: Get the low power mode status of the plug-in module + * used by the network device. + * @set_module_low_power: Set the low power mode status of the plug-in module + * used by the network device. * * All operations are optional (i.e. the function pointer may be set * to %NULL) and callers must take this into account. Callers must @@ -689,6 +693,11 @@ struct ethtool_ops { void (*get_rmon_stats)(struct net_device *dev, struct ethtool_rmon_stats *rmon_stats, const struct ethtool_rmon_hist_range **ranges); + int (*get_module_low_power)(struct net_device *dev, + bool *p_low_power, + struct netlink_ext_ack *extack); + int (*set_module_low_power)(struct net_device *dev, bool low_power, + struct netlink_ext_ack *extack); }; int ethtool_check_ops(const struct ethtool_ops *ops); diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h index b3b93710eff7..72fb821f3928 100644 --- a/include/uapi/linux/ethtool_netlink.h +++ b/include/uapi/linux/ethtool_netlink.h @@ -47,6 +47,8 @@ enum { ETHTOOL_MSG_MODULE_EEPROM_GET, ETHTOOL_MSG_STATS_GET, ETHTOOL_MSG_PHC_VCLOCKS_GET, + ETHTOOL_MSG_MODULE_GET, + ETHTOOL_MSG_MODULE_SET, /* add new constants above here */ __ETHTOOL_MSG_USER_CNT, @@ -90,6 +92,8 @@ enum { ETHTOOL_MSG_MODULE_EEPROM_GET_REPLY, ETHTOOL_MSG_STATS_GET_REPLY, ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY, + ETHTOOL_MSG_MODULE_GET_REPLY, + ETHTOOL_MSG_MODULE_NTF, /* add new constants above here */ __ETHTOOL_MSG_KERNEL_CNT, @@ -831,6 +835,18 @@ enum { ETHTOOL_A_STATS_RMON_MAX = (__ETHTOOL_A_STATS_RMON_CNT - 1) }; +/* MODULE */ + +enum { + ETHTOOL_A_MODULE_UNSPEC, + ETHTOOL_A_MODULE_HEADER, /* nest - _A_HEADER_* */ + ETHTOOL_A_MODULE_LOW_POWER_ENABLED, /* u8 */ + + /* add new constants above here */ + __ETHTOOL_A_MODULE_CNT, + ETHTOOL_A_MODULE_MAX = (__ETHTOOL_A_MODULE_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 0a19470efbfb..b76432e70e6b 100644 --- a/net/ethtool/Makefile +++ b/net/ethtool/Makefile @@ -7,4 +7,4 @@ obj-$(CONFIG_ETHTOOL_NETLINK) += ethtool_nl.o ethtool_nl-y := 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 + tunnels.o fec.o eeprom.o stats.o phc_vclocks.o module.o diff --git a/net/ethtool/module.c b/net/ethtool/module.c new file mode 100644 index 000000000000..947f2188d725 --- /dev/null +++ b/net/ethtool/module.c @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include + +#include "netlink.h" +#include "common.h" +#include "bitset.h" + +struct module_req_info { + struct ethnl_req_info base; +}; + +struct module_reply_data { + struct ethnl_reply_data base; + u8 low_power:1, + low_power_valid:1; +}; + +#define MODULE_REPDATA(__reply_base) \ + container_of(__reply_base, struct module_reply_data, base) + +/* MODULE_GET */ + +const struct nla_policy ethnl_module_get_policy[ETHTOOL_A_MODULE_HEADER + 1] = { + [ETHTOOL_A_MODULE_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy), +}; + +static int module_get_low_power(struct net_device *dev, + struct module_reply_data *data, + struct netlink_ext_ack *extack) +{ + const struct ethtool_ops *ops = dev->ethtool_ops; + bool low_power; + int ret; + + if (!ops->get_module_low_power) + return 0; + + ret = ops->get_module_low_power(dev, &low_power, extack); + if (ret < 0) + return ret; + + data->low_power = low_power; + data->low_power_valid = true; + + return 0; +} + +static int module_prepare_data(const struct ethnl_req_info *req_base, + struct ethnl_reply_data *reply_base, + struct genl_info *info) +{ + struct module_reply_data *data = MODULE_REPDATA(reply_base); + struct netlink_ext_ack *extack = info ? info->extack : NULL; + struct net_device *dev = reply_base->dev; + int ret; + + ret = ethnl_ops_begin(dev); + if (ret < 0) + return ret; + + ret = module_get_low_power(dev, data, extack); + if (ret < 0) + goto out_complete; + +out_complete: + ethnl_ops_complete(dev); + return ret; +} + +static int module_reply_size(const struct ethnl_req_info *req_base, + const struct ethnl_reply_data *reply_base) +{ + struct module_reply_data *data = MODULE_REPDATA(reply_base); + int len = 0; + + if (data->low_power_valid) + len += nla_total_size(sizeof(u8)); /* _MODULE_LOW_POWER_ENABLED */ + + return len; +} + +static int module_fill_reply(struct sk_buff *skb, + const struct ethnl_req_info *req_base, + const struct ethnl_reply_data *reply_base) +{ + const struct module_reply_data *data = MODULE_REPDATA(reply_base); + + if (data->low_power_valid && + nla_put_u8(skb, ETHTOOL_A_MODULE_LOW_POWER_ENABLED, + data->low_power)) + return -EMSGSIZE; + + return 0; +} + +const struct ethnl_request_ops ethnl_module_request_ops = { + .request_cmd = ETHTOOL_MSG_MODULE_GET, + .reply_cmd = ETHTOOL_MSG_MODULE_GET_REPLY, + .hdr_attr = ETHTOOL_A_MODULE_HEADER, + .req_info_size = sizeof(struct module_req_info), + .reply_data_size = sizeof(struct module_reply_data), + + .prepare_data = module_prepare_data, + .reply_size = module_reply_size, + .fill_reply = module_fill_reply, +}; + +/* MODULE_SET */ + +const struct nla_policy ethnl_module_set_policy[ETHTOOL_A_MODULE_LOW_POWER_ENABLED + 1] = { + [ETHTOOL_A_MODULE_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy), + [ETHTOOL_A_MODULE_LOW_POWER_ENABLED] = NLA_POLICY_MAX(NLA_U8, 1), +}; + +static int module_set_low_power(struct net_device *dev, struct nlattr **tb, + bool *p_mod, struct netlink_ext_ack *extack) +{ + const struct ethtool_ops *ops = dev->ethtool_ops; + bool low_power_new, low_power; + int ret; + + if (!tb[ETHTOOL_A_MODULE_LOW_POWER_ENABLED]) + return 0; + + if (!ops->get_module_low_power || !ops->set_module_low_power) { + NL_SET_ERR_MSG_ATTR(extack, + tb[ETHTOOL_A_MODULE_LOW_POWER_ENABLED], + "Setting low power mode is not supported by this device"); + return -EOPNOTSUPP; + } + + if (netif_running(dev)) { + NL_SET_ERR_MSG_ATTR(extack, + tb[ETHTOOL_A_MODULE_LOW_POWER_ENABLED], + "Cannot set low power mode when port is administratively up"); + return -EINVAL; + } + + low_power_new = !!nla_get_u8(tb[ETHTOOL_A_MODULE_LOW_POWER_ENABLED]); + ret = ops->get_module_low_power(dev, &low_power, extack); + if (ret < 0) + return ret; + *p_mod = low_power_new != low_power; + + return ops->set_module_low_power(dev, low_power_new, extack); +} + +int ethnl_set_module(struct sk_buff *skb, struct genl_info *info) +{ + struct ethnl_req_info req_info = {}; + struct nlattr **tb = info->attrs; + struct net_device *dev; + bool mod = false; + int ret; + + ret = ethnl_parse_header_dev_get(&req_info, tb[ETHTOOL_A_MODULE_HEADER], + genl_info_net(info), info->extack, + true); + if (ret < 0) + return ret; + dev = req_info.dev; + + rtnl_lock(); + ret = ethnl_ops_begin(dev); + if (ret < 0) + goto out_rtnl; + + ret = module_set_low_power(dev, tb, &mod, info->extack); + if (ret < 0) + goto out_ops; + + if (!mod) + goto out_ops; + + ethtool_notify(dev, ETHTOOL_MSG_MODULE_NTF, NULL); + +out_ops: + ethnl_ops_complete(dev); +out_rtnl: + rtnl_unlock(); + dev_put(dev); + return ret; +} diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index 1797a0a90019..38b44c0291b1 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -282,6 +282,7 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = { [ETHTOOL_MSG_MODULE_EEPROM_GET] = ðnl_module_eeprom_request_ops, [ETHTOOL_MSG_STATS_GET] = ðnl_stats_request_ops, [ETHTOOL_MSG_PHC_VCLOCKS_GET] = ðnl_phc_vclocks_request_ops, + [ETHTOOL_MSG_MODULE_GET] = ðnl_module_request_ops, }; static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb) @@ -593,6 +594,7 @@ ethnl_default_notify_ops[ETHTOOL_MSG_KERNEL_MAX + 1] = { [ETHTOOL_MSG_PAUSE_NTF] = ðnl_pause_request_ops, [ETHTOOL_MSG_EEE_NTF] = ðnl_eee_request_ops, [ETHTOOL_MSG_FEC_NTF] = ðnl_fec_request_ops, + [ETHTOOL_MSG_MODULE_NTF] = ðnl_module_request_ops, }; /* default notification handler */ @@ -686,6 +688,7 @@ static const ethnl_notify_handler_t ethnl_notify_handlers[] = { [ETHTOOL_MSG_PAUSE_NTF] = ethnl_default_notify, [ETHTOOL_MSG_EEE_NTF] = ethnl_default_notify, [ETHTOOL_MSG_FEC_NTF] = ethnl_default_notify, + [ETHTOOL_MSG_MODULE_NTF] = ethnl_default_notify, }; void ethtool_notify(struct net_device *dev, unsigned int cmd, const void *data) @@ -999,6 +1002,22 @@ static const struct genl_ops ethtool_genl_ops[] = { .policy = ethnl_phc_vclocks_get_policy, .maxattr = ARRAY_SIZE(ethnl_phc_vclocks_get_policy) - 1, }, + { + .cmd = ETHTOOL_MSG_MODULE_GET, + .doit = ethnl_default_doit, + .start = ethnl_default_start, + .dumpit = ethnl_default_dumpit, + .done = ethnl_default_done, + .policy = ethnl_module_get_policy, + .maxattr = ARRAY_SIZE(ethnl_module_get_policy) - 1, + }, + { + .cmd = ETHTOOL_MSG_MODULE_SET, + .flags = GENL_UNS_ADMIN_PERM, + .doit = ethnl_set_module, + .policy = ethnl_module_set_policy, + .maxattr = ARRAY_SIZE(ethnl_module_set_policy) - 1, + }, }; static const struct genl_multicast_group ethtool_nl_mcgrps[] = { diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h index 077aac3929a8..cf0fcbfe3c5c 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -337,6 +337,7 @@ extern const struct ethnl_request_ops ethnl_fec_request_ops; extern const struct ethnl_request_ops ethnl_module_eeprom_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 nla_policy ethnl_header_policy[ETHTOOL_A_HEADER_FLAGS + 1]; extern const struct nla_policy ethnl_header_policy_stats[ETHTOOL_A_HEADER_FLAGS + 1]; @@ -373,6 +374,8 @@ extern const struct nla_policy ethnl_fec_set_policy[ETHTOOL_A_FEC_AUTO + 1]; extern const struct nla_policy ethnl_module_eeprom_get_policy[ETHTOOL_A_MODULE_EEPROM_I2C_ADDRESS + 1]; extern const struct nla_policy ethnl_stats_get_policy[ETHTOOL_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_HEADER + 1]; +extern const struct nla_policy ethnl_module_set_policy[ETHTOOL_A_MODULE_LOW_POWER_ENABLED + 1]; int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info); int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info); @@ -391,6 +394,7 @@ int ethnl_tunnel_info_doit(struct sk_buff *skb, struct genl_info *info); int ethnl_tunnel_info_start(struct netlink_callback *cb); int ethnl_tunnel_info_dumpit(struct sk_buff *skb, struct netlink_callback *cb); int ethnl_set_fec(struct sk_buff *skb, struct genl_info *info); +int ethnl_set_module(struct sk_buff *skb, struct genl_info *info); extern const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN]; extern const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN]; From patchwork Mon Aug 9 10:21:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ido Schimmel X-Patchwork-Id: 494877 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C1184C4320E for ; Mon, 9 Aug 2021 10:22:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 97FD261040 for ; Mon, 9 Aug 2021 10:22:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234538AbhHIKWt (ORCPT ); Mon, 9 Aug 2021 06:22:49 -0400 Received: from out3-smtp.messagingengine.com ([66.111.4.27]:44887 "EHLO out3-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234344AbhHIKWn (ORCPT ); Mon, 9 Aug 2021 06:22:43 -0400 Received: from compute2.internal (compute2.nyi.internal [10.202.2.42]) by mailout.nyi.internal (Postfix) with ESMTP id E7CF25C00CE; Mon, 9 Aug 2021 06:22:20 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute2.internal (MEProxy); Mon, 09 Aug 2021 06:22:20 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=vYJT8H8ACxsHWzoto/oj9HCCktdxmpAiKZRuDOB9FCk=; b=W0xw+C/0 bRLWyhZWfcpVlGwFlarmDRFprG0XU90YY5pKdqlE1fAmVaHCJ1kDeEVesV16P3li F9FsV78f5zhBtAawhbjV/yFeg2w/A+PIlPzI6zxLWSsWu7G1wY2mbwWqe60pPCmz m95zdoezWh9nf5w5DRV7pJ8HRH1d0adqIQPWb7jro3lIrP9N07u3AeXgIJWz8Hac dwn/vSgL7VxYrrYfXe4IWLL/VO9lA8sffy+U7IdqI2NF3rgTgVATX/IFsFfYbDmb 04/T+5w0upITmBos8KbRIZ8eOHeHAKR80TIcWYxYW3d38jqHyI4FE8rCumsjMmGt MVkd7yhAA34DWQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrjeejgddvkecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffojghfggfgsedtkeertd ertddtnecuhfhrohhmpefkughoucfutghhihhmmhgvlhcuoehiughoshgthhesihguohhs tghhrdhorhhgqeenucggtffrrghtthgvrhhnpeduteeiveffffevleekleejffekhfekhe fgtdfftefhledvjefggfehgfevjeekhfenucevlhhushhtvghrufhiiigvpedtnecurfgr rhgrmhepmhgrihhlfhhrohhmpehiughoshgthhesihguohhstghhrdhorhhg X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 9 Aug 2021 06:22:18 -0400 (EDT) From: Ido Schimmel To: netdev@vger.kernel.org Cc: davem@davemloft.net, kuba@kernel.org, andrew@lunn.ch, mkubecek@suse.cz, pali@kernel.org, vadimp@nvidia.com, mlxsw@nvidia.com, Ido Schimmel Subject: [RFC PATCH net-next 2/8] ethtool: Add ability to reset transceiver modules Date: Mon, 9 Aug 2021 13:21:46 +0300 Message-Id: <20210809102152.719961-3-idosch@idosch.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210809102152.719961-1-idosch@idosch.org> References: <20210809102152.719961-1-idosch@idosch.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Ido Schimmel Add a new ethtool message, 'ETHTOOL_MSG_MODULE_RESET_ACT', which allows user space to request a reset of transceiver modules. A successful reset results in a notification being emitted to user space in the form of a 'ETHTOOL_MSG_MODULE_RESET_NTF' message. Reset can be performed by either asserting the relevant hardware signal ("Reset" in CMIS / "ResetL" in SFF-8636) or by writing to the relevant reset bit in the module's EEPROM (page 00h, byte 26, bit 3 in CMIS / page 00h, byte 93, bit 7 in SFF-8636). Reset is useful in order to allow a module to transition out of a fault state. From section 6.3.2.12 in CMIS 5.0: "Except for a power cycle, the only exit path from the ModuleFault state is to perform a module reset by taking an action that causes the ResetS transition signal to become TRUE (see Table 6-11)". To avoid changes to the operational state of the device, reset can only be performed when the device is administratively down. Example usage: # ethtool --reset-module swp11 netlink error: Cannot reset module when port is administratively up netlink error: Invalid argument # ip link set dev swp11 down # ethtool --reset-module swp11 Monitor notifications: $ ethtool --monitor listening... Module reset done for swp11 Signed-off-by: Ido Schimmel --- Documentation/networking/ethtool-netlink.rst | 28 +++++++ include/linux/ethtool.h | 3 + include/uapi/linux/ethtool_netlink.h | 2 + net/ethtool/module.c | 80 ++++++++++++++++++++ net/ethtool/netlink.c | 7 ++ net/ethtool/netlink.h | 2 + 6 files changed, 122 insertions(+) diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst index 07eac5bc9cfc..4e4d0c6a943e 100644 --- a/Documentation/networking/ethtool-netlink.rst +++ b/Documentation/networking/ethtool-netlink.rst @@ -215,6 +215,7 @@ 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_MODULE_RESET_ACT`` action reset transceiver module ===================================== ================================= Kernel to userspace: @@ -255,6 +256,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_MODULE_RESET_NTF`` transceiver module reset ======================================== ================================= ``GET`` requests are sent by userspace applications to retrieve device @@ -1547,6 +1549,31 @@ For SFF-8636 modules, low power mode is forced by the 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. +MODULE_RESET_ACT +================ + +Resets the transceiver module to its initial state, as if it was just +plugged-in. The Module State Machine (MSM) is reset to the "Reset" steady state +and module's registers are reset to their default values. + +Action contents: + + ====================================== ====== ========================== + ``ETHTOOL_A_MODULE_HEADER`` nested request header + ====================================== ====== ========================== + +Upon a successful reset, a ``ETHTOOL_MSG_MODULE_RESET_NTF`` notification is +sent to user space. + +To avoid changes to the operational state of the device, reset can only be +performed when the device is administratively down. + +For SFF-8636 modules, reset can be implemented according to section 4.4.3 in +revision 2.10a of the specification. + +For CMIS modules, reset can be implemented according to table 6-11 in revision +5.0 of the specification. + Request translation =================== @@ -1648,4 +1675,5 @@ 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_MODULE_RESET_ACT`` =================================== ===================================== diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 04286debdcdc..ab67b061be32 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -574,6 +574,7 @@ struct ethtool_module_eeprom { * used by the network device. * @set_module_low_power: Set the low power mode status of the plug-in module * used by the network device. + * @reset_module: Reset the plug-in module used by the network device. * * All operations are optional (i.e. the function pointer may be set * to %NULL) and callers must take this into account. Callers must @@ -698,6 +699,8 @@ struct ethtool_ops { struct netlink_ext_ack *extack); int (*set_module_low_power)(struct net_device *dev, bool low_power, struct netlink_ext_ack *extack); + int (*reset_module)(struct net_device *dev, + struct netlink_ext_ack *extack); }; int ethtool_check_ops(const struct ethtool_ops *ops); diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h index 72fb821f3928..4e1c1baad250 100644 --- a/include/uapi/linux/ethtool_netlink.h +++ b/include/uapi/linux/ethtool_netlink.h @@ -49,6 +49,7 @@ enum { ETHTOOL_MSG_PHC_VCLOCKS_GET, ETHTOOL_MSG_MODULE_GET, ETHTOOL_MSG_MODULE_SET, + ETHTOOL_MSG_MODULE_RESET_ACT, /* add new constants above here */ __ETHTOOL_MSG_USER_CNT, @@ -94,6 +95,7 @@ enum { ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY, ETHTOOL_MSG_MODULE_GET_REPLY, ETHTOOL_MSG_MODULE_NTF, + ETHTOOL_MSG_MODULE_RESET_NTF, /* add new constants above here */ __ETHTOOL_MSG_KERNEL_CNT, diff --git a/net/ethtool/module.c b/net/ethtool/module.c index 947f2188d725..f5b730eb0645 100644 --- a/net/ethtool/module.c +++ b/net/ethtool/module.c @@ -182,3 +182,83 @@ int ethnl_set_module(struct sk_buff *skb, struct genl_info *info) dev_put(dev); return ret; } + +/* MODULE_RESET_ACT */ + +const struct nla_policy ethnl_module_reset_act_policy[ETHTOOL_A_MODULE_HEADER + 1] = { + [ETHTOOL_A_MODULE_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy), +}; + +static void ethnl_module_reset_done(struct net_device *dev) +{ + struct sk_buff *skb; + void *ehdr; + int ret; + + skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!skb) + return; + + ehdr = ethnl_bcastmsg_put(skb, ETHTOOL_MSG_MODULE_RESET_NTF); + if (!ehdr) + goto out; + + ret = ethnl_fill_reply_header(skb, dev, ETHTOOL_A_MODULE_HEADER); + if (ret < 0) + goto out; + + genlmsg_end(skb, ehdr); + ethnl_multicast(skb, dev); + return; + +out: + nlmsg_free(skb); +} + +int ethnl_act_module_reset(struct sk_buff *skb, struct genl_info *info) +{ + struct ethnl_req_info req_info = {}; + struct nlattr **tb = info->attrs; + const struct ethtool_ops *ops; + struct net_device *dev; + int ret; + + ret = ethnl_parse_header_dev_get(&req_info, + tb[ETHTOOL_A_MODULE_HEADER], + genl_info_net(info), info->extack, + true); + if (ret < 0) + return ret; + + dev = req_info.dev; + + rtnl_lock(); + ops = dev->ethtool_ops; + if (!ops->reset_module) { + ret = -EOPNOTSUPP; + goto out_rtnl; + } + + if (netif_running(dev)) { + NL_SET_ERR_MSG(info->extack, + "Cannot reset module when port is administratively up"); + ret = -EINVAL; + goto out_rtnl; + } + + ret = ethnl_ops_begin(dev); + if (ret < 0) + goto out_rtnl; + + ret = ops->reset_module(dev, info->extack); + + ethnl_ops_complete(dev); + + if (!ret) + ethnl_module_reset_done(dev); + +out_rtnl: + rtnl_unlock(); + dev_put(dev); + return ret; +} diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index 38b44c0291b1..8558caa1a963 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -1018,6 +1018,13 @@ static const struct genl_ops ethtool_genl_ops[] = { .policy = ethnl_module_set_policy, .maxattr = ARRAY_SIZE(ethnl_module_set_policy) - 1, }, + { + .cmd = ETHTOOL_MSG_MODULE_RESET_ACT, + .flags = GENL_UNS_ADMIN_PERM, + .doit = ethnl_act_module_reset, + .policy = ethnl_module_reset_act_policy, + .maxattr = ARRAY_SIZE(ethnl_module_reset_act_policy) - 1, + }, }; static const struct genl_multicast_group ethtool_nl_mcgrps[] = { diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h index cf0fcbfe3c5c..7087cd20c4d0 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -376,6 +376,7 @@ extern const struct nla_policy ethnl_stats_get_policy[ETHTOOL_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_HEADER + 1]; extern const struct nla_policy ethnl_module_set_policy[ETHTOOL_A_MODULE_LOW_POWER_ENABLED + 1]; +extern const struct nla_policy ethnl_module_reset_act_policy[ETHTOOL_A_MODULE_HEADER + 1]; int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info); int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info); @@ -395,6 +396,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_act_module_reset(struct sk_buff *skb, struct genl_info *info); extern const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN]; extern const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN]; From patchwork Mon Aug 9 10:21:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ido Schimmel X-Patchwork-Id: 494259 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A96D6C4320A for ; Mon, 9 Aug 2021 10:22:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8B0D7610E7 for ; Mon, 9 Aug 2021 10:22:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234365AbhHIKWq (ORCPT ); Mon, 9 Aug 2021 06:22:46 -0400 Received: from out3-smtp.messagingengine.com ([66.111.4.27]:45877 "EHLO out3-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234342AbhHIKWn (ORCPT ); Mon, 9 Aug 2021 06:22:43 -0400 Received: from compute2.internal (compute2.nyi.internal [10.202.2.42]) by mailout.nyi.internal (Postfix) with ESMTP id 0D05E5C00C9; Mon, 9 Aug 2021 06:22:23 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute2.internal (MEProxy); Mon, 09 Aug 2021 06:22:23 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=cb55FD5+j/9oBoOflBOsDvA/h/sWtBIJa9rDRvx6Khw=; b=B2E7kA2n w82hJ/cmdqNOT04UoCOGIMgC8idvAO2VSujYwoDag0Cb/wfSt/UXIRMs0rC/s8gq vBoTPdVshIv0vYd+SLMoWzRbWGl8KYfvlRDkpQ8hSVo6KZImmWFws0If9i0HjEOK 5QquJSw9FQP6rR25WZ9/mTIJN0Ntu+D5HCyZzzjchK8fU5EV4g2oDKuRlmTeUqVP M9YOkg2wqOPqLnO6nVufSEJt+1AonxOf+z+OwpvapmPvx4ht6UtNtLs3bQ12moLd PtHduNXrFUE5TCSC2QKlMSjY5+EB+f1TMfZsmyCCerHUIQ4LMZdvRAkiPPTHDma/ L4Eb2QNRWjsJ7w== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrjeejgddvkecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffojghfggfgsedtkeertd ertddtnecuhfhrohhmpefkughoucfutghhihhmmhgvlhcuoehiughoshgthhesihguohhs tghhrdhorhhgqeenucggtffrrghtthgvrhhnpeduteeiveffffevleekleejffekhfekhe fgtdfftefhledvjefggfehgfevjeekhfenucevlhhushhtvghrufhiiigvpedunecurfgr rhgrmhepmhgrihhlfhhrohhmpehiughoshgthhesihguohhstghhrdhorhhg X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 9 Aug 2021 06:22:21 -0400 (EDT) From: Ido Schimmel To: netdev@vger.kernel.org Cc: davem@davemloft.net, kuba@kernel.org, andrew@lunn.ch, mkubecek@suse.cz, pali@kernel.org, vadimp@nvidia.com, mlxsw@nvidia.com, Ido Schimmel Subject: [RFC PATCH net-next 3/8] mlxsw: reg: Add fields to PMAOS register Date: Mon, 9 Aug 2021 13:21:47 +0300 Message-Id: <20210809102152.719961-4-idosch@idosch.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210809102152.719961-1-idosch@idosch.org> References: <20210809102152.719961-1-idosch@idosch.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Ido Schimmel The Ports Module Administrative and Operational Status (PMAOS) register configures and retrieves the per-module status. Extend it with fields required to support various module settings such as reset and low power mode. Signed-off-by: Ido Schimmel --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 58 +++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 6fbda6ebd590..b2c55259f333 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -5681,6 +5681,14 @@ static inline void mlxsw_reg_pspa_pack(char *payload, u8 swid, u8 local_port) MLXSW_REG_DEFINE(pmaos, MLXSW_REG_PMAOS_ID, MLXSW_REG_PMAOS_LEN); +/* reg_pmaos_rst + * Module reset toggle. + * Note: Setting reset while module is plugged-in will result in transition to + * "initializing" operational state. + * Access: OP + */ +MLXSW_ITEM32(reg, pmaos, rst, 0x00, 31, 1); + /* reg_pmaos_slot_index * Slot index. * Access: Index @@ -5693,6 +5701,38 @@ MLXSW_ITEM32(reg, pmaos, slot_index, 0x00, 24, 4); */ MLXSW_ITEM32(reg, pmaos, module, 0x00, 16, 8); +enum mlxsw_reg_pmaos_admin_status { + MLXSW_REG_PMAOS_ADMIN_STATUS_ENABLED = 1, + MLXSW_REG_PMAOS_ADMIN_STATUS_DISABLED = 2, + /* If the module is active and then unplugged, or experienced an error + * event, the operational status should go to "disabled" and can only + * be enabled upon explicit enable command. + */ + MLXSW_REG_PMAOS_ADMIN_STATUS_ENABLED_ONCE = 3, +}; + +/* reg_pmaos_admin_status + * Module administrative state (the desired state of the module). + * Note: To disable a module, all ports associated with the port must be + * administatively down first. + * Access: RW + */ +MLXSW_ITEM32(reg, pmaos, admin_status, 0x00, 8, 4); + +enum mlxsw_reg_pmaos_oper_status { + MLXSW_REG_PMAOS_OPER_STATUS_INITIALIZING, + MLXSW_REG_PMAOS_OPER_STATUS_PLUGGED_ENABLED, + MLXSW_REG_PMAOS_OPER_STATUS_UNPLUGGED, + /* Error code can be read from PMAOS.error_type */ + MLXSW_REG_PMAOS_OPER_STATUS_PLUGGED_ERROR, +}; + +/* reg_pmaos_oper_status + * Module state. Reserved while administrative state is disabled. + * Access: RO + */ +MLXSW_ITEM32(reg, pmaos, oper_status, 0x00, 0, 4); + /* reg_pmaos_ase * Admin state update enable. * If this bit is set, admin state will be updated based on admin_state field. @@ -5709,6 +5749,24 @@ MLXSW_ITEM32(reg, pmaos, ase, 0x04, 31, 1); */ MLXSW_ITEM32(reg, pmaos, ee, 0x04, 30, 1); +enum mlxsw_reg_pmaos_error_type { + MLXSW_REG_PMAOS_ERROR_TYPE_POWER_BUDGET_EXCEEDED = 0, + /* I2C data or clock shorted */ + MLXSW_REG_PMAOS_ERROR_TYPE_BUS_STUCK = 2, + MLXSW_REG_PMAOS_ERROR_TYPE_BAD_UNSUPPORTED_EEPROM = 3, + MLXSW_REG_PMAOS_ERROR_TYPE_UNSUPPORTED_CABLE = 5, + MLXSW_REG_PMAOS_ERROR_TYPE_HIGH_TEMP = 6, + /* Module / cable is shorted */ + MLXSW_REG_PMAOS_ERROR_TYPE_BAD_CABLE = 7, +}; + +/* reg_pmaos_error_type + * Module error details. Only valid when operational status is "plugged with + * error". + * Access: RO + */ +MLXSW_ITEM32(reg, pmaos, error_type, 0x04, 8, 4); + enum mlxsw_reg_pmaos_e { MLXSW_REG_PMAOS_E_DO_NOT_GENERATE_EVENT, MLXSW_REG_PMAOS_E_GENERATE_EVENT, From patchwork Mon Aug 9 10:21:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ido Schimmel X-Patchwork-Id: 494258 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 54348C4320E for ; Mon, 9 Aug 2021 10:22:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 310D86108C for ; Mon, 9 Aug 2021 10:22:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234691AbhHIKWz (ORCPT ); Mon, 9 Aug 2021 06:22:55 -0400 Received: from out3-smtp.messagingengine.com ([66.111.4.27]:59393 "EHLO out3-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234409AbhHIKWq (ORCPT ); Mon, 9 Aug 2021 06:22:46 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailout.nyi.internal (Postfix) with ESMTP id CDFC85C00CE; Mon, 9 Aug 2021 06:22:25 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Mon, 09 Aug 2021 06:22:25 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=Ezmm/eovCc3HMKlZrdY3IL0BGI/w4/hT54UfxXc4uvY=; b=smMq1c95 lYCaiqMim5cFieGhV69Dk1ILLXi7UjAQ6ai3jzAhtdWuN/o4T7ItfSwTjdZvHSQ4 t/AnO41OukCsrxiZ+bVVf+hI9mceHMUJsfUpfhtc00VGhDdq982cqO+e1rWhEYTZ WS2tfWnWFHVj2W/KzLhtZLh7o4AU+nwLbQfLN5A8yP8AAF8MPl9F1RtOoUM/0z1E yctelZDEDUOzXewY0KMQ3Jw8DZFz9B8svbez5/DZGxViMkmvqdb6GdVq5J6GCwMA b/ZEk2A7Fkvmo8LvgRMBUj3TWuqsmdttjPgX/qGN9ylR0622Hc15ME29gLhanqUw Lxizncl6Dvapyw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrjeejgddvkecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffojghfggfgsedtkeertd ertddtnecuhfhrohhmpefkughoucfutghhihhmmhgvlhcuoehiughoshgthhesihguohhs tghhrdhorhhgqeenucggtffrrghtthgvrhhnpeduteeiveffffevleekleejffekhfekhe fgtdfftefhledvjefggfehgfevjeekhfenucevlhhushhtvghrufhiiigvpedtnecurfgr rhgrmhepmhgrihhlfhhrohhmpehiughoshgthhesihguohhstghhrdhorhhg X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 9 Aug 2021 06:22:23 -0400 (EDT) From: Ido Schimmel To: netdev@vger.kernel.org Cc: davem@davemloft.net, kuba@kernel.org, andrew@lunn.ch, mkubecek@suse.cz, pali@kernel.org, vadimp@nvidia.com, mlxsw@nvidia.com, Ido Schimmel Subject: [RFC PATCH net-next 4/8] mlxsw: Make PMAOS pack function more generic Date: Mon, 9 Aug 2021 13:21:48 +0300 Message-Id: <20210809102152.719961-5-idosch@idosch.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210809102152.719961-1-idosch@idosch.org> References: <20210809102152.719961-1-idosch@idosch.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Ido Schimmel The PMAOS register has enable bits (e.g., PMAOS.ee) that allow changing only a subset of the fields, which is exactly what subsequent patches will need to do. Instead of passing multiple arguments to its pack function, only pass the module index and let the rest be set by the different callers. No functional changes intended. Signed-off-by: Ido Schimmel --- drivers/net/ethernet/mellanox/mlxsw/core_env.c | 6 ++++-- drivers/net/ethernet/mellanox/mlxsw/reg.h | 5 +---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c index 3713c45cfa1e..32554910506e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c @@ -652,8 +652,10 @@ mlxsw_env_module_oper_state_event_enable(struct mlxsw_core *mlxsw_core, for (i = 0; i < module_count; i++) { char pmaos_pl[MLXSW_REG_PMAOS_LEN]; - mlxsw_reg_pmaos_pack(pmaos_pl, i, - MLXSW_REG_PMAOS_E_GENERATE_EVENT); + mlxsw_reg_pmaos_pack(pmaos_pl, i); + mlxsw_reg_pmaos_e_set(pmaos_pl, + MLXSW_REG_PMAOS_E_GENERATE_EVENT); + mlxsw_reg_pmaos_ee_set(pmaos_pl, true); err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(pmaos), pmaos_pl); if (err) return err; diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index b2c55259f333..d0361f60d70d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -5779,13 +5779,10 @@ enum mlxsw_reg_pmaos_e { */ MLXSW_ITEM32(reg, pmaos, e, 0x04, 0, 2); -static inline void mlxsw_reg_pmaos_pack(char *payload, u8 module, - enum mlxsw_reg_pmaos_e e) +static inline void mlxsw_reg_pmaos_pack(char *payload, u8 module) { MLXSW_REG_ZERO(pmaos, payload); mlxsw_reg_pmaos_module_set(payload, module); - mlxsw_reg_pmaos_e_set(payload, e); - mlxsw_reg_pmaos_ee_set(payload, true); } /* PPLR - Port Physical Loopback Register From patchwork Mon Aug 9 10:21:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ido Schimmel X-Patchwork-Id: 494876 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3CC76C432BE for ; Mon, 9 Aug 2021 10:22:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2430F61078 for ; Mon, 9 Aug 2021 10:22:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234959AbhHIKXB (ORCPT ); Mon, 9 Aug 2021 06:23:01 -0400 Received: from out3-smtp.messagingengine.com ([66.111.4.27]:55951 "EHLO out3-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234478AbhHIKWt (ORCPT ); Mon, 9 Aug 2021 06:22:49 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 925CE5C00DB; Mon, 9 Aug 2021 06:22:28 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute4.internal (MEProxy); Mon, 09 Aug 2021 06:22:28 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=l9YGg2Yfk86TixqcGojB4/U6R6PGKzckUIyCiOSaVEo=; b=s7eloP7B IOARDJydjE5lUlHDMLuIsDtCmNz3NsoSQdVVbSx2g6QQ5abNMHSHj4go88+/pAJq ySabZU35TIvZfaW9i7olZhQ0iCynW43eg7FZiGvUBG5FwBHc8f95EFFHMeysDeHR K1ZvlFR6oZUDDt3/KEKHblelHMwcAB04rhn3wc0z06/6rtBXlgd4RZn8H8cX5Ca8 f7c42BFKaMs90UaxrP1KdMOTk/VTnxGnNE3mQ/MGFo2l7hJLj0xhx4oEOg3P1R6N Qi1V3LuhWR5Ae8RN+5OwKHuHf2mNo8uTkdD84sbLr133hkpk5Xvexxl4esHPgHCv TnPtlwewOehWpg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrjeejgddvkecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffojghfggfgsedtkeertd ertddtnecuhfhrohhmpefkughoucfutghhihhmmhgvlhcuoehiughoshgthhesihguohhs tghhrdhorhhgqeenucggtffrrghtthgvrhhnpeduteeiveffffevleekleejffekhfekhe fgtdfftefhledvjefggfehgfevjeekhfenucevlhhushhtvghrufhiiigvpedtnecurfgr rhgrmhepmhgrihhlfhhrohhmpehiughoshgthhesihguohhstghhrdhorhhg X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 9 Aug 2021 06:22:26 -0400 (EDT) From: Ido Schimmel To: netdev@vger.kernel.org Cc: davem@davemloft.net, kuba@kernel.org, andrew@lunn.ch, mkubecek@suse.cz, pali@kernel.org, vadimp@nvidia.com, mlxsw@nvidia.com, Ido Schimmel Subject: [RFC PATCH net-next 5/8] mlxsw: reg: Add Port Module Memory Map Properties register Date: Mon, 9 Aug 2021 13:21:49 +0300 Message-Id: <20210809102152.719961-6-idosch@idosch.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210809102152.719961-1-idosch@idosch.org> References: <20210809102152.719961-1-idosch@idosch.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Ido Schimmel Add the Port Module Memory Map Properties register. It will be used to force a module into low power mode in subsequent patches. Signed-off-by: Ido Schimmel --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 44 +++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index d0361f60d70d..7808b308e7af 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -5915,6 +5915,49 @@ static inline void mlxsw_reg_pddr_pack(char *payload, u8 local_port, mlxsw_reg_pddr_page_select_set(payload, page_select); } +/* PMMP - Port Module Memory Map Properties Register + * ------------------------------------------------- + * The PMMP register allows to override the module memory map advertisement. + * The register can only be set when the module is disabled by PMAOS register. + */ +#define MLXSW_REG_PMMP_ID 0x5044 +#define MLXSW_REG_PMMP_LEN 0x2C + +MLXSW_REG_DEFINE(pmmp, MLXSW_REG_PMMP_ID, MLXSW_REG_PMMP_LEN); + +/* reg_pmmp_module + * Module number. + * Access: Index + */ +MLXSW_ITEM32(reg, pmmp, module, 0x00, 16, 8); + +/* reg_pmmp_eeprom_override_mask + * Write mask bit (negative polarity). + * 0 - Allow write + * 1 - Ignore write + * On write, indicates which of the bits from eeprom_override field are + * updated. + * Access: WO + */ +MLXSW_ITEM32(reg, pmmp, eeprom_override_mask, 0x04, 16, 16); + +enum { + /* Set module to low power mode */ + MLXSW_REG_PMMP_EEPROM_OVERRIDE_LOW_POWER_MASK = BIT(8), +}; + +/* reg_pmmp_eeprom_override + * Override / ignore EEPROM advertisement properties bitmask + * Access: RW + */ +MLXSW_ITEM32(reg, pmmp, eeprom_override, 0x04, 0, 16); + +static inline void mlxsw_reg_pmmp_pack(char *payload, u8 module) +{ + MLXSW_REG_ZERO(pmmp, payload); + mlxsw_reg_pmmp_module_set(payload, module); +} + /* PMTM - Port Module Type Mapping Register * ---------------------------------------- * The PMTM allows query or configuration of module types. @@ -12257,6 +12300,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { MLXSW_REG(pplr), MLXSW_REG(pmpe), MLXSW_REG(pddr), + MLXSW_REG(pmmp), MLXSW_REG(pmtm), MLXSW_REG(htgt), MLXSW_REG(hpkt), From patchwork Mon Aug 9 10:21:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ido Schimmel X-Patchwork-Id: 494875 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EAF0DC432BE for ; Mon, 9 Aug 2021 10:22:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D055B61078 for ; Mon, 9 Aug 2021 10:22:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234656AbhHIKXG (ORCPT ); Mon, 9 Aug 2021 06:23:06 -0400 Received: from out3-smtp.messagingengine.com ([66.111.4.27]:40699 "EHLO out3-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234597AbhHIKWw (ORCPT ); Mon, 9 Aug 2021 06:22:52 -0400 Received: from compute6.internal (compute6.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id BC05A5C00E7; Mon, 9 Aug 2021 06:22:31 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute6.internal (MEProxy); Mon, 09 Aug 2021 06:22:31 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=nO9kRBp2X0GUH0GXIeBd+0FGgjAX3QvpoASO+AyL5ng=; b=j+Iwa422 QRDRAe22WOxgn9s82g6TC7kmOY6ojujeXabG9nNGM1lM7DKbgmEkbZhRyWfXiqsB mhe0OlD3BLUVSQAgvEeGbz/TJaqaazS/HffuQJx83+tTGJaMtcFPdxQYXws7yZ75 37asWrr9dYpJ3speZKvhZcdewwHQJiSmEHqVdkVwhtHzTlCeyMscC/WJRzDSSHND ZFbFMessikMnyrjmtU8B7NfG4zp9HXL/FOnsFN+GGpjdhCtt4ln4PiBJIssn1N8N mZT1LMlfUkmAk/MfbhrqmIOyggeuUoZvKNUeHQcScNxLy65tvzE+DYTtdXQ72XuF X2lXdGIaguGW3A== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrjeejgddvkecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffojghfggfgsedtkeertd ertddtnecuhfhrohhmpefkughoucfutghhihhmmhgvlhcuoehiughoshgthhesihguohhs tghhrdhorhhgqeenucggtffrrghtthgvrhhnpeduteeiveffffevleekleejffekhfekhe fgtdfftefhledvjefggfehgfevjeekhfenucevlhhushhtvghrufhiiigvpedtnecurfgr rhgrmhepmhgrihhlfhhrohhmpehiughoshgthhesihguohhstghhrdhorhhg X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 9 Aug 2021 06:22:28 -0400 (EDT) From: Ido Schimmel To: netdev@vger.kernel.org Cc: davem@davemloft.net, kuba@kernel.org, andrew@lunn.ch, mkubecek@suse.cz, pali@kernel.org, vadimp@nvidia.com, mlxsw@nvidia.com, Ido Schimmel Subject: [RFC PATCH net-next 6/8] mlxsw: reg: Add Management Cable IO and Notifications register Date: Mon, 9 Aug 2021 13:21:50 +0300 Message-Id: <20210809102152.719961-7-idosch@idosch.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210809102152.719961-1-idosch@idosch.org> References: <20210809102152.719961-1-idosch@idosch.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Ido Schimmel Add the Management Cable IO and Notifications register. It will be used to retrieve the low power mode status of a module in subsequent patches. Signed-off-by: Ido Schimmel --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 33 +++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 7808b308e7af..d25ca5f714f4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -10306,6 +10306,38 @@ static inline void mlxsw_reg_mlcr_pack(char *payload, u8 local_port, MLXSW_REG_MLCR_DURATION_MAX : 0); } +/* MCION - Management Cable IO and Notifications Register + * ------------------------------------------------------ + * The MCION register is used to query transceiver modules' IO pins and other + * notifications. + */ +#define MLXSW_REG_MCION_ID 0x9052 +#define MLXSW_REG_MCION_LEN 0x18 + +MLXSW_REG_DEFINE(mcion, MLXSW_REG_MCION_ID, MLXSW_REG_MCION_LEN); + +/* reg_mcion_module + * Module number. + * Access: Index + */ +MLXSW_ITEM32(reg, mcion, module, 0x00, 16, 8); + +enum { + MLXSW_REG_MCION_MODULE_STATUS_BITS_LOW_POWER_MASK = BIT(8), +}; + +/* reg_mcion_module_status_bits + * Module IO status as defined by SFF. + * Access: RO + */ +MLXSW_ITEM32(reg, mcion, module_status_bits, 0x04, 0, 16); + +static inline void mlxsw_reg_mcion_pack(char *payload, u8 module) +{ + MLXSW_REG_ZERO(mcion, payload); + mlxsw_reg_mcion_module_set(payload, module); +} + /* MTPPS - Management Pulse Per Second Register * -------------------------------------------- * This register provides the device PPS capabilities, configure the PPS in and @@ -12348,6 +12380,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { MLXSW_REG(mgir), MLXSW_REG(mrsr), MLXSW_REG(mlcr), + MLXSW_REG(mcion), MLXSW_REG(mtpps), MLXSW_REG(mtutc), MLXSW_REG(mpsc), From patchwork Mon Aug 9 10:21:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ido Schimmel X-Patchwork-Id: 494257 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D5A8CC4338F for ; Mon, 9 Aug 2021 10:22:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BD41161078 for ; Mon, 9 Aug 2021 10:22:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234973AbhHIKXD (ORCPT ); Mon, 9 Aug 2021 06:23:03 -0400 Received: from out3-smtp.messagingengine.com ([66.111.4.27]:35949 "EHLO out3-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234600AbhHIKWy (ORCPT ); Mon, 9 Aug 2021 06:22:54 -0400 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id 3D4095C0101; Mon, 9 Aug 2021 06:22:34 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Mon, 09 Aug 2021 06:22:34 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=GzlajbeI3bm43rJbD/jbWh989Jdxcvahoqk3zJHsb9A=; b=uf0qV7x6 IlTGENlT+1Mvzgf46CedI9Px2k+JXQAsDF2c4Zg644YHTjzISN1J6hq0NXFDs/Ql sxBdpgJ8bQFfGYiieosEhgaeOhMsZmSWrDUt2E4HTBzb7iydOiCl/3Dz0M/j9J7G T0zLqF9G679kQVmadiHz6WZTWMuksZ7hHseEN2MilogqONvR8hTLSxScCmzL7vbm ZLE8weL0Ouf4AgB+bjEKsCsxuIUS3FcASVh9xC7M5PY3h6NK+yXd5pGBTQ42A5X6 iwe85ZdYA9FB418/4kmDNU8Exj5kc0/uOsHp4LkjAc/VqbxXZWfLLoP763XniWWn DLeGUkxF2kzOlA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrjeejgddvkecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffojghfggfgsedtkeertd ertddtnecuhfhrohhmpefkughoucfutghhihhmmhgvlhcuoehiughoshgthhesihguohhs tghhrdhorhhgqeenucggtffrrghtthgvrhhnpeduteeiveffffevleekleejffekhfekhe fgtdfftefhledvjefggfehgfevjeekhfenucevlhhushhtvghrufhiiigvpedunecurfgr rhgrmhepmhgrihhlfhhrohhmpehiughoshgthhesihguohhstghhrdhorhhg X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 9 Aug 2021 06:22:31 -0400 (EDT) From: Ido Schimmel To: netdev@vger.kernel.org Cc: davem@davemloft.net, kuba@kernel.org, andrew@lunn.ch, mkubecek@suse.cz, pali@kernel.org, vadimp@nvidia.com, mlxsw@nvidia.com, Ido Schimmel Subject: [RFC PATCH net-next 7/8] mlxsw: Add ability to control transceiver modules' low power mode Date: Mon, 9 Aug 2021 13:21:51 +0300 Message-Id: <20210809102152.719961-8-idosch@idosch.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210809102152.719961-1-idosch@idosch.org> References: <20210809102152.719961-1-idosch@idosch.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Ido Schimmel Implement support for ethtool_ops::.get_module_low_power and ethtool_ops::set_module_low_power. The get operation is implemented using the Management Cable IO and Notifications (MCION) register that reports the low power mode status of the module. The set operation is implemented using the Port Module Memory Map Properties (PMMP) register. The register instructs the device's firmware to transition a plugged-in module to / out of low power mode by writing to its memory map. Before using the PMMP register, the module must be disabled by the PMAOS register. All the ports mapped to the module are iterated to ensure they are administratively down, so that their operational state will not change during the operation. After the operation is performed, the module is re-enabled and its operational state is polled to ensure the module transitioned back to a valid state. If not, an error is reported to user space via extack. Signed-off-by: Ido Schimmel --- .../net/ethernet/mellanox/mlxsw/core_env.c | 198 ++++++++++++++++++ .../net/ethernet/mellanox/mlxsw/core_env.h | 8 + drivers/net/ethernet/mellanox/mlxsw/minimal.c | 24 +++ .../mellanox/mlxsw/spectrum_ethtool.c | 49 +++++ 4 files changed, 279 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c index 32554910506e..1ae06730d374 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "core.h" #include "core_env.h" @@ -389,6 +390,203 @@ mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, u8 module, } EXPORT_SYMBOL(mlxsw_env_get_module_eeprom_by_page); +int mlxsw_env_get_module_low_power(struct mlxsw_core *mlxsw_core, u8 module, + bool *p_low_power, + struct netlink_ext_ack *extack) +{ + char mcion_pl[MLXSW_REG_MCION_LEN]; + u16 status_bits; + int err; + + mlxsw_reg_mcion_pack(mcion_pl, module); + + err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcion), mcion_pl); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Failed to retrieve module's low power mode"); + return err; + } + + status_bits = mlxsw_reg_mcion_module_status_bits_get(mcion_pl); + *p_low_power = + status_bits & MLXSW_REG_MCION_MODULE_STATUS_BITS_LOW_POWER_MASK; + + return 0; +} +EXPORT_SYMBOL(mlxsw_env_get_module_low_power); + +static int mlxsw_env_module_enable_set(struct mlxsw_core *mlxsw_core, u8 module, + bool enable) +{ + enum mlxsw_reg_pmaos_admin_status admin_status; + char pmaos_pl[MLXSW_REG_PMAOS_LEN]; + + mlxsw_reg_pmaos_pack(pmaos_pl, module); + admin_status = enable ? MLXSW_REG_PMAOS_ADMIN_STATUS_ENABLED : + MLXSW_REG_PMAOS_ADMIN_STATUS_DISABLED; + mlxsw_reg_pmaos_admin_status_set(pmaos_pl, admin_status); + mlxsw_reg_pmaos_ase_set(pmaos_pl, true); + + return mlxsw_reg_write(mlxsw_core, MLXSW_REG(pmaos), pmaos_pl); +} + +static int mlxsw_env_module_low_power_set(struct mlxsw_core *mlxsw_core, + u8 module, bool low_power) +{ + u16 eeprom_override_mask, eeprom_override; + char pmmp_pl[MLXSW_REG_PMMP_LEN]; + + mlxsw_reg_pmmp_pack(pmmp_pl, module); + /* Mask all the bits except low power mode. */ + eeprom_override_mask = ~MLXSW_REG_PMMP_EEPROM_OVERRIDE_LOW_POWER_MASK; + mlxsw_reg_pmmp_eeprom_override_mask_set(pmmp_pl, eeprom_override_mask); + eeprom_override = low_power ? MLXSW_REG_PMMP_EEPROM_OVERRIDE_LOW_POWER_MASK : + 0; + mlxsw_reg_pmmp_eeprom_override_set(pmmp_pl, eeprom_override); + + return mlxsw_reg_write(mlxsw_core, MLXSW_REG(pmmp), pmmp_pl); +} + +static int mlxsw_env_module_error_process(const char *pmaos_pl, + struct netlink_ext_ack *extack) +{ + enum mlxsw_reg_pmaos_error_type error_type; + + error_type = mlxsw_reg_pmaos_error_type_get(pmaos_pl); + switch (error_type) { + case MLXSW_REG_PMAOS_ERROR_TYPE_POWER_BUDGET_EXCEEDED: + NL_SET_ERR_MSG_MOD(extack, "Module's power budget exceeded"); + return -EINVAL; + case MLXSW_REG_PMAOS_ERROR_TYPE_BUS_STUCK: + NL_SET_ERR_MSG_MOD(extack, "Module's I2C bus is stuck. Data or clock shorted"); + return -EIO; + case MLXSW_REG_PMAOS_ERROR_TYPE_BAD_UNSUPPORTED_EEPROM: + NL_SET_ERR_MSG_MOD(extack, "Bad or unsupported module EEPROM"); + return -EOPNOTSUPP; + case MLXSW_REG_PMAOS_ERROR_TYPE_UNSUPPORTED_CABLE: + NL_SET_ERR_MSG_MOD(extack, "Unsupported cable"); + return -EOPNOTSUPP; + case MLXSW_REG_PMAOS_ERROR_TYPE_HIGH_TEMP: + NL_SET_ERR_MSG_MOD(extack, "Module's temperature is too high"); + return -EINVAL; + case MLXSW_REG_PMAOS_ERROR_TYPE_BAD_CABLE: + NL_SET_ERR_MSG_MOD(extack, "Bad module. Module / cable is shorted"); + return -EINVAL; + default: + NL_SET_ERR_MSG_MOD(extack, "Encountered unknown module error type"); + return -EINVAL; + } +} + +static bool mlxsw_env_module_oper_should_wait(const char *pmaos_pl) +{ + enum mlxsw_reg_pmaos_oper_status oper_status; + + oper_status = mlxsw_reg_pmaos_oper_status_get(pmaos_pl); + switch (oper_status) { + case MLXSW_REG_PMAOS_OPER_STATUS_PLUGGED_ENABLED: + case MLXSW_REG_PMAOS_OPER_STATUS_UNPLUGGED: + return false; + default: + /* Module might not be accessible just after its re-enablement, + * so ignore errors or unknown states during this time period. + */ + return true; + } +} + +static int mlxsw_env_module_oper_status_process(const char *pmaos_pl, + struct netlink_ext_ack *extack) +{ + enum mlxsw_reg_pmaos_oper_status oper_status; + + oper_status = mlxsw_reg_pmaos_oper_status_get(pmaos_pl); + switch (oper_status) { + case MLXSW_REG_PMAOS_OPER_STATUS_INITIALIZING: + NL_SET_ERR_MSG_MOD(extack, "Module is still initializing"); + return -EBUSY; + case MLXSW_REG_PMAOS_OPER_STATUS_PLUGGED_ENABLED: + case MLXSW_REG_PMAOS_OPER_STATUS_UNPLUGGED: + return 0; + case MLXSW_REG_PMAOS_OPER_STATUS_PLUGGED_ERROR: + return mlxsw_env_module_error_process(pmaos_pl, extack); + default: + NL_SET_ERR_MSG_MOD(extack, "Encountered unknown module operational status"); + return -EINVAL; + } +} + +/* Firmware should take about 2-3 seconds to initialize the module. */ +#define MLXSW_ENV_MODULE_TIMEOUT_MSECS 5000 +#define MLXSW_ENV_MODULE_WAIT_INTERVAL_MSECS 100 + +static int mlxsw_env_module_oper_wait(struct mlxsw_core *mlxsw_core, u8 module, + struct netlink_ext_ack *extack) +{ + char pmaos_pl[MLXSW_REG_PMAOS_LEN]; + unsigned long end; + + end = jiffies + msecs_to_jiffies(MLXSW_ENV_MODULE_TIMEOUT_MSECS); + do { + int err; + + mlxsw_reg_pmaos_pack(pmaos_pl, module); + err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(pmaos), pmaos_pl); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Failed to query module's operational status"); + return err; + } + + if (!mlxsw_env_module_oper_should_wait(pmaos_pl)) + break; + msleep(MLXSW_ENV_MODULE_WAIT_INTERVAL_MSECS); + } while (time_before(jiffies, end)); + + return mlxsw_env_module_oper_status_process(pmaos_pl, extack); +} + +int mlxsw_env_set_module_low_power(struct mlxsw_core *mlxsw_core, u8 module, + bool low_power, + struct netlink_ext_ack *extack) +{ + int err; + + err = mlxsw_env_module_enable_set(mlxsw_core, module, false); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Failed to disable module"); + return err; + } + + err = mlxsw_env_module_low_power_set(mlxsw_core, module, low_power); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Failed to set module's low power mode"); + goto err_module_low_power_set; + } + + err = mlxsw_env_module_enable_set(mlxsw_core, module, true); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Failed to enable module"); + goto err_module_enable_set; + } + + /* Wait for the module to reach a valid operational state following its + * re-enablement. + */ + err = mlxsw_env_module_oper_wait(mlxsw_core, module, extack); + if (err) + goto err_module_oper_wait; + + return 0; + +err_module_oper_wait: + mlxsw_env_module_enable_set(mlxsw_core, module, false); +err_module_enable_set: + mlxsw_env_module_low_power_set(mlxsw_core, module, !low_power); +err_module_low_power_set: + mlxsw_env_module_enable_set(mlxsw_core, module, true); + return err; +} +EXPORT_SYMBOL(mlxsw_env_set_module_low_power); + static int mlxsw_env_module_has_temp_sensor(struct mlxsw_core *mlxsw_core, u8 module, bool *p_has_temp_sensor) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.h b/drivers/net/ethernet/mellanox/mlxsw/core_env.h index 0bf5bd0f8a7e..32960de96674 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.h @@ -24,6 +24,14 @@ mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, u8 module, const struct ethtool_module_eeprom *page, struct netlink_ext_ack *extack); +int mlxsw_env_get_module_low_power(struct mlxsw_core *mlxsw_core, u8 module, + bool *p_low_power, + struct netlink_ext_ack *extack); + +int mlxsw_env_set_module_low_power(struct mlxsw_core *mlxsw_core, u8 module, + bool low_power, + struct netlink_ext_ack *extack); + int mlxsw_env_module_overheat_counter_get(struct mlxsw_core *mlxsw_core, u8 module, u64 *p_counter); diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c index d9d56c44e994..6fb8204c4d8a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c @@ -124,11 +124,35 @@ mlxsw_m_get_module_eeprom_by_page(struct net_device *netdev, page, extack); } +static int mlxsw_m_get_module_low_power(struct net_device *netdev, + bool *p_low_power, + struct netlink_ext_ack *extack) +{ + struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev); + struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; + + return mlxsw_env_get_module_low_power(core, mlxsw_m_port->module, + p_low_power, extack); +} + +static int mlxsw_m_set_module_low_power(struct net_device *netdev, + bool low_power, + struct netlink_ext_ack *extack) +{ + struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev); + struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; + + return mlxsw_env_set_module_low_power(core, mlxsw_m_port->module, + low_power, extack); +} + static const struct ethtool_ops mlxsw_m_port_ethtool_ops = { .get_drvinfo = mlxsw_m_module_get_drvinfo, .get_module_info = mlxsw_m_get_module_info, .get_module_eeprom = mlxsw_m_get_module_eeprom, .get_module_eeprom_by_page = mlxsw_m_get_module_eeprom_by_page, + .get_module_low_power = mlxsw_m_get_module_low_power, + .set_module_low_power = mlxsw_m_set_module_low_power, }; static int diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c index 267590a0eee7..fb6256f16c50 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c @@ -1197,6 +1197,53 @@ mlxsw_sp_get_rmon_stats(struct net_device *dev, *ranges = mlxsw_rmon_ranges; } +static int mlxsw_sp_get_module_low_power(struct net_device *dev, + bool *p_low_power, + struct netlink_ext_ack *extack) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + u8 module = mlxsw_sp_port->mapping.module; + + return mlxsw_env_get_module_low_power(mlxsw_sp->core, module, + p_low_power, extack); +} + +static bool mlxsw_sp_module_ports_up_check(struct mlxsw_sp *mlxsw_sp, u8 module) +{ + int i; + + for (i = 1; i < mlxsw_core_max_ports(mlxsw_sp->core); i++) { + if (!mlxsw_sp->ports[i]) + continue; + if (mlxsw_sp->ports[i]->mapping.module != module) + continue; + if (netif_running(mlxsw_sp->ports[i]->dev)) + return true; + } + + return false; +} + +static int mlxsw_sp_set_module_low_power(struct net_device *dev, bool low_power, + struct netlink_ext_ack *extack) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + u8 module = mlxsw_sp_port->mapping.module; + + /* We are going to take the module down, so no port using it can be + * administratively up. + */ + if (mlxsw_sp_module_ports_up_check(mlxsw_sp, module)) { + NL_SET_ERR_MSG_MOD(extack, "Cannot set low power mode when ports using the module are administratively up"); + return -EINVAL; + } + + return mlxsw_env_set_module_low_power(mlxsw_sp->core, module, low_power, + extack); +} + const struct ethtool_ops mlxsw_sp_port_ethtool_ops = { .cap_link_lanes_supported = true, .get_drvinfo = mlxsw_sp_port_get_drvinfo, @@ -1218,6 +1265,8 @@ const struct ethtool_ops mlxsw_sp_port_ethtool_ops = { .get_eth_mac_stats = mlxsw_sp_get_eth_mac_stats, .get_eth_ctrl_stats = mlxsw_sp_get_eth_ctrl_stats, .get_rmon_stats = mlxsw_sp_get_rmon_stats, + .get_module_low_power = mlxsw_sp_get_module_low_power, + .set_module_low_power = mlxsw_sp_set_module_low_power, }; struct mlxsw_sp1_port_link_mode { From patchwork Mon Aug 9 10:21:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ido Schimmel X-Patchwork-Id: 494256 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A52B7C4338F for ; Mon, 9 Aug 2021 10:23:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 83F496108C for ; Mon, 9 Aug 2021 10:23:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234611AbhHIKXU (ORCPT ); Mon, 9 Aug 2021 06:23:20 -0400 Received: from out3-smtp.messagingengine.com ([66.111.4.27]:39615 "EHLO out3-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234585AbhHIKW5 (ORCPT ); Mon, 9 Aug 2021 06:22:57 -0400 Received: from compute6.internal (compute6.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id BE8E25C00E4; Mon, 9 Aug 2021 06:22:36 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute6.internal (MEProxy); Mon, 09 Aug 2021 06:22:36 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=Q/lnHpXsuuGGhgH7J2OtinC7PqY0h8vrUQbYPdx9ov0=; b=q7/BJvQg jilz1LoRSgot7dE3YBuqU/vA8q8x1udYHPinobKvxWyBE7gPks8zw6WVrQGJh3c1 H9pQD4mJjrXrhwpYLww9k6YQsRzqMWQeHHGKwF1NVKNIqQbbYQTZA9TcGUTsQ5cS nP63f6hZqNttZ/52v1SdWODXH74VjAqW6oP7oi92b4+UzW5ioDVA9YBjQXIHkLDq +ueg6JiJSNC1pvyGm3YtGXIxIMwEWlD8sC8HHFdJ28ytCykft7X11/mfwAmbLtjK NgrwFMb4qxLlRVEipgpcj5EVOtGnBNpwX5239Qh5ObAPLSt6yEzD/PB6ueFfx0b3 zH+ns7Lb8KB65Q== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrjeejgddvkecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffojghfggfgsedtkeertd ertddtnecuhfhrohhmpefkughoucfutghhihhmmhgvlhcuoehiughoshgthhesihguohhs tghhrdhorhhgqeenucggtffrrghtthgvrhhnpeduteeiveffffevleekleejffekhfekhe fgtdfftefhledvjefggfehgfevjeekhfenucevlhhushhtvghrufhiiigvpedunecurfgr rhgrmhepmhgrihhlfhhrohhmpehiughoshgthhesihguohhstghhrdhorhhg X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 9 Aug 2021 06:22:34 -0400 (EDT) From: Ido Schimmel To: netdev@vger.kernel.org Cc: davem@davemloft.net, kuba@kernel.org, andrew@lunn.ch, mkubecek@suse.cz, pali@kernel.org, vadimp@nvidia.com, mlxsw@nvidia.com, Ido Schimmel Subject: [RFC PATCH net-next 8/8] mlxsw: Add ability to reset transceiver modules Date: Mon, 9 Aug 2021 13:21:52 +0300 Message-Id: <20210809102152.719961-9-idosch@idosch.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210809102152.719961-1-idosch@idosch.org> References: <20210809102152.719961-1-idosch@idosch.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Ido Schimmel Implement support for ethtool_ops::reset_module. This is done by writing to the "rst" bit of the PMAOS register and waiting for the module to reach a valid operational state. If the module does not transition to a valid state, an error is reported to user space via extack. Signed-off-by: Ido Schimmel --- .../net/ethernet/mellanox/mlxsw/core_env.c | 28 +++++++++++++++++++ .../net/ethernet/mellanox/mlxsw/core_env.h | 3 ++ drivers/net/ethernet/mellanox/mlxsw/minimal.c | 10 +++++++ .../mellanox/mlxsw/spectrum_ethtool.c | 19 +++++++++++++ 4 files changed, 60 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c index 1ae06730d374..df578ef3319c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c @@ -587,6 +587,34 @@ int mlxsw_env_set_module_low_power(struct mlxsw_core *mlxsw_core, u8 module, } EXPORT_SYMBOL(mlxsw_env_set_module_low_power); +static int mlxsw_env_module_reset(struct mlxsw_core *mlxsw_core, u8 module) +{ + char pmaos_pl[MLXSW_REG_PMAOS_LEN]; + + mlxsw_reg_pmaos_pack(pmaos_pl, module); + mlxsw_reg_pmaos_rst_set(pmaos_pl, true); + + return mlxsw_reg_write(mlxsw_core, MLXSW_REG(pmaos), pmaos_pl); +} + +int mlxsw_env_reset_module(struct mlxsw_core *mlxsw_core, u8 module, + struct netlink_ext_ack *extack) +{ + int err; + + err = mlxsw_env_module_reset(mlxsw_core, module); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Failed to reset module"); + return err; + } + + /* Wait for the module to reach a valid operational state following its + * reset. + */ + return mlxsw_env_module_oper_wait(mlxsw_core, module, extack); +} +EXPORT_SYMBOL(mlxsw_env_reset_module); + static int mlxsw_env_module_has_temp_sensor(struct mlxsw_core *mlxsw_core, u8 module, bool *p_has_temp_sensor) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.h b/drivers/net/ethernet/mellanox/mlxsw/core_env.h index 32960de96674..465a095e6a3e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.h @@ -32,6 +32,9 @@ int mlxsw_env_set_module_low_power(struct mlxsw_core *mlxsw_core, u8 module, bool low_power, struct netlink_ext_ack *extack); +int mlxsw_env_reset_module(struct mlxsw_core *mlxsw_core, u8 module, + struct netlink_ext_ack *extack); + int mlxsw_env_module_overheat_counter_get(struct mlxsw_core *mlxsw_core, u8 module, u64 *p_counter); diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c index 6fb8204c4d8a..d206442270df 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c @@ -146,6 +146,15 @@ static int mlxsw_m_set_module_low_power(struct net_device *netdev, low_power, extack); } +static int mlxsw_m_reset_module(struct net_device *netdev, + struct netlink_ext_ack *extack) +{ + struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev); + struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; + + return mlxsw_env_reset_module(core, mlxsw_m_port->module, extack); +} + static const struct ethtool_ops mlxsw_m_port_ethtool_ops = { .get_drvinfo = mlxsw_m_module_get_drvinfo, .get_module_info = mlxsw_m_get_module_info, @@ -153,6 +162,7 @@ static const struct ethtool_ops mlxsw_m_port_ethtool_ops = { .get_module_eeprom_by_page = mlxsw_m_get_module_eeprom_by_page, .get_module_low_power = mlxsw_m_get_module_low_power, .set_module_low_power = mlxsw_m_set_module_low_power, + .reset_module = mlxsw_m_reset_module, }; static int diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c index fb6256f16c50..9526ef71e513 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c @@ -1244,6 +1244,24 @@ static int mlxsw_sp_set_module_low_power(struct net_device *dev, bool low_power, extack); } +static int mlxsw_sp_reset_module(struct net_device *dev, + struct netlink_ext_ack *extack) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + u8 module = mlxsw_sp_port->mapping.module; + + /* We are going to take the module down, so no port using it can be + * administratively up. + */ + if (mlxsw_sp_module_ports_up_check(mlxsw_sp, module)) { + NL_SET_ERR_MSG_MOD(extack, "Cannot reset module when ports using it are administratively up"); + return -EINVAL; + } + + return mlxsw_env_reset_module(mlxsw_sp->core, module, extack); +} + const struct ethtool_ops mlxsw_sp_port_ethtool_ops = { .cap_link_lanes_supported = true, .get_drvinfo = mlxsw_sp_port_get_drvinfo, @@ -1267,6 +1285,7 @@ const struct ethtool_ops mlxsw_sp_port_ethtool_ops = { .get_rmon_stats = mlxsw_sp_get_rmon_stats, .get_module_low_power = mlxsw_sp_get_module_low_power, .set_module_low_power = mlxsw_sp_set_module_low_power, + .reset_module = mlxsw_sp_reset_module, }; struct mlxsw_sp1_port_link_mode {