Netdev List
 help / color / mirror / Atom feed
From: Danielle Ratson <danieller@nvidia.com>
To: <netdev@vger.kernel.org>
Cc: <mkubecek@suse.cz>, <idosch@nvidia.com>, <petrm@nvidia.com>,
	"Danielle Ratson" <danieller@nvidia.com>
Subject: [PATCH ethtool-next 3/5] module: Add per-type EEPROM page hex dump functions
Date: Thu, 7 May 2026 14:47:19 +0300	[thread overview]
Message-ID: <20260507114721.3409128-4-danieller@nvidia.com> (raw)
In-Reply-To: <20260507114721.3409128-1-danieller@nvidia.com>

Extend sff8079_show_all_nl(), cmis_show_all_nl() and
sff8636_show_all_nl() with a bool dump_pages parameter to support
hex dump output alongside their existing pretty-print output. Each
function first retrieves all the necessary pages and then either
pretty-prints them or performs a hex dump according to the argument.

The hex dump and pretty-print logic is extracted into dedicated static
functions for each parser type:
- cmis_hex_dump() / cmis_pretty_print()
- sff8636_hex_dump() / sff8636_pretty_print()
- sff8079_hex_dump() / sff8079_pretty_print()

Each function dumps the same pages as the corresponding pretty-printer:

- CMIS: uses cmis_memory_map_init_pages() to read the lower memory and
  relevant upper pages across all supported banks, using generic iteration
  over the memory map. Uses module_dump_eeprom_page_hex() for hex output.
- SFF-8636: uses sff8636_memory_map_init_pages() to read the lower memory
  and relevant upper pages, using generic iteration over the memory map.
  Uses module_dump_eeprom_page_hex() for hex output.
- SFF-8079: uses sff8079_get_eeprom_page() to read A0h lower and optional
  A2h lower and identifies each block by its I2C address. Uses dump_hex()
  directly with I2C address headers.

Assisted-by: Claude:claude-sonnet-4.6
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Danielle Ratson <danieller@nvidia.com>
---
 cmis.c                  | 49 +++++++++++++++++++++++++++++++++++------
 cmis.h                  |  2 +-
 internal.h              |  4 ++--
 netlink/module-eeprom.c |  6 ++---
 qsfp.c                  | 48 ++++++++++++++++++++++++++++++++++------
 sfpid.c                 | 43 +++++++++++++++++++++++++++---------
 6 files changed, 122 insertions(+), 30 deletions(-)

diff --git a/cmis.c b/cmis.c
index 996e9eb..29592b2 100644
--- a/cmis.c
+++ b/cmis.c
@@ -1022,6 +1022,43 @@ void cmis_show_all_ioctl(const __u8 *id)
 	cmis_show_all_common(&map);
 }
 
