Blame SOURCES/0024-sff-8636-Request-specific-pages-for-parsing-in-netli.patch

2a1b01
From fdae2732b25090f9d41e192a5dd47a45a6516a94 Mon Sep 17 00:00:00 2001
2a1b01
From: Ido Schimmel <idosch@nvidia.com>
2a1b01
Date: Tue, 12 Oct 2021 16:25:23 +0300
2a1b01
Subject: [PATCH 24/35] sff-8636: 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 pages is
2a1b01
advertised via various bits in the EEPROM contents.
2a1b01
2a1b01
Currently, for SFF-8636, the Lower Memory, Page 00h and the optional
2a1b01
Page 03h are requested by the netlink code (i.e.,
2a1b01
netlink/module-eeprom.c) and passed to the SFF-8636 code (i.e., qsfp.c)
2a1b01
as two arguments for parsing.
2a1b01
2a1b01
This is problematic for several reasons. First, this approach is not
2a1b01
very scaleable as SFF-8636 supports a lot of optional pages. Passing
2a1b01
them as separate arguments to the SFF-8636 code is not going to work.
2a1b01
2a1b01
Second, the knowledge of which optional pages are available is
2a1b01
encapsulated in the SFF-8636 parsing code. As such, the common netlink
2a1b01
code has no business of fetching optional pages that might be invalid.
2a1b01
2a1b01
Instead, pass the command context to the SFF-8636 parsing function and
2a1b01
allow 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
 internal.h              |  3 +--
2a1b01
 netlink/module-eeprom.c |  3 +--
2a1b01
 qsfp.c                  | 60 ++++++++++++++++++++++++++++++++---------
2a1b01
 3 files changed, 49 insertions(+), 17 deletions(-)
2a1b01
2a1b01
diff --git a/internal.h b/internal.h
2a1b01
index a77efd385698..2407d3c223fa 100644
2a1b01
--- a/internal.h
2a1b01
+++ b/internal.h
2a1b01
@@ -392,8 +392,7 @@ void sff8472_show_all(const __u8 *id);
2a1b01
 
2a1b01
 /* QSFP Optics diagnostics */
2a1b01
 void sff8636_show_all_ioctl(const __u8 *id, __u32 eeprom_len);
2a1b01
-void sff8636_show_all_nl(const struct ethtool_module_eeprom *page_zero,
2a1b01
-			 const struct ethtool_module_eeprom *page_three);
2a1b01
+int sff8636_show_all_nl(struct cmd_context *ctx);
2a1b01
 
2a1b01
 /* FUJITSU Extended Socket network device */
2a1b01
 int fjes_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
2a1b01
diff --git a/netlink/module-eeprom.c b/netlink/module-eeprom.c
2a1b01
index a8e2662e0b8c..f04f8e134223 100644
2a1b01
--- a/netlink/module-eeprom.c
2a1b01
+++ b/netlink/module-eeprom.c
2a1b01
@@ -316,7 +316,6 @@ static int decoder_prefetch(struct nl_context *nlctx)
2a1b01
 
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
 	u8 module_id = page_zero->data[SFF8636_ID_OFFSET];
2a1b01
 
2a1b01
@@ -327,7 +326,7 @@ static void decoder_print(struct cmd_context *ctx)
2a1b01
 	case SFF8024_ID_QSFP:
2a1b01
 	case SFF8024_ID_QSFP28:
2a1b01
 	case SFF8024_ID_QSFP_PLUS:
2a1b01
-		sff8636_show_all_nl(page_zero, page_three);
2a1b01
+		sff8636_show_all_nl(ctx);
2a1b01
 		break;
2a1b01
 	case SFF8024_ID_QSFP_DD:
2a1b01
 	case SFF8024_ID_DSFP:
2a1b01
diff --git a/qsfp.c b/qsfp.c
2a1b01
index 4aa49351e6b7..e7c2f51cd9c6 100644
2a1b01
--- a/qsfp.c
2a1b01
+++ b/qsfp.c
2a1b01
@@ -55,10 +55,12 @@
2a1b01
  **/
2a1b01
 #include <stdio.h>
2a1b01
 #include <math.h>
2a1b01
+#include <errno.h>
2a1b01
 #include "internal.h"
2a1b01
 #include "sff-common.h"
2a1b01
 #include "qsfp.h"
2a1b01
 #include "cmis.h"
2a1b01
+#include "netlink/extapi.h"
2a1b01
 
2a1b01
 struct sff8636_memory_map {
2a1b01
 	const __u8 *lower_memory;
2a1b01
@@ -68,6 +70,7 @@ struct sff8636_memory_map {
2a1b01
 };
2a1b01
 
2a1b01
 #define SFF8636_PAGE_SIZE	0x80
2a1b01
+#define SFF8636_I2C_ADDRESS	0x50
2a1b01
 
2a1b01
 #define MAX_DESC_SIZE	42
2a1b01
 
2a1b01
@@ -947,36 +950,67 @@ void sff8636_show_all_ioctl(const __u8 *id, __u32 eeprom_len)
2a1b01
 	sff8636_show_all_common(&map);
2a1b01
 }
2a1b01
 
2a1b01
-static void
2a1b01
-sff8636_memory_map_init_pages(struct sff8636_memory_map *map,
2a1b01
-			      const struct ethtool_module_eeprom *page_zero,
2a1b01
-			      const struct ethtool_module_eeprom *page_three)
2a1b01
+static void sff8636_request_init(struct ethtool_module_eeprom *request, u8 page,
2a1b01
+				 u32 offset)
2a1b01
+{
2a1b01
+	request->offset = offset;
2a1b01
+	request->length = SFF8636_PAGE_SIZE;
2a1b01
+	request->page = page;
2a1b01
+	request->bank = 0;
2a1b01
+	request->i2c_address = SFF8636_I2C_ADDRESS;
2a1b01
+	request->data = NULL;
2a1b01
+}
2a1b01
+
2a1b01
+static int
2a1b01
+sff8636_memory_map_init_pages(struct cmd_context *ctx,
2a1b01
+			      struct sff8636_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
+	sff8636_request_init(&request, 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
+	sff8636_request_init(&request, 0x0, SFF8636_PAGE_SIZE);
2a1b01
+	ret = nl_get_eeprom_page(ctx, &request);
2a1b01
+	if (ret < 0)
2a1b01
+		return ret;
2a1b01
+	map->page_00h = request.data - SFF8636_PAGE_SIZE;
2a1b01
 
2a1b01
 	/* Page 03h is only present when the module memory model is paged and
2a1b01
 	 * not flat.
2a1b01
 	 */
2a1b01
 	if (map->lower_memory[SFF8636_STATUS_2_OFFSET] &
2a1b01
 	    SFF8636_STATUS_PAGE_3_PRESENT)
2a1b01
-		return;
2a1b01
+		return 0;
2a1b01
 
2a1b01
-	map->page_03h = page_three->data - SFF8636_PAGE_SIZE;
2a1b01
+	sff8636_request_init(&request, 0x3, SFF8636_PAGE_SIZE);
2a1b01
+	ret = nl_get_eeprom_page(ctx, &request);
2a1b01
+	if (ret < 0)
2a1b01
+		return ret;
2a1b01
+	map->page_03h = request.data - SFF8636_PAGE_SIZE;
2a1b01
+
2a1b01
+	return 0;
2a1b01
 }
2a1b01
 
2a1b01
-void sff8636_show_all_nl(const struct ethtool_module_eeprom *page_zero,
2a1b01
-			 const struct ethtool_module_eeprom *page_three)
2a1b01
+int sff8636_show_all_nl(struct cmd_context *ctx)
2a1b01
 {
2a1b01
 	struct sff8636_memory_map map = {};
2a1b01
+	int ret;
2a1b01
 
2a1b01
-	sff8636_memory_map_init_pages(&map, page_zero, page_three);
2a1b01
+	ret = sff8636_memory_map_init_pages(ctx, &map);
2a1b01
+	if (ret < 0)
2a1b01
+		return ret;
2a1b01
 	sff8636_show_all_common(&map);
2a1b01
+
2a1b01
+	return 0;
2a1b01
 }
2a1b01
-- 
2a1b01
2.35.1
2a1b01