89ea86
From 5f45f370e132f144cdbab9ea718393bd37ee23db Mon Sep 17 00:00:00 2001
89ea86
From: Ido Schimmel <idosch@nvidia.com>
89ea86
Date: Tue, 12 Oct 2021 16:25:22 +0300
89ea86
Subject: [PATCH 23/35] cmis: Request specific pages for parsing in netlink
89ea86
 path
89ea86
89ea86
In the netlink path, unlike the IOCTL path, user space requests specific
89ea86
EEPROM pages from the kernel. The presence of optional and banked pages
89ea86
is advertised via various bits in the EEPROM contents.
89ea86
89ea86
Currently, for CMIS, the Lower Memory, Page 00h and the optional Page
89ea86
01h are requested by the netlink code (i.e., netlink/module-eeprom.c)
89ea86
and passed to the CMIS code (i.e., cmis.c) as two arguments for parsing.
89ea86
89ea86
This is problematic for several reasons. First, this approach is not
89ea86
very scaleable as CMIS supports a lot of optional and banked pages.
89ea86
Passing them as separate arguments to the CMIS code is not going to
89ea86
work.
89ea86
89ea86
Second, the knowledge of which optional and banked pages are available
89ea86
is encapsulated in the CMIS parsing code. As such, the common netlink
89ea86
code has no business of fetching optional and banked pages that might be
89ea86
invalid.
89ea86
89ea86
Instead, pass the command context to the CMIS parsing function and allow
89ea86
it to fetch only valid pages via the 'MODULE_EEPROM_GET' netlink
89ea86
message.
89ea86
89ea86
Tested by making sure that the output of 'ethtool -m' does not change
89ea86
before and after the patch.
89ea86
89ea86
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
89ea86
---
89ea86
 cmis.c                  | 60 ++++++++++++++++++++++++++++++++---------
89ea86
 cmis.h                  |  3 +--
89ea86
 netlink/module-eeprom.c |  7 +++--
89ea86
 3 files changed, 51 insertions(+), 19 deletions(-)
89ea86
89ea86
diff --git a/cmis.c b/cmis.c
89ea86
index eb7791dd59df..4798fd4c7d68 100644
89ea86
--- a/cmis.c
89ea86
+++ b/cmis.c
89ea86
@@ -9,9 +9,11 @@
89ea86
 
89ea86
 #include <stdio.h>
89ea86
 #include <math.h>
89ea86
+#include <errno.h>
89ea86
 #include "internal.h"
89ea86
 #include "sff-common.h"
89ea86
 #include "cmis.h"
89ea86
+#include "netlink/extapi.h"
89ea86
 