+static void cmis_hex_dump(const struct cmis_memory_map *map)
+{
+	u8 bank, page;
+
+	module_dump_eeprom_page_hex(map->lower_memory, 0, 0x0, 0,
+				    CMIS_PAGE_SIZE);
+	for (bank = 0; bank < CMIS_MAX_BANKS; bank++) {
+		for (page = 0; page < CMIS_MAX_PAGES; page++) {
+			const __u8 *buf = map->upper_memory[bank][page];
+
+			if (!buf)
+				continue;
+
+			/* Upper memory starts at one page size into
+			 * the buffer, since pages are accessed at
+			 * offset between page size and twice the
+			 * page size.
+			 */
+			module_dump_eeprom_page_hex(buf + CMIS_PAGE_SIZE, bank,
+						    page, CMIS_PAGE_SIZE,
+						    CMIS_PAGE_SIZE);
+		}
+	}
+}
+
+static void cmis_pretty_print(struct cmd_context *ctx,
+			      const struct cmis_memory_map *map)
+{
+	new_json_obj(ctx->json);
+	open_json_object(NULL);
+
+	cmis_show_all_common(map);
+
+	close_json_object();
+	delete_json_obj();
+}
+
 static void cmis_request_init(struct ethtool_module_eeprom *request, u8 bank,
 			      u8 page, u32 offset)
 {
@@ -1117,21 +1154,19 @@ cmis_memory_map_init_pages(struct cmd_context *ctx,
 	return 0;
 }
 
-int cmis_show_all_nl(struct cmd_context *ctx)
+int cmis_show_all_nl(struct cmd_context *ctx, bool dump_pages)
 {
 	struct cmis_memory_map map = {};
 	int ret;
 
-	new_json_obj(ctx->json);
-	open_json_object(NULL);
-
 	ret = cmis_memory_map_init_pages(ctx, &map);
 	if (ret < 0)
 		return ret;
-	cmis_show_all_common(&map);
 
-	close_json_object();
-	delete_json_obj();
+	if (dump_pages)
+		cmis_hex_dump(&map);
+	else
+		cmis_pretty_print(ctx, &map);
 
 	return 0;
 }
diff --git a/cmis.h b/cmis.h
index 007632a..82fd245 100644
--- a/cmis.h
+++ b/cmis.h
@@ -201,6 +201,6 @@
 
 void cmis_show_all_ioctl(const __u8 *id);
 
-int cmis_show_all_nl(struct cmd_context *ctx);
+int cmis_show_all_nl(struct cmd_context *ctx, bool dump_pages);
 
 #endif /* CMIS_H__ */
diff --git a/internal.h b/internal.h
index cbf3c09..19fff41 100644
--- a/internal.h
+++ b/internal.h
@@ -381,14 +381,14 @@ int rxclass_rule_del(struct cmd_context *ctx, __u32 loc);
 
 /* Module EEPROM parsing code */
 void sff8079_show_all_ioctl(const __u8 *id);
-int sff8079_show_all_nl(struct cmd_context *ctx);
+int sff8079_show_all_nl(struct cmd_context *ctx, bool dump_pages);
 
 /* Optics diagnostics */
 void sff8472_show_all(const __u8 *id);
 
 /* QSFP Optics diagnostics */
 void sff8636_show_all_ioctl(const __u8 *id, __u32 eeprom_len);
-int sff8636_show_all_nl(struct cmd_context *ctx);
+int sff8636_show_all_nl(struct cmd_context *ctx, bool dump_pages);
 
 /* FUJITSU Extended Socket network device */
 int fjes_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
diff --git a/netlink/module-eeprom.c b/netlink/module-eeprom.c
index ce6a7d9..7e4e6ac 100644
--- a/netlink/module-eeprom.c
+++ b/netlink/module-eeprom.c
@@ -228,18 +228,18 @@ static int eeprom_parse(struct cmd_context *ctx)
 	case MODULE_ID_GBIC:
 	case MODULE_ID_SOLDERED_MODULE:
 	case MODULE_ID_SFP:
-		return sff8079_show_all_nl(ctx);
+		return sff8079_show_all_nl(ctx, false);
 	case MODULE_ID_QSFP:
 	case MODULE_ID_QSFP28:
 	case MODULE_ID_QSFP_PLUS:
-		return sff8636_show_all_nl(ctx);
+		return sff8636_show_all_nl(ctx, false);
 	case MODULE_ID_QSFP_DD:
 	case MODULE_ID_OSFP:
 	case MODULE_ID_DSFP:
 	case MODULE_ID_QSFP_PLUS_CMIS:
 	case MODULE_ID_SFP_DD_CMIS:
 	case MODULE_ID_SFP_PLUS_CMIS:
-		return cmis_show_all_nl(ctx);
+		return cmis_show_all_nl(ctx, false);
 #endif
 	default:
 		/* If we cannot recognize the memory map, default to dumping
diff --git a/qsfp.c b/qsfp.c
index 09d9ace..6e1b9ff 100644
--- a/qsfp.c
+++ b/qsfp.c
@@ -62,9 +62,11 @@
 #include "cmis.h"
 #include "netlink/extapi.h"
 
+#define SFF8636_MAX_PAGES	4
+
 struct sff8636_memory_map {
 	const __u8 *lower_memory;
-	const __u8 *upper_memory[4];
+	const __u8 *upper_memory[SFF8636_MAX_PAGES];
 #define page_00h upper_memory[0x0]
 #define page_03h upper_memory[0x3]
 };
@@ -1078,21 +1080,53 @@ sff8636_memory_map_init_pages(struct cmd_context *ctx,
 	return 0;
 }
 
-int sff8636_show_all_nl(struct cmd_context *ctx)
+static void sff8636_hex_dump(const struct sff8636_memory_map *map)
 {
-	struct sff8636_memory_map map = {};
-	int ret;
+	u8 page;
+
+	module_dump_eeprom_page_hex(map->lower_memory, 0, 0x0, 0,
+				    SFF8636_PAGE_SIZE);
+	for (page = 0; page < SFF8636_MAX_PAGES; page++) {
+		const __u8 *buf = map->upper_memory[page];
+
+		if (!buf)
+			continue;
 
+		/* Upper memory starts at one page size into the
+		 * buffer, since pages are accessed at offset between
+		 * page size and twice the page size.
+		 */
+		module_dump_eeprom_page_hex(buf + SFF8636_PAGE_SIZE, 0,
+					    page, SFF8636_PAGE_SIZE,
+					    SFF8636_PAGE_SIZE);
+	}
+}
+
+static void sff8636_pretty_print(struct cmd_context *ctx,
+				 const struct sff8636_memory_map *map)
+{
 	new_json_obj(ctx->json);
 	open_json_object(NULL);
 
+	sff8636_show_all_common(map);
+
+	close_json_object();
+	delete_json_obj();
+}
+
+int sff8636_show_all_nl(struct cmd_context *ctx, bool dump_pages)
+{
+	struct sff8636_memory_map map = {};
+	int ret;
+
 	ret = sff8636_memory_map_init_pages(ctx, &map);
 	if (ret < 0)
 		return ret;
-	sff8636_show_all_common(&map);
 
-	close_json_object();
-	delete_json_obj();
+	if (dump_pages)
+		sff8636_hex_dump(&map);
+	else
+		sff8636_pretty_print(ctx, &map);
 
 	return 0;
 }
