All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Björn Töpel" <bjorn@kernel.org>
To: netdev@vger.kernel.org, "David S. Miller" <davem@davemloft.net>,
	Andrew Lunn <andrew+netdev@lunn.ch>,
	Donald Hunter <donald.hunter@gmail.com>,
	Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>,
	Maxime Chevallier <maxime.chevallier@bootlin.com>,
	Naveen Mamindlapalli <naveenm@marvell.com>,
	Paolo Abeni <pabeni@redhat.com>, Simon Horman <horms@kernel.org>
Cc: "Björn Töpel" <bjorn@kernel.org>,
	"Danielle Ratson" <danieller@nvidia.com>,
	"Hariprasad Kelam" <hkelam@marvell.com>,
	"Ido Schimmel" <idosch@nvidia.com>,
	"Kory Maincent" <kory.maincent@bootlin.com>,
	"Leon Romanovsky" <leon@kernel.org>,
	"Michael Chan" <michael.chan@broadcom.com>,
	"Oleksij Rempel" <o.rempel@pengutronix.de>,
	"Pavan Chebbi" <pavan.chebbi@broadcom.com>,
	"Piergiorgio Beruto" <piergiorgio.beruto@gmail.com>,
	"Russell King" <linux@armlinux.org.uk>,
	"Saeed Mahameed" <saeedm@nvidia.com>,
	"Shuah Khan" <shuah@kernel.org>,
	"Tariq Toukan" <tariqt@nvidia.com>,
	"Willem de Bruijn" <willemb@google.com>,
	"Kees Cook" <kees@kernel.org>,
	linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
	linux-rdma@vger.kernel.org
Subject: [PATCH net-next v2 05/12] ethtool: Add CMIS loopback helpers for module loopback control
Date: Wed, 25 Mar 2026 15:50:12 +0100	[thread overview]
Message-ID: <20260325145022.2607545-6-bjorn@kernel.org> (raw)
In-Reply-To: <20260325145022.2607545-1-bjorn@kernel.org>

Add CMIS loopback functions and wire them into loopback.c for the
MODULE component:

 - ethtool_cmis_get_loopback(): reads Page 13h capabilities and
   current state, appends one entry per supported loopback point
   ("cmis-host" and/or "cmis-media").

 - ethtool_cmis_get_loopback_by_index(): used to enumerate what the
   module supports.

 - ethtool_cmis_set_loopback(): resolves name to a pair of control
   byte indices, validates direction, and writes the Page 13h control
   bytes (0xff = all lanes on, 0x00 = off).

Directions are mutually exclusive: switching from local to remote
first disables the active direction in a separate EEPROM write, then
enables the new one. Requesting multiple direction flags is rejected.

CMIS register mapping (Page 13h, Bytes 180-183):

 - MODULE, "cmis-host",  local    ->  Host Side Input    (Byte 183)
 - MODULE, "cmis-host",  remote   ->  Host Side Output   (Byte 182)
 - MODULE, "cmis-media", local    ->  Media Side Input   (Byte 181)
 - MODULE, "cmis-media", remote   ->  Media Side Output  (Byte 180)

The helpers work entirely over get/set_module_eeprom_by_page, so any
driver with EEPROM page access gets module loopback without new
ethtool_ops or driver changes. SET is rejected when firmware flashing
is in progress or the interface is UP.

Signed-off-by: Björn Töpel <bjorn@kernel.org>
---
 net/ethtool/Makefile        |   2 +-
 net/ethtool/cmis_loopback.c | 407 ++++++++++++++++++++++++++++++++++++
 net/ethtool/loopback.c      |   6 +-
 net/ethtool/netlink.h       |   8 +
 4 files changed, 421 insertions(+), 2 deletions(-)
 create mode 100644 net/ethtool/cmis_loopback.c

