diff --git a/0003-update-UAPI-header-copies.patch b/0003-update-UAPI-header-copies.patch index a5b318f7e26739ec402c583f96b8bbffcbf1b421..2fb2a5809f266e94263160d28a6bec870ec8131d 100644 --- a/0003-update-UAPI-header-copies.patch +++ b/0003-update-UAPI-header-copies.patch @@ -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 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 --- - 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 diff --git a/0007-cmis-Rename-CMIS-parsing-functions.patch b/0007-cmis-Rename-CMIS-parsing-functions.patch new file mode 100644 index 0000000000000000000000000000000000000000..203a1fae8e876ff099cf8a8cfe8c1465ab331c46 --- /dev/null +++ b/0007-cmis-Rename-CMIS-parsing-functions.patch @@ -0,0 +1,98 @@ +From 02055157bf85134de4551e496e3fb39930f68731 Mon Sep 17 00:00:00 2001 +From: Ido Schimmel +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 +--- + 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 + diff --git a/0008-cmis-Initialize-CMIS-memory-map.patch b/0008-cmis-Initialize-CMIS-memory-map.patch new file mode 100644 index 0000000000000000000000000000000000000000..681a000d354a06c7c6054e45d8a1c6f50d63391a --- /dev/null +++ b/0008-cmis-Initialize-CMIS-memory-map.patch @@ -0,0 +1,148 @@ +From 9cfd4eac291dfa43e63ea01309a3a0d400b3286a Mon Sep 17 00:00:00 2001 +From: Ido Schimmel +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 +--- + 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 + diff --git a/0009-cmis-Use-memory-map-during-parsing.patch b/0009-cmis-Use-memory-map-during-parsing.patch new file mode 100644 index 0000000000000000000000000000000000000000..2052a15ffa1cfa823ce0f776be72b358e4f33480 --- /dev/null +++ b/0009-cmis-Use-memory-map-during-parsing.patch @@ -0,0 +1,397 @@ +From 7fba1d13bf33839c204fe3ea9d3d8db60e7cda0d Mon Sep 17 00:00:00 2001 +From: Ido Schimmel +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 +--- + 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 + diff --git a/0010-cmis-Consolidate-code-between-IOCTL-and-netlink-path.patch b/0010-cmis-Consolidate-code-between-IOCTL-and-netlink-path.patch new file mode 100644 index 0000000000000000000000000000000000000000..790c0dfde08e2757dc9ea765a04db0b0c1615791 --- /dev/null +++ b/0010-cmis-Consolidate-code-between-IOCTL-and-netlink-path.patch @@ -0,0 +1,80 @@ +From 98d2c71b11a0ffb72f56da6bccb7d274e00d96f5 Mon Sep 17 00:00:00 2001 +From: Ido Schimmel +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 +--- + 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 + diff --git a/0011-sff-8636-Rename-SFF-8636-parsing-functions.patch b/0011-sff-8636-Rename-SFF-8636-parsing-functions.patch new file mode 100644 index 0000000000000000000000000000000000000000..83b19991a84bd2dd938853614d7c62ff3459c379 --- /dev/null +++ b/0011-sff-8636-Rename-SFF-8636-parsing-functions.patch @@ -0,0 +1,100 @@ +From e54061aec49839249b00562b812f8dd6912bdef5 Mon Sep 17 00:00:00 2001 +From: Ido Schimmel +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 +--- + 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 + diff --git a/0012-sff-8636-Initialize-SFF-8636-memory-map.patch b/0012-sff-8636-Initialize-SFF-8636-memory-map.patch new file mode 100644 index 0000000000000000000000000000000000000000..ab6d9d8917c1d54edb07a25ee2f5588115d6ccc4 --- /dev/null +++ b/0012-sff-8636-Initialize-SFF-8636-memory-map.patch @@ -0,0 +1,140 @@ +From 10337aa0fa92342e26f430cc50feb8948d55a2ac Mon Sep 17 00:00:00 2001 +From: Ido Schimmel +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 +--- + 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 + diff --git a/0013-sff-8636-Use-memory-map-during-parsing.patch b/0013-sff-8636-Use-memory-map-during-parsing.patch new file mode 100644 index 0000000000000000000000000000000000000000..352755781ea2eb83e5851f6a7c3c77241200b8c3 --- /dev/null +++ b/0013-sff-8636-Use-memory-map-during-parsing.patch @@ -0,0 +1,610 @@ +From 3926a20160a6c817df272e6ab443415a43c65470 Mon Sep 17 00:00:00 2001 +From: Ido Schimmel +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 +--- + 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 + diff --git a/0014-sff-8636-Consolidate-code-between-IOCTL-and-netlink-.patch b/0014-sff-8636-Consolidate-code-between-IOCTL-and-netlink-.patch new file mode 100644 index 0000000000000000000000000000000000000000..4fa93d1f8e2f959846a939e95b647f826d5dc718 --- /dev/null +++ b/0014-sff-8636-Consolidate-code-between-IOCTL-and-netlink-.patch @@ -0,0 +1,76 @@ +From f7cad168f8326cee8c9abdf5ed0156c537b057bb Mon Sep 17 00:00:00 2001 +From: Ido Schimmel +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 +--- + 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 + diff --git a/0015-sff-8079-Split-SFF-8079-parsing-function.patch b/0015-sff-8079-Split-SFF-8079-parsing-function.patch new file mode 100644 index 0000000000000000000000000000000000000000..cbbf1c02c71b4a6b348ca494405d94f0e1ad5070 --- /dev/null +++ b/0015-sff-8079-Split-SFF-8079-parsing-function.patch @@ -0,0 +1,104 @@ +From a9e34753118e1fea1cb5d7dc7ad09b8b66fa926f Mon Sep 17 00:00:00 2001 +From: Ido Schimmel +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 +--- + 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 + diff --git a/0016-netlink-eeprom-Export-a-function-to-request-an-EEPRO.patch b/0016-netlink-eeprom-Export-a-function-to-request-an-EEPRO.patch new file mode 100644 index 0000000000000000000000000000000000000000..effc2052023d825336835c8531bfc280d745cb78 --- /dev/null +++ b/0016-netlink-eeprom-Export-a-function-to-request-an-EEPRO.patch @@ -0,0 +1,177 @@ +From 508d443bfdc7e11f478b4d2361621ec90ee4da35 Mon Sep 17 00:00:00 2001 +From: Ido Schimmel +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 +--- + 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 + diff --git a/0017-cmis-Request-specific-pages-for-parsing-in-netlink-p.patch b/0017-cmis-Request-specific-pages-for-parsing-in-netlink-p.patch new file mode 100644 index 0000000000000000000000000000000000000000..df2bc6e3e22c246e4e034f46baf90ac593aa4124 --- /dev/null +++ b/0017-cmis-Request-specific-pages-for-parsing-in-netlink-p.patch @@ -0,0 +1,197 @@ +From da5cd8deac6cfa6a45840e79a41c800282f043ce Mon Sep 17 00:00:00 2001 +From: Ido Schimmel +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 +--- + 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 + #include ++#include + #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 + diff --git a/0018-sff-8636-Request-specific-pages-for-parsing-in-netli.patch b/0018-sff-8636-Request-specific-pages-for-parsing-in-netli.patch new file mode 100644 index 0000000000000000000000000000000000000000..dce474c12368ce59c027cad9ee72ed559c4401a8 --- /dev/null +++ b/0018-sff-8636-Request-specific-pages-for-parsing-in-netli.patch @@ -0,0 +1,184 @@ +From 25c34d626d39d80cb7abacddd81191c006dbe57c Mon Sep 17 00:00:00 2001 +From: Ido Schimmel +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 +--- + 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 + #include ++#include + #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 + diff --git a/0019-sff-8079-Request-specific-pages-for-parsing-in-netli.patch b/0019-sff-8079-Request-specific-pages-for-parsing-in-netli.patch new file mode 100644 index 0000000000000000000000000000000000000000..e7fb0823fbac7bae71af854dbb25a8438e537e33 --- /dev/null +++ b/0019-sff-8079-Request-specific-pages-for-parsing-in-netli.patch @@ -0,0 +1,95 @@ +From b5da70307ffb04f67db2114f62165875fb24cd92 Mon Sep 17 00:00:00 2001 +From: Ido Schimmel +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 +--- + 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 ++#include + #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 + diff --git a/0020-netlink-eeprom-Defer-page-requests-to-individual-par.patch b/0020-netlink-eeprom-Defer-page-requests-to-individual-par.patch new file mode 100644 index 0000000000000000000000000000000000000000..7d7269f861845c95179eaa621be080d05043b678 --- /dev/null +++ b/0020-netlink-eeprom-Defer-page-requests-to-individual-par.patch @@ -0,0 +1,431 @@ +From 48a99d9618acb40c5e9ea49623fe011c57367e18 Mon Sep 17 00:00:00 2001 +From: Ido Schimmel +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 +--- + 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 + diff --git a/0021-sff-8636-Use-an-SFF-8636-specific-define-for-maximum.patch b/0021-sff-8636-Use-an-SFF-8636-specific-define-for-maximum.patch new file mode 100644 index 0000000000000000000000000000000000000000..78395ba230fd4e5e7cc2524b472ed9de5dbc7764 --- /dev/null +++ b/0021-sff-8636-Use-an-SFF-8636-specific-define-for-maximum.patch @@ -0,0 +1,87 @@ +From 57543639e3a8b10142726afc7e277d257f902283 Mon Sep 17 00:00:00 2001 +From: Ido Schimmel +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 +--- + 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 + diff --git a/0022-sff-common-Move-OFFSET_TO_U16_PTR-to-common-header-f.patch b/0022-sff-common-Move-OFFSET_TO_U16_PTR-to-common-header-f.patch new file mode 100644 index 0000000000000000000000000000000000000000..f25ef2e0c8f03c1c57ab9c7586ce6ef0c44a614a --- /dev/null +++ b/0022-sff-common-Move-OFFSET_TO_U16_PTR-to-common-header-f.patch @@ -0,0 +1,48 @@ +From 822d80bb0be204b9e970b193066ffcbd43960105 Mon Sep 17 00:00:00 2001 +From: Ido Schimmel +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 +--- + 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 + diff --git a/0023-sff-8636-Print-Power-set-and-Power-override-bits.patch b/0023-sff-8636-Print-Power-set-and-Power-override-bits.patch new file mode 100644 index 0000000000000000000000000000000000000000..737f0321e7461710ed93f82c34f2f46cbe5c6017 --- /dev/null +++ b/0023-sff-8636-Print-Power-set-and-Power-override-bits.patch @@ -0,0 +1,111 @@ +From d306db1bab15361f36d967800c4f8dd7e3f2ee3b Mon Sep 17 00:00:00 2001 +From: Ido Schimmel +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 +--- + 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 + diff --git a/0024-ethtool-Add-ability-to-control-transceiver-modules-p.patch b/0024-ethtool-Add-ability-to-control-transceiver-modules-p.patch new file mode 100644 index 0000000000000000000000000000000000000000..58c96b5dc6de0a8a65b2e394982b1a50a7e7e380 --- /dev/null +++ b/0024-ethtool-Add-ability-to-control-transceiver-modules-p.patch @@ -0,0 +1,459 @@ +From 1bc52b04285906efcbdf7e9429ed668170ebf97a Mon Sep 17 00:00:00 2001 +From: Ido Schimmel +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 +--- + 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 " and ++ * "ethtool --set-module ..." ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#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 + diff --git a/0025-ethtool-Add-support-for-OSFP-transceiver-modules.patch b/0025-ethtool-Add-support-for-OSFP-transceiver-modules.patch new file mode 100644 index 0000000000000000000000000000000000000000..b074a268d1de90632335fc276c92bcbf17f23a7a --- /dev/null +++ b/0025-ethtool-Add-support-for-OSFP-transceiver-modules.patch @@ -0,0 +1,85 @@ +From f7d99859bc603649705e439472c8f79386a8b217 Mon Sep 17 00:00:00 2001 +From: Danielle Ratson +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 +Reviewed-by: Ido Schimmel +--- + 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 + diff --git a/0026-ethtool-Add-support-for-more-CMIS-transceiver-module.patch b/0026-ethtool-Add-support-for-more-CMIS-transceiver-module.patch new file mode 100644 index 0000000000000000000000000000000000000000..a4b2454705e1999ffe613c7385fcbc789b615bfd --- /dev/null +++ b/0026-ethtool-Add-support-for-more-CMIS-transceiver-module.patch @@ -0,0 +1,205 @@ +From 176cd20c04800b4455521536f65408a076eb213d Mon Sep 17 00:00:00 2001 +From: Ido Schimmel +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 +Tested-by: Mark Wang +Signed-off-by: Ido Schimmel +--- + 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 + diff --git a/ethtool.spec b/ethtool.spec index 872cda6b8d8a48f416b93337dc695b2ed969c88d..ab84c8de48bae11487c6d389018f551377efd89b 100644 --- a/ethtool.spec +++ b/ethtool.spec @@ -1,7 +1,7 @@ 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 @@ -14,6 +14,26 @@ 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: 0007-cmis-Rename-CMIS-parsing-functions.patch +Patch8: 0008-cmis-Initialize-CMIS-memory-map.patch +Patch9: 0009-cmis-Use-memory-map-during-parsing.patch +Patch10: 0010-cmis-Consolidate-code-between-IOCTL-and-netlink-path.patch +Patch11: 0011-sff-8636-Rename-SFF-8636-parsing-functions.patch +Patch12: 0012-sff-8636-Initialize-SFF-8636-memory-map.patch +Patch13: 0013-sff-8636-Use-memory-map-during-parsing.patch +Patch14: 0014-sff-8636-Consolidate-code-between-IOCTL-and-netlink-.patch +Patch15: 0015-sff-8079-Split-SFF-8079-parsing-function.patch +Patch16: 0016-netlink-eeprom-Export-a-function-to-request-an-EEPRO.patch +Patch17: 0017-cmis-Request-specific-pages-for-parsing-in-netlink-p.patch +Patch18: 0018-sff-8636-Request-specific-pages-for-parsing-in-netli.patch +Patch19: 0019-sff-8079-Request-specific-pages-for-parsing-in-netli.patch +Patch20: 0020-netlink-eeprom-Defer-page-requests-to-individual-par.patch +Patch21: 0021-sff-8636-Use-an-SFF-8636-specific-define-for-maximum.patch +Patch22: 0022-sff-common-Move-OFFSET_TO_U16_PTR-to-common-header-f.patch +Patch23: 0023-sff-8636-Print-Power-set-and-Power-override-bits.patch +Patch24: 0024-ethtool-Add-ability-to-control-transceiver-modules-p.patch +Patch25: 0025-ethtool-Add-support-for-OSFP-transceiver-modules.patch +Patch26: 0026-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 +* Tue Mar 21 2023 xiaojiantao - 2:5.15-7 +- Type:requirement +- Id:NA +- SUG:NA +- DESC:add support for more CMIS transceiver modules + * Tue Sep 26 2023 xiaojiantao - 2:5.15-6 - Type:requirement - Id:NA