diff --git a/sfpid.c b/sfpid.c
index f753917..73e714e 100644
--- a/sfpid.c
+++ b/sfpid.c
@@ -498,7 +498,35 @@ static int sff8079_get_eeprom_page(struct cmd_context *ctx, u8 i2c_address,
 	return ret;
 }
 
-int sff8079_show_all_nl(struct cmd_context *ctx)
+static void sff8079_hex_dump(const u8 *buf, bool a2h_present)
+{
+	printf("I2C Address: 0x%02x\n\n", SFF8079_I2C_ADDRESS_LOW);
+	dump_hex(stdout, buf, SFF8079_PAGE_SIZE, 0);
+	printf("\n");
+
+	if (a2h_present) {
+		printf("I2C Address: 0x%02x\n\n", SFF8079_I2C_ADDRESS_HIGH);
+		dump_hex(stdout, buf + ETH_MODULE_SFF_8079_LEN,
+			 SFF8079_PAGE_SIZE, 0);
+		printf("\n");
+	}
+}
+
+static void sff8079_pretty_print(struct cmd_context *ctx, const u8 *buf,
+				 bool a2h_present)
+{
+	new_json_obj(ctx->json);
+	open_json_object(NULL);
+	sff8079_show_all_common(buf);
+
+	if (a2h_present)
+		sff8472_show_all(buf);
+
+	close_json_object();
+	delete_json_obj();
+}
+
+int sff8079_show_all_nl(struct cmd_context *ctx, bool dump_pages)
 {
 	bool a2h_present;
 	u8 *buf;
@@ -530,15 +558,10 @@ int sff8079_show_all_nl(struct cmd_context *ctx)
 		}
 	}
 
-	new_json_obj(ctx->json);
-	open_json_object(NULL);
-	sff8079_show_all_common(buf);
-
-	if (a2h_present)
-		sff8472_show_all(buf);
-
-	close_json_object();
-	delete_json_obj();
+	if (dump_pages)
+		sff8079_hex_dump(buf, a2h_present);
+	else
+		sff8079_pretty_print(ctx, buf, a2h_present);
 out:
 	free(buf);
 
-- 
2.51.0


  parent reply	other threads:[~2026-05-07 11:48 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-07 11:47 [PATCH ethtool-next 0/5] ethtool: Add 'pages on|off' option for module EEROM hex dump Danielle Ratson
2026-05-07 11:47 ` [PATCH ethtool-next 1/5] module-common: Add module_dump_eeprom_page_hex() helper Danielle Ratson
2026-05-07 11:47 ` [PATCH ethtool-next 2/5] sfpid: Refactor sff8079_show_all_nl() to separate page retrieval from display Danielle Ratson
2026-05-07 11:47 ` Danielle Ratson [this message]
2026-05-07 11:47 ` [PATCH ethtool-next 4/5] netlink: module-eeprom: Add 'hex on pages on' option for page-organized hex dump Danielle Ratson
2026-05-07 11:47 ` [PATCH ethtool-next 5/5] ethtool: Add man page and bash completion for 'pages on|off' Danielle Ratson
2026-05-07 12:07 ` [PATCH ethtool-next 0/5] ethtool: Add 'pages on|off' option for module EEROM hex dump Michal Kubecek
2026-05-07 12:37   ` Danielle Ratson
2026-05-07 14:32     ` Michal Kubecek
2026-05-07 12:23 ` Andrew Lunn
2026-05-07 17:19   ` Danielle Ratson

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=20260507114721.3409128-4-danieller@nvidia.com \
    --to=danieller@nvidia.com \
    --cc=idosch@nvidia.com \
    --cc=mkubecek@suse.cz \
    --cc=netdev@vger.kernel.org \
    --cc=petrm@nvidia.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox