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