Blame SOURCES/0023-cmis-Request-specific-pages-for-parsing-in-netlink-p.patch

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