import ethtool-5.13-2.el8

This commit is contained in:
CentOS Sources 2022-11-08 02:04:18 -05:00 committed by Stepan Oksanichenko
parent ab73c57020
commit d1431a3c10
36 changed files with 5062 additions and 1 deletions

View File

@ -0,0 +1,110 @@
From bb89624c1a62de701f87d7deb669e40586c920d2 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 14 Sep 2021 14:27:34 +0300
Subject: [PATCH 01/35] sff-8636: Fix parsing of Page 03h in IOCTL path
The offset of Page 03h compared to the base address of the Lower Memory
is 512 bytes. However, all the offsets to the page start at address 128,
which is the address that separates Lower and Upper memory (see Figure
6-1 in SFF-8636). Therefore, reading these offsets compared to the start
of Page 03h results in incorrect memory accesses as can be seen in the
output below.
Instead, pass Page 03h with the correct offset.
This is a temporary solution until SFF-8636 is refactored to use a
memory map for parsing.
Before patch:
# ethtool -m swp13
...
Laser bias current high alarm threshold : 16.448 mA
Laser bias current low alarm threshold : 16.500 mA
Laser bias current high warning threshold : 16.480 mA
Laser bias current low warning threshold : 61.538 mA
Laser output power high alarm threshold : 1.2576 mW / 1.00 dBm
Laser output power low alarm threshold : 1.0321 mW / 0.14 dBm
Laser output power high warning threshold : 2.1318 mW / 3.29 dBm
Laser output power low warning threshold : 2.0530 mW / 3.12 dBm
Module temperature high alarm threshold : 0.00 degrees C / 32.00 degrees F
Module temperature low alarm threshold : 0.00 degrees C / 32.00 degrees F
Module temperature high warning threshold : 0.00 degrees C / 32.00 degrees F
Module temperature low warning threshold : 0.00 degrees C / 32.00 degrees F
Module voltage high alarm threshold : 0.2377 V
Module voltage low alarm threshold : 2.5701 V
Module voltage high warning threshold : 2.8276 V
Module voltage low warning threshold : 2.6982 V
Laser rx power high alarm threshold : 0.8224 mW / -0.85 dBm
Laser rx power low alarm threshold : 0.8224 mW / -0.85 dBm
Laser rx power high warning threshold : 0.8224 mW / -0.85 dBm
Laser rx power low warning threshold : 0.8224 mW / -0.85 dBm
After patch:
# ethtool -m swp13
...
Laser bias current high alarm threshold : 8.500 mA
Laser bias current low alarm threshold : 5.492 mA
Laser bias current high warning threshold : 8.000 mA
Laser bias current low warning threshold : 6.000 mA
Laser output power high alarm threshold : 3.4673 mW / 5.40 dBm
Laser output power low alarm threshold : 0.0724 mW / -11.40 dBm
Laser output power high warning threshold : 1.7378 mW / 2.40 dBm
Laser output power low warning threshold : 0.1445 mW / -8.40 dBm
Module temperature high alarm threshold : 80.00 degrees C / 176.00 degrees F
Module temperature low alarm threshold : -10.00 degrees C / 14.00 degrees F
Module temperature high warning threshold : 70.00 degrees C / 158.00 degrees F
Module temperature low warning threshold : 0.00 degrees C / 32.00 degrees F
Module voltage high alarm threshold : 3.5000 V
Module voltage low alarm threshold : 3.1000 V
Module voltage high warning threshold : 3.4650 V
Module voltage low warning threshold : 3.1350 V
Laser rx power high alarm threshold : 3.4673 mW / 5.40 dBm
Laser rx power low alarm threshold : 0.0467 mW / -13.31 dBm
Laser rx power high warning threshold : 1.7378 mW / 2.40 dBm
Laser rx power low warning threshold : 0.0933 mW / -10.30 dBm
The following AddressSanitizer report is fixed:
==44670==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x617000000320 at pc 0x00000047ad93 bp 0x7ffcb4dc0070 sp 0x7ffcb4dc0068
READ of size 1 at 0x617000000320 thread T0
#0 0x47ad92 in sff8636_dom_parse qsfp.c:683
#1 0x47c5d6 in sff8636_show_dom qsfp.c:771
#2 0x47d21f in sff8636_show_all qsfp.c:870
#3 0x42130b in do_getmodule ethtool.c:4908
#4 0x42a38a in main ethtool.c:6383
#5 0x7f500bf421e1 in __libc_start_main (/lib64/libc.so.6+0x281e1)
#6 0x40258d in _start (ethtool+0x40258d)
0x617000000320 is located 16 bytes to the right of 656-byte region [0x617000000080,0x617000000310)
allocated by thread T0 here:
#0 0x7f500c2d6527 in __interceptor_calloc (/lib64/libasan.so.6+0xab527)
#1 0x420d8c in do_getmodule ethtool.c:4859
#2 0x42a38a in main ethtool.c:6383
#3 0x7f500bf421e1 in __libc_start_main (/lib64/libc.so.6+0x281e1)
SUMMARY: AddressSanitizer: heap-buffer-overflow qsfp.c:683 in sff8636_dom_parse
Fixes: fc47fdb7c364 ("ethtool: Refactor human-readable module EEPROM output for new API")
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
qsfp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/qsfp.c b/qsfp.c
index 644fe148a5aa..e84226bc1554 100644
--- a/qsfp.c
+++ b/qsfp.c
@@ -867,7 +867,7 @@ void sff8636_show_all(const __u8 *id, __u32 eeprom_len)
(id[SFF8636_ID_OFFSET] == SFF8024_ID_QSFP_PLUS) ||
(id[SFF8636_ID_OFFSET] == SFF8024_ID_QSFP28)) {
sff6836_show_page_zero(id);
- sff8636_show_dom(id, id + SFF8636_PAGE03H_OFFSET, eeprom_len);
+ sff8636_show_dom(id, id + 3 * 0x80, eeprom_len);
}
}
--
2.35.1

View File

@ -0,0 +1,55 @@
From 1c14a6d8ebad07bc6ff090164ca15ab7656e7167 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 14 Sep 2021 14:27:35 +0300
Subject: [PATCH 02/35] cmis: Fix invalid memory access in IOCTL path
Page 01h is an optional page that is not available for flat memory
modules. Trying to blindly access it results in the following report
from AddressSanitizer [1].
Instead, pass the base address of the Lower Memory. This results in
wrong information being parsed, but this never worked correctly since
CMIS support first appeared in cited commit.
The information will be parsed correctly in a follow-up submission that
reworks the EEPROM parsing code to use a memory map with pointers to
individual pages instead of passing one large buffer.
[1]
==968785==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6120000001d4 at pc 0x0000004806ee bp 0x7ffefbc977a0 sp 0x7ffefbc97798
READ of size 1 at 0x6120000001d4 thread T0
#0 0x4806ed in cmis_print_smf_cbl_len cmis.c:127
#1 0x48113e in cmis_show_link_len_from_page cmis.c:279
#2 0x4811e3 in cmis_show_link_len cmis.c:300
#3 0x481358 in qsfp_dd_show_all cmis.c:336
#4 0x47d190 in sff8636_show_all qsfp.c:861
#5 0x42130b in do_getmodule ethtool.c:4908
#6 0x42a38a in main ethtool.c:6383
#7 0x7f11db6c51e1 in __libc_start_main (/lib64/libc.so.6+0x281e1)
#8 0x40258d in _start (ethtool+0x40258d)
Address 0x6120000001d4 is a wild pointer.
SUMMARY: AddressSanitizer: heap-buffer-overflow cmis.c:127 in cmis_print_smf_cbl_len
Fixes: 88ca347ef35a ("Add QSFP-DD support").
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
cmis.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cmis.c b/cmis.c
index 361b721f332f..1a91e798e4b8 100644
--- a/cmis.c
+++ b/cmis.c
@@ -297,7 +297,7 @@ static void cmis_show_link_len_from_page(const __u8 *page_one_data)
*/
static void cmis_show_link_len(const __u8 *id)
{
- cmis_show_link_len_from_page(id + PAG01H_UPPER_OFFSET);
+ cmis_show_link_len_from_page(id);
}
/**
--
2.35.1

View File

@ -0,0 +1,87 @@
From 04d36d7c373db7069554a6d21ece628e2cf6b21c Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 14 Sep 2021 14:27:36 +0300
Subject: [PATCH 03/35] netlink: eeprom: Fallback to IOCTL when a complete
hex/raw dump is requested
The IOCTL backend provides a complete hex/raw dump of the module EEPROM
contents:
# ethtool -m swp11 hex on | wc -l
34
# ethtool -m swp11 raw on | wc -c
512
With the netlink backend, only the first 128 bytes from I2C address 0x50
are dumped:
# ethtool -m swp11 hex on | wc -l
10
# ethtool -m swp11 raw on | wc -c
128
The presence of optional / banked pages is unknown without parsing the
EEPROM contents which is unavailable when pretty printing is disabled
(i.e., configure --disable-pretty-dump). With the IOCTL backend, this
parsing happens inside the kernel.
Therefore, when a complete hex/raw dump is requested, fallback to the
IOCTL backend.
After the patch:
# ethtool -m swp11 hex on | wc -l
34
# ethtool -m swp11 raw on | wc -c
512
This avoids breaking users that are relying on current behavior.
If users want a hex/raw dump of optional/banked pages that are not
returned with the IOCTL backend, they will be required to request these
explicitly via the netlink backend. For example:
# ethtool -m swp11 hex on page 0x2
This is desirable as that way there is no ambiguity regarding the
location of optional/banked pages in the dump.
Another way to implement the above would be to use the 'nlchk' callback
added in commit 67a9ef551661 ("ethtool: add nlchk for redirecting to
netlink"). However, it is called before the netlink instance is
initialized and before the command line parameters are parsed via
nl_parser().
Fixes: 25b64c66f58d ("ethtool: Add netlink handler for getmodule (-m)")
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
netlink/module-eeprom.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/netlink/module-eeprom.c b/netlink/module-eeprom.c
index 38e7d2cd6cf3..e9a122df3259 100644
--- a/netlink/module-eeprom.c
+++ b/netlink/module-eeprom.c
@@ -365,6 +365,16 @@ int nl_getmodule(struct cmd_context *ctx)
return -EINVAL;
}
+ /* When complete hex/raw dump of the EEPROM is requested, fallback to
+ * ioctl. Netlink can only request specific pages.
+ */
+ if ((getmodule_cmd_params.dump_hex || getmodule_cmd_params.dump_raw) &&
+ !getmodule_cmd_params.page && !getmodule_cmd_params.bank &&
+ !getmodule_cmd_params.i2c_address) {
+ nlctx->ioctl_fallback = true;
+ return -EOPNOTSUPP;
+ }
+
request.i2c_address = ETH_I2C_ADDRESS_LOW;
request.length = 128;
ret = page_fetch(nlctx, &request);
--
2.35.1

View File

@ -0,0 +1,84 @@
From 3960c91ade7b1ca9979eec5200a90dc11f339cfd Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 14 Sep 2021 14:27:37 +0300
Subject: [PATCH 04/35] ethtool: Fix compilation warning when pretty dump is
disabled
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
When pretty dump is disabled (i.e., configure --disable-pretty-dump),
gcc 11.2.1 emits the following warning:
ethtool.c: In function dump_regs:
ethtool.c:1160:31: warning: comparison is always false due to limited range of data type [-Wtype-limits]
1160 | for (i = 0; i < ARRAY_SIZE(driver_list); i++)
| ^
Fix it by avoiding iterating over 'driver_list' when pretty dump is
disabled.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
ethtool.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/ethtool.c b/ethtool.c
index 33a0a492cb15..1b79e9f8d958 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -1089,12 +1089,12 @@ static int parse_hkey(char **rss_hkey, u32 key_size,
return 0;
}
+#ifdef ETHTOOL_ENABLE_PRETTY_DUMP
static const struct {
const char *name;
int (*func)(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
} driver_list[] = {
-#ifdef ETHTOOL_ENABLE_PRETTY_DUMP
{ "8139cp", realtek_dump_regs },
{ "8139too", realtek_dump_regs },
{ "r8169", realtek_dump_regs },
@@ -1129,8 +1129,8 @@ static const struct {
{ "fec", fec_dump_regs },
{ "igc", igc_dump_regs },
{ "bnxt_en", bnxt_dump_regs },
-#endif
};
+#endif
void dump_hex(FILE *file, const u8 *data, int len, int offset)
{
@@ -1149,14 +1149,15 @@ void dump_hex(FILE *file, const u8 *data, int len, int offset)
static int dump_regs(int gregs_dump_raw, int gregs_dump_hex,
struct ethtool_drvinfo *info, struct ethtool_regs *regs)
{
- unsigned int i;
-
if (gregs_dump_raw) {
fwrite(regs->data, regs->len, 1, stdout);
goto nested;
}
- if (!gregs_dump_hex)
+#ifdef ETHTOOL_ENABLE_PRETTY_DUMP
+ if (!gregs_dump_hex) {
+ unsigned int i;
+
for (i = 0; i < ARRAY_SIZE(driver_list); i++)
if (!strncmp(driver_list[i].name, info->driver,
ETHTOOL_BUSINFO_LEN)) {
@@ -1168,6 +1169,8 @@ static int dump_regs(int gregs_dump_raw, int gregs_dump_hex,
*/
break;
}
+ }
+#endif
dump_hex(stdout, regs->data, regs->len, 0);
--
2.35.1

View File

@ -0,0 +1,62 @@
From 08d9f72f5e4ce12e2cc1fc47d1ffde9aa1326c8c Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 14 Sep 2021 14:27:38 +0300
Subject: [PATCH 05/35] netlink: eeprom: Fix compilation when pretty dump is
disabled
When pretty dump is disabled (i.e., configure --disable-pretty-dump),
the following errors are emitted:
/usr/bin/ld: netlink/module-eeprom.o: in function `decoder_print':
netlink/module-eeprom.c:330: undefined reference to `sff8636_show_all_paged'
netlink/module-eeprom.c:334: undefined reference to `cmis_show_all'
netlink/module-eeprom.c:325: undefined reference to `sff8079_show_all'
The else clause is unreachable when pretty dump is disabled, so wrap it
with ifdef directive.
This will be re-worked in future patches where the netlink code only
queries the SFF-8024 Identifier Value and defers page requests to
individual parsers.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
netlink/module-eeprom.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/netlink/module-eeprom.c b/netlink/module-eeprom.c
index e9a122df3259..48cd2cc55bee 100644
--- a/netlink/module-eeprom.c
+++ b/netlink/module-eeprom.c
@@ -275,6 +275,7 @@ static int page_fetch(struct nl_context *nlctx, const struct ethtool_module_eepr
return nlsock_process_reply(nlsock, nomsg_reply_cb, NULL);
}
+#ifdef ETHTOOL_ENABLE_PRETTY_DUMP
static int decoder_prefetch(struct nl_context *nlctx)
{
struct ethtool_module_eeprom *page_zero_lower = cache_get(0, 0, ETH_I2C_ADDRESS_LOW);
@@ -338,6 +339,7 @@ static void decoder_print(void)
break;
}
}
+#endif
int nl_getmodule(struct cmd_context *ctx)
{
@@ -414,10 +416,12 @@ int nl_getmodule(struct cmd_context *ctx)
else
dump_hex(stdout, eeprom_data, dump_length, request.offset);
} else {
+#ifdef ETHTOOL_ENABLE_PRETTY_DUMP
ret = decoder_prefetch(nlctx);
if (ret)
goto cleanup;
decoder_print();
+#endif
}
cleanup:
--
2.35.1

View File

@ -0,0 +1,66 @@
From 5b46ca06c9888c663a74bdd804b0ecb7199cfb62 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Fri, 1 Oct 2021 18:06:21 +0300
Subject: [PATCH 06/35] cmis: Fix CLEI code parsing
In CMIS, unlike SFF-8636, there is no presence indication for the CLEI
code (Common Language Equipment Identification) field. The field is
always present, but might not be supported. In which case, "a value of
all ASCII 20h (spaces) shall be entered".
Therefore, remove the erroneous check which seems to be influenced from
SFF-8636 and only print the string if it is supported and has a non-zero
length.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
cmis.c | 8 +++++---
cmis.h | 4 ++--
2 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/cmis.c b/cmis.c
index 1a91e798e4b8..499355d0e024 100644
--- a/cmis.c
+++ b/cmis.c
@@ -307,6 +307,8 @@ static void cmis_show_link_len(const __u8 *id)
*/
static void cmis_show_vendor_info(const __u8 *id)
{
+ const char *clei = (const char *)(id + CMIS_CLEI_START_OFFSET);
+
sff_show_ascii(id, CMIS_VENDOR_NAME_START_OFFSET,
CMIS_VENDOR_NAME_END_OFFSET, "Vendor name");
cmis_show_oui(id);
@@ -319,9 +321,9 @@ static void cmis_show_vendor_info(const __u8 *id)
sff_show_ascii(id, CMIS_DATE_YEAR_OFFSET,
CMIS_DATE_VENDOR_LOT_OFFSET + 1, "Date code");
- if (id[CMIS_CLEI_PRESENT_BYTE] & CMIS_CLEI_PRESENT_MASK)
- sff_show_ascii(id, CMIS_CLEI_START_OFFSET,
- CMIS_CLEI_END_OFFSET, "CLEI code");
+ if (*clei && strncmp(clei, CMIS_CLEI_BLANK, CMIS_CLEI_LEN))
+ sff_show_ascii(id, CMIS_CLEI_START_OFFSET, CMIS_CLEI_END_OFFSET,
+ "CLEI code");
}
void qsfp_dd_show_all(const __u8 *id)
diff --git a/cmis.h b/cmis.h
index 78ee1495bc33..cfac08f42904 100644
--- a/cmis.h
+++ b/cmis.h
@@ -34,10 +34,10 @@
#define CMIS_DATE_VENDOR_LOT_OFFSET 0xBC
/* CLEI Code (Page 0) */
-#define CMIS_CLEI_PRESENT_BYTE 0x02
-#define CMIS_CLEI_PRESENT_MASK 0x20
#define CMIS_CLEI_START_OFFSET 0xBE
#define CMIS_CLEI_END_OFFSET 0xC7
+#define CMIS_CLEI_BLANK " "
+#define CMIS_CLEI_LEN 0x0A
/* Cable assembly length */
#define CMIS_CBL_ASM_LEN_OFFSET 0xCA
--
2.35.1

View File

@ -0,0 +1,42 @@
From a934091a0b42cd7c71c9e71a235e57af718c9952 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Fri, 1 Oct 2021 18:06:22 +0300
Subject: [PATCH 07/35] cmis: Fix wrong define name
Offset 0x10 in the Lower Memory stores the "VccMonVoltage".
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
cmis.c | 2 +-
cmis.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/cmis.c b/cmis.c
index 499355d0e024..408db6f26c3b 100644
--- a/cmis.c
+++ b/cmis.c
@@ -271,7 +271,7 @@ static void cmis_show_mod_lvl_monitors(const __u8 *id)
PRINT_TEMP("Module temperature",
OFFSET_TO_TEMP(CMIS_CURR_TEMP_OFFSET));
PRINT_VCC("Module voltage",
- OFFSET_TO_U16(CMIS_CURR_CURR_OFFSET));
+ OFFSET_TO_U16(CMIS_CURR_VCC_OFFSET));
}
static void cmis_show_link_len_from_page(const __u8 *page_one_data)
diff --git a/cmis.h b/cmis.h
index cfac08f42904..e3012ccfdd79 100644
--- a/cmis.h
+++ b/cmis.h
@@ -11,7 +11,7 @@
/* Module-Level Monitors (Page 0) */
#define CMIS_CURR_TEMP_OFFSET 0x0E
-#define CMIS_CURR_CURR_OFFSET 0x10
+#define CMIS_CURR_VCC_OFFSET 0x10
#define CMIS_CTOR_OFFSET 0xCB
--
2.35.1

View File

@ -0,0 +1,29 @@
From 030ba06f12761d13722a12773bb8063748242b50 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Fri, 1 Oct 2021 18:06:23 +0300
Subject: [PATCH 08/35] cmis: Correct comment
The file is concerned with CMIS support, not QSFP-DD which is the
physical form factor.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
cmis.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cmis.c b/cmis.c
index 408db6f26c3b..591cc72953b7 100644
--- a/cmis.c
+++ b/cmis.c
@@ -1,7 +1,7 @@
/**
* Description:
*
- * This module adds QSFP-DD support to ethtool. The changes are similar to
+ * This module adds CMIS support to ethtool. The changes are similar to
* the ones already existing in qsfp.c, but customized to use the memory
* addresses and logic as defined in the specification's document.
*
--
2.35.1

View File

@ -0,0 +1,30 @@
From f1b4bafbb30e77fedb10a23d1b70119b9059f684 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Fri, 1 Oct 2021 18:06:24 +0300
Subject: [PATCH 09/35] sff-8636: Remove incorrect comment
The comment was copied from SFF-8472 (i.e., sfpdiag.c) where the
diagnostic page is at I2C address 0x51. SFF-8636 only uses I2C address
0x50.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
qsfp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/qsfp.c b/qsfp.c
index e84226bc1554..263cf188377d 100644
--- a/qsfp.c
+++ b/qsfp.c
@@ -64,7 +64,7 @@
static struct sff8636_aw_flags {
const char *str; /* Human-readable string, null at the end */
- int offset; /* A2-relative address offset */
+ int offset;
__u8 value; /* Alarm is on if (offset & value) != 0. */
} sff8636_aw_flags[] = {
{ "Laser bias current high alarm (Chan 1)",
--
2.35.1

View File

@ -0,0 +1,48 @@
From dc4a75242e8674da02a579e6c875ad4ac77a8c20 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Fri, 1 Oct 2021 18:06:25 +0300
Subject: [PATCH 10/35] sff-8636: Fix incorrect function name
The specification is called SFF-8636, not SFF-6836.
Rename the function accordingly.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
qsfp.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/qsfp.c b/qsfp.c
index 263cf188377d..3401db84352d 100644
--- a/qsfp.c
+++ b/qsfp.c
@@ -820,7 +820,7 @@ static void sff8636_show_dom(const __u8 *id, const __u8 *page_three, __u32 eepro
}
-static void sff6836_show_page_zero(const __u8 *id)
+static void sff8636_show_page_zero(const __u8 *id)
{
sff8636_show_ext_identifier(id);
sff8636_show_connector(id);
@@ -866,7 +866,7 @@ void sff8636_show_all(const __u8 *id, __u32 eeprom_len)
if ((id[SFF8636_ID_OFFSET] == SFF8024_ID_QSFP) ||
(id[SFF8636_ID_OFFSET] == SFF8024_ID_QSFP_PLUS) ||
(id[SFF8636_ID_OFFSET] == SFF8024_ID_QSFP28)) {
- sff6836_show_page_zero(id);
+ sff8636_show_page_zero(id);
sff8636_show_dom(id, id + 3 * 0x80, eeprom_len);
}
}
@@ -875,7 +875,7 @@ void sff8636_show_all_paged(const struct ethtool_module_eeprom *page_zero,
const struct ethtool_module_eeprom *page_three)
{
sff8636_show_identifier(page_zero->data);
- sff6836_show_page_zero(page_zero->data);
+ sff8636_show_page_zero(page_zero->data);
if (page_three)
sff8636_show_dom(page_zero->data, page_three->data - 0x80,
ETH_MODULE_SFF_8636_MAX_LEN);
--
2.35.1

View File

@ -0,0 +1,37 @@
From 9d6316a62b6ab24dfd3cb800841df7fbbdc648ae Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Fri, 1 Oct 2021 18:06:26 +0300
Subject: [PATCH 11/35] sff-8636: Convert if statement to switch-case
The indentation is wrong and the statement can be more clearly
represented using a switch-case statement. Convert it.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
qsfp.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/qsfp.c b/qsfp.c
index 3401db84352d..d1464cb50fdc 100644
--- a/qsfp.c
+++ b/qsfp.c
@@ -863,11 +863,13 @@ void sff8636_show_all(const __u8 *id, __u32 eeprom_len)
}
sff8636_show_identifier(id);
- if ((id[SFF8636_ID_OFFSET] == SFF8024_ID_QSFP) ||
- (id[SFF8636_ID_OFFSET] == SFF8024_ID_QSFP_PLUS) ||
- (id[SFF8636_ID_OFFSET] == SFF8024_ID_QSFP28)) {
+ switch (id[SFF8636_ID_OFFSET]) {
+ case SFF8024_ID_QSFP:
+ case SFF8024_ID_QSFP_PLUS:
+ case SFF8024_ID_QSFP28:
sff8636_show_page_zero(id);
sff8636_show_dom(id, id + 3 * 0x80, eeprom_len);
+ break;
}
}
--
2.35.1

View File

@ -0,0 +1,35 @@
From 539a255fab8401a197e2a98c0c3dd39800ca65e5 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Fri, 1 Oct 2021 18:06:27 +0300
Subject: [PATCH 12/35] sff-8636: Remove extra blank lines
Not needed, so remove them.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
qsfp.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/qsfp.c b/qsfp.c
index d1464cb50fdc..3f37f1036e96 100644
--- a/qsfp.c
+++ b/qsfp.c
@@ -738,7 +738,6 @@ static void sff8636_dom_parse(const __u8 *id, const __u8 *page_three, struct sff
sd->scd[i].rx_power = OFFSET_TO_U16(rx_power_offset);
sd->scd[i].tx_power = OFFSET_TO_U16(tx_power_offset);
}
-
}
static void sff8636_show_dom(const __u8 *id, const __u8 *page_three, __u32 eeprom_len)
@@ -819,7 +818,6 @@ static void sff8636_show_dom(const __u8 *id, const __u8 *page_three, __u32 eepro
}
}
-
static void sff8636_show_page_zero(const __u8 *id)
{
sff8636_show_ext_identifier(id);
--
2.35.1

View File

@ -0,0 +1,95 @@
From 56c6dc7ab5f9170c6d399c12a87bbdb4c8de8958 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:12 +0300
Subject: [PATCH 13/35] cmis: Rename CMIS parsing functions
Currently, there are two CMIS parsing functions. qsfp_dd_show_all() and
cmis_show_all(). The former is called from the IOCTL path with a buffer
containing EEPROM contents and the latter is called from the netlink
path with pointer to individual EEPROM pages.
Rename them with '_ioctl' and '_nl' suffixes to make the distinction
clear.
In subsequent patches, these two functions will only differ in the way
they initialize the CMIS memory map for parsing, while the parsing code
itself will be shared between the two.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
cmis.c | 6 +++---
cmis.h | 6 +++---
netlink/module-eeprom.c | 2 +-
qsfp.c | 2 +-
4 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/cmis.c b/cmis.c
index 591cc72953b7..68c5b2d3277b 100644
--- a/cmis.c
+++ b/cmis.c
@@ -326,7 +326,7 @@ static void cmis_show_vendor_info(const __u8 *id)
"CLEI code");
}
-void qsfp_dd_show_all(const __u8 *id)
+void cmis_show_all_ioctl(const __u8 *id)
{
cmis_show_identifier(id);
cmis_show_power_info(id);
@@ -340,8 +340,8 @@ void qsfp_dd_show_all(const __u8 *id)
cmis_show_rev_compliance(id);
}
-void cmis_show_all(const struct ethtool_module_eeprom *page_zero,
- const struct ethtool_module_eeprom *page_one)
+void cmis_show_all_nl(const struct ethtool_module_eeprom *page_zero,
+ const struct ethtool_module_eeprom *page_one)
{
const __u8 *page_zero_data = page_zero->data;
diff --git a/cmis.h b/cmis.h
index e3012ccfdd79..734b90f4ddb4 100644
--- a/cmis.h
+++ b/cmis.h
@@ -120,9 +120,9 @@
#define YESNO(x) (((x) != 0) ? "Yes" : "No")
#define ONOFF(x) (((x) != 0) ? "On" : "Off")
-void qsfp_dd_show_all(const __u8 *id);
+void cmis_show_all_ioctl(const __u8 *id);
-void cmis_show_all(const struct ethtool_module_eeprom *page_zero,
- const struct ethtool_module_eeprom *page_one);
+void cmis_show_all_nl(const struct ethtool_module_eeprom *page_zero,
+ const struct ethtool_module_eeprom *page_one);
#endif /* CMIS_H__ */
diff --git a/netlink/module-eeprom.c b/netlink/module-eeprom.c
index 48cd2cc55bee..fc4ef1a53aff 100644
--- a/netlink/module-eeprom.c
+++ b/netlink/module-eeprom.c
@@ -332,7 +332,7 @@ static void decoder_print(void)
break;
case SFF8024_ID_QSFP_DD:
case SFF8024_ID_DSFP:
- cmis_show_all(page_zero, page_one);
+ cmis_show_all_nl(page_zero, page_one);
break;
default:
dump_hex(stdout, page_zero->data, page_zero->length, page_zero->offset);
diff --git a/qsfp.c b/qsfp.c
index 3f37f1036e96..27fdd3bd1771 100644
--- a/qsfp.c
+++ b/qsfp.c
@@ -856,7 +856,7 @@ static void sff8636_show_page_zero(const __u8 *id)
void sff8636_show_all(const __u8 *id, __u32 eeprom_len)
{
if (id[SFF8636_ID_OFFSET] == SFF8024_ID_QSFP_DD) {
- qsfp_dd_show_all(id);
+ cmis_show_all_ioctl(id);
return;
}
--
2.35.1

View File

@ -0,0 +1,145 @@
From 912115ebf8ca6eb76dfdadbe8881b7c348743f27 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:13 +0300
Subject: [PATCH 14/35] cmis: Initialize CMIS memory map
The CMIS memory map [1] consists of Lower Memory and Upper Memory.
The content of the Lower Memory is fixed and can be addressed using an
offset between 0 and 127 (inclusive).
The Upper Memory is variable and optional and can be addressed by
specifying a bank number, a page number and an offset between 128 and
255 (inclusive).
Create a structure describing this memory map and initialize it with
pointers to available pages.
In the IOCTL path, the structure holds pointers to regions of the
continuous buffer passed to user space via the 'ETHTOOL_GMODULEEEPROM'
command.
In the netlink path, the structure holds pointers to individual pages
passed to user space via the 'MODULE_EEPROM_GET' message.
This structure will later allow us to consolidate the IOCTL and netlink
parsing code paths and also easily support additional EEPROM pages.
[1] CMIS Rev. 5, pag. 97, section 8.1.1, Figure 8-1
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
cmis.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cmis.h | 2 ++
2 files changed, 65 insertions(+)
diff --git a/cmis.c b/cmis.c
index 68c5b2d3277b..8a6788416a00 100644
--- a/cmis.c
+++ b/cmis.c
@@ -13,6 +13,15 @@
#include "sff-common.h"
#include "cmis.h"
+struct cmis_memory_map {
+ const __u8 *lower_memory;
+ const __u8 *upper_memory[1][2]; /* Bank, Page */
+#define page_00h upper_memory[0x0][0x0]
+#define page_01h upper_memory[0x0][0x1]
+};
+
+#define CMIS_PAGE_SIZE 0x80
+
static void cmis_show_identifier(const __u8 *id)
{
sff8024_show_identifier(id, CMIS_ID_OFFSET);
@@ -326,8 +335,34 @@ static void cmis_show_vendor_info(const __u8 *id)
"CLEI code");
}
+static void cmis_memory_map_init_buf(struct cmis_memory_map *map,
+ const __u8 *id)
+{
+ /* Lower Memory and Page 00h are always present.
+ *
+ * Offset into Upper Memory is between page size and twice the page
+ * size. Therefore, set the base address of each page to base address
+ * plus page size multiplied by the page number.
+ */
+ map->lower_memory = id;
+ map->page_00h = id;
+
+ /* Page 01h is only present when the module memory model is paged and
+ * not flat.
+ */
+ if (map->lower_memory[CMIS_MEMORY_MODEL_OFFSET] &
+ CMIS_MEMORY_MODEL_MASK)
+ return;
+
+ map->page_01h = id + CMIS_PAGE_SIZE;
+}
+
void cmis_show_all_ioctl(const __u8 *id)
{
+ struct cmis_memory_map map = {};
+
+ cmis_memory_map_init_buf(&map, id);
+
cmis_show_identifier(id);
cmis_show_power_info(id);
cmis_show_connector(id);
@@ -340,10 +375,38 @@ void cmis_show_all_ioctl(const __u8 *id)
cmis_show_rev_compliance(id);
}
+static void
+cmis_memory_map_init_pages(struct cmis_memory_map *map,
+ const struct ethtool_module_eeprom *page_zero,
+ const struct ethtool_module_eeprom *page_one)
+{
+ /* Lower Memory and Page 00h are always present.
+ *
+ * Offset into Upper Memory is between page size and twice the page
+ * size. Therefore, set the base address of each page to its base
+ * address minus page size. For Page 00h, this is the address of the
+ * Lower Memory.
+ */
+ map->lower_memory = page_zero->data;
+ map->page_00h = page_zero->data;
+
+ /* Page 01h is only present when the module memory model is paged and
+ * not flat.
+ */
+ if (map->lower_memory[CMIS_MEMORY_MODEL_OFFSET] &
+ CMIS_MEMORY_MODEL_MASK)
+ return;
+
+ map->page_01h = page_one->data - CMIS_PAGE_SIZE;
+}
+
void cmis_show_all_nl(const struct ethtool_module_eeprom *page_zero,
const struct ethtool_module_eeprom *page_one)
{
const __u8 *page_zero_data = page_zero->data;
+ struct cmis_memory_map map = {};
+
+ cmis_memory_map_init_pages(&map, page_zero, page_one);
cmis_show_identifier(page_zero_data);
cmis_show_power_info(page_zero_data);
diff --git a/cmis.h b/cmis.h
index 734b90f4ddb4..53cbb5f57127 100644
--- a/cmis.h
+++ b/cmis.h
@@ -4,6 +4,8 @@
/* Identifier and revision compliance (Page 0) */
#define CMIS_ID_OFFSET 0x00
#define CMIS_REV_COMPLIANCE_OFFSET 0x01
+#define CMIS_MEMORY_MODEL_OFFSET 0x02
+#define CMIS_MEMORY_MODEL_MASK 0x80
#define CMIS_MODULE_TYPE_OFFSET 0x55
#define CMIS_MT_MMF 0x01
--
2.35.1

View File

@ -0,0 +1,394 @@
From 6e6aed12948d2d191660252a4be9bb33dc283bed Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:14 +0300
Subject: [PATCH 15/35] cmis: Use memory map during parsing
Instead of passing one large buffer to the individual parsing functions,
use the memory map structure from the previous patch.
This has the added benefit of checking which optional pages are actually
available and it will also allow us to consolidate the IOCTL and netlink
parsing code paths.
Tested by making sure that the only differences in output in both the
IOCTL and netlink paths before and after the patch are in a few
registers in Page 01h that were previously parsed from Page 00h.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
cmis.c | 175 +++++++++++++++++++++++++++++----------------------------
cmis.h | 1 -
2 files changed, 88 insertions(+), 88 deletions(-)
diff --git a/cmis.c b/cmis.c
index 8a6788416a00..2e01446b2315 100644
--- a/cmis.c
+++ b/cmis.c
@@ -22,19 +22,19 @@ struct cmis_memory_map {
#define CMIS_PAGE_SIZE 0x80
-static void cmis_show_identifier(const __u8 *id)
+static void cmis_show_identifier(const struct cmis_memory_map *map)
{
- sff8024_show_identifier(id, CMIS_ID_OFFSET);
+ sff8024_show_identifier(map->lower_memory, CMIS_ID_OFFSET);
}
-static void cmis_show_connector(const __u8 *id)
+static void cmis_show_connector(const struct cmis_memory_map *map)
{
- sff8024_show_connector(id, CMIS_CTOR_OFFSET);
+ sff8024_show_connector(map->page_00h, CMIS_CTOR_OFFSET);
}
-static void cmis_show_oui(const __u8 *id)
+static void cmis_show_oui(const struct cmis_memory_map *map)
{
- sff8024_show_oui(id, CMIS_VENDOR_OUI_OFFSET);
+ sff8024_show_oui(map->page_00h, CMIS_VENDOR_OUI_OFFSET);
}
/**
@@ -42,9 +42,9 @@ static void cmis_show_oui(const __u8 *id)
* [1] CMIS Rev. 3, pag. 45, section 1.7.2.1, Table 18
* [2] CMIS Rev. 4, pag. 81, section 8.2.1, Table 8-2
*/
-static void cmis_show_rev_compliance(const __u8 *id)
+static void cmis_show_rev_compliance(const struct cmis_memory_map *map)
{
- __u8 rev = id[CMIS_REV_COMPLIANCE_OFFSET];
+ __u8 rev = map->lower_memory[CMIS_REV_COMPLIANCE_OFFSET];
int major = (rev >> 4) & 0x0F;
int minor = rev & 0x0F;
@@ -58,17 +58,17 @@ static void cmis_show_rev_compliance(const __u8 *id)
* [2] CMIS Rev. 4, pag. 94, section 8.3.9, Table 8-18
* [3] QSFP-DD Hardware Rev 5.0, pag. 22, section 4.2.1
*/
-static void cmis_show_power_info(const __u8 *id)
+static void cmis_show_power_info(const struct cmis_memory_map *map)
{
float max_power = 0.0f;
__u8 base_power = 0;
__u8 power_class;
/* Get the power class (first 3 most significat bytes) */
- power_class = (id[CMIS_PWR_CLASS_OFFSET] >> 5) & 0x07;
+ power_class = (map->page_00h[CMIS_PWR_CLASS_OFFSET] >> 5) & 0x07;
/* Get the base power in multiples of 0.25W */
- base_power = id[CMIS_PWR_MAX_POWER_OFFSET];
+ base_power = map->page_00h[CMIS_PWR_MAX_POWER_OFFSET];
max_power = base_power * 0.25f;
printf("\t%-41s : %d\n", "Power class", power_class + 1);
@@ -83,20 +83,20 @@ static void cmis_show_power_info(const __u8 *id)
* [1] CMIS Rev. 3, pag. 59, section 1.7.3.10, Table 31
* [2] CMIS Rev. 4, pag. 94, section 8.3.10, Table 8-19
*/
-static void cmis_show_cbl_asm_len(const __u8 *id)
+static void cmis_show_cbl_asm_len(const struct cmis_memory_map *map)
{
static const char *fn = "Cable assembly length";
float mul = 1.0f;
float val = 0.0f;
/* Check if max length */
- if (id[CMIS_CBL_ASM_LEN_OFFSET] == CMIS_6300M_MAX_LEN) {
+ if (map->page_00h[CMIS_CBL_ASM_LEN_OFFSET] == CMIS_6300M_MAX_LEN) {
printf("\t%-41s : > 6.3km\n", fn);
return;
}
/* Get the multiplier from the first two bits */
- switch (id[CMIS_CBL_ASM_LEN_OFFSET] & CMIS_LEN_MUL_MASK) {
+ switch (map->page_00h[CMIS_CBL_ASM_LEN_OFFSET] & CMIS_LEN_MUL_MASK) {
case CMIS_MULTIPLIER_00:
mul = 0.1f;
break;
@@ -114,7 +114,7 @@ static void cmis_show_cbl_asm_len(const __u8 *id)
}
/* Get base value from first 6 bits and multiply by mul */
- val = (id[CMIS_CBL_ASM_LEN_OFFSET] & CMIS_LEN_VAL_MASK);
+ val = (map->page_00h[CMIS_CBL_ASM_LEN_OFFSET] & CMIS_LEN_VAL_MASK);
val = (float)val * mul;
printf("\t%-41s : %0.2fm\n", fn, val);
}
@@ -126,14 +126,17 @@ static void cmis_show_cbl_asm_len(const __u8 *id)
* [1] CMIS Rev. 3, pag. 63, section 1.7.4.2, Table 39
* [2] CMIS Rev. 4, pag. 99, section 8.4.2, Table 8-27
*/
-static void cmis_print_smf_cbl_len(const __u8 *id)
+static void cmis_print_smf_cbl_len(const struct cmis_memory_map *map)
{
static const char *fn = "Length (SMF)";
float mul = 1.0f;
float val = 0.0f;
+ if (!map->page_01h)
+ return;
+
/* Get the multiplier from the first two bits */
- switch (id[CMIS_SMF_LEN_OFFSET] & CMIS_LEN_MUL_MASK) {
+ switch (map->page_01h[CMIS_SMF_LEN_OFFSET] & CMIS_LEN_MUL_MASK) {
case CMIS_MULTIPLIER_00:
mul = 0.1f;
break;
@@ -145,7 +148,7 @@ static void cmis_print_smf_cbl_len(const __u8 *id)
}
/* Get base value from first 6 bits and multiply by mul */
- val = (id[CMIS_SMF_LEN_OFFSET] & CMIS_LEN_VAL_MASK);
+ val = (map->page_01h[CMIS_SMF_LEN_OFFSET] & CMIS_LEN_VAL_MASK);
val = (float)val * mul;
printf("\t%-41s : %0.2fkm\n", fn, val);
}
@@ -155,21 +158,24 @@ static void cmis_print_smf_cbl_len(const __u8 *id)
* [1] CMIS Rev. 3, pag. 71, section 1.7.4.10, Table 46
* [2] CMIS Rev. 4, pag. 105, section 8.4.10, Table 8-34
*/
-static void cmis_show_sig_integrity(const __u8 *id)
+static void cmis_show_sig_integrity(const struct cmis_memory_map *map)
{
+ if (!map->page_01h)
+ return;
+
/* CDR Bypass control: 2nd bit from each byte */
printf("\t%-41s : ", "Tx CDR bypass control");
- printf("%s\n", YESNO(id[CMIS_SIG_INTEG_TX_OFFSET] & 0x02));
+ printf("%s\n", YESNO(map->page_01h[CMIS_SIG_INTEG_TX_OFFSET] & 0x02));
printf("\t%-41s : ", "Rx CDR bypass control");
- printf("%s\n", YESNO(id[CMIS_SIG_INTEG_RX_OFFSET] & 0x02));
+ printf("%s\n", YESNO(map->page_01h[CMIS_SIG_INTEG_RX_OFFSET] & 0x02));
/* CDR Implementation: 1st bit from each byte */
printf("\t%-41s : ", "Tx CDR");
- printf("%s\n", YESNO(id[CMIS_SIG_INTEG_TX_OFFSET] & 0x01));
+ printf("%s\n", YESNO(map->page_01h[CMIS_SIG_INTEG_TX_OFFSET] & 0x01));
printf("\t%-41s : ", "Rx CDR");
- printf("%s\n", YESNO(id[CMIS_SIG_INTEG_RX_OFFSET] & 0x01));
+ printf("%s\n", YESNO(map->page_01h[CMIS_SIG_INTEG_RX_OFFSET] & 0x01));
}
/**
@@ -182,14 +188,14 @@ static void cmis_show_sig_integrity(const __u8 *id)
* --> pag. 98, section 8.4, Table 8-25
* --> page 100, section 8.4.3, 8.4.4
*/
-static void cmis_show_mit_compliance(const __u8 *id)
+static void cmis_show_mit_compliance(const struct cmis_memory_map *map)
{
static const char *cc = " (Copper cable,";
printf("\t%-41s : 0x%02x", "Transmitter technology",
- id[CMIS_MEDIA_INTF_TECH_OFFSET]);
+ map->page_00h[CMIS_MEDIA_INTF_TECH_OFFSET]);
- switch (id[CMIS_MEDIA_INTF_TECH_OFFSET]) {
+ switch (map->page_00h[CMIS_MEDIA_INTF_TECH_OFFSET]) {
case CMIS_850_VCSEL:
printf(" (850 nm VCSEL)\n");
break;
@@ -240,22 +246,22 @@ static void cmis_show_mit_compliance(const __u8 *id)
break;
}
- if (id[CMIS_MEDIA_INTF_TECH_OFFSET] >= CMIS_COPPER_UNEQUAL) {
+ if (map->page_00h[CMIS_MEDIA_INTF_TECH_OFFSET] >= CMIS_COPPER_UNEQUAL) {
printf("\t%-41s : %udb\n", "Attenuation at 5GHz",
- id[CMIS_COPPER_ATT_5GHZ]);
+ map->page_00h[CMIS_COPPER_ATT_5GHZ]);
printf("\t%-41s : %udb\n", "Attenuation at 7GHz",
- id[CMIS_COPPER_ATT_7GHZ]);
+ map->page_00h[CMIS_COPPER_ATT_7GHZ]);
printf("\t%-41s : %udb\n", "Attenuation at 12.9GHz",
- id[CMIS_COPPER_ATT_12P9GHZ]);
+ map->page_00h[CMIS_COPPER_ATT_12P9GHZ]);
printf("\t%-41s : %udb\n", "Attenuation at 25.8GHz",
- id[CMIS_COPPER_ATT_25P8GHZ]);
- } else {
+ map->page_00h[CMIS_COPPER_ATT_25P8GHZ]);
+ } else if (map->page_01h) {
printf("\t%-41s : %.3lfnm\n", "Laser wavelength",
- (((id[CMIS_NOM_WAVELENGTH_MSB] << 8) |
- id[CMIS_NOM_WAVELENGTH_LSB]) * 0.05));
+ (((map->page_01h[CMIS_NOM_WAVELENGTH_MSB] << 8) |
+ map->page_01h[CMIS_NOM_WAVELENGTH_LSB]) * 0.05));
printf("\t%-41s : %.3lfnm\n", "Laser wavelength tolerance",
- (((id[CMIS_WAVELENGTH_TOL_MSB] << 8) |
- id[CMIS_WAVELENGTH_TOL_LSB]) * 0.005));
+ (((map->page_01h[CMIS_WAVELENGTH_TOL_MSB] << 8) |
+ map->page_01h[CMIS_WAVELENGTH_TOL_LSB]) * 0.005));
}
}
@@ -275,28 +281,16 @@ static void cmis_show_mit_compliance(const __u8 *id)
* [2] CMIS Rev. 4:
* --> pag. 84, section 8.2.4, Table 8-6
*/
-static void cmis_show_mod_lvl_monitors(const __u8 *id)
+static void cmis_show_mod_lvl_monitors(const struct cmis_memory_map *map)
{
+ const __u8 *id = map->lower_memory;
+
PRINT_TEMP("Module temperature",
OFFSET_TO_TEMP(CMIS_CURR_TEMP_OFFSET));
PRINT_VCC("Module voltage",
OFFSET_TO_U16(CMIS_CURR_VCC_OFFSET));
}
-static void cmis_show_link_len_from_page(const __u8 *page_one_data)
-{
- cmis_print_smf_cbl_len(page_one_data);
- sff_show_value_with_unit(page_one_data, CMIS_OM5_LEN_OFFSET,
- "Length (OM5)", 2, "m");
- sff_show_value_with_unit(page_one_data, CMIS_OM4_LEN_OFFSET,
- "Length (OM4)", 2, "m");
- sff_show_value_with_unit(page_one_data, CMIS_OM3_LEN_OFFSET,
- "Length (OM3 50/125um)", 2, "m");
- sff_show_value_with_unit(page_one_data, CMIS_OM2_LEN_OFFSET,
- "Length (OM2 50/125um)", 1, "m");
-}
-
-
/**
* Print relevant info about the maximum supported fiber media length
* for each type of fiber media at the maximum module-supported bit rate.
@@ -304,9 +298,19 @@ static void cmis_show_link_len_from_page(const __u8 *page_one_data)
* [1] CMIS Rev. 3, page 64, section 1.7.4.2, Table 39
* [2] CMIS Rev. 4, page 99, section 8.4.2, Table 8-27
*/
-static void cmis_show_link_len(const __u8 *id)
+static void cmis_show_link_len(const struct cmis_memory_map *map)
{
- cmis_show_link_len_from_page(id);
+ cmis_print_smf_cbl_len(map);
+ if (!map->page_01h)
+ return;
+ sff_show_value_with_unit(map->page_01h, CMIS_OM5_LEN_OFFSET,
+ "Length (OM5)", 2, "m");
+ sff_show_value_with_unit(map->page_01h, CMIS_OM4_LEN_OFFSET,
+ "Length (OM4)", 2, "m");
+ sff_show_value_with_unit(map->page_01h, CMIS_OM3_LEN_OFFSET,
+ "Length (OM3 50/125um)", 2, "m");
+ sff_show_value_with_unit(map->page_01h, CMIS_OM2_LEN_OFFSET,
+ "Length (OM2 50/125um)", 1, "m");
}
/**
@@ -314,25 +318,26 @@ static void cmis_show_link_len(const __u8 *id)
* [1] CMIS Rev. 3, page 56, section 1.7.3, Table 27
* [2] CMIS Rev. 4, page 91, section 8.2, Table 8-15
*/
-static void cmis_show_vendor_info(const __u8 *id)
+static void cmis_show_vendor_info(const struct cmis_memory_map *map)
{
- const char *clei = (const char *)(id + CMIS_CLEI_START_OFFSET);
+ const char *clei;
- sff_show_ascii(id, CMIS_VENDOR_NAME_START_OFFSET,
+ sff_show_ascii(map->page_00h, CMIS_VENDOR_NAME_START_OFFSET,
CMIS_VENDOR_NAME_END_OFFSET, "Vendor name");
- cmis_show_oui(id);
- sff_show_ascii(id, CMIS_VENDOR_PN_START_OFFSET,
+ cmis_show_oui(map);
+ sff_show_ascii(map->page_00h, CMIS_VENDOR_PN_START_OFFSET,
CMIS_VENDOR_PN_END_OFFSET, "Vendor PN");
- sff_show_ascii(id, CMIS_VENDOR_REV_START_OFFSET,
+ sff_show_ascii(map->page_00h, CMIS_VENDOR_REV_START_OFFSET,
CMIS_VENDOR_REV_END_OFFSET, "Vendor rev");
- sff_show_ascii(id, CMIS_VENDOR_SN_START_OFFSET,
+ sff_show_ascii(map->page_00h, CMIS_VENDOR_SN_START_OFFSET,
CMIS_VENDOR_SN_END_OFFSET, "Vendor SN");
- sff_show_ascii(id, CMIS_DATE_YEAR_OFFSET,
+ sff_show_ascii(map->page_00h, CMIS_DATE_YEAR_OFFSET,
CMIS_DATE_VENDOR_LOT_OFFSET + 1, "Date code");
+ clei = (const char *)(map->page_00h + CMIS_CLEI_START_OFFSET);
if (*clei && strncmp(clei, CMIS_CLEI_BLANK, CMIS_CLEI_LEN))
- sff_show_ascii(id, CMIS_CLEI_START_OFFSET, CMIS_CLEI_END_OFFSET,
- "CLEI code");
+ sff_show_ascii(map->page_00h, CMIS_CLEI_START_OFFSET,
+ CMIS_CLEI_END_OFFSET, "CLEI code");
}
static void cmis_memory_map_init_buf(struct cmis_memory_map *map,
@@ -363,16 +368,16 @@ void cmis_show_all_ioctl(const __u8 *id)
cmis_memory_map_init_buf(&map, id);
- cmis_show_identifier(id);
- cmis_show_power_info(id);
- cmis_show_connector(id);
- cmis_show_cbl_asm_len(id);
- cmis_show_sig_integrity(id);
- cmis_show_mit_compliance(id);
- cmis_show_mod_lvl_monitors(id);
- cmis_show_link_len(id);
- cmis_show_vendor_info(id);
- cmis_show_rev_compliance(id);
+ cmis_show_identifier(&map);
+ cmis_show_power_info(&map);
+ cmis_show_connector(&map);
+ cmis_show_cbl_asm_len(&map);
+ cmis_show_sig_integrity(&map);
+ cmis_show_mit_compliance(&map);
+ cmis_show_mod_lvl_monitors(&map);
+ cmis_show_link_len(&map);
+ cmis_show_vendor_info(&map);
+ cmis_show_rev_compliance(&map);
}
static void
@@ -403,22 +408,18 @@ cmis_memory_map_init_pages(struct cmis_memory_map *map,
void cmis_show_all_nl(const struct ethtool_module_eeprom *page_zero,
const struct ethtool_module_eeprom *page_one)
{
- const __u8 *page_zero_data = page_zero->data;
struct cmis_memory_map map = {};
cmis_memory_map_init_pages(&map, page_zero, page_one);
- cmis_show_identifier(page_zero_data);
- cmis_show_power_info(page_zero_data);
- cmis_show_connector(page_zero_data);
- cmis_show_cbl_asm_len(page_zero_data);
- cmis_show_sig_integrity(page_zero_data);
- cmis_show_mit_compliance(page_zero_data);
- cmis_show_mod_lvl_monitors(page_zero_data);
-
- if (page_one)
- cmis_show_link_len_from_page(page_one->data - 0x80);
-
- cmis_show_vendor_info(page_zero_data);
- cmis_show_rev_compliance(page_zero_data);
+ cmis_show_identifier(&map);
+ cmis_show_power_info(&map);
+ cmis_show_connector(&map);
+ cmis_show_cbl_asm_len(&map);
+ cmis_show_sig_integrity(&map);
+ cmis_show_mit_compliance(&map);
+ cmis_show_mod_lvl_monitors(&map);
+ cmis_show_link_len(&map);
+ cmis_show_vendor_info(&map);
+ cmis_show_rev_compliance(&map);
}
diff --git a/cmis.h b/cmis.h
index 53cbb5f57127..c878e3bc5afd 100644
--- a/cmis.h
+++ b/cmis.h
@@ -100,7 +100,6 @@
* that are unique to active modules and cable assemblies.
* GlobalOffset = 2 * 0x80 + LocalOffset
*/
-#define PAG01H_UPPER_OFFSET (0x02 * 0x80)
/* Supported Link Length (Page 1) */
#define CMIS_SMF_LEN_OFFSET 0x84
--
2.35.1

View File

@ -0,0 +1,77 @@
From 284886fbb4a85103cd82d061ebe4d1c93730b783 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:15 +0300
Subject: [PATCH 16/35] cmis: Consolidate code between IOCTL and netlink paths
Now that both the netlink and IOCTL paths use the same memory map
structure for parsing, the code can be easily consolidated.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
cmis.c | 38 ++++++++++++++++----------------------
1 file changed, 16 insertions(+), 22 deletions(-)
diff --git a/cmis.c b/cmis.c
index 2e01446b2315..eb7791dd59df 100644
--- a/cmis.c
+++ b/cmis.c
@@ -340,6 +340,20 @@ static void cmis_show_vendor_info(const struct cmis_memory_map *map)
CMIS_CLEI_END_OFFSET, "CLEI code");
}
+static void cmis_show_all_common(const struct cmis_memory_map *map)
+{
+ cmis_show_identifier(map);
+ cmis_show_power_info(map);
+ cmis_show_connector(map);
+ cmis_show_cbl_asm_len(map);
+ cmis_show_sig_integrity(map);
+ cmis_show_mit_compliance(map);
+ cmis_show_mod_lvl_monitors(map);
+ cmis_show_link_len(map);
+ cmis_show_vendor_info(map);
+ cmis_show_rev_compliance(map);
+}
+
static void cmis_memory_map_init_buf(struct cmis_memory_map *map,
const __u8 *id)
{
@@ -367,17 +381,7 @@ void cmis_show_all_ioctl(const __u8 *id)
struct cmis_memory_map map = {};
cmis_memory_map_init_buf(&map, id);
-
- cmis_show_identifier(&map);
- cmis_show_power_info(&map);
- cmis_show_connector(&map);
- cmis_show_cbl_asm_len(&map);
- cmis_show_sig_integrity(&map);
- cmis_show_mit_compliance(&map);
- cmis_show_mod_lvl_monitors(&map);
- cmis_show_link_len(&map);
- cmis_show_vendor_info(&map);
- cmis_show_rev_compliance(&map);
+ cmis_show_all_common(&map);
}
static void
@@ -411,15 +415,5 @@ void cmis_show_all_nl(const struct ethtool_module_eeprom *page_zero,
struct cmis_memory_map map = {};
cmis_memory_map_init_pages(&map, page_zero, page_one);
-
- cmis_show_identifier(&map);
- cmis_show_power_info(&map);
- cmis_show_connector(&map);
- cmis_show_cbl_asm_len(&map);
- cmis_show_sig_integrity(&map);
- cmis_show_mit_compliance(&map);
- cmis_show_mod_lvl_monitors(&map);
- cmis_show_link_len(&map);
- cmis_show_vendor_info(&map);
- cmis_show_rev_compliance(&map);
+ cmis_show_all_common(&map);
}
--
2.35.1

View File

@ -0,0 +1,97 @@
From a8419e965891901217756254e0ed1a3351b2a3cb Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:16 +0300
Subject: [PATCH 17/35] sff-8636: Rename SFF-8636 parsing functions
Currently, there are two SFF-8636 parsing functions. sff8636_show_all()
and sff8636_show_all_paged(). The former is called from the IOCTL path
with a buffer containing EEPROM contents and the latter is called from
the netlink path with pointer to individual EEPROM pages.
Rename them with '_ioctl' and '_nl' suffixes to make the distinction
clear.
In subsequent patches, these two functions will only differ in the way
they initialize the SFF-8636 memory map for parsing, while the parsing
code itself will be shared between the two.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
ethtool.c | 4 ++--
internal.h | 6 +++---
netlink/module-eeprom.c | 2 +-
qsfp.c | 6 +++---
4 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/ethtool.c b/ethtool.c
index 1b79e9f8d958..6c744ff84eb9 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -4908,8 +4908,8 @@ static int do_getmodule(struct cmd_context *ctx)
break;
case ETH_MODULE_SFF_8436:
case ETH_MODULE_SFF_8636:
- sff8636_show_all(eeprom->data,
- modinfo.eeprom_len);
+ sff8636_show_all_ioctl(eeprom->data,
+ modinfo.eeprom_len);
break;
#endif
default:
diff --git a/internal.h b/internal.h
index 33e619b3ac53..7ca6066d4e12 100644
--- a/internal.h
+++ b/internal.h
@@ -390,9 +390,9 @@ void sff8079_show_all(const __u8 *id);
void sff8472_show_all(const __u8 *id);
/* QSFP Optics diagnostics */
-void sff8636_show_all(const __u8 *id, __u32 eeprom_len);
-void sff8636_show_all_paged(const struct ethtool_module_eeprom *page_zero,
- const struct ethtool_module_eeprom *page_three);
+void sff8636_show_all_ioctl(const __u8 *id, __u32 eeprom_len);
+void sff8636_show_all_nl(const struct ethtool_module_eeprom *page_zero,
+ const struct ethtool_module_eeprom *page_three);
/* 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 fc4ef1a53aff..18b1abbe1252 100644
--- a/netlink/module-eeprom.c
+++ b/netlink/module-eeprom.c
@@ -328,7 +328,7 @@ static void decoder_print(void)
case SFF8024_ID_QSFP:
case SFF8024_ID_QSFP28:
case SFF8024_ID_QSFP_PLUS:
- sff8636_show_all_paged(page_zero, page_three);
+ sff8636_show_all_nl(page_zero, page_three);
break;
case SFF8024_ID_QSFP_DD:
case SFF8024_ID_DSFP:
diff --git a/qsfp.c b/qsfp.c
index 27fdd3bd1771..dc6407d3ef6f 100644
--- a/qsfp.c
+++ b/qsfp.c
@@ -853,7 +853,7 @@ static void sff8636_show_page_zero(const __u8 *id)
}
-void sff8636_show_all(const __u8 *id, __u32 eeprom_len)
+void sff8636_show_all_ioctl(const __u8 *id, __u32 eeprom_len)
{
if (id[SFF8636_ID_OFFSET] == SFF8024_ID_QSFP_DD) {
cmis_show_all_ioctl(id);
@@ -871,8 +871,8 @@ void sff8636_show_all(const __u8 *id, __u32 eeprom_len)
}
}
-void sff8636_show_all_paged(const struct ethtool_module_eeprom *page_zero,
- const struct ethtool_module_eeprom *page_three)
+void sff8636_show_all_nl(const struct ethtool_module_eeprom *page_zero,
+ const struct ethtool_module_eeprom *page_three)
{
sff8636_show_identifier(page_zero->data);
sff8636_show_page_zero(page_zero->data);
--
2.35.1

View File

@ -0,0 +1,137 @@
From c77b5adfb3f94762a08554d1b4d75f6cbd8a6abe Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:17 +0300
Subject: [PATCH 18/35] sff-8636: Initialize SFF-8636 memory map
The SFF-8636 memory map [1] consists of Lower Memory and Upper Memory.
The content of the Lower Memory is fixed and can be addressed using an
offset between 0 and 127 (inclusive).
The Upper Memory is variable and optional and can be addressed by
specifying a page number and an offset between 128 and 255 (inclusive).
Create a structure describing this memory map and initialize it with
pointers to available pages.
In the IOCTL path, the structure holds pointers to regions of the
continuous buffer passed to user space via the 'ETHTOOL_GMODULEEEPROM'
command.
In the netlink path, the structure holds pointers to individual pages
passed to user space via the 'MODULE_EEPROM_GET' message.
This structure will later allow us to consolidate the IOCTL and netlink
parsing code paths and also easily support additional EEPROM pages, when
needed.
[1] SFF-8636 Rev. 2.10a, pag. 30, section 6.1, Figure 6-1
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
qsfp.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 65 insertions(+)
diff --git a/qsfp.c b/qsfp.c
index dc6407d3ef6f..80000d40f6e8 100644
--- a/qsfp.c
+++ b/qsfp.c
@@ -60,6 +60,15 @@
#include "qsfp.h"
#include "cmis.h"
+struct sff8636_memory_map {
+ const __u8 *lower_memory;
+ const __u8 *upper_memory[4];
+#define page_00h upper_memory[0x0]
+#define page_03h upper_memory[0x3]
+};
+
+#define SFF8636_PAGE_SIZE 0x80
+
#define MAX_DESC_SIZE 42
static struct sff8636_aw_flags {
@@ -853,13 +862,40 @@ static void sff8636_show_page_zero(const __u8 *id)
}
+static void sff8636_memory_map_init_buf(struct sff8636_memory_map *map,
+ const __u8 *id, __u32 eeprom_len)
+{
+ /* Lower Memory and Page 00h are always present.
+ *
+ * Offset into Upper Memory is between page size and twice the page
+ * size. Therefore, set the base address of each page to base address
+ * plus page size multiplied by the page number.
+ */
+ map->lower_memory = id;
+ map->page_00h = id;
+
+ /* Page 03h is only present when the module memory model is paged and
+ * not flat and when we got a big enough buffer from the kernel.
+ */
+ if (map->lower_memory[SFF8636_STATUS_2_OFFSET] &
+ SFF8636_STATUS_PAGE_3_PRESENT ||
+ eeprom_len != ETH_MODULE_SFF_8636_MAX_LEN)
+ return;
+
+ map->page_03h = id + 3 * SFF8636_PAGE_SIZE;
+}
+
void sff8636_show_all_ioctl(const __u8 *id, __u32 eeprom_len)
{
+ struct sff8636_memory_map map = {};
+
if (id[SFF8636_ID_OFFSET] == SFF8024_ID_QSFP_DD) {
cmis_show_all_ioctl(id);
return;
}
+ sff8636_memory_map_init_buf(&map, id, eeprom_len);
+
sff8636_show_identifier(id);
switch (id[SFF8636_ID_OFFSET]) {
case SFF8024_ID_QSFP:
@@ -871,9 +907,38 @@ void sff8636_show_all_ioctl(const __u8 *id, __u32 eeprom_len)
}
}
+static void
+sff8636_memory_map_init_pages(struct sff8636_memory_map *map,
+ const struct ethtool_module_eeprom *page_zero,
+ const struct ethtool_module_eeprom *page_three)
+{
+ /* Lower Memory and Page 00h are always present.
+ *
+ * Offset into Upper Memory is between page size and twice the page
+ * size. Therefore, set the base address of each page to its base
+ * address minus page size. For Page 00h, this is the address of the
+ * Lower Memory.
+ */
+ map->lower_memory = page_zero->data;
+ map->page_00h = page_zero->data;
+
+ /* Page 03h is only present when the module memory model is paged and
+ * not flat.
+ */
+ if (map->lower_memory[SFF8636_STATUS_2_OFFSET] &
+ SFF8636_STATUS_PAGE_3_PRESENT)
+ return;
+
+ map->page_03h = page_three->data - SFF8636_PAGE_SIZE;
+}
+
void sff8636_show_all_nl(const struct ethtool_module_eeprom *page_zero,
const struct ethtool_module_eeprom *page_three)
{
+ struct sff8636_memory_map map = {};
+
+ sff8636_memory_map_init_pages(&map, page_zero, page_three);
+
sff8636_show_identifier(page_zero->data);
sff8636_show_page_zero(page_zero->data);
if (page_three)
--
2.35.1

View File

@ -0,0 +1,607 @@
From 85023fa5dd7e79ce46a92ab567b4b675c3145775 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:18 +0300
Subject: [PATCH 19/35] sff-8636: Use memory map during parsing
Instead of passing one large buffer to the individual parsing functions,
use the memory map structure from the previous patch.
This has the added benefit of checking which optional pages are actually
available and it will also allow us to consolidate the IOCTL and netlink
parsing code paths.
Tested by making sure that there are no differences in output in both
the IOCTL and netlink paths before and after the patch.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
qsfp.c | 368 +++++++++++++++++++++++++++++++--------------------------
1 file changed, 201 insertions(+), 167 deletions(-)
diff --git a/qsfp.c b/qsfp.c
index 80000d40f6e8..354b3b1ce9ff 100644
--- a/qsfp.c
+++ b/qsfp.c
@@ -205,20 +205,21 @@ static struct sff8636_aw_flags {
{ NULL, 0, 0 },
};
-static void sff8636_show_identifier(const __u8 *id)
+static void sff8636_show_identifier(const struct sff8636_memory_map *map)
{
- sff8024_show_identifier(id, SFF8636_ID_OFFSET);
+ sff8024_show_identifier(map->lower_memory, SFF8636_ID_OFFSET);
}
-static void sff8636_show_ext_identifier(const __u8 *id)
+static void sff8636_show_ext_identifier(const struct sff8636_memory_map *map)
{
printf("\t%-41s : 0x%02x\n", "Extended identifier",
- id[SFF8636_EXT_ID_OFFSET]);
+ map->page_00h[SFF8636_EXT_ID_OFFSET]);
static const char *pfx =
"\tExtended identifier description :";
- switch (id[SFF8636_EXT_ID_OFFSET] & SFF8636_EXT_ID_PWR_CLASS_MASK) {
+ switch (map->page_00h[SFF8636_EXT_ID_OFFSET] &
+ SFF8636_EXT_ID_PWR_CLASS_MASK) {
case SFF8636_EXT_ID_PWR_CLASS_1:
printf("%s 1.5W max. Power consumption\n", pfx);
break;
@@ -233,17 +234,18 @@ static void sff8636_show_ext_identifier(const __u8 *id)
break;
}
- if (id[SFF8636_EXT_ID_OFFSET] & SFF8636_EXT_ID_CDR_TX_MASK)
+ if (map->page_00h[SFF8636_EXT_ID_OFFSET] & SFF8636_EXT_ID_CDR_TX_MASK)
printf("%s CDR present in TX,", pfx);
else
printf("%s No CDR in TX,", pfx);
- if (id[SFF8636_EXT_ID_OFFSET] & SFF8636_EXT_ID_CDR_RX_MASK)
+ if (map->page_00h[SFF8636_EXT_ID_OFFSET] & SFF8636_EXT_ID_CDR_RX_MASK)
printf(" CDR present in RX\n");
else
printf(" No CDR in RX\n");
- switch (id[SFF8636_EXT_ID_OFFSET] & SFF8636_EXT_ID_EPWR_CLASS_MASK) {
+ switch (map->page_00h[SFF8636_EXT_ID_OFFSET] &
+ SFF8636_EXT_ID_EPWR_CLASS_MASK) {
case SFF8636_EXT_ID_PWR_CLASS_LEGACY:
printf("%s", pfx);
break;
@@ -257,18 +259,19 @@ static void sff8636_show_ext_identifier(const __u8 *id)
printf("%s 5.0W max. Power consumption, ", pfx);
break;
}
- if (id[SFF8636_PWR_MODE_OFFSET] & SFF8636_HIGH_PWR_ENABLE)
+ if (map->lower_memory[SFF8636_PWR_MODE_OFFSET] &
+ SFF8636_HIGH_PWR_ENABLE)
printf(" High Power Class (> 3.5 W) enabled\n");
else
printf(" High Power Class (> 3.5 W) not enabled\n");
}
-static void sff8636_show_connector(const __u8 *id)
+static void sff8636_show_connector(const struct sff8636_memory_map *map)
{
- sff8024_show_connector(id, SFF8636_CTOR_OFFSET);
+ sff8024_show_connector(map->page_00h, SFF8636_CTOR_OFFSET);
}
-static void sff8636_show_transceiver(const __u8 *id)
+static void sff8636_show_transceiver(const struct sff8636_memory_map *map)
{
static const char *pfx =
"\tTransceiver type :";
@@ -276,33 +279,41 @@ static void sff8636_show_transceiver(const __u8 *id)
printf("\t%-41s : 0x%02x 0x%02x 0x%02x " \
"0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
"Transceiver codes",
- id[SFF8636_ETHERNET_COMP_OFFSET],
- id[SFF8636_SONET_COMP_OFFSET],
- id[SFF8636_SAS_COMP_OFFSET],
- id[SFF8636_GIGE_COMP_OFFSET],
- id[SFF8636_FC_LEN_OFFSET],
- id[SFF8636_FC_TECH_OFFSET],
- id[SFF8636_FC_TRANS_MEDIA_OFFSET],
- id[SFF8636_FC_SPEED_OFFSET]);
+ map->page_00h[SFF8636_ETHERNET_COMP_OFFSET],
+ map->page_00h[SFF8636_SONET_COMP_OFFSET],
+ map->page_00h[SFF8636_SAS_COMP_OFFSET],
+ map->page_00h[SFF8636_GIGE_COMP_OFFSET],
+ map->page_00h[SFF8636_FC_LEN_OFFSET],
+ map->page_00h[SFF8636_FC_TECH_OFFSET],
+ map->page_00h[SFF8636_FC_TRANS_MEDIA_OFFSET],
+ map->page_00h[SFF8636_FC_SPEED_OFFSET]);
/* 10G/40G Ethernet Compliance Codes */
- if (id[SFF8636_ETHERNET_COMP_OFFSET] & SFF8636_ETHERNET_10G_LRM)
+ if (map->page_00h[SFF8636_ETHERNET_COMP_OFFSET] &
+ SFF8636_ETHERNET_10G_LRM)
printf("%s 10G Ethernet: 10G Base-LRM\n", pfx);
- if (id[SFF8636_ETHERNET_COMP_OFFSET] & SFF8636_ETHERNET_10G_LR)
+ if (map->page_00h[SFF8636_ETHERNET_COMP_OFFSET] &
+ SFF8636_ETHERNET_10G_LR)
printf("%s 10G Ethernet: 10G Base-LR\n", pfx);
- if (id[SFF8636_ETHERNET_COMP_OFFSET] & SFF8636_ETHERNET_10G_SR)
+ if (map->page_00h[SFF8636_ETHERNET_COMP_OFFSET] &
+ SFF8636_ETHERNET_10G_SR)
printf("%s 10G Ethernet: 10G Base-SR\n", pfx);
- if (id[SFF8636_ETHERNET_COMP_OFFSET] & SFF8636_ETHERNET_40G_CR4)
+ if (map->page_00h[SFF8636_ETHERNET_COMP_OFFSET] &
+ SFF8636_ETHERNET_40G_CR4)
printf("%s 40G Ethernet: 40G Base-CR4\n", pfx);
- if (id[SFF8636_ETHERNET_COMP_OFFSET] & SFF8636_ETHERNET_40G_SR4)
+ if (map->page_00h[SFF8636_ETHERNET_COMP_OFFSET] &
+ SFF8636_ETHERNET_40G_SR4)
printf("%s 40G Ethernet: 40G Base-SR4\n", pfx);
- if (id[SFF8636_ETHERNET_COMP_OFFSET] & SFF8636_ETHERNET_40G_LR4)
+ if (map->page_00h[SFF8636_ETHERNET_COMP_OFFSET] &
+ SFF8636_ETHERNET_40G_LR4)
printf("%s 40G Ethernet: 40G Base-LR4\n", pfx);
- if (id[SFF8636_ETHERNET_COMP_OFFSET] & SFF8636_ETHERNET_40G_ACTIVE)
+ if (map->page_00h[SFF8636_ETHERNET_COMP_OFFSET] &
+ SFF8636_ETHERNET_40G_ACTIVE)
printf("%s 40G Ethernet: 40G Active Cable (XLPPI)\n", pfx);
/* Extended Specification Compliance Codes from SFF-8024 */
- if (id[SFF8636_ETHERNET_COMP_OFFSET] & SFF8636_ETHERNET_RSRVD) {
- switch (id[SFF8636_OPTION_1_OFFSET]) {
+ if (map->page_00h[SFF8636_ETHERNET_COMP_OFFSET] &
+ SFF8636_ETHERNET_RSRVD) {
+ switch (map->page_00h[SFF8636_OPTION_1_OFFSET]) {
case SFF8636_ETHERNET_UNSPECIFIED:
printf("%s (reserved or unknown)\n", pfx);
break;
@@ -493,113 +504,122 @@ static void sff8636_show_transceiver(const __u8 *id)
}
/* SONET Compliance Codes */
- if (id[SFF8636_SONET_COMP_OFFSET] & (SFF8636_SONET_40G_OTN))
+ if (map->page_00h[SFF8636_SONET_COMP_OFFSET] &
+ (SFF8636_SONET_40G_OTN))
printf("%s 40G OTN (OTU3B/OTU3C)\n", pfx);
- if (id[SFF8636_SONET_COMP_OFFSET] & (SFF8636_SONET_OC48_LR))
+ if (map->page_00h[SFF8636_SONET_COMP_OFFSET] & (SFF8636_SONET_OC48_LR))
printf("%s SONET: OC-48, long reach\n", pfx);
- if (id[SFF8636_SONET_COMP_OFFSET] & (SFF8636_SONET_OC48_IR))
+ if (map->page_00h[SFF8636_SONET_COMP_OFFSET] & (SFF8636_SONET_OC48_IR))
printf("%s SONET: OC-48, intermediate reach\n", pfx);
- if (id[SFF8636_SONET_COMP_OFFSET] & (SFF8636_SONET_OC48_SR))
+ if (map->page_00h[SFF8636_SONET_COMP_OFFSET] & (SFF8636_SONET_OC48_SR))
printf("%s SONET: OC-48, short reach\n", pfx);
/* SAS/SATA Compliance Codes */
- if (id[SFF8636_SAS_COMP_OFFSET] & (SFF8636_SAS_6G))
+ if (map->page_00h[SFF8636_SAS_COMP_OFFSET] & (SFF8636_SAS_6G))
printf("%s SAS 6.0G\n", pfx);
- if (id[SFF8636_SAS_COMP_OFFSET] & (SFF8636_SAS_3G))
+ if (map->page_00h[SFF8636_SAS_COMP_OFFSET] & (SFF8636_SAS_3G))
printf("%s SAS 3.0G\n", pfx);
/* Ethernet Compliance Codes */
- if (id[SFF8636_GIGE_COMP_OFFSET] & SFF8636_GIGE_1000_BASE_T)
+ if (map->page_00h[SFF8636_GIGE_COMP_OFFSET] & SFF8636_GIGE_1000_BASE_T)
printf("%s Ethernet: 1000BASE-T\n", pfx);
- if (id[SFF8636_GIGE_COMP_OFFSET] & SFF8636_GIGE_1000_BASE_CX)
+ if (map->page_00h[SFF8636_GIGE_COMP_OFFSET] & SFF8636_GIGE_1000_BASE_CX)
printf("%s Ethernet: 1000BASE-CX\n", pfx);
- if (id[SFF8636_GIGE_COMP_OFFSET] & SFF8636_GIGE_1000_BASE_LX)
+ if (map->page_00h[SFF8636_GIGE_COMP_OFFSET] & SFF8636_GIGE_1000_BASE_LX)
printf("%s Ethernet: 1000BASE-LX\n", pfx);
- if (id[SFF8636_GIGE_COMP_OFFSET] & SFF8636_GIGE_1000_BASE_SX)
+ if (map->page_00h[SFF8636_GIGE_COMP_OFFSET] & SFF8636_GIGE_1000_BASE_SX)
printf("%s Ethernet: 1000BASE-SX\n", pfx);
/* Fibre Channel link length */
- if (id[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_LEN_VERY_LONG)
+ if (map->page_00h[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_LEN_VERY_LONG)
printf("%s FC: very long distance (V)\n", pfx);
- if (id[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_LEN_SHORT)
+ if (map->page_00h[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_LEN_SHORT)
printf("%s FC: short distance (S)\n", pfx);
- if (id[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_LEN_INT)
+ if (map->page_00h[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_LEN_INT)
printf("%s FC: intermediate distance (I)\n", pfx);
- if (id[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_LEN_LONG)
+ if (map->page_00h[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_LEN_LONG)
printf("%s FC: long distance (L)\n", pfx);
- if (id[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_LEN_MED)
+ if (map->page_00h[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_LEN_MED)
printf("%s FC: medium distance (M)\n", pfx);
/* Fibre Channel transmitter technology */
- if (id[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_TECH_LONG_LC)
+ if (map->page_00h[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_TECH_LONG_LC)
printf("%s FC: Longwave laser (LC)\n", pfx);
- if (id[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_TECH_ELEC_INTER)
+ if (map->page_00h[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_TECH_ELEC_INTER)
printf("%s FC: Electrical inter-enclosure (EL)\n", pfx);
- if (id[SFF8636_FC_TECH_OFFSET] & SFF8636_FC_TECH_ELEC_INTRA)
+ if (map->page_00h[SFF8636_FC_TECH_OFFSET] & SFF8636_FC_TECH_ELEC_INTRA)
printf("%s FC: Electrical intra-enclosure (EL)\n", pfx);
- if (id[SFF8636_FC_TECH_OFFSET] & SFF8636_FC_TECH_SHORT_WO_OFC)
+ if (map->page_00h[SFF8636_FC_TECH_OFFSET] &
+ SFF8636_FC_TECH_SHORT_WO_OFC)
printf("%s FC: Shortwave laser w/o OFC (SN)\n", pfx);
- if (id[SFF8636_FC_TECH_OFFSET] & SFF8636_FC_TECH_SHORT_W_OFC)
+ if (map->page_00h[SFF8636_FC_TECH_OFFSET] & SFF8636_FC_TECH_SHORT_W_OFC)
printf("%s FC: Shortwave laser with OFC (SL)\n", pfx);
- if (id[SFF8636_FC_TECH_OFFSET] & SFF8636_FC_TECH_LONG_LL)
+ if (map->page_00h[SFF8636_FC_TECH_OFFSET] & SFF8636_FC_TECH_LONG_LL)
printf("%s FC: Longwave laser (LL)\n", pfx);
/* Fibre Channel transmission media */
- if (id[SFF8636_FC_TRANS_MEDIA_OFFSET] & SFF8636_FC_TRANS_MEDIA_TW)
+ if (map->page_00h[SFF8636_FC_TRANS_MEDIA_OFFSET] &
+ SFF8636_FC_TRANS_MEDIA_TW)
printf("%s FC: Twin Axial Pair (TW)\n", pfx);
- if (id[SFF8636_FC_TRANS_MEDIA_OFFSET] & SFF8636_FC_TRANS_MEDIA_TP)
+ if (map->page_00h[SFF8636_FC_TRANS_MEDIA_OFFSET] &
+ SFF8636_FC_TRANS_MEDIA_TP)
printf("%s FC: Twisted Pair (TP)\n", pfx);
- if (id[SFF8636_FC_TRANS_MEDIA_OFFSET] & SFF8636_FC_TRANS_MEDIA_MI)
+ if (map->page_00h[SFF8636_FC_TRANS_MEDIA_OFFSET] &
+ SFF8636_FC_TRANS_MEDIA_MI)
printf("%s FC: Miniature Coax (MI)\n", pfx);
- if (id[SFF8636_FC_TRANS_MEDIA_OFFSET] & SFF8636_FC_TRANS_MEDIA_TV)
+ if (map->page_00h[SFF8636_FC_TRANS_MEDIA_OFFSET] &
+ SFF8636_FC_TRANS_MEDIA_TV)
printf("%s FC: Video Coax (TV)\n", pfx);
- if (id[SFF8636_FC_TRANS_MEDIA_OFFSET] & SFF8636_FC_TRANS_MEDIA_M6)
+ if (map->page_00h[SFF8636_FC_TRANS_MEDIA_OFFSET] &
+ SFF8636_FC_TRANS_MEDIA_M6)
printf("%s FC: Multimode, 62.5m (M6)\n", pfx);
- if (id[SFF8636_FC_TRANS_MEDIA_OFFSET] & SFF8636_FC_TRANS_MEDIA_M5)
+ if (map->page_00h[SFF8636_FC_TRANS_MEDIA_OFFSET] &
+ SFF8636_FC_TRANS_MEDIA_M5)
printf("%s FC: Multimode, 50m (M5)\n", pfx);
- if (id[SFF8636_FC_TRANS_MEDIA_OFFSET] & SFF8636_FC_TRANS_MEDIA_OM3)
+ if (map->page_00h[SFF8636_FC_TRANS_MEDIA_OFFSET] &
+ SFF8636_FC_TRANS_MEDIA_OM3)
printf("%s FC: Multimode, 50um (OM3)\n", pfx);
- if (id[SFF8636_FC_TRANS_MEDIA_OFFSET] & SFF8636_FC_TRANS_MEDIA_SM)
+ if (map->page_00h[SFF8636_FC_TRANS_MEDIA_OFFSET] &
+ SFF8636_FC_TRANS_MEDIA_SM)
printf("%s FC: Single Mode (SM)\n", pfx);
/* Fibre Channel speed */
- if (id[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_1200_MBPS)
+ if (map->page_00h[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_1200_MBPS)
printf("%s FC: 1200 MBytes/sec\n", pfx);
- if (id[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_800_MBPS)
+ if (map->page_00h[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_800_MBPS)
printf("%s FC: 800 MBytes/sec\n", pfx);
- if (id[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_1600_MBPS)
+ if (map->page_00h[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_1600_MBPS)
printf("%s FC: 1600 MBytes/sec\n", pfx);
- if (id[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_400_MBPS)
+ if (map->page_00h[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_400_MBPS)
printf("%s FC: 400 MBytes/sec\n", pfx);
- if (id[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_200_MBPS)
+ if (map->page_00h[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_200_MBPS)
printf("%s FC: 200 MBytes/sec\n", pfx);
- if (id[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_100_MBPS)
+ if (map->page_00h[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_100_MBPS)
printf("%s FC: 100 MBytes/sec\n", pfx);
}
-static void sff8636_show_encoding(const __u8 *id)
+static void sff8636_show_encoding(const struct sff8636_memory_map *map)
{
- sff8024_show_encoding(id, SFF8636_ENCODING_OFFSET, ETH_MODULE_SFF_8636);
+ sff8024_show_encoding(map->page_00h, SFF8636_ENCODING_OFFSET,
+ ETH_MODULE_SFF_8636);
}
-static void sff8636_show_rate_identifier(const __u8 *id)
+static void sff8636_show_rate_identifier(const struct sff8636_memory_map *map)
{
/* TODO: Need to fix rate select logic */
printf("\t%-41s : 0x%02x\n", "Rate identifier",
- id[SFF8636_EXT_RS_OFFSET]);
+ map->page_00h[SFF8636_EXT_RS_OFFSET]);
}
-static void sff8636_show_oui(const __u8 *id, int id_offset)
-{
- sff8024_show_oui(id, id_offset);
-}
-
-static void sff8636_show_wavelength_or_copper_compliance(const __u8 *id)
+static void
+sff8636_show_wavelength_or_copper_compliance(const struct sff8636_memory_map *map)
{
printf("\t%-41s : 0x%02x", "Transmitter technology",
- (id[SFF8636_DEVICE_TECH_OFFSET] & SFF8636_TRANS_TECH_MASK));
+ map->page_00h[SFF8636_DEVICE_TECH_OFFSET] &
+ SFF8636_TRANS_TECH_MASK);
- switch (id[SFF8636_DEVICE_TECH_OFFSET] & SFF8636_TRANS_TECH_MASK) {
+ switch (map->page_00h[SFF8636_DEVICE_TECH_OFFSET] &
+ SFF8636_TRANS_TECH_MASK) {
case SFF8636_TRANS_850_VCSEL:
printf(" (850 nm VCSEL)\n");
break;
@@ -650,31 +670,26 @@ static void sff8636_show_wavelength_or_copper_compliance(const __u8 *id)
break;
}
- if ((id[SFF8636_DEVICE_TECH_OFFSET] & SFF8636_TRANS_TECH_MASK)
- >= SFF8636_TRANS_COPPER_PAS_UNEQUAL) {
+ if ((map->page_00h[SFF8636_DEVICE_TECH_OFFSET] &
+ SFF8636_TRANS_TECH_MASK) >= SFF8636_TRANS_COPPER_PAS_UNEQUAL) {
printf("\t%-41s : %udb\n", "Attenuation at 2.5GHz",
- id[SFF8636_WAVELEN_HIGH_BYTE_OFFSET]);
+ map->page_00h[SFF8636_WAVELEN_HIGH_BYTE_OFFSET]);
printf("\t%-41s : %udb\n", "Attenuation at 5.0GHz",
- id[SFF8636_WAVELEN_LOW_BYTE_OFFSET]);
+ map->page_00h[SFF8636_WAVELEN_LOW_BYTE_OFFSET]);
printf("\t%-41s : %udb\n", "Attenuation at 7.0GHz",
- id[SFF8636_WAVE_TOL_HIGH_BYTE_OFFSET]);
+ map->page_00h[SFF8636_WAVE_TOL_HIGH_BYTE_OFFSET]);
printf("\t%-41s : %udb\n", "Attenuation at 12.9GHz",
- id[SFF8636_WAVE_TOL_LOW_BYTE_OFFSET]);
+ map->page_00h[SFF8636_WAVE_TOL_LOW_BYTE_OFFSET]);
} else {
printf("\t%-41s : %.3lfnm\n", "Laser wavelength",
- (((id[SFF8636_WAVELEN_HIGH_BYTE_OFFSET] << 8) |
- id[SFF8636_WAVELEN_LOW_BYTE_OFFSET])*0.05));
+ (((map->page_00h[SFF8636_WAVELEN_HIGH_BYTE_OFFSET] << 8) |
+ map->page_00h[SFF8636_WAVELEN_LOW_BYTE_OFFSET]) * 0.05));
printf("\t%-41s : %.3lfnm\n", "Laser wavelength tolerance",
- (((id[SFF8636_WAVE_TOL_HIGH_BYTE_OFFSET] << 8) |
- id[SFF8636_WAVE_TOL_LOW_BYTE_OFFSET])*0.005));
+ (((map->page_00h[SFF8636_WAVE_TOL_HIGH_BYTE_OFFSET] << 8) |
+ map->page_00h[SFF8636_WAVE_TOL_LOW_BYTE_OFFSET]) * 0.005));
}
}
-static void sff8636_show_revision_compliance(const __u8 *id)
-{
- sff_show_revision_compliance(id, SFF8636_REV_COMPLIANCE_OFFSET);
-}
-
/*
* 2-byte internal temperature conversions:
* First byte is a signed 8-bit integer, which is the temp decimal part
@@ -683,39 +698,65 @@ static void sff8636_show_revision_compliance(const __u8 *id)
#define SFF8636_OFFSET_TO_TEMP(offset) ((__s16)OFFSET_TO_U16(offset))
#define OFFSET_TO_U16_PTR(ptr, offset) (ptr[offset] << 8 | ptr[(offset) + 1])
-static void sff8636_dom_parse(const __u8 *id, const __u8 *page_three, struct sff_diags *sd)
+static void sff8636_dom_parse(const struct sff8636_memory_map *map,
+ struct sff_diags *sd)
{
+ const __u8 *id = map->lower_memory;
int i = 0;
/* Monitoring Thresholds for Alarms and Warnings */
sd->sfp_voltage[MCURR] = OFFSET_TO_U16_PTR(id, SFF8636_VCC_CURR);
- sd->sfp_voltage[HALRM] = OFFSET_TO_U16_PTR(page_three, SFF8636_VCC_HALRM);
- sd->sfp_voltage[LALRM] = OFFSET_TO_U16_PTR(page_three, SFF8636_VCC_LALRM);
- sd->sfp_voltage[HWARN] = OFFSET_TO_U16_PTR(page_three, SFF8636_VCC_HWARN);
- sd->sfp_voltage[LWARN] = OFFSET_TO_U16_PTR(page_three, SFF8636_VCC_LWARN);
-
sd->sfp_temp[MCURR] = SFF8636_OFFSET_TO_TEMP(SFF8636_TEMP_CURR);
- sd->sfp_temp[HALRM] = (__s16)OFFSET_TO_U16_PTR(page_three, SFF8636_TEMP_HALRM);
- sd->sfp_temp[LALRM] = (__s16)OFFSET_TO_U16_PTR(page_three, SFF8636_TEMP_LALRM);
- sd->sfp_temp[HWARN] = (__s16)OFFSET_TO_U16_PTR(page_three, SFF8636_TEMP_HWARN);
- sd->sfp_temp[LWARN] = (__s16)OFFSET_TO_U16_PTR(page_three, SFF8636_TEMP_LWARN);
-
- sd->bias_cur[HALRM] = OFFSET_TO_U16_PTR(page_three, SFF8636_TX_BIAS_HALRM);
- sd->bias_cur[LALRM] = OFFSET_TO_U16_PTR(page_three, SFF8636_TX_BIAS_LALRM);
- sd->bias_cur[HWARN] = OFFSET_TO_U16_PTR(page_three, SFF8636_TX_BIAS_HWARN);
- sd->bias_cur[LWARN] = OFFSET_TO_U16_PTR(page_three, SFF8636_TX_BIAS_LWARN);
-
- sd->tx_power[HALRM] = OFFSET_TO_U16_PTR(page_three, SFF8636_TX_PWR_HALRM);
- sd->tx_power[LALRM] = OFFSET_TO_U16_PTR(page_three, SFF8636_TX_PWR_LALRM);
- sd->tx_power[HWARN] = OFFSET_TO_U16_PTR(page_three, SFF8636_TX_PWR_HWARN);
- sd->tx_power[LWARN] = OFFSET_TO_U16_PTR(page_three, SFF8636_TX_PWR_LWARN);
-
- sd->rx_power[HALRM] = OFFSET_TO_U16_PTR(page_three, SFF8636_RX_PWR_HALRM);
- sd->rx_power[LALRM] = OFFSET_TO_U16_PTR(page_three, SFF8636_RX_PWR_LALRM);
- sd->rx_power[HWARN] = OFFSET_TO_U16_PTR(page_three, SFF8636_RX_PWR_HWARN);
- sd->rx_power[LWARN] = OFFSET_TO_U16_PTR(page_three, SFF8636_RX_PWR_LWARN);
-
+ if (!map->page_03h)
+ goto out;
+
+ sd->sfp_voltage[HALRM] = OFFSET_TO_U16_PTR(map->page_03h,
+ SFF8636_VCC_HALRM);
+ sd->sfp_voltage[LALRM] = OFFSET_TO_U16_PTR(map->page_03h,
+ SFF8636_VCC_LALRM);
+ sd->sfp_voltage[HWARN] = OFFSET_TO_U16_PTR(map->page_03h,
+ SFF8636_VCC_HWARN);
+ sd->sfp_voltage[LWARN] = OFFSET_TO_U16_PTR(map->page_03h,
+ SFF8636_VCC_LWARN);
+
+ sd->sfp_temp[HALRM] = (__s16)OFFSET_TO_U16_PTR(map->page_03h,
+ SFF8636_TEMP_HALRM);
+ sd->sfp_temp[LALRM] = (__s16)OFFSET_TO_U16_PTR(map->page_03h,
+ SFF8636_TEMP_LALRM);
+ sd->sfp_temp[HWARN] = (__s16)OFFSET_TO_U16_PTR(map->page_03h,
+ SFF8636_TEMP_HWARN);
+ sd->sfp_temp[LWARN] = (__s16)OFFSET_TO_U16_PTR(map->page_03h,
+ SFF8636_TEMP_LWARN);
+
+ sd->bias_cur[HALRM] = OFFSET_TO_U16_PTR(map->page_03h,
+ SFF8636_TX_BIAS_HALRM);
+ sd->bias_cur[LALRM] = OFFSET_TO_U16_PTR(map->page_03h,
+ SFF8636_TX_BIAS_LALRM);
+ sd->bias_cur[HWARN] = OFFSET_TO_U16_PTR(map->page_03h,
+ SFF8636_TX_BIAS_HWARN);
+ sd->bias_cur[LWARN] = OFFSET_TO_U16_PTR(map->page_03h,
+ SFF8636_TX_BIAS_LWARN);
+
+ sd->tx_power[HALRM] = OFFSET_TO_U16_PTR(map->page_03h,
+ SFF8636_TX_PWR_HALRM);
+ sd->tx_power[LALRM] = OFFSET_TO_U16_PTR(map->page_03h,
+ SFF8636_TX_PWR_LALRM);
+ sd->tx_power[HWARN] = OFFSET_TO_U16_PTR(map->page_03h,
+ SFF8636_TX_PWR_HWARN);
+ sd->tx_power[LWARN] = OFFSET_TO_U16_PTR(map->page_03h,
+ SFF8636_TX_PWR_LWARN);
+
+ sd->rx_power[HALRM] = OFFSET_TO_U16_PTR(map->page_03h,
+ SFF8636_RX_PWR_HALRM);
+ sd->rx_power[LALRM] = OFFSET_TO_U16_PTR(map->page_03h,
+ SFF8636_RX_PWR_LALRM);
+ sd->rx_power[HWARN] = OFFSET_TO_U16_PTR(map->page_03h,
+ SFF8636_RX_PWR_HWARN);
+ sd->rx_power[LWARN] = OFFSET_TO_U16_PTR(map->page_03h,
+ SFF8636_RX_PWR_LWARN);
+
+out:
/* Channel Specific Data */
for (i = 0; i < MAX_CHANNEL_NUM; i++) {
u8 rx_power_offset, tx_bias_offset;
@@ -749,7 +790,7 @@ static void sff8636_dom_parse(const __u8 *id, const __u8 *page_three, struct sff
}
}
-static void sff8636_show_dom(const __u8 *id, const __u8 *page_three, __u32 eeprom_len)
+static void sff8636_show_dom(const struct sff8636_memory_map *map)
{
struct sff_diags sd = {0};
char *rx_power_string = NULL;
@@ -763,20 +804,15 @@ static void sff8636_show_dom(const __u8 *id, const __u8 *page_three, __u32 eepro
* and thresholds
* If pagging support exists, then supports_alarms is marked as 1
*/
+ if (map->page_03h)
+ sd.supports_alarms = 1;
- if (eeprom_len == ETH_MODULE_SFF_8636_MAX_LEN) {
- if (!(id[SFF8636_STATUS_2_OFFSET] &
- SFF8636_STATUS_PAGE_3_PRESENT)) {
- sd.supports_alarms = 1;
- }
- }
+ sd.rx_power_type = map->page_00h[SFF8636_DIAG_TYPE_OFFSET] &
+ SFF8636_RX_PWR_TYPE_MASK;
+ sd.tx_power_type = map->page_00h[SFF8636_DIAG_TYPE_OFFSET] &
+ SFF8636_RX_PWR_TYPE_MASK;
- sd.rx_power_type = id[SFF8636_DIAG_TYPE_OFFSET] &
- SFF8636_RX_PWR_TYPE_MASK;
- sd.tx_power_type = id[SFF8636_DIAG_TYPE_OFFSET] &
- SFF8636_RX_PWR_TYPE_MASK;
-
- sff8636_dom_parse(id, page_three, &sd);
+ sff8636_dom_parse(map, &sd);
PRINT_TEMP("Module temperature", sd.sfp_temp[MCURR]);
PRINT_VCC("Module voltage", sd.sfp_voltage[MCURR]);
@@ -819,7 +855,7 @@ static void sff8636_show_dom(const __u8 *id, const __u8 *page_three, __u32 eepro
if (sd.supports_alarms) {
for (i = 0; sff8636_aw_flags[i].str; ++i) {
printf("\t%-41s : %s\n", sff8636_aw_flags[i].str,
- id[sff8636_aw_flags[i].offset]
+ map->lower_memory[sff8636_aw_flags[i].offset]
& sff8636_aw_flags[i].value ? "On" : "Off");
}
@@ -827,39 +863,39 @@ static void sff8636_show_dom(const __u8 *id, const __u8 *page_three, __u32 eepro
}
}
-static void sff8636_show_page_zero(const __u8 *id)
+static void sff8636_show_page_zero(const struct sff8636_memory_map *map)
{
- sff8636_show_ext_identifier(id);
- sff8636_show_connector(id);
- sff8636_show_transceiver(id);
- sff8636_show_encoding(id);
- sff_show_value_with_unit(id, SFF8636_BR_NOMINAL_OFFSET,
- "BR, Nominal", 100, "Mbps");
- sff8636_show_rate_identifier(id);
- sff_show_value_with_unit(id, SFF8636_SM_LEN_OFFSET,
- "Length (SMF,km)", 1, "km");
- sff_show_value_with_unit(id, SFF8636_OM3_LEN_OFFSET,
- "Length (OM3 50um)", 2, "m");
- sff_show_value_with_unit(id, SFF8636_OM2_LEN_OFFSET,
- "Length (OM2 50um)", 1, "m");
- sff_show_value_with_unit(id, SFF8636_OM1_LEN_OFFSET,
- "Length (OM1 62.5um)", 1, "m");
- sff_show_value_with_unit(id, SFF8636_CBL_LEN_OFFSET,
- "Length (Copper or Active cable)", 1, "m");
- sff8636_show_wavelength_or_copper_compliance(id);
- sff_show_ascii(id, SFF8636_VENDOR_NAME_START_OFFSET,
+ sff8636_show_ext_identifier(map);
+ sff8636_show_connector(map);
+ sff8636_show_transceiver(map);
+ sff8636_show_encoding(map);
+ sff_show_value_with_unit(map->page_00h, SFF8636_BR_NOMINAL_OFFSET,
+ "BR, Nominal", 100, "Mbps");
+ sff8636_show_rate_identifier(map);
+ sff_show_value_with_unit(map->page_00h, SFF8636_SM_LEN_OFFSET,
+ "Length (SMF,km)", 1, "km");
+ sff_show_value_with_unit(map->page_00h, SFF8636_OM3_LEN_OFFSET,
+ "Length (OM3 50um)", 2, "m");
+ sff_show_value_with_unit(map->page_00h, SFF8636_OM2_LEN_OFFSET,
+ "Length (OM2 50um)", 1, "m");
+ sff_show_value_with_unit(map->page_00h, SFF8636_OM1_LEN_OFFSET,
+ "Length (OM1 62.5um)", 1, "m");
+ sff_show_value_with_unit(map->page_00h, SFF8636_CBL_LEN_OFFSET,
+ "Length (Copper or Active cable)", 1, "m");
+ sff8636_show_wavelength_or_copper_compliance(map);
+ sff_show_ascii(map->page_00h, SFF8636_VENDOR_NAME_START_OFFSET,
SFF8636_VENDOR_NAME_END_OFFSET, "Vendor name");
- sff8636_show_oui(id, SFF8636_VENDOR_OUI_OFFSET);
- sff_show_ascii(id, SFF8636_VENDOR_PN_START_OFFSET,
+ sff8024_show_oui(map->page_00h, SFF8636_VENDOR_OUI_OFFSET);
+ sff_show_ascii(map->page_00h, SFF8636_VENDOR_PN_START_OFFSET,
SFF8636_VENDOR_PN_END_OFFSET, "Vendor PN");
- sff_show_ascii(id, SFF8636_VENDOR_REV_START_OFFSET,
+ sff_show_ascii(map->page_00h, SFF8636_VENDOR_REV_START_OFFSET,
SFF8636_VENDOR_REV_END_OFFSET, "Vendor rev");
- sff_show_ascii(id, SFF8636_VENDOR_SN_START_OFFSET,
+ sff_show_ascii(map->page_00h, SFF8636_VENDOR_SN_START_OFFSET,
SFF8636_VENDOR_SN_END_OFFSET, "Vendor SN");
- sff_show_ascii(id, SFF8636_DATE_YEAR_OFFSET,
+ sff_show_ascii(map->page_00h, SFF8636_DATE_YEAR_OFFSET,
SFF8636_DATE_VENDOR_LOT_OFFSET + 1, "Date code");
- sff8636_show_revision_compliance(id);
-
+ sff_show_revision_compliance(map->lower_memory,
+ SFF8636_REV_COMPLIANCE_OFFSET);
}
static void sff8636_memory_map_init_buf(struct sff8636_memory_map *map,
@@ -896,13 +932,13 @@ void sff8636_show_all_ioctl(const __u8 *id, __u32 eeprom_len)
sff8636_memory_map_init_buf(&map, id, eeprom_len);
- sff8636_show_identifier(id);
- switch (id[SFF8636_ID_OFFSET]) {
+ sff8636_show_identifier(&map);
+ switch (map.lower_memory[SFF8636_ID_OFFSET]) {
case SFF8024_ID_QSFP:
case SFF8024_ID_QSFP_PLUS:
case SFF8024_ID_QSFP28:
- sff8636_show_page_zero(id);
- sff8636_show_dom(id, id + 3 * 0x80, eeprom_len);
+ sff8636_show_page_zero(&map);
+ sff8636_show_dom(&map);
break;
}
}
@@ -939,9 +975,7 @@ void sff8636_show_all_nl(const struct ethtool_module_eeprom *page_zero,
sff8636_memory_map_init_pages(&map, page_zero, page_three);
- sff8636_show_identifier(page_zero->data);
- sff8636_show_page_zero(page_zero->data);
- if (page_three)
- sff8636_show_dom(page_zero->data, page_three->data - 0x80,
- ETH_MODULE_SFF_8636_MAX_LEN);
+ sff8636_show_identifier(&map);
+ sff8636_show_page_zero(&map);
+ sff8636_show_dom(&map);
}
--
2.35.1

View File

@ -0,0 +1,73 @@
From 2e122ad9aa2aa0259df1035e3ec2765d8e008394 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:19 +0300
Subject: [PATCH 20/35] sff-8636: Consolidate code between IOCTL and netlink
paths
Now that both the netlink and IOCTL paths use the same memory map
structure for parsing, the code can be easily consolidated.
Note that the switch-case statement is not necessary for the netlink
path, as the netlink code (i.e., netlink/module-eeprom.c) already
performed the check, but it is required for the IOCTL path.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
qsfp.c | 29 +++++++++++++++--------------
1 file changed, 15 insertions(+), 14 deletions(-)
diff --git a/qsfp.c b/qsfp.c
index 354b3b1ce9ff..4aa49351e6b7 100644
--- a/qsfp.c
+++ b/qsfp.c
@@ -898,6 +898,19 @@ static void sff8636_show_page_zero(const struct sff8636_memory_map *map)
SFF8636_REV_COMPLIANCE_OFFSET);
}
+static void sff8636_show_all_common(const struct sff8636_memory_map *map)
+{
+ sff8636_show_identifier(map);
+ switch (map->lower_memory[SFF8636_ID_OFFSET]) {
+ case SFF8024_ID_QSFP:
+ case SFF8024_ID_QSFP_PLUS:
+ case SFF8024_ID_QSFP28:
+ sff8636_show_page_zero(map);
+ sff8636_show_dom(map);
+ break;
+ }
+}
+
static void sff8636_memory_map_init_buf(struct sff8636_memory_map *map,
const __u8 *id, __u32 eeprom_len)
{
@@ -931,16 +944,7 @@ void sff8636_show_all_ioctl(const __u8 *id, __u32 eeprom_len)
}
sff8636_memory_map_init_buf(&map, id, eeprom_len);
-
- sff8636_show_identifier(&map);
- switch (map.lower_memory[SFF8636_ID_OFFSET]) {
- case SFF8024_ID_QSFP:
- case SFF8024_ID_QSFP_PLUS:
- case SFF8024_ID_QSFP28:
- sff8636_show_page_zero(&map);
- sff8636_show_dom(&map);
- break;
- }
+ sff8636_show_all_common(&map);
}
static void
@@ -974,8 +978,5 @@ void sff8636_show_all_nl(const struct ethtool_module_eeprom *page_zero,
struct sff8636_memory_map map = {};
sff8636_memory_map_init_pages(&map, page_zero, page_three);
-
- sff8636_show_identifier(&map);
- sff8636_show_page_zero(&map);
- sff8636_show_dom(&map);
+ sff8636_show_all_common(&map);
}
--
2.35.1

View File

@ -0,0 +1,101 @@
From 1f20fb8e8b94d049672e48388ae57f89e89e880b Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:20 +0300
Subject: [PATCH 21/35] sff-8079: Split SFF-8079 parsing function
SFF-8079, unlike CMIS and SFF-8636, only has a single page and therefore
its parsing function (i.e., sff8079_show_all()) is called from both the
IOCTL and netlink paths with a buffer pointing to that single page.
In future patches, the netlink code (i.e., netlink/module-eeprom.c) will
no longer call the SFF-8079 code with a buffer pointing to the first 128
bytes of the EEPROM. Instead, the SFF-8079 code will need to request the
needed EEPROM data, as will be done in CMIS and SFF-8636.
Therefore, as a preparation for this change, split the main parsing
function into IOCTL and netlink variants.
No functional changes intended.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
ethtool.c | 4 ++--
internal.h | 3 ++-
netlink/module-eeprom.c | 2 +-
sfpid.c | 12 +++++++++++-
4 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/ethtool.c b/ethtool.c
index 6c744ff84eb9..5d4b5afbfd47 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -4900,10 +4900,10 @@ static int do_getmodule(struct cmd_context *ctx)
switch (modinfo.type) {
#ifdef ETHTOOL_ENABLE_PRETTY_DUMP
case ETH_MODULE_SFF_8079:
- sff8079_show_all(eeprom->data);
+ sff8079_show_all_ioctl(eeprom->data);
break;
case ETH_MODULE_SFF_8472:
- sff8079_show_all(eeprom->data);
+ sff8079_show_all_ioctl(eeprom->data);
sff8472_show_all(eeprom->data);
break;
case ETH_MODULE_SFF_8436:
diff --git a/internal.h b/internal.h
index 7ca6066d4e12..a77efd385698 100644
--- a/internal.h
+++ b/internal.h
@@ -384,7 +384,8 @@ int rxclass_rule_ins(struct cmd_context *ctx,
int rxclass_rule_del(struct cmd_context *ctx, __u32 loc);
/* Module EEPROM parsing code */
-void sff8079_show_all(const __u8 *id);
+void sff8079_show_all_ioctl(const __u8 *id);
+void sff8079_show_all_nl(const __u8 *id);
/* Optics diagnostics */
void sff8472_show_all(const __u8 *id);
diff --git a/netlink/module-eeprom.c b/netlink/module-eeprom.c
index 18b1abbe1252..101d5943c2bc 100644
--- a/netlink/module-eeprom.c
+++ b/netlink/module-eeprom.c
@@ -323,7 +323,7 @@ static void decoder_print(void)
switch (module_id) {
case SFF8024_ID_SFP:
- sff8079_show_all(page_zero->data);
+ sff8079_show_all_nl(page_zero->data);
break;
case SFF8024_ID_QSFP:
case SFF8024_ID_QSFP28:
diff --git a/sfpid.c b/sfpid.c
index da2b3f4df3d2..c214820226d1 100644
--- a/sfpid.c
+++ b/sfpid.c
@@ -396,7 +396,7 @@ static void sff8079_show_options(const __u8 *id)
printf("%s Power level 3 requirement\n", pfx);
}
-void sff8079_show_all(const __u8 *id)
+static void sff8079_show_all_common(const __u8 *id)
{
sff8079_show_identifier(id);
if (((id[0] == 0x02) || (id[0] == 0x03)) && (id[1] == 0x04)) {
@@ -439,3 +439,13 @@ void sff8079_show_all(const __u8 *id)
sff8079_show_ascii(id, 84, 91, "Date code");
}
}
+
+void sff8079_show_all_ioctl(const __u8 *id)
+{
+ sff8079_show_all_common(id);
+}
+
+void sff8079_show_all_nl(const __u8 *id)
+{
+ sff8079_show_all_common(id);
+}
--
2.35.1

View File

@ -0,0 +1,174 @@
From fdb457a0ebb57c99fb987d0e34b2549f10dd4161 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:21 +0300
Subject: [PATCH 22/35] netlink: eeprom: Export a function to request an EEPROM
page
The function will be used by the EEPROM parsing code (e.g., cmis.c) to
request a specific page for parsing.
All the data buffers used to store EEPROM page contents are stored on a
linked list that is flushed on exit. This relieves callers from the need
to explicitly free the requested pages.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
netlink/extapi.h | 11 +++++
netlink/module-eeprom.c | 105 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 116 insertions(+)
diff --git a/netlink/extapi.h b/netlink/extapi.h
index 91bf02b5e3be..129e2931d01d 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -48,6 +48,9 @@ int nl_getmodule(struct cmd_context *ctx);
void nl_monitor_usage(void);
+int nl_get_eeprom_page(struct cmd_context *ctx,
+ struct ethtool_module_eeprom *request);
+
#else /* ETHTOOL_ENABLE_NETLINK */
static inline void netlink_run_handler(struct cmd_context *ctx __maybe_unused,
@@ -73,6 +76,14 @@ static inline void nl_monitor_usage(void)
{
}
+static inline int
+nl_get_eeprom_page(struct cmd_context *ctx __maybe_unused,
+ struct ethtool_module_eeprom *request __maybe_unused)
+{
+ fprintf(stderr, "Netlink not supported by ethtool.\n");
+ return -EOPNOTSUPP;
+}
+
#define nl_gset NULL
#define nl_sset NULL
#define nl_permaddr NULL
diff --git a/netlink/module-eeprom.c b/netlink/module-eeprom.c
index 101d5943c2bc..ee5508840157 100644
--- a/netlink/module-eeprom.c
+++ b/netlink/module-eeprom.c
@@ -341,6 +341,110 @@ static void decoder_print(void)
}
#endif
+static struct list_head eeprom_page_list = LIST_HEAD_INIT(eeprom_page_list);
+
+struct eeprom_page_entry {
+ struct list_head list; /* Member of eeprom_page_list */
+ void *data;
+};
+
+static int eeprom_page_list_add(void *data)
+{
+ struct eeprom_page_entry *entry;
+
+ entry = malloc(sizeof(*entry));
+ if (!entry)
+ return -ENOMEM;
+
+ entry->data = data;
+ list_add(&entry->list, &eeprom_page_list);
+
+ return 0;
+}
+
+static void eeprom_page_list_flush(void)
+{
+ struct eeprom_page_entry *entry;
+ struct list_head *head, *next;
+
+ list_for_each_safe(head, next, &eeprom_page_list) {
+ entry = (struct eeprom_page_entry *) head;
+ free(entry->data);
+ list_del(head);
+ free(entry);
+ }
+}
+
+static int get_eeprom_page_reply_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+ const struct nlattr *tb[ETHTOOL_A_MODULE_EEPROM_DATA + 1] = {};
+ struct ethtool_module_eeprom *request = data;
+ DECLARE_ATTR_TB_INFO(tb);
+ u8 *eeprom_data;
+ int ret;
+
+ ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
+ if (ret < 0)
+ return ret;
+
+ if (!tb[ETHTOOL_A_MODULE_EEPROM_DATA])
+ return MNL_CB_ERROR;
+
+ eeprom_data = mnl_attr_get_payload(tb[ETHTOOL_A_MODULE_EEPROM_DATA]);
+ request->data = malloc(request->length);
+ if (!request->data)
+ return MNL_CB_ERROR;
+ memcpy(request->data, eeprom_data, request->length);
+
+ ret = eeprom_page_list_add(request->data);
+ if (ret < 0)
+ goto err_list_add;
+
+ return MNL_CB_OK;
+
+err_list_add:
+ free(request->data);
+ return MNL_CB_ERROR;
+}
+
+int nl_get_eeprom_page(struct cmd_context *ctx,
+ struct ethtool_module_eeprom *request)
+{
+ struct nl_context *nlctx = ctx->nlctx;
+ struct nl_socket *nlsock;
+ struct nl_msg_buff *msg;
+ int ret;
+
+ if (!request || request->i2c_address > ETH_I2C_MAX_ADDRESS)
+ return -EINVAL;
+
+ nlsock = nlctx->ethnl_socket;
+ msg = &nlsock->msgbuff;
+
+ ret = nlsock_prep_get_request(nlsock, ETHTOOL_MSG_MODULE_EEPROM_GET,
+ ETHTOOL_A_MODULE_EEPROM_HEADER, 0);
+ if (ret < 0)
+ return ret;
+
+ if (ethnla_put_u32(msg, ETHTOOL_A_MODULE_EEPROM_LENGTH,
+ request->length) ||
+ ethnla_put_u32(msg, ETHTOOL_A_MODULE_EEPROM_OFFSET,
+ request->offset) ||
+ ethnla_put_u8(msg, ETHTOOL_A_MODULE_EEPROM_PAGE,
+ request->page) ||
+ ethnla_put_u8(msg, ETHTOOL_A_MODULE_EEPROM_BANK,
+ request->bank) ||
+ ethnla_put_u8(msg, ETHTOOL_A_MODULE_EEPROM_I2C_ADDRESS,
+ request->i2c_address))
+ return -EMSGSIZE;
+
+ ret = nlsock_sendmsg(nlsock, NULL);
+ if (ret < 0)
+ return ret;
+ return nlsock_process_reply(nlsock, get_eeprom_page_reply_cb,
+ (void *)request);
+}
+
int nl_getmodule(struct cmd_context *ctx)
{
struct cmd_params getmodule_cmd_params = {};
@@ -425,6 +529,7 @@ int nl_getmodule(struct cmd_context *ctx)
}
cleanup:
+ eeprom_page_list_flush();
cache_free();
return ret;
}
--
2.35.1

View File

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

View File

@ -0,0 +1,181 @@
From fdae2732b25090f9d41e192a5dd47a45a6516a94 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:23 +0300
Subject: [PATCH 24/35] sff-8636: Request specific pages for parsing in netlink
path
In the netlink path, unlike the IOCTL path, user space requests specific
EEPROM pages from the kernel. The presence of optional pages is
advertised via various bits in the EEPROM contents.
Currently, for SFF-8636, the Lower Memory, Page 00h and the optional
Page 03h are requested by the netlink code (i.e.,
netlink/module-eeprom.c) and passed to the SFF-8636 code (i.e., qsfp.c)
as two arguments for parsing.
This is problematic for several reasons. First, this approach is not
very scaleable as SFF-8636 supports a lot of optional pages. Passing
them as separate arguments to the SFF-8636 code is not going to work.
Second, the knowledge of which optional pages are available is
encapsulated in the SFF-8636 parsing code. As such, the common netlink
code has no business of fetching optional pages that might be invalid.
Instead, pass the command context to the SFF-8636 parsing function and
allow it to fetch only valid pages via the 'MODULE_EEPROM_GET' netlink
message.
Tested by making sure that the output of 'ethtool -m' does not change
before and after the patch.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
internal.h | 3 +--
netlink/module-eeprom.c | 3 +--
qsfp.c | 60 ++++++++++++++++++++++++++++++++---------
3 files changed, 49 insertions(+), 17 deletions(-)
diff --git a/internal.h b/internal.h
index a77efd385698..2407d3c223fa 100644
--- a/internal.h
+++ b/internal.h
@@ -392,8 +392,7 @@ void sff8472_show_all(const __u8 *id);
/* QSFP Optics diagnostics */
void sff8636_show_all_ioctl(const __u8 *id, __u32 eeprom_len);
-void sff8636_show_all_nl(const struct ethtool_module_eeprom *page_zero,
- const struct ethtool_module_eeprom *page_three);
+int sff8636_show_all_nl(struct cmd_context *ctx);
/* 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 a8e2662e0b8c..f04f8e134223 100644
--- a/netlink/module-eeprom.c
+++ b/netlink/module-eeprom.c
@@ -316,7 +316,6 @@ static int decoder_prefetch(struct nl_context *nlctx)
static void decoder_print(struct cmd_context *ctx)
{
- struct ethtool_module_eeprom *page_three = cache_get(3, 0, ETH_I2C_ADDRESS_LOW);
struct ethtool_module_eeprom *page_zero = cache_get(0, 0, ETH_I2C_ADDRESS_LOW);
u8 module_id = page_zero->data[SFF8636_ID_OFFSET];
@@ -327,7 +326,7 @@ static void decoder_print(struct cmd_context *ctx)
case SFF8024_ID_QSFP:
case SFF8024_ID_QSFP28:
case SFF8024_ID_QSFP_PLUS:
- sff8636_show_all_nl(page_zero, page_three);
+ sff8636_show_all_nl(ctx);
break;
case SFF8024_ID_QSFP_DD:
case SFF8024_ID_DSFP:
diff --git a/qsfp.c b/qsfp.c
index 4aa49351e6b7..e7c2f51cd9c6 100644
--- a/qsfp.c
+++ b/qsfp.c
@@ -55,10 +55,12 @@
**/
#include <stdio.h>
#include <math.h>
+#include <errno.h>
#include "internal.h"
#include "sff-common.h"
#include "qsfp.h"
#include "cmis.h"
+#include "netlink/extapi.h"
struct sff8636_memory_map {
const __u8 *lower_memory;
@@ -68,6 +70,7 @@ struct sff8636_memory_map {
};
#define SFF8636_PAGE_SIZE 0x80
+#define SFF8636_I2C_ADDRESS 0x50
#define MAX_DESC_SIZE 42
@@ -947,36 +950,67 @@ void sff8636_show_all_ioctl(const __u8 *id, __u32 eeprom_len)
sff8636_show_all_common(&map);
}
-static void
-sff8636_memory_map_init_pages(struct sff8636_memory_map *map,
- const struct ethtool_module_eeprom *page_zero,
- const struct ethtool_module_eeprom *page_three)
+static void sff8636_request_init(struct ethtool_module_eeprom *request, u8 page,
+ u32 offset)
+{
+ request->offset = offset;
+ request->length = SFF8636_PAGE_SIZE;
+ request->page = page;
+ request->bank = 0;
+ request->i2c_address = SFF8636_I2C_ADDRESS;
+ request->data = NULL;
+}
+
+static int
+sff8636_memory_map_init_pages(struct cmd_context *ctx,
+ struct sff8636_memory_map *map)
{
+ struct ethtool_module_eeprom request;
+ int ret;
+
/* Lower Memory and Page 00h are always present.
*
* Offset into Upper Memory is between page size and twice the page
* size. Therefore, set the base address of each page to its base
- * address minus page size. For Page 00h, this is the address of the
- * Lower Memory.
+ * address minus page size.
*/
- map->lower_memory = page_zero->data;
- map->page_00h = page_zero->data;
+ sff8636_request_init(&request, 0x0, 0);
+ ret = nl_get_eeprom_page(ctx, &request);
+ if (ret < 0)
+ return ret;
+ map->lower_memory = request.data;
+
+ sff8636_request_init(&request, 0x0, SFF8636_PAGE_SIZE);
+ ret = nl_get_eeprom_page(ctx, &request);
+ if (ret < 0)
+ return ret;
+ map->page_00h = request.data - SFF8636_PAGE_SIZE;
/* Page 03h is only present when the module memory model is paged and
* not flat.
*/
if (map->lower_memory[SFF8636_STATUS_2_OFFSET] &
SFF8636_STATUS_PAGE_3_PRESENT)
- return;
+ return 0;
- map->page_03h = page_three->data - SFF8636_PAGE_SIZE;
+ sff8636_request_init(&request, 0x3, SFF8636_PAGE_SIZE);
+ ret = nl_get_eeprom_page(ctx, &request);
+ if (ret < 0)
+ return ret;
+ map->page_03h = request.data - SFF8636_PAGE_SIZE;
+
+ return 0;
}
-void sff8636_show_all_nl(const struct ethtool_module_eeprom *page_zero,
- const struct ethtool_module_eeprom *page_three)
+int sff8636_show_all_nl(struct cmd_context *ctx)
{
struct sff8636_memory_map map = {};
+ int ret;
- sff8636_memory_map_init_pages(&map, page_zero, page_three);
+ ret = sff8636_memory_map_init_pages(ctx, &map);
+ if (ret < 0)
+ return ret;
sff8636_show_all_common(&map);
+
+ return 0;
}
--
2.35.1

View File

@ -0,0 +1,92 @@
From bda06d81f41bb1cde16a319728d479cda4b9f295 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:24 +0300
Subject: [PATCH 25/35] sff-8079: Request specific pages for parsing in netlink
path
Convert the SFF-8079 code to request the required EEPROM contents in the
netlink path as was done for CMIS and SFF-8636. It will allow us to
remove standard-specific code from the netlink code (i.e.,
netlink/module-eeprom.c).
In addition, in the future, it will allow the netlink path to support
parsing of SFF-8472.
Tested by making sure that the output of 'ethtool -m' does not change
before and after the patch.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
internal.h | 2 +-
netlink/module-eeprom.c | 2 +-
sfpid.c | 20 ++++++++++++++++++--
3 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/internal.h b/internal.h
index 2407d3c223fa..0d9d816ab563 100644
--- a/internal.h
+++ b/internal.h
@@ -385,7 +385,7 @@ int rxclass_rule_del(struct cmd_context *ctx, __u32 loc);
/* Module EEPROM parsing code */
void sff8079_show_all_ioctl(const __u8 *id);
-void sff8079_show_all_nl(const __u8 *id);
+int sff8079_show_all_nl(struct cmd_context *ctx);
/* Optics diagnostics */
void sff8472_show_all(const __u8 *id);
diff --git a/netlink/module-eeprom.c b/netlink/module-eeprom.c
index f04f8e134223..6d76b8a96461 100644
--- a/netlink/module-eeprom.c
+++ b/netlink/module-eeprom.c
@@ -321,7 +321,7 @@ static void decoder_print(struct cmd_context *ctx)
switch (module_id) {
case SFF8024_ID_SFP:
- sff8079_show_all_nl(page_zero->data);
+ sff8079_show_all_nl(ctx);
break;
case SFF8024_ID_QSFP:
case SFF8024_ID_QSFP28:
diff --git a/sfpid.c b/sfpid.c
index c214820226d1..621d1e86c278 100644
--- a/sfpid.c
+++ b/sfpid.c
@@ -8,8 +8,13 @@
*/
#include <stdio.h>
+#include <errno.h>
#include "internal.h"
#include "sff-common.h"
+#include "netlink/extapi.h"
+
+#define SFF8079_PAGE_SIZE 0x80
+#define SFF8079_I2C_ADDRESS_LOW 0x50
static void sff8079_show_identifier(const __u8 *id)
{
@@ -445,7 +450,18 @@ void sff8079_show_all_ioctl(const __u8 *id)
sff8079_show_all_common(id);
}
-void sff8079_show_all_nl(const __u8 *id)
+int sff8079_show_all_nl(struct cmd_context *ctx)
{
- sff8079_show_all_common(id);
+ struct ethtool_module_eeprom request = {
+ .length = SFF8079_PAGE_SIZE,
+ .i2c_address = SFF8079_I2C_ADDRESS_LOW,
+ };
+ int ret;
+
+ ret = nl_get_eeprom_page(ctx, &request);
+ if (ret < 0)
+ return ret;
+ sff8079_show_all_common(request.data);
+
+ return 0;
}
--
2.35.1

View File

@ -0,0 +1,428 @@
From b6005ecf2ce2aaeb86995fa50df97e7384f46f99 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:25 +0300
Subject: [PATCH 26/35] netlink: eeprom: Defer page requests to individual
parsers
The individual EEPROM parsers (e.g., CMIS, SFF-8636) now request the
EEPROM pages they intend to parse and populate their memory maps before
parsing them.
Therefore, there is no need for the common netlink code to request
potentially invalid pages and pass them as blobs to these parsers.
Instead, only query the SFF-8024 Identifier Value which is located at
I2C address 0x50, byte 0 and dispatch to the relevant EEPROM parser.
Tested by making sure that the output of 'ethtool -m' does not change
for SFF-8079, SFF-8636 and CMIS before and after the patch.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
netlink/module-eeprom.c | 347 +++++++---------------------------------
1 file changed, 59 insertions(+), 288 deletions(-)
diff --git a/netlink/module-eeprom.c b/netlink/module-eeprom.c
index 6d76b8a96461..f359aeec4ddf 100644
--- a/netlink/module-eeprom.c
+++ b/netlink/module-eeprom.c
@@ -19,7 +19,6 @@
#include "parser.h"
#define ETH_I2C_ADDRESS_LOW 0x50
-#define ETH_I2C_ADDRESS_HIGH 0x51
#define ETH_I2C_MAX_ADDRESS 0x7F
struct cmd_params {
@@ -78,267 +77,6 @@ static const struct param_parser getmodule_params[] = {
{}
};
-struct page_entry {
- struct list_head link;
- struct ethtool_module_eeprom *page;
-};
-
-static struct list_head page_list = LIST_HEAD_INIT(page_list);
-
-static int cache_add(struct ethtool_module_eeprom *page)
-{
- struct page_entry *list_element;
-
- if (!page)
- return -1;
- list_element = malloc(sizeof(*list_element));
- if (!list_element)
- return -ENOMEM;
- list_element->page = page;
-
- list_add(&list_element->link, &page_list);
- return 0;
-}
-
-static void page_free(struct ethtool_module_eeprom *page)
-{
- free(page->data);
- free(page);
-}
-
-static void cache_del(struct ethtool_module_eeprom *page)
-{
- struct ethtool_module_eeprom *entry;
- struct list_head *head, *next;
-
- list_for_each_safe(head, next, &page_list) {
- entry = ((struct page_entry *)head)->page;
- if (entry == page) {
- list_del(head);
- free(head);
- page_free(entry);
- break;
- }
- }
-}
-
-static void cache_free(void)
-{
- struct ethtool_module_eeprom *entry;
- struct list_head *head, *next;
-
- list_for_each_safe(head, next, &page_list) {
- entry = ((struct page_entry *)head)->page;
- list_del(head);
- free(head);
- page_free(entry);
- }
-}
-
-static struct ethtool_module_eeprom *page_join(struct ethtool_module_eeprom *page_a,
- struct ethtool_module_eeprom *page_b)
-{
- struct ethtool_module_eeprom *joined_page;
- u32 total_length;
-
- if (!page_a || !page_b ||
- page_a->page != page_b->page ||
- page_a->bank != page_b->bank ||
- page_a->i2c_address != page_b->i2c_address)
- return NULL;
-
- total_length = page_a->length + page_b->length;
- joined_page = calloc(1, sizeof(*joined_page));
- joined_page->data = calloc(1, total_length);
- joined_page->page = page_a->page;
- joined_page->bank = page_a->bank;
- joined_page->length = total_length;
- joined_page->i2c_address = page_a->i2c_address;
-
- if (page_a->offset < page_b->offset) {
- memcpy(joined_page->data, page_a->data, page_a->length);
- memcpy(joined_page->data + page_a->length, page_b->data, page_b->length);
- joined_page->offset = page_a->offset;
- } else {
- memcpy(joined_page->data, page_b->data, page_b->length);
- memcpy(joined_page->data + page_b->length, page_a->data, page_a->length);
- joined_page->offset = page_b->offset;
- }
-
- return joined_page;
-}
-
-static struct ethtool_module_eeprom *cache_get(u32 page, u32 bank, u8 i2c_address)
-{
- struct ethtool_module_eeprom *entry;
- struct list_head *head, *next;
-
- list_for_each_safe(head, next, &page_list) {
- entry = ((struct page_entry *)head)->page;
- if (entry->page == page && entry->bank == bank &&
- entry->i2c_address == i2c_address)
- return entry;
- }
-
- return NULL;
-}
-
-static int getmodule_page_fetch_reply_cb(const struct nlmsghdr *nlhdr,
- void *data)
-{
- const struct nlattr *tb[ETHTOOL_A_MODULE_EEPROM_DATA + 1] = {};
- DECLARE_ATTR_TB_INFO(tb);
- struct ethtool_module_eeprom *lower_page;
- struct ethtool_module_eeprom *response;
- struct ethtool_module_eeprom *request;
- struct ethtool_module_eeprom *joined;
- u8 *eeprom_data;
- int ret;
-
- ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
- if (ret < 0)
- return ret;
-
- if (!tb[ETHTOOL_A_MODULE_EEPROM_DATA]) {
- fprintf(stderr, "Malformed netlink message (getmodule)\n");
- return MNL_CB_ERROR;
- }
-
- response = calloc(1, sizeof(*response));
- if (!response)
- return -ENOMEM;
-
- request = (struct ethtool_module_eeprom *)data;
- response->offset = request->offset;
- response->page = request->page;
- response->bank = request->bank;
- response->i2c_address = request->i2c_address;
- response->length = mnl_attr_get_payload_len(tb[ETHTOOL_A_MODULE_EEPROM_DATA]);
- eeprom_data = mnl_attr_get_payload(tb[ETHTOOL_A_MODULE_EEPROM_DATA]);
-
- response->data = malloc(response->length);
- if (!response->data) {
- free(response);
- return -ENOMEM;
- }
- memcpy(response->data, eeprom_data, response->length);
-
- if (!request->page) {
- lower_page = cache_get(request->page, request->bank, response->i2c_address);
- if (lower_page) {
- joined = page_join(lower_page, response);
- page_free(response);
- cache_del(lower_page);
- return cache_add(joined);
- }
- }
-
- return cache_add(response);
-}
-
-static int page_fetch(struct nl_context *nlctx, const struct ethtool_module_eeprom *request)
-{
- struct nl_socket *nlsock = nlctx->ethnl_socket;
- struct nl_msg_buff *msg = &nlsock->msgbuff;
- struct ethtool_module_eeprom *page;
- int ret;
-
- if (!request || request->i2c_address > ETH_I2C_MAX_ADDRESS)
- return -EINVAL;
-
- /* Satisfy request right away, if region is already in cache */
- page = cache_get(request->page, request->bank, request->i2c_address);
- if (page && page->offset <= request->offset &&
- page->offset + page->length >= request->offset + request->length) {
- return 0;
- }
-
- ret = nlsock_prep_get_request(nlsock, ETHTOOL_MSG_MODULE_EEPROM_GET,
- ETHTOOL_A_MODULE_EEPROM_HEADER, 0);
- if (ret < 0)
- return ret;
-
- if (ethnla_put_u32(msg, ETHTOOL_A_MODULE_EEPROM_LENGTH, request->length) ||
- ethnla_put_u32(msg, ETHTOOL_A_MODULE_EEPROM_OFFSET, request->offset) ||
- ethnla_put_u8(msg, ETHTOOL_A_MODULE_EEPROM_PAGE, request->page) ||
- ethnla_put_u8(msg, ETHTOOL_A_MODULE_EEPROM_BANK, request->bank) ||
- ethnla_put_u8(msg, ETHTOOL_A_MODULE_EEPROM_I2C_ADDRESS, request->i2c_address))
- return -EMSGSIZE;
-
- ret = nlsock_sendmsg(nlsock, NULL);
- if (ret < 0)
- return ret;
- ret = nlsock_process_reply(nlsock, getmodule_page_fetch_reply_cb, (void *)request);
- if (ret < 0)
- return ret;
-
- return nlsock_process_reply(nlsock, nomsg_reply_cb, NULL);
-}
-
-#ifdef ETHTOOL_ENABLE_PRETTY_DUMP
-static int decoder_prefetch(struct nl_context *nlctx)
-{
- struct ethtool_module_eeprom *page_zero_lower = cache_get(0, 0, ETH_I2C_ADDRESS_LOW);
- struct ethtool_module_eeprom request = {0};
- u8 module_id = page_zero_lower->data[0];
- int err = 0;
-
- /* Fetch rest of page 00 */
- request.i2c_address = ETH_I2C_ADDRESS_LOW;
- request.offset = 128;
- request.length = 128;
- err = page_fetch(nlctx, &request);
- if (err)
- return err;
-
- switch (module_id) {
- case SFF8024_ID_QSFP:
- case SFF8024_ID_QSFP28:
- case SFF8024_ID_QSFP_PLUS:
- memset(&request, 0, sizeof(request));
- request.i2c_address = ETH_I2C_ADDRESS_LOW;
- request.offset = 128;
- request.length = 128;
- request.page = 3;
- break;
- case SFF8024_ID_QSFP_DD:
- case SFF8024_ID_DSFP:
- memset(&request, 0, sizeof(request));
- request.i2c_address = ETH_I2C_ADDRESS_LOW;
- request.offset = 128;
- request.length = 128;
- request.page = 1;
- break;
- }
-
- return page_fetch(nlctx, &request);
-}
-
-static void decoder_print(struct cmd_context *ctx)
-{
- struct ethtool_module_eeprom *page_zero = cache_get(0, 0, ETH_I2C_ADDRESS_LOW);
- u8 module_id = page_zero->data[SFF8636_ID_OFFSET];
-
- switch (module_id) {
- case SFF8024_ID_SFP:
- sff8079_show_all_nl(ctx);
- break;
- case SFF8024_ID_QSFP:
- case SFF8024_ID_QSFP28:
- case SFF8024_ID_QSFP_PLUS:
- sff8636_show_all_nl(ctx);
- break;
- case SFF8024_ID_QSFP_DD:
- case SFF8024_ID_DSFP:
- cmis_show_all_nl(ctx);
- break;
- default:
- dump_hex(stdout, page_zero->data, page_zero->length, page_zero->offset);
- break;
- }
-}
-#endif
-
static struct list_head eeprom_page_list = LIST_HEAD_INIT(eeprom_page_list);
struct eeprom_page_entry {
@@ -443,14 +181,64 @@ int nl_get_eeprom_page(struct cmd_context *ctx,
(void *)request);
}
+static int eeprom_dump_hex(struct cmd_context *ctx)
+{
+ struct ethtool_module_eeprom request = {
+ .length = 128,
+ .i2c_address = ETH_I2C_ADDRESS_LOW,
+ };
+ int ret;
+
+ ret = nl_get_eeprom_page(ctx, &request);
+ if (ret < 0)
+ return ret;
+
+ dump_hex(stdout, request.data, request.length, request.offset);
+
+ return 0;
+}
+
+static int eeprom_parse(struct cmd_context *ctx)
+{
+ struct ethtool_module_eeprom request = {
+ .length = 1,
+ .i2c_address = ETH_I2C_ADDRESS_LOW,
+ };
+ int ret;
+
+ /* Fetch the SFF-8024 Identifier Value. For all supported standards, it
+ * is located at I2C address 0x50, byte 0. See section 4.1 in SFF-8024,
+ * revision 4.9.
+ */
+ ret = nl_get_eeprom_page(ctx, &request);
+ if (ret < 0)
+ return ret;
+
+ switch (request.data[0]) {
+#ifdef ETHTOOL_ENABLE_PRETTY_DUMP
+ case SFF8024_ID_SFP:
+ return sff8079_show_all_nl(ctx);
+ case SFF8024_ID_QSFP:
+ case SFF8024_ID_QSFP28:
+ case SFF8024_ID_QSFP_PLUS:
+ return sff8636_show_all_nl(ctx);
+ case SFF8024_ID_QSFP_DD:
+ case SFF8024_ID_DSFP:
+ return cmis_show_all_nl(ctx);
+#endif
+ default:
+ /* If we cannot recognize the memory map, default to dumping
+ * the first 128 bytes in hex.
+ */
+ return eeprom_dump_hex(ctx);
+ }
+}
+
int nl_getmodule(struct cmd_context *ctx)
{
struct cmd_params getmodule_cmd_params = {};
struct ethtool_module_eeprom request = {0};
- struct ethtool_module_eeprom *reply_page;
struct nl_context *nlctx = ctx->nlctx;
- u32 dump_length;
- u8 *eeprom_data;
int ret;
if (netlink_cmd_check(ctx, ETHTOOL_MSG_MODULE_EEPROM_GET, false))
@@ -479,12 +267,6 @@ int nl_getmodule(struct cmd_context *ctx)
return -EOPNOTSUPP;
}
- request.i2c_address = ETH_I2C_ADDRESS_LOW;
- request.length = 128;
- ret = page_fetch(nlctx, &request);
- if (ret)
- goto cleanup;
-
#ifdef ETHTOOL_ENABLE_PRETTY_DUMP
if (getmodule_cmd_params.page || getmodule_cmd_params.bank ||
getmodule_cmd_params.offset || getmodule_cmd_params.length)
@@ -501,33 +283,22 @@ int nl_getmodule(struct cmd_context *ctx)
request.offset = 128;
if (getmodule_cmd_params.dump_hex || getmodule_cmd_params.dump_raw) {
- ret = page_fetch(nlctx, &request);
+ ret = nl_get_eeprom_page(ctx, &request);
if (ret < 0)
goto cleanup;
- reply_page = cache_get(request.page, request.bank, request.i2c_address);
- if (!reply_page) {
- ret = -EINVAL;
- goto cleanup;
- }
- eeprom_data = reply_page->data + (request.offset - reply_page->offset);
- dump_length = reply_page->length < request.length ? reply_page->length
- : request.length;
if (getmodule_cmd_params.dump_raw)
- fwrite(eeprom_data, 1, request.length, stdout);
+ fwrite(request.data, 1, request.length, stdout);
else
- dump_hex(stdout, eeprom_data, dump_length, request.offset);
+ dump_hex(stdout, request.data, request.length,
+ request.offset);
} else {
-#ifdef ETHTOOL_ENABLE_PRETTY_DUMP
- ret = decoder_prefetch(nlctx);
- if (ret)
+ ret = eeprom_parse(ctx);
+ if (ret < 0)
goto cleanup;
- decoder_print(ctx);
-#endif
}
cleanup:
eeprom_page_list_flush();
- cache_free();
return ret;
}
--
2.35.1

View File

@ -0,0 +1,84 @@
From 37093971b0f645542c4bff603f41f807e8023bd3 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 23 Nov 2021 19:40:55 +0200
Subject: [PATCH 27/35] sff-8636: Use an SFF-8636 specific define for maximum
number of channels
'MAX_CHANNEL_NUM' is defined in the common SFF code as 4 and used to set
the size of the per-channel diagnostics array in the common 'sff_diags'
structure.
The CMIS parsing code is also going to use the structure, but it can
have up to 32 channels, unlike SFF-8636 that only has 4.
Therefore, set 'MAX_CHANNEL_NUM' to 32 and change the SFF-8636 code to
use an SFF-8636 specific define instead of the common 'MAX_CHANNEL_NUM'.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
qsfp.c | 9 +++++----
sff-common.h | 2 +-
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/qsfp.c b/qsfp.c
index e7c2f51cd9c6..58c4c4775e9b 100644
--- a/qsfp.c
+++ b/qsfp.c
@@ -71,6 +71,7 @@ struct sff8636_memory_map {
#define SFF8636_PAGE_SIZE 0x80
#define SFF8636_I2C_ADDRESS 0x50
+#define SFF8636_MAX_CHANNEL_NUM 4
#define MAX_DESC_SIZE 42
@@ -761,7 +762,7 @@ static void sff8636_dom_parse(const struct sff8636_memory_map *map,
out:
/* Channel Specific Data */
- for (i = 0; i < MAX_CHANNEL_NUM; i++) {
+ for (i = 0; i < SFF8636_MAX_CHANNEL_NUM; i++) {
u8 rx_power_offset, tx_bias_offset;
u8 tx_power_offset;
@@ -832,13 +833,13 @@ static void sff8636_show_dom(const struct sff8636_memory_map *map)
printf("\t%-41s : %s\n", "Alarm/warning flags implemented",
(sd.supports_alarms ? "Yes" : "No"));
- for (i = 0; i < MAX_CHANNEL_NUM; i++) {
+ for (i = 0; i < SFF8636_MAX_CHANNEL_NUM; i++) {
snprintf(power_string, MAX_DESC_SIZE, "%s (Channel %d)",
"Laser tx bias current", i+1);
PRINT_BIAS(power_string, sd.scd[i].bias_cur);
}
- for (i = 0; i < MAX_CHANNEL_NUM; i++) {
+ for (i = 0; i < SFF8636_MAX_CHANNEL_NUM; i++) {
snprintf(power_string, MAX_DESC_SIZE, "%s (Channel %d)",
"Transmit avg optical power", i+1);
PRINT_xX_PWR(power_string, sd.scd[i].tx_power);
@@ -849,7 +850,7 @@ static void sff8636_show_dom(const struct sff8636_memory_map *map)
else
rx_power_string = "Rcvr signal avg optical power";
- for (i = 0; i < MAX_CHANNEL_NUM; i++) {
+ for (i = 0; i < SFF8636_MAX_CHANNEL_NUM; i++) {
snprintf(power_string, MAX_DESC_SIZE, "%s(Channel %d)",
rx_power_string, i+1);
PRINT_xX_PWR(power_string, sd.scd[i].rx_power);
diff --git a/sff-common.h b/sff-common.h
index 2183f41ff9c9..aab306e0b74f 100644
--- a/sff-common.h
+++ b/sff-common.h
@@ -160,7 +160,7 @@ struct sff_channel_diags {
/* Module Monitoring Fields */
struct sff_diags {
-#define MAX_CHANNEL_NUM 4
+#define MAX_CHANNEL_NUM 32
#define LWARN 0
#define HWARN 1
#define LALRM 2
--
2.35.1

View File

@ -0,0 +1,45 @@
From 2dcf6b9dc1c1874705b9e71e13e00dde9f7f576c Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 23 Nov 2021 19:40:56 +0200
Subject: [PATCH 28/35] sff-common: Move OFFSET_TO_U16_PTR() to common header
file
The define is also useful for CMIS, so move it from SFF-8636 to the
common header file.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
qsfp.c | 1 -
sff-common.h | 4 ++--
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/qsfp.c b/qsfp.c
index 58c4c4775e9b..b3c9e1516af9 100644
--- a/qsfp.c
+++ b/qsfp.c
@@ -700,7 +700,6 @@ sff8636_show_wavelength_or_copper_compliance(const struct sff8636_memory_map *ma
* Second byte are 1/256th of degree, which are added to the dec part.
*/
#define SFF8636_OFFSET_TO_TEMP(offset) ((__s16)OFFSET_TO_U16(offset))
-#define OFFSET_TO_U16_PTR(ptr, offset) (ptr[offset] << 8 | ptr[(offset) + 1])
static void sff8636_dom_parse(const struct sff8636_memory_map *map,
struct sff_diags *sd)
diff --git a/sff-common.h b/sff-common.h
index aab306e0b74f..9e323008ba19 100644
--- a/sff-common.h
+++ b/sff-common.h
@@ -126,8 +126,8 @@
#define SFF8024_ENCODING_PAM4 0x08
/* Most common case: 16-bit unsigned integer in a certain unit */
-#define OFFSET_TO_U16(offset) \
- (id[offset] << 8 | id[(offset) + 1])
+#define OFFSET_TO_U16_PTR(ptr, offset) (ptr[offset] << 8 | ptr[(offset) + 1])
+#define OFFSET_TO_U16(offset) OFFSET_TO_U16_PTR(id, offset)
# define PRINT_xX_PWR(string, var) \
printf("\t%-41s : %.4f mW / %.2f dBm\n", (string), \
--
2.35.1

View File

@ -0,0 +1,59 @@
From 86853162d53b47cd0f6bcb926810aa0fd68b8898 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 23 Nov 2021 19:40:57 +0200
Subject: [PATCH 29/35] cmis: Initialize Page 02h in memory map
Page 02h stores module and lane thresholds that are going to be parsed
and displayed in subsequent patches.
Request it via the 'MODULE_EEPROM_GET' netlink message and initialize it
in the memory map.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
cmis.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/cmis.c b/cmis.c
index 4798fd4c7d68..55b9d1b959cd 100644
--- a/cmis.c
+++ b/cmis.c
@@ -17,9 +17,10 @@
struct cmis_memory_map {
const __u8 *lower_memory;
- const __u8 *upper_memory[1][2]; /* Bank, Page */
+ const __u8 *upper_memory[1][3]; /* Bank, Page */
#define page_00h upper_memory[0x0][0x0]
#define page_01h upper_memory[0x0][0x1]
+#define page_02h upper_memory[0x0][0x2]
};
#define CMIS_PAGE_SIZE 0x80
@@ -423,8 +424,8 @@ cmis_memory_map_init_pages(struct cmd_context *ctx,
return ret;
map->page_00h = request.data - CMIS_PAGE_SIZE;
- /* Page 01h is only present when the module memory model is paged and
- * not flat.
+ /* Pages 01h and 02h are only present when the module memory model is
+ * paged and not flat.
*/
if (map->lower_memory[CMIS_MEMORY_MODEL_OFFSET] &
CMIS_MEMORY_MODEL_MASK)
@@ -436,6 +437,12 @@ cmis_memory_map_init_pages(struct cmd_context *ctx,
return ret;
map->page_01h = request.data - CMIS_PAGE_SIZE;
+ cmis_request_init(&request, 0, 0x2, CMIS_PAGE_SIZE);
+ ret = nl_get_eeprom_page(ctx, &request);
+ if (ret < 0)
+ return ret;
+ map->page_02h = request.data - CMIS_PAGE_SIZE;
+
return 0;
}
--
2.35.1

View File

@ -0,0 +1,122 @@
From 21367ae2b8ebbe5173cbed22dfa51680a3fe48d2 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 23 Nov 2021 19:40:58 +0200
Subject: [PATCH 30/35] cmis: Initialize Banked Page 11h in memory map
Banked Page 11h stores, among other things, lane-specific flags and
monitors that are going to be parsed and displayed in subsequent
patches.
Request it via the 'MODULE_EEPROM_GET' netlink message and initialize it
in the memory map.
Only initialize it in supported Banks.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
cmis.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++--
cmis.h | 7 +++++++
2 files changed, 54 insertions(+), 2 deletions(-)
diff --git a/cmis.c b/cmis.c
index 55b9d1b959cd..83ced4d253ae 100644
--- a/cmis.c
+++ b/cmis.c
@@ -15,9 +15,17 @@
#include "cmis.h"
#include "netlink/extapi.h"
+/* The maximum number of supported Banks. Relevant documents:
+ * [1] CMIS Rev. 5, page. 128, section 8.4.4, Table 8-40
+ */
+#define CMIS_MAX_BANKS 4
+
+/* We are not parsing further than Page 11h. */
+#define CMIS_MAX_PAGES 18
+
struct cmis_memory_map {
const __u8 *lower_memory;
- const __u8 *upper_memory[1][3]; /* Bank, Page */
+ const __u8 *upper_memory[CMIS_MAX_BANKS][CMIS_MAX_PAGES];
#define page_00h upper_memory[0x0][0x0]
#define page_01h upper_memory[0x0][0x1]
#define page_02h upper_memory[0x0][0x2]
@@ -399,12 +407,33 @@ static void cmis_request_init(struct ethtool_module_eeprom *request, u8 bank,
request->data = NULL;
}
+static int cmis_num_banks_get(const struct cmis_memory_map *map,
+ int *p_num_banks)
+{
+ switch (map->page_01h[CMIS_PAGES_ADVER_OFFSET] &
+ CMIS_BANKS_SUPPORTED_MASK) {
+ case CMIS_BANK_0_SUPPORTED:
+ *p_num_banks = 1;
+ break;
+ case CMIS_BANK_0_1_SUPPORTED:
+ *p_num_banks = 2;
+ break;
+ case CMIS_BANK_0_3_SUPPORTED:
+ *p_num_banks = 4;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int
cmis_memory_map_init_pages(struct cmd_context *ctx,
struct cmis_memory_map *map)
{
struct ethtool_module_eeprom request;
- int ret;
+ int num_banks, i, ret;
/* Lower Memory and Page 00h are always present.
*
@@ -443,6 +472,22 @@ cmis_memory_map_init_pages(struct cmd_context *ctx,
return ret;
map->page_02h = request.data - CMIS_PAGE_SIZE;
+ /* Bank 0 of Page 11h provides lane-specific registers for the first 8
+ * lanes, and each additional Banks provides support for an additional
+ * 8 lanes. Only initialize supported Banks.
+ */
+ ret = cmis_num_banks_get(map, &num_banks);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < num_banks; i++) {
+ cmis_request_init(&request, i, 0x11, CMIS_PAGE_SIZE);
+ ret = nl_get_eeprom_page(ctx, &request);
+ if (ret < 0)
+ return ret;
+ map->upper_memory[i][0x11] = request.data - CMIS_PAGE_SIZE;
+ }
+
return 0;
}
diff --git a/cmis.h b/cmis.h
index 911491dc5c8f..8d90a04756ad 100644
--- a/cmis.h
+++ b/cmis.h
@@ -114,6 +114,13 @@
#define CMIS_WAVELENGTH_TOL_MSB 0x8C
#define CMIS_WAVELENGTH_TOL_LSB 0x8D
+/* Supported Pages Advertising (Page 1) */
+#define CMIS_PAGES_ADVER_OFFSET 0x8E
+#define CMIS_BANKS_SUPPORTED_MASK 0x03
+#define CMIS_BANK_0_SUPPORTED 0x00
+#define CMIS_BANK_0_1_SUPPORTED 0x01
+#define CMIS_BANK_0_3_SUPPORTED 0x02
+
/* Signal integrity controls */
#define CMIS_SIG_INTEG_TX_OFFSET 0xA1
#define CMIS_SIG_INTEG_RX_OFFSET 0xA2
--
2.35.1

View File

@ -0,0 +1,631 @@
From 086662c0b884c2b2e44ec472566d56c68a4330e0 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 23 Nov 2021 19:40:59 +0200
Subject: [PATCH 31/35] cmis: Parse and print diagnostic information
Like SFF-8636, CMIS has module-level monitors such as temperature and
voltage and channel-level monitors such as Tx optical power.
These monitors have thresholds and flags that are set when the monitors
cross the thresholds.
Print and parse these values in a similar fashion to SFF-8636.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
cmis.c | 466 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
cmis.h | 79 ++++++++++
2 files changed, 518 insertions(+), 27 deletions(-)
diff --git a/cmis.c b/cmis.c
index 83ced4d253ae..d7b7097139b3 100644
--- a/cmis.c
+++ b/cmis.c
@@ -19,6 +19,8 @@
* [1] CMIS Rev. 5, page. 128, section 8.4.4, Table 8-40
*/
#define CMIS_MAX_BANKS 4
+#define CMIS_CHANNELS_PER_BANK 8
+#define CMIS_MAX_CHANNEL_NUM (CMIS_MAX_BANKS * CMIS_CHANNELS_PER_BANK)
/* We are not parsing further than Page 11h. */
#define CMIS_MAX_PAGES 18
@@ -34,6 +36,80 @@ struct cmis_memory_map {
#define CMIS_PAGE_SIZE 0x80
#define CMIS_I2C_ADDRESS 0x50
+static struct {
+ const char *str;
+ int offset;
+ __u8 value; /* Alarm is on if (offset & value) != 0. */
+} cmis_aw_mod_flags[] = {
+ { "Module temperature high alarm",
+ CMIS_TEMP_AW_OFFSET, CMIS_TEMP_HALARM_STATUS },
+ { "Module temperature low alarm",
+ CMIS_TEMP_AW_OFFSET, CMIS_TEMP_LALARM_STATUS },
+ { "Module temperature high warning",
+ CMIS_TEMP_AW_OFFSET, CMIS_TEMP_HWARN_STATUS },
+ { "Module temperature low warning",
+ CMIS_TEMP_AW_OFFSET, CMIS_TEMP_LWARN_STATUS },
+
+ { "Module voltage high alarm",
+ CMIS_VCC_AW_OFFSET, CMIS_VCC_HALARM_STATUS },
+ { "Module voltage low alarm",
+ CMIS_VCC_AW_OFFSET, CMIS_VCC_LALARM_STATUS },
+ { "Module voltage high warning",
+ CMIS_VCC_AW_OFFSET, CMIS_VCC_HWARN_STATUS },
+ { "Module voltage low warning",
+ CMIS_VCC_AW_OFFSET, CMIS_VCC_LWARN_STATUS },
+
+ { NULL, 0, 0 },
+};
+
+static struct {
+ const char *fmt_str;
+ int offset;
+ int adver_offset; /* In Page 01h. */
+ __u8 adver_value; /* Supported if (offset & value) != 0. */
+} cmis_aw_chan_flags[] = {
+ { "Laser bias current high alarm (Chan %d)",
+ CMIS_TX_BIAS_AW_HALARM_OFFSET,
+ CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_TX_BIAS_MON_MASK },
+ { "Laser bias current low alarm (Chan %d)",
+ CMIS_TX_BIAS_AW_LALARM_OFFSET,
+ CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_TX_BIAS_MON_MASK },
+ { "Laser bias current high warning (Chan %d)",
+ CMIS_TX_BIAS_AW_HWARN_OFFSET,
+ CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_TX_BIAS_MON_MASK },
+ { "Laser bias current low warning (Chan %d)",
+ CMIS_TX_BIAS_AW_LWARN_OFFSET,
+ CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_TX_BIAS_MON_MASK },
+
+ { "Laser tx power high alarm (Channel %d)",
+ CMIS_TX_PWR_AW_HALARM_OFFSET,
+ CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_TX_PWR_MON_MASK },
+ { "Laser tx power low alarm (Channel %d)",
+ CMIS_TX_PWR_AW_LALARM_OFFSET,
+ CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_TX_PWR_MON_MASK },
+ { "Laser tx power high warning (Channel %d)",
+ CMIS_TX_PWR_AW_HWARN_OFFSET,
+ CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_TX_PWR_MON_MASK },
+ { "Laser tx power low warning (Channel %d)",
+ CMIS_TX_PWR_AW_LWARN_OFFSET,
+ CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_TX_PWR_MON_MASK },
+
+ { "Laser rx power high alarm (Channel %d)",
+ CMIS_RX_PWR_AW_HALARM_OFFSET,
+ CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_RX_PWR_MON_MASK },
+ { "Laser rx power low alarm (Channel %d)",
+ CMIS_RX_PWR_AW_LALARM_OFFSET,
+ CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_RX_PWR_MON_MASK },
+ { "Laser rx power high warning (Channel %d)",
+ CMIS_RX_PWR_AW_HWARN_OFFSET,
+ CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_RX_PWR_MON_MASK },
+ { "Laser rx power low warning (Channel %d)",
+ CMIS_RX_PWR_AW_LWARN_OFFSET,
+ CMIS_DIAG_CHAN_ADVER_OFFSET, CMIS_RX_PWR_MON_MASK },
+
+ { NULL, 0, 0, 0 },
+};
+
static void cmis_show_identifier(const struct cmis_memory_map *map)
{
sff8024_show_identifier(map->lower_memory, CMIS_ID_OFFSET);
@@ -277,32 +353,6 @@ static void cmis_show_mit_compliance(const struct cmis_memory_map *map)
}
}
-/*
- * 2-byte internal temperature conversions:
- * First byte is a signed 8-bit integer, which is the temp decimal part
- * Second byte is a multiple of 1/256th of a degree, which is added to
- * the dec part.
- */
-#define OFFSET_TO_TEMP(offset) ((__s16)OFFSET_TO_U16(offset))
-
-/**
- * Print relevant module level monitoring values. Relevant documents:
- * [1] CMIS Rev. 3:
- * --> pag. 50, section 1.7.2.4, Table 22
- *
- * [2] CMIS Rev. 4:
- * --> pag. 84, section 8.2.4, Table 8-6
- */
-static void cmis_show_mod_lvl_monitors(const struct cmis_memory_map *map)
-{
- const __u8 *id = map->lower_memory;
-
- PRINT_TEMP("Module temperature",
- OFFSET_TO_TEMP(CMIS_CURR_TEMP_OFFSET));
- PRINT_VCC("Module voltage",
- OFFSET_TO_U16(CMIS_CURR_VCC_OFFSET));
-}
-
/**
* Print relevant info about the maximum supported fiber media length
* for each type of fiber media at the maximum module-supported bit rate.
@@ -352,6 +402,368 @@ static void cmis_show_vendor_info(const struct cmis_memory_map *map)
CMIS_CLEI_END_OFFSET, "CLEI code");
}
+static void cmis_parse_dom_power_type(const struct cmis_memory_map *map,
+ struct sff_diags *sd)
+{
+ sd->rx_power_type = map->page_01h[CMIS_DIAG_TYPE_OFFSET] &
+ CMIS_RX_PWR_TYPE_MASK;
+ sd->tx_power_type = map->page_01h[CMIS_DIAG_CHAN_ADVER_OFFSET] &
+ CMIS_TX_PWR_MON_MASK;
+}
+
+static void cmis_parse_dom_mod_lvl_monitors(const struct cmis_memory_map *map,
+ struct sff_diags *sd)
+{
+ sd->sfp_voltage[MCURR] = OFFSET_TO_U16_PTR(map->lower_memory,
+ CMIS_CURR_VCC_OFFSET);
+ sd->sfp_temp[MCURR] = (__s16)OFFSET_TO_U16_PTR(map->lower_memory,
+ CMIS_CURR_TEMP_OFFSET);
+}
+
+static void cmis_parse_dom_mod_lvl_thresh(const struct cmis_memory_map *map,
+ struct sff_diags *sd)
+{
+ /* Page is not present in IOCTL path. */
+ if (!map->page_02h)
+ return;
+ sd->supports_alarms = 1;
+
+ sd->sfp_voltage[HALRM] = OFFSET_TO_U16_PTR(map->page_02h,
+ CMIS_VCC_HALRM_OFFSET);
+ sd->sfp_voltage[LALRM] = OFFSET_TO_U16_PTR(map->page_02h,
+ CMIS_VCC_LALRM_OFFSET);
+ sd->sfp_voltage[HWARN] = OFFSET_TO_U16_PTR(map->page_02h,
+ CMIS_VCC_HWARN_OFFSET);
+ sd->sfp_voltage[LWARN] = OFFSET_TO_U16_PTR(map->page_02h,
+ CMIS_VCC_LWARN_OFFSET);
+
+ sd->sfp_temp[HALRM] = (__s16)OFFSET_TO_U16_PTR(map->page_02h,
+ CMIS_TEMP_HALRM_OFFSET);
+ sd->sfp_temp[LALRM] = (__s16)OFFSET_TO_U16_PTR(map->page_02h,
+ CMIS_TEMP_LALRM_OFFSET);
+ sd->sfp_temp[HWARN] = (__s16)OFFSET_TO_U16_PTR(map->page_02h,
+ CMIS_TEMP_HWARN_OFFSET);
+ sd->sfp_temp[LWARN] = (__s16)OFFSET_TO_U16_PTR(map->page_02h,
+ CMIS_TEMP_LWARN_OFFSET);
+}
+
+static __u8 cmis_tx_bias_mul(const struct cmis_memory_map *map)
+{
+ switch (map->page_01h[CMIS_DIAG_CHAN_ADVER_OFFSET] &
+ CMIS_TX_BIAS_MUL_MASK) {
+ case CMIS_TX_BIAS_MUL_1:
+ return 0;
+ case CMIS_TX_BIAS_MUL_2:
+ return 1;
+ case CMIS_TX_BIAS_MUL_4:
+ return 2;
+ }
+
+ return 0;
+}
+
+static void
+cmis_parse_dom_chan_lvl_monitors_bank(const struct cmis_memory_map *map,
+ struct sff_diags *sd, int bank)
+{
+ const __u8 *page_11h = map->upper_memory[bank][0x11];
+ int i;
+
+ if (!page_11h)
+ return;
+
+ for (i = 0; i < CMIS_CHANNELS_PER_BANK; i++) {
+ __u8 tx_bias_offset, rx_power_offset, tx_power_offset;
+ int chan = bank * CMIS_CHANNELS_PER_BANK + i;
+ __u8 bias_mul = cmis_tx_bias_mul(map);
+
+ tx_bias_offset = CMIS_TX_BIAS_OFFSET + i * sizeof(__u16);
+ rx_power_offset = CMIS_RX_PWR_OFFSET + i * sizeof(__u16);
+ tx_power_offset = CMIS_TX_PWR_OFFSET + i * sizeof(__u16);
+
+ sd->scd[chan].bias_cur = OFFSET_TO_U16_PTR(page_11h,
+ tx_bias_offset);
+ sd->scd[chan].bias_cur >>= bias_mul;
+ sd->scd[chan].rx_power = OFFSET_TO_U16_PTR(page_11h,
+ rx_power_offset);
+ sd->scd[chan].tx_power = OFFSET_TO_U16_PTR(page_11h,
+ tx_power_offset);
+ }
+}
+
+static void cmis_parse_dom_chan_lvl_monitors(const struct cmis_memory_map *map,
+ struct sff_diags *sd)
+{
+ int i;
+
+ for (i = 0; i < CMIS_MAX_BANKS; i++)
+ cmis_parse_dom_chan_lvl_monitors_bank(map, sd, i);
+}
+
+static void cmis_parse_dom_chan_lvl_thresh(const struct cmis_memory_map *map,
+ struct sff_diags *sd)
+{
+ __u8 bias_mul = cmis_tx_bias_mul(map);
+
+ if (!map->page_02h)
+ return;
+
+ sd->bias_cur[HALRM] = OFFSET_TO_U16_PTR(map->page_02h,
+ CMIS_TX_BIAS_HALRM_OFFSET);
+ sd->bias_cur[HALRM] >>= bias_mul;
+ sd->bias_cur[LALRM] = OFFSET_TO_U16_PTR(map->page_02h,
+ CMIS_TX_BIAS_LALRM_OFFSET);
+ sd->bias_cur[LALRM] >>= bias_mul;
+ sd->bias_cur[HWARN] = OFFSET_TO_U16_PTR(map->page_02h,
+ CMIS_TX_BIAS_HWARN_OFFSET);
+ sd->bias_cur[HWARN] >>= bias_mul;
+ sd->bias_cur[LWARN] = OFFSET_TO_U16_PTR(map->page_02h,
+ CMIS_TX_BIAS_LWARN_OFFSET);
+ sd->bias_cur[LWARN] >>= bias_mul;
+
+ sd->tx_power[HALRM] = OFFSET_TO_U16_PTR(map->page_02h,
+ CMIS_TX_PWR_HALRM_OFFSET);
+ sd->tx_power[LALRM] = OFFSET_TO_U16_PTR(map->page_02h,
+ CMIS_TX_PWR_LALRM_OFFSET);
+ sd->tx_power[HWARN] = OFFSET_TO_U16_PTR(map->page_02h,
+ CMIS_TX_PWR_HWARN_OFFSET);
+ sd->tx_power[LWARN] = OFFSET_TO_U16_PTR(map->page_02h,
+ CMIS_TX_PWR_LWARN_OFFSET);
+
+ sd->rx_power[HALRM] = OFFSET_TO_U16_PTR(map->page_02h,
+ CMIS_RX_PWR_HALRM_OFFSET);
+ sd->rx_power[LALRM] = OFFSET_TO_U16_PTR(map->page_02h,
+ CMIS_RX_PWR_LALRM_OFFSET);
+ sd->rx_power[HWARN] = OFFSET_TO_U16_PTR(map->page_02h,
+ CMIS_RX_PWR_HWARN_OFFSET);
+ sd->rx_power[LWARN] = OFFSET_TO_U16_PTR(map->page_02h,
+ CMIS_RX_PWR_LWARN_OFFSET);
+}
+
+static void cmis_parse_dom(const struct cmis_memory_map *map,
+ struct sff_diags *sd)
+{
+ cmis_parse_dom_power_type(map, sd);
+ cmis_parse_dom_mod_lvl_monitors(map, sd);
+ cmis_parse_dom_mod_lvl_thresh(map, sd);
+ cmis_parse_dom_chan_lvl_monitors(map, sd);
+ cmis_parse_dom_chan_lvl_thresh(map, sd);
+}
+
+/* Print module-level monitoring values. Relevant documents:
+ * [1] CMIS Rev. 5, page 110, section 8.2.5, Table 8-9
+ */
+static void cmis_show_dom_mod_lvl_monitors(const struct sff_diags *sd)
+{
+ PRINT_TEMP("Module temperature", sd->sfp_temp[MCURR]);
+ PRINT_VCC("Module voltage", sd->sfp_voltage[MCURR]);
+}
+
+/* Print channel Tx laser bias current. Relevant documents:
+ * [1] CMIS Rev. 5, page 165, section 8.9.4, Table 8-79
+ */
+static void
+cmis_show_dom_chan_lvl_tx_bias_bank(const struct cmis_memory_map *map,
+ const struct sff_diags *sd, int bank)
+{
+ const __u8 *page_11h = map->upper_memory[bank][0x11];
+ int i;
+
+ if (!page_11h)
+ return;
+
+ for (i = 0; i < CMIS_CHANNELS_PER_BANK; i++) {
+ int chan = bank * CMIS_CHANNELS_PER_BANK + i;
+ char fmt_str[80];
+
+ snprintf(fmt_str, 80, "%s (Channel %d)",
+ "Laser tx bias current", chan + 1);
+ PRINT_BIAS(fmt_str, sd->scd[chan].bias_cur);
+ }
+}
+
+static void cmis_show_dom_chan_lvl_tx_bias(const struct cmis_memory_map *map,
+ const struct sff_diags *sd)
+{
+ int i;
+
+ if(!(map->page_01h[CMIS_DIAG_CHAN_ADVER_OFFSET] &
+ CMIS_TX_BIAS_MON_MASK))
+ return;
+
+ for (i = 0; i < CMIS_MAX_BANKS; i++)
+ cmis_show_dom_chan_lvl_tx_bias_bank(map, sd, i);
+}
+
+/* Print channel Tx average optical power. Relevant documents:
+ * [1] CMIS Rev. 5, page 165, section 8.9.4, Table 8-79
+ */
+static void
+cmis_show_dom_chan_lvl_tx_power_bank(const struct cmis_memory_map *map,
+ const struct sff_diags *sd, int bank)
+{
+ const __u8 *page_11h = map->upper_memory[bank][0x11];
+ int i;
+
+ if (!page_11h)
+ return;
+
+ for (i = 0; i < CMIS_CHANNELS_PER_BANK; i++) {
+ int chan = bank * CMIS_CHANNELS_PER_BANK + i;
+ char fmt_str[80];
+
+ snprintf(fmt_str, 80, "%s (Channel %d)",
+ "Transmit avg optical power", chan + 1);
+ PRINT_xX_PWR(fmt_str, sd->scd[chan].tx_power);
+ }
+}
+
+static void cmis_show_dom_chan_lvl_tx_power(const struct cmis_memory_map *map,
+ const struct sff_diags *sd)
+{
+ int i;
+
+ if (!sd->tx_power_type)
+ return;
+
+ for (i = 0; i < CMIS_MAX_BANKS; i++)
+ cmis_show_dom_chan_lvl_tx_power_bank(map, sd, i);
+}
+
+/* Print channel Rx input optical power. Relevant documents:
+ * [1] CMIS Rev. 5, page 165, section 8.9.4, Table 8-79
+ */
+static void
+cmis_show_dom_chan_lvl_rx_power_bank(const struct cmis_memory_map *map,
+ const struct sff_diags *sd, int bank)
+{
+ const __u8 *page_11h = map->upper_memory[bank][0x11];
+ int i;
+
+ if (!page_11h)
+ return;
+
+ for (i = 0; i < CMIS_CHANNELS_PER_BANK; i++) {
+ int chan = bank * CMIS_CHANNELS_PER_BANK + i;
+ char *rx_power_str;
+ char fmt_str[80];
+
+ if (!sd->rx_power_type)
+ rx_power_str = "Receiver signal OMA";
+ else
+ rx_power_str = "Rcvr signal avg optical power";
+
+ snprintf(fmt_str, 80, "%s (Channel %d)", rx_power_str,
+ chan + 1);
+ PRINT_xX_PWR(fmt_str, sd->scd[chan].rx_power);
+ }
+}
+
+static void cmis_show_dom_chan_lvl_rx_power(const struct cmis_memory_map *map,
+ const struct sff_diags *sd)
+{
+ int i;
+
+ if(!(map->page_01h[CMIS_DIAG_CHAN_ADVER_OFFSET] & CMIS_RX_PWR_MON_MASK))
+ return;
+
+ for (i = 0; i < CMIS_MAX_BANKS; i++)
+ cmis_show_dom_chan_lvl_rx_power_bank(map, sd, i);
+}
+
+static void cmis_show_dom_chan_lvl_monitors(const struct cmis_memory_map *map,
+ const struct sff_diags *sd)
+{
+ cmis_show_dom_chan_lvl_tx_bias(map, sd);
+ cmis_show_dom_chan_lvl_tx_power(map, sd);
+ cmis_show_dom_chan_lvl_rx_power(map, sd);
+}
+
+/* Print module-level flags. Relevant documents:
+ * [1] CMIS Rev. 5, page 109, section 8.2.4, Table 8-8
+ */
+static void cmis_show_dom_mod_lvl_flags(const struct cmis_memory_map *map)
+{
+ int i;
+
+ for (i = 0; cmis_aw_mod_flags[i].str; i++) {
+ printf("\t%-41s : %s\n", cmis_aw_mod_flags[i].str,
+ map->lower_memory[cmis_aw_mod_flags[i].offset] &
+ cmis_aw_mod_flags[i].value ? "On" : "Off");
+ }
+}
+
+/* Print channel-level flags. Relevant documents:
+ * [1] CMIS Rev. 5, page 162, section 8.9.3, Table 8-77
+ * [1] CMIS Rev. 5, page 164, section 8.9.3, Table 8-78
+ */
+static void cmis_show_dom_chan_lvl_flags_chan(const struct cmis_memory_map *map,
+ int bank, int chan)
+{
+ const __u8 *page_11h = map->upper_memory[bank][0x11];
+ int i;
+
+ for (i = 0; cmis_aw_chan_flags[i].fmt_str; i++) {
+ char str[80];
+
+ if (!(map->page_01h[cmis_aw_chan_flags[i].adver_offset] &
+ cmis_aw_chan_flags[i].adver_value))
+ continue;
+
+ snprintf(str, 80, cmis_aw_chan_flags[i].fmt_str, chan + 1);
+ printf("\t%-41s : %s\n", str,
+ page_11h[cmis_aw_chan_flags[i].offset] & chan ?
+ "On" : "Off");
+ }
+}
+
+static void
+cmis_show_dom_chan_lvl_flags_bank(const struct cmis_memory_map *map,
+ int bank)
+{
+ const __u8 *page_11h = map->upper_memory[bank][0x11];
+ int i;
+
+ if (!page_11h)
+ return;
+
+ for (i = 0; i < CMIS_CHANNELS_PER_BANK; i++) {
+ int chan = bank * CMIS_CHANNELS_PER_BANK + i;
+
+ cmis_show_dom_chan_lvl_flags_chan(map, bank, chan);
+ }
+}
+
+static void cmis_show_dom_chan_lvl_flags(const struct cmis_memory_map *map)
+{
+ int i;
+
+ for (i = 0; i < CMIS_MAX_BANKS; i++)
+ cmis_show_dom_chan_lvl_flags_bank(map, i);
+}
+
+
+static void cmis_show_dom(const struct cmis_memory_map *map)
+{
+ struct sff_diags sd = {};
+
+ /* Diagnostic information is only relevant when the module memory
+ * model is paged and not flat.
+ */
+ if (map->lower_memory[CMIS_MEMORY_MODEL_OFFSET] &
+ CMIS_MEMORY_MODEL_MASK)
+ return;
+
+ cmis_parse_dom(map, &sd);
+
+ cmis_show_dom_mod_lvl_monitors(&sd);
+ cmis_show_dom_chan_lvl_monitors(map, &sd);
+ cmis_show_dom_mod_lvl_flags(map);
+ cmis_show_dom_chan_lvl_flags(map);
+ if (sd.supports_alarms)
+ sff_show_thresholds(sd);
+}
+
static void cmis_show_all_common(const struct cmis_memory_map *map)
{
cmis_show_identifier(map);
@@ -360,10 +772,10 @@ static void cmis_show_all_common(const struct cmis_memory_map *map)
cmis_show_cbl_asm_len(map);
cmis_show_sig_integrity(map);
cmis_show_mit_compliance(map);
- cmis_show_mod_lvl_monitors(map);
cmis_show_link_len(map);
cmis_show_vendor_info(map);
cmis_show_rev_compliance(map);
+ cmis_show_dom(map);
}
static void cmis_memory_map_init_buf(struct cmis_memory_map *map,
diff --git a/cmis.h b/cmis.h
index 8d90a04756ad..310697b0ef32 100644
--- a/cmis.h
+++ b/cmis.h
@@ -7,6 +7,18 @@
#define CMIS_MEMORY_MODEL_OFFSET 0x02
#define CMIS_MEMORY_MODEL_MASK 0x80
+/* Module Flags (Page 0) */
+#define CMIS_VCC_AW_OFFSET 0x09
+#define CMIS_VCC_LWARN_STATUS 0x80
+#define CMIS_VCC_HWARN_STATUS 0x40
+#define CMIS_VCC_LALARM_STATUS 0x20
+#define CMIS_VCC_HALARM_STATUS 0x10
+#define CMIS_TEMP_AW_OFFSET 0x09
+#define CMIS_TEMP_LWARN_STATUS 0x08
+#define CMIS_TEMP_HWARN_STATUS 0x04
+#define CMIS_TEMP_LALARM_STATUS 0x02
+#define CMIS_TEMP_HALARM_STATUS 0x01
+
#define CMIS_MODULE_TYPE_OFFSET 0x55
#define CMIS_MT_MMF 0x01
#define CMIS_MT_SMF 0x02
@@ -121,10 +133,77 @@
#define CMIS_BANK_0_1_SUPPORTED 0x01
#define CMIS_BANK_0_3_SUPPORTED 0x02
+/* Module Characteristics Advertising (Page 1) */
+#define CMIS_DIAG_TYPE_OFFSET 0x97
+#define CMIS_RX_PWR_TYPE_MASK 0x10
+
+/* Supported Monitors Advertisement (Page 1) */
+#define CMIS_DIAG_CHAN_ADVER_OFFSET 0xA0
+#define CMIS_TX_BIAS_MON_MASK 0x01
+#define CMIS_TX_PWR_MON_MASK 0x02
+#define CMIS_RX_PWR_MON_MASK 0x04
+#define CMIS_TX_BIAS_MUL_MASK 0x18
+#define CMIS_TX_BIAS_MUL_1 0x00
+#define CMIS_TX_BIAS_MUL_2 0x08
+#define CMIS_TX_BIAS_MUL_4 0x10
+
/* Signal integrity controls */
#define CMIS_SIG_INTEG_TX_OFFSET 0xA1
#define CMIS_SIG_INTEG_RX_OFFSET 0xA2
+/*-----------------------------------------------------------------------
+ * Upper Memory Page 0x02: Optional Page that informs about module-defined
+ * thresholds for module-level and lane-specific threshold crossing monitors.
+ */
+
+/* Module-Level Monitor Thresholds (Page 2) */
+#define CMIS_TEMP_HALRM_OFFSET 0x80
+#define CMIS_TEMP_LALRM_OFFSET 0x82
+#define CMIS_TEMP_HWARN_OFFSET 0x84
+#define CMIS_TEMP_LWARN_OFFSET 0x86
+#define CMIS_VCC_HALRM_OFFSET 0x88
+#define CMIS_VCC_LALRM_OFFSET 0x8A
+#define CMIS_VCC_HWARN_OFFSET 0x8C
+#define CMIS_VCC_LWARN_OFFSET 0x8E
+
+/* Lane-Related Monitor Thresholds (Page 2) */
+#define CMIS_TX_PWR_HALRM_OFFSET 0xB0
+#define CMIS_TX_PWR_LALRM_OFFSET 0xB2
+#define CMIS_TX_PWR_HWARN_OFFSET 0xB4
+#define CMIS_TX_PWR_LWARN_OFFSET 0xB6
+#define CMIS_TX_BIAS_HALRM_OFFSET 0xB8
+#define CMIS_TX_BIAS_LALRM_OFFSET 0xBA
+#define CMIS_TX_BIAS_HWARN_OFFSET 0xBC
+#define CMIS_TX_BIAS_LWARN_OFFSET 0xBE
+#define CMIS_RX_PWR_HALRM_OFFSET 0xC0
+#define CMIS_RX_PWR_LALRM_OFFSET 0xC2
+#define CMIS_RX_PWR_HWARN_OFFSET 0xC4
+#define CMIS_RX_PWR_LWARN_OFFSET 0xC6
+
+/*-----------------------------------------------------------------------
+ * Upper Memory Page 0x11: Optional Page that contains lane dynamic status
+ * bytes.
+ */
+
+/* Media Lane-Specific Flags (Page 0x11) */
+#define CMIS_TX_PWR_AW_HALARM_OFFSET 0x8B
+#define CMIS_TX_PWR_AW_LALARM_OFFSET 0x8C
+#define CMIS_TX_PWR_AW_HWARN_OFFSET 0x8D
+#define CMIS_TX_PWR_AW_LWARN_OFFSET 0x8E
+#define CMIS_TX_BIAS_AW_HALARM_OFFSET 0x8F
+#define CMIS_TX_BIAS_AW_LALARM_OFFSET 0x90
+#define CMIS_TX_BIAS_AW_HWARN_OFFSET 0x91
+#define CMIS_TX_BIAS_AW_LWARN_OFFSET 0x92
+#define CMIS_RX_PWR_AW_HALARM_OFFSET 0x95
+#define CMIS_RX_PWR_AW_LALARM_OFFSET 0x96
+#define CMIS_RX_PWR_AW_HWARN_OFFSET 0x97
+#define CMIS_RX_PWR_AW_LWARN_OFFSET 0x98
+
+/* Media Lane-Specific Monitors (Page 0x11) */
+#define CMIS_TX_PWR_OFFSET 0x9A
+#define CMIS_TX_BIAS_OFFSET 0xAA
+#define CMIS_RX_PWR_OFFSET 0xBA
+
#define YESNO(x) (((x) != 0) ? "Yes" : "No")
#define ONOFF(x) (((x) != 0) ? "On" : "Off")
--
2.35.1

View File

@ -0,0 +1,155 @@
From 4a86034f138e1a96e54047b8036b0a4425e99944 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 23 Nov 2021 19:41:00 +0200
Subject: [PATCH 32/35] cmis: Print Module State and Fault Cause
Print the CMIS Module State when dumping EEPROM contents via the '-m'
option. It can be used, for example, to test module power mode settings.
Example output:
# ethtool -m swp11
Identifier : 0x18 (QSFP-DD Double Density 8X Pluggable Transceiver (INF-8628))
...
Module State : 0x03 (ModuleReady)
# ethtool --set-module swp11 power-mode-policy auto
# ethtool -m swp11
Identifier : 0x18 (QSFP-DD Double Density 8X Pluggable Transceiver (INF-8628))
...
Module State : 0x01 (ModuleLowPwr)
In case the module is in fault state, print the CMIS Module Fault Cause.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
cmis.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cmis.h | 16 ++++++++++++++
2 files changed, 86 insertions(+)
diff --git a/cmis.c b/cmis.c
index d7b7097139b3..a32cc9f8b1f6 100644
--- a/cmis.c
+++ b/cmis.c
@@ -402,6 +402,74 @@ static void cmis_show_vendor_info(const struct cmis_memory_map *map)
CMIS_CLEI_END_OFFSET, "CLEI code");
}
+/* Print the current Module State. Relevant documents:
+ * [1] CMIS Rev. 5, pag. 57, section 6.3.2.2, Figure 6-3
+ * [2] CMIS Rev. 5, pag. 60, section 6.3.2.3, Figure 6-4
+ * [3] CMIS Rev. 5, pag. 107, section 8.2.2, Table 8-6
+ */
+static void cmis_show_mod_state(const struct cmis_memory_map *map)
+{
+ __u8 mod_state;
+
+ mod_state = (map->lower_memory[CMIS_MODULE_STATE_OFFSET] &
+ CMIS_MODULE_STATE_MASK) >> 1;
+ printf("\t%-41s : 0x%02x", "Module State", mod_state);
+ switch (mod_state) {
+ case CMIS_MODULE_STATE_MODULE_LOW_PWR:
+ printf(" (ModuleLowPwr)\n");
+ break;
+ case CMIS_MODULE_STATE_MODULE_PWR_UP:
+ printf(" (ModulePwrUp)\n");
+ break;
+ case CMIS_MODULE_STATE_MODULE_READY:
+ printf(" (ModuleReady)\n");
+ break;
+ case CMIS_MODULE_STATE_MODULE_PWR_DN:
+ printf(" (ModulePwrDn)\n");
+ break;
+ case CMIS_MODULE_STATE_MODULE_FAULT:
+ printf(" (ModuleFault)\n");
+ break;
+ default:
+ printf(" (reserved or unknown)\n");
+ break;
+ }
+}
+
+/* Print the Module Fault Information. Relevant documents:
+ * [1] CMIS Rev. 5, pag. 64, section 6.3.2.12
+ * [2] CMIS Rev. 5, pag. 115, section 8.2.10, Table 8-15
+ */
+static void cmis_show_mod_fault_cause(const struct cmis_memory_map *map)
+{
+ __u8 mod_state, fault_cause;
+
+ mod_state = (map->lower_memory[CMIS_MODULE_STATE_OFFSET] &
+ CMIS_MODULE_STATE_MASK) >> 1;
+ if (mod_state != CMIS_MODULE_STATE_MODULE_FAULT)
+ return;
+
+ fault_cause = map->lower_memory[CMIS_MODULE_FAULT_OFFSET];
+ printf("\t%-41s : 0x%02x", "Module Fault Cause", fault_cause);
+ switch (fault_cause) {
+ case CMIS_MODULE_FAULT_NO_FAULT:
+ printf(" (No fault detected / not supported)\n");
+ break;
+ case CMIS_MODULE_FAULT_TEC_RUNAWAY:
+ printf(" (TEC runaway)\n");
+ break;
+ case CMIS_MODULE_FAULT_DATA_MEM_CORRUPTED:
+ printf(" (Data memory corrupted)\n");
+ break;
+ case CMIS_MODULE_FAULT_PROG_MEM_CORRUPTED:
+ printf(" (Program memory corrupted)\n");
+ break;
+ default:
+ printf(" (reserved or unknown)\n");
+ break;
+ }
+}
+
static void cmis_parse_dom_power_type(const struct cmis_memory_map *map,
struct sff_diags *sd)
{
@@ -775,6 +843,8 @@ static void cmis_show_all_common(const struct cmis_memory_map *map)
cmis_show_link_len(map);
cmis_show_vendor_info(map);
cmis_show_rev_compliance(map);
+ cmis_show_mod_state(map);
+ cmis_show_mod_fault_cause(map);
cmis_show_dom(map);
}
diff --git a/cmis.h b/cmis.h
index 310697b0ef32..2c67ad5640ab 100644
--- a/cmis.h
+++ b/cmis.h
@@ -7,6 +7,15 @@
#define CMIS_MEMORY_MODEL_OFFSET 0x02
#define CMIS_MEMORY_MODEL_MASK 0x80
+/* Global Status Information (Page 0) */
+#define CMIS_MODULE_STATE_OFFSET 0x03
+#define CMIS_MODULE_STATE_MASK 0x0E
+#define CMIS_MODULE_STATE_MODULE_LOW_PWR 0x01
+#define CMIS_MODULE_STATE_MODULE_PWR_UP 0x02
+#define CMIS_MODULE_STATE_MODULE_READY 0x03
+#define CMIS_MODULE_STATE_MODULE_PWR_DN 0x04
+#define CMIS_MODULE_STATE_MODULE_FAULT 0x05
+
/* Module Flags (Page 0) */
#define CMIS_VCC_AW_OFFSET 0x09
#define CMIS_VCC_LWARN_STATUS 0x80
@@ -27,6 +36,13 @@
#define CMIS_CURR_TEMP_OFFSET 0x0E
#define CMIS_CURR_VCC_OFFSET 0x10
+/* Module Fault Information (Page 0) */
+#define CMIS_MODULE_FAULT_OFFSET 0x29
+#define CMIS_MODULE_FAULT_NO_FAULT 0x00
+#define CMIS_MODULE_FAULT_TEC_RUNAWAY 0x01
+#define CMIS_MODULE_FAULT_DATA_MEM_CORRUPTED 0x02
+#define CMIS_MODULE_FAULT_PROG_MEM_CORRUPTED 0x03
+
#define CMIS_CTOR_OFFSET 0xCB
/* Vendor related information (Page 0) */
--
2.35.1

View File

@ -0,0 +1,196 @@
From 0b45f392c6c92e9823d6332622d7a45e7a36365e Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 23 Nov 2021 19:41:01 +0200
Subject: [PATCH 33/35] cmis: Print Module-Level Controls
Print the CMIS Module-Level Controls when dumping EEPROM contents via
the '-m' option. It can be used to understand low power mode enforcement
by the host.
Example output:
# ethtool -m swp11
Identifier : 0x18 (QSFP-DD Double Density 8X Pluggable Transceiver (INF-8628))
...
Module State : 0x03 (ModuleReady)
LowPwrAllowRequestHW : Off
LowPwrRequestSW : Off
...
Transmit avg optical power (Channel 1) : 1.3222 mW / 1.21 dBm
Transmit avg optical power (Channel 2) : 1.2666 mW / 1.03 dBm
Transmit avg optical power (Channel 3) : 1.2860 mW / 1.09 dBm
Transmit avg optical power (Channel 4) : 1.2988 mW / 1.14 dBm
Transmit avg optical power (Channel 5) : 1.2828 mW / 1.08 dBm
Transmit avg optical power (Channel 6) : 1.2913 mW / 1.11 dBm
Transmit avg optical power (Channel 7) : 1.2636 mW / 1.02 dBm
Transmit avg optical power (Channel 8) : 1.3408 mW / 1.27 dBm
Transmit avg optical power (Channel 9) : 1.3222 mW / 1.21 dBm
Transmit avg optical power (Channel 10) : 1.2666 mW / 1.03 dBm
Transmit avg optical power (Channel 11) : 1.2860 mW / 1.09 dBm
Transmit avg optical power (Channel 12) : 1.2988 mW / 1.14 dBm
Transmit avg optical power (Channel 13) : 1.2828 mW / 1.08 dBm
Transmit avg optical power (Channel 14) : 1.2913 mW / 1.11 dBm
Transmit avg optical power (Channel 15) : 1.2636 mW / 1.02 dBm
Transmit avg optical power (Channel 16) : 1.3408 mW / 1.27 dBm
Rcvr signal avg optical power (Channel 1) : 1.1351 mW / 0.55 dBm
Rcvr signal avg optical power (Channel 2) : 1.1603 mW / 0.65 dBm
Rcvr signal avg optical power (Channel 3) : 1.1529 mW / 0.62 dBm
Rcvr signal avg optical power (Channel 4) : 1.1670 mW / 0.67 dBm
Rcvr signal avg optical power (Channel 5) : 1.1759 mW / 0.70 dBm
Rcvr signal avg optical power (Channel 6) : 1.1744 mW / 0.70 dBm
Rcvr signal avg optical power (Channel 7) : 1.1188 mW / 0.49 dBm
Rcvr signal avg optical power (Channel 8) : 1.1640 mW / 0.66 dBm
Rcvr signal avg optical power (Channel 9) : 1.1351 mW / 0.55 dBm
Rcvr signal avg optical power (Channel 10) : 1.1603 mW / 0.65 dBm
Rcvr signal avg optical power (Channel 11) : 1.1529 mW / 0.62 dBm
Rcvr signal avg optical power (Channel 12) : 1.1670 mW / 0.67 dBm
Rcvr signal avg optical power (Channel 13) : 1.1759 mW / 0.70 dBm
Rcvr signal avg optical power (Channel 14) : 1.1744 mW / 0.70 dBm
Rcvr signal avg optical power (Channel 15) : 1.1188 mW / 0.49 dBm
Rcvr signal avg optical power (Channel 16) : 1.1640 mW / 0.66 dBm
# ethtool --set-module swp11 power-mode-policy auto
# ethtool -m swp11
Identifier : 0x18 (QSFP-DD Double Density 8X Pluggable Transceiver (INF-8628))
...
Module State : 0x01 (ModuleLowPwr)
LowPwrAllowRequestHW : Off
LowPwrRequestSW : On
...
Transmit avg optical power (Channel 1) : 0.0001 mW / -40.00 dBm
Transmit avg optical power (Channel 2) : 0.0001 mW / -40.00 dBm
Transmit avg optical power (Channel 3) : 0.0001 mW / -40.00 dBm
Transmit avg optical power (Channel 4) : 0.0001 mW / -40.00 dBm
Transmit avg optical power (Channel 5) : 0.0001 mW / -40.00 dBm
Transmit avg optical power (Channel 6) : 0.0001 mW / -40.00 dBm
Transmit avg optical power (Channel 7) : 0.0001 mW / -40.00 dBm
Transmit avg optical power (Channel 8) : 0.0001 mW / -40.00 dBm
Transmit avg optical power (Channel 9) : 0.0001 mW / -40.00 dBm
Transmit avg optical power (Channel 10) : 0.0001 mW / -40.00 dBm
Transmit avg optical power (Channel 11) : 0.0001 mW / -40.00 dBm
Transmit avg optical power (Channel 12) : 0.0001 mW / -40.00 dBm
Transmit avg optical power (Channel 13) : 0.0001 mW / -40.00 dBm
Transmit avg optical power (Channel 14) : 0.0001 mW / -40.00 dBm
Transmit avg optical power (Channel 15) : 0.0001 mW / -40.00 dBm
Transmit avg optical power (Channel 16) : 0.0001 mW / -40.00 dBm
Rcvr signal avg optical power (Channel 1) : 0.0001 mW / -40.00 dBm
Rcvr signal avg optical power (Channel 2) : 0.0001 mW / -40.00 dBm
Rcvr signal avg optical power (Channel 3) : 0.0001 mW / -40.00 dBm
Rcvr signal avg optical power (Channel 4) : 0.0001 mW / -40.00 dBm
Rcvr signal avg optical power (Channel 5) : 0.0001 mW / -40.00 dBm
Rcvr signal avg optical power (Channel 6) : 0.0001 mW / -40.00 dBm
Rcvr signal avg optical power (Channel 7) : 0.0001 mW / -40.00 dBm
Rcvr signal avg optical power (Channel 8) : 0.0001 mW / -40.00 dBm
Rcvr signal avg optical power (Channel 9) : 0.0001 mW / -40.00 dBm
Rcvr signal avg optical power (Channel 10) : 0.0001 mW / -40.00 dBm
Rcvr signal avg optical power (Channel 11) : 0.0001 mW / -40.00 dBm
Rcvr signal avg optical power (Channel 12) : 0.0001 mW / -40.00 dBm
Rcvr signal avg optical power (Channel 13) : 0.0001 mW / -40.00 dBm
Rcvr signal avg optical power (Channel 14) : 0.0001 mW / -40.00 dBm
Rcvr signal avg optical power (Channel 15) : 0.0001 mW / -40.00 dBm
Rcvr signal avg optical power (Channel 16) : 0.0001 mW / -40.00 dBm
# ethtool --set-module swp11 power-mode-policy high
# ethtool -m swp11
Identifier : 0x18 (QSFP-DD Double Density 8X Pluggable Transceiver (INF-8628))
...
Module State : 0x03 (ModuleReady)
LowPwrAllowRequestHW : Off
LowPwrRequestSW : Off
...
Transmit avg optical power (Channel 1) : 1.3690 mW / 1.36 dBm
Transmit avg optical power (Channel 2) : 1.3036 mW / 1.15 dBm
Transmit avg optical power (Channel 3) : 1.3358 mW / 1.26 dBm
Transmit avg optical power (Channel 4) : 1.3509 mW / 1.31 dBm
Transmit avg optical power (Channel 5) : 1.3193 mW / 1.20 dBm
Transmit avg optical power (Channel 6) : 1.3314 mW / 1.24 dBm
Transmit avg optical power (Channel 7) : 1.3042 mW / 1.15 dBm
Transmit avg optical power (Channel 8) : 1.3919 mW / 1.44 dBm
Transmit avg optical power (Channel 9) : 1.3690 mW / 1.36 dBm
Transmit avg optical power (Channel 10) : 1.3036 mW / 1.15 dBm
Transmit avg optical power (Channel 11) : 1.3358 mW / 1.26 dBm
Transmit avg optical power (Channel 12) : 1.3509 mW / 1.31 dBm
Transmit avg optical power (Channel 13) : 1.3193 mW / 1.20 dBm
Transmit avg optical power (Channel 14) : 1.3314 mW / 1.24 dBm
Transmit avg optical power (Channel 15) : 1.3042 mW / 1.15 dBm
Transmit avg optical power (Channel 16) : 1.3919 mW / 1.44 dBm
Rcvr signal avg optical power (Channel 1) : 1.1299 mW / 0.53 dBm
Rcvr signal avg optical power (Channel 2) : 1.1566 mW / 0.63 dBm
Rcvr signal avg optical power (Channel 3) : 1.1484 mW / 0.60 dBm
Rcvr signal avg optical power (Channel 4) : 1.1655 mW / 0.67 dBm
Rcvr signal avg optical power (Channel 5) : 1.1751 mW / 0.70 dBm
Rcvr signal avg optical power (Channel 6) : 1.1595 mW / 0.64 dBm
Rcvr signal avg optical power (Channel 7) : 1.1158 mW / 0.48 dBm
Rcvr signal avg optical power (Channel 8) : 1.1595 mW / 0.64 dBm
Rcvr signal avg optical power (Channel 9) : 1.1299 mW / 0.53 dBm
Rcvr signal avg optical power (Channel 10) : 1.1566 mW / 0.63 dBm
Rcvr signal avg optical power (Channel 11) : 1.1484 mW / 0.60 dBm
Rcvr signal avg optical power (Channel 12) : 1.1655 mW / 0.67 dBm
Rcvr signal avg optical power (Channel 13) : 1.1751 mW / 0.70 dBm
Rcvr signal avg optical power (Channel 14) : 1.1595 mW / 0.64 dBm
Rcvr signal avg optical power (Channel 15) : 1.1158 mW / 0.48 dBm
Rcvr signal avg optical power (Channel 16) : 1.1595 mW / 0.64 dBm
In the above example, the LowPwrRequestHW signal is ignored and low
power mode is controlled via software only.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
cmis.c | 15 +++++++++++++++
cmis.h | 5 +++++
2 files changed, 20 insertions(+)
diff --git a/cmis.c b/cmis.c
index a32cc9f8b1f6..d0b62728e998 100644
--- a/cmis.c
+++ b/cmis.c
@@ -470,6 +470,20 @@ static void cmis_show_mod_fault_cause(const struct cmis_memory_map *map)
}
}
+/* Print the current Module-Level Controls. Relevant documents:
+ * [1] CMIS Rev. 5, pag. 58, section 6.3.2.2, Table 6-12
+ * [2] CMIS Rev. 5, pag. 111, section 8.2.6, Table 8-10
+ */
+static void cmis_show_mod_lvl_controls(const struct cmis_memory_map *map)
+{
+ printf("\t%-41s : ", "LowPwrAllowRequestHW");
+ printf("%s\n", ONOFF(map->lower_memory[CMIS_MODULE_CONTROL_OFFSET] &
+ CMIS_LOW_PWR_ALLOW_REQUEST_HW_MASK));
+ printf("\t%-41s : ", "LowPwrRequestSW");
+ printf("%s\n", ONOFF(map->lower_memory[CMIS_MODULE_CONTROL_OFFSET] &
+ CMIS_LOW_PWR_REQUEST_SW_MASK));
+}
+
static void cmis_parse_dom_power_type(const struct cmis_memory_map *map,
struct sff_diags *sd)
{
@@ -845,6 +859,7 @@ static void cmis_show_all_common(const struct cmis_memory_map *map)
cmis_show_rev_compliance(map);
cmis_show_mod_state(map);
cmis_show_mod_fault_cause(map);
+ cmis_show_mod_lvl_controls(map);
cmis_show_dom(map);
}
diff --git a/cmis.h b/cmis.h
index 2c67ad5640ab..46797081f13c 100644
--- a/cmis.h
+++ b/cmis.h
@@ -36,6 +36,11 @@
#define CMIS_CURR_TEMP_OFFSET 0x0E
#define CMIS_CURR_VCC_OFFSET 0x10
+/* Module Global Controls (Page 0) */
+#define CMIS_MODULE_CONTROL_OFFSET 0x1A
+#define CMIS_LOW_PWR_ALLOW_REQUEST_HW_MASK 0x40
+#define CMIS_LOW_PWR_REQUEST_SW_MASK 0x10
+
/* Module Fault Information (Page 0) */
#define CMIS_MODULE_FAULT_OFFSET 0x29
#define CMIS_MODULE_FAULT_NO_FAULT 0x00
--
2.35.1

View File

@ -0,0 +1,108 @@
From 48391fa16592b47d37ef63466111c751a10c3e56 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 23 Nov 2021 19:41:02 +0200
Subject: [PATCH 34/35] sff-8636: Print Power set and Power override bits
Print the SFF-8636 Power set and Power override bits when dumping EEPROM
contents via the '-m' option. They can be used to understand low power
mode enforcement by the host.
The 'SFF8636_LOW_PWR_MODE' define is renamed to 'SFF8636_LOW_PWR_SET' to
reflect its naming in the standard for QSFP+/QSFP28.
Example output:
# ethtool -m swp13
Identifier : 0x11 (QSFP28)
...
Extended identifier description : 5.0W max. Power consumption, High Power Class (> 3.5 W) enabled
Power set : Off
Power override : On
...
Transmit avg optical power (Channel 1) : 0.7633 mW / -1.17 dBm
Transmit avg optical power (Channel 2) : 0.7649 mW / -1.16 dBm
Transmit avg optical power (Channel 3) : 0.7696 mW / -1.14 dBm
Transmit avg optical power (Channel 4) : 0.7739 mW / -1.11 dBm
Rcvr signal avg optical power(Channel 1) : 0.9240 mW / -0.34 dBm
Rcvr signal avg optical power(Channel 2) : 0.9129 mW / -0.40 dBm
Rcvr signal avg optical power(Channel 3) : 0.9194 mW / -0.36 dBm
Rcvr signal avg optical power(Channel 4) : 0.8708 mW / -0.60 dBm
# ethtool --set-module swp13 power-mode-policy auto
# ethtool -m swp13
Identifier : 0x11 (QSFP28)
...
Extended identifier description : 5.0W max. Power consumption, High Power Class (> 3.5 W) not enabled
Power set : On
Power override : On
...
Transmit avg optical power (Channel 1) : 0.0000 mW / -inf dBm
Transmit avg optical power (Channel 2) : 0.0000 mW / -inf dBm
Transmit avg optical power (Channel 3) : 0.0000 mW / -inf dBm
Transmit avg optical power (Channel 4) : 0.0000 mW / -inf dBm
Rcvr signal avg optical power(Channel 1) : 0.0000 mW / -inf dBm
Rcvr signal avg optical power(Channel 2) : 0.0000 mW / -inf dBm
Rcvr signal avg optical power(Channel 3) : 0.0000 mW / -inf dBm
Rcvr signal avg optical power(Channel 4) : 0.0000 mW / -inf dBm
# ethtool --set-module swp13 power-mode-policy high
# ethtool -m swp13
Identifier : 0x11 (QSFP28)
...
Extended identifier description : 5.0W max. Power consumption, High Power Class (> 3.5 W) enabled
Power set : Off
Power override : On
...
Transmit avg optical power (Channel 1) : 0.7733 mW / -1.12 dBm
Transmit avg optical power (Channel 2) : 0.7754 mW / -1.10 dBm
Transmit avg optical power (Channel 3) : 0.7885 mW / -1.03 dBm
Transmit avg optical power (Channel 4) : 0.7886 mW / -1.03 dBm
Rcvr signal avg optical power(Channel 1) : 0.9248 mW / -0.34 dBm
Rcvr signal avg optical power(Channel 2) : 0.9129 mW / -0.40 dBm
Rcvr signal avg optical power(Channel 3) : 0.9187 mW / -0.37 dBm
Rcvr signal avg optical power(Channel 4) : 0.8785 mW / -0.56 dBm
In the above example, the LPMode signal is ignored (Power override is
always on) and low power mode is controlled via software only.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
qsfp.c | 6 ++++++
qsfp.h | 2 +-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/qsfp.c b/qsfp.c
index b3c9e1516af9..57aac86bd5f6 100644
--- a/qsfp.c
+++ b/qsfp.c
@@ -268,6 +268,12 @@ static void sff8636_show_ext_identifier(const struct sff8636_memory_map *map)
printf(" High Power Class (> 3.5 W) enabled\n");
else
printf(" High Power Class (> 3.5 W) not enabled\n");
+ printf("\t%-41s : ", "Power set");
+ printf("%s\n", ONOFF(map->lower_memory[SFF8636_PWR_MODE_OFFSET] &
+ SFF8636_LOW_PWR_SET));
+ printf("\t%-41s : ", "Power override");
+ printf("%s\n", ONOFF(map->lower_memory[SFF8636_PWR_MODE_OFFSET] &
+ SFF8636_PWR_OVERRIDE));
}
static void sff8636_show_connector(const struct sff8636_memory_map *map)
diff --git a/qsfp.h b/qsfp.h
index 1d8f24b5cbc2..aabf09fdc623 100644
--- a/qsfp.h
+++ b/qsfp.h
@@ -180,7 +180,7 @@
#define SFF8636_PWR_MODE_OFFSET 0x5D
#define SFF8636_HIGH_PWR_ENABLE (1 << 2)
-#define SFF8636_LOW_PWR_MODE (1 << 1)
+#define SFF8636_LOW_PWR_SET (1 << 1)
#define SFF8636_PWR_OVERRIDE (1 << 0)
#define SFF8636_TX_APP_SELECT_4_OFFSET 0x5E
--
2.35.1

View File

@ -0,0 +1,107 @@
From 206cd00caf9b71ae20f897075b4bd261e923e563 Mon Sep 17 00:00:00 2001
From: Ivan Vecera <ivecera@redhat.com>
Date: Tue, 31 May 2022 20:55:03 +0200
Subject: [PATCH 35/35] sff-8079/8472: Fix missing sff-8472 output in netlink
path
Commit 25b64c66f58d ("ethtool: Add netlink handler for
getmodule (-m)") provided a netlink variant for getmodule
but also introduced a regression as netlink output is different
from ioctl output that provides information from A2h page
via sff8472_show_all().
To fix this the netlink path should check a presence of A2h page
by value of bit 6 in byte 92 of page A0h and if it is set then
get A2h page and call sff8472_show_all().
Fixes: 25b64c66f58d ("ethtool: Add netlink handler for getmodule (-m)")
Tested-by: Daniel Juarez <djuarezg@cern.ch>
Tested-by: Ido Schimmel <idosch@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Co-authored-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
---
sfpid.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 46 insertions(+), 8 deletions(-)
diff --git a/sfpid.c b/sfpid.c
index 621d1e86c278..1bc45c183770 100644
--- a/sfpid.c
+++ b/sfpid.c
@@ -13,8 +13,9 @@
#include "sff-common.h"
#include "netlink/extapi.h"
-#define SFF8079_PAGE_SIZE 0x80
-#define SFF8079_I2C_ADDRESS_LOW 0x50
+#define SFF8079_PAGE_SIZE 0x80
+#define SFF8079_I2C_ADDRESS_LOW 0x50
+#define SFF8079_I2C_ADDRESS_HIGH 0x51
static void sff8079_show_identifier(const __u8 *id)
{
@@ -450,18 +451,55 @@ void sff8079_show_all_ioctl(const __u8 *id)
sff8079_show_all_common(id);
}
-int sff8079_show_all_nl(struct cmd_context *ctx)
+static int sff8079_get_eeprom_page(struct cmd_context *ctx, u8 i2c_address,
+ __u8 *buf)
{
struct ethtool_module_eeprom request = {
.length = SFF8079_PAGE_SIZE,
- .i2c_address = SFF8079_I2C_ADDRESS_LOW,
+ .i2c_address = i2c_address,
};
int ret;
ret = nl_get_eeprom_page(ctx, &request);
- if (ret < 0)
- return ret;
- sff8079_show_all_common(request.data);
+ if (!ret)
+ memcpy(buf, request.data, SFF8079_PAGE_SIZE);
+
+ return ret;
+}
+
+int sff8079_show_all_nl(struct cmd_context *ctx)
+{
+ u8 *buf;
+ int ret;
+
+ /* The SFF-8472 parser expects a single buffer that contains the
+ * concatenation of the first 256 bytes from addresses A0h and A2h,
+ * respectively.
+ */
+ buf = calloc(1, ETH_MODULE_SFF_8472_LEN);
+ if (!buf)
+ return -ENOMEM;
+
+ /* Read A0h page */
+ ret = sff8079_get_eeprom_page(ctx, SFF8079_I2C_ADDRESS_LOW, buf);
+ if (ret)
+ goto out;
+
+ sff8079_show_all_common(buf);
+
+ /* Finish if A2h page is not present */
+ if (!(buf[92] & (1 << 6)))
+ goto out;
+
+ /* Read A2h page */
+ ret = sff8079_get_eeprom_page(ctx, SFF8079_I2C_ADDRESS_HIGH,
+ buf + ETH_MODULE_SFF_8079_LEN);
+ if (ret)
+ goto out;
+
+ sff8472_show_all(buf);
+out:
+ free(buf);
- return 0;
+ return ret;
}
--
2.35.1

View File

@ -1,7 +1,7 @@
Name: ethtool
Epoch: 2
Version: 5.13
Release: 1%{?dist}
Release: 2%{?dist}
Summary: Settings tool for Ethernet NICs
License: GPLv2
Group: Applications/System
@ -10,6 +10,42 @@ Source0: https://www.kernel.org/pub/software/network/%{name}/%{name}-%{version}.
BuildRequires: libmnl-devel
Conflicts: filesystem < 3
Patch1: 0001-sff-8636-Fix-parsing-of-Page-03h-in-IOCTL-path.patch
Patch2: 0002-cmis-Fix-invalid-memory-access-in-IOCTL-path.patch
Patch3: 0003-netlink-eeprom-Fallback-to-IOCTL-when-a-complete-hex.patch
Patch4: 0004-ethtool-Fix-compilation-warning-when-pretty-dump-is-.patch
Patch5: 0005-netlink-eeprom-Fix-compilation-when-pretty-dump-is-d.patch
Patch6: 0006-cmis-Fix-CLEI-code-parsing.patch
Patch7: 0007-cmis-Fix-wrong-define-name.patch
Patch8: 0008-cmis-Correct-comment.patch
Patch9: 0009-sff-8636-Remove-incorrect-comment.patch
Patch10: 0010-sff-8636-Fix-incorrect-function-name.patch
Patch11: 0011-sff-8636-Convert-if-statement-to-switch-case.patch
Patch12: 0012-sff-8636-Remove-extra-blank-lines.patch
Patch13: 0013-cmis-Rename-CMIS-parsing-functions.patch
Patch14: 0014-cmis-Initialize-CMIS-memory-map.patch
Patch15: 0015-cmis-Use-memory-map-during-parsing.patch
Patch16: 0016-cmis-Consolidate-code-between-IOCTL-and-netlink-path.patch
Patch17: 0017-sff-8636-Rename-SFF-8636-parsing-functions.patch
Patch18: 0018-sff-8636-Initialize-SFF-8636-memory-map.patch
Patch19: 0019-sff-8636-Use-memory-map-during-parsing.patch
Patch20: 0020-sff-8636-Consolidate-code-between-IOCTL-and-netlink-.patch
Patch21: 0021-sff-8079-Split-SFF-8079-parsing-function.patch
Patch22: 0022-netlink-eeprom-Export-a-function-to-request-an-EEPRO.patch
Patch23: 0023-cmis-Request-specific-pages-for-parsing-in-netlink-p.patch
Patch24: 0024-sff-8636-Request-specific-pages-for-parsing-in-netli.patch
Patch25: 0025-sff-8079-Request-specific-pages-for-parsing-in-netli.patch
Patch26: 0026-netlink-eeprom-Defer-page-requests-to-individual-par.patch
Patch27: 0027-sff-8636-Use-an-SFF-8636-specific-define-for-maximum.patch
Patch28: 0028-sff-common-Move-OFFSET_TO_U16_PTR-to-common-header-f.patch
Patch29: 0029-cmis-Initialize-Page-02h-in-memory-map.patch
Patch30: 0030-cmis-Initialize-Banked-Page-11h-in-memory-map.patch
Patch31: 0031-cmis-Parse-and-print-diagnostic-information.patch
Patch32: 0032-cmis-Print-Module-State-and-Fault-Cause.patch
Patch33: 0033-cmis-Print-Module-Level-Controls.patch
Patch34: 0034-sff-8636-Print-Power-set-and-Power-override-bits.patch
Patch35: 0035-sff-8079-8472-Fix-missing-sff-8472-output-in-netlink.patch
%description
This utility allows querying and changing settings such as speed,
port, auto-negotiation, PCI locations and checksum offload on many
@ -17,6 +53,41 @@ network devices, especially of Ethernet devices.
%prep
%setup -q
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch13 -p1
%patch14 -p1
%patch15 -p1
%patch16 -p1
%patch17 -p1
%patch18 -p1
%patch19 -p1
%patch20 -p1
%patch21 -p1
%patch22 -p1
%patch23 -p1
%patch24 -p1
%patch25 -p1
%patch26 -p1
%patch27 -p1
%patch28 -p1
%patch29 -p1
%patch30 -p1
%patch31 -p1
%patch32 -p1
%patch33 -p1
%patch34 -p1
%patch35 -p1
%build
%configure
@ -33,6 +104,9 @@ make DESTDIR=%{buildroot} INSTALL='install -p' install
%{_datadir}/bash-completion/completions/ethtool
%changelog
* Thu Jun 02 2022 Ivan Vecera <ivecera@redhat.com> - 2:5.13-2
- Module (SFP/QSFP/CMIS) related bugfixes
* Thu Nov 18 2021 Ivan Vecera <ivecera@redhat.com> - 2:5.13-1
- Updated to upstream v5.13