diff --git a/net/ethtool/Makefile b/net/ethtool/Makefile
index ef534b55d724..2f821c7875e1 100644
--- a/net/ethtool/Makefile
+++ b/net/ethtool/Makefile
@@ -9,4 +9,4 @@ ethtool_nl-y	:= netlink.o bitset.o strset.o linkinfo.o linkmodes.o rss.o \
 		   channels.o coalesce.o pause.o eee.o tsinfo.o cabletest.o \
 		   tunnels.o fec.o eeprom.o stats.o phc_vclocks.o mm.o \
 		   module.o cmis_fw_update.o cmis_cdb.o pse-pd.o plca.o \
-		   phy.o tsconfig.o mse.o loopback.o
+		   phy.o tsconfig.o mse.o loopback.o cmis_loopback.o
diff --git a/net/ethtool/cmis_loopback.c b/net/ethtool/cmis_loopback.c
new file mode 100644
index 000000000000..c4e8808ceaff
--- /dev/null
+++ b/net/ethtool/cmis_loopback.c
@@ -0,0 +1,407 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/* CMIS loopback helpers for drivers implementing ethtool
+ * get/set_loopback.
+ *
+ * Maps the generic ethtool loopback model to CMIS Page 13h registers
+ * (CMIS 5.3, Table 8-128).
+ *
+ * Capabilities are read from Page 13h Byte 128, with Page 13h
+ * availability checked via Page 01h Byte 142 bit 5.
+ */
+
+#include <linux/ethtool.h>
+#include <linux/sfp.h>
+
+#include "common.h"
+#include "module_fw.h"
+#include "cmis.h"
+
+/* CMIS Page 00h, Byte 0: Physical module identifier */
+#define CMIS_PHYS_ID_PAGE		0x00
+#define CMIS_PHYS_ID_OFFSET		0x00
+
+/* CMIS Page 01h, Byte 142: Diagnostic Pages Support */
+#define CMIS_DIAG_SUPPORT_PAGE		0x01
+#define CMIS_DIAG_SUPPORT_OFFSET	0x8e
+#define CMIS_DIAG_PAGE13_BIT		BIT(5)
+
+/* CMIS Page 13h, Byte 128: Loopback Capability Advertisement */
+#define CMIS_LB_CAPS_PAGE		0x13
+#define CMIS_LB_CAPS_OFFSET		0x80
+#define CMIS_LB_CAP_MEDIA_OUTPUT	BIT(0)
+#define CMIS_LB_CAP_MEDIA_INPUT		BIT(1)
+#define CMIS_LB_CAP_HOST_OUTPUT		BIT(2)
+#define CMIS_LB_CAP_HOST_INPUT		BIT(3)
+
+/* CMIS Page 13h, Bytes 180-183: Per-Lane Loopback Control
+ *   Byte 180 (0xb4): Media Side Output  -> MODULE, "cmis-media", remote
+ *   Byte 181 (0xb5): Media Side Input   -> MODULE, "cmis-media", local
+ *   Byte 182 (0xb6): Host Side Output   -> MODULE, "cmis-host",  remote
+ *   Byte 183 (0xb7): Host Side Input    -> MODULE, "cmis-host",  local
+ */
+#define CMIS_LB_CTRL_PAGE		0x13
+#define CMIS_LB_CTRL_OFFSET		0xb4
+#define CMIS_LB_CTRL_LEN		4
+#define CMIS_LB_CTRL_IDX_MEDIA_OUTPUT	0
+#define CMIS_LB_CTRL_IDX_MEDIA_INPUT	1
+#define CMIS_LB_CTRL_IDX_HOST_OUTPUT	2
+#define CMIS_LB_CTRL_IDX_HOST_INPUT	3
+
+#define CMIS_LB_NAME_HOST		"cmis-host"
+#define CMIS_LB_NAME_MEDIA		"cmis-media"
+
+static bool cmis_is_module(u8 phys_id)
+{
+	switch (phys_id) {
+	case SFF8024_ID_QSFP_DD:
+	case SFF8024_ID_OSFP:
+	case SFF8024_ID_DSFP:
+	case SFF8024_ID_QSFP_PLUS_CMIS:
+	case SFF8024_ID_SFP_DD_CMIS:
+	case SFF8024_ID_SFP_PLUS_CMIS:
+		return true;
+	default:
+		return false;
+	}
+}
+
+/**
+ * cmis_loopback_caps - Read CMIS loopback capability mask
+ * @dev: Network device
+ *
+ * Return: >0 capability bitmask, 0 if not a CMIS module or no Page
+ *         13h, negative errno on failure.
+ */
+static int cmis_loopback_caps(struct net_device *dev)
+{
+	const struct ethtool_ops *ops = dev->ethtool_ops;
+	struct ethtool_module_eeprom page = {};
+	int ret;
+	u8 val;
+
+	if (!ops->get_module_eeprom_by_page)
+		return 0;
+
+	/* Read physical identifier */
+	ethtool_cmis_page_init(&page, CMIS_PHYS_ID_PAGE,
+			       CMIS_PHYS_ID_OFFSET, sizeof(val));
+	page.data = &val;
+	ret = ops->get_module_eeprom_by_page(dev, &page, NULL);
+	if (ret < 0)
+		return ret;
+	if (!cmis_is_module(val))
+		return 0;
+
+	/* Check Page 13h availability */
+	ethtool_cmis_page_init(&page, CMIS_DIAG_SUPPORT_PAGE,
+			       CMIS_DIAG_SUPPORT_OFFSET, sizeof(val));
+	page.data = &val;
+	ret = ops->get_module_eeprom_by_page(dev, &page, NULL);
+	if (ret < 0)
+		return ret;
+	if (!(val & CMIS_DIAG_PAGE13_BIT))
+		return 0;
+
+	/* Read capability byte */
+	ethtool_cmis_page_init(&page, CMIS_LB_CAPS_PAGE,
+			       CMIS_LB_CAPS_OFFSET, sizeof(val));
+	page.data = &val;
+	ret = ops->get_module_eeprom_by_page(dev, &page, NULL);
+	if (ret < 0)
+		return ret;
+
+	return val & (CMIS_LB_CAP_MEDIA_OUTPUT | CMIS_LB_CAP_MEDIA_INPUT |
+		      CMIS_LB_CAP_HOST_OUTPUT | CMIS_LB_CAP_HOST_INPUT);
+}
+
+/**
+ * cmis_loopback_read - Read CMIS loopback capabilities and build entries
+ * @dev: Network device with get_module_eeprom_by_page support
+ * @host: Output host loopback entry (populated if host caps exist)
+ * @media: Output media loopback entry (populated if media caps exist)
+ * @has_host: Set to true if host loopback is supported
+ * @has_media: Set to true if media loopback is supported
+ *
+ * Common helper that reads CMIS caps and control bytes, then populates
+ * the host and media entries with current state.
+ *
+ * Return: 0 on success, -EOPNOTSUPP if no CMIS loopback support,
+ *         negative errno on failure.
+ */
+static int cmis_loopback_read(struct net_device *dev,
+			      struct ethtool_loopback_entry *host,
+			      struct ethtool_loopback_entry *media,
+			      bool *has_host, bool *has_media)
+{
+	const struct ethtool_ops *ops = dev->ethtool_ops;
+	struct ethtool_module_eeprom page = {};
+	u8 ctrl[CMIS_LB_CTRL_LEN];
+	int caps, ret;
+
+	*has_host = false;
+	*has_media = false;
+
+	if (dev->ethtool->module_fw_flash_in_progress)
+		return -EBUSY;
+
+	caps = cmis_loopback_caps(dev);
+	if (caps <= 0)
+		return caps ? caps : -EOPNOTSUPP;
+
+	ethtool_cmis_page_init(&page, CMIS_LB_CTRL_PAGE,
+			       CMIS_LB_CTRL_OFFSET, sizeof(ctrl));
+	page.data = ctrl;
+	ret = ops->get_module_eeprom_by_page(dev, &page, NULL);
+	if (ret < 0)
+		return ret;
+
+	memset(host, 0, sizeof(*host));
+	host->component = ETHTOOL_LOOPBACK_COMPONENT_MODULE;
+	strscpy(host->name, CMIS_LB_NAME_HOST, sizeof(host->name));
+
+	memset(media, 0, sizeof(*media));
+	media->component = ETHTOOL_LOOPBACK_COMPONENT_MODULE;
+	strscpy(media->name, CMIS_LB_NAME_MEDIA, sizeof(media->name));
+
+	if (caps & CMIS_LB_CAP_HOST_INPUT) {
+		*has_host = true;
+		host->supported |= ETHTOOL_LOOPBACK_DIRECTION_LOCAL;
+		if (ctrl[CMIS_LB_CTRL_IDX_HOST_INPUT])
+			host->direction |= ETHTOOL_LOOPBACK_DIRECTION_LOCAL;
+	}
+	if (caps & CMIS_LB_CAP_HOST_OUTPUT) {
+		*has_host = true;
+		host->supported |= ETHTOOL_LOOPBACK_DIRECTION_REMOTE;
+		if (ctrl[CMIS_LB_CTRL_IDX_HOST_OUTPUT])
+			host->direction |= ETHTOOL_LOOPBACK_DIRECTION_REMOTE;
+	}
+	if (caps & CMIS_LB_CAP_MEDIA_INPUT) {
+		*has_media = true;
+		media->supported |= ETHTOOL_LOOPBACK_DIRECTION_LOCAL;
+		if (ctrl[CMIS_LB_CTRL_IDX_MEDIA_INPUT])
+			media->direction |= ETHTOOL_LOOPBACK_DIRECTION_LOCAL;
+	}
+	if (caps & CMIS_LB_CAP_MEDIA_OUTPUT) {
+		*has_media = true;
+		media->supported |= ETHTOOL_LOOPBACK_DIRECTION_REMOTE;
+		if (ctrl[CMIS_LB_CTRL_IDX_MEDIA_OUTPUT])
+			media->direction |= ETHTOOL_LOOPBACK_DIRECTION_REMOTE;
+	}
+
+	return 0;
+}
+
+/**
+ * ethtool_cmis_get_loopback_by_index - Enumerate CMIS loopback entry by index
+ * @dev: Network device with get_module_eeprom_by_page support
+ * @index: Zero-based index of the loopback entry to retrieve
+ * @entry: Output loopback entry
+ *
+ * Used by the dump infrastructure to iterate one entry at a time.
+ *
+ * Return: 0 on success, -EOPNOTSUPP if the index is out of range or
+ *         no CMIS loopback support, negative errno on failure.
+ */
+int ethtool_cmis_get_loopback_by_index(struct net_device *dev, u32 index,
+				       struct ethtool_loopback_entry *entry)
+{
+	struct ethtool_loopback_entry host, media;
+	bool has_host, has_media;
+	u32 cur = 0;
+	int ret;
+
+	ret = cmis_loopback_read(dev, &host, &media, &has_host, &has_media);
+	if (ret)
+		return ret;
+
+	if (has_host) {
+		if (cur == index) {
+			memcpy(entry, &host, sizeof(*entry));
+			return 0;
+		}
+		cur++;
+	}
+
+	if (has_media) {
+		if (cur == index) {
+			memcpy(entry, &media, sizeof(*entry));
+			return 0;
+		}
+	}
+
+	return -EOPNOTSUPP;
+}
+
+/**
+ * ethtool_cmis_get_loopback - Look up CMIS loopback entry by name
+ * @dev: Network device with get_module_eeprom_by_page support
+ * @name: Loopback point name ("cmis-host" or "cmis-media")
+ * @entry: Output loopback entry
+ *
+ * Used by doit requests to look up a specific loopback point.
+ *
+ * Return: 0 on success, -EOPNOTSUPP if name doesn't match or no CMIS
+ *         support, negative errno on failure.
+ */
+int ethtool_cmis_get_loopback(struct net_device *dev,
+			      const char *name,
+			      struct ethtool_loopback_entry *entry)
+{
+	struct ethtool_loopback_entry host, media;
+	bool has_host, has_media;
+	int ret;
+
+	ret = cmis_loopback_read(dev, &host, &media, &has_host, &has_media);
+	if (ret)
+		return ret;
+
+	if (has_host && !strcmp(name, CMIS_LB_NAME_HOST)) {
+		memcpy(entry, &host, sizeof(*entry));
+		return 0;
+	}
+
+	if (has_media && !strcmp(name, CMIS_LB_NAME_MEDIA)) {
+		memcpy(entry, &media, sizeof(*entry));
+		return 0;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+/**
+ * ethtool_cmis_set_loopback - Apply one MODULE loopback entry to CMIS
+ * @dev: Network device with get/set_module_eeprom_by_page support
+ * @entry: Loopback entry to apply (must be MODULE component)
+ * @extack: Netlink extended ack for error reporting
+ *
+ * Matches the entry against CMIS loopback points by name and
+ * direction, then reads, modifies, and writes the corresponding Page
+ * 13h control byte (0xff for all-lanes enable, 0x00 for disable).
+ *
+ * When disabling (direction == 0), all loopback points matching the
+ * name are disabled regardless of their direction. When enabling,
+ * only the specific direction is activated.
+ *
+ * Return: 1 if hardware state changed, 0 if already in requested state,
+ *         negative errno on failure.
+ */
+int ethtool_cmis_set_loopback(struct net_device *dev,
+			      const struct ethtool_loopback_entry *entry,
+			      struct netlink_ext_ack *extack)
+{
+	struct ethtool_module_eeprom page = {};
+	u8 ctrl[CMIS_LB_CTRL_LEN];
+	int local_idx, remote_idx;
+	u8 local_cap, remote_cap;
+	bool mod = false;
+	int caps, ret;
+
+	if (!dev->ethtool_ops->set_module_eeprom_by_page) {
+		NL_SET_ERR_MSG(extack,
+			       "Module EEPROM write access not supported");
+		return -EOPNOTSUPP;
+	}
+
+	if (dev->ethtool->module_fw_flash_in_progress) {
+		NL_SET_ERR_MSG(extack,
+			       "Module firmware flashing is in progress");
+		return -EBUSY;
+	}
+
+	if (dev->flags & IFF_UP) {
+		NL_SET_ERR_MSG(extack,
+			       "Netdevice is up, module loopback change not permitted");
+		return -EBUSY;
+	}
+
+	if (entry->direction && !is_power_of_2(entry->direction)) {
+		NL_SET_ERR_MSG(extack,
+			       "Only one loopback direction may be enabled at a time");
+		return -EINVAL;
+	}
+
+	if (!strcmp(entry->name, CMIS_LB_NAME_HOST)) {
+		local_idx = CMIS_LB_CTRL_IDX_HOST_INPUT;
+		remote_idx = CMIS_LB_CTRL_IDX_HOST_OUTPUT;
+		local_cap = CMIS_LB_CAP_HOST_INPUT;
+		remote_cap = CMIS_LB_CAP_HOST_OUTPUT;
+	} else if (!strcmp(entry->name, CMIS_LB_NAME_MEDIA)) {
+		local_idx = CMIS_LB_CTRL_IDX_MEDIA_INPUT;
+		remote_idx = CMIS_LB_CTRL_IDX_MEDIA_OUTPUT;
+		local_cap = CMIS_LB_CAP_MEDIA_INPUT;
+		remote_cap = CMIS_LB_CAP_MEDIA_OUTPUT;
+	} else {
+		NL_SET_ERR_MSG(extack, "Unknown CMIS loopback name");
+		return -EINVAL;
+	}
+
+	caps = cmis_loopback_caps(dev);
+	if (caps < 0)
+		return caps;
+	if (!caps) {
+		NL_SET_ERR_MSG(extack, "Module does not support CMIS loopback");
+		return -EOPNOTSUPP;
+	}
+
+	/* Read current control bytes */
+	ethtool_cmis_page_init(&page, CMIS_LB_CTRL_PAGE,
+			       CMIS_LB_CTRL_OFFSET, sizeof(ctrl));
+	page.data = ctrl;
+	ret = dev->ethtool_ops->get_module_eeprom_by_page(dev, &page, NULL);
+	if (ret < 0)
+		return ret;
+
+	if (!entry->direction) {
+		/* Disable both directions */
+		if (ctrl[local_idx]) {
+			ctrl[local_idx] = 0x00;
+			mod = true;
+		}
+		if (ctrl[remote_idx]) {
+			ctrl[remote_idx] = 0x00;
+			mod = true;
+		}
+	} else {
+		int enable_idx, disable_idx;
+		u8 enable_cap;
+
+		if (entry->direction & ETHTOOL_LOOPBACK_DIRECTION_LOCAL) {
+			enable_idx = local_idx;
+			enable_cap = local_cap;
+			disable_idx = remote_idx;
+		} else {
+			enable_idx = remote_idx;
+			enable_cap = remote_cap;
+			disable_idx = local_idx;
+		}
+
+		if (!(caps & enable_cap)) {
+			NL_SET_ERR_MSG(extack,
+				       "Loopback mode not supported by module");
+			return -EOPNOTSUPP;
+		}
+
+		/* Disable opposite direction first (mutual exclusivity) */
+		if (ctrl[disable_idx]) {
+			ctrl[disable_idx] = 0x00;
+			ret = dev->ethtool_ops->set_module_eeprom_by_page(dev,
+				&page, extack);
+			if (ret < 0)
+				return ret;
+			mod = true;
+		}
+
+		if (ctrl[enable_idx] != 0xff) {
+			ctrl[enable_idx] = 0xff;
+			mod = true;
+		}
+	}
+
+	if (!mod)
+		return 0;
+
+	ret = dev->ethtool_ops->set_module_eeprom_by_page(dev, &page, extack);
+
+	return ret < 0 ? ret : 1;
+}
diff --git a/net/ethtool/loopback.c b/net/ethtool/loopback.c
index 03b86662dc0f..2d0ad62ce42f 100644
--- a/net/ethtool/loopback.c
+++ b/net/ethtool/loopback.c
@@ -88,6 +88,8 @@ static int loopback_get(struct net_device *dev,
 			struct ethtool_loopback_entry *entry)
 {
 	switch (component) {
+	case ETHTOOL_LOOPBACK_COMPONENT_MODULE:
+		return ethtool_cmis_get_loopback(dev, name, entry);
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -96,7 +98,7 @@ static int loopback_get(struct net_device *dev,
 static int loopback_get_by_index(struct net_device *dev, u32 index,
 				 struct ethtool_loopback_entry *entry)
 {
-	return -EOPNOTSUPP;
+	return ethtool_cmis_get_loopback_by_index(dev, index, entry);
 }
 
 static int loopback_prepare_data(const struct ethnl_req_info *req_base,
@@ -233,6 +235,8 @@ static int __loopback_set(struct net_device *dev,
 			  struct netlink_ext_ack *extack)
 {
 	switch (entry->component) {
+	case ETHTOOL_LOOPBACK_COMPONENT_MODULE:
+		return ethtool_cmis_set_loopback(dev, entry, extack);
 	default:
 		return -EOPNOTSUPP;
 	}
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index 693df12eef63..1017d653673d 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -556,6 +556,14 @@ int ethnl_perphy_dump_one_dev(struct sk_buff *skb,
 			      struct ethnl_dump_ctx *ctx,
 			      unsigned long *pos_sub,
 			      const struct genl_info *info);
+int ethtool_cmis_get_loopback_by_index(struct net_device *dev, u32 index,
+				       struct ethtool_loopback_entry *entry);
+int ethtool_cmis_get_loopback(struct net_device *dev,
+			      const char *name,
+			      struct ethtool_loopback_entry *entry);
+int ethtool_cmis_set_loopback(struct net_device *dev,
+			      const struct ethtool_loopback_entry *entry,
+			      struct netlink_ext_ack *extack);
 
 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];
-- 
2.53.0


  parent reply	other threads:[~2026-03-25 14:51 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-25 14:50 [PATCH net-next v2 00/12] ethtool: Generic loopback support Björn Töpel
2026-03-25 14:50 ` [PATCH net-next v2 01/12] ethtool: Add dump_one_dev callback for per-device sub-iteration Björn Töpel
2026-03-25 18:20   ` Maxime Chevallier
2026-03-25 14:50 ` [PATCH net-next v2 02/12] ethtool: Convert per-PHY commands to dump_one_dev Björn Töpel
2026-03-25 18:21   ` Maxime Chevallier
2026-03-25 14:50 ` [PATCH net-next v2 03/12] ethtool: Add loopback netlink UAPI definitions Björn Töpel
2026-03-26  8:10   ` Maxime Chevallier
2026-03-26  8:55     ` Björn Töpel
2026-03-26 22:22   ` Jakub Kicinski
2026-03-26 22:23   ` Jakub Kicinski
2026-03-27  8:57     ` Maxime Chevallier
2026-03-25 14:50 ` [PATCH net-next v2 04/12] ethtool: Add loopback GET/SET netlink implementation Björn Töpel
2026-03-25 14:50 ` Björn Töpel [this message]
2026-03-25 14:50 ` [PATCH net-next v2 06/12] selftests: drv-net: Add loopback driver test Björn Töpel
2026-03-25 14:50 ` [PATCH net-next v2 07/12] ethtool: Add MAC loopback support via ethtool_ops Björn Töpel
2026-03-26  9:49   ` Breno Leitao
2026-03-25 14:50 ` [PATCH net-next v2 08/12] netdevsim: Add MAC loopback simulation Björn Töpel
2026-03-26  9:40   ` Breno Leitao
2026-03-25 14:50 ` [PATCH net-next v2 09/12] selftests: drv-net: Add MAC loopback netdevsim test Björn Töpel
2026-03-26  9:32   ` Breno Leitao
2026-03-26  9:44     ` Björn Töpel
2026-03-25 14:50 ` [PATCH net-next v2 10/12] MAINTAINERS: Add entry for ethtool loopback Björn Töpel
2026-03-25 14:50 ` [PATCH net-next v2 11/12] netdevsim: Add module EEPROM simulation via debugfs Björn Töpel
2026-03-25 14:50 ` [PATCH net-next v2 12/12] selftests: drv-net: Add CMIS loopback netdevsim test Björn Töpel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260325145022.2607545-6-bjorn@kernel.org \
    --to=bjorn@kernel.org \
    --cc=andrew+netdev@lunn.ch \
    --cc=danieller@nvidia.com \
    --cc=davem@davemloft.net \
    --cc=donald.hunter@gmail.com \
    --cc=edumazet@google.com \
    --cc=hkelam@marvell.com \
    --cc=horms@kernel.org \
    --cc=idosch@nvidia.com \
    --cc=kees@kernel.org \
    --cc=kory.maincent@bootlin.com \
    --cc=kuba@kernel.org \
    --cc=leon@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-rdma@vger.kernel.org \
    --cc=linux@armlinux.org.uk \
    --cc=maxime.chevallier@bootlin.com \
    --cc=michael.chan@broadcom.com \
    --cc=naveenm@marvell.com \
    --cc=netdev@vger.kernel.org \
    --cc=o.rempel@pengutronix.de \
    --cc=pabeni@redhat.com \
    --cc=pavan.chebbi@broadcom.com \
    --cc=piergiorgio.beruto@gmail.com \
    --cc=saeedm@nvidia.com \
    --cc=shuah@kernel.org \
    --cc=tariqt@nvidia.com \
    --cc=willemb@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.