Compare commits
No commits in common. 'c9' and 'c8' have entirely different histories.
@ -1,2 +1 @@
|
|||||||
faa54e107797fc0d8b2a107216629bcc816039d8 SOURCES/ethtool-6.2.tar.xz
|
2414cbdb4b767da4612a2608d22ad17502cd3d37 SOURCES/ethtool-5.13.tar.xz
|
||||||
7cf93f0c53feec1e86e9c5c8bba2a32fa19a888d SOURCES/gpgkey-D2CB120AB45957B721CD9596F4554567B91DE934.gpg
|
|
||||||
|
@ -1,2 +1 @@
|
|||||||
SOURCES/ethtool-6.2.tar.xz
|
SOURCES/ethtool-5.13.tar.xz
|
||||||
SOURCES/gpgkey-D2CB120AB45957B721CD9596F4554567B91DE934.gpg
|
|
||||||
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -1,11 +0,0 @@
|
|||||||
-----BEGIN PGP SIGNATURE-----
|
|
||||||
|
|
||||||
iQEzBAABCAAdFiEEWN3j3bieVmp26mKO538sG/LRdpUFAmP02/EACgkQ538sG/LR
|
|
||||||
dpXlcAf8CKHsG9DW7GU8dU4BycH/hgUG3lnRtm6JW3pukQiJF7nHzlITYXTDPNes
|
|
||||||
s9WdMfZMEN3qCojsFhaUHum5oHuhkR8meMggVajIfgZRVcPOkBpZkf5Hjrj2CmY9
|
|
||||||
+pBXm4JEziuN0YiTRNcqtWrTd14k0+TdLOwc7ScoXbktxxpBp5Ji/mpzpHM9PBr6
|
|
||||||
kskDDJlFxYV8z4N+HqxR+2UL9U/oYDSgvtGVn0j0zKq1shTWxkzUp0/ggyPiSTCB
|
|
||||||
w6XLjF/diIf2C5R4P5I6VBPIX8xIDw0XloGVPXsA8RSg5GBpWrK4X5Vhj4eij6xd
|
|
||||||
OEoG0MGFI3SB16st2+m9VpllSYzm0g==
|
|
||||||
=fR5P
|
|
||||||
-----END PGP SIGNATURE-----
|
|
Loading…
Reference in new issue