!37 ethtool: backport some patches to support more CMIS transceiver modules

From: @chen-hao418 
Reviewed-by: @wangboe2022, @robertxw 
Signed-off-by: @robertxw
This commit is contained in:
openeuler-ci-bot 2024-06-11 02:12:48 +00:00 committed by Gitee
commit d66fcaff03
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
22 changed files with 3974 additions and 52 deletions

View File

@ -1,7 +1,7 @@
From 6428870f54e7107c2f37202f14818ebab0112e5f Mon Sep 17 00:00:00 2001
From 17afa43fa85e03ebe3b9a4e82f5e18a6cfbef082 Mon Sep 17 00:00:00 2001
From: Jie Wang <wangjie125@huawei.com>
Date: Fri, 29 Apr 2022 17:17:03 +0800
Subject: update UAPI header copies
Subject: [PATCH] update UAPI header copies
Update to kernel commit cc4bdef26ecd.
@ -9,20 +9,20 @@ commit: bd138ee
Reference: https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=bd138ee083c4
change log: Some macros for rx buf len in other patch. To avoid add
unnecrssary content, add like "ETHTOOL_TX_COPYBREAK_BUF_SIZE"
"ETHTOOL_A_RINGS_RX_BUF_LEN" "IFLA_BOND_MISSED_MAX" in this patch
"ETHTOOL_A_RINGS_RX_BUF_LEN" "IFLA_BOND_MISSED_MAX" and merger
commit 1c5526968e27 in this patch.
Signed-off-by: Jie Wang <wangjie125@huawei.com>
---
uapi/linux/ethtool.h | 1 +
uapi/linux/ethtool_netlink.h | 10 ++++
uapi/linux/ethtool.h | 30 +++++++++++
uapi/linux/ethtool_netlink.h | 31 +++++++++++-
uapi/linux/if_link.h | 98 ++++++++++++++++++++++++++++++++++++
uapi/linux/net_tstamp.h | 17 ++++++-
uapi/linux/netlink.h | 1 +
uapi/linux/rtnetlink.h | 16 ++++++
6 files changed, 142 insertions(+), 1 deletion(-)
5 files changed, 175 insertions(+), 1 deletion(-)
diff --git a/uapi/linux/ethtool.h b/uapi/linux/ethtool.h
index a7f549a..4a36287 100644
index a7f549a..85548f9 100644
--- a/uapi/linux/ethtool.h
+++ b/uapi/linux/ethtool.h
@@ -229,6 +229,7 @@ enum tunable_id {
@ -33,11 +33,79 @@ index a7f549a..4a36287 100644
/*
* Add your fresh new tunable attribute above and remember to update
* tunable_strings[] in net/ethtool/common.c
@@ -601,6 +602,7 @@ enum ethtool_link_ext_state {
ETHTOOL_LINK_EXT_STATE_CALIBRATION_FAILURE,
ETHTOOL_LINK_EXT_STATE_POWER_BUDGET_EXCEEDED,
ETHTOOL_LINK_EXT_STATE_OVERHEAT,
+ ETHTOOL_LINK_EXT_STATE_MODULE,
};
/* More information in addition to ETHTOOL_LINK_EXT_STATE_AUTONEG. */
@@ -647,6 +649,11 @@ enum ethtool_link_ext_substate_cable_issue {
ETHTOOL_LINK_EXT_SUBSTATE_CI_CABLE_TEST_FAILURE,
};
+/* More information in addition to ETHTOOL_LINK_EXT_STATE_MODULE. */
+enum ethtool_link_ext_substate_module {
+ ETHTOOL_LINK_EXT_SUBSTATE_MODULE_CMIS_NOT_READY = 1,
+};
+
#define ETH_GSTRING_LEN 32
/**
@@ -704,6 +711,29 @@ enum ethtool_stringset {
ETH_SS_COUNT
};
+/**
+ * enum ethtool_module_power_mode_policy - plug-in module power mode policy
+ * @ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH: Module is always in high power mode.
+ * @ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO: Module is transitioned by the host
+ * to high power mode when the first port using it is put administratively
+ * up and to low power mode when the last port using it is put
+ * administratively down.
+ */
+enum ethtool_module_power_mode_policy {
+ ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH = 1,
+ ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO,
+};
+
+/**
+ * enum ethtool_module_power_mode - plug-in module power mode
+ * @ETHTOOL_MODULE_POWER_MODE_LOW: Module is in low power mode.
+ * @ETHTOOL_MODULE_POWER_MODE_HIGH: Module is in high power mode.
+ */
+enum ethtool_module_power_mode {
+ ETHTOOL_MODULE_POWER_MODE_LOW = 1,
+ ETHTOOL_MODULE_POWER_MODE_HIGH,
+};
+
/**
* struct ethtool_gstrings - string set for data tagging
* @cmd: Command number = %ETHTOOL_GSTRINGS
diff --git a/uapi/linux/ethtool_netlink.h b/uapi/linux/ethtool_netlink.h
index 5665d64..aaadce7 100644
index 5665d64..378ad7d 100644
--- a/uapi/linux/ethtool_netlink.h
+++ b/uapi/linux/ethtool_netlink.h
@@ -314,6 +314,12 @@ enum {
@@ -47,6 +47,8 @@ enum {
ETHTOOL_MSG_MODULE_EEPROM_GET,
ETHTOOL_MSG_STATS_GET,
ETHTOOL_MSG_PHC_VCLOCKS_GET,
+ ETHTOOL_MSG_MODULE_GET,
+ ETHTOOL_MSG_MODULE_SET,
/* add new constants above here */
__ETHTOOL_MSG_USER_CNT,
@@ -90,6 +92,8 @@ enum {
ETHTOOL_MSG_MODULE_EEPROM_GET_REPLY,
ETHTOOL_MSG_STATS_GET_REPLY,
ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY,
+ ETHTOOL_MSG_MODULE_GET_REPLY,
+ ETHTOOL_MSG_MODULE_NTF,
/* add new constants above here */
__ETHTOOL_MSG_KERNEL_CNT,
@@ -314,6 +318,12 @@ enum {
/* RINGS */
@ -50,17 +118,48 @@ index 5665d64..aaadce7 100644
enum {
ETHTOOL_A_RINGS_UNSPEC,
ETHTOOL_A_RINGS_HEADER, /* nest - _A_HEADER_* */
@@ -325,6 +331,10 @@ enum {
@@ -325,6 +335,10 @@ enum {
ETHTOOL_A_RINGS_RX_MINI, /* u32 */
ETHTOOL_A_RINGS_RX_JUMBO, /* u32 */
ETHTOOL_A_RINGS_TX, /* u32 */
+ ETHTOOL_A_RINGS_RX_BUF_LEN, /* u32 */
+ ETHTOOL_A_RINGS_TCP_DATA_SPLIT, /* u8 */
+ ETHTOOL_A_RINGS_RX_BUF_LEN, /* u32 */
+ ETHTOOL_A_RINGS_TCP_DATA_SPLIT, /* u8 */
+ ETHTOOL_A_RINGS_CQE_SIZE, /* u32 */
+ ETHTOOL_A_RINGS_TX_PUSH, /* u8 */
+ ETHTOOL_A_RINGS_TX_PUSH, /* u8 */
/* add new constants above here */
__ETHTOOL_A_RINGS_CNT,
@@ -407,7 +421,9 @@ enum {
ETHTOOL_A_PAUSE_STAT_TX_FRAMES,
ETHTOOL_A_PAUSE_STAT_RX_FRAMES,
- /* add new constants above here */
+ /* add new constants above here
+ * adjust ETHTOOL_PAUSE_STAT_CNT if adding non-stats!
+ */
__ETHTOOL_A_PAUSE_STAT_CNT,
ETHTOOL_A_PAUSE_STAT_MAX = (__ETHTOOL_A_PAUSE_STAT_CNT - 1)
};
@@ -833,6 +849,19 @@ enum {
ETHTOOL_A_STATS_RMON_MAX = (__ETHTOOL_A_STATS_RMON_CNT - 1)
};
+/* MODULE */
+
+enum {
+ ETHTOOL_A_MODULE_UNSPEC,
+ ETHTOOL_A_MODULE_HEADER, /* nest - _A_HEADER_* */
+ ETHTOOL_A_MODULE_POWER_MODE_POLICY, /* u8 */
+ ETHTOOL_A_MODULE_POWER_MODE, /* u8 */
+
+ /* add new constants above here */
+ __ETHTOOL_A_MODULE_CNT,
+ ETHTOOL_A_MODULE_MAX = (__ETHTOOL_A_MODULE_CNT - 1)
+};
+
/* generic netlink info */
#define ETHTOOL_GENL_NAME "ethtool"
#define ETHTOOL_GENL_VERSION 1
diff --git a/uapi/linux/if_link.h b/uapi/linux/if_link.h
index 1d4ed60..34002e7 100644
--- a/uapi/linux/if_link.h
@ -245,41 +344,6 @@ index 1d4ed60..34002e7 100644
/* XDP section */
#define XDP_FLAGS_UPDATE_IF_NOEXIST (1U << 0)
diff --git a/uapi/linux/net_tstamp.h b/uapi/linux/net_tstamp.h
index fcc61c7..55501e5 100644
--- a/uapi/linux/net_tstamp.h
+++ b/uapi/linux/net_tstamp.h
@@ -62,7 +62,7 @@ struct so_timestamping {
/**
* struct hwtstamp_config - %SIOCGHWTSTAMP and %SIOCSHWTSTAMP parameter
*
- * @flags: no flags defined right now, must be zero for %SIOCSHWTSTAMP
+ * @flags: one of HWTSTAMP_FLAG_*
* @tx_type: one of HWTSTAMP_TX_*
* @rx_filter: one of HWTSTAMP_FILTER_*
*
@@ -78,6 +78,21 @@ struct hwtstamp_config {
int rx_filter;
};
+/* possible values for hwtstamp_config->flags */
+enum hwtstamp_flags {
+ /*
+ * With this flag, the user could get bond active interface's
+ * PHC index. Note this PHC index is not stable as when there
+ * is a failover, the bond active interface will be changed, so
+ * will be the PHC index.
+ */
+ HWTSTAMP_FLAG_BONDED_PHC_INDEX = (1<<0),
+#define HWTSTAMP_FLAG_BONDED_PHC_INDEX HWTSTAMP_FLAG_BONDED_PHC_INDEX
+
+ HWTSTAMP_FLAG_LAST = HWTSTAMP_FLAG_BONDED_PHC_INDEX,
+ HWTSTAMP_FLAG_MASK = (HWTSTAMP_FLAG_LAST - 1) | HWTSTAMP_FLAG_LAST
+};
+
/* possible values for hwtstamp_config->tx_type */
enum hwtstamp_tx_types {
/*
diff --git a/uapi/linux/netlink.h b/uapi/linux/netlink.h
index e83e2e3..105b79f 100644
--- a/uapi/linux/netlink.h
@ -341,5 +405,5 @@ index e01efa2..8f874be 100644
/* End of information exported to user level */
--
2.33.0
2.30.0

View File

@ -0,0 +1,80 @@
From 98d2c71b11a0ffb72f56da6bccb7d274e00d96f5 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:15 +0300
Subject: [PATCH 10/26] 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.
commit: 6acaeb9
Reference: https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=6acaeb94402a
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 2e01446..eb7791d 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.30.0

View File

@ -0,0 +1,148 @@
From 9cfd4eac291dfa43e63ea01309a3a0d400b3286a Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:13 +0300
Subject: [PATCH 08/26] 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
commit: 369b43a
Reference: https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=369b43a1a066
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 68c5b2d..8a67884 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 734b90f..53cbb5f 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.30.0

View File

@ -0,0 +1,98 @@
From 02055157bf85134de4551e496e3fb39930f68731 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:12 +0300
Subject: [PATCH 07/26] 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.
commit: 795f420
Reference: https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=795f42092f20
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 591cc72..68c5b2d 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 e3012cc..734b90f 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 48cd2cc..fc4ef1a 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 3f37f10..27fdd3b 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.30.0

View File

@ -0,0 +1,197 @@
From da5cd8deac6cfa6a45840e79a41c800282f043ce Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:22 +0300
Subject: [PATCH 17/26] 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.
commit: 86792db
Reference: https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=86792dbbebf3
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 eb7791d..4798fd4 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 c878e3b..911491d 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 ee55088..a8e2662 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.30.0

View File

@ -0,0 +1,397 @@
From 7fba1d13bf33839c204fe3ea9d3d8db60e7cda0d Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:14 +0300
Subject: [PATCH 09/26] 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.
commit: da16288
Reference: https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=da1628840bd6
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 8a67884..2e01446 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 53cbb5f..c878e3b 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.30.0

View File

@ -0,0 +1,459 @@
From 1bc52b04285906efcbdf7e9429ed668170ebf97a Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 7 Dec 2021 11:33:58 +0200
Subject: [PATCH 24/26] ethtool: Add ability to control transceiver modules'
power mode
Add ability to control transceiver modules' power mode over netlink.
Example output and usage:
# ip link set dev swp11 up
$ ethtool --show-module swp11
Module parameters for swp11:
power-mode-policy: high
power-mode: high
$ ethtool --json --show-module swp11
[ {
"ifname": "swp11",
"power-mode-policy": "high",
"power-mode": "high"
} ]
# ethtool --set-module swp11 power-mode-policy auto
$ ethtool --show-module swp11
Module parameters for swp11:
power-mode-policy: auto
power-mode: high
# ethtool --set-module swp11 power-mode-policy auto
# ethtool --set-module swp11 power-mode-policy high
Despite three set commands, only two notifications were emitted, as the
kernel only emits notifications when an attribute changes:
$ ethtool --monitor
listening...
Module parameters for swp11:
power-mode-policy: auto
power-mode: high
Module parameters for swp11:
power-mode-policy: high
power-mode: high
commit: 2d4c5b7
Reference: https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=2d4c5b7bb38b
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
Makefile.am | 2 +-
ethtool.8.in | 25 +++++
ethtool.c | 12 +++
netlink/desc-ethtool.c | 11 +++
netlink/extapi.h | 4 +
netlink/module.c | 179 ++++++++++++++++++++++++++++++++++
netlink/monitor.c | 4 +
netlink/netlink.h | 1 +
shell-completion/bash/ethtool | 23 +++++
9 files changed, 260 insertions(+), 1 deletion(-)
create mode 100644 netlink/module.c
diff --git a/Makefile.am b/Makefile.am
index a8f7a39..1ee6f13 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -39,7 +39,7 @@ ethtool_SOURCES += \
netlink/eee.c netlink/tsinfo.c netlink/fec.c \
netlink/stats.c \
netlink/desc-ethtool.c netlink/desc-genlctrl.c \
- netlink/module-eeprom.c \
+ netlink/module-eeprom.c netlink/module.c \
netlink/desc-rtnl.c netlink/cable_test.c netlink/tunnels.c \
uapi/linux/ethtool_netlink.h \
uapi/linux/netlink.h uapi/linux/genetlink.h \
diff --git a/ethtool.8.in b/ethtool.8.in
index af1c5bc..7016c3a 100644
--- a/ethtool.8.in
+++ b/ethtool.8.in
@@ -479,6 +479,14 @@ ethtool \- query or control network driver and hardware settings
.HP
.B ethtool \-\-show\-tunnels
.I devname
+.HP
+.B ethtool \-\-show\-module
+.I devname
+.HP
+.B ethtool \-\-set\-module
+.I devname
+.RB [ power\-mode\-policy
+.BR high | auto ]
.
.\" Adjust lines (i.e. full justification) and hyphenate.
.ad
@@ -1468,6 +1476,23 @@ Show tunnel-related device capabilities and state.
List UDP ports kernel has programmed the device to parse as VxLAN,
or GENEVE tunnels.
.RE
+.TP
+.B \-\-show\-module
+Show the transceiver module's parameters.
+.RE
+.TP
+.B \-\-set\-module
+Set the transceiver module's parameters.
+.RS 4
+.TP
+.A2 power-mode-policy high auto
+Set the power mode policy for the module. When set to \fBhigh\fR, the module
+always operates at high power mode. When set to \fBauto\fR, the module is
+transitioned by the host to high power mode when the first port using it is put
+administratively up and to low power mode when the last port using it is put
+administratively down. The power mode policy can be set before a module is
+plugged-in.
+.RE
.SH BUGS
Not supported (in part or whole) on all network drivers.
.SH AUTHOR
diff --git a/ethtool.c b/ethtool.c
index 461d1f2..2a13196 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -6056,6 +6056,18 @@ static const struct option args[] = {
.nlfunc = nl_gtunnels,
.help = "Show NIC tunnel offload information",
},
+ {
+ .opts = "--show-module",
+ .json = true,
+ .nlfunc = nl_gmodule,
+ .help = "Show transceiver module settings",
+ },
+ {
+ .opts = "--set-module",
+ .nlfunc = nl_smodule,
+ .help = "Set transceiver module settings",
+ .xhelp = " [ power-mode-policy high|auto ]\n"
+ },
{
.opts = "-h|--help",
.no_dev = true,
diff --git a/netlink/desc-ethtool.c b/netlink/desc-ethtool.c
index 69f6561..2b27c32 100644
--- a/netlink/desc-ethtool.c
+++ b/netlink/desc-ethtool.c
@@ -392,6 +392,13 @@ static const struct pretty_nla_desc __phc_vclocks_desc[] = {
NLATTR_DESC_BINARY(ETHTOOL_A_PHC_VCLOCKS_INDEX),
};
+static const struct pretty_nla_desc __module_desc[] = {
+ NLATTR_DESC_INVALID(ETHTOOL_A_MODULE_UNSPEC),
+ NLATTR_DESC_NESTED(ETHTOOL_A_MODULE_HEADER, header),
+ NLATTR_DESC_U8(ETHTOOL_A_MODULE_POWER_MODE_POLICY),
+ NLATTR_DESC_U8(ETHTOOL_A_MODULE_POWER_MODE),
+};
+
const struct pretty_nlmsg_desc ethnl_umsg_desc[] = {
NLMSG_DESC_INVALID(ETHTOOL_MSG_USER_NONE),
NLMSG_DESC(ETHTOOL_MSG_STRSET_GET, strset),
@@ -427,6 +434,8 @@ const struct pretty_nlmsg_desc ethnl_umsg_desc[] = {
NLMSG_DESC(ETHTOOL_MSG_MODULE_EEPROM_GET, module_eeprom),
NLMSG_DESC(ETHTOOL_MSG_STATS_GET, stats),
NLMSG_DESC(ETHTOOL_MSG_PHC_VCLOCKS_GET, phc_vclocks),
+ NLMSG_DESC(ETHTOOL_MSG_MODULE_GET, module),
+ NLMSG_DESC(ETHTOOL_MSG_MODULE_SET, module),
};
const unsigned int ethnl_umsg_n_desc = ARRAY_SIZE(ethnl_umsg_desc);
@@ -467,6 +476,8 @@ const struct pretty_nlmsg_desc ethnl_kmsg_desc[] = {
NLMSG_DESC(ETHTOOL_MSG_MODULE_EEPROM_GET_REPLY, module_eeprom),
NLMSG_DESC(ETHTOOL_MSG_STATS_GET_REPLY, stats),
NLMSG_DESC(ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY, phc_vclocks),
+ NLMSG_DESC(ETHTOOL_MSG_MODULE_GET_REPLY, module),
+ NLMSG_DESC(ETHTOOL_MSG_MODULE_NTF, module),
};
const unsigned int ethnl_kmsg_n_desc = ARRAY_SIZE(ethnl_kmsg_desc);
diff --git a/netlink/extapi.h b/netlink/extapi.h
index 129e293..1bb580a 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -43,6 +43,8 @@ int nl_gfec(struct cmd_context *ctx);
int nl_sfec(struct cmd_context *ctx);
bool nl_gstats_chk(struct cmd_context *ctx);
int nl_gstats(struct cmd_context *ctx);
+int nl_gmodule(struct cmd_context *ctx);
+int nl_smodule(struct cmd_context *ctx);
int nl_monitor(struct cmd_context *ctx);
int nl_getmodule(struct cmd_context *ctx);
@@ -110,6 +112,8 @@ nl_get_eeprom_page(struct cmd_context *ctx __maybe_unused,
#define nl_gstats_chk NULL
#define nl_gstats NULL
#define nl_getmodule NULL
+#define nl_gmodule NULL
+#define nl_smodule NULL
#endif /* ETHTOOL_ENABLE_NETLINK */
diff --git a/netlink/module.c b/netlink/module.c
new file mode 100644
index 0000000..54aa6d0
--- /dev/null
+++ b/netlink/module.c
@@ -0,0 +1,179 @@
+/*
+ * module.c - netlink implementation of module commands
+ *
+ * Implementation of "ethtool --show-module <dev>" and
+ * "ethtool --set-module <dev> ..."
+ */
+
+#include <errno.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "../internal.h"
+#include "../common.h"
+#include "netlink.h"
+#include "parser.h"
+
+/* MODULE_GET */
+
+static const char *module_power_mode_policy_name(u8 val)
+{
+ switch (val) {
+ case ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH:
+ return "high";
+ case ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO:
+ return "auto";
+ default:
+ return "unknown";
+ }
+}
+
+static const char *module_power_mode_name(u8 val)
+{
+ switch (val) {
+ case ETHTOOL_MODULE_POWER_MODE_LOW:
+ return "low";
+ case ETHTOOL_MODULE_POWER_MODE_HIGH:
+ return "high";
+ default:
+ return "unknown";
+ }
+}
+
+int module_reply_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+ const struct nlattr *tb[ETHTOOL_A_MODULE_MAX + 1] = {};
+ struct nl_context *nlctx = data;
+ DECLARE_ATTR_TB_INFO(tb);
+ bool silent;
+ int err_ret;
+ int ret;
+
+ silent = nlctx->is_dump || nlctx->is_monitor;
+ err_ret = silent ? MNL_CB_OK : MNL_CB_ERROR;
+ ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
+ if (ret < 0)
+ return err_ret;
+ nlctx->devname = get_dev_name(tb[ETHTOOL_A_MODULE_HEADER]);
+ if (!dev_ok(nlctx))
+ return err_ret;
+
+ if (silent)
+ print_nl();
+
+ open_json_object(NULL);
+
+ print_string(PRINT_ANY, "ifname", "Module parameters for %s:\n",
+ nlctx->devname);
+
+ if (tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY]) {
+ u8 val;
+
+ val = mnl_attr_get_u8(tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY]);
+ print_string(PRINT_ANY, "power-mode-policy",
+ "power-mode-policy: %s\n",
+ module_power_mode_policy_name(val));
+ }
+
+ if (tb[ETHTOOL_A_MODULE_POWER_MODE]) {
+ u8 val;
+
+ val = mnl_attr_get_u8(tb[ETHTOOL_A_MODULE_POWER_MODE]);
+ print_string(PRINT_ANY, "power-mode",
+ "power-mode: %s\n", module_power_mode_name(val));
+ }
+
+ close_json_object();
+
+ return MNL_CB_OK;
+}
+
+int nl_gmodule(struct cmd_context *ctx)
+{
+ struct nl_context *nlctx = ctx->nlctx;
+ struct nl_socket *nlsk;
+ int ret;
+
+ if (netlink_cmd_check(ctx, ETHTOOL_MSG_MODULE_GET, true))
+ return -EOPNOTSUPP;
+ if (ctx->argc > 0) {
+ fprintf(stderr, "ethtool: unexpected parameter '%s'\n",
+ *ctx->argp);
+ return 1;
+ }
+
+ nlsk = nlctx->ethnl_socket;
+ ret = nlsock_prep_get_request(nlsk, ETHTOOL_MSG_MODULE_GET,
+ ETHTOOL_A_MODULE_HEADER, 0);
+ if (ret < 0)
+ return ret;
+
+ new_json_obj(ctx->json);
+ ret = nlsock_send_get_request(nlsk, module_reply_cb);
+ delete_json_obj();
+ return ret;
+}
+
+/* MODULE_SET */
+
+static const struct lookup_entry_u8 power_mode_policy_values[] = {
+ { .arg = "high", .val = ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH },
+ { .arg = "auto", .val = ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO },
+ {}
+};
+
+static const struct param_parser smodule_params[] = {
+ {
+ .arg = "power-mode-policy",
+ .type = ETHTOOL_A_MODULE_POWER_MODE_POLICY,
+ .handler = nl_parse_lookup_u8,
+ .handler_data = power_mode_policy_values,
+ .min_argc = 1,
+ },
+ {}
+};
+
+int nl_smodule(struct cmd_context *ctx)
+{
+ struct nl_context *nlctx = ctx->nlctx;
+ struct nl_msg_buff *msgbuff;
+ struct nl_socket *nlsk;
+ int ret;
+
+ if (netlink_cmd_check(ctx, ETHTOOL_MSG_MODULE_SET, false))
+ return -EOPNOTSUPP;
+ if (!ctx->argc) {
+ fprintf(stderr, "ethtool (--set-module): parameters missing\n");
+ return 1;
+ }
+
+ nlctx->cmd = "--set-module";
+ nlctx->argp = ctx->argp;
+ nlctx->argc = ctx->argc;
+ nlctx->devname = ctx->devname;
+ nlsk = nlctx->ethnl_socket;
+ msgbuff = &nlsk->msgbuff;
+
+ ret = msg_init(nlctx, msgbuff, ETHTOOL_MSG_MODULE_SET,
+ NLM_F_REQUEST | NLM_F_ACK);
+ if (ret < 0)
+ return 2;
+ if (ethnla_fill_header(msgbuff, ETHTOOL_A_MODULE_HEADER,
+ ctx->devname, 0))
+ return -EMSGSIZE;
+
+ ret = nl_parser(nlctx, smodule_params, NULL, PARSER_GROUP_NONE, NULL);
+ if (ret < 0)
+ return 1;
+
+ ret = nlsock_sendmsg(nlsk, NULL);
+ if (ret < 0)
+ return 83;
+ ret = nlsock_process_reply(nlsk, nomsg_reply_cb, nlctx);
+ if (ret == 0)
+ return 0;
+ else
+ return nlctx->exit_code ?: 83;
+}
diff --git a/netlink/monitor.c b/netlink/monitor.c
index 0c4df9e..d631907 100644
--- a/netlink/monitor.c
+++ b/netlink/monitor.c
@@ -71,6 +71,10 @@ static struct {
.cmd = ETHTOOL_MSG_FEC_NTF,
.cb = fec_reply_cb,
},
+ {
+ .cmd = ETHTOOL_MSG_MODULE_NTF,
+ .cb = module_reply_cb,
+ },
};
static void clear_filter(struct nl_context *nlctx)
diff --git a/netlink/netlink.h b/netlink/netlink.h
index 70fa666..f43c1bf 100644
--- a/netlink/netlink.h
+++ b/netlink/netlink.h
@@ -91,6 +91,7 @@ int cable_test_ntf_cb(const struct nlmsghdr *nlhdr, void *data);
int cable_test_tdr_reply_cb(const struct nlmsghdr *nlhdr, void *data);
int cable_test_tdr_ntf_cb(const struct nlmsghdr *nlhdr, void *data);
int fec_reply_cb(const struct nlmsghdr *nlhdr, void *data);
+int module_reply_cb(const struct nlmsghdr *nlhdr, void *data);
/* dump helpers */
diff --git a/shell-completion/bash/ethtool b/shell-completion/bash/ethtool
index 4557341..46334b5 100644
--- a/shell-completion/bash/ethtool
+++ b/shell-completion/bash/ethtool
@@ -1137,6 +1137,27 @@ _ethtool_test()
fi
}
+# Completion for ethtool --set-module
+_ethtool_set_module()
+{
+ local -A settings=(
+ [power-mode-policy]=1
+ )
+
+ case "$prev" in
+ power-mode-policy)
+ COMPREPLY=( $( compgen -W 'high auto' -- "$cur" ) )
+ return ;;
+ esac
+
+ # Remove settings which have been seen
+ local word
+ for word in "${words[@]:3:${#words[@]}-4}"; do
+ unset "settings[$word]"
+ done
+
+ COMPREPLY=( $( compgen -W "${!settings[*]}" -- "$cur" ) )
+}
# Complete any ethtool command
_ethtool()
@@ -1189,6 +1210,8 @@ _ethtool()
[--show-time-stamping]=devname
[--statistics]=devname
[--test]=test
+ [--set-module]=set_module
+ [--show-module]=devname
)
local -A other_funcs=(
[--config-ntuple]=config_nfc
--
2.30.0

View File

@ -0,0 +1,85 @@
From f7d99859bc603649705e439472c8f79386a8b217 Mon Sep 17 00:00:00 2001
From: Danielle Ratson <danieller@nvidia.com>
Date: Mon, 7 Feb 2022 11:12:31 +0200
Subject: [PATCH 25/26] ethtool: Add support for OSFP transceiver modules
OSFP transceiver modules use the same management interface specification
(CMIS) as QSFP-DD and DSFP modules.
Allow ethtool to dump, parse and print their EEPROM contents by adding
their SFF-8024 Identifier Value (0x19).
This is required for future NVIDIA Spectrum-4 based systems that will be
equipped with OSFP transceivers.
While at it, add the DSFP identifier to the IOCTL path, as it was
missing.
commit: b9f25ea
Reference: https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=b9f25ea9058d
Signed-off-by: Danielle Ratson <danieller@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
netlink/module-eeprom.c | 1 +
qsfp.c | 4 +++-
sff-common.c | 3 +++
sff-common.h | 1 +
4 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/netlink/module-eeprom.c b/netlink/module-eeprom.c
index f359aee..49833a2 100644
--- a/netlink/module-eeprom.c
+++ b/netlink/module-eeprom.c
@@ -223,6 +223,7 @@ static int eeprom_parse(struct cmd_context *ctx)
case SFF8024_ID_QSFP_PLUS:
return sff8636_show_all_nl(ctx);
case SFF8024_ID_QSFP_DD:
+ case SFF8024_ID_OSFP:
case SFF8024_ID_DSFP:
return cmis_show_all_nl(ctx);
#endif
diff --git a/qsfp.c b/qsfp.c
index 57aac86..1fe5de1 100644
--- a/qsfp.c
+++ b/qsfp.c
@@ -947,7 +947,9 @@ 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) {
+ if (id[SFF8636_ID_OFFSET] == SFF8024_ID_QSFP_DD ||
+ id[SFF8636_ID_OFFSET] == SFF8024_ID_OSFP ||
+ id[SFF8636_ID_OFFSET] == SFF8024_ID_DSFP) {
cmis_show_all_ioctl(id);
return;
}
diff --git a/sff-common.c b/sff-common.c
index 2815951..e951cf1 100644
--- a/sff-common.c
+++ b/sff-common.c
@@ -139,6 +139,9 @@ void sff8024_show_identifier(const __u8 *id, int id_offset)
case SFF8024_ID_QSFP_DD:
printf(" (QSFP-DD Double Density 8X Pluggable Transceiver (INF-8628))\n");
break;
+ case SFF8024_ID_OSFP:
+ printf(" (OSFP 8X Pluggable Transceiver)\n");
+ break;
case SFF8024_ID_DSFP:
printf(" (DSFP Dual Small Form Factor Pluggable Transceiver)\n");
break;
diff --git a/sff-common.h b/sff-common.h
index 9e32300..dd12dda 100644
--- a/sff-common.h
+++ b/sff-common.h
@@ -62,6 +62,7 @@
#define SFF8024_ID_CDFP_S3 0x16
#define SFF8024_ID_MICRO_QSFP 0x17
#define SFF8024_ID_QSFP_DD 0x18
+#define SFF8024_ID_OSFP 0x19
#define SFF8024_ID_DSFP 0x1B
#define SFF8024_ID_LAST SFF8024_ID_DSFP
#define SFF8024_ID_UNALLOCATED_LAST 0x7F
--
2.30.0

View File

@ -0,0 +1,205 @@
From 176cd20c04800b4455521536f65408a076eb213d Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Mon, 30 Oct 2023 09:23:53 +0200
Subject: [PATCH] ethtool: Add support for more CMIS transceiver modules
Add three more SFF-8024 Identifier Values that according to the standard
support the Common Management Interface Specification (CMIS) memory map
so that ethtool will be able to dump, parse and print their EEPROM
contents.
commit: 8ad5035
Reference: https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=8ad503517b45
change log: change Makefile.in for openEuler CI building.
Reported-by: Mark Wang <markwang@nvidia.com>
Tested-by: Mark Wang <markwang@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
Makefile.in | 39 +++++++++++++++++++++++++++++++++++----
netlink/module-eeprom.c | 3 +++
qsfp.c | 10 +++++++---
sff-common.c | 9 +++++++++
sff-common.h | 5 ++++-
5 files changed, 58 insertions(+), 8 deletions(-)
diff --git a/Makefile.in b/Makefile.in
index 0f035a9..f4515b3 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -109,7 +109,7 @@ sbin_PROGRAMS = ethtool$(EXEEXT)
@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/eee.c netlink/tsinfo.c netlink/fec.c \
@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/stats.c \
@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/desc-ethtool.c netlink/desc-genlctrl.c \
-@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/module-eeprom.c \
+@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/module-eeprom.c netlink/module.c \
@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/desc-rtnl.c netlink/cable_test.c netlink/tunnels.c \
@ETHTOOL_ENABLE_NETLINK_TRUE@ uapi/linux/ethtool_netlink.h \
@ETHTOOL_ENABLE_NETLINK_TRUE@ uapi/linux/netlink.h uapi/linux/genetlink.h \
@@ -157,7 +157,7 @@ am__ethtool_SOURCES_DIST = ethtool.c uapi/linux/ethtool.h internal.h \
netlink/rings.c netlink/channels.c netlink/coalesce.c \
netlink/pause.c netlink/eee.c netlink/tsinfo.c netlink/fec.c \
netlink/stats.c netlink/desc-ethtool.c netlink/desc-genlctrl.c \
- netlink/module-eeprom.c netlink/desc-rtnl.c \
+ netlink/module-eeprom.c netlink/module.c netlink/desc-rtnl.c \
netlink/cable_test.c netlink/tunnels.c \
uapi/linux/ethtool_netlink.h uapi/linux/netlink.h \
uapi/linux/genetlink.h uapi/linux/rtnetlink.h \
@@ -217,6 +217,7 @@ am__dirstamp = $(am__leading_dot)dirstamp
@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/desc-ethtool.$(OBJEXT) \
@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/desc-genlctrl.$(OBJEXT) \
@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/module-eeprom.$(OBJEXT) \
+@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/module.$(OBJEXT) \
@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/desc-rtnl.$(OBJEXT) \
@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/cable_test.$(OBJEXT) \
@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/tunnels.$(OBJEXT)
@@ -246,7 +247,7 @@ am__test_cmdline_SOURCES_DIST = test-cmdline.c test-common.c ethtool.c \
netlink/channels.c netlink/coalesce.c netlink/pause.c \
netlink/eee.c netlink/tsinfo.c netlink/fec.c netlink/stats.c \
netlink/desc-ethtool.c netlink/desc-genlctrl.c \
- netlink/module-eeprom.c netlink/desc-rtnl.c \
+ netlink/module-eeprom.c netlink/module.c netlink/desc-rtnl.c \
netlink/cable_test.c netlink/tunnels.c \
uapi/linux/ethtool_netlink.h uapi/linux/netlink.h \
uapi/linux/genetlink.h uapi/linux/rtnetlink.h \
@@ -309,6 +310,7 @@ am__test_cmdline_SOURCES_DIST = test-cmdline.c test-common.c ethtool.c \
@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/test_cmdline-desc-ethtool.$(OBJEXT) \
@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/test_cmdline-desc-genlctrl.$(OBJEXT) \
@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/test_cmdline-module-eeprom.$(OBJEXT) \
+@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/test_cmdline-module.$(OBJEXT) \
@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/test_cmdline-desc-rtnl.$(OBJEXT) \
@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/test_cmdline-cable_test.$(OBJEXT) \
@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/test_cmdline-tunnels.$(OBJEXT)
@@ -343,7 +345,7 @@ am__test_features_SOURCES_DIST = test-features.c test-common.c \
netlink/rings.c netlink/channels.c netlink/coalesce.c \
netlink/pause.c netlink/eee.c netlink/tsinfo.c netlink/fec.c \
netlink/stats.c netlink/desc-ethtool.c netlink/desc-genlctrl.c \
- netlink/module-eeprom.c netlink/desc-rtnl.c \
+ netlink/module-eeprom.c netlink/module.c netlink/desc-rtnl.c \
netlink/cable_test.c netlink/tunnels.c \
uapi/linux/ethtool_netlink.h uapi/linux/netlink.h \
uapi/linux/genetlink.h uapi/linux/rtnetlink.h \
@@ -406,6 +408,7 @@ am__test_features_SOURCES_DIST = test-features.c test-common.c \
@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/test_features-desc-ethtool.$(OBJEXT) \
@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/test_features-desc-genlctrl.$(OBJEXT) \
@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/test_features-module-eeprom.$(OBJEXT) \
+@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/test_features-module.$(OBJEXT) \
@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/test_features-desc-rtnl.$(OBJEXT) \
@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/test_features-cable_test.$(OBJEXT) \
@ETHTOOL_ENABLE_NETLINK_TRUE@ netlink/test_features-tunnels.$(OBJEXT)
@@ -2238,6 +2241,20 @@ netlink/test_cmdline-module-eeprom.obj: netlink/module-eeprom.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_cmdline_CFLAGS) $(CFLAGS) -c -o netlink/test_cmdline-module-eeprom.obj `if test -f 'netlink/module-eeprom.c'; then $(CYGPATH_W) 'netlink/module-eeprom.c'; else $(CYGPATH_W) '$(srcdir)/netlink/module-eeprom.c'; fi`
+netlink/test_cmdline-module.o: netlink/module.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_cmdline_CFLAGS) $(CFLAGS) -MT netlink/test_cmdline-module.o -MD -MP -MF netlink/$(DEPDIR)/test_cmdline-module.Tpo -c -o netlink/test_cmdline-module.o `test -f 'netlink/module.c' || echo '$(srcdir)/'`netlink/module.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) netlink/$(DEPDIR)/test_cmdline-module.Tpo netlink/$(DEPDIR)/test_cmdline-module.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netlink/module.c' object='netlink/test_cmdline-module.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_cmdline_CFLAGS) $(CFLAGS) -c -o netlink/test_cmdline-module.o `test -f 'netlink/module.c' || echo '$(srcdir)/'`netlink/module.c
+
+netlink/test_cmdline-module.obj: netlink/module.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_cmdline_CFLAGS) $(CFLAGS) -MT netlink/test_cmdline-module.obj -MD -MP -MF netlink/$(DEPDIR)/test_cmdline-module.Tpo -c -o netlink/test_cmdline-module.obj `if test -f 'netlink/module.c'; then $(CYGPATH_W) 'netlink/module.c'; else $(CYGPATH_W) '$(srcdir)/netlink/module.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) netlink/$(DEPDIR)/test_cmdline-module.Tpo netlink/$(DEPDIR)/test_cmdline-module.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netlink/module.c' object='netlink/test_cmdline-module.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_cmdline_CFLAGS) $(CFLAGS) -c -o netlink/test_cmdline-module.obj `if test -f 'netlink/module.c'; then $(CYGPATH_W) 'netlink/module.c'; else $(CYGPATH_W) '$(srcdir)/netlink/module.c'; fi`
+
netlink/test_cmdline-desc-rtnl.o: netlink/desc-rtnl.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_cmdline_CFLAGS) $(CFLAGS) -MT netlink/test_cmdline-desc-rtnl.o -MD -MP -MF netlink/$(DEPDIR)/test_cmdline-desc-rtnl.Tpo -c -o netlink/test_cmdline-desc-rtnl.o `test -f 'netlink/desc-rtnl.c' || echo '$(srcdir)/'`netlink/desc-rtnl.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) netlink/$(DEPDIR)/test_cmdline-desc-rtnl.Tpo netlink/$(DEPDIR)/test_cmdline-desc-rtnl.Po
@@ -3176,6 +3193,20 @@ netlink/test_features-module-eeprom.obj: netlink/module-eeprom.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_features_CFLAGS) $(CFLAGS) -c -o netlink/test_features-module-eeprom.obj `if test -f 'netlink/module-eeprom.c'; then $(CYGPATH_W) 'netlink/module-eeprom.c'; else $(CYGPATH_W) '$(srcdir)/netlink/module-eeprom.c'; fi`
+netlink/test_features-module.o: netlink/module.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_features_CFLAGS) $(CFLAGS) -MT netlink/test_features-module.o -MD -MP -MF netlink/$(DEPDIR)/test_features-module.Tpo -c -o netlink/test_features-module.o `test -f 'netlink/module.c' || echo '$(srcdir)/'`netlink/module.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) netlink/$(DEPDIR)/test_features-module.Tpo netlink/$(DEPDIR)/test_features-module.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netlink/module.c' object='netlink/test_features-module.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_features_CFLAGS) $(CFLAGS) -c -o netlink/test_features-module.o `test -f 'netlink/module.c' || echo '$(srcdir)/'`netlink/module.c
+
+netlink/test_features-module.obj: netlink/module.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_features_CFLAGS) $(CFLAGS) -MT netlink/test_features-module.obj -MD -MP -MF netlink/$(DEPDIR)/test_features-module.Tpo -c -o netlink/test_features-module.obj `if test -f 'netlink/module.c'; then $(CYGPATH_W) 'netlink/module.c'; else $(CYGPATH_W) '$(srcdir)/netlink/module.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) netlink/$(DEPDIR)/test_features-module.Tpo netlink/$(DEPDIR)/test_features-module.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netlink/module.c' object='netlink/test_features-module.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_features_CFLAGS) $(CFLAGS) -c -o netlink/test_features-module.obj `if test -f 'netlink/module.c'; then $(CYGPATH_W) 'netlink/module.c'; else $(CYGPATH_W) '$(srcdir)/netlink/module.c'; fi`
+
netlink/test_features-desc-rtnl.o: netlink/desc-rtnl.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_features_CFLAGS) $(CFLAGS) -MT netlink/test_features-desc-rtnl.o -MD -MP -MF netlink/$(DEPDIR)/test_features-desc-rtnl.Tpo -c -o netlink/test_features-desc-rtnl.o `test -f 'netlink/desc-rtnl.c' || echo '$(srcdir)/'`netlink/desc-rtnl.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) netlink/$(DEPDIR)/test_features-desc-rtnl.Tpo netlink/$(DEPDIR)/test_features-desc-rtnl.Po
diff --git a/netlink/module-eeprom.c b/netlink/module-eeprom.c
index 49833a2..09ad580 100644
--- a/netlink/module-eeprom.c
+++ b/netlink/module-eeprom.c
@@ -225,6 +225,9 @@ static int eeprom_parse(struct cmd_context *ctx)
case SFF8024_ID_QSFP_DD:
case SFF8024_ID_OSFP:
case SFF8024_ID_DSFP:
+ case SFF8024_ID_QSFP_PLUS_CMIS:
+ case SFF8024_ID_SFP_DD_CMIS:
+ case SFF8024_ID_SFP_PLUS_CMIS:
return cmis_show_all_nl(ctx);
#endif
default:
diff --git a/qsfp.c b/qsfp.c
index 1fe5de1..ae4a581 100644
--- a/qsfp.c
+++ b/qsfp.c
@@ -947,9 +947,13 @@ 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 ||
- id[SFF8636_ID_OFFSET] == SFF8024_ID_OSFP ||
- id[SFF8636_ID_OFFSET] == SFF8024_ID_DSFP) {
+ switch (id[SFF8636_ID_OFFSET]) {
+ case SFF8024_ID_QSFP_DD:
+ case SFF8024_ID_OSFP:
+ case SFF8024_ID_DSFP:
+ case SFF8024_ID_QSFP_PLUS_CMIS:
+ case SFF8024_ID_SFP_DD_CMIS:
+ case SFF8024_ID_SFP_PLUS_CMIS:
cmis_show_all_ioctl(id);
return;
}
diff --git a/sff-common.c b/sff-common.c
index e951cf1..9e4a89b 100644
--- a/sff-common.c
+++ b/sff-common.c
@@ -145,6 +145,15 @@ void sff8024_show_identifier(const __u8 *id, int id_offset)
case SFF8024_ID_DSFP:
printf(" (DSFP Dual Small Form Factor Pluggable Transceiver)\n");
break;
+ case SFF8024_ID_QSFP_PLUS_CMIS:
+ printf(" (QSFP+ or later with Common Management Interface Specification (CMIS))\n");
+ break;
+ case SFF8024_ID_SFP_DD_CMIS:
+ printf(" (SFP-DD Double Density 2X Pluggable Transceiver with Common Management Interface Specification (CMIS))\n");
+ break;
+ case SFF8024_ID_SFP_PLUS_CMIS:
+ printf(" (SFP+ and later with Common Management Interface Specification (CMIS))\n");
+ break;
default:
printf(" (reserved or unknown)\n");
break;
diff --git a/sff-common.h b/sff-common.h
index dd12dda..94827cc 100644
--- a/sff-common.h
+++ b/sff-common.h
@@ -64,7 +64,10 @@
#define SFF8024_ID_QSFP_DD 0x18
#define SFF8024_ID_OSFP 0x19
#define SFF8024_ID_DSFP 0x1B
-#define SFF8024_ID_LAST SFF8024_ID_DSFP
+#define SFF8024_ID_QSFP_PLUS_CMIS 0x1E
+#define SFF8024_ID_SFP_DD_CMIS 0x1F
+#define SFF8024_ID_SFP_PLUS_CMIS 0x20
+#define SFF8024_ID_LAST SFF8024_ID_SFP_PLUS_CMIS
#define SFF8024_ID_UNALLOCATED_LAST 0x7F
#define SFF8024_ID_VENDOR_START 0x80
#define SFF8024_ID_VENDOR_LAST 0xFF
--
2.30.0

View File

@ -0,0 +1,431 @@
From 48a99d9618acb40c5e9ea49623fe011c57367e18 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:25 +0300
Subject: [PATCH 20/26] 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.
commit: 9538f38
Reference: https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=9538f384b535
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 6d76b8a..f359aee 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.30.0

View File

@ -0,0 +1,177 @@
From 508d443bfdc7e11f478b4d2361621ec90ee4da35 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:21 +0300
Subject: [PATCH 16/26] 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.
commit: 2ccda25
Reference: https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=2ccda2570d65
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 91bf02b..129e293 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 101d594..ee55088 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.30.0

View File

@ -0,0 +1,95 @@
From b5da70307ffb04f67db2114f62165875fb24cd92 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:24 +0300
Subject: [PATCH 19/26] 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.
commit: c2170d4
Reference: https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=c2170d40b6a1
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 1646e25..c424ef9 100644
--- a/internal.h
+++ b/internal.h
@@ -388,7 +388,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 f04f8e1..6d76b8a 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 c214820..621d1e8 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.30.0

View File

@ -0,0 +1,104 @@
From a9e34753118e1fea1cb5d7dc7ad09b8b66fa926f Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:20 +0300
Subject: [PATCH 15/26] 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.
commit: 9fdf45c
Reference: https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=9fdf45ca1726
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 fa5a347..461d1f2 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -4901,10 +4901,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 ed4f180..aa033ca 100644
--- a/internal.h
+++ b/internal.h
@@ -387,7 +387,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 18b1abb..101d594 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 da2b3f4..c214820 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.30.0

View File

@ -0,0 +1,76 @@
From f7cad168f8326cee8c9abdf5ed0156c537b057bb Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:19 +0300
Subject: [PATCH 14/26] 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.
commit: 799572f
Reference: https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=799572f86647
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 354b3b1..4aa4935 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.30.0

View File

@ -0,0 +1,140 @@
From 10337aa0fa92342e26f430cc50feb8948d55a2ac Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:17 +0300
Subject: [PATCH 12/26] 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
commit: 4230597
Reference: https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=4230597fe952
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 dc6407d..80000d4 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.30.0

View File

@ -0,0 +1,111 @@
From d306db1bab15361f36d967800c4f8dd7e3f2ee3b Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 23 Nov 2021 19:41:02 +0200
Subject: [PATCH 23/26] 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.
commit: d7b1007
Reference: https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=d7b100713f73
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 b3c9e15..57aac86 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 1d8f24b..aabf09f 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.30.0

View File

@ -0,0 +1,100 @@
From e54061aec49839249b00562b812f8dd6912bdef5 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:16 +0300
Subject: [PATCH 11/26] 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.
commit: d7d15f7
Reference: https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=d7d15f737ab7
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 7652440..fa5a347 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -4909,8 +4909,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 a30f76e..ed4f180 100644
--- a/internal.h
+++ b/internal.h
@@ -393,9 +393,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 fc4ef1a..18b1abb 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 27fdd3b..dc6407d 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.30.0

View File

@ -0,0 +1,184 @@
From 25c34d626d39d80cb7abacddd81191c006dbe57c Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:23 +0300
Subject: [PATCH 18/26] 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.
commit: 6e2b32a
Reference: https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=6e2b32a0d0ea
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 aa033ca..1646e25 100644
--- a/internal.h
+++ b/internal.h
@@ -395,8 +395,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 a8e2662..f04f8e1 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 4aa4935..e7c2f51 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.30.0

View File

@ -0,0 +1,87 @@
From 57543639e3a8b10142726afc7e277d257f902283 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 23 Nov 2021 19:40:55 +0200
Subject: [PATCH 21/26] 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'.
commit: 73091cd
Reference: https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=73091cd94023
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 e7c2f51..58c4c47 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 2183f41..aab306e 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.30.0

View File

@ -0,0 +1,610 @@
From 3926a20160a6c817df272e6ab443415a43c65470 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 12 Oct 2021 16:25:18 +0300
Subject: [PATCH 13/26] 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.
commit: b74c040
Reference: https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=b74c040256de
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 80000d4..354b3b1 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.30.0

View File

@ -0,0 +1,48 @@
From 822d80bb0be204b9e970b193066ffcbd43960105 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Tue, 23 Nov 2021 19:40:56 +0200
Subject: [PATCH 22/26] 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.
commit: 837c166
Reference: https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=837c1662ebd6
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 58c4c47..b3c9e15 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 aab306e..9e32300 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.30.0

View File

@ -1,19 +1,39 @@
Name: ethtool
Epoch: 2
Version: 5.15
Release: 6
Release: 7
Summary: Settings tool for Ethernet NICs
License: GPLv2
URL: https://www.kernel.org/pub/software/network/ethtool
Source0: https://www.kernel.org/pub/software/network/%{name}/%{name}-%{version}.tar.xz
Patch0: backport-ioctl-add-the-memory-free-operation-after-send_ioctl.patch
Patch0: backport-ioctl-add-the-memory-free-operation-after-send_ioctl.patch
Patch1: 0001-rings-add-support-to-set-get-rx-buf-len.patch
Patch2: 0002-tunables-add-support-to-get-set-tx-copybreak-buf-siz.patch
Patch3: 0003-update-UAPI-header-copies.patch
Patch4: 0004-ethtool-add-support-to-get-set-tx-push-by-ethtool-G-.patch
Patch5: 0005-ethtool-add-suppport-specifications-for-vxlan-by-eth.patch
Patch6: 0006-hns3-add-support-dump-registers-for-hns3-driver.patch
Patch7: backport-cmis-Rename-CMIS-parsing-functions.patch
Patch8: backport-cmis-Initialize-CMIS-memory-map.patch
Patch9: backport-cmis-Use-memory-map-during-parsing.patch
Patch10: backport-cmis-Consolidate-code-between-IOCTL-and-netlink-path.patch
Patch11: backport-sff-8636-Rename-SFF-8636-parsing-functions.patch
Patch12: backport-sff-8636-Initialize-SFF-8636-memory-map.patch
Patch13: backport-sff-8636-Use-memory-map-during-parsing.patch
Patch14: backport-sff-8636-Consolidate-code-between-IOCTL-and-netlink-.patch
Patch15: backport-sff-8079-Split-SFF-8079-parsing-function.patch
Patch16: backport-netlink-eeprom-Export-a-function-to-request-an-EEPRO.patch
Patch17: backport-cmis-Request-specific-pages-for-parsing-in-netlink-p.patch
Patch18: backport-sff-8636-Request-specific-pages-for-parsing-in-netli.patch
Patch19: backport-sff-8079-Request-specific-pages-for-parsing-in-netli.patch
Patch20: backport-netlink-eeprom-Defer-page-requests-to-individual-par.patch
Patch21: backport-sff-8636-Use-an-SFF-8636-specific-define-for-maximum.patch
Patch22: backport-sff-common-Move-OFFSET_TO_U16_PTR-to-common-header-f.patch
Patch23: backport-sff-8636-Print-Power-set-and-Power-override-bits.patch
Patch24: backport-ethtool-Add-ability-to-control-transceiver-modules-p.patch
Patch25: backport-ethtool-Add-support-for-OSFP-transceiver-modules.patch
Patch26: backport-ethtool-Add-support-for-more-CMIS-transceiver-module.patch
BuildRequires: gcc
BuildRequires: libmnl-devel
@ -61,6 +81,12 @@ make check
%{_mandir}/man8/%{name}.8*
%changelog
* Fri Jun 7 2024 xiaojiantao <xiaojiantao1@h-partners.com> - 2:5.15-7
- Type:requirement
- Id:NA
- SUG:NA
- DESC:add support for more CMIS transceiver modules
* Tue Sep 26 2023 xiaojiantao <xiaojiantao1@h-partners.com> - 2:5.15-6
- Type:requirement
- Id:NA