89ea86
 struct cmis_memory_map {
89ea86
 	const __u8 *lower_memory;
89ea86
@@ -21,6 +23,7 @@ struct cmis_memory_map {
89ea86
 };
89ea86
 
89ea86
 #define CMIS_PAGE_SIZE		0x80
89ea86
+#define CMIS_I2C_ADDRESS	0x50
89ea86
 
89ea86
 static void cmis_show_identifier(const struct cmis_memory_map *map)
89ea86
 {
89ea86
@@ -384,36 +387,67 @@ void cmis_show_all_ioctl(const __u8 *id)
89ea86
 	cmis_show_all_common(&map);
89ea86
 }
89ea86
 
89ea86
-static void
89ea86
-cmis_memory_map_init_pages(struct cmis_memory_map *map,
89ea86
-			   const struct ethtool_module_eeprom *page_zero,
89ea86
-			   const struct ethtool_module_eeprom *page_one)
89ea86
+static void cmis_request_init(struct ethtool_module_eeprom *request, u8 bank,
89ea86
+			      u8 page, u32 offset)
89ea86
 {
89ea86
+	request->offset = offset;
89ea86
+	request->length = CMIS_PAGE_SIZE;
89ea86
+	request->page = page;
89ea86
+	request->bank = bank;
89ea86
+	request->i2c_address = CMIS_I2C_ADDRESS;
89ea86
+	request->data = NULL;
89ea86
+}
89ea86
+
89ea86
+static int
89ea86
+cmis_memory_map_init_pages(struct cmd_context *ctx,
89ea86
+			   struct cmis_memory_map *map)
89ea86
+{
89ea86
+	struct ethtool_module_eeprom request;
89ea86
+	int ret;
89ea86
+
89ea86
 	/* Lower Memory and Page 00h are always present.
89ea86
 	 *
89ea86
 	 * Offset into Upper Memory is between page size and twice the page
89ea86
 	 * size. Therefore, set the base address of each page to its base
89ea86
-	 * address minus page size. For Page 00h, this is the address of the
89ea86
-	 * Lower Memory.
89ea86
+	 * address minus page size.
89ea86
 	 */
89ea86
-	map->lower_memory = page_zero->data;
89ea86
-	map->page_00h = page_zero->data;
89ea86
+	cmis_request_init(&request, 0, 0x0, 0);
89ea86
+	ret = nl_get_eeprom_page(ctx, &request);
89ea86
+	if (ret < 0)
89ea86
+		return ret;
89ea86
+	map->lower_memory = request.data;
89ea86
+
89ea86
+	cmis_request_init(&request, 0, 0x0, CMIS_PAGE_SIZE);
89ea86
+	ret = nl_get_eeprom_page(ctx, &request);
89ea86
+	if (ret < 0)
89ea86
+		return ret;
89ea86
+	map->page_00h = request.data - CMIS_PAGE_SIZE;
89ea86
 
89ea86
 	/* Page 01h is only present when the module memory model is paged and
89ea86
 	 * not flat.
89ea86
 	 */
89ea86
 	if (map->lower_memory[CMIS_MEMORY_MODEL_OFFSET] &
89ea86
 	    CMIS_MEMORY_MODEL_MASK)
89ea86
-		return;
89ea86
+		return 0;
89ea86
+
89ea86
+	cmis_request_init(&request, 0, 0x1, CMIS_PAGE_SIZE);
89ea86
+	ret = nl_get_eeprom_page(ctx, &request);
89ea86
+	if (ret < 0)
89ea86
+		return ret;
89ea86
+	map->page_01h = request.data - CMIS_PAGE_SIZE;
89ea86
 
89ea86
-	map->page_01h = page_one->data - CMIS_PAGE_SIZE;
89ea86
+	return 0;
89ea86
 }
89ea86
 
89ea86
-void cmis_show_all_nl(const struct ethtool_module_eeprom *page_zero,
89ea86
-		      const struct ethtool_module_eeprom *page_one)
89ea86
+int cmis_show_all_nl(struct cmd_context *ctx)
89ea86
 {
89ea86
 	struct cmis_memory_map map = {};
89ea86
+	int ret;
89ea86
 
89ea86
-	cmis_memory_map_init_pages(&map, page_zero, page_one);
89ea86
+	ret = cmis_memory_map_init_pages(ctx, &map);
89ea86
+	if (ret < 0)
89ea86
+		return ret;
89ea86
 	cmis_show_all_common(&map);
89ea86
+
89ea86
+	return 0;
89ea86
 }
89ea86
diff --git a/cmis.h b/cmis.h
89ea86
index c878e3bc5afd..911491dc5c8f 100644
89ea86
--- a/cmis.h
89ea86
+++ b/cmis.h
89ea86
@@ -123,7 +123,6 @@
89ea86
 
89ea86
 void cmis_show_all_ioctl(const __u8 *id);
89ea86
 
89ea86
-void cmis_show_all_nl(const struct ethtool_module_eeprom *page_zero,
89ea86
-		      const struct ethtool_module_eeprom *page_one);
89ea86
+int cmis_show_all_nl(struct cmd_context *ctx);
89ea86
 
89ea86
 #endif /* CMIS_H__ */
89ea86
diff --git a/netlink/module-eeprom.c b/netlink/module-eeprom.c
89ea86
index ee5508840157..a8e2662e0b8c 100644
89ea86
--- a/netlink/module-eeprom.c
89ea86
+++ b/netlink/module-eeprom.c
89ea86
@@ -314,11 +314,10 @@ static int decoder_prefetch(struct nl_context *nlctx)
89ea86
 	return page_fetch(nlctx, &request);
89ea86
 }
89ea86
 
89ea86
-static void decoder_print(void)
89ea86
+static void decoder_print(struct cmd_context *ctx)
89ea86
 {
89ea86
 	struct ethtool_module_eeprom *page_three = cache_get(3, 0, ETH_I2C_ADDRESS_LOW);
89ea86
 	struct ethtool_module_eeprom *page_zero = cache_get(0, 0, ETH_I2C_ADDRESS_LOW);
89ea86
-	struct ethtool_module_eeprom *page_one = cache_get(1, 0, ETH_I2C_ADDRESS_LOW);
89ea86
 	u8 module_id = page_zero->data[SFF8636_ID_OFFSET];
89ea86
 
89ea86
 	switch (module_id) {
89ea86
@@ -332,7 +331,7 @@ static void decoder_print(void)
89ea86
 		break;
89ea86
 	case SFF8024_ID_QSFP_DD:
89ea86
 	case SFF8024_ID_DSFP:
89ea86
-		cmis_show_all_nl(page_zero, page_one);
89ea86
+		cmis_show_all_nl(ctx);
89ea86
 		break;
89ea86
 	default:
89ea86
 		dump_hex(stdout, page_zero->data, page_zero->length, page_zero->offset);
89ea86
@@ -524,7 +523,7 @@ int nl_getmodule(struct cmd_context *ctx)
89ea86
 		ret = decoder_prefetch(nlctx);
89ea86
 		if (ret)
89ea86
 			goto cleanup;
89ea86
-		decoder_print();
89ea86
+		decoder_print(ctx);
89ea86
 #endif
89ea86
 	}
89ea86
 
89ea86
-- 
89ea86
2.35.1
89ea86