netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH ethtool-next 0/8] ethtool: Add support for CMIS diagnostic information
@ 2021-11-23 17:40 Ido Schimmel
  2021-11-23 17:40 ` [PATCH ethtool-next 1/8] sff-8636: Use an SFF-8636 specific define for maximum number of channels Ido Schimmel
                   ` (9 more replies)
  0 siblings, 10 replies; 14+ messages in thread
From: Ido Schimmel @ 2021-11-23 17:40 UTC (permalink / raw)
  To: netdev; +Cc: mkubecek, popadrian1996, andrew, mlxsw, moshe, Ido Schimmel

From: Ido Schimmel <idosch@nvidia.com>

This patchset extends ethtool(8) to retrieve, parse and print CMIS
diagnostic information. This information includes module-level monitors
(e.g., temperature, voltage), channel-level monitors (e.g., Tx optical
power) and related thresholds and flags.

ethtool(8) already supports SFF-8636 (e.g., QSFP) and SFF-8472 (e.g.,
SFP) diagnostic information, but until recently CMIS diagnostic
information was unavailable to ethtool(8) as it resides in optional and
banked pages.

Testing
=======

Build tested each patch with the following configuration options:

netlink | pretty-dump
--------|------------
v       | v
x       | x
v       | x
x       | v

Except fields that were added, no difference in output before and after
the patchset. Tested with both PC and AOC QSFP-DD modules.

No reports from AddressSanitizer / valgrind.

Patchset overview
=================

Patches #1-#2 are small preparations.

Patches #3-#4 retrieve (over netlink) and initialize the optional and
banked pages in the CMIS memory map. These pages contain the previously
mentioned diagnostic information.

Patch #5 parses and prints the CMIS diagnostic information in a similar
fashion to the way it is done for SFF-8636.

Patches #6-#7 print a few additional fields from the CMIS EEPROM dump.
The examples contain an ethtool command that is supported by the kernel,
but not yet by ethtool(8). It will be sent as a follow-up patchset.

Patch #8 prints the equivalent module-level fields for SFF-8636.

Ido Schimmel (8):
  sff-8636: Use an SFF-8636 specific define for maximum number of
    channels
  sff-common: Move OFFSET_TO_U16_PTR() to common header file
  cmis: Initialize Page 02h in memory map
  cmis: Initialize Banked Page 11h in memory map
  cmis: Parse and print diagnostic information
  cmis: Print Module State and Fault Cause
  cmis: Print Module-Level Controls
  sff-8636: Print Power set and Power override bits

 cmis.c       | 611 ++++++++++++++++++++++++++++++++++++++++++++++++---
 cmis.h       | 107 +++++++++
 qsfp.c       |  16 +-
 qsfp.h       |   2 +-
 sff-common.h |   6 +-
 5 files changed, 702 insertions(+), 40 deletions(-)

-- 
2.31.1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH ethtool-next 1/8] sff-8636: Use an SFF-8636 specific define for maximum number of channels
  2021-11-23 17:40 [PATCH ethtool-next 0/8] ethtool: Add support for CMIS diagnostic information Ido Schimmel
@ 2021-11-23 17:40 ` Ido Schimmel
  2021-11-23 17:40 ` [PATCH ethtool-next 2/8] sff-common: Move OFFSET_TO_U16_PTR() to common header file Ido Schimmel
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Ido Schimmel @ 2021-11-23 17:40 UTC (permalink / raw)
  To: netdev; +Cc: mkubecek, popadrian1996, andrew, mlxsw, moshe, Ido Schimmel

From: Ido Schimmel <idosch@nvidia.com>

'MAX_CHANNEL_NUM' is defined in the common SFF code as 4 and used to set
the size of the per-channel diagnostics array in the common 'sff_diags'
structure.

The CMIS parsing code is also going to use the structure, but it can
have up to 32 channels, unlike SFF-8636 that only has 4.

Therefore, set 'MAX_CHANNEL_NUM' to 32 and change the SFF-8636 code to
use an SFF-8636 specific define instead of the common 'MAX_CHANNEL_NUM'.

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 qsfp.c       | 9 +++++----
 sff-common.h | 2 +-
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/qsfp.c b/qsfp.c
index e7c2f51cd9c6..58c4c4775e9b 100644
--- a/qsfp.c
+++ b/qsfp.c
@@ -71,6 +71,7 @@ struct sff8636_memory_map {
 
 #define SFF8636_PAGE_SIZE	0x80
 #define SFF8636_I2C_ADDRESS	0x50
+#define SFF8636_MAX_CHANNEL_NUM	4
 
 #define MAX_DESC_SIZE	42
 
@@ -761,7 +762,7 @@ static void sff8636_dom_parse(const struct sff8636_memory_map *map,
 
 out:
 	/* Channel Specific Data */
-	for (i = 0; i < MAX_CHANNEL_NUM; i++) {
+	for (i = 0; i < SFF8636_MAX_CHANNEL_NUM; i++) {
 		u8 rx_power_offset, tx_bias_offset;
 		u8 tx_power_offset;
 
@@ -832,13 +833,13 @@ static void sff8636_show_dom(const struct sff8636_memory_map *map)
 	printf("\t%-41s : %s\n", "Alarm/warning flags implemented",
 		(sd.supports_alarms ? "Yes" : "No"));
 
-	for (i = 0; i < MAX_CHANNEL_NUM; i++) {
+	for (i = 0; i < SFF8636_MAX_CHANNEL_NUM; i++) {
 		snprintf(power_string, MAX_DESC_SIZE, "%s (Channel %d)",
 					"Laser tx bias current", i+1);
 		PRINT_BIAS(power_string, sd.scd[i].bias_cur);
 	}
 
-	for (i = 0; i < MAX_CHANNEL_NUM; i++) {
+	for (i = 0; i < SFF8636_MAX_CHANNEL_NUM; i++) {
 		snprintf(power_string, MAX_DESC_SIZE, "%s (Channel %d)",
 					"Transmit avg optical power", i+1);
 		PRINT_xX_PWR(power_string, sd.scd[i].tx_power);
@@ -849,7 +850,7 @@ static void sff8636_show_dom(const struct sff8636_memory_map *map)
 	else
 		rx_power_string = "Rcvr signal avg optical power";
 
-	for (i = 0; i < MAX_CHANNEL_NUM; i++) {
+	for (i = 0; i < SFF8636_MAX_CHANNEL_NUM; i++) {
 		snprintf(power_string, MAX_DESC_SIZE, "%s(Channel %d)",
 					rx_power_string, i+1);
 		PRINT_xX_PWR(power_string, sd.scd[i].rx_power);
diff --git a/sff-common.h b/sff-common.h
index 2183f41ff9c9..aab306e0b74f 100644
--- a/sff-common.h
+++ b/sff-common.h
@@ -160,7 +160,7 @@ struct sff_channel_diags {
 /* Module Monitoring Fields */
 struct sff_diags {
 
-#define MAX_CHANNEL_NUM 4
+#define MAX_CHANNEL_NUM 32
 #define LWARN 0
 #define HWARN 1
 #define LALRM 2
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH ethtool-next 2/8] sff-common: Move OFFSET_TO_U16_PTR() to common header file
  2021-11-23 17:40 [PATCH ethtool-next 0/8] ethtool: Add support for CMIS diagnostic information Ido Schimmel
  2021-11-23 17:40 ` [PATCH ethtool-next 1/8] sff-8636: Use an SFF-8636 specific define for maximum number of channels Ido Schimmel
@ 2021-11-23 17:40 ` Ido Schimmel
  2021-12-02 21:55   ` Michal Kubecek
  2021-11-23 17:40 ` [PATCH ethtool-next 3/8] cmis: Initialize Page 02h in memory map Ido Schimmel
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 14+ messages in thread
From: Ido Schimmel @ 2021-11-23 17:40 UTC (permalink / raw)
  To: netdev; +Cc: mkubecek, popadrian1996, andrew, mlxsw, moshe, Ido Schimmel

From: Ido Schimmel <idosch@nvidia.com>

The define is also useful for CMIS, so move it from SFF-8636 to the
common header file.

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 qsfp.c       | 1 -
 sff-common.h | 4 ++--
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/qsfp.c b/qsfp.c
index 58c4c4775e9b..b3c9e1516af9 100644
--- a/qsfp.c
+++ b/qsfp.c
@@ -700,7 +700,6 @@ sff8636_show_wavelength_or_copper_compliance(const struct sff8636_memory_map *ma
  * Second byte are 1/256th of degree, which are added to the dec part.
  */
 #define SFF8636_OFFSET_TO_TEMP(offset) ((__s16)OFFSET_TO_U16(offset))
-#define OFFSET_TO_U16_PTR(ptr, offset) (ptr[offset] << 8 | ptr[(offset) + 1])
 
 static void sff8636_dom_parse(const struct sff8636_memory_map *map,
 			      struct sff_diags *sd)
diff --git a/sff-common.h b/sff-common.h
index aab306e0b74f..9e323008ba19 100644
--- a/sff-common.h
+++ b/sff-common.h
@@ -126,8 +126,8 @@
 #define  SFF8024_ENCODING_PAM4			0x08
 
 /* Most common case: 16-bit unsigned integer in a certain unit */
-#define OFFSET_TO_U16(offset) \
-		(id[offset] << 8 | id[(offset) + 1])
+#define OFFSET_TO_U16_PTR(ptr, offset) (ptr[offset] << 8 | ptr[(offset) + 1])
+#define OFFSET_TO_U16(offset) OFFSET_TO_U16_PTR(id, offset)
 
 # define PRINT_xX_PWR(string, var)                             \
 		printf("\t%-41s : %.4f mW / %.2f dBm\n", (string),         \
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH ethtool-next 3/8] cmis: Initialize Page 02h in memory map
  2021-11-23 17:40 [PATCH ethtool-next 0/8] ethtool: Add support for CMIS diagnostic information Ido Schimmel
  2021-11-23 17:40 ` [PATCH ethtool-next 1/8] sff-8636: Use an SFF-8636 specific define for maximum number of channels Ido Schimmel
  2021-11-23 17:40 ` [PATCH ethtool-next 2/8] sff-common: Move OFFSET_TO_U16_PTR() to common header file Ido Schimmel
@ 2021-11-23 17:40 ` Ido Schimmel
  2021-11-23 17:40 ` [PATCH ethtool-next 4/8] cmis: Initialize Banked Page 11h " Ido Schimmel
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Ido Schimmel @ 2021-11-23 17:40 UTC (permalink / raw)
  To: netdev; +Cc: mkubecek, popadrian1996, andrew, mlxsw, moshe, Ido Schimmel

From: Ido Schimmel <idosch@nvidia.com>

Page 02h stores module and lane thresholds that are going to be parsed
and displayed in subsequent patches.

Request it via the 'MODULE_EEPROM_GET' netlink message and initialize it
in the memory map.

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 cmis.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/cmis.c b/cmis.c
index 4798fd4c7d68..55b9d1b959cd 100644
--- a/cmis.c
+++ b/cmis.c
@@ -17,9 +17,10 @@
 
 struct cmis_memory_map {
 	const __u8 *lower_memory;
-	const __u8 *upper_memory[1][2];	/* Bank, Page */
+	const __u8 *upper_memory[1][3];	/* Bank, Page */
 #define page_00h upper_memory[0x0][0x0]
 #define page_01h upper_memory[0x0][0x1]
+#define page_02h upper_memory[0x0][0x2]
 };
 
 #define CMIS_PAGE_SIZE		0x80
@@ -423,8 +424,8 @@ cmis_memory_map_init_pages(struct cmd_context *ctx,
 		return ret;
 	map->page_00h = request.data - CMIS_PAGE_SIZE;
 
-	/* Page 01h is only present when the module memory model is paged and
-	 * not flat.
+	/* Pages 01h and 02h are only present when the module memory model is
+	 * paged and not flat.
 	 */
 	if (map->lower_memory[CMIS_MEMORY_MODEL_OFFSET] &
 	    CMIS_MEMORY_MODEL_MASK)
@@ -436,6 +437,12 @@ cmis_memory_map_init_pages(struct cmd_context *ctx,
 		return ret;
 	map->page_01h = request.data - CMIS_PAGE_SIZE;
 
+	cmis_request_init(&request, 0, 0x2, CMIS_PAGE_SIZE);
+	ret = nl_get_eeprom_page(ctx, &request);
+	if (ret < 0)
+		return ret;
+	map->page_02h = request.data - CMIS_PAGE_SIZE;
+
 	return 0;
 }
 
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH ethtool-next 4/8] cmis: Initialize Banked Page 11h in memory map
  2021-11-23 17:40 [PATCH ethtool-next 0/8] ethtool: Add support for CMIS diagnostic information Ido Schimmel
                   ` (2 preceding siblings ...)
  2021-11-23 17:40 ` [PATCH ethtool-next 3/8] cmis: Initialize Page 02h in memory map Ido Schimmel
@ 2021-11-23 17:40 ` Ido Schimmel
  2021-11-23 17:40 ` [PATCH ethtool-next 5/8] cmis: Parse and print diagnostic information Ido Schimmel
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Ido Schimmel @ 2021-11-23 17:40 UTC (permalink / raw)
  To: netdev; +Cc: mkubecek, popadrian1996, andrew, mlxsw, moshe, Ido Schimmel

From: Ido Schimmel <idosch@nvidia.com>

Banked Page 11h stores, among other things, lane-specific flags and
monitors that are going to be parsed and displayed in subsequent
patches.

Request it via the 'MODULE_EEPROM_GET' netlink message and initialize it
in the memory map.

Only initialize it in supported Banks.

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 cmis.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++--
 cmis.h |  7 +++++++
 2 files changed, 54 insertions(+), 2 deletions(-)

diff --git a/cmis.c b/cmis.c
index 55b9d1b959cd..83ced4d253ae 100644
--- a/cmis.c
+++ b/cmis.c
@@ -15,9 +15,17 @@
 #include "cmis.h"
 #include "netlink/extapi.h"
 
+/* The maximum number of supported Banks. Relevant documents:
+ * [1] CMIS Rev. 5, page. 128, section 8.4.4, Table 8-40
+ */
+#define CMIS_MAX_BANKS	4
+
+/* We are not parsing further than Page 11h. */
+#define CMIS_MAX_PAGES	18
+
 struct cmis_memory_map {
 	const __u8 *lower_memory;
-	const __u8 *upper_memory[1][3];	/* Bank, Page */
+	const __u8 *upper_memory[CMIS_MAX_BANKS][CMIS_MAX_PAGES];
 #define page_00h upper_memory[0x0][0x0]
 #define page_01h upper_memory[0x0][0x1]
 #define page_02h upper_memory[0x0][0x2]
@@ -399,12 +407,33 @@ static void cmis_request_init(struct ethtool_module_eeprom *request, u8 bank,
 	request->data = NULL;
 }
 
+static int cmis_num_banks_get(const struct cmis_memory_map *map,
+			      int *p_num_banks)
+{
+	switch (map->page_01h[CMIS_PAGES_ADVER_OFFSET] &
+		CMIS_BANKS_SUPPORTED_MASK) {
+	case CMIS_BANK_0_SUPPORTED:
+		*p_num_banks = 1;
+		break;
+	case CMIS_BANK_0_1_SUPPORTED:
+		*p_num_banks = 2;
+		break;
+	case CMIS_BANK_0_3_SUPPORTED:
+		*p_num_banks = 4;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int
 cmis_memory_map_init_pages(struct cmd_context *ctx,
 			   struct cmis_memory_map *map)
 {
 	struct ethtool_module_eeprom request;
-	int ret;
+	int num_banks, i, ret;
 
 	/* Lower Memory and Page 00h are always present.
 	 *
@@ -443,6 +472,22 @@ cmis_memory_map_init_pages(struct cmd_context *ctx,
 		return ret;
 	map->page_02h = request.data - CMIS_PAGE_SIZE;
 
+	/* Bank 0 of Page 11h provides lane-specific registers for the first 8
+	 * lanes, and each additional Banks provides support for an additional
+	 * 8 lanes. Only initialize supported Banks.
+	 */
+	ret = cmis_num_banks_get(map, &num_banks);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < num_banks; i++) {
+		cmis_request_init(&request, i, 0x11, CMIS_PAGE_SIZE);
+		ret = nl_get_eeprom_page(ctx, &request);
+		if (ret < 0)
+			return ret;
+		map->upper_memory[i][0x11] = request.data - CMIS_PAGE_SIZE;
+	}
+
 	return 0;
 }
 
diff --git a/cmis.h b/cmis.h
index 911491dc5c8f..8d90a04756ad 100644
--- a/cmis.h
+++ b/cmis.h
@@ -114,6 +114,13 @@
 #define CMIS_WAVELENGTH_TOL_MSB			0x8C
 #define CMIS_WAVELENGTH_TOL_LSB			0x8D
 
+/* Supported Pages Advertising (Page 1) */
+#define CMIS_PAGES_ADVER_OFFSET			0x8E
+#define CMIS_BANKS_SUPPORTED_MASK		0x03
+#define CMIS_BANK_0_SUPPORTED			0x00
+#define CMIS_BANK_0_1_SUPPORTED			0x01
+#define CMIS_BANK_0_3_SUPPORTED			0x02
+
 /* Signal integrity controls */
 #define CMIS_SIG_INTEG_TX_OFFSET		0xA1
 #define CMIS_SIG_INTEG_RX_OFFSET		0xA2
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH ethtool-next 5/8] cmis: Parse and print diagnostic information
  2021-11-23 17:40 [PATCH ethtool-next 0/8] ethtool: Add support for CMIS diagnostic information Ido Schimmel
                   ` (3 preceding siblings ...)
  2021-11-23 17:40 ` [PATCH ethtool-next 4/8] cmis: Initialize Banked Page 11h " Ido Schimmel
@ 2021-11-23 17:40 ` Ido Schimmel
  2021-11-23 17:41 ` [PATCH ethtool-next 6/8] cmis: Print Module State and Fault Cause Ido Schimmel
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Ido Schimmel @ 2021-11-23 17:40 UTC (permalink / raw)
  To: netdev; +Cc: mkubecek, popadrian1996, andrew, mlxsw, moshe, Ido Schimmel

From: Ido Schimmel <idosch@nvidia.com>

Like SFF-8636, CMIS has module-level monitors such as temperature and
voltage and channel-level monitors such as Tx optical power.

These monitors have thresholds and flags that are set when the monitors
cross the thresholds.

Print and parse these values in a similar fashion to SFF-8636.

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 cmis.c | 466 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
 cmis.h |  79 ++++++++++
 2 files changed, 518 insertions(+), 27 deletions(-)

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


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH ethtool-next 6/8] cmis: Print Module State and Fault Cause
  2021-11-23 17:40 [PATCH ethtool-next 0/8] ethtool: Add support for CMIS diagnostic information Ido Schimmel
                   ` (4 preceding siblings ...)
  2021-11-23 17:40 ` [PATCH ethtool-next 5/8] cmis: Parse and print diagnostic information Ido Schimmel
@ 2021-11-23 17:41 ` Ido Schimmel
  2021-11-23 17:41 ` [PATCH ethtool-next 7/8] cmis: Print Module-Level Controls Ido Schimmel
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Ido Schimmel @ 2021-11-23 17:41 UTC (permalink / raw)
  To: netdev; +Cc: mkubecek, popadrian1996, andrew, mlxsw, moshe, Ido Schimmel

From: Ido Schimmel <idosch@nvidia.com>

Print the CMIS Module State when dumping EEPROM contents via the '-m'
option. It can be used, for example, to test module power mode settings.

Example output:

 # ethtool -m swp11
 Identifier                                : 0x18 (QSFP-DD Double Density 8X Pluggable Transceiver (INF-8628))
 ...
 Module State                              : 0x03 (ModuleReady)

 # ethtool --set-module swp11 power-mode-policy auto

 # ethtool -m swp11
 Identifier                                : 0x18 (QSFP-DD Double Density 8X Pluggable Transceiver (INF-8628))
 ...
 Module State                              : 0x01 (ModuleLowPwr)

In case the module is in fault state, print the CMIS Module Fault Cause.

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 cmis.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 cmis.h | 16 ++++++++++++++
 2 files changed, 86 insertions(+)

diff --git a/cmis.c b/cmis.c
index d7b7097139b3..a32cc9f8b1f6 100644
--- a/cmis.c
+++ b/cmis.c
@@ -402,6 +402,74 @@ static void cmis_show_vendor_info(const struct cmis_memory_map *map)
 			       CMIS_CLEI_END_OFFSET, "CLEI code");
 }
 
+/* Print the current Module State. Relevant documents:
+ * [1] CMIS Rev. 5, pag. 57, section 6.3.2.2, Figure 6-3
+ * [2] CMIS Rev. 5, pag. 60, section 6.3.2.3, Figure 6-4
+ * [3] CMIS Rev. 5, pag. 107, section 8.2.2, Table 8-6
+ */
+static void cmis_show_mod_state(const struct cmis_memory_map *map)
+{
+	__u8 mod_state;
+
+	mod_state = (map->lower_memory[CMIS_MODULE_STATE_OFFSET] &
+		     CMIS_MODULE_STATE_MASK) >> 1;
+	printf("\t%-41s : 0x%02x", "Module State", mod_state);
+	switch (mod_state) {
+	case CMIS_MODULE_STATE_MODULE_LOW_PWR:
+		printf(" (ModuleLowPwr)\n");
+		break;
+	case CMIS_MODULE_STATE_MODULE_PWR_UP:
+		printf(" (ModulePwrUp)\n");
+		break;
+	case CMIS_MODULE_STATE_MODULE_READY:
+		printf(" (ModuleReady)\n");
+		break;
+	case CMIS_MODULE_STATE_MODULE_PWR_DN:
+		printf(" (ModulePwrDn)\n");
+		break;
+	case CMIS_MODULE_STATE_MODULE_FAULT:
+		printf(" (ModuleFault)\n");
+		break;
+	default:
+		printf(" (reserved or unknown)\n");
+		break;
+	}
+}
+
+/* Print the Module Fault Information. Relevant documents:
+ * [1] CMIS Rev. 5, pag. 64, section 6.3.2.12
+ * [2] CMIS Rev. 5, pag. 115, section 8.2.10, Table 8-15
+ */
+static void cmis_show_mod_fault_cause(const struct cmis_memory_map *map)
+{
+	__u8 mod_state, fault_cause;
+
+	mod_state = (map->lower_memory[CMIS_MODULE_STATE_OFFSET] &
+		     CMIS_MODULE_STATE_MASK) >> 1;
+	if (mod_state != CMIS_MODULE_STATE_MODULE_FAULT)
+		return;
+
+	fault_cause = map->lower_memory[CMIS_MODULE_FAULT_OFFSET];
+	printf("\t%-41s : 0x%02x", "Module Fault Cause", fault_cause);
+	switch (fault_cause) {
+	case CMIS_MODULE_FAULT_NO_FAULT:
+		printf(" (No fault detected / not supported)\n");
+		break;
+	case CMIS_MODULE_FAULT_TEC_RUNAWAY:
+		printf(" (TEC runaway)\n");
+		break;
+	case CMIS_MODULE_FAULT_DATA_MEM_CORRUPTED:
+		printf(" (Data memory corrupted)\n");
+		break;
+	case CMIS_MODULE_FAULT_PROG_MEM_CORRUPTED:
+		printf(" (Program memory corrupted)\n");
+		break;
+	default:
+		printf(" (reserved or unknown)\n");
+		break;
+	}
+}
+
 static void cmis_parse_dom_power_type(const struct cmis_memory_map *map,
 				      struct sff_diags *sd)
 {
@@ -775,6 +843,8 @@ static void cmis_show_all_common(const struct cmis_memory_map *map)
 	cmis_show_link_len(map);
 	cmis_show_vendor_info(map);
 	cmis_show_rev_compliance(map);
+	cmis_show_mod_state(map);
+	cmis_show_mod_fault_cause(map);
 	cmis_show_dom(map);
 }
 
diff --git a/cmis.h b/cmis.h
index 310697b0ef32..2c67ad5640ab 100644
--- a/cmis.h
+++ b/cmis.h
@@ -7,6 +7,15 @@
 #define CMIS_MEMORY_MODEL_OFFSET		0x02
 #define CMIS_MEMORY_MODEL_MASK			0x80
 
+/* Global Status Information (Page 0) */
+#define CMIS_MODULE_STATE_OFFSET		0x03
+#define CMIS_MODULE_STATE_MASK			0x0E
+#define CMIS_MODULE_STATE_MODULE_LOW_PWR	0x01
+#define CMIS_MODULE_STATE_MODULE_PWR_UP		0x02
+#define CMIS_MODULE_STATE_MODULE_READY		0x03
+#define CMIS_MODULE_STATE_MODULE_PWR_DN		0x04
+#define CMIS_MODULE_STATE_MODULE_FAULT		0x05
+
 /* Module Flags (Page 0) */
 #define CMIS_VCC_AW_OFFSET			0x09
 #define CMIS_VCC_LWARN_STATUS			0x80
@@ -27,6 +36,13 @@
 #define CMIS_CURR_TEMP_OFFSET			0x0E
 #define CMIS_CURR_VCC_OFFSET			0x10
 
+/* Module Fault Information (Page 0) */
+#define CMIS_MODULE_FAULT_OFFSET		0x29
+#define CMIS_MODULE_FAULT_NO_FAULT		0x00
+#define CMIS_MODULE_FAULT_TEC_RUNAWAY		0x01
+#define CMIS_MODULE_FAULT_DATA_MEM_CORRUPTED	0x02
+#define CMIS_MODULE_FAULT_PROG_MEM_CORRUPTED	0x03
+
 #define CMIS_CTOR_OFFSET			0xCB
 
 /* Vendor related information (Page 0) */
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH ethtool-next 7/8] cmis: Print Module-Level Controls
  2021-11-23 17:40 [PATCH ethtool-next 0/8] ethtool: Add support for CMIS diagnostic information Ido Schimmel
                   ` (5 preceding siblings ...)
  2021-11-23 17:41 ` [PATCH ethtool-next 6/8] cmis: Print Module State and Fault Cause Ido Schimmel
@ 2021-11-23 17:41 ` Ido Schimmel
  2021-11-23 17:41 ` [PATCH ethtool-next 8/8] sff-8636: Print Power set and Power override bits Ido Schimmel
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Ido Schimmel @ 2021-11-23 17:41 UTC (permalink / raw)
  To: netdev; +Cc: mkubecek, popadrian1996, andrew, mlxsw, moshe, Ido Schimmel

From: Ido Schimmel <idosch@nvidia.com>

Print the CMIS Module-Level Controls when dumping EEPROM contents via
the '-m' option. It can be used to understand low power mode enforcement
by the host.

Example output:

 # ethtool -m swp11
 Identifier                                : 0x18 (QSFP-DD Double Density 8X Pluggable Transceiver (INF-8628))
 ...
 Module State                              : 0x03 (ModuleReady)
 LowPwrAllowRequestHW                      : Off
 LowPwrRequestSW                           : Off
 ...
 Transmit avg optical power (Channel 1)    : 1.3222 mW / 1.21 dBm
 Transmit avg optical power (Channel 2)    : 1.2666 mW / 1.03 dBm
 Transmit avg optical power (Channel 3)    : 1.2860 mW / 1.09 dBm
 Transmit avg optical power (Channel 4)    : 1.2988 mW / 1.14 dBm
 Transmit avg optical power (Channel 5)    : 1.2828 mW / 1.08 dBm
 Transmit avg optical power (Channel 6)    : 1.2913 mW / 1.11 dBm
 Transmit avg optical power (Channel 7)    : 1.2636 mW / 1.02 dBm
 Transmit avg optical power (Channel 8)    : 1.3408 mW / 1.27 dBm
 Transmit avg optical power (Channel 9)    : 1.3222 mW / 1.21 dBm
 Transmit avg optical power (Channel 10)   : 1.2666 mW / 1.03 dBm
 Transmit avg optical power (Channel 11)   : 1.2860 mW / 1.09 dBm
 Transmit avg optical power (Channel 12)   : 1.2988 mW / 1.14 dBm
 Transmit avg optical power (Channel 13)   : 1.2828 mW / 1.08 dBm
 Transmit avg optical power (Channel 14)   : 1.2913 mW / 1.11 dBm
 Transmit avg optical power (Channel 15)   : 1.2636 mW / 1.02 dBm
 Transmit avg optical power (Channel 16)   : 1.3408 mW / 1.27 dBm
 Rcvr signal avg optical power (Channel 1) : 1.1351 mW / 0.55 dBm
 Rcvr signal avg optical power (Channel 2) : 1.1603 mW / 0.65 dBm
 Rcvr signal avg optical power (Channel 3) : 1.1529 mW / 0.62 dBm
 Rcvr signal avg optical power (Channel 4) : 1.1670 mW / 0.67 dBm
 Rcvr signal avg optical power (Channel 5) : 1.1759 mW / 0.70 dBm
 Rcvr signal avg optical power (Channel 6) : 1.1744 mW / 0.70 dBm
 Rcvr signal avg optical power (Channel 7) : 1.1188 mW / 0.49 dBm
 Rcvr signal avg optical power (Channel 8) : 1.1640 mW / 0.66 dBm
 Rcvr signal avg optical power (Channel 9) : 1.1351 mW / 0.55 dBm
 Rcvr signal avg optical power (Channel 10) : 1.1603 mW / 0.65 dBm
 Rcvr signal avg optical power (Channel 11) : 1.1529 mW / 0.62 dBm
 Rcvr signal avg optical power (Channel 12) : 1.1670 mW / 0.67 dBm
 Rcvr signal avg optical power (Channel 13) : 1.1759 mW / 0.70 dBm
 Rcvr signal avg optical power (Channel 14) : 1.1744 mW / 0.70 dBm
 Rcvr signal avg optical power (Channel 15) : 1.1188 mW / 0.49 dBm
 Rcvr signal avg optical power (Channel 16) : 1.1640 mW / 0.66 dBm

 # ethtool --set-module swp11 power-mode-policy auto

 # ethtool -m swp11
 Identifier                                : 0x18 (QSFP-DD Double Density 8X Pluggable Transceiver (INF-8628))
 ...
 Module State                              : 0x01 (ModuleLowPwr)
 LowPwrAllowRequestHW                      : Off
 LowPwrRequestSW                           : On
 ...
 Transmit avg optical power (Channel 1)    : 0.0001 mW / -40.00 dBm
 Transmit avg optical power (Channel 2)    : 0.0001 mW / -40.00 dBm
 Transmit avg optical power (Channel 3)    : 0.0001 mW / -40.00 dBm
 Transmit avg optical power (Channel 4)    : 0.0001 mW / -40.00 dBm
 Transmit avg optical power (Channel 5)    : 0.0001 mW / -40.00 dBm
 Transmit avg optical power (Channel 6)    : 0.0001 mW / -40.00 dBm
 Transmit avg optical power (Channel 7)    : 0.0001 mW / -40.00 dBm
 Transmit avg optical power (Channel 8)    : 0.0001 mW / -40.00 dBm
 Transmit avg optical power (Channel 9)    : 0.0001 mW / -40.00 dBm
 Transmit avg optical power (Channel 10)   : 0.0001 mW / -40.00 dBm
 Transmit avg optical power (Channel 11)   : 0.0001 mW / -40.00 dBm
 Transmit avg optical power (Channel 12)   : 0.0001 mW / -40.00 dBm
 Transmit avg optical power (Channel 13)   : 0.0001 mW / -40.00 dBm
 Transmit avg optical power (Channel 14)   : 0.0001 mW / -40.00 dBm
 Transmit avg optical power (Channel 15)   : 0.0001 mW / -40.00 dBm
 Transmit avg optical power (Channel 16)   : 0.0001 mW / -40.00 dBm
 Rcvr signal avg optical power (Channel 1) : 0.0001 mW / -40.00 dBm
 Rcvr signal avg optical power (Channel 2) : 0.0001 mW / -40.00 dBm
 Rcvr signal avg optical power (Channel 3) : 0.0001 mW / -40.00 dBm
 Rcvr signal avg optical power (Channel 4) : 0.0001 mW / -40.00 dBm
 Rcvr signal avg optical power (Channel 5) : 0.0001 mW / -40.00 dBm
 Rcvr signal avg optical power (Channel 6) : 0.0001 mW / -40.00 dBm
 Rcvr signal avg optical power (Channel 7) : 0.0001 mW / -40.00 dBm
 Rcvr signal avg optical power (Channel 8) : 0.0001 mW / -40.00 dBm
 Rcvr signal avg optical power (Channel 9) : 0.0001 mW / -40.00 dBm
 Rcvr signal avg optical power (Channel 10) : 0.0001 mW / -40.00 dBm
 Rcvr signal avg optical power (Channel 11) : 0.0001 mW / -40.00 dBm
 Rcvr signal avg optical power (Channel 12) : 0.0001 mW / -40.00 dBm
 Rcvr signal avg optical power (Channel 13) : 0.0001 mW / -40.00 dBm
 Rcvr signal avg optical power (Channel 14) : 0.0001 mW / -40.00 dBm
 Rcvr signal avg optical power (Channel 15) : 0.0001 mW / -40.00 dBm
 Rcvr signal avg optical power (Channel 16) : 0.0001 mW / -40.00 dBm

 # ethtool --set-module swp11 power-mode-policy high

 # ethtool -m swp11
 Identifier                                : 0x18 (QSFP-DD Double Density 8X Pluggable Transceiver (INF-8628))
 ...
 Module State                              : 0x03 (ModuleReady)
 LowPwrAllowRequestHW                      : Off
 LowPwrRequestSW                           : Off
 ...
 Transmit avg optical power (Channel 1)    : 1.3690 mW / 1.36 dBm
 Transmit avg optical power (Channel 2)    : 1.3036 mW / 1.15 dBm
 Transmit avg optical power (Channel 3)    : 1.3358 mW / 1.26 dBm
 Transmit avg optical power (Channel 4)    : 1.3509 mW / 1.31 dBm
 Transmit avg optical power (Channel 5)    : 1.3193 mW / 1.20 dBm
 Transmit avg optical power (Channel 6)    : 1.3314 mW / 1.24 dBm
 Transmit avg optical power (Channel 7)    : 1.3042 mW / 1.15 dBm
 Transmit avg optical power (Channel 8)    : 1.3919 mW / 1.44 dBm
 Transmit avg optical power (Channel 9)    : 1.3690 mW / 1.36 dBm
 Transmit avg optical power (Channel 10)   : 1.3036 mW / 1.15 dBm
 Transmit avg optical power (Channel 11)   : 1.3358 mW / 1.26 dBm
 Transmit avg optical power (Channel 12)   : 1.3509 mW / 1.31 dBm
 Transmit avg optical power (Channel 13)   : 1.3193 mW / 1.20 dBm
 Transmit avg optical power (Channel 14)   : 1.3314 mW / 1.24 dBm
 Transmit avg optical power (Channel 15)   : 1.3042 mW / 1.15 dBm
 Transmit avg optical power (Channel 16)   : 1.3919 mW / 1.44 dBm
 Rcvr signal avg optical power (Channel 1) : 1.1299 mW / 0.53 dBm
 Rcvr signal avg optical power (Channel 2) : 1.1566 mW / 0.63 dBm
 Rcvr signal avg optical power (Channel 3) : 1.1484 mW / 0.60 dBm
 Rcvr signal avg optical power (Channel 4) : 1.1655 mW / 0.67 dBm
 Rcvr signal avg optical power (Channel 5) : 1.1751 mW / 0.70 dBm
 Rcvr signal avg optical power (Channel 6) : 1.1595 mW / 0.64 dBm
 Rcvr signal avg optical power (Channel 7) : 1.1158 mW / 0.48 dBm
 Rcvr signal avg optical power (Channel 8) : 1.1595 mW / 0.64 dBm
 Rcvr signal avg optical power (Channel 9) : 1.1299 mW / 0.53 dBm
 Rcvr signal avg optical power (Channel 10) : 1.1566 mW / 0.63 dBm
 Rcvr signal avg optical power (Channel 11) : 1.1484 mW / 0.60 dBm
 Rcvr signal avg optical power (Channel 12) : 1.1655 mW / 0.67 dBm
 Rcvr signal avg optical power (Channel 13) : 1.1751 mW / 0.70 dBm
 Rcvr signal avg optical power (Channel 14) : 1.1595 mW / 0.64 dBm
 Rcvr signal avg optical power (Channel 15) : 1.1158 mW / 0.48 dBm
 Rcvr signal avg optical power (Channel 16) : 1.1595 mW / 0.64 dBm

In the above example, the LowPwrRequestHW signal is ignored and low
power mode is controlled via software only.

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 cmis.c | 15 +++++++++++++++
 cmis.h |  5 +++++
 2 files changed, 20 insertions(+)

diff --git a/cmis.c b/cmis.c
index a32cc9f8b1f6..d0b62728e998 100644
--- a/cmis.c
+++ b/cmis.c
@@ -470,6 +470,20 @@ static void cmis_show_mod_fault_cause(const struct cmis_memory_map *map)
 	}
 }
 
+/* Print the current Module-Level Controls. Relevant documents:
+ * [1] CMIS Rev. 5, pag. 58, section 6.3.2.2, Table 6-12
+ * [2] CMIS Rev. 5, pag. 111, section 8.2.6, Table 8-10
+ */
+static void cmis_show_mod_lvl_controls(const struct cmis_memory_map *map)
+{
+	printf("\t%-41s : ", "LowPwrAllowRequestHW");
+	printf("%s\n", ONOFF(map->lower_memory[CMIS_MODULE_CONTROL_OFFSET] &
+			     CMIS_LOW_PWR_ALLOW_REQUEST_HW_MASK));
+	printf("\t%-41s : ", "LowPwrRequestSW");
+	printf("%s\n", ONOFF(map->lower_memory[CMIS_MODULE_CONTROL_OFFSET] &
+			     CMIS_LOW_PWR_REQUEST_SW_MASK));
+}
+
 static void cmis_parse_dom_power_type(const struct cmis_memory_map *map,
 				      struct sff_diags *sd)
 {
@@ -845,6 +859,7 @@ static void cmis_show_all_common(const struct cmis_memory_map *map)
 	cmis_show_rev_compliance(map);
 	cmis_show_mod_state(map);
 	cmis_show_mod_fault_cause(map);
+	cmis_show_mod_lvl_controls(map);
 	cmis_show_dom(map);
 }
 
diff --git a/cmis.h b/cmis.h
index 2c67ad5640ab..46797081f13c 100644
--- a/cmis.h
+++ b/cmis.h
@@ -36,6 +36,11 @@
 #define CMIS_CURR_TEMP_OFFSET			0x0E
 #define CMIS_CURR_VCC_OFFSET			0x10
 
+/* Module Global Controls (Page 0) */
+#define CMIS_MODULE_CONTROL_OFFSET		0x1A
+#define CMIS_LOW_PWR_ALLOW_REQUEST_HW_MASK	0x40
+#define CMIS_LOW_PWR_REQUEST_SW_MASK		0x10
+
 /* Module Fault Information (Page 0) */
 #define CMIS_MODULE_FAULT_OFFSET		0x29
 #define CMIS_MODULE_FAULT_NO_FAULT		0x00
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH ethtool-next 8/8] sff-8636: Print Power set and Power override bits
  2021-11-23 17:40 [PATCH ethtool-next 0/8] ethtool: Add support for CMIS diagnostic information Ido Schimmel
                   ` (6 preceding siblings ...)
  2021-11-23 17:41 ` [PATCH ethtool-next 7/8] cmis: Print Module-Level Controls Ido Schimmel
@ 2021-11-23 17:41 ` Ido Schimmel
  2021-12-02 21:45 ` [PATCH ethtool-next 0/8] ethtool: Add support for CMIS diagnostic information Michal Kubecek
  2021-12-02 22:00 ` patchwork-bot+netdevbpf
  9 siblings, 0 replies; 14+ messages in thread
From: Ido Schimmel @ 2021-11-23 17:41 UTC (permalink / raw)
  To: netdev; +Cc: mkubecek, popadrian1996, andrew, mlxsw, moshe, Ido Schimmel

From: Ido Schimmel <idosch@nvidia.com>

Print the SFF-8636 Power set and Power override bits when dumping EEPROM
contents via the '-m' option. They can be used to understand low power
mode enforcement by the host.

The 'SFF8636_LOW_PWR_MODE' define is renamed to 'SFF8636_LOW_PWR_SET' to
reflect its naming in the standard for QSFP+/QSFP28.

Example output:

 # ethtool -m swp13
 Identifier                                : 0x11 (QSFP28)
 ...
 Extended identifier description           : 5.0W max. Power consumption,  High Power Class (> 3.5 W) enabled
 Power set                                 : Off
 Power override                            : On
 ...
 Transmit avg optical power (Channel 1)    : 0.7633 mW / -1.17 dBm
 Transmit avg optical power (Channel 2)    : 0.7649 mW / -1.16 dBm
 Transmit avg optical power (Channel 3)    : 0.7696 mW / -1.14 dBm
 Transmit avg optical power (Channel 4)    : 0.7739 mW / -1.11 dBm
 Rcvr signal avg optical power(Channel 1)  : 0.9240 mW / -0.34 dBm
 Rcvr signal avg optical power(Channel 2)  : 0.9129 mW / -0.40 dBm
 Rcvr signal avg optical power(Channel 3)  : 0.9194 mW / -0.36 dBm
 Rcvr signal avg optical power(Channel 4)  : 0.8708 mW / -0.60 dBm

 # ethtool --set-module swp13 power-mode-policy auto

 # ethtool -m swp13
 Identifier                                : 0x11 (QSFP28)
 ...
 Extended identifier description           : 5.0W max. Power consumption,  High Power Class (> 3.5 W) not enabled
 Power set                                 : On
 Power override                            : On
 ...
 Transmit avg optical power (Channel 1)    : 0.0000 mW / -inf dBm
 Transmit avg optical power (Channel 2)    : 0.0000 mW / -inf dBm
 Transmit avg optical power (Channel 3)    : 0.0000 mW / -inf dBm
 Transmit avg optical power (Channel 4)    : 0.0000 mW / -inf dBm
 Rcvr signal avg optical power(Channel 1)  : 0.0000 mW / -inf dBm
 Rcvr signal avg optical power(Channel 2)  : 0.0000 mW / -inf dBm
 Rcvr signal avg optical power(Channel 3)  : 0.0000 mW / -inf dBm
 Rcvr signal avg optical power(Channel 4)  : 0.0000 mW / -inf dBm

 # ethtool --set-module swp13 power-mode-policy high

 # ethtool -m swp13
 Identifier                                : 0x11 (QSFP28)
 ...
 Extended identifier description           : 5.0W max. Power consumption,  High Power Class (> 3.5 W) enabled
 Power set                                 : Off
 Power override                            : On
 ...
 Transmit avg optical power (Channel 1)    : 0.7733 mW / -1.12 dBm
 Transmit avg optical power (Channel 2)    : 0.7754 mW / -1.10 dBm
 Transmit avg optical power (Channel 3)    : 0.7885 mW / -1.03 dBm
 Transmit avg optical power (Channel 4)    : 0.7886 mW / -1.03 dBm
 Rcvr signal avg optical power(Channel 1)  : 0.9248 mW / -0.34 dBm
 Rcvr signal avg optical power(Channel 2)  : 0.9129 mW / -0.40 dBm
 Rcvr signal avg optical power(Channel 3)  : 0.9187 mW / -0.37 dBm
 Rcvr signal avg optical power(Channel 4)  : 0.8785 mW / -0.56 dBm

In the above example, the LPMode signal is ignored (Power override is
always on) and low power mode is controlled via software only.

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 qsfp.c | 6 ++++++
 qsfp.h | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/qsfp.c b/qsfp.c
index b3c9e1516af9..57aac86bd5f6 100644
--- a/qsfp.c
+++ b/qsfp.c
@@ -268,6 +268,12 @@ static void sff8636_show_ext_identifier(const struct sff8636_memory_map *map)
 		printf(" High Power Class (> 3.5 W) enabled\n");
 	else
 		printf(" High Power Class (> 3.5 W) not enabled\n");
+	printf("\t%-41s : ", "Power set");
+	printf("%s\n", ONOFF(map->lower_memory[SFF8636_PWR_MODE_OFFSET] &
+			     SFF8636_LOW_PWR_SET));
+	printf("\t%-41s : ", "Power override");
+	printf("%s\n", ONOFF(map->lower_memory[SFF8636_PWR_MODE_OFFSET] &
+			     SFF8636_PWR_OVERRIDE));
 }
 
 static void sff8636_show_connector(const struct sff8636_memory_map *map)
diff --git a/qsfp.h b/qsfp.h
index 1d8f24b5cbc2..aabf09fdc623 100644
--- a/qsfp.h
+++ b/qsfp.h
@@ -180,7 +180,7 @@
 
 #define	SFF8636_PWR_MODE_OFFSET		0x5D
 #define	 SFF8636_HIGH_PWR_ENABLE		(1 << 2)
-#define	 SFF8636_LOW_PWR_MODE			(1 << 1)
+#define	 SFF8636_LOW_PWR_SET			(1 << 1)
 #define	 SFF8636_PWR_OVERRIDE			(1 << 0)
 
 #define	SFF8636_TX_APP_SELECT_4_OFFSET	0x5E
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH ethtool-next 0/8] ethtool: Add support for CMIS diagnostic information
  2021-11-23 17:40 [PATCH ethtool-next 0/8] ethtool: Add support for CMIS diagnostic information Ido Schimmel
                   ` (7 preceding siblings ...)
  2021-11-23 17:41 ` [PATCH ethtool-next 8/8] sff-8636: Print Power set and Power override bits Ido Schimmel
@ 2021-12-02 21:45 ` Michal Kubecek
  2021-12-02 21:52   ` Ido Schimmel
  2021-12-02 22:00 ` patchwork-bot+netdevbpf
  9 siblings, 1 reply; 14+ messages in thread
From: Michal Kubecek @ 2021-12-02 21:45 UTC (permalink / raw)
  To: Ido Schimmel; +Cc: netdev, popadrian1996, andrew, mlxsw, moshe, Ido Schimmel

[-- Attachment #1: Type: text/plain, Size: 2023 bytes --]

On Tue, Nov 23, 2021 at 07:40:54PM +0200, Ido Schimmel wrote:
> From: Ido Schimmel <idosch@nvidia.com>
> 
> This patchset extends ethtool(8) to retrieve, parse and print CMIS
> diagnostic information. This information includes module-level monitors
> (e.g., temperature, voltage), channel-level monitors (e.g., Tx optical
> power) and related thresholds and flags.
> 
> ethtool(8) already supports SFF-8636 (e.g., QSFP) and SFF-8472 (e.g.,
> SFP) diagnostic information, but until recently CMIS diagnostic
> information was unavailable to ethtool(8) as it resides in optional and
> banked pages.
> 
> Testing
> =======
> 
> Build tested each patch with the following configuration options:
> 
> netlink | pretty-dump
> --------|------------
> v       | v
> x       | x
> v       | x
> x       | v
> 
> Except fields that were added, no difference in output before and after
> the patchset. Tested with both PC and AOC QSFP-DD modules.
> 
> No reports from AddressSanitizer / valgrind.
> 
> Patchset overview
> =================
> 
> Patches #1-#2 are small preparations.
> 
> Patches #3-#4 retrieve (over netlink) and initialize the optional and
> banked pages in the CMIS memory map. These pages contain the previously
> mentioned diagnostic information.
> 
> Patch #5 parses and prints the CMIS diagnostic information in a similar
> fashion to the way it is done for SFF-8636.
> 
> Patches #6-#7 print a few additional fields from the CMIS EEPROM dump.
> The examples contain an ethtool command that is supported by the kernel,
> but not yet by ethtool(8). It will be sent as a follow-up patchset.
> 
> Patch #8 prints the equivalent module-level fields for SFF-8636.

The series looks good to me and I'm ready to merge it but as it is
marked "ethtool-next", I better make sure: is it OK to merge it into
master branch (targeting ethtool 5.16)? In other words, do I see
correctly that it does not depend on any features that would be missing
in 5.16 kernel?

Michal

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH ethtool-next 0/8] ethtool: Add support for CMIS diagnostic information
  2021-12-02 21:45 ` [PATCH ethtool-next 0/8] ethtool: Add support for CMIS diagnostic information Michal Kubecek
@ 2021-12-02 21:52   ` Ido Schimmel
  2021-12-02 22:01     ` Michal Kubecek
  0 siblings, 1 reply; 14+ messages in thread
From: Ido Schimmel @ 2021-12-02 21:52 UTC (permalink / raw)
  To: Michal Kubecek; +Cc: netdev, popadrian1996, andrew, mlxsw, moshe, Ido Schimmel

On Thu, Dec 02, 2021 at 10:45:18PM +0100, Michal Kubecek wrote:
> The series looks good to me and I'm ready to merge it but as it is
> marked "ethtool-next", I better make sure: is it OK to merge it into
> master branch (targeting ethtool 5.16)? In other words, do I see
> correctly that it does not depend on any features that would be missing
> in 5.16 kernel?

Yes

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH ethtool-next 2/8] sff-common: Move OFFSET_TO_U16_PTR() to common header file
  2021-11-23 17:40 ` [PATCH ethtool-next 2/8] sff-common: Move OFFSET_TO_U16_PTR() to common header file Ido Schimmel
@ 2021-12-02 21:55   ` Michal Kubecek
  0 siblings, 0 replies; 14+ messages in thread
From: Michal Kubecek @ 2021-12-02 21:55 UTC (permalink / raw)
  To: Ido Schimmel; +Cc: netdev, popadrian1996, andrew, mlxsw, moshe, Ido Schimmel

[-- Attachment #1: Type: text/plain, Size: 1954 bytes --]

On Tue, Nov 23, 2021 at 07:40:56PM +0200, Ido Schimmel wrote:
> From: Ido Schimmel <idosch@nvidia.com>
> 
> The define is also useful for CMIS, so move it from SFF-8636 to the
> common header file.
> 
> Signed-off-by: Ido Schimmel <idosch@nvidia.com>
> ---
>  qsfp.c       | 1 -
>  sff-common.h | 4 ++--
>  2 files changed, 2 insertions(+), 3 deletions(-)
> 
> diff --git a/qsfp.c b/qsfp.c
> index 58c4c4775e9b..b3c9e1516af9 100644
> --- a/qsfp.c
> +++ b/qsfp.c
> @@ -700,7 +700,6 @@ sff8636_show_wavelength_or_copper_compliance(const struct sff8636_memory_map *ma
>   * Second byte are 1/256th of degree, which are added to the dec part.
>   */
>  #define SFF8636_OFFSET_TO_TEMP(offset) ((__s16)OFFSET_TO_U16(offset))
> -#define OFFSET_TO_U16_PTR(ptr, offset) (ptr[offset] << 8 | ptr[(offset) + 1])
>  
>  static void sff8636_dom_parse(const struct sff8636_memory_map *map,
>  			      struct sff_diags *sd)
> diff --git a/sff-common.h b/sff-common.h
> index aab306e0b74f..9e323008ba19 100644
> --- a/sff-common.h
> +++ b/sff-common.h
> @@ -126,8 +126,8 @@
>  #define  SFF8024_ENCODING_PAM4			0x08
>  
>  /* Most common case: 16-bit unsigned integer in a certain unit */
> -#define OFFSET_TO_U16(offset) \
> -		(id[offset] << 8 | id[(offset) + 1])
> +#define OFFSET_TO_U16_PTR(ptr, offset) (ptr[offset] << 8 | ptr[(offset) + 1])
> +#define OFFSET_TO_U16(offset) OFFSET_TO_U16_PTR(id, offset)

I'm aware that you are just moving an old piece of code around so this
is rather meant as a tip for a future cleanup: OFFSET_TO_U16_PTR() does
not really need to be a macro so an inline function would be cleaner
(and type safe). OFFSET_TO_U16() is only used in 4 places, AFAICS, so
it is IMHO questionable if it is worth the worse readability.

Michal

>  
>  # define PRINT_xX_PWR(string, var)                             \
>  		printf("\t%-41s : %.4f mW / %.2f dBm\n", (string),         \
> -- 
> 2.31.1
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH ethtool-next 0/8] ethtool: Add support for CMIS diagnostic information
  2021-11-23 17:40 [PATCH ethtool-next 0/8] ethtool: Add support for CMIS diagnostic information Ido Schimmel
                   ` (8 preceding siblings ...)
  2021-12-02 21:45 ` [PATCH ethtool-next 0/8] ethtool: Add support for CMIS diagnostic information Michal Kubecek
@ 2021-12-02 22:00 ` patchwork-bot+netdevbpf
  9 siblings, 0 replies; 14+ messages in thread
From: patchwork-bot+netdevbpf @ 2021-12-02 22:00 UTC (permalink / raw)
  To: Ido Schimmel
  Cc: netdev, mkubecek, popadrian1996, andrew, mlxsw, moshe, idosch

Hello:

This series was applied to ethtool/ethtool.git (master)
by Michal Kubecek <mkubecek@suse.cz>:

On Tue, 23 Nov 2021 19:40:54 +0200 you wrote:
> From: Ido Schimmel <idosch@nvidia.com>
> 
> This patchset extends ethtool(8) to retrieve, parse and print CMIS
> diagnostic information. This information includes module-level monitors
> (e.g., temperature, voltage), channel-level monitors (e.g., Tx optical
> power) and related thresholds and flags.
> 
> [...]

Here is the summary with links:
  - [ethtool-next,1/8] sff-8636: Use an SFF-8636 specific define for maximum number of channels
    https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=73091cd94023
  - [ethtool-next,2/8] sff-common: Move OFFSET_TO_U16_PTR() to common header file
    https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=837c1662ebd6
  - [ethtool-next,3/8] cmis: Initialize Page 02h in memory map
    https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=8658852e0ef7
  - [ethtool-next,4/8] cmis: Initialize Banked Page 11h in memory map
    https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=27b42a92286b
  - [ethtool-next,5/8] cmis: Parse and print diagnostic information
    https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=340d88ee1289
  - [ethtool-next,6/8] cmis: Print Module State and Fault Cause
    https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=eae6a99f3d13
  - [ethtool-next,7/8] cmis: Print Module-Level Controls
    https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=82012f2dbfeb
  - [ethtool-next,8/8] sff-8636: Print Power set and Power override bits
    https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/commit/?id=d7b100713f73

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH ethtool-next 0/8] ethtool: Add support for CMIS diagnostic information
  2021-12-02 21:52   ` Ido Schimmel
@ 2021-12-02 22:01     ` Michal Kubecek
  0 siblings, 0 replies; 14+ messages in thread
From: Michal Kubecek @ 2021-12-02 22:01 UTC (permalink / raw)
  To: Ido Schimmel; +Cc: netdev, popadrian1996, andrew, mlxsw, moshe, Ido Schimmel

[-- Attachment #1: Type: text/plain, Size: 524 bytes --]

On Thu, Dec 02, 2021 at 11:52:59PM +0200, Ido Schimmel wrote:
> On Thu, Dec 02, 2021 at 10:45:18PM +0100, Michal Kubecek wrote:
> > The series looks good to me and I'm ready to merge it but as it is
> > marked "ethtool-next", I better make sure: is it OK to merge it into
> > master branch (targeting ethtool 5.16)? In other words, do I see
> > correctly that it does not depend on any features that would be missing
> > in 5.16 kernel?
> 
> Yes

Thank you. The series is merged into master branch now.

Michal

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2021-12-02 22:01 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-11-23 17:40 [PATCH ethtool-next 0/8] ethtool: Add support for CMIS diagnostic information Ido Schimmel
2021-11-23 17:40 ` [PATCH ethtool-next 1/8] sff-8636: Use an SFF-8636 specific define for maximum number of channels Ido Schimmel
2021-11-23 17:40 ` [PATCH ethtool-next 2/8] sff-common: Move OFFSET_TO_U16_PTR() to common header file Ido Schimmel
2021-12-02 21:55   ` Michal Kubecek
2021-11-23 17:40 ` [PATCH ethtool-next 3/8] cmis: Initialize Page 02h in memory map Ido Schimmel
2021-11-23 17:40 ` [PATCH ethtool-next 4/8] cmis: Initialize Banked Page 11h " Ido Schimmel
2021-11-23 17:40 ` [PATCH ethtool-next 5/8] cmis: Parse and print diagnostic information Ido Schimmel
2021-11-23 17:41 ` [PATCH ethtool-next 6/8] cmis: Print Module State and Fault Cause Ido Schimmel
2021-11-23 17:41 ` [PATCH ethtool-next 7/8] cmis: Print Module-Level Controls Ido Schimmel
2021-11-23 17:41 ` [PATCH ethtool-next 8/8] sff-8636: Print Power set and Power override bits Ido Schimmel
2021-12-02 21:45 ` [PATCH ethtool-next 0/8] ethtool: Add support for CMIS diagnostic information Michal Kubecek
2021-12-02 21:52   ` Ido Schimmel
2021-12-02 22:01     ` Michal Kubecek
2021-12-02 22:00 ` patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).