* [PATCH] app/testpmd: format dump information of module EEPROM @ 2022-02-15 10:18 Robin Zhang 2022-02-15 13:28 ` Ferruh Yigit ` (4 more replies) 0 siblings, 5 replies; 77+ messages in thread From: Robin Zhang @ 2022-02-15 10:18 UTC (permalink / raw) To: dev Cc: xiaoyun.li, aman.deep.singh, yuying.zhang, junfeng.guo, stevex.yang, Robin Zhang This patch add a format specific information of different module eeprom. The format support for SFP(Small Formfactor Pluggable)/SFP+ /QSFP+(Quad Small Formfactor Pluggable)/QSFP28 modules based on SFF(Small Form Factor) Committee specifications SFF-8079/SFF-8472/SFF-8024/SFF-8636. Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- app/test-pmd/cmdline.c | 74 +- app/test-pmd/config.c | 24 +- app/test-pmd/meson.build | 4 + app/test-pmd/sff_8079.c | 376 ++++++++++ app/test-pmd/sff_8472.c | 281 ++++++++ app/test-pmd/sff_8636.c | 742 ++++++++++++++++++++ app/test-pmd/sff_8636.h | 592 ++++++++++++++++ app/test-pmd/sff_common.c | 296 ++++++++ app/test-pmd/sff_common.h | 178 +++++ app/test-pmd/testpmd.h | 13 +- doc/guides/testpmd_app_ug/testpmd_funcs.rst | 11 +- 11 files changed, 2575 insertions(+), 16 deletions(-) create mode 100644 app/test-pmd/sff_8079.c create mode 100644 app/test-pmd/sff_8472.c create mode 100644 app/test-pmd/sff_8636.c create mode 100644 app/test-pmd/sff_8636.h create mode 100644 app/test-pmd/sff_common.c create mode 100644 app/test-pmd/sff_common.h diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index b4ba8da2b0..d4f0bb8d64 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -166,8 +166,12 @@ static void cmd_help_long_parsed(void *parsed_result, "show port info (port_id) representor\n" " Show supported representors for a specific port\n\n" - "show port port_id (module_eeprom|eeprom)\n" - " Display the module EEPROM or EEPROM information for port_id.\n\n" + "show port port_id eeprom\n" + " Display the EEPROM raw data for port_id.\n\n" + + "show port port_id module_eeprom (format|hex)\n" + " Display the module EEPROM information for port_id" + " with specific format or hex dump.\n\n" "show port X rss reta (size) (mask0,mask1,...)\n" " Display the rss redirection table entry indicated" @@ -8393,12 +8397,12 @@ cmdline_parse_inst_t cmd_showdevice = { }, }; -/* *** SHOW MODULE EEPROM/EEPROM port INFO *** */ +/* *** SHOW EEPROM port INFO *** */ struct cmd_showeeprom_result { cmdline_fixed_string_t show; cmdline_fixed_string_t port; uint16_t portnum; - cmdline_fixed_string_t type; + cmdline_fixed_string_t keyword; }; static void cmd_showeeprom_parsed(void *parsed_result, @@ -8407,10 +8411,8 @@ static void cmd_showeeprom_parsed(void *parsed_result, { struct cmd_showeeprom_result *res = parsed_result; - if (!strcmp(res->type, "eeprom")) + if (!strcmp(res->keyword, "eeprom")) port_eeprom_display(res->portnum); - else if (!strcmp(res->type, "module_eeprom")) - port_module_eeprom_display(res->portnum); else fprintf(stderr, "Unknown argument\n"); } @@ -8422,18 +8424,67 @@ cmdline_parse_token_string_t cmd_showeeprom_port = cmdline_parse_token_num_t cmd_showeeprom_portnum = TOKEN_NUM_INITIALIZER(struct cmd_showeeprom_result, portnum, RTE_UINT16); -cmdline_parse_token_string_t cmd_showeeprom_type = - TOKEN_STRING_INITIALIZER(struct cmd_showeeprom_result, type, "module_eeprom#eeprom"); +cmdline_parse_token_string_t cmd_showeeprom_keyword = + TOKEN_STRING_INITIALIZER(struct cmd_showeeprom_result, keyword, "eeprom"); cmdline_parse_inst_t cmd_showeeprom = { .f = cmd_showeeprom_parsed, .data = NULL, - .help_str = "show port <port_id> module_eeprom|eeprom", + .help_str = "show port <port_id> eeprom", .tokens = { (void *)&cmd_showeeprom_show, (void *)&cmd_showeeprom_port, (void *)&cmd_showeeprom_portnum, - (void *)&cmd_showeeprom_type, + (void *)&cmd_showeeprom_keyword, + NULL, + }, +}; + +/* *** SHOW MODULE EEPROM port INFO *** */ +struct cmd_show_module_eeprom_result { + cmdline_fixed_string_t show; + cmdline_fixed_string_t port; + uint16_t portnum; + cmdline_fixed_string_t keyword; + cmdline_fixed_string_t type; +}; + +static void cmd_show_module_eeprom_parsed(void *parsed_result, + __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + struct cmd_show_module_eeprom_result *res = parsed_result; + + if (!strcmp(res->type, "format")) + port_module_eeprom_display(res->portnum, 0); + else if (!strcmp(res->type, "hex")) + port_module_eeprom_display(res->portnum, 1); + else + fprintf(stderr, "Unknown argument\n"); +} + +cmdline_parse_token_string_t cmd_show_module_eeprom_show = + TOKEN_STRING_INITIALIZER(struct cmd_show_module_eeprom_result, show, "show"); +cmdline_parse_token_string_t cmd_show_module_eeprom_port = + TOKEN_STRING_INITIALIZER(struct cmd_show_module_eeprom_result, port, "port"); +cmdline_parse_token_num_t cmd_show_module_eeprom_portnum = + TOKEN_NUM_INITIALIZER(struct cmd_show_module_eeprom_result, portnum, + RTE_UINT16); +cmdline_parse_token_string_t cmd_show_module_eeprom_keyword = + TOKEN_STRING_INITIALIZER(struct cmd_show_module_eeprom_result, keyword, "module_eeprom"); +cmdline_parse_token_string_t cmd_show_module_eeprom_type = + TOKEN_STRING_INITIALIZER(struct cmd_show_module_eeprom_result, type, "format#hex"); + +cmdline_parse_inst_t cmd_show_module_eeprom = { + .f = cmd_show_module_eeprom_parsed, + .data = NULL, + .help_str = "show port <port_id> module_eeprom format|hex", + .tokens = { + (void *)&cmd_show_module_eeprom_show, + (void *)&cmd_show_module_eeprom_port, + (void *)&cmd_show_module_eeprom_portnum, + (void *)&cmd_show_module_eeprom_keyword, + (void *)&cmd_show_module_eeprom_type, NULL, }, }; @@ -17817,6 +17868,7 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_showport, (cmdline_parse_inst_t *)&cmd_showqueue, (cmdline_parse_inst_t *)&cmd_showeeprom, + (cmdline_parse_inst_t *)&cmd_show_module_eeprom, (cmdline_parse_inst_t *)&cmd_showportall, (cmdline_parse_inst_t *)&cmd_representor_info, (cmdline_parse_inst_t *)&cmd_showdevice, diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index de1ec14bc7..6775c05cb1 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -948,7 +948,7 @@ port_eeprom_display(portid_t port_id) } void -port_module_eeprom_display(portid_t port_id) +port_module_eeprom_display(portid_t port_id, uint8_t hex_on) { struct rte_eth_dev_module_info minfo; struct rte_dev_eeprom_info einfo; @@ -1011,7 +1011,27 @@ port_module_eeprom_display(portid_t port_id) return; } - rte_hexdump(stdout, "hexdump", einfo.data, einfo.length); + if (hex_on) + rte_hexdump(stdout, "hexdump", einfo.data, einfo.length); + else { + switch (minfo.type) { + case RTE_ETH_MODULE_SFF_8079: + sff_8079_show_all(einfo.data); + break; + case RTE_ETH_MODULE_SFF_8472: + sff_8079_show_all(einfo.data); + sff_8472_show_all(einfo.data); + break; + case RTE_ETH_MODULE_SFF_8436: + case RTE_ETH_MODULE_SFF_8636: + sff_8636_show_all(einfo.data, einfo.length); + break; + default: + printf("Unsupported plug in module, show hex dump.\n"); + rte_hexdump(stdout, "hexdump", einfo.data, einfo.length); + break; + } + } printf("Finish -- Port: %d MODULE EEPROM length: %d bytes\n", port_id, einfo.length); free(einfo.data); } diff --git a/app/test-pmd/meson.build b/app/test-pmd/meson.build index 43130c8856..733e5d70c5 100644 --- a/app/test-pmd/meson.build +++ b/app/test-pmd/meson.build @@ -22,6 +22,10 @@ sources = files( 'noisy_vnf.c', 'parameters.c', 'rxonly.c', + 'sff_8079.c', + 'sff_8472.c', + 'sff_8636.c', + 'sff_common.c', 'shared_rxq_fwd.c', 'testpmd.c', 'txonly.c', diff --git a/app/test-pmd/sff_8079.c b/app/test-pmd/sff_8079.c new file mode 100644 index 0000000000..0f8652543b --- /dev/null +++ b/app/test-pmd/sff_8079.c @@ -0,0 +1,376 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2022 Intel Corporation + * + * Implements SFF-8079 optics diagnostics. + * + */ + +#include <stdio.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "testpmd.h" +#include "sff_common.h" + +static void sff_8079_show_identifier(const uint8_t *id) +{ + sff_8024_show_identifier(id, 0); +} + +static void sff_8079_show_ext_identifier(const uint8_t *id) +{ + printf("%-41s : 0x%02x", "Extended identifier", id[1]); + if (id[1] == 0x00) + printf(" (GBIC not specified / not MOD_DEF compliant)\n"); + else if (id[1] == 0x04) + printf(" (GBIC/SFP defined by 2-wire interface ID)\n"); + else if (id[1] <= 0x07) + printf(" (GBIC compliant with MOD_DEF %u)\n", id[1]); + else + printf(" (unknown)\n"); +} + +static void sff_8079_show_connector(const uint8_t *id) +{ + sff_8024_show_connector(id, 2); +} + +static void sff_8079_show_transceiver(const uint8_t *id) +{ + static const char *pfx = + "Transceiver type :"; + + printf("%-41s : 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", + "Transceiver codes", + id[3], id[4], id[5], id[6], + id[7], id[8], id[9], id[10], id[36]); + /* 10G Ethernet Compliance Codes */ + if (id[3] & (1 << 7)) + printf("%s 10G Ethernet: 10G Base-ER [SFF-8472 rev10.4 onwards]\n", pfx); + if (id[3] & (1 << 6)) + printf("%s 10G Ethernet: 10G Base-LRM\n", pfx); + if (id[3] & (1 << 5)) + printf("%s 10G Ethernet: 10G Base-LR\n", pfx); + if (id[3] & (1 << 4)) + printf("%s 10G Ethernet: 10G Base-SR\n", pfx); + /* Infiniband Compliance Codes */ + if (id[3] & (1 << 3)) + printf("%s Infiniband: 1X SX\n", pfx); + if (id[3] & (1 << 2)) + printf("%s Infiniband: 1X LX\n", pfx); + if (id[3] & (1 << 1)) + printf("%s Infiniband: 1X Copper Active\n", pfx); + if (id[3] & (1 << 0)) + printf("%s Infiniband: 1X Copper Passive\n", pfx); + /* ESCON Compliance Codes */ + if (id[4] & (1 << 7)) + printf("%s ESCON: ESCON MMF, 1310nm LED\n", pfx); + if (id[4] & (1 << 6)) + printf("%s ESCON: ESCON SMF, 1310nm Laser\n", pfx); + /* SONET Compliance Codes */ + if (id[4] & (1 << 5)) + printf("%s SONET: OC-192, short reach\n", pfx); + if (id[4] & (1 << 4)) + printf("%s SONET: SONET reach specifier bit 1\n", pfx); + if (id[4] & (1 << 3)) + printf("%s SONET: SONET reach specifier bit 2\n", pfx); + if (id[4] & (1 << 2)) + printf("%s SONET: OC-48, long reach\n", pfx); + if (id[4] & (1 << 1)) + printf("%s SONET: OC-48, intermediate reach\n", pfx); + if (id[4] & (1 << 0)) + printf("%s SONET: OC-48, short reach\n", pfx); + if (id[5] & (1 << 6)) + printf("%s SONET: OC-12, single mode, long reach\n", pfx); + if (id[5] & (1 << 5)) + printf("%s SONET: OC-12, single mode, inter. reach\n", pfx); + if (id[5] & (1 << 4)) + printf("%s SONET: OC-12, short reach\n", pfx); + if (id[5] & (1 << 2)) + printf("%s SONET: OC-3, single mode, long reach\n", pfx); + if (id[5] & (1 << 1)) + printf("%s SONET: OC-3, single mode, inter. reach\n", pfx); + if (id[5] & (1 << 0)) + printf("%s SONET: OC-3, short reach\n", pfx); + /* Ethernet Compliance Codes */ + if (id[6] & (1 << 7)) + printf("%s Ethernet: BASE-PX\n", pfx); + if (id[6] & (1 << 6)) + printf("%s Ethernet: BASE-BX10\n", pfx); + if (id[6] & (1 << 5)) + printf("%s Ethernet: 100BASE-FX\n", pfx); + if (id[6] & (1 << 4)) + printf("%s Ethernet: 100BASE-LX/LX10\n", pfx); + if (id[6] & (1 << 3)) + printf("%s Ethernet: 1000BASE-T\n", pfx); + if (id[6] & (1 << 2)) + printf("%s Ethernet: 1000BASE-CX\n", pfx); + if (id[6] & (1 << 1)) + printf("%s Ethernet: 1000BASE-LX\n", pfx); + if (id[6] & (1 << 0)) + printf("%s Ethernet: 1000BASE-SX\n", pfx); + /* Fibre Channel link length */ + if (id[7] & (1 << 7)) + printf("%s FC: very long distance (V)\n", pfx); + if (id[7] & (1 << 6)) + printf("%s FC: short distance (S)\n", pfx); + if (id[7] & (1 << 5)) + printf("%s FC: intermediate distance (I)\n", pfx); + if (id[7] & (1 << 4)) + printf("%s FC: long distance (L)\n", pfx); + if (id[7] & (1 << 3)) + printf("%s FC: medium distance (M)\n", pfx); + /* Fibre Channel transmitter technology */ + if (id[7] & (1 << 2)) + printf("%s FC: Shortwave laser, linear Rx (SA)\n", pfx); + if (id[7] & (1 << 1)) + printf("%s FC: Longwave laser (LC)\n", pfx); + if (id[7] & (1 << 0)) + printf("%s FC: Electrical inter-enclosure (EL)\n", pfx); + if (id[8] & (1 << 7)) + printf("%s FC: Electrical intra-enclosure (EL)\n", pfx); + if (id[8] & (1 << 6)) + printf("%s FC: Shortwave laser w/o OFC (SN)\n", pfx); + if (id[8] & (1 << 5)) + printf("%s FC: Shortwave laser with OFC (SL)\n", pfx); + if (id[8] & (1 << 4)) + printf("%s FC: Longwave laser (LL)\n", pfx); + if (id[8] & (1 << 3)) + printf("%s Active Cable\n", pfx); + if (id[8] & (1 << 2)) + printf("%s Passive Cable\n", pfx); + if (id[8] & (1 << 1)) + printf("%s FC: Copper FC-BaseT\n", pfx); + /* Fibre Channel transmission media */ + if (id[9] & (1 << 7)) + printf("%s FC: Twin Axial Pair (TW)\n", pfx); + if (id[9] & (1 << 6)) + printf("%s FC: Twisted Pair (TP)\n", pfx); + if (id[9] & (1 << 5)) + printf("%s FC: Miniature Coax (MI)\n", pfx); + if (id[9] & (1 << 4)) + printf("%s FC: Video Coax (TV)\n", pfx); + if (id[9] & (1 << 3)) + printf("%s FC: Multimode, 62.5um (M6)\n", pfx); + if (id[9] & (1 << 2)) + printf("%s FC: Multimode, 50um (M5)\n", pfx); + if (id[9] & (1 << 0)) + printf("%s FC: Single Mode (SM)\n", pfx); + /* Fibre Channel speed */ + if (id[10] & (1 << 7)) + printf("%s FC: 1200 MBytes/sec\n", pfx); + if (id[10] & (1 << 6)) + printf("%s FC: 800 MBytes/sec\n", pfx); + if (id[10] & (1 << 4)) + printf("%s FC: 400 MBytes/sec\n", pfx); + if (id[10] & (1 << 2)) + printf("%s FC: 200 MBytes/sec\n", pfx); + if (id[10] & (1 << 0)) + printf("%s FC: 100 MBytes/sec\n", pfx); + /* Extended Specification Compliance Codes from SFF-8024 */ + if (id[36] == 0x1) + printf("%s Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)\n", + pfx); + if (id[36] == 0x2) + printf("%s Extended: 100G Base-SR4 or 25GBase-SR\n", pfx); + if (id[36] == 0x3) + printf("%s Extended: 100G Base-LR4 or 25GBase-LR\n", pfx); + if (id[36] == 0x4) + printf("%s Extended: 100G Base-ER4 or 25GBase-ER\n", pfx); + if (id[36] == 0x8) + printf("%s Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)\n", + pfx); + if (id[36] == 0xb) + printf("%s Extended: 100G Base-CR4 or 25G Base-CR CA-L\n", pfx); + if (id[36] == 0xc) + printf("%s Extended: 25G Base-CR CA-S\n", pfx); + if (id[36] == 0xd) + printf("%s Extended: 25G Base-CR CA-N\n", pfx); + if (id[36] == 0x16) + printf("%s Extended: 10Gbase-T with SFI electrical interface\n", pfx); + if (id[36] == 0x18) + printf("%s Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)\n", + pfx); + if (id[36] == 0x19) + printf("%s Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)\n", + pfx); + if (id[36] == 0x1c) + printf("%s Extended: 10Gbase-T Short Reach\n", pfx); +} + +static void sff_8079_show_encoding(const uint8_t *id) +{ + sff_8024_show_encoding(id, 11, RTE_ETH_MODULE_SFF_8472); +} + +static void sff_8079_show_rate_identifier(const uint8_t *id) +{ + printf("%-41s : 0x%02x", "Rate identifier", id[13]); + switch (id[13]) { + case 0x00: + printf(" (unspecified)\n"); + break; + case 0x01: + printf(" (4/2/1G Rate_Select & AS0/AS1)\n"); + break; + case 0x02: + printf(" (8/4/2G Rx Rate_Select only)\n"); + break; + case 0x03: + printf(" (8/4/2G Independent Rx & Tx Rate_Select)\n"); + break; + case 0x04: + printf(" (8/4/2G Tx Rate_Select only)\n"); + break; + default: + printf(" (reserved or unknown)\n"); + break; + } +} + +static void sff_8079_show_oui(const uint8_t *id) +{ + printf("%-41s : %02x:%02x:%02x\n", "Vendor OUI", + id[37], id[38], id[39]); +} + +static void sff_8079_show_wavelength_or_copper_compliance(const uint8_t *id) +{ + if (id[8] & (1 << 2)) { + printf("%-41s : 0x%02x", "Passive Cu cmplnce.", id[60]); + switch (id[60]) { + case 0x00: + printf(" (unspecified)"); + break; + case 0x01: + printf(" (SFF-8431 appendix E)"); + break; + default: + printf(" (unknown)"); + break; + } + printf(" [SFF-8472 rev10.4 only]\n"); + } else if (id[8] & (1 << 3)) { + printf("%-41s : 0x%02x", "Active Cu cmplnce.", id[60]); + switch (id[60]) { + case 0x00: + printf(" (unspecified)"); + break; + case 0x01: + printf(" (SFF-8431 appendix E)"); + break; + case 0x04: + printf(" (SFF-8431 limiting)"); + break; + default: + printf(" (unknown)"); + break; + } + printf(" [SFF-8472 rev10.4 only]\n"); + } else { + printf("%-41s : %unm\n", "Laser wavelength", + (id[60] << 8) | id[61]); + } +} + +static void sff_8079_show_value_with_unit(const uint8_t *id, unsigned int reg, + const char *name, unsigned int mult, + const char *unit) +{ + unsigned int val = id[reg]; + + printf("%-41s : %u%s\n", name, val * mult, unit); +} + +static void sff_8079_show_ascii(const uint8_t *id, unsigned int first_reg, + unsigned int last_reg, const char *name) +{ + unsigned int reg, val; + + printf("%-41s : ", name); + while (first_reg <= last_reg && id[last_reg] == ' ') + last_reg--; + for (reg = first_reg; reg <= last_reg; reg++) { + val = id[reg]; + putchar(((val >= 32) && (val <= 126)) ? val : '_'); + } + printf("\n"); +} + +static void sff_8079_show_options(const uint8_t *id) +{ + static const char *pfx = + "Option :"; + + printf("%-41s : 0x%02x 0x%02x\n", "Option values", id[64], id[65]); + if (id[65] & (1 << 1)) + printf("%s RX_LOS implemented\n", pfx); + if (id[65] & (1 << 2)) + printf("%s RX_LOS implemented, inverted\n", pfx); + if (id[65] & (1 << 3)) + printf("%s TX_FAULT implemented\n", pfx); + if (id[65] & (1 << 4)) + printf("%s TX_DISABLE implemented\n", pfx); + if (id[65] & (1 << 5)) + printf("%s RATE_SELECT implemented\n", pfx); + if (id[65] & (1 << 6)) + printf("%s Tunable transmitter technology\n", pfx); + if (id[65] & (1 << 7)) + printf("%s Receiver decision threshold implemented\n", pfx); + if (id[64] & (1 << 0)) + printf("%s Linear receiver output implemented\n", pfx); + if (id[64] & (1 << 1)) + printf("%s Power level 2 requirement\n", pfx); + if (id[64] & (1 << 2)) + printf("%s Cooled transceiver implemented\n", pfx); + if (id[64] & (1 << 3)) + printf("%s Retimer or CDR implemented\n", pfx); + if (id[64] & (1 << 4)) + printf("%s Paging implemented\n", pfx); + if (id[64] & (1 << 5)) + printf("%s Power level 3 requirement\n", pfx); +} + +void sff_8079_show_all(const uint8_t *id) +{ + sff_8079_show_identifier(id); + if (((id[0] == 0x02) || (id[0] == 0x03)) && (id[1] == 0x04)) { + unsigned int br_nom, br_min, br_max; + + if (id[12] == 0) { + br_nom = br_min = br_max = 0; + } else if (id[12] == 255) { + br_nom = id[66] * 250; + br_max = id[67]; + br_min = id[67]; + } else { + br_nom = id[12] * 100; + br_max = id[66]; + br_min = id[67]; + } + sff_8079_show_ext_identifier(id); + sff_8079_show_connector(id); + sff_8079_show_transceiver(id); + sff_8079_show_encoding(id); + printf("%-41s : %u%s\n", "BR, Nominal", br_nom, "MBd"); + sff_8079_show_rate_identifier(id); + sff_8079_show_value_with_unit(id, 14, + "Length (SMF,km)", 1, "km"); + sff_8079_show_value_with_unit(id, 15, "Length (SMF)", 100, "m"); + sff_8079_show_value_with_unit(id, 16, "Length (50um)", 10, "m"); + sff_8079_show_value_with_unit(id, 17, + "Length (62.5um)", 10, "m"); + sff_8079_show_value_with_unit(id, 18, "Length (Copper)", 1, "m"); + sff_8079_show_value_with_unit(id, 19, "Length (OM3)", 10, "m"); + sff_8079_show_wavelength_or_copper_compliance(id); + sff_8079_show_ascii(id, 20, 35, "Vendor name"); + sff_8079_show_oui(id); + sff_8079_show_ascii(id, 40, 55, "Vendor PN"); + sff_8079_show_ascii(id, 56, 59, "Vendor rev"); + sff_8079_show_options(id); + printf("%-41s : %u%s\n", "BR margin, max", br_max, "%"); + printf("%-41s : %u%s\n", "BR margin, min", br_min, "%"); + sff_8079_show_ascii(id, 68, 83, "Vendor SN"); + sff_8079_show_ascii(id, 84, 91, "Date code"); + } +} diff --git a/app/test-pmd/sff_8472.c b/app/test-pmd/sff_8472.c new file mode 100644 index 0000000000..a419d1df78 --- /dev/null +++ b/app/test-pmd/sff_8472.c @@ -0,0 +1,281 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2022 Intel Corporation + * + * Implements SFF-8472 optics diagnostics. + * + */ + +#include <stdio.h> +#include <math.h> +#include <arpa/inet.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "testpmd.h" +#include "sff_common.h" + +/* Offsets in decimal, for direct comparison with the SFF specs */ + +/* A0-based EEPROM offsets for DOM support checks */ +#define SFF_A0_DOM 92 +#define SFF_A0_OPTIONS 93 +#define SFF_A0_COMP 94 + +/* EEPROM bit values for various registers */ +#define SFF_A0_DOM_EXTCAL (1 << 4) +#define SFF_A0_DOM_INTCAL (1 << 5) +#define SFF_A0_DOM_IMPL (1 << 6) +#define SFF_A0_DOM_PWRT (1 << 3) + +#define SFF_A0_OPTIONS_AW (1 << 7) + +/* + * See ethtool.c comments about SFF-8472, this is the offset + * at which the A2 page is in the EEPROM blob returned by the + * kernel. + */ +#define SFF_A2_BASE 0x100 + +/* A2-based offsets for DOM */ +#define SFF_A2_TEMP 96 +#define SFF_A2_TEMP_HALRM 0 +#define SFF_A2_TEMP_LALRM 2 +#define SFF_A2_TEMP_HWARN 4 +#define SFF_A2_TEMP_LWARN 6 + +#define SFF_A2_VCC 98 +#define SFF_A2_VCC_HALRM 8 +#define SFF_A2_VCC_LALRM 10 +#define SFF_A2_VCC_HWARN 12 +#define SFF_A2_VCC_LWARN 14 + +#define SFF_A2_BIAS 100 +#define SFF_A2_BIAS_HALRM 16 +#define SFF_A2_BIAS_LALRM 18 +#define SFF_A2_BIAS_HWARN 20 +#define SFF_A2_BIAS_LWARN 22 + +#define SFF_A2_TX_PWR 102 +#define SFF_A2_TX_PWR_HALRM 24 +#define SFF_A2_TX_PWR_LALRM 26 +#define SFF_A2_TX_PWR_HWARN 28 +#define SFF_A2_TX_PWR_LWARN 30 + +#define SFF_A2_RX_PWR 104 +#define SFF_A2_RX_PWR_HALRM 32 +#define SFF_A2_RX_PWR_LALRM 34 +#define SFF_A2_RX_PWR_HWARN 36 +#define SFF_A2_RX_PWR_LWARN 38 + +#define SFF_A2_ALRM_FLG 112 +#define SFF_A2_WARN_FLG 116 + +/* 32-bit little-endian calibration constants */ +#define SFF_A2_CAL_RXPWR4 56 +#define SFF_A2_CAL_RXPWR3 60 +#define SFF_A2_CAL_RXPWR2 64 +#define SFF_A2_CAL_RXPWR1 68 +#define SFF_A2_CAL_RXPWR0 72 + +/* 16-bit little endian calibration constants */ +#define SFF_A2_CAL_TXI_SLP 76 +#define SFF_A2_CAL_TXI_OFF 78 +#define SFF_A2_CAL_TXPWR_SLP 80 +#define SFF_A2_CAL_TXPWR_OFF 82 +#define SFF_A2_CAL_T_SLP 84 +#define SFF_A2_CAL_T_OFF 86 +#define SFF_A2_CAL_V_SLP 88 +#define SFF_A2_CAL_V_OFF 90 + +static struct sff_8472_aw_flags { + const char *str; /* Human-readable string, null at the end */ + int offset; /* A2-relative address offset */ + uint8_t value; /* Alarm is on if (offset & value) != 0. */ +} sff_8472_aw_flags[] = { + { "Laser bias current high alarm", SFF_A2_ALRM_FLG, (1 << 3) }, + { "Laser bias current low alarm", SFF_A2_ALRM_FLG, (1 << 2) }, + { "Laser bias current high warning", SFF_A2_WARN_FLG, (1 << 3) }, + { "Laser bias current low warning", SFF_A2_WARN_FLG, (1 << 2) }, + + { "Laser output power high alarm", SFF_A2_ALRM_FLG, (1 << 1) }, + { "Laser output power low alarm", SFF_A2_ALRM_FLG, (1 << 0) }, + { "Laser output power high warning", SFF_A2_WARN_FLG, (1 << 1) }, + { "Laser output power low warning", SFF_A2_WARN_FLG, (1 << 0) }, + + { "Module temperature high alarm", SFF_A2_ALRM_FLG, (1 << 7) }, + { "Module temperature low alarm", SFF_A2_ALRM_FLG, (1 << 6) }, + { "Module temperature high warning", SFF_A2_WARN_FLG, (1 << 7) }, + { "Module temperature low warning", SFF_A2_WARN_FLG, (1 << 6) }, + + { "Module voltage high alarm", SFF_A2_ALRM_FLG, (1 << 5) }, + { "Module voltage low alarm", SFF_A2_ALRM_FLG, (1 << 4) }, + { "Module voltage high warning", SFF_A2_WARN_FLG, (1 << 5) }, + { "Module voltage low warning", SFF_A2_WARN_FLG, (1 << 4) }, + + { "Laser rx power high alarm", SFF_A2_ALRM_FLG + 1, (1 << 7) }, + { "Laser rx power low alarm", SFF_A2_ALRM_FLG + 1, (1 << 6) }, + { "Laser rx power high warning", SFF_A2_WARN_FLG + 1, (1 << 7) }, + { "Laser rx power low warning", SFF_A2_WARN_FLG + 1, (1 << 6) }, + + { NULL, 0, 0 }, +}; + +/* Most common case: 16-bit unsigned integer in a certain unit */ +#define A2_OFFSET_TO_U16(offset) \ + (id[SFF_A2_BASE + (offset)] << 8 | id[SFF_A2_BASE + (offset) + 1]) + +/* Calibration slope is a number between 0.0 included and 256.0 excluded. */ +#define A2_OFFSET_TO_SLP(offset) \ + (id[SFF_A2_BASE + (offset)] + id[SFF_A2_BASE + (offset) + 1] / 256.) + +/* Calibration offset is an integer from -32768 to 32767 */ +#define A2_OFFSET_TO_OFF(offset) \ + ((int16_t)A2_OFFSET_TO_U16(offset)) + +/* RXPWR(x) are IEEE-754 floating point numbers in big-endian format */ +#define A2_OFFSET_TO_RXPWRx(offset) \ + (befloattoh((const uint32_t *)(id + SFF_A2_BASE + (offset)))) + +/* + * 2-byte internal temperature conversions: + * First byte is a signed 8-bit integer, which is the temp decimal part + * Second byte are 1/256th of degree, which are added to the dec part. + */ +#define A2_OFFSET_TO_TEMP(offset) ((int16_t)A2_OFFSET_TO_U16(offset)) + +static void sff_8472_dom_parse(const uint8_t *id, struct sff_diags *sd) +{ + sd->bias_cur[MCURR] = A2_OFFSET_TO_U16(SFF_A2_BIAS); + sd->bias_cur[HALRM] = A2_OFFSET_TO_U16(SFF_A2_BIAS_HALRM); + sd->bias_cur[LALRM] = A2_OFFSET_TO_U16(SFF_A2_BIAS_LALRM); + sd->bias_cur[HWARN] = A2_OFFSET_TO_U16(SFF_A2_BIAS_HWARN); + sd->bias_cur[LWARN] = A2_OFFSET_TO_U16(SFF_A2_BIAS_LWARN); + + sd->sfp_voltage[MCURR] = A2_OFFSET_TO_U16(SFF_A2_VCC); + sd->sfp_voltage[HALRM] = A2_OFFSET_TO_U16(SFF_A2_VCC_HALRM); + sd->sfp_voltage[LALRM] = A2_OFFSET_TO_U16(SFF_A2_VCC_LALRM); + sd->sfp_voltage[HWARN] = A2_OFFSET_TO_U16(SFF_A2_VCC_HWARN); + sd->sfp_voltage[LWARN] = A2_OFFSET_TO_U16(SFF_A2_VCC_LWARN); + + sd->tx_power[MCURR] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR); + sd->tx_power[HALRM] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_HALRM); + sd->tx_power[LALRM] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_LALRM); + sd->tx_power[HWARN] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_HWARN); + sd->tx_power[LWARN] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_LWARN); + + sd->rx_power[MCURR] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR); + sd->rx_power[HALRM] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_HALRM); + sd->rx_power[LALRM] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_LALRM); + sd->rx_power[HWARN] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_HWARN); + sd->rx_power[LWARN] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_LWARN); + + sd->sfp_temp[MCURR] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP); + sd->sfp_temp[HALRM] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_HALRM); + sd->sfp_temp[LALRM] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_LALRM); + sd->sfp_temp[HWARN] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_HWARN); + sd->sfp_temp[LWARN] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_LWARN); +} + +/* Converts to a float from a big-endian 4-byte source buffer. */ +static float befloattoh(const uint32_t *source) +{ + union { + uint32_t src; + float dst; + } converter; + + converter.src = ntohl(*source); + return converter.dst; +} + +static void sff_8472_calibration(const uint8_t *id, struct sff_diags *sd) +{ + unsigned long i; + uint16_t rx_reading; + + /* Calibration should occur for all values (threshold and current) */ + for (i = 0; i < ARRAY_SIZE(sd->bias_cur); ++i) { + /* + * Apply calibration formula 1 (Temp., Voltage, Bias, Tx Power) + */ + sd->bias_cur[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_TXI_SLP); + sd->tx_power[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_TXPWR_SLP); + sd->sfp_voltage[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_V_SLP); + sd->sfp_temp[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_T_SLP); + + sd->bias_cur[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_TXI_OFF); + sd->tx_power[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_TXPWR_OFF); + sd->sfp_voltage[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_V_OFF); + sd->sfp_temp[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_T_OFF); + + /* + * Apply calibration formula 2 (Rx Power only) + */ + rx_reading = sd->rx_power[i]; + sd->rx_power[i] = A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR0); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR1); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR2); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR3); + } +} + +static void sff_8472_parse_eeprom(const uint8_t *id, struct sff_diags *sd) +{ + sd->supports_dom = id[SFF_A0_DOM] & SFF_A0_DOM_IMPL; + sd->supports_alarms = id[SFF_A0_OPTIONS] & SFF_A0_OPTIONS_AW; + sd->calibrated_ext = id[SFF_A0_DOM] & SFF_A0_DOM_EXTCAL; + sd->rx_power_type = id[SFF_A0_DOM] & SFF_A0_DOM_PWRT; + + sff_8472_dom_parse(id, sd); + + /* + * If the SFP is externally calibrated, we need to read calibration data + * and compensate the already stored readings. + */ + if (sd->calibrated_ext) + sff_8472_calibration(id, sd); +} + +void sff_8472_show_all(const uint8_t *id) +{ + struct sff_diags sd = {0}; + const char *rx_power_string = NULL; + int i; + + sff_8472_parse_eeprom(id, &sd); + + if (!sd.supports_dom) { + printf("%-41s : No\n", "Optical diagnostics support"); + return; + } + printf("%-41s : Yes\n", "Optical diagnostics support"); + + PRINT_BIAS("Laser bias current", sd.bias_cur[MCURR]); + PRINT_xX_PWR("Laser output power", sd.tx_power[MCURR]); + + if (!sd.rx_power_type) + rx_power_string = "Receiver signal OMA"; + else + rx_power_string = "Receiver signal average optical power"; + + PRINT_xX_PWR(rx_power_string, sd.rx_power[MCURR]); + + PRINT_TEMP("Module temperature", sd.sfp_temp[MCURR]); + PRINT_VCC("Module voltage", sd.sfp_voltage[MCURR]); + + printf("%-41s : %s\n", "Alarm/warning flags implemented", + (sd.supports_alarms ? "Yes" : "No")); + if (sd.supports_alarms) { + + for (i = 0; sff_8472_aw_flags[i].str; ++i) { + printf("%-41s : %s\n", sff_8472_aw_flags[i].str, + id[SFF_A2_BASE + sff_8472_aw_flags[i].offset] + & sff_8472_aw_flags[i].value ? "On" : "Off"); + } + sff_show_thresholds(sd); + } +} + diff --git a/app/test-pmd/sff_8636.c b/app/test-pmd/sff_8636.c new file mode 100644 index 0000000000..cb57fe576c --- /dev/null +++ b/app/test-pmd/sff_8636.c @@ -0,0 +1,742 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2022 Intel Corporation + * + * Implements SFF-8636 based QSFP+/QSFP28 Diagnostics Memory map. + * + */ + +#include <stdio.h> +#include <math.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "testpmd.h" +#include "sff_common.h" +#include "sff_8636.h" + +#define MAX_DESC_SIZE 42 + +static struct sff_8636_aw_flags { + const char *str; /* Human-readable string, null at the end */ + int offset; /* A2-relative address offset */ + uint8_t value; /* Alarm is on if (offset & value) != 0. */ +} sff_8636_aw_flags[] = { + { "Laser bias current high alarm (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_HALARM) }, + { "Laser bias current low alarm (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_LALARM) }, + { "Laser bias current high warning (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_HWARN) }, + { "Laser bias current low warning (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_LWARN) }, + + { "Laser bias current high alarm (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_HALARM) }, + { "Laser bias current low alarm (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_LALARM) }, + { "Laser bias current high warning (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_HWARN) }, + { "Laser bias current low warning (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_LWARN) }, + + { "Laser bias current high alarm (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_HALARM) }, + { "Laser bias current low alarm (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_LALARM) }, + { "Laser bias current high warning (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_HWARN) }, + { "Laser bias current low warning (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_LWARN) }, + + { "Laser bias current high alarm (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_HALARM) }, + { "Laser bias current low alarm (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_LALARM) }, + { "Laser bias current high warning (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_HWARN) }, + { "Laser bias current low warning (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_LWARN) }, + + { "Module temperature high alarm", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_HALARM_STATUS) }, + { "Module temperature low alarm", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_LALARM_STATUS) }, + { "Module temperature high warning", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_HWARN_STATUS) }, + { "Module temperature low warning", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_LWARN_STATUS) }, + + { "Module voltage high alarm", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_HALARM_STATUS) }, + { "Module voltage low alarm", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_LALARM_STATUS) }, + { "Module voltage high warning", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_HWARN_STATUS) }, + { "Module voltage low warning", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_LWARN_STATUS) }, + + { "Laser tx power high alarm (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_HALARM) }, + { "Laser tx power low alarm (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_LALARM) }, + { "Laser tx power high warning (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_HWARN) }, + { "Laser tx power low warning (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_LWARN) }, + + { "Laser tx power high alarm (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_HALARM) }, + { "Laser tx power low alarm (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_LALARM) }, + { "Laser tx power high warning (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_HWARN) }, + { "Laser tx power low warning (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_LWARN) }, + + { "Laser tx power high alarm (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_HALARM) }, + { "Laser tx power low alarm (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_LALARM) }, + { "Laser tx power high warning (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_HWARN) }, + { "Laser tx power low warning (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_LWARN) }, + + { "Laser tx power high alarm (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_HALARM) }, + { "Laser tx power low alarm (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_LALARM) }, + { "Laser tx power high warning (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_HWARN) }, + { "Laser tx power low warning (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_LWARN) }, + + { "Laser rx power high alarm (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_HALARM) }, + { "Laser rx power low alarm (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_LALARM) }, + { "Laser rx power high warning (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_HWARN) }, + { "Laser rx power low warning (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_LWARN) }, + + { "Laser rx power high alarm (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_HALARM) }, + { "Laser rx power low alarm (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_LALARM) }, + { "Laser rx power high warning (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_HWARN) }, + { "Laser rx power low warning (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_LWARN) }, + + { "Laser rx power high alarm (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_HALARM) }, + { "Laser rx power low alarm (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_LALARM) }, + { "Laser rx power high warning (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_HWARN) }, + { "Laser rx power low warning (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_LWARN) }, + + { "Laser rx power high alarm (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_HALARM) }, + { "Laser rx power low alarm (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_LALARM) }, + { "Laser rx power high warning (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_HWARN) }, + { "Laser rx power low warning (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_LWARN) }, + + { NULL, 0, 0 }, +}; + +static void sff_8636_show_identifier(const uint8_t *id) +{ + sff_8024_show_identifier(id, SFF_8636_ID_OFFSET); +} + +static void sff_8636_show_ext_identifier(const uint8_t *id) +{ + printf("%-41s : 0x%02x\n", "Extended identifier", + id[SFF_8636_EXT_ID_OFFSET]); + + static const char *pfx = + "Extended identifier description :"; + + switch (id[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_PWR_CLASS_MASK) { + case SFF_8636_EXT_ID_PWR_CLASS_1: + printf("%s 1.5W max. Power consumption\n", pfx); + break; + case SFF_8636_EXT_ID_PWR_CLASS_2: + printf("%s 2.0W max. Power consumption\n", pfx); + break; + case SFF_8636_EXT_ID_PWR_CLASS_3: + printf("%s 2.5W max. Power consumption\n", pfx); + break; + case SFF_8636_EXT_ID_PWR_CLASS_4: + printf("%s 3.5W max. Power consumption\n", pfx); + break; + } + + if (id[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_CDR_TX_MASK) + printf("%s CDR present in TX,", pfx); + else + printf("%s No CDR in TX,", pfx); + + if (id[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_CDR_RX_MASK) + printf(" CDR present in RX\n"); + else + printf(" No CDR in RX\n"); + + switch (id[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_EPWR_CLASS_MASK) { + case SFF_8636_EXT_ID_PWR_CLASS_LEGACY: + printf("%s", pfx); + break; + case SFF_8636_EXT_ID_PWR_CLASS_5: + printf("%s 4.0W max. Power consumption,", pfx); + break; + case SFF_8636_EXT_ID_PWR_CLASS_6: + printf("%s 4.5W max. Power consumption, ", pfx); + break; + case SFF_8636_EXT_ID_PWR_CLASS_7: + printf("%s 5.0W max. Power consumption, ", pfx); + break; + } + if (id[SFF_8636_PWR_MODE_OFFSET] & SFF_8636_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 sff_8636_show_connector(const uint8_t *id) +{ + sff_8024_show_connector(id, SFF_8636_CTOR_OFFSET); +} + +static void sff_8636_show_transceiver(const uint8_t *id) +{ + static const char *pfx = + "Transceiver type :"; + + printf("%-41s : 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", + "Transceiver codes", + id[SFF_8636_ETHERNET_COMP_OFFSET], + id[SFF_8636_SONET_COMP_OFFSET], + id[SFF_8636_SAS_COMP_OFFSET], + id[SFF_8636_GIGE_COMP_OFFSET], + id[SFF_8636_FC_LEN_OFFSET], + id[SFF_8636_FC_TECH_OFFSET], + id[SFF_8636_FC_TRANS_MEDIA_OFFSET], + id[SFF_8636_FC_SPEED_OFFSET]); + + /* 10G/40G Ethernet Compliance Codes */ + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_LRM) + printf("%s 10G Ethernet: 10G Base-LRM\n", pfx); + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_LR) + printf("%s 10G Ethernet: 10G Base-LR\n", pfx); + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_SR) + printf("%s 10G Ethernet: 10G Base-SR\n", pfx); + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_CR4) + printf("%s 40G Ethernet: 40G Base-CR4\n", pfx); + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_SR4) + printf("%s 40G Ethernet: 40G Base-SR4\n", pfx); + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_LR4) + printf("%s 40G Ethernet: 40G Base-LR4\n", pfx); + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_ACTIVE) + printf("%s 40G Ethernet: 40G Active Cable (XLPPI)\n", pfx); + /* Extended Specification Compliance Codes from SFF-8024 */ + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_RSRVD) { + switch (id[SFF_8636_OPTION_1_OFFSET]) { + case SFF_8636_ETHERNET_UNSPECIFIED: + printf("%s (reserved or unknown)\n", pfx); + break; + case SFF_8636_ETHERNET_100G_AOC: + printf("%s 100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)\n", + pfx); + break; + case SFF_8636_ETHERNET_100G_SR4: + printf("%s 100G Ethernet: 100G Base-SR4 or 25GBase-SR\n", + pfx); + break; + case SFF_8636_ETHERNET_100G_LR4: + printf("%s 100G Ethernet: 100G Base-LR4\n", pfx); + break; + case SFF_8636_ETHERNET_100G_ER4: + printf("%s 100G Ethernet: 100G Base-ER4\n", pfx); + break; + case SFF_8636_ETHERNET_100G_SR10: + printf("%s 100G Ethernet: 100G Base-SR10\n", pfx); + break; + case SFF_8636_ETHERNET_100G_CWDM4_FEC: + printf("%s 100G Ethernet: 100G CWDM4 MSA with FEC\n", pfx); + break; + case SFF_8636_ETHERNET_100G_PSM4: + printf("%s 100G Ethernet: 100G PSM4 Parallel SMF\n", pfx); + break; + case SFF_8636_ETHERNET_100G_ACC: + printf("%s 100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)\n", + pfx); + break; + case SFF_8636_ETHERNET_100G_CWDM4_NO_FEC: + printf("%s 100G Ethernet: 100G CWDM4 MSA without FEC\n", pfx); + break; + case SFF_8636_ETHERNET_100G_RSVD1: + printf("%s (reserved or unknown)\n", pfx); + break; + case SFF_8636_ETHERNET_100G_CR4: + printf("%s 100G Ethernet: 100G Base-CR4 or 25G Base-CR CA-L\n", + pfx); + break; + case SFF_8636_ETHERNET_25G_CR_CA_S: + printf("%s 25G Ethernet: 25G Base-CR CA-S\n", pfx); + break; + case SFF_8636_ETHERNET_25G_CR_CA_N: + printf("%s 25G Ethernet: 25G Base-CR CA-N\n", pfx); + break; + case SFF_8636_ETHERNET_40G_ER4: + printf("%s 40G Ethernet: 40G Base-ER4\n", pfx); + break; + case SFF_8636_ETHERNET_4X10_SR: + printf("%s 4x10G Ethernet: 10G Base-SR\n", pfx); + break; + case SFF_8636_ETHERNET_40G_PSM4: + printf("%s 40G Ethernet: 40G PSM4 Parallel SMF\n", pfx); + break; + case SFF_8636_ETHERNET_G959_P1I1_2D1: + printf("%s Ethernet: G959.1 profile P1I1-2D1 (10709 MBd, 2km, 1310nm SM)\n", + pfx); + break; + case SFF_8636_ETHERNET_G959_P1S1_2D2: + printf("%s Ethernet: G959.1 profile P1S1-2D2 (10709 MBd, 40km, 1550nm SM)\n", + pfx); + break; + case SFF_8636_ETHERNET_G959_P1L1_2D2: + printf("%s Ethernet: G959.1 profile P1L1-2D2 (10709 MBd, 80km, 1550nm SM)\n", + pfx); + break; + case SFF_8636_ETHERNET_10GT_SFI: + printf("%s 10G Ethernet: 10G Base-T with SFI electrical interface\n", + pfx); + break; + case SFF_8636_ETHERNET_100G_CLR4: + printf("%s 100G Ethernet: 100G CLR4\n", pfx); + break; + case SFF_8636_ETHERNET_100G_AOC2: + printf("%s 100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)\n", + pfx); + break; + case SFF_8636_ETHERNET_100G_ACC2: + printf("%s 100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)\n", + pfx); + break; + default: + printf("%s (reserved or unknown)\n", pfx); + break; + } + } + + /* SONET Compliance Codes */ + if (id[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_40G_OTN) + printf("%s 40G OTN (OTU3B/OTU3C)\n", pfx); + if (id[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_LR) + printf("%s SONET: OC-48, long reach\n", pfx); + if (id[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_IR) + printf("%s SONET: OC-48, intermediate reach\n", pfx); + if (id[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_SR) + printf("%s SONET: OC-48, short reach\n", pfx); + + /* SAS/SATA Compliance Codes */ + if (id[SFF_8636_SAS_COMP_OFFSET] & SFF_8636_SAS_6G) + printf("%s SAS 6.0G\n", pfx); + if (id[SFF_8636_SAS_COMP_OFFSET] & SFF_8636_SAS_3G) + printf("%s SAS 3.0G\n", pfx); + + /* Ethernet Compliance Codes */ + if (id[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_T) + printf("%s Ethernet: 1000BASE-T\n", pfx); + if (id[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_CX) + printf("%s Ethernet: 1000BASE-CX\n", pfx); + if (id[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_LX) + printf("%s Ethernet: 1000BASE-LX\n", pfx); + if (id[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_SX) + printf("%s Ethernet: 1000BASE-SX\n", pfx); + + /* Fibre Channel link length */ + if (id[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_VERY_LONG) + printf("%s FC: very long distance (V)\n", pfx); + if (id[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_SHORT) + printf("%s FC: short distance (S)\n", pfx); + if (id[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_INT) + printf("%s FC: intermediate distance (I)\n", pfx); + if (id[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_LONG) + printf("%s FC: long distance (L)\n", pfx); + if (id[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_MED) + printf("%s FC: medium distance (M)\n", pfx); + + /* Fibre Channel transmitter technology */ + if (id[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_TECH_LONG_LC) + printf("%s FC: Longwave laser (LC)\n", pfx); + if (id[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_TECH_ELEC_INTER) + printf("%s FC: Electrical inter-enclosure (EL)\n", pfx); + if (id[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_ELEC_INTRA) + printf("%s FC: Electrical intra-enclosure (EL)\n", pfx); + if (id[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_SHORT_WO_OFC) + printf("%s FC: Shortwave laser w/o OFC (SN)\n", pfx); + if (id[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_SHORT_W_OFC) + printf("%s FC: Shortwave laser with OFC (SL)\n", pfx); + if (id[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_LONG_LL) + printf("%s FC: Longwave laser (LL)\n", pfx); + + /* Fibre Channel transmission media */ + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TW) + printf("%s FC: Twin Axial Pair (TW)\n", pfx); + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TP) + printf("%s FC: Twisted Pair (TP)\n", pfx); + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_MI) + printf("%s FC: Miniature Coax (MI)\n", pfx); + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TV) + printf("%s FC: Video Coax (TV)\n", pfx); + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_M6) + printf("%s FC: Multimode, 62.5m (M6)\n", pfx); + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_M5) + printf("%s FC: Multimode, 50m (M5)\n", pfx); + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_OM3) + printf("%s FC: Multimode, 50um (OM3)\n", pfx); + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_SM) + printf("%s FC: Single Mode (SM)\n", pfx); + + /* Fibre Channel speed */ + if (id[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_1200_MBPS) + printf("%s FC: 1200 MBytes/sec\n", pfx); + if (id[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_800_MBPS) + printf("%s FC: 800 MBytes/sec\n", pfx); + if (id[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_1600_MBPS) + printf("%s FC: 1600 MBytes/sec\n", pfx); + if (id[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_400_MBPS) + printf("%s FC: 400 MBytes/sec\n", pfx); + if (id[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_200_MBPS) + printf("%s FC: 200 MBytes/sec\n", pfx); + if (id[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_100_MBPS) + printf("%s FC: 100 MBytes/sec\n", pfx); +} + +static void sff_8636_show_encoding(const uint8_t *id) +{ + sff_8024_show_encoding(id, SFF_8636_ENCODING_OFFSET, RTE_ETH_MODULE_SFF_8636); +} + +static void sff_8636_show_rate_identifier(const uint8_t *id) +{ + /* TODO: Need to fix rate select logic */ + printf("%-41s : 0x%02x\n", "Rate identifier", + id[SFF_8636_EXT_RS_OFFSET]); +} + +static void sff_8636_show_oui(const uint8_t *id) +{ + sff_8024_show_oui(id, SFF_8636_VENDOR_OUI_OFFSET); +} + +static void sff_8636_show_wavelength_or_copper_compliance(const uint8_t *id) +{ + printf("%-41s : 0x%02x", "Transmitter technology", + (id[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK)); + + switch (id[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK) { + case SFF_8636_TRANS_850_VCSEL: + printf(" (850 nm VCSEL)\n"); + break; + case SFF_8636_TRANS_1310_VCSEL: + printf(" (1310 nm VCSEL)\n"); + break; + case SFF_8636_TRANS_1550_VCSEL: + printf(" (1550 nm VCSEL)\n"); + break; + case SFF_8636_TRANS_1310_FP: + printf(" (1310 nm FP)\n"); + break; + case SFF_8636_TRANS_1310_DFB: + printf(" (1310 nm DFB)\n"); + break; + case SFF_8636_TRANS_1550_DFB: + printf(" (1550 nm DFB)\n"); + break; + case SFF_8636_TRANS_1310_EML: + printf(" (1310 nm EML)\n"); + break; + case SFF_8636_TRANS_1550_EML: + printf(" (1550 nm EML)\n"); + break; + case SFF_8636_TRANS_OTHERS: + printf(" (Others/Undefined)\n"); + break; + case SFF_8636_TRANS_1490_DFB: + printf(" (1490 nm DFB)\n"); + break; + case SFF_8636_TRANS_COPPER_PAS_UNEQUAL: + printf(" (Copper cable unequalized)\n"); + break; + case SFF_8636_TRANS_COPPER_PAS_EQUAL: + printf(" (Copper cable passive equalized)\n"); + break; + case SFF_8636_TRANS_COPPER_LNR_FAR_EQUAL: + printf(" (Copper cable, near and far end limiting active equalizers)\n"); + break; + case SFF_8636_TRANS_COPPER_FAR_EQUAL: + printf(" (Copper cable, far end limiting active equalizers)\n"); + break; + case SFF_8636_TRANS_COPPER_NEAR_EQUAL: + printf(" (Copper cable, near end limiting active equalizers)\n"); + break; + case SFF_8636_TRANS_COPPER_LNR_EQUAL: + printf(" (Copper cable, linear active equalizers)\n"); + break; + } + + if ((id[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK) + >= SFF_8636_TRANS_COPPER_PAS_UNEQUAL) { + printf("%-41s : %udb\n", "Attenuation at 2.5GHz", + id[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + printf("%-41s : %udb\n", "Attenuation at 5.0GHz", + id[SFF_8636_WAVELEN_LOW_BYTE_OFFSET]); + printf("%-41s : %udb\n", "Attenuation at 7.0GHz", + id[SFF_8636_WAVE_TOL_HIGH_BYTE_OFFSET]); + printf("%-41s : %udb\n", "Attenuation at 12.9GHz", + id[SFF_8636_WAVE_TOL_LOW_BYTE_OFFSET]); + } else { + printf("%-41s : %.3lfnm\n", "Laser wavelength", + (((id[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET] << 8) | + id[SFF_8636_WAVELEN_LOW_BYTE_OFFSET])*0.05)); + printf("%-41s : %.3lfnm\n", "Laser wavelength tolerance", + (((id[SFF_8636_WAVE_TOL_HIGH_BYTE_OFFSET] << 8) | + id[SFF_8636_WAVE_TOL_LOW_BYTE_OFFSET])*0.005)); + } +} + +static void sff_8636_show_revision_compliance(const uint8_t *id) +{ + static const char *pfx = + "Revision Compliance :"; + + switch (id[SFF_8636_REV_COMPLIANCE_OFFSET]) { + case SFF_8636_REV_UNSPECIFIED: + printf("%s Revision not specified\n", pfx); + break; + case SFF_8636_REV_8436_48: + printf("%s SFF-8436 Rev 4.8 or earlier\n", pfx); + break; + case SFF_8636_REV_8436_8636: + printf("%s SFF-8436 Rev 4.8 or earlier\n", pfx); + break; + case SFF_8636_REV_8636_13: + printf("%s SFF-8636 Rev 1.3 or earlier\n", pfx); + break; + case SFF_8636_REV_8636_14: + printf("%s SFF-8636 Rev 1.4\n", pfx); + break; + case SFF_8636_REV_8636_15: + printf("%s SFF-8636 Rev 1.5\n", pfx); + break; + case SFF_8636_REV_8636_20: + printf("%s SFF-8636 Rev 2.0\n", pfx); + break; + case SFF_8636_REV_8636_27: + printf("%s SFF-8636 Rev 2.5/2.6/2.7\n", pfx); + break; + default: + printf("%s Unallocated\n", pfx); + break; + } +} + +/* + * 2-byte internal temperature conversions: + * First byte is a signed 8-bit integer, which is the temp decimal part + * Second byte are 1/256th of degree, which are added to the dec part. + */ +#define SFF_8636_OFFSET_TO_TEMP(offset) ((int16_t)OFFSET_TO_U16(offset)) + +static void sff_8636_dom_parse(const uint8_t *id, struct sff_diags *sd) +{ + int i = 0; + + /* Monitoring Thresholds for Alarms and Warnings */ + sd->sfp_voltage[MCURR] = OFFSET_TO_U16(SFF_8636_VCC_CURR); + sd->sfp_voltage[HALRM] = OFFSET_TO_U16(SFF_8636_VCC_HALRM); + sd->sfp_voltage[LALRM] = OFFSET_TO_U16(SFF_8636_VCC_LALRM); + sd->sfp_voltage[HWARN] = OFFSET_TO_U16(SFF_8636_VCC_HWARN); + sd->sfp_voltage[LWARN] = OFFSET_TO_U16(SFF_8636_VCC_LWARN); + + sd->sfp_temp[MCURR] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_CURR); + sd->sfp_temp[HALRM] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_HALRM); + sd->sfp_temp[LALRM] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_LALRM); + sd->sfp_temp[HWARN] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_HWARN); + sd->sfp_temp[LWARN] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_LWARN); + + sd->bias_cur[HALRM] = OFFSET_TO_U16(SFF_8636_TX_BIAS_HALRM); + sd->bias_cur[LALRM] = OFFSET_TO_U16(SFF_8636_TX_BIAS_LALRM); + sd->bias_cur[HWARN] = OFFSET_TO_U16(SFF_8636_TX_BIAS_HWARN); + sd->bias_cur[LWARN] = OFFSET_TO_U16(SFF_8636_TX_BIAS_LWARN); + + sd->tx_power[HALRM] = OFFSET_TO_U16(SFF_8636_TX_PWR_HALRM); + sd->tx_power[LALRM] = OFFSET_TO_U16(SFF_8636_TX_PWR_LALRM); + sd->tx_power[HWARN] = OFFSET_TO_U16(SFF_8636_TX_PWR_HWARN); + sd->tx_power[LWARN] = OFFSET_TO_U16(SFF_8636_TX_PWR_LWARN); + + sd->rx_power[HALRM] = OFFSET_TO_U16(SFF_8636_RX_PWR_HALRM); + sd->rx_power[LALRM] = OFFSET_TO_U16(SFF_8636_RX_PWR_LALRM); + sd->rx_power[HWARN] = OFFSET_TO_U16(SFF_8636_RX_PWR_HWARN); + sd->rx_power[LWARN] = OFFSET_TO_U16(SFF_8636_RX_PWR_LWARN); + + + /* Channel Specific Data */ + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + uint8_t rx_power_offset, tx_bias_offset; + uint8_t tx_power_offset; + + switch (i) { + case 0: + rx_power_offset = SFF_8636_RX_PWR_1_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_1_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_1_OFFSET; + break; + case 1: + rx_power_offset = SFF_8636_RX_PWR_2_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_2_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_2_OFFSET; + break; + case 2: + rx_power_offset = SFF_8636_RX_PWR_3_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_3_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_3_OFFSET; + break; + case 3: + rx_power_offset = SFF_8636_RX_PWR_4_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_4_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_4_OFFSET; + break; + } + sd->scd[i].bias_cur = OFFSET_TO_U16(tx_bias_offset); + sd->scd[i].rx_power = OFFSET_TO_U16(rx_power_offset); + sd->scd[i].tx_power = OFFSET_TO_U16(tx_power_offset); + } + +} + +static void sff_8636_show_dom(const uint8_t *id, uint32_t eeprom_len) +{ + struct sff_diags sd = {0}; + const char *rx_power_string = NULL; + char power_string[MAX_DESC_SIZE]; + int i; + + /* + * There is no clear identifier to signify the existence of + * optical diagnostics similar to SFF-8472. So checking existence + * of page 3, will provide the gurantee for existence of alarms + * and thresholds + * If pagging support exists, then supports_alarms is marked as 1 + */ + + if (eeprom_len == RTE_ETH_MODULE_SFF_8636_MAX_LEN) { + if (!(id[SFF_8636_STATUS_2_OFFSET] & + SFF_8636_STATUS_PAGE_3_PRESENT)) { + sd.supports_alarms = 1; + } + } + + sd.rx_power_type = id[SFF_8636_DIAG_TYPE_OFFSET] & + SFF_8636_RX_PWR_TYPE_MASK; + sd.tx_power_type = id[SFF_8636_DIAG_TYPE_OFFSET] & + SFF_8636_RX_PWR_TYPE_MASK; + + sff_8636_dom_parse(id, &sd); + + PRINT_TEMP("Module temperature", sd.sfp_temp[MCURR]); + PRINT_VCC("Module voltage", sd.sfp_voltage[MCURR]); + + /* + * SFF-8636/8436 spec is not clear whether RX power/ TX bias + * current fields are supported or not. A valid temperature + * reading is used as existence for TX/RX power. + */ + if ((sd.sfp_temp[MCURR] == 0x0) || + (sd.sfp_temp[MCURR] == (int16_t)0xFFFF)) + return; + + printf("%-41s : %s\n", "Alarm/warning flags implemented", + (sd.supports_alarms ? "Yes" : "No")); + + for (i = 0; i < 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++) { + 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); + } + + if (!sd.rx_power_type) + rx_power_string = "Receiver signal OMA"; + else + rx_power_string = "Rcvr signal avg optical power"; + + for (i = 0; i < 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); + } + + if (sd.supports_alarms) { + for (i = 0; sff_8636_aw_flags[i].str; ++i) { + printf("%-41s : %s\n", sff_8636_aw_flags[i].str, + id[sff_8636_aw_flags[i].offset] + & sff_8636_aw_flags[i].value ? "On" : "Off"); + } + + sff_show_thresholds(sd); + } + +} +void sff_8636_show_all(const uint8_t *id, uint32_t eeprom_len) +{ + sff_8636_show_identifier(id); + if ((id[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP) || + (id[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP_PLUS) || + (id[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP28)) { + sff_8636_show_ext_identifier(id); + sff_8636_show_connector(id); + sff_8636_show_transceiver(id); + sff_8636_show_encoding(id); + sff_show_value_with_unit(id, SFF_8636_BR_NOMINAL_OFFSET, + "BR, Nominal", 100, "Mbps"); + sff_8636_show_rate_identifier(id); + sff_show_value_with_unit(id, SFF_8636_SM_LEN_OFFSET, + "Length (SMF,km)", 1, "km"); + sff_show_value_with_unit(id, SFF_8636_OM3_LEN_OFFSET, + "Length (OM3 50um)", 2, "m"); + sff_show_value_with_unit(id, SFF_8636_OM2_LEN_OFFSET, + "Length (OM2 50um)", 1, "m"); + sff_show_value_with_unit(id, SFF_8636_OM1_LEN_OFFSET, + "Length (OM1 62.5um)", 1, "m"); + sff_show_value_with_unit(id, SFF_8636_CBL_LEN_OFFSET, + "Length (Copper or Active cable)", 1, "m"); + sff_8636_show_wavelength_or_copper_compliance(id); + sff_show_ascii(id, SFF_8636_VENDOR_NAME_START_OFFSET, + SFF_8636_VENDOR_NAME_END_OFFSET, "Vendor name"); + sff_8636_show_oui(id); + sff_show_ascii(id, SFF_8636_VENDOR_PN_START_OFFSET, + SFF_8636_VENDOR_PN_END_OFFSET, "Vendor PN"); + sff_show_ascii(id, SFF_8636_VENDOR_REV_START_OFFSET, + SFF_8636_VENDOR_REV_END_OFFSET, "Vendor rev"); + sff_show_ascii(id, SFF_8636_VENDOR_SN_START_OFFSET, + SFF_8636_VENDOR_SN_END_OFFSET, "Vendor SN"); + sff_show_ascii(id, SFF_8636_DATE_YEAR_OFFSET, + SFF_8636_DATE_VENDOR_LOT_OFFSET + 1, "Date code"); + sff_8636_show_revision_compliance(id); + sff_8636_show_dom(id, eeprom_len); + } +} diff --git a/app/test-pmd/sff_8636.h b/app/test-pmd/sff_8636.h new file mode 100644 index 0000000000..d19e6c744e --- /dev/null +++ b/app/test-pmd/sff_8636.h @@ -0,0 +1,592 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2022 Intel Corporation + * + * SFF-8636 standards based QSFP EEPROM Field Definitions + * + */ + +#ifndef SFF_8636_H__ +#define SFF_8636_H__ + +/*------------------------------------------------------------------------------ + * + * QSFP EEPROM data structures + * + * register info from SFF-8636 Rev 2.7 + */ + +/*------------------------------------------------------------------------------ + * + * Lower Memory Page 00h + * Measurement, Diagnostic and Control Functions + * + */ +/* Identifier - 0 */ +/* Values are defined under SFF_8024_ID_OFFSET */ +#define SFF_8636_ID_OFFSET 0x00 + +#define SFF_8636_REV_COMPLIANCE_OFFSET 0x01 +#define SFF_8636_REV_UNSPECIFIED 0x00 +#define SFF_8636_REV_8436_48 0x01 +#define SFF_8636_REV_8436_8636 0x02 +#define SFF_8636_REV_8636_13 0x03 +#define SFF_8636_REV_8636_14 0x04 +#define SFF_8636_REV_8636_15 0x05 +#define SFF_8636_REV_8636_20 0x06 +#define SFF_8636_REV_8636_27 0x07 + +#define SFF_8636_STATUS_2_OFFSET 0x02 +/* Flat Memory:0- Paging, 1- Page 0 only */ +#define SFF_8636_STATUS_PAGE_3_PRESENT (1 << 2) +#define SFF_8636_STATUS_INTL_OUTPUT (1 << 1) +#define SFF_8636_STATUS_DATA_NOT_READY (1 << 0) + +/* Channel Status Interrupt Flags - 3-5 */ +#define SFF_8636_LOS_AW_OFFSET 0x03 +#define SFF_8636_TX4_LOS_AW (1 << 7) +#define SFF_8636_TX3_LOS_AW (1 << 6) +#define SFF_8636_TX2_LOS_AW (1 << 5) +#define SFF_8636_TX1_LOS_AW (1 << 4) +#define SFF_8636_RX4_LOS_AW (1 << 3) +#define SFF_8636_RX3_LOS_AW (1 << 2) +#define SFF_8636_RX2_LOS_AW (1 << 1) +#define SFF_8636_RX1_LOS_AW (1 << 0) + +#define SFF_8636_FAULT_AW_OFFSET 0x04 +#define SFF_8636_TX4_FAULT_AW (1 << 3) +#define SFF_8636_TX3_FAULT_AW (1 << 2) +#define SFF_8636_TX2_FAULT_AW (1 << 1) +#define SFF_8636_TX1_FAULT_AW (1 << 0) + +/* Module Monitor Interrupt Flags - 6-8 */ +#define SFF_8636_TEMP_AW_OFFSET 0x06 +#define SFF_8636_TEMP_HALARM_STATUS (1 << 7) +#define SFF_8636_TEMP_LALARM_STATUS (1 << 6) +#define SFF_8636_TEMP_HWARN_STATUS (1 << 5) +#define SFF_8636_TEMP_LWARN_STATUS (1 << 4) + +#define SFF_8636_VCC_AW_OFFSET 0x07 +#define SFF_8636_VCC_HALARM_STATUS (1 << 7) +#define SFF_8636_VCC_LALARM_STATUS (1 << 6) +#define SFF_8636_VCC_HWARN_STATUS (1 << 5) +#define SFF_8636_VCC_LWARN_STATUS (1 << 4) + +/* Channel Monitor Interrupt Flags - 9-21 */ +#define SFF_8636_RX_PWR_12_AW_OFFSET 0x09 +#define SFF_8636_RX_PWR_1_HALARM (1 << 7) +#define SFF_8636_RX_PWR_1_LALARM (1 << 6) +#define SFF_8636_RX_PWR_1_HWARN (1 << 5) +#define SFF_8636_RX_PWR_1_LWARN (1 << 4) +#define SFF_8636_RX_PWR_2_HALARM (1 << 3) +#define SFF_8636_RX_PWR_2_LALARM (1 << 2) +#define SFF_8636_RX_PWR_2_HWARN (1 << 1) +#define SFF_8636_RX_PWR_2_LWARN (1 << 0) + +#define SFF_8636_RX_PWR_34_AW_OFFSET 0x0A +#define SFF_8636_RX_PWR_3_HALARM (1 << 7) +#define SFF_8636_RX_PWR_3_LALARM (1 << 6) +#define SFF_8636_RX_PWR_3_HWARN (1 << 5) +#define SFF_8636_RX_PWR_3_LWARN (1 << 4) +#define SFF_8636_RX_PWR_4_HALARM (1 << 3) +#define SFF_8636_RX_PWR_4_LALARM (1 << 2) +#define SFF_8636_RX_PWR_4_HWARN (1 << 1) +#define SFF_8636_RX_PWR_4_LWARN (1 << 0) + +#define SFF_8636_TX_BIAS_12_AW_OFFSET 0x0B +#define SFF_8636_TX_BIAS_1_HALARM (1 << 7) +#define SFF_8636_TX_BIAS_1_LALARM (1 << 6) +#define SFF_8636_TX_BIAS_1_HWARN (1 << 5) +#define SFF_8636_TX_BIAS_1_LWARN (1 << 4) +#define SFF_8636_TX_BIAS_2_HALARM (1 << 3) +#define SFF_8636_TX_BIAS_2_LALARM (1 << 2) +#define SFF_8636_TX_BIAS_2_HWARN (1 << 1) +#define SFF_8636_TX_BIAS_2_LWARN (1 << 0) + +#define SFF_8636_TX_BIAS_34_AW_OFFSET 0xC +#define SFF_8636_TX_BIAS_3_HALARM (1 << 7) +#define SFF_8636_TX_BIAS_3_LALARM (1 << 6) +#define SFF_8636_TX_BIAS_3_HWARN (1 << 5) +#define SFF_8636_TX_BIAS_3_LWARN (1 << 4) +#define SFF_8636_TX_BIAS_4_HALARM (1 << 3) +#define SFF_8636_TX_BIAS_4_LALARM (1 << 2) +#define SFF_8636_TX_BIAS_4_HWARN (1 << 1) +#define SFF_8636_TX_BIAS_4_LWARN (1 << 0) + +#define SFF_8636_TX_PWR_12_AW_OFFSET 0x0D +#define SFF_8636_TX_PWR_1_HALARM (1 << 7) +#define SFF_8636_TX_PWR_1_LALARM (1 << 6) +#define SFF_8636_TX_PWR_1_HWARN (1 << 5) +#define SFF_8636_TX_PWR_1_LWARN (1 << 4) +#define SFF_8636_TX_PWR_2_HALARM (1 << 3) +#define SFF_8636_TX_PWR_2_LALARM (1 << 2) +#define SFF_8636_TX_PWR_2_HWARN (1 << 1) +#define SFF_8636_TX_PWR_2_LWARN (1 << 0) + +#define SFF_8636_TX_PWR_34_AW_OFFSET 0x0E +#define SFF_8636_TX_PWR_3_HALARM (1 << 7) +#define SFF_8636_TX_PWR_3_LALARM (1 << 6) +#define SFF_8636_TX_PWR_3_HWARN (1 << 5) +#define SFF_8636_TX_PWR_3_LWARN (1 << 4) +#define SFF_8636_TX_PWR_4_HALARM (1 << 3) +#define SFF_8636_TX_PWR_4_LALARM (1 << 2) +#define SFF_8636_TX_PWR_4_HWARN (1 << 1) +#define SFF_8636_TX_PWR_4_LWARN (1 << 0) + +/* Module Monitoring Values - 22-33 */ +#define SFF_8636_TEMP_CURR 0x16 +#define SFF_8636_TEMP_MSB_OFFSET 0x16 +#define SFF_8636_TEMP_LSB_OFFSET 0x17 + +#define SFF_8636_VCC_CURR 0x1A +#define SFF_8636_VCC_MSB_OFFSET 0x1A +#define SFF_8636_VCC_LSB_OFFSET 0x1B + +/* Channel Monitoring Values - 34-81 */ +#define SFF_8636_RX_PWR_1_OFFSET 0x22 +#define SFF_8636_RX_PWR_2_OFFSET 0x24 +#define SFF_8636_RX_PWR_3_OFFSET 0x26 +#define SFF_8636_RX_PWR_4_OFFSET 0x28 + +#define SFF_8636_TX_BIAS_1_OFFSET 0x2A +#define SFF_8636_TX_BIAS_2_OFFSET 0x2C +#define SFF_8636_TX_BIAS_3_OFFSET 0x2E +#define SFF_8636_TX_BIAS_4_OFFSET 0x30 + +#define SFF_8636_TX_PWR_1_OFFSET 0x32 +#define SFF_8636_TX_PWR_2_OFFSET 0x34 +#define SFF_8636_TX_PWR_3_OFFSET 0x36 +#define SFF_8636_TX_PWR_4_OFFSET 0x38 + +/* Control Bytes - 86 - 99 */ +#define SFF_8636_TX_DISABLE_OFFSET 0x56 +#define SFF_8636_TX_DISABLE_4 (1 << 3) +#define SFF_8636_TX_DISABLE_3 (1 << 2) +#define SFF_8636_TX_DISABLE_2 (1 << 1) +#define SFF_8636_TX_DISABLE_1 (1 << 0) + +#define SFF_8636_RX_RATE_SELECT_OFFSET 0x57 +#define SFF_8636_RX_RATE_SELECT_4_MASK (3 << 6) +#define SFF_8636_RX_RATE_SELECT_3_MASK (3 << 4) +#define SFF_8636_RX_RATE_SELECT_2_MASK (3 << 2) +#define SFF_8636_RX_RATE_SELECT_1_MASK (3 << 0) + +#define SFF_8636_TX_RATE_SELECT_OFFSET 0x58 +#define SFF_8636_TX_RATE_SELECT_4_MASK (3 << 6) +#define SFF_8636_TX_RATE_SELECT_3_MASK (3 << 4) +#define SFF_8636_TX_RATE_SELECT_2_MASK (3 << 2) +#define SFF_8636_TX_RATE_SELECT_1_MASK (3 << 0) + +#define SFF_8636_RX_APP_SELECT_4_OFFSET 0x58 +#define SFF_8636_RX_APP_SELECT_3_OFFSET 0x59 +#define SFF_8636_RX_APP_SELECT_2_OFFSET 0x5A +#define SFF_8636_RX_APP_SELECT_1_OFFSET 0x5B + +#define SFF_8636_PWR_MODE_OFFSET 0x5D +#define SFF_8636_HIGH_PWR_ENABLE (1 << 2) +#define SFF_8636_LOW_PWR_MODE (1 << 1) +#define SFF_8636_PWR_OVERRIDE (1 << 0) + +#define SFF_8636_TX_APP_SELECT_4_OFFSET 0x5E +#define SFF_8636_TX_APP_SELECT_3_OFFSET 0x5F +#define SFF_8636_TX_APP_SELECT_2_OFFSET 0x60 +#define SFF_8636_TX_APP_SELECT_1_OFFSET 0x61 + +#define SFF_8636_LOS_MASK_OFFSET 0x64 +#define SFF_8636_TX_LOS_4_MASK (1 << 7) +#define SFF_8636_TX_LOS_3_MASK (1 << 6) +#define SFF_8636_TX_LOS_2_MASK (1 << 5) +#define SFF_8636_TX_LOS_1_MASK (1 << 4) +#define SFF_8636_RX_LOS_4_MASK (1 << 3) +#define SFF_8636_RX_LOS_3_MASK (1 << 2) +#define SFF_8636_RX_LOS_2_MASK (1 << 1) +#define SFF_8636_RX_LOS_1_MASK (1 << 0) + +#define SFF_8636_FAULT_MASK_OFFSET 0x65 +#define SFF_8636_TX_FAULT_1_MASK (1 << 3) +#define SFF_8636_TX_FAULT_2_MASK (1 << 2) +#define SFF_8636_TX_FAULT_3_MASK (1 << 1) +#define SFF_8636_TX_FAULT_4_MASK (1 << 0) + +#define SFF_8636_TEMP_MASK_OFFSET 0x67 +#define SFF_8636_TEMP_HALARM_MASK (1 << 7) +#define SFF_8636_TEMP_LALARM_MASK (1 << 6) +#define SFF_8636_TEMP_HWARN_MASK (1 << 5) +#define SFF_8636_TEMP_LWARN_MASK (1 << 4) + +#define SFF_8636_VCC_MASK_OFFSET 0x68 +#define SFF_8636_VCC_HALARM_MASK (1 << 7) +#define SFF_8636_VCC_LALARM_MASK (1 << 6) +#define SFF_8636_VCC_HWARN_MASK (1 << 5) +#define SFF_8636_VCC_LWARN_MASK (1 << 4) + +/*------------------------------------------------------------------------------ + * + * Upper Memory Page 00h + * Serial ID - Base ID, Extended ID and Vendor Specific ID fields + * + */ +/* Identifier - 128 */ +/* Identifier values same as Lower Memory Page 00h */ +#define SFF_8636_UPPER_PAGE_0_ID_OFFSET 0x80 + +/* Extended Identifier - 128 */ +#define SFF_8636_EXT_ID_OFFSET 0x81 +#define SFF_8636_EXT_ID_PWR_CLASS_MASK 0xC0 +#define SFF_8636_EXT_ID_PWR_CLASS_1 (0 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_2 (1 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_3 (2 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_4 (3 << 6) +#define SFF_8636_EXT_ID_CLIE_MASK 0x10 +#define SFF_8636_EXT_ID_CLIEI_CODE_PRESENT (1 << 4) +#define SFF_8636_EXT_ID_CDR_TX_MASK 0x08 +#define SFF_8636_EXT_ID_CDR_TX_PRESENT (1 << 3) +#define SFF_8636_EXT_ID_CDR_RX_MASK 0x04 +#define SFF_8636_EXT_ID_CDR_RX_PRESENT (1 << 2) +#define SFF_8636_EXT_ID_EPWR_CLASS_MASK 0x03 +#define SFF_8636_EXT_ID_PWR_CLASS_LEGACY 0 +#define SFF_8636_EXT_ID_PWR_CLASS_5 1 +#define SFF_8636_EXT_ID_PWR_CLASS_6 2 +#define SFF_8636_EXT_ID_PWR_CLASS_7 3 + +/* Connector Values offset - 130 */ +/* Values are defined under SFF_8024_CTOR */ +#define SFF_8636_CTOR_OFFSET 0x82 +#define SFF_8636_CTOR_UNKNOWN 0x00 +#define SFF_8636_CTOR_SC 0x01 +#define SFF_8636_CTOR_FC_STYLE_1 0x02 +#define SFF_8636_CTOR_FC_STYLE_2 0x03 +#define SFF_8636_CTOR_BNC_TNC 0x04 +#define SFF_8636_CTOR_FC_COAX 0x05 +#define SFF_8636_CTOR_FIBER_JACK 0x06 +#define SFF_8636_CTOR_LC 0x07 +#define SFF_8636_CTOR_MT_RJ 0x08 +#define SFF_8636_CTOR_MU 0x09 +#define SFF_8636_CTOR_SG 0x0A +#define SFF_8636_CTOR_OPT_PT 0x0B +#define SFF_8636_CTOR_MPO 0x0C +/* 0D-1Fh --- Reserved */ +#define SFF_8636_CTOR_HSDC_II 0x20 +#define SFF_8636_CTOR_COPPER_PT 0x21 +#define SFF_8636_CTOR_RJ45 0x22 +#define SFF_8636_CTOR_NO_SEPARABLE 0x23 +#define SFF_8636_CTOR_MXC_2X16 0x24 + +/* Specification Compliance - 131-138 */ +/* Ethernet Compliance Codes - 131 */ +#define SFF_8636_ETHERNET_COMP_OFFSET 0x83 +#define SFF_8636_ETHERNET_RSRVD (1 << 7) +#define SFF_8636_ETHERNET_10G_LRM (1 << 6) +#define SFF_8636_ETHERNET_10G_LR (1 << 5) +#define SFF_8636_ETHERNET_10G_SR (1 << 4) +#define SFF_8636_ETHERNET_40G_CR4 (1 << 3) +#define SFF_8636_ETHERNET_40G_SR4 (1 << 2) +#define SFF_8636_ETHERNET_40G_LR4 (1 << 1) +#define SFF_8636_ETHERNET_40G_ACTIVE (1 << 0) + +/* SONET Compliance Codes - 132 */ +#define SFF_8636_SONET_COMP_OFFSET 0x84 +#define SFF_8636_SONET_40G_OTN (1 << 3) +#define SFF_8636_SONET_OC48_LR (1 << 2) +#define SFF_8636_SONET_OC48_IR (1 << 1) +#define SFF_8636_SONET_OC48_SR (1 << 0) + +/* SAS/SATA Complaince Codes - 133 */ +#define SFF_8636_SAS_COMP_OFFSET 0x85 +#define SFF_8636_SAS_12G (1 << 6) +#define SFF_8636_SAS_6G (1 << 5) +#define SFF_8636_SAS_3G (1 << 4) + +/* Gigabit Ethernet Compliance Codes - 134 */ +#define SFF_8636_GIGE_COMP_OFFSET 0x86 +#define SFF_8636_GIGE_1000_BASE_T (1 << 3) +#define SFF_8636_GIGE_1000_BASE_CX (1 << 2) +#define SFF_8636_GIGE_1000_BASE_LX (1 << 1) +#define SFF_8636_GIGE_1000_BASE_SX (1 << 0) + +/* Fibre Channel Link length/Transmitter Tech. - 135,136 */ +#define SFF_8636_FC_LEN_OFFSET 0x87 +#define SFF_8636_FC_LEN_VERY_LONG (1 << 7) +#define SFF_8636_FC_LEN_SHORT (1 << 6) +#define SFF_8636_FC_LEN_INT (1 << 5) +#define SFF_8636_FC_LEN_LONG (1 << 4) +#define SFF_8636_FC_LEN_MED (1 << 3) +#define SFF_8636_FC_TECH_LONG_LC (1 << 1) +#define SFF_8636_FC_TECH_ELEC_INTER (1 << 0) + +#define SFF_8636_FC_TECH_OFFSET 0x88 +#define SFF_8636_FC_TECH_ELEC_INTRA (1 << 7) +#define SFF_8636_FC_TECH_SHORT_WO_OFC (1 << 6) +#define SFF_8636_FC_TECH_SHORT_W_OFC (1 << 5) +#define SFF_8636_FC_TECH_LONG_LL (1 << 4) + +/* Fibre Channel Transmitter Media - 137 */ +#define SFF_8636_FC_TRANS_MEDIA_OFFSET 0x89 +/* Twin Axial Pair */ +#define SFF_8636_FC_TRANS_MEDIA_TW (1 << 7) +/* Shielded Twisted Pair */ +#define SFF_8636_FC_TRANS_MEDIA_TP (1 << 6) +/* Miniature Coax */ +#define SFF_8636_FC_TRANS_MEDIA_MI (1 << 5) +/* Video Coax */ +#define SFF_8636_FC_TRANS_MEDIA_TV (1 << 4) +/* Multi-mode 62.5m */ +#define SFF_8636_FC_TRANS_MEDIA_M6 (1 << 3) +/* Multi-mode 50m */ +#define SFF_8636_FC_TRANS_MEDIA_M5 (1 << 2) +/* Multi-mode 50um */ +#define SFF_8636_FC_TRANS_MEDIA_OM3 (1 << 1) +/* Single Mode */ +#define SFF_8636_FC_TRANS_MEDIA_SM (1 << 0) + +/* Fibre Channel Speed - 138 */ +#define SFF_8636_FC_SPEED_OFFSET 0x8A +#define SFF_8636_FC_SPEED_1200_MBPS (1 << 7) +#define SFF_8636_FC_SPEED_800_MBPS (1 << 6) +#define SFF_8636_FC_SPEED_1600_MBPS (1 << 5) +#define SFF_8636_FC_SPEED_400_MBPS (1 << 4) +#define SFF_8636_FC_SPEED_200_MBPS (1 << 2) +#define SFF_8636_FC_SPEED_100_MBPS (1 << 0) + +/* Encoding - 139 */ +/* Values are defined under SFF_8024_ENCODING */ +#define SFF_8636_ENCODING_OFFSET 0x8B +#define SFF_8636_ENCODING_MANCHESTER 0x06 +#define SFF_8636_ENCODING_64B66B 0x05 +#define SFF_8636_ENCODING_SONET 0x04 +#define SFF_8636_ENCODING_NRZ 0x03 +#define SFF_8636_ENCODING_4B5B 0x02 +#define SFF_8636_ENCODING_8B10B 0x01 +#define SFF_8636_ENCODING_UNSPEC 0x00 + +/* BR, Nominal - 140 */ +#define SFF_8636_BR_NOMINAL_OFFSET 0x8C + +/* Extended RateSelect - 141 */ +#define SFF_8636_EXT_RS_OFFSET 0x8D +#define SFF_8636_EXT_RS_V1 (1 << 0) + +/* Length (Standard SM Fiber)-km - 142 */ +#define SFF_8636_SM_LEN_OFFSET 0x8E + +/* Length (OM3)-Unit 2m - 143 */ +#define SFF_8636_OM3_LEN_OFFSET 0x8F + +/* Length (OM2)-Unit 1m - 144 */ +#define SFF_8636_OM2_LEN_OFFSET 0x90 + +/* Length (OM1)-Unit 1m - 145 */ +#define SFF_8636_OM1_LEN_OFFSET 0x91 + +/* Cable Assembly Length -Unit 1m - 146 */ +#define SFF_8636_CBL_LEN_OFFSET 0x92 + +/* Device Technology - 147 */ +#define SFF_8636_DEVICE_TECH_OFFSET 0x93 +/* Transmitter Technology */ +#define SFF_8636_TRANS_TECH_MASK 0xF0 +/* Copper cable, linear active equalizers */ +#define SFF_8636_TRANS_COPPER_LNR_EQUAL (15 << 4) +/* Copper cable, near end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_NEAR_EQUAL (14 << 4) +/* Copper cable, far end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_FAR_EQUAL (13 << 4) +/* Copper cable, near & far end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_LNR_FAR_EQUAL (12 << 4) +/* Copper cable, passive equalized */ +#define SFF_8636_TRANS_COPPER_PAS_EQUAL (11 << 4) +/* Copper cable, unequalized */ +#define SFF_8636_TRANS_COPPER_PAS_UNEQUAL (10 << 4) +/* 1490 nm DFB */ +#define SFF_8636_TRANS_1490_DFB (9 << 4) +/* Others */ +#define SFF_8636_TRANS_OTHERS (8 << 4) +/* 1550 nm EML */ +#define SFF_8636_TRANS_1550_EML (7 << 4) +/* 1310 nm EML */ +#define SFF_8636_TRANS_1310_EML (6 << 4) +/* 1550 nm DFB */ +#define SFF_8636_TRANS_1550_DFB (5 << 4) +/* 1310 nm DFB */ +#define SFF_8636_TRANS_1310_DFB (4 << 4) +/* 1310 nm FP */ +#define SFF_8636_TRANS_1310_FP (3 << 4) +/* 1550 nm VCSEL */ +#define SFF_8636_TRANS_1550_VCSEL (2 << 4) +/* 1310 nm VCSEL */ +#define SFF_8636_TRANS_1310_VCSEL (1 << 4) +/* 850 nm VCSEL */ +#define SFF_8636_TRANS_850_VCSEL (0 << 4) + + /* Active/No wavelength control */ +#define SFF_8636_DEV_TECH_ACTIVE_WAVE_LEN (1 << 3) +/* Cooled transmitter */ +#define SFF_8636_DEV_TECH_COOL_TRANS (1 << 2) +/* APD/Pin Detector */ +#define SFF_8636_DEV_TECH_APD_DETECTOR (1 << 1) +/* Transmitter tunable */ +#define SFF_8636_DEV_TECH_TUNABLE (1 << 0) + +/* Vendor Name - 148-163 */ +#define SFF_8636_VENDOR_NAME_START_OFFSET 0x94 +#define SFF_8636_VENDOR_NAME_END_OFFSET 0xA3 + +/* Extended Module Codes - 164 */ +#define SFF_8636_EXT_MOD_CODE_OFFSET 0xA4 +#define SFF_8636_EXT_MOD_INFINIBAND_EDR (1 << 4) +#define SFF_8636_EXT_MOD_INFINIBAND_FDR (1 << 3) +#define SFF_8636_EXT_MOD_INFINIBAND_QDR (1 << 2) +#define SFF_8636_EXT_MOD_INFINIBAND_DDR (1 << 1) +#define SFF_8636_EXT_MOD_INFINIBAND_SDR (1 << 0) + +/* Vendor OUI - 165-167 */ +#define SFF_8636_VENDOR_OUI_OFFSET 0xA5 +#define SFF_8636_VENDOR_OUI_LEN 3 + +/* Vendor OUI - 165-167 */ +#define SFF_8636_VENDOR_PN_START_OFFSET 0xA8 +#define SFF_8636_VENDOR_PN_END_OFFSET 0xB7 + +/* Vendor Revision - 184-185 */ +#define SFF_8636_VENDOR_REV_START_OFFSET 0xB8 +#define SFF_8636_VENDOR_REV_END_OFFSET 0xB9 + +/* Wavelength - 186-187 */ +#define SFF_8636_WAVELEN_HIGH_BYTE_OFFSET 0xBA +#define SFF_8636_WAVELEN_LOW_BYTE_OFFSET 0xBB + +/* Wavelength Tolerance- 188-189 */ +#define SFF_8636_WAVE_TOL_HIGH_BYTE_OFFSET 0xBC +#define SFF_8636_WAVE_TOL_LOW_BYTE_OFFSET 0xBD + +/* Max case temp - Other than 70 C - 190 */ +#define SFF_8636_MAXCASE_TEMP_OFFSET 0xBE + +/* CC_BASE - 191 */ +#define SFF_8636_CC_BASE_OFFSET 0xBF + +/* Option Values - 192-195 */ +#define SFF_8636_OPTION_1_OFFSET 0xC0 +#define SFF_8636_ETHERNET_UNSPECIFIED 0x00 +#define SFF_8636_ETHERNET_100G_AOC 0x01 +#define SFF_8636_ETHERNET_100G_SR4 0x02 +#define SFF_8636_ETHERNET_100G_LR4 0x03 +#define SFF_8636_ETHERNET_100G_ER4 0x04 +#define SFF_8636_ETHERNET_100G_SR10 0x05 +#define SFF_8636_ETHERNET_100G_CWDM4_FEC 0x06 +#define SFF_8636_ETHERNET_100G_PSM4 0x07 +#define SFF_8636_ETHERNET_100G_ACC 0x08 +#define SFF_8636_ETHERNET_100G_CWDM4_NO_FEC 0x09 +#define SFF_8636_ETHERNET_100G_RSVD1 0x0A +#define SFF_8636_ETHERNET_100G_CR4 0x0B +#define SFF_8636_ETHERNET_25G_CR_CA_S 0x0C +#define SFF_8636_ETHERNET_25G_CR_CA_N 0x0D +#define SFF_8636_ETHERNET_40G_ER4 0x10 +#define SFF_8636_ETHERNET_4X10_SR 0x11 +#define SFF_8636_ETHERNET_40G_PSM4 0x12 +#define SFF_8636_ETHERNET_G959_P1I1_2D1 0x13 +#define SFF_8636_ETHERNET_G959_P1S1_2D2 0x14 +#define SFF_8636_ETHERNET_G959_P1L1_2D2 0x15 +#define SFF_8636_ETHERNET_10GT_SFI 0x16 +#define SFF_8636_ETHERNET_100G_CLR4 0x17 +#define SFF_8636_ETHERNET_100G_AOC2 0x18 +#define SFF_8636_ETHERNET_100G_ACC2 0x19 + +#define SFF_8636_OPTION_2_OFFSET 0xC1 +/* Rx output amplitude */ +#define SFF_8636_O2_RX_OUTPUT_AMP (1 << 0) +#define SFF_8636_OPTION_3_OFFSET 0xC2 +/* Rx Squelch Disable */ +#define SFF_8636_O3_RX_SQL_DSBL (1 << 3) +/* Rx Output Disable capable */ +#define SFF_8636_O3_RX_OUTPUT_DSBL (1 << 2) +/* Tx Squelch Disable */ +#define SFF_8636_O3_TX_SQL_DSBL (1 << 1) +/* Tx Squelch Impl */ +#define SFF_8636_O3_TX_SQL_IMPL (1 << 0) +#define SFF_8636_OPTION_4_OFFSET 0xC3 +/* Memory Page 02 present */ +#define SFF_8636_O4_PAGE_02_PRESENT (1 << 7) +/* Memory Page 01 present */ +#define SFF_8636_O4_PAGE_01_PRESENT (1 << 6) +/* Rate Select implemented */ +#define SFF_8636_O4_RATE_SELECT (1 << 5) +/* Tx_DISABLE implemented */ +#define SFF_8636_O4_TX_DISABLE (1 << 4) +/* Tx_FAULT implemented */ +#define SFF_8636_O4_TX_FAULT (1 << 3) +/* Tx Squelch implemented */ +#define SFF_8636_O4_TX_SQUELCH (1 << 2) +/* Tx Loss of Signal */ +#define SFF_8636_O4_TX_LOS (1 << 1) + +/* Vendor SN - 196-211 */ +#define SFF_8636_VENDOR_SN_START_OFFSET 0xC4 +#define SFF_8636_VENDOR_SN_END_OFFSET 0xD3 + +/* Vendor Date - 212-219 */ +#define SFF_8636_DATE_YEAR_OFFSET 0xD4 +#define SFF_8636_DATE_YEAR_LEN 2 +#define SFF_8636_DATE_MONTH_OFFSET 0xD6 +#define SFF_8636_DATE_MONTH_LEN 2 +#define SFF_8636_DATE_DAY_OFFSET 0xD8 +#define SFF_8636_DATE_DAY_LEN 2 +#define SFF_8636_DATE_VENDOR_LOT_OFFSET 0xDA +#define SFF_8636_DATE_VENDOR_LOT_LEN 2 + +/* Diagnostic Monitoring Type - 220 */ +#define SFF_8636_DIAG_TYPE_OFFSET 0xDC +#define SFF_8636_RX_PWR_TYPE_MASK 0x8 +#define SFF_8636_RX_PWR_TYPE_AVG_PWR (1 << 3) +#define SFF_8636_RX_PWR_TYPE_OMA (0 << 3) +#define SFF_8636_TX_PWR_TYPE_MASK 0x4 +#define SFF_8636_TX_PWR_TYPE_AVG_PWR (1 << 2) + +/* Enhanced Options - 221 */ +#define SFF_8636_ENH_OPTIONS_OFFSET 0xDD +#define SFF_8636_RATE_SELECT_EXT_SUPPORT (1 << 3) +#define SFF_8636_RATE_SELECT_APP_TABLE_SUPPORT (1 << 2) + +/* Check code - 223 */ +#define SFF_8636_CC_EXT_OFFSET 0xDF +#define SFF_8636_CC_EXT_LEN 1 + +/*------------------------------------------------------------------------------ + * + * Upper Memory Page 03h + * Contains module thresholds, channel thresholds and masks, + * and optional channel controls + * + * Offset - Page Num(3) * PageSize(0x80) + Page offset + */ + +/* Module Thresholds (48 Bytes) 128-175 */ +/* MSB at low address, LSB at high address */ +#define SFF_8636_TEMP_HALRM 0x200 +#define SFF_8636_TEMP_LALRM 0x202 +#define SFF_8636_TEMP_HWARN 0x204 +#define SFF_8636_TEMP_LWARN 0x206 + +#define SFF_8636_VCC_HALRM 0x210 +#define SFF_8636_VCC_LALRM 0x212 +#define SFF_8636_VCC_HWARN 0x214 +#define SFF_8636_VCC_LWARN 0x216 + +#define SFF_8636_RX_PWR_HALRM 0x230 +#define SFF_8636_RX_PWR_LALRM 0x232 +#define SFF_8636_RX_PWR_HWARN 0x234 +#define SFF_8636_RX_PWR_LWARN 0x236 + +#define SFF_8636_TX_BIAS_HALRM 0x238 +#define SFF_8636_TX_BIAS_LALRM 0x23A +#define SFF_8636_TX_BIAS_HWARN 0x23C +#define SFF_8636_TX_BIAS_LWARN 0x23E + +#define SFF_8636_TX_PWR_HALRM 0x240 +#define SFF_8636_TX_PWR_LALRM 0x242 +#define SFF_8636_TX_PWR_HWARN 0x244 +#define SFF_8636_TX_PWR_LWARN 0x246 + +#define ETH_MODULE_SFF_8636_MAX_LEN 640 +#define ETH_MODULE_SFF_8436_MAX_LEN 640 + +#endif /*SFF_8636_H__ */ diff --git a/app/test-pmd/sff_common.c b/app/test-pmd/sff_common.c new file mode 100644 index 0000000000..f0433d9c8c --- /dev/null +++ b/app/test-pmd/sff_common.c @@ -0,0 +1,296 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2022 Intel Corporation + * + * Implements SFF-8024 Rev 4.0 of pluggable I/O configuration + * + * Common utilities for SFF-8436/8636 and SFF-8472/8079 + * + */ + +#include <stdio.h> +#include <math.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "testpmd.h" + + +double convert_mw_to_dbm(double mw) +{ + return (10. * log10(mw / 1000.)) + 30.; +} + +void sff_show_value_with_unit(const uint8_t *id, unsigned int reg, + const char *name, unsigned int mult, + const char *unit) +{ + unsigned int val = id[reg]; + + printf("%-41s : %u%s\n", name, val * mult, unit); +} + +void sff_show_ascii(const uint8_t *id, unsigned int first_reg, + unsigned int last_reg, const char *name) +{ + unsigned int reg, val; + + printf("%-41s : ", name); + while (first_reg <= last_reg && id[last_reg] == ' ') + last_reg--; + for (reg = first_reg; reg <= last_reg; reg++) { + val = id[reg]; + putchar(((val >= 32) && (val <= 126)) ? val : '_'); + } + printf("\n"); +} + +void sff_8024_show_oui(const uint8_t *id, int id_offset) +{ + printf("%-41s : %02x:%02x:%02x\n", "Vendor OUI", + id[id_offset], id[(id_offset) + 1], + id[(id_offset) + 2]); +} + +void sff_8024_show_identifier(const uint8_t *id, int id_offset) +{ + printf("%-41s : 0x%02x", "Identifier", id[id_offset]); + switch (id[id_offset]) { + case SFF_8024_ID_UNKNOWN: + printf(" (no module present, unknown, or unspecified)\n"); + break; + case SFF_8024_ID_GBIC: + printf(" (GBIC)\n"); + break; + case SFF_8024_ID_SOLDERED_MODULE: + printf(" (module soldered to motherboard)\n"); + break; + case SFF_8024_ID_SFP: + printf(" (SFP)\n"); + break; + case SFF_8024_ID_300_PIN_XBI: + printf(" (300 pin XBI)\n"); + break; + case SFF_8024_ID_XENPAK: + printf(" (XENPAK)\n"); + break; + case SFF_8024_ID_XFP: + printf(" (XFP)\n"); + break; + case SFF_8024_ID_XFF: + printf(" (XFF)\n"); + break; + case SFF_8024_ID_XFP_E: + printf(" (XFP-E)\n"); + break; + case SFF_8024_ID_XPAK: + printf(" (XPAK)\n"); + break; + case SFF_8024_ID_X2: + printf(" (X2)\n"); + break; + case SFF_8024_ID_DWDM_SFP: + printf(" (DWDM-SFP)\n"); + break; + case SFF_8024_ID_QSFP: + printf(" (QSFP)\n"); + break; + case SFF_8024_ID_QSFP_PLUS: + printf(" (QSFP+)\n"); + break; + case SFF_8024_ID_CXP: + printf(" (CXP)\n"); + break; + case SFF_8024_ID_HD4X: + printf(" (Shielded Mini Multilane HD 4X)\n"); + break; + case SFF_8024_ID_HD8X: + printf(" (Shielded Mini Multilane HD 8X)\n"); + break; + case SFF_8024_ID_QSFP28: + printf(" (QSFP28)\n"); + break; + case SFF_8024_ID_CXP2: + printf(" (CXP2/CXP28)\n"); + break; + case SFF_8024_ID_CDFP: + printf(" (CDFP Style 1/Style 2)\n"); + break; + case SFF_8024_ID_HD4X_FANOUT: + printf(" (Shielded Mini Multilane HD 4X Fanout Cable)\n"); + break; + case SFF_8024_ID_HD8X_FANOUT: + printf(" (Shielded Mini Multilane HD 8X Fanout Cable)\n"); + break; + case SFF_8024_ID_CDFP_S3: + printf(" (CDFP Style 3)\n"); + break; + case SFF_8024_ID_MICRO_QSFP: + printf(" (microQSFP)\n"); + break; + default: + printf(" (reserved or unknown)\n"); + break; + } +} + +void sff_8024_show_connector(const uint8_t *id, int ctor_offset) +{ + printf("%-41s : 0x%02x", "Connector", id[ctor_offset]); + switch (id[ctor_offset]) { + case SFF_8024_CTOR_UNKNOWN: + printf(" (unknown or unspecified)\n"); + break; + case SFF_8024_CTOR_SC: + printf(" (SC)\n"); + break; + case SFF_8024_CTOR_FC_STYLE_1: + printf(" (Fibre Channel Style 1 copper)\n"); + break; + case SFF_8024_CTOR_FC_STYLE_2: + printf(" (Fibre Channel Style 2 copper)\n"); + break; + case SFF_8024_CTOR_BNC_TNC: + printf(" (BNC/TNC)\n"); + break; + case SFF_8024_CTOR_FC_COAX: + printf(" (Fibre Channel coaxial headers)\n"); + break; + case SFF_8024_CTOR_FIBER_JACK: + printf(" (FibreJack)\n"); + break; + case SFF_8024_CTOR_LC: + printf(" (LC)\n"); + break; + case SFF_8024_CTOR_MT_RJ: + printf(" (MT-RJ)\n"); + break; + case SFF_8024_CTOR_MU: + printf(" (MU)\n"); + break; + case SFF_8024_CTOR_SG: + printf(" (SG)\n"); + break; + case SFF_8024_CTOR_OPT_PT: + printf(" (Optical pigtail)\n"); + break; + case SFF_8024_CTOR_MPO: + printf(" (MPO Parallel Optic)\n"); + break; + case SFF_8024_CTOR_MPO_2: + printf(" (MPO Parallel Optic - 2x16)\n"); + break; + case SFF_8024_CTOR_HSDC_II: + printf(" (HSSDC II)\n"); + break; + case SFF_8024_CTOR_COPPER_PT: + printf(" (Copper pigtail)\n"); + break; + case SFF_8024_CTOR_RJ45: + printf(" (RJ45)\n"); + break; + case SFF_8024_CTOR_NO_SEPARABLE: + printf(" (No separable connector)\n"); + break; + case SFF_8024_CTOR_MXC_2x16: + printf(" (MXC 2x16)\n"); + break; + default: + printf(" (reserved or unknown)\n"); + break; + } +} + +void sff_8024_show_encoding(const uint8_t *id, int encoding_offset, int sff_type) +{ + printf("%-41s : 0x%02x", "Encoding", id[encoding_offset]); + switch (id[encoding_offset]) { + case SFF_8024_ENCODING_UNSPEC: + printf(" (unspecified)\n"); + break; + case SFF_8024_ENCODING_8B10B: + printf(" (8B/10B)\n"); + break; + case SFF_8024_ENCODING_4B5B: + printf(" (4B/5B)\n"); + break; + case SFF_8024_ENCODING_NRZ: + printf(" (NRZ)\n"); + break; + case SFF_8024_ENCODING_4h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) + printf(" (Manchester)\n"); + else if (sff_type == RTE_ETH_MODULE_SFF_8636) + printf(" (SONET Scrambled)\n"); + break; + case SFF_8024_ENCODING_5h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) + printf(" (SONET Scrambled)\n"); + else if (sff_type == RTE_ETH_MODULE_SFF_8636) + printf(" (64B/66B)\n"); + break; + case SFF_8024_ENCODING_6h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) + printf(" (64B/66B)\n"); + else if (sff_type == RTE_ETH_MODULE_SFF_8636) + printf(" (Manchester)\n"); + break; + case SFF_8024_ENCODING_256B: + printf(" ((256B/257B (transcoded FEC-enabled data))\n"); + break; + case SFF_8024_ENCODING_PAM4: + printf(" (PAM4)\n"); + break; + default: + printf(" (reserved or unknown)\n"); + break; + } +} + +void sff_show_thresholds(struct sff_diags sd) +{ + PRINT_BIAS("Laser bias current high alarm threshold", + sd.bias_cur[HALRM]); + PRINT_BIAS("Laser bias current low alarm threshold", + sd.bias_cur[LALRM]); + PRINT_BIAS("Laser bias current high warning threshold", + sd.bias_cur[HWARN]); + PRINT_BIAS("Laser bias current low warning threshold", + sd.bias_cur[LWARN]); + + PRINT_xX_PWR("Laser output power high alarm threshold", + sd.tx_power[HALRM]); + PRINT_xX_PWR("Laser output power low alarm threshold", + sd.tx_power[LALRM]); + PRINT_xX_PWR("Laser output power high warning threshold", + sd.tx_power[HWARN]); + PRINT_xX_PWR("Laser output power low warning threshold", + sd.tx_power[LWARN]); + + PRINT_TEMP("Module temperature high alarm threshold", + sd.sfp_temp[HALRM]); + PRINT_TEMP("Module temperature low alarm threshold", + sd.sfp_temp[LALRM]); + PRINT_TEMP("Module temperature high warning threshold", + sd.sfp_temp[HWARN]); + PRINT_TEMP("Module temperature low warning threshold", + sd.sfp_temp[LWARN]); + + PRINT_VCC("Module voltage high alarm threshold", + sd.sfp_voltage[HALRM]); + PRINT_VCC("Module voltage low alarm threshold", + sd.sfp_voltage[LALRM]); + PRINT_VCC("Module voltage high warning threshold", + sd.sfp_voltage[HWARN]); + PRINT_VCC("Module voltage low warning threshold", + sd.sfp_voltage[LWARN]); + + PRINT_xX_PWR("Laser rx power high alarm threshold", + sd.rx_power[HALRM]); + PRINT_xX_PWR("Laser rx power low alarm threshold", + sd.rx_power[LALRM]); + PRINT_xX_PWR("Laser rx power high warning threshold", + sd.rx_power[HWARN]); + PRINT_xX_PWR("Laser rx power low warning threshold", + sd.rx_power[LWARN]); +} diff --git a/app/test-pmd/sff_common.h b/app/test-pmd/sff_common.h new file mode 100644 index 0000000000..0b708a9a7a --- /dev/null +++ b/app/test-pmd/sff_common.h @@ -0,0 +1,178 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2022 Intel Corporation + * + * Implements SFF-8024 Rev 4.0 of pluggable I/O configuration + * + * Common utilities for SFF-8436/8636 and SFF-8472/8079 + * + */ + +#ifndef SFF_COMMON_H__ +#define SFF_COMMON_H__ + +#include <stdio.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> + +#define SFF_8024_ID_OFFSET 0x00 +#define SFF_8024_ID_UNKNOWN 0x00 +#define SFF_8024_ID_GBIC 0x01 +#define SFF_8024_ID_SOLDERED_MODULE 0x02 +#define SFF_8024_ID_SFP 0x03 +#define SFF_8024_ID_300_PIN_XBI 0x04 +#define SFF_8024_ID_XENPAK 0x05 +#define SFF_8024_ID_XFP 0x06 +#define SFF_8024_ID_XFF 0x07 +#define SFF_8024_ID_XFP_E 0x08 +#define SFF_8024_ID_XPAK 0x09 +#define SFF_8024_ID_X2 0x0A +#define SFF_8024_ID_DWDM_SFP 0x0B +#define SFF_8024_ID_QSFP 0x0C +#define SFF_8024_ID_QSFP_PLUS 0x0D +#define SFF_8024_ID_CXP 0x0E +#define SFF_8024_ID_HD4X 0x0F +#define SFF_8024_ID_HD8X 0x10 +#define SFF_8024_ID_QSFP28 0x11 +#define SFF_8024_ID_CXP2 0x12 +#define SFF_8024_ID_CDFP 0x13 +#define SFF_8024_ID_HD4X_FANOUT 0x14 +#define SFF_8024_ID_HD8X_FANOUT 0x15 +#define SFF_8024_ID_CDFP_S3 0x16 +#define SFF_8024_ID_MICRO_QSFP 0x17 +#define SFF_8024_ID_LAST SFF_8024_ID_MICRO_QSFP +#define SFF_8024_ID_UNALLOCATED_LAST 0x7F +#define SFF_8024_ID_VENDOR_START 0x80 +#define SFF_8024_ID_VENDOR_LAST 0xFF + +#define SFF_8024_CTOR_UNKNOWN 0x00 +#define SFF_8024_CTOR_SC 0x01 +#define SFF_8024_CTOR_FC_STYLE_1 0x02 +#define SFF_8024_CTOR_FC_STYLE_2 0x03 +#define SFF_8024_CTOR_BNC_TNC 0x04 +#define SFF_8024_CTOR_FC_COAX 0x05 +#define SFF_8024_CTOR_FIBER_JACK 0x06 +#define SFF_8024_CTOR_LC 0x07 +#define SFF_8024_CTOR_MT_RJ 0x08 +#define SFF_8024_CTOR_MU 0x09 +#define SFF_8024_CTOR_SG 0x0A +#define SFF_8024_CTOR_OPT_PT 0x0B +#define SFF_8024_CTOR_MPO 0x0C +#define SFF_8024_CTOR_MPO_2 0x0D +/* 0E-1Fh --- Reserved */ +#define SFF_8024_CTOR_HSDC_II 0x20 +#define SFF_8024_CTOR_COPPER_PT 0x21 +#define SFF_8024_CTOR_RJ45 0x22 +#define SFF_8024_CTOR_NO_SEPARABLE 0x23 +#define SFF_8024_CTOR_MXC_2x16 0x24 +#define SFF_8024_CTOR_LAST SFF_8024_CTOR_MXC_2x16 +#define SFF_8024_CTOR_UNALLOCATED_LAST 0x7F +#define SFF_8024_CTOR_VENDOR_START 0x80 +#define SFF_8024_CTOR_VENDOR_LAST 0xFF + +/* ENCODING Values */ +#define SFF_8024_ENCODING_UNSPEC 0x00 +#define SFF_8024_ENCODING_8B10B 0x01 +#define SFF_8024_ENCODING_4B5B 0x02 +#define SFF_8024_ENCODING_NRZ 0x03 +/* + * Value: 04h + * SFF-8472 - Manchester + * SFF-8436/8636 - SONET Scrambled + */ +#define SFF_8024_ENCODING_4h 0x04 +/* + * Value: 05h + * SFF-8472 - SONET Scrambled + * SFF-8436/8636 - 64B/66B + */ +#define SFF_8024_ENCODING_5h 0x05 +/* + * Value: 06h + * SFF-8472 - 64B/66B + * SFF-8436/8636 - Manchester + */ +#define SFF_8024_ENCODING_6h 0x06 +#define SFF_8024_ENCODING_256B 0x07 +#define SFF_8024_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 PRINT_xX_PWR(string, var) \ + printf("%-41s : %.4f mW / %.2f dBm\n", (string), \ + (double)((var) / 10000.), \ + convert_mw_to_dbm((double)((var) / 10000.))) + +#define PRINT_BIAS(string, bias_cur) \ + printf("%-41s : %.3f mA\n", (string), \ + (double)(bias_cur / 500.)) + +#define PRINT_TEMP(string, temp) \ + printf("%-41s : %.2f degrees C / %.2f degrees F\n", \ + (string), (double)(temp / 256.), \ + (double)(temp / 256. * 1.8 + 32.)) + +#define PRINT_VCC(string, sfp_voltage) \ + printf("%-41s : %.4f V\n", (string), \ + (double)(sfp_voltage / 10000.)) + +# define PRINT_xX_THRESH_PWR(string, var, index) \ + PRINT_xX_PWR(string, (var)[(index)]) + +/* Channel Monitoring Fields */ +struct sff_channel_diags { + uint16_t bias_cur; /* Measured bias current in 2uA units */ + uint16_t rx_power; /* Measured RX Power */ + uint16_t tx_power; /* Measured TX Power */ +}; + +/* Module Monitoring Fields */ +struct sff_diags { + +#define MAX_CHANNEL_NUM 4 +#define LWARN 0 +#define HWARN 1 +#define LALRM 2 +#define HALRM 3 +#define MCURR 4 + + /* Supports DOM */ + uint8_t supports_dom; + /* Supports alarm/warning thold */ + uint8_t supports_alarms; + /* RX Power: 0 = OMA, 1 = Average power */ + uint8_t rx_power_type; + /* TX Power: 0 = Not supported, 1 = Average power */ + uint8_t tx_power_type; + + uint8_t calibrated_ext; /* Is externally calibrated */ + /* [5] tables are low/high warn, low/high alarm, current */ + /* SFP voltage in 0.1mV units */ + uint16_t sfp_voltage[5]; + /* SFP Temp in 16-bit signed 1/256 Celcius */ + int16_t sfp_temp[5]; + /* Measured bias current in 2uA units */ + uint16_t bias_cur[5]; + /* Measured TX Power */ + uint16_t tx_power[5]; + /* Measured RX Power */ + uint16_t rx_power[5]; + struct sff_channel_diags scd[MAX_CHANNEL_NUM]; +}; + +double convert_mw_to_dbm(double mw); +void sff_show_value_with_unit(const uint8_t *id, unsigned int reg, + const char *name, unsigned int mult, + const char *unit); +void sff_show_ascii(const uint8_t *id, unsigned int first_reg, + unsigned int last_reg, const char *name); +void sff_show_thresholds(struct sff_diags sd); + +void sff_8024_show_oui(const uint8_t *id, int id_offset); +void sff_8024_show_identifier(const uint8_t *id, int id_offset); +void sff_8024_show_connector(const uint8_t *id, int ctor_offset); +void sff_8024_show_encoding(const uint8_t *id, int encoding_offset, int sff_type); + +#endif /* SFF_COMMON_H__ */ diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 9967825044..eabcca21ea 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -72,6 +72,8 @@ #define NUMA_NO_CONFIG 0xFF #define UMA_NO_CONFIG 0xFF +#define ARRAY_SIZE(arr) RTE_DIM(arr) + typedef uint8_t lcoreid_t; typedef uint16_t portid_t; typedef uint16_t queueid_t; @@ -850,7 +852,7 @@ void device_infos_display(const char *identifier); void port_infos_display(portid_t port_id); void port_summary_display(portid_t port_id); void port_eeprom_display(portid_t port_id); -void port_module_eeprom_display(portid_t port_id); +void port_module_eeprom_display(portid_t port_id, uint8_t hex_on); void port_summary_header_display(void); void rx_queue_infos_display(portid_t port_idi, uint16_t queue_id); void tx_queue_infos_display(portid_t port_idi, uint16_t queue_id); @@ -1039,6 +1041,15 @@ int eth_macaddr_get_print_err(uint16_t port_id, void show_macs(portid_t port_id); void show_mcast_macs(portid_t port_id); +/* SFF-8079 Optics diagnostics */ +extern void sff_8079_show_all(const uint8_t *id); + +/* SFF-8472 Optics diagnostics */ +extern void sff_8472_show_all(const uint8_t *id); + +/* SFF-8636 Optics diagnostics */ +extern void sff_8636_show_all(const uint8_t *id, uint32_t eeprom_len); + /* Functions to manage the set of filtered Multicast MAC addresses */ void mcast_addr_add(portid_t port_id, struct rte_ether_addr *mc_addr); void mcast_addr_remove(portid_t port_id, struct rte_ether_addr *mc_addr); diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst index 9cc248084f..ffcb87d03e 100644 --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst @@ -214,12 +214,19 @@ For example: nvgre vxlan-gpe -show port (module_eeprom|eeprom) +show port eeprom ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Display the EEPROM information of a port:: - testpmd> show port (port_id) (module_eeprom|eeprom) + testpmd> show port (port_id) eeprom + +show port module_eeprom (format|hex) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Display the module EEPROM with specific format or hex dump of a port:: + + testpmd> show port (port_id) module_eeprom (format|hex) show port rss reta ~~~~~~~~~~~~~~~~~~ -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH] app/testpmd: format dump information of module EEPROM 2022-02-15 10:18 [PATCH] app/testpmd: format dump information of module EEPROM Robin Zhang @ 2022-02-15 13:28 ` Ferruh Yigit 2022-02-15 15:07 ` Thomas Monjalon 2022-04-08 10:23 ` [PATCH v2] common/sff_module: add telemetry command to dump " Robin Zhang ` (3 subsequent siblings) 4 siblings, 1 reply; 77+ messages in thread From: Ferruh Yigit @ 2022-02-15 13:28 UTC (permalink / raw) To: Robin Zhang, dev, Qi Zhang Cc: xiaoyun.li, aman.deep.singh, yuying.zhang, junfeng.guo, stevex.yang, Thomas Monjalon, David Marchand On 2/15/2022 10:18 AM, Robin Zhang wrote: > This patch add a format specific information of different module eeprom. > The format support for SFP(Small Formfactor Pluggable)/SFP+ > /QSFP+(Quad Small Formfactor Pluggable)/QSFP28 modules based on > SFF(Small Form Factor) Committee specifications > SFF-8079/SFF-8472/SFF-8024/SFF-8636. > Hi Robin, First of all, can you please clarify the motivation of this patch? Why we are adding this eeprom parsing, and who will be user of this patch? And, just to confirm, this parses the eeprom module based on SFF spec, right? So it doesn't specific or depends any vendor. But still, this is too much SFF specific code in the testpmd, and it is not small amount of code. I am not comfortable to get this into testpmd unless there is a good reason. What do you think to have this as a sample application? > Signed-off-by: Robin Zhang <robinx.zhang@intel.com> > --- > app/test-pmd/cmdline.c | 74 +- > app/test-pmd/config.c | 24 +- > app/test-pmd/meson.build | 4 + > app/test-pmd/sff_8079.c | 376 ++++++++++ > app/test-pmd/sff_8472.c | 281 ++++++++ > app/test-pmd/sff_8636.c | 742 ++++++++++++++++++++ > app/test-pmd/sff_8636.h | 592 ++++++++++++++++ > app/test-pmd/sff_common.c | 296 ++++++++ > app/test-pmd/sff_common.h | 178 +++++ > app/test-pmd/testpmd.h | 13 +- > doc/guides/testpmd_app_ug/testpmd_funcs.rst | 11 +- > 11 files changed, 2575 insertions(+), 16 deletions(-) > create mode 100644 app/test-pmd/sff_8079.c > create mode 100644 app/test-pmd/sff_8472.c > create mode 100644 app/test-pmd/sff_8636.c > create mode 100644 app/test-pmd/sff_8636.h > create mode 100644 app/test-pmd/sff_common.c > create mode 100644 app/test-pmd/sff_common.h > <...> ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH] app/testpmd: format dump information of module EEPROM 2022-02-15 13:28 ` Ferruh Yigit @ 2022-02-15 15:07 ` Thomas Monjalon 2022-02-16 2:26 ` Zhang, RobinX 0 siblings, 1 reply; 77+ messages in thread From: Thomas Monjalon @ 2022-02-15 15:07 UTC (permalink / raw) To: Robin Zhang, dev, Qi Zhang, Ferruh Yigit Cc: xiaoyun.li, aman.deep.singh, yuying.zhang, junfeng.guo, stevex.yang, David Marchand 15/02/2022 14:28, Ferruh Yigit: > On 2/15/2022 10:18 AM, Robin Zhang wrote: > > This patch add a format specific information of different module eeprom. > > The format support for SFP(Small Formfactor Pluggable)/SFP+ > > /QSFP+(Quad Small Formfactor Pluggable)/QSFP28 modules based on > > SFF(Small Form Factor) Committee specifications > > SFF-8079/SFF-8472/SFF-8024/SFF-8636. > > > > Hi Robin, > > First of all, can you please clarify the motivation of this > patch? Why we are adding this eeprom parsing, and who will be > user of this patch? > > > And, just to confirm, this parses the eeprom module based on > SFF spec, right? So it doesn't specific or depends any vendor. > > But still, this is too much SFF specific code in the testpmd, > and it is not small amount of code. I am not comfortable to > get this into testpmd unless there is a good reason. Please remember that testpmd is supposed to be the application for testing ethdev API and drivers. It doesn't make sense to add code if it does not directly help with the goal above. > What do you think to have this as a sample application? It can be in the directory app/ maybe. ^ permalink raw reply [flat|nested] 77+ messages in thread
* RE: [PATCH] app/testpmd: format dump information of module EEPROM 2022-02-15 15:07 ` Thomas Monjalon @ 2022-02-16 2:26 ` Zhang, RobinX 2022-02-16 8:03 ` David Marchand 0 siblings, 1 reply; 77+ messages in thread From: Zhang, RobinX @ 2022-02-16 2:26 UTC (permalink / raw) To: Thomas Monjalon, dev, Zhang, Qi Z, Yigit, Ferruh Cc: Li, Xiaoyun, Singh, Aman Deep, Zhang, Yuying, Guo, Junfeng, Yang, SteveX, David Marchand Hi Ferruh, Thomas > -----Original Message----- > From: Thomas Monjalon <thomas@monjalon.net> > Sent: Tuesday, February 15, 2022 11:08 PM > To: Zhang, RobinX <robinx.zhang@intel.com>; dev@dpdk.org; Zhang, Qi Z > <qi.z.zhang@intel.com>; Yigit, Ferruh <ferruh.yigit@intel.com> > Cc: Li, Xiaoyun <xiaoyun.li@intel.com>; Singh, Aman Deep > <aman.deep.singh@intel.com>; Zhang, Yuying <yuying.zhang@intel.com>; > Guo, Junfeng <junfeng.guo@intel.com>; Yang, SteveX > <stevex.yang@intel.com>; David Marchand <david.marchand@redhat.com> > Subject: Re: [PATCH] app/testpmd: format dump information of module > EEPROM > > 15/02/2022 14:28, Ferruh Yigit: > > On 2/15/2022 10:18 AM, Robin Zhang wrote: > > > This patch add a format specific information of different module eeprom. > > > The format support for SFP(Small Formfactor Pluggable)/SFP+ > > > /QSFP+(Quad Small Formfactor Pluggable)/QSFP28 modules based on > > > SFF(Small Form Factor) Committee specifications > > > SFF-8079/SFF-8472/SFF-8024/SFF-8636. > > > > > > > Hi Robin, > > > > First of all, can you please clarify the motivation of this patch? Why > > we are adding this eeprom parsing, and who will be user of this patch? > > > > > > And, just to confirm, this parses the eeprom module based on SFF spec, > > right? So it doesn't specific or depends any vendor. > > > > But still, this is too much SFF specific code in the testpmd, and it > > is not small amount of code. I am not comfortable to get this into > > testpmd unless there is a good reason. > > Please remember that testpmd is supposed to be the application for testing > ethdev API and drivers. > It doesn't make sense to add code if it does not directly help with the goal > above. The idea behind this is to monitor the quality of the link in the field during testpmd operations. It is supported in Linux driver with ethtool command "ethtool -m xxx", but missing in DPDK. This feature is requested by customer 6WIND and we have been told this is highly important in production. 6WIND also mentioned some other customers: NEC, EOLO and Open Systems. Similar request also received from customer CheckPoint. > > > What do you think to have this as a sample application? > > It can be in the directory app/ maybe. > Base on the above background, I'm not sure if customer could accept this feature as a sample application. @Zhang, Qi Z, could you kindly please share your comments on this? Thanks. > ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH] app/testpmd: format dump information of module EEPROM 2022-02-16 2:26 ` Zhang, RobinX @ 2022-02-16 8:03 ` David Marchand 2022-02-16 8:45 ` Thomas Monjalon 0 siblings, 1 reply; 77+ messages in thread From: David Marchand @ 2022-02-16 8:03 UTC (permalink / raw) To: Zhang, RobinX, Yigit, Ferruh, Thomas Monjalon Cc: dev, Zhang, Qi Z, Li, Xiaoyun, Singh, Aman Deep, Zhang, Yuying, Guo, Junfeng, Yang, SteveX On Wed, Feb 16, 2022 at 3:27 AM Zhang, RobinX <robinx.zhang@intel.com> wrote: > The idea behind this is to monitor the quality of the link in the field during testpmd operations. > It is supported in Linux driver with ethtool command "ethtool -m xxx", but missing in DPDK. > > This feature is requested by customer 6WIND and we have been told this is highly important in production. > 6WIND also mentioned some other customers: NEC, EOLO and Open Systems. > Similar request also received from customer CheckPoint. > > > > > > What do you think to have this as a sample application? > > > > It can be in the directory app/ maybe. > > > > Base on the above background, I'm not sure if customer could accept this feature as a sample application. Rather than add this in testpmd or a sample app, does it make sense to provide this info as a telemetry command? This makes those status information available in any dpdk application. There is a "but" with this proposal. Existing applications might have been calling "eeprom" ethdev API already, and adding such a callback in telemetry could lead to concurrency issues. I see that we have other telemetry callbacks for stats, link status which might already have the issue. -- David Marchand ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH] app/testpmd: format dump information of module EEPROM 2022-02-16 8:03 ` David Marchand @ 2022-02-16 8:45 ` Thomas Monjalon 2022-02-16 9:30 ` Bruce Richardson 0 siblings, 1 reply; 77+ messages in thread From: Thomas Monjalon @ 2022-02-16 8:45 UTC (permalink / raw) To: Zhang, RobinX, Yigit, Ferruh Cc: dev, Zhang, Qi Z, Li, Xiaoyun, Singh, Aman Deep, Zhang, Yuying, Guo, Junfeng, Yang, SteveX, David Marchand, bruce.richardson, ciara.power 16/02/2022 09:03, David Marchand: > On Wed, Feb 16, 2022 at 3:27 AM Zhang, RobinX <robinx.zhang@intel.com> wrote: > > The idea behind this is to monitor the quality of the link in the field during testpmd operations. > > It is supported in Linux driver with ethtool command "ethtool -m xxx", but missing in DPDK. That's why the bifurcated model used by mlx drivers is so much valuable: you can use such ethtool command while using DPDK. > > This feature is requested by customer 6WIND and we have been told this is highly important in production. > > 6WIND also mentioned some other customers: NEC, EOLO and Open Systems. > > Similar request also received from customer CheckPoint. > > > > > > What do you think to have this as a sample application? > > > > > > It can be in the directory app/ maybe. > > > > Base on the above background, I'm not sure if customer could accept this feature as a sample application. > > Rather than add this in testpmd or a sample app, does it make sense to > provide this info as a telemetry command? > This makes those status information available in any dpdk application. +1 Production code should be in a DPDK library. > There is a "but" with this proposal. > Existing applications might have been calling "eeprom" ethdev API > already, and adding such a callback in telemetry could lead to > concurrency issues. > > I see that we have other telemetry callbacks for stats, link status > which might already have the issue. You mean there is no lock protection? Neither in the API, nor in telemetry? ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH] app/testpmd: format dump information of module EEPROM 2022-02-16 8:45 ` Thomas Monjalon @ 2022-02-16 9:30 ` Bruce Richardson 2022-02-16 9:41 ` David Marchand 0 siblings, 1 reply; 77+ messages in thread From: Bruce Richardson @ 2022-02-16 9:30 UTC (permalink / raw) To: Thomas Monjalon Cc: Zhang, RobinX, Yigit, Ferruh, dev, Zhang, Qi Z, Li, Xiaoyun, Singh, Aman Deep, Zhang, Yuying, Guo, Junfeng, Yang, SteveX, David Marchand, ciara.power On Wed, Feb 16, 2022 at 09:45:33AM +0100, Thomas Monjalon wrote: > 16/02/2022 09:03, David Marchand: > > On Wed, Feb 16, 2022 at 3:27 AM Zhang, RobinX <robinx.zhang@intel.com> wrote: > > > The idea behind this is to monitor the quality of the link in the field during testpmd operations. > > > It is supported in Linux driver with ethtool command "ethtool -m xxx", but missing in DPDK. > > That's why the bifurcated model used by mlx drivers is so much valuable: > you can use such ethtool command while using DPDK. > > > > This feature is requested by customer 6WIND and we have been told this is highly important in production. > > > 6WIND also mentioned some other customers: NEC, EOLO and Open Systems. > > > Similar request also received from customer CheckPoint. > > > > > > > > What do you think to have this as a sample application? > > > > > > > > It can be in the directory app/ maybe. > > > > > > Base on the above background, I'm not sure if customer could accept this feature as a sample application. > > > > Rather than add this in testpmd or a sample app, does it make sense to > > provide this info as a telemetry command? > > This makes those status information available in any dpdk application. > > +1 > Production code should be in a DPDK library. > > > There is a "but" with this proposal. > > Existing applications might have been calling "eeprom" ethdev API > > already, and adding such a callback in telemetry could lead to > > concurrency issues. > > > > I see that we have other telemetry callbacks for stats, link status > > which might already have the issue. > > You mean there is no lock protection? > Neither in the API, nor in telemetry? > For reporting out stats or link status, I'm not sure a lock should ever be needed since both are just read-only operations. Therefore, I don't believe we have a general issue here. /Bruce ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH] app/testpmd: format dump information of module EEPROM 2022-02-16 9:30 ` Bruce Richardson @ 2022-02-16 9:41 ` David Marchand 2022-02-16 10:02 ` Bruce Richardson 0 siblings, 1 reply; 77+ messages in thread From: David Marchand @ 2022-02-16 9:41 UTC (permalink / raw) To: Bruce Richardson Cc: Thomas Monjalon, Zhang, RobinX, Yigit, Ferruh, dev, Zhang, Qi Z, Li, Xiaoyun, Singh, Aman Deep, Zhang, Yuying, Guo, Junfeng, Yang, SteveX, Ciara Power On Wed, Feb 16, 2022 at 10:31 AM Bruce Richardson <bruce.richardson@intel.com> wrote: > > > I see that we have other telemetry callbacks for stats, link status > > > which might already have the issue. > > > > You mean there is no lock protection? > > Neither in the API, nor in telemetry? > > > For reporting out stats or link status, I'm not sure a lock should ever be > needed since both are just read-only operations. Therefore, I don't believe > we have a general issue here. Ok, if you are sure about this for all drivers for stats and link status, you can discard my comment. -- David Marchand ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH] app/testpmd: format dump information of module EEPROM 2022-02-16 9:41 ` David Marchand @ 2022-02-16 10:02 ` Bruce Richardson 2022-02-16 10:15 ` David Marchand 0 siblings, 1 reply; 77+ messages in thread From: Bruce Richardson @ 2022-02-16 10:02 UTC (permalink / raw) To: David Marchand Cc: Thomas Monjalon, Zhang, RobinX, Yigit, Ferruh, dev, Zhang, Qi Z, Li, Xiaoyun, Singh, Aman Deep, Zhang, Yuying, Guo, Junfeng, Yang, SteveX, Ciara Power On Wed, Feb 16, 2022 at 10:41:43AM +0100, David Marchand wrote: > On Wed, Feb 16, 2022 at 10:31 AM Bruce Richardson > <bruce.richardson@intel.com> wrote: > > > > I see that we have other telemetry callbacks for stats, link status > > > > which might already have the issue. > > > > > > You mean there is no lock protection? Neither in the API, nor in > > > telemetry? > > > > > For reporting out stats or link status, I'm not sure a lock should ever > > be needed since both are just read-only operations. Therefore, I don't > > believe we have a general issue here. > > Ok, if you are sure about this for all drivers for stats and link status, > you can discard my comment. > No, I'm not 100% sure about it, but if any driver has issues with multiple threads reading stats simultaneously I would hope that that should be resolved at the driver level. Normally, one would expect read-only operations to be implicitly multi-thread safe, and I also see that the documentation on e.g. rte_eth_stats_get() makes no reference to needing locks or not being thread-safe. I note too, that any such issues would not be limited to telemetry only, but would also apply to pdump or any mechanism we would want to have for reading information about a running process. /Bruce ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH] app/testpmd: format dump information of module EEPROM 2022-02-16 10:02 ` Bruce Richardson @ 2022-02-16 10:15 ` David Marchand 0 siblings, 0 replies; 77+ messages in thread From: David Marchand @ 2022-02-16 10:15 UTC (permalink / raw) To: Bruce Richardson Cc: Thomas Monjalon, Zhang, RobinX, Yigit, Ferruh, dev, Zhang, Qi Z, Li, Xiaoyun, Singh, Aman Deep, Zhang, Yuying, Guo, Junfeng, Yang, SteveX, Ciara Power On Wed, Feb 16, 2022 at 11:02 AM Bruce Richardson <bruce.richardson@intel.com> wrote: > On Wed, Feb 16, 2022 at 10:41:43AM +0100, David Marchand wrote: > > On Wed, Feb 16, 2022 at 10:31 AM Bruce Richardson > > <bruce.richardson@intel.com> wrote: > > > > > I see that we have other telemetry callbacks for stats, link status > > > > > which might already have the issue. > > > > > > > > You mean there is no lock protection? Neither in the API, nor in > > > > telemetry? > > > > > > > For reporting out stats or link status, I'm not sure a lock should ever > > > be needed since both are just read-only operations. Therefore, I don't > > > believe we have a general issue here. > > > > Ok, if you are sure about this for all drivers for stats and link status, > > you can discard my comment. > > > No, I'm not 100% sure about it, but if any driver has issues with multiple > threads reading stats simultaneously I would hope that that should be > resolved at the driver level. Normally, one would expect read-only > operations to be implicitly multi-thread safe, and I also see that the > documentation on e.g. rte_eth_stats_get() makes no reference to needing > locks or not being thread-safe. I agree, resolving at the driver level is better. -- David Marchand ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v2] common/sff_module: add telemetry command to dump module EEPROM 2022-02-15 10:18 [PATCH] app/testpmd: format dump information of module EEPROM Robin Zhang 2022-02-15 13:28 ` Ferruh Yigit @ 2022-04-08 10:23 ` Robin Zhang 2022-04-08 10:33 ` Bruce Richardson 2022-04-20 7:00 ` [PATCH v3 0/5] add telemetry command for show " Robin Zhang ` (2 subsequent siblings) 4 siblings, 1 reply; 77+ messages in thread From: Robin Zhang @ 2022-04-08 10:23 UTC (permalink / raw) To: dev; +Cc: qiming.yang, qi.z.zhang, stevex.yang, Robin Zhang This patch introduce a new telemetry command '/sff_module/info' to dump format module EEPROM information. The format support for SFP(Small Formfactor Pluggable)/SFP+ /QSFP+(Quad Small Formfactor Pluggable)/QSFP28 modules based on SFF(Small Form Factor) Committee specifications SFF-8079/SFF-8472/SFF-8024/SFF-8636. Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- v2: - Redesign the dump function as a telemetry command, so that the EEPROM information can be used by other app. - The usage like this: Launch the primary application with telemetry: Take testpmd as example: ./app/dpdk-testpmd Then launch the telemetry client script: ./usertools/dpdk-telemetry.py In telemetry client run command: --> /sff_module/info,<port number> Both primary application and telemetry client will show the formated module EEPROM information. drivers/common/meson.build | 1 + drivers/common/sff_module/meson.build | 16 + drivers/common/sff_module/sff_8079.c | 672 ++++++++++++++ drivers/common/sff_module/sff_8472.c | 301 ++++++ drivers/common/sff_module/sff_8636.c | 1004 +++++++++++++++++++++ drivers/common/sff_module/sff_8636.h | 592 ++++++++++++ drivers/common/sff_module/sff_common.c | 415 +++++++++ drivers/common/sff_module/sff_common.h | 192 ++++ drivers/common/sff_module/sff_telemetry.c | 142 +++ drivers/common/sff_module/sff_telemetry.h | 41 + drivers/common/sff_module/version.map | 9 + 11 files changed, 3385 insertions(+) create mode 100644 drivers/common/sff_module/meson.build create mode 100644 drivers/common/sff_module/sff_8079.c create mode 100644 drivers/common/sff_module/sff_8472.c create mode 100644 drivers/common/sff_module/sff_8636.c create mode 100644 drivers/common/sff_module/sff_8636.h create mode 100644 drivers/common/sff_module/sff_common.c create mode 100644 drivers/common/sff_module/sff_common.h create mode 100644 drivers/common/sff_module/sff_telemetry.c create mode 100644 drivers/common/sff_module/sff_telemetry.h create mode 100644 drivers/common/sff_module/version.map diff --git a/drivers/common/meson.build b/drivers/common/meson.build index ea261dd70a..7b183769ca 100644 --- a/drivers/common/meson.build +++ b/drivers/common/meson.build @@ -8,4 +8,5 @@ drivers = [ 'iavf', 'mvep', 'octeontx', + 'sff_module', ] diff --git a/drivers/common/sff_module/meson.build b/drivers/common/sff_module/meson.build new file mode 100644 index 0000000000..1160b07ba2 --- /dev/null +++ b/drivers/common/sff_module/meson.build @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2019-2021 Intel Corporation + +sources = files( + 'sff_common.c', + 'sff_8079.c', + 'sff_8472.c', + 'sff_8636.c', + 'sff_telemetry.c' +) + +deps += ['ethdev'] + +if cc.has_argument('-Wno-pointer-to-int-cast') + cflags += '-Wno-pointer-to-int-cast' +endif \ No newline at end of file diff --git a/drivers/common/sff_module/sff_8079.c b/drivers/common/sff_module/sff_8079.c new file mode 100644 index 0000000000..173cb0493e --- /dev/null +++ b/drivers/common/sff_module/sff_8079.c @@ -0,0 +1,672 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2022 Intel Corporation + * + * Implements SFF-8079 optics diagnostics. + * + */ + +#include <stdio.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "sff_telemetry.h" + +static void sff_8079_show_identifier(const uint8_t *id, sff_item *items) +{ + sff_8024_show_identifier(id, 0, items); +} + +static void sff_8079_show_ext_identifier(const uint8_t *id, sff_item *items) +{ + char val_string[TMP_STRING_SIZE]; + + printf("%-41s : 0x%02x", "Extended identifier", id[1]); + sprintf(val_string, "0x%02x", id[1]); + if (id[1] == 0x00) { + printf(" (GBIC not specified / not MOD_DEF compliant)\n"); + strcat(val_string, " (GBIC not specified / not MOD_DEF compliant)"); + } else if (id[1] == 0x04) { + printf(" (GBIC/SFP defined by 2-wire interface ID)\n"); + strcat(val_string, " (GBIC/SFP defined by 2-wire interface ID)"); + } else if (id[1] <= 0x07) { + printf(" (GBIC compliant with MOD_DEF %u)\n", id[1]); + char *tmp; + sprintf(tmp, " (GBIC compliant with MOD_DEF %u)", id[1]); + strcat(val_string, tmp); + } else { + printf(" (unknown)\n"); + strcat(val_string, " (unknown)"); + } + add_item_string(items, "Extended identifier", val_string); +} + +static void sff_8079_show_connector(const uint8_t *id, sff_item *items) +{ + sff_8024_show_connector(id, 2, items); +} + +static void sff_8079_show_transceiver(const uint8_t *id, sff_item *items) +{ + static const char *pfx = + "Transceiver type :"; + char val_string[TMP_STRING_SIZE]; + + printf("%-41s : 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", + "Transceiver codes", + id[3], id[4], id[5], id[6], + id[7], id[8], id[9], id[10], id[36]); + sprintf(val_string, + "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + id[3], id[4], id[5], id[6], id[7], id[8], id[9], id[10], id[36]); + add_item_string(items, "Transceiver codes", val_string); + + /* 10G Ethernet Compliance Codes */ + if (id[3] & (1 << 7)) { + printf("%s 10G Ethernet: 10G Base-ER [SFF-8472 rev10.4 onwards]\n", pfx); + add_item_string(items, "10G Ethernet transceiver type", + "10G Ethernet: 10G Base-ER [SFF-8472 rev10.4 onwards]"); + } + if (id[3] & (1 << 6)) { + printf("%s 10G Ethernet: 10G Base-LRM\n", pfx); + add_item_string(items, "Transceiver type", + "10G Ethernet: 10G Base-LRM"); + } + if (id[3] & (1 << 5)) { + printf("%s 10G Ethernet: 10G Base-LR\n", pfx); + add_item_string(items, "Transceiver type", + "10G Ethernet: 10G Base-LR"); + } + if (id[3] & (1 << 4)) { + printf("%s 10G Ethernet: 10G Base-SR\n", pfx); + add_item_string(items, "Transceiver type", + "10G Ethernet: 10G Base-SR"); + } + + /* Infiniband Compliance Codes */ + if (id[3] & (1 << 3)) { + printf("%s Infiniband: 1X SX\n", pfx); + add_item_string(items, "Transceiver type", + "Infiniband: 1X SX"); + } + if (id[3] & (1 << 2)) { + printf("%s Infiniband: 1X LX\n", pfx); + add_item_string(items, "Transceiver type", + "Infiniband: 1X LX"); + } + if (id[3] & (1 << 1)) { + printf("%s Infiniband: 1X Copper Active\n", pfx); + add_item_string(items, "Transceiver type", + "Infiniband: 1X Copper Active"); + } + if (id[3] & (1 << 0)) { + printf("%s Infiniband: 1X Copper Passive\n", pfx); + add_item_string(items, "Transceiver type", + "Infiniband: 1X Copper Passive"); + } + + /* ESCON Compliance Codes */ + if (id[4] & (1 << 7)) { + printf("%s ESCON: ESCON MMF, 1310nm LED\n", pfx); + add_item_string(items, "Transceiver type", + "ESCON: ESCON MMF, 1310nm LED"); + } + if (id[4] & (1 << 6)) { + printf("%s ESCON: ESCON SMF, 1310nm Laser\n", pfx); + add_item_string(items, "Transceiver type", + "ESCON: ESCON SMF, 1310nm Laser"); + } + + /* SONET Compliance Codes */ + if (id[4] & (1 << 5)) { + printf("%s SONET: OC-192, short reach\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: OC-192, short reach"); + } + if (id[4] & (1 << 4)) { + printf("%s SONET: SONET reach specifier bit 1\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: SONET reach specifier bit 1"); + } + if (id[4] & (1 << 3)) { + printf("%s SONET: SONET reach specifier bit 2\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: SONET reach specifier bit 2"); + } + if (id[4] & (1 << 2)) { + printf("%s SONET: OC-48, long reach\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: OC-48, long reach"); + } + if (id[4] & (1 << 1)) { + printf("%s SONET: OC-48, intermediate reach\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: OC-48, intermediate reach"); + } + if (id[4] & (1 << 0)) { + printf("%s SONET: OC-48, short reach\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: OC-48, short reach"); + } + if (id[5] & (1 << 6)) { + printf("%s SONET: OC-12, single mode, long reach\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: OC-12, single mode, long reach"); + } + if (id[5] & (1 << 5)) { + printf("%s SONET: OC-12, single mode, inter. reach\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: OC-12, single mode, inter. reach"); + } + if (id[5] & (1 << 4)) { + printf("%s SONET: OC-12, short reach\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: OC-12, short reach"); + } + if (id[5] & (1 << 2)) { + printf("%s SONET: OC-3, single mode, long reach\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: OC-3, single mode, long reach"); + } + if (id[5] & (1 << 1)) { + printf("%s SONET: OC-3, single mode, inter. reach\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: OC-3, single mode, inter. reach"); + } + if (id[5] & (1 << 0)) { + printf("%s SONET: OC-3, short reach\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: OC-3, short reach"); + } + + /* Ethernet Compliance Codes */ + if (id[6] & (1 << 7)) { + printf("%s Ethernet: BASE-PX\n", pfx); + add_item_string(items, "Transceiver type", + "Ethernet: BASE-PX"); + } + if (id[6] & (1 << 6)) { + printf("%s Ethernet: BASE-BX10\n", pfx); + add_item_string(items, "Transceiver type", + "Ethernet: BASE-BX10"); + } + if (id[6] & (1 << 5)) { + printf("%s Ethernet: 100BASE-FX\n", pfx); + add_item_string(items, "Transceiver type", + "Ethernet: 100BASE-FX"); + } + if (id[6] & (1 << 4)) { + printf("%s Ethernet: 100BASE-LX/LX10\n", pfx); + add_item_string(items, "Transceiver type", + "Ethernet: 100BASE-LX/LX10"); + } + if (id[6] & (1 << 3)) { + printf("%s Ethernet: 1000BASE-T\n", pfx); + add_item_string(items, "Transceiver type", + "Ethernet: 1000BASE-T"); + } + if (id[6] & (1 << 2)) { + printf("%s Ethernet: 1000BASE-CX\n", pfx); + add_item_string(items, "Transceiver type", + "Ethernet: 1000BASE-CX"); + } + if (id[6] & (1 << 1)) { + printf("%s Ethernet: 1000BASE-LX\n", pfx); + add_item_string(items, "Transceiver type", + "Ethernet: 1000BASE-LX"); + } + if (id[6] & (1 << 0)) { + printf("%s Ethernet: 1000BASE-SX\n", pfx); + add_item_string(items, "Transceiver type", + "Ethernet: 1000BASE-SX"); + } + + /* Fibre Channel link length */ + if (id[7] & (1 << 7)) { + printf("%s FC: very long distance (V)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: very long distance (V)"); + } + if (id[7] & (1 << 6)) { + printf("%s FC: short distance (S)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: short distance (S)"); + } + if (id[7] & (1 << 5)) { + printf("%s FC: intermediate distance (I)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: intermediate distance (I)"); + } + if (id[7] & (1 << 4)) { + printf("%s FC: long distance (L)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: long distance (L)"); + } + if (id[7] & (1 << 3)) { + printf("%s FC: medium distance (M)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: medium distance (M)"); + } + + /* Fibre Channel transmitter technology */ + if (id[7] & (1 << 2)) { + printf("%s FC: Shortwave laser, linear Rx (SA)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Shortwave laser, linear Rx (SA)"); + } + if (id[7] & (1 << 1)) { + printf("%s FC: Longwave laser (LC)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Longwave laser (LC)"); + } + if (id[7] & (1 << 0)) { + printf("%s FC: Electrical inter-enclosure (EL)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Electrical inter-enclosure (EL)"); + } + if (id[8] & (1 << 7)) { + printf("%s FC: Electrical intra-enclosure (EL)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Electrical intra-enclosure (EL)"); + } + if (id[8] & (1 << 6)) { + printf("%s FC: Shortwave laser w/o OFC (SN)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Shortwave laser w/o OFC (SN)"); + } + if (id[8] & (1 << 5)) { + printf("%s FC: Shortwave laser with OFC (SL)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Shortwave laser with OFC (SL)"); + } + if (id[8] & (1 << 4)) { + printf("%s FC: Longwave laser (LL)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Longwave laser (LL)"); + } + if (id[8] & (1 << 3)) { + printf("%s Active Cable\n", pfx); + add_item_string(items, "Transceiver type", + "Active Cable"); + } + if (id[8] & (1 << 2)) { + printf("%s Passive Cable\n", pfx); + add_item_string(items, "Transceiver type", + "Passive Cable"); + } + if (id[8] & (1 << 1)) { + printf("%s FC: Copper FC-BaseT\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Copper FC-BaseT"); + } + + /* Fibre Channel transmission media */ + if (id[9] & (1 << 7)) { + printf("%s FC: Twin Axial Pair (TW)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Twin Axial Pair (TW)"); + } + if (id[9] & (1 << 6)) { + printf("%s FC: Twisted Pair (TP)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Twisted Pair (TP)"); + } + if (id[9] & (1 << 5)) { + printf("%s FC: Miniature Coax (MI)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Miniature Coax (MI)"); + } + if (id[9] & (1 << 4)) { + printf("%s FC: Video Coax (TV)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Video Coax (TV)"); + } + if (id[9] & (1 << 3)) { + printf("%s FC: Multimode, 62.5um (M6)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Multimode, 62.5um (M6)"); + } + if (id[9] & (1 << 2)) { + printf("%s FC: Multimode, 50um (M5)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Multimode, 50um (M5)"); + } + if (id[9] & (1 << 0)) { + printf("%s FC: Single Mode (SM)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Single Mode (SM)"); + } + + /* Fibre Channel speed */ + if (id[10] & (1 << 7)) { + printf("%s FC: 1200 MBytes/sec\n", pfx); + add_item_string(items, "Transceiver type", + "FC: 1200 MBytes/sec"); + } + if (id[10] & (1 << 6)) { + printf("%s FC: 800 MBytes/sec\n", pfx); + add_item_string(items, "Transceiver type", + "FC: 800 MBytes/sec"); + } + if (id[10] & (1 << 4)) { + printf("%s FC: 400 MBytes/sec\n", pfx); + add_item_string(items, "Transceiver type", + "FC: 400 MBytes/sec"); + } + if (id[10] & (1 << 2)) { + printf("%s FC: 200 MBytes/sec\n", pfx); + add_item_string(items, "Transceiver type", + "FC: 200 MBytes/sec"); + } + if (id[10] & (1 << 0)) { + printf("%s FC: 100 MBytes/sec\n", pfx); + add_item_string(items, "Transceiver type", + "FC: 100 MBytes/sec"); + } + + /* Extended Specification Compliance Codes from SFF-8024 */ + switch (id[36]) { + case 0x1: + printf("%s Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)\n", + pfx); + add_item_string(items, "Transceiver type", + "Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)"); + break; + case 0x2: + printf("%s Extended: 100G Base-SR4 or 25GBase-SR\n", pfx); + add_item_string(items, "Transceiver type", + "Extended: 100G Base-SR4 or 25GBase-SR"); + break; + case 0x3: + printf("%s Extended: 100G Base-LR4 or 25GBase-LR\n", pfx); + add_item_string(items, "Transceiver type", + "Extended: 100G Base-LR4 or 25GBase-LR"); + break; + case 0x4: + printf("%s Extended: 100G Base-ER4 or 25GBase-ER\n", pfx); + add_item_string(items, "Transceiver type", + "Extended: 100G Base-ER4 or 25GBase-ER"); + break; + case 0x8: + printf("%s Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)\n", + pfx); + add_item_string(items, "Transceiver type", + "Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)"); + break; + case 0xb: + printf("%s Extended: 100G Base-CR4 or 25G Base-CR CA-L\n", pfx); + add_item_string(items, "Transceiver type", + "Extended: 100G Base-CR4 or 25G Base-CR CA-L"); + break; + case 0xc: + printf("%s Extended: 25G Base-CR CA-S\n", pfx); + add_item_string(items, "Transceiver type", + "Extended: 25G Base-CR CA-S"); + break; + case 0xd: + printf("%s Extended: 25G Base-CR CA-N\n", pfx); + add_item_string(items, "Transceiver type", + "Extended: 25G Base-CR CA-N"); + break; + case 0x16: + printf("%s Extended: 10Gbase-T with SFI electrical interface\n", pfx); + add_item_string(items, "Transceiver type", + "Extended: 10Gbase-T with SFI electrical interface"); + break; + case 0x18: + printf("%s Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)\n", + pfx); + add_item_string(items, "Transceiver type", + "Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)"); + break; + case 0x19: + printf("%s Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)\n", + pfx); + add_item_string(items, "Transceiver type", + "Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)"); + break; + case 0x1c: + printf("%s Extended: 10Gbase-T Short Reach\n", pfx); + add_item_string(items, "Transceiver type", + "Extended: 10Gbase-T Short Reach"); + break; + default: + break; + } +} + +static void sff_8079_show_encoding(const uint8_t *id, sff_item *items) +{ + sff_8024_show_encoding(id, 11, RTE_ETH_MODULE_SFF_8472, items); +} + +static void sff_8079_show_rate_identifier(const uint8_t *id, sff_item *items) +{ + char val_string[TMP_STRING_SIZE]; + + printf("%-41s : 0x%02x", "Rate identifier", id[13]); + sprintf(val_string, "0x%02x", id[13]); + + switch (id[13]) { + case 0x00: + printf(" (unspecified)\n"); + strcat(val_string, " (unspecified)"); + break; + case 0x01: + printf(" (4/2/1G Rate_Select & AS0/AS1)\n"); + strcat(val_string, " (4/2/1G Rate_Select & AS0/AS1)"); + break; + case 0x02: + printf(" (8/4/2G Rx Rate_Select only)\n"); + strcat(val_string, " (8/4/2G Rx Rate_Select only)"); + break; + case 0x03: + printf(" (8/4/2G Independent Rx & Tx Rate_Select)\n"); + strcat(val_string, " (8/4/2G Independent Rx & Tx Rate_Select)"); + break; + case 0x04: + printf(" (8/4/2G Tx Rate_Select only)\n"); + strcat(val_string, " (8/4/2G Tx Rate_Select only)"); + break; + default: + printf(" (reserved or unknown)\n"); + strcat(val_string, " (reserved or unknown)"); + break; + } + add_item_string(items, "Rate identifier", val_string); +} + +static void sff_8079_show_oui(const uint8_t *id, sff_item *items) +{ + sff_8024_show_oui(id, 37, items); +} + +static void +sff_8079_show_wavelength_or_copper_compliance(const uint8_t *id, + sff_item *items) +{ + char val_string[TMP_STRING_SIZE]; + + if (id[8] & (1 << 2)) { + printf("%-41s : 0x%02x", "Passive Cu cmplnce.", id[60]); + sprintf(val_string, "0x%02x", id[60]); + switch (id[60]) { + case 0x00: + printf(" (unspecified)"); + strcat(val_string, " (unspecified)"); + break; + case 0x01: + printf(" (SFF-8431 appendix E)"); + strcat(val_string, " (SFF-8431 appendix E)"); + break; + default: + printf(" (unknown)"); + strcat(val_string, " (unknown)"); + break; + } + printf(" [SFF-8472 rev10.4 only]\n"); + strcat(val_string, " [SFF-8472 rev10.4 only]"); + add_item_string(items, "Passive Cu cmplnce.", val_string); + } else if (id[8] & (1 << 3)) { + printf("%-41s : 0x%02x", "Active Cu cmplnce.", id[60]); + sprintf(val_string, "0x%02x", id[60]); + switch (id[60]) { + case 0x00: + printf(" (unspecified)"); + strcat(val_string, " (unspecified)"); + break; + case 0x01: + printf(" (SFF-8431 appendix E)"); + strcat(val_string, " (SFF-8431 appendix E)"); + break; + case 0x04: + printf(" (SFF-8431 limiting)"); + strcat(val_string, " (SFF-8431 limiting)"); + break; + default: + printf(" (unknown)"); + strcat(val_string, " (unknown)"); + break; + } + printf(" [SFF-8472 rev10.4 only]\n"); + strcat(val_string, " [SFF-8472 rev10.4 only]"); + add_item_string(items, "Active Cu cmplnce.", val_string); + } else { + printf("%-41s : %unm\n", "Laser wavelength", + (id[60] << 8) | id[61]); + sprintf(val_string, "%unm", (id[60] << 8) | id[61]); + add_item_string(items, "Laser wavelength", val_string); + } +} + +static void sff_8079_show_options(const uint8_t *id, sff_item *items) +{ + static const char *pfx = + "Option :"; + char val_string[TMP_STRING_SIZE]; + + printf("%-41s : 0x%02x 0x%02x\n", "Option values", id[64], id[65]); + sprintf(val_string, "0x%02x 0x%02x", id[64], id[65]); + add_item_string(items, "Option values", val_string); + + if (id[65] & (1 << 1)) { + printf("%s RX_LOS implemented\n", pfx); + add_item_string(items, "Option", + "RX_LOS implemented"); + } + if (id[65] & (1 << 2)) { + printf("%s RX_LOS implemented, inverted\n", pfx); + add_item_string(items, "Option", + "RX_LOS implemented, inverted"); + } + if (id[65] & (1 << 3)) { + printf("%s TX_FAULT implemented\n", pfx); + add_item_string(items, "Option", + "TX_FAULT implemented"); + } + if (id[65] & (1 << 4)) { + printf("%s TX_DISABLE implemented\n", pfx); + add_item_string(items, "Option", + "TX_DISABLE implemented"); + } + if (id[65] & (1 << 5)) { + printf("%s RATE_SELECT implemented\n", pfx); + add_item_string(items, "Option", + "RATE_SELECT implemented"); + } + if (id[65] & (1 << 6)) { + printf("%s Tunable transmitter technology\n", pfx); + add_item_string(items, "Option", + "Tunable transmitter technology"); + } + if (id[65] & (1 << 7)) { + printf("%s Receiver decision threshold implemented\n", pfx); + add_item_string(items, "Option", + "Receiver decision threshold implemented"); + } + if (id[64] & (1 << 0)) { + printf("%s Linear receiver output implemented\n", pfx); + add_item_string(items, "Option", + "Linear receiver output implemented"); + } + if (id[64] & (1 << 1)) { + printf("%s Power level 2 requirement\n", pfx); + add_item_string(items, "Option", + "Power level 2 requirement"); + } + if (id[64] & (1 << 2)) { + printf("%s Cooled transceiver implemented\n", pfx); + add_item_string(items, "Option", + "Cooled transceiver implemented"); + } + if (id[64] & (1 << 3)) { + printf("%s Retimer or CDR implemented\n", pfx); + add_item_string(items, "Option", + "Retimer or CDR implemented"); + } + if (id[64] & (1 << 4)) { + printf("%s Paging implemented\n", pfx); + add_item_string(items, "Option", + "Paging implemented"); + } + if (id[64] & (1 << 5)) { + printf("%s Power level 3 requirement\n", pfx); + add_item_string(items, "Option", + "Power level 3 requirement"); + } +} + +void sff_8079_show_all(const uint8_t *id, sff_item *items) +{ + sff_8079_show_identifier(id, items); + if (((id[0] == 0x02) || (id[0] == 0x03)) && (id[1] == 0x04)) { + unsigned int br_nom, br_min, br_max; + char val_string[TMP_STRING_SIZE]; + + if (id[12] == 0) { + br_nom = br_min = br_max = 0; + } else if (id[12] == 255) { + br_nom = id[66] * 250; + br_max = id[67]; + br_min = id[67]; + } else { + br_nom = id[12] * 100; + br_max = id[66]; + br_min = id[67]; + } + sff_8079_show_ext_identifier(id, items); + sff_8079_show_connector(id, items); + sff_8079_show_transceiver(id, items); + sff_8079_show_encoding(id, items); + + printf("%-41s : %u%s\n", "BR, Nominal", br_nom, "MBd"); + sprintf(val_string, "%uMBd", br_nom); + add_item_string(items, "BR, Nominal", val_string); + + sff_8079_show_rate_identifier(id, items); + sff_show_value_with_unit(id, 14, + "Length (SMF,km)", 1, "km", items); + sff_show_value_with_unit(id, 15, "Length (SMF)", 100, "m", items); + sff_show_value_with_unit(id, 16, "Length (50um)", 10, "m", items); + sff_show_value_with_unit(id, 17, + "Length (62.5um)", 10, "m", items); + sff_show_value_with_unit(id, 18, "Length (Copper)", 1, "m", items); + sff_show_value_with_unit(id, 19, "Length (OM3)", 10, "m", items); + sff_8079_show_wavelength_or_copper_compliance(id, items); + sff_show_ascii(id, 20, 35, "Vendor name", items); + sff_8079_show_oui(id, items); + sff_show_ascii(id, 40, 55, "Vendor PN", items); + sff_show_ascii(id, 56, 59, "Vendor rev", items); + sff_8079_show_options(id, items); + + printf("%-41s : %u%s\n", "BR margin, max", br_max, "%"); + sprintf(val_string, "%u%%", br_max); + add_item_string(items, "BR margin, max", val_string); + printf("%-41s : %u%s\n", "BR margin, min", br_min, "%"); + sprintf(val_string, "%u%%", br_min); + add_item_string(items, "BR margin, min", val_string); + + sff_show_ascii(id, 68, 83, "Vendor SN", items); + sff_show_ascii(id, 84, 91, "Date code", items); + } +} diff --git a/drivers/common/sff_module/sff_8472.c b/drivers/common/sff_module/sff_8472.c new file mode 100644 index 0000000000..6111b25e12 --- /dev/null +++ b/drivers/common/sff_module/sff_8472.c @@ -0,0 +1,301 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2022 Intel Corporation + * + * Implements SFF-8472 optics diagnostics. + * + */ + +#include <stdio.h> +#include <math.h> +#include <arpa/inet.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "sff_telemetry.h" + +/* Offsets in decimal, for direct comparison with the SFF specs */ + +/* A0-based EEPROM offsets for DOM support checks */ +#define SFF_A0_DOM 92 +#define SFF_A0_OPTIONS 93 +#define SFF_A0_COMP 94 + +/* EEPROM bit values for various registers */ +#define SFF_A0_DOM_EXTCAL (1 << 4) +#define SFF_A0_DOM_INTCAL (1 << 5) +#define SFF_A0_DOM_IMPL (1 << 6) +#define SFF_A0_DOM_PWRT (1 << 3) + +#define SFF_A0_OPTIONS_AW (1 << 7) + +/* + * This is the offset at which the A2 page is in the EEPROM + * blob returned by the kernel. + */ +#define SFF_A2_BASE 0x100 + +/* A2-based offsets for DOM */ +#define SFF_A2_TEMP 96 +#define SFF_A2_TEMP_HALRM 0 +#define SFF_A2_TEMP_LALRM 2 +#define SFF_A2_TEMP_HWARN 4 +#define SFF_A2_TEMP_LWARN 6 + +#define SFF_A2_VCC 98 +#define SFF_A2_VCC_HALRM 8 +#define SFF_A2_VCC_LALRM 10 +#define SFF_A2_VCC_HWARN 12 +#define SFF_A2_VCC_LWARN 14 + +#define SFF_A2_BIAS 100 +#define SFF_A2_BIAS_HALRM 16 +#define SFF_A2_BIAS_LALRM 18 +#define SFF_A2_BIAS_HWARN 20 +#define SFF_A2_BIAS_LWARN 22 + +#define SFF_A2_TX_PWR 102 +#define SFF_A2_TX_PWR_HALRM 24 +#define SFF_A2_TX_PWR_LALRM 26 +#define SFF_A2_TX_PWR_HWARN 28 +#define SFF_A2_TX_PWR_LWARN 30 + +#define SFF_A2_RX_PWR 104 +#define SFF_A2_RX_PWR_HALRM 32 +#define SFF_A2_RX_PWR_LALRM 34 +#define SFF_A2_RX_PWR_HWARN 36 +#define SFF_A2_RX_PWR_LWARN 38 + +#define SFF_A2_ALRM_FLG 112 +#define SFF_A2_WARN_FLG 116 + +/* 32-bit little-endian calibration constants */ +#define SFF_A2_CAL_RXPWR4 56 +#define SFF_A2_CAL_RXPWR3 60 +#define SFF_A2_CAL_RXPWR2 64 +#define SFF_A2_CAL_RXPWR1 68 +#define SFF_A2_CAL_RXPWR0 72 + +/* 16-bit little endian calibration constants */ +#define SFF_A2_CAL_TXI_SLP 76 +#define SFF_A2_CAL_TXI_OFF 78 +#define SFF_A2_CAL_TXPWR_SLP 80 +#define SFF_A2_CAL_TXPWR_OFF 82 +#define SFF_A2_CAL_T_SLP 84 +#define SFF_A2_CAL_T_OFF 86 +#define SFF_A2_CAL_V_SLP 88 +#define SFF_A2_CAL_V_OFF 90 + +static struct sff_8472_aw_flags { + const char *str; /* Human-readable string, null at the end */ + int offset; /* A2-relative address offset */ + uint8_t value; /* Alarm is on if (offset & value) != 0. */ +} sff_8472_aw_flags[] = { + { "Laser bias current high alarm", SFF_A2_ALRM_FLG, (1 << 3) }, + { "Laser bias current low alarm", SFF_A2_ALRM_FLG, (1 << 2) }, + { "Laser bias current high warning", SFF_A2_WARN_FLG, (1 << 3) }, + { "Laser bias current low warning", SFF_A2_WARN_FLG, (1 << 2) }, + + { "Laser output power high alarm", SFF_A2_ALRM_FLG, (1 << 1) }, + { "Laser output power low alarm", SFF_A2_ALRM_FLG, (1 << 0) }, + { "Laser output power high warning", SFF_A2_WARN_FLG, (1 << 1) }, + { "Laser output power low warning", SFF_A2_WARN_FLG, (1 << 0) }, + + { "Module temperature high alarm", SFF_A2_ALRM_FLG, (1 << 7) }, + { "Module temperature low alarm", SFF_A2_ALRM_FLG, (1 << 6) }, + { "Module temperature high warning", SFF_A2_WARN_FLG, (1 << 7) }, + { "Module temperature low warning", SFF_A2_WARN_FLG, (1 << 6) }, + + { "Module voltage high alarm", SFF_A2_ALRM_FLG, (1 << 5) }, + { "Module voltage low alarm", SFF_A2_ALRM_FLG, (1 << 4) }, + { "Module voltage high warning", SFF_A2_WARN_FLG, (1 << 5) }, + { "Module voltage low warning", SFF_A2_WARN_FLG, (1 << 4) }, + + { "Laser rx power high alarm", SFF_A2_ALRM_FLG + 1, (1 << 7) }, + { "Laser rx power low alarm", SFF_A2_ALRM_FLG + 1, (1 << 6) }, + { "Laser rx power high warning", SFF_A2_WARN_FLG + 1, (1 << 7) }, + { "Laser rx power low warning", SFF_A2_WARN_FLG + 1, (1 << 6) }, + + { NULL, 0, 0 }, +}; + +/* Most common case: 16-bit unsigned integer in a certain unit */ +#define A2_OFFSET_TO_U16(offset) \ + (id[SFF_A2_BASE + (offset)] << 8 | id[SFF_A2_BASE + (offset) + 1]) + +/* Calibration slope is a number between 0.0 included and 256.0 excluded. */ +#define A2_OFFSET_TO_SLP(offset) \ + (id[SFF_A2_BASE + (offset)] + id[SFF_A2_BASE + (offset) + 1] / 256.) + +/* Calibration offset is an integer from -32768 to 32767 */ +#define A2_OFFSET_TO_OFF(offset) \ + ((int16_t)A2_OFFSET_TO_U16(offset)) + +/* RXPWR(x) are IEEE-754 floating point numbers in big-endian format */ +#define A2_OFFSET_TO_RXPWRx(offset) \ + (befloattoh((const uint32_t *)(id + SFF_A2_BASE + (offset)))) + +/* + * 2-byte internal temperature conversions: + * First byte is a signed 8-bit integer, which is the temp decimal part + * Second byte are 1/256th of degree, which are added to the dec part. + */ +#define A2_OFFSET_TO_TEMP(offset) ((int16_t)A2_OFFSET_TO_U16(offset)) + +static void sff_8472_dom_parse(const uint8_t *id, struct sff_diags *sd) +{ + sd->bias_cur[MCURR] = A2_OFFSET_TO_U16(SFF_A2_BIAS); + sd->bias_cur[HALRM] = A2_OFFSET_TO_U16(SFF_A2_BIAS_HALRM); + sd->bias_cur[LALRM] = A2_OFFSET_TO_U16(SFF_A2_BIAS_LALRM); + sd->bias_cur[HWARN] = A2_OFFSET_TO_U16(SFF_A2_BIAS_HWARN); + sd->bias_cur[LWARN] = A2_OFFSET_TO_U16(SFF_A2_BIAS_LWARN); + + sd->sfp_voltage[MCURR] = A2_OFFSET_TO_U16(SFF_A2_VCC); + sd->sfp_voltage[HALRM] = A2_OFFSET_TO_U16(SFF_A2_VCC_HALRM); + sd->sfp_voltage[LALRM] = A2_OFFSET_TO_U16(SFF_A2_VCC_LALRM); + sd->sfp_voltage[HWARN] = A2_OFFSET_TO_U16(SFF_A2_VCC_HWARN); + sd->sfp_voltage[LWARN] = A2_OFFSET_TO_U16(SFF_A2_VCC_LWARN); + + sd->tx_power[MCURR] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR); + sd->tx_power[HALRM] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_HALRM); + sd->tx_power[LALRM] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_LALRM); + sd->tx_power[HWARN] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_HWARN); + sd->tx_power[LWARN] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_LWARN); + + sd->rx_power[MCURR] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR); + sd->rx_power[HALRM] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_HALRM); + sd->rx_power[LALRM] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_LALRM); + sd->rx_power[HWARN] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_HWARN); + sd->rx_power[LWARN] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_LWARN); + + sd->sfp_temp[MCURR] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP); + sd->sfp_temp[HALRM] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_HALRM); + sd->sfp_temp[LALRM] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_LALRM); + sd->sfp_temp[HWARN] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_HWARN); + sd->sfp_temp[LWARN] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_LWARN); +} + +/* Converts to a float from a big-endian 4-byte source buffer. */ +static float befloattoh(const uint32_t *source) +{ + union { + uint32_t src; + float dst; + } converter; + + converter.src = ntohl(*source); + return converter.dst; +} + +static void sff_8472_calibration(const uint8_t *id, struct sff_diags *sd) +{ + unsigned long i; + uint16_t rx_reading; + + /* Calibration should occur for all values (threshold and current) */ + for (i = 0; i < ARRAY_SIZE(sd->bias_cur); ++i) { + /* + * Apply calibration formula 1 (Temp., Voltage, Bias, Tx Power) + */ + sd->bias_cur[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_TXI_SLP); + sd->tx_power[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_TXPWR_SLP); + sd->sfp_voltage[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_V_SLP); + sd->sfp_temp[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_T_SLP); + + sd->bias_cur[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_TXI_OFF); + sd->tx_power[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_TXPWR_OFF); + sd->sfp_voltage[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_V_OFF); + sd->sfp_temp[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_T_OFF); + + /* + * Apply calibration formula 2 (Rx Power only) + */ + rx_reading = sd->rx_power[i]; + sd->rx_power[i] = A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR0); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR1); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR2); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR3); + } +} + +static void sff_8472_parse_eeprom(const uint8_t *id, struct sff_diags *sd) +{ + sd->supports_dom = id[SFF_A0_DOM] & SFF_A0_DOM_IMPL; + sd->supports_alarms = id[SFF_A0_OPTIONS] & SFF_A0_OPTIONS_AW; + sd->calibrated_ext = id[SFF_A0_DOM] & SFF_A0_DOM_EXTCAL; + sd->rx_power_type = id[SFF_A0_DOM] & SFF_A0_DOM_PWRT; + + sff_8472_dom_parse(id, sd); + + /* + * If the SFP is externally calibrated, we need to read calibration data + * and compensate the already stored readings. + */ + if (sd->calibrated_ext) + sff_8472_calibration(id, sd); +} + +void sff_8472_show_all(const uint8_t *id, sff_item *items) +{ + struct sff_diags sd = {0}; + const char *rx_power_string = NULL; + char val_string[TMP_STRING_SIZE]; + int i; + + sff_8472_parse_eeprom(id, &sd); + + if (!sd.supports_dom) { + printf("%-41s : No\n", "Optical diagnostics support"); + add_item_string(items, "Optical diagnostics support", "No"); + return; + } + printf("%-41s : Yes\n", "Optical diagnostics support"); + add_item_string(items, "Optical diagnostics support", "Yes"); + + PRINT_BIAS("Laser bias current", sd.bias_cur[MCURR]); + SPRINT_BIAS(val_string, sd.bias_cur[MCURR]); + add_item_string(items, "Laser bias current", val_string); + + PRINT_xX_PWR("Laser output power", sd.tx_power[MCURR]); + SPRINT_xX_PWR(val_string, sd.tx_power[MCURR]); + add_item_string(items, "Laser output power", val_string); + + if (!sd.rx_power_type) + rx_power_string = "Receiver signal OMA"; + else + rx_power_string = "Receiver signal average optical power"; + + PRINT_xX_PWR(rx_power_string, sd.rx_power[MCURR]); + SPRINT_xX_PWR(val_string, sd.rx_power[MCURR]); + add_item_string(items, rx_power_string, val_string); + + PRINT_TEMP("Module temperature", sd.sfp_temp[MCURR]); + SPRINT_TEMP(val_string, sd.sfp_temp[MCURR]); + add_item_string(items, "Module temperature", val_string); + + PRINT_VCC("Module voltage", sd.sfp_voltage[MCURR]); + SPRINT_VCC(val_string, sd.sfp_voltage[MCURR]); + add_item_string(items, "Module voltage", val_string); + + printf("%-41s : %s\n", "Alarm/warning flags implemented", + (sd.supports_alarms ? "Yes" : "No")); + add_item_string(items, "Alarm/warning flags implemented", + (sd.supports_alarms ? "Yes" : "No")); + + if (sd.supports_alarms) { + + for (i = 0; sff_8472_aw_flags[i].str; ++i) { + printf("%-41s : %s\n", sff_8472_aw_flags[i].str, + id[SFF_A2_BASE + sff_8472_aw_flags[i].offset] + & sff_8472_aw_flags[i].value ? "On" : "Off"); + add_item_string(items, sff_8472_aw_flags[i].str, + id[SFF_A2_BASE + sff_8472_aw_flags[i].offset] + & sff_8472_aw_flags[i].value ? "On" : "Off"); + } + sff_show_thresholds(sd, items); + } +} + diff --git a/drivers/common/sff_module/sff_8636.c b/drivers/common/sff_module/sff_8636.c new file mode 100644 index 0000000000..c21e0665b6 --- /dev/null +++ b/drivers/common/sff_module/sff_8636.c @@ -0,0 +1,1004 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2022 Intel Corporation + * + * Implements SFF-8636 based QSFP+/QSFP28 Diagnostics Memory map. + * + */ + +#include <stdio.h> +#include <math.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "sff_8636.h" +#include "sff_telemetry.h" + +#define MAX_DESC_SIZE 42 + +static struct sff_8636_aw_flags { + const char *str; /* Human-readable string, null at the end */ + int offset; /* A2-relative address offset */ + uint8_t value; /* Alarm is on if (offset & value) != 0. */ +} sff_8636_aw_flags[] = { + { "Laser bias current high alarm (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_HALARM) }, + { "Laser bias current low alarm (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_LALARM) }, + { "Laser bias current high warning (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_HWARN) }, + { "Laser bias current low warning (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_LWARN) }, + + { "Laser bias current high alarm (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_HALARM) }, + { "Laser bias current low alarm (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_LALARM) }, + { "Laser bias current high warning (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_HWARN) }, + { "Laser bias current low warning (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_LWARN) }, + + { "Laser bias current high alarm (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_HALARM) }, + { "Laser bias current low alarm (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_LALARM) }, + { "Laser bias current high warning (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_HWARN) }, + { "Laser bias current low warning (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_LWARN) }, + + { "Laser bias current high alarm (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_HALARM) }, + { "Laser bias current low alarm (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_LALARM) }, + { "Laser bias current high warning (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_HWARN) }, + { "Laser bias current low warning (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_LWARN) }, + + { "Module temperature high alarm", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_HALARM_STATUS) }, + { "Module temperature low alarm", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_LALARM_STATUS) }, + { "Module temperature high warning", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_HWARN_STATUS) }, + { "Module temperature low warning", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_LWARN_STATUS) }, + + { "Module voltage high alarm", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_HALARM_STATUS) }, + { "Module voltage low alarm", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_LALARM_STATUS) }, + { "Module voltage high warning", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_HWARN_STATUS) }, + { "Module voltage low warning", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_LWARN_STATUS) }, + + { "Laser tx power high alarm (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_HALARM) }, + { "Laser tx power low alarm (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_LALARM) }, + { "Laser tx power high warning (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_HWARN) }, + { "Laser tx power low warning (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_LWARN) }, + + { "Laser tx power high alarm (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_HALARM) }, + { "Laser tx power low alarm (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_LALARM) }, + { "Laser tx power high warning (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_HWARN) }, + { "Laser tx power low warning (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_LWARN) }, + + { "Laser tx power high alarm (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_HALARM) }, + { "Laser tx power low alarm (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_LALARM) }, + { "Laser tx power high warning (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_HWARN) }, + { "Laser tx power low warning (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_LWARN) }, + + { "Laser tx power high alarm (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_HALARM) }, + { "Laser tx power low alarm (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_LALARM) }, + { "Laser tx power high warning (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_HWARN) }, + { "Laser tx power low warning (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_LWARN) }, + + { "Laser rx power high alarm (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_HALARM) }, + { "Laser rx power low alarm (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_LALARM) }, + { "Laser rx power high warning (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_HWARN) }, + { "Laser rx power low warning (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_LWARN) }, + + { "Laser rx power high alarm (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_HALARM) }, + { "Laser rx power low alarm (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_LALARM) }, + { "Laser rx power high warning (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_HWARN) }, + { "Laser rx power low warning (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_LWARN) }, + + { "Laser rx power high alarm (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_HALARM) }, + { "Laser rx power low alarm (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_LALARM) }, + { "Laser rx power high warning (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_HWARN) }, + { "Laser rx power low warning (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_LWARN) }, + + { "Laser rx power high alarm (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_HALARM) }, + { "Laser rx power low alarm (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_LALARM) }, + { "Laser rx power high warning (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_HWARN) }, + { "Laser rx power low warning (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_LWARN) }, + + { NULL, 0, 0 }, +}; + +static void sff_8636_show_identifier(const uint8_t *id, sff_item *items) +{ + sff_8024_show_identifier(id, SFF_8636_ID_OFFSET, items); +} + +static void sff_8636_show_ext_identifier(const uint8_t *id, sff_item *items) +{ + char val_string[TMP_STRING_SIZE]; + printf("%-41s : 0x%02x\n", "Extended identifier", + id[SFF_8636_EXT_ID_OFFSET]); + sprintf(val_string, "0x%02x", id[SFF_8636_EXT_ID_OFFSET]); + add_item_string(items, "Extended identifier", val_string); + + static const char *pfx = + "Extended identifier description :"; + + switch (id[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_PWR_CLASS_MASK) { + case SFF_8636_EXT_ID_PWR_CLASS_1: + printf("%s 1.5W max. Power consumption\n", pfx); + add_item_string(items, "Extended identifier description", + "1.5W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_2: + printf("%s 2.0W max. Power consumption\n", pfx); + add_item_string(items, "Extended identifier description", + "2.0W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_3: + printf("%s 2.5W max. Power consumption\n", pfx); + add_item_string(items, "Extended identifier description", + "2.5W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_4: + printf("%s 3.5W max. Power consumption\n", pfx); + add_item_string(items, "Extended identifier description", + "3.5W max. Power consumption"); + break; + } + + if (id[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_CDR_TX_MASK) { + printf("%s CDR present in TX,", pfx); + add_item_string(items, "Extended identifier description", + "CDR present in TX"); + } else { + printf("%s No CDR in TX,", pfx); + add_item_string(items, "Extended identifier description", + "No CDR in TX"); + } + + if (id[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_CDR_RX_MASK) { + printf(" CDR present in RX\n"); + add_item_string(items, "Extended identifier description", + "CDR present in RX"); + } else { + printf(" No CDR in RX\n"); + add_item_string(items, "Extended identifier description", + "No CDR in RX"); + } + + switch (id[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_EPWR_CLASS_MASK) { + case SFF_8636_EXT_ID_PWR_CLASS_LEGACY: + printf("%s", pfx); + sprintf(val_string, "%s", ""); + break; + case SFF_8636_EXT_ID_PWR_CLASS_5: + printf("%s 4.0W max. Power consumption,", pfx); + sprintf(val_string, "%s", "4.0W max. Power consumption, "); + break; + case SFF_8636_EXT_ID_PWR_CLASS_6: + printf("%s 4.5W max. Power consumption, ", pfx); + sprintf(val_string, "%s", "4.5W max. Power consumption, "); + break; + case SFF_8636_EXT_ID_PWR_CLASS_7: + printf("%s 5.0W max. Power consumption, ", pfx); + sprintf(val_string, "%s", "5.0W max. Power consumption, "); + break; + } + if (id[SFF_8636_PWR_MODE_OFFSET] & SFF_8636_HIGH_PWR_ENABLE) { + printf(" High Power Class (> 3.5 W) enabled\n"); + strcat(val_string, "High Power Class (> 3.5 W) enabled"); + } else { + printf(" High Power Class (> 3.5 W) not enabled\n"); + strcat(val_string, "High Power Class (> 3.5 W) not enabled"); + } + add_item_string(items, "Extended identifier description", val_string); +} + +static void sff_8636_show_connector(const uint8_t *id, sff_item *items) +{ + sff_8024_show_connector(id, SFF_8636_CTOR_OFFSET, items); +} + +static void sff_8636_show_transceiver(const uint8_t *id, sff_item *items) +{ + static const char *pfx = + "Transceiver type :"; + static const char *name_string = "Transceiver type"; + char val_string[TMP_STRING_SIZE]; + + printf("%-41s : 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", + "Transceiver codes", + id[SFF_8636_ETHERNET_COMP_OFFSET], + id[SFF_8636_SONET_COMP_OFFSET], + id[SFF_8636_SAS_COMP_OFFSET], + id[SFF_8636_GIGE_COMP_OFFSET], + id[SFF_8636_FC_LEN_OFFSET], + id[SFF_8636_FC_TECH_OFFSET], + id[SFF_8636_FC_TRANS_MEDIA_OFFSET], + id[SFF_8636_FC_SPEED_OFFSET]); + sprintf(val_string, "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + id[SFF_8636_ETHERNET_COMP_OFFSET], + id[SFF_8636_SONET_COMP_OFFSET], + id[SFF_8636_SAS_COMP_OFFSET], + id[SFF_8636_GIGE_COMP_OFFSET], + id[SFF_8636_FC_LEN_OFFSET], + id[SFF_8636_FC_TECH_OFFSET], + id[SFF_8636_FC_TRANS_MEDIA_OFFSET], + id[SFF_8636_FC_SPEED_OFFSET]); + add_item_string(items, "Transceiver codes", val_string); + + /* 10G/40G Ethernet Compliance Codes */ + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_LRM) { + printf("%s 10G Ethernet: 10G Base-LRM\n", pfx); + add_item_string(items, name_string, + "10G Ethernet: 10G Base-LRM"); + } + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_LR) { + printf("%s 10G Ethernet: 10G Base-LR\n", pfx); + add_item_string(items, name_string, + "10G Ethernet: 10G Base-LR"); + } + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_SR) { + printf("%s 10G Ethernet: 10G Base-SR\n", pfx); + add_item_string(items, name_string, + "10G Ethernet: 10G Base-SR"); + } + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_CR4) { + printf("%s 40G Ethernet: 40G Base-CR4\n", pfx); + add_item_string(items, name_string, + "40G Ethernet: 40G Base-CR4"); + } + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_SR4) { + printf("%s 40G Ethernet: 40G Base-SR4\n", pfx); + add_item_string(items, name_string, + "40G Ethernet: 40G Base-SR4"); + } + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_LR4) { + printf("%s 40G Ethernet: 40G Base-LR4\n", pfx); + add_item_string(items, name_string, + "40G Ethernet: 40G Base-LR4"); + } + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_ACTIVE) { + printf("%s 40G Ethernet: 40G Active Cable (XLPPI)\n", pfx); + add_item_string(items, name_string, + "40G Ethernet: 40G Active Cable (XLPPI)"); + } + /* Extended Specification Compliance Codes from SFF-8024 */ + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_RSRVD) { + switch (id[SFF_8636_OPTION_1_OFFSET]) { + case SFF_8636_ETHERNET_UNSPECIFIED: + printf("%s (reserved or unknown)\n", pfx); + add_item_string(items, name_string, + "(reserved or unknown)"); + break; + case SFF_8636_ETHERNET_100G_AOC: + printf("%s 100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)\n", + pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)"); + break; + case SFF_8636_ETHERNET_100G_SR4: + printf("%s 100G Ethernet: 100G Base-SR4 or 25GBase-SR\n", + pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G Base-SR4 or 25GBase-SR"); + break; + case SFF_8636_ETHERNET_100G_LR4: + printf("%s 100G Ethernet: 100G Base-LR4\n", pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G Base-LR4"); + break; + case SFF_8636_ETHERNET_100G_ER4: + printf("%s 100G Ethernet: 100G Base-ER4\n", pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G Base-ER4"); + break; + case SFF_8636_ETHERNET_100G_SR10: + printf("%s 100G Ethernet: 100G Base-SR10\n", pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G Base-SR10"); + break; + case SFF_8636_ETHERNET_100G_CWDM4_FEC: + printf("%s 100G Ethernet: 100G CWDM4 MSA with FEC\n", pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G CWDM4 MSA with FEC"); + break; + case SFF_8636_ETHERNET_100G_PSM4: + printf("%s 100G Ethernet: 100G PSM4 Parallel SMF\n", pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G PSM4 Parallel SMF"); + break; + case SFF_8636_ETHERNET_100G_ACC: + printf("%s 100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)\n", + pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)"); + break; + case SFF_8636_ETHERNET_100G_CWDM4_NO_FEC: + printf("%s 100G Ethernet: 100G CWDM4 MSA without FEC\n", pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G CWDM4 MSA without FEC"); + break; + case SFF_8636_ETHERNET_100G_RSVD1: + printf("%s (reserved or unknown)\n", pfx); + add_item_string(items, name_string, + "(reserved or unknown)"); + break; + case SFF_8636_ETHERNET_100G_CR4: + printf("%s 100G Ethernet: 100G Base-CR4 or 25G Base-CR CA-L\n", + pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G Base-CR4 or 25G Base-CR CA-L"); + break; + case SFF_8636_ETHERNET_25G_CR_CA_S: + printf("%s 25G Ethernet: 25G Base-CR CA-S\n", pfx); + add_item_string(items, name_string, + "25G Ethernet: 25G Base-CR CA-S"); + break; + case SFF_8636_ETHERNET_25G_CR_CA_N: + printf("%s 25G Ethernet: 25G Base-CR CA-N\n", pfx); + add_item_string(items, name_string, + "25G Ethernet: 25G Base-CR CA-N"); + break; + case SFF_8636_ETHERNET_40G_ER4: + printf("%s 40G Ethernet: 40G Base-ER4\n", pfx); + add_item_string(items, name_string, + "40G Ethernet: 40G Base-ER4"); + break; + case SFF_8636_ETHERNET_4X10_SR: + printf("%s 4x10G Ethernet: 10G Base-SR\n", pfx); + add_item_string(items, name_string, + "4x10G Ethernet: 10G Base-SR"); + break; + case SFF_8636_ETHERNET_40G_PSM4: + printf("%s 40G Ethernet: 40G PSM4 Parallel SMF\n", pfx); + add_item_string(items, name_string, + "40G Ethernet: 40G PSM4 Parallel SMF"); + break; + case SFF_8636_ETHERNET_G959_P1I1_2D1: + printf("%s Ethernet: G959.1 profile P1I1-2D1 (10709 MBd, 2km, 1310nm SM)\n", + pfx); + add_item_string(items, name_string, + "Ethernet: G959.1 profile P1I1-2D1 (10709 MBd, 2km, 1310nm SM)"); + break; + case SFF_8636_ETHERNET_G959_P1S1_2D2: + printf("%s Ethernet: G959.1 profile P1S1-2D2 (10709 MBd, 40km, 1550nm SM)\n", + pfx); + add_item_string(items, name_string, + "Ethernet: G959.1 profile P1S1-2D2 (10709 MBd, 40km, 1550nm SM)"); + break; + case SFF_8636_ETHERNET_G959_P1L1_2D2: + printf("%s Ethernet: G959.1 profile P1L1-2D2 (10709 MBd, 80km, 1550nm SM)\n", + pfx); + add_item_string(items, name_string, + "Ethernet: G959.1 profile P1L1-2D2 (10709 MBd, 80km, 1550nm SM)"); + break; + case SFF_8636_ETHERNET_10GT_SFI: + printf("%s 10G Ethernet: 10G Base-T with SFI electrical interface\n", + pfx); + add_item_string(items, name_string, + "10G Ethernet: 10G Base-T with SFI electrical interface"); + break; + case SFF_8636_ETHERNET_100G_CLR4: + printf("%s 100G Ethernet: 100G CLR4\n", pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G CLR4"); + break; + case SFF_8636_ETHERNET_100G_AOC2: + printf("%s 100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)\n", + pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)"); + break; + case SFF_8636_ETHERNET_100G_ACC2: + printf("%s 100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)\n", + pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)"); + break; + default: + printf("%s (reserved or unknown)\n", pfx); + add_item_string(items, name_string, + "(reserved or unknown)"); + break; + } + } + + /* SONET Compliance Codes */ + if (id[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_40G_OTN) { + printf("%s 40G OTN (OTU3B/OTU3C)\n", pfx); + add_item_string(items, name_string, "40G OTN (OTU3B/OTU3C)"); + } + if (id[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_LR) { + printf("%s SONET: OC-48, long reach\n", pfx); + add_item_string(items, name_string, "SONET: OC-48, long reach"); + } + if (id[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_IR) { + printf("%s SONET: OC-48, intermediate reach\n", pfx); + add_item_string(items, name_string, "SONET: OC-48, intermediate reach"); + } + if (id[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_SR) { + printf("%s SONET: OC-48, short reach\n", pfx); + add_item_string(items, name_string, "SONET: OC-48, short reach"); + } + + /* SAS/SATA Compliance Codes */ + if (id[SFF_8636_SAS_COMP_OFFSET] & SFF_8636_SAS_6G) { + printf("%s SAS 6.0G\n", pfx); + add_item_string(items, name_string, "SAS 6.0G"); + } + if (id[SFF_8636_SAS_COMP_OFFSET] & SFF_8636_SAS_3G) { + printf("%s SAS 3.0G\n", pfx); + add_item_string(items, name_string, "SAS 3.0G"); + } + + /* Ethernet Compliance Codes */ + if (id[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_T) { + printf("%s Ethernet: 1000BASE-T\n", pfx); + add_item_string(items, name_string, "Ethernet: 1000BASE-T"); + } + if (id[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_CX) { + printf("%s Ethernet: 1000BASE-CX\n", pfx); + add_item_string(items, name_string, "Ethernet: 1000BASE-CX"); + } + if (id[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_LX) { + printf("%s Ethernet: 1000BASE-LX\n", pfx); + add_item_string(items, name_string, "Ethernet: 1000BASE-LX"); + } + if (id[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_SX) { + printf("%s Ethernet: 1000BASE-SX\n", pfx); + add_item_string(items, name_string, "Ethernet: 1000BASE-SX"); + } + + /* Fibre Channel link length */ + if (id[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_VERY_LONG) { + printf("%s FC: very long distance (V)\n", pfx); + add_item_string(items, name_string, "FC: very long distance (V)"); + } + if (id[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_SHORT) { + printf("%s FC: short distance (S)\n", pfx); + add_item_string(items, name_string, "FC: short distance (S)"); + } + if (id[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_INT) { + printf("%s FC: intermediate distance (I)\n", pfx); + add_item_string(items, name_string, "FC: intermediate distance (I)"); + } + if (id[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_LONG) { + printf("%s FC: long distance (L)\n", pfx); + add_item_string(items, name_string, "FC: long distance (L)"); + } + if (id[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_MED) { + printf("%s FC: medium distance (M)\n", pfx); + add_item_string(items, name_string, "FC: medium distance (M)"); + } + + /* Fibre Channel transmitter technology */ + if (id[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_TECH_LONG_LC) { + printf("%s FC: Longwave laser (LC)\n", pfx); + add_item_string(items, name_string, "FC: Longwave laser (LC)"); + } + if (id[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_TECH_ELEC_INTER) { + printf("%s FC: Electrical inter-enclosure (EL)\n", pfx); + add_item_string(items, name_string, "FC: Electrical inter-enclosure (EL)"); + } + if (id[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_ELEC_INTRA) { + printf("%s FC: Electrical intra-enclosure (EL)\n", pfx); + add_item_string(items, name_string, "FC: Electrical intra-enclosure (EL)"); + } + if (id[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_SHORT_WO_OFC) { + printf("%s FC: Shortwave laser w/o OFC (SN)\n", pfx); + add_item_string(items, name_string, "FC: Shortwave laser w/o OFC (SN)"); + } + if (id[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_SHORT_W_OFC) { + printf("%s FC: Shortwave laser with OFC (SL)\n", pfx); + add_item_string(items, name_string, "FC: Shortwave laser with OFC (SL)"); + } + if (id[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_LONG_LL) { + printf("%s FC: Longwave laser (LL)\n", pfx); + add_item_string(items, name_string, "FC: Longwave laser (LL)"); + } + + /* Fibre Channel transmission media */ + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TW) { + printf("%s FC: Twin Axial Pair (TW)\n", pfx); + add_item_string(items, name_string, "FC: Twin Axial Pair (TW)"); + } + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TP) { + printf("%s FC: Twisted Pair (TP)\n", pfx); + add_item_string(items, name_string, "FC: Twisted Pair (TP)"); + } + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_MI) { + printf("%s FC: Miniature Coax (MI)\n", pfx); + add_item_string(items, name_string, "FC: Miniature Coax (MI)"); + } + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TV) { + printf("%s FC: Video Coax (TV)\n", pfx); + add_item_string(items, name_string, "FC: Video Coax (TV)"); + } + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_M6) { + printf("%s FC: Multimode, 62.5m (M6)\n", pfx); + add_item_string(items, name_string, "FC: Multimode, 62.5m (M6)"); + } + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_M5) { + printf("%s FC: Multimode, 50m (M5)\n", pfx); + add_item_string(items, name_string, "FC: Multimode, 50m (M5)"); + } + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_OM3) { + printf("%s FC: Multimode, 50um (OM3)\n", pfx); + add_item_string(items, name_string, "FC: Multimode, 50um (OM3)"); + } + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_SM) { + printf("%s FC: Single Mode (SM)\n", pfx); + add_item_string(items, name_string, "FC: Single Mode (SM)"); + } + + /* Fibre Channel speed */ + if (id[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_1200_MBPS) { + printf("%s FC: 1200 MBytes/sec\n", pfx); + add_item_string(items, name_string, "FC: 1200 MBytes/sec"); + } + if (id[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_800_MBPS) { + printf("%s FC: 800 MBytes/sec\n", pfx); + add_item_string(items, name_string, "FC: 800 MBytes/sec"); + } + if (id[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_1600_MBPS) { + printf("%s FC: 1600 MBytes/sec\n", pfx); + add_item_string(items, name_string, "FC: 1600 MBytes/sec"); + } + if (id[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_400_MBPS) { + printf("%s FC: 400 MBytes/sec\n", pfx); + add_item_string(items, name_string, "FC: 400 MBytes/sec"); + } + if (id[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_200_MBPS) { + printf("%s FC: 200 MBytes/sec\n", pfx); + add_item_string(items, name_string, "FC: 200 MBytes/sec"); + } + if (id[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_100_MBPS) { + printf("%s FC: 100 MBytes/sec\n", pfx); + add_item_string(items, name_string, "FC: 100 MBytes/sec"); + } +} + +static void sff_8636_show_encoding(const uint8_t *id, sff_item *items) +{ + sff_8024_show_encoding(id, SFF_8636_ENCODING_OFFSET, + RTE_ETH_MODULE_SFF_8636, items); +} + +static void sff_8636_show_rate_identifier(const uint8_t *id, sff_item *items) +{ + char val_string[20]; + /* TODO: Need to fix rate select logic */ + printf("%-41s : 0x%02x\n", "Rate identifier", + id[SFF_8636_EXT_RS_OFFSET]); + sprintf(val_string, "0x%02x", id[SFF_8636_EXT_RS_OFFSET]); + add_item_string(items, "Rate identifier", val_string); +} + +static void sff_8636_show_oui(const uint8_t *id, sff_item *items) +{ + sff_8024_show_oui(id, SFF_8636_VENDOR_OUI_OFFSET, items); +} + +static void sff_8636_show_wavelength_or_copper_compliance(const uint8_t *id, sff_item *items) +{ + char val_string[TMP_STRING_SIZE]; + printf("%-41s : 0x%02x", "Transmitter technology", + (id[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK)); + sprintf(val_string, "0x%02x", + (id[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK)); + + switch (id[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK) { + case SFF_8636_TRANS_850_VCSEL: + printf(" (850 nm VCSEL)\n"); + strcat(val_string, " (850 nm VCSEL)"); + break; + case SFF_8636_TRANS_1310_VCSEL: + printf(" (1310 nm VCSEL)\n"); + strcat(val_string, " (1310 nm VCSEL)"); + break; + case SFF_8636_TRANS_1550_VCSEL: + printf(" (1550 nm VCSEL)\n"); + strcat(val_string, " (1550 nm VCSEL)"); + break; + case SFF_8636_TRANS_1310_FP: + printf(" (1310 nm FP)\n"); + strcat(val_string, " (1310 nm FP)"); + break; + case SFF_8636_TRANS_1310_DFB: + printf(" (1310 nm DFB)\n"); + strcat(val_string, " (1310 nm DFB)"); + break; + case SFF_8636_TRANS_1550_DFB: + printf(" (1550 nm DFB)\n"); + strcat(val_string, " (1550 nm DFB)"); + break; + case SFF_8636_TRANS_1310_EML: + printf(" (1310 nm EML)\n"); + strcat(val_string, " (1310 nm EML)"); + break; + case SFF_8636_TRANS_1550_EML: + printf(" (1550 nm EML)\n"); + strcat(val_string, " (1550 nm EML)"); + break; + case SFF_8636_TRANS_OTHERS: + printf(" (Others/Undefined)\n"); + strcat(val_string, " (Others/Undefined)"); + break; + case SFF_8636_TRANS_1490_DFB: + printf(" (1490 nm DFB)\n"); + strcat(val_string, " (1490 nm DFB)"); + break; + case SFF_8636_TRANS_COPPER_PAS_UNEQUAL: + printf(" (Copper cable unequalized)\n"); + strcat(val_string, " (Copper cable unequalized)"); + break; + case SFF_8636_TRANS_COPPER_PAS_EQUAL: + printf(" (Copper cable passive equalized)\n"); + strcat(val_string, " (Copper cable passive equalized)"); + break; + case SFF_8636_TRANS_COPPER_LNR_FAR_EQUAL: + printf(" (Copper cable, near and far end limiting active equalizers)\n"); + strcat(val_string, + " (Copper cable, near and far end limiting active equalizers)"); + break; + case SFF_8636_TRANS_COPPER_FAR_EQUAL: + printf(" (Copper cable, far end limiting active equalizers)\n"); + strcat(val_string, " (Copper cable, far end limiting active equalizers)"); + break; + case SFF_8636_TRANS_COPPER_NEAR_EQUAL: + printf(" (Copper cable, near end limiting active equalizers)\n"); + strcat(val_string, " (Copper cable, near end limiting active equalizers)"); + break; + case SFF_8636_TRANS_COPPER_LNR_EQUAL: + printf(" (Copper cable, linear active equalizers)\n"); + strcat(val_string, " (Copper cable, linear active equalizers)"); + break; + } + add_item_string(items, "Transmitter technology", val_string); + + if ((id[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK) + >= SFF_8636_TRANS_COPPER_PAS_UNEQUAL) { + printf("%-41s : %udb\n", "Attenuation at 2.5GHz", + id[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + sprintf(val_string, "%udb", id[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + add_item_string(items, "Attenuation at 2.5GHz", val_string); + + printf("%-41s : %udb\n", "Attenuation at 5.0GHz", + id[SFF_8636_WAVELEN_LOW_BYTE_OFFSET]); + sprintf(val_string, "%udb", id[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + add_item_string(items, "Attenuation at 5.0GHz", val_string); + + printf("%-41s : %udb\n", "Attenuation at 7.0GHz", + id[SFF_8636_WAVE_TOL_HIGH_BYTE_OFFSET]); + sprintf(val_string, "%udb", id[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + add_item_string(items, "Attenuation at 7.0GHz", val_string); + + printf("%-41s : %udb\n", "Attenuation at 12.9GHz", + id[SFF_8636_WAVE_TOL_LOW_BYTE_OFFSET]); + sprintf(val_string, "%udb", id[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + add_item_string(items, "Attenuation at 12.9GHz", val_string); + } else { + printf("%-41s : %.3lfnm\n", "Laser wavelength", + (((id[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET] << 8) | + id[SFF_8636_WAVELEN_LOW_BYTE_OFFSET])*0.05)); + sprintf(val_string, "%.3lfnm", + (((id[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET] << 8) | + id[SFF_8636_WAVELEN_LOW_BYTE_OFFSET])*0.05)); + add_item_string(items, "Laser wavelength", val_string); + + printf("%-41s : %.3lfnm\n", "Laser wavelength tolerance", + (((id[SFF_8636_WAVE_TOL_HIGH_BYTE_OFFSET] << 8) | + id[SFF_8636_WAVE_TOL_LOW_BYTE_OFFSET])*0.005)); + sprintf(val_string, "%.3lfnm", + (((id[SFF_8636_WAVE_TOL_HIGH_BYTE_OFFSET] << 8) | + id[SFF_8636_WAVE_TOL_LOW_BYTE_OFFSET])*0.005)); + add_item_string(items, "Laser wavelength tolerance", val_string); + } +} + +static void sff_8636_show_revision_compliance(const uint8_t *id, sff_item *items) +{ + static const char *pfx = + "Revision Compliance :"; + + switch (id[SFF_8636_REV_COMPLIANCE_OFFSET]) { + case SFF_8636_REV_UNSPECIFIED: + printf("%s Revision not specified\n", pfx); + add_item_string(items, "Revision Compliance", + "Revision not specified"); + break; + case SFF_8636_REV_8436_48: + printf("%s SFF-8436 Rev 4.8 or earlier\n", pfx); + add_item_string(items, "Revision Compliance", + "SFF-8436 Rev 4.8 or earlier"); + break; + case SFF_8636_REV_8436_8636: + printf("%s SFF-8436 Rev 4.8 or earlier\n", pfx); + add_item_string(items, "Revision Compliance", + "SFF-8436 Rev 4.8 or earlier"); + break; + case SFF_8636_REV_8636_13: + printf("%s SFF-8636 Rev 1.3 or earlier\n", pfx); + add_item_string(items, "Revision Compliance", + "SFF-8636 Rev 1.3 or earlier"); + break; + case SFF_8636_REV_8636_14: + printf("%s SFF-8636 Rev 1.4\n", pfx); + add_item_string(items, "Revision Compliance", + "SFF-8636 Rev 1.4"); + break; + case SFF_8636_REV_8636_15: + printf("%s SFF-8636 Rev 1.5\n", pfx); + add_item_string(items, "Revision Compliance", + "SFF-8636 Rev 1.5"); + break; + case SFF_8636_REV_8636_20: + printf("%s SFF-8636 Rev 2.0\n", pfx); + add_item_string(items, "Revision Compliance", + "SFF-8636 Rev 2.0"); + break; + case SFF_8636_REV_8636_27: + printf("%s SFF-8636 Rev 2.5/2.6/2.7\n", pfx); + add_item_string(items, "Revision Compliance", + "SFF-8636 Rev 2.5/2.6/2.7"); + break; + default: + printf("%s Unallocated\n", pfx); + add_item_string(items, "Revision Compliance", + "Unallocated"); + break; + } +} + +/* + * 2-byte internal temperature conversions: + * First byte is a signed 8-bit integer, which is the temp decimal part + * Second byte are 1/256th of degree, which are added to the dec part. + */ +#define SFF_8636_OFFSET_TO_TEMP(offset) ((int16_t)OFFSET_TO_U16(offset)) + +static void sff_8636_dom_parse(const uint8_t *id, struct sff_diags *sd) +{ + int i = 0; + + /* Monitoring Thresholds for Alarms and Warnings */ + sd->sfp_voltage[MCURR] = OFFSET_TO_U16(SFF_8636_VCC_CURR); + sd->sfp_voltage[HALRM] = OFFSET_TO_U16(SFF_8636_VCC_HALRM); + sd->sfp_voltage[LALRM] = OFFSET_TO_U16(SFF_8636_VCC_LALRM); + sd->sfp_voltage[HWARN] = OFFSET_TO_U16(SFF_8636_VCC_HWARN); + sd->sfp_voltage[LWARN] = OFFSET_TO_U16(SFF_8636_VCC_LWARN); + + sd->sfp_temp[MCURR] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_CURR); + sd->sfp_temp[HALRM] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_HALRM); + sd->sfp_temp[LALRM] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_LALRM); + sd->sfp_temp[HWARN] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_HWARN); + sd->sfp_temp[LWARN] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_LWARN); + + sd->bias_cur[HALRM] = OFFSET_TO_U16(SFF_8636_TX_BIAS_HALRM); + sd->bias_cur[LALRM] = OFFSET_TO_U16(SFF_8636_TX_BIAS_LALRM); + sd->bias_cur[HWARN] = OFFSET_TO_U16(SFF_8636_TX_BIAS_HWARN); + sd->bias_cur[LWARN] = OFFSET_TO_U16(SFF_8636_TX_BIAS_LWARN); + + sd->tx_power[HALRM] = OFFSET_TO_U16(SFF_8636_TX_PWR_HALRM); + sd->tx_power[LALRM] = OFFSET_TO_U16(SFF_8636_TX_PWR_LALRM); + sd->tx_power[HWARN] = OFFSET_TO_U16(SFF_8636_TX_PWR_HWARN); + sd->tx_power[LWARN] = OFFSET_TO_U16(SFF_8636_TX_PWR_LWARN); + + sd->rx_power[HALRM] = OFFSET_TO_U16(SFF_8636_RX_PWR_HALRM); + sd->rx_power[LALRM] = OFFSET_TO_U16(SFF_8636_RX_PWR_LALRM); + sd->rx_power[HWARN] = OFFSET_TO_U16(SFF_8636_RX_PWR_HWARN); + sd->rx_power[LWARN] = OFFSET_TO_U16(SFF_8636_RX_PWR_LWARN); + + + /* Channel Specific Data */ + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + uint8_t rx_power_offset, tx_bias_offset; + uint8_t tx_power_offset; + + switch (i) { + case 0: + rx_power_offset = SFF_8636_RX_PWR_1_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_1_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_1_OFFSET; + break; + case 1: + rx_power_offset = SFF_8636_RX_PWR_2_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_2_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_2_OFFSET; + break; + case 2: + rx_power_offset = SFF_8636_RX_PWR_3_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_3_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_3_OFFSET; + break; + case 3: + rx_power_offset = SFF_8636_RX_PWR_4_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_4_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_4_OFFSET; + break; + } + sd->scd[i].bias_cur = OFFSET_TO_U16(tx_bias_offset); + sd->scd[i].rx_power = OFFSET_TO_U16(rx_power_offset); + sd->scd[i].tx_power = OFFSET_TO_U16(tx_power_offset); + } + +} + +static void sff_8636_show_dom(const uint8_t *id, uint32_t eeprom_len, sff_item *items) +{ + struct sff_diags sd = {0}; + const char *rx_power_string = NULL; + char power_string[MAX_DESC_SIZE]; + char val_string[TMP_STRING_SIZE]; + int i; + + /* + * There is no clear identifier to signify the existence of + * optical diagnostics similar to SFF-8472. So checking existence + * of page 3, will provide the gurantee for existence of alarms + * and thresholds + * If pagging support exists, then supports_alarms is marked as 1 + */ + + if (eeprom_len == RTE_ETH_MODULE_SFF_8636_MAX_LEN) { + if (!(id[SFF_8636_STATUS_2_OFFSET] & + SFF_8636_STATUS_PAGE_3_PRESENT)) { + sd.supports_alarms = 1; + } + } + + sd.rx_power_type = id[SFF_8636_DIAG_TYPE_OFFSET] & + SFF_8636_RX_PWR_TYPE_MASK; + sd.tx_power_type = id[SFF_8636_DIAG_TYPE_OFFSET] & + SFF_8636_RX_PWR_TYPE_MASK; + + sff_8636_dom_parse(id, &sd); + + PRINT_TEMP("Module temperature", sd.sfp_temp[MCURR]); + SPRINT_TEMP(val_string, sd.sfp_temp[MCURR]); + add_item_string(items, "Module temperature", val_string); + + PRINT_VCC("Module voltage", sd.sfp_voltage[MCURR]); + SPRINT_VCC(val_string, sd.sfp_voltage[MCURR]); + add_item_string(items, "Module voltage", val_string); + + /* + * SFF-8636/8436 spec is not clear whether RX power/ TX bias + * current fields are supported or not. A valid temperature + * reading is used as existence for TX/RX power. + */ + if ((sd.sfp_temp[MCURR] == 0x0) || + (sd.sfp_temp[MCURR] == (int16_t)0xFFFF)) + return; + + printf("%-41s : %s\n", "Alarm/warning flags implemented", + (sd.supports_alarms ? "Yes" : "No")); + add_item_string(items, "Alarm/warning flags implemented", + (sd.supports_alarms ? "Yes" : "No")); + + for (i = 0; i < 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); + SPRINT_BIAS(val_string, sd.scd[i].bias_cur); + add_item_string(items, power_string, val_string); + } + + for (i = 0; i < 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); + SPRINT_xX_PWR(val_string, sd.scd[i].tx_power); + add_item_string(items, power_string, val_string); + } + + if (!sd.rx_power_type) + rx_power_string = "Receiver signal OMA"; + else + rx_power_string = "Rcvr signal avg optical power"; + + for (i = 0; i < 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); + SPRINT_xX_PWR(val_string, sd.scd[i].rx_power); + add_item_string(items, power_string, val_string); + } + + if (sd.supports_alarms) { + for (i = 0; sff_8636_aw_flags[i].str; ++i) { + printf("%-41s : %s\n", sff_8636_aw_flags[i].str, + id[sff_8636_aw_flags[i].offset] + & sff_8636_aw_flags[i].value ? "On" : "Off"); + add_item_string(items, sff_8636_aw_flags[i].str, + id[sff_8636_aw_flags[i].offset] + & sff_8636_aw_flags[i].value ? "On" : "Off"); + } + + sff_show_thresholds(sd, items); + } + +} +void sff_8636_show_all(const uint8_t *id, uint32_t eeprom_len, sff_item *items) +{ + sff_8636_show_identifier(id, items); + if ((id[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP) || + (id[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP_PLUS) || + (id[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP28)) { + sff_8636_show_ext_identifier(id, items); + sff_8636_show_connector(id, items); + sff_8636_show_transceiver(id, items); + sff_8636_show_encoding(id, items); + sff_show_value_with_unit(id, SFF_8636_BR_NOMINAL_OFFSET, + "BR, Nominal", 100, "Mbps", items); + sff_8636_show_rate_identifier(id, items); + sff_show_value_with_unit(id, SFF_8636_SM_LEN_OFFSET, + "Length (SMF,km)", 1, "km", items); + sff_show_value_with_unit(id, SFF_8636_OM3_LEN_OFFSET, + "Length (OM3 50um)", 2, "m", items); + sff_show_value_with_unit(id, SFF_8636_OM2_LEN_OFFSET, + "Length (OM2 50um)", 1, "m", items); + sff_show_value_with_unit(id, SFF_8636_OM1_LEN_OFFSET, + "Length (OM1 62.5um)", 1, "m", items); + sff_show_value_with_unit(id, SFF_8636_CBL_LEN_OFFSET, + "Length (Copper or Active cable)", 1, "m", items); + sff_8636_show_wavelength_or_copper_compliance(id, items); + sff_show_ascii(id, SFF_8636_VENDOR_NAME_START_OFFSET, + SFF_8636_VENDOR_NAME_END_OFFSET, "Vendor name", items); + sff_8636_show_oui(id, items); + sff_show_ascii(id, SFF_8636_VENDOR_PN_START_OFFSET, + SFF_8636_VENDOR_PN_END_OFFSET, "Vendor PN", items); + sff_show_ascii(id, SFF_8636_VENDOR_REV_START_OFFSET, + SFF_8636_VENDOR_REV_END_OFFSET, "Vendor rev", items); + sff_show_ascii(id, SFF_8636_VENDOR_SN_START_OFFSET, + SFF_8636_VENDOR_SN_END_OFFSET, "Vendor SN", items); + sff_show_ascii(id, SFF_8636_DATE_YEAR_OFFSET, + SFF_8636_DATE_VENDOR_LOT_OFFSET + 1, "Date code", items); + sff_8636_show_revision_compliance(id, items); + sff_8636_show_dom(id, eeprom_len, items); + } +} diff --git a/drivers/common/sff_module/sff_8636.h b/drivers/common/sff_module/sff_8636.h new file mode 100644 index 0000000000..d19e6c744e --- /dev/null +++ b/drivers/common/sff_module/sff_8636.h @@ -0,0 +1,592 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2022 Intel Corporation + * + * SFF-8636 standards based QSFP EEPROM Field Definitions + * + */ + +#ifndef SFF_8636_H__ +#define SFF_8636_H__ + +/*------------------------------------------------------------------------------ + * + * QSFP EEPROM data structures + * + * register info from SFF-8636 Rev 2.7 + */ + +/*------------------------------------------------------------------------------ + * + * Lower Memory Page 00h + * Measurement, Diagnostic and Control Functions + * + */ +/* Identifier - 0 */ +/* Values are defined under SFF_8024_ID_OFFSET */ +#define SFF_8636_ID_OFFSET 0x00 + +#define SFF_8636_REV_COMPLIANCE_OFFSET 0x01 +#define SFF_8636_REV_UNSPECIFIED 0x00 +#define SFF_8636_REV_8436_48 0x01 +#define SFF_8636_REV_8436_8636 0x02 +#define SFF_8636_REV_8636_13 0x03 +#define SFF_8636_REV_8636_14 0x04 +#define SFF_8636_REV_8636_15 0x05 +#define SFF_8636_REV_8636_20 0x06 +#define SFF_8636_REV_8636_27 0x07 + +#define SFF_8636_STATUS_2_OFFSET 0x02 +/* Flat Memory:0- Paging, 1- Page 0 only */ +#define SFF_8636_STATUS_PAGE_3_PRESENT (1 << 2) +#define SFF_8636_STATUS_INTL_OUTPUT (1 << 1) +#define SFF_8636_STATUS_DATA_NOT_READY (1 << 0) + +/* Channel Status Interrupt Flags - 3-5 */ +#define SFF_8636_LOS_AW_OFFSET 0x03 +#define SFF_8636_TX4_LOS_AW (1 << 7) +#define SFF_8636_TX3_LOS_AW (1 << 6) +#define SFF_8636_TX2_LOS_AW (1 << 5) +#define SFF_8636_TX1_LOS_AW (1 << 4) +#define SFF_8636_RX4_LOS_AW (1 << 3) +#define SFF_8636_RX3_LOS_AW (1 << 2) +#define SFF_8636_RX2_LOS_AW (1 << 1) +#define SFF_8636_RX1_LOS_AW (1 << 0) + +#define SFF_8636_FAULT_AW_OFFSET 0x04 +#define SFF_8636_TX4_FAULT_AW (1 << 3) +#define SFF_8636_TX3_FAULT_AW (1 << 2) +#define SFF_8636_TX2_FAULT_AW (1 << 1) +#define SFF_8636_TX1_FAULT_AW (1 << 0) + +/* Module Monitor Interrupt Flags - 6-8 */ +#define SFF_8636_TEMP_AW_OFFSET 0x06 +#define SFF_8636_TEMP_HALARM_STATUS (1 << 7) +#define SFF_8636_TEMP_LALARM_STATUS (1 << 6) +#define SFF_8636_TEMP_HWARN_STATUS (1 << 5) +#define SFF_8636_TEMP_LWARN_STATUS (1 << 4) + +#define SFF_8636_VCC_AW_OFFSET 0x07 +#define SFF_8636_VCC_HALARM_STATUS (1 << 7) +#define SFF_8636_VCC_LALARM_STATUS (1 << 6) +#define SFF_8636_VCC_HWARN_STATUS (1 << 5) +#define SFF_8636_VCC_LWARN_STATUS (1 << 4) + +/* Channel Monitor Interrupt Flags - 9-21 */ +#define SFF_8636_RX_PWR_12_AW_OFFSET 0x09 +#define SFF_8636_RX_PWR_1_HALARM (1 << 7) +#define SFF_8636_RX_PWR_1_LALARM (1 << 6) +#define SFF_8636_RX_PWR_1_HWARN (1 << 5) +#define SFF_8636_RX_PWR_1_LWARN (1 << 4) +#define SFF_8636_RX_PWR_2_HALARM (1 << 3) +#define SFF_8636_RX_PWR_2_LALARM (1 << 2) +#define SFF_8636_RX_PWR_2_HWARN (1 << 1) +#define SFF_8636_RX_PWR_2_LWARN (1 << 0) + +#define SFF_8636_RX_PWR_34_AW_OFFSET 0x0A +#define SFF_8636_RX_PWR_3_HALARM (1 << 7) +#define SFF_8636_RX_PWR_3_LALARM (1 << 6) +#define SFF_8636_RX_PWR_3_HWARN (1 << 5) +#define SFF_8636_RX_PWR_3_LWARN (1 << 4) +#define SFF_8636_RX_PWR_4_HALARM (1 << 3) +#define SFF_8636_RX_PWR_4_LALARM (1 << 2) +#define SFF_8636_RX_PWR_4_HWARN (1 << 1) +#define SFF_8636_RX_PWR_4_LWARN (1 << 0) + +#define SFF_8636_TX_BIAS_12_AW_OFFSET 0x0B +#define SFF_8636_TX_BIAS_1_HALARM (1 << 7) +#define SFF_8636_TX_BIAS_1_LALARM (1 << 6) +#define SFF_8636_TX_BIAS_1_HWARN (1 << 5) +#define SFF_8636_TX_BIAS_1_LWARN (1 << 4) +#define SFF_8636_TX_BIAS_2_HALARM (1 << 3) +#define SFF_8636_TX_BIAS_2_LALARM (1 << 2) +#define SFF_8636_TX_BIAS_2_HWARN (1 << 1) +#define SFF_8636_TX_BIAS_2_LWARN (1 << 0) + +#define SFF_8636_TX_BIAS_34_AW_OFFSET 0xC +#define SFF_8636_TX_BIAS_3_HALARM (1 << 7) +#define SFF_8636_TX_BIAS_3_LALARM (1 << 6) +#define SFF_8636_TX_BIAS_3_HWARN (1 << 5) +#define SFF_8636_TX_BIAS_3_LWARN (1 << 4) +#define SFF_8636_TX_BIAS_4_HALARM (1 << 3) +#define SFF_8636_TX_BIAS_4_LALARM (1 << 2) +#define SFF_8636_TX_BIAS_4_HWARN (1 << 1) +#define SFF_8636_TX_BIAS_4_LWARN (1 << 0) + +#define SFF_8636_TX_PWR_12_AW_OFFSET 0x0D +#define SFF_8636_TX_PWR_1_HALARM (1 << 7) +#define SFF_8636_TX_PWR_1_LALARM (1 << 6) +#define SFF_8636_TX_PWR_1_HWARN (1 << 5) +#define SFF_8636_TX_PWR_1_LWARN (1 << 4) +#define SFF_8636_TX_PWR_2_HALARM (1 << 3) +#define SFF_8636_TX_PWR_2_LALARM (1 << 2) +#define SFF_8636_TX_PWR_2_HWARN (1 << 1) +#define SFF_8636_TX_PWR_2_LWARN (1 << 0) + +#define SFF_8636_TX_PWR_34_AW_OFFSET 0x0E +#define SFF_8636_TX_PWR_3_HALARM (1 << 7) +#define SFF_8636_TX_PWR_3_LALARM (1 << 6) +#define SFF_8636_TX_PWR_3_HWARN (1 << 5) +#define SFF_8636_TX_PWR_3_LWARN (1 << 4) +#define SFF_8636_TX_PWR_4_HALARM (1 << 3) +#define SFF_8636_TX_PWR_4_LALARM (1 << 2) +#define SFF_8636_TX_PWR_4_HWARN (1 << 1) +#define SFF_8636_TX_PWR_4_LWARN (1 << 0) + +/* Module Monitoring Values - 22-33 */ +#define SFF_8636_TEMP_CURR 0x16 +#define SFF_8636_TEMP_MSB_OFFSET 0x16 +#define SFF_8636_TEMP_LSB_OFFSET 0x17 + +#define SFF_8636_VCC_CURR 0x1A +#define SFF_8636_VCC_MSB_OFFSET 0x1A +#define SFF_8636_VCC_LSB_OFFSET 0x1B + +/* Channel Monitoring Values - 34-81 */ +#define SFF_8636_RX_PWR_1_OFFSET 0x22 +#define SFF_8636_RX_PWR_2_OFFSET 0x24 +#define SFF_8636_RX_PWR_3_OFFSET 0x26 +#define SFF_8636_RX_PWR_4_OFFSET 0x28 + +#define SFF_8636_TX_BIAS_1_OFFSET 0x2A +#define SFF_8636_TX_BIAS_2_OFFSET 0x2C +#define SFF_8636_TX_BIAS_3_OFFSET 0x2E +#define SFF_8636_TX_BIAS_4_OFFSET 0x30 + +#define SFF_8636_TX_PWR_1_OFFSET 0x32 +#define SFF_8636_TX_PWR_2_OFFSET 0x34 +#define SFF_8636_TX_PWR_3_OFFSET 0x36 +#define SFF_8636_TX_PWR_4_OFFSET 0x38 + +/* Control Bytes - 86 - 99 */ +#define SFF_8636_TX_DISABLE_OFFSET 0x56 +#define SFF_8636_TX_DISABLE_4 (1 << 3) +#define SFF_8636_TX_DISABLE_3 (1 << 2) +#define SFF_8636_TX_DISABLE_2 (1 << 1) +#define SFF_8636_TX_DISABLE_1 (1 << 0) + +#define SFF_8636_RX_RATE_SELECT_OFFSET 0x57 +#define SFF_8636_RX_RATE_SELECT_4_MASK (3 << 6) +#define SFF_8636_RX_RATE_SELECT_3_MASK (3 << 4) +#define SFF_8636_RX_RATE_SELECT_2_MASK (3 << 2) +#define SFF_8636_RX_RATE_SELECT_1_MASK (3 << 0) + +#define SFF_8636_TX_RATE_SELECT_OFFSET 0x58 +#define SFF_8636_TX_RATE_SELECT_4_MASK (3 << 6) +#define SFF_8636_TX_RATE_SELECT_3_MASK (3 << 4) +#define SFF_8636_TX_RATE_SELECT_2_MASK (3 << 2) +#define SFF_8636_TX_RATE_SELECT_1_MASK (3 << 0) + +#define SFF_8636_RX_APP_SELECT_4_OFFSET 0x58 +#define SFF_8636_RX_APP_SELECT_3_OFFSET 0x59 +#define SFF_8636_RX_APP_SELECT_2_OFFSET 0x5A +#define SFF_8636_RX_APP_SELECT_1_OFFSET 0x5B + +#define SFF_8636_PWR_MODE_OFFSET 0x5D +#define SFF_8636_HIGH_PWR_ENABLE (1 << 2) +#define SFF_8636_LOW_PWR_MODE (1 << 1) +#define SFF_8636_PWR_OVERRIDE (1 << 0) + +#define SFF_8636_TX_APP_SELECT_4_OFFSET 0x5E +#define SFF_8636_TX_APP_SELECT_3_OFFSET 0x5F +#define SFF_8636_TX_APP_SELECT_2_OFFSET 0x60 +#define SFF_8636_TX_APP_SELECT_1_OFFSET 0x61 + +#define SFF_8636_LOS_MASK_OFFSET 0x64 +#define SFF_8636_TX_LOS_4_MASK (1 << 7) +#define SFF_8636_TX_LOS_3_MASK (1 << 6) +#define SFF_8636_TX_LOS_2_MASK (1 << 5) +#define SFF_8636_TX_LOS_1_MASK (1 << 4) +#define SFF_8636_RX_LOS_4_MASK (1 << 3) +#define SFF_8636_RX_LOS_3_MASK (1 << 2) +#define SFF_8636_RX_LOS_2_MASK (1 << 1) +#define SFF_8636_RX_LOS_1_MASK (1 << 0) + +#define SFF_8636_FAULT_MASK_OFFSET 0x65 +#define SFF_8636_TX_FAULT_1_MASK (1 << 3) +#define SFF_8636_TX_FAULT_2_MASK (1 << 2) +#define SFF_8636_TX_FAULT_3_MASK (1 << 1) +#define SFF_8636_TX_FAULT_4_MASK (1 << 0) + +#define SFF_8636_TEMP_MASK_OFFSET 0x67 +#define SFF_8636_TEMP_HALARM_MASK (1 << 7) +#define SFF_8636_TEMP_LALARM_MASK (1 << 6) +#define SFF_8636_TEMP_HWARN_MASK (1 << 5) +#define SFF_8636_TEMP_LWARN_MASK (1 << 4) + +#define SFF_8636_VCC_MASK_OFFSET 0x68 +#define SFF_8636_VCC_HALARM_MASK (1 << 7) +#define SFF_8636_VCC_LALARM_MASK (1 << 6) +#define SFF_8636_VCC_HWARN_MASK (1 << 5) +#define SFF_8636_VCC_LWARN_MASK (1 << 4) + +/*------------------------------------------------------------------------------ + * + * Upper Memory Page 00h + * Serial ID - Base ID, Extended ID and Vendor Specific ID fields + * + */ +/* Identifier - 128 */ +/* Identifier values same as Lower Memory Page 00h */ +#define SFF_8636_UPPER_PAGE_0_ID_OFFSET 0x80 + +/* Extended Identifier - 128 */ +#define SFF_8636_EXT_ID_OFFSET 0x81 +#define SFF_8636_EXT_ID_PWR_CLASS_MASK 0xC0 +#define SFF_8636_EXT_ID_PWR_CLASS_1 (0 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_2 (1 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_3 (2 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_4 (3 << 6) +#define SFF_8636_EXT_ID_CLIE_MASK 0x10 +#define SFF_8636_EXT_ID_CLIEI_CODE_PRESENT (1 << 4) +#define SFF_8636_EXT_ID_CDR_TX_MASK 0x08 +#define SFF_8636_EXT_ID_CDR_TX_PRESENT (1 << 3) +#define SFF_8636_EXT_ID_CDR_RX_MASK 0x04 +#define SFF_8636_EXT_ID_CDR_RX_PRESENT (1 << 2) +#define SFF_8636_EXT_ID_EPWR_CLASS_MASK 0x03 +#define SFF_8636_EXT_ID_PWR_CLASS_LEGACY 0 +#define SFF_8636_EXT_ID_PWR_CLASS_5 1 +#define SFF_8636_EXT_ID_PWR_CLASS_6 2 +#define SFF_8636_EXT_ID_PWR_CLASS_7 3 + +/* Connector Values offset - 130 */ +/* Values are defined under SFF_8024_CTOR */ +#define SFF_8636_CTOR_OFFSET 0x82 +#define SFF_8636_CTOR_UNKNOWN 0x00 +#define SFF_8636_CTOR_SC 0x01 +#define SFF_8636_CTOR_FC_STYLE_1 0x02 +#define SFF_8636_CTOR_FC_STYLE_2 0x03 +#define SFF_8636_CTOR_BNC_TNC 0x04 +#define SFF_8636_CTOR_FC_COAX 0x05 +#define SFF_8636_CTOR_FIBER_JACK 0x06 +#define SFF_8636_CTOR_LC 0x07 +#define SFF_8636_CTOR_MT_RJ 0x08 +#define SFF_8636_CTOR_MU 0x09 +#define SFF_8636_CTOR_SG 0x0A +#define SFF_8636_CTOR_OPT_PT 0x0B +#define SFF_8636_CTOR_MPO 0x0C +/* 0D-1Fh --- Reserved */ +#define SFF_8636_CTOR_HSDC_II 0x20 +#define SFF_8636_CTOR_COPPER_PT 0x21 +#define SFF_8636_CTOR_RJ45 0x22 +#define SFF_8636_CTOR_NO_SEPARABLE 0x23 +#define SFF_8636_CTOR_MXC_2X16 0x24 + +/* Specification Compliance - 131-138 */ +/* Ethernet Compliance Codes - 131 */ +#define SFF_8636_ETHERNET_COMP_OFFSET 0x83 +#define SFF_8636_ETHERNET_RSRVD (1 << 7) +#define SFF_8636_ETHERNET_10G_LRM (1 << 6) +#define SFF_8636_ETHERNET_10G_LR (1 << 5) +#define SFF_8636_ETHERNET_10G_SR (1 << 4) +#define SFF_8636_ETHERNET_40G_CR4 (1 << 3) +#define SFF_8636_ETHERNET_40G_SR4 (1 << 2) +#define SFF_8636_ETHERNET_40G_LR4 (1 << 1) +#define SFF_8636_ETHERNET_40G_ACTIVE (1 << 0) + +/* SONET Compliance Codes - 132 */ +#define SFF_8636_SONET_COMP_OFFSET 0x84 +#define SFF_8636_SONET_40G_OTN (1 << 3) +#define SFF_8636_SONET_OC48_LR (1 << 2) +#define SFF_8636_SONET_OC48_IR (1 << 1) +#define SFF_8636_SONET_OC48_SR (1 << 0) + +/* SAS/SATA Complaince Codes - 133 */ +#define SFF_8636_SAS_COMP_OFFSET 0x85 +#define SFF_8636_SAS_12G (1 << 6) +#define SFF_8636_SAS_6G (1 << 5) +#define SFF_8636_SAS_3G (1 << 4) + +/* Gigabit Ethernet Compliance Codes - 134 */ +#define SFF_8636_GIGE_COMP_OFFSET 0x86 +#define SFF_8636_GIGE_1000_BASE_T (1 << 3) +#define SFF_8636_GIGE_1000_BASE_CX (1 << 2) +#define SFF_8636_GIGE_1000_BASE_LX (1 << 1) +#define SFF_8636_GIGE_1000_BASE_SX (1 << 0) + +/* Fibre Channel Link length/Transmitter Tech. - 135,136 */ +#define SFF_8636_FC_LEN_OFFSET 0x87 +#define SFF_8636_FC_LEN_VERY_LONG (1 << 7) +#define SFF_8636_FC_LEN_SHORT (1 << 6) +#define SFF_8636_FC_LEN_INT (1 << 5) +#define SFF_8636_FC_LEN_LONG (1 << 4) +#define SFF_8636_FC_LEN_MED (1 << 3) +#define SFF_8636_FC_TECH_LONG_LC (1 << 1) +#define SFF_8636_FC_TECH_ELEC_INTER (1 << 0) + +#define SFF_8636_FC_TECH_OFFSET 0x88 +#define SFF_8636_FC_TECH_ELEC_INTRA (1 << 7) +#define SFF_8636_FC_TECH_SHORT_WO_OFC (1 << 6) +#define SFF_8636_FC_TECH_SHORT_W_OFC (1 << 5) +#define SFF_8636_FC_TECH_LONG_LL (1 << 4) + +/* Fibre Channel Transmitter Media - 137 */ +#define SFF_8636_FC_TRANS_MEDIA_OFFSET 0x89 +/* Twin Axial Pair */ +#define SFF_8636_FC_TRANS_MEDIA_TW (1 << 7) +/* Shielded Twisted Pair */ +#define SFF_8636_FC_TRANS_MEDIA_TP (1 << 6) +/* Miniature Coax */ +#define SFF_8636_FC_TRANS_MEDIA_MI (1 << 5) +/* Video Coax */ +#define SFF_8636_FC_TRANS_MEDIA_TV (1 << 4) +/* Multi-mode 62.5m */ +#define SFF_8636_FC_TRANS_MEDIA_M6 (1 << 3) +/* Multi-mode 50m */ +#define SFF_8636_FC_TRANS_MEDIA_M5 (1 << 2) +/* Multi-mode 50um */ +#define SFF_8636_FC_TRANS_MEDIA_OM3 (1 << 1) +/* Single Mode */ +#define SFF_8636_FC_TRANS_MEDIA_SM (1 << 0) + +/* Fibre Channel Speed - 138 */ +#define SFF_8636_FC_SPEED_OFFSET 0x8A +#define SFF_8636_FC_SPEED_1200_MBPS (1 << 7) +#define SFF_8636_FC_SPEED_800_MBPS (1 << 6) +#define SFF_8636_FC_SPEED_1600_MBPS (1 << 5) +#define SFF_8636_FC_SPEED_400_MBPS (1 << 4) +#define SFF_8636_FC_SPEED_200_MBPS (1 << 2) +#define SFF_8636_FC_SPEED_100_MBPS (1 << 0) + +/* Encoding - 139 */ +/* Values are defined under SFF_8024_ENCODING */ +#define SFF_8636_ENCODING_OFFSET 0x8B +#define SFF_8636_ENCODING_MANCHESTER 0x06 +#define SFF_8636_ENCODING_64B66B 0x05 +#define SFF_8636_ENCODING_SONET 0x04 +#define SFF_8636_ENCODING_NRZ 0x03 +#define SFF_8636_ENCODING_4B5B 0x02 +#define SFF_8636_ENCODING_8B10B 0x01 +#define SFF_8636_ENCODING_UNSPEC 0x00 + +/* BR, Nominal - 140 */ +#define SFF_8636_BR_NOMINAL_OFFSET 0x8C + +/* Extended RateSelect - 141 */ +#define SFF_8636_EXT_RS_OFFSET 0x8D +#define SFF_8636_EXT_RS_V1 (1 << 0) + +/* Length (Standard SM Fiber)-km - 142 */ +#define SFF_8636_SM_LEN_OFFSET 0x8E + +/* Length (OM3)-Unit 2m - 143 */ +#define SFF_8636_OM3_LEN_OFFSET 0x8F + +/* Length (OM2)-Unit 1m - 144 */ +#define SFF_8636_OM2_LEN_OFFSET 0x90 + +/* Length (OM1)-Unit 1m - 145 */ +#define SFF_8636_OM1_LEN_OFFSET 0x91 + +/* Cable Assembly Length -Unit 1m - 146 */ +#define SFF_8636_CBL_LEN_OFFSET 0x92 + +/* Device Technology - 147 */ +#define SFF_8636_DEVICE_TECH_OFFSET 0x93 +/* Transmitter Technology */ +#define SFF_8636_TRANS_TECH_MASK 0xF0 +/* Copper cable, linear active equalizers */ +#define SFF_8636_TRANS_COPPER_LNR_EQUAL (15 << 4) +/* Copper cable, near end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_NEAR_EQUAL (14 << 4) +/* Copper cable, far end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_FAR_EQUAL (13 << 4) +/* Copper cable, near & far end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_LNR_FAR_EQUAL (12 << 4) +/* Copper cable, passive equalized */ +#define SFF_8636_TRANS_COPPER_PAS_EQUAL (11 << 4) +/* Copper cable, unequalized */ +#define SFF_8636_TRANS_COPPER_PAS_UNEQUAL (10 << 4) +/* 1490 nm DFB */ +#define SFF_8636_TRANS_1490_DFB (9 << 4) +/* Others */ +#define SFF_8636_TRANS_OTHERS (8 << 4) +/* 1550 nm EML */ +#define SFF_8636_TRANS_1550_EML (7 << 4) +/* 1310 nm EML */ +#define SFF_8636_TRANS_1310_EML (6 << 4) +/* 1550 nm DFB */ +#define SFF_8636_TRANS_1550_DFB (5 << 4) +/* 1310 nm DFB */ +#define SFF_8636_TRANS_1310_DFB (4 << 4) +/* 1310 nm FP */ +#define SFF_8636_TRANS_1310_FP (3 << 4) +/* 1550 nm VCSEL */ +#define SFF_8636_TRANS_1550_VCSEL (2 << 4) +/* 1310 nm VCSEL */ +#define SFF_8636_TRANS_1310_VCSEL (1 << 4) +/* 850 nm VCSEL */ +#define SFF_8636_TRANS_850_VCSEL (0 << 4) + + /* Active/No wavelength control */ +#define SFF_8636_DEV_TECH_ACTIVE_WAVE_LEN (1 << 3) +/* Cooled transmitter */ +#define SFF_8636_DEV_TECH_COOL_TRANS (1 << 2) +/* APD/Pin Detector */ +#define SFF_8636_DEV_TECH_APD_DETECTOR (1 << 1) +/* Transmitter tunable */ +#define SFF_8636_DEV_TECH_TUNABLE (1 << 0) + +/* Vendor Name - 148-163 */ +#define SFF_8636_VENDOR_NAME_START_OFFSET 0x94 +#define SFF_8636_VENDOR_NAME_END_OFFSET 0xA3 + +/* Extended Module Codes - 164 */ +#define SFF_8636_EXT_MOD_CODE_OFFSET 0xA4 +#define SFF_8636_EXT_MOD_INFINIBAND_EDR (1 << 4) +#define SFF_8636_EXT_MOD_INFINIBAND_FDR (1 << 3) +#define SFF_8636_EXT_MOD_INFINIBAND_QDR (1 << 2) +#define SFF_8636_EXT_MOD_INFINIBAND_DDR (1 << 1) +#define SFF_8636_EXT_MOD_INFINIBAND_SDR (1 << 0) + +/* Vendor OUI - 165-167 */ +#define SFF_8636_VENDOR_OUI_OFFSET 0xA5 +#define SFF_8636_VENDOR_OUI_LEN 3 + +/* Vendor OUI - 165-167 */ +#define SFF_8636_VENDOR_PN_START_OFFSET 0xA8 +#define SFF_8636_VENDOR_PN_END_OFFSET 0xB7 + +/* Vendor Revision - 184-185 */ +#define SFF_8636_VENDOR_REV_START_OFFSET 0xB8 +#define SFF_8636_VENDOR_REV_END_OFFSET 0xB9 + +/* Wavelength - 186-187 */ +#define SFF_8636_WAVELEN_HIGH_BYTE_OFFSET 0xBA +#define SFF_8636_WAVELEN_LOW_BYTE_OFFSET 0xBB + +/* Wavelength Tolerance- 188-189 */ +#define SFF_8636_WAVE_TOL_HIGH_BYTE_OFFSET 0xBC +#define SFF_8636_WAVE_TOL_LOW_BYTE_OFFSET 0xBD + +/* Max case temp - Other than 70 C - 190 */ +#define SFF_8636_MAXCASE_TEMP_OFFSET 0xBE + +/* CC_BASE - 191 */ +#define SFF_8636_CC_BASE_OFFSET 0xBF + +/* Option Values - 192-195 */ +#define SFF_8636_OPTION_1_OFFSET 0xC0 +#define SFF_8636_ETHERNET_UNSPECIFIED 0x00 +#define SFF_8636_ETHERNET_100G_AOC 0x01 +#define SFF_8636_ETHERNET_100G_SR4 0x02 +#define SFF_8636_ETHERNET_100G_LR4 0x03 +#define SFF_8636_ETHERNET_100G_ER4 0x04 +#define SFF_8636_ETHERNET_100G_SR10 0x05 +#define SFF_8636_ETHERNET_100G_CWDM4_FEC 0x06 +#define SFF_8636_ETHERNET_100G_PSM4 0x07 +#define SFF_8636_ETHERNET_100G_ACC 0x08 +#define SFF_8636_ETHERNET_100G_CWDM4_NO_FEC 0x09 +#define SFF_8636_ETHERNET_100G_RSVD1 0x0A +#define SFF_8636_ETHERNET_100G_CR4 0x0B +#define SFF_8636_ETHERNET_25G_CR_CA_S 0x0C +#define SFF_8636_ETHERNET_25G_CR_CA_N 0x0D +#define SFF_8636_ETHERNET_40G_ER4 0x10 +#define SFF_8636_ETHERNET_4X10_SR 0x11 +#define SFF_8636_ETHERNET_40G_PSM4 0x12 +#define SFF_8636_ETHERNET_G959_P1I1_2D1 0x13 +#define SFF_8636_ETHERNET_G959_P1S1_2D2 0x14 +#define SFF_8636_ETHERNET_G959_P1L1_2D2 0x15 +#define SFF_8636_ETHERNET_10GT_SFI 0x16 +#define SFF_8636_ETHERNET_100G_CLR4 0x17 +#define SFF_8636_ETHERNET_100G_AOC2 0x18 +#define SFF_8636_ETHERNET_100G_ACC2 0x19 + +#define SFF_8636_OPTION_2_OFFSET 0xC1 +/* Rx output amplitude */ +#define SFF_8636_O2_RX_OUTPUT_AMP (1 << 0) +#define SFF_8636_OPTION_3_OFFSET 0xC2 +/* Rx Squelch Disable */ +#define SFF_8636_O3_RX_SQL_DSBL (1 << 3) +/* Rx Output Disable capable */ +#define SFF_8636_O3_RX_OUTPUT_DSBL (1 << 2) +/* Tx Squelch Disable */ +#define SFF_8636_O3_TX_SQL_DSBL (1 << 1) +/* Tx Squelch Impl */ +#define SFF_8636_O3_TX_SQL_IMPL (1 << 0) +#define SFF_8636_OPTION_4_OFFSET 0xC3 +/* Memory Page 02 present */ +#define SFF_8636_O4_PAGE_02_PRESENT (1 << 7) +/* Memory Page 01 present */ +#define SFF_8636_O4_PAGE_01_PRESENT (1 << 6) +/* Rate Select implemented */ +#define SFF_8636_O4_RATE_SELECT (1 << 5) +/* Tx_DISABLE implemented */ +#define SFF_8636_O4_TX_DISABLE (1 << 4) +/* Tx_FAULT implemented */ +#define SFF_8636_O4_TX_FAULT (1 << 3) +/* Tx Squelch implemented */ +#define SFF_8636_O4_TX_SQUELCH (1 << 2) +/* Tx Loss of Signal */ +#define SFF_8636_O4_TX_LOS (1 << 1) + +/* Vendor SN - 196-211 */ +#define SFF_8636_VENDOR_SN_START_OFFSET 0xC4 +#define SFF_8636_VENDOR_SN_END_OFFSET 0xD3 + +/* Vendor Date - 212-219 */ +#define SFF_8636_DATE_YEAR_OFFSET 0xD4 +#define SFF_8636_DATE_YEAR_LEN 2 +#define SFF_8636_DATE_MONTH_OFFSET 0xD6 +#define SFF_8636_DATE_MONTH_LEN 2 +#define SFF_8636_DATE_DAY_OFFSET 0xD8 +#define SFF_8636_DATE_DAY_LEN 2 +#define SFF_8636_DATE_VENDOR_LOT_OFFSET 0xDA +#define SFF_8636_DATE_VENDOR_LOT_LEN 2 + +/* Diagnostic Monitoring Type - 220 */ +#define SFF_8636_DIAG_TYPE_OFFSET 0xDC +#define SFF_8636_RX_PWR_TYPE_MASK 0x8 +#define SFF_8636_RX_PWR_TYPE_AVG_PWR (1 << 3) +#define SFF_8636_RX_PWR_TYPE_OMA (0 << 3) +#define SFF_8636_TX_PWR_TYPE_MASK 0x4 +#define SFF_8636_TX_PWR_TYPE_AVG_PWR (1 << 2) + +/* Enhanced Options - 221 */ +#define SFF_8636_ENH_OPTIONS_OFFSET 0xDD +#define SFF_8636_RATE_SELECT_EXT_SUPPORT (1 << 3) +#define SFF_8636_RATE_SELECT_APP_TABLE_SUPPORT (1 << 2) + +/* Check code - 223 */ +#define SFF_8636_CC_EXT_OFFSET 0xDF +#define SFF_8636_CC_EXT_LEN 1 + +/*------------------------------------------------------------------------------ + * + * Upper Memory Page 03h + * Contains module thresholds, channel thresholds and masks, + * and optional channel controls + * + * Offset - Page Num(3) * PageSize(0x80) + Page offset + */ + +/* Module Thresholds (48 Bytes) 128-175 */ +/* MSB at low address, LSB at high address */ +#define SFF_8636_TEMP_HALRM 0x200 +#define SFF_8636_TEMP_LALRM 0x202 +#define SFF_8636_TEMP_HWARN 0x204 +#define SFF_8636_TEMP_LWARN 0x206 + +#define SFF_8636_VCC_HALRM 0x210 +#define SFF_8636_VCC_LALRM 0x212 +#define SFF_8636_VCC_HWARN 0x214 +#define SFF_8636_VCC_LWARN 0x216 + +#define SFF_8636_RX_PWR_HALRM 0x230 +#define SFF_8636_RX_PWR_LALRM 0x232 +#define SFF_8636_RX_PWR_HWARN 0x234 +#define SFF_8636_RX_PWR_LWARN 0x236 + +#define SFF_8636_TX_BIAS_HALRM 0x238 +#define SFF_8636_TX_BIAS_LALRM 0x23A +#define SFF_8636_TX_BIAS_HWARN 0x23C +#define SFF_8636_TX_BIAS_LWARN 0x23E + +#define SFF_8636_TX_PWR_HALRM 0x240 +#define SFF_8636_TX_PWR_LALRM 0x242 +#define SFF_8636_TX_PWR_HWARN 0x244 +#define SFF_8636_TX_PWR_LWARN 0x246 + +#define ETH_MODULE_SFF_8636_MAX_LEN 640 +#define ETH_MODULE_SFF_8436_MAX_LEN 640 + +#endif /*SFF_8636_H__ */ diff --git a/drivers/common/sff_module/sff_common.c b/drivers/common/sff_module/sff_common.c new file mode 100644 index 0000000000..e5bc18650c --- /dev/null +++ b/drivers/common/sff_module/sff_common.c @@ -0,0 +1,415 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2022 Intel Corporation + * + * Implements SFF-8024 Rev 4.0 of pluggable I/O configuration + * + * Common utilities for SFF-8436/8636 and SFF-8472/8079 + * + */ + +#include <stdio.h> +#include <math.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "sff_telemetry.h" + + +double convert_mw_to_dbm(double mw) +{ + return (10. * log10(mw / 1000.)) + 30.; +} + +void sff_show_value_with_unit(const uint8_t *id, unsigned int reg, + const char *name, unsigned int mult, + const char *unit, sff_item *items) +{ + unsigned int val = id[reg]; + char val_string[TMP_STRING_SIZE]; + + printf("%-41s : %u%s\n", name, val * mult, unit); + sprintf(val_string, "%u%s", val * mult, unit); + add_item_string(items, name, val_string); +} + +void sff_show_ascii(const uint8_t *id, unsigned int first_reg, + unsigned int last_reg, const char *name, sff_item *items) +{ + unsigned int reg, val; + char tmp[3]; + char val_string[TMP_STRING_SIZE]; + + memset(val_string, 0, sizeof(val_string)); + + printf("%-41s : ", name); + while (first_reg <= last_reg && id[last_reg] == ' ') + last_reg--; + for (reg = first_reg; reg <= last_reg; reg++) { + val = id[reg]; + putchar(((val >= 32) && (val <= 126)) ? val : '_'); + if ((val >= 32) && (val <= 126)) { + sprintf(tmp, "%c", val); + strcat(val_string, tmp); + } else { + strcat(val_string, "_"); + } + } + printf("\n"); + add_item_string(items, name, val_string); +} + +void sff_8024_show_oui(const uint8_t *id, int id_offset, sff_item *items) +{ + char val_string[TMP_STRING_SIZE]; + + printf("%-41s : %02x:%02x:%02x\n", "Vendor OUI", + id[id_offset], id[(id_offset) + 1], + id[(id_offset) + 2]); + sprintf(val_string, "%02x:%02x:%02x", + id[id_offset], id[(id_offset) + 1], id[(id_offset) + 2]); + add_item_string(items, "Vendor OUI", val_string); +} + +void sff_8024_show_identifier(const uint8_t *id, int id_offset, sff_item *items) +{ + char val_string[TMP_STRING_SIZE]; + + printf("%-41s : 0x%02x", "Identifier", id[id_offset]); + sprintf(val_string, "0x%02x", id[id_offset]); + + switch (id[id_offset]) { + case SFF_8024_ID_UNKNOWN: + printf(" (no module present, unknown, or unspecified)\n"); + strcat(val_string, " (no module present, unknown, or unspecified)"); + break; + case SFF_8024_ID_GBIC: + printf(" (GBIC)\n"); + strcat(val_string, " (GBIC)"); + break; + case SFF_8024_ID_SOLDERED_MODULE: + printf(" (module soldered to motherboard)\n"); + strcat(val_string, " (module soldered to motherboard)"); + break; + case SFF_8024_ID_SFP: + printf(" (SFP)\n"); + strcat(val_string, " (SFP)"); + break; + case SFF_8024_ID_300_PIN_XBI: + printf(" (300 pin XBI)\n"); + strcat(val_string, " (300 pin XBI)"); + break; + case SFF_8024_ID_XENPAK: + printf(" (XENPAK)\n"); + strcat(val_string, " (XENPAK)"); + break; + case SFF_8024_ID_XFP: + printf(" (XFP)\n"); + strcat(val_string, " (XFP)"); + break; + case SFF_8024_ID_XFF: + printf(" (XFF)\n"); + strcat(val_string, " (XFF)"); + break; + case SFF_8024_ID_XFP_E: + printf(" (XFP-E)\n"); + strcat(val_string, " (XFP-E)"); + break; + case SFF_8024_ID_XPAK: + printf(" (XPAK)\n"); + strcat(val_string, " (XPAK)"); + break; + case SFF_8024_ID_X2: + printf(" (X2)\n"); + strcat(val_string, " (X2)"); + break; + case SFF_8024_ID_DWDM_SFP: + printf(" (DWDM-SFP)\n"); + strcat(val_string, " (DWDM-SFP)"); + break; + case SFF_8024_ID_QSFP: + printf(" (QSFP)\n"); + strcat(val_string, " (QSFP)"); + break; + case SFF_8024_ID_QSFP_PLUS: + printf(" (QSFP+)\n"); + strcat(val_string, " (QSFP+)"); + break; + case SFF_8024_ID_CXP: + printf(" (CXP)\n"); + strcat(val_string, " (CXP)"); + break; + case SFF_8024_ID_HD4X: + printf(" (Shielded Mini Multilane HD 4X)\n"); + strcat(val_string, " (Shielded Mini Multilane HD 4X)"); + break; + case SFF_8024_ID_HD8X: + printf(" (Shielded Mini Multilane HD 8X)\n"); + strcat(val_string, " (Shielded Mini Multilane HD 8X)"); + break; + case SFF_8024_ID_QSFP28: + printf(" (QSFP28)\n"); + strcat(val_string, " (QSFP28)"); + break; + case SFF_8024_ID_CXP2: + printf(" (CXP2/CXP28)\n"); + strcat(val_string, " (CXP2/CXP28)"); + break; + case SFF_8024_ID_CDFP: + printf(" (CDFP Style 1/Style 2)\n"); + strcat(val_string, " (CDFP Style 1/Style 2)"); + break; + case SFF_8024_ID_HD4X_FANOUT: + printf(" (Shielded Mini Multilane HD 4X Fanout Cable)\n"); + strcat(val_string, " (Shielded Mini Multilane HD 4X Fanout Cable)"); + break; + case SFF_8024_ID_HD8X_FANOUT: + printf(" (Shielded Mini Multilane HD 8X Fanout Cable)\n"); + strcat(val_string, " (Shielded Mini Multilane HD 8X Fanout Cable)"); + break; + case SFF_8024_ID_CDFP_S3: + printf(" (CDFP Style 3)\n"); + strcat(val_string, " (CDFP Style 3)"); + break; + case SFF_8024_ID_MICRO_QSFP: + printf(" (microQSFP)\n"); + strcat(val_string, " (microQSFP)"); + break; + default: + printf(" (reserved or unknown)\n"); + strcat(val_string, " (reserved or unknown)"); + break; + } + add_item_string(items, "Identifier", val_string); +} + +void sff_8024_show_connector(const uint8_t *id, int ctor_offset, sff_item *items) +{ + char val_string[TMP_STRING_SIZE]; + + printf("%-41s : 0x%02x", "Connector", id[ctor_offset]); + sprintf(val_string, "0x%02x", id[ctor_offset]); + + switch (id[ctor_offset]) { + case SFF_8024_CTOR_UNKNOWN: + printf(" (unknown or unspecified)\n"); + strcat(val_string, " (unknown or unspecified)"); + break; + case SFF_8024_CTOR_SC: + printf(" (SC)\n"); + strcat(val_string, " (SC)"); + break; + case SFF_8024_CTOR_FC_STYLE_1: + printf(" (Fibre Channel Style 1 copper)\n"); + strcat(val_string, " (Fibre Channel Style 1 copper)"); + break; + case SFF_8024_CTOR_FC_STYLE_2: + printf(" (Fibre Channel Style 2 copper)\n"); + strcat(val_string, " (Fibre Channel Style 2 copper)"); + break; + case SFF_8024_CTOR_BNC_TNC: + printf(" (BNC/TNC)\n"); + strcat(val_string, " (BNC/TNC)"); + break; + case SFF_8024_CTOR_FC_COAX: + printf(" (Fibre Channel coaxial headers)\n"); + strcat(val_string, " (Fibre Channel coaxial headers)"); + break; + case SFF_8024_CTOR_FIBER_JACK: + printf(" (FibreJack)\n"); + strcat(val_string, " (FibreJack)"); + break; + case SFF_8024_CTOR_LC: + printf(" (LC)\n"); + strcat(val_string, " (LC)"); + break; + case SFF_8024_CTOR_MT_RJ: + printf(" (MT-RJ)\n"); + strcat(val_string, " (MT-RJ)"); + break; + case SFF_8024_CTOR_MU: + printf(" (MU)\n"); + strcat(val_string, " (MU)"); + break; + case SFF_8024_CTOR_SG: + printf(" (SG)\n"); + strcat(val_string, " (SG)"); + break; + case SFF_8024_CTOR_OPT_PT: + printf(" (Optical pigtail)\n"); + strcat(val_string, " (Optical pigtail)"); + break; + case SFF_8024_CTOR_MPO: + printf(" (MPO Parallel Optic)\n"); + strcat(val_string, " (MPO Parallel Optic)"); + break; + case SFF_8024_CTOR_MPO_2: + printf(" (MPO Parallel Optic - 2x16)\n"); + strcat(val_string, " (MPO Parallel Optic - 2x16)"); + break; + case SFF_8024_CTOR_HSDC_II: + printf(" (HSSDC II)\n"); + strcat(val_string, " (HSSDC II)"); + break; + case SFF_8024_CTOR_COPPER_PT: + printf(" (Copper pigtail)\n"); + strcat(val_string, " (Copper pigtail)"); + break; + case SFF_8024_CTOR_RJ45: + printf(" (RJ45)\n"); + strcat(val_string, " (RJ45)"); + break; + case SFF_8024_CTOR_NO_SEPARABLE: + printf(" (No separable connector)\n"); + strcat(val_string, " (No separable connector)"); + break; + case SFF_8024_CTOR_MXC_2x16: + printf(" (MXC 2x16)\n"); + strcat(val_string, " (MXC 2x16)"); + break; + default: + printf(" (reserved or unknown)\n"); + strcat(val_string, " (reserved or unknown)"); + break; + } + add_item_string(items, "Connector", val_string); +} + +void sff_8024_show_encoding(const uint8_t *id, int encoding_offset, + int sff_type, sff_item *items) +{ + char val_string[TMP_STRING_SIZE]; + + printf("%-41s : 0x%02x", "Encoding", id[encoding_offset]); + sprintf(val_string, "0x%02x", id[encoding_offset]); + + switch (id[encoding_offset]) { + case SFF_8024_ENCODING_UNSPEC: + printf(" (unspecified)\n"); + strcat(val_string, " (unspecified)"); + break; + case SFF_8024_ENCODING_8B10B: + printf(" (8B/10B)\n"); + strcat(val_string, " (8B/10B)"); + break; + case SFF_8024_ENCODING_4B5B: + printf(" (4B/5B)\n"); + strcat(val_string, " (4B/5B)"); + break; + case SFF_8024_ENCODING_NRZ: + printf(" (NRZ)\n"); + strcat(val_string, " (NRZ)"); + break; + case SFF_8024_ENCODING_4h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) { + printf(" (Manchester)\n"); + strcat(val_string, " (Manchester)"); + } else if (sff_type == RTE_ETH_MODULE_SFF_8636) { + printf(" (SONET Scrambled)\n"); + strcat(val_string, " (SONET Scrambled)"); + } + break; + case SFF_8024_ENCODING_5h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) { + printf(" (SONET Scrambled)\n"); + strcat(val_string, " (SONET Scrambled)"); + } else if (sff_type == RTE_ETH_MODULE_SFF_8636) { + printf(" (64B/66B)\n"); + strcat(val_string, " (64B/66B)"); + } + break; + case SFF_8024_ENCODING_6h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) { + printf(" (64B/66B)\n"); + strcat(val_string, " (64B/66B)"); + } else if (sff_type == RTE_ETH_MODULE_SFF_8636) { + printf(" (Manchester)\n"); + strcat(val_string, " (Manchester)"); + } + break; + case SFF_8024_ENCODING_256B: + printf(" ((256B/257B (transcoded FEC-enabled data))\n"); + strcat(val_string, + " ((256B/257B (transcoded FEC-enabled data))"); + break; + case SFF_8024_ENCODING_PAM4: + printf(" (PAM4)\n"); + strcat(val_string, " (PAM4)"); + break; + default: + printf(" (reserved or unknown)\n"); + strcat(val_string, " (reserved or unknown)"); + break; + } + add_item_string(items, "Encoding", val_string); +} + +void sff_show_thresholds(struct sff_diags sd, sff_item *items) +{ + char val_string[TMP_STRING_SIZE]; + + PRINT_BIAS("Laser bias current high alarm threshold", sd.bias_cur[HALRM]); + SPRINT_BIAS(val_string, sd.bias_cur[HALRM]); + add_item_string(items, "Laser bias current high alarm threshold", val_string); + PRINT_BIAS("Laser bias current low alarm threshold", sd.bias_cur[LALRM]); + SPRINT_BIAS(val_string, sd.bias_cur[LALRM]); + add_item_string(items, "Laser bias current low alarm threshold", val_string); + PRINT_BIAS("Laser bias current high warning threshold", sd.bias_cur[HWARN]); + SPRINT_BIAS(val_string, sd.bias_cur[HWARN]); + add_item_string(items, "Laser bias current high warning threshold", val_string); + PRINT_BIAS("Laser bias current low warning threshold", sd.bias_cur[LWARN]); + SPRINT_BIAS(val_string, sd.bias_cur[LWARN]); + add_item_string(items, "Laser bias current low warning threshold", val_string); + + PRINT_xX_PWR("Laser output power high alarm threshold", sd.tx_power[HALRM]); + SPRINT_xX_PWR(val_string, sd.tx_power[HALRM]); + add_item_string(items, "Laser output power high alarm threshold", val_string); + PRINT_xX_PWR("Laser output power low alarm threshold", sd.tx_power[LALRM]); + SPRINT_xX_PWR(val_string, sd.tx_power[LALRM]); + add_item_string(items, "Laser output power low alarm threshold", val_string); + PRINT_xX_PWR("Laser output power high warning threshold", sd.tx_power[HWARN]); + SPRINT_xX_PWR(val_string, sd.tx_power[HWARN]); + add_item_string(items, "Laser output power high warning threshold", val_string); + PRINT_xX_PWR("Laser output power low warning threshold", sd.tx_power[LWARN]); + SPRINT_xX_PWR(val_string, sd.tx_power[LWARN]); + add_item_string(items, "Laser output power low warning threshold", val_string); + + PRINT_TEMP("Module temperature high alarm threshold", sd.sfp_temp[HALRM]); + SPRINT_TEMP(val_string, sd.sfp_temp[HALRM]); + add_item_string(items, "Module temperature high alarm threshold", val_string); + PRINT_TEMP("Module temperature low alarm threshold", sd.sfp_temp[LALRM]); + SPRINT_TEMP(val_string, sd.sfp_temp[LALRM]); + add_item_string(items, "Module temperature low alarm threshold", val_string); + PRINT_TEMP("Module temperature high warning threshold", sd.sfp_temp[HWARN]); + SPRINT_TEMP(val_string, sd.sfp_temp[HWARN]); + add_item_string(items, "Module temperature high warning threshold", val_string); + PRINT_TEMP("Module temperature low warning threshold", sd.sfp_temp[LWARN]); + SPRINT_TEMP(val_string, sd.sfp_temp[LWARN]); + add_item_string(items, "Module temperature low warning threshold", val_string); + + PRINT_VCC("Module voltage high alarm threshold", sd.sfp_voltage[HALRM]); + SPRINT_VCC(val_string, sd.sfp_voltage[HALRM]); + add_item_string(items, "Module voltage high alarm threshold", val_string); + PRINT_VCC("Module voltage low alarm threshold", sd.sfp_voltage[LALRM]); + SPRINT_VCC(val_string, sd.sfp_voltage[LALRM]); + add_item_string(items, "Module voltage low alarm threshold", val_string); + PRINT_VCC("Module voltage high warning threshold", sd.sfp_voltage[HWARN]); + SPRINT_VCC(val_string, sd.sfp_voltage[HWARN]); + add_item_string(items, "Module voltage high warning threshold", val_string); + PRINT_VCC("Module voltage low warning threshold", sd.sfp_voltage[LWARN]); + SPRINT_VCC(val_string, sd.sfp_voltage[LWARN]); + add_item_string(items, "Module voltage low alarm threshold", val_string); + + PRINT_xX_PWR("Laser rx power high alarm threshold", sd.rx_power[HALRM]); + SPRINT_xX_PWR(val_string, sd.rx_power[HALRM]); + add_item_string(items, "Laser rx power high alarm threshold", val_string); + PRINT_xX_PWR("Laser rx power low alarm threshold", sd.rx_power[LALRM]); + SPRINT_xX_PWR(val_string, sd.rx_power[LALRM]); + add_item_string(items, "Laser rx power low alarm threshold", val_string); + PRINT_xX_PWR("Laser rx power high warning threshold", sd.rx_power[HWARN]); + SPRINT_xX_PWR(val_string, sd.rx_power[HWARN]); + add_item_string(items, "Laser rx power high warning threshold", val_string); + PRINT_xX_PWR("Laser rx power low warning threshold", sd.rx_power[LWARN]); + SPRINT_xX_PWR(val_string, sd.rx_power[LWARN]); + add_item_string(items, "Laser rx power low warning threshold", val_string); +} diff --git a/drivers/common/sff_module/sff_common.h b/drivers/common/sff_module/sff_common.h new file mode 100644 index 0000000000..04b6a54a87 --- /dev/null +++ b/drivers/common/sff_module/sff_common.h @@ -0,0 +1,192 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2022 Intel Corporation + * + * Implements SFF-8024 Rev 4.0 of pluggable I/O configuration + * + * Common utilities for SFF-8436/8636 and SFF-8472/8079 + * + */ + +#ifndef SFF_COMMON_H__ +#define SFF_COMMON_H__ + +#include <stdio.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include <sff_telemetry.h> + +#define SFF_8024_ID_OFFSET 0x00 +#define SFF_8024_ID_UNKNOWN 0x00 +#define SFF_8024_ID_GBIC 0x01 +#define SFF_8024_ID_SOLDERED_MODULE 0x02 +#define SFF_8024_ID_SFP 0x03 +#define SFF_8024_ID_300_PIN_XBI 0x04 +#define SFF_8024_ID_XENPAK 0x05 +#define SFF_8024_ID_XFP 0x06 +#define SFF_8024_ID_XFF 0x07 +#define SFF_8024_ID_XFP_E 0x08 +#define SFF_8024_ID_XPAK 0x09 +#define SFF_8024_ID_X2 0x0A +#define SFF_8024_ID_DWDM_SFP 0x0B +#define SFF_8024_ID_QSFP 0x0C +#define SFF_8024_ID_QSFP_PLUS 0x0D +#define SFF_8024_ID_CXP 0x0E +#define SFF_8024_ID_HD4X 0x0F +#define SFF_8024_ID_HD8X 0x10 +#define SFF_8024_ID_QSFP28 0x11 +#define SFF_8024_ID_CXP2 0x12 +#define SFF_8024_ID_CDFP 0x13 +#define SFF_8024_ID_HD4X_FANOUT 0x14 +#define SFF_8024_ID_HD8X_FANOUT 0x15 +#define SFF_8024_ID_CDFP_S3 0x16 +#define SFF_8024_ID_MICRO_QSFP 0x17 +#define SFF_8024_ID_LAST SFF_8024_ID_MICRO_QSFP +#define SFF_8024_ID_UNALLOCATED_LAST 0x7F +#define SFF_8024_ID_VENDOR_START 0x80 +#define SFF_8024_ID_VENDOR_LAST 0xFF + +#define SFF_8024_CTOR_UNKNOWN 0x00 +#define SFF_8024_CTOR_SC 0x01 +#define SFF_8024_CTOR_FC_STYLE_1 0x02 +#define SFF_8024_CTOR_FC_STYLE_2 0x03 +#define SFF_8024_CTOR_BNC_TNC 0x04 +#define SFF_8024_CTOR_FC_COAX 0x05 +#define SFF_8024_CTOR_FIBER_JACK 0x06 +#define SFF_8024_CTOR_LC 0x07 +#define SFF_8024_CTOR_MT_RJ 0x08 +#define SFF_8024_CTOR_MU 0x09 +#define SFF_8024_CTOR_SG 0x0A +#define SFF_8024_CTOR_OPT_PT 0x0B +#define SFF_8024_CTOR_MPO 0x0C +#define SFF_8024_CTOR_MPO_2 0x0D +/* 0E-1Fh --- Reserved */ +#define SFF_8024_CTOR_HSDC_II 0x20 +#define SFF_8024_CTOR_COPPER_PT 0x21 +#define SFF_8024_CTOR_RJ45 0x22 +#define SFF_8024_CTOR_NO_SEPARABLE 0x23 +#define SFF_8024_CTOR_MXC_2x16 0x24 +#define SFF_8024_CTOR_LAST SFF_8024_CTOR_MXC_2x16 +#define SFF_8024_CTOR_UNALLOCATED_LAST 0x7F +#define SFF_8024_CTOR_VENDOR_START 0x80 +#define SFF_8024_CTOR_VENDOR_LAST 0xFF + +/* ENCODING Values */ +#define SFF_8024_ENCODING_UNSPEC 0x00 +#define SFF_8024_ENCODING_8B10B 0x01 +#define SFF_8024_ENCODING_4B5B 0x02 +#define SFF_8024_ENCODING_NRZ 0x03 +/* + * Value: 04h + * SFF-8472 - Manchester + * SFF-8436/8636 - SONET Scrambled + */ +#define SFF_8024_ENCODING_4h 0x04 +/* + * Value: 05h + * SFF-8472 - SONET Scrambled + * SFF-8436/8636 - 64B/66B + */ +#define SFF_8024_ENCODING_5h 0x05 +/* + * Value: 06h + * SFF-8472 - 64B/66B + * SFF-8436/8636 - Manchester + */ +#define SFF_8024_ENCODING_6h 0x06 +#define SFF_8024_ENCODING_256B 0x07 +#define SFF_8024_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 PRINT_xX_PWR(string, var) \ + printf("%-41s : %.4f mW / %.2f dBm\n", (string), \ + (double)((var) / 10000.), \ + convert_mw_to_dbm((double)((var) / 10000.))) +#define SPRINT_xX_PWR(str, var) \ + sprintf(str, "%.4f mW / %.2f dBm", \ + (double)((var) / 10000.), \ + convert_mw_to_dbm((double)((var) / 10000.))) + +#define PRINT_BIAS(string, bias_cur) \ + printf("%-41s : %.3f mA\n", (string), \ + (double)(bias_cur / 500.)) +#define SPRINT_BIAS(str, bias_cur) \ + sprintf(str, "%.3f mA", (double)(bias_cur / 500.)) + +#define PRINT_TEMP(string, temp) \ + printf("%-41s : %.2f degrees C / %.2f degrees F\n", \ + (string), (double)(temp / 256.), \ + (double)(temp / 256. * 1.8 + 32.)) +#define SPRINT_TEMP(str, temp) \ + sprintf(str, "%.2f degrees C / %.2f degrees F", \ + (double)(temp / 256.), \ + (double)(temp / 256. * 1.8 + 32.)) + +#define PRINT_VCC(string, sfp_voltage) \ + printf("%-41s : %.4f V\n", (string), \ + (double)(sfp_voltage / 10000.)) +#define SPRINT_VCC(str, sfp_voltage) \ + sprintf(str, "%.4f V", (double)(sfp_voltage / 10000.)) + +#define PRINT_xX_THRESH_PWR(string, var, index) \ + PRINT_xX_PWR(string, (var)[(index)]) + +/* Channel Monitoring Fields */ +struct sff_channel_diags { + uint16_t bias_cur; /* Measured bias current in 2uA units */ + uint16_t rx_power; /* Measured RX Power */ + uint16_t tx_power; /* Measured TX Power */ +}; + +/* Module Monitoring Fields */ +struct sff_diags { + +#define MAX_CHANNEL_NUM 4 +#define LWARN 0 +#define HWARN 1 +#define LALRM 2 +#define HALRM 3 +#define MCURR 4 + + /* Supports DOM */ + uint8_t supports_dom; + /* Supports alarm/warning thold */ + uint8_t supports_alarms; + /* RX Power: 0 = OMA, 1 = Average power */ + uint8_t rx_power_type; + /* TX Power: 0 = Not supported, 1 = Average power */ + uint8_t tx_power_type; + + uint8_t calibrated_ext; /* Is externally calibrated */ + /* [5] tables are low/high warn, low/high alarm, current */ + /* SFP voltage in 0.1mV units */ + uint16_t sfp_voltage[5]; + /* SFP Temp in 16-bit signed 1/256 Celcius */ + int16_t sfp_temp[5]; + /* Measured bias current in 2uA units */ + uint16_t bias_cur[5]; + /* Measured TX Power */ + uint16_t tx_power[5]; + /* Measured RX Power */ + uint16_t rx_power[5]; + struct sff_channel_diags scd[MAX_CHANNEL_NUM]; +}; + +double convert_mw_to_dbm(double mw); +void sff_show_value_with_unit(const uint8_t *id, unsigned int reg, + const char *name, unsigned int mult, + const char *unit, sff_item *items); +void sff_show_ascii(const uint8_t *id, unsigned int first_reg, + unsigned int last_reg, const char *name, sff_item *items); +void sff_show_thresholds(struct sff_diags sd, sff_item *items); + +void sff_8024_show_oui(const uint8_t *id, int id_offset, sff_item *items); +void sff_8024_show_identifier(const uint8_t *id, int id_offset, sff_item *items); +void sff_8024_show_connector(const uint8_t *id, int ctor_offset, sff_item *items); +void sff_8024_show_encoding(const uint8_t *id, int encoding_offset, + int sff_type, sff_item *items); + +#endif /* SFF_COMMON_H__ */ diff --git a/drivers/common/sff_module/sff_telemetry.c b/drivers/common/sff_module/sff_telemetry.c new file mode 100644 index 0000000000..dd838b6012 --- /dev/null +++ b/drivers/common/sff_module/sff_telemetry.c @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Cavium, Inc + */ + +#include <rte_ethdev.h> +#include <rte_common.h> +#include "sff_telemetry.h" + +static void +sff_port_module_eeprom_display(uint16_t port_id, sff_item *items) +{ + struct rte_eth_dev_module_info minfo; + struct rte_dev_eeprom_info einfo; + int ret; + + ret = rte_eth_dev_get_module_info(port_id, &minfo); + if (ret != 0) { + switch (ret) { + case -ENODEV: + fprintf(stderr, "port index %d invalid\n", port_id); + break; + case -ENOTSUP: + fprintf(stderr, "operation not supported by device\n"); + break; + case -EIO: + fprintf(stderr, "device is removed\n"); + break; + default: + fprintf(stderr, "Unable to get module EEPROM: %d\n", + ret); + break; + } + return; + } + + einfo.offset = 0; + einfo.length = minfo.eeprom_len; + einfo.data = calloc(1, minfo.eeprom_len); + if (!einfo.data) { + fprintf(stderr, + "Allocation of port %u eeprom data failed\n", + port_id); + return; + } + + ret = rte_eth_dev_get_module_eeprom(port_id, &einfo); + if (ret != 0) { + switch (ret) { + case -ENODEV: + fprintf(stderr, "port index %d invalid\n", port_id); + break; + case -ENOTSUP: + fprintf(stderr, "operation not supported by device\n"); + break; + case -EIO: + fprintf(stderr, "device is removed\n"); + break; + default: + fprintf(stderr, "Unable to get module EEPROM: %d\n", + ret); + break; + } + free(einfo.data); + return; + } + + switch (minfo.type) { + case RTE_ETH_MODULE_SFF_8079: + sff_8079_show_all(einfo.data, items); + break; + case RTE_ETH_MODULE_SFF_8472: + sff_8079_show_all(einfo.data, items); + sff_8472_show_all(einfo.data, items); + break; + case RTE_ETH_MODULE_SFF_8436: + case RTE_ETH_MODULE_SFF_8636: + sff_8636_show_all(einfo.data, einfo.length, items); + break; + default: + break; + } + printf("Finish -- Port: %d MODULE EEPROM length: %d bytes\n", port_id, einfo.length); + free(einfo.data); +} + +void +add_item_string(sff_item *items, const char *name_str, const char *value_str) +{ + /* append different values for same keys */ + if (sff_item_count > 0 && + (strcmp(items[sff_item_count - 1].name, name_str) == 0)) { + strcat(items[sff_item_count - 1].value, "; "); + strcat(items[sff_item_count - 1].value, value_str); + return; + } + + sprintf(items[sff_item_count].name, "%s", name_str); + sprintf(items[sff_item_count].value, "%s", value_str); + sff_item_count++; +} + +static int +sff_module_tel_handle_info(const char *cmd __rte_unused, const char *params, + struct rte_tel_data *d) +{ + /* handle module info */ + char *end_param; + int port_id, i; + sff_item *items; + sff_item_count = 0; + + if (params == NULL || strlen(params) == 0 || !isdigit(*params)) + return -1; + + port_id = strtoul(params, &end_param, 0); + if (*end_param != '\0') + RTE_ETHDEV_LOG(NOTICE, + "Extra parameters passed to ethdev telemetry command, ignoring"); + + items = (sff_item *)malloc(SFF_ITEM_SIZE * SFF_ITEM_MAX_COUNT); + if (items == NULL) { + printf("Error allocating memory of items\n"); + free(items); + return -1; + } + + sff_port_module_eeprom_display(port_id, items); + + rte_tel_data_start_dict(d); + for (i = 0; i < sff_item_count; i++) + rte_tel_data_add_dict_string(d, items[i].name, items[i].value); + + free(items); + return 0; +} + +RTE_INIT(sff_module_info_init_telemetry) +{ + rte_telemetry_register_cmd( + "/sff_module/info", sff_module_tel_handle_info, + "Returns eeprom module info. Parameters: port_id"); +} diff --git a/drivers/common/sff_module/sff_telemetry.h b/drivers/common/sff_module/sff_telemetry.h new file mode 100644 index 0000000000..917197fb46 --- /dev/null +++ b/drivers/common/sff_module/sff_telemetry.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Cavium, Inc + */ + +#ifndef SFF_TELEMETRY_H_ +#define SFF_TELEMETRY_H_ + +#include <rte_ethdev.h> +#include <rte_telemetry.h> + +#define ARRAY_SIZE(arr) RTE_DIM(arr) + +#define SFF_ITEM_NAME_SIZE 64 +#define SFF_ITEM_VALUE_SIZE 256 +#define SFF_ITEM_MAX_COUNT 256 +#define TMP_STRING_SIZE 64 + +typedef struct sff_module_info_item { + char name[SFF_ITEM_NAME_SIZE]; /* The item name. */ + char value[SFF_ITEM_VALUE_SIZE]; /* The item value. */ +} sff_item; + +#define SFF_ITEM_SIZE sizeof(sff_item) + +uint16_t sff_item_count; + +/* SFF-8079 Optics diagnostics */ +__rte_internal +extern void sff_8079_show_all(const uint8_t *id, sff_item *items); + +/* SFF-8472 Optics diagnostics */ +__rte_internal +extern void sff_8472_show_all(const uint8_t *id, sff_item *items); + +/* SFF-8636 Optics diagnostics */ +__rte_internal +extern void sff_8636_show_all(const uint8_t *id, uint32_t eeprom_len, sff_item *items); + +void add_item_string(sff_item *items, const char *name_str, const char *value_str); + +#endif /* SFF_TELEMETRY_H_ */ diff --git a/drivers/common/sff_module/version.map b/drivers/common/sff_module/version.map new file mode 100644 index 0000000000..769b7af777 --- /dev/null +++ b/drivers/common/sff_module/version.map @@ -0,0 +1,9 @@ +INTERNAL { + global: + + sff_8079_show_all; + sff_8472_show_all; + sff_8636_show_all; + + local: *; +}; \ No newline at end of file -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v2] common/sff_module: add telemetry command to dump module EEPROM 2022-04-08 10:23 ` [PATCH v2] common/sff_module: add telemetry command to dump " Robin Zhang @ 2022-04-08 10:33 ` Bruce Richardson 2022-04-08 10:55 ` Zhang, RobinX 0 siblings, 1 reply; 77+ messages in thread From: Bruce Richardson @ 2022-04-08 10:33 UTC (permalink / raw) To: Robin Zhang; +Cc: dev, qiming.yang, qi.z.zhang, stevex.yang On Fri, Apr 08, 2022 at 10:23:30AM +0000, Robin Zhang wrote: > This patch introduce a new telemetry command '/sff_module/info' > to dump format module EEPROM information. > > The format support for SFP(Small Formfactor Pluggable)/SFP+ > /QSFP+(Quad Small Formfactor Pluggable)/QSFP28 modules based on > SFF(Small Form Factor) Committee specifications > SFF-8079/SFF-8472/SFF-8024/SFF-8636. > > Signed-off-by: Robin Zhang <robinx.zhang@intel.com> > --- > > v2: > - Redesign the dump function as a telemetry command, so that the EEPROM > information can be used by other app. > > - The usage like this: > > Launch the primary application with telemetry: > Take testpmd as example: ./app/dpdk-testpmd > > Then launch the telemetry client script: > ./usertools/dpdk-telemetry.py > > In telemetry client run command: > --> /sff_module/info,<port number> > > Both primary application and telemetry client will show the formated > module EEPROM information. > > drivers/common/meson.build | 1 + > drivers/common/sff_module/meson.build | 16 + > drivers/common/sff_module/sff_8079.c | 672 ++++++++++++++ > drivers/common/sff_module/sff_8472.c | 301 ++++++ > drivers/common/sff_module/sff_8636.c | 1004 +++++++++++++++++++++ > drivers/common/sff_module/sff_8636.h | 592 ++++++++++++ > drivers/common/sff_module/sff_common.c | 415 +++++++++ > drivers/common/sff_module/sff_common.h | 192 ++++ > drivers/common/sff_module/sff_telemetry.c | 142 +++ > drivers/common/sff_module/sff_telemetry.h | 41 + > drivers/common/sff_module/version.map | 9 + > 11 files changed, 3385 insertions(+) > create mode 100644 drivers/common/sff_module/meson.build > create mode 100644 drivers/common/sff_module/sff_8079.c > create mode 100644 drivers/common/sff_module/sff_8472.c > create mode 100644 drivers/common/sff_module/sff_8636.c > create mode 100644 drivers/common/sff_module/sff_8636.h > create mode 100644 drivers/common/sff_module/sff_common.c > create mode 100644 drivers/common/sff_module/sff_common.h > create mode 100644 drivers/common/sff_module/sff_telemetry.c > create mode 100644 drivers/common/sff_module/sff_telemetry.h > create mode 100644 drivers/common/sff_module/version.map > Is this is whole new driver just to provide telemetry dumps of SFP information? I can understand the problem somewhat - though I am in some doubt that telemetry is the best way to expose this information - but creating a new driver seems the wrong approach here. SFPs are for NIC devices, so why isn't this available in a common API such as ethdev? /Bruce ^ permalink raw reply [flat|nested] 77+ messages in thread
* RE: [PATCH v2] common/sff_module: add telemetry command to dump module EEPROM 2022-04-08 10:33 ` Bruce Richardson @ 2022-04-08 10:55 ` Zhang, RobinX 2022-04-08 11:00 ` Bruce Richardson 0 siblings, 1 reply; 77+ messages in thread From: Zhang, RobinX @ 2022-04-08 10:55 UTC (permalink / raw) To: Richardson, Bruce; +Cc: dev, Yang, Qiming, Zhang, Qi Z, Yang, SteveX Hi Bruce, > -----Original Message----- > From: Richardson, Bruce <bruce.richardson@intel.com> > Sent: Friday, April 8, 2022 6:33 PM > To: Zhang, RobinX <robinx.zhang@intel.com> > Cc: dev@dpdk.org; Yang, Qiming <qiming.yang@intel.com>; Zhang, Qi Z > <qi.z.zhang@intel.com>; Yang, SteveX <stevex.yang@intel.com> > Subject: Re: [PATCH v2] common/sff_module: add telemetry command to > dump module EEPROM > > On Fri, Apr 08, 2022 at 10:23:30AM +0000, Robin Zhang wrote: > > This patch introduce a new telemetry command '/sff_module/info' > > to dump format module EEPROM information. > > > > The format support for SFP(Small Formfactor Pluggable)/SFP+ > > /QSFP+(Quad Small Formfactor Pluggable)/QSFP28 modules based on > > SFF(Small Form Factor) Committee specifications > > SFF-8079/SFF-8472/SFF-8024/SFF-8636. > > > > Signed-off-by: Robin Zhang <robinx.zhang@intel.com> > > --- > > > > v2: > > - Redesign the dump function as a telemetry command, so that the > EEPROM > > information can be used by other app. > > > > - The usage like this: > > > > Launch the primary application with telemetry: > > Take testpmd as example: ./app/dpdk-testpmd > > > > Then launch the telemetry client script: > > ./usertools/dpdk-telemetry.py > > > > In telemetry client run command: > > --> /sff_module/info,<port number> > > > > Both primary application and telemetry client will show the formated > > module EEPROM information. > > > > drivers/common/meson.build | 1 + > > drivers/common/sff_module/meson.build | 16 + > > drivers/common/sff_module/sff_8079.c | 672 ++++++++++++++ > > drivers/common/sff_module/sff_8472.c | 301 ++++++ > > drivers/common/sff_module/sff_8636.c | 1004 > +++++++++++++++++++++ > > drivers/common/sff_module/sff_8636.h | 592 ++++++++++++ > > drivers/common/sff_module/sff_common.c | 415 +++++++++ > > drivers/common/sff_module/sff_common.h | 192 ++++ > > drivers/common/sff_module/sff_telemetry.c | 142 +++ > > drivers/common/sff_module/sff_telemetry.h | 41 + > > drivers/common/sff_module/version.map | 9 + > > 11 files changed, 3385 insertions(+) > > create mode 100644 drivers/common/sff_module/meson.build > > create mode 100644 drivers/common/sff_module/sff_8079.c > > create mode 100644 drivers/common/sff_module/sff_8472.c > > create mode 100644 drivers/common/sff_module/sff_8636.c > > create mode 100644 drivers/common/sff_module/sff_8636.h > > create mode 100644 drivers/common/sff_module/sff_common.c > > create mode 100644 drivers/common/sff_module/sff_common.h > > create mode 100644 drivers/common/sff_module/sff_telemetry.c > > create mode 100644 drivers/common/sff_module/sff_telemetry.h > > create mode 100644 drivers/common/sff_module/version.map > > > Is this is whole new driver just to provide telemetry dumps of SFP > information? I can understand the problem somewhat - though I am in some > doubt that telemetry is the best way to expose this information - but > creating a new driver seems the wrong approach here. SFPs are for NIC > devices, so why isn't this available in a common API such as ethdev? > I have considered add this function as a new telemetry command of ethdev (like '/ethdev/sff_module_info') to dump these SFP information. But I'm not sure if it's acceptable to add all these production code (sff_8xxx.c) into lib/ethdev? If it's OK, I can make V3 patches to change it as a telemetry command of ethdev. > /Bruce ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v2] common/sff_module: add telemetry command to dump module EEPROM 2022-04-08 10:55 ` Zhang, RobinX @ 2022-04-08 11:00 ` Bruce Richardson 2022-04-08 11:20 ` Zhang, RobinX 0 siblings, 1 reply; 77+ messages in thread From: Bruce Richardson @ 2022-04-08 11:00 UTC (permalink / raw) To: Zhang, RobinX; +Cc: dev, Yang, Qiming, Zhang, Qi Z, Yang, SteveX On Fri, Apr 08, 2022 at 11:55:07AM +0100, Zhang, RobinX wrote: > Hi Bruce, > > > -----Original Message----- > > From: Richardson, Bruce <bruce.richardson@intel.com> > > Sent: Friday, April 8, 2022 6:33 PM > > To: Zhang, RobinX <robinx.zhang@intel.com> > > Cc: dev@dpdk.org; Yang, Qiming <qiming.yang@intel.com>; Zhang, Qi Z > > <qi.z.zhang@intel.com>; Yang, SteveX <stevex.yang@intel.com> > > Subject: Re: [PATCH v2] common/sff_module: add telemetry command to > > dump module EEPROM > > > > On Fri, Apr 08, 2022 at 10:23:30AM +0000, Robin Zhang wrote: > > > This patch introduce a new telemetry command '/sff_module/info' > > > to dump format module EEPROM information. > > > > > > The format support for SFP(Small Formfactor Pluggable)/SFP+ > > > /QSFP+(Quad Small Formfactor Pluggable)/QSFP28 modules based on > > > SFF(Small Form Factor) Committee specifications > > > SFF-8079/SFF-8472/SFF-8024/SFF-8636. > > > > > > Signed-off-by: Robin Zhang <robinx.zhang@intel.com> > > > --- > > > > > > v2: > > > - Redesign the dump function as a telemetry command, so that the > > EEPROM > > > information can be used by other app. > > > > > > - The usage like this: > > > > > > Launch the primary application with telemetry: > > > Take testpmd as example: ./app/dpdk-testpmd > > > > > > Then launch the telemetry client script: > > > ./usertools/dpdk-telemetry.py > > > > > > In telemetry client run command: > > > --> /sff_module/info,<port number> > > > > > > Both primary application and telemetry client will show the formated > > > module EEPROM information. > > > > > > drivers/common/meson.build | 1 + > > > drivers/common/sff_module/meson.build | 16 + > > > drivers/common/sff_module/sff_8079.c | 672 ++++++++++++++ > > > drivers/common/sff_module/sff_8472.c | 301 ++++++ > > > drivers/common/sff_module/sff_8636.c | 1004 > > +++++++++++++++++++++ > > > drivers/common/sff_module/sff_8636.h | 592 ++++++++++++ > > > drivers/common/sff_module/sff_common.c | 415 +++++++++ > > > drivers/common/sff_module/sff_common.h | 192 ++++ > > > drivers/common/sff_module/sff_telemetry.c | 142 +++ > > > drivers/common/sff_module/sff_telemetry.h | 41 + > > > drivers/common/sff_module/version.map | 9 + > > > 11 files changed, 3385 insertions(+) > > > create mode 100644 drivers/common/sff_module/meson.build > > > create mode 100644 drivers/common/sff_module/sff_8079.c > > > create mode 100644 drivers/common/sff_module/sff_8472.c > > > create mode 100644 drivers/common/sff_module/sff_8636.c > > > create mode 100644 drivers/common/sff_module/sff_8636.h > > > create mode 100644 drivers/common/sff_module/sff_common.c > > > create mode 100644 drivers/common/sff_module/sff_common.h > > > create mode 100644 drivers/common/sff_module/sff_telemetry.c > > > create mode 100644 drivers/common/sff_module/sff_telemetry.h > > > create mode 100644 drivers/common/sff_module/version.map > > > > > Is this is whole new driver just to provide telemetry dumps of SFP > > information? I can understand the problem somewhat - though I am in some > > doubt that telemetry is the best way to expose this information - but > > creating a new driver seems the wrong approach here. SFPs are for NIC > > devices, so why isn't this available in a common API such as ethdev? > > > > I have considered add this function as a new telemetry command of ethdev (like '/ethdev/sff_module_info') to dump these SFP information. > But I'm not sure if it's acceptable to add all these production code (sff_8xxx.c) into lib/ethdev? > If it's OK, I can make V3 patches to change it as a telemetry command of ethdev. > Hi, I think some discussion is needed before you go preparing a new version of this patchset. Some initial questions: 1. Does SFF code apply only to Intel products/NICs or is it multi-vendor? 2. For the driver approach you previously took, how was the presence of hardware detected to load the driver? 3. Does this work on SFPs need to interact with the NIC drivers in any way? Thanks, /Bruce ^ permalink raw reply [flat|nested] 77+ messages in thread
* RE: [PATCH v2] common/sff_module: add telemetry command to dump module EEPROM 2022-04-08 11:00 ` Bruce Richardson @ 2022-04-08 11:20 ` Zhang, RobinX 2022-04-08 11:26 ` Bruce Richardson 0 siblings, 1 reply; 77+ messages in thread From: Zhang, RobinX @ 2022-04-08 11:20 UTC (permalink / raw) To: Richardson, Bruce; +Cc: dev, Yang, Qiming, Zhang, Qi Z, Yang, SteveX Hi Bruce > -----Original Message----- > From: Richardson, Bruce <bruce.richardson@intel.com> > Sent: Friday, April 8, 2022 7:01 PM > To: Zhang, RobinX <robinx.zhang@intel.com> > Cc: dev@dpdk.org; Yang, Qiming <qiming.yang@intel.com>; Zhang, Qi Z > <qi.z.zhang@intel.com>; Yang, SteveX <stevex.yang@intel.com> > Subject: Re: [PATCH v2] common/sff_module: add telemetry command to > dump module EEPROM > > On Fri, Apr 08, 2022 at 11:55:07AM +0100, Zhang, RobinX wrote: > > Hi Bruce, > > > > > -----Original Message----- > > > From: Richardson, Bruce <bruce.richardson@intel.com> > > > Sent: Friday, April 8, 2022 6:33 PM > > > To: Zhang, RobinX <robinx.zhang@intel.com> > > > Cc: dev@dpdk.org; Yang, Qiming <qiming.yang@intel.com>; Zhang, Qi Z > > > <qi.z.zhang@intel.com>; Yang, SteveX <stevex.yang@intel.com> > > > Subject: Re: [PATCH v2] common/sff_module: add telemetry command > to > > > dump module EEPROM > > > > > > On Fri, Apr 08, 2022 at 10:23:30AM +0000, Robin Zhang wrote: > > > > This patch introduce a new telemetry command '/sff_module/info' > > > > to dump format module EEPROM information. > > > > > > > > The format support for SFP(Small Formfactor Pluggable)/SFP+ > > > > /QSFP+(Quad Small Formfactor Pluggable)/QSFP28 modules based on > > > > SFF(Small Form Factor) Committee specifications > > > > SFF-8079/SFF-8472/SFF-8024/SFF-8636. > > > > > > > > Signed-off-by: Robin Zhang <robinx.zhang@intel.com> > > > > --- > > > > > > > > v2: > > > > - Redesign the dump function as a telemetry command, so that the > > > EEPROM > > > > information can be used by other app. > > > > > > > > - The usage like this: > > > > > > > > Launch the primary application with telemetry: > > > > Take testpmd as example: ./app/dpdk-testpmd > > > > > > > > Then launch the telemetry client script: > > > > ./usertools/dpdk-telemetry.py > > > > > > > > In telemetry client run command: > > > > --> /sff_module/info,<port number> > > > > > > > > Both primary application and telemetry client will show the formated > > > > module EEPROM information. > > > > > > > > drivers/common/meson.build | 1 + > > > > drivers/common/sff_module/meson.build | 16 + > > > > drivers/common/sff_module/sff_8079.c | 672 ++++++++++++++ > > > > drivers/common/sff_module/sff_8472.c | 301 ++++++ > > > > drivers/common/sff_module/sff_8636.c | 1004 > > > +++++++++++++++++++++ > > > > drivers/common/sff_module/sff_8636.h | 592 ++++++++++++ > > > > drivers/common/sff_module/sff_common.c | 415 +++++++++ > > > > drivers/common/sff_module/sff_common.h | 192 ++++ > > > > drivers/common/sff_module/sff_telemetry.c | 142 +++ > > > > drivers/common/sff_module/sff_telemetry.h | 41 + > > > > drivers/common/sff_module/version.map | 9 + > > > > 11 files changed, 3385 insertions(+) create mode 100644 > > > > drivers/common/sff_module/meson.build > > > > create mode 100644 drivers/common/sff_module/sff_8079.c > > > > create mode 100644 drivers/common/sff_module/sff_8472.c > > > > create mode 100644 drivers/common/sff_module/sff_8636.c > > > > create mode 100644 drivers/common/sff_module/sff_8636.h > > > > create mode 100644 drivers/common/sff_module/sff_common.c > > > > create mode 100644 drivers/common/sff_module/sff_common.h > > > > create mode 100644 drivers/common/sff_module/sff_telemetry.c > > > > create mode 100644 drivers/common/sff_module/sff_telemetry.h > > > > create mode 100644 drivers/common/sff_module/version.map > > > > > > > Is this is whole new driver just to provide telemetry dumps of SFP > > > information? I can understand the problem somewhat - though I am in > > > some doubt that telemetry is the best way to expose this information > > > - but creating a new driver seems the wrong approach here. SFPs are > > > for NIC devices, so why isn't this available in a common API such as > ethdev? > > > > > > > I have considered add this function as a new telemetry command of > ethdev (like '/ethdev/sff_module_info') to dump these SFP information. > > But I'm not sure if it's acceptable to add all these production code > (sff_8xxx.c) into lib/ethdev? > > If it's OK, I can make V3 patches to change it as a telemetry command of > ethdev. > > > > Hi, > > I think some discussion is needed before you go preparing a new version of > this patchset. > > Some initial questions: > > 1. Does SFF code apply only to Intel products/NICs or is it multi-vendor? The SFF code apply to multi-vendor. In fact, it's applied to all the NIC driver which implemented dev_ops->get_module_eeprom. > 2. For the driver approach you previously took, how was the presence of > hardware detected to load the driver? The purpose of put these production code into drivers/common is want to treat it as a common function for NIC drivers. It will not related to any presence of hardware. > 3. Does this work on SFPs need to interact with the NIC drivers in any way? > Yes, just like my answer in question 1, the module EEPROM raw data is get from dev_ops->get_module_eeprom. So need the NIC drivers to implement dev_ops->get_module_eeprom. > Thanks, > /Bruce ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v2] common/sff_module: add telemetry command to dump module EEPROM 2022-04-08 11:20 ` Zhang, RobinX @ 2022-04-08 11:26 ` Bruce Richardson 2022-04-11 8:13 ` Zhang, RobinX 0 siblings, 1 reply; 77+ messages in thread From: Bruce Richardson @ 2022-04-08 11:26 UTC (permalink / raw) To: Zhang, RobinX; +Cc: dev, Yang, Qiming, Zhang, Qi Z, Yang, SteveX On Fri, Apr 08, 2022 at 12:20:23PM +0100, Zhang, RobinX wrote: > Hi Bruce > > > -----Original Message----- > > From: Richardson, Bruce <bruce.richardson@intel.com> > > Sent: Friday, April 8, 2022 7:01 PM > > To: Zhang, RobinX <robinx.zhang@intel.com> > > Cc: dev@dpdk.org; Yang, Qiming <qiming.yang@intel.com>; Zhang, Qi Z > > <qi.z.zhang@intel.com>; Yang, SteveX <stevex.yang@intel.com> > > Subject: Re: [PATCH v2] common/sff_module: add telemetry command to > > dump module EEPROM > > > > On Fri, Apr 08, 2022 at 11:55:07AM +0100, Zhang, RobinX wrote: > > > Hi Bruce, > > > > > > > -----Original Message----- > > > > From: Richardson, Bruce <bruce.richardson@intel.com> > > > > Sent: Friday, April 8, 2022 6:33 PM > > > > To: Zhang, RobinX <robinx.zhang@intel.com> > > > > Cc: dev@dpdk.org; Yang, Qiming <qiming.yang@intel.com>; Zhang, Qi Z > > > > <qi.z.zhang@intel.com>; Yang, SteveX <stevex.yang@intel.com> > > > > Subject: Re: [PATCH v2] common/sff_module: add telemetry command > > to > > > > dump module EEPROM > > > > > > > > On Fri, Apr 08, 2022 at 10:23:30AM +0000, Robin Zhang wrote: > > > > > This patch introduce a new telemetry command '/sff_module/info' > > > > > to dump format module EEPROM information. > > > > > > > > > > The format support for SFP(Small Formfactor Pluggable)/SFP+ > > > > > /QSFP+(Quad Small Formfactor Pluggable)/QSFP28 modules based on > > > > > SFF(Small Form Factor) Committee specifications > > > > > SFF-8079/SFF-8472/SFF-8024/SFF-8636. > > > > > > > > > > Signed-off-by: Robin Zhang <robinx.zhang@intel.com> > > > > > --- > > > > > > > > > > v2: > > > > > - Redesign the dump function as a telemetry command, so that the > > > > EEPROM > > > > > information can be used by other app. > > > > > > > > > > - The usage like this: > > > > > > > > > > Launch the primary application with telemetry: > > > > > Take testpmd as example: ./app/dpdk-testpmd > > > > > > > > > > Then launch the telemetry client script: > > > > > ./usertools/dpdk-telemetry.py > > > > > > > > > > In telemetry client run command: > > > > > --> /sff_module/info,<port number> > > > > > > > > > > Both primary application and telemetry client will show the formated > > > > > module EEPROM information. > > > > > > > > > > drivers/common/meson.build | 1 + > > > > > drivers/common/sff_module/meson.build | 16 + > > > > > drivers/common/sff_module/sff_8079.c | 672 ++++++++++++++ > > > > > drivers/common/sff_module/sff_8472.c | 301 ++++++ > > > > > drivers/common/sff_module/sff_8636.c | 1004 > > > > +++++++++++++++++++++ > > > > > drivers/common/sff_module/sff_8636.h | 592 ++++++++++++ > > > > > drivers/common/sff_module/sff_common.c | 415 +++++++++ > > > > > drivers/common/sff_module/sff_common.h | 192 ++++ > > > > > drivers/common/sff_module/sff_telemetry.c | 142 +++ > > > > > drivers/common/sff_module/sff_telemetry.h | 41 + > > > > > drivers/common/sff_module/version.map | 9 + > > > > > 11 files changed, 3385 insertions(+) create mode 100644 > > > > > drivers/common/sff_module/meson.build > > > > > create mode 100644 drivers/common/sff_module/sff_8079.c > > > > > create mode 100644 drivers/common/sff_module/sff_8472.c > > > > > create mode 100644 drivers/common/sff_module/sff_8636.c > > > > > create mode 100644 drivers/common/sff_module/sff_8636.h > > > > > create mode 100644 drivers/common/sff_module/sff_common.c > > > > > create mode 100644 drivers/common/sff_module/sff_common.h > > > > > create mode 100644 drivers/common/sff_module/sff_telemetry.c > > > > > create mode 100644 drivers/common/sff_module/sff_telemetry.h > > > > > create mode 100644 drivers/common/sff_module/version.map > > > > > > > > > Is this is whole new driver just to provide telemetry dumps of SFP > > > > information? I can understand the problem somewhat - though I am in > > > > some doubt that telemetry is the best way to expose this information > > > > - but creating a new driver seems the wrong approach here. SFPs are > > > > for NIC devices, so why isn't this available in a common API such as > > ethdev? > > > > > > > > > > I have considered add this function as a new telemetry command of > > ethdev (like '/ethdev/sff_module_info') to dump these SFP information. > > > But I'm not sure if it's acceptable to add all these production code > > (sff_8xxx.c) into lib/ethdev? > > > If it's OK, I can make V3 patches to change it as a telemetry command of > > ethdev. > > > > > > > Hi, > > > > I think some discussion is needed before you go preparing a new version of > > this patchset. > > > > Some initial questions: > > > > 1. Does SFF code apply only to Intel products/NICs or is it multi-vendor? > The SFF code apply to multi-vendor. > In fact, it's applied to all the NIC driver which implemented dev_ops->get_module_eeprom. > > > 2. For the driver approach you previously took, how was the presence of > > hardware detected to load the driver? > The purpose of put these production code into drivers/common is want to treat it as a common function for NIC drivers. > It will not related to any presence of hardware. > > > 3. Does this work on SFPs need to interact with the NIC drivers in any way? > > > Yes, just like my answer in question 1, the module EEPROM raw data is get from dev_ops->get_module_eeprom. > So need the NIC drivers to implement dev_ops->get_module_eeprom. > So is the intent that individual NIC drivers would add a get_module_eeprom function to their drivers pointing at this driver? If so, this approach of putting the code in drivers/common does make sense. However, this needs to be better explained in the patch description, and maybe include with the driver patch (which should probably be split up into easier reviewed sections), additional patches to add the get_eeprom function to some drivers to show use. Thanks, /Bruce ^ permalink raw reply [flat|nested] 77+ messages in thread
* RE: [PATCH v2] common/sff_module: add telemetry command to dump module EEPROM 2022-04-08 11:26 ` Bruce Richardson @ 2022-04-11 8:13 ` Zhang, RobinX 2022-04-11 9:13 ` Bruce Richardson 0 siblings, 1 reply; 77+ messages in thread From: Zhang, RobinX @ 2022-04-11 8:13 UTC (permalink / raw) To: Richardson, Bruce; +Cc: dev, Yang, Qiming, Zhang, Qi Z, Yang, SteveX Hi Bruce, > -----Original Message----- > From: Richardson, Bruce <bruce.richardson@intel.com> > Sent: Friday, April 8, 2022 7:27 PM > To: Zhang, RobinX <robinx.zhang@intel.com> > Cc: dev@dpdk.org; Yang, Qiming <qiming.yang@intel.com>; Zhang, Qi Z > <qi.z.zhang@intel.com>; Yang, SteveX <stevex.yang@intel.com> > Subject: Re: [PATCH v2] common/sff_module: add telemetry command to > dump module EEPROM > > On Fri, Apr 08, 2022 at 12:20:23PM +0100, Zhang, RobinX wrote: > > Hi Bruce > > > > > -----Original Message----- > > > From: Richardson, Bruce <bruce.richardson@intel.com> > > > Sent: Friday, April 8, 2022 7:01 PM > > > To: Zhang, RobinX <robinx.zhang@intel.com> > > > Cc: dev@dpdk.org; Yang, Qiming <qiming.yang@intel.com>; Zhang, Qi Z > > > <qi.z.zhang@intel.com>; Yang, SteveX <stevex.yang@intel.com> > > > Subject: Re: [PATCH v2] common/sff_module: add telemetry command > to > > > dump module EEPROM > > > > > > On Fri, Apr 08, 2022 at 11:55:07AM +0100, Zhang, RobinX wrote: > > > > Hi Bruce, > > > > > > > > > -----Original Message----- > > > > > From: Richardson, Bruce <bruce.richardson@intel.com> > > > > > Sent: Friday, April 8, 2022 6:33 PM > > > > > To: Zhang, RobinX <robinx.zhang@intel.com> > > > > > Cc: dev@dpdk.org; Yang, Qiming <qiming.yang@intel.com>; Zhang, > > > > > Qi Z <qi.z.zhang@intel.com>; Yang, SteveX > > > > > <stevex.yang@intel.com> > > > > > Subject: Re: [PATCH v2] common/sff_module: add telemetry > command > > > to > > > > > dump module EEPROM > > > > > > > > > > On Fri, Apr 08, 2022 at 10:23:30AM +0000, Robin Zhang wrote: > > > > > > This patch introduce a new telemetry command '/sff_module/info' > > > > > > to dump format module EEPROM information. > > > > > > > > > > > > The format support for SFP(Small Formfactor Pluggable)/SFP+ > > > > > > /QSFP+(Quad Small Formfactor Pluggable)/QSFP28 modules based > > > > > > on SFF(Small Form Factor) Committee specifications > > > > > > SFF-8079/SFF-8472/SFF-8024/SFF-8636. > > > > > > > > > > > > Signed-off-by: Robin Zhang <robinx.zhang@intel.com> > > > > > > --- > > > > > > > > > > > > v2: > > > > > > - Redesign the dump function as a telemetry command, so that > > > > > > the > > > > > EEPROM > > > > > > information can be used by other app. > > > > > > > > > > > > - The usage like this: > > > > > > > > > > > > Launch the primary application with telemetry: > > > > > > Take testpmd as example: ./app/dpdk-testpmd > > > > > > > > > > > > Then launch the telemetry client script: > > > > > > ./usertools/dpdk-telemetry.py > > > > > > > > > > > > In telemetry client run command: > > > > > > --> /sff_module/info,<port number> > > > > > > > > > > > > Both primary application and telemetry client will show the > formated > > > > > > module EEPROM information. > > > > > > > > > > > > drivers/common/meson.build | 1 + > > > > > > drivers/common/sff_module/meson.build | 16 + > > > > > > drivers/common/sff_module/sff_8079.c | 672 > ++++++++++++++ > > > > > > drivers/common/sff_module/sff_8472.c | 301 ++++++ > > > > > > drivers/common/sff_module/sff_8636.c | 1004 > > > > > +++++++++++++++++++++ > > > > > > drivers/common/sff_module/sff_8636.h | 592 ++++++++++++ > > > > > > drivers/common/sff_module/sff_common.c | 415 +++++++++ > > > > > > drivers/common/sff_module/sff_common.h | 192 ++++ > > > > > > drivers/common/sff_module/sff_telemetry.c | 142 +++ > > > > > > drivers/common/sff_module/sff_telemetry.h | 41 + > > > > > > drivers/common/sff_module/version.map | 9 + > > > > > > 11 files changed, 3385 insertions(+) create mode 100644 > > > > > > drivers/common/sff_module/meson.build > > > > > > create mode 100644 drivers/common/sff_module/sff_8079.c > > > > > > create mode 100644 drivers/common/sff_module/sff_8472.c > > > > > > create mode 100644 drivers/common/sff_module/sff_8636.c > > > > > > create mode 100644 drivers/common/sff_module/sff_8636.h > > > > > > create mode 100644 drivers/common/sff_module/sff_common.c > > > > > > create mode 100644 drivers/common/sff_module/sff_common.h > > > > > > create mode 100644 drivers/common/sff_module/sff_telemetry.c > > > > > > create mode 100644 drivers/common/sff_module/sff_telemetry.h > > > > > > create mode 100644 drivers/common/sff_module/version.map > > > > > > > > > > > Is this is whole new driver just to provide telemetry dumps of > > > > > SFP information? I can understand the problem somewhat - though > > > > > I am in some doubt that telemetry is the best way to expose this > > > > > information > > > > > - but creating a new driver seems the wrong approach here. SFPs > > > > > are for NIC devices, so why isn't this available in a common API > > > > > such as > > > ethdev? > > > > > > > > > > > > > I have considered add this function as a new telemetry command of > > > ethdev (like '/ethdev/sff_module_info') to dump these SFP information. > > > > But I'm not sure if it's acceptable to add all these production > > > > code > > > (sff_8xxx.c) into lib/ethdev? > > > > If it's OK, I can make V3 patches to change it as a telemetry > > > > command of > > > ethdev. > > > > > > > > > > Hi, > > > > > > I think some discussion is needed before you go preparing a new > > > version of this patchset. > > > > > > Some initial questions: > > > > > > 1. Does SFF code apply only to Intel products/NICs or is it multi-vendor? > > The SFF code apply to multi-vendor. > > In fact, it's applied to all the NIC driver which implemented dev_ops- > >get_module_eeprom. > > > > > 2. For the driver approach you previously took, how was the presence of > > > hardware detected to load the driver? > > The purpose of put these production code into drivers/common is want to > treat it as a common function for NIC drivers. > > It will not related to any presence of hardware. > > > > > 3. Does this work on SFPs need to interact with the NIC drivers in any way? > > > > > Yes, just like my answer in question 1, the module EEPROM raw data is get > from dev_ops->get_module_eeprom. > > So need the NIC drivers to implement dev_ops->get_module_eeprom. > > > > So is the intent that individual NIC drivers would add a get_module_eeprom > function to their drivers pointing at this driver? If so, this approach of putting > the code in drivers/common does make sense. However, this needs to be > better explained in the patch description, and maybe include with the driver > patch (which should probably be split up into easier reviewed sections), > additional patches to add the get_eeprom function to some drivers to show > use. > Let me explain in more detail. This patch actually include two parts: 1. Module EEPROM raw data parser code Files: sff_common.h, sff_common.c, sff_8xxx.* 2. Add new telemetry command Files: sff_telemetry.h, sff_telemetry.c Part 1 will only parsing the module EEPROM raw data base on different module type. Now DPDK support 4 types that defined in rte_dev_info.h with macro RTE_ETH_MODULE_SFF_8xxx. Part 2 will call rte_eth_dev_get_module_info and rte_eth_dev_get_module_eeprom to get the module EEPROM raw data, then pass the raw data to Part 1 parser code. Finally, Part 1 parser code will print formatted information. So, these codes are more likely a common tool than a common driver, because it will only read the module EEPROM raw data from NIC PMD driver. For those NIC drivers who has not implemented get_module_info and get_module_eeprom dev_ops, we will simply return not support. > Thanks, > /Bruce ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v2] common/sff_module: add telemetry command to dump module EEPROM 2022-04-11 8:13 ` Zhang, RobinX @ 2022-04-11 9:13 ` Bruce Richardson 2022-04-13 12:13 ` Thomas Monjalon 0 siblings, 1 reply; 77+ messages in thread From: Bruce Richardson @ 2022-04-11 9:13 UTC (permalink / raw) To: Zhang, RobinX Cc: dev, Yang, Qiming, Zhang, Qi Z, Yang, SteveX, thomas, david.marchand, andrew.rybchenko On Mon, Apr 11, 2022 at 09:13:47AM +0100, Zhang, RobinX wrote: > Hi Bruce, > > > -----Original Message----- > > From: Richardson, Bruce <bruce.richardson@intel.com> > > Sent: Friday, April 8, 2022 7:27 PM > > To: Zhang, RobinX <robinx.zhang@intel.com> > > Cc: dev@dpdk.org; Yang, Qiming <qiming.yang@intel.com>; Zhang, Qi Z > > <qi.z.zhang@intel.com>; Yang, SteveX <stevex.yang@intel.com> > > Subject: Re: [PATCH v2] common/sff_module: add telemetry command to > > dump module EEPROM > > > > On Fri, Apr 08, 2022 at 12:20:23PM +0100, Zhang, RobinX wrote: > > > Hi Bruce > > > > > > > -----Original Message----- > > > > From: Richardson, Bruce <bruce.richardson@intel.com> > > > > Sent: Friday, April 8, 2022 7:01 PM > > > > To: Zhang, RobinX <robinx.zhang@intel.com> > > > > Cc: dev@dpdk.org; Yang, Qiming <qiming.yang@intel.com>; Zhang, Qi Z > > > > <qi.z.zhang@intel.com>; Yang, SteveX <stevex.yang@intel.com> > > > > Subject: Re: [PATCH v2] common/sff_module: add telemetry command > > to > > > > dump module EEPROM > > > > > > > > On Fri, Apr 08, 2022 at 11:55:07AM +0100, Zhang, RobinX wrote: > > > > > Hi Bruce, > > > > > > > > > > > -----Original Message----- > > > > > > From: Richardson, Bruce <bruce.richardson@intel.com> > > > > > > Sent: Friday, April 8, 2022 6:33 PM > > > > > > To: Zhang, RobinX <robinx.zhang@intel.com> > > > > > > Cc: dev@dpdk.org; Yang, Qiming <qiming.yang@intel.com>; Zhang, > > > > > > Qi Z <qi.z.zhang@intel.com>; Yang, SteveX > > > > > > <stevex.yang@intel.com> > > > > > > Subject: Re: [PATCH v2] common/sff_module: add telemetry > > command > > > > to > > > > > > dump module EEPROM > > > > > > > > > > > > On Fri, Apr 08, 2022 at 10:23:30AM +0000, Robin Zhang wrote: > > > > > > > This patch introduce a new telemetry command '/sff_module/info' > > > > > > > to dump format module EEPROM information. > > > > > > > > > > > > > > The format support for SFP(Small Formfactor Pluggable)/SFP+ > > > > > > > /QSFP+(Quad Small Formfactor Pluggable)/QSFP28 modules based > > > > > > > on SFF(Small Form Factor) Committee specifications > > > > > > > SFF-8079/SFF-8472/SFF-8024/SFF-8636. > > > > > > > > > > > > > > Signed-off-by: Robin Zhang <robinx.zhang@intel.com> > > > > > > > --- > > > > > > > > > > > > > > v2: > > > > > > > - Redesign the dump function as a telemetry command, so that > > > > > > > the > > > > > > EEPROM > > > > > > > information can be used by other app. > > > > > > > > > > > > > > - The usage like this: > > > > > > > > > > > > > > Launch the primary application with telemetry: > > > > > > > Take testpmd as example: ./app/dpdk-testpmd > > > > > > > > > > > > > > Then launch the telemetry client script: > > > > > > > ./usertools/dpdk-telemetry.py > > > > > > > > > > > > > > In telemetry client run command: > > > > > > > --> /sff_module/info,<port number> > > > > > > > > > > > > > > Both primary application and telemetry client will show the > > formated > > > > > > > module EEPROM information. > > > > > > > > > > > > > > drivers/common/meson.build | 1 + > > > > > > > drivers/common/sff_module/meson.build | 16 + > > > > > > > drivers/common/sff_module/sff_8079.c | 672 > > ++++++++++++++ > > > > > > > drivers/common/sff_module/sff_8472.c | 301 ++++++ > > > > > > > drivers/common/sff_module/sff_8636.c | 1004 > > > > > > +++++++++++++++++++++ > > > > > > > drivers/common/sff_module/sff_8636.h | 592 ++++++++++++ > > > > > > > drivers/common/sff_module/sff_common.c | 415 +++++++++ > > > > > > > drivers/common/sff_module/sff_common.h | 192 ++++ > > > > > > > drivers/common/sff_module/sff_telemetry.c | 142 +++ > > > > > > > drivers/common/sff_module/sff_telemetry.h | 41 + > > > > > > > drivers/common/sff_module/version.map | 9 + > > > > > > > 11 files changed, 3385 insertions(+) create mode 100644 > > > > > > > drivers/common/sff_module/meson.build > > > > > > > create mode 100644 drivers/common/sff_module/sff_8079.c > > > > > > > create mode 100644 drivers/common/sff_module/sff_8472.c > > > > > > > create mode 100644 drivers/common/sff_module/sff_8636.c > > > > > > > create mode 100644 drivers/common/sff_module/sff_8636.h > > > > > > > create mode 100644 drivers/common/sff_module/sff_common.c > > > > > > > create mode 100644 drivers/common/sff_module/sff_common.h > > > > > > > create mode 100644 drivers/common/sff_module/sff_telemetry.c > > > > > > > create mode 100644 drivers/common/sff_module/sff_telemetry.h > > > > > > > create mode 100644 drivers/common/sff_module/version.map > > > > > > > > > > > > > Is this is whole new driver just to provide telemetry dumps of > > > > > > SFP information? I can understand the problem somewhat - though > > > > > > I am in some doubt that telemetry is the best way to expose this > > > > > > information > > > > > > - but creating a new driver seems the wrong approach here. SFPs > > > > > > are for NIC devices, so why isn't this available in a common API > > > > > > such as > > > > ethdev? > > > > > > > > > > > > > > > > I have considered add this function as a new telemetry command of > > > > ethdev (like '/ethdev/sff_module_info') to dump these SFP information. > > > > > But I'm not sure if it's acceptable to add all these production > > > > > code > > > > (sff_8xxx.c) into lib/ethdev? > > > > > If it's OK, I can make V3 patches to change it as a telemetry > > > > > command of > > > > ethdev. > > > > > > > > > > > > > Hi, > > > > > > > > I think some discussion is needed before you go preparing a new > > > > version of this patchset. > > > > > > > > Some initial questions: > > > > > > > > 1. Does SFF code apply only to Intel products/NICs or is it multi-vendor? > > > The SFF code apply to multi-vendor. > > > In fact, it's applied to all the NIC driver which implemented dev_ops- > > >get_module_eeprom. > > > > > > > 2. For the driver approach you previously took, how was the presence of > > > > hardware detected to load the driver? > > > The purpose of put these production code into drivers/common is want to > > treat it as a common function for NIC drivers. > > > It will not related to any presence of hardware. > > > > > > > 3. Does this work on SFPs need to interact with the NIC drivers in any way? > > > > > > > Yes, just like my answer in question 1, the module EEPROM raw data is get > > from dev_ops->get_module_eeprom. > > > So need the NIC drivers to implement dev_ops->get_module_eeprom. > > > > > > > So is the intent that individual NIC drivers would add a get_module_eeprom > > function to their drivers pointing at this driver? If so, this approach of putting > > the code in drivers/common does make sense. However, this needs to be > > better explained in the patch description, and maybe include with the driver > > patch (which should probably be split up into easier reviewed sections), > > additional patches to add the get_eeprom function to some drivers to show > > use. > > > > Let me explain in more detail. > > This patch actually include two parts: > 1. Module EEPROM raw data parser code > Files: sff_common.h, sff_common.c, sff_8xxx.* > 2. Add new telemetry command > Files: sff_telemetry.h, sff_telemetry.c > > Part 1 will only parsing the module EEPROM raw data base on different module type. > Now DPDK support 4 types that defined in rte_dev_info.h with macro RTE_ETH_MODULE_SFF_8xxx. > > Part 2 will call rte_eth_dev_get_module_info and rte_eth_dev_get_module_eeprom to get the module EEPROM raw data, then pass the raw data to Part 1 parser code. Finally, Part 1 parser code will print formatted information. > > So, these codes are more likely a common tool than a common driver, because it will only read the module EEPROM raw data from NIC PMD driver. > For those NIC drivers who has not implemented get_module_info and get_module_eeprom dev_ops, we will simply return not support. > Thanks for the additional explanation. Adding more folks on CC who may have more thoughts on the best way to handle this. /Bruce ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v2] common/sff_module: add telemetry command to dump module EEPROM 2022-04-11 9:13 ` Bruce Richardson @ 2022-04-13 12:13 ` Thomas Monjalon 2022-04-14 7:41 ` David Marchand 0 siblings, 1 reply; 77+ messages in thread From: Thomas Monjalon @ 2022-04-13 12:13 UTC (permalink / raw) To: Zhang, RobinX, Bruce Richardson Cc: dev, Yang, Qiming, Zhang, Qi Z, Yang, SteveX, david.marchand, andrew.rybchenko 11/04/2022 11:13, Bruce Richardson: > On Mon, Apr 11, 2022 at 09:13:47AM +0100, Zhang, RobinX wrote: > > Hi Bruce, > > > > > -----Original Message----- > > > From: Richardson, Bruce <bruce.richardson@intel.com> > > > Sent: Friday, April 8, 2022 7:27 PM > > > To: Zhang, RobinX <robinx.zhang@intel.com> > > > Cc: dev@dpdk.org; Yang, Qiming <qiming.yang@intel.com>; Zhang, Qi Z > > > <qi.z.zhang@intel.com>; Yang, SteveX <stevex.yang@intel.com> > > > Subject: Re: [PATCH v2] common/sff_module: add telemetry command to > > > dump module EEPROM > > > > > > On Fri, Apr 08, 2022 at 12:20:23PM +0100, Zhang, RobinX wrote: > > > > Hi Bruce > > > > > > > > > -----Original Message----- > > > > > From: Richardson, Bruce <bruce.richardson@intel.com> > > > > > Sent: Friday, April 8, 2022 7:01 PM > > > > > To: Zhang, RobinX <robinx.zhang@intel.com> > > > > > Cc: dev@dpdk.org; Yang, Qiming <qiming.yang@intel.com>; Zhang, Qi Z > > > > > <qi.z.zhang@intel.com>; Yang, SteveX <stevex.yang@intel.com> > > > > > Subject: Re: [PATCH v2] common/sff_module: add telemetry command > > > to > > > > > dump module EEPROM > > > > > > > > > > On Fri, Apr 08, 2022 at 11:55:07AM +0100, Zhang, RobinX wrote: > > > > > > Hi Bruce, > > > > > > > > > > > > > -----Original Message----- > > > > > > > From: Richardson, Bruce <bruce.richardson@intel.com> > > > > > > > Sent: Friday, April 8, 2022 6:33 PM > > > > > > > To: Zhang, RobinX <robinx.zhang@intel.com> > > > > > > > Cc: dev@dpdk.org; Yang, Qiming <qiming.yang@intel.com>; Zhang, > > > > > > > Qi Z <qi.z.zhang@intel.com>; Yang, SteveX > > > > > > > <stevex.yang@intel.com> > > > > > > > Subject: Re: [PATCH v2] common/sff_module: add telemetry > > > command > > > > > to > > > > > > > dump module EEPROM > > > > > > > > > > > > > > On Fri, Apr 08, 2022 at 10:23:30AM +0000, Robin Zhang wrote: > > > > > > > > This patch introduce a new telemetry command '/sff_module/info' > > > > > > > > to dump format module EEPROM information. > > > > > > > > > > > > > > > > The format support for SFP(Small Formfactor Pluggable)/SFP+ > > > > > > > > /QSFP+(Quad Small Formfactor Pluggable)/QSFP28 modules based > > > > > > > > on SFF(Small Form Factor) Committee specifications > > > > > > > > SFF-8079/SFF-8472/SFF-8024/SFF-8636. > > > > > > > > > > > > > > > > Signed-off-by: Robin Zhang <robinx.zhang@intel.com> > > > > > > > > --- > > > > > > > > > > > > > > > > v2: > > > > > > > > - Redesign the dump function as a telemetry command, so that > > > > > > > > the > > > > > > > EEPROM > > > > > > > > information can be used by other app. > > > > > > > > > > > > > > > > - The usage like this: > > > > > > > > > > > > > > > > Launch the primary application with telemetry: > > > > > > > > Take testpmd as example: ./app/dpdk-testpmd > > > > > > > > > > > > > > > > Then launch the telemetry client script: > > > > > > > > ./usertools/dpdk-telemetry.py > > > > > > > > > > > > > > > > In telemetry client run command: > > > > > > > > --> /sff_module/info,<port number> > > > > > > > > > > > > > > > > Both primary application and telemetry client will show the > > > formated > > > > > > > > module EEPROM information. > > > > > > > > > > > > > > > > drivers/common/meson.build | 1 + > > > > > > > > drivers/common/sff_module/meson.build | 16 + > > > > > > > > drivers/common/sff_module/sff_8079.c | 672 > > > ++++++++++++++ > > > > > > > > drivers/common/sff_module/sff_8472.c | 301 ++++++ > > > > > > > > drivers/common/sff_module/sff_8636.c | 1004 > > > > > > > +++++++++++++++++++++ > > > > > > > > drivers/common/sff_module/sff_8636.h | 592 ++++++++++++ > > > > > > > > drivers/common/sff_module/sff_common.c | 415 +++++++++ > > > > > > > > drivers/common/sff_module/sff_common.h | 192 ++++ > > > > > > > > drivers/common/sff_module/sff_telemetry.c | 142 +++ > > > > > > > > drivers/common/sff_module/sff_telemetry.h | 41 + > > > > > > > > drivers/common/sff_module/version.map | 9 + > > > > > > > > 11 files changed, 3385 insertions(+) create mode 100644 > > > > > > > > drivers/common/sff_module/meson.build > > > > > > > > create mode 100644 drivers/common/sff_module/sff_8079.c > > > > > > > > create mode 100644 drivers/common/sff_module/sff_8472.c > > > > > > > > create mode 100644 drivers/common/sff_module/sff_8636.c > > > > > > > > create mode 100644 drivers/common/sff_module/sff_8636.h > > > > > > > > create mode 100644 drivers/common/sff_module/sff_common.c > > > > > > > > create mode 100644 drivers/common/sff_module/sff_common.h > > > > > > > > create mode 100644 drivers/common/sff_module/sff_telemetry.c > > > > > > > > create mode 100644 drivers/common/sff_module/sff_telemetry.h > > > > > > > > create mode 100644 drivers/common/sff_module/version.map > > > > > > > > > > > > > > > Is this is whole new driver just to provide telemetry dumps of > > > > > > > SFP information? I can understand the problem somewhat - though > > > > > > > I am in some doubt that telemetry is the best way to expose this > > > > > > > information > > > > > > > - but creating a new driver seems the wrong approach here. SFPs > > > > > > > are for NIC devices, so why isn't this available in a common API > > > > > > > such as > > > > > ethdev? > > > > > > > > > > > > > > > > > > > I have considered add this function as a new telemetry command of > > > > > ethdev (like '/ethdev/sff_module_info') to dump these SFP information. > > > > > > But I'm not sure if it's acceptable to add all these production > > > > > > code > > > > > (sff_8xxx.c) into lib/ethdev? > > > > > > If it's OK, I can make V3 patches to change it as a telemetry > > > > > > command of > > > > > ethdev. > > > > > > > > > > > > > > > > Hi, > > > > > > > > > > I think some discussion is needed before you go preparing a new > > > > > version of this patchset. > > > > > > > > > > Some initial questions: > > > > > > > > > > 1. Does SFF code apply only to Intel products/NICs or is it multi-vendor? > > > > The SFF code apply to multi-vendor. > > > > In fact, it's applied to all the NIC driver which implemented dev_ops- > > > >get_module_eeprom. > > > > > > > > > 2. For the driver approach you previously took, how was the presence of > > > > > hardware detected to load the driver? > > > > The purpose of put these production code into drivers/common is want to > > > treat it as a common function for NIC drivers. > > > > It will not related to any presence of hardware. > > > > > > > > > 3. Does this work on SFPs need to interact with the NIC drivers in any way? > > > > > > > > > Yes, just like my answer in question 1, the module EEPROM raw data is get > > > from dev_ops->get_module_eeprom. > > > > So need the NIC drivers to implement dev_ops->get_module_eeprom. > > > > > > > > > > So is the intent that individual NIC drivers would add a get_module_eeprom > > > function to their drivers pointing at this driver? If so, this approach of putting > > > the code in drivers/common does make sense. However, this needs to be > > > better explained in the patch description, and maybe include with the driver > > > patch (which should probably be split up into easier reviewed sections), > > > additional patches to add the get_eeprom function to some drivers to show > > > use. > > > > > > > Let me explain in more detail. > > > > This patch actually include two parts: > > 1. Module EEPROM raw data parser code > > Files: sff_common.h, sff_common.c, sff_8xxx.* > > 2. Add new telemetry command > > Files: sff_telemetry.h, sff_telemetry.c > > > > Part 1 will only parsing the module EEPROM raw data base on different module type. > > Now DPDK support 4 types that defined in rte_dev_info.h with macro RTE_ETH_MODULE_SFF_8xxx. > > > > Part 2 will call rte_eth_dev_get_module_info and rte_eth_dev_get_module_eeprom to get the module EEPROM raw data, then pass the raw data to Part 1 parser code. Finally, Part 1 parser code will print formatted information. > > > > So, these codes are more likely a common tool than a common driver, because it will only read the module EEPROM raw data from NIC PMD driver. > > For those NIC drivers who has not implemented get_module_info and get_module_eeprom dev_ops, we will simply return not support. > > > Thanks for the additional explanation. Adding more folks on CC who may have > more thoughts on the best way to handle this. That's ethdev and/or net driver code. If I understand well, SFF are standards and no tight to any HW, right? In this case, I think the common code can be in ethdev library. ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v2] common/sff_module: add telemetry command to dump module EEPROM 2022-04-13 12:13 ` Thomas Monjalon @ 2022-04-14 7:41 ` David Marchand 0 siblings, 0 replies; 77+ messages in thread From: David Marchand @ 2022-04-14 7:41 UTC (permalink / raw) To: Thomas Monjalon Cc: Zhang, RobinX, Bruce Richardson, dev, Yang, Qiming, Zhang, Qi Z, Yang, SteveX, Andrew Rybchenko On Wed, Apr 13, 2022 at 2:13 PM Thomas Monjalon <thomas@monjalon.net> wrote: > > > Let me explain in more detail. > > > > > > This patch actually include two parts: > > > 1. Module EEPROM raw data parser code > > > Files: sff_common.h, sff_common.c, sff_8xxx.* > > > 2. Add new telemetry command > > > Files: sff_telemetry.h, sff_telemetry.c > > > > > > Part 1 will only parsing the module EEPROM raw data base on different module type. > > > Now DPDK support 4 types that defined in rte_dev_info.h with macro RTE_ETH_MODULE_SFF_8xxx. > > > > > > Part 2 will call rte_eth_dev_get_module_info and rte_eth_dev_get_module_eeprom to get the module EEPROM raw data, then pass the raw data to Part 1 parser code. Finally, Part 1 parser code will print formatted information. > > > > > > So, these codes are more likely a common tool than a common driver, because it will only read the module EEPROM raw data from NIC PMD driver. > > > For those NIC drivers who has not implemented get_module_info and get_module_eeprom dev_ops, we will simply return not support. > > > > > Thanks for the additional explanation. Adding more folks on CC who may have > > more thoughts on the best way to handle this. > > That's ethdev and/or net driver code. > If I understand well, SFF are standards and no tight to any HW, right? That's my understanding too. > In this case, I think the common code can be in ethdev library. +1 -- David Marchand ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v3 0/5] add telemetry command for show module EEPROM 2022-02-15 10:18 [PATCH] app/testpmd: format dump information of module EEPROM Robin Zhang 2022-02-15 13:28 ` Ferruh Yigit 2022-04-08 10:23 ` [PATCH v2] common/sff_module: add telemetry command to dump " Robin Zhang @ 2022-04-20 7:00 ` Robin Zhang 2022-04-20 7:00 ` [PATCH v3 1/5] ethdev: add telemetry command for " Robin Zhang ` (5 more replies) 2022-04-25 5:34 ` [PATCH v4 " Robin Zhang 2022-04-26 2:43 ` [PATCH v5 0/5] add telemetry command for show module EEPROM Robin Zhang 4 siblings, 6 replies; 77+ messages in thread From: Robin Zhang @ 2022-04-20 7:00 UTC (permalink / raw) To: dev Cc: qiming.yang, qi.z.zhang, stevex.yang, thomas, andrew.rybchenko, bruce.richardson, david.marchand, Robin Zhang Introduce a new telemetry command /ethdev/module_eeprom to show module EEPROM for each port. The format of module EEPROM information follows the SFF(Small Form Factor) Committee specifications. Current the format support SFP(Small Formfactor Pluggable)/SFP+/ QSFP+(Quad Small Formfactor Pluggable)/QSFP28 with specs SFF-8079/ SFF-8472/SFF-8024/SFF-8636. Afther run the /ethdev/module_eeprom command, both primary application and telemetry client will show the module EEPROM information. For primary application, we keep the same format with Linux utility ethtool, refer to command 'ethtool -m' of ethtool v5.4. For telemetry client, we record the key value pairs of each item, then show them in telemetry client dictionary. Robin Zhang (5): ethdev: add telemetry command for module EEPROM ethdev: common utilities for different SFF specs ethdev: format module EEPROM for SFF-8079 ethdev: format module EEPROM for SFF-8472 ethdev: format module EEPROM for SFF-8636 lib/ethdev/ethdev_sff_telemetry.c | 135 ++++ lib/ethdev/ethdev_sff_telemetry.h | 42 ++ lib/ethdev/meson.build | 5 + lib/ethdev/rte_ethdev.c | 3 + lib/ethdev/sff_8079.c | 672 +++++++++++++++++++ lib/ethdev/sff_8472.c | 301 +++++++++ lib/ethdev/sff_8636.c | 1004 +++++++++++++++++++++++++++++ lib/ethdev/sff_8636.h | 592 +++++++++++++++++ lib/ethdev/sff_common.c | 414 ++++++++++++ lib/ethdev/sff_common.h | 191 ++++++ 10 files changed, 3359 insertions(+) create mode 100644 lib/ethdev/ethdev_sff_telemetry.c create mode 100644 lib/ethdev/ethdev_sff_telemetry.h create mode 100644 lib/ethdev/sff_8079.c create mode 100644 lib/ethdev/sff_8472.c create mode 100644 lib/ethdev/sff_8636.c create mode 100644 lib/ethdev/sff_8636.h create mode 100644 lib/ethdev/sff_common.c create mode 100644 lib/ethdev/sff_common.h -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v3 1/5] ethdev: add telemetry command for module EEPROM 2022-04-20 7:00 ` [PATCH v3 0/5] add telemetry command for show " Robin Zhang @ 2022-04-20 7:00 ` Robin Zhang 2022-04-20 9:16 ` Andrew Rybchenko 2022-04-20 7:00 ` [PATCH v3 2/5] ethdev: common utilities for different SFF specs Robin Zhang ` (4 subsequent siblings) 5 siblings, 1 reply; 77+ messages in thread From: Robin Zhang @ 2022-04-20 7:00 UTC (permalink / raw) To: dev Cc: qiming.yang, qi.z.zhang, stevex.yang, thomas, andrew.rybchenko, bruce.richardson, david.marchand, Robin Zhang Add a new telemetry command /ethdev/module_eeprom to dump the module EEPROM of each port. The format of module EEPROM information follows the SFF(Small Form Factor) Committee specifications. Current the format support SFP(Small Formfactor Pluggable)/SFP+/ QSFP+(Quad Small Formfactor Pluggable)/QSFP28 with specs SFF-8079/ SFF-8472/SFF-8024/SFF-8636. Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/ethdev_sff_telemetry.c | 135 ++++++++++++++++++++++++++++++ lib/ethdev/ethdev_sff_telemetry.h | 42 ++++++++++ lib/ethdev/meson.build | 5 ++ lib/ethdev/rte_ethdev.c | 3 + 4 files changed, 185 insertions(+) create mode 100644 lib/ethdev/ethdev_sff_telemetry.c create mode 100644 lib/ethdev/ethdev_sff_telemetry.h diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c new file mode 100644 index 0000000000..60dc19c206 --- /dev/null +++ b/lib/ethdev/ethdev_sff_telemetry.c @@ -0,0 +1,135 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Cavium, Inc + */ + +#include <rte_ethdev.h> +#include <rte_common.h> +#include "ethdev_sff_telemetry.h" + +static void +sff_port_module_eeprom_display(uint16_t port_id, sff_item *items) +{ + struct rte_eth_dev_module_info minfo; + struct rte_dev_eeprom_info einfo; + int ret; + + ret = rte_eth_dev_get_module_info(port_id, &minfo); + if (ret != 0) { + switch (ret) { + case -ENODEV: + fprintf(stderr, "port index %d invalid\n", port_id); + break; + case -ENOTSUP: + fprintf(stderr, "operation not supported by device\n"); + break; + case -EIO: + fprintf(stderr, "device is removed\n"); + break; + default: + fprintf(stderr, "Unable to get module EEPROM: %d\n", + ret); + break; + } + return; + } + + einfo.offset = 0; + einfo.length = minfo.eeprom_len; + einfo.data = calloc(1, minfo.eeprom_len); + if (!einfo.data) { + fprintf(stderr, + "Allocation of port %u eeprom data failed\n", + port_id); + return; + } + + ret = rte_eth_dev_get_module_eeprom(port_id, &einfo); + if (ret != 0) { + switch (ret) { + case -ENODEV: + fprintf(stderr, "port index %d invalid\n", port_id); + break; + case -ENOTSUP: + fprintf(stderr, "operation not supported by device\n"); + break; + case -EIO: + fprintf(stderr, "device is removed\n"); + break; + default: + fprintf(stderr, "Unable to get module EEPROM: %d\n", + ret); + break; + } + free(einfo.data); + return; + } + + switch (minfo.type) { + case RTE_ETH_MODULE_SFF_8079: + sff_8079_show_all(einfo.data, items); + break; + case RTE_ETH_MODULE_SFF_8472: + sff_8079_show_all(einfo.data, items); + sff_8472_show_all(einfo.data, items); + break; + case RTE_ETH_MODULE_SFF_8436: + case RTE_ETH_MODULE_SFF_8636: + sff_8636_show_all(einfo.data, einfo.length, items); + break; + default: + break; + } + printf("Finish -- Port: %d MODULE EEPROM length: %d bytes\n", port_id, einfo.length); + free(einfo.data); +} + +void +add_item_string(sff_item *items, const char *name_str, const char *value_str) +{ + /* append different values for same keys */ + if (sff_item_count > 0 && + (strcmp(items[sff_item_count - 1].name, name_str) == 0)) { + strcat(items[sff_item_count - 1].value, "; "); + strcat(items[sff_item_count - 1].value, value_str); + return; + } + + sprintf(items[sff_item_count].name, "%s", name_str); + sprintf(items[sff_item_count].value, "%s", value_str); + sff_item_count++; +} + +int +eth_dev_handle_port_module_eeprom(const char *cmd __rte_unused, const char *params, + struct rte_tel_data *d) +{ + char *end_param; + int port_id, i; + sff_item *items; + sff_item_count = 0; + + if (params == NULL || strlen(params) == 0 || !isdigit(*params)) + return -1; + + port_id = strtoul(params, &end_param, 0); + if (*end_param != '\0') + RTE_ETHDEV_LOG(NOTICE, + "Extra parameters passed to ethdev telemetry command, ignoring"); + + items = (sff_item *)malloc(SFF_ITEM_SIZE * SFF_ITEM_MAX_COUNT); + if (items == NULL) { + printf("Error allocating memory of items\n"); + free(items); + return -1; + } + + sff_port_module_eeprom_display(port_id, items); + + rte_tel_data_start_dict(d); + for (i = 0; i < sff_item_count; i++) + rte_tel_data_add_dict_string(d, items[i].name, items[i].value); + + free(items); + return 0; +} + diff --git a/lib/ethdev/ethdev_sff_telemetry.h b/lib/ethdev/ethdev_sff_telemetry.h new file mode 100644 index 0000000000..fd032407c8 --- /dev/null +++ b/lib/ethdev/ethdev_sff_telemetry.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Cavium, Inc + */ + +#ifndef ETHDEV_SFF_H_ +#define ETHDEV_SFF_H_ + +#include <rte_ethdev.h> +#include <rte_telemetry.h> + +#define ARRAY_SIZE(arr) RTE_DIM(arr) + +#define SFF_ITEM_NAME_SIZE 64 +#define SFF_ITEM_VALUE_SIZE 256 +#define SFF_ITEM_MAX_COUNT 256 +#define TMP_STRING_SIZE 64 + +typedef struct sff_module_info_item { + char name[SFF_ITEM_NAME_SIZE]; /* The item name. */ + char value[SFF_ITEM_VALUE_SIZE]; /* The item value. */ +} sff_item; + +#define SFF_ITEM_SIZE sizeof(sff_item) + +uint16_t sff_item_count; + +/* SFF-8079 Optics diagnostics */ +void sff_8079_show_all(const uint8_t *id, sff_item *items); + +/* SFF-8472 Optics diagnostics */ +void sff_8472_show_all(const uint8_t *id, sff_item *items); + +/* SFF-8636 Optics diagnostics */ +void sff_8636_show_all(const uint8_t *id, uint32_t eeprom_len, sff_item *items); + +int eth_dev_handle_port_module_eeprom(const char *cmd __rte_unused, + const char *params, + struct rte_tel_data *d); + +void add_item_string(sff_item *items, const char *name_str, const char *value_str); + +#endif /* ETHDEV_SFF_H_ */ diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index a094585bf7..88ceeb12b9 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -11,6 +11,11 @@ sources = files( 'rte_flow.c', 'rte_mtr.c', 'rte_tm.c', + 'ethdev_sff_telemetry.c', + 'sff_common.c', + 'sff_8079.c', + 'sff_8472.c', + 'sff_8636.c', ) headers = files( diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c index 29a3d80466..2b87df1b32 100644 --- a/lib/ethdev/rte_ethdev.c +++ b/lib/ethdev/rte_ethdev.c @@ -39,6 +39,7 @@ #include "ethdev_driver.h" #include "ethdev_profile.h" #include "ethdev_private.h" +#include "ethdev_sff_telemetry.h" struct rte_eth_dev rte_eth_devices[RTE_MAX_ETHPORTS]; @@ -5876,4 +5877,6 @@ RTE_INIT(ethdev_init_telemetry) "Returns the link status for a port. Parameters: int port_id"); rte_telemetry_register_cmd("/ethdev/info", eth_dev_handle_port_info, "Returns the device info for a port. Parameters: int port_id"); + rte_telemetry_register_cmd("/ethdev/module_eeprom", eth_dev_handle_port_module_eeprom, + "Returns module EEPROM info with SFF specs. Parameters: int port_id"); } -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v3 1/5] ethdev: add telemetry command for module EEPROM 2022-04-20 7:00 ` [PATCH v3 1/5] ethdev: add telemetry command for " Robin Zhang @ 2022-04-20 9:16 ` Andrew Rybchenko 0 siblings, 0 replies; 77+ messages in thread From: Andrew Rybchenko @ 2022-04-20 9:16 UTC (permalink / raw) To: Robin Zhang, dev Cc: qiming.yang, qi.z.zhang, stevex.yang, thomas, bruce.richardson, david.marchand On 4/20/22 10:00, Robin Zhang wrote: > Add a new telemetry command /ethdev/module_eeprom to dump the module > EEPROM of each port. The format of module EEPROM information follows > the SFF(Small Form Factor) Committee specifications. > > Current the format support SFP(Small Formfactor Pluggable)/SFP+/ > QSFP+(Quad Small Formfactor Pluggable)/QSFP28 with specs SFF-8079/ > SFF-8472/SFF-8024/SFF-8636. > > Signed-off-by: Robin Zhang <robinx.zhang@intel.com> > --- > lib/ethdev/ethdev_sff_telemetry.c | 135 ++++++++++++++++++++++++++++++ > lib/ethdev/ethdev_sff_telemetry.h | 42 ++++++++++ > lib/ethdev/meson.build | 5 ++ > lib/ethdev/rte_ethdev.c | 3 + > 4 files changed, 185 insertions(+) > create mode 100644 lib/ethdev/ethdev_sff_telemetry.c > create mode 100644 lib/ethdev/ethdev_sff_telemetry.h > > diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c > new file mode 100644 > index 0000000000..60dc19c206 > --- /dev/null > +++ b/lib/ethdev/ethdev_sff_telemetry.c > @@ -0,0 +1,135 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2018 Cavium, Inc I'm wondering why the patch comes from intel.com, but has Cavium copyright dated by 2018. > + */ > + > +#include <rte_ethdev.h> > +#include <rte_common.h> > +#include "ethdev_sff_telemetry.h" > + > +static void > +sff_port_module_eeprom_display(uint16_t port_id, sff_item *items) > +{ > + struct rte_eth_dev_module_info minfo; > + struct rte_dev_eeprom_info einfo; > + int ret; > + > + ret = rte_eth_dev_get_module_info(port_id, &minfo); > + if (ret != 0) { > + switch (ret) { > + case -ENODEV: > + fprintf(stderr, "port index %d invalid\n", port_id); Why is it go to stderr directly? Shouldn't DPDK logging be used? > + break; > + case -ENOTSUP: > + fprintf(stderr, "operation not supported by device\n"); > + break; > + case -EIO: > + fprintf(stderr, "device is removed\n"); > + break; > + default: > + fprintf(stderr, "Unable to get module EEPROM: %d\n", > + ret); > + break; > + } > + return; > + } > + > + einfo.offset = 0; > + einfo.length = minfo.eeprom_len; > + einfo.data = calloc(1, minfo.eeprom_len); > + if (!einfo.data) { Compare vs NULL > + fprintf(stderr, > + "Allocation of port %u eeprom data failed\n", > + port_id); > + return; > + } > + > + ret = rte_eth_dev_get_module_eeprom(port_id, &einfo); > + if (ret != 0) { > + switch (ret) { > + case -ENODEV: > + fprintf(stderr, "port index %d invalid\n", port_id); > + break; > + case -ENOTSUP: > + fprintf(stderr, "operation not supported by device\n"); > + break; > + case -EIO: > + fprintf(stderr, "device is removed\n"); > + break; > + default: > + fprintf(stderr, "Unable to get module EEPROM: %d\n", > + ret); > + break; > + } It looks like a duplicate of above switch. > + free(einfo.data); > + return; > + } > + > + switch (minfo.type) { > + case RTE_ETH_MODULE_SFF_8079: > + sff_8079_show_all(einfo.data, items); I guess the build is broken after the patch since the function is not defined. It is added in follow up patches. I think corresponding cases should be added in follow up patches which add corresponding spec support. > + break; > + case RTE_ETH_MODULE_SFF_8472: > + sff_8079_show_all(einfo.data, items); > + sff_8472_show_all(einfo.data, items); same here > + break; > + case RTE_ETH_MODULE_SFF_8436: > + case RTE_ETH_MODULE_SFF_8636: > + sff_8636_show_all(einfo.data, einfo.length, items); same here > + break; > + default: Don't we need some logging to help user to understand that eeprom type is not supported? > + break; > + } > + printf("Finish -- Port: %d MODULE EEPROM length: %d bytes\n", port_id, einfo.length); > + free(einfo.data); > +} > + > +void > +add_item_string(sff_item *items, const char *name_str, const char *value_str) > +{ > + /* append different values for same keys */ > + if (sff_item_count > 0 && > + (strcmp(items[sff_item_count - 1].name, name_str) == 0)) { > + strcat(items[sff_item_count - 1].value, "; "); > + strcat(items[sff_item_count - 1].value, value_str); > + return; > + } > + > + sprintf(items[sff_item_count].name, "%s", name_str); > + sprintf(items[sff_item_count].value, "%s", value_str); strcat() and sprintf() are terribly unsafe and should be avoided. Use strlcat() and snprintf() instead. > + sff_item_count++; > +} > + > +int > +eth_dev_handle_port_module_eeprom(const char *cmd __rte_unused, const char *params, > + struct rte_tel_data *d) > +{ > + char *end_param; > + int port_id, i; > + sff_item *items; > + sff_item_count = 0; > + > + if (params == NULL || strlen(params) == 0 || !isdigit(*params)) > + return -1; > + > + port_id = strtoul(params, &end_param, 0); Strictly speaking we need to care about about overflow here, since if input string is a long long string of digits, end_param will point to \0, but errno will be set to ERANGE. 'man strtoul' recommends to reset errno to 0 and check it after the call. > + if (*end_param != '\0') > + RTE_ETHDEV_LOG(NOTICE, > + "Extra parameters passed to ethdev telemetry command, ignoring"); > + > + items = (sff_item *)malloc(SFF_ITEM_SIZE * SFF_ITEM_MAX_COUNT); Since we allocate an array here with specified element size and number of elements, calloc() should be used. Type cast from 'void *' is not required in C. > + if (items == NULL) { > + printf("Error allocating memory of items\n"); Why is RTE_ETHDEV_LOG used above, but not here? Why above error logging uses fprintf(stderr, ...), but error logs are sent to stdout here? I think that RTE_ETHDEV_LOG should be used everywhere. > + free(items); What's the point to free items, if it is known to be NULL? > + return -1; > + } > + > + sff_port_module_eeprom_display(port_id, items); > + > + rte_tel_data_start_dict(d); > + for (i = 0; i < sff_item_count; i++) > + rte_tel_data_add_dict_string(d, items[i].name, items[i].value); > + > + free(items); > + return 0; > +} > + > diff --git a/lib/ethdev/ethdev_sff_telemetry.h b/lib/ethdev/ethdev_sff_telemetry.h > new file mode 100644 > index 0000000000..fd032407c8 > --- /dev/null > +++ b/lib/ethdev/ethdev_sff_telemetry.h > @@ -0,0 +1,42 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2018 Cavium, Inc > + */ > + > +#ifndef ETHDEV_SFF_H_ > +#define ETHDEV_SFF_H_ Header guard names should follow file name, i.e. ETHDEV_SFF_TELEMETRY_H_. (It is still open question to have some prefix, leading understand etc since various approaches are present in DPDK headers). > + > +#include <rte_ethdev.h> It looks like the include is not actually used in the header. > +#include <rte_telemetry.h> > + > +#define ARRAY_SIZE(arr) RTE_DIM(arr) > + > +#define SFF_ITEM_NAME_SIZE 64 > +#define SFF_ITEM_VALUE_SIZE 256 > +#define SFF_ITEM_MAX_COUNT 256 > +#define TMP_STRING_SIZE 64 This one is really bad define since it does not explain its indented usage. Is it for value? Or is it to compose name? So, it is hard to say if specified value is sufficient and taking into account that you don't check overflow anyway. > + > +typedef struct sff_module_info_item { > + char name[SFF_ITEM_NAME_SIZE]; /* The item name. */ > + char value[SFF_ITEM_VALUE_SIZE]; /* The item value. */ > +} sff_item; Typically DPDK does not use typedefs for structures and use 'struct sff_item' as is. > + > +#define SFF_ITEM_SIZE sizeof(sff_item) I see no value in introduction of the define. As far as I can see it is used only once and sizeof(struct sff_item) would look better there. > + > +uint16_t sff_item_count; > + > +/* SFF-8079 Optics diagnostics */ > +void sff_8079_show_all(const uint8_t *id, sff_item *items); What is 'id' above? Is it some kind identifier? As far as I can see struct rte_dev_eeprom_info.data is passed there. If so, why is it called 'id' here? Don't we need to pass length to check inside that we never have out-of-bounds access (e.g. if something is buggy and provided information is not terminated properly). > + > +/* SFF-8472 Optics diagnostics */ > +void sff_8472_show_all(const uint8_t *id, sff_item *items); > + > +/* SFF-8636 Optics diagnostics */ > +void sff_8636_show_all(const uint8_t *id, uint32_t eeprom_len, sff_item *items); > + > +int eth_dev_handle_port_module_eeprom(const char *cmd __rte_unused, > + const char *params, > + struct rte_tel_data *d); > + > +void add_item_string(sff_item *items, const char *name_str, const char *value_str); > + > +#endif /* ETHDEV_SFF_H_ */ > diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build > index a094585bf7..88ceeb12b9 100644 > --- a/lib/ethdev/meson.build > +++ b/lib/ethdev/meson.build > @@ -11,6 +11,11 @@ sources = files( > 'rte_flow.c', > 'rte_mtr.c', > 'rte_tm.c', > + 'ethdev_sff_telemetry.c', > + 'sff_common.c', > + 'sff_8079.c', > + 'sff_8472.c', > + 'sff_8636.c', Is it a mail client glitch or alignment above really differs: TABs vs spaces? > ) > > headers = files( [snip] ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v3 2/5] ethdev: common utilities for different SFF specs 2022-04-20 7:00 ` [PATCH v3 0/5] add telemetry command for show " Robin Zhang 2022-04-20 7:00 ` [PATCH v3 1/5] ethdev: add telemetry command for " Robin Zhang @ 2022-04-20 7:00 ` Robin Zhang 2022-04-20 7:00 ` [PATCH v3 3/5] ethdev: format module EEPROM for SFF-8079 Robin Zhang ` (3 subsequent siblings) 5 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-04-20 7:00 UTC (permalink / raw) To: dev Cc: qiming.yang, qi.z.zhang, stevex.yang, thomas, andrew.rybchenko, bruce.richardson, david.marchand, Robin Zhang This patch implements SFF-8024 Rev 4.0 of pluggable I/O configuration and some common utilities for SFF-8436/8636 and SFF-8472/8079. Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/sff_common.c | 414 ++++++++++++++++++++++++++++++++++++++++ lib/ethdev/sff_common.h | 191 ++++++++++++++++++ 2 files changed, 605 insertions(+) create mode 100644 lib/ethdev/sff_common.c create mode 100644 lib/ethdev/sff_common.h diff --git a/lib/ethdev/sff_common.c b/lib/ethdev/sff_common.c new file mode 100644 index 0000000000..015ea268db --- /dev/null +++ b/lib/ethdev/sff_common.c @@ -0,0 +1,414 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2022 Intel Corporation + * + * Implements SFF-8024 Rev 4.0 of pluggable I/O configuration and some + * common utilities for SFF-8436/8636 and SFF-8472/8079 + * + */ + +#include <stdio.h> +#include <math.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "ethdev_sff_telemetry.h" + + +double convert_mw_to_dbm(double mw) +{ + return (10. * log10(mw / 1000.)) + 30.; +} + +void sff_show_value_with_unit(const uint8_t *id, unsigned int reg, + const char *name, unsigned int mult, + const char *unit, sff_item *items) +{ + unsigned int val = id[reg]; + char val_string[TMP_STRING_SIZE]; + + printf("%-41s : %u%s\n", name, val * mult, unit); + sprintf(val_string, "%u%s", val * mult, unit); + add_item_string(items, name, val_string); +} + +void sff_show_ascii(const uint8_t *id, unsigned int first_reg, + unsigned int last_reg, const char *name, sff_item *items) +{ + unsigned int reg, val; + char tmp[3]; + char val_string[TMP_STRING_SIZE]; + + memset(val_string, 0, sizeof(val_string)); + + printf("%-41s : ", name); + while (first_reg <= last_reg && id[last_reg] == ' ') + last_reg--; + for (reg = first_reg; reg <= last_reg; reg++) { + val = id[reg]; + putchar(((val >= 32) && (val <= 126)) ? val : '_'); + if ((val >= 32) && (val <= 126)) { + sprintf(tmp, "%c", val); + strcat(val_string, tmp); + } else { + strcat(val_string, "_"); + } + } + printf("\n"); + add_item_string(items, name, val_string); +} + +void sff_8024_show_oui(const uint8_t *id, int id_offset, sff_item *items) +{ + char val_string[TMP_STRING_SIZE]; + + printf("%-41s : %02x:%02x:%02x\n", "Vendor OUI", + id[id_offset], id[(id_offset) + 1], + id[(id_offset) + 2]); + sprintf(val_string, "%02x:%02x:%02x", + id[id_offset], id[(id_offset) + 1], id[(id_offset) + 2]); + add_item_string(items, "Vendor OUI", val_string); +} + +void sff_8024_show_identifier(const uint8_t *id, int id_offset, sff_item *items) +{ + char val_string[TMP_STRING_SIZE]; + + printf("%-41s : 0x%02x", "Identifier", id[id_offset]); + sprintf(val_string, "0x%02x", id[id_offset]); + + switch (id[id_offset]) { + case SFF_8024_ID_UNKNOWN: + printf(" (no module present, unknown, or unspecified)\n"); + strcat(val_string, " (no module present, unknown, or unspecified)"); + break; + case SFF_8024_ID_GBIC: + printf(" (GBIC)\n"); + strcat(val_string, " (GBIC)"); + break; + case SFF_8024_ID_SOLDERED_MODULE: + printf(" (module soldered to motherboard)\n"); + strcat(val_string, " (module soldered to motherboard)"); + break; + case SFF_8024_ID_SFP: + printf(" (SFP)\n"); + strcat(val_string, " (SFP)"); + break; + case SFF_8024_ID_300_PIN_XBI: + printf(" (300 pin XBI)\n"); + strcat(val_string, " (300 pin XBI)"); + break; + case SFF_8024_ID_XENPAK: + printf(" (XENPAK)\n"); + strcat(val_string, " (XENPAK)"); + break; + case SFF_8024_ID_XFP: + printf(" (XFP)\n"); + strcat(val_string, " (XFP)"); + break; + case SFF_8024_ID_XFF: + printf(" (XFF)\n"); + strcat(val_string, " (XFF)"); + break; + case SFF_8024_ID_XFP_E: + printf(" (XFP-E)\n"); + strcat(val_string, " (XFP-E)"); + break; + case SFF_8024_ID_XPAK: + printf(" (XPAK)\n"); + strcat(val_string, " (XPAK)"); + break; + case SFF_8024_ID_X2: + printf(" (X2)\n"); + strcat(val_string, " (X2)"); + break; + case SFF_8024_ID_DWDM_SFP: + printf(" (DWDM-SFP)\n"); + strcat(val_string, " (DWDM-SFP)"); + break; + case SFF_8024_ID_QSFP: + printf(" (QSFP)\n"); + strcat(val_string, " (QSFP)"); + break; + case SFF_8024_ID_QSFP_PLUS: + printf(" (QSFP+)\n"); + strcat(val_string, " (QSFP+)"); + break; + case SFF_8024_ID_CXP: + printf(" (CXP)\n"); + strcat(val_string, " (CXP)"); + break; + case SFF_8024_ID_HD4X: + printf(" (Shielded Mini Multilane HD 4X)\n"); + strcat(val_string, " (Shielded Mini Multilane HD 4X)"); + break; + case SFF_8024_ID_HD8X: + printf(" (Shielded Mini Multilane HD 8X)\n"); + strcat(val_string, " (Shielded Mini Multilane HD 8X)"); + break; + case SFF_8024_ID_QSFP28: + printf(" (QSFP28)\n"); + strcat(val_string, " (QSFP28)"); + break; + case SFF_8024_ID_CXP2: + printf(" (CXP2/CXP28)\n"); + strcat(val_string, " (CXP2/CXP28)"); + break; + case SFF_8024_ID_CDFP: + printf(" (CDFP Style 1/Style 2)\n"); + strcat(val_string, " (CDFP Style 1/Style 2)"); + break; + case SFF_8024_ID_HD4X_FANOUT: + printf(" (Shielded Mini Multilane HD 4X Fanout Cable)\n"); + strcat(val_string, " (Shielded Mini Multilane HD 4X Fanout Cable)"); + break; + case SFF_8024_ID_HD8X_FANOUT: + printf(" (Shielded Mini Multilane HD 8X Fanout Cable)\n"); + strcat(val_string, " (Shielded Mini Multilane HD 8X Fanout Cable)"); + break; + case SFF_8024_ID_CDFP_S3: + printf(" (CDFP Style 3)\n"); + strcat(val_string, " (CDFP Style 3)"); + break; + case SFF_8024_ID_MICRO_QSFP: + printf(" (microQSFP)\n"); + strcat(val_string, " (microQSFP)"); + break; + default: + printf(" (reserved or unknown)\n"); + strcat(val_string, " (reserved or unknown)"); + break; + } + add_item_string(items, "Identifier", val_string); +} + +void sff_8024_show_connector(const uint8_t *id, int ctor_offset, sff_item *items) +{ + char val_string[TMP_STRING_SIZE]; + + printf("%-41s : 0x%02x", "Connector", id[ctor_offset]); + sprintf(val_string, "0x%02x", id[ctor_offset]); + + switch (id[ctor_offset]) { + case SFF_8024_CTOR_UNKNOWN: + printf(" (unknown or unspecified)\n"); + strcat(val_string, " (unknown or unspecified)"); + break; + case SFF_8024_CTOR_SC: + printf(" (SC)\n"); + strcat(val_string, " (SC)"); + break; + case SFF_8024_CTOR_FC_STYLE_1: + printf(" (Fibre Channel Style 1 copper)\n"); + strcat(val_string, " (Fibre Channel Style 1 copper)"); + break; + case SFF_8024_CTOR_FC_STYLE_2: + printf(" (Fibre Channel Style 2 copper)\n"); + strcat(val_string, " (Fibre Channel Style 2 copper)"); + break; + case SFF_8024_CTOR_BNC_TNC: + printf(" (BNC/TNC)\n"); + strcat(val_string, " (BNC/TNC)"); + break; + case SFF_8024_CTOR_FC_COAX: + printf(" (Fibre Channel coaxial headers)\n"); + strcat(val_string, " (Fibre Channel coaxial headers)"); + break; + case SFF_8024_CTOR_FIBER_JACK: + printf(" (FibreJack)\n"); + strcat(val_string, " (FibreJack)"); + break; + case SFF_8024_CTOR_LC: + printf(" (LC)\n"); + strcat(val_string, " (LC)"); + break; + case SFF_8024_CTOR_MT_RJ: + printf(" (MT-RJ)\n"); + strcat(val_string, " (MT-RJ)"); + break; + case SFF_8024_CTOR_MU: + printf(" (MU)\n"); + strcat(val_string, " (MU)"); + break; + case SFF_8024_CTOR_SG: + printf(" (SG)\n"); + strcat(val_string, " (SG)"); + break; + case SFF_8024_CTOR_OPT_PT: + printf(" (Optical pigtail)\n"); + strcat(val_string, " (Optical pigtail)"); + break; + case SFF_8024_CTOR_MPO: + printf(" (MPO Parallel Optic)\n"); + strcat(val_string, " (MPO Parallel Optic)"); + break; + case SFF_8024_CTOR_MPO_2: + printf(" (MPO Parallel Optic - 2x16)\n"); + strcat(val_string, " (MPO Parallel Optic - 2x16)"); + break; + case SFF_8024_CTOR_HSDC_II: + printf(" (HSSDC II)\n"); + strcat(val_string, " (HSSDC II)"); + break; + case SFF_8024_CTOR_COPPER_PT: + printf(" (Copper pigtail)\n"); + strcat(val_string, " (Copper pigtail)"); + break; + case SFF_8024_CTOR_RJ45: + printf(" (RJ45)\n"); + strcat(val_string, " (RJ45)"); + break; + case SFF_8024_CTOR_NO_SEPARABLE: + printf(" (No separable connector)\n"); + strcat(val_string, " (No separable connector)"); + break; + case SFF_8024_CTOR_MXC_2x16: + printf(" (MXC 2x16)\n"); + strcat(val_string, " (MXC 2x16)"); + break; + default: + printf(" (reserved or unknown)\n"); + strcat(val_string, " (reserved or unknown)"); + break; + } + add_item_string(items, "Connector", val_string); +} + +void sff_8024_show_encoding(const uint8_t *id, int encoding_offset, + int sff_type, sff_item *items) +{ + char val_string[TMP_STRING_SIZE]; + + printf("%-41s : 0x%02x", "Encoding", id[encoding_offset]); + sprintf(val_string, "0x%02x", id[encoding_offset]); + + switch (id[encoding_offset]) { + case SFF_8024_ENCODING_UNSPEC: + printf(" (unspecified)\n"); + strcat(val_string, " (unspecified)"); + break; + case SFF_8024_ENCODING_8B10B: + printf(" (8B/10B)\n"); + strcat(val_string, " (8B/10B)"); + break; + case SFF_8024_ENCODING_4B5B: + printf(" (4B/5B)\n"); + strcat(val_string, " (4B/5B)"); + break; + case SFF_8024_ENCODING_NRZ: + printf(" (NRZ)\n"); + strcat(val_string, " (NRZ)"); + break; + case SFF_8024_ENCODING_4h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) { + printf(" (Manchester)\n"); + strcat(val_string, " (Manchester)"); + } else if (sff_type == RTE_ETH_MODULE_SFF_8636) { + printf(" (SONET Scrambled)\n"); + strcat(val_string, " (SONET Scrambled)"); + } + break; + case SFF_8024_ENCODING_5h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) { + printf(" (SONET Scrambled)\n"); + strcat(val_string, " (SONET Scrambled)"); + } else if (sff_type == RTE_ETH_MODULE_SFF_8636) { + printf(" (64B/66B)\n"); + strcat(val_string, " (64B/66B)"); + } + break; + case SFF_8024_ENCODING_6h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) { + printf(" (64B/66B)\n"); + strcat(val_string, " (64B/66B)"); + } else if (sff_type == RTE_ETH_MODULE_SFF_8636) { + printf(" (Manchester)\n"); + strcat(val_string, " (Manchester)"); + } + break; + case SFF_8024_ENCODING_256B: + printf(" ((256B/257B (transcoded FEC-enabled data))\n"); + strcat(val_string, + " ((256B/257B (transcoded FEC-enabled data))"); + break; + case SFF_8024_ENCODING_PAM4: + printf(" (PAM4)\n"); + strcat(val_string, " (PAM4)"); + break; + default: + printf(" (reserved or unknown)\n"); + strcat(val_string, " (reserved or unknown)"); + break; + } + add_item_string(items, "Encoding", val_string); +} + +void sff_show_thresholds(struct sff_diags sd, sff_item *items) +{ + char val_string[TMP_STRING_SIZE]; + + PRINT_BIAS("Laser bias current high alarm threshold", sd.bias_cur[HALRM]); + SPRINT_BIAS(val_string, sd.bias_cur[HALRM]); + add_item_string(items, "Laser bias current high alarm threshold", val_string); + PRINT_BIAS("Laser bias current low alarm threshold", sd.bias_cur[LALRM]); + SPRINT_BIAS(val_string, sd.bias_cur[LALRM]); + add_item_string(items, "Laser bias current low alarm threshold", val_string); + PRINT_BIAS("Laser bias current high warning threshold", sd.bias_cur[HWARN]); + SPRINT_BIAS(val_string, sd.bias_cur[HWARN]); + add_item_string(items, "Laser bias current high warning threshold", val_string); + PRINT_BIAS("Laser bias current low warning threshold", sd.bias_cur[LWARN]); + SPRINT_BIAS(val_string, sd.bias_cur[LWARN]); + add_item_string(items, "Laser bias current low warning threshold", val_string); + + PRINT_xX_PWR("Laser output power high alarm threshold", sd.tx_power[HALRM]); + SPRINT_xX_PWR(val_string, sd.tx_power[HALRM]); + add_item_string(items, "Laser output power high alarm threshold", val_string); + PRINT_xX_PWR("Laser output power low alarm threshold", sd.tx_power[LALRM]); + SPRINT_xX_PWR(val_string, sd.tx_power[LALRM]); + add_item_string(items, "Laser output power low alarm threshold", val_string); + PRINT_xX_PWR("Laser output power high warning threshold", sd.tx_power[HWARN]); + SPRINT_xX_PWR(val_string, sd.tx_power[HWARN]); + add_item_string(items, "Laser output power high warning threshold", val_string); + PRINT_xX_PWR("Laser output power low warning threshold", sd.tx_power[LWARN]); + SPRINT_xX_PWR(val_string, sd.tx_power[LWARN]); + add_item_string(items, "Laser output power low warning threshold", val_string); + + PRINT_TEMP("Module temperature high alarm threshold", sd.sfp_temp[HALRM]); + SPRINT_TEMP(val_string, sd.sfp_temp[HALRM]); + add_item_string(items, "Module temperature high alarm threshold", val_string); + PRINT_TEMP("Module temperature low alarm threshold", sd.sfp_temp[LALRM]); + SPRINT_TEMP(val_string, sd.sfp_temp[LALRM]); + add_item_string(items, "Module temperature low alarm threshold", val_string); + PRINT_TEMP("Module temperature high warning threshold", sd.sfp_temp[HWARN]); + SPRINT_TEMP(val_string, sd.sfp_temp[HWARN]); + add_item_string(items, "Module temperature high warning threshold", val_string); + PRINT_TEMP("Module temperature low warning threshold", sd.sfp_temp[LWARN]); + SPRINT_TEMP(val_string, sd.sfp_temp[LWARN]); + add_item_string(items, "Module temperature low warning threshold", val_string); + + PRINT_VCC("Module voltage high alarm threshold", sd.sfp_voltage[HALRM]); + SPRINT_VCC(val_string, sd.sfp_voltage[HALRM]); + add_item_string(items, "Module voltage high alarm threshold", val_string); + PRINT_VCC("Module voltage low alarm threshold", sd.sfp_voltage[LALRM]); + SPRINT_VCC(val_string, sd.sfp_voltage[LALRM]); + add_item_string(items, "Module voltage low alarm threshold", val_string); + PRINT_VCC("Module voltage high warning threshold", sd.sfp_voltage[HWARN]); + SPRINT_VCC(val_string, sd.sfp_voltage[HWARN]); + add_item_string(items, "Module voltage high warning threshold", val_string); + PRINT_VCC("Module voltage low warning threshold", sd.sfp_voltage[LWARN]); + SPRINT_VCC(val_string, sd.sfp_voltage[LWARN]); + add_item_string(items, "Module voltage low alarm threshold", val_string); + + PRINT_xX_PWR("Laser rx power high alarm threshold", sd.rx_power[HALRM]); + SPRINT_xX_PWR(val_string, sd.rx_power[HALRM]); + add_item_string(items, "Laser rx power high alarm threshold", val_string); + PRINT_xX_PWR("Laser rx power low alarm threshold", sd.rx_power[LALRM]); + SPRINT_xX_PWR(val_string, sd.rx_power[LALRM]); + add_item_string(items, "Laser rx power low alarm threshold", val_string); + PRINT_xX_PWR("Laser rx power high warning threshold", sd.rx_power[HWARN]); + SPRINT_xX_PWR(val_string, sd.rx_power[HWARN]); + add_item_string(items, "Laser rx power high warning threshold", val_string); + PRINT_xX_PWR("Laser rx power low warning threshold", sd.rx_power[LWARN]); + SPRINT_xX_PWR(val_string, sd.rx_power[LWARN]); + add_item_string(items, "Laser rx power low warning threshold", val_string); +} diff --git a/lib/ethdev/sff_common.h b/lib/ethdev/sff_common.h new file mode 100644 index 0000000000..fc3b1288dd --- /dev/null +++ b/lib/ethdev/sff_common.h @@ -0,0 +1,191 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2022 Intel Corporation + * + * Implements SFF-8024 Rev 4.0 of pluggable I/O configuration and some + * common utilities for SFF-8436/8636 and SFF-8472/8079 + * + */ + +#ifndef SFF_COMMON_H__ +#define SFF_COMMON_H__ + +#include <stdio.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "ethdev_sff_telemetry.h" + +#define SFF_8024_ID_OFFSET 0x00 +#define SFF_8024_ID_UNKNOWN 0x00 +#define SFF_8024_ID_GBIC 0x01 +#define SFF_8024_ID_SOLDERED_MODULE 0x02 +#define SFF_8024_ID_SFP 0x03 +#define SFF_8024_ID_300_PIN_XBI 0x04 +#define SFF_8024_ID_XENPAK 0x05 +#define SFF_8024_ID_XFP 0x06 +#define SFF_8024_ID_XFF 0x07 +#define SFF_8024_ID_XFP_E 0x08 +#define SFF_8024_ID_XPAK 0x09 +#define SFF_8024_ID_X2 0x0A +#define SFF_8024_ID_DWDM_SFP 0x0B +#define SFF_8024_ID_QSFP 0x0C +#define SFF_8024_ID_QSFP_PLUS 0x0D +#define SFF_8024_ID_CXP 0x0E +#define SFF_8024_ID_HD4X 0x0F +#define SFF_8024_ID_HD8X 0x10 +#define SFF_8024_ID_QSFP28 0x11 +#define SFF_8024_ID_CXP2 0x12 +#define SFF_8024_ID_CDFP 0x13 +#define SFF_8024_ID_HD4X_FANOUT 0x14 +#define SFF_8024_ID_HD8X_FANOUT 0x15 +#define SFF_8024_ID_CDFP_S3 0x16 +#define SFF_8024_ID_MICRO_QSFP 0x17 +#define SFF_8024_ID_LAST SFF_8024_ID_MICRO_QSFP +#define SFF_8024_ID_UNALLOCATED_LAST 0x7F +#define SFF_8024_ID_VENDOR_START 0x80 +#define SFF_8024_ID_VENDOR_LAST 0xFF + +#define SFF_8024_CTOR_UNKNOWN 0x00 +#define SFF_8024_CTOR_SC 0x01 +#define SFF_8024_CTOR_FC_STYLE_1 0x02 +#define SFF_8024_CTOR_FC_STYLE_2 0x03 +#define SFF_8024_CTOR_BNC_TNC 0x04 +#define SFF_8024_CTOR_FC_COAX 0x05 +#define SFF_8024_CTOR_FIBER_JACK 0x06 +#define SFF_8024_CTOR_LC 0x07 +#define SFF_8024_CTOR_MT_RJ 0x08 +#define SFF_8024_CTOR_MU 0x09 +#define SFF_8024_CTOR_SG 0x0A +#define SFF_8024_CTOR_OPT_PT 0x0B +#define SFF_8024_CTOR_MPO 0x0C +#define SFF_8024_CTOR_MPO_2 0x0D +/* 0E-1Fh --- Reserved */ +#define SFF_8024_CTOR_HSDC_II 0x20 +#define SFF_8024_CTOR_COPPER_PT 0x21 +#define SFF_8024_CTOR_RJ45 0x22 +#define SFF_8024_CTOR_NO_SEPARABLE 0x23 +#define SFF_8024_CTOR_MXC_2x16 0x24 +#define SFF_8024_CTOR_LAST SFF_8024_CTOR_MXC_2x16 +#define SFF_8024_CTOR_UNALLOCATED_LAST 0x7F +#define SFF_8024_CTOR_VENDOR_START 0x80 +#define SFF_8024_CTOR_VENDOR_LAST 0xFF + +/* ENCODING Values */ +#define SFF_8024_ENCODING_UNSPEC 0x00 +#define SFF_8024_ENCODING_8B10B 0x01 +#define SFF_8024_ENCODING_4B5B 0x02 +#define SFF_8024_ENCODING_NRZ 0x03 +/* + * Value: 04h + * SFF-8472 - Manchester + * SFF-8436/8636 - SONET Scrambled + */ +#define SFF_8024_ENCODING_4h 0x04 +/* + * Value: 05h + * SFF-8472 - SONET Scrambled + * SFF-8436/8636 - 64B/66B + */ +#define SFF_8024_ENCODING_5h 0x05 +/* + * Value: 06h + * SFF-8472 - 64B/66B + * SFF-8436/8636 - Manchester + */ +#define SFF_8024_ENCODING_6h 0x06 +#define SFF_8024_ENCODING_256B 0x07 +#define SFF_8024_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 PRINT_xX_PWR(string, var) \ + printf("%-41s : %.4f mW / %.2f dBm\n", (string), \ + (double)((var) / 10000.), \ + convert_mw_to_dbm((double)((var) / 10000.))) +#define SPRINT_xX_PWR(str, var) \ + sprintf(str, "%.4f mW / %.2f dBm", \ + (double)((var) / 10000.), \ + convert_mw_to_dbm((double)((var) / 10000.))) + +#define PRINT_BIAS(string, bias_cur) \ + printf("%-41s : %.3f mA\n", (string), \ + (double)(bias_cur / 500.)) +#define SPRINT_BIAS(str, bias_cur) \ + sprintf(str, "%.3f mA", (double)(bias_cur / 500.)) + +#define PRINT_TEMP(string, temp) \ + printf("%-41s : %.2f degrees C / %.2f degrees F\n", \ + (string), (double)(temp / 256.), \ + (double)(temp / 256. * 1.8 + 32.)) +#define SPRINT_TEMP(str, temp) \ + sprintf(str, "%.2f degrees C / %.2f degrees F", \ + (double)(temp / 256.), \ + (double)(temp / 256. * 1.8 + 32.)) + +#define PRINT_VCC(string, sfp_voltage) \ + printf("%-41s : %.4f V\n", (string), \ + (double)(sfp_voltage / 10000.)) +#define SPRINT_VCC(str, sfp_voltage) \ + sprintf(str, "%.4f V", (double)(sfp_voltage / 10000.)) + +#define PRINT_xX_THRESH_PWR(string, var, index) \ + PRINT_xX_PWR(string, (var)[(index)]) + +/* Channel Monitoring Fields */ +struct sff_channel_diags { + uint16_t bias_cur; /* Measured bias current in 2uA units */ + uint16_t rx_power; /* Measured RX Power */ + uint16_t tx_power; /* Measured TX Power */ +}; + +/* Module Monitoring Fields */ +struct sff_diags { + +#define MAX_CHANNEL_NUM 4 +#define LWARN 0 +#define HWARN 1 +#define LALRM 2 +#define HALRM 3 +#define MCURR 4 + + /* Supports DOM */ + uint8_t supports_dom; + /* Supports alarm/warning thold */ + uint8_t supports_alarms; + /* RX Power: 0 = OMA, 1 = Average power */ + uint8_t rx_power_type; + /* TX Power: 0 = Not supported, 1 = Average power */ + uint8_t tx_power_type; + + uint8_t calibrated_ext; /* Is externally calibrated */ + /* [5] tables are low/high warn, low/high alarm, current */ + /* SFP voltage in 0.1mV units */ + uint16_t sfp_voltage[5]; + /* SFP Temp in 16-bit signed 1/256 Celcius */ + int16_t sfp_temp[5]; + /* Measured bias current in 2uA units */ + uint16_t bias_cur[5]; + /* Measured TX Power */ + uint16_t tx_power[5]; + /* Measured RX Power */ + uint16_t rx_power[5]; + struct sff_channel_diags scd[MAX_CHANNEL_NUM]; +}; + +double convert_mw_to_dbm(double mw); +void sff_show_value_with_unit(const uint8_t *id, unsigned int reg, + const char *name, unsigned int mult, + const char *unit, sff_item *items); +void sff_show_ascii(const uint8_t *id, unsigned int first_reg, + unsigned int last_reg, const char *name, sff_item *items); +void sff_show_thresholds(struct sff_diags sd, sff_item *items); + +void sff_8024_show_oui(const uint8_t *id, int id_offset, sff_item *items); +void sff_8024_show_identifier(const uint8_t *id, int id_offset, sff_item *items); +void sff_8024_show_connector(const uint8_t *id, int ctor_offset, sff_item *items); +void sff_8024_show_encoding(const uint8_t *id, int encoding_offset, + int sff_type, sff_item *items); + +#endif /* SFF_COMMON_H__ */ -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v3 3/5] ethdev: format module EEPROM for SFF-8079 2022-04-20 7:00 ` [PATCH v3 0/5] add telemetry command for show " Robin Zhang 2022-04-20 7:00 ` [PATCH v3 1/5] ethdev: add telemetry command for " Robin Zhang 2022-04-20 7:00 ` [PATCH v3 2/5] ethdev: common utilities for different SFF specs Robin Zhang @ 2022-04-20 7:00 ` Robin Zhang 2022-04-20 7:00 ` [PATCH v3 4/5] ethdev: format module EEPROM for SFF-8472 Robin Zhang ` (2 subsequent siblings) 5 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-04-20 7:00 UTC (permalink / raw) To: dev Cc: qiming.yang, qi.z.zhang, stevex.yang, thomas, andrew.rybchenko, bruce.richardson, david.marchand, Robin Zhang This patch implements format module EEPROM information for SFF-8079 Rev 1.7 Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/sff_8079.c | 672 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 672 insertions(+) create mode 100644 lib/ethdev/sff_8079.c diff --git a/lib/ethdev/sff_8079.c b/lib/ethdev/sff_8079.c new file mode 100644 index 0000000000..535f54817b --- /dev/null +++ b/lib/ethdev/sff_8079.c @@ -0,0 +1,672 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2022 Intel Corporation + * + * Implements SFF-8079 optics diagnostics. + * + */ + +#include <stdio.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "ethdev_sff_telemetry.h" + +static void sff_8079_show_identifier(const uint8_t *id, sff_item *items) +{ + sff_8024_show_identifier(id, 0, items); +} + +static void sff_8079_show_ext_identifier(const uint8_t *id, sff_item *items) +{ + char val_string[TMP_STRING_SIZE]; + + printf("%-41s : 0x%02x", "Extended identifier", id[1]); + sprintf(val_string, "0x%02x", id[1]); + if (id[1] == 0x00) { + printf(" (GBIC not specified / not MOD_DEF compliant)\n"); + strcat(val_string, " (GBIC not specified / not MOD_DEF compliant)"); + } else if (id[1] == 0x04) { + printf(" (GBIC/SFP defined by 2-wire interface ID)\n"); + strcat(val_string, " (GBIC/SFP defined by 2-wire interface ID)"); + } else if (id[1] <= 0x07) { + printf(" (GBIC compliant with MOD_DEF %u)\n", id[1]); + char tmp[TMP_STRING_SIZE]; + sprintf(tmp, " (GBIC compliant with MOD_DEF %u)", id[1]); + strcat(val_string, tmp); + } else { + printf(" (unknown)\n"); + strcat(val_string, " (unknown)"); + } + add_item_string(items, "Extended identifier", val_string); +} + +static void sff_8079_show_connector(const uint8_t *id, sff_item *items) +{ + sff_8024_show_connector(id, 2, items); +} + +static void sff_8079_show_transceiver(const uint8_t *id, sff_item *items) +{ + static const char *pfx = + "Transceiver type :"; + char val_string[TMP_STRING_SIZE]; + + printf("%-41s : 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", + "Transceiver codes", + id[3], id[4], id[5], id[6], + id[7], id[8], id[9], id[10], id[36]); + sprintf(val_string, + "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + id[3], id[4], id[5], id[6], id[7], id[8], id[9], id[10], id[36]); + add_item_string(items, "Transceiver codes", val_string); + + /* 10G Ethernet Compliance Codes */ + if (id[3] & (1 << 7)) { + printf("%s 10G Ethernet: 10G Base-ER [SFF-8472 rev10.4 onwards]\n", pfx); + add_item_string(items, "10G Ethernet transceiver type", + "10G Ethernet: 10G Base-ER [SFF-8472 rev10.4 onwards]"); + } + if (id[3] & (1 << 6)) { + printf("%s 10G Ethernet: 10G Base-LRM\n", pfx); + add_item_string(items, "Transceiver type", + "10G Ethernet: 10G Base-LRM"); + } + if (id[3] & (1 << 5)) { + printf("%s 10G Ethernet: 10G Base-LR\n", pfx); + add_item_string(items, "Transceiver type", + "10G Ethernet: 10G Base-LR"); + } + if (id[3] & (1 << 4)) { + printf("%s 10G Ethernet: 10G Base-SR\n", pfx); + add_item_string(items, "Transceiver type", + "10G Ethernet: 10G Base-SR"); + } + + /* Infiniband Compliance Codes */ + if (id[3] & (1 << 3)) { + printf("%s Infiniband: 1X SX\n", pfx); + add_item_string(items, "Transceiver type", + "Infiniband: 1X SX"); + } + if (id[3] & (1 << 2)) { + printf("%s Infiniband: 1X LX\n", pfx); + add_item_string(items, "Transceiver type", + "Infiniband: 1X LX"); + } + if (id[3] & (1 << 1)) { + printf("%s Infiniband: 1X Copper Active\n", pfx); + add_item_string(items, "Transceiver type", + "Infiniband: 1X Copper Active"); + } + if (id[3] & (1 << 0)) { + printf("%s Infiniband: 1X Copper Passive\n", pfx); + add_item_string(items, "Transceiver type", + "Infiniband: 1X Copper Passive"); + } + + /* ESCON Compliance Codes */ + if (id[4] & (1 << 7)) { + printf("%s ESCON: ESCON MMF, 1310nm LED\n", pfx); + add_item_string(items, "Transceiver type", + "ESCON: ESCON MMF, 1310nm LED"); + } + if (id[4] & (1 << 6)) { + printf("%s ESCON: ESCON SMF, 1310nm Laser\n", pfx); + add_item_string(items, "Transceiver type", + "ESCON: ESCON SMF, 1310nm Laser"); + } + + /* SONET Compliance Codes */ + if (id[4] & (1 << 5)) { + printf("%s SONET: OC-192, short reach\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: OC-192, short reach"); + } + if (id[4] & (1 << 4)) { + printf("%s SONET: SONET reach specifier bit 1\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: SONET reach specifier bit 1"); + } + if (id[4] & (1 << 3)) { + printf("%s SONET: SONET reach specifier bit 2\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: SONET reach specifier bit 2"); + } + if (id[4] & (1 << 2)) { + printf("%s SONET: OC-48, long reach\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: OC-48, long reach"); + } + if (id[4] & (1 << 1)) { + printf("%s SONET: OC-48, intermediate reach\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: OC-48, intermediate reach"); + } + if (id[4] & (1 << 0)) { + printf("%s SONET: OC-48, short reach\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: OC-48, short reach"); + } + if (id[5] & (1 << 6)) { + printf("%s SONET: OC-12, single mode, long reach\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: OC-12, single mode, long reach"); + } + if (id[5] & (1 << 5)) { + printf("%s SONET: OC-12, single mode, inter. reach\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: OC-12, single mode, inter. reach"); + } + if (id[5] & (1 << 4)) { + printf("%s SONET: OC-12, short reach\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: OC-12, short reach"); + } + if (id[5] & (1 << 2)) { + printf("%s SONET: OC-3, single mode, long reach\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: OC-3, single mode, long reach"); + } + if (id[5] & (1 << 1)) { + printf("%s SONET: OC-3, single mode, inter. reach\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: OC-3, single mode, inter. reach"); + } + if (id[5] & (1 << 0)) { + printf("%s SONET: OC-3, short reach\n", pfx); + add_item_string(items, "Transceiver type", + "SONET: OC-3, short reach"); + } + + /* Ethernet Compliance Codes */ + if (id[6] & (1 << 7)) { + printf("%s Ethernet: BASE-PX\n", pfx); + add_item_string(items, "Transceiver type", + "Ethernet: BASE-PX"); + } + if (id[6] & (1 << 6)) { + printf("%s Ethernet: BASE-BX10\n", pfx); + add_item_string(items, "Transceiver type", + "Ethernet: BASE-BX10"); + } + if (id[6] & (1 << 5)) { + printf("%s Ethernet: 100BASE-FX\n", pfx); + add_item_string(items, "Transceiver type", + "Ethernet: 100BASE-FX"); + } + if (id[6] & (1 << 4)) { + printf("%s Ethernet: 100BASE-LX/LX10\n", pfx); + add_item_string(items, "Transceiver type", + "Ethernet: 100BASE-LX/LX10"); + } + if (id[6] & (1 << 3)) { + printf("%s Ethernet: 1000BASE-T\n", pfx); + add_item_string(items, "Transceiver type", + "Ethernet: 1000BASE-T"); + } + if (id[6] & (1 << 2)) { + printf("%s Ethernet: 1000BASE-CX\n", pfx); + add_item_string(items, "Transceiver type", + "Ethernet: 1000BASE-CX"); + } + if (id[6] & (1 << 1)) { + printf("%s Ethernet: 1000BASE-LX\n", pfx); + add_item_string(items, "Transceiver type", + "Ethernet: 1000BASE-LX"); + } + if (id[6] & (1 << 0)) { + printf("%s Ethernet: 1000BASE-SX\n", pfx); + add_item_string(items, "Transceiver type", + "Ethernet: 1000BASE-SX"); + } + + /* Fibre Channel link length */ + if (id[7] & (1 << 7)) { + printf("%s FC: very long distance (V)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: very long distance (V)"); + } + if (id[7] & (1 << 6)) { + printf("%s FC: short distance (S)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: short distance (S)"); + } + if (id[7] & (1 << 5)) { + printf("%s FC: intermediate distance (I)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: intermediate distance (I)"); + } + if (id[7] & (1 << 4)) { + printf("%s FC: long distance (L)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: long distance (L)"); + } + if (id[7] & (1 << 3)) { + printf("%s FC: medium distance (M)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: medium distance (M)"); + } + + /* Fibre Channel transmitter technology */ + if (id[7] & (1 << 2)) { + printf("%s FC: Shortwave laser, linear Rx (SA)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Shortwave laser, linear Rx (SA)"); + } + if (id[7] & (1 << 1)) { + printf("%s FC: Longwave laser (LC)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Longwave laser (LC)"); + } + if (id[7] & (1 << 0)) { + printf("%s FC: Electrical inter-enclosure (EL)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Electrical inter-enclosure (EL)"); + } + if (id[8] & (1 << 7)) { + printf("%s FC: Electrical intra-enclosure (EL)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Electrical intra-enclosure (EL)"); + } + if (id[8] & (1 << 6)) { + printf("%s FC: Shortwave laser w/o OFC (SN)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Shortwave laser w/o OFC (SN)"); + } + if (id[8] & (1 << 5)) { + printf("%s FC: Shortwave laser with OFC (SL)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Shortwave laser with OFC (SL)"); + } + if (id[8] & (1 << 4)) { + printf("%s FC: Longwave laser (LL)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Longwave laser (LL)"); + } + if (id[8] & (1 << 3)) { + printf("%s Active Cable\n", pfx); + add_item_string(items, "Transceiver type", + "Active Cable"); + } + if (id[8] & (1 << 2)) { + printf("%s Passive Cable\n", pfx); + add_item_string(items, "Transceiver type", + "Passive Cable"); + } + if (id[8] & (1 << 1)) { + printf("%s FC: Copper FC-BaseT\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Copper FC-BaseT"); + } + + /* Fibre Channel transmission media */ + if (id[9] & (1 << 7)) { + printf("%s FC: Twin Axial Pair (TW)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Twin Axial Pair (TW)"); + } + if (id[9] & (1 << 6)) { + printf("%s FC: Twisted Pair (TP)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Twisted Pair (TP)"); + } + if (id[9] & (1 << 5)) { + printf("%s FC: Miniature Coax (MI)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Miniature Coax (MI)"); + } + if (id[9] & (1 << 4)) { + printf("%s FC: Video Coax (TV)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Video Coax (TV)"); + } + if (id[9] & (1 << 3)) { + printf("%s FC: Multimode, 62.5um (M6)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Multimode, 62.5um (M6)"); + } + if (id[9] & (1 << 2)) { + printf("%s FC: Multimode, 50um (M5)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Multimode, 50um (M5)"); + } + if (id[9] & (1 << 0)) { + printf("%s FC: Single Mode (SM)\n", pfx); + add_item_string(items, "Transceiver type", + "FC: Single Mode (SM)"); + } + + /* Fibre Channel speed */ + if (id[10] & (1 << 7)) { + printf("%s FC: 1200 MBytes/sec\n", pfx); + add_item_string(items, "Transceiver type", + "FC: 1200 MBytes/sec"); + } + if (id[10] & (1 << 6)) { + printf("%s FC: 800 MBytes/sec\n", pfx); + add_item_string(items, "Transceiver type", + "FC: 800 MBytes/sec"); + } + if (id[10] & (1 << 4)) { + printf("%s FC: 400 MBytes/sec\n", pfx); + add_item_string(items, "Transceiver type", + "FC: 400 MBytes/sec"); + } + if (id[10] & (1 << 2)) { + printf("%s FC: 200 MBytes/sec\n", pfx); + add_item_string(items, "Transceiver type", + "FC: 200 MBytes/sec"); + } + if (id[10] & (1 << 0)) { + printf("%s FC: 100 MBytes/sec\n", pfx); + add_item_string(items, "Transceiver type", + "FC: 100 MBytes/sec"); + } + + /* Extended Specification Compliance Codes from SFF-8024 */ + switch (id[36]) { + case 0x1: + printf("%s Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)\n", + pfx); + add_item_string(items, "Transceiver type", + "Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)"); + break; + case 0x2: + printf("%s Extended: 100G Base-SR4 or 25GBase-SR\n", pfx); + add_item_string(items, "Transceiver type", + "Extended: 100G Base-SR4 or 25GBase-SR"); + break; + case 0x3: + printf("%s Extended: 100G Base-LR4 or 25GBase-LR\n", pfx); + add_item_string(items, "Transceiver type", + "Extended: 100G Base-LR4 or 25GBase-LR"); + break; + case 0x4: + printf("%s Extended: 100G Base-ER4 or 25GBase-ER\n", pfx); + add_item_string(items, "Transceiver type", + "Extended: 100G Base-ER4 or 25GBase-ER"); + break; + case 0x8: + printf("%s Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)\n", + pfx); + add_item_string(items, "Transceiver type", + "Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)"); + break; + case 0xb: + printf("%s Extended: 100G Base-CR4 or 25G Base-CR CA-L\n", pfx); + add_item_string(items, "Transceiver type", + "Extended: 100G Base-CR4 or 25G Base-CR CA-L"); + break; + case 0xc: + printf("%s Extended: 25G Base-CR CA-S\n", pfx); + add_item_string(items, "Transceiver type", + "Extended: 25G Base-CR CA-S"); + break; + case 0xd: + printf("%s Extended: 25G Base-CR CA-N\n", pfx); + add_item_string(items, "Transceiver type", + "Extended: 25G Base-CR CA-N"); + break; + case 0x16: + printf("%s Extended: 10Gbase-T with SFI electrical interface\n", pfx); + add_item_string(items, "Transceiver type", + "Extended: 10Gbase-T with SFI electrical interface"); + break; + case 0x18: + printf("%s Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)\n", + pfx); + add_item_string(items, "Transceiver type", + "Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)"); + break; + case 0x19: + printf("%s Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)\n", + pfx); + add_item_string(items, "Transceiver type", + "Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)"); + break; + case 0x1c: + printf("%s Extended: 10Gbase-T Short Reach\n", pfx); + add_item_string(items, "Transceiver type", + "Extended: 10Gbase-T Short Reach"); + break; + default: + break; + } +} + +static void sff_8079_show_encoding(const uint8_t *id, sff_item *items) +{ + sff_8024_show_encoding(id, 11, RTE_ETH_MODULE_SFF_8472, items); +} + +static void sff_8079_show_rate_identifier(const uint8_t *id, sff_item *items) +{ + char val_string[TMP_STRING_SIZE]; + + printf("%-41s : 0x%02x", "Rate identifier", id[13]); + sprintf(val_string, "0x%02x", id[13]); + + switch (id[13]) { + case 0x00: + printf(" (unspecified)\n"); + strcat(val_string, " (unspecified)"); + break; + case 0x01: + printf(" (4/2/1G Rate_Select & AS0/AS1)\n"); + strcat(val_string, " (4/2/1G Rate_Select & AS0/AS1)"); + break; + case 0x02: + printf(" (8/4/2G Rx Rate_Select only)\n"); + strcat(val_string, " (8/4/2G Rx Rate_Select only)"); + break; + case 0x03: + printf(" (8/4/2G Independent Rx & Tx Rate_Select)\n"); + strcat(val_string, " (8/4/2G Independent Rx & Tx Rate_Select)"); + break; + case 0x04: + printf(" (8/4/2G Tx Rate_Select only)\n"); + strcat(val_string, " (8/4/2G Tx Rate_Select only)"); + break; + default: + printf(" (reserved or unknown)\n"); + strcat(val_string, " (reserved or unknown)"); + break; + } + add_item_string(items, "Rate identifier", val_string); +} + +static void sff_8079_show_oui(const uint8_t *id, sff_item *items) +{ + sff_8024_show_oui(id, 37, items); +} + +static void +sff_8079_show_wavelength_or_copper_compliance(const uint8_t *id, + sff_item *items) +{ + char val_string[TMP_STRING_SIZE]; + + if (id[8] & (1 << 2)) { + printf("%-41s : 0x%02x", "Passive Cu cmplnce.", id[60]); + sprintf(val_string, "0x%02x", id[60]); + switch (id[60]) { + case 0x00: + printf(" (unspecified)"); + strcat(val_string, " (unspecified)"); + break; + case 0x01: + printf(" (SFF-8431 appendix E)"); + strcat(val_string, " (SFF-8431 appendix E)"); + break; + default: + printf(" (unknown)"); + strcat(val_string, " (unknown)"); + break; + } + printf(" [SFF-8472 rev10.4 only]\n"); + strcat(val_string, " [SFF-8472 rev10.4 only]"); + add_item_string(items, "Passive Cu cmplnce.", val_string); + } else if (id[8] & (1 << 3)) { + printf("%-41s : 0x%02x", "Active Cu cmplnce.", id[60]); + sprintf(val_string, "0x%02x", id[60]); + switch (id[60]) { + case 0x00: + printf(" (unspecified)"); + strcat(val_string, " (unspecified)"); + break; + case 0x01: + printf(" (SFF-8431 appendix E)"); + strcat(val_string, " (SFF-8431 appendix E)"); + break; + case 0x04: + printf(" (SFF-8431 limiting)"); + strcat(val_string, " (SFF-8431 limiting)"); + break; + default: + printf(" (unknown)"); + strcat(val_string, " (unknown)"); + break; + } + printf(" [SFF-8472 rev10.4 only]\n"); + strcat(val_string, " [SFF-8472 rev10.4 only]"); + add_item_string(items, "Active Cu cmplnce.", val_string); + } else { + printf("%-41s : %unm\n", "Laser wavelength", + (id[60] << 8) | id[61]); + sprintf(val_string, "%unm", (id[60] << 8) | id[61]); + add_item_string(items, "Laser wavelength", val_string); + } +} + +static void sff_8079_show_options(const uint8_t *id, sff_item *items) +{ + static const char *pfx = + "Option :"; + char val_string[TMP_STRING_SIZE]; + + printf("%-41s : 0x%02x 0x%02x\n", "Option values", id[64], id[65]); + sprintf(val_string, "0x%02x 0x%02x", id[64], id[65]); + add_item_string(items, "Option values", val_string); + + if (id[65] & (1 << 1)) { + printf("%s RX_LOS implemented\n", pfx); + add_item_string(items, "Option", + "RX_LOS implemented"); + } + if (id[65] & (1 << 2)) { + printf("%s RX_LOS implemented, inverted\n", pfx); + add_item_string(items, "Option", + "RX_LOS implemented, inverted"); + } + if (id[65] & (1 << 3)) { + printf("%s TX_FAULT implemented\n", pfx); + add_item_string(items, "Option", + "TX_FAULT implemented"); + } + if (id[65] & (1 << 4)) { + printf("%s TX_DISABLE implemented\n", pfx); + add_item_string(items, "Option", + "TX_DISABLE implemented"); + } + if (id[65] & (1 << 5)) { + printf("%s RATE_SELECT implemented\n", pfx); + add_item_string(items, "Option", + "RATE_SELECT implemented"); + } + if (id[65] & (1 << 6)) { + printf("%s Tunable transmitter technology\n", pfx); + add_item_string(items, "Option", + "Tunable transmitter technology"); + } + if (id[65] & (1 << 7)) { + printf("%s Receiver decision threshold implemented\n", pfx); + add_item_string(items, "Option", + "Receiver decision threshold implemented"); + } + if (id[64] & (1 << 0)) { + printf("%s Linear receiver output implemented\n", pfx); + add_item_string(items, "Option", + "Linear receiver output implemented"); + } + if (id[64] & (1 << 1)) { + printf("%s Power level 2 requirement\n", pfx); + add_item_string(items, "Option", + "Power level 2 requirement"); + } + if (id[64] & (1 << 2)) { + printf("%s Cooled transceiver implemented\n", pfx); + add_item_string(items, "Option", + "Cooled transceiver implemented"); + } + if (id[64] & (1 << 3)) { + printf("%s Retimer or CDR implemented\n", pfx); + add_item_string(items, "Option", + "Retimer or CDR implemented"); + } + if (id[64] & (1 << 4)) { + printf("%s Paging implemented\n", pfx); + add_item_string(items, "Option", + "Paging implemented"); + } + if (id[64] & (1 << 5)) { + printf("%s Power level 3 requirement\n", pfx); + add_item_string(items, "Option", + "Power level 3 requirement"); + } +} + +void sff_8079_show_all(const uint8_t *id, sff_item *items) +{ + sff_8079_show_identifier(id, items); + if (((id[0] == 0x02) || (id[0] == 0x03)) && (id[1] == 0x04)) { + unsigned int br_nom, br_min, br_max; + char val_string[TMP_STRING_SIZE]; + + if (id[12] == 0) { + br_nom = br_min = br_max = 0; + } else if (id[12] == 255) { + br_nom = id[66] * 250; + br_max = id[67]; + br_min = id[67]; + } else { + br_nom = id[12] * 100; + br_max = id[66]; + br_min = id[67]; + } + sff_8079_show_ext_identifier(id, items); + sff_8079_show_connector(id, items); + sff_8079_show_transceiver(id, items); + sff_8079_show_encoding(id, items); + + printf("%-41s : %u%s\n", "BR, Nominal", br_nom, "MBd"); + sprintf(val_string, "%uMBd", br_nom); + add_item_string(items, "BR, Nominal", val_string); + + sff_8079_show_rate_identifier(id, items); + sff_show_value_with_unit(id, 14, + "Length (SMF,km)", 1, "km", items); + sff_show_value_with_unit(id, 15, "Length (SMF)", 100, "m", items); + sff_show_value_with_unit(id, 16, "Length (50um)", 10, "m", items); + sff_show_value_with_unit(id, 17, + "Length (62.5um)", 10, "m", items); + sff_show_value_with_unit(id, 18, "Length (Copper)", 1, "m", items); + sff_show_value_with_unit(id, 19, "Length (OM3)", 10, "m", items); + sff_8079_show_wavelength_or_copper_compliance(id, items); + sff_show_ascii(id, 20, 35, "Vendor name", items); + sff_8079_show_oui(id, items); + sff_show_ascii(id, 40, 55, "Vendor PN", items); + sff_show_ascii(id, 56, 59, "Vendor rev", items); + sff_8079_show_options(id, items); + + printf("%-41s : %u%s\n", "BR margin, max", br_max, "%"); + sprintf(val_string, "%u%%", br_max); + add_item_string(items, "BR margin, max", val_string); + printf("%-41s : %u%s\n", "BR margin, min", br_min, "%"); + sprintf(val_string, "%u%%", br_min); + add_item_string(items, "BR margin, min", val_string); + + sff_show_ascii(id, 68, 83, "Vendor SN", items); + sff_show_ascii(id, 84, 91, "Date code", items); + } +} -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v3 4/5] ethdev: format module EEPROM for SFF-8472 2022-04-20 7:00 ` [PATCH v3 0/5] add telemetry command for show " Robin Zhang ` (2 preceding siblings ...) 2022-04-20 7:00 ` [PATCH v3 3/5] ethdev: format module EEPROM for SFF-8079 Robin Zhang @ 2022-04-20 7:00 ` Robin Zhang 2022-04-20 7:00 ` [PATCH v3 5/5] ethdev: format module EEPROM for SFF-8636 Robin Zhang 2022-04-20 8:49 ` [PATCH v3 0/5] add telemetry command for show module EEPROM Morten Brørup 5 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-04-20 7:00 UTC (permalink / raw) To: dev Cc: qiming.yang, qi.z.zhang, stevex.yang, thomas, andrew.rybchenko, bruce.richardson, david.marchand, Robin Zhang This patch implements format module EEPROM information for SFF-8472 Rev 12.0 Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/sff_8472.c | 301 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 301 insertions(+) create mode 100644 lib/ethdev/sff_8472.c diff --git a/lib/ethdev/sff_8472.c b/lib/ethdev/sff_8472.c new file mode 100644 index 0000000000..5ed18bb402 --- /dev/null +++ b/lib/ethdev/sff_8472.c @@ -0,0 +1,301 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2022 Intel Corporation + * + * Implements SFF-8472 optics diagnostics. + * + */ + +#include <stdio.h> +#include <math.h> +#include <arpa/inet.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "ethdev_sff_telemetry.h" + +/* Offsets in decimal, for direct comparison with the SFF specs */ + +/* A0-based EEPROM offsets for DOM support checks */ +#define SFF_A0_DOM 92 +#define SFF_A0_OPTIONS 93 +#define SFF_A0_COMP 94 + +/* EEPROM bit values for various registers */ +#define SFF_A0_DOM_EXTCAL (1 << 4) +#define SFF_A0_DOM_INTCAL (1 << 5) +#define SFF_A0_DOM_IMPL (1 << 6) +#define SFF_A0_DOM_PWRT (1 << 3) + +#define SFF_A0_OPTIONS_AW (1 << 7) + +/* + * This is the offset at which the A2 page is in the EEPROM + * blob returned by the kernel. + */ +#define SFF_A2_BASE 0x100 + +/* A2-based offsets for DOM */ +#define SFF_A2_TEMP 96 +#define SFF_A2_TEMP_HALRM 0 +#define SFF_A2_TEMP_LALRM 2 +#define SFF_A2_TEMP_HWARN 4 +#define SFF_A2_TEMP_LWARN 6 + +#define SFF_A2_VCC 98 +#define SFF_A2_VCC_HALRM 8 +#define SFF_A2_VCC_LALRM 10 +#define SFF_A2_VCC_HWARN 12 +#define SFF_A2_VCC_LWARN 14 + +#define SFF_A2_BIAS 100 +#define SFF_A2_BIAS_HALRM 16 +#define SFF_A2_BIAS_LALRM 18 +#define SFF_A2_BIAS_HWARN 20 +#define SFF_A2_BIAS_LWARN 22 + +#define SFF_A2_TX_PWR 102 +#define SFF_A2_TX_PWR_HALRM 24 +#define SFF_A2_TX_PWR_LALRM 26 +#define SFF_A2_TX_PWR_HWARN 28 +#define SFF_A2_TX_PWR_LWARN 30 + +#define SFF_A2_RX_PWR 104 +#define SFF_A2_RX_PWR_HALRM 32 +#define SFF_A2_RX_PWR_LALRM 34 +#define SFF_A2_RX_PWR_HWARN 36 +#define SFF_A2_RX_PWR_LWARN 38 + +#define SFF_A2_ALRM_FLG 112 +#define SFF_A2_WARN_FLG 116 + +/* 32-bit little-endian calibration constants */ +#define SFF_A2_CAL_RXPWR4 56 +#define SFF_A2_CAL_RXPWR3 60 +#define SFF_A2_CAL_RXPWR2 64 +#define SFF_A2_CAL_RXPWR1 68 +#define SFF_A2_CAL_RXPWR0 72 + +/* 16-bit little endian calibration constants */ +#define SFF_A2_CAL_TXI_SLP 76 +#define SFF_A2_CAL_TXI_OFF 78 +#define SFF_A2_CAL_TXPWR_SLP 80 +#define SFF_A2_CAL_TXPWR_OFF 82 +#define SFF_A2_CAL_T_SLP 84 +#define SFF_A2_CAL_T_OFF 86 +#define SFF_A2_CAL_V_SLP 88 +#define SFF_A2_CAL_V_OFF 90 + +static struct sff_8472_aw_flags { + const char *str; /* Human-readable string, null at the end */ + int offset; /* A2-relative address offset */ + uint8_t value; /* Alarm is on if (offset & value) != 0. */ +} sff_8472_aw_flags[] = { + { "Laser bias current high alarm", SFF_A2_ALRM_FLG, (1 << 3) }, + { "Laser bias current low alarm", SFF_A2_ALRM_FLG, (1 << 2) }, + { "Laser bias current high warning", SFF_A2_WARN_FLG, (1 << 3) }, + { "Laser bias current low warning", SFF_A2_WARN_FLG, (1 << 2) }, + + { "Laser output power high alarm", SFF_A2_ALRM_FLG, (1 << 1) }, + { "Laser output power low alarm", SFF_A2_ALRM_FLG, (1 << 0) }, + { "Laser output power high warning", SFF_A2_WARN_FLG, (1 << 1) }, + { "Laser output power low warning", SFF_A2_WARN_FLG, (1 << 0) }, + + { "Module temperature high alarm", SFF_A2_ALRM_FLG, (1 << 7) }, + { "Module temperature low alarm", SFF_A2_ALRM_FLG, (1 << 6) }, + { "Module temperature high warning", SFF_A2_WARN_FLG, (1 << 7) }, + { "Module temperature low warning", SFF_A2_WARN_FLG, (1 << 6) }, + + { "Module voltage high alarm", SFF_A2_ALRM_FLG, (1 << 5) }, + { "Module voltage low alarm", SFF_A2_ALRM_FLG, (1 << 4) }, + { "Module voltage high warning", SFF_A2_WARN_FLG, (1 << 5) }, + { "Module voltage low warning", SFF_A2_WARN_FLG, (1 << 4) }, + + { "Laser rx power high alarm", SFF_A2_ALRM_FLG + 1, (1 << 7) }, + { "Laser rx power low alarm", SFF_A2_ALRM_FLG + 1, (1 << 6) }, + { "Laser rx power high warning", SFF_A2_WARN_FLG + 1, (1 << 7) }, + { "Laser rx power low warning", SFF_A2_WARN_FLG + 1, (1 << 6) }, + + { NULL, 0, 0 }, +}; + +/* Most common case: 16-bit unsigned integer in a certain unit */ +#define A2_OFFSET_TO_U16(offset) \ + (id[SFF_A2_BASE + (offset)] << 8 | id[SFF_A2_BASE + (offset) + 1]) + +/* Calibration slope is a number between 0.0 included and 256.0 excluded. */ +#define A2_OFFSET_TO_SLP(offset) \ + (id[SFF_A2_BASE + (offset)] + id[SFF_A2_BASE + (offset) + 1] / 256.) + +/* Calibration offset is an integer from -32768 to 32767 */ +#define A2_OFFSET_TO_OFF(offset) \ + ((int16_t)A2_OFFSET_TO_U16(offset)) + +/* RXPWR(x) are IEEE-754 floating point numbers in big-endian format */ +#define A2_OFFSET_TO_RXPWRx(offset) \ + (befloattoh((const uint32_t *)(id + SFF_A2_BASE + (offset)))) + +/* + * 2-byte internal temperature conversions: + * First byte is a signed 8-bit integer, which is the temp decimal part + * Second byte are 1/256th of degree, which are added to the dec part. + */ +#define A2_OFFSET_TO_TEMP(offset) ((int16_t)A2_OFFSET_TO_U16(offset)) + +static void sff_8472_dom_parse(const uint8_t *id, struct sff_diags *sd) +{ + sd->bias_cur[MCURR] = A2_OFFSET_TO_U16(SFF_A2_BIAS); + sd->bias_cur[HALRM] = A2_OFFSET_TO_U16(SFF_A2_BIAS_HALRM); + sd->bias_cur[LALRM] = A2_OFFSET_TO_U16(SFF_A2_BIAS_LALRM); + sd->bias_cur[HWARN] = A2_OFFSET_TO_U16(SFF_A2_BIAS_HWARN); + sd->bias_cur[LWARN] = A2_OFFSET_TO_U16(SFF_A2_BIAS_LWARN); + + sd->sfp_voltage[MCURR] = A2_OFFSET_TO_U16(SFF_A2_VCC); + sd->sfp_voltage[HALRM] = A2_OFFSET_TO_U16(SFF_A2_VCC_HALRM); + sd->sfp_voltage[LALRM] = A2_OFFSET_TO_U16(SFF_A2_VCC_LALRM); + sd->sfp_voltage[HWARN] = A2_OFFSET_TO_U16(SFF_A2_VCC_HWARN); + sd->sfp_voltage[LWARN] = A2_OFFSET_TO_U16(SFF_A2_VCC_LWARN); + + sd->tx_power[MCURR] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR); + sd->tx_power[HALRM] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_HALRM); + sd->tx_power[LALRM] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_LALRM); + sd->tx_power[HWARN] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_HWARN); + sd->tx_power[LWARN] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_LWARN); + + sd->rx_power[MCURR] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR); + sd->rx_power[HALRM] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_HALRM); + sd->rx_power[LALRM] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_LALRM); + sd->rx_power[HWARN] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_HWARN); + sd->rx_power[LWARN] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_LWARN); + + sd->sfp_temp[MCURR] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP); + sd->sfp_temp[HALRM] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_HALRM); + sd->sfp_temp[LALRM] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_LALRM); + sd->sfp_temp[HWARN] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_HWARN); + sd->sfp_temp[LWARN] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_LWARN); +} + +/* Converts to a float from a big-endian 4-byte source buffer. */ +static float befloattoh(const uint32_t *source) +{ + union { + uint32_t src; + float dst; + } converter; + + converter.src = ntohl(*source); + return converter.dst; +} + +static void sff_8472_calibration(const uint8_t *id, struct sff_diags *sd) +{ + unsigned long i; + uint16_t rx_reading; + + /* Calibration should occur for all values (threshold and current) */ + for (i = 0; i < ARRAY_SIZE(sd->bias_cur); ++i) { + /* + * Apply calibration formula 1 (Temp., Voltage, Bias, Tx Power) + */ + sd->bias_cur[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_TXI_SLP); + sd->tx_power[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_TXPWR_SLP); + sd->sfp_voltage[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_V_SLP); + sd->sfp_temp[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_T_SLP); + + sd->bias_cur[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_TXI_OFF); + sd->tx_power[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_TXPWR_OFF); + sd->sfp_voltage[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_V_OFF); + sd->sfp_temp[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_T_OFF); + + /* + * Apply calibration formula 2 (Rx Power only) + */ + rx_reading = sd->rx_power[i]; + sd->rx_power[i] = A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR0); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR1); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR2); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR3); + } +} + +static void sff_8472_parse_eeprom(const uint8_t *id, struct sff_diags *sd) +{ + sd->supports_dom = id[SFF_A0_DOM] & SFF_A0_DOM_IMPL; + sd->supports_alarms = id[SFF_A0_OPTIONS] & SFF_A0_OPTIONS_AW; + sd->calibrated_ext = id[SFF_A0_DOM] & SFF_A0_DOM_EXTCAL; + sd->rx_power_type = id[SFF_A0_DOM] & SFF_A0_DOM_PWRT; + + sff_8472_dom_parse(id, sd); + + /* + * If the SFP is externally calibrated, we need to read calibration data + * and compensate the already stored readings. + */ + if (sd->calibrated_ext) + sff_8472_calibration(id, sd); +} + +void sff_8472_show_all(const uint8_t *id, sff_item *items) +{ + struct sff_diags sd = {0}; + const char *rx_power_string = NULL; + char val_string[TMP_STRING_SIZE]; + int i; + + sff_8472_parse_eeprom(id, &sd); + + if (!sd.supports_dom) { + printf("%-41s : No\n", "Optical diagnostics support"); + add_item_string(items, "Optical diagnostics support", "No"); + return; + } + printf("%-41s : Yes\n", "Optical diagnostics support"); + add_item_string(items, "Optical diagnostics support", "Yes"); + + PRINT_BIAS("Laser bias current", sd.bias_cur[MCURR]); + SPRINT_BIAS(val_string, sd.bias_cur[MCURR]); + add_item_string(items, "Laser bias current", val_string); + + PRINT_xX_PWR("Laser output power", sd.tx_power[MCURR]); + SPRINT_xX_PWR(val_string, sd.tx_power[MCURR]); + add_item_string(items, "Laser output power", val_string); + + if (!sd.rx_power_type) + rx_power_string = "Receiver signal OMA"; + else + rx_power_string = "Receiver signal average optical power"; + + PRINT_xX_PWR(rx_power_string, sd.rx_power[MCURR]); + SPRINT_xX_PWR(val_string, sd.rx_power[MCURR]); + add_item_string(items, rx_power_string, val_string); + + PRINT_TEMP("Module temperature", sd.sfp_temp[MCURR]); + SPRINT_TEMP(val_string, sd.sfp_temp[MCURR]); + add_item_string(items, "Module temperature", val_string); + + PRINT_VCC("Module voltage", sd.sfp_voltage[MCURR]); + SPRINT_VCC(val_string, sd.sfp_voltage[MCURR]); + add_item_string(items, "Module voltage", val_string); + + printf("%-41s : %s\n", "Alarm/warning flags implemented", + (sd.supports_alarms ? "Yes" : "No")); + add_item_string(items, "Alarm/warning flags implemented", + (sd.supports_alarms ? "Yes" : "No")); + + if (sd.supports_alarms) { + + for (i = 0; sff_8472_aw_flags[i].str; ++i) { + printf("%-41s : %s\n", sff_8472_aw_flags[i].str, + id[SFF_A2_BASE + sff_8472_aw_flags[i].offset] + & sff_8472_aw_flags[i].value ? "On" : "Off"); + add_item_string(items, sff_8472_aw_flags[i].str, + id[SFF_A2_BASE + sff_8472_aw_flags[i].offset] + & sff_8472_aw_flags[i].value ? "On" : "Off"); + } + sff_show_thresholds(sd, items); + } +} + -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v3 5/5] ethdev: format module EEPROM for SFF-8636 2022-04-20 7:00 ` [PATCH v3 0/5] add telemetry command for show " Robin Zhang ` (3 preceding siblings ...) 2022-04-20 7:00 ` [PATCH v3 4/5] ethdev: format module EEPROM for SFF-8472 Robin Zhang @ 2022-04-20 7:00 ` Robin Zhang 2022-04-20 8:49 ` [PATCH v3 0/5] add telemetry command for show module EEPROM Morten Brørup 5 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-04-20 7:00 UTC (permalink / raw) To: dev Cc: qiming.yang, qi.z.zhang, stevex.yang, thomas, andrew.rybchenko, bruce.richardson, david.marchand, Robin Zhang This patch implements format module EEPROM information for SFF-8636 Rev 2.7 Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/sff_8636.c | 1004 +++++++++++++++++++++++++++++++++++++++++ lib/ethdev/sff_8636.h | 592 ++++++++++++++++++++++++ 2 files changed, 1596 insertions(+) create mode 100644 lib/ethdev/sff_8636.c create mode 100644 lib/ethdev/sff_8636.h diff --git a/lib/ethdev/sff_8636.c b/lib/ethdev/sff_8636.c new file mode 100644 index 0000000000..9bc9e1fcee --- /dev/null +++ b/lib/ethdev/sff_8636.c @@ -0,0 +1,1004 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2022 Intel Corporation + * + * Implements SFF-8636 based QSFP+/QSFP28 Diagnostics Memory map. + * + */ + +#include <stdio.h> +#include <math.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "sff_8636.h" +#include "ethdev_sff_telemetry.h" + +#define MAX_DESC_SIZE 42 + +static struct sff_8636_aw_flags { + const char *str; /* Human-readable string, null at the end */ + int offset; /* A2-relative address offset */ + uint8_t value; /* Alarm is on if (offset & value) != 0. */ +} sff_8636_aw_flags[] = { + { "Laser bias current high alarm (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_HALARM) }, + { "Laser bias current low alarm (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_LALARM) }, + { "Laser bias current high warning (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_HWARN) }, + { "Laser bias current low warning (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_LWARN) }, + + { "Laser bias current high alarm (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_HALARM) }, + { "Laser bias current low alarm (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_LALARM) }, + { "Laser bias current high warning (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_HWARN) }, + { "Laser bias current low warning (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_LWARN) }, + + { "Laser bias current high alarm (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_HALARM) }, + { "Laser bias current low alarm (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_LALARM) }, + { "Laser bias current high warning (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_HWARN) }, + { "Laser bias current low warning (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_LWARN) }, + + { "Laser bias current high alarm (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_HALARM) }, + { "Laser bias current low alarm (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_LALARM) }, + { "Laser bias current high warning (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_HWARN) }, + { "Laser bias current low warning (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_LWARN) }, + + { "Module temperature high alarm", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_HALARM_STATUS) }, + { "Module temperature low alarm", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_LALARM_STATUS) }, + { "Module temperature high warning", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_HWARN_STATUS) }, + { "Module temperature low warning", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_LWARN_STATUS) }, + + { "Module voltage high alarm", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_HALARM_STATUS) }, + { "Module voltage low alarm", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_LALARM_STATUS) }, + { "Module voltage high warning", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_HWARN_STATUS) }, + { "Module voltage low warning", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_LWARN_STATUS) }, + + { "Laser tx power high alarm (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_HALARM) }, + { "Laser tx power low alarm (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_LALARM) }, + { "Laser tx power high warning (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_HWARN) }, + { "Laser tx power low warning (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_LWARN) }, + + { "Laser tx power high alarm (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_HALARM) }, + { "Laser tx power low alarm (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_LALARM) }, + { "Laser tx power high warning (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_HWARN) }, + { "Laser tx power low warning (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_LWARN) }, + + { "Laser tx power high alarm (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_HALARM) }, + { "Laser tx power low alarm (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_LALARM) }, + { "Laser tx power high warning (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_HWARN) }, + { "Laser tx power low warning (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_LWARN) }, + + { "Laser tx power high alarm (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_HALARM) }, + { "Laser tx power low alarm (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_LALARM) }, + { "Laser tx power high warning (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_HWARN) }, + { "Laser tx power low warning (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_LWARN) }, + + { "Laser rx power high alarm (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_HALARM) }, + { "Laser rx power low alarm (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_LALARM) }, + { "Laser rx power high warning (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_HWARN) }, + { "Laser rx power low warning (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_LWARN) }, + + { "Laser rx power high alarm (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_HALARM) }, + { "Laser rx power low alarm (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_LALARM) }, + { "Laser rx power high warning (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_HWARN) }, + { "Laser rx power low warning (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_LWARN) }, + + { "Laser rx power high alarm (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_HALARM) }, + { "Laser rx power low alarm (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_LALARM) }, + { "Laser rx power high warning (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_HWARN) }, + { "Laser rx power low warning (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_LWARN) }, + + { "Laser rx power high alarm (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_HALARM) }, + { "Laser rx power low alarm (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_LALARM) }, + { "Laser rx power high warning (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_HWARN) }, + { "Laser rx power low warning (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_LWARN) }, + + { NULL, 0, 0 }, +}; + +static void sff_8636_show_identifier(const uint8_t *id, sff_item *items) +{ + sff_8024_show_identifier(id, SFF_8636_ID_OFFSET, items); +} + +static void sff_8636_show_ext_identifier(const uint8_t *id, sff_item *items) +{ + char val_string[TMP_STRING_SIZE]; + printf("%-41s : 0x%02x\n", "Extended identifier", + id[SFF_8636_EXT_ID_OFFSET]); + sprintf(val_string, "0x%02x", id[SFF_8636_EXT_ID_OFFSET]); + add_item_string(items, "Extended identifier", val_string); + + static const char *pfx = + "Extended identifier description :"; + + switch (id[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_PWR_CLASS_MASK) { + case SFF_8636_EXT_ID_PWR_CLASS_1: + printf("%s 1.5W max. Power consumption\n", pfx); + add_item_string(items, "Extended identifier description", + "1.5W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_2: + printf("%s 2.0W max. Power consumption\n", pfx); + add_item_string(items, "Extended identifier description", + "2.0W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_3: + printf("%s 2.5W max. Power consumption\n", pfx); + add_item_string(items, "Extended identifier description", + "2.5W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_4: + printf("%s 3.5W max. Power consumption\n", pfx); + add_item_string(items, "Extended identifier description", + "3.5W max. Power consumption"); + break; + } + + if (id[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_CDR_TX_MASK) { + printf("%s CDR present in TX,", pfx); + add_item_string(items, "Extended identifier description", + "CDR present in TX"); + } else { + printf("%s No CDR in TX,", pfx); + add_item_string(items, "Extended identifier description", + "No CDR in TX"); + } + + if (id[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_CDR_RX_MASK) { + printf(" CDR present in RX\n"); + add_item_string(items, "Extended identifier description", + "CDR present in RX"); + } else { + printf(" No CDR in RX\n"); + add_item_string(items, "Extended identifier description", + "No CDR in RX"); + } + + switch (id[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_EPWR_CLASS_MASK) { + case SFF_8636_EXT_ID_PWR_CLASS_LEGACY: + printf("%s", pfx); + sprintf(val_string, "%s", ""); + break; + case SFF_8636_EXT_ID_PWR_CLASS_5: + printf("%s 4.0W max. Power consumption,", pfx); + sprintf(val_string, "%s", "4.0W max. Power consumption, "); + break; + case SFF_8636_EXT_ID_PWR_CLASS_6: + printf("%s 4.5W max. Power consumption, ", pfx); + sprintf(val_string, "%s", "4.5W max. Power consumption, "); + break; + case SFF_8636_EXT_ID_PWR_CLASS_7: + printf("%s 5.0W max. Power consumption, ", pfx); + sprintf(val_string, "%s", "5.0W max. Power consumption, "); + break; + } + if (id[SFF_8636_PWR_MODE_OFFSET] & SFF_8636_HIGH_PWR_ENABLE) { + printf(" High Power Class (> 3.5 W) enabled\n"); + strcat(val_string, "High Power Class (> 3.5 W) enabled"); + } else { + printf(" High Power Class (> 3.5 W) not enabled\n"); + strcat(val_string, "High Power Class (> 3.5 W) not enabled"); + } + add_item_string(items, "Extended identifier description", val_string); +} + +static void sff_8636_show_connector(const uint8_t *id, sff_item *items) +{ + sff_8024_show_connector(id, SFF_8636_CTOR_OFFSET, items); +} + +static void sff_8636_show_transceiver(const uint8_t *id, sff_item *items) +{ + static const char *pfx = + "Transceiver type :"; + static const char *name_string = "Transceiver type"; + char val_string[TMP_STRING_SIZE]; + + printf("%-41s : 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", + "Transceiver codes", + id[SFF_8636_ETHERNET_COMP_OFFSET], + id[SFF_8636_SONET_COMP_OFFSET], + id[SFF_8636_SAS_COMP_OFFSET], + id[SFF_8636_GIGE_COMP_OFFSET], + id[SFF_8636_FC_LEN_OFFSET], + id[SFF_8636_FC_TECH_OFFSET], + id[SFF_8636_FC_TRANS_MEDIA_OFFSET], + id[SFF_8636_FC_SPEED_OFFSET]); + sprintf(val_string, "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + id[SFF_8636_ETHERNET_COMP_OFFSET], + id[SFF_8636_SONET_COMP_OFFSET], + id[SFF_8636_SAS_COMP_OFFSET], + id[SFF_8636_GIGE_COMP_OFFSET], + id[SFF_8636_FC_LEN_OFFSET], + id[SFF_8636_FC_TECH_OFFSET], + id[SFF_8636_FC_TRANS_MEDIA_OFFSET], + id[SFF_8636_FC_SPEED_OFFSET]); + add_item_string(items, "Transceiver codes", val_string); + + /* 10G/40G Ethernet Compliance Codes */ + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_LRM) { + printf("%s 10G Ethernet: 10G Base-LRM\n", pfx); + add_item_string(items, name_string, + "10G Ethernet: 10G Base-LRM"); + } + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_LR) { + printf("%s 10G Ethernet: 10G Base-LR\n", pfx); + add_item_string(items, name_string, + "10G Ethernet: 10G Base-LR"); + } + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_SR) { + printf("%s 10G Ethernet: 10G Base-SR\n", pfx); + add_item_string(items, name_string, + "10G Ethernet: 10G Base-SR"); + } + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_CR4) { + printf("%s 40G Ethernet: 40G Base-CR4\n", pfx); + add_item_string(items, name_string, + "40G Ethernet: 40G Base-CR4"); + } + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_SR4) { + printf("%s 40G Ethernet: 40G Base-SR4\n", pfx); + add_item_string(items, name_string, + "40G Ethernet: 40G Base-SR4"); + } + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_LR4) { + printf("%s 40G Ethernet: 40G Base-LR4\n", pfx); + add_item_string(items, name_string, + "40G Ethernet: 40G Base-LR4"); + } + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_ACTIVE) { + printf("%s 40G Ethernet: 40G Active Cable (XLPPI)\n", pfx); + add_item_string(items, name_string, + "40G Ethernet: 40G Active Cable (XLPPI)"); + } + /* Extended Specification Compliance Codes from SFF-8024 */ + if (id[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_RSRVD) { + switch (id[SFF_8636_OPTION_1_OFFSET]) { + case SFF_8636_ETHERNET_UNSPECIFIED: + printf("%s (reserved or unknown)\n", pfx); + add_item_string(items, name_string, + "(reserved or unknown)"); + break; + case SFF_8636_ETHERNET_100G_AOC: + printf("%s 100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)\n", + pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)"); + break; + case SFF_8636_ETHERNET_100G_SR4: + printf("%s 100G Ethernet: 100G Base-SR4 or 25GBase-SR\n", + pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G Base-SR4 or 25GBase-SR"); + break; + case SFF_8636_ETHERNET_100G_LR4: + printf("%s 100G Ethernet: 100G Base-LR4\n", pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G Base-LR4"); + break; + case SFF_8636_ETHERNET_100G_ER4: + printf("%s 100G Ethernet: 100G Base-ER4\n", pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G Base-ER4"); + break; + case SFF_8636_ETHERNET_100G_SR10: + printf("%s 100G Ethernet: 100G Base-SR10\n", pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G Base-SR10"); + break; + case SFF_8636_ETHERNET_100G_CWDM4_FEC: + printf("%s 100G Ethernet: 100G CWDM4 MSA with FEC\n", pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G CWDM4 MSA with FEC"); + break; + case SFF_8636_ETHERNET_100G_PSM4: + printf("%s 100G Ethernet: 100G PSM4 Parallel SMF\n", pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G PSM4 Parallel SMF"); + break; + case SFF_8636_ETHERNET_100G_ACC: + printf("%s 100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)\n", + pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)"); + break; + case SFF_8636_ETHERNET_100G_CWDM4_NO_FEC: + printf("%s 100G Ethernet: 100G CWDM4 MSA without FEC\n", pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G CWDM4 MSA without FEC"); + break; + case SFF_8636_ETHERNET_100G_RSVD1: + printf("%s (reserved or unknown)\n", pfx); + add_item_string(items, name_string, + "(reserved or unknown)"); + break; + case SFF_8636_ETHERNET_100G_CR4: + printf("%s 100G Ethernet: 100G Base-CR4 or 25G Base-CR CA-L\n", + pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G Base-CR4 or 25G Base-CR CA-L"); + break; + case SFF_8636_ETHERNET_25G_CR_CA_S: + printf("%s 25G Ethernet: 25G Base-CR CA-S\n", pfx); + add_item_string(items, name_string, + "25G Ethernet: 25G Base-CR CA-S"); + break; + case SFF_8636_ETHERNET_25G_CR_CA_N: + printf("%s 25G Ethernet: 25G Base-CR CA-N\n", pfx); + add_item_string(items, name_string, + "25G Ethernet: 25G Base-CR CA-N"); + break; + case SFF_8636_ETHERNET_40G_ER4: + printf("%s 40G Ethernet: 40G Base-ER4\n", pfx); + add_item_string(items, name_string, + "40G Ethernet: 40G Base-ER4"); + break; + case SFF_8636_ETHERNET_4X10_SR: + printf("%s 4x10G Ethernet: 10G Base-SR\n", pfx); + add_item_string(items, name_string, + "4x10G Ethernet: 10G Base-SR"); + break; + case SFF_8636_ETHERNET_40G_PSM4: + printf("%s 40G Ethernet: 40G PSM4 Parallel SMF\n", pfx); + add_item_string(items, name_string, + "40G Ethernet: 40G PSM4 Parallel SMF"); + break; + case SFF_8636_ETHERNET_G959_P1I1_2D1: + printf("%s Ethernet: G959.1 profile P1I1-2D1 (10709 MBd, 2km, 1310nm SM)\n", + pfx); + add_item_string(items, name_string, + "Ethernet: G959.1 profile P1I1-2D1 (10709 MBd, 2km, 1310nm SM)"); + break; + case SFF_8636_ETHERNET_G959_P1S1_2D2: + printf("%s Ethernet: G959.1 profile P1S1-2D2 (10709 MBd, 40km, 1550nm SM)\n", + pfx); + add_item_string(items, name_string, + "Ethernet: G959.1 profile P1S1-2D2 (10709 MBd, 40km, 1550nm SM)"); + break; + case SFF_8636_ETHERNET_G959_P1L1_2D2: + printf("%s Ethernet: G959.1 profile P1L1-2D2 (10709 MBd, 80km, 1550nm SM)\n", + pfx); + add_item_string(items, name_string, + "Ethernet: G959.1 profile P1L1-2D2 (10709 MBd, 80km, 1550nm SM)"); + break; + case SFF_8636_ETHERNET_10GT_SFI: + printf("%s 10G Ethernet: 10G Base-T with SFI electrical interface\n", + pfx); + add_item_string(items, name_string, + "10G Ethernet: 10G Base-T with SFI electrical interface"); + break; + case SFF_8636_ETHERNET_100G_CLR4: + printf("%s 100G Ethernet: 100G CLR4\n", pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G CLR4"); + break; + case SFF_8636_ETHERNET_100G_AOC2: + printf("%s 100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)\n", + pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)"); + break; + case SFF_8636_ETHERNET_100G_ACC2: + printf("%s 100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)\n", + pfx); + add_item_string(items, name_string, + "100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)"); + break; + default: + printf("%s (reserved or unknown)\n", pfx); + add_item_string(items, name_string, + "(reserved or unknown)"); + break; + } + } + + /* SONET Compliance Codes */ + if (id[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_40G_OTN) { + printf("%s 40G OTN (OTU3B/OTU3C)\n", pfx); + add_item_string(items, name_string, "40G OTN (OTU3B/OTU3C)"); + } + if (id[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_LR) { + printf("%s SONET: OC-48, long reach\n", pfx); + add_item_string(items, name_string, "SONET: OC-48, long reach"); + } + if (id[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_IR) { + printf("%s SONET: OC-48, intermediate reach\n", pfx); + add_item_string(items, name_string, "SONET: OC-48, intermediate reach"); + } + if (id[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_SR) { + printf("%s SONET: OC-48, short reach\n", pfx); + add_item_string(items, name_string, "SONET: OC-48, short reach"); + } + + /* SAS/SATA Compliance Codes */ + if (id[SFF_8636_SAS_COMP_OFFSET] & SFF_8636_SAS_6G) { + printf("%s SAS 6.0G\n", pfx); + add_item_string(items, name_string, "SAS 6.0G"); + } + if (id[SFF_8636_SAS_COMP_OFFSET] & SFF_8636_SAS_3G) { + printf("%s SAS 3.0G\n", pfx); + add_item_string(items, name_string, "SAS 3.0G"); + } + + /* Ethernet Compliance Codes */ + if (id[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_T) { + printf("%s Ethernet: 1000BASE-T\n", pfx); + add_item_string(items, name_string, "Ethernet: 1000BASE-T"); + } + if (id[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_CX) { + printf("%s Ethernet: 1000BASE-CX\n", pfx); + add_item_string(items, name_string, "Ethernet: 1000BASE-CX"); + } + if (id[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_LX) { + printf("%s Ethernet: 1000BASE-LX\n", pfx); + add_item_string(items, name_string, "Ethernet: 1000BASE-LX"); + } + if (id[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_SX) { + printf("%s Ethernet: 1000BASE-SX\n", pfx); + add_item_string(items, name_string, "Ethernet: 1000BASE-SX"); + } + + /* Fibre Channel link length */ + if (id[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_VERY_LONG) { + printf("%s FC: very long distance (V)\n", pfx); + add_item_string(items, name_string, "FC: very long distance (V)"); + } + if (id[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_SHORT) { + printf("%s FC: short distance (S)\n", pfx); + add_item_string(items, name_string, "FC: short distance (S)"); + } + if (id[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_INT) { + printf("%s FC: intermediate distance (I)\n", pfx); + add_item_string(items, name_string, "FC: intermediate distance (I)"); + } + if (id[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_LONG) { + printf("%s FC: long distance (L)\n", pfx); + add_item_string(items, name_string, "FC: long distance (L)"); + } + if (id[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_MED) { + printf("%s FC: medium distance (M)\n", pfx); + add_item_string(items, name_string, "FC: medium distance (M)"); + } + + /* Fibre Channel transmitter technology */ + if (id[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_TECH_LONG_LC) { + printf("%s FC: Longwave laser (LC)\n", pfx); + add_item_string(items, name_string, "FC: Longwave laser (LC)"); + } + if (id[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_TECH_ELEC_INTER) { + printf("%s FC: Electrical inter-enclosure (EL)\n", pfx); + add_item_string(items, name_string, "FC: Electrical inter-enclosure (EL)"); + } + if (id[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_ELEC_INTRA) { + printf("%s FC: Electrical intra-enclosure (EL)\n", pfx); + add_item_string(items, name_string, "FC: Electrical intra-enclosure (EL)"); + } + if (id[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_SHORT_WO_OFC) { + printf("%s FC: Shortwave laser w/o OFC (SN)\n", pfx); + add_item_string(items, name_string, "FC: Shortwave laser w/o OFC (SN)"); + } + if (id[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_SHORT_W_OFC) { + printf("%s FC: Shortwave laser with OFC (SL)\n", pfx); + add_item_string(items, name_string, "FC: Shortwave laser with OFC (SL)"); + } + if (id[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_LONG_LL) { + printf("%s FC: Longwave laser (LL)\n", pfx); + add_item_string(items, name_string, "FC: Longwave laser (LL)"); + } + + /* Fibre Channel transmission media */ + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TW) { + printf("%s FC: Twin Axial Pair (TW)\n", pfx); + add_item_string(items, name_string, "FC: Twin Axial Pair (TW)"); + } + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TP) { + printf("%s FC: Twisted Pair (TP)\n", pfx); + add_item_string(items, name_string, "FC: Twisted Pair (TP)"); + } + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_MI) { + printf("%s FC: Miniature Coax (MI)\n", pfx); + add_item_string(items, name_string, "FC: Miniature Coax (MI)"); + } + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TV) { + printf("%s FC: Video Coax (TV)\n", pfx); + add_item_string(items, name_string, "FC: Video Coax (TV)"); + } + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_M6) { + printf("%s FC: Multimode, 62.5m (M6)\n", pfx); + add_item_string(items, name_string, "FC: Multimode, 62.5m (M6)"); + } + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_M5) { + printf("%s FC: Multimode, 50m (M5)\n", pfx); + add_item_string(items, name_string, "FC: Multimode, 50m (M5)"); + } + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_OM3) { + printf("%s FC: Multimode, 50um (OM3)\n", pfx); + add_item_string(items, name_string, "FC: Multimode, 50um (OM3)"); + } + if (id[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_SM) { + printf("%s FC: Single Mode (SM)\n", pfx); + add_item_string(items, name_string, "FC: Single Mode (SM)"); + } + + /* Fibre Channel speed */ + if (id[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_1200_MBPS) { + printf("%s FC: 1200 MBytes/sec\n", pfx); + add_item_string(items, name_string, "FC: 1200 MBytes/sec"); + } + if (id[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_800_MBPS) { + printf("%s FC: 800 MBytes/sec\n", pfx); + add_item_string(items, name_string, "FC: 800 MBytes/sec"); + } + if (id[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_1600_MBPS) { + printf("%s FC: 1600 MBytes/sec\n", pfx); + add_item_string(items, name_string, "FC: 1600 MBytes/sec"); + } + if (id[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_400_MBPS) { + printf("%s FC: 400 MBytes/sec\n", pfx); + add_item_string(items, name_string, "FC: 400 MBytes/sec"); + } + if (id[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_200_MBPS) { + printf("%s FC: 200 MBytes/sec\n", pfx); + add_item_string(items, name_string, "FC: 200 MBytes/sec"); + } + if (id[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_100_MBPS) { + printf("%s FC: 100 MBytes/sec\n", pfx); + add_item_string(items, name_string, "FC: 100 MBytes/sec"); + } +} + +static void sff_8636_show_encoding(const uint8_t *id, sff_item *items) +{ + sff_8024_show_encoding(id, SFF_8636_ENCODING_OFFSET, + RTE_ETH_MODULE_SFF_8636, items); +} + +static void sff_8636_show_rate_identifier(const uint8_t *id, sff_item *items) +{ + char val_string[20]; + /* TODO: Need to fix rate select logic */ + printf("%-41s : 0x%02x\n", "Rate identifier", + id[SFF_8636_EXT_RS_OFFSET]); + sprintf(val_string, "0x%02x", id[SFF_8636_EXT_RS_OFFSET]); + add_item_string(items, "Rate identifier", val_string); +} + +static void sff_8636_show_oui(const uint8_t *id, sff_item *items) +{ + sff_8024_show_oui(id, SFF_8636_VENDOR_OUI_OFFSET, items); +} + +static void sff_8636_show_wavelength_or_copper_compliance(const uint8_t *id, sff_item *items) +{ + char val_string[TMP_STRING_SIZE]; + printf("%-41s : 0x%02x", "Transmitter technology", + (id[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK)); + sprintf(val_string, "0x%02x", + (id[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK)); + + switch (id[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK) { + case SFF_8636_TRANS_850_VCSEL: + printf(" (850 nm VCSEL)\n"); + strcat(val_string, " (850 nm VCSEL)"); + break; + case SFF_8636_TRANS_1310_VCSEL: + printf(" (1310 nm VCSEL)\n"); + strcat(val_string, " (1310 nm VCSEL)"); + break; + case SFF_8636_TRANS_1550_VCSEL: + printf(" (1550 nm VCSEL)\n"); + strcat(val_string, " (1550 nm VCSEL)"); + break; + case SFF_8636_TRANS_1310_FP: + printf(" (1310 nm FP)\n"); + strcat(val_string, " (1310 nm FP)"); + break; + case SFF_8636_TRANS_1310_DFB: + printf(" (1310 nm DFB)\n"); + strcat(val_string, " (1310 nm DFB)"); + break; + case SFF_8636_TRANS_1550_DFB: + printf(" (1550 nm DFB)\n"); + strcat(val_string, " (1550 nm DFB)"); + break; + case SFF_8636_TRANS_1310_EML: + printf(" (1310 nm EML)\n"); + strcat(val_string, " (1310 nm EML)"); + break; + case SFF_8636_TRANS_1550_EML: + printf(" (1550 nm EML)\n"); + strcat(val_string, " (1550 nm EML)"); + break; + case SFF_8636_TRANS_OTHERS: + printf(" (Others/Undefined)\n"); + strcat(val_string, " (Others/Undefined)"); + break; + case SFF_8636_TRANS_1490_DFB: + printf(" (1490 nm DFB)\n"); + strcat(val_string, " (1490 nm DFB)"); + break; + case SFF_8636_TRANS_COPPER_PAS_UNEQUAL: + printf(" (Copper cable unequalized)\n"); + strcat(val_string, " (Copper cable unequalized)"); + break; + case SFF_8636_TRANS_COPPER_PAS_EQUAL: + printf(" (Copper cable passive equalized)\n"); + strcat(val_string, " (Copper cable passive equalized)"); + break; + case SFF_8636_TRANS_COPPER_LNR_FAR_EQUAL: + printf(" (Copper cable, near and far end limiting active equalizers)\n"); + strcat(val_string, + " (Copper cable, near and far end limiting active equalizers)"); + break; + case SFF_8636_TRANS_COPPER_FAR_EQUAL: + printf(" (Copper cable, far end limiting active equalizers)\n"); + strcat(val_string, " (Copper cable, far end limiting active equalizers)"); + break; + case SFF_8636_TRANS_COPPER_NEAR_EQUAL: + printf(" (Copper cable, near end limiting active equalizers)\n"); + strcat(val_string, " (Copper cable, near end limiting active equalizers)"); + break; + case SFF_8636_TRANS_COPPER_LNR_EQUAL: + printf(" (Copper cable, linear active equalizers)\n"); + strcat(val_string, " (Copper cable, linear active equalizers)"); + break; + } + add_item_string(items, "Transmitter technology", val_string); + + if ((id[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK) + >= SFF_8636_TRANS_COPPER_PAS_UNEQUAL) { + printf("%-41s : %udb\n", "Attenuation at 2.5GHz", + id[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + sprintf(val_string, "%udb", id[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + add_item_string(items, "Attenuation at 2.5GHz", val_string); + + printf("%-41s : %udb\n", "Attenuation at 5.0GHz", + id[SFF_8636_WAVELEN_LOW_BYTE_OFFSET]); + sprintf(val_string, "%udb", id[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + add_item_string(items, "Attenuation at 5.0GHz", val_string); + + printf("%-41s : %udb\n", "Attenuation at 7.0GHz", + id[SFF_8636_WAVE_TOL_HIGH_BYTE_OFFSET]); + sprintf(val_string, "%udb", id[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + add_item_string(items, "Attenuation at 7.0GHz", val_string); + + printf("%-41s : %udb\n", "Attenuation at 12.9GHz", + id[SFF_8636_WAVE_TOL_LOW_BYTE_OFFSET]); + sprintf(val_string, "%udb", id[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + add_item_string(items, "Attenuation at 12.9GHz", val_string); + } else { + printf("%-41s : %.3lfnm\n", "Laser wavelength", + (((id[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET] << 8) | + id[SFF_8636_WAVELEN_LOW_BYTE_OFFSET])*0.05)); + sprintf(val_string, "%.3lfnm", + (((id[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET] << 8) | + id[SFF_8636_WAVELEN_LOW_BYTE_OFFSET])*0.05)); + add_item_string(items, "Laser wavelength", val_string); + + printf("%-41s : %.3lfnm\n", "Laser wavelength tolerance", + (((id[SFF_8636_WAVE_TOL_HIGH_BYTE_OFFSET] << 8) | + id[SFF_8636_WAVE_TOL_LOW_BYTE_OFFSET])*0.005)); + sprintf(val_string, "%.3lfnm", + (((id[SFF_8636_WAVE_TOL_HIGH_BYTE_OFFSET] << 8) | + id[SFF_8636_WAVE_TOL_LOW_BYTE_OFFSET])*0.005)); + add_item_string(items, "Laser wavelength tolerance", val_string); + } +} + +static void sff_8636_show_revision_compliance(const uint8_t *id, sff_item *items) +{ + static const char *pfx = + "Revision Compliance :"; + + switch (id[SFF_8636_REV_COMPLIANCE_OFFSET]) { + case SFF_8636_REV_UNSPECIFIED: + printf("%s Revision not specified\n", pfx); + add_item_string(items, "Revision Compliance", + "Revision not specified"); + break; + case SFF_8636_REV_8436_48: + printf("%s SFF-8436 Rev 4.8 or earlier\n", pfx); + add_item_string(items, "Revision Compliance", + "SFF-8436 Rev 4.8 or earlier"); + break; + case SFF_8636_REV_8436_8636: + printf("%s SFF-8436 Rev 4.8 or earlier\n", pfx); + add_item_string(items, "Revision Compliance", + "SFF-8436 Rev 4.8 or earlier"); + break; + case SFF_8636_REV_8636_13: + printf("%s SFF-8636 Rev 1.3 or earlier\n", pfx); + add_item_string(items, "Revision Compliance", + "SFF-8636 Rev 1.3 or earlier"); + break; + case SFF_8636_REV_8636_14: + printf("%s SFF-8636 Rev 1.4\n", pfx); + add_item_string(items, "Revision Compliance", + "SFF-8636 Rev 1.4"); + break; + case SFF_8636_REV_8636_15: + printf("%s SFF-8636 Rev 1.5\n", pfx); + add_item_string(items, "Revision Compliance", + "SFF-8636 Rev 1.5"); + break; + case SFF_8636_REV_8636_20: + printf("%s SFF-8636 Rev 2.0\n", pfx); + add_item_string(items, "Revision Compliance", + "SFF-8636 Rev 2.0"); + break; + case SFF_8636_REV_8636_27: + printf("%s SFF-8636 Rev 2.5/2.6/2.7\n", pfx); + add_item_string(items, "Revision Compliance", + "SFF-8636 Rev 2.5/2.6/2.7"); + break; + default: + printf("%s Unallocated\n", pfx); + add_item_string(items, "Revision Compliance", + "Unallocated"); + break; + } +} + +/* + * 2-byte internal temperature conversions: + * First byte is a signed 8-bit integer, which is the temp decimal part + * Second byte are 1/256th of degree, which are added to the dec part. + */ +#define SFF_8636_OFFSET_TO_TEMP(offset) ((int16_t)OFFSET_TO_U16(offset)) + +static void sff_8636_dom_parse(const uint8_t *id, struct sff_diags *sd) +{ + int i = 0; + + /* Monitoring Thresholds for Alarms and Warnings */ + sd->sfp_voltage[MCURR] = OFFSET_TO_U16(SFF_8636_VCC_CURR); + sd->sfp_voltage[HALRM] = OFFSET_TO_U16(SFF_8636_VCC_HALRM); + sd->sfp_voltage[LALRM] = OFFSET_TO_U16(SFF_8636_VCC_LALRM); + sd->sfp_voltage[HWARN] = OFFSET_TO_U16(SFF_8636_VCC_HWARN); + sd->sfp_voltage[LWARN] = OFFSET_TO_U16(SFF_8636_VCC_LWARN); + + sd->sfp_temp[MCURR] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_CURR); + sd->sfp_temp[HALRM] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_HALRM); + sd->sfp_temp[LALRM] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_LALRM); + sd->sfp_temp[HWARN] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_HWARN); + sd->sfp_temp[LWARN] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_LWARN); + + sd->bias_cur[HALRM] = OFFSET_TO_U16(SFF_8636_TX_BIAS_HALRM); + sd->bias_cur[LALRM] = OFFSET_TO_U16(SFF_8636_TX_BIAS_LALRM); + sd->bias_cur[HWARN] = OFFSET_TO_U16(SFF_8636_TX_BIAS_HWARN); + sd->bias_cur[LWARN] = OFFSET_TO_U16(SFF_8636_TX_BIAS_LWARN); + + sd->tx_power[HALRM] = OFFSET_TO_U16(SFF_8636_TX_PWR_HALRM); + sd->tx_power[LALRM] = OFFSET_TO_U16(SFF_8636_TX_PWR_LALRM); + sd->tx_power[HWARN] = OFFSET_TO_U16(SFF_8636_TX_PWR_HWARN); + sd->tx_power[LWARN] = OFFSET_TO_U16(SFF_8636_TX_PWR_LWARN); + + sd->rx_power[HALRM] = OFFSET_TO_U16(SFF_8636_RX_PWR_HALRM); + sd->rx_power[LALRM] = OFFSET_TO_U16(SFF_8636_RX_PWR_LALRM); + sd->rx_power[HWARN] = OFFSET_TO_U16(SFF_8636_RX_PWR_HWARN); + sd->rx_power[LWARN] = OFFSET_TO_U16(SFF_8636_RX_PWR_LWARN); + + + /* Channel Specific Data */ + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + uint8_t rx_power_offset, tx_bias_offset; + uint8_t tx_power_offset; + + switch (i) { + case 0: + rx_power_offset = SFF_8636_RX_PWR_1_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_1_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_1_OFFSET; + break; + case 1: + rx_power_offset = SFF_8636_RX_PWR_2_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_2_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_2_OFFSET; + break; + case 2: + rx_power_offset = SFF_8636_RX_PWR_3_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_3_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_3_OFFSET; + break; + case 3: + rx_power_offset = SFF_8636_RX_PWR_4_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_4_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_4_OFFSET; + break; + } + sd->scd[i].bias_cur = OFFSET_TO_U16(tx_bias_offset); + sd->scd[i].rx_power = OFFSET_TO_U16(rx_power_offset); + sd->scd[i].tx_power = OFFSET_TO_U16(tx_power_offset); + } + +} + +static void sff_8636_show_dom(const uint8_t *id, uint32_t eeprom_len, sff_item *items) +{ + struct sff_diags sd = {0}; + const char *rx_power_string = NULL; + char power_string[MAX_DESC_SIZE]; + char val_string[TMP_STRING_SIZE]; + int i; + + /* + * There is no clear identifier to signify the existence of + * optical diagnostics similar to SFF-8472. So checking existence + * of page 3, will provide the gurantee for existence of alarms + * and thresholds + * If pagging support exists, then supports_alarms is marked as 1 + */ + + if (eeprom_len == RTE_ETH_MODULE_SFF_8636_MAX_LEN) { + if (!(id[SFF_8636_STATUS_2_OFFSET] & + SFF_8636_STATUS_PAGE_3_PRESENT)) { + sd.supports_alarms = 1; + } + } + + sd.rx_power_type = id[SFF_8636_DIAG_TYPE_OFFSET] & + SFF_8636_RX_PWR_TYPE_MASK; + sd.tx_power_type = id[SFF_8636_DIAG_TYPE_OFFSET] & + SFF_8636_RX_PWR_TYPE_MASK; + + sff_8636_dom_parse(id, &sd); + + PRINT_TEMP("Module temperature", sd.sfp_temp[MCURR]); + SPRINT_TEMP(val_string, sd.sfp_temp[MCURR]); + add_item_string(items, "Module temperature", val_string); + + PRINT_VCC("Module voltage", sd.sfp_voltage[MCURR]); + SPRINT_VCC(val_string, sd.sfp_voltage[MCURR]); + add_item_string(items, "Module voltage", val_string); + + /* + * SFF-8636/8436 spec is not clear whether RX power/ TX bias + * current fields are supported or not. A valid temperature + * reading is used as existence for TX/RX power. + */ + if ((sd.sfp_temp[MCURR] == 0x0) || + (sd.sfp_temp[MCURR] == (int16_t)0xFFFF)) + return; + + printf("%-41s : %s\n", "Alarm/warning flags implemented", + (sd.supports_alarms ? "Yes" : "No")); + add_item_string(items, "Alarm/warning flags implemented", + (sd.supports_alarms ? "Yes" : "No")); + + for (i = 0; i < 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); + SPRINT_BIAS(val_string, sd.scd[i].bias_cur); + add_item_string(items, power_string, val_string); + } + + for (i = 0; i < 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); + SPRINT_xX_PWR(val_string, sd.scd[i].tx_power); + add_item_string(items, power_string, val_string); + } + + if (!sd.rx_power_type) + rx_power_string = "Receiver signal OMA"; + else + rx_power_string = "Rcvr signal avg optical power"; + + for (i = 0; i < 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); + SPRINT_xX_PWR(val_string, sd.scd[i].rx_power); + add_item_string(items, power_string, val_string); + } + + if (sd.supports_alarms) { + for (i = 0; sff_8636_aw_flags[i].str; ++i) { + printf("%-41s : %s\n", sff_8636_aw_flags[i].str, + id[sff_8636_aw_flags[i].offset] + & sff_8636_aw_flags[i].value ? "On" : "Off"); + add_item_string(items, sff_8636_aw_flags[i].str, + id[sff_8636_aw_flags[i].offset] + & sff_8636_aw_flags[i].value ? "On" : "Off"); + } + + sff_show_thresholds(sd, items); + } + +} +void sff_8636_show_all(const uint8_t *id, uint32_t eeprom_len, sff_item *items) +{ + sff_8636_show_identifier(id, items); + if ((id[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP) || + (id[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP_PLUS) || + (id[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP28)) { + sff_8636_show_ext_identifier(id, items); + sff_8636_show_connector(id, items); + sff_8636_show_transceiver(id, items); + sff_8636_show_encoding(id, items); + sff_show_value_with_unit(id, SFF_8636_BR_NOMINAL_OFFSET, + "BR, Nominal", 100, "Mbps", items); + sff_8636_show_rate_identifier(id, items); + sff_show_value_with_unit(id, SFF_8636_SM_LEN_OFFSET, + "Length (SMF,km)", 1, "km", items); + sff_show_value_with_unit(id, SFF_8636_OM3_LEN_OFFSET, + "Length (OM3 50um)", 2, "m", items); + sff_show_value_with_unit(id, SFF_8636_OM2_LEN_OFFSET, + "Length (OM2 50um)", 1, "m", items); + sff_show_value_with_unit(id, SFF_8636_OM1_LEN_OFFSET, + "Length (OM1 62.5um)", 1, "m", items); + sff_show_value_with_unit(id, SFF_8636_CBL_LEN_OFFSET, + "Length (Copper or Active cable)", 1, "m", items); + sff_8636_show_wavelength_or_copper_compliance(id, items); + sff_show_ascii(id, SFF_8636_VENDOR_NAME_START_OFFSET, + SFF_8636_VENDOR_NAME_END_OFFSET, "Vendor name", items); + sff_8636_show_oui(id, items); + sff_show_ascii(id, SFF_8636_VENDOR_PN_START_OFFSET, + SFF_8636_VENDOR_PN_END_OFFSET, "Vendor PN", items); + sff_show_ascii(id, SFF_8636_VENDOR_REV_START_OFFSET, + SFF_8636_VENDOR_REV_END_OFFSET, "Vendor rev", items); + sff_show_ascii(id, SFF_8636_VENDOR_SN_START_OFFSET, + SFF_8636_VENDOR_SN_END_OFFSET, "Vendor SN", items); + sff_show_ascii(id, SFF_8636_DATE_YEAR_OFFSET, + SFF_8636_DATE_VENDOR_LOT_OFFSET + 1, "Date code", items); + sff_8636_show_revision_compliance(id, items); + sff_8636_show_dom(id, eeprom_len, items); + } +} diff --git a/lib/ethdev/sff_8636.h b/lib/ethdev/sff_8636.h new file mode 100644 index 0000000000..d19e6c744e --- /dev/null +++ b/lib/ethdev/sff_8636.h @@ -0,0 +1,592 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2022 Intel Corporation + * + * SFF-8636 standards based QSFP EEPROM Field Definitions + * + */ + +#ifndef SFF_8636_H__ +#define SFF_8636_H__ + +/*------------------------------------------------------------------------------ + * + * QSFP EEPROM data structures + * + * register info from SFF-8636 Rev 2.7 + */ + +/*------------------------------------------------------------------------------ + * + * Lower Memory Page 00h + * Measurement, Diagnostic and Control Functions + * + */ +/* Identifier - 0 */ +/* Values are defined under SFF_8024_ID_OFFSET */ +#define SFF_8636_ID_OFFSET 0x00 + +#define SFF_8636_REV_COMPLIANCE_OFFSET 0x01 +#define SFF_8636_REV_UNSPECIFIED 0x00 +#define SFF_8636_REV_8436_48 0x01 +#define SFF_8636_REV_8436_8636 0x02 +#define SFF_8636_REV_8636_13 0x03 +#define SFF_8636_REV_8636_14 0x04 +#define SFF_8636_REV_8636_15 0x05 +#define SFF_8636_REV_8636_20 0x06 +#define SFF_8636_REV_8636_27 0x07 + +#define SFF_8636_STATUS_2_OFFSET 0x02 +/* Flat Memory:0- Paging, 1- Page 0 only */ +#define SFF_8636_STATUS_PAGE_3_PRESENT (1 << 2) +#define SFF_8636_STATUS_INTL_OUTPUT (1 << 1) +#define SFF_8636_STATUS_DATA_NOT_READY (1 << 0) + +/* Channel Status Interrupt Flags - 3-5 */ +#define SFF_8636_LOS_AW_OFFSET 0x03 +#define SFF_8636_TX4_LOS_AW (1 << 7) +#define SFF_8636_TX3_LOS_AW (1 << 6) +#define SFF_8636_TX2_LOS_AW (1 << 5) +#define SFF_8636_TX1_LOS_AW (1 << 4) +#define SFF_8636_RX4_LOS_AW (1 << 3) +#define SFF_8636_RX3_LOS_AW (1 << 2) +#define SFF_8636_RX2_LOS_AW (1 << 1) +#define SFF_8636_RX1_LOS_AW (1 << 0) + +#define SFF_8636_FAULT_AW_OFFSET 0x04 +#define SFF_8636_TX4_FAULT_AW (1 << 3) +#define SFF_8636_TX3_FAULT_AW (1 << 2) +#define SFF_8636_TX2_FAULT_AW (1 << 1) +#define SFF_8636_TX1_FAULT_AW (1 << 0) + +/* Module Monitor Interrupt Flags - 6-8 */ +#define SFF_8636_TEMP_AW_OFFSET 0x06 +#define SFF_8636_TEMP_HALARM_STATUS (1 << 7) +#define SFF_8636_TEMP_LALARM_STATUS (1 << 6) +#define SFF_8636_TEMP_HWARN_STATUS (1 << 5) +#define SFF_8636_TEMP_LWARN_STATUS (1 << 4) + +#define SFF_8636_VCC_AW_OFFSET 0x07 +#define SFF_8636_VCC_HALARM_STATUS (1 << 7) +#define SFF_8636_VCC_LALARM_STATUS (1 << 6) +#define SFF_8636_VCC_HWARN_STATUS (1 << 5) +#define SFF_8636_VCC_LWARN_STATUS (1 << 4) + +/* Channel Monitor Interrupt Flags - 9-21 */ +#define SFF_8636_RX_PWR_12_AW_OFFSET 0x09 +#define SFF_8636_RX_PWR_1_HALARM (1 << 7) +#define SFF_8636_RX_PWR_1_LALARM (1 << 6) +#define SFF_8636_RX_PWR_1_HWARN (1 << 5) +#define SFF_8636_RX_PWR_1_LWARN (1 << 4) +#define SFF_8636_RX_PWR_2_HALARM (1 << 3) +#define SFF_8636_RX_PWR_2_LALARM (1 << 2) +#define SFF_8636_RX_PWR_2_HWARN (1 << 1) +#define SFF_8636_RX_PWR_2_LWARN (1 << 0) + +#define SFF_8636_RX_PWR_34_AW_OFFSET 0x0A +#define SFF_8636_RX_PWR_3_HALARM (1 << 7) +#define SFF_8636_RX_PWR_3_LALARM (1 << 6) +#define SFF_8636_RX_PWR_3_HWARN (1 << 5) +#define SFF_8636_RX_PWR_3_LWARN (1 << 4) +#define SFF_8636_RX_PWR_4_HALARM (1 << 3) +#define SFF_8636_RX_PWR_4_LALARM (1 << 2) +#define SFF_8636_RX_PWR_4_HWARN (1 << 1) +#define SFF_8636_RX_PWR_4_LWARN (1 << 0) + +#define SFF_8636_TX_BIAS_12_AW_OFFSET 0x0B +#define SFF_8636_TX_BIAS_1_HALARM (1 << 7) +#define SFF_8636_TX_BIAS_1_LALARM (1 << 6) +#define SFF_8636_TX_BIAS_1_HWARN (1 << 5) +#define SFF_8636_TX_BIAS_1_LWARN (1 << 4) +#define SFF_8636_TX_BIAS_2_HALARM (1 << 3) +#define SFF_8636_TX_BIAS_2_LALARM (1 << 2) +#define SFF_8636_TX_BIAS_2_HWARN (1 << 1) +#define SFF_8636_TX_BIAS_2_LWARN (1 << 0) + +#define SFF_8636_TX_BIAS_34_AW_OFFSET 0xC +#define SFF_8636_TX_BIAS_3_HALARM (1 << 7) +#define SFF_8636_TX_BIAS_3_LALARM (1 << 6) +#define SFF_8636_TX_BIAS_3_HWARN (1 << 5) +#define SFF_8636_TX_BIAS_3_LWARN (1 << 4) +#define SFF_8636_TX_BIAS_4_HALARM (1 << 3) +#define SFF_8636_TX_BIAS_4_LALARM (1 << 2) +#define SFF_8636_TX_BIAS_4_HWARN (1 << 1) +#define SFF_8636_TX_BIAS_4_LWARN (1 << 0) + +#define SFF_8636_TX_PWR_12_AW_OFFSET 0x0D +#define SFF_8636_TX_PWR_1_HALARM (1 << 7) +#define SFF_8636_TX_PWR_1_LALARM (1 << 6) +#define SFF_8636_TX_PWR_1_HWARN (1 << 5) +#define SFF_8636_TX_PWR_1_LWARN (1 << 4) +#define SFF_8636_TX_PWR_2_HALARM (1 << 3) +#define SFF_8636_TX_PWR_2_LALARM (1 << 2) +#define SFF_8636_TX_PWR_2_HWARN (1 << 1) +#define SFF_8636_TX_PWR_2_LWARN (1 << 0) + +#define SFF_8636_TX_PWR_34_AW_OFFSET 0x0E +#define SFF_8636_TX_PWR_3_HALARM (1 << 7) +#define SFF_8636_TX_PWR_3_LALARM (1 << 6) +#define SFF_8636_TX_PWR_3_HWARN (1 << 5) +#define SFF_8636_TX_PWR_3_LWARN (1 << 4) +#define SFF_8636_TX_PWR_4_HALARM (1 << 3) +#define SFF_8636_TX_PWR_4_LALARM (1 << 2) +#define SFF_8636_TX_PWR_4_HWARN (1 << 1) +#define SFF_8636_TX_PWR_4_LWARN (1 << 0) + +/* Module Monitoring Values - 22-33 */ +#define SFF_8636_TEMP_CURR 0x16 +#define SFF_8636_TEMP_MSB_OFFSET 0x16 +#define SFF_8636_TEMP_LSB_OFFSET 0x17 + +#define SFF_8636_VCC_CURR 0x1A +#define SFF_8636_VCC_MSB_OFFSET 0x1A +#define SFF_8636_VCC_LSB_OFFSET 0x1B + +/* Channel Monitoring Values - 34-81 */ +#define SFF_8636_RX_PWR_1_OFFSET 0x22 +#define SFF_8636_RX_PWR_2_OFFSET 0x24 +#define SFF_8636_RX_PWR_3_OFFSET 0x26 +#define SFF_8636_RX_PWR_4_OFFSET 0x28 + +#define SFF_8636_TX_BIAS_1_OFFSET 0x2A +#define SFF_8636_TX_BIAS_2_OFFSET 0x2C +#define SFF_8636_TX_BIAS_3_OFFSET 0x2E +#define SFF_8636_TX_BIAS_4_OFFSET 0x30 + +#define SFF_8636_TX_PWR_1_OFFSET 0x32 +#define SFF_8636_TX_PWR_2_OFFSET 0x34 +#define SFF_8636_TX_PWR_3_OFFSET 0x36 +#define SFF_8636_TX_PWR_4_OFFSET 0x38 + +/* Control Bytes - 86 - 99 */ +#define SFF_8636_TX_DISABLE_OFFSET 0x56 +#define SFF_8636_TX_DISABLE_4 (1 << 3) +#define SFF_8636_TX_DISABLE_3 (1 << 2) +#define SFF_8636_TX_DISABLE_2 (1 << 1) +#define SFF_8636_TX_DISABLE_1 (1 << 0) + +#define SFF_8636_RX_RATE_SELECT_OFFSET 0x57 +#define SFF_8636_RX_RATE_SELECT_4_MASK (3 << 6) +#define SFF_8636_RX_RATE_SELECT_3_MASK (3 << 4) +#define SFF_8636_RX_RATE_SELECT_2_MASK (3 << 2) +#define SFF_8636_RX_RATE_SELECT_1_MASK (3 << 0) + +#define SFF_8636_TX_RATE_SELECT_OFFSET 0x58 +#define SFF_8636_TX_RATE_SELECT_4_MASK (3 << 6) +#define SFF_8636_TX_RATE_SELECT_3_MASK (3 << 4) +#define SFF_8636_TX_RATE_SELECT_2_MASK (3 << 2) +#define SFF_8636_TX_RATE_SELECT_1_MASK (3 << 0) + +#define SFF_8636_RX_APP_SELECT_4_OFFSET 0x58 +#define SFF_8636_RX_APP_SELECT_3_OFFSET 0x59 +#define SFF_8636_RX_APP_SELECT_2_OFFSET 0x5A +#define SFF_8636_RX_APP_SELECT_1_OFFSET 0x5B + +#define SFF_8636_PWR_MODE_OFFSET 0x5D +#define SFF_8636_HIGH_PWR_ENABLE (1 << 2) +#define SFF_8636_LOW_PWR_MODE (1 << 1) +#define SFF_8636_PWR_OVERRIDE (1 << 0) + +#define SFF_8636_TX_APP_SELECT_4_OFFSET 0x5E +#define SFF_8636_TX_APP_SELECT_3_OFFSET 0x5F +#define SFF_8636_TX_APP_SELECT_2_OFFSET 0x60 +#define SFF_8636_TX_APP_SELECT_1_OFFSET 0x61 + +#define SFF_8636_LOS_MASK_OFFSET 0x64 +#define SFF_8636_TX_LOS_4_MASK (1 << 7) +#define SFF_8636_TX_LOS_3_MASK (1 << 6) +#define SFF_8636_TX_LOS_2_MASK (1 << 5) +#define SFF_8636_TX_LOS_1_MASK (1 << 4) +#define SFF_8636_RX_LOS_4_MASK (1 << 3) +#define SFF_8636_RX_LOS_3_MASK (1 << 2) +#define SFF_8636_RX_LOS_2_MASK (1 << 1) +#define SFF_8636_RX_LOS_1_MASK (1 << 0) + +#define SFF_8636_FAULT_MASK_OFFSET 0x65 +#define SFF_8636_TX_FAULT_1_MASK (1 << 3) +#define SFF_8636_TX_FAULT_2_MASK (1 << 2) +#define SFF_8636_TX_FAULT_3_MASK (1 << 1) +#define SFF_8636_TX_FAULT_4_MASK (1 << 0) + +#define SFF_8636_TEMP_MASK_OFFSET 0x67 +#define SFF_8636_TEMP_HALARM_MASK (1 << 7) +#define SFF_8636_TEMP_LALARM_MASK (1 << 6) +#define SFF_8636_TEMP_HWARN_MASK (1 << 5) +#define SFF_8636_TEMP_LWARN_MASK (1 << 4) + +#define SFF_8636_VCC_MASK_OFFSET 0x68 +#define SFF_8636_VCC_HALARM_MASK (1 << 7) +#define SFF_8636_VCC_LALARM_MASK (1 << 6) +#define SFF_8636_VCC_HWARN_MASK (1 << 5) +#define SFF_8636_VCC_LWARN_MASK (1 << 4) + +/*------------------------------------------------------------------------------ + * + * Upper Memory Page 00h + * Serial ID - Base ID, Extended ID and Vendor Specific ID fields + * + */ +/* Identifier - 128 */ +/* Identifier values same as Lower Memory Page 00h */ +#define SFF_8636_UPPER_PAGE_0_ID_OFFSET 0x80 + +/* Extended Identifier - 128 */ +#define SFF_8636_EXT_ID_OFFSET 0x81 +#define SFF_8636_EXT_ID_PWR_CLASS_MASK 0xC0 +#define SFF_8636_EXT_ID_PWR_CLASS_1 (0 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_2 (1 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_3 (2 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_4 (3 << 6) +#define SFF_8636_EXT_ID_CLIE_MASK 0x10 +#define SFF_8636_EXT_ID_CLIEI_CODE_PRESENT (1 << 4) +#define SFF_8636_EXT_ID_CDR_TX_MASK 0x08 +#define SFF_8636_EXT_ID_CDR_TX_PRESENT (1 << 3) +#define SFF_8636_EXT_ID_CDR_RX_MASK 0x04 +#define SFF_8636_EXT_ID_CDR_RX_PRESENT (1 << 2) +#define SFF_8636_EXT_ID_EPWR_CLASS_MASK 0x03 +#define SFF_8636_EXT_ID_PWR_CLASS_LEGACY 0 +#define SFF_8636_EXT_ID_PWR_CLASS_5 1 +#define SFF_8636_EXT_ID_PWR_CLASS_6 2 +#define SFF_8636_EXT_ID_PWR_CLASS_7 3 + +/* Connector Values offset - 130 */ +/* Values are defined under SFF_8024_CTOR */ +#define SFF_8636_CTOR_OFFSET 0x82 +#define SFF_8636_CTOR_UNKNOWN 0x00 +#define SFF_8636_CTOR_SC 0x01 +#define SFF_8636_CTOR_FC_STYLE_1 0x02 +#define SFF_8636_CTOR_FC_STYLE_2 0x03 +#define SFF_8636_CTOR_BNC_TNC 0x04 +#define SFF_8636_CTOR_FC_COAX 0x05 +#define SFF_8636_CTOR_FIBER_JACK 0x06 +#define SFF_8636_CTOR_LC 0x07 +#define SFF_8636_CTOR_MT_RJ 0x08 +#define SFF_8636_CTOR_MU 0x09 +#define SFF_8636_CTOR_SG 0x0A +#define SFF_8636_CTOR_OPT_PT 0x0B +#define SFF_8636_CTOR_MPO 0x0C +/* 0D-1Fh --- Reserved */ +#define SFF_8636_CTOR_HSDC_II 0x20 +#define SFF_8636_CTOR_COPPER_PT 0x21 +#define SFF_8636_CTOR_RJ45 0x22 +#define SFF_8636_CTOR_NO_SEPARABLE 0x23 +#define SFF_8636_CTOR_MXC_2X16 0x24 + +/* Specification Compliance - 131-138 */ +/* Ethernet Compliance Codes - 131 */ +#define SFF_8636_ETHERNET_COMP_OFFSET 0x83 +#define SFF_8636_ETHERNET_RSRVD (1 << 7) +#define SFF_8636_ETHERNET_10G_LRM (1 << 6) +#define SFF_8636_ETHERNET_10G_LR (1 << 5) +#define SFF_8636_ETHERNET_10G_SR (1 << 4) +#define SFF_8636_ETHERNET_40G_CR4 (1 << 3) +#define SFF_8636_ETHERNET_40G_SR4 (1 << 2) +#define SFF_8636_ETHERNET_40G_LR4 (1 << 1) +#define SFF_8636_ETHERNET_40G_ACTIVE (1 << 0) + +/* SONET Compliance Codes - 132 */ +#define SFF_8636_SONET_COMP_OFFSET 0x84 +#define SFF_8636_SONET_40G_OTN (1 << 3) +#define SFF_8636_SONET_OC48_LR (1 << 2) +#define SFF_8636_SONET_OC48_IR (1 << 1) +#define SFF_8636_SONET_OC48_SR (1 << 0) + +/* SAS/SATA Complaince Codes - 133 */ +#define SFF_8636_SAS_COMP_OFFSET 0x85 +#define SFF_8636_SAS_12G (1 << 6) +#define SFF_8636_SAS_6G (1 << 5) +#define SFF_8636_SAS_3G (1 << 4) + +/* Gigabit Ethernet Compliance Codes - 134 */ +#define SFF_8636_GIGE_COMP_OFFSET 0x86 +#define SFF_8636_GIGE_1000_BASE_T (1 << 3) +#define SFF_8636_GIGE_1000_BASE_CX (1 << 2) +#define SFF_8636_GIGE_1000_BASE_LX (1 << 1) +#define SFF_8636_GIGE_1000_BASE_SX (1 << 0) + +/* Fibre Channel Link length/Transmitter Tech. - 135,136 */ +#define SFF_8636_FC_LEN_OFFSET 0x87 +#define SFF_8636_FC_LEN_VERY_LONG (1 << 7) +#define SFF_8636_FC_LEN_SHORT (1 << 6) +#define SFF_8636_FC_LEN_INT (1 << 5) +#define SFF_8636_FC_LEN_LONG (1 << 4) +#define SFF_8636_FC_LEN_MED (1 << 3) +#define SFF_8636_FC_TECH_LONG_LC (1 << 1) +#define SFF_8636_FC_TECH_ELEC_INTER (1 << 0) + +#define SFF_8636_FC_TECH_OFFSET 0x88 +#define SFF_8636_FC_TECH_ELEC_INTRA (1 << 7) +#define SFF_8636_FC_TECH_SHORT_WO_OFC (1 << 6) +#define SFF_8636_FC_TECH_SHORT_W_OFC (1 << 5) +#define SFF_8636_FC_TECH_LONG_LL (1 << 4) + +/* Fibre Channel Transmitter Media - 137 */ +#define SFF_8636_FC_TRANS_MEDIA_OFFSET 0x89 +/* Twin Axial Pair */ +#define SFF_8636_FC_TRANS_MEDIA_TW (1 << 7) +/* Shielded Twisted Pair */ +#define SFF_8636_FC_TRANS_MEDIA_TP (1 << 6) +/* Miniature Coax */ +#define SFF_8636_FC_TRANS_MEDIA_MI (1 << 5) +/* Video Coax */ +#define SFF_8636_FC_TRANS_MEDIA_TV (1 << 4) +/* Multi-mode 62.5m */ +#define SFF_8636_FC_TRANS_MEDIA_M6 (1 << 3) +/* Multi-mode 50m */ +#define SFF_8636_FC_TRANS_MEDIA_M5 (1 << 2) +/* Multi-mode 50um */ +#define SFF_8636_FC_TRANS_MEDIA_OM3 (1 << 1) +/* Single Mode */ +#define SFF_8636_FC_TRANS_MEDIA_SM (1 << 0) + +/* Fibre Channel Speed - 138 */ +#define SFF_8636_FC_SPEED_OFFSET 0x8A +#define SFF_8636_FC_SPEED_1200_MBPS (1 << 7) +#define SFF_8636_FC_SPEED_800_MBPS (1 << 6) +#define SFF_8636_FC_SPEED_1600_MBPS (1 << 5) +#define SFF_8636_FC_SPEED_400_MBPS (1 << 4) +#define SFF_8636_FC_SPEED_200_MBPS (1 << 2) +#define SFF_8636_FC_SPEED_100_MBPS (1 << 0) + +/* Encoding - 139 */ +/* Values are defined under SFF_8024_ENCODING */ +#define SFF_8636_ENCODING_OFFSET 0x8B +#define SFF_8636_ENCODING_MANCHESTER 0x06 +#define SFF_8636_ENCODING_64B66B 0x05 +#define SFF_8636_ENCODING_SONET 0x04 +#define SFF_8636_ENCODING_NRZ 0x03 +#define SFF_8636_ENCODING_4B5B 0x02 +#define SFF_8636_ENCODING_8B10B 0x01 +#define SFF_8636_ENCODING_UNSPEC 0x00 + +/* BR, Nominal - 140 */ +#define SFF_8636_BR_NOMINAL_OFFSET 0x8C + +/* Extended RateSelect - 141 */ +#define SFF_8636_EXT_RS_OFFSET 0x8D +#define SFF_8636_EXT_RS_V1 (1 << 0) + +/* Length (Standard SM Fiber)-km - 142 */ +#define SFF_8636_SM_LEN_OFFSET 0x8E + +/* Length (OM3)-Unit 2m - 143 */ +#define SFF_8636_OM3_LEN_OFFSET 0x8F + +/* Length (OM2)-Unit 1m - 144 */ +#define SFF_8636_OM2_LEN_OFFSET 0x90 + +/* Length (OM1)-Unit 1m - 145 */ +#define SFF_8636_OM1_LEN_OFFSET 0x91 + +/* Cable Assembly Length -Unit 1m - 146 */ +#define SFF_8636_CBL_LEN_OFFSET 0x92 + +/* Device Technology - 147 */ +#define SFF_8636_DEVICE_TECH_OFFSET 0x93 +/* Transmitter Technology */ +#define SFF_8636_TRANS_TECH_MASK 0xF0 +/* Copper cable, linear active equalizers */ +#define SFF_8636_TRANS_COPPER_LNR_EQUAL (15 << 4) +/* Copper cable, near end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_NEAR_EQUAL (14 << 4) +/* Copper cable, far end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_FAR_EQUAL (13 << 4) +/* Copper cable, near & far end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_LNR_FAR_EQUAL (12 << 4) +/* Copper cable, passive equalized */ +#define SFF_8636_TRANS_COPPER_PAS_EQUAL (11 << 4) +/* Copper cable, unequalized */ +#define SFF_8636_TRANS_COPPER_PAS_UNEQUAL (10 << 4) +/* 1490 nm DFB */ +#define SFF_8636_TRANS_1490_DFB (9 << 4) +/* Others */ +#define SFF_8636_TRANS_OTHERS (8 << 4) +/* 1550 nm EML */ +#define SFF_8636_TRANS_1550_EML (7 << 4) +/* 1310 nm EML */ +#define SFF_8636_TRANS_1310_EML (6 << 4) +/* 1550 nm DFB */ +#define SFF_8636_TRANS_1550_DFB (5 << 4) +/* 1310 nm DFB */ +#define SFF_8636_TRANS_1310_DFB (4 << 4) +/* 1310 nm FP */ +#define SFF_8636_TRANS_1310_FP (3 << 4) +/* 1550 nm VCSEL */ +#define SFF_8636_TRANS_1550_VCSEL (2 << 4) +/* 1310 nm VCSEL */ +#define SFF_8636_TRANS_1310_VCSEL (1 << 4) +/* 850 nm VCSEL */ +#define SFF_8636_TRANS_850_VCSEL (0 << 4) + + /* Active/No wavelength control */ +#define SFF_8636_DEV_TECH_ACTIVE_WAVE_LEN (1 << 3) +/* Cooled transmitter */ +#define SFF_8636_DEV_TECH_COOL_TRANS (1 << 2) +/* APD/Pin Detector */ +#define SFF_8636_DEV_TECH_APD_DETECTOR (1 << 1) +/* Transmitter tunable */ +#define SFF_8636_DEV_TECH_TUNABLE (1 << 0) + +/* Vendor Name - 148-163 */ +#define SFF_8636_VENDOR_NAME_START_OFFSET 0x94 +#define SFF_8636_VENDOR_NAME_END_OFFSET 0xA3 + +/* Extended Module Codes - 164 */ +#define SFF_8636_EXT_MOD_CODE_OFFSET 0xA4 +#define SFF_8636_EXT_MOD_INFINIBAND_EDR (1 << 4) +#define SFF_8636_EXT_MOD_INFINIBAND_FDR (1 << 3) +#define SFF_8636_EXT_MOD_INFINIBAND_QDR (1 << 2) +#define SFF_8636_EXT_MOD_INFINIBAND_DDR (1 << 1) +#define SFF_8636_EXT_MOD_INFINIBAND_SDR (1 << 0) + +/* Vendor OUI - 165-167 */ +#define SFF_8636_VENDOR_OUI_OFFSET 0xA5 +#define SFF_8636_VENDOR_OUI_LEN 3 + +/* Vendor OUI - 165-167 */ +#define SFF_8636_VENDOR_PN_START_OFFSET 0xA8 +#define SFF_8636_VENDOR_PN_END_OFFSET 0xB7 + +/* Vendor Revision - 184-185 */ +#define SFF_8636_VENDOR_REV_START_OFFSET 0xB8 +#define SFF_8636_VENDOR_REV_END_OFFSET 0xB9 + +/* Wavelength - 186-187 */ +#define SFF_8636_WAVELEN_HIGH_BYTE_OFFSET 0xBA +#define SFF_8636_WAVELEN_LOW_BYTE_OFFSET 0xBB + +/* Wavelength Tolerance- 188-189 */ +#define SFF_8636_WAVE_TOL_HIGH_BYTE_OFFSET 0xBC +#define SFF_8636_WAVE_TOL_LOW_BYTE_OFFSET 0xBD + +/* Max case temp - Other than 70 C - 190 */ +#define SFF_8636_MAXCASE_TEMP_OFFSET 0xBE + +/* CC_BASE - 191 */ +#define SFF_8636_CC_BASE_OFFSET 0xBF + +/* Option Values - 192-195 */ +#define SFF_8636_OPTION_1_OFFSET 0xC0 +#define SFF_8636_ETHERNET_UNSPECIFIED 0x00 +#define SFF_8636_ETHERNET_100G_AOC 0x01 +#define SFF_8636_ETHERNET_100G_SR4 0x02 +#define SFF_8636_ETHERNET_100G_LR4 0x03 +#define SFF_8636_ETHERNET_100G_ER4 0x04 +#define SFF_8636_ETHERNET_100G_SR10 0x05 +#define SFF_8636_ETHERNET_100G_CWDM4_FEC 0x06 +#define SFF_8636_ETHERNET_100G_PSM4 0x07 +#define SFF_8636_ETHERNET_100G_ACC 0x08 +#define SFF_8636_ETHERNET_100G_CWDM4_NO_FEC 0x09 +#define SFF_8636_ETHERNET_100G_RSVD1 0x0A +#define SFF_8636_ETHERNET_100G_CR4 0x0B +#define SFF_8636_ETHERNET_25G_CR_CA_S 0x0C +#define SFF_8636_ETHERNET_25G_CR_CA_N 0x0D +#define SFF_8636_ETHERNET_40G_ER4 0x10 +#define SFF_8636_ETHERNET_4X10_SR 0x11 +#define SFF_8636_ETHERNET_40G_PSM4 0x12 +#define SFF_8636_ETHERNET_G959_P1I1_2D1 0x13 +#define SFF_8636_ETHERNET_G959_P1S1_2D2 0x14 +#define SFF_8636_ETHERNET_G959_P1L1_2D2 0x15 +#define SFF_8636_ETHERNET_10GT_SFI 0x16 +#define SFF_8636_ETHERNET_100G_CLR4 0x17 +#define SFF_8636_ETHERNET_100G_AOC2 0x18 +#define SFF_8636_ETHERNET_100G_ACC2 0x19 + +#define SFF_8636_OPTION_2_OFFSET 0xC1 +/* Rx output amplitude */ +#define SFF_8636_O2_RX_OUTPUT_AMP (1 << 0) +#define SFF_8636_OPTION_3_OFFSET 0xC2 +/* Rx Squelch Disable */ +#define SFF_8636_O3_RX_SQL_DSBL (1 << 3) +/* Rx Output Disable capable */ +#define SFF_8636_O3_RX_OUTPUT_DSBL (1 << 2) +/* Tx Squelch Disable */ +#define SFF_8636_O3_TX_SQL_DSBL (1 << 1) +/* Tx Squelch Impl */ +#define SFF_8636_O3_TX_SQL_IMPL (1 << 0) +#define SFF_8636_OPTION_4_OFFSET 0xC3 +/* Memory Page 02 present */ +#define SFF_8636_O4_PAGE_02_PRESENT (1 << 7) +/* Memory Page 01 present */ +#define SFF_8636_O4_PAGE_01_PRESENT (1 << 6) +/* Rate Select implemented */ +#define SFF_8636_O4_RATE_SELECT (1 << 5) +/* Tx_DISABLE implemented */ +#define SFF_8636_O4_TX_DISABLE (1 << 4) +/* Tx_FAULT implemented */ +#define SFF_8636_O4_TX_FAULT (1 << 3) +/* Tx Squelch implemented */ +#define SFF_8636_O4_TX_SQUELCH (1 << 2) +/* Tx Loss of Signal */ +#define SFF_8636_O4_TX_LOS (1 << 1) + +/* Vendor SN - 196-211 */ +#define SFF_8636_VENDOR_SN_START_OFFSET 0xC4 +#define SFF_8636_VENDOR_SN_END_OFFSET 0xD3 + +/* Vendor Date - 212-219 */ +#define SFF_8636_DATE_YEAR_OFFSET 0xD4 +#define SFF_8636_DATE_YEAR_LEN 2 +#define SFF_8636_DATE_MONTH_OFFSET 0xD6 +#define SFF_8636_DATE_MONTH_LEN 2 +#define SFF_8636_DATE_DAY_OFFSET 0xD8 +#define SFF_8636_DATE_DAY_LEN 2 +#define SFF_8636_DATE_VENDOR_LOT_OFFSET 0xDA +#define SFF_8636_DATE_VENDOR_LOT_LEN 2 + +/* Diagnostic Monitoring Type - 220 */ +#define SFF_8636_DIAG_TYPE_OFFSET 0xDC +#define SFF_8636_RX_PWR_TYPE_MASK 0x8 +#define SFF_8636_RX_PWR_TYPE_AVG_PWR (1 << 3) +#define SFF_8636_RX_PWR_TYPE_OMA (0 << 3) +#define SFF_8636_TX_PWR_TYPE_MASK 0x4 +#define SFF_8636_TX_PWR_TYPE_AVG_PWR (1 << 2) + +/* Enhanced Options - 221 */ +#define SFF_8636_ENH_OPTIONS_OFFSET 0xDD +#define SFF_8636_RATE_SELECT_EXT_SUPPORT (1 << 3) +#define SFF_8636_RATE_SELECT_APP_TABLE_SUPPORT (1 << 2) + +/* Check code - 223 */ +#define SFF_8636_CC_EXT_OFFSET 0xDF +#define SFF_8636_CC_EXT_LEN 1 + +/*------------------------------------------------------------------------------ + * + * Upper Memory Page 03h + * Contains module thresholds, channel thresholds and masks, + * and optional channel controls + * + * Offset - Page Num(3) * PageSize(0x80) + Page offset + */ + +/* Module Thresholds (48 Bytes) 128-175 */ +/* MSB at low address, LSB at high address */ +#define SFF_8636_TEMP_HALRM 0x200 +#define SFF_8636_TEMP_LALRM 0x202 +#define SFF_8636_TEMP_HWARN 0x204 +#define SFF_8636_TEMP_LWARN 0x206 + +#define SFF_8636_VCC_HALRM 0x210 +#define SFF_8636_VCC_LALRM 0x212 +#define SFF_8636_VCC_HWARN 0x214 +#define SFF_8636_VCC_LWARN 0x216 + +#define SFF_8636_RX_PWR_HALRM 0x230 +#define SFF_8636_RX_PWR_LALRM 0x232 +#define SFF_8636_RX_PWR_HWARN 0x234 +#define SFF_8636_RX_PWR_LWARN 0x236 + +#define SFF_8636_TX_BIAS_HALRM 0x238 +#define SFF_8636_TX_BIAS_LALRM 0x23A +#define SFF_8636_TX_BIAS_HWARN 0x23C +#define SFF_8636_TX_BIAS_LWARN 0x23E + +#define SFF_8636_TX_PWR_HALRM 0x240 +#define SFF_8636_TX_PWR_LALRM 0x242 +#define SFF_8636_TX_PWR_HWARN 0x244 +#define SFF_8636_TX_PWR_LWARN 0x246 + +#define ETH_MODULE_SFF_8636_MAX_LEN 640 +#define ETH_MODULE_SFF_8436_MAX_LEN 640 + +#endif /*SFF_8636_H__ */ -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* RE: [PATCH v3 0/5] add telemetry command for show module EEPROM 2022-04-20 7:00 ` [PATCH v3 0/5] add telemetry command for show " Robin Zhang ` (4 preceding siblings ...) 2022-04-20 7:00 ` [PATCH v3 5/5] ethdev: format module EEPROM for SFF-8636 Robin Zhang @ 2022-04-20 8:49 ` Morten Brørup 5 siblings, 0 replies; 77+ messages in thread From: Morten Brørup @ 2022-04-20 8:49 UTC (permalink / raw) To: Robin Zhang, dev Cc: qiming.yang, qi.z.zhang, stevex.yang, thomas, andrew.rybchenko, bruce.richardson, david.marchand > From: Robin Zhang [mailto:robinx.zhang@intel.com] > Sent: Wednesday, 20 April 2022 09.00 > > Introduce a new telemetry command /ethdev/module_eeprom to show module > EEPROM for each port. The format of module EEPROM information follows > the SFF(Small Form Factor) Committee specifications. > > Current the format support SFP(Small Formfactor Pluggable)/SFP+/ > QSFP+(Quad Small Formfactor Pluggable)/QSFP28 with specs SFF-8079/ > SFF-8472/SFF-8024/SFF-8636. > > Afther run the /ethdev/module_eeprom command, both primary application > and telemetry client will show the module EEPROM information. For > primary application, we keep the same format with Linux utility > ethtool, > refer to command 'ethtool -m' of ethtool v5.4. For telemetry client, > we record the key value pairs of each item, then show them in telemetry > client dictionary. This patch uses printf() a lot. It should only collect the data and give the data to the telemetry library, not printf() anything. It is up to the application (which asked the telemetry library for the data) to determine how the data should be presented to the end user. E.g. the application could present the data in an SNMP packet, as the response to an SNMP request received by the application's SNMP agent. The separation of data and presentation is a key point of the telemetry library. -Morten ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v4 0/5] add telemetry command for show module EEPROM 2022-02-15 10:18 [PATCH] app/testpmd: format dump information of module EEPROM Robin Zhang ` (2 preceding siblings ...) 2022-04-20 7:00 ` [PATCH v3 0/5] add telemetry command for show " Robin Zhang @ 2022-04-25 5:34 ` Robin Zhang 2022-04-25 5:34 ` [PATCH v4 1/5] ethdev: add telemetry command for " Robin Zhang ` (4 more replies) 2022-04-26 2:43 ` [PATCH v5 0/5] add telemetry command for show module EEPROM Robin Zhang 4 siblings, 5 replies; 77+ messages in thread From: Robin Zhang @ 2022-04-25 5:34 UTC (permalink / raw) To: dev Cc: qiming.yang, qi.z.zhang, stevex.yang, thomas, andrew.rybchenko, bruce.richardson, david.marchand, Robin Zhang Introduce a new telemetry command /ethdev/module_eeprom to show module EEPROM for each port. The format of module EEPROM information follows the SFF(Small Form Factor) Committee specifications. Current the format support SFP(Small Formfactor Pluggable)/SFP+/ QSFP+(Quad Small Formfactor Pluggable)/QSFP28 with specs SFF-8079/ SFF-8472/SFF-8024/SFF-8636. Afther run the /ethdev/module_eeprom command, telemetry client will show the module EEPROM information. We keep the same information content compare with Linux utility ethtool, refer to command 'ethtool -m' of ethtool v5.4. v4: - remove all printf in primary application, only show information in tememetry client - refine codes v3: - split up codes into several patches for better reivew Robin Zhang (5): ethdev: add telemetry command for module EEPROM ethdev: common utilities for different SFF specs ethdev: format module EEPROM for SFF-8079 ethdev: format module EEPROM for SFF-8472 ethdev: format module EEPROM for SFF-8636 lib/ethdev/ethdev_sff_telemetry.c | 140 ++++++ lib/ethdev/ethdev_sff_telemetry.h | 39 ++ lib/ethdev/meson.build | 5 + lib/ethdev/rte_ethdev.c | 3 + lib/ethdev/sff_8079.c | 407 ++++++++++++++++ lib/ethdev/sff_8472.c | 287 +++++++++++ lib/ethdev/sff_8636.c | 775 ++++++++++++++++++++++++++++++ lib/ethdev/sff_8636.h | 592 +++++++++++++++++++++++ lib/ethdev/sff_common.c | 326 +++++++++++++ lib/ethdev/sff_common.h | 174 +++++++ 10 files changed, 2748 insertions(+) create mode 100644 lib/ethdev/ethdev_sff_telemetry.c create mode 100644 lib/ethdev/ethdev_sff_telemetry.h create mode 100644 lib/ethdev/sff_8079.c create mode 100644 lib/ethdev/sff_8472.c create mode 100644 lib/ethdev/sff_8636.c create mode 100644 lib/ethdev/sff_8636.h create mode 100644 lib/ethdev/sff_common.c create mode 100644 lib/ethdev/sff_common.h -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v4 1/5] ethdev: add telemetry command for module EEPROM 2022-04-25 5:34 ` [PATCH v4 " Robin Zhang @ 2022-04-25 5:34 ` Robin Zhang 2022-04-25 5:34 ` [PATCH v4 2/5] ethdev: common utilities for different SFF specs Robin Zhang ` (3 subsequent siblings) 4 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-04-25 5:34 UTC (permalink / raw) To: dev Cc: qiming.yang, qi.z.zhang, stevex.yang, thomas, andrew.rybchenko, bruce.richardson, david.marchand, Robin Zhang Add a new telemetry command /ethdev/module_eeprom to dump the module EEPROM of each port. The format of module EEPROM information follows the SFF(Small Form Factor) Committee specifications. Current the format support SFP(Small Formfactor Pluggable)/SFP+/ QSFP+(Quad Small Formfactor Pluggable)/QSFP28 with specs SFF-8079/ SFF-8472/SFF-8024/SFF-8636. Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/ethdev_sff_telemetry.c | 129 ++++++++++++++++++++++++++++++ lib/ethdev/ethdev_sff_telemetry.h | 39 +++++++++ lib/ethdev/meson.build | 1 + lib/ethdev/rte_ethdev.c | 3 + 4 files changed, 172 insertions(+) create mode 100644 lib/ethdev/ethdev_sff_telemetry.c create mode 100644 lib/ethdev/ethdev_sff_telemetry.h diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c new file mode 100644 index 0000000000..507571d995 --- /dev/null +++ b/lib/ethdev/ethdev_sff_telemetry.c @@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + */ + +#include <errno.h> + +#include <rte_ethdev.h> +#include <rte_common.h> +#include "ethdev_sff_telemetry.h" + +static void +sff_port_module_eeprom_display(uint16_t port_id, struct sff_item *items) +{ + struct rte_eth_dev_module_info minfo; + struct rte_dev_eeprom_info einfo; + int ret; + + ret = rte_eth_dev_get_module_info(port_id, &minfo); + if (ret != 0) { + switch (ret) { + case -ENODEV: + RTE_ETHDEV_LOG(ERR, "port index %d invalid\n", port_id); + break; + case -ENOTSUP: + RTE_ETHDEV_LOG(ERR, "operation not supported by device\n"); + break; + case -EIO: + RTE_ETHDEV_LOG(ERR, "device is removed\n"); + break; + default: + RTE_ETHDEV_LOG(ERR, "Unable to get port %d EEPROM module info\n", ret); + break; + } + return; + } + + einfo.offset = 0; + einfo.length = minfo.eeprom_len; + einfo.data = calloc(1, minfo.eeprom_len); + if (einfo.data == NULL) { + RTE_ETHDEV_LOG(ERR, "Allocation of port %u eeprom data failed\n", port_id); + return; + } + + ret = rte_eth_dev_get_module_eeprom(port_id, &einfo); + if (ret != 0) { + switch (ret) { + case -ENODEV: + RTE_ETHDEV_LOG(ERR, "port index %d invalid\n", port_id); + break; + case -ENOTSUP: + RTE_ETHDEV_LOG(ERR, "operation not supported by device\n"); + break; + case -EIO: + RTE_ETHDEV_LOG(ERR, "device is removed\n"); + break; + default: + RTE_ETHDEV_LOG(ERR, "Unable to get port %d module EEPROM\n", ret); + break; + } + free(einfo.data); + return; + } + + switch (minfo.type) { + /* parsing module EEPROM data base on different module type */ + default: + RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); + break; + } + + free(einfo.data); +} + +void +add_item_string(struct sff_item *items, const char *name_str, const char *value_str) +{ + /* append different values for same keys */ + if (sff_item_count > 0 && + (strcmp(items[sff_item_count - 1].name, name_str) == 0)) { + strlcat(items[sff_item_count - 1].value, "; ", SFF_ITEM_VALUE_SIZE); + strlcat(items[sff_item_count - 1].value, value_str, SFF_ITEM_VALUE_SIZE); + return; + } + + snprintf(items[sff_item_count].name, SFF_ITEM_NAME_SIZE, "%s", name_str); + snprintf(items[sff_item_count].value, SFF_ITEM_VALUE_SIZE, "%s", value_str); + sff_item_count++; +} + +int +eth_dev_handle_port_module_eeprom(const char *cmd __rte_unused, const char *params, + struct rte_tel_data *d) +{ + char *end_param; + int port_id, i; + struct sff_item *items; + sff_item_count = 0; + + if (params == NULL || strlen(params) == 0 || !isdigit(*params)) + return -1; + + errno = 0; + port_id = strtoul(params, &end_param, 0); + + if (errno != 0) { + RTE_ETHDEV_LOG(ERR, "Invalid argument\n"); + return -1; + } + + if (*end_param != '\0') + RTE_ETHDEV_LOG(NOTICE, + "Extra parameters passed to ethdev telemetry command, ignoring"); + + items = calloc(1, sizeof(struct sff_item) * SFF_ITEM_MAX_COUNT); + if (items == NULL) { + RTE_ETHDEV_LOG(ERR, "Error allocating memory of items\n"); + return -1; + } + + sff_port_module_eeprom_display(port_id, items); + + rte_tel_data_start_dict(d); + for (i = 0; i < sff_item_count; i++) + rte_tel_data_add_dict_string(d, items[i].name, items[i].value); + + free(items); + return 0; +} diff --git a/lib/ethdev/ethdev_sff_telemetry.h b/lib/ethdev/ethdev_sff_telemetry.h new file mode 100644 index 0000000000..0134fe2b5f --- /dev/null +++ b/lib/ethdev/ethdev_sff_telemetry.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + */ + +#ifndef _ETHDEV_SFF_TELEMETRY_H_ +#define _ETHDEV_SFF_TELEMETRY_H_ + +#include <rte_telemetry.h> + +#define ARRAY_SIZE(arr) RTE_DIM(arr) + +#define SFF_ITEM_NAME_SIZE 64 +#define SFF_ITEM_VALUE_SIZE 256 +#define SFF_ITEM_MAX_COUNT 256 +#define SFF_ITEM_VAL_COMPOSE_SIZE 64 + +struct sff_item { + char name[SFF_ITEM_NAME_SIZE]; /* The item name. */ + char value[SFF_ITEM_VALUE_SIZE]; /* The item value. */ +}; + +uint16_t sff_item_count; + +/* SFF-8079 Optics diagnostics */ +void sff_8079_show_all(const uint8_t *data, struct sff_item *items); + +/* SFF-8472 Optics diagnostics */ +void sff_8472_show_all(const uint8_t *data, struct sff_item *items); + +/* SFF-8636 Optics diagnostics */ +void sff_8636_show_all(const uint8_t *data, uint32_t eeprom_len, struct sff_item *items); + +int eth_dev_handle_port_module_eeprom(const char *cmd __rte_unused, + const char *params, + struct rte_tel_data *d); + +void add_item_string(struct sff_item *items, const char *name_str, const char *value_str); + +#endif /* _ETHDEV_SFF_TELEMETRY_H_ */ diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index a094585bf7..49c77acb3f 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -11,6 +11,7 @@ sources = files( 'rte_flow.c', 'rte_mtr.c', 'rte_tm.c', + 'ethdev_sff_telemetry.c', ) headers = files( diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c index 29a3d80466..2b87df1b32 100644 --- a/lib/ethdev/rte_ethdev.c +++ b/lib/ethdev/rte_ethdev.c @@ -39,6 +39,7 @@ #include "ethdev_driver.h" #include "ethdev_profile.h" #include "ethdev_private.h" +#include "ethdev_sff_telemetry.h" struct rte_eth_dev rte_eth_devices[RTE_MAX_ETHPORTS]; @@ -5876,4 +5877,6 @@ RTE_INIT(ethdev_init_telemetry) "Returns the link status for a port. Parameters: int port_id"); rte_telemetry_register_cmd("/ethdev/info", eth_dev_handle_port_info, "Returns the device info for a port. Parameters: int port_id"); + rte_telemetry_register_cmd("/ethdev/module_eeprom", eth_dev_handle_port_module_eeprom, + "Returns module EEPROM info with SFF specs. Parameters: int port_id"); } -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v4 2/5] ethdev: common utilities for different SFF specs 2022-04-25 5:34 ` [PATCH v4 " Robin Zhang 2022-04-25 5:34 ` [PATCH v4 1/5] ethdev: add telemetry command for " Robin Zhang @ 2022-04-25 5:34 ` Robin Zhang 2022-04-25 5:34 ` [PATCH v4 3/5] ethdev: format module EEPROM for SFF-8079 Robin Zhang ` (2 subsequent siblings) 4 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-04-25 5:34 UTC (permalink / raw) To: dev Cc: qiming.yang, qi.z.zhang, stevex.yang, thomas, andrew.rybchenko, bruce.richardson, david.marchand, Robin Zhang This patch implements SFF-8024 Rev 4.0 of pluggable I/O configuration and some common utilities for SFF-8436/8636 and SFF-8472/8079. Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/meson.build | 1 + lib/ethdev/sff_common.c | 326 ++++++++++++++++++++++++++++++++++++++++ lib/ethdev/sff_common.h | 174 +++++++++++++++++++++ 3 files changed, 501 insertions(+) create mode 100644 lib/ethdev/sff_common.c create mode 100644 lib/ethdev/sff_common.h diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index 49c77acb3f..8f39739e43 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -12,6 +12,7 @@ sources = files( 'rte_mtr.c', 'rte_tm.c', 'ethdev_sff_telemetry.c', + 'sff_common.c', ) headers = files( diff --git a/lib/ethdev/sff_common.c b/lib/ethdev/sff_common.c new file mode 100644 index 0000000000..c9a0227205 --- /dev/null +++ b/lib/ethdev/sff_common.c @@ -0,0 +1,326 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8024 Rev 4.0 of pluggable I/O configuration and some + * common utilities for SFF-8436/8636 and SFF-8472/8079 + * + */ + +#include <stdio.h> +#include <math.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "ethdev_sff_telemetry.h" + + +double convert_mw_to_dbm(double mw) +{ + return (10. * log10(mw / 1000.)) + 30.; +} + +void sff_show_value_with_unit(const uint8_t *data, unsigned int reg, + const char *name, unsigned int mult, + const char *unit, struct sff_item *items) +{ + unsigned int val = data[reg]; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "%u%s", val * mult, unit); + add_item_string(items, name, val_string); +} + +void sff_show_ascii(const uint8_t *data, unsigned int first_reg, + unsigned int last_reg, const char *name, struct sff_item *items) +{ + unsigned int reg, val; + char tmp[3]; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + memset(val_string, 0, sizeof(val_string)); + + while (first_reg <= last_reg && data[last_reg] == ' ') + last_reg--; + for (reg = first_reg; reg <= last_reg; reg++) { + val = data[reg]; + if ((val >= 32) && (val <= 126)) { + snprintf(tmp, sizeof(tmp), "%c", val); + strlcat(val_string, tmp, sizeof(val_string)); + } else { + strlcat(val_string, "_", sizeof(val_string)); + } + } + add_item_string(items, name, val_string); +} + +void sff_8024_show_oui(const uint8_t *data, int id_offset, struct sff_item *items) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "%02x:%02x:%02x", + data[id_offset], data[(id_offset) + 1], data[(id_offset) + 2]); + add_item_string(items, "Vendor OUI", val_string); +} + +void sff_8024_show_identifier(const uint8_t *data, int id_offset, struct sff_item *items) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[id_offset]); + + switch (data[id_offset]) { + case SFF_8024_ID_UNKNOWN: + strlcat(val_string, " (no module present, unknown, or unspecified)", + sizeof(val_string)); + break; + case SFF_8024_ID_GBIC: + strlcat(val_string, " (GBIC)", sizeof(val_string)); + break; + case SFF_8024_ID_SOLDERED_MODULE: + strlcat(val_string, " (module soldered to motherboard)", sizeof(val_string)); + break; + case SFF_8024_ID_SFP: + strlcat(val_string, " (SFP)", sizeof(val_string)); + break; + case SFF_8024_ID_300_PIN_XBI: + strlcat(val_string, " (300 pin XBI)", sizeof(val_string)); + break; + case SFF_8024_ID_XENPAK: + strlcat(val_string, " (XENPAK)", sizeof(val_string)); + break; + case SFF_8024_ID_XFP: + strlcat(val_string, " (XFP)", sizeof(val_string)); + break; + case SFF_8024_ID_XFF: + strlcat(val_string, " (XFF)", sizeof(val_string)); + break; + case SFF_8024_ID_XFP_E: + strlcat(val_string, " (XFP-E)", sizeof(val_string)); + break; + case SFF_8024_ID_XPAK: + strlcat(val_string, " (XPAK)", sizeof(val_string)); + break; + case SFF_8024_ID_X2: + strlcat(val_string, " (X2)", sizeof(val_string)); + break; + case SFF_8024_ID_DWDM_SFP: + strlcat(val_string, " (DWDM-SFP)", sizeof(val_string)); + break; + case SFF_8024_ID_QSFP: + strlcat(val_string, " (QSFP)", sizeof(val_string)); + break; + case SFF_8024_ID_QSFP_PLUS: + strlcat(val_string, " (QSFP+)", sizeof(val_string)); + break; + case SFF_8024_ID_CXP: + strlcat(val_string, " (CXP)", sizeof(val_string)); + break; + case SFF_8024_ID_HD4X: + strlcat(val_string, " (Shielded Mini Multilane HD 4X)", sizeof(val_string)); + break; + case SFF_8024_ID_HD8X: + strlcat(val_string, " (Shielded Mini Multilane HD 8X)", sizeof(val_string)); + break; + case SFF_8024_ID_QSFP28: + strlcat(val_string, " (QSFP28)", sizeof(val_string)); + break; + case SFF_8024_ID_CXP2: + strlcat(val_string, " (CXP2/CXP28)", sizeof(val_string)); + break; + case SFF_8024_ID_CDFP: + strlcat(val_string, " (CDFP Style 1/Style 2)", sizeof(val_string)); + break; + case SFF_8024_ID_HD4X_FANOUT: + strlcat(val_string, " (Shielded Mini Multilane HD 4X Fanout Cable)", + sizeof(val_string)); + break; + case SFF_8024_ID_HD8X_FANOUT: + strlcat(val_string, " (Shielded Mini Multilane HD 8X Fanout Cable)", + sizeof(val_string)); + break; + case SFF_8024_ID_CDFP_S3: + strlcat(val_string, " (CDFP Style 3)", sizeof(val_string)); + break; + case SFF_8024_ID_MICRO_QSFP: + strlcat(val_string, " (microQSFP)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + add_item_string(items, "Identifier", val_string); +} + +void sff_8024_show_connector(const uint8_t *data, int ctor_offset, struct sff_item *items) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[ctor_offset]); + + switch (data[ctor_offset]) { + case SFF_8024_CTOR_UNKNOWN: + strlcat(val_string, " (unknown or unspecified)", sizeof(val_string)); + break; + case SFF_8024_CTOR_SC: + strlcat(val_string, " (SC)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FC_STYLE_1: + strlcat(val_string, " (Fibre Channel Style 1 copper)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FC_STYLE_2: + strlcat(val_string, " (Fibre Channel Style 2 copper)", sizeof(val_string)); + break; + case SFF_8024_CTOR_BNC_TNC: + strlcat(val_string, " (BNC/TNC)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FC_COAX: + strlcat(val_string, " (Fibre Channel coaxial headers)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FIBER_JACK: + strlcat(val_string, " (FibreJack)", sizeof(val_string)); + break; + case SFF_8024_CTOR_LC: + strlcat(val_string, " (LC)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MT_RJ: + strlcat(val_string, " (MT-RJ)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MU: + strlcat(val_string, " (MU)", sizeof(val_string)); + break; + case SFF_8024_CTOR_SG: + strlcat(val_string, " (SG)", sizeof(val_string)); + break; + case SFF_8024_CTOR_OPT_PT: + strlcat(val_string, " (Optical pigtail)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MPO: + strlcat(val_string, " (MPO Parallel Optic)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MPO_2: + strlcat(val_string, " (MPO Parallel Optic - 2x16)", sizeof(val_string)); + break; + case SFF_8024_CTOR_HSDC_II: + strlcat(val_string, " (HSSDC II)", sizeof(val_string)); + break; + case SFF_8024_CTOR_COPPER_PT: + strlcat(val_string, " (Copper pigtail)", sizeof(val_string)); + break; + case SFF_8024_CTOR_RJ45: + strlcat(val_string, " (RJ45)", sizeof(val_string)); + break; + case SFF_8024_CTOR_NO_SEPARABLE: + strlcat(val_string, " (No separable connector)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MXC_2x16: + strlcat(val_string, " (MXC 2x16)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + add_item_string(items, "Connector", val_string); +} + +void sff_8024_show_encoding(const uint8_t *data, int encoding_offset, + int sff_type, struct sff_item *items) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[encoding_offset]); + + switch (data[encoding_offset]) { + case SFF_8024_ENCODING_UNSPEC: + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_8B10B: + strlcat(val_string, " (8B/10B)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_4B5B: + strlcat(val_string, " (4B/5B)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_NRZ: + strlcat(val_string, " (NRZ)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_4h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) + strlcat(val_string, " (Manchester)", sizeof(val_string)); + else if (sff_type == RTE_ETH_MODULE_SFF_8636) + strlcat(val_string, " (SONET Scrambled)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_5h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) + strlcat(val_string, " (SONET Scrambled)", sizeof(val_string)); + else if (sff_type == RTE_ETH_MODULE_SFF_8636) + strlcat(val_string, " (64B/66B)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_6h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) + strlcat(val_string, " (64B/66B)", sizeof(val_string)); + else if (sff_type == RTE_ETH_MODULE_SFF_8636) + strlcat(val_string, " (Manchester)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_256B: + strlcat(val_string, + " ((256B/257B (transcoded FEC-enabled data))", sizeof(val_string)); + break; + case SFF_8024_ENCODING_PAM4: + strlcat(val_string, " (PAM4)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + add_item_string(items, "Encoding", val_string); +} + +void sff_show_thresholds(struct sff_diags sd, struct sff_item *items) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + SPRINT_BIAS(val_string, sd.bias_cur[HALRM]); + add_item_string(items, "Laser bias current high alarm threshold", val_string); + SPRINT_BIAS(val_string, sd.bias_cur[LALRM]); + add_item_string(items, "Laser bias current low alarm threshold", val_string); + SPRINT_BIAS(val_string, sd.bias_cur[HWARN]); + add_item_string(items, "Laser bias current high warning threshold", val_string); + SPRINT_BIAS(val_string, sd.bias_cur[LWARN]); + add_item_string(items, "Laser bias current low warning threshold", val_string); + + SPRINT_xX_PWR(val_string, sd.tx_power[HALRM]); + add_item_string(items, "Laser output power high alarm threshold", val_string); + SPRINT_xX_PWR(val_string, sd.tx_power[LALRM]); + add_item_string(items, "Laser output power low alarm threshold", val_string); + SPRINT_xX_PWR(val_string, sd.tx_power[HWARN]); + add_item_string(items, "Laser output power high warning threshold", val_string); + SPRINT_xX_PWR(val_string, sd.tx_power[LWARN]); + add_item_string(items, "Laser output power low warning threshold", val_string); + + SPRINT_TEMP(val_string, sd.sfp_temp[HALRM]); + add_item_string(items, "Module temperature high alarm threshold", val_string); + SPRINT_TEMP(val_string, sd.sfp_temp[LALRM]); + add_item_string(items, "Module temperature low alarm threshold", val_string); + SPRINT_TEMP(val_string, sd.sfp_temp[HWARN]); + add_item_string(items, "Module temperature high warning threshold", val_string); + SPRINT_TEMP(val_string, sd.sfp_temp[LWARN]); + add_item_string(items, "Module temperature low warning threshold", val_string); + + SPRINT_VCC(val_string, sd.sfp_voltage[HALRM]); + add_item_string(items, "Module voltage high alarm threshold", val_string); + SPRINT_VCC(val_string, sd.sfp_voltage[LALRM]); + add_item_string(items, "Module voltage low alarm threshold", val_string); + SPRINT_VCC(val_string, sd.sfp_voltage[HWARN]); + add_item_string(items, "Module voltage high warning threshold", val_string); + SPRINT_VCC(val_string, sd.sfp_voltage[LWARN]); + add_item_string(items, "Module voltage low alarm threshold", val_string); + + SPRINT_xX_PWR(val_string, sd.rx_power[HALRM]); + add_item_string(items, "Laser rx power high alarm threshold", val_string); + SPRINT_xX_PWR(val_string, sd.rx_power[LALRM]); + add_item_string(items, "Laser rx power low alarm threshold", val_string); + SPRINT_xX_PWR(val_string, sd.rx_power[HWARN]); + add_item_string(items, "Laser rx power high warning threshold", val_string); + SPRINT_xX_PWR(val_string, sd.rx_power[LWARN]); + add_item_string(items, "Laser rx power low warning threshold", val_string); +} diff --git a/lib/ethdev/sff_common.h b/lib/ethdev/sff_common.h new file mode 100644 index 0000000000..877d5e54e4 --- /dev/null +++ b/lib/ethdev/sff_common.h @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8024 Rev 4.0 of pluggable I/O configuration and some + * common utilities for SFF-8436/8636 and SFF-8472/8079 + * + */ + +#ifndef _SFF_COMMON_H_ +#define _SFF_COMMON_H_ + +#include <stdio.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "ethdev_sff_telemetry.h" + +#define SFF_8024_ID_OFFSET 0x00 +#define SFF_8024_ID_UNKNOWN 0x00 +#define SFF_8024_ID_GBIC 0x01 +#define SFF_8024_ID_SOLDERED_MODULE 0x02 +#define SFF_8024_ID_SFP 0x03 +#define SFF_8024_ID_300_PIN_XBI 0x04 +#define SFF_8024_ID_XENPAK 0x05 +#define SFF_8024_ID_XFP 0x06 +#define SFF_8024_ID_XFF 0x07 +#define SFF_8024_ID_XFP_E 0x08 +#define SFF_8024_ID_XPAK 0x09 +#define SFF_8024_ID_X2 0x0A +#define SFF_8024_ID_DWDM_SFP 0x0B +#define SFF_8024_ID_QSFP 0x0C +#define SFF_8024_ID_QSFP_PLUS 0x0D +#define SFF_8024_ID_CXP 0x0E +#define SFF_8024_ID_HD4X 0x0F +#define SFF_8024_ID_HD8X 0x10 +#define SFF_8024_ID_QSFP28 0x11 +#define SFF_8024_ID_CXP2 0x12 +#define SFF_8024_ID_CDFP 0x13 +#define SFF_8024_ID_HD4X_FANOUT 0x14 +#define SFF_8024_ID_HD8X_FANOUT 0x15 +#define SFF_8024_ID_CDFP_S3 0x16 +#define SFF_8024_ID_MICRO_QSFP 0x17 +#define SFF_8024_ID_LAST SFF_8024_ID_MICRO_QSFP +#define SFF_8024_ID_UNALLOCATED_LAST 0x7F +#define SFF_8024_ID_VENDOR_START 0x80 +#define SFF_8024_ID_VENDOR_LAST 0xFF + +#define SFF_8024_CTOR_UNKNOWN 0x00 +#define SFF_8024_CTOR_SC 0x01 +#define SFF_8024_CTOR_FC_STYLE_1 0x02 +#define SFF_8024_CTOR_FC_STYLE_2 0x03 +#define SFF_8024_CTOR_BNC_TNC 0x04 +#define SFF_8024_CTOR_FC_COAX 0x05 +#define SFF_8024_CTOR_FIBER_JACK 0x06 +#define SFF_8024_CTOR_LC 0x07 +#define SFF_8024_CTOR_MT_RJ 0x08 +#define SFF_8024_CTOR_MU 0x09 +#define SFF_8024_CTOR_SG 0x0A +#define SFF_8024_CTOR_OPT_PT 0x0B +#define SFF_8024_CTOR_MPO 0x0C +#define SFF_8024_CTOR_MPO_2 0x0D +/* 0E-1Fh --- Reserved */ +#define SFF_8024_CTOR_HSDC_II 0x20 +#define SFF_8024_CTOR_COPPER_PT 0x21 +#define SFF_8024_CTOR_RJ45 0x22 +#define SFF_8024_CTOR_NO_SEPARABLE 0x23 +#define SFF_8024_CTOR_MXC_2x16 0x24 +#define SFF_8024_CTOR_LAST SFF_8024_CTOR_MXC_2x16 +#define SFF_8024_CTOR_UNALLOCATED_LAST 0x7F +#define SFF_8024_CTOR_VENDOR_START 0x80 +#define SFF_8024_CTOR_VENDOR_LAST 0xFF + +/* ENCODING Values */ +#define SFF_8024_ENCODING_UNSPEC 0x00 +#define SFF_8024_ENCODING_8B10B 0x01 +#define SFF_8024_ENCODING_4B5B 0x02 +#define SFF_8024_ENCODING_NRZ 0x03 +/* + * Value: 04h + * SFF-8472 - Manchester + * SFF-8436/8636 - SONET Scrambled + */ +#define SFF_8024_ENCODING_4h 0x04 +/* + * Value: 05h + * SFF-8472 - SONET Scrambled + * SFF-8436/8636 - 64B/66B + */ +#define SFF_8024_ENCODING_5h 0x05 +/* + * Value: 06h + * SFF-8472 - 64B/66B + * SFF-8436/8636 - Manchester + */ +#define SFF_8024_ENCODING_6h 0x06 +#define SFF_8024_ENCODING_256B 0x07 +#define SFF_8024_ENCODING_PAM4 0x08 + +/* Most common case: 16-bit unsigned integer in a certain unit */ +#define OFFSET_TO_U16(offset) \ + (data[offset] << 8 | data[(offset) + 1]) + +#define SPRINT_xX_PWR(str, var) \ + snprintf(str, sizeof(str), "%.4f mW / %.2f dBm", \ + (double)((var) / 10000.), \ + convert_mw_to_dbm((double)((var) / 10000.))) + +#define SPRINT_BIAS(str, bias_cur) \ + snprintf(str, sizeof(str), "%.3f mA", (double)(bias_cur / 500.)) + +#define SPRINT_TEMP(str, temp) \ + snprintf(str, sizeof(str), "%.2f degrees C / %.2f degrees F", \ + (double)(temp / 256.), \ + (double)(temp / 256. * 1.8 + 32.)) + +#define SPRINT_VCC(str, sfp_voltage) \ + snprintf(str, sizeof(str), "%.4f V", (double)(sfp_voltage / 10000.)) + +/* Channel Monitoring Fields */ +struct sff_channel_diags { + uint16_t bias_cur; /* Measured bias current in 2uA units */ + uint16_t rx_power; /* Measured RX Power */ + uint16_t tx_power; /* Measured TX Power */ +}; + +/* Module Monitoring Fields */ +struct sff_diags { + +#define MAX_CHANNEL_NUM 4 +#define LWARN 0 +#define HWARN 1 +#define LALRM 2 +#define HALRM 3 +#define MCURR 4 + + /* Supports DOM */ + uint8_t supports_dom; + /* Supports alarm/warning thold */ + uint8_t supports_alarms; + /* RX Power: 0 = OMA, 1 = Average power */ + uint8_t rx_power_type; + /* TX Power: 0 = Not supported, 1 = Average power */ + uint8_t tx_power_type; + + uint8_t calibrated_ext; /* Is externally calibrated */ + /* [5] tables are low/high warn, low/high alarm, current */ + /* SFP voltage in 0.1mV units */ + uint16_t sfp_voltage[5]; + /* SFP Temp in 16-bit signed 1/256 Celcius */ + int16_t sfp_temp[5]; + /* Measured bias current in 2uA units */ + uint16_t bias_cur[5]; + /* Measured TX Power */ + uint16_t tx_power[5]; + /* Measured RX Power */ + uint16_t rx_power[5]; + struct sff_channel_diags scd[MAX_CHANNEL_NUM]; +}; + +double convert_mw_to_dbm(double mw); +void sff_show_value_with_unit(const uint8_t *data, unsigned int reg, + const char *name, unsigned int mult, + const char *unit, struct sff_item *items); +void sff_show_ascii(const uint8_t *data, unsigned int first_reg, + unsigned int last_reg, const char *name, struct sff_item *items); +void sff_show_thresholds(struct sff_diags sd, struct sff_item *items); + +void sff_8024_show_oui(const uint8_t *data, int id_offset, struct sff_item *items); +void sff_8024_show_identifier(const uint8_t *data, int id_offset, struct sff_item *items); +void sff_8024_show_connector(const uint8_t *data, int ctor_offset, struct sff_item *items); +void sff_8024_show_encoding(const uint8_t *data, int encoding_offset, + int sff_type, struct sff_item *items); + +#endif /* _SFF_COMMON_H_ */ -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v4 3/5] ethdev: format module EEPROM for SFF-8079 2022-04-25 5:34 ` [PATCH v4 " Robin Zhang 2022-04-25 5:34 ` [PATCH v4 1/5] ethdev: add telemetry command for " Robin Zhang 2022-04-25 5:34 ` [PATCH v4 2/5] ethdev: common utilities for different SFF specs Robin Zhang @ 2022-04-25 5:34 ` Robin Zhang 2022-04-25 5:34 ` [PATCH v4 4/5] ethdev: format module EEPROM for SFF-8472 Robin Zhang 2022-04-25 5:34 ` [PATCH v4 5/5] ethdev: format module EEPROM for SFF-8636 Robin Zhang 4 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-04-25 5:34 UTC (permalink / raw) To: dev Cc: qiming.yang, qi.z.zhang, stevex.yang, thomas, andrew.rybchenko, bruce.richardson, david.marchand, Robin Zhang This patch implements format module EEPROM information for SFF-8079 Rev 1.7 Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/ethdev_sff_telemetry.c | 3 + lib/ethdev/meson.build | 1 + lib/ethdev/sff_8079.c | 407 ++++++++++++++++++++++++++++++ 3 files changed, 411 insertions(+) create mode 100644 lib/ethdev/sff_8079.c diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c index 507571d995..aa1e859068 100644 --- a/lib/ethdev/ethdev_sff_telemetry.c +++ b/lib/ethdev/ethdev_sff_telemetry.c @@ -64,6 +64,9 @@ sff_port_module_eeprom_display(uint16_t port_id, struct sff_item *items) switch (minfo.type) { /* parsing module EEPROM data base on different module type */ + case RTE_ETH_MODULE_SFF_8079: + sff_8079_show_all(einfo.data, items); + break; default: RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); break; diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index 8f39739e43..d94860da0c 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -13,6 +13,7 @@ sources = files( 'rte_tm.c', 'ethdev_sff_telemetry.c', 'sff_common.c', + 'sff_8079.c', ) headers = files( diff --git a/lib/ethdev/sff_8079.c b/lib/ethdev/sff_8079.c new file mode 100644 index 0000000000..b6736da29e --- /dev/null +++ b/lib/ethdev/sff_8079.c @@ -0,0 +1,407 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8079 optics diagnostics. + * + */ + +#include <stdio.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "ethdev_sff_telemetry.h" + +static void sff_8079_show_identifier(const uint8_t *data, struct sff_item *items) +{ + sff_8024_show_identifier(data, 0, items); +} + +static void sff_8079_show_ext_identifier(const uint8_t *data, struct sff_item *items) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[1]); + if (data[1] == 0x00) + strlcat(val_string, " (GBIC not specified / not MOD_DEF compliant)", + sizeof(val_string)); + else if (data[1] == 0x04) + strlcat(val_string, " (GBIC/SFP defined by 2-wire interface ID)", + sizeof(val_string)); + else if (data[1] <= 0x07) { + char tmp[SFF_ITEM_VAL_COMPOSE_SIZE]; + snprintf(tmp, sizeof(tmp), " (GBIC compliant with MOD_DEF %u)", data[1]); + strlcat(val_string, tmp, sizeof(val_string)); + } else + strlcat(val_string, " (unknown)", sizeof(val_string)); + add_item_string(items, "Extended identifier", val_string); +} + +static void sff_8079_show_connector(const uint8_t *data, struct sff_item *items) +{ + sff_8024_show_connector(data, 2, items); +} + +static void sff_8079_show_transceiver(const uint8_t *data, struct sff_item *items) +{ + static const char *name = "Transceiver type"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), + "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[36]); + add_item_string(items, "Transceiver codes", val_string); + + /* 10G Ethernet Compliance Codes */ + if (data[3] & (1 << 7)) + add_item_string(items, "10G Ethernet transceiver type", + "10G Ethernet: 10G Base-ER [SFF-8472 rev10.4 onwards]"); + if (data[3] & (1 << 6)) + add_item_string(items, name, "10G Ethernet: 10G Base-LRM"); + if (data[3] & (1 << 5)) + add_item_string(items, name, "10G Ethernet: 10G Base-LR"); + if (data[3] & (1 << 4)) + add_item_string(items, name, "10G Ethernet: 10G Base-SR"); + + /* Infiniband Compliance Codes */ + if (data[3] & (1 << 3)) + add_item_string(items, name, "Infiniband: 1X SX"); + if (data[3] & (1 << 2)) + add_item_string(items, name, "Infiniband: 1X LX"); + if (data[3] & (1 << 1)) + add_item_string(items, name, "Infiniband: 1X Copper Active"); + if (data[3] & (1 << 0)) + add_item_string(items, name, "Infiniband: 1X Copper Passive"); + + /* ESCON Compliance Codes */ + if (data[4] & (1 << 7)) + add_item_string(items, name, "ESCON: ESCON MMF, 1310nm LED"); + if (data[4] & (1 << 6)) + add_item_string(items, name, "ESCON: ESCON SMF, 1310nm Laser"); + + /* SONET Compliance Codes */ + if (data[4] & (1 << 5)) + add_item_string(items, name, "SONET: OC-192, short reach"); + if (data[4] & (1 << 4)) + add_item_string(items, name, "SONET: SONET reach specifier bit 1"); + if (data[4] & (1 << 3)) + add_item_string(items, name, "SONET: SONET reach specifier bit 2"); + if (data[4] & (1 << 2)) + add_item_string(items, name, "SONET: OC-48, long reach"); + if (data[4] & (1 << 1)) + add_item_string(items, name, "SONET: OC-48, intermediate reach"); + if (data[4] & (1 << 0)) + add_item_string(items, name, "SONET: OC-48, short reach"); + if (data[5] & (1 << 6)) + add_item_string(items, name, "SONET: OC-12, single mode, long reach"); + if (data[5] & (1 << 5)) + add_item_string(items, name, "SONET: OC-12, single mode, inter. reach"); + if (data[5] & (1 << 4)) + add_item_string(items, name, "SONET: OC-12, short reach"); + if (data[5] & (1 << 2)) + add_item_string(items, name, "SONET: OC-3, single mode, long reach"); + if (data[5] & (1 << 1)) + add_item_string(items, name, "SONET: OC-3, single mode, inter. reach"); + if (data[5] & (1 << 0)) + add_item_string(items, name, "SONET: OC-3, short reach"); + + /* Ethernet Compliance Codes */ + if (data[6] & (1 << 7)) + add_item_string(items, name, "Ethernet: BASE-PX"); + if (data[6] & (1 << 6)) + add_item_string(items, name, "Ethernet: BASE-BX10"); + if (data[6] & (1 << 5)) + add_item_string(items, name, "Ethernet: 100BASE-FX"); + if (data[6] & (1 << 4)) + add_item_string(items, name, "Ethernet: 100BASE-LX/LX10"); + if (data[6] & (1 << 3)) + add_item_string(items, name, "Ethernet: 1000BASE-T"); + if (data[6] & (1 << 2)) + add_item_string(items, name, "Ethernet: 1000BASE-CX"); + if (data[6] & (1 << 1)) + add_item_string(items, name, "Ethernet: 1000BASE-LX"); + if (data[6] & (1 << 0)) + add_item_string(items, name, "Ethernet: 1000BASE-SX"); + + /* Fibre Channel link length */ + if (data[7] & (1 << 7)) + add_item_string(items, name, "FC: very long distance (V)"); + if (data[7] & (1 << 6)) + add_item_string(items, name, "FC: short distance (S)"); + if (data[7] & (1 << 5)) + add_item_string(items, name, "FC: intermediate distance (I)"); + if (data[7] & (1 << 4)) + add_item_string(items, name, "FC: long distance (L)"); + if (data[7] & (1 << 3)) + add_item_string(items, name, "FC: medium distance (M)"); + + /* Fibre Channel transmitter technology */ + if (data[7] & (1 << 2)) + add_item_string(items, name, "FC: Shortwave laser, linear Rx (SA)"); + if (data[7] & (1 << 1)) + add_item_string(items, name, "FC: Longwave laser (LC)"); + if (data[7] & (1 << 0)) + add_item_string(items, name, "FC: Electrical inter-enclosure (EL)"); + if (data[8] & (1 << 7)) + add_item_string(items, name, "FC: Electrical intra-enclosure (EL)"); + if (data[8] & (1 << 6)) + add_item_string(items, name, "FC: Shortwave laser w/o OFC (SN)"); + if (data[8] & (1 << 5)) + add_item_string(items, name, "FC: Shortwave laser with OFC (SL)"); + if (data[8] & (1 << 4)) + add_item_string(items, name, "FC: Longwave laser (LL)"); + if (data[8] & (1 << 3)) + add_item_string(items, name, "Active Cable"); + if (data[8] & (1 << 2)) + add_item_string(items, name, "Passive Cable"); + if (data[8] & (1 << 1)) + add_item_string(items, name, "FC: Copper FC-BaseT"); + + /* Fibre Channel transmission media */ + if (data[9] & (1 << 7)) + add_item_string(items, name, "FC: Twin Axial Pair (TW)"); + if (data[9] & (1 << 6)) + add_item_string(items, name, "FC: Twisted Pair (TP)"); + if (data[9] & (1 << 5)) + add_item_string(items, name, "FC: Miniature Coax (MI)"); + if (data[9] & (1 << 4)) + add_item_string(items, name, "FC: Video Coax (TV)"); + if (data[9] & (1 << 3)) + add_item_string(items, name, "FC: Multimode, 62.5um (M6)"); + if (data[9] & (1 << 2)) + add_item_string(items, name, "FC: Multimode, 50um (M5)"); + if (data[9] & (1 << 0)) + add_item_string(items, name, "FC: Single Mode (SM)"); + + /* Fibre Channel speed */ + if (data[10] & (1 << 7)) + add_item_string(items, name, "FC: 1200 MBytes/sec"); + if (data[10] & (1 << 6)) + add_item_string(items, name, "FC: 800 MBytes/sec"); + if (data[10] & (1 << 4)) + add_item_string(items, name, "FC: 400 MBytes/sec"); + if (data[10] & (1 << 2)) + add_item_string(items, name, "FC: 200 MBytes/sec"); + if (data[10] & (1 << 0)) + add_item_string(items, name, "FC: 100 MBytes/sec"); + + /* Extended Specification Compliance Codes from SFF-8024 */ + switch (data[36]) { + case 0x1: + add_item_string(items, name, + "Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)"); + break; + case 0x2: + add_item_string(items, name, "Extended: 100G Base-SR4 or 25GBase-SR"); + break; + case 0x3: + add_item_string(items, name, "Extended: 100G Base-LR4 or 25GBase-LR"); + break; + case 0x4: + add_item_string(items, name, "Extended: 100G Base-ER4 or 25GBase-ER"); + break; + case 0x8: + add_item_string(items, name, + "Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)"); + break; + case 0xb: + add_item_string(items, name, "Extended: 100G Base-CR4 or 25G Base-CR CA-L"); + break; + case 0xc: + add_item_string(items, name, "Extended: 25G Base-CR CA-S"); + break; + case 0xd: + add_item_string(items, name, "Extended: 25G Base-CR CA-N"); + break; + case 0x16: + add_item_string(items, name, "Extended: 10Gbase-T with SFI electrical interface"); + break; + case 0x18: + add_item_string(items, name, + "Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)"); + break; + case 0x19: + add_item_string(items, name, + "Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)"); + break; + case 0x1c: + add_item_string(items, name, "Extended: 10Gbase-T Short Reach"); + break; + default: + break; + } +} + +static void sff_8079_show_encoding(const uint8_t *data, struct sff_item *items) +{ + sff_8024_show_encoding(data, 11, RTE_ETH_MODULE_SFF_8472, items); +} + +static void sff_8079_show_rate_identifier(const uint8_t *data, struct sff_item *items) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[13]); + + switch (data[13]) { + case 0x00: + printf(" (unspecified)\n"); + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case 0x01: + strlcat(val_string, " (4/2/1G Rate_Select & AS0/AS1)", sizeof(val_string)); + break; + case 0x02: + strlcat(val_string, " (8/4/2G Rx Rate_Select only)", sizeof(val_string)); + break; + case 0x03: + strlcat(val_string, " (8/4/2G Independent Rx & Tx Rate_Select)", + sizeof(val_string)); + break; + case 0x04: + strlcat(val_string, " (8/4/2G Tx Rate_Select only)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + add_item_string(items, "Rate identifier", val_string); +} + +static void sff_8079_show_oui(const uint8_t *data, struct sff_item *items) +{ + sff_8024_show_oui(data, 37, items); +} + +static void +sff_8079_show_wavelength_or_copper_compliance(const uint8_t *data, + struct sff_item *items) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + if (data[8] & (1 << 2)) { + snprintf(val_string, sizeof(val_string), "0x%02x", data[60]); + switch (data[60]) { + case 0x00: + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case 0x01: + strlcat(val_string, " (SFF-8431 appendix E)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (unknown)", sizeof(val_string)); + break; + } + strlcat(val_string, " [SFF-8472 rev10.4 only]", sizeof(val_string)); + add_item_string(items, "Passive Cu cmplnce.", val_string); + } else if (data[8] & (1 << 3)) { + snprintf(val_string, sizeof(val_string), "0x%02x", data[60]); + switch (data[60]) { + case 0x00: + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case 0x01: + strlcat(val_string, " (SFF-8431 appendix E)", sizeof(val_string)); + break; + case 0x04: + strlcat(val_string, " (SFF-8431 limiting)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (unknown)", sizeof(val_string)); + break; + } + strlcat(val_string, " [SFF-8472 rev10.4 only]", sizeof(val_string)); + add_item_string(items, "Active Cu cmplnce.", val_string); + } else { + snprintf(val_string, sizeof(val_string), "%unm", (data[60] << 8) | data[61]); + add_item_string(items, "Laser wavelength", val_string); + } +} + +static void sff_8079_show_options(const uint8_t *data, struct sff_item *items) +{ + static const char *name = "Option"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x 0x%02x", data[64], data[65]); + add_item_string(items, "Option values", val_string); + + if (data[65] & (1 << 1)) + add_item_string(items, name, "RX_LOS implemented"); + if (data[65] & (1 << 2)) + add_item_string(items, name, "RX_LOS implemented, inverted"); + if (data[65] & (1 << 3)) + add_item_string(items, name, "TX_FAULT implemented"); + if (data[65] & (1 << 4)) + add_item_string(items, name, "TX_DISABLE implemented"); + if (data[65] & (1 << 5)) + add_item_string(items, name, "RATE_SELECT implemented"); + if (data[65] & (1 << 6)) + add_item_string(items, name, "Tunable transmitter technology"); + if (data[65] & (1 << 7)) + add_item_string(items, name, "Receiver decision threshold implemented"); + if (data[64] & (1 << 0)) + add_item_string(items, name, "Linear receiver output implemented"); + if (data[64] & (1 << 1)) + add_item_string(items, name, "Power level 2 requirement"); + if (data[64] & (1 << 2)) + add_item_string(items, name, "Cooled transceiver implemented"); + if (data[64] & (1 << 3)) + add_item_string(items, name, "Retimer or CDR implemented"); + if (data[64] & (1 << 4)) + add_item_string(items, name, "Paging implemented"); + if (data[64] & (1 << 5)) + add_item_string(items, name, "Power level 3 requirement"); +} + +void sff_8079_show_all(const uint8_t *data, struct sff_item *items) +{ + sff_8079_show_identifier(data, items); + if (((data[0] == 0x02) || (data[0] == 0x03)) && (data[1] == 0x04)) { + unsigned int br_nom, br_min, br_max; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + if (data[12] == 0) { + br_nom = br_min = br_max = 0; + } else if (data[12] == 255) { + br_nom = data[66] * 250; + br_max = data[67]; + br_min = data[67]; + } else { + br_nom = data[12] * 100; + br_max = data[66]; + br_min = data[67]; + } + sff_8079_show_ext_identifier(data, items); + sff_8079_show_connector(data, items); + sff_8079_show_transceiver(data, items); + sff_8079_show_encoding(data, items); + + snprintf(val_string, sizeof(val_string), "%uMBd", br_nom); + add_item_string(items, "BR, Nominal", val_string); + + sff_8079_show_rate_identifier(data, items); + sff_show_value_with_unit(data, 14, + "Length (SMF,km)", 1, "km", items); + sff_show_value_with_unit(data, 15, "Length (SMF)", 100, "m", items); + sff_show_value_with_unit(data, 16, "Length (50um)", 10, "m", items); + sff_show_value_with_unit(data, 17, + "Length (62.5um)", 10, "m", items); + sff_show_value_with_unit(data, 18, "Length (Copper)", 1, "m", items); + sff_show_value_with_unit(data, 19, "Length (OM3)", 10, "m", items); + sff_8079_show_wavelength_or_copper_compliance(data, items); + sff_show_ascii(data, 20, 35, "Vendor name", items); + sff_8079_show_oui(data, items); + sff_show_ascii(data, 40, 55, "Vendor PN", items); + sff_show_ascii(data, 56, 59, "Vendor rev", items); + sff_8079_show_options(data, items); + + snprintf(val_string, sizeof(val_string), "%u%%", br_max); + add_item_string(items, "BR margin, max", val_string); + snprintf(val_string, sizeof(val_string), "%u%%", br_min); + add_item_string(items, "BR margin, min", val_string); + + sff_show_ascii(data, 68, 83, "Vendor SN", items); + sff_show_ascii(data, 84, 91, "Date code", items); + } +} -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v4 4/5] ethdev: format module EEPROM for SFF-8472 2022-04-25 5:34 ` [PATCH v4 " Robin Zhang ` (2 preceding siblings ...) 2022-04-25 5:34 ` [PATCH v4 3/5] ethdev: format module EEPROM for SFF-8079 Robin Zhang @ 2022-04-25 5:34 ` Robin Zhang 2022-04-25 5:34 ` [PATCH v4 5/5] ethdev: format module EEPROM for SFF-8636 Robin Zhang 4 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-04-25 5:34 UTC (permalink / raw) To: dev Cc: qiming.yang, qi.z.zhang, stevex.yang, thomas, andrew.rybchenko, bruce.richardson, david.marchand, Robin Zhang This patch implements format module EEPROM information for SFF-8472 Rev 12.0 Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/ethdev_sff_telemetry.c | 4 + lib/ethdev/meson.build | 1 + lib/ethdev/sff_8472.c | 287 ++++++++++++++++++++++++++++++ 3 files changed, 292 insertions(+) create mode 100644 lib/ethdev/sff_8472.c diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c index aa1e859068..fa93b35275 100644 --- a/lib/ethdev/ethdev_sff_telemetry.c +++ b/lib/ethdev/ethdev_sff_telemetry.c @@ -67,6 +67,10 @@ sff_port_module_eeprom_display(uint16_t port_id, struct sff_item *items) case RTE_ETH_MODULE_SFF_8079: sff_8079_show_all(einfo.data, items); break; + case RTE_ETH_MODULE_SFF_8472: + sff_8079_show_all(einfo.data, items); + sff_8472_show_all(einfo.data, items); + break; default: RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); break; diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index d94860da0c..4d81a35c09 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -14,6 +14,7 @@ sources = files( 'ethdev_sff_telemetry.c', 'sff_common.c', 'sff_8079.c', + 'sff_8472.c', ) headers = files( diff --git a/lib/ethdev/sff_8472.c b/lib/ethdev/sff_8472.c new file mode 100644 index 0000000000..b4869d69c0 --- /dev/null +++ b/lib/ethdev/sff_8472.c @@ -0,0 +1,287 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8472 optics diagnostics. + * + */ + +#include <stdio.h> +#include <math.h> +#include <arpa/inet.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "ethdev_sff_telemetry.h" + +/* Offsets in decimal, for direct comparison with the SFF specs */ + +/* A0-based EEPROM offsets for DOM support checks */ +#define SFF_A0_DOM 92 +#define SFF_A0_OPTIONS 93 +#define SFF_A0_COMP 94 + +/* EEPROM bit values for various registers */ +#define SFF_A0_DOM_EXTCAL (1 << 4) +#define SFF_A0_DOM_INTCAL (1 << 5) +#define SFF_A0_DOM_IMPL (1 << 6) +#define SFF_A0_DOM_PWRT (1 << 3) + +#define SFF_A0_OPTIONS_AW (1 << 7) + +/* + * This is the offset at which the A2 page is in the EEPROM + * blob returned by the kernel. + */ +#define SFF_A2_BASE 0x100 + +/* A2-based offsets for DOM */ +#define SFF_A2_TEMP 96 +#define SFF_A2_TEMP_HALRM 0 +#define SFF_A2_TEMP_LALRM 2 +#define SFF_A2_TEMP_HWARN 4 +#define SFF_A2_TEMP_LWARN 6 + +#define SFF_A2_VCC 98 +#define SFF_A2_VCC_HALRM 8 +#define SFF_A2_VCC_LALRM 10 +#define SFF_A2_VCC_HWARN 12 +#define SFF_A2_VCC_LWARN 14 + +#define SFF_A2_BIAS 100 +#define SFF_A2_BIAS_HALRM 16 +#define SFF_A2_BIAS_LALRM 18 +#define SFF_A2_BIAS_HWARN 20 +#define SFF_A2_BIAS_LWARN 22 + +#define SFF_A2_TX_PWR 102 +#define SFF_A2_TX_PWR_HALRM 24 +#define SFF_A2_TX_PWR_LALRM 26 +#define SFF_A2_TX_PWR_HWARN 28 +#define SFF_A2_TX_PWR_LWARN 30 + +#define SFF_A2_RX_PWR 104 +#define SFF_A2_RX_PWR_HALRM 32 +#define SFF_A2_RX_PWR_LALRM 34 +#define SFF_A2_RX_PWR_HWARN 36 +#define SFF_A2_RX_PWR_LWARN 38 + +#define SFF_A2_ALRM_FLG 112 +#define SFF_A2_WARN_FLG 116 + +/* 32-bit little-endian calibration constants */ +#define SFF_A2_CAL_RXPWR4 56 +#define SFF_A2_CAL_RXPWR3 60 +#define SFF_A2_CAL_RXPWR2 64 +#define SFF_A2_CAL_RXPWR1 68 +#define SFF_A2_CAL_RXPWR0 72 + +/* 16-bit little endian calibration constants */ +#define SFF_A2_CAL_TXI_SLP 76 +#define SFF_A2_CAL_TXI_OFF 78 +#define SFF_A2_CAL_TXPWR_SLP 80 +#define SFF_A2_CAL_TXPWR_OFF 82 +#define SFF_A2_CAL_T_SLP 84 +#define SFF_A2_CAL_T_OFF 86 +#define SFF_A2_CAL_V_SLP 88 +#define SFF_A2_CAL_V_OFF 90 + +static struct sff_8472_aw_flags { + const char *str; /* Human-readable string, null at the end */ + int offset; /* A2-relative address offset */ + uint8_t value; /* Alarm is on if (offset & value) != 0. */ +} sff_8472_aw_flags[] = { + { "Laser bias current high alarm", SFF_A2_ALRM_FLG, (1 << 3) }, + { "Laser bias current low alarm", SFF_A2_ALRM_FLG, (1 << 2) }, + { "Laser bias current high warning", SFF_A2_WARN_FLG, (1 << 3) }, + { "Laser bias current low warning", SFF_A2_WARN_FLG, (1 << 2) }, + + { "Laser output power high alarm", SFF_A2_ALRM_FLG, (1 << 1) }, + { "Laser output power low alarm", SFF_A2_ALRM_FLG, (1 << 0) }, + { "Laser output power high warning", SFF_A2_WARN_FLG, (1 << 1) }, + { "Laser output power low warning", SFF_A2_WARN_FLG, (1 << 0) }, + + { "Module temperature high alarm", SFF_A2_ALRM_FLG, (1 << 7) }, + { "Module temperature low alarm", SFF_A2_ALRM_FLG, (1 << 6) }, + { "Module temperature high warning", SFF_A2_WARN_FLG, (1 << 7) }, + { "Module temperature low warning", SFF_A2_WARN_FLG, (1 << 6) }, + + { "Module voltage high alarm", SFF_A2_ALRM_FLG, (1 << 5) }, + { "Module voltage low alarm", SFF_A2_ALRM_FLG, (1 << 4) }, + { "Module voltage high warning", SFF_A2_WARN_FLG, (1 << 5) }, + { "Module voltage low warning", SFF_A2_WARN_FLG, (1 << 4) }, + + { "Laser rx power high alarm", SFF_A2_ALRM_FLG + 1, (1 << 7) }, + { "Laser rx power low alarm", SFF_A2_ALRM_FLG + 1, (1 << 6) }, + { "Laser rx power high warning", SFF_A2_WARN_FLG + 1, (1 << 7) }, + { "Laser rx power low warning", SFF_A2_WARN_FLG + 1, (1 << 6) }, + + { NULL, 0, 0 }, +}; + +/* Most common case: 16-bit unsigned integer in a certain unit */ +#define A2_OFFSET_TO_U16(offset) \ + (data[SFF_A2_BASE + (offset)] << 8 | data[SFF_A2_BASE + (offset) + 1]) + +/* Calibration slope is a number between 0.0 included and 256.0 excluded. */ +#define A2_OFFSET_TO_SLP(offset) \ + (data[SFF_A2_BASE + (offset)] + data[SFF_A2_BASE + (offset) + 1] / 256.) + +/* Calibration offset is an integer from -32768 to 32767 */ +#define A2_OFFSET_TO_OFF(offset) \ + ((int16_t)A2_OFFSET_TO_U16(offset)) + +/* RXPWR(x) are IEEE-754 floating point numbers in big-endian format */ +#define A2_OFFSET_TO_RXPWRx(offset) \ + (befloattoh((const uint32_t *)(data + SFF_A2_BASE + (offset)))) + +/* + * 2-byte internal temperature conversions: + * First byte is a signed 8-bit integer, which is the temp decimal part + * Second byte are 1/256th of degree, which are added to the dec part. + */ +#define A2_OFFSET_TO_TEMP(offset) ((int16_t)A2_OFFSET_TO_U16(offset)) + +static void sff_8472_dom_parse(const uint8_t *data, struct sff_diags *sd) +{ + sd->bias_cur[MCURR] = A2_OFFSET_TO_U16(SFF_A2_BIAS); + sd->bias_cur[HALRM] = A2_OFFSET_TO_U16(SFF_A2_BIAS_HALRM); + sd->bias_cur[LALRM] = A2_OFFSET_TO_U16(SFF_A2_BIAS_LALRM); + sd->bias_cur[HWARN] = A2_OFFSET_TO_U16(SFF_A2_BIAS_HWARN); + sd->bias_cur[LWARN] = A2_OFFSET_TO_U16(SFF_A2_BIAS_LWARN); + + sd->sfp_voltage[MCURR] = A2_OFFSET_TO_U16(SFF_A2_VCC); + sd->sfp_voltage[HALRM] = A2_OFFSET_TO_U16(SFF_A2_VCC_HALRM); + sd->sfp_voltage[LALRM] = A2_OFFSET_TO_U16(SFF_A2_VCC_LALRM); + sd->sfp_voltage[HWARN] = A2_OFFSET_TO_U16(SFF_A2_VCC_HWARN); + sd->sfp_voltage[LWARN] = A2_OFFSET_TO_U16(SFF_A2_VCC_LWARN); + + sd->tx_power[MCURR] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR); + sd->tx_power[HALRM] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_HALRM); + sd->tx_power[LALRM] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_LALRM); + sd->tx_power[HWARN] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_HWARN); + sd->tx_power[LWARN] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_LWARN); + + sd->rx_power[MCURR] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR); + sd->rx_power[HALRM] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_HALRM); + sd->rx_power[LALRM] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_LALRM); + sd->rx_power[HWARN] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_HWARN); + sd->rx_power[LWARN] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_LWARN); + + sd->sfp_temp[MCURR] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP); + sd->sfp_temp[HALRM] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_HALRM); + sd->sfp_temp[LALRM] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_LALRM); + sd->sfp_temp[HWARN] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_HWARN); + sd->sfp_temp[LWARN] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_LWARN); +} + +/* Converts to a float from a big-endian 4-byte source buffer. */ +static float befloattoh(const uint32_t *source) +{ + union { + uint32_t src; + float dst; + } converter; + + converter.src = ntohl(*source); + return converter.dst; +} + +static void sff_8472_calibration(const uint8_t *data, struct sff_diags *sd) +{ + unsigned long i; + uint16_t rx_reading; + + /* Calibration should occur for all values (threshold and current) */ + for (i = 0; i < ARRAY_SIZE(sd->bias_cur); ++i) { + /* + * Apply calibration formula 1 (Temp., Voltage, Bias, Tx Power) + */ + sd->bias_cur[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_TXI_SLP); + sd->tx_power[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_TXPWR_SLP); + sd->sfp_voltage[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_V_SLP); + sd->sfp_temp[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_T_SLP); + + sd->bias_cur[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_TXI_OFF); + sd->tx_power[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_TXPWR_OFF); + sd->sfp_voltage[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_V_OFF); + sd->sfp_temp[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_T_OFF); + + /* + * Apply calibration formula 2 (Rx Power only) + */ + rx_reading = sd->rx_power[i]; + sd->rx_power[i] = A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR0); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR1); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR2); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR3); + } +} + +static void sff_8472_parse_eeprom(const uint8_t *data, struct sff_diags *sd) +{ + sd->supports_dom = data[SFF_A0_DOM] & SFF_A0_DOM_IMPL; + sd->supports_alarms = data[SFF_A0_OPTIONS] & SFF_A0_OPTIONS_AW; + sd->calibrated_ext = data[SFF_A0_DOM] & SFF_A0_DOM_EXTCAL; + sd->rx_power_type = data[SFF_A0_DOM] & SFF_A0_DOM_PWRT; + + sff_8472_dom_parse(data, sd); + + /* + * If the SFP is externally calibrated, we need to read calibration data + * and compensate the already stored readings. + */ + if (sd->calibrated_ext) + sff_8472_calibration(data, sd); +} + +void sff_8472_show_all(const uint8_t *data, struct sff_item *items) +{ + struct sff_diags sd = {0}; + const char *rx_power_string = NULL; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + int i; + + sff_8472_parse_eeprom(data, &sd); + + if (!sd.supports_dom) { + add_item_string(items, "Optical diagnostics support", "No"); + return; + } + add_item_string(items, "Optical diagnostics support", "Yes"); + + SPRINT_BIAS(val_string, sd.bias_cur[MCURR]); + add_item_string(items, "Laser bias current", val_string); + + SPRINT_xX_PWR(val_string, sd.tx_power[MCURR]); + add_item_string(items, "Laser output power", val_string); + + if (!sd.rx_power_type) + rx_power_string = "Receiver signal OMA"; + else + rx_power_string = "Receiver signal average optical power"; + + SPRINT_xX_PWR(val_string, sd.rx_power[MCURR]); + add_item_string(items, rx_power_string, val_string); + + SPRINT_TEMP(val_string, sd.sfp_temp[MCURR]); + add_item_string(items, "Module temperature", val_string); + + SPRINT_VCC(val_string, sd.sfp_voltage[MCURR]); + add_item_string(items, "Module voltage", val_string); + + add_item_string(items, "Alarm/warning flags implemented", + (sd.supports_alarms ? "Yes" : "No")); + + if (sd.supports_alarms) { + for (i = 0; sff_8472_aw_flags[i].str; ++i) { + add_item_string(items, sff_8472_aw_flags[i].str, + data[SFF_A2_BASE + sff_8472_aw_flags[i].offset] + & sff_8472_aw_flags[i].value ? "On" : "Off"); + } + sff_show_thresholds(sd, items); + } +} -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v4 5/5] ethdev: format module EEPROM for SFF-8636 2022-04-25 5:34 ` [PATCH v4 " Robin Zhang ` (3 preceding siblings ...) 2022-04-25 5:34 ` [PATCH v4 4/5] ethdev: format module EEPROM for SFF-8472 Robin Zhang @ 2022-04-25 5:34 ` Robin Zhang 4 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-04-25 5:34 UTC (permalink / raw) To: dev Cc: qiming.yang, qi.z.zhang, stevex.yang, thomas, andrew.rybchenko, bruce.richardson, david.marchand, Robin Zhang This patch implements format module EEPROM information for SFF-8636 Rev 2.7 Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/ethdev_sff_telemetry.c | 4 + lib/ethdev/meson.build | 1 + lib/ethdev/sff_8636.c | 775 ++++++++++++++++++++++++++++++ lib/ethdev/sff_8636.h | 592 +++++++++++++++++++++++ 4 files changed, 1372 insertions(+) create mode 100644 lib/ethdev/sff_8636.c create mode 100644 lib/ethdev/sff_8636.h diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c index fa93b35275..241ca28743 100644 --- a/lib/ethdev/ethdev_sff_telemetry.c +++ b/lib/ethdev/ethdev_sff_telemetry.c @@ -71,6 +71,10 @@ sff_port_module_eeprom_display(uint16_t port_id, struct sff_item *items) sff_8079_show_all(einfo.data, items); sff_8472_show_all(einfo.data, items); break; + case RTE_ETH_MODULE_SFF_8436: + case RTE_ETH_MODULE_SFF_8636: + sff_8636_show_all(einfo.data, einfo.length, items); + break; default: RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); break; diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index 4d81a35c09..88ceeb12b9 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -15,6 +15,7 @@ sources = files( 'sff_common.c', 'sff_8079.c', 'sff_8472.c', + 'sff_8636.c', ) headers = files( diff --git a/lib/ethdev/sff_8636.c b/lib/ethdev/sff_8636.c new file mode 100644 index 0000000000..290b31e973 --- /dev/null +++ b/lib/ethdev/sff_8636.c @@ -0,0 +1,775 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8636 based QSFP+/QSFP28 Diagnostics Memory map. + * + */ + +#include <stdio.h> +#include <math.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "sff_8636.h" +#include "ethdev_sff_telemetry.h" + +#define MAX_DESC_SIZE 42 + +static struct sff_8636_aw_flags { + const char *str; /* Human-readable string, null at the end */ + int offset; /* A2-relative address offset */ + uint8_t value; /* Alarm is on if (offset & value) != 0. */ +} sff_8636_aw_flags[] = { + { "Laser bias current high alarm (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_HALARM) }, + { "Laser bias current low alarm (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_LALARM) }, + { "Laser bias current high warning (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_HWARN) }, + { "Laser bias current low warning (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_LWARN) }, + + { "Laser bias current high alarm (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_HALARM) }, + { "Laser bias current low alarm (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_LALARM) }, + { "Laser bias current high warning (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_HWARN) }, + { "Laser bias current low warning (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_LWARN) }, + + { "Laser bias current high alarm (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_HALARM) }, + { "Laser bias current low alarm (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_LALARM) }, + { "Laser bias current high warning (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_HWARN) }, + { "Laser bias current low warning (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_LWARN) }, + + { "Laser bias current high alarm (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_HALARM) }, + { "Laser bias current low alarm (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_LALARM) }, + { "Laser bias current high warning (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_HWARN) }, + { "Laser bias current low warning (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_LWARN) }, + + { "Module temperature high alarm", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_HALARM_STATUS) }, + { "Module temperature low alarm", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_LALARM_STATUS) }, + { "Module temperature high warning", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_HWARN_STATUS) }, + { "Module temperature low warning", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_LWARN_STATUS) }, + + { "Module voltage high alarm", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_HALARM_STATUS) }, + { "Module voltage low alarm", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_LALARM_STATUS) }, + { "Module voltage high warning", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_HWARN_STATUS) }, + { "Module voltage low warning", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_LWARN_STATUS) }, + + { "Laser tx power high alarm (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_HALARM) }, + { "Laser tx power low alarm (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_LALARM) }, + { "Laser tx power high warning (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_HWARN) }, + { "Laser tx power low warning (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_LWARN) }, + + { "Laser tx power high alarm (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_HALARM) }, + { "Laser tx power low alarm (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_LALARM) }, + { "Laser tx power high warning (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_HWARN) }, + { "Laser tx power low warning (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_LWARN) }, + + { "Laser tx power high alarm (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_HALARM) }, + { "Laser tx power low alarm (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_LALARM) }, + { "Laser tx power high warning (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_HWARN) }, + { "Laser tx power low warning (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_LWARN) }, + + { "Laser tx power high alarm (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_HALARM) }, + { "Laser tx power low alarm (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_LALARM) }, + { "Laser tx power high warning (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_HWARN) }, + { "Laser tx power low warning (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_LWARN) }, + + { "Laser rx power high alarm (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_HALARM) }, + { "Laser rx power low alarm (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_LALARM) }, + { "Laser rx power high warning (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_HWARN) }, + { "Laser rx power low warning (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_LWARN) }, + + { "Laser rx power high alarm (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_HALARM) }, + { "Laser rx power low alarm (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_LALARM) }, + { "Laser rx power high warning (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_HWARN) }, + { "Laser rx power low warning (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_LWARN) }, + + { "Laser rx power high alarm (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_HALARM) }, + { "Laser rx power low alarm (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_LALARM) }, + { "Laser rx power high warning (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_HWARN) }, + { "Laser rx power low warning (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_LWARN) }, + + { "Laser rx power high alarm (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_HALARM) }, + { "Laser rx power low alarm (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_LALARM) }, + { "Laser rx power high warning (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_HWARN) }, + { "Laser rx power low warning (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_LWARN) }, + + { NULL, 0, 0 }, +}; + +static void sff_8636_show_identifier(const uint8_t *data, struct sff_item *items) +{ + sff_8024_show_identifier(data, SFF_8636_ID_OFFSET, items); +} + +static void sff_8636_show_ext_identifier(const uint8_t *data, struct sff_item *items) +{ + static const char *name = "Extended identifier description"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + snprintf(val_string, sizeof(val_string), "0x%02x", data[SFF_8636_EXT_ID_OFFSET]); + add_item_string(items, "Extended identifier", val_string); + + switch (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_PWR_CLASS_MASK) { + case SFF_8636_EXT_ID_PWR_CLASS_1: + add_item_string(items, name, "1.5W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_2: + add_item_string(items, name, "2.0W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_3: + add_item_string(items, name, "2.5W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_4: + add_item_string(items, name, "3.5W max. Power consumption"); + break; + } + + if (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_CDR_TX_MASK) + add_item_string(items, name, "CDR present in TX"); + else + add_item_string(items, name, "No CDR in TX"); + + if (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_CDR_RX_MASK) + add_item_string(items, name, "CDR present in RX"); + else + add_item_string(items, name, "No CDR in RX"); + + switch (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_EPWR_CLASS_MASK) { + case SFF_8636_EXT_ID_PWR_CLASS_LEGACY: + snprintf(val_string, sizeof(val_string), "%s", ""); + break; + case SFF_8636_EXT_ID_PWR_CLASS_5: + snprintf(val_string, sizeof(val_string), "%s", "4.0W max. Power consumption, "); + break; + case SFF_8636_EXT_ID_PWR_CLASS_6: + snprintf(val_string, sizeof(val_string), "%s", "4.5W max. Power consumption, "); + break; + case SFF_8636_EXT_ID_PWR_CLASS_7: + snprintf(val_string, sizeof(val_string), "%s", "5.0W max. Power consumption, "); + break; + } + + if (data[SFF_8636_PWR_MODE_OFFSET] & SFF_8636_HIGH_PWR_ENABLE) + strlcat(val_string, "High Power Class (> 3.5 W) enabled", sizeof(val_string)); + else + strlcat(val_string, "High Power Class (> 3.5 W) not enabled", sizeof(val_string)); + + add_item_string(items, name, val_string); +} + +static void sff_8636_show_connector(const uint8_t *data, struct sff_item *items) +{ + sff_8024_show_connector(data, SFF_8636_CTOR_OFFSET, items); +} + +static void sff_8636_show_transceiver(const uint8_t *data, struct sff_item *items) +{ + static const char *name = "Transceiver type"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + data[SFF_8636_ETHERNET_COMP_OFFSET], + data[SFF_8636_SONET_COMP_OFFSET], + data[SFF_8636_SAS_COMP_OFFSET], + data[SFF_8636_GIGE_COMP_OFFSET], + data[SFF_8636_FC_LEN_OFFSET], + data[SFF_8636_FC_TECH_OFFSET], + data[SFF_8636_FC_TRANS_MEDIA_OFFSET], + data[SFF_8636_FC_SPEED_OFFSET]); + add_item_string(items, "Transceiver codes", val_string); + + /* 10G/40G Ethernet Compliance Codes */ + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_LRM) + add_item_string(items, name, "10G Ethernet: 10G Base-LRM"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_LR) + add_item_string(items, name, "10G Ethernet: 10G Base-LR"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_SR) + add_item_string(items, name, "10G Ethernet: 10G Base-SR"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_CR4) + add_item_string(items, name, "40G Ethernet: 40G Base-CR4"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_SR4) + add_item_string(items, name, "40G Ethernet: 40G Base-SR4"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_LR4) + add_item_string(items, name, "40G Ethernet: 40G Base-LR4"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_ACTIVE) + add_item_string(items, name, "40G Ethernet: 40G Active Cable (XLPPI)"); + + /* Extended Specification Compliance Codes from SFF-8024 */ + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_RSRVD) { + switch (data[SFF_8636_OPTION_1_OFFSET]) { + case SFF_8636_ETHERNET_UNSPECIFIED: + add_item_string(items, name, "(reserved or unknown)"); + break; + case SFF_8636_ETHERNET_100G_AOC: + add_item_string(items, name, + "100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)"); + break; + case SFF_8636_ETHERNET_100G_SR4: + add_item_string(items, name, + "100G Ethernet: 100G Base-SR4 or 25GBase-SR"); + break; + case SFF_8636_ETHERNET_100G_LR4: + add_item_string(items, name, "100G Ethernet: 100G Base-LR4"); + break; + case SFF_8636_ETHERNET_100G_ER4: + add_item_string(items, name, "100G Ethernet: 100G Base-ER4"); + break; + case SFF_8636_ETHERNET_100G_SR10: + add_item_string(items, name, "100G Ethernet: 100G Base-SR10"); + break; + case SFF_8636_ETHERNET_100G_CWDM4_FEC: + add_item_string(items, name, "100G Ethernet: 100G CWDM4 MSA with FEC"); + break; + case SFF_8636_ETHERNET_100G_PSM4: + add_item_string(items, name, "100G Ethernet: 100G PSM4 Parallel SMF"); + break; + case SFF_8636_ETHERNET_100G_ACC: + add_item_string(items, name, + "100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)"); + break; + case SFF_8636_ETHERNET_100G_CWDM4_NO_FEC: + add_item_string(items, name, + "100G Ethernet: 100G CWDM4 MSA without FEC"); + break; + case SFF_8636_ETHERNET_100G_RSVD1: + add_item_string(items, name, "(reserved or unknown)"); + break; + case SFF_8636_ETHERNET_100G_CR4: + add_item_string(items, name, + "100G Ethernet: 100G Base-CR4 or 25G Base-CR CA-L"); + break; + case SFF_8636_ETHERNET_25G_CR_CA_S: + add_item_string(items, name, "25G Ethernet: 25G Base-CR CA-S"); + break; + case SFF_8636_ETHERNET_25G_CR_CA_N: + add_item_string(items, name, "25G Ethernet: 25G Base-CR CA-N"); + break; + case SFF_8636_ETHERNET_40G_ER4: + add_item_string(items, name, "40G Ethernet: 40G Base-ER4"); + break; + case SFF_8636_ETHERNET_4X10_SR: + add_item_string(items, name, "4x10G Ethernet: 10G Base-SR"); + break; + case SFF_8636_ETHERNET_40G_PSM4: + add_item_string(items, name, "40G Ethernet: 40G PSM4 Parallel SMF"); + break; + case SFF_8636_ETHERNET_G959_P1I1_2D1: + add_item_string(items, name, + "Ethernet: G959.1 profile P1I1-2D1 (10709 MBd, 2km, 1310nm SM)"); + break; + case SFF_8636_ETHERNET_G959_P1S1_2D2: + add_item_string(items, name, + "Ethernet: G959.1 profile P1S1-2D2 (10709 MBd, 40km, 1550nm SM)"); + break; + case SFF_8636_ETHERNET_G959_P1L1_2D2: + add_item_string(items, name, + "Ethernet: G959.1 profile P1L1-2D2 (10709 MBd, 80km, 1550nm SM)"); + break; + case SFF_8636_ETHERNET_10GT_SFI: + add_item_string(items, name, + "10G Ethernet: 10G Base-T with SFI electrical interface"); + break; + case SFF_8636_ETHERNET_100G_CLR4: + add_item_string(items, name, "100G Ethernet: 100G CLR4"); + break; + case SFF_8636_ETHERNET_100G_AOC2: + add_item_string(items, name, + "100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)"); + break; + case SFF_8636_ETHERNET_100G_ACC2: + add_item_string(items, name, + "100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)"); + break; + default: + add_item_string(items, name, "(reserved or unknown)"); + break; + } + } + + /* SONET Compliance Codes */ + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_40G_OTN) + add_item_string(items, name, "40G OTN (OTU3B/OTU3C)"); + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_LR) + add_item_string(items, name, "SONET: OC-48, long reach"); + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_IR) + add_item_string(items, name, "SONET: OC-48, intermediate reach"); + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_SR) + add_item_string(items, name, "SONET: OC-48, short reach"); + + /* SAS/SATA Compliance Codes */ + if (data[SFF_8636_SAS_COMP_OFFSET] & SFF_8636_SAS_6G) + add_item_string(items, name, "SAS 6.0G"); + if (data[SFF_8636_SAS_COMP_OFFSET] & SFF_8636_SAS_3G) + add_item_string(items, name, "SAS 3.0G"); + + /* Ethernet Compliance Codes */ + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_T) + add_item_string(items, name, "Ethernet: 1000BASE-T"); + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_CX) + add_item_string(items, name, "Ethernet: 1000BASE-CX"); + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_LX) + add_item_string(items, name, "Ethernet: 1000BASE-LX"); + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_SX) + add_item_string(items, name, "Ethernet: 1000BASE-SX"); + + /* Fibre Channel link length */ + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_VERY_LONG) + add_item_string(items, name, "FC: very long distance (V)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_SHORT) + add_item_string(items, name, "FC: short distance (S)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_INT) + add_item_string(items, name, "FC: intermediate distance (I)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_LONG) + add_item_string(items, name, "FC: long distance (L)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_MED) + add_item_string(items, name, "FC: medium distance (M)"); + + /* Fibre Channel transmitter technology */ + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_TECH_LONG_LC) + add_item_string(items, name, "FC: Longwave laser (LC)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_TECH_ELEC_INTER) + add_item_string(items, name, "FC: Electrical inter-enclosure (EL)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_ELEC_INTRA) + add_item_string(items, name, "FC: Electrical intra-enclosure (EL)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_SHORT_WO_OFC) + add_item_string(items, name, "FC: Shortwave laser w/o OFC (SN)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_SHORT_W_OFC) + add_item_string(items, name, "FC: Shortwave laser with OFC (SL)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_LONG_LL) + add_item_string(items, name, "FC: Longwave laser (LL)"); + + /* Fibre Channel transmission media */ + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TW) + add_item_string(items, name, "FC: Twin Axial Pair (TW)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TP) + add_item_string(items, name, "FC: Twisted Pair (TP)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_MI) + add_item_string(items, name, "FC: Miniature Coax (MI)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TV) + add_item_string(items, name, "FC: Video Coax (TV)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_M6) + add_item_string(items, name, "FC: Multimode, 62.5m (M6)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_M5) + add_item_string(items, name, "FC: Multimode, 50m (M5)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_OM3) + add_item_string(items, name, "FC: Multimode, 50um (OM3)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_SM) + add_item_string(items, name, "FC: Single Mode (SM)"); + + /* Fibre Channel speed */ + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_1200_MBPS) + add_item_string(items, name, "FC: 1200 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_800_MBPS) + add_item_string(items, name, "FC: 800 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_1600_MBPS) + add_item_string(items, name, "FC: 1600 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_400_MBPS) + add_item_string(items, name, "FC: 400 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_200_MBPS) + add_item_string(items, name, "FC: 200 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_100_MBPS) + add_item_string(items, name, "FC: 100 MBytes/sec"); +} + +static void sff_8636_show_encoding(const uint8_t *data, struct sff_item *items) +{ + sff_8024_show_encoding(data, SFF_8636_ENCODING_OFFSET, + RTE_ETH_MODULE_SFF_8636, items); +} + +static void sff_8636_show_rate_identifier(const uint8_t *data, struct sff_item *items) +{ + char val_string[20]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[SFF_8636_EXT_RS_OFFSET]); + add_item_string(items, "Rate identifier", val_string); +} + +static void sff_8636_show_oui(const uint8_t *data, struct sff_item *items) +{ + sff_8024_show_oui(data, SFF_8636_VENDOR_OUI_OFFSET, items); +} + +static void sff_8636_show_wavelength_or_copper_compliance(const uint8_t *data, + struct sff_item *items) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + snprintf(val_string, sizeof(val_string), "0x%02x", + (data[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK)); + + switch (data[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK) { + case SFF_8636_TRANS_850_VCSEL: + strlcat(val_string, " (850 nm VCSEL)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_VCSEL: + strlcat(val_string, " (1310 nm VCSEL)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1550_VCSEL: + strlcat(val_string, " (1550 nm VCSEL)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_FP: + strlcat(val_string, " (1310 nm FP)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_DFB: + strlcat(val_string, " (1310 nm DFB)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1550_DFB: + strlcat(val_string, " (1550 nm DFB)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_EML: + strlcat(val_string, " (1310 nm EML)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1550_EML: + strlcat(val_string, " (1550 nm EML)", sizeof(val_string)); + break; + case SFF_8636_TRANS_OTHERS: + strlcat(val_string, " (Others/Undefined)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1490_DFB: + strlcat(val_string, " (1490 nm DFB)", sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_PAS_UNEQUAL: + strlcat(val_string, " (Copper cable unequalized)", sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_PAS_EQUAL: + strlcat(val_string, " (Copper cable passive equalized)", sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_LNR_FAR_EQUAL: + strlcat(val_string, + " (Copper cable, near and far end limiting active equalizers)", + sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_FAR_EQUAL: + strlcat(val_string, + " (Copper cable, far end limiting active equalizers)", + sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_NEAR_EQUAL: + strlcat(val_string, + " (Copper cable, near end limiting active equalizers)", + sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_LNR_EQUAL: + strlcat(val_string, + " (Copper cable, linear active equalizers)", + sizeof(val_string)); + break; + } + add_item_string(items, "Transmitter technology", val_string); + + if ((data[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK) + >= SFF_8636_TRANS_COPPER_PAS_UNEQUAL) { + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + add_item_string(items, "Attenuation at 2.5GHz", val_string); + + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + add_item_string(items, "Attenuation at 5.0GHz", val_string); + + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + add_item_string(items, "Attenuation at 7.0GHz", val_string); + + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + add_item_string(items, "Attenuation at 12.9GHz", val_string); + } else { + snprintf(val_string, sizeof(val_string), "%.3lfnm", + (((data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET] << 8) | + data[SFF_8636_WAVELEN_LOW_BYTE_OFFSET])*0.05)); + add_item_string(items, "Laser wavelength", val_string); + + snprintf(val_string, sizeof(val_string), "%.3lfnm", + (((data[SFF_8636_WAVE_TOL_HIGH_BYTE_OFFSET] << 8) | + data[SFF_8636_WAVE_TOL_LOW_BYTE_OFFSET])*0.005)); + add_item_string(items, "Laser wavelength tolerance", val_string); + } +} + +static void sff_8636_show_revision_compliance(const uint8_t *data, struct sff_item *items) +{ + static const char *name = "Revision Compliance"; + + switch (data[SFF_8636_REV_COMPLIANCE_OFFSET]) { + case SFF_8636_REV_UNSPECIFIED: + add_item_string(items, name, "Revision not specified"); + break; + case SFF_8636_REV_8436_48: + add_item_string(items, name, "SFF-8436 Rev 4.8 or earlier"); + break; + case SFF_8636_REV_8436_8636: + add_item_string(items, name, "SFF-8436 Rev 4.8 or earlier"); + break; + case SFF_8636_REV_8636_13: + add_item_string(items, name, "SFF-8636 Rev 1.3 or earlier"); + break; + case SFF_8636_REV_8636_14: + add_item_string(items, name, "SFF-8636 Rev 1.4"); + break; + case SFF_8636_REV_8636_15: + add_item_string(items, name, "SFF-8636 Rev 1.5"); + break; + case SFF_8636_REV_8636_20: + add_item_string(items, name, "SFF-8636 Rev 2.0"); + break; + case SFF_8636_REV_8636_27: + add_item_string(items, name, "SFF-8636 Rev 2.5/2.6/2.7"); + break; + default: + add_item_string(items, name, "Unallocated"); + break; + } +} + +/* + * 2-byte internal temperature conversions: + * First byte is a signed 8-bit integer, which is the temp decimal part + * Second byte are 1/256th of degree, which are added to the dec part. + */ +#define SFF_8636_OFFSET_TO_TEMP(offset) ((int16_t)OFFSET_TO_U16(offset)) + +static void sff_8636_dom_parse(const uint8_t *data, struct sff_diags *sd) +{ + int i = 0; + + /* Monitoring Thresholds for Alarms and Warnings */ + sd->sfp_voltage[MCURR] = OFFSET_TO_U16(SFF_8636_VCC_CURR); + sd->sfp_voltage[HALRM] = OFFSET_TO_U16(SFF_8636_VCC_HALRM); + sd->sfp_voltage[LALRM] = OFFSET_TO_U16(SFF_8636_VCC_LALRM); + sd->sfp_voltage[HWARN] = OFFSET_TO_U16(SFF_8636_VCC_HWARN); + sd->sfp_voltage[LWARN] = OFFSET_TO_U16(SFF_8636_VCC_LWARN); + + sd->sfp_temp[MCURR] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_CURR); + sd->sfp_temp[HALRM] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_HALRM); + sd->sfp_temp[LALRM] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_LALRM); + sd->sfp_temp[HWARN] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_HWARN); + sd->sfp_temp[LWARN] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_LWARN); + + sd->bias_cur[HALRM] = OFFSET_TO_U16(SFF_8636_TX_BIAS_HALRM); + sd->bias_cur[LALRM] = OFFSET_TO_U16(SFF_8636_TX_BIAS_LALRM); + sd->bias_cur[HWARN] = OFFSET_TO_U16(SFF_8636_TX_BIAS_HWARN); + sd->bias_cur[LWARN] = OFFSET_TO_U16(SFF_8636_TX_BIAS_LWARN); + + sd->tx_power[HALRM] = OFFSET_TO_U16(SFF_8636_TX_PWR_HALRM); + sd->tx_power[LALRM] = OFFSET_TO_U16(SFF_8636_TX_PWR_LALRM); + sd->tx_power[HWARN] = OFFSET_TO_U16(SFF_8636_TX_PWR_HWARN); + sd->tx_power[LWARN] = OFFSET_TO_U16(SFF_8636_TX_PWR_LWARN); + + sd->rx_power[HALRM] = OFFSET_TO_U16(SFF_8636_RX_PWR_HALRM); + sd->rx_power[LALRM] = OFFSET_TO_U16(SFF_8636_RX_PWR_LALRM); + sd->rx_power[HWARN] = OFFSET_TO_U16(SFF_8636_RX_PWR_HWARN); + sd->rx_power[LWARN] = OFFSET_TO_U16(SFF_8636_RX_PWR_LWARN); + + + /* Channel Specific Data */ + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + uint8_t rx_power_offset, tx_bias_offset; + uint8_t tx_power_offset; + + switch (i) { + case 0: + rx_power_offset = SFF_8636_RX_PWR_1_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_1_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_1_OFFSET; + break; + case 1: + rx_power_offset = SFF_8636_RX_PWR_2_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_2_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_2_OFFSET; + break; + case 2: + rx_power_offset = SFF_8636_RX_PWR_3_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_3_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_3_OFFSET; + break; + case 3: + rx_power_offset = SFF_8636_RX_PWR_4_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_4_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_4_OFFSET; + break; + } + sd->scd[i].bias_cur = OFFSET_TO_U16(tx_bias_offset); + sd->scd[i].rx_power = OFFSET_TO_U16(rx_power_offset); + sd->scd[i].tx_power = OFFSET_TO_U16(tx_power_offset); + } + +} + +static void sff_8636_show_dom(const uint8_t *data, uint32_t eeprom_len, struct sff_item *items) +{ + struct sff_diags sd = {0}; + const char *rx_power_string = NULL; + char power_string[MAX_DESC_SIZE]; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + int i; + + /* + * There is no clear identifier to signify the existence of + * optical diagnostics similar to SFF-8472. So checking existence + * of page 3, will provide the gurantee for existence of alarms + * and thresholds + * If pagging support exists, then supports_alarms is marked as 1 + */ + + if (eeprom_len == RTE_ETH_MODULE_SFF_8636_MAX_LEN) { + if (!(data[SFF_8636_STATUS_2_OFFSET] & + SFF_8636_STATUS_PAGE_3_PRESENT)) { + sd.supports_alarms = 1; + } + } + + sd.rx_power_type = data[SFF_8636_DIAG_TYPE_OFFSET] & + SFF_8636_RX_PWR_TYPE_MASK; + sd.tx_power_type = data[SFF_8636_DIAG_TYPE_OFFSET] & + SFF_8636_RX_PWR_TYPE_MASK; + + sff_8636_dom_parse(data, &sd); + + SPRINT_TEMP(val_string, sd.sfp_temp[MCURR]); + add_item_string(items, "Module temperature", val_string); + + SPRINT_VCC(val_string, sd.sfp_voltage[MCURR]); + add_item_string(items, "Module voltage", val_string); + + /* + * SFF-8636/8436 spec is not clear whether RX power/ TX bias + * current fields are supported or not. A valid temperature + * reading is used as existence for TX/RX power. + */ + if ((sd.sfp_temp[MCURR] == 0x0) || + (sd.sfp_temp[MCURR] == (int16_t)0xFFFF)) + return; + + add_item_string(items, "Alarm/warning flags implemented", + (sd.supports_alarms ? "Yes" : "No")); + + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + snprintf(power_string, MAX_DESC_SIZE, "%s (Channel %d)", + "Laser tx bias current", i+1); + SPRINT_BIAS(val_string, sd.scd[i].bias_cur); + add_item_string(items, power_string, val_string); + } + + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + snprintf(power_string, MAX_DESC_SIZE, "%s (Channel %d)", + "Transmit avg optical power", i+1); + SPRINT_xX_PWR(val_string, sd.scd[i].tx_power); + add_item_string(items, power_string, val_string); + } + + if (!sd.rx_power_type) + rx_power_string = "Receiver signal OMA"; + else + rx_power_string = "Rcvr signal avg optical power"; + + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + snprintf(power_string, MAX_DESC_SIZE, "%s(Channel %d)", + rx_power_string, i+1); + SPRINT_xX_PWR(val_string, sd.scd[i].rx_power); + add_item_string(items, power_string, val_string); + } + + if (sd.supports_alarms) { + for (i = 0; sff_8636_aw_flags[i].str; ++i) { + add_item_string(items, sff_8636_aw_flags[i].str, + data[sff_8636_aw_flags[i].offset] + & sff_8636_aw_flags[i].value ? "On" : "Off"); + } + + sff_show_thresholds(sd, items); + } + +} +void sff_8636_show_all(const uint8_t *data, uint32_t eeprom_len, struct sff_item *items) +{ + sff_8636_show_identifier(data, items); + if ((data[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP) || + (data[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP_PLUS) || + (data[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP28)) { + sff_8636_show_ext_identifier(data, items); + sff_8636_show_connector(data, items); + sff_8636_show_transceiver(data, items); + sff_8636_show_encoding(data, items); + sff_show_value_with_unit(data, SFF_8636_BR_NOMINAL_OFFSET, + "BR, Nominal", 100, "Mbps", items); + sff_8636_show_rate_identifier(data, items); + sff_show_value_with_unit(data, SFF_8636_SM_LEN_OFFSET, + "Length (SMF,km)", 1, "km", items); + sff_show_value_with_unit(data, SFF_8636_OM3_LEN_OFFSET, + "Length (OM3 50um)", 2, "m", items); + sff_show_value_with_unit(data, SFF_8636_OM2_LEN_OFFSET, + "Length (OM2 50um)", 1, "m", items); + sff_show_value_with_unit(data, SFF_8636_OM1_LEN_OFFSET, + "Length (OM1 62.5um)", 1, "m", items); + sff_show_value_with_unit(data, SFF_8636_CBL_LEN_OFFSET, + "Length (Copper or Active cable)", 1, "m", items); + sff_8636_show_wavelength_or_copper_compliance(data, items); + sff_show_ascii(data, SFF_8636_VENDOR_NAME_START_OFFSET, + SFF_8636_VENDOR_NAME_END_OFFSET, "Vendor name", items); + sff_8636_show_oui(data, items); + sff_show_ascii(data, SFF_8636_VENDOR_PN_START_OFFSET, + SFF_8636_VENDOR_PN_END_OFFSET, "Vendor PN", items); + sff_show_ascii(data, SFF_8636_VENDOR_REV_START_OFFSET, + SFF_8636_VENDOR_REV_END_OFFSET, "Vendor rev", items); + sff_show_ascii(data, SFF_8636_VENDOR_SN_START_OFFSET, + SFF_8636_VENDOR_SN_END_OFFSET, "Vendor SN", items); + sff_show_ascii(data, SFF_8636_DATE_YEAR_OFFSET, + SFF_8636_DATE_VENDOR_LOT_OFFSET + 1, "Date code", items); + sff_8636_show_revision_compliance(data, items); + sff_8636_show_dom(data, eeprom_len, items); + } +} diff --git a/lib/ethdev/sff_8636.h b/lib/ethdev/sff_8636.h new file mode 100644 index 0000000000..fc656775f9 --- /dev/null +++ b/lib/ethdev/sff_8636.h @@ -0,0 +1,592 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * SFF-8636 standards based QSFP EEPROM Field Definitions + * + */ + +#ifndef _SFF_8636_H_ +#define _SFF_8636_H_ + +/*------------------------------------------------------------------------------ + * + * QSFP EEPROM data structures + * + * register info from SFF-8636 Rev 2.7 + */ + +/*------------------------------------------------------------------------------ + * + * Lower Memory Page 00h + * Measurement, Diagnostic and Control Functions + * + */ +/* Identifier - 0 */ +/* Values are defined under SFF_8024_ID_OFFSET */ +#define SFF_8636_ID_OFFSET 0x00 + +#define SFF_8636_REV_COMPLIANCE_OFFSET 0x01 +#define SFF_8636_REV_UNSPECIFIED 0x00 +#define SFF_8636_REV_8436_48 0x01 +#define SFF_8636_REV_8436_8636 0x02 +#define SFF_8636_REV_8636_13 0x03 +#define SFF_8636_REV_8636_14 0x04 +#define SFF_8636_REV_8636_15 0x05 +#define SFF_8636_REV_8636_20 0x06 +#define SFF_8636_REV_8636_27 0x07 + +#define SFF_8636_STATUS_2_OFFSET 0x02 +/* Flat Memory:0- Paging, 1- Page 0 only */ +#define SFF_8636_STATUS_PAGE_3_PRESENT (1 << 2) +#define SFF_8636_STATUS_INTL_OUTPUT (1 << 1) +#define SFF_8636_STATUS_DATA_NOT_READY (1 << 0) + +/* Channel Status Interrupt Flags - 3-5 */ +#define SFF_8636_LOS_AW_OFFSET 0x03 +#define SFF_8636_TX4_LOS_AW (1 << 7) +#define SFF_8636_TX3_LOS_AW (1 << 6) +#define SFF_8636_TX2_LOS_AW (1 << 5) +#define SFF_8636_TX1_LOS_AW (1 << 4) +#define SFF_8636_RX4_LOS_AW (1 << 3) +#define SFF_8636_RX3_LOS_AW (1 << 2) +#define SFF_8636_RX2_LOS_AW (1 << 1) +#define SFF_8636_RX1_LOS_AW (1 << 0) + +#define SFF_8636_FAULT_AW_OFFSET 0x04 +#define SFF_8636_TX4_FAULT_AW (1 << 3) +#define SFF_8636_TX3_FAULT_AW (1 << 2) +#define SFF_8636_TX2_FAULT_AW (1 << 1) +#define SFF_8636_TX1_FAULT_AW (1 << 0) + +/* Module Monitor Interrupt Flags - 6-8 */ +#define SFF_8636_TEMP_AW_OFFSET 0x06 +#define SFF_8636_TEMP_HALARM_STATUS (1 << 7) +#define SFF_8636_TEMP_LALARM_STATUS (1 << 6) +#define SFF_8636_TEMP_HWARN_STATUS (1 << 5) +#define SFF_8636_TEMP_LWARN_STATUS (1 << 4) + +#define SFF_8636_VCC_AW_OFFSET 0x07 +#define SFF_8636_VCC_HALARM_STATUS (1 << 7) +#define SFF_8636_VCC_LALARM_STATUS (1 << 6) +#define SFF_8636_VCC_HWARN_STATUS (1 << 5) +#define SFF_8636_VCC_LWARN_STATUS (1 << 4) + +/* Channel Monitor Interrupt Flags - 9-21 */ +#define SFF_8636_RX_PWR_12_AW_OFFSET 0x09 +#define SFF_8636_RX_PWR_1_HALARM (1 << 7) +#define SFF_8636_RX_PWR_1_LALARM (1 << 6) +#define SFF_8636_RX_PWR_1_HWARN (1 << 5) +#define SFF_8636_RX_PWR_1_LWARN (1 << 4) +#define SFF_8636_RX_PWR_2_HALARM (1 << 3) +#define SFF_8636_RX_PWR_2_LALARM (1 << 2) +#define SFF_8636_RX_PWR_2_HWARN (1 << 1) +#define SFF_8636_RX_PWR_2_LWARN (1 << 0) + +#define SFF_8636_RX_PWR_34_AW_OFFSET 0x0A +#define SFF_8636_RX_PWR_3_HALARM (1 << 7) +#define SFF_8636_RX_PWR_3_LALARM (1 << 6) +#define SFF_8636_RX_PWR_3_HWARN (1 << 5) +#define SFF_8636_RX_PWR_3_LWARN (1 << 4) +#define SFF_8636_RX_PWR_4_HALARM (1 << 3) +#define SFF_8636_RX_PWR_4_LALARM (1 << 2) +#define SFF_8636_RX_PWR_4_HWARN (1 << 1) +#define SFF_8636_RX_PWR_4_LWARN (1 << 0) + +#define SFF_8636_TX_BIAS_12_AW_OFFSET 0x0B +#define SFF_8636_TX_BIAS_1_HALARM (1 << 7) +#define SFF_8636_TX_BIAS_1_LALARM (1 << 6) +#define SFF_8636_TX_BIAS_1_HWARN (1 << 5) +#define SFF_8636_TX_BIAS_1_LWARN (1 << 4) +#define SFF_8636_TX_BIAS_2_HALARM (1 << 3) +#define SFF_8636_TX_BIAS_2_LALARM (1 << 2) +#define SFF_8636_TX_BIAS_2_HWARN (1 << 1) +#define SFF_8636_TX_BIAS_2_LWARN (1 << 0) + +#define SFF_8636_TX_BIAS_34_AW_OFFSET 0xC +#define SFF_8636_TX_BIAS_3_HALARM (1 << 7) +#define SFF_8636_TX_BIAS_3_LALARM (1 << 6) +#define SFF_8636_TX_BIAS_3_HWARN (1 << 5) +#define SFF_8636_TX_BIAS_3_LWARN (1 << 4) +#define SFF_8636_TX_BIAS_4_HALARM (1 << 3) +#define SFF_8636_TX_BIAS_4_LALARM (1 << 2) +#define SFF_8636_TX_BIAS_4_HWARN (1 << 1) +#define SFF_8636_TX_BIAS_4_LWARN (1 << 0) + +#define SFF_8636_TX_PWR_12_AW_OFFSET 0x0D +#define SFF_8636_TX_PWR_1_HALARM (1 << 7) +#define SFF_8636_TX_PWR_1_LALARM (1 << 6) +#define SFF_8636_TX_PWR_1_HWARN (1 << 5) +#define SFF_8636_TX_PWR_1_LWARN (1 << 4) +#define SFF_8636_TX_PWR_2_HALARM (1 << 3) +#define SFF_8636_TX_PWR_2_LALARM (1 << 2) +#define SFF_8636_TX_PWR_2_HWARN (1 << 1) +#define SFF_8636_TX_PWR_2_LWARN (1 << 0) + +#define SFF_8636_TX_PWR_34_AW_OFFSET 0x0E +#define SFF_8636_TX_PWR_3_HALARM (1 << 7) +#define SFF_8636_TX_PWR_3_LALARM (1 << 6) +#define SFF_8636_TX_PWR_3_HWARN (1 << 5) +#define SFF_8636_TX_PWR_3_LWARN (1 << 4) +#define SFF_8636_TX_PWR_4_HALARM (1 << 3) +#define SFF_8636_TX_PWR_4_LALARM (1 << 2) +#define SFF_8636_TX_PWR_4_HWARN (1 << 1) +#define SFF_8636_TX_PWR_4_LWARN (1 << 0) + +/* Module Monitoring Values - 22-33 */ +#define SFF_8636_TEMP_CURR 0x16 +#define SFF_8636_TEMP_MSB_OFFSET 0x16 +#define SFF_8636_TEMP_LSB_OFFSET 0x17 + +#define SFF_8636_VCC_CURR 0x1A +#define SFF_8636_VCC_MSB_OFFSET 0x1A +#define SFF_8636_VCC_LSB_OFFSET 0x1B + +/* Channel Monitoring Values - 34-81 */ +#define SFF_8636_RX_PWR_1_OFFSET 0x22 +#define SFF_8636_RX_PWR_2_OFFSET 0x24 +#define SFF_8636_RX_PWR_3_OFFSET 0x26 +#define SFF_8636_RX_PWR_4_OFFSET 0x28 + +#define SFF_8636_TX_BIAS_1_OFFSET 0x2A +#define SFF_8636_TX_BIAS_2_OFFSET 0x2C +#define SFF_8636_TX_BIAS_3_OFFSET 0x2E +#define SFF_8636_TX_BIAS_4_OFFSET 0x30 + +#define SFF_8636_TX_PWR_1_OFFSET 0x32 +#define SFF_8636_TX_PWR_2_OFFSET 0x34 +#define SFF_8636_TX_PWR_3_OFFSET 0x36 +#define SFF_8636_TX_PWR_4_OFFSET 0x38 + +/* Control Bytes - 86 - 99 */ +#define SFF_8636_TX_DISABLE_OFFSET 0x56 +#define SFF_8636_TX_DISABLE_4 (1 << 3) +#define SFF_8636_TX_DISABLE_3 (1 << 2) +#define SFF_8636_TX_DISABLE_2 (1 << 1) +#define SFF_8636_TX_DISABLE_1 (1 << 0) + +#define SFF_8636_RX_RATE_SELECT_OFFSET 0x57 +#define SFF_8636_RX_RATE_SELECT_4_MASK (3 << 6) +#define SFF_8636_RX_RATE_SELECT_3_MASK (3 << 4) +#define SFF_8636_RX_RATE_SELECT_2_MASK (3 << 2) +#define SFF_8636_RX_RATE_SELECT_1_MASK (3 << 0) + +#define SFF_8636_TX_RATE_SELECT_OFFSET 0x58 +#define SFF_8636_TX_RATE_SELECT_4_MASK (3 << 6) +#define SFF_8636_TX_RATE_SELECT_3_MASK (3 << 4) +#define SFF_8636_TX_RATE_SELECT_2_MASK (3 << 2) +#define SFF_8636_TX_RATE_SELECT_1_MASK (3 << 0) + +#define SFF_8636_RX_APP_SELECT_4_OFFSET 0x58 +#define SFF_8636_RX_APP_SELECT_3_OFFSET 0x59 +#define SFF_8636_RX_APP_SELECT_2_OFFSET 0x5A +#define SFF_8636_RX_APP_SELECT_1_OFFSET 0x5B + +#define SFF_8636_PWR_MODE_OFFSET 0x5D +#define SFF_8636_HIGH_PWR_ENABLE (1 << 2) +#define SFF_8636_LOW_PWR_MODE (1 << 1) +#define SFF_8636_PWR_OVERRIDE (1 << 0) + +#define SFF_8636_TX_APP_SELECT_4_OFFSET 0x5E +#define SFF_8636_TX_APP_SELECT_3_OFFSET 0x5F +#define SFF_8636_TX_APP_SELECT_2_OFFSET 0x60 +#define SFF_8636_TX_APP_SELECT_1_OFFSET 0x61 + +#define SFF_8636_LOS_MASK_OFFSET 0x64 +#define SFF_8636_TX_LOS_4_MASK (1 << 7) +#define SFF_8636_TX_LOS_3_MASK (1 << 6) +#define SFF_8636_TX_LOS_2_MASK (1 << 5) +#define SFF_8636_TX_LOS_1_MASK (1 << 4) +#define SFF_8636_RX_LOS_4_MASK (1 << 3) +#define SFF_8636_RX_LOS_3_MASK (1 << 2) +#define SFF_8636_RX_LOS_2_MASK (1 << 1) +#define SFF_8636_RX_LOS_1_MASK (1 << 0) + +#define SFF_8636_FAULT_MASK_OFFSET 0x65 +#define SFF_8636_TX_FAULT_1_MASK (1 << 3) +#define SFF_8636_TX_FAULT_2_MASK (1 << 2) +#define SFF_8636_TX_FAULT_3_MASK (1 << 1) +#define SFF_8636_TX_FAULT_4_MASK (1 << 0) + +#define SFF_8636_TEMP_MASK_OFFSET 0x67 +#define SFF_8636_TEMP_HALARM_MASK (1 << 7) +#define SFF_8636_TEMP_LALARM_MASK (1 << 6) +#define SFF_8636_TEMP_HWARN_MASK (1 << 5) +#define SFF_8636_TEMP_LWARN_MASK (1 << 4) + +#define SFF_8636_VCC_MASK_OFFSET 0x68 +#define SFF_8636_VCC_HALARM_MASK (1 << 7) +#define SFF_8636_VCC_LALARM_MASK (1 << 6) +#define SFF_8636_VCC_HWARN_MASK (1 << 5) +#define SFF_8636_VCC_LWARN_MASK (1 << 4) + +/*------------------------------------------------------------------------------ + * + * Upper Memory Page 00h + * Serial ID - Base ID, Extended ID and Vendor Specific ID fields + * + */ +/* Identifier - 128 */ +/* Identifier values same as Lower Memory Page 00h */ +#define SFF_8636_UPPER_PAGE_0_ID_OFFSET 0x80 + +/* Extended Identifier - 128 */ +#define SFF_8636_EXT_ID_OFFSET 0x81 +#define SFF_8636_EXT_ID_PWR_CLASS_MASK 0xC0 +#define SFF_8636_EXT_ID_PWR_CLASS_1 (0 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_2 (1 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_3 (2 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_4 (3 << 6) +#define SFF_8636_EXT_ID_CLIE_MASK 0x10 +#define SFF_8636_EXT_ID_CLIEI_CODE_PRESENT (1 << 4) +#define SFF_8636_EXT_ID_CDR_TX_MASK 0x08 +#define SFF_8636_EXT_ID_CDR_TX_PRESENT (1 << 3) +#define SFF_8636_EXT_ID_CDR_RX_MASK 0x04 +#define SFF_8636_EXT_ID_CDR_RX_PRESENT (1 << 2) +#define SFF_8636_EXT_ID_EPWR_CLASS_MASK 0x03 +#define SFF_8636_EXT_ID_PWR_CLASS_LEGACY 0 +#define SFF_8636_EXT_ID_PWR_CLASS_5 1 +#define SFF_8636_EXT_ID_PWR_CLASS_6 2 +#define SFF_8636_EXT_ID_PWR_CLASS_7 3 + +/* Connector Values offset - 130 */ +/* Values are defined under SFF_8024_CTOR */ +#define SFF_8636_CTOR_OFFSET 0x82 +#define SFF_8636_CTOR_UNKNOWN 0x00 +#define SFF_8636_CTOR_SC 0x01 +#define SFF_8636_CTOR_FC_STYLE_1 0x02 +#define SFF_8636_CTOR_FC_STYLE_2 0x03 +#define SFF_8636_CTOR_BNC_TNC 0x04 +#define SFF_8636_CTOR_FC_COAX 0x05 +#define SFF_8636_CTOR_FIBER_JACK 0x06 +#define SFF_8636_CTOR_LC 0x07 +#define SFF_8636_CTOR_MT_RJ 0x08 +#define SFF_8636_CTOR_MU 0x09 +#define SFF_8636_CTOR_SG 0x0A +#define SFF_8636_CTOR_OPT_PT 0x0B +#define SFF_8636_CTOR_MPO 0x0C +/* 0D-1Fh --- Reserved */ +#define SFF_8636_CTOR_HSDC_II 0x20 +#define SFF_8636_CTOR_COPPER_PT 0x21 +#define SFF_8636_CTOR_RJ45 0x22 +#define SFF_8636_CTOR_NO_SEPARABLE 0x23 +#define SFF_8636_CTOR_MXC_2X16 0x24 + +/* Specification Compliance - 131-138 */ +/* Ethernet Compliance Codes - 131 */ +#define SFF_8636_ETHERNET_COMP_OFFSET 0x83 +#define SFF_8636_ETHERNET_RSRVD (1 << 7) +#define SFF_8636_ETHERNET_10G_LRM (1 << 6) +#define SFF_8636_ETHERNET_10G_LR (1 << 5) +#define SFF_8636_ETHERNET_10G_SR (1 << 4) +#define SFF_8636_ETHERNET_40G_CR4 (1 << 3) +#define SFF_8636_ETHERNET_40G_SR4 (1 << 2) +#define SFF_8636_ETHERNET_40G_LR4 (1 << 1) +#define SFF_8636_ETHERNET_40G_ACTIVE (1 << 0) + +/* SONET Compliance Codes - 132 */ +#define SFF_8636_SONET_COMP_OFFSET 0x84 +#define SFF_8636_SONET_40G_OTN (1 << 3) +#define SFF_8636_SONET_OC48_LR (1 << 2) +#define SFF_8636_SONET_OC48_IR (1 << 1) +#define SFF_8636_SONET_OC48_SR (1 << 0) + +/* SAS/SATA Complaince Codes - 133 */ +#define SFF_8636_SAS_COMP_OFFSET 0x85 +#define SFF_8636_SAS_12G (1 << 6) +#define SFF_8636_SAS_6G (1 << 5) +#define SFF_8636_SAS_3G (1 << 4) + +/* Gigabit Ethernet Compliance Codes - 134 */ +#define SFF_8636_GIGE_COMP_OFFSET 0x86 +#define SFF_8636_GIGE_1000_BASE_T (1 << 3) +#define SFF_8636_GIGE_1000_BASE_CX (1 << 2) +#define SFF_8636_GIGE_1000_BASE_LX (1 << 1) +#define SFF_8636_GIGE_1000_BASE_SX (1 << 0) + +/* Fibre Channel Link length/Transmitter Tech. - 135,136 */ +#define SFF_8636_FC_LEN_OFFSET 0x87 +#define SFF_8636_FC_LEN_VERY_LONG (1 << 7) +#define SFF_8636_FC_LEN_SHORT (1 << 6) +#define SFF_8636_FC_LEN_INT (1 << 5) +#define SFF_8636_FC_LEN_LONG (1 << 4) +#define SFF_8636_FC_LEN_MED (1 << 3) +#define SFF_8636_FC_TECH_LONG_LC (1 << 1) +#define SFF_8636_FC_TECH_ELEC_INTER (1 << 0) + +#define SFF_8636_FC_TECH_OFFSET 0x88 +#define SFF_8636_FC_TECH_ELEC_INTRA (1 << 7) +#define SFF_8636_FC_TECH_SHORT_WO_OFC (1 << 6) +#define SFF_8636_FC_TECH_SHORT_W_OFC (1 << 5) +#define SFF_8636_FC_TECH_LONG_LL (1 << 4) + +/* Fibre Channel Transmitter Media - 137 */ +#define SFF_8636_FC_TRANS_MEDIA_OFFSET 0x89 +/* Twin Axial Pair */ +#define SFF_8636_FC_TRANS_MEDIA_TW (1 << 7) +/* Shielded Twisted Pair */ +#define SFF_8636_FC_TRANS_MEDIA_TP (1 << 6) +/* Miniature Coax */ +#define SFF_8636_FC_TRANS_MEDIA_MI (1 << 5) +/* Video Coax */ +#define SFF_8636_FC_TRANS_MEDIA_TV (1 << 4) +/* Multi-mode 62.5m */ +#define SFF_8636_FC_TRANS_MEDIA_M6 (1 << 3) +/* Multi-mode 50m */ +#define SFF_8636_FC_TRANS_MEDIA_M5 (1 << 2) +/* Multi-mode 50um */ +#define SFF_8636_FC_TRANS_MEDIA_OM3 (1 << 1) +/* Single Mode */ +#define SFF_8636_FC_TRANS_MEDIA_SM (1 << 0) + +/* Fibre Channel Speed - 138 */ +#define SFF_8636_FC_SPEED_OFFSET 0x8A +#define SFF_8636_FC_SPEED_1200_MBPS (1 << 7) +#define SFF_8636_FC_SPEED_800_MBPS (1 << 6) +#define SFF_8636_FC_SPEED_1600_MBPS (1 << 5) +#define SFF_8636_FC_SPEED_400_MBPS (1 << 4) +#define SFF_8636_FC_SPEED_200_MBPS (1 << 2) +#define SFF_8636_FC_SPEED_100_MBPS (1 << 0) + +/* Encoding - 139 */ +/* Values are defined under SFF_8024_ENCODING */ +#define SFF_8636_ENCODING_OFFSET 0x8B +#define SFF_8636_ENCODING_MANCHESTER 0x06 +#define SFF_8636_ENCODING_64B66B 0x05 +#define SFF_8636_ENCODING_SONET 0x04 +#define SFF_8636_ENCODING_NRZ 0x03 +#define SFF_8636_ENCODING_4B5B 0x02 +#define SFF_8636_ENCODING_8B10B 0x01 +#define SFF_8636_ENCODING_UNSPEC 0x00 + +/* BR, Nominal - 140 */ +#define SFF_8636_BR_NOMINAL_OFFSET 0x8C + +/* Extended RateSelect - 141 */ +#define SFF_8636_EXT_RS_OFFSET 0x8D +#define SFF_8636_EXT_RS_V1 (1 << 0) + +/* Length (Standard SM Fiber)-km - 142 */ +#define SFF_8636_SM_LEN_OFFSET 0x8E + +/* Length (OM3)-Unit 2m - 143 */ +#define SFF_8636_OM3_LEN_OFFSET 0x8F + +/* Length (OM2)-Unit 1m - 144 */ +#define SFF_8636_OM2_LEN_OFFSET 0x90 + +/* Length (OM1)-Unit 1m - 145 */ +#define SFF_8636_OM1_LEN_OFFSET 0x91 + +/* Cable Assembly Length -Unit 1m - 146 */ +#define SFF_8636_CBL_LEN_OFFSET 0x92 + +/* Device Technology - 147 */ +#define SFF_8636_DEVICE_TECH_OFFSET 0x93 +/* Transmitter Technology */ +#define SFF_8636_TRANS_TECH_MASK 0xF0 +/* Copper cable, linear active equalizers */ +#define SFF_8636_TRANS_COPPER_LNR_EQUAL (15 << 4) +/* Copper cable, near end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_NEAR_EQUAL (14 << 4) +/* Copper cable, far end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_FAR_EQUAL (13 << 4) +/* Copper cable, near & far end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_LNR_FAR_EQUAL (12 << 4) +/* Copper cable, passive equalized */ +#define SFF_8636_TRANS_COPPER_PAS_EQUAL (11 << 4) +/* Copper cable, unequalized */ +#define SFF_8636_TRANS_COPPER_PAS_UNEQUAL (10 << 4) +/* 1490 nm DFB */ +#define SFF_8636_TRANS_1490_DFB (9 << 4) +/* Others */ +#define SFF_8636_TRANS_OTHERS (8 << 4) +/* 1550 nm EML */ +#define SFF_8636_TRANS_1550_EML (7 << 4) +/* 1310 nm EML */ +#define SFF_8636_TRANS_1310_EML (6 << 4) +/* 1550 nm DFB */ +#define SFF_8636_TRANS_1550_DFB (5 << 4) +/* 1310 nm DFB */ +#define SFF_8636_TRANS_1310_DFB (4 << 4) +/* 1310 nm FP */ +#define SFF_8636_TRANS_1310_FP (3 << 4) +/* 1550 nm VCSEL */ +#define SFF_8636_TRANS_1550_VCSEL (2 << 4) +/* 1310 nm VCSEL */ +#define SFF_8636_TRANS_1310_VCSEL (1 << 4) +/* 850 nm VCSEL */ +#define SFF_8636_TRANS_850_VCSEL (0 << 4) + + /* Active/No wavelength control */ +#define SFF_8636_DEV_TECH_ACTIVE_WAVE_LEN (1 << 3) +/* Cooled transmitter */ +#define SFF_8636_DEV_TECH_COOL_TRANS (1 << 2) +/* APD/Pin Detector */ +#define SFF_8636_DEV_TECH_APD_DETECTOR (1 << 1) +/* Transmitter tunable */ +#define SFF_8636_DEV_TECH_TUNABLE (1 << 0) + +/* Vendor Name - 148-163 */ +#define SFF_8636_VENDOR_NAME_START_OFFSET 0x94 +#define SFF_8636_VENDOR_NAME_END_OFFSET 0xA3 + +/* Extended Module Codes - 164 */ +#define SFF_8636_EXT_MOD_CODE_OFFSET 0xA4 +#define SFF_8636_EXT_MOD_INFINIBAND_EDR (1 << 4) +#define SFF_8636_EXT_MOD_INFINIBAND_FDR (1 << 3) +#define SFF_8636_EXT_MOD_INFINIBAND_QDR (1 << 2) +#define SFF_8636_EXT_MOD_INFINIBAND_DDR (1 << 1) +#define SFF_8636_EXT_MOD_INFINIBAND_SDR (1 << 0) + +/* Vendor OUI - 165-167 */ +#define SFF_8636_VENDOR_OUI_OFFSET 0xA5 +#define SFF_8636_VENDOR_OUI_LEN 3 + +/* Vendor OUI - 165-167 */ +#define SFF_8636_VENDOR_PN_START_OFFSET 0xA8 +#define SFF_8636_VENDOR_PN_END_OFFSET 0xB7 + +/* Vendor Revision - 184-185 */ +#define SFF_8636_VENDOR_REV_START_OFFSET 0xB8 +#define SFF_8636_VENDOR_REV_END_OFFSET 0xB9 + +/* Wavelength - 186-187 */ +#define SFF_8636_WAVELEN_HIGH_BYTE_OFFSET 0xBA +#define SFF_8636_WAVELEN_LOW_BYTE_OFFSET 0xBB + +/* Wavelength Tolerance- 188-189 */ +#define SFF_8636_WAVE_TOL_HIGH_BYTE_OFFSET 0xBC +#define SFF_8636_WAVE_TOL_LOW_BYTE_OFFSET 0xBD + +/* Max case temp - Other than 70 C - 190 */ +#define SFF_8636_MAXCASE_TEMP_OFFSET 0xBE + +/* CC_BASE - 191 */ +#define SFF_8636_CC_BASE_OFFSET 0xBF + +/* Option Values - 192-195 */ +#define SFF_8636_OPTION_1_OFFSET 0xC0 +#define SFF_8636_ETHERNET_UNSPECIFIED 0x00 +#define SFF_8636_ETHERNET_100G_AOC 0x01 +#define SFF_8636_ETHERNET_100G_SR4 0x02 +#define SFF_8636_ETHERNET_100G_LR4 0x03 +#define SFF_8636_ETHERNET_100G_ER4 0x04 +#define SFF_8636_ETHERNET_100G_SR10 0x05 +#define SFF_8636_ETHERNET_100G_CWDM4_FEC 0x06 +#define SFF_8636_ETHERNET_100G_PSM4 0x07 +#define SFF_8636_ETHERNET_100G_ACC 0x08 +#define SFF_8636_ETHERNET_100G_CWDM4_NO_FEC 0x09 +#define SFF_8636_ETHERNET_100G_RSVD1 0x0A +#define SFF_8636_ETHERNET_100G_CR4 0x0B +#define SFF_8636_ETHERNET_25G_CR_CA_S 0x0C +#define SFF_8636_ETHERNET_25G_CR_CA_N 0x0D +#define SFF_8636_ETHERNET_40G_ER4 0x10 +#define SFF_8636_ETHERNET_4X10_SR 0x11 +#define SFF_8636_ETHERNET_40G_PSM4 0x12 +#define SFF_8636_ETHERNET_G959_P1I1_2D1 0x13 +#define SFF_8636_ETHERNET_G959_P1S1_2D2 0x14 +#define SFF_8636_ETHERNET_G959_P1L1_2D2 0x15 +#define SFF_8636_ETHERNET_10GT_SFI 0x16 +#define SFF_8636_ETHERNET_100G_CLR4 0x17 +#define SFF_8636_ETHERNET_100G_AOC2 0x18 +#define SFF_8636_ETHERNET_100G_ACC2 0x19 + +#define SFF_8636_OPTION_2_OFFSET 0xC1 +/* Rx output amplitude */ +#define SFF_8636_O2_RX_OUTPUT_AMP (1 << 0) +#define SFF_8636_OPTION_3_OFFSET 0xC2 +/* Rx Squelch Disable */ +#define SFF_8636_O3_RX_SQL_DSBL (1 << 3) +/* Rx Output Disable capable */ +#define SFF_8636_O3_RX_OUTPUT_DSBL (1 << 2) +/* Tx Squelch Disable */ +#define SFF_8636_O3_TX_SQL_DSBL (1 << 1) +/* Tx Squelch Impl */ +#define SFF_8636_O3_TX_SQL_IMPL (1 << 0) +#define SFF_8636_OPTION_4_OFFSET 0xC3 +/* Memory Page 02 present */ +#define SFF_8636_O4_PAGE_02_PRESENT (1 << 7) +/* Memory Page 01 present */ +#define SFF_8636_O4_PAGE_01_PRESENT (1 << 6) +/* Rate Select implemented */ +#define SFF_8636_O4_RATE_SELECT (1 << 5) +/* Tx_DISABLE implemented */ +#define SFF_8636_O4_TX_DISABLE (1 << 4) +/* Tx_FAULT implemented */ +#define SFF_8636_O4_TX_FAULT (1 << 3) +/* Tx Squelch implemented */ +#define SFF_8636_O4_TX_SQUELCH (1 << 2) +/* Tx Loss of Signal */ +#define SFF_8636_O4_TX_LOS (1 << 1) + +/* Vendor SN - 196-211 */ +#define SFF_8636_VENDOR_SN_START_OFFSET 0xC4 +#define SFF_8636_VENDOR_SN_END_OFFSET 0xD3 + +/* Vendor Date - 212-219 */ +#define SFF_8636_DATE_YEAR_OFFSET 0xD4 +#define SFF_8636_DATE_YEAR_LEN 2 +#define SFF_8636_DATE_MONTH_OFFSET 0xD6 +#define SFF_8636_DATE_MONTH_LEN 2 +#define SFF_8636_DATE_DAY_OFFSET 0xD8 +#define SFF_8636_DATE_DAY_LEN 2 +#define SFF_8636_DATE_VENDOR_LOT_OFFSET 0xDA +#define SFF_8636_DATE_VENDOR_LOT_LEN 2 + +/* Diagnostic Monitoring Type - 220 */ +#define SFF_8636_DIAG_TYPE_OFFSET 0xDC +#define SFF_8636_RX_PWR_TYPE_MASK 0x8 +#define SFF_8636_RX_PWR_TYPE_AVG_PWR (1 << 3) +#define SFF_8636_RX_PWR_TYPE_OMA (0 << 3) +#define SFF_8636_TX_PWR_TYPE_MASK 0x4 +#define SFF_8636_TX_PWR_TYPE_AVG_PWR (1 << 2) + +/* Enhanced Options - 221 */ +#define SFF_8636_ENH_OPTIONS_OFFSET 0xDD +#define SFF_8636_RATE_SELECT_EXT_SUPPORT (1 << 3) +#define SFF_8636_RATE_SELECT_APP_TABLE_SUPPORT (1 << 2) + +/* Check code - 223 */ +#define SFF_8636_CC_EXT_OFFSET 0xDF +#define SFF_8636_CC_EXT_LEN 1 + +/*------------------------------------------------------------------------------ + * + * Upper Memory Page 03h + * Contains module thresholds, channel thresholds and masks, + * and optional channel controls + * + * Offset - Page Num(3) * PageSize(0x80) + Page offset + */ + +/* Module Thresholds (48 Bytes) 128-175 */ +/* MSB at low address, LSB at high address */ +#define SFF_8636_TEMP_HALRM 0x200 +#define SFF_8636_TEMP_LALRM 0x202 +#define SFF_8636_TEMP_HWARN 0x204 +#define SFF_8636_TEMP_LWARN 0x206 + +#define SFF_8636_VCC_HALRM 0x210 +#define SFF_8636_VCC_LALRM 0x212 +#define SFF_8636_VCC_HWARN 0x214 +#define SFF_8636_VCC_LWARN 0x216 + +#define SFF_8636_RX_PWR_HALRM 0x230 +#define SFF_8636_RX_PWR_LALRM 0x232 +#define SFF_8636_RX_PWR_HWARN 0x234 +#define SFF_8636_RX_PWR_LWARN 0x236 + +#define SFF_8636_TX_BIAS_HALRM 0x238 +#define SFF_8636_TX_BIAS_LALRM 0x23A +#define SFF_8636_TX_BIAS_HWARN 0x23C +#define SFF_8636_TX_BIAS_LWARN 0x23E + +#define SFF_8636_TX_PWR_HALRM 0x240 +#define SFF_8636_TX_PWR_LALRM 0x242 +#define SFF_8636_TX_PWR_HWARN 0x244 +#define SFF_8636_TX_PWR_LWARN 0x246 + +#define ETH_MODULE_SFF_8636_MAX_LEN 640 +#define ETH_MODULE_SFF_8436_MAX_LEN 640 + +#endif /* _SFF_8636_H_ */ -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v5 0/5] add telemetry command for show module EEPROM 2022-02-15 10:18 [PATCH] app/testpmd: format dump information of module EEPROM Robin Zhang ` (3 preceding siblings ...) 2022-04-25 5:34 ` [PATCH v4 " Robin Zhang @ 2022-04-26 2:43 ` Robin Zhang 2022-04-26 2:43 ` [PATCH v5 1/5] ethdev: add telemetry command for " Robin Zhang ` (6 more replies) 4 siblings, 7 replies; 77+ messages in thread From: Robin Zhang @ 2022-04-26 2:43 UTC (permalink / raw) To: dev Cc: qiming.yang, qi.z.zhang, stevex.yang, thomas, andrew.rybchenko, bruce.richardson, david.marchand, Robin Zhang Introduce a new telemetry command /ethdev/module_eeprom to show module EEPROM for each port. The format of module EEPROM information follows the SFF(Small Form Factor) Committee specifications. Current the format support SFP(Small Formfactor Pluggable)/SFP+/ QSFP+(Quad Small Formfactor Pluggable)/QSFP28 with specs SFF-8079/ SFF-8472/SFF-8024/SFF-8636. Afther run the /ethdev/module_eeprom command, telemetry client will show the module EEPROM information. We keep the same information content compare with Linux utility ethtool, refer to command 'ethtool -m' of ethtool v5.4. v5: - fix CI robot compile fail issue v4: - remove all printf in primary application, only show information in tememetry client - refine codes v3: - split up codes into several patches for better reivew Robin Zhang (5): ethdev: add telemetry command for module EEPROM ethdev: common utilities for different SFF specs ethdev: format module EEPROM for SFF-8079 ethdev: format module EEPROM for SFF-8472 ethdev: format module EEPROM for SFF-8636 lib/ethdev/ethdev_sff_telemetry.c | 142 ++++++ lib/ethdev/ethdev_sff_telemetry.h | 37 ++ lib/ethdev/meson.build | 5 + lib/ethdev/rte_ethdev.c | 3 + lib/ethdev/sff_8079.c | 407 ++++++++++++++++ lib/ethdev/sff_8472.c | 287 +++++++++++ lib/ethdev/sff_8636.c | 775 ++++++++++++++++++++++++++++++ lib/ethdev/sff_8636.h | 592 +++++++++++++++++++++++ lib/ethdev/sff_common.c | 326 +++++++++++++ lib/ethdev/sff_common.h | 174 +++++++ 10 files changed, 2748 insertions(+) create mode 100644 lib/ethdev/ethdev_sff_telemetry.c create mode 100644 lib/ethdev/ethdev_sff_telemetry.h create mode 100644 lib/ethdev/sff_8079.c create mode 100644 lib/ethdev/sff_8472.c create mode 100644 lib/ethdev/sff_8636.c create mode 100644 lib/ethdev/sff_8636.h create mode 100644 lib/ethdev/sff_common.c create mode 100644 lib/ethdev/sff_common.h -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v5 1/5] ethdev: add telemetry command for module EEPROM 2022-04-26 2:43 ` [PATCH v5 0/5] add telemetry command for show module EEPROM Robin Zhang @ 2022-04-26 2:43 ` Robin Zhang 2022-05-04 10:16 ` Andrew Rybchenko 2022-04-26 2:43 ` [PATCH v5 2/5] ethdev: common utilities for different SFF specs Robin Zhang ` (5 subsequent siblings) 6 siblings, 1 reply; 77+ messages in thread From: Robin Zhang @ 2022-04-26 2:43 UTC (permalink / raw) To: dev Cc: qiming.yang, qi.z.zhang, stevex.yang, thomas, andrew.rybchenko, bruce.richardson, david.marchand, Robin Zhang Add a new telemetry command /ethdev/module_eeprom to dump the module EEPROM of each port. The format of module EEPROM information follows the SFF(Small Form Factor) Committee specifications. Current the format support SFP(Small Formfactor Pluggable)/SFP+/ QSFP+(Quad Small Formfactor Pluggable)/QSFP28 with specs SFF-8079/ SFF-8472/SFF-8024/SFF-8636. Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/ethdev_sff_telemetry.c | 131 ++++++++++++++++++++++++++++++ lib/ethdev/ethdev_sff_telemetry.h | 37 +++++++++ lib/ethdev/meson.build | 1 + lib/ethdev/rte_ethdev.c | 3 + 4 files changed, 172 insertions(+) create mode 100644 lib/ethdev/ethdev_sff_telemetry.c create mode 100644 lib/ethdev/ethdev_sff_telemetry.h diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c new file mode 100644 index 0000000000..968b640b17 --- /dev/null +++ b/lib/ethdev/ethdev_sff_telemetry.c @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + */ + +#include <errno.h> + +#include <rte_ethdev.h> +#include <rte_common.h> +#include "ethdev_sff_telemetry.h" + +static uint16_t sff_item_count; + +static void +sff_port_module_eeprom_display(uint16_t port_id, struct sff_item *items) +{ + struct rte_eth_dev_module_info minfo; + struct rte_dev_eeprom_info einfo; + int ret; + + ret = rte_eth_dev_get_module_info(port_id, &minfo); + if (ret != 0) { + switch (ret) { + case -ENODEV: + RTE_ETHDEV_LOG(ERR, "port index %d invalid\n", port_id); + break; + case -ENOTSUP: + RTE_ETHDEV_LOG(ERR, "operation not supported by device\n"); + break; + case -EIO: + RTE_ETHDEV_LOG(ERR, "device is removed\n"); + break; + default: + RTE_ETHDEV_LOG(ERR, "Unable to get port %d EEPROM module info\n", ret); + break; + } + return; + } + + einfo.offset = 0; + einfo.length = minfo.eeprom_len; + einfo.data = calloc(1, minfo.eeprom_len); + if (einfo.data == NULL) { + RTE_ETHDEV_LOG(ERR, "Allocation of port %u eeprom data failed\n", port_id); + return; + } + + ret = rte_eth_dev_get_module_eeprom(port_id, &einfo); + if (ret != 0) { + switch (ret) { + case -ENODEV: + RTE_ETHDEV_LOG(ERR, "port index %d invalid\n", port_id); + break; + case -ENOTSUP: + RTE_ETHDEV_LOG(ERR, "operation not supported by device\n"); + break; + case -EIO: + RTE_ETHDEV_LOG(ERR, "device is removed\n"); + break; + default: + RTE_ETHDEV_LOG(ERR, "Unable to get port %d module EEPROM\n", ret); + break; + } + free(einfo.data); + return; + } + + switch (minfo.type) { + /* parsing module EEPROM data base on different module type */ + default: + RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); + break; + } + + free(einfo.data); +} + +void +add_item_string(struct sff_item *items, const char *name_str, const char *value_str) +{ + /* append different values for same keys */ + if (sff_item_count > 0 && + (strcmp(items[sff_item_count - 1].name, name_str) == 0)) { + strlcat(items[sff_item_count - 1].value, "; ", SFF_ITEM_VALUE_SIZE); + strlcat(items[sff_item_count - 1].value, value_str, SFF_ITEM_VALUE_SIZE); + return; + } + + snprintf(items[sff_item_count].name, SFF_ITEM_NAME_SIZE, "%s", name_str); + snprintf(items[sff_item_count].value, SFF_ITEM_VALUE_SIZE, "%s", value_str); + sff_item_count++; +} + +int +eth_dev_handle_port_module_eeprom(const char *cmd __rte_unused, const char *params, + struct rte_tel_data *d) +{ + char *end_param; + int port_id, i; + struct sff_item *items; + sff_item_count = 0; + + if (params == NULL || strlen(params) == 0 || !isdigit(*params)) + return -1; + + errno = 0; + port_id = strtoul(params, &end_param, 0); + + if (errno != 0) { + RTE_ETHDEV_LOG(ERR, "Invalid argument\n"); + return -1; + } + + if (*end_param != '\0') + RTE_ETHDEV_LOG(NOTICE, + "Extra parameters passed to ethdev telemetry command, ignoring"); + + items = calloc(1, sizeof(struct sff_item) * SFF_ITEM_MAX_COUNT); + if (items == NULL) { + RTE_ETHDEV_LOG(ERR, "Error allocating memory of items\n"); + return -1; + } + + sff_port_module_eeprom_display(port_id, items); + + rte_tel_data_start_dict(d); + for (i = 0; i < sff_item_count; i++) + rte_tel_data_add_dict_string(d, items[i].name, items[i].value); + + free(items); + return 0; +} diff --git a/lib/ethdev/ethdev_sff_telemetry.h b/lib/ethdev/ethdev_sff_telemetry.h new file mode 100644 index 0000000000..5788bd6e60 --- /dev/null +++ b/lib/ethdev/ethdev_sff_telemetry.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + */ + +#ifndef _ETHDEV_SFF_TELEMETRY_H_ +#define _ETHDEV_SFF_TELEMETRY_H_ + +#include <rte_telemetry.h> + +#define ARRAY_SIZE(arr) RTE_DIM(arr) + +#define SFF_ITEM_NAME_SIZE 64 +#define SFF_ITEM_VALUE_SIZE 256 +#define SFF_ITEM_MAX_COUNT 256 +#define SFF_ITEM_VAL_COMPOSE_SIZE 64 + +struct sff_item { + char name[SFF_ITEM_NAME_SIZE]; /* The item name. */ + char value[SFF_ITEM_VALUE_SIZE]; /* The item value. */ +}; + +/* SFF-8079 Optics diagnostics */ +void sff_8079_show_all(const uint8_t *data, struct sff_item *items); + +/* SFF-8472 Optics diagnostics */ +void sff_8472_show_all(const uint8_t *data, struct sff_item *items); + +/* SFF-8636 Optics diagnostics */ +void sff_8636_show_all(const uint8_t *data, uint32_t eeprom_len, struct sff_item *items); + +int eth_dev_handle_port_module_eeprom(const char *cmd __rte_unused, + const char *params, + struct rte_tel_data *d); + +void add_item_string(struct sff_item *items, const char *name_str, const char *value_str); + +#endif /* _ETHDEV_SFF_TELEMETRY_H_ */ diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index a094585bf7..49c77acb3f 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -11,6 +11,7 @@ sources = files( 'rte_flow.c', 'rte_mtr.c', 'rte_tm.c', + 'ethdev_sff_telemetry.c', ) headers = files( diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c index 29a3d80466..2b87df1b32 100644 --- a/lib/ethdev/rte_ethdev.c +++ b/lib/ethdev/rte_ethdev.c @@ -39,6 +39,7 @@ #include "ethdev_driver.h" #include "ethdev_profile.h" #include "ethdev_private.h" +#include "ethdev_sff_telemetry.h" struct rte_eth_dev rte_eth_devices[RTE_MAX_ETHPORTS]; @@ -5876,4 +5877,6 @@ RTE_INIT(ethdev_init_telemetry) "Returns the link status for a port. Parameters: int port_id"); rte_telemetry_register_cmd("/ethdev/info", eth_dev_handle_port_info, "Returns the device info for a port. Parameters: int port_id"); + rte_telemetry_register_cmd("/ethdev/module_eeprom", eth_dev_handle_port_module_eeprom, + "Returns module EEPROM info with SFF specs. Parameters: int port_id"); } -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v5 1/5] ethdev: add telemetry command for module EEPROM 2022-04-26 2:43 ` [PATCH v5 1/5] ethdev: add telemetry command for " Robin Zhang @ 2022-05-04 10:16 ` Andrew Rybchenko 0 siblings, 0 replies; 77+ messages in thread From: Andrew Rybchenko @ 2022-05-04 10:16 UTC (permalink / raw) To: Robin Zhang, dev Cc: qiming.yang, qi.z.zhang, stevex.yang, thomas, bruce.richardson, david.marchand On 4/26/22 05:43, Robin Zhang wrote: > Add a new telemetry command /ethdev/module_eeprom to dump the module > EEPROM of each port. The format of module EEPROM information follows > the SFF(Small Form Factor) Committee specifications. > > Current the format support SFP(Small Formfactor Pluggable)/SFP+/ > QSFP+(Quad Small Formfactor Pluggable)/QSFP28 with specs SFF-8079/ > SFF-8472/SFF-8024/SFF-8636. Above sounds misleading in the patch since support for some specs is added in subsequent patches. > > Signed-off-by: Robin Zhang <robinx.zhang@intel.com> There is a warning if I build just after the patch: [2/146] Compiling C object lib/librte_ethdev.a.p/ethdev_ethdev_sff_telemetry.c.o ../../src/dpdk/lib/ethdev/ethdev_sff_telemetry.c: In function ‘sff_port_module_eeprom_display’: ../../src/dpdk/lib/ethdev/ethdev_sff_telemetry.c:14:67: warning: unused parameter ‘items’ [-Wunused-parameter] 14 | sff_port_module_eeprom_display(uint16_t port_id, struct sff_item *items) | ~~~~~~~~~~~~~~~~~^~~~~ [snip] > diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c > new file mode 100644 > index 0000000000..968b640b17 > --- /dev/null > +++ b/lib/ethdev/ethdev_sff_telemetry.c > @@ -0,0 +1,131 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2022 Intel Corporation > + */ > + > +#include <errno.h> > + > +#include <rte_ethdev.h> > +#include <rte_common.h> > +#include "ethdev_sff_telemetry.h" > + > +static uint16_t sff_item_count; Do we really need the static variable? It raises too many questions about threadsafity and typically says that API is defined bad. You pass 'items' anywya. What's the problem to pass the count as well? > + > +static void > +sff_port_module_eeprom_display(uint16_t port_id, struct sff_item *items) > +{ > + struct rte_eth_dev_module_info minfo; > + struct rte_dev_eeprom_info einfo; > + int ret; > + > + ret = rte_eth_dev_get_module_info(port_id, &minfo); > + if (ret != 0) { > + switch (ret) { > + case -ENODEV: > + RTE_ETHDEV_LOG(ERR, "port index %d invalid\n", port_id); > + break; > + case -ENOTSUP: > + RTE_ETHDEV_LOG(ERR, "operation not supported by device\n"); > + break; > + case -EIO: > + RTE_ETHDEV_LOG(ERR, "device is removed\n"); > + break; > + default: > + RTE_ETHDEV_LOG(ERR, "Unable to get port %d EEPROM module info\n", ret); Above log message sounds like 'ret' contains port number. > + break; > + } > + return; > + } Close curly bracket is incorrectly aligned above. > + > + einfo.offset = 0; > + einfo.length = minfo.eeprom_len; > + einfo.data = calloc(1, minfo.eeprom_len); > + if (einfo.data == NULL) { > + RTE_ETHDEV_LOG(ERR, "Allocation of port %u eeprom data failed\n", port_id); > + return; > + } > + > + ret = rte_eth_dev_get_module_eeprom(port_id, &einfo); > + if (ret != 0) { > + switch (ret) { > + case -ENODEV: > + RTE_ETHDEV_LOG(ERR, "port index %d invalid\n", port_id); > + break; > + case -ENOTSUP: > + RTE_ETHDEV_LOG(ERR, "operation not supported by device\n"); > + break; > + case -EIO: > + RTE_ETHDEV_LOG(ERR, "device is removed\n"); > + break; > + default: > + RTE_ETHDEV_LOG(ERR, "Unable to get port %d module EEPROM\n", ret); same here > + break; > + } > + free(einfo.data); > + return; > + } > + > + switch (minfo.type) { > + /* parsing module EEPROM data base on different module type */ > + default: > + RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); > + break; > + } > + > + free(einfo.data); > +} > + > +void > +add_item_string(struct sff_item *items, const char *name_str, const char *value_str) > +{ > + /* append different values for same keys */ > + if (sff_item_count > 0 && > + (strcmp(items[sff_item_count - 1].name, name_str) == 0)) { Can we have the same key in on of previous item? > + strlcat(items[sff_item_count - 1].value, "; ", SFF_ITEM_VALUE_SIZE); > + strlcat(items[sff_item_count - 1].value, value_str, SFF_ITEM_VALUE_SIZE); > + return; > + } > + > + snprintf(items[sff_item_count].name, SFF_ITEM_NAME_SIZE, "%s", name_str); > + snprintf(items[sff_item_count].value, SFF_ITEM_VALUE_SIZE, "%s", value_str); If you just want to copy string, strlcpy() should be used. > + sff_item_count++; > +} > + > +int > +eth_dev_handle_port_module_eeprom(const char *cmd __rte_unused, const char *params, > + struct rte_tel_data *d) > +{ > + char *end_param; > + int port_id, i; > + struct sff_item *items; > + sff_item_count = 0; > + > + if (params == NULL || strlen(params) == 0 || !isdigit(*params)) > + return -1; > + > + errno = 0; > + port_id = strtoul(params, &end_param, 0); > + > + if (errno != 0) { > + RTE_ETHDEV_LOG(ERR, "Invalid argument\n"); > + return -1; > + } > + > + if (*end_param != '\0') > + RTE_ETHDEV_LOG(NOTICE, > + "Extra parameters passed to ethdev telemetry command, ignoring"); missing \n, also it would be useful to log these extra parameters. > + > + items = calloc(1, sizeof(struct sff_item) * SFF_ITEM_MAX_COUNT); Since you use calloc, it should be: items = calloc(SFF_ITEM_MAX_COUNT, sizeof(struct sff_item)); > + if (items == NULL) { > + RTE_ETHDEV_LOG(ERR, "Error allocating memory of items\n"); > + return -1; > + } > + > + sff_port_module_eeprom_display(port_id, items); Function name sounds like it prints out the information to terminal etc, but as I understand it just fill in items array. > + > + rte_tel_data_start_dict(d); > + for (i = 0; i < sff_item_count; i++) > + rte_tel_data_add_dict_string(d, items[i].name, items[i].value); What I really don't understand is why do we need intermediate storage at all? Can we add to telemetry dictionary from the very beginning? The only argument to use intermediate storage is "append to the same key", but since we check the last element only, I guess we can handle it easily inside the code. > + > + free(items); > + return 0; > +} > diff --git a/lib/ethdev/ethdev_sff_telemetry.h b/lib/ethdev/ethdev_sff_telemetry.h > new file mode 100644 > index 0000000000..5788bd6e60 > --- /dev/null > +++ b/lib/ethdev/ethdev_sff_telemetry.h > @@ -0,0 +1,37 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2022 Intel Corporation > + */ > + > +#ifndef _ETHDEV_SFF_TELEMETRY_H_ > +#define _ETHDEV_SFF_TELEMETRY_H_ > + > +#include <rte_telemetry.h> > + > +#define ARRAY_SIZE(arr) RTE_DIM(arr) What's the point to define it? You can use RTE_DIM() directly instead. > + > +#define SFF_ITEM_NAME_SIZE 64 > +#define SFF_ITEM_VALUE_SIZE 256 > +#define SFF_ITEM_MAX_COUNT 256 > +#define SFF_ITEM_VAL_COMPOSE_SIZE 64 Are above defines come from spec? If yes, please, add comments with references to spec. Or is it current implementation limitations? > + > +struct sff_item { > + char name[SFF_ITEM_NAME_SIZE]; /* The item name. */ > + char value[SFF_ITEM_VALUE_SIZE]; /* The item value. */ > +}; > + > +/* SFF-8079 Optics diagnostics */ > +void sff_8079_show_all(const uint8_t *data, struct sff_item *items); > + > +/* SFF-8472 Optics diagnostics */ > +void sff_8472_show_all(const uint8_t *data, struct sff_item *items); > + > +/* SFF-8636 Optics diagnostics */ > +void sff_8636_show_all(const uint8_t *data, uint32_t eeprom_len, struct sff_item *items); > + > +int eth_dev_handle_port_module_eeprom(const char *cmd __rte_unused, > + const char *params, > + struct rte_tel_data *d); > + > +void add_item_string(struct sff_item *items, const char *name_str, const char *value_str); The function name sounds too generic. Please, add sff_ prefix. May be just sff_add_item()? > + > +#endif /* _ETHDEV_SFF_TELEMETRY_H_ */ > diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build > index a094585bf7..49c77acb3f 100644 > --- a/lib/ethdev/meson.build > +++ b/lib/ethdev/meson.build > @@ -11,6 +11,7 @@ sources = files( > 'rte_flow.c', > 'rte_mtr.c', > 'rte_tm.c', > + 'ethdev_sff_telemetry.c', > ) > > headers = files( > diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c > index 29a3d80466..2b87df1b32 100644 > --- a/lib/ethdev/rte_ethdev.c > +++ b/lib/ethdev/rte_ethdev.c > @@ -39,6 +39,7 @@ > #include "ethdev_driver.h" > #include "ethdev_profile.h" > #include "ethdev_private.h" > +#include "ethdev_sff_telemetry.h" > > struct rte_eth_dev rte_eth_devices[RTE_MAX_ETHPORTS]; > > @@ -5876,4 +5877,6 @@ RTE_INIT(ethdev_init_telemetry) > "Returns the link status for a port. Parameters: int port_id"); > rte_telemetry_register_cmd("/ethdev/info", eth_dev_handle_port_info, > "Returns the device info for a port. Parameters: int port_id"); > + rte_telemetry_register_cmd("/ethdev/module_eeprom", eth_dev_handle_port_module_eeprom, > + "Returns module EEPROM info with SFF specs. Parameters: int port_id"); > } ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v5 2/5] ethdev: common utilities for different SFF specs 2022-04-26 2:43 ` [PATCH v5 0/5] add telemetry command for show module EEPROM Robin Zhang 2022-04-26 2:43 ` [PATCH v5 1/5] ethdev: add telemetry command for " Robin Zhang @ 2022-04-26 2:43 ` Robin Zhang 2022-04-26 2:43 ` [PATCH v5 3/5] ethdev: format module EEPROM for SFF-8079 Robin Zhang ` (4 subsequent siblings) 6 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-04-26 2:43 UTC (permalink / raw) To: dev Cc: qiming.yang, qi.z.zhang, stevex.yang, thomas, andrew.rybchenko, bruce.richardson, david.marchand, Robin Zhang This patch implements SFF-8024 Rev 4.0 of pluggable I/O configuration and some common utilities for SFF-8436/8636 and SFF-8472/8079. Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/meson.build | 1 + lib/ethdev/sff_common.c | 326 ++++++++++++++++++++++++++++++++++++++++ lib/ethdev/sff_common.h | 174 +++++++++++++++++++++ 3 files changed, 501 insertions(+) create mode 100644 lib/ethdev/sff_common.c create mode 100644 lib/ethdev/sff_common.h diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index 49c77acb3f..8f39739e43 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -12,6 +12,7 @@ sources = files( 'rte_mtr.c', 'rte_tm.c', 'ethdev_sff_telemetry.c', + 'sff_common.c', ) headers = files( diff --git a/lib/ethdev/sff_common.c b/lib/ethdev/sff_common.c new file mode 100644 index 0000000000..c9a0227205 --- /dev/null +++ b/lib/ethdev/sff_common.c @@ -0,0 +1,326 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8024 Rev 4.0 of pluggable I/O configuration and some + * common utilities for SFF-8436/8636 and SFF-8472/8079 + * + */ + +#include <stdio.h> +#include <math.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "ethdev_sff_telemetry.h" + + +double convert_mw_to_dbm(double mw) +{ + return (10. * log10(mw / 1000.)) + 30.; +} + +void sff_show_value_with_unit(const uint8_t *data, unsigned int reg, + const char *name, unsigned int mult, + const char *unit, struct sff_item *items) +{ + unsigned int val = data[reg]; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "%u%s", val * mult, unit); + add_item_string(items, name, val_string); +} + +void sff_show_ascii(const uint8_t *data, unsigned int first_reg, + unsigned int last_reg, const char *name, struct sff_item *items) +{ + unsigned int reg, val; + char tmp[3]; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + memset(val_string, 0, sizeof(val_string)); + + while (first_reg <= last_reg && data[last_reg] == ' ') + last_reg--; + for (reg = first_reg; reg <= last_reg; reg++) { + val = data[reg]; + if ((val >= 32) && (val <= 126)) { + snprintf(tmp, sizeof(tmp), "%c", val); + strlcat(val_string, tmp, sizeof(val_string)); + } else { + strlcat(val_string, "_", sizeof(val_string)); + } + } + add_item_string(items, name, val_string); +} + +void sff_8024_show_oui(const uint8_t *data, int id_offset, struct sff_item *items) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "%02x:%02x:%02x", + data[id_offset], data[(id_offset) + 1], data[(id_offset) + 2]); + add_item_string(items, "Vendor OUI", val_string); +} + +void sff_8024_show_identifier(const uint8_t *data, int id_offset, struct sff_item *items) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[id_offset]); + + switch (data[id_offset]) { + case SFF_8024_ID_UNKNOWN: + strlcat(val_string, " (no module present, unknown, or unspecified)", + sizeof(val_string)); + break; + case SFF_8024_ID_GBIC: + strlcat(val_string, " (GBIC)", sizeof(val_string)); + break; + case SFF_8024_ID_SOLDERED_MODULE: + strlcat(val_string, " (module soldered to motherboard)", sizeof(val_string)); + break; + case SFF_8024_ID_SFP: + strlcat(val_string, " (SFP)", sizeof(val_string)); + break; + case SFF_8024_ID_300_PIN_XBI: + strlcat(val_string, " (300 pin XBI)", sizeof(val_string)); + break; + case SFF_8024_ID_XENPAK: + strlcat(val_string, " (XENPAK)", sizeof(val_string)); + break; + case SFF_8024_ID_XFP: + strlcat(val_string, " (XFP)", sizeof(val_string)); + break; + case SFF_8024_ID_XFF: + strlcat(val_string, " (XFF)", sizeof(val_string)); + break; + case SFF_8024_ID_XFP_E: + strlcat(val_string, " (XFP-E)", sizeof(val_string)); + break; + case SFF_8024_ID_XPAK: + strlcat(val_string, " (XPAK)", sizeof(val_string)); + break; + case SFF_8024_ID_X2: + strlcat(val_string, " (X2)", sizeof(val_string)); + break; + case SFF_8024_ID_DWDM_SFP: + strlcat(val_string, " (DWDM-SFP)", sizeof(val_string)); + break; + case SFF_8024_ID_QSFP: + strlcat(val_string, " (QSFP)", sizeof(val_string)); + break; + case SFF_8024_ID_QSFP_PLUS: + strlcat(val_string, " (QSFP+)", sizeof(val_string)); + break; + case SFF_8024_ID_CXP: + strlcat(val_string, " (CXP)", sizeof(val_string)); + break; + case SFF_8024_ID_HD4X: + strlcat(val_string, " (Shielded Mini Multilane HD 4X)", sizeof(val_string)); + break; + case SFF_8024_ID_HD8X: + strlcat(val_string, " (Shielded Mini Multilane HD 8X)", sizeof(val_string)); + break; + case SFF_8024_ID_QSFP28: + strlcat(val_string, " (QSFP28)", sizeof(val_string)); + break; + case SFF_8024_ID_CXP2: + strlcat(val_string, " (CXP2/CXP28)", sizeof(val_string)); + break; + case SFF_8024_ID_CDFP: + strlcat(val_string, " (CDFP Style 1/Style 2)", sizeof(val_string)); + break; + case SFF_8024_ID_HD4X_FANOUT: + strlcat(val_string, " (Shielded Mini Multilane HD 4X Fanout Cable)", + sizeof(val_string)); + break; + case SFF_8024_ID_HD8X_FANOUT: + strlcat(val_string, " (Shielded Mini Multilane HD 8X Fanout Cable)", + sizeof(val_string)); + break; + case SFF_8024_ID_CDFP_S3: + strlcat(val_string, " (CDFP Style 3)", sizeof(val_string)); + break; + case SFF_8024_ID_MICRO_QSFP: + strlcat(val_string, " (microQSFP)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + add_item_string(items, "Identifier", val_string); +} + +void sff_8024_show_connector(const uint8_t *data, int ctor_offset, struct sff_item *items) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[ctor_offset]); + + switch (data[ctor_offset]) { + case SFF_8024_CTOR_UNKNOWN: + strlcat(val_string, " (unknown or unspecified)", sizeof(val_string)); + break; + case SFF_8024_CTOR_SC: + strlcat(val_string, " (SC)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FC_STYLE_1: + strlcat(val_string, " (Fibre Channel Style 1 copper)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FC_STYLE_2: + strlcat(val_string, " (Fibre Channel Style 2 copper)", sizeof(val_string)); + break; + case SFF_8024_CTOR_BNC_TNC: + strlcat(val_string, " (BNC/TNC)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FC_COAX: + strlcat(val_string, " (Fibre Channel coaxial headers)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FIBER_JACK: + strlcat(val_string, " (FibreJack)", sizeof(val_string)); + break; + case SFF_8024_CTOR_LC: + strlcat(val_string, " (LC)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MT_RJ: + strlcat(val_string, " (MT-RJ)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MU: + strlcat(val_string, " (MU)", sizeof(val_string)); + break; + case SFF_8024_CTOR_SG: + strlcat(val_string, " (SG)", sizeof(val_string)); + break; + case SFF_8024_CTOR_OPT_PT: + strlcat(val_string, " (Optical pigtail)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MPO: + strlcat(val_string, " (MPO Parallel Optic)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MPO_2: + strlcat(val_string, " (MPO Parallel Optic - 2x16)", sizeof(val_string)); + break; + case SFF_8024_CTOR_HSDC_II: + strlcat(val_string, " (HSSDC II)", sizeof(val_string)); + break; + case SFF_8024_CTOR_COPPER_PT: + strlcat(val_string, " (Copper pigtail)", sizeof(val_string)); + break; + case SFF_8024_CTOR_RJ45: + strlcat(val_string, " (RJ45)", sizeof(val_string)); + break; + case SFF_8024_CTOR_NO_SEPARABLE: + strlcat(val_string, " (No separable connector)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MXC_2x16: + strlcat(val_string, " (MXC 2x16)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + add_item_string(items, "Connector", val_string); +} + +void sff_8024_show_encoding(const uint8_t *data, int encoding_offset, + int sff_type, struct sff_item *items) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[encoding_offset]); + + switch (data[encoding_offset]) { + case SFF_8024_ENCODING_UNSPEC: + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_8B10B: + strlcat(val_string, " (8B/10B)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_4B5B: + strlcat(val_string, " (4B/5B)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_NRZ: + strlcat(val_string, " (NRZ)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_4h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) + strlcat(val_string, " (Manchester)", sizeof(val_string)); + else if (sff_type == RTE_ETH_MODULE_SFF_8636) + strlcat(val_string, " (SONET Scrambled)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_5h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) + strlcat(val_string, " (SONET Scrambled)", sizeof(val_string)); + else if (sff_type == RTE_ETH_MODULE_SFF_8636) + strlcat(val_string, " (64B/66B)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_6h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) + strlcat(val_string, " (64B/66B)", sizeof(val_string)); + else if (sff_type == RTE_ETH_MODULE_SFF_8636) + strlcat(val_string, " (Manchester)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_256B: + strlcat(val_string, + " ((256B/257B (transcoded FEC-enabled data))", sizeof(val_string)); + break; + case SFF_8024_ENCODING_PAM4: + strlcat(val_string, " (PAM4)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + add_item_string(items, "Encoding", val_string); +} + +void sff_show_thresholds(struct sff_diags sd, struct sff_item *items) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + SPRINT_BIAS(val_string, sd.bias_cur[HALRM]); + add_item_string(items, "Laser bias current high alarm threshold", val_string); + SPRINT_BIAS(val_string, sd.bias_cur[LALRM]); + add_item_string(items, "Laser bias current low alarm threshold", val_string); + SPRINT_BIAS(val_string, sd.bias_cur[HWARN]); + add_item_string(items, "Laser bias current high warning threshold", val_string); + SPRINT_BIAS(val_string, sd.bias_cur[LWARN]); + add_item_string(items, "Laser bias current low warning threshold", val_string); + + SPRINT_xX_PWR(val_string, sd.tx_power[HALRM]); + add_item_string(items, "Laser output power high alarm threshold", val_string); + SPRINT_xX_PWR(val_string, sd.tx_power[LALRM]); + add_item_string(items, "Laser output power low alarm threshold", val_string); + SPRINT_xX_PWR(val_string, sd.tx_power[HWARN]); + add_item_string(items, "Laser output power high warning threshold", val_string); + SPRINT_xX_PWR(val_string, sd.tx_power[LWARN]); + add_item_string(items, "Laser output power low warning threshold", val_string); + + SPRINT_TEMP(val_string, sd.sfp_temp[HALRM]); + add_item_string(items, "Module temperature high alarm threshold", val_string); + SPRINT_TEMP(val_string, sd.sfp_temp[LALRM]); + add_item_string(items, "Module temperature low alarm threshold", val_string); + SPRINT_TEMP(val_string, sd.sfp_temp[HWARN]); + add_item_string(items, "Module temperature high warning threshold", val_string); + SPRINT_TEMP(val_string, sd.sfp_temp[LWARN]); + add_item_string(items, "Module temperature low warning threshold", val_string); + + SPRINT_VCC(val_string, sd.sfp_voltage[HALRM]); + add_item_string(items, "Module voltage high alarm threshold", val_string); + SPRINT_VCC(val_string, sd.sfp_voltage[LALRM]); + add_item_string(items, "Module voltage low alarm threshold", val_string); + SPRINT_VCC(val_string, sd.sfp_voltage[HWARN]); + add_item_string(items, "Module voltage high warning threshold", val_string); + SPRINT_VCC(val_string, sd.sfp_voltage[LWARN]); + add_item_string(items, "Module voltage low alarm threshold", val_string); + + SPRINT_xX_PWR(val_string, sd.rx_power[HALRM]); + add_item_string(items, "Laser rx power high alarm threshold", val_string); + SPRINT_xX_PWR(val_string, sd.rx_power[LALRM]); + add_item_string(items, "Laser rx power low alarm threshold", val_string); + SPRINT_xX_PWR(val_string, sd.rx_power[HWARN]); + add_item_string(items, "Laser rx power high warning threshold", val_string); + SPRINT_xX_PWR(val_string, sd.rx_power[LWARN]); + add_item_string(items, "Laser rx power low warning threshold", val_string); +} diff --git a/lib/ethdev/sff_common.h b/lib/ethdev/sff_common.h new file mode 100644 index 0000000000..877d5e54e4 --- /dev/null +++ b/lib/ethdev/sff_common.h @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8024 Rev 4.0 of pluggable I/O configuration and some + * common utilities for SFF-8436/8636 and SFF-8472/8079 + * + */ + +#ifndef _SFF_COMMON_H_ +#define _SFF_COMMON_H_ + +#include <stdio.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "ethdev_sff_telemetry.h" + +#define SFF_8024_ID_OFFSET 0x00 +#define SFF_8024_ID_UNKNOWN 0x00 +#define SFF_8024_ID_GBIC 0x01 +#define SFF_8024_ID_SOLDERED_MODULE 0x02 +#define SFF_8024_ID_SFP 0x03 +#define SFF_8024_ID_300_PIN_XBI 0x04 +#define SFF_8024_ID_XENPAK 0x05 +#define SFF_8024_ID_XFP 0x06 +#define SFF_8024_ID_XFF 0x07 +#define SFF_8024_ID_XFP_E 0x08 +#define SFF_8024_ID_XPAK 0x09 +#define SFF_8024_ID_X2 0x0A +#define SFF_8024_ID_DWDM_SFP 0x0B +#define SFF_8024_ID_QSFP 0x0C +#define SFF_8024_ID_QSFP_PLUS 0x0D +#define SFF_8024_ID_CXP 0x0E +#define SFF_8024_ID_HD4X 0x0F +#define SFF_8024_ID_HD8X 0x10 +#define SFF_8024_ID_QSFP28 0x11 +#define SFF_8024_ID_CXP2 0x12 +#define SFF_8024_ID_CDFP 0x13 +#define SFF_8024_ID_HD4X_FANOUT 0x14 +#define SFF_8024_ID_HD8X_FANOUT 0x15 +#define SFF_8024_ID_CDFP_S3 0x16 +#define SFF_8024_ID_MICRO_QSFP 0x17 +#define SFF_8024_ID_LAST SFF_8024_ID_MICRO_QSFP +#define SFF_8024_ID_UNALLOCATED_LAST 0x7F +#define SFF_8024_ID_VENDOR_START 0x80 +#define SFF_8024_ID_VENDOR_LAST 0xFF + +#define SFF_8024_CTOR_UNKNOWN 0x00 +#define SFF_8024_CTOR_SC 0x01 +#define SFF_8024_CTOR_FC_STYLE_1 0x02 +#define SFF_8024_CTOR_FC_STYLE_2 0x03 +#define SFF_8024_CTOR_BNC_TNC 0x04 +#define SFF_8024_CTOR_FC_COAX 0x05 +#define SFF_8024_CTOR_FIBER_JACK 0x06 +#define SFF_8024_CTOR_LC 0x07 +#define SFF_8024_CTOR_MT_RJ 0x08 +#define SFF_8024_CTOR_MU 0x09 +#define SFF_8024_CTOR_SG 0x0A +#define SFF_8024_CTOR_OPT_PT 0x0B +#define SFF_8024_CTOR_MPO 0x0C +#define SFF_8024_CTOR_MPO_2 0x0D +/* 0E-1Fh --- Reserved */ +#define SFF_8024_CTOR_HSDC_II 0x20 +#define SFF_8024_CTOR_COPPER_PT 0x21 +#define SFF_8024_CTOR_RJ45 0x22 +#define SFF_8024_CTOR_NO_SEPARABLE 0x23 +#define SFF_8024_CTOR_MXC_2x16 0x24 +#define SFF_8024_CTOR_LAST SFF_8024_CTOR_MXC_2x16 +#define SFF_8024_CTOR_UNALLOCATED_LAST 0x7F +#define SFF_8024_CTOR_VENDOR_START 0x80 +#define SFF_8024_CTOR_VENDOR_LAST 0xFF + +/* ENCODING Values */ +#define SFF_8024_ENCODING_UNSPEC 0x00 +#define SFF_8024_ENCODING_8B10B 0x01 +#define SFF_8024_ENCODING_4B5B 0x02 +#define SFF_8024_ENCODING_NRZ 0x03 +/* + * Value: 04h + * SFF-8472 - Manchester + * SFF-8436/8636 - SONET Scrambled + */ +#define SFF_8024_ENCODING_4h 0x04 +/* + * Value: 05h + * SFF-8472 - SONET Scrambled + * SFF-8436/8636 - 64B/66B + */ +#define SFF_8024_ENCODING_5h 0x05 +/* + * Value: 06h + * SFF-8472 - 64B/66B + * SFF-8436/8636 - Manchester + */ +#define SFF_8024_ENCODING_6h 0x06 +#define SFF_8024_ENCODING_256B 0x07 +#define SFF_8024_ENCODING_PAM4 0x08 + +/* Most common case: 16-bit unsigned integer in a certain unit */ +#define OFFSET_TO_U16(offset) \ + (data[offset] << 8 | data[(offset) + 1]) + +#define SPRINT_xX_PWR(str, var) \ + snprintf(str, sizeof(str), "%.4f mW / %.2f dBm", \ + (double)((var) / 10000.), \ + convert_mw_to_dbm((double)((var) / 10000.))) + +#define SPRINT_BIAS(str, bias_cur) \ + snprintf(str, sizeof(str), "%.3f mA", (double)(bias_cur / 500.)) + +#define SPRINT_TEMP(str, temp) \ + snprintf(str, sizeof(str), "%.2f degrees C / %.2f degrees F", \ + (double)(temp / 256.), \ + (double)(temp / 256. * 1.8 + 32.)) + +#define SPRINT_VCC(str, sfp_voltage) \ + snprintf(str, sizeof(str), "%.4f V", (double)(sfp_voltage / 10000.)) + +/* Channel Monitoring Fields */ +struct sff_channel_diags { + uint16_t bias_cur; /* Measured bias current in 2uA units */ + uint16_t rx_power; /* Measured RX Power */ + uint16_t tx_power; /* Measured TX Power */ +}; + +/* Module Monitoring Fields */ +struct sff_diags { + +#define MAX_CHANNEL_NUM 4 +#define LWARN 0 +#define HWARN 1 +#define LALRM 2 +#define HALRM 3 +#define MCURR 4 + + /* Supports DOM */ + uint8_t supports_dom; + /* Supports alarm/warning thold */ + uint8_t supports_alarms; + /* RX Power: 0 = OMA, 1 = Average power */ + uint8_t rx_power_type; + /* TX Power: 0 = Not supported, 1 = Average power */ + uint8_t tx_power_type; + + uint8_t calibrated_ext; /* Is externally calibrated */ + /* [5] tables are low/high warn, low/high alarm, current */ + /* SFP voltage in 0.1mV units */ + uint16_t sfp_voltage[5]; + /* SFP Temp in 16-bit signed 1/256 Celcius */ + int16_t sfp_temp[5]; + /* Measured bias current in 2uA units */ + uint16_t bias_cur[5]; + /* Measured TX Power */ + uint16_t tx_power[5]; + /* Measured RX Power */ + uint16_t rx_power[5]; + struct sff_channel_diags scd[MAX_CHANNEL_NUM]; +}; + +double convert_mw_to_dbm(double mw); +void sff_show_value_with_unit(const uint8_t *data, unsigned int reg, + const char *name, unsigned int mult, + const char *unit, struct sff_item *items); +void sff_show_ascii(const uint8_t *data, unsigned int first_reg, + unsigned int last_reg, const char *name, struct sff_item *items); +void sff_show_thresholds(struct sff_diags sd, struct sff_item *items); + +void sff_8024_show_oui(const uint8_t *data, int id_offset, struct sff_item *items); +void sff_8024_show_identifier(const uint8_t *data, int id_offset, struct sff_item *items); +void sff_8024_show_connector(const uint8_t *data, int ctor_offset, struct sff_item *items); +void sff_8024_show_encoding(const uint8_t *data, int encoding_offset, + int sff_type, struct sff_item *items); + +#endif /* _SFF_COMMON_H_ */ -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v5 3/5] ethdev: format module EEPROM for SFF-8079 2022-04-26 2:43 ` [PATCH v5 0/5] add telemetry command for show module EEPROM Robin Zhang 2022-04-26 2:43 ` [PATCH v5 1/5] ethdev: add telemetry command for " Robin Zhang 2022-04-26 2:43 ` [PATCH v5 2/5] ethdev: common utilities for different SFF specs Robin Zhang @ 2022-04-26 2:43 ` Robin Zhang 2022-04-26 2:43 ` [PATCH v5 4/5] ethdev: format module EEPROM for SFF-8472 Robin Zhang ` (3 subsequent siblings) 6 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-04-26 2:43 UTC (permalink / raw) To: dev Cc: qiming.yang, qi.z.zhang, stevex.yang, thomas, andrew.rybchenko, bruce.richardson, david.marchand, Robin Zhang This patch implements format module EEPROM information for SFF-8079 Rev 1.7 Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/ethdev_sff_telemetry.c | 3 + lib/ethdev/meson.build | 1 + lib/ethdev/sff_8079.c | 407 ++++++++++++++++++++++++++++++ 3 files changed, 411 insertions(+) create mode 100644 lib/ethdev/sff_8079.c diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c index 968b640b17..c09352959c 100644 --- a/lib/ethdev/ethdev_sff_telemetry.c +++ b/lib/ethdev/ethdev_sff_telemetry.c @@ -66,6 +66,9 @@ sff_port_module_eeprom_display(uint16_t port_id, struct sff_item *items) switch (minfo.type) { /* parsing module EEPROM data base on different module type */ + case RTE_ETH_MODULE_SFF_8079: + sff_8079_show_all(einfo.data, items); + break; default: RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); break; diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index 8f39739e43..d94860da0c 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -13,6 +13,7 @@ sources = files( 'rte_tm.c', 'ethdev_sff_telemetry.c', 'sff_common.c', + 'sff_8079.c', ) headers = files( diff --git a/lib/ethdev/sff_8079.c b/lib/ethdev/sff_8079.c new file mode 100644 index 0000000000..b6736da29e --- /dev/null +++ b/lib/ethdev/sff_8079.c @@ -0,0 +1,407 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8079 optics diagnostics. + * + */ + +#include <stdio.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "ethdev_sff_telemetry.h" + +static void sff_8079_show_identifier(const uint8_t *data, struct sff_item *items) +{ + sff_8024_show_identifier(data, 0, items); +} + +static void sff_8079_show_ext_identifier(const uint8_t *data, struct sff_item *items) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[1]); + if (data[1] == 0x00) + strlcat(val_string, " (GBIC not specified / not MOD_DEF compliant)", + sizeof(val_string)); + else if (data[1] == 0x04) + strlcat(val_string, " (GBIC/SFP defined by 2-wire interface ID)", + sizeof(val_string)); + else if (data[1] <= 0x07) { + char tmp[SFF_ITEM_VAL_COMPOSE_SIZE]; + snprintf(tmp, sizeof(tmp), " (GBIC compliant with MOD_DEF %u)", data[1]); + strlcat(val_string, tmp, sizeof(val_string)); + } else + strlcat(val_string, " (unknown)", sizeof(val_string)); + add_item_string(items, "Extended identifier", val_string); +} + +static void sff_8079_show_connector(const uint8_t *data, struct sff_item *items) +{ + sff_8024_show_connector(data, 2, items); +} + +static void sff_8079_show_transceiver(const uint8_t *data, struct sff_item *items) +{ + static const char *name = "Transceiver type"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), + "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[36]); + add_item_string(items, "Transceiver codes", val_string); + + /* 10G Ethernet Compliance Codes */ + if (data[3] & (1 << 7)) + add_item_string(items, "10G Ethernet transceiver type", + "10G Ethernet: 10G Base-ER [SFF-8472 rev10.4 onwards]"); + if (data[3] & (1 << 6)) + add_item_string(items, name, "10G Ethernet: 10G Base-LRM"); + if (data[3] & (1 << 5)) + add_item_string(items, name, "10G Ethernet: 10G Base-LR"); + if (data[3] & (1 << 4)) + add_item_string(items, name, "10G Ethernet: 10G Base-SR"); + + /* Infiniband Compliance Codes */ + if (data[3] & (1 << 3)) + add_item_string(items, name, "Infiniband: 1X SX"); + if (data[3] & (1 << 2)) + add_item_string(items, name, "Infiniband: 1X LX"); + if (data[3] & (1 << 1)) + add_item_string(items, name, "Infiniband: 1X Copper Active"); + if (data[3] & (1 << 0)) + add_item_string(items, name, "Infiniband: 1X Copper Passive"); + + /* ESCON Compliance Codes */ + if (data[4] & (1 << 7)) + add_item_string(items, name, "ESCON: ESCON MMF, 1310nm LED"); + if (data[4] & (1 << 6)) + add_item_string(items, name, "ESCON: ESCON SMF, 1310nm Laser"); + + /* SONET Compliance Codes */ + if (data[4] & (1 << 5)) + add_item_string(items, name, "SONET: OC-192, short reach"); + if (data[4] & (1 << 4)) + add_item_string(items, name, "SONET: SONET reach specifier bit 1"); + if (data[4] & (1 << 3)) + add_item_string(items, name, "SONET: SONET reach specifier bit 2"); + if (data[4] & (1 << 2)) + add_item_string(items, name, "SONET: OC-48, long reach"); + if (data[4] & (1 << 1)) + add_item_string(items, name, "SONET: OC-48, intermediate reach"); + if (data[4] & (1 << 0)) + add_item_string(items, name, "SONET: OC-48, short reach"); + if (data[5] & (1 << 6)) + add_item_string(items, name, "SONET: OC-12, single mode, long reach"); + if (data[5] & (1 << 5)) + add_item_string(items, name, "SONET: OC-12, single mode, inter. reach"); + if (data[5] & (1 << 4)) + add_item_string(items, name, "SONET: OC-12, short reach"); + if (data[5] & (1 << 2)) + add_item_string(items, name, "SONET: OC-3, single mode, long reach"); + if (data[5] & (1 << 1)) + add_item_string(items, name, "SONET: OC-3, single mode, inter. reach"); + if (data[5] & (1 << 0)) + add_item_string(items, name, "SONET: OC-3, short reach"); + + /* Ethernet Compliance Codes */ + if (data[6] & (1 << 7)) + add_item_string(items, name, "Ethernet: BASE-PX"); + if (data[6] & (1 << 6)) + add_item_string(items, name, "Ethernet: BASE-BX10"); + if (data[6] & (1 << 5)) + add_item_string(items, name, "Ethernet: 100BASE-FX"); + if (data[6] & (1 << 4)) + add_item_string(items, name, "Ethernet: 100BASE-LX/LX10"); + if (data[6] & (1 << 3)) + add_item_string(items, name, "Ethernet: 1000BASE-T"); + if (data[6] & (1 << 2)) + add_item_string(items, name, "Ethernet: 1000BASE-CX"); + if (data[6] & (1 << 1)) + add_item_string(items, name, "Ethernet: 1000BASE-LX"); + if (data[6] & (1 << 0)) + add_item_string(items, name, "Ethernet: 1000BASE-SX"); + + /* Fibre Channel link length */ + if (data[7] & (1 << 7)) + add_item_string(items, name, "FC: very long distance (V)"); + if (data[7] & (1 << 6)) + add_item_string(items, name, "FC: short distance (S)"); + if (data[7] & (1 << 5)) + add_item_string(items, name, "FC: intermediate distance (I)"); + if (data[7] & (1 << 4)) + add_item_string(items, name, "FC: long distance (L)"); + if (data[7] & (1 << 3)) + add_item_string(items, name, "FC: medium distance (M)"); + + /* Fibre Channel transmitter technology */ + if (data[7] & (1 << 2)) + add_item_string(items, name, "FC: Shortwave laser, linear Rx (SA)"); + if (data[7] & (1 << 1)) + add_item_string(items, name, "FC: Longwave laser (LC)"); + if (data[7] & (1 << 0)) + add_item_string(items, name, "FC: Electrical inter-enclosure (EL)"); + if (data[8] & (1 << 7)) + add_item_string(items, name, "FC: Electrical intra-enclosure (EL)"); + if (data[8] & (1 << 6)) + add_item_string(items, name, "FC: Shortwave laser w/o OFC (SN)"); + if (data[8] & (1 << 5)) + add_item_string(items, name, "FC: Shortwave laser with OFC (SL)"); + if (data[8] & (1 << 4)) + add_item_string(items, name, "FC: Longwave laser (LL)"); + if (data[8] & (1 << 3)) + add_item_string(items, name, "Active Cable"); + if (data[8] & (1 << 2)) + add_item_string(items, name, "Passive Cable"); + if (data[8] & (1 << 1)) + add_item_string(items, name, "FC: Copper FC-BaseT"); + + /* Fibre Channel transmission media */ + if (data[9] & (1 << 7)) + add_item_string(items, name, "FC: Twin Axial Pair (TW)"); + if (data[9] & (1 << 6)) + add_item_string(items, name, "FC: Twisted Pair (TP)"); + if (data[9] & (1 << 5)) + add_item_string(items, name, "FC: Miniature Coax (MI)"); + if (data[9] & (1 << 4)) + add_item_string(items, name, "FC: Video Coax (TV)"); + if (data[9] & (1 << 3)) + add_item_string(items, name, "FC: Multimode, 62.5um (M6)"); + if (data[9] & (1 << 2)) + add_item_string(items, name, "FC: Multimode, 50um (M5)"); + if (data[9] & (1 << 0)) + add_item_string(items, name, "FC: Single Mode (SM)"); + + /* Fibre Channel speed */ + if (data[10] & (1 << 7)) + add_item_string(items, name, "FC: 1200 MBytes/sec"); + if (data[10] & (1 << 6)) + add_item_string(items, name, "FC: 800 MBytes/sec"); + if (data[10] & (1 << 4)) + add_item_string(items, name, "FC: 400 MBytes/sec"); + if (data[10] & (1 << 2)) + add_item_string(items, name, "FC: 200 MBytes/sec"); + if (data[10] & (1 << 0)) + add_item_string(items, name, "FC: 100 MBytes/sec"); + + /* Extended Specification Compliance Codes from SFF-8024 */ + switch (data[36]) { + case 0x1: + add_item_string(items, name, + "Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)"); + break; + case 0x2: + add_item_string(items, name, "Extended: 100G Base-SR4 or 25GBase-SR"); + break; + case 0x3: + add_item_string(items, name, "Extended: 100G Base-LR4 or 25GBase-LR"); + break; + case 0x4: + add_item_string(items, name, "Extended: 100G Base-ER4 or 25GBase-ER"); + break; + case 0x8: + add_item_string(items, name, + "Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)"); + break; + case 0xb: + add_item_string(items, name, "Extended: 100G Base-CR4 or 25G Base-CR CA-L"); + break; + case 0xc: + add_item_string(items, name, "Extended: 25G Base-CR CA-S"); + break; + case 0xd: + add_item_string(items, name, "Extended: 25G Base-CR CA-N"); + break; + case 0x16: + add_item_string(items, name, "Extended: 10Gbase-T with SFI electrical interface"); + break; + case 0x18: + add_item_string(items, name, + "Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)"); + break; + case 0x19: + add_item_string(items, name, + "Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)"); + break; + case 0x1c: + add_item_string(items, name, "Extended: 10Gbase-T Short Reach"); + break; + default: + break; + } +} + +static void sff_8079_show_encoding(const uint8_t *data, struct sff_item *items) +{ + sff_8024_show_encoding(data, 11, RTE_ETH_MODULE_SFF_8472, items); +} + +static void sff_8079_show_rate_identifier(const uint8_t *data, struct sff_item *items) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[13]); + + switch (data[13]) { + case 0x00: + printf(" (unspecified)\n"); + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case 0x01: + strlcat(val_string, " (4/2/1G Rate_Select & AS0/AS1)", sizeof(val_string)); + break; + case 0x02: + strlcat(val_string, " (8/4/2G Rx Rate_Select only)", sizeof(val_string)); + break; + case 0x03: + strlcat(val_string, " (8/4/2G Independent Rx & Tx Rate_Select)", + sizeof(val_string)); + break; + case 0x04: + strlcat(val_string, " (8/4/2G Tx Rate_Select only)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + add_item_string(items, "Rate identifier", val_string); +} + +static void sff_8079_show_oui(const uint8_t *data, struct sff_item *items) +{ + sff_8024_show_oui(data, 37, items); +} + +static void +sff_8079_show_wavelength_or_copper_compliance(const uint8_t *data, + struct sff_item *items) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + if (data[8] & (1 << 2)) { + snprintf(val_string, sizeof(val_string), "0x%02x", data[60]); + switch (data[60]) { + case 0x00: + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case 0x01: + strlcat(val_string, " (SFF-8431 appendix E)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (unknown)", sizeof(val_string)); + break; + } + strlcat(val_string, " [SFF-8472 rev10.4 only]", sizeof(val_string)); + add_item_string(items, "Passive Cu cmplnce.", val_string); + } else if (data[8] & (1 << 3)) { + snprintf(val_string, sizeof(val_string), "0x%02x", data[60]); + switch (data[60]) { + case 0x00: + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case 0x01: + strlcat(val_string, " (SFF-8431 appendix E)", sizeof(val_string)); + break; + case 0x04: + strlcat(val_string, " (SFF-8431 limiting)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (unknown)", sizeof(val_string)); + break; + } + strlcat(val_string, " [SFF-8472 rev10.4 only]", sizeof(val_string)); + add_item_string(items, "Active Cu cmplnce.", val_string); + } else { + snprintf(val_string, sizeof(val_string), "%unm", (data[60] << 8) | data[61]); + add_item_string(items, "Laser wavelength", val_string); + } +} + +static void sff_8079_show_options(const uint8_t *data, struct sff_item *items) +{ + static const char *name = "Option"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x 0x%02x", data[64], data[65]); + add_item_string(items, "Option values", val_string); + + if (data[65] & (1 << 1)) + add_item_string(items, name, "RX_LOS implemented"); + if (data[65] & (1 << 2)) + add_item_string(items, name, "RX_LOS implemented, inverted"); + if (data[65] & (1 << 3)) + add_item_string(items, name, "TX_FAULT implemented"); + if (data[65] & (1 << 4)) + add_item_string(items, name, "TX_DISABLE implemented"); + if (data[65] & (1 << 5)) + add_item_string(items, name, "RATE_SELECT implemented"); + if (data[65] & (1 << 6)) + add_item_string(items, name, "Tunable transmitter technology"); + if (data[65] & (1 << 7)) + add_item_string(items, name, "Receiver decision threshold implemented"); + if (data[64] & (1 << 0)) + add_item_string(items, name, "Linear receiver output implemented"); + if (data[64] & (1 << 1)) + add_item_string(items, name, "Power level 2 requirement"); + if (data[64] & (1 << 2)) + add_item_string(items, name, "Cooled transceiver implemented"); + if (data[64] & (1 << 3)) + add_item_string(items, name, "Retimer or CDR implemented"); + if (data[64] & (1 << 4)) + add_item_string(items, name, "Paging implemented"); + if (data[64] & (1 << 5)) + add_item_string(items, name, "Power level 3 requirement"); +} + +void sff_8079_show_all(const uint8_t *data, struct sff_item *items) +{ + sff_8079_show_identifier(data, items); + if (((data[0] == 0x02) || (data[0] == 0x03)) && (data[1] == 0x04)) { + unsigned int br_nom, br_min, br_max; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + if (data[12] == 0) { + br_nom = br_min = br_max = 0; + } else if (data[12] == 255) { + br_nom = data[66] * 250; + br_max = data[67]; + br_min = data[67]; + } else { + br_nom = data[12] * 100; + br_max = data[66]; + br_min = data[67]; + } + sff_8079_show_ext_identifier(data, items); + sff_8079_show_connector(data, items); + sff_8079_show_transceiver(data, items); + sff_8079_show_encoding(data, items); + + snprintf(val_string, sizeof(val_string), "%uMBd", br_nom); + add_item_string(items, "BR, Nominal", val_string); + + sff_8079_show_rate_identifier(data, items); + sff_show_value_with_unit(data, 14, + "Length (SMF,km)", 1, "km", items); + sff_show_value_with_unit(data, 15, "Length (SMF)", 100, "m", items); + sff_show_value_with_unit(data, 16, "Length (50um)", 10, "m", items); + sff_show_value_with_unit(data, 17, + "Length (62.5um)", 10, "m", items); + sff_show_value_with_unit(data, 18, "Length (Copper)", 1, "m", items); + sff_show_value_with_unit(data, 19, "Length (OM3)", 10, "m", items); + sff_8079_show_wavelength_or_copper_compliance(data, items); + sff_show_ascii(data, 20, 35, "Vendor name", items); + sff_8079_show_oui(data, items); + sff_show_ascii(data, 40, 55, "Vendor PN", items); + sff_show_ascii(data, 56, 59, "Vendor rev", items); + sff_8079_show_options(data, items); + + snprintf(val_string, sizeof(val_string), "%u%%", br_max); + add_item_string(items, "BR margin, max", val_string); + snprintf(val_string, sizeof(val_string), "%u%%", br_min); + add_item_string(items, "BR margin, min", val_string); + + sff_show_ascii(data, 68, 83, "Vendor SN", items); + sff_show_ascii(data, 84, 91, "Date code", items); + } +} -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v5 4/5] ethdev: format module EEPROM for SFF-8472 2022-04-26 2:43 ` [PATCH v5 0/5] add telemetry command for show module EEPROM Robin Zhang ` (2 preceding siblings ...) 2022-04-26 2:43 ` [PATCH v5 3/5] ethdev: format module EEPROM for SFF-8079 Robin Zhang @ 2022-04-26 2:43 ` Robin Zhang 2022-04-26 2:43 ` [PATCH v5 5/5] ethdev: format module EEPROM for SFF-8636 Robin Zhang ` (2 subsequent siblings) 6 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-04-26 2:43 UTC (permalink / raw) To: dev Cc: qiming.yang, qi.z.zhang, stevex.yang, thomas, andrew.rybchenko, bruce.richardson, david.marchand, Robin Zhang This patch implements format module EEPROM information for SFF-8472 Rev 12.0 Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/ethdev_sff_telemetry.c | 4 + lib/ethdev/meson.build | 1 + lib/ethdev/sff_8472.c | 287 ++++++++++++++++++++++++++++++ 3 files changed, 292 insertions(+) create mode 100644 lib/ethdev/sff_8472.c diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c index c09352959c..2bfed792e0 100644 --- a/lib/ethdev/ethdev_sff_telemetry.c +++ b/lib/ethdev/ethdev_sff_telemetry.c @@ -69,6 +69,10 @@ sff_port_module_eeprom_display(uint16_t port_id, struct sff_item *items) case RTE_ETH_MODULE_SFF_8079: sff_8079_show_all(einfo.data, items); break; + case RTE_ETH_MODULE_SFF_8472: + sff_8079_show_all(einfo.data, items); + sff_8472_show_all(einfo.data, items); + break; default: RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); break; diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index d94860da0c..4d81a35c09 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -14,6 +14,7 @@ sources = files( 'ethdev_sff_telemetry.c', 'sff_common.c', 'sff_8079.c', + 'sff_8472.c', ) headers = files( diff --git a/lib/ethdev/sff_8472.c b/lib/ethdev/sff_8472.c new file mode 100644 index 0000000000..b4869d69c0 --- /dev/null +++ b/lib/ethdev/sff_8472.c @@ -0,0 +1,287 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8472 optics diagnostics. + * + */ + +#include <stdio.h> +#include <math.h> +#include <arpa/inet.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "ethdev_sff_telemetry.h" + +/* Offsets in decimal, for direct comparison with the SFF specs */ + +/* A0-based EEPROM offsets for DOM support checks */ +#define SFF_A0_DOM 92 +#define SFF_A0_OPTIONS 93 +#define SFF_A0_COMP 94 + +/* EEPROM bit values for various registers */ +#define SFF_A0_DOM_EXTCAL (1 << 4) +#define SFF_A0_DOM_INTCAL (1 << 5) +#define SFF_A0_DOM_IMPL (1 << 6) +#define SFF_A0_DOM_PWRT (1 << 3) + +#define SFF_A0_OPTIONS_AW (1 << 7) + +/* + * This is the offset at which the A2 page is in the EEPROM + * blob returned by the kernel. + */ +#define SFF_A2_BASE 0x100 + +/* A2-based offsets for DOM */ +#define SFF_A2_TEMP 96 +#define SFF_A2_TEMP_HALRM 0 +#define SFF_A2_TEMP_LALRM 2 +#define SFF_A2_TEMP_HWARN 4 +#define SFF_A2_TEMP_LWARN 6 + +#define SFF_A2_VCC 98 +#define SFF_A2_VCC_HALRM 8 +#define SFF_A2_VCC_LALRM 10 +#define SFF_A2_VCC_HWARN 12 +#define SFF_A2_VCC_LWARN 14 + +#define SFF_A2_BIAS 100 +#define SFF_A2_BIAS_HALRM 16 +#define SFF_A2_BIAS_LALRM 18 +#define SFF_A2_BIAS_HWARN 20 +#define SFF_A2_BIAS_LWARN 22 + +#define SFF_A2_TX_PWR 102 +#define SFF_A2_TX_PWR_HALRM 24 +#define SFF_A2_TX_PWR_LALRM 26 +#define SFF_A2_TX_PWR_HWARN 28 +#define SFF_A2_TX_PWR_LWARN 30 + +#define SFF_A2_RX_PWR 104 +#define SFF_A2_RX_PWR_HALRM 32 +#define SFF_A2_RX_PWR_LALRM 34 +#define SFF_A2_RX_PWR_HWARN 36 +#define SFF_A2_RX_PWR_LWARN 38 + +#define SFF_A2_ALRM_FLG 112 +#define SFF_A2_WARN_FLG 116 + +/* 32-bit little-endian calibration constants */ +#define SFF_A2_CAL_RXPWR4 56 +#define SFF_A2_CAL_RXPWR3 60 +#define SFF_A2_CAL_RXPWR2 64 +#define SFF_A2_CAL_RXPWR1 68 +#define SFF_A2_CAL_RXPWR0 72 + +/* 16-bit little endian calibration constants */ +#define SFF_A2_CAL_TXI_SLP 76 +#define SFF_A2_CAL_TXI_OFF 78 +#define SFF_A2_CAL_TXPWR_SLP 80 +#define SFF_A2_CAL_TXPWR_OFF 82 +#define SFF_A2_CAL_T_SLP 84 +#define SFF_A2_CAL_T_OFF 86 +#define SFF_A2_CAL_V_SLP 88 +#define SFF_A2_CAL_V_OFF 90 + +static struct sff_8472_aw_flags { + const char *str; /* Human-readable string, null at the end */ + int offset; /* A2-relative address offset */ + uint8_t value; /* Alarm is on if (offset & value) != 0. */ +} sff_8472_aw_flags[] = { + { "Laser bias current high alarm", SFF_A2_ALRM_FLG, (1 << 3) }, + { "Laser bias current low alarm", SFF_A2_ALRM_FLG, (1 << 2) }, + { "Laser bias current high warning", SFF_A2_WARN_FLG, (1 << 3) }, + { "Laser bias current low warning", SFF_A2_WARN_FLG, (1 << 2) }, + + { "Laser output power high alarm", SFF_A2_ALRM_FLG, (1 << 1) }, + { "Laser output power low alarm", SFF_A2_ALRM_FLG, (1 << 0) }, + { "Laser output power high warning", SFF_A2_WARN_FLG, (1 << 1) }, + { "Laser output power low warning", SFF_A2_WARN_FLG, (1 << 0) }, + + { "Module temperature high alarm", SFF_A2_ALRM_FLG, (1 << 7) }, + { "Module temperature low alarm", SFF_A2_ALRM_FLG, (1 << 6) }, + { "Module temperature high warning", SFF_A2_WARN_FLG, (1 << 7) }, + { "Module temperature low warning", SFF_A2_WARN_FLG, (1 << 6) }, + + { "Module voltage high alarm", SFF_A2_ALRM_FLG, (1 << 5) }, + { "Module voltage low alarm", SFF_A2_ALRM_FLG, (1 << 4) }, + { "Module voltage high warning", SFF_A2_WARN_FLG, (1 << 5) }, + { "Module voltage low warning", SFF_A2_WARN_FLG, (1 << 4) }, + + { "Laser rx power high alarm", SFF_A2_ALRM_FLG + 1, (1 << 7) }, + { "Laser rx power low alarm", SFF_A2_ALRM_FLG + 1, (1 << 6) }, + { "Laser rx power high warning", SFF_A2_WARN_FLG + 1, (1 << 7) }, + { "Laser rx power low warning", SFF_A2_WARN_FLG + 1, (1 << 6) }, + + { NULL, 0, 0 }, +}; + +/* Most common case: 16-bit unsigned integer in a certain unit */ +#define A2_OFFSET_TO_U16(offset) \ + (data[SFF_A2_BASE + (offset)] << 8 | data[SFF_A2_BASE + (offset) + 1]) + +/* Calibration slope is a number between 0.0 included and 256.0 excluded. */ +#define A2_OFFSET_TO_SLP(offset) \ + (data[SFF_A2_BASE + (offset)] + data[SFF_A2_BASE + (offset) + 1] / 256.) + +/* Calibration offset is an integer from -32768 to 32767 */ +#define A2_OFFSET_TO_OFF(offset) \ + ((int16_t)A2_OFFSET_TO_U16(offset)) + +/* RXPWR(x) are IEEE-754 floating point numbers in big-endian format */ +#define A2_OFFSET_TO_RXPWRx(offset) \ + (befloattoh((const uint32_t *)(data + SFF_A2_BASE + (offset)))) + +/* + * 2-byte internal temperature conversions: + * First byte is a signed 8-bit integer, which is the temp decimal part + * Second byte are 1/256th of degree, which are added to the dec part. + */ +#define A2_OFFSET_TO_TEMP(offset) ((int16_t)A2_OFFSET_TO_U16(offset)) + +static void sff_8472_dom_parse(const uint8_t *data, struct sff_diags *sd) +{ + sd->bias_cur[MCURR] = A2_OFFSET_TO_U16(SFF_A2_BIAS); + sd->bias_cur[HALRM] = A2_OFFSET_TO_U16(SFF_A2_BIAS_HALRM); + sd->bias_cur[LALRM] = A2_OFFSET_TO_U16(SFF_A2_BIAS_LALRM); + sd->bias_cur[HWARN] = A2_OFFSET_TO_U16(SFF_A2_BIAS_HWARN); + sd->bias_cur[LWARN] = A2_OFFSET_TO_U16(SFF_A2_BIAS_LWARN); + + sd->sfp_voltage[MCURR] = A2_OFFSET_TO_U16(SFF_A2_VCC); + sd->sfp_voltage[HALRM] = A2_OFFSET_TO_U16(SFF_A2_VCC_HALRM); + sd->sfp_voltage[LALRM] = A2_OFFSET_TO_U16(SFF_A2_VCC_LALRM); + sd->sfp_voltage[HWARN] = A2_OFFSET_TO_U16(SFF_A2_VCC_HWARN); + sd->sfp_voltage[LWARN] = A2_OFFSET_TO_U16(SFF_A2_VCC_LWARN); + + sd->tx_power[MCURR] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR); + sd->tx_power[HALRM] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_HALRM); + sd->tx_power[LALRM] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_LALRM); + sd->tx_power[HWARN] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_HWARN); + sd->tx_power[LWARN] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_LWARN); + + sd->rx_power[MCURR] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR); + sd->rx_power[HALRM] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_HALRM); + sd->rx_power[LALRM] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_LALRM); + sd->rx_power[HWARN] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_HWARN); + sd->rx_power[LWARN] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_LWARN); + + sd->sfp_temp[MCURR] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP); + sd->sfp_temp[HALRM] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_HALRM); + sd->sfp_temp[LALRM] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_LALRM); + sd->sfp_temp[HWARN] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_HWARN); + sd->sfp_temp[LWARN] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_LWARN); +} + +/* Converts to a float from a big-endian 4-byte source buffer. */ +static float befloattoh(const uint32_t *source) +{ + union { + uint32_t src; + float dst; + } converter; + + converter.src = ntohl(*source); + return converter.dst; +} + +static void sff_8472_calibration(const uint8_t *data, struct sff_diags *sd) +{ + unsigned long i; + uint16_t rx_reading; + + /* Calibration should occur for all values (threshold and current) */ + for (i = 0; i < ARRAY_SIZE(sd->bias_cur); ++i) { + /* + * Apply calibration formula 1 (Temp., Voltage, Bias, Tx Power) + */ + sd->bias_cur[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_TXI_SLP); + sd->tx_power[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_TXPWR_SLP); + sd->sfp_voltage[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_V_SLP); + sd->sfp_temp[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_T_SLP); + + sd->bias_cur[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_TXI_OFF); + sd->tx_power[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_TXPWR_OFF); + sd->sfp_voltage[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_V_OFF); + sd->sfp_temp[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_T_OFF); + + /* + * Apply calibration formula 2 (Rx Power only) + */ + rx_reading = sd->rx_power[i]; + sd->rx_power[i] = A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR0); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR1); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR2); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR3); + } +} + +static void sff_8472_parse_eeprom(const uint8_t *data, struct sff_diags *sd) +{ + sd->supports_dom = data[SFF_A0_DOM] & SFF_A0_DOM_IMPL; + sd->supports_alarms = data[SFF_A0_OPTIONS] & SFF_A0_OPTIONS_AW; + sd->calibrated_ext = data[SFF_A0_DOM] & SFF_A0_DOM_EXTCAL; + sd->rx_power_type = data[SFF_A0_DOM] & SFF_A0_DOM_PWRT; + + sff_8472_dom_parse(data, sd); + + /* + * If the SFP is externally calibrated, we need to read calibration data + * and compensate the already stored readings. + */ + if (sd->calibrated_ext) + sff_8472_calibration(data, sd); +} + +void sff_8472_show_all(const uint8_t *data, struct sff_item *items) +{ + struct sff_diags sd = {0}; + const char *rx_power_string = NULL; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + int i; + + sff_8472_parse_eeprom(data, &sd); + + if (!sd.supports_dom) { + add_item_string(items, "Optical diagnostics support", "No"); + return; + } + add_item_string(items, "Optical diagnostics support", "Yes"); + + SPRINT_BIAS(val_string, sd.bias_cur[MCURR]); + add_item_string(items, "Laser bias current", val_string); + + SPRINT_xX_PWR(val_string, sd.tx_power[MCURR]); + add_item_string(items, "Laser output power", val_string); + + if (!sd.rx_power_type) + rx_power_string = "Receiver signal OMA"; + else + rx_power_string = "Receiver signal average optical power"; + + SPRINT_xX_PWR(val_string, sd.rx_power[MCURR]); + add_item_string(items, rx_power_string, val_string); + + SPRINT_TEMP(val_string, sd.sfp_temp[MCURR]); + add_item_string(items, "Module temperature", val_string); + + SPRINT_VCC(val_string, sd.sfp_voltage[MCURR]); + add_item_string(items, "Module voltage", val_string); + + add_item_string(items, "Alarm/warning flags implemented", + (sd.supports_alarms ? "Yes" : "No")); + + if (sd.supports_alarms) { + for (i = 0; sff_8472_aw_flags[i].str; ++i) { + add_item_string(items, sff_8472_aw_flags[i].str, + data[SFF_A2_BASE + sff_8472_aw_flags[i].offset] + & sff_8472_aw_flags[i].value ? "On" : "Off"); + } + sff_show_thresholds(sd, items); + } +} -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v5 5/5] ethdev: format module EEPROM for SFF-8636 2022-04-26 2:43 ` [PATCH v5 0/5] add telemetry command for show module EEPROM Robin Zhang ` (3 preceding siblings ...) 2022-04-26 2:43 ` [PATCH v5 4/5] ethdev: format module EEPROM for SFF-8472 Robin Zhang @ 2022-04-26 2:43 ` Robin Zhang 2022-05-04 8:13 ` [PATCH v5 0/5] add telemetry command for show module EEPROM Andrew Rybchenko 2022-05-11 2:14 ` [PATCH v6 " Robin Zhang 6 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-04-26 2:43 UTC (permalink / raw) To: dev Cc: qiming.yang, qi.z.zhang, stevex.yang, thomas, andrew.rybchenko, bruce.richardson, david.marchand, Robin Zhang This patch implements format module EEPROM information for SFF-8636 Rev 2.7 Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/ethdev_sff_telemetry.c | 4 + lib/ethdev/meson.build | 1 + lib/ethdev/sff_8636.c | 775 ++++++++++++++++++++++++++++++ lib/ethdev/sff_8636.h | 592 +++++++++++++++++++++++ 4 files changed, 1372 insertions(+) create mode 100644 lib/ethdev/sff_8636.c create mode 100644 lib/ethdev/sff_8636.h diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c index 2bfed792e0..9ff0b2eb4a 100644 --- a/lib/ethdev/ethdev_sff_telemetry.c +++ b/lib/ethdev/ethdev_sff_telemetry.c @@ -73,6 +73,10 @@ sff_port_module_eeprom_display(uint16_t port_id, struct sff_item *items) sff_8079_show_all(einfo.data, items); sff_8472_show_all(einfo.data, items); break; + case RTE_ETH_MODULE_SFF_8436: + case RTE_ETH_MODULE_SFF_8636: + sff_8636_show_all(einfo.data, einfo.length, items); + break; default: RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); break; diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index 4d81a35c09..88ceeb12b9 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -15,6 +15,7 @@ sources = files( 'sff_common.c', 'sff_8079.c', 'sff_8472.c', + 'sff_8636.c', ) headers = files( diff --git a/lib/ethdev/sff_8636.c b/lib/ethdev/sff_8636.c new file mode 100644 index 0000000000..290b31e973 --- /dev/null +++ b/lib/ethdev/sff_8636.c @@ -0,0 +1,775 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8636 based QSFP+/QSFP28 Diagnostics Memory map. + * + */ + +#include <stdio.h> +#include <math.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "sff_8636.h" +#include "ethdev_sff_telemetry.h" + +#define MAX_DESC_SIZE 42 + +static struct sff_8636_aw_flags { + const char *str; /* Human-readable string, null at the end */ + int offset; /* A2-relative address offset */ + uint8_t value; /* Alarm is on if (offset & value) != 0. */ +} sff_8636_aw_flags[] = { + { "Laser bias current high alarm (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_HALARM) }, + { "Laser bias current low alarm (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_LALARM) }, + { "Laser bias current high warning (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_HWARN) }, + { "Laser bias current low warning (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_LWARN) }, + + { "Laser bias current high alarm (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_HALARM) }, + { "Laser bias current low alarm (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_LALARM) }, + { "Laser bias current high warning (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_HWARN) }, + { "Laser bias current low warning (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_LWARN) }, + + { "Laser bias current high alarm (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_HALARM) }, + { "Laser bias current low alarm (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_LALARM) }, + { "Laser bias current high warning (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_HWARN) }, + { "Laser bias current low warning (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_LWARN) }, + + { "Laser bias current high alarm (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_HALARM) }, + { "Laser bias current low alarm (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_LALARM) }, + { "Laser bias current high warning (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_HWARN) }, + { "Laser bias current low warning (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_LWARN) }, + + { "Module temperature high alarm", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_HALARM_STATUS) }, + { "Module temperature low alarm", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_LALARM_STATUS) }, + { "Module temperature high warning", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_HWARN_STATUS) }, + { "Module temperature low warning", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_LWARN_STATUS) }, + + { "Module voltage high alarm", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_HALARM_STATUS) }, + { "Module voltage low alarm", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_LALARM_STATUS) }, + { "Module voltage high warning", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_HWARN_STATUS) }, + { "Module voltage low warning", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_LWARN_STATUS) }, + + { "Laser tx power high alarm (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_HALARM) }, + { "Laser tx power low alarm (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_LALARM) }, + { "Laser tx power high warning (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_HWARN) }, + { "Laser tx power low warning (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_LWARN) }, + + { "Laser tx power high alarm (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_HALARM) }, + { "Laser tx power low alarm (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_LALARM) }, + { "Laser tx power high warning (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_HWARN) }, + { "Laser tx power low warning (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_LWARN) }, + + { "Laser tx power high alarm (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_HALARM) }, + { "Laser tx power low alarm (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_LALARM) }, + { "Laser tx power high warning (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_HWARN) }, + { "Laser tx power low warning (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_LWARN) }, + + { "Laser tx power high alarm (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_HALARM) }, + { "Laser tx power low alarm (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_LALARM) }, + { "Laser tx power high warning (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_HWARN) }, + { "Laser tx power low warning (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_LWARN) }, + + { "Laser rx power high alarm (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_HALARM) }, + { "Laser rx power low alarm (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_LALARM) }, + { "Laser rx power high warning (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_HWARN) }, + { "Laser rx power low warning (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_LWARN) }, + + { "Laser rx power high alarm (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_HALARM) }, + { "Laser rx power low alarm (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_LALARM) }, + { "Laser rx power high warning (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_HWARN) }, + { "Laser rx power low warning (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_LWARN) }, + + { "Laser rx power high alarm (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_HALARM) }, + { "Laser rx power low alarm (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_LALARM) }, + { "Laser rx power high warning (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_HWARN) }, + { "Laser rx power low warning (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_LWARN) }, + + { "Laser rx power high alarm (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_HALARM) }, + { "Laser rx power low alarm (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_LALARM) }, + { "Laser rx power high warning (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_HWARN) }, + { "Laser rx power low warning (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_LWARN) }, + + { NULL, 0, 0 }, +}; + +static void sff_8636_show_identifier(const uint8_t *data, struct sff_item *items) +{ + sff_8024_show_identifier(data, SFF_8636_ID_OFFSET, items); +} + +static void sff_8636_show_ext_identifier(const uint8_t *data, struct sff_item *items) +{ + static const char *name = "Extended identifier description"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + snprintf(val_string, sizeof(val_string), "0x%02x", data[SFF_8636_EXT_ID_OFFSET]); + add_item_string(items, "Extended identifier", val_string); + + switch (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_PWR_CLASS_MASK) { + case SFF_8636_EXT_ID_PWR_CLASS_1: + add_item_string(items, name, "1.5W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_2: + add_item_string(items, name, "2.0W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_3: + add_item_string(items, name, "2.5W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_4: + add_item_string(items, name, "3.5W max. Power consumption"); + break; + } + + if (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_CDR_TX_MASK) + add_item_string(items, name, "CDR present in TX"); + else + add_item_string(items, name, "No CDR in TX"); + + if (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_CDR_RX_MASK) + add_item_string(items, name, "CDR present in RX"); + else + add_item_string(items, name, "No CDR in RX"); + + switch (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_EPWR_CLASS_MASK) { + case SFF_8636_EXT_ID_PWR_CLASS_LEGACY: + snprintf(val_string, sizeof(val_string), "%s", ""); + break; + case SFF_8636_EXT_ID_PWR_CLASS_5: + snprintf(val_string, sizeof(val_string), "%s", "4.0W max. Power consumption, "); + break; + case SFF_8636_EXT_ID_PWR_CLASS_6: + snprintf(val_string, sizeof(val_string), "%s", "4.5W max. Power consumption, "); + break; + case SFF_8636_EXT_ID_PWR_CLASS_7: + snprintf(val_string, sizeof(val_string), "%s", "5.0W max. Power consumption, "); + break; + } + + if (data[SFF_8636_PWR_MODE_OFFSET] & SFF_8636_HIGH_PWR_ENABLE) + strlcat(val_string, "High Power Class (> 3.5 W) enabled", sizeof(val_string)); + else + strlcat(val_string, "High Power Class (> 3.5 W) not enabled", sizeof(val_string)); + + add_item_string(items, name, val_string); +} + +static void sff_8636_show_connector(const uint8_t *data, struct sff_item *items) +{ + sff_8024_show_connector(data, SFF_8636_CTOR_OFFSET, items); +} + +static void sff_8636_show_transceiver(const uint8_t *data, struct sff_item *items) +{ + static const char *name = "Transceiver type"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + data[SFF_8636_ETHERNET_COMP_OFFSET], + data[SFF_8636_SONET_COMP_OFFSET], + data[SFF_8636_SAS_COMP_OFFSET], + data[SFF_8636_GIGE_COMP_OFFSET], + data[SFF_8636_FC_LEN_OFFSET], + data[SFF_8636_FC_TECH_OFFSET], + data[SFF_8636_FC_TRANS_MEDIA_OFFSET], + data[SFF_8636_FC_SPEED_OFFSET]); + add_item_string(items, "Transceiver codes", val_string); + + /* 10G/40G Ethernet Compliance Codes */ + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_LRM) + add_item_string(items, name, "10G Ethernet: 10G Base-LRM"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_LR) + add_item_string(items, name, "10G Ethernet: 10G Base-LR"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_SR) + add_item_string(items, name, "10G Ethernet: 10G Base-SR"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_CR4) + add_item_string(items, name, "40G Ethernet: 40G Base-CR4"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_SR4) + add_item_string(items, name, "40G Ethernet: 40G Base-SR4"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_LR4) + add_item_string(items, name, "40G Ethernet: 40G Base-LR4"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_ACTIVE) + add_item_string(items, name, "40G Ethernet: 40G Active Cable (XLPPI)"); + + /* Extended Specification Compliance Codes from SFF-8024 */ + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_RSRVD) { + switch (data[SFF_8636_OPTION_1_OFFSET]) { + case SFF_8636_ETHERNET_UNSPECIFIED: + add_item_string(items, name, "(reserved or unknown)"); + break; + case SFF_8636_ETHERNET_100G_AOC: + add_item_string(items, name, + "100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)"); + break; + case SFF_8636_ETHERNET_100G_SR4: + add_item_string(items, name, + "100G Ethernet: 100G Base-SR4 or 25GBase-SR"); + break; + case SFF_8636_ETHERNET_100G_LR4: + add_item_string(items, name, "100G Ethernet: 100G Base-LR4"); + break; + case SFF_8636_ETHERNET_100G_ER4: + add_item_string(items, name, "100G Ethernet: 100G Base-ER4"); + break; + case SFF_8636_ETHERNET_100G_SR10: + add_item_string(items, name, "100G Ethernet: 100G Base-SR10"); + break; + case SFF_8636_ETHERNET_100G_CWDM4_FEC: + add_item_string(items, name, "100G Ethernet: 100G CWDM4 MSA with FEC"); + break; + case SFF_8636_ETHERNET_100G_PSM4: + add_item_string(items, name, "100G Ethernet: 100G PSM4 Parallel SMF"); + break; + case SFF_8636_ETHERNET_100G_ACC: + add_item_string(items, name, + "100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)"); + break; + case SFF_8636_ETHERNET_100G_CWDM4_NO_FEC: + add_item_string(items, name, + "100G Ethernet: 100G CWDM4 MSA without FEC"); + break; + case SFF_8636_ETHERNET_100G_RSVD1: + add_item_string(items, name, "(reserved or unknown)"); + break; + case SFF_8636_ETHERNET_100G_CR4: + add_item_string(items, name, + "100G Ethernet: 100G Base-CR4 or 25G Base-CR CA-L"); + break; + case SFF_8636_ETHERNET_25G_CR_CA_S: + add_item_string(items, name, "25G Ethernet: 25G Base-CR CA-S"); + break; + case SFF_8636_ETHERNET_25G_CR_CA_N: + add_item_string(items, name, "25G Ethernet: 25G Base-CR CA-N"); + break; + case SFF_8636_ETHERNET_40G_ER4: + add_item_string(items, name, "40G Ethernet: 40G Base-ER4"); + break; + case SFF_8636_ETHERNET_4X10_SR: + add_item_string(items, name, "4x10G Ethernet: 10G Base-SR"); + break; + case SFF_8636_ETHERNET_40G_PSM4: + add_item_string(items, name, "40G Ethernet: 40G PSM4 Parallel SMF"); + break; + case SFF_8636_ETHERNET_G959_P1I1_2D1: + add_item_string(items, name, + "Ethernet: G959.1 profile P1I1-2D1 (10709 MBd, 2km, 1310nm SM)"); + break; + case SFF_8636_ETHERNET_G959_P1S1_2D2: + add_item_string(items, name, + "Ethernet: G959.1 profile P1S1-2D2 (10709 MBd, 40km, 1550nm SM)"); + break; + case SFF_8636_ETHERNET_G959_P1L1_2D2: + add_item_string(items, name, + "Ethernet: G959.1 profile P1L1-2D2 (10709 MBd, 80km, 1550nm SM)"); + break; + case SFF_8636_ETHERNET_10GT_SFI: + add_item_string(items, name, + "10G Ethernet: 10G Base-T with SFI electrical interface"); + break; + case SFF_8636_ETHERNET_100G_CLR4: + add_item_string(items, name, "100G Ethernet: 100G CLR4"); + break; + case SFF_8636_ETHERNET_100G_AOC2: + add_item_string(items, name, + "100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)"); + break; + case SFF_8636_ETHERNET_100G_ACC2: + add_item_string(items, name, + "100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)"); + break; + default: + add_item_string(items, name, "(reserved or unknown)"); + break; + } + } + + /* SONET Compliance Codes */ + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_40G_OTN) + add_item_string(items, name, "40G OTN (OTU3B/OTU3C)"); + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_LR) + add_item_string(items, name, "SONET: OC-48, long reach"); + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_IR) + add_item_string(items, name, "SONET: OC-48, intermediate reach"); + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_SR) + add_item_string(items, name, "SONET: OC-48, short reach"); + + /* SAS/SATA Compliance Codes */ + if (data[SFF_8636_SAS_COMP_OFFSET] & SFF_8636_SAS_6G) + add_item_string(items, name, "SAS 6.0G"); + if (data[SFF_8636_SAS_COMP_OFFSET] & SFF_8636_SAS_3G) + add_item_string(items, name, "SAS 3.0G"); + + /* Ethernet Compliance Codes */ + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_T) + add_item_string(items, name, "Ethernet: 1000BASE-T"); + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_CX) + add_item_string(items, name, "Ethernet: 1000BASE-CX"); + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_LX) + add_item_string(items, name, "Ethernet: 1000BASE-LX"); + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_SX) + add_item_string(items, name, "Ethernet: 1000BASE-SX"); + + /* Fibre Channel link length */ + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_VERY_LONG) + add_item_string(items, name, "FC: very long distance (V)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_SHORT) + add_item_string(items, name, "FC: short distance (S)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_INT) + add_item_string(items, name, "FC: intermediate distance (I)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_LONG) + add_item_string(items, name, "FC: long distance (L)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_MED) + add_item_string(items, name, "FC: medium distance (M)"); + + /* Fibre Channel transmitter technology */ + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_TECH_LONG_LC) + add_item_string(items, name, "FC: Longwave laser (LC)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_TECH_ELEC_INTER) + add_item_string(items, name, "FC: Electrical inter-enclosure (EL)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_ELEC_INTRA) + add_item_string(items, name, "FC: Electrical intra-enclosure (EL)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_SHORT_WO_OFC) + add_item_string(items, name, "FC: Shortwave laser w/o OFC (SN)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_SHORT_W_OFC) + add_item_string(items, name, "FC: Shortwave laser with OFC (SL)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_LONG_LL) + add_item_string(items, name, "FC: Longwave laser (LL)"); + + /* Fibre Channel transmission media */ + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TW) + add_item_string(items, name, "FC: Twin Axial Pair (TW)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TP) + add_item_string(items, name, "FC: Twisted Pair (TP)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_MI) + add_item_string(items, name, "FC: Miniature Coax (MI)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TV) + add_item_string(items, name, "FC: Video Coax (TV)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_M6) + add_item_string(items, name, "FC: Multimode, 62.5m (M6)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_M5) + add_item_string(items, name, "FC: Multimode, 50m (M5)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_OM3) + add_item_string(items, name, "FC: Multimode, 50um (OM3)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_SM) + add_item_string(items, name, "FC: Single Mode (SM)"); + + /* Fibre Channel speed */ + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_1200_MBPS) + add_item_string(items, name, "FC: 1200 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_800_MBPS) + add_item_string(items, name, "FC: 800 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_1600_MBPS) + add_item_string(items, name, "FC: 1600 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_400_MBPS) + add_item_string(items, name, "FC: 400 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_200_MBPS) + add_item_string(items, name, "FC: 200 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_100_MBPS) + add_item_string(items, name, "FC: 100 MBytes/sec"); +} + +static void sff_8636_show_encoding(const uint8_t *data, struct sff_item *items) +{ + sff_8024_show_encoding(data, SFF_8636_ENCODING_OFFSET, + RTE_ETH_MODULE_SFF_8636, items); +} + +static void sff_8636_show_rate_identifier(const uint8_t *data, struct sff_item *items) +{ + char val_string[20]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[SFF_8636_EXT_RS_OFFSET]); + add_item_string(items, "Rate identifier", val_string); +} + +static void sff_8636_show_oui(const uint8_t *data, struct sff_item *items) +{ + sff_8024_show_oui(data, SFF_8636_VENDOR_OUI_OFFSET, items); +} + +static void sff_8636_show_wavelength_or_copper_compliance(const uint8_t *data, + struct sff_item *items) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + snprintf(val_string, sizeof(val_string), "0x%02x", + (data[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK)); + + switch (data[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK) { + case SFF_8636_TRANS_850_VCSEL: + strlcat(val_string, " (850 nm VCSEL)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_VCSEL: + strlcat(val_string, " (1310 nm VCSEL)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1550_VCSEL: + strlcat(val_string, " (1550 nm VCSEL)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_FP: + strlcat(val_string, " (1310 nm FP)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_DFB: + strlcat(val_string, " (1310 nm DFB)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1550_DFB: + strlcat(val_string, " (1550 nm DFB)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_EML: + strlcat(val_string, " (1310 nm EML)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1550_EML: + strlcat(val_string, " (1550 nm EML)", sizeof(val_string)); + break; + case SFF_8636_TRANS_OTHERS: + strlcat(val_string, " (Others/Undefined)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1490_DFB: + strlcat(val_string, " (1490 nm DFB)", sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_PAS_UNEQUAL: + strlcat(val_string, " (Copper cable unequalized)", sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_PAS_EQUAL: + strlcat(val_string, " (Copper cable passive equalized)", sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_LNR_FAR_EQUAL: + strlcat(val_string, + " (Copper cable, near and far end limiting active equalizers)", + sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_FAR_EQUAL: + strlcat(val_string, + " (Copper cable, far end limiting active equalizers)", + sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_NEAR_EQUAL: + strlcat(val_string, + " (Copper cable, near end limiting active equalizers)", + sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_LNR_EQUAL: + strlcat(val_string, + " (Copper cable, linear active equalizers)", + sizeof(val_string)); + break; + } + add_item_string(items, "Transmitter technology", val_string); + + if ((data[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK) + >= SFF_8636_TRANS_COPPER_PAS_UNEQUAL) { + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + add_item_string(items, "Attenuation at 2.5GHz", val_string); + + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + add_item_string(items, "Attenuation at 5.0GHz", val_string); + + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + add_item_string(items, "Attenuation at 7.0GHz", val_string); + + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + add_item_string(items, "Attenuation at 12.9GHz", val_string); + } else { + snprintf(val_string, sizeof(val_string), "%.3lfnm", + (((data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET] << 8) | + data[SFF_8636_WAVELEN_LOW_BYTE_OFFSET])*0.05)); + add_item_string(items, "Laser wavelength", val_string); + + snprintf(val_string, sizeof(val_string), "%.3lfnm", + (((data[SFF_8636_WAVE_TOL_HIGH_BYTE_OFFSET] << 8) | + data[SFF_8636_WAVE_TOL_LOW_BYTE_OFFSET])*0.005)); + add_item_string(items, "Laser wavelength tolerance", val_string); + } +} + +static void sff_8636_show_revision_compliance(const uint8_t *data, struct sff_item *items) +{ + static const char *name = "Revision Compliance"; + + switch (data[SFF_8636_REV_COMPLIANCE_OFFSET]) { + case SFF_8636_REV_UNSPECIFIED: + add_item_string(items, name, "Revision not specified"); + break; + case SFF_8636_REV_8436_48: + add_item_string(items, name, "SFF-8436 Rev 4.8 or earlier"); + break; + case SFF_8636_REV_8436_8636: + add_item_string(items, name, "SFF-8436 Rev 4.8 or earlier"); + break; + case SFF_8636_REV_8636_13: + add_item_string(items, name, "SFF-8636 Rev 1.3 or earlier"); + break; + case SFF_8636_REV_8636_14: + add_item_string(items, name, "SFF-8636 Rev 1.4"); + break; + case SFF_8636_REV_8636_15: + add_item_string(items, name, "SFF-8636 Rev 1.5"); + break; + case SFF_8636_REV_8636_20: + add_item_string(items, name, "SFF-8636 Rev 2.0"); + break; + case SFF_8636_REV_8636_27: + add_item_string(items, name, "SFF-8636 Rev 2.5/2.6/2.7"); + break; + default: + add_item_string(items, name, "Unallocated"); + break; + } +} + +/* + * 2-byte internal temperature conversions: + * First byte is a signed 8-bit integer, which is the temp decimal part + * Second byte are 1/256th of degree, which are added to the dec part. + */ +#define SFF_8636_OFFSET_TO_TEMP(offset) ((int16_t)OFFSET_TO_U16(offset)) + +static void sff_8636_dom_parse(const uint8_t *data, struct sff_diags *sd) +{ + int i = 0; + + /* Monitoring Thresholds for Alarms and Warnings */ + sd->sfp_voltage[MCURR] = OFFSET_TO_U16(SFF_8636_VCC_CURR); + sd->sfp_voltage[HALRM] = OFFSET_TO_U16(SFF_8636_VCC_HALRM); + sd->sfp_voltage[LALRM] = OFFSET_TO_U16(SFF_8636_VCC_LALRM); + sd->sfp_voltage[HWARN] = OFFSET_TO_U16(SFF_8636_VCC_HWARN); + sd->sfp_voltage[LWARN] = OFFSET_TO_U16(SFF_8636_VCC_LWARN); + + sd->sfp_temp[MCURR] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_CURR); + sd->sfp_temp[HALRM] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_HALRM); + sd->sfp_temp[LALRM] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_LALRM); + sd->sfp_temp[HWARN] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_HWARN); + sd->sfp_temp[LWARN] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_LWARN); + + sd->bias_cur[HALRM] = OFFSET_TO_U16(SFF_8636_TX_BIAS_HALRM); + sd->bias_cur[LALRM] = OFFSET_TO_U16(SFF_8636_TX_BIAS_LALRM); + sd->bias_cur[HWARN] = OFFSET_TO_U16(SFF_8636_TX_BIAS_HWARN); + sd->bias_cur[LWARN] = OFFSET_TO_U16(SFF_8636_TX_BIAS_LWARN); + + sd->tx_power[HALRM] = OFFSET_TO_U16(SFF_8636_TX_PWR_HALRM); + sd->tx_power[LALRM] = OFFSET_TO_U16(SFF_8636_TX_PWR_LALRM); + sd->tx_power[HWARN] = OFFSET_TO_U16(SFF_8636_TX_PWR_HWARN); + sd->tx_power[LWARN] = OFFSET_TO_U16(SFF_8636_TX_PWR_LWARN); + + sd->rx_power[HALRM] = OFFSET_TO_U16(SFF_8636_RX_PWR_HALRM); + sd->rx_power[LALRM] = OFFSET_TO_U16(SFF_8636_RX_PWR_LALRM); + sd->rx_power[HWARN] = OFFSET_TO_U16(SFF_8636_RX_PWR_HWARN); + sd->rx_power[LWARN] = OFFSET_TO_U16(SFF_8636_RX_PWR_LWARN); + + + /* Channel Specific Data */ + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + uint8_t rx_power_offset, tx_bias_offset; + uint8_t tx_power_offset; + + switch (i) { + case 0: + rx_power_offset = SFF_8636_RX_PWR_1_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_1_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_1_OFFSET; + break; + case 1: + rx_power_offset = SFF_8636_RX_PWR_2_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_2_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_2_OFFSET; + break; + case 2: + rx_power_offset = SFF_8636_RX_PWR_3_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_3_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_3_OFFSET; + break; + case 3: + rx_power_offset = SFF_8636_RX_PWR_4_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_4_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_4_OFFSET; + break; + } + sd->scd[i].bias_cur = OFFSET_TO_U16(tx_bias_offset); + sd->scd[i].rx_power = OFFSET_TO_U16(rx_power_offset); + sd->scd[i].tx_power = OFFSET_TO_U16(tx_power_offset); + } + +} + +static void sff_8636_show_dom(const uint8_t *data, uint32_t eeprom_len, struct sff_item *items) +{ + struct sff_diags sd = {0}; + const char *rx_power_string = NULL; + char power_string[MAX_DESC_SIZE]; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + int i; + + /* + * There is no clear identifier to signify the existence of + * optical diagnostics similar to SFF-8472. So checking existence + * of page 3, will provide the gurantee for existence of alarms + * and thresholds + * If pagging support exists, then supports_alarms is marked as 1 + */ + + if (eeprom_len == RTE_ETH_MODULE_SFF_8636_MAX_LEN) { + if (!(data[SFF_8636_STATUS_2_OFFSET] & + SFF_8636_STATUS_PAGE_3_PRESENT)) { + sd.supports_alarms = 1; + } + } + + sd.rx_power_type = data[SFF_8636_DIAG_TYPE_OFFSET] & + SFF_8636_RX_PWR_TYPE_MASK; + sd.tx_power_type = data[SFF_8636_DIAG_TYPE_OFFSET] & + SFF_8636_RX_PWR_TYPE_MASK; + + sff_8636_dom_parse(data, &sd); + + SPRINT_TEMP(val_string, sd.sfp_temp[MCURR]); + add_item_string(items, "Module temperature", val_string); + + SPRINT_VCC(val_string, sd.sfp_voltage[MCURR]); + add_item_string(items, "Module voltage", val_string); + + /* + * SFF-8636/8436 spec is not clear whether RX power/ TX bias + * current fields are supported or not. A valid temperature + * reading is used as existence for TX/RX power. + */ + if ((sd.sfp_temp[MCURR] == 0x0) || + (sd.sfp_temp[MCURR] == (int16_t)0xFFFF)) + return; + + add_item_string(items, "Alarm/warning flags implemented", + (sd.supports_alarms ? "Yes" : "No")); + + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + snprintf(power_string, MAX_DESC_SIZE, "%s (Channel %d)", + "Laser tx bias current", i+1); + SPRINT_BIAS(val_string, sd.scd[i].bias_cur); + add_item_string(items, power_string, val_string); + } + + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + snprintf(power_string, MAX_DESC_SIZE, "%s (Channel %d)", + "Transmit avg optical power", i+1); + SPRINT_xX_PWR(val_string, sd.scd[i].tx_power); + add_item_string(items, power_string, val_string); + } + + if (!sd.rx_power_type) + rx_power_string = "Receiver signal OMA"; + else + rx_power_string = "Rcvr signal avg optical power"; + + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + snprintf(power_string, MAX_DESC_SIZE, "%s(Channel %d)", + rx_power_string, i+1); + SPRINT_xX_PWR(val_string, sd.scd[i].rx_power); + add_item_string(items, power_string, val_string); + } + + if (sd.supports_alarms) { + for (i = 0; sff_8636_aw_flags[i].str; ++i) { + add_item_string(items, sff_8636_aw_flags[i].str, + data[sff_8636_aw_flags[i].offset] + & sff_8636_aw_flags[i].value ? "On" : "Off"); + } + + sff_show_thresholds(sd, items); + } + +} +void sff_8636_show_all(const uint8_t *data, uint32_t eeprom_len, struct sff_item *items) +{ + sff_8636_show_identifier(data, items); + if ((data[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP) || + (data[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP_PLUS) || + (data[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP28)) { + sff_8636_show_ext_identifier(data, items); + sff_8636_show_connector(data, items); + sff_8636_show_transceiver(data, items); + sff_8636_show_encoding(data, items); + sff_show_value_with_unit(data, SFF_8636_BR_NOMINAL_OFFSET, + "BR, Nominal", 100, "Mbps", items); + sff_8636_show_rate_identifier(data, items); + sff_show_value_with_unit(data, SFF_8636_SM_LEN_OFFSET, + "Length (SMF,km)", 1, "km", items); + sff_show_value_with_unit(data, SFF_8636_OM3_LEN_OFFSET, + "Length (OM3 50um)", 2, "m", items); + sff_show_value_with_unit(data, SFF_8636_OM2_LEN_OFFSET, + "Length (OM2 50um)", 1, "m", items); + sff_show_value_with_unit(data, SFF_8636_OM1_LEN_OFFSET, + "Length (OM1 62.5um)", 1, "m", items); + sff_show_value_with_unit(data, SFF_8636_CBL_LEN_OFFSET, + "Length (Copper or Active cable)", 1, "m", items); + sff_8636_show_wavelength_or_copper_compliance(data, items); + sff_show_ascii(data, SFF_8636_VENDOR_NAME_START_OFFSET, + SFF_8636_VENDOR_NAME_END_OFFSET, "Vendor name", items); + sff_8636_show_oui(data, items); + sff_show_ascii(data, SFF_8636_VENDOR_PN_START_OFFSET, + SFF_8636_VENDOR_PN_END_OFFSET, "Vendor PN", items); + sff_show_ascii(data, SFF_8636_VENDOR_REV_START_OFFSET, + SFF_8636_VENDOR_REV_END_OFFSET, "Vendor rev", items); + sff_show_ascii(data, SFF_8636_VENDOR_SN_START_OFFSET, + SFF_8636_VENDOR_SN_END_OFFSET, "Vendor SN", items); + sff_show_ascii(data, SFF_8636_DATE_YEAR_OFFSET, + SFF_8636_DATE_VENDOR_LOT_OFFSET + 1, "Date code", items); + sff_8636_show_revision_compliance(data, items); + sff_8636_show_dom(data, eeprom_len, items); + } +} diff --git a/lib/ethdev/sff_8636.h b/lib/ethdev/sff_8636.h new file mode 100644 index 0000000000..fc656775f9 --- /dev/null +++ b/lib/ethdev/sff_8636.h @@ -0,0 +1,592 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * SFF-8636 standards based QSFP EEPROM Field Definitions + * + */ + +#ifndef _SFF_8636_H_ +#define _SFF_8636_H_ + +/*------------------------------------------------------------------------------ + * + * QSFP EEPROM data structures + * + * register info from SFF-8636 Rev 2.7 + */ + +/*------------------------------------------------------------------------------ + * + * Lower Memory Page 00h + * Measurement, Diagnostic and Control Functions + * + */ +/* Identifier - 0 */ +/* Values are defined under SFF_8024_ID_OFFSET */ +#define SFF_8636_ID_OFFSET 0x00 + +#define SFF_8636_REV_COMPLIANCE_OFFSET 0x01 +#define SFF_8636_REV_UNSPECIFIED 0x00 +#define SFF_8636_REV_8436_48 0x01 +#define SFF_8636_REV_8436_8636 0x02 +#define SFF_8636_REV_8636_13 0x03 +#define SFF_8636_REV_8636_14 0x04 +#define SFF_8636_REV_8636_15 0x05 +#define SFF_8636_REV_8636_20 0x06 +#define SFF_8636_REV_8636_27 0x07 + +#define SFF_8636_STATUS_2_OFFSET 0x02 +/* Flat Memory:0- Paging, 1- Page 0 only */ +#define SFF_8636_STATUS_PAGE_3_PRESENT (1 << 2) +#define SFF_8636_STATUS_INTL_OUTPUT (1 << 1) +#define SFF_8636_STATUS_DATA_NOT_READY (1 << 0) + +/* Channel Status Interrupt Flags - 3-5 */ +#define SFF_8636_LOS_AW_OFFSET 0x03 +#define SFF_8636_TX4_LOS_AW (1 << 7) +#define SFF_8636_TX3_LOS_AW (1 << 6) +#define SFF_8636_TX2_LOS_AW (1 << 5) +#define SFF_8636_TX1_LOS_AW (1 << 4) +#define SFF_8636_RX4_LOS_AW (1 << 3) +#define SFF_8636_RX3_LOS_AW (1 << 2) +#define SFF_8636_RX2_LOS_AW (1 << 1) +#define SFF_8636_RX1_LOS_AW (1 << 0) + +#define SFF_8636_FAULT_AW_OFFSET 0x04 +#define SFF_8636_TX4_FAULT_AW (1 << 3) +#define SFF_8636_TX3_FAULT_AW (1 << 2) +#define SFF_8636_TX2_FAULT_AW (1 << 1) +#define SFF_8636_TX1_FAULT_AW (1 << 0) + +/* Module Monitor Interrupt Flags - 6-8 */ +#define SFF_8636_TEMP_AW_OFFSET 0x06 +#define SFF_8636_TEMP_HALARM_STATUS (1 << 7) +#define SFF_8636_TEMP_LALARM_STATUS (1 << 6) +#define SFF_8636_TEMP_HWARN_STATUS (1 << 5) +#define SFF_8636_TEMP_LWARN_STATUS (1 << 4) + +#define SFF_8636_VCC_AW_OFFSET 0x07 +#define SFF_8636_VCC_HALARM_STATUS (1 << 7) +#define SFF_8636_VCC_LALARM_STATUS (1 << 6) +#define SFF_8636_VCC_HWARN_STATUS (1 << 5) +#define SFF_8636_VCC_LWARN_STATUS (1 << 4) + +/* Channel Monitor Interrupt Flags - 9-21 */ +#define SFF_8636_RX_PWR_12_AW_OFFSET 0x09 +#define SFF_8636_RX_PWR_1_HALARM (1 << 7) +#define SFF_8636_RX_PWR_1_LALARM (1 << 6) +#define SFF_8636_RX_PWR_1_HWARN (1 << 5) +#define SFF_8636_RX_PWR_1_LWARN (1 << 4) +#define SFF_8636_RX_PWR_2_HALARM (1 << 3) +#define SFF_8636_RX_PWR_2_LALARM (1 << 2) +#define SFF_8636_RX_PWR_2_HWARN (1 << 1) +#define SFF_8636_RX_PWR_2_LWARN (1 << 0) + +#define SFF_8636_RX_PWR_34_AW_OFFSET 0x0A +#define SFF_8636_RX_PWR_3_HALARM (1 << 7) +#define SFF_8636_RX_PWR_3_LALARM (1 << 6) +#define SFF_8636_RX_PWR_3_HWARN (1 << 5) +#define SFF_8636_RX_PWR_3_LWARN (1 << 4) +#define SFF_8636_RX_PWR_4_HALARM (1 << 3) +#define SFF_8636_RX_PWR_4_LALARM (1 << 2) +#define SFF_8636_RX_PWR_4_HWARN (1 << 1) +#define SFF_8636_RX_PWR_4_LWARN (1 << 0) + +#define SFF_8636_TX_BIAS_12_AW_OFFSET 0x0B +#define SFF_8636_TX_BIAS_1_HALARM (1 << 7) +#define SFF_8636_TX_BIAS_1_LALARM (1 << 6) +#define SFF_8636_TX_BIAS_1_HWARN (1 << 5) +#define SFF_8636_TX_BIAS_1_LWARN (1 << 4) +#define SFF_8636_TX_BIAS_2_HALARM (1 << 3) +#define SFF_8636_TX_BIAS_2_LALARM (1 << 2) +#define SFF_8636_TX_BIAS_2_HWARN (1 << 1) +#define SFF_8636_TX_BIAS_2_LWARN (1 << 0) + +#define SFF_8636_TX_BIAS_34_AW_OFFSET 0xC +#define SFF_8636_TX_BIAS_3_HALARM (1 << 7) +#define SFF_8636_TX_BIAS_3_LALARM (1 << 6) +#define SFF_8636_TX_BIAS_3_HWARN (1 << 5) +#define SFF_8636_TX_BIAS_3_LWARN (1 << 4) +#define SFF_8636_TX_BIAS_4_HALARM (1 << 3) +#define SFF_8636_TX_BIAS_4_LALARM (1 << 2) +#define SFF_8636_TX_BIAS_4_HWARN (1 << 1) +#define SFF_8636_TX_BIAS_4_LWARN (1 << 0) + +#define SFF_8636_TX_PWR_12_AW_OFFSET 0x0D +#define SFF_8636_TX_PWR_1_HALARM (1 << 7) +#define SFF_8636_TX_PWR_1_LALARM (1 << 6) +#define SFF_8636_TX_PWR_1_HWARN (1 << 5) +#define SFF_8636_TX_PWR_1_LWARN (1 << 4) +#define SFF_8636_TX_PWR_2_HALARM (1 << 3) +#define SFF_8636_TX_PWR_2_LALARM (1 << 2) +#define SFF_8636_TX_PWR_2_HWARN (1 << 1) +#define SFF_8636_TX_PWR_2_LWARN (1 << 0) + +#define SFF_8636_TX_PWR_34_AW_OFFSET 0x0E +#define SFF_8636_TX_PWR_3_HALARM (1 << 7) +#define SFF_8636_TX_PWR_3_LALARM (1 << 6) +#define SFF_8636_TX_PWR_3_HWARN (1 << 5) +#define SFF_8636_TX_PWR_3_LWARN (1 << 4) +#define SFF_8636_TX_PWR_4_HALARM (1 << 3) +#define SFF_8636_TX_PWR_4_LALARM (1 << 2) +#define SFF_8636_TX_PWR_4_HWARN (1 << 1) +#define SFF_8636_TX_PWR_4_LWARN (1 << 0) + +/* Module Monitoring Values - 22-33 */ +#define SFF_8636_TEMP_CURR 0x16 +#define SFF_8636_TEMP_MSB_OFFSET 0x16 +#define SFF_8636_TEMP_LSB_OFFSET 0x17 + +#define SFF_8636_VCC_CURR 0x1A +#define SFF_8636_VCC_MSB_OFFSET 0x1A +#define SFF_8636_VCC_LSB_OFFSET 0x1B + +/* Channel Monitoring Values - 34-81 */ +#define SFF_8636_RX_PWR_1_OFFSET 0x22 +#define SFF_8636_RX_PWR_2_OFFSET 0x24 +#define SFF_8636_RX_PWR_3_OFFSET 0x26 +#define SFF_8636_RX_PWR_4_OFFSET 0x28 + +#define SFF_8636_TX_BIAS_1_OFFSET 0x2A +#define SFF_8636_TX_BIAS_2_OFFSET 0x2C +#define SFF_8636_TX_BIAS_3_OFFSET 0x2E +#define SFF_8636_TX_BIAS_4_OFFSET 0x30 + +#define SFF_8636_TX_PWR_1_OFFSET 0x32 +#define SFF_8636_TX_PWR_2_OFFSET 0x34 +#define SFF_8636_TX_PWR_3_OFFSET 0x36 +#define SFF_8636_TX_PWR_4_OFFSET 0x38 + +/* Control Bytes - 86 - 99 */ +#define SFF_8636_TX_DISABLE_OFFSET 0x56 +#define SFF_8636_TX_DISABLE_4 (1 << 3) +#define SFF_8636_TX_DISABLE_3 (1 << 2) +#define SFF_8636_TX_DISABLE_2 (1 << 1) +#define SFF_8636_TX_DISABLE_1 (1 << 0) + +#define SFF_8636_RX_RATE_SELECT_OFFSET 0x57 +#define SFF_8636_RX_RATE_SELECT_4_MASK (3 << 6) +#define SFF_8636_RX_RATE_SELECT_3_MASK (3 << 4) +#define SFF_8636_RX_RATE_SELECT_2_MASK (3 << 2) +#define SFF_8636_RX_RATE_SELECT_1_MASK (3 << 0) + +#define SFF_8636_TX_RATE_SELECT_OFFSET 0x58 +#define SFF_8636_TX_RATE_SELECT_4_MASK (3 << 6) +#define SFF_8636_TX_RATE_SELECT_3_MASK (3 << 4) +#define SFF_8636_TX_RATE_SELECT_2_MASK (3 << 2) +#define SFF_8636_TX_RATE_SELECT_1_MASK (3 << 0) + +#define SFF_8636_RX_APP_SELECT_4_OFFSET 0x58 +#define SFF_8636_RX_APP_SELECT_3_OFFSET 0x59 +#define SFF_8636_RX_APP_SELECT_2_OFFSET 0x5A +#define SFF_8636_RX_APP_SELECT_1_OFFSET 0x5B + +#define SFF_8636_PWR_MODE_OFFSET 0x5D +#define SFF_8636_HIGH_PWR_ENABLE (1 << 2) +#define SFF_8636_LOW_PWR_MODE (1 << 1) +#define SFF_8636_PWR_OVERRIDE (1 << 0) + +#define SFF_8636_TX_APP_SELECT_4_OFFSET 0x5E +#define SFF_8636_TX_APP_SELECT_3_OFFSET 0x5F +#define SFF_8636_TX_APP_SELECT_2_OFFSET 0x60 +#define SFF_8636_TX_APP_SELECT_1_OFFSET 0x61 + +#define SFF_8636_LOS_MASK_OFFSET 0x64 +#define SFF_8636_TX_LOS_4_MASK (1 << 7) +#define SFF_8636_TX_LOS_3_MASK (1 << 6) +#define SFF_8636_TX_LOS_2_MASK (1 << 5) +#define SFF_8636_TX_LOS_1_MASK (1 << 4) +#define SFF_8636_RX_LOS_4_MASK (1 << 3) +#define SFF_8636_RX_LOS_3_MASK (1 << 2) +#define SFF_8636_RX_LOS_2_MASK (1 << 1) +#define SFF_8636_RX_LOS_1_MASK (1 << 0) + +#define SFF_8636_FAULT_MASK_OFFSET 0x65 +#define SFF_8636_TX_FAULT_1_MASK (1 << 3) +#define SFF_8636_TX_FAULT_2_MASK (1 << 2) +#define SFF_8636_TX_FAULT_3_MASK (1 << 1) +#define SFF_8636_TX_FAULT_4_MASK (1 << 0) + +#define SFF_8636_TEMP_MASK_OFFSET 0x67 +#define SFF_8636_TEMP_HALARM_MASK (1 << 7) +#define SFF_8636_TEMP_LALARM_MASK (1 << 6) +#define SFF_8636_TEMP_HWARN_MASK (1 << 5) +#define SFF_8636_TEMP_LWARN_MASK (1 << 4) + +#define SFF_8636_VCC_MASK_OFFSET 0x68 +#define SFF_8636_VCC_HALARM_MASK (1 << 7) +#define SFF_8636_VCC_LALARM_MASK (1 << 6) +#define SFF_8636_VCC_HWARN_MASK (1 << 5) +#define SFF_8636_VCC_LWARN_MASK (1 << 4) + +/*------------------------------------------------------------------------------ + * + * Upper Memory Page 00h + * Serial ID - Base ID, Extended ID and Vendor Specific ID fields + * + */ +/* Identifier - 128 */ +/* Identifier values same as Lower Memory Page 00h */ +#define SFF_8636_UPPER_PAGE_0_ID_OFFSET 0x80 + +/* Extended Identifier - 128 */ +#define SFF_8636_EXT_ID_OFFSET 0x81 +#define SFF_8636_EXT_ID_PWR_CLASS_MASK 0xC0 +#define SFF_8636_EXT_ID_PWR_CLASS_1 (0 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_2 (1 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_3 (2 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_4 (3 << 6) +#define SFF_8636_EXT_ID_CLIE_MASK 0x10 +#define SFF_8636_EXT_ID_CLIEI_CODE_PRESENT (1 << 4) +#define SFF_8636_EXT_ID_CDR_TX_MASK 0x08 +#define SFF_8636_EXT_ID_CDR_TX_PRESENT (1 << 3) +#define SFF_8636_EXT_ID_CDR_RX_MASK 0x04 +#define SFF_8636_EXT_ID_CDR_RX_PRESENT (1 << 2) +#define SFF_8636_EXT_ID_EPWR_CLASS_MASK 0x03 +#define SFF_8636_EXT_ID_PWR_CLASS_LEGACY 0 +#define SFF_8636_EXT_ID_PWR_CLASS_5 1 +#define SFF_8636_EXT_ID_PWR_CLASS_6 2 +#define SFF_8636_EXT_ID_PWR_CLASS_7 3 + +/* Connector Values offset - 130 */ +/* Values are defined under SFF_8024_CTOR */ +#define SFF_8636_CTOR_OFFSET 0x82 +#define SFF_8636_CTOR_UNKNOWN 0x00 +#define SFF_8636_CTOR_SC 0x01 +#define SFF_8636_CTOR_FC_STYLE_1 0x02 +#define SFF_8636_CTOR_FC_STYLE_2 0x03 +#define SFF_8636_CTOR_BNC_TNC 0x04 +#define SFF_8636_CTOR_FC_COAX 0x05 +#define SFF_8636_CTOR_FIBER_JACK 0x06 +#define SFF_8636_CTOR_LC 0x07 +#define SFF_8636_CTOR_MT_RJ 0x08 +#define SFF_8636_CTOR_MU 0x09 +#define SFF_8636_CTOR_SG 0x0A +#define SFF_8636_CTOR_OPT_PT 0x0B +#define SFF_8636_CTOR_MPO 0x0C +/* 0D-1Fh --- Reserved */ +#define SFF_8636_CTOR_HSDC_II 0x20 +#define SFF_8636_CTOR_COPPER_PT 0x21 +#define SFF_8636_CTOR_RJ45 0x22 +#define SFF_8636_CTOR_NO_SEPARABLE 0x23 +#define SFF_8636_CTOR_MXC_2X16 0x24 + +/* Specification Compliance - 131-138 */ +/* Ethernet Compliance Codes - 131 */ +#define SFF_8636_ETHERNET_COMP_OFFSET 0x83 +#define SFF_8636_ETHERNET_RSRVD (1 << 7) +#define SFF_8636_ETHERNET_10G_LRM (1 << 6) +#define SFF_8636_ETHERNET_10G_LR (1 << 5) +#define SFF_8636_ETHERNET_10G_SR (1 << 4) +#define SFF_8636_ETHERNET_40G_CR4 (1 << 3) +#define SFF_8636_ETHERNET_40G_SR4 (1 << 2) +#define SFF_8636_ETHERNET_40G_LR4 (1 << 1) +#define SFF_8636_ETHERNET_40G_ACTIVE (1 << 0) + +/* SONET Compliance Codes - 132 */ +#define SFF_8636_SONET_COMP_OFFSET 0x84 +#define SFF_8636_SONET_40G_OTN (1 << 3) +#define SFF_8636_SONET_OC48_LR (1 << 2) +#define SFF_8636_SONET_OC48_IR (1 << 1) +#define SFF_8636_SONET_OC48_SR (1 << 0) + +/* SAS/SATA Complaince Codes - 133 */ +#define SFF_8636_SAS_COMP_OFFSET 0x85 +#define SFF_8636_SAS_12G (1 << 6) +#define SFF_8636_SAS_6G (1 << 5) +#define SFF_8636_SAS_3G (1 << 4) + +/* Gigabit Ethernet Compliance Codes - 134 */ +#define SFF_8636_GIGE_COMP_OFFSET 0x86 +#define SFF_8636_GIGE_1000_BASE_T (1 << 3) +#define SFF_8636_GIGE_1000_BASE_CX (1 << 2) +#define SFF_8636_GIGE_1000_BASE_LX (1 << 1) +#define SFF_8636_GIGE_1000_BASE_SX (1 << 0) + +/* Fibre Channel Link length/Transmitter Tech. - 135,136 */ +#define SFF_8636_FC_LEN_OFFSET 0x87 +#define SFF_8636_FC_LEN_VERY_LONG (1 << 7) +#define SFF_8636_FC_LEN_SHORT (1 << 6) +#define SFF_8636_FC_LEN_INT (1 << 5) +#define SFF_8636_FC_LEN_LONG (1 << 4) +#define SFF_8636_FC_LEN_MED (1 << 3) +#define SFF_8636_FC_TECH_LONG_LC (1 << 1) +#define SFF_8636_FC_TECH_ELEC_INTER (1 << 0) + +#define SFF_8636_FC_TECH_OFFSET 0x88 +#define SFF_8636_FC_TECH_ELEC_INTRA (1 << 7) +#define SFF_8636_FC_TECH_SHORT_WO_OFC (1 << 6) +#define SFF_8636_FC_TECH_SHORT_W_OFC (1 << 5) +#define SFF_8636_FC_TECH_LONG_LL (1 << 4) + +/* Fibre Channel Transmitter Media - 137 */ +#define SFF_8636_FC_TRANS_MEDIA_OFFSET 0x89 +/* Twin Axial Pair */ +#define SFF_8636_FC_TRANS_MEDIA_TW (1 << 7) +/* Shielded Twisted Pair */ +#define SFF_8636_FC_TRANS_MEDIA_TP (1 << 6) +/* Miniature Coax */ +#define SFF_8636_FC_TRANS_MEDIA_MI (1 << 5) +/* Video Coax */ +#define SFF_8636_FC_TRANS_MEDIA_TV (1 << 4) +/* Multi-mode 62.5m */ +#define SFF_8636_FC_TRANS_MEDIA_M6 (1 << 3) +/* Multi-mode 50m */ +#define SFF_8636_FC_TRANS_MEDIA_M5 (1 << 2) +/* Multi-mode 50um */ +#define SFF_8636_FC_TRANS_MEDIA_OM3 (1 << 1) +/* Single Mode */ +#define SFF_8636_FC_TRANS_MEDIA_SM (1 << 0) + +/* Fibre Channel Speed - 138 */ +#define SFF_8636_FC_SPEED_OFFSET 0x8A +#define SFF_8636_FC_SPEED_1200_MBPS (1 << 7) +#define SFF_8636_FC_SPEED_800_MBPS (1 << 6) +#define SFF_8636_FC_SPEED_1600_MBPS (1 << 5) +#define SFF_8636_FC_SPEED_400_MBPS (1 << 4) +#define SFF_8636_FC_SPEED_200_MBPS (1 << 2) +#define SFF_8636_FC_SPEED_100_MBPS (1 << 0) + +/* Encoding - 139 */ +/* Values are defined under SFF_8024_ENCODING */ +#define SFF_8636_ENCODING_OFFSET 0x8B +#define SFF_8636_ENCODING_MANCHESTER 0x06 +#define SFF_8636_ENCODING_64B66B 0x05 +#define SFF_8636_ENCODING_SONET 0x04 +#define SFF_8636_ENCODING_NRZ 0x03 +#define SFF_8636_ENCODING_4B5B 0x02 +#define SFF_8636_ENCODING_8B10B 0x01 +#define SFF_8636_ENCODING_UNSPEC 0x00 + +/* BR, Nominal - 140 */ +#define SFF_8636_BR_NOMINAL_OFFSET 0x8C + +/* Extended RateSelect - 141 */ +#define SFF_8636_EXT_RS_OFFSET 0x8D +#define SFF_8636_EXT_RS_V1 (1 << 0) + +/* Length (Standard SM Fiber)-km - 142 */ +#define SFF_8636_SM_LEN_OFFSET 0x8E + +/* Length (OM3)-Unit 2m - 143 */ +#define SFF_8636_OM3_LEN_OFFSET 0x8F + +/* Length (OM2)-Unit 1m - 144 */ +#define SFF_8636_OM2_LEN_OFFSET 0x90 + +/* Length (OM1)-Unit 1m - 145 */ +#define SFF_8636_OM1_LEN_OFFSET 0x91 + +/* Cable Assembly Length -Unit 1m - 146 */ +#define SFF_8636_CBL_LEN_OFFSET 0x92 + +/* Device Technology - 147 */ +#define SFF_8636_DEVICE_TECH_OFFSET 0x93 +/* Transmitter Technology */ +#define SFF_8636_TRANS_TECH_MASK 0xF0 +/* Copper cable, linear active equalizers */ +#define SFF_8636_TRANS_COPPER_LNR_EQUAL (15 << 4) +/* Copper cable, near end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_NEAR_EQUAL (14 << 4) +/* Copper cable, far end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_FAR_EQUAL (13 << 4) +/* Copper cable, near & far end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_LNR_FAR_EQUAL (12 << 4) +/* Copper cable, passive equalized */ +#define SFF_8636_TRANS_COPPER_PAS_EQUAL (11 << 4) +/* Copper cable, unequalized */ +#define SFF_8636_TRANS_COPPER_PAS_UNEQUAL (10 << 4) +/* 1490 nm DFB */ +#define SFF_8636_TRANS_1490_DFB (9 << 4) +/* Others */ +#define SFF_8636_TRANS_OTHERS (8 << 4) +/* 1550 nm EML */ +#define SFF_8636_TRANS_1550_EML (7 << 4) +/* 1310 nm EML */ +#define SFF_8636_TRANS_1310_EML (6 << 4) +/* 1550 nm DFB */ +#define SFF_8636_TRANS_1550_DFB (5 << 4) +/* 1310 nm DFB */ +#define SFF_8636_TRANS_1310_DFB (4 << 4) +/* 1310 nm FP */ +#define SFF_8636_TRANS_1310_FP (3 << 4) +/* 1550 nm VCSEL */ +#define SFF_8636_TRANS_1550_VCSEL (2 << 4) +/* 1310 nm VCSEL */ +#define SFF_8636_TRANS_1310_VCSEL (1 << 4) +/* 850 nm VCSEL */ +#define SFF_8636_TRANS_850_VCSEL (0 << 4) + + /* Active/No wavelength control */ +#define SFF_8636_DEV_TECH_ACTIVE_WAVE_LEN (1 << 3) +/* Cooled transmitter */ +#define SFF_8636_DEV_TECH_COOL_TRANS (1 << 2) +/* APD/Pin Detector */ +#define SFF_8636_DEV_TECH_APD_DETECTOR (1 << 1) +/* Transmitter tunable */ +#define SFF_8636_DEV_TECH_TUNABLE (1 << 0) + +/* Vendor Name - 148-163 */ +#define SFF_8636_VENDOR_NAME_START_OFFSET 0x94 +#define SFF_8636_VENDOR_NAME_END_OFFSET 0xA3 + +/* Extended Module Codes - 164 */ +#define SFF_8636_EXT_MOD_CODE_OFFSET 0xA4 +#define SFF_8636_EXT_MOD_INFINIBAND_EDR (1 << 4) +#define SFF_8636_EXT_MOD_INFINIBAND_FDR (1 << 3) +#define SFF_8636_EXT_MOD_INFINIBAND_QDR (1 << 2) +#define SFF_8636_EXT_MOD_INFINIBAND_DDR (1 << 1) +#define SFF_8636_EXT_MOD_INFINIBAND_SDR (1 << 0) + +/* Vendor OUI - 165-167 */ +#define SFF_8636_VENDOR_OUI_OFFSET 0xA5 +#define SFF_8636_VENDOR_OUI_LEN 3 + +/* Vendor OUI - 165-167 */ +#define SFF_8636_VENDOR_PN_START_OFFSET 0xA8 +#define SFF_8636_VENDOR_PN_END_OFFSET 0xB7 + +/* Vendor Revision - 184-185 */ +#define SFF_8636_VENDOR_REV_START_OFFSET 0xB8 +#define SFF_8636_VENDOR_REV_END_OFFSET 0xB9 + +/* Wavelength - 186-187 */ +#define SFF_8636_WAVELEN_HIGH_BYTE_OFFSET 0xBA +#define SFF_8636_WAVELEN_LOW_BYTE_OFFSET 0xBB + +/* Wavelength Tolerance- 188-189 */ +#define SFF_8636_WAVE_TOL_HIGH_BYTE_OFFSET 0xBC +#define SFF_8636_WAVE_TOL_LOW_BYTE_OFFSET 0xBD + +/* Max case temp - Other than 70 C - 190 */ +#define SFF_8636_MAXCASE_TEMP_OFFSET 0xBE + +/* CC_BASE - 191 */ +#define SFF_8636_CC_BASE_OFFSET 0xBF + +/* Option Values - 192-195 */ +#define SFF_8636_OPTION_1_OFFSET 0xC0 +#define SFF_8636_ETHERNET_UNSPECIFIED 0x00 +#define SFF_8636_ETHERNET_100G_AOC 0x01 +#define SFF_8636_ETHERNET_100G_SR4 0x02 +#define SFF_8636_ETHERNET_100G_LR4 0x03 +#define SFF_8636_ETHERNET_100G_ER4 0x04 +#define SFF_8636_ETHERNET_100G_SR10 0x05 +#define SFF_8636_ETHERNET_100G_CWDM4_FEC 0x06 +#define SFF_8636_ETHERNET_100G_PSM4 0x07 +#define SFF_8636_ETHERNET_100G_ACC 0x08 +#define SFF_8636_ETHERNET_100G_CWDM4_NO_FEC 0x09 +#define SFF_8636_ETHERNET_100G_RSVD1 0x0A +#define SFF_8636_ETHERNET_100G_CR4 0x0B +#define SFF_8636_ETHERNET_25G_CR_CA_S 0x0C +#define SFF_8636_ETHERNET_25G_CR_CA_N 0x0D +#define SFF_8636_ETHERNET_40G_ER4 0x10 +#define SFF_8636_ETHERNET_4X10_SR 0x11 +#define SFF_8636_ETHERNET_40G_PSM4 0x12 +#define SFF_8636_ETHERNET_G959_P1I1_2D1 0x13 +#define SFF_8636_ETHERNET_G959_P1S1_2D2 0x14 +#define SFF_8636_ETHERNET_G959_P1L1_2D2 0x15 +#define SFF_8636_ETHERNET_10GT_SFI 0x16 +#define SFF_8636_ETHERNET_100G_CLR4 0x17 +#define SFF_8636_ETHERNET_100G_AOC2 0x18 +#define SFF_8636_ETHERNET_100G_ACC2 0x19 + +#define SFF_8636_OPTION_2_OFFSET 0xC1 +/* Rx output amplitude */ +#define SFF_8636_O2_RX_OUTPUT_AMP (1 << 0) +#define SFF_8636_OPTION_3_OFFSET 0xC2 +/* Rx Squelch Disable */ +#define SFF_8636_O3_RX_SQL_DSBL (1 << 3) +/* Rx Output Disable capable */ +#define SFF_8636_O3_RX_OUTPUT_DSBL (1 << 2) +/* Tx Squelch Disable */ +#define SFF_8636_O3_TX_SQL_DSBL (1 << 1) +/* Tx Squelch Impl */ +#define SFF_8636_O3_TX_SQL_IMPL (1 << 0) +#define SFF_8636_OPTION_4_OFFSET 0xC3 +/* Memory Page 02 present */ +#define SFF_8636_O4_PAGE_02_PRESENT (1 << 7) +/* Memory Page 01 present */ +#define SFF_8636_O4_PAGE_01_PRESENT (1 << 6) +/* Rate Select implemented */ +#define SFF_8636_O4_RATE_SELECT (1 << 5) +/* Tx_DISABLE implemented */ +#define SFF_8636_O4_TX_DISABLE (1 << 4) +/* Tx_FAULT implemented */ +#define SFF_8636_O4_TX_FAULT (1 << 3) +/* Tx Squelch implemented */ +#define SFF_8636_O4_TX_SQUELCH (1 << 2) +/* Tx Loss of Signal */ +#define SFF_8636_O4_TX_LOS (1 << 1) + +/* Vendor SN - 196-211 */ +#define SFF_8636_VENDOR_SN_START_OFFSET 0xC4 +#define SFF_8636_VENDOR_SN_END_OFFSET 0xD3 + +/* Vendor Date - 212-219 */ +#define SFF_8636_DATE_YEAR_OFFSET 0xD4 +#define SFF_8636_DATE_YEAR_LEN 2 +#define SFF_8636_DATE_MONTH_OFFSET 0xD6 +#define SFF_8636_DATE_MONTH_LEN 2 +#define SFF_8636_DATE_DAY_OFFSET 0xD8 +#define SFF_8636_DATE_DAY_LEN 2 +#define SFF_8636_DATE_VENDOR_LOT_OFFSET 0xDA +#define SFF_8636_DATE_VENDOR_LOT_LEN 2 + +/* Diagnostic Monitoring Type - 220 */ +#define SFF_8636_DIAG_TYPE_OFFSET 0xDC +#define SFF_8636_RX_PWR_TYPE_MASK 0x8 +#define SFF_8636_RX_PWR_TYPE_AVG_PWR (1 << 3) +#define SFF_8636_RX_PWR_TYPE_OMA (0 << 3) +#define SFF_8636_TX_PWR_TYPE_MASK 0x4 +#define SFF_8636_TX_PWR_TYPE_AVG_PWR (1 << 2) + +/* Enhanced Options - 221 */ +#define SFF_8636_ENH_OPTIONS_OFFSET 0xDD +#define SFF_8636_RATE_SELECT_EXT_SUPPORT (1 << 3) +#define SFF_8636_RATE_SELECT_APP_TABLE_SUPPORT (1 << 2) + +/* Check code - 223 */ +#define SFF_8636_CC_EXT_OFFSET 0xDF +#define SFF_8636_CC_EXT_LEN 1 + +/*------------------------------------------------------------------------------ + * + * Upper Memory Page 03h + * Contains module thresholds, channel thresholds and masks, + * and optional channel controls + * + * Offset - Page Num(3) * PageSize(0x80) + Page offset + */ + +/* Module Thresholds (48 Bytes) 128-175 */ +/* MSB at low address, LSB at high address */ +#define SFF_8636_TEMP_HALRM 0x200 +#define SFF_8636_TEMP_LALRM 0x202 +#define SFF_8636_TEMP_HWARN 0x204 +#define SFF_8636_TEMP_LWARN 0x206 + +#define SFF_8636_VCC_HALRM 0x210 +#define SFF_8636_VCC_LALRM 0x212 +#define SFF_8636_VCC_HWARN 0x214 +#define SFF_8636_VCC_LWARN 0x216 + +#define SFF_8636_RX_PWR_HALRM 0x230 +#define SFF_8636_RX_PWR_LALRM 0x232 +#define SFF_8636_RX_PWR_HWARN 0x234 +#define SFF_8636_RX_PWR_LWARN 0x236 + +#define SFF_8636_TX_BIAS_HALRM 0x238 +#define SFF_8636_TX_BIAS_LALRM 0x23A +#define SFF_8636_TX_BIAS_HWARN 0x23C +#define SFF_8636_TX_BIAS_LWARN 0x23E + +#define SFF_8636_TX_PWR_HALRM 0x240 +#define SFF_8636_TX_PWR_LALRM 0x242 +#define SFF_8636_TX_PWR_HWARN 0x244 +#define SFF_8636_TX_PWR_LWARN 0x246 + +#define ETH_MODULE_SFF_8636_MAX_LEN 640 +#define ETH_MODULE_SFF_8436_MAX_LEN 640 + +#endif /* _SFF_8636_H_ */ -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v5 0/5] add telemetry command for show module EEPROM 2022-04-26 2:43 ` [PATCH v5 0/5] add telemetry command for show module EEPROM Robin Zhang ` (4 preceding siblings ...) 2022-04-26 2:43 ` [PATCH v5 5/5] ethdev: format module EEPROM for SFF-8636 Robin Zhang @ 2022-05-04 8:13 ` Andrew Rybchenko 2022-05-11 2:14 ` [PATCH v6 " Robin Zhang 6 siblings, 0 replies; 77+ messages in thread From: Andrew Rybchenko @ 2022-05-04 8:13 UTC (permalink / raw) To: Robin Zhang, dev Cc: qiming.yang, qi.z.zhang, stevex.yang, thomas, bruce.richardson, david.marchand On 4/26/22 05:43, Robin Zhang wrote: > Introduce a new telemetry command /ethdev/module_eeprom to show module > EEPROM for each port. The format of module EEPROM information follows > the SFF(Small Form Factor) Committee specifications. > > Current the format support SFP(Small Formfactor Pluggable)/SFP+/ > QSFP+(Quad Small Formfactor Pluggable)/QSFP28 with specs SFF-8079/ > SFF-8472/SFF-8024/SFF-8636. > > Afther run the /ethdev/module_eeprom command, telemetry client will > show the module EEPROM information. We keep the same information content > compare with Linux utility ethtool, refer to command 'ethtool -m' of > ethtool v5.4. > > v5: > - fix CI robot compile fail issue The series still breaks build [1]. Now it is on Windows because of missing arpa/inet.h. [1] http://mails.dpdk.org/archives/test-report/2022-April/276614.html ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v6 0/5] add telemetry command for show module EEPROM 2022-04-26 2:43 ` [PATCH v5 0/5] add telemetry command for show module EEPROM Robin Zhang ` (5 preceding siblings ...) 2022-05-04 8:13 ` [PATCH v5 0/5] add telemetry command for show module EEPROM Andrew Rybchenko @ 2022-05-11 2:14 ` Robin Zhang 2022-05-11 2:14 ` [PATCH v6 1/5] ethdev: add telemetry command for " Robin Zhang ` (5 more replies) 6 siblings, 6 replies; 77+ messages in thread From: Robin Zhang @ 2022-05-11 2:14 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon, Ferruh Yigit, Andrew Rybchenko, Robin Zhang Introduce a new telemetry command /ethdev/module_eeprom to show module EEPROM for each port. The format of module EEPROM information follows the SFF(Small Form Factor) Committee specifications. Current the format support SFP(Small Formfactor Pluggable)/SFP+/ QSFP+(Quad Small Formfactor Pluggable)/QSFP28 with specs SFF-8079/ SFF-8472/SFF-8024/SFF-8636. Afther run the /ethdev/module_eeprom command, telemetry client will show the module EEPROM information. We keep the same information content compare with Linux utility ethtool, refer to command 'ethtool -m' of ethtool v5.4. v6: - refine code v5: - fix CI robot compile fail issue v4: - remove all printf in primary application, only show information in tememetry client - refine codes v3: - split up codes into several patches for better reivew Robin Zhang (5): ethdev: add telemetry command for module EEPROM ethdev: common utilities for different SFF specs ethdev: format module EEPROM for SFF-8079 ethdev: format module EEPROM for SFF-8472 ethdev: format module EEPROM for SFF-8636 lib/ethdev/ethdev_sff_telemetry.c | 149 ++++++ lib/ethdev/ethdev_sff_telemetry.h | 27 ++ lib/ethdev/meson.build | 5 + lib/ethdev/rte_ethdev.c | 3 + lib/ethdev/sff_8079.c | 406 ++++++++++++++++ lib/ethdev/sff_8472.c | 287 +++++++++++ lib/ethdev/sff_8636.c | 775 ++++++++++++++++++++++++++++++ lib/ethdev/sff_8636.h | 592 +++++++++++++++++++++++ lib/ethdev/sff_common.c | 326 +++++++++++++ lib/ethdev/sff_common.h | 174 +++++++ 10 files changed, 2744 insertions(+) create mode 100644 lib/ethdev/ethdev_sff_telemetry.c create mode 100644 lib/ethdev/ethdev_sff_telemetry.h create mode 100644 lib/ethdev/sff_8079.c create mode 100644 lib/ethdev/sff_8472.c create mode 100644 lib/ethdev/sff_8636.c create mode 100644 lib/ethdev/sff_8636.h create mode 100644 lib/ethdev/sff_common.c create mode 100644 lib/ethdev/sff_common.h -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v6 1/5] ethdev: add telemetry command for module EEPROM 2022-05-11 2:14 ` [PATCH v6 " Robin Zhang @ 2022-05-11 2:14 ` Robin Zhang 2022-05-11 2:14 ` [PATCH v6 2/5] ethdev: common utilities for different SFF specs Robin Zhang ` (4 subsequent siblings) 5 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-05-11 2:14 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon, Ferruh Yigit, Andrew Rybchenko, Robin Zhang Add a new telemetry command /ethdev/module_eeprom to dump the module EEPROM of each port. The format of module EEPROM information follows the SFF(Small Form Factor) Committee specifications. Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/ethdev_sff_telemetry.c | 138 ++++++++++++++++++++++++++++++ lib/ethdev/ethdev_sff_telemetry.h | 27 ++++++ lib/ethdev/meson.build | 1 + lib/ethdev/rte_ethdev.c | 3 + 4 files changed, 169 insertions(+) create mode 100644 lib/ethdev/ethdev_sff_telemetry.c create mode 100644 lib/ethdev/ethdev_sff_telemetry.h diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c new file mode 100644 index 0000000000..f756b9643f --- /dev/null +++ b/lib/ethdev/ethdev_sff_telemetry.c @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + */ + +#include <errno.h> + +#include <rte_ethdev.h> +#include <rte_common.h> +#include "ethdev_sff_telemetry.h" +#include "telemetry_data.h" + +static void +sff_port_module_eeprom_parse(uint16_t port_id, struct rte_tel_data *d) +{ + struct rte_eth_dev_module_info minfo; + struct rte_dev_eeprom_info einfo; + int ret; + + if (d == NULL) { + RTE_ETHDEV_LOG(ERR, "Dict invalid\n"); + return; + } + + ret = rte_eth_dev_get_module_info(port_id, &minfo); + if (ret != 0) { + switch (ret) { + case -ENODEV: + RTE_ETHDEV_LOG(ERR, "port index %d invalid\n", port_id); + break; + case -ENOTSUP: + RTE_ETHDEV_LOG(ERR, "operation not supported by device\n"); + break; + case -EIO: + RTE_ETHDEV_LOG(ERR, "device is removed\n"); + break; + default: + RTE_ETHDEV_LOG(ERR, "Unable to get port module info, %d\n", ret); + break; + } + return; + } + + einfo.offset = 0; + einfo.length = minfo.eeprom_len; + einfo.data = calloc(1, minfo.eeprom_len); + if (einfo.data == NULL) { + RTE_ETHDEV_LOG(ERR, "Allocation of port %u eeprom data failed\n", port_id); + return; + } + + ret = rte_eth_dev_get_module_eeprom(port_id, &einfo); + if (ret != 0) { + switch (ret) { + case -ENODEV: + RTE_ETHDEV_LOG(ERR, "port index %d invalid\n", port_id); + break; + case -ENOTSUP: + RTE_ETHDEV_LOG(ERR, "operation not supported by device\n"); + break; + case -EIO: + RTE_ETHDEV_LOG(ERR, "device is removed\n"); + break; + default: + RTE_ETHDEV_LOG(ERR, "Unable to get port module EEPROM, %d\n", ret); + break; + } + free(einfo.data); + return; + } + + switch (minfo.type) { + /* parsing module EEPROM data base on different module type */ + default: + RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); + break; + } + + free(einfo.data); +} + +void +ssf_add_dict_string(struct rte_tel_data *d, const char *name_str, const char *value_str) +{ + struct tel_dict_entry *e = &d->data.dict[d->data_len]; + + if (d->type != RTE_TEL_DICT) + return; + if (d->data_len >= RTE_TEL_MAX_DICT_ENTRIES) { + RTE_ETHDEV_LOG(ERR, "data_len has exceeded the maximum number of inserts\n"); + return; + } + + e->type = RTE_TEL_STRING_VAL; + /* append different values for same keys */ + if (d->data_len > 0) { + struct tel_dict_entry *previous = &d->data.dict[d->data_len - 1]; + if (strcmp(previous->name, name_str) == 0) { + strlcat(previous->value.sval, "; ", RTE_TEL_MAX_STRING_LEN); + strlcat(previous->value.sval, value_str, RTE_TEL_MAX_STRING_LEN); + goto end; + } + } + strlcpy(e->value.sval, value_str, RTE_TEL_MAX_STRING_LEN); + strlcpy(e->name, name_str, RTE_TEL_MAX_STRING_LEN); + d->data_len++; + +end: + return; +} + +int +eth_dev_handle_port_module_eeprom(const char *cmd __rte_unused, const char *params, + struct rte_tel_data *d) +{ + char *end_param; + int port_id; + + if (params == NULL || strlen(params) == 0 || !isdigit(*params)) + return -1; + + errno = 0; + port_id = strtoul(params, &end_param, 0); + + if (errno != 0) { + RTE_ETHDEV_LOG(ERR, "Invalid argument\n"); + return -1; + } + + if (*end_param != '\0') + RTE_ETHDEV_LOG(NOTICE, + "Extra parameters passed to ethdev telemetry command, ignoring\n"); + + rte_tel_data_start_dict(d); + + sff_port_module_eeprom_parse(port_id, d); + + return 0; +} diff --git a/lib/ethdev/ethdev_sff_telemetry.h b/lib/ethdev/ethdev_sff_telemetry.h new file mode 100644 index 0000000000..1fd870e0ef --- /dev/null +++ b/lib/ethdev/ethdev_sff_telemetry.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + */ + +#ifndef _ETHDEV_SFF_TELEMETRY_H_ +#define _ETHDEV_SFF_TELEMETRY_H_ + +#include <rte_telemetry.h> + +#define SFF_ITEM_VAL_COMPOSE_SIZE 64 + +/* SFF-8079 Optics diagnostics */ +void sff_8079_show_all(const uint8_t *data, struct rte_tel_data *d); + +/* SFF-8472 Optics diagnostics */ +void sff_8472_show_all(const uint8_t *data, struct rte_tel_data *d); + +/* SFF-8636 Optics diagnostics */ +void sff_8636_show_all(const uint8_t *data, uint32_t eeprom_len, struct rte_tel_data *d); + +int eth_dev_handle_port_module_eeprom(const char *cmd __rte_unused, + const char *params, + struct rte_tel_data *d); + +void ssf_add_dict_string(struct rte_tel_data *d, const char *name_str, const char *value_str); + +#endif /* _ETHDEV_SFF_TELEMETRY_H_ */ diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index a094585bf7..49c77acb3f 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -11,6 +11,7 @@ sources = files( 'rte_flow.c', 'rte_mtr.c', 'rte_tm.c', + 'ethdev_sff_telemetry.c', ) headers = files( diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c index 29a3d80466..2b87df1b32 100644 --- a/lib/ethdev/rte_ethdev.c +++ b/lib/ethdev/rte_ethdev.c @@ -39,6 +39,7 @@ #include "ethdev_driver.h" #include "ethdev_profile.h" #include "ethdev_private.h" +#include "ethdev_sff_telemetry.h" struct rte_eth_dev rte_eth_devices[RTE_MAX_ETHPORTS]; @@ -5876,4 +5877,6 @@ RTE_INIT(ethdev_init_telemetry) "Returns the link status for a port. Parameters: int port_id"); rte_telemetry_register_cmd("/ethdev/info", eth_dev_handle_port_info, "Returns the device info for a port. Parameters: int port_id"); + rte_telemetry_register_cmd("/ethdev/module_eeprom", eth_dev_handle_port_module_eeprom, + "Returns module EEPROM info with SFF specs. Parameters: int port_id"); } -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v6 2/5] ethdev: common utilities for different SFF specs 2022-05-11 2:14 ` [PATCH v6 " Robin Zhang 2022-05-11 2:14 ` [PATCH v6 1/5] ethdev: add telemetry command for " Robin Zhang @ 2022-05-11 2:14 ` Robin Zhang 2022-05-11 2:14 ` [PATCH v6 3/5] ethdev: format module EEPROM for SFF-8079 Robin Zhang ` (3 subsequent siblings) 5 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-05-11 2:14 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon, Ferruh Yigit, Andrew Rybchenko, Robin Zhang This patch implements SFF-8024 Rev 4.0 of pluggable I/O configuration and some common utilities for SFF-8436/8636 and SFF-8472/8079. Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/meson.build | 1 + lib/ethdev/sff_common.c | 326 ++++++++++++++++++++++++++++++++++++++++ lib/ethdev/sff_common.h | 174 +++++++++++++++++++++ 3 files changed, 501 insertions(+) create mode 100644 lib/ethdev/sff_common.c create mode 100644 lib/ethdev/sff_common.h diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index 49c77acb3f..8f39739e43 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -12,6 +12,7 @@ sources = files( 'rte_mtr.c', 'rte_tm.c', 'ethdev_sff_telemetry.c', + 'sff_common.c', ) headers = files( diff --git a/lib/ethdev/sff_common.c b/lib/ethdev/sff_common.c new file mode 100644 index 0000000000..06d96fac72 --- /dev/null +++ b/lib/ethdev/sff_common.c @@ -0,0 +1,326 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8024 Rev 4.0 of pluggable I/O configuration and some + * common utilities for SFF-8436/8636 and SFF-8472/8079 + * + */ + +#include <stdio.h> +#include <math.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "ethdev_sff_telemetry.h" + + +double convert_mw_to_dbm(double mw) +{ + return (10. * log10(mw / 1000.)) + 30.; +} + +void sff_show_value_with_unit(const uint8_t *data, unsigned int reg, + const char *name, unsigned int mult, + const char *unit, struct rte_tel_data *d) +{ + unsigned int val = data[reg]; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "%u%s", val * mult, unit); + ssf_add_dict_string(d, name, val_string); +} + +void sff_show_ascii(const uint8_t *data, unsigned int first_reg, + unsigned int last_reg, const char *name, struct rte_tel_data *d) +{ + unsigned int reg, val; + char tmp[3]; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + memset(val_string, 0, sizeof(val_string)); + + while (first_reg <= last_reg && data[last_reg] == ' ') + last_reg--; + for (reg = first_reg; reg <= last_reg; reg++) { + val = data[reg]; + if ((val >= 32) && (val <= 126)) { + snprintf(tmp, sizeof(tmp), "%c", val); + strlcat(val_string, tmp, sizeof(val_string)); + } else { + strlcat(val_string, "_", sizeof(val_string)); + } + } + ssf_add_dict_string(d, name, val_string); +} + +void sff_8024_show_oui(const uint8_t *data, int id_offset, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "%02x:%02x:%02x", + data[id_offset], data[(id_offset) + 1], data[(id_offset) + 2]); + ssf_add_dict_string(d, "Vendor OUI", val_string); +} + +void sff_8024_show_identifier(const uint8_t *data, int id_offset, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[id_offset]); + + switch (data[id_offset]) { + case SFF_8024_ID_UNKNOWN: + strlcat(val_string, " (no module present, unknown, or unspecified)", + sizeof(val_string)); + break; + case SFF_8024_ID_GBIC: + strlcat(val_string, " (GBIC)", sizeof(val_string)); + break; + case SFF_8024_ID_SOLDERED_MODULE: + strlcat(val_string, " (module soldered to motherboard)", sizeof(val_string)); + break; + case SFF_8024_ID_SFP: + strlcat(val_string, " (SFP)", sizeof(val_string)); + break; + case SFF_8024_ID_300_PIN_XBI: + strlcat(val_string, " (300 pin XBI)", sizeof(val_string)); + break; + case SFF_8024_ID_XENPAK: + strlcat(val_string, " (XENPAK)", sizeof(val_string)); + break; + case SFF_8024_ID_XFP: + strlcat(val_string, " (XFP)", sizeof(val_string)); + break; + case SFF_8024_ID_XFF: + strlcat(val_string, " (XFF)", sizeof(val_string)); + break; + case SFF_8024_ID_XFP_E: + strlcat(val_string, " (XFP-E)", sizeof(val_string)); + break; + case SFF_8024_ID_XPAK: + strlcat(val_string, " (XPAK)", sizeof(val_string)); + break; + case SFF_8024_ID_X2: + strlcat(val_string, " (X2)", sizeof(val_string)); + break; + case SFF_8024_ID_DWDM_SFP: + strlcat(val_string, " (DWDM-SFP)", sizeof(val_string)); + break; + case SFF_8024_ID_QSFP: + strlcat(val_string, " (QSFP)", sizeof(val_string)); + break; + case SFF_8024_ID_QSFP_PLUS: + strlcat(val_string, " (QSFP+)", sizeof(val_string)); + break; + case SFF_8024_ID_CXP: + strlcat(val_string, " (CXP)", sizeof(val_string)); + break; + case SFF_8024_ID_HD4X: + strlcat(val_string, " (Shielded Mini Multilane HD 4X)", sizeof(val_string)); + break; + case SFF_8024_ID_HD8X: + strlcat(val_string, " (Shielded Mini Multilane HD 8X)", sizeof(val_string)); + break; + case SFF_8024_ID_QSFP28: + strlcat(val_string, " (QSFP28)", sizeof(val_string)); + break; + case SFF_8024_ID_CXP2: + strlcat(val_string, " (CXP2/CXP28)", sizeof(val_string)); + break; + case SFF_8024_ID_CDFP: + strlcat(val_string, " (CDFP Style 1/Style 2)", sizeof(val_string)); + break; + case SFF_8024_ID_HD4X_FANOUT: + strlcat(val_string, " (Shielded Mini Multilane HD 4X Fanout Cable)", + sizeof(val_string)); + break; + case SFF_8024_ID_HD8X_FANOUT: + strlcat(val_string, " (Shielded Mini Multilane HD 8X Fanout Cable)", + sizeof(val_string)); + break; + case SFF_8024_ID_CDFP_S3: + strlcat(val_string, " (CDFP Style 3)", sizeof(val_string)); + break; + case SFF_8024_ID_MICRO_QSFP: + strlcat(val_string, " (microQSFP)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + ssf_add_dict_string(d, "Identifier", val_string); +} + +void sff_8024_show_connector(const uint8_t *data, int ctor_offset, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[ctor_offset]); + + switch (data[ctor_offset]) { + case SFF_8024_CTOR_UNKNOWN: + strlcat(val_string, " (unknown or unspecified)", sizeof(val_string)); + break; + case SFF_8024_CTOR_SC: + strlcat(val_string, " (SC)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FC_STYLE_1: + strlcat(val_string, " (Fibre Channel Style 1 copper)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FC_STYLE_2: + strlcat(val_string, " (Fibre Channel Style 2 copper)", sizeof(val_string)); + break; + case SFF_8024_CTOR_BNC_TNC: + strlcat(val_string, " (BNC/TNC)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FC_COAX: + strlcat(val_string, " (Fibre Channel coaxial headers)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FIBER_JACK: + strlcat(val_string, " (FibreJack)", sizeof(val_string)); + break; + case SFF_8024_CTOR_LC: + strlcat(val_string, " (LC)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MT_RJ: + strlcat(val_string, " (MT-RJ)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MU: + strlcat(val_string, " (MU)", sizeof(val_string)); + break; + case SFF_8024_CTOR_SG: + strlcat(val_string, " (SG)", sizeof(val_string)); + break; + case SFF_8024_CTOR_OPT_PT: + strlcat(val_string, " (Optical pigtail)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MPO: + strlcat(val_string, " (MPO Parallel Optic)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MPO_2: + strlcat(val_string, " (MPO Parallel Optic - 2x16)", sizeof(val_string)); + break; + case SFF_8024_CTOR_HSDC_II: + strlcat(val_string, " (HSSDC II)", sizeof(val_string)); + break; + case SFF_8024_CTOR_COPPER_PT: + strlcat(val_string, " (Copper pigtail)", sizeof(val_string)); + break; + case SFF_8024_CTOR_RJ45: + strlcat(val_string, " (RJ45)", sizeof(val_string)); + break; + case SFF_8024_CTOR_NO_SEPARABLE: + strlcat(val_string, " (No separable connector)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MXC_2x16: + strlcat(val_string, " (MXC 2x16)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + ssf_add_dict_string(d, "Connector", val_string); +} + +void sff_8024_show_encoding(const uint8_t *data, int encoding_offset, + int sff_type, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[encoding_offset]); + + switch (data[encoding_offset]) { + case SFF_8024_ENCODING_UNSPEC: + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_8B10B: + strlcat(val_string, " (8B/10B)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_4B5B: + strlcat(val_string, " (4B/5B)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_NRZ: + strlcat(val_string, " (NRZ)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_4h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) + strlcat(val_string, " (Manchester)", sizeof(val_string)); + else if (sff_type == RTE_ETH_MODULE_SFF_8636) + strlcat(val_string, " (SONET Scrambled)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_5h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) + strlcat(val_string, " (SONET Scrambled)", sizeof(val_string)); + else if (sff_type == RTE_ETH_MODULE_SFF_8636) + strlcat(val_string, " (64B/66B)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_6h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) + strlcat(val_string, " (64B/66B)", sizeof(val_string)); + else if (sff_type == RTE_ETH_MODULE_SFF_8636) + strlcat(val_string, " (Manchester)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_256B: + strlcat(val_string, + " ((256B/257B (transcoded FEC-enabled data))", sizeof(val_string)); + break; + case SFF_8024_ENCODING_PAM4: + strlcat(val_string, " (PAM4)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + ssf_add_dict_string(d, "Encoding", val_string); +} + +void sff_show_thresholds(struct sff_diags sd, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + SPRINT_BIAS(val_string, sd.bias_cur[HALRM]); + ssf_add_dict_string(d, "Laser bias current high alarm threshold", val_string); + SPRINT_BIAS(val_string, sd.bias_cur[LALRM]); + ssf_add_dict_string(d, "Laser bias current low alarm threshold", val_string); + SPRINT_BIAS(val_string, sd.bias_cur[HWARN]); + ssf_add_dict_string(d, "Laser bias current high warning threshold", val_string); + SPRINT_BIAS(val_string, sd.bias_cur[LWARN]); + ssf_add_dict_string(d, "Laser bias current low warning threshold", val_string); + + SPRINT_xX_PWR(val_string, sd.tx_power[HALRM]); + ssf_add_dict_string(d, "Laser output power high alarm threshold", val_string); + SPRINT_xX_PWR(val_string, sd.tx_power[LALRM]); + ssf_add_dict_string(d, "Laser output power low alarm threshold", val_string); + SPRINT_xX_PWR(val_string, sd.tx_power[HWARN]); + ssf_add_dict_string(d, "Laser output power high warning threshold", val_string); + SPRINT_xX_PWR(val_string, sd.tx_power[LWARN]); + ssf_add_dict_string(d, "Laser output power low warning threshold", val_string); + + SPRINT_TEMP(val_string, sd.sfp_temp[HALRM]); + ssf_add_dict_string(d, "Module temperature high alarm threshold", val_string); + SPRINT_TEMP(val_string, sd.sfp_temp[LALRM]); + ssf_add_dict_string(d, "Module temperature low alarm threshold", val_string); + SPRINT_TEMP(val_string, sd.sfp_temp[HWARN]); + ssf_add_dict_string(d, "Module temperature high warning threshold", val_string); + SPRINT_TEMP(val_string, sd.sfp_temp[LWARN]); + ssf_add_dict_string(d, "Module temperature low warning threshold", val_string); + + SPRINT_VCC(val_string, sd.sfp_voltage[HALRM]); + ssf_add_dict_string(d, "Module voltage high alarm threshold", val_string); + SPRINT_VCC(val_string, sd.sfp_voltage[LALRM]); + ssf_add_dict_string(d, "Module voltage low alarm threshold", val_string); + SPRINT_VCC(val_string, sd.sfp_voltage[HWARN]); + ssf_add_dict_string(d, "Module voltage high warning threshold", val_string); + SPRINT_VCC(val_string, sd.sfp_voltage[LWARN]); + ssf_add_dict_string(d, "Module voltage low alarm threshold", val_string); + + SPRINT_xX_PWR(val_string, sd.rx_power[HALRM]); + ssf_add_dict_string(d, "Laser rx power high alarm threshold", val_string); + SPRINT_xX_PWR(val_string, sd.rx_power[LALRM]); + ssf_add_dict_string(d, "Laser rx power low alarm threshold", val_string); + SPRINT_xX_PWR(val_string, sd.rx_power[HWARN]); + ssf_add_dict_string(d, "Laser rx power high warning threshold", val_string); + SPRINT_xX_PWR(val_string, sd.rx_power[LWARN]); + ssf_add_dict_string(d, "Laser rx power low warning threshold", val_string); +} diff --git a/lib/ethdev/sff_common.h b/lib/ethdev/sff_common.h new file mode 100644 index 0000000000..264fb915cd --- /dev/null +++ b/lib/ethdev/sff_common.h @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8024 Rev 4.0 of pluggable I/O configuration and some + * common utilities for SFF-8436/8636 and SFF-8472/8079 + * + */ + +#ifndef _SFF_COMMON_H_ +#define _SFF_COMMON_H_ + +#include <stdio.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "ethdev_sff_telemetry.h" + +#define SFF_8024_ID_OFFSET 0x00 +#define SFF_8024_ID_UNKNOWN 0x00 +#define SFF_8024_ID_GBIC 0x01 +#define SFF_8024_ID_SOLDERED_MODULE 0x02 +#define SFF_8024_ID_SFP 0x03 +#define SFF_8024_ID_300_PIN_XBI 0x04 +#define SFF_8024_ID_XENPAK 0x05 +#define SFF_8024_ID_XFP 0x06 +#define SFF_8024_ID_XFF 0x07 +#define SFF_8024_ID_XFP_E 0x08 +#define SFF_8024_ID_XPAK 0x09 +#define SFF_8024_ID_X2 0x0A +#define SFF_8024_ID_DWDM_SFP 0x0B +#define SFF_8024_ID_QSFP 0x0C +#define SFF_8024_ID_QSFP_PLUS 0x0D +#define SFF_8024_ID_CXP 0x0E +#define SFF_8024_ID_HD4X 0x0F +#define SFF_8024_ID_HD8X 0x10 +#define SFF_8024_ID_QSFP28 0x11 +#define SFF_8024_ID_CXP2 0x12 +#define SFF_8024_ID_CDFP 0x13 +#define SFF_8024_ID_HD4X_FANOUT 0x14 +#define SFF_8024_ID_HD8X_FANOUT 0x15 +#define SFF_8024_ID_CDFP_S3 0x16 +#define SFF_8024_ID_MICRO_QSFP 0x17 +#define SFF_8024_ID_LAST SFF_8024_ID_MICRO_QSFP +#define SFF_8024_ID_UNALLOCATED_LAST 0x7F +#define SFF_8024_ID_VENDOR_START 0x80 +#define SFF_8024_ID_VENDOR_LAST 0xFF + +#define SFF_8024_CTOR_UNKNOWN 0x00 +#define SFF_8024_CTOR_SC 0x01 +#define SFF_8024_CTOR_FC_STYLE_1 0x02 +#define SFF_8024_CTOR_FC_STYLE_2 0x03 +#define SFF_8024_CTOR_BNC_TNC 0x04 +#define SFF_8024_CTOR_FC_COAX 0x05 +#define SFF_8024_CTOR_FIBER_JACK 0x06 +#define SFF_8024_CTOR_LC 0x07 +#define SFF_8024_CTOR_MT_RJ 0x08 +#define SFF_8024_CTOR_MU 0x09 +#define SFF_8024_CTOR_SG 0x0A +#define SFF_8024_CTOR_OPT_PT 0x0B +#define SFF_8024_CTOR_MPO 0x0C +#define SFF_8024_CTOR_MPO_2 0x0D +/* 0E-1Fh --- Reserved */ +#define SFF_8024_CTOR_HSDC_II 0x20 +#define SFF_8024_CTOR_COPPER_PT 0x21 +#define SFF_8024_CTOR_RJ45 0x22 +#define SFF_8024_CTOR_NO_SEPARABLE 0x23 +#define SFF_8024_CTOR_MXC_2x16 0x24 +#define SFF_8024_CTOR_LAST SFF_8024_CTOR_MXC_2x16 +#define SFF_8024_CTOR_UNALLOCATED_LAST 0x7F +#define SFF_8024_CTOR_VENDOR_START 0x80 +#define SFF_8024_CTOR_VENDOR_LAST 0xFF + +/* ENCODING Values */ +#define SFF_8024_ENCODING_UNSPEC 0x00 +#define SFF_8024_ENCODING_8B10B 0x01 +#define SFF_8024_ENCODING_4B5B 0x02 +#define SFF_8024_ENCODING_NRZ 0x03 +/* + * Value: 04h + * SFF-8472 - Manchester + * SFF-8436/8636 - SONET Scrambled + */ +#define SFF_8024_ENCODING_4h 0x04 +/* + * Value: 05h + * SFF-8472 - SONET Scrambled + * SFF-8436/8636 - 64B/66B + */ +#define SFF_8024_ENCODING_5h 0x05 +/* + * Value: 06h + * SFF-8472 - 64B/66B + * SFF-8436/8636 - Manchester + */ +#define SFF_8024_ENCODING_6h 0x06 +#define SFF_8024_ENCODING_256B 0x07 +#define SFF_8024_ENCODING_PAM4 0x08 + +/* Most common case: 16-bit unsigned integer in a certain unit */ +#define OFFSET_TO_U16(offset) \ + (data[offset] << 8 | data[(offset) + 1]) + +#define SPRINT_xX_PWR(str, var) \ + snprintf(str, sizeof(str), "%.4f mW / %.2f dBm", \ + (double)((var) / 10000.), \ + convert_mw_to_dbm((double)((var) / 10000.))) + +#define SPRINT_BIAS(str, bias_cur) \ + snprintf(str, sizeof(str), "%.3f mA", (double)(bias_cur / 500.)) + +#define SPRINT_TEMP(str, temp) \ + snprintf(str, sizeof(str), "%.2f degrees C / %.2f degrees F", \ + (double)(temp / 256.), \ + (double)(temp / 256. * 1.8 + 32.)) + +#define SPRINT_VCC(str, sfp_voltage) \ + snprintf(str, sizeof(str), "%.4f V", (double)(sfp_voltage / 10000.)) + +/* Channel Monitoring Fields */ +struct sff_channel_diags { + uint16_t bias_cur; /* Measured bias current in 2uA units */ + uint16_t rx_power; /* Measured RX Power */ + uint16_t tx_power; /* Measured TX Power */ +}; + +/* Module Monitoring Fields */ +struct sff_diags { + +#define MAX_CHANNEL_NUM 4 +#define LWARN 0 +#define HWARN 1 +#define LALRM 2 +#define HALRM 3 +#define MCURR 4 + + /* Supports DOM */ + uint8_t supports_dom; + /* Supports alarm/warning thold */ + uint8_t supports_alarms; + /* RX Power: 0 = OMA, 1 = Average power */ + uint8_t rx_power_type; + /* TX Power: 0 = Not supported, 1 = Average power */ + uint8_t tx_power_type; + + uint8_t calibrated_ext; /* Is externally calibrated */ + /* [5] tables are low/high warn, low/high alarm, current */ + /* SFP voltage in 0.1mV units */ + uint16_t sfp_voltage[5]; + /* SFP Temp in 16-bit signed 1/256 Celcius */ + int16_t sfp_temp[5]; + /* Measured bias current in 2uA units */ + uint16_t bias_cur[5]; + /* Measured TX Power */ + uint16_t tx_power[5]; + /* Measured RX Power */ + uint16_t rx_power[5]; + struct sff_channel_diags scd[MAX_CHANNEL_NUM]; +}; + +double convert_mw_to_dbm(double mw); +void sff_show_value_with_unit(const uint8_t *data, unsigned int reg, + const char *name, unsigned int mult, + const char *unit, struct rte_tel_data *d); +void sff_show_ascii(const uint8_t *data, unsigned int first_reg, + unsigned int last_reg, const char *name, struct rte_tel_data *d); +void sff_show_thresholds(struct sff_diags sd, struct rte_tel_data *d); + +void sff_8024_show_oui(const uint8_t *data, int id_offset, struct rte_tel_data *d); +void sff_8024_show_identifier(const uint8_t *data, int id_offset, struct rte_tel_data *d); +void sff_8024_show_connector(const uint8_t *data, int ctor_offset, struct rte_tel_data *d); +void sff_8024_show_encoding(const uint8_t *data, int encoding_offset, + int sff_type, struct rte_tel_data *d); + +#endif /* _SFF_COMMON_H_ */ -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v6 3/5] ethdev: format module EEPROM for SFF-8079 2022-05-11 2:14 ` [PATCH v6 " Robin Zhang 2022-05-11 2:14 ` [PATCH v6 1/5] ethdev: add telemetry command for " Robin Zhang 2022-05-11 2:14 ` [PATCH v6 2/5] ethdev: common utilities for different SFF specs Robin Zhang @ 2022-05-11 2:14 ` Robin Zhang 2022-05-11 2:14 ` [PATCH v6 4/5] ethdev: format module EEPROM for SFF-8472 Robin Zhang ` (2 subsequent siblings) 5 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-05-11 2:14 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon, Ferruh Yigit, Andrew Rybchenko, Robin Zhang This patch implements format module EEPROM information for SFF-8079 Rev 1.7 Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/ethdev_sff_telemetry.c | 3 + lib/ethdev/meson.build | 1 + lib/ethdev/sff_8079.c | 406 ++++++++++++++++++++++++++++++ 3 files changed, 410 insertions(+) create mode 100644 lib/ethdev/sff_8079.c diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c index f756b9643f..63b0d21786 100644 --- a/lib/ethdev/ethdev_sff_telemetry.c +++ b/lib/ethdev/ethdev_sff_telemetry.c @@ -70,6 +70,9 @@ sff_port_module_eeprom_parse(uint16_t port_id, struct rte_tel_data *d) switch (minfo.type) { /* parsing module EEPROM data base on different module type */ + case RTE_ETH_MODULE_SFF_8079: + sff_8079_show_all(einfo.data, d); + break; default: RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); break; diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index 8f39739e43..d94860da0c 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -13,6 +13,7 @@ sources = files( 'rte_tm.c', 'ethdev_sff_telemetry.c', 'sff_common.c', + 'sff_8079.c', ) headers = files( diff --git a/lib/ethdev/sff_8079.c b/lib/ethdev/sff_8079.c new file mode 100644 index 0000000000..cfa20bd3cb --- /dev/null +++ b/lib/ethdev/sff_8079.c @@ -0,0 +1,406 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8079 optics diagnostics. + * + */ + +#include <stdio.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "ethdev_sff_telemetry.h" + +static void sff_8079_show_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_identifier(data, 0, d); +} + +static void sff_8079_show_ext_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[1]); + if (data[1] == 0x00) + strlcat(val_string, " (GBIC not specified / not MOD_DEF compliant)", + sizeof(val_string)); + else if (data[1] == 0x04) + strlcat(val_string, " (GBIC/SFP defined by 2-wire interface ID)", + sizeof(val_string)); + else if (data[1] <= 0x07) { + char tmp[SFF_ITEM_VAL_COMPOSE_SIZE]; + snprintf(tmp, sizeof(tmp), " (GBIC compliant with MOD_DEF %u)", data[1]); + strlcat(val_string, tmp, sizeof(val_string)); + } else + strlcat(val_string, " (unknown)", sizeof(val_string)); + ssf_add_dict_string(d, "Extended identifier", val_string); +} + +static void sff_8079_show_connector(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_connector(data, 2, d); +} + +static void sff_8079_show_transceiver(const uint8_t *data, struct rte_tel_data *d) +{ + static const char *name = "Transceiver type"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), + "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[36]); + ssf_add_dict_string(d, "Transceiver codes", val_string); + + /* 10G Ethernet Compliance Codes */ + if (data[3] & (1 << 7)) + ssf_add_dict_string(d, "10G Ethernet transceiver type", + "10G Ethernet: 10G Base-ER [SFF-8472 rev10.4 onwards]"); + if (data[3] & (1 << 6)) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-LRM"); + if (data[3] & (1 << 5)) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-LR"); + if (data[3] & (1 << 4)) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-SR"); + + /* Infiniband Compliance Codes */ + if (data[3] & (1 << 3)) + ssf_add_dict_string(d, name, "Infiniband: 1X SX"); + if (data[3] & (1 << 2)) + ssf_add_dict_string(d, name, "Infiniband: 1X LX"); + if (data[3] & (1 << 1)) + ssf_add_dict_string(d, name, "Infiniband: 1X Copper Active"); + if (data[3] & (1 << 0)) + ssf_add_dict_string(d, name, "Infiniband: 1X Copper Passive"); + + /* ESCON Compliance Codes */ + if (data[4] & (1 << 7)) + ssf_add_dict_string(d, name, "ESCON: ESCON MMF, 1310nm LED"); + if (data[4] & (1 << 6)) + ssf_add_dict_string(d, name, "ESCON: ESCON SMF, 1310nm Laser"); + + /* SONET Compliance Codes */ + if (data[4] & (1 << 5)) + ssf_add_dict_string(d, name, "SONET: OC-192, short reach"); + if (data[4] & (1 << 4)) + ssf_add_dict_string(d, name, "SONET: SONET reach specifier bit 1"); + if (data[4] & (1 << 3)) + ssf_add_dict_string(d, name, "SONET: SONET reach specifier bit 2"); + if (data[4] & (1 << 2)) + ssf_add_dict_string(d, name, "SONET: OC-48, long reach"); + if (data[4] & (1 << 1)) + ssf_add_dict_string(d, name, "SONET: OC-48, intermediate reach"); + if (data[4] & (1 << 0)) + ssf_add_dict_string(d, name, "SONET: OC-48, short reach"); + if (data[5] & (1 << 6)) + ssf_add_dict_string(d, name, "SONET: OC-12, single mode, long reach"); + if (data[5] & (1 << 5)) + ssf_add_dict_string(d, name, "SONET: OC-12, single mode, inter. reach"); + if (data[5] & (1 << 4)) + ssf_add_dict_string(d, name, "SONET: OC-12, short reach"); + if (data[5] & (1 << 2)) + ssf_add_dict_string(d, name, "SONET: OC-3, single mode, long reach"); + if (data[5] & (1 << 1)) + ssf_add_dict_string(d, name, "SONET: OC-3, single mode, inter. reach"); + if (data[5] & (1 << 0)) + ssf_add_dict_string(d, name, "SONET: OC-3, short reach"); + + /* Ethernet Compliance Codes */ + if (data[6] & (1 << 7)) + ssf_add_dict_string(d, name, "Ethernet: BASE-PX"); + if (data[6] & (1 << 6)) + ssf_add_dict_string(d, name, "Ethernet: BASE-BX10"); + if (data[6] & (1 << 5)) + ssf_add_dict_string(d, name, "Ethernet: 100BASE-FX"); + if (data[6] & (1 << 4)) + ssf_add_dict_string(d, name, "Ethernet: 100BASE-LX/LX10"); + if (data[6] & (1 << 3)) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-T"); + if (data[6] & (1 << 2)) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-CX"); + if (data[6] & (1 << 1)) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-LX"); + if (data[6] & (1 << 0)) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-SX"); + + /* Fibre Channel link length */ + if (data[7] & (1 << 7)) + ssf_add_dict_string(d, name, "FC: very long distance (V)"); + if (data[7] & (1 << 6)) + ssf_add_dict_string(d, name, "FC: short distance (S)"); + if (data[7] & (1 << 5)) + ssf_add_dict_string(d, name, "FC: intermediate distance (I)"); + if (data[7] & (1 << 4)) + ssf_add_dict_string(d, name, "FC: long distance (L)"); + if (data[7] & (1 << 3)) + ssf_add_dict_string(d, name, "FC: medium distance (M)"); + + /* Fibre Channel transmitter technology */ + if (data[7] & (1 << 2)) + ssf_add_dict_string(d, name, "FC: Shortwave laser, linear Rx (SA)"); + if (data[7] & (1 << 1)) + ssf_add_dict_string(d, name, "FC: Longwave laser (LC)"); + if (data[7] & (1 << 0)) + ssf_add_dict_string(d, name, "FC: Electrical inter-enclosure (EL)"); + if (data[8] & (1 << 7)) + ssf_add_dict_string(d, name, "FC: Electrical intra-enclosure (EL)"); + if (data[8] & (1 << 6)) + ssf_add_dict_string(d, name, "FC: Shortwave laser w/o OFC (SN)"); + if (data[8] & (1 << 5)) + ssf_add_dict_string(d, name, "FC: Shortwave laser with OFC (SL)"); + if (data[8] & (1 << 4)) + ssf_add_dict_string(d, name, "FC: Longwave laser (LL)"); + if (data[8] & (1 << 3)) + ssf_add_dict_string(d, name, "Active Cable"); + if (data[8] & (1 << 2)) + ssf_add_dict_string(d, name, "Passive Cable"); + if (data[8] & (1 << 1)) + ssf_add_dict_string(d, name, "FC: Copper FC-BaseT"); + + /* Fibre Channel transmission media */ + if (data[9] & (1 << 7)) + ssf_add_dict_string(d, name, "FC: Twin Axial Pair (TW)"); + if (data[9] & (1 << 6)) + ssf_add_dict_string(d, name, "FC: Twisted Pair (TP)"); + if (data[9] & (1 << 5)) + ssf_add_dict_string(d, name, "FC: Miniature Coax (MI)"); + if (data[9] & (1 << 4)) + ssf_add_dict_string(d, name, "FC: Video Coax (TV)"); + if (data[9] & (1 << 3)) + ssf_add_dict_string(d, name, "FC: Multimode, 62.5um (M6)"); + if (data[9] & (1 << 2)) + ssf_add_dict_string(d, name, "FC: Multimode, 50um (M5)"); + if (data[9] & (1 << 0)) + ssf_add_dict_string(d, name, "FC: Single Mode (SM)"); + + /* Fibre Channel speed */ + if (data[10] & (1 << 7)) + ssf_add_dict_string(d, name, "FC: 1200 MBytes/sec"); + if (data[10] & (1 << 6)) + ssf_add_dict_string(d, name, "FC: 800 MBytes/sec"); + if (data[10] & (1 << 4)) + ssf_add_dict_string(d, name, "FC: 400 MBytes/sec"); + if (data[10] & (1 << 2)) + ssf_add_dict_string(d, name, "FC: 200 MBytes/sec"); + if (data[10] & (1 << 0)) + ssf_add_dict_string(d, name, "FC: 100 MBytes/sec"); + + /* Extended Specification Compliance Codes from SFF-8024 */ + switch (data[36]) { + case 0x1: + ssf_add_dict_string(d, name, + "Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)"); + break; + case 0x2: + ssf_add_dict_string(d, name, "Extended: 100G Base-SR4 or 25GBase-SR"); + break; + case 0x3: + ssf_add_dict_string(d, name, "Extended: 100G Base-LR4 or 25GBase-LR"); + break; + case 0x4: + ssf_add_dict_string(d, name, "Extended: 100G Base-ER4 or 25GBase-ER"); + break; + case 0x8: + ssf_add_dict_string(d, name, + "Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)"); + break; + case 0xb: + ssf_add_dict_string(d, name, "Extended: 100G Base-CR4 or 25G Base-CR CA-L"); + break; + case 0xc: + ssf_add_dict_string(d, name, "Extended: 25G Base-CR CA-S"); + break; + case 0xd: + ssf_add_dict_string(d, name, "Extended: 25G Base-CR CA-N"); + break; + case 0x16: + ssf_add_dict_string(d, name, "Extended: 10Gbase-T with SFI electrical interface"); + break; + case 0x18: + ssf_add_dict_string(d, name, + "Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)"); + break; + case 0x19: + ssf_add_dict_string(d, name, + "Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)"); + break; + case 0x1c: + ssf_add_dict_string(d, name, "Extended: 10Gbase-T Short Reach"); + break; + default: + break; + } +} + +static void sff_8079_show_encoding(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_encoding(data, 11, RTE_ETH_MODULE_SFF_8472, d); +} + +static void sff_8079_show_rate_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[13]); + + switch (data[13]) { + case 0x00: + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case 0x01: + strlcat(val_string, " (4/2/1G Rate_Select & AS0/AS1)", sizeof(val_string)); + break; + case 0x02: + strlcat(val_string, " (8/4/2G Rx Rate_Select only)", sizeof(val_string)); + break; + case 0x03: + strlcat(val_string, " (8/4/2G Independent Rx & Tx Rate_Select)", + sizeof(val_string)); + break; + case 0x04: + strlcat(val_string, " (8/4/2G Tx Rate_Select only)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + ssf_add_dict_string(d, "Rate identifier", val_string); +} + +static void sff_8079_show_oui(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_oui(data, 37, d); +} + +static void +sff_8079_show_wavelength_or_copper_compliance(const uint8_t *data, + struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + if (data[8] & (1 << 2)) { + snprintf(val_string, sizeof(val_string), "0x%02x", data[60]); + switch (data[60]) { + case 0x00: + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case 0x01: + strlcat(val_string, " (SFF-8431 appendix E)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (unknown)", sizeof(val_string)); + break; + } + strlcat(val_string, " [SFF-8472 rev10.4 only]", sizeof(val_string)); + ssf_add_dict_string(d, "Passive Cu cmplnce.", val_string); + } else if (data[8] & (1 << 3)) { + snprintf(val_string, sizeof(val_string), "0x%02x", data[60]); + switch (data[60]) { + case 0x00: + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case 0x01: + strlcat(val_string, " (SFF-8431 appendix E)", sizeof(val_string)); + break; + case 0x04: + strlcat(val_string, " (SFF-8431 limiting)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (unknown)", sizeof(val_string)); + break; + } + strlcat(val_string, " [SFF-8472 rev10.4 only]", sizeof(val_string)); + ssf_add_dict_string(d, "Active Cu cmplnce.", val_string); + } else { + snprintf(val_string, sizeof(val_string), "%unm", (data[60] << 8) | data[61]); + ssf_add_dict_string(d, "Laser wavelength", val_string); + } +} + +static void sff_8079_show_options(const uint8_t *data, struct rte_tel_data *d) +{ + static const char *name = "Option"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x 0x%02x", data[64], data[65]); + ssf_add_dict_string(d, "Option values", val_string); + + if (data[65] & (1 << 1)) + ssf_add_dict_string(d, name, "RX_LOS implemented"); + if (data[65] & (1 << 2)) + ssf_add_dict_string(d, name, "RX_LOS implemented, inverted"); + if (data[65] & (1 << 3)) + ssf_add_dict_string(d, name, "TX_FAULT implemented"); + if (data[65] & (1 << 4)) + ssf_add_dict_string(d, name, "TX_DISABLE implemented"); + if (data[65] & (1 << 5)) + ssf_add_dict_string(d, name, "RATE_SELECT implemented"); + if (data[65] & (1 << 6)) + ssf_add_dict_string(d, name, "Tunable transmitter technology"); + if (data[65] & (1 << 7)) + ssf_add_dict_string(d, name, "Receiver decision threshold implemented"); + if (data[64] & (1 << 0)) + ssf_add_dict_string(d, name, "Linear receiver output implemented"); + if (data[64] & (1 << 1)) + ssf_add_dict_string(d, name, "Power level 2 requirement"); + if (data[64] & (1 << 2)) + ssf_add_dict_string(d, name, "Cooled transceiver implemented"); + if (data[64] & (1 << 3)) + ssf_add_dict_string(d, name, "Retimer or CDR implemented"); + if (data[64] & (1 << 4)) + ssf_add_dict_string(d, name, "Paging implemented"); + if (data[64] & (1 << 5)) + ssf_add_dict_string(d, name, "Power level 3 requirement"); +} + +void sff_8079_show_all(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8079_show_identifier(data, d); + if (((data[0] == 0x02) || (data[0] == 0x03)) && (data[1] == 0x04)) { + unsigned int br_nom, br_min, br_max; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + if (data[12] == 0) { + br_nom = br_min = br_max = 0; + } else if (data[12] == 255) { + br_nom = data[66] * 250; + br_max = data[67]; + br_min = data[67]; + } else { + br_nom = data[12] * 100; + br_max = data[66]; + br_min = data[67]; + } + sff_8079_show_ext_identifier(data, d); + sff_8079_show_connector(data, d); + sff_8079_show_transceiver(data, d); + sff_8079_show_encoding(data, d); + + snprintf(val_string, sizeof(val_string), "%uMBd", br_nom); + ssf_add_dict_string(d, "BR, Nominal", val_string); + + sff_8079_show_rate_identifier(data, d); + sff_show_value_with_unit(data, 14, + "Length (SMF,km)", 1, "km", d); + sff_show_value_with_unit(data, 15, "Length (SMF)", 100, "m", d); + sff_show_value_with_unit(data, 16, "Length (50um)", 10, "m", d); + sff_show_value_with_unit(data, 17, + "Length (62.5um)", 10, "m", d); + sff_show_value_with_unit(data, 18, "Length (Copper)", 1, "m", d); + sff_show_value_with_unit(data, 19, "Length (OM3)", 10, "m", d); + sff_8079_show_wavelength_or_copper_compliance(data, d); + sff_show_ascii(data, 20, 35, "Vendor name", d); + sff_8079_show_oui(data, d); + sff_show_ascii(data, 40, 55, "Vendor PN", d); + sff_show_ascii(data, 56, 59, "Vendor rev", d); + sff_8079_show_options(data, d); + + snprintf(val_string, sizeof(val_string), "%u%%", br_max); + ssf_add_dict_string(d, "BR margin, max", val_string); + snprintf(val_string, sizeof(val_string), "%u%%", br_min); + ssf_add_dict_string(d, "BR margin, min", val_string); + + sff_show_ascii(data, 68, 83, "Vendor SN", d); + sff_show_ascii(data, 84, 91, "Date code", d); + } +} -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v6 4/5] ethdev: format module EEPROM for SFF-8472 2022-05-11 2:14 ` [PATCH v6 " Robin Zhang ` (2 preceding siblings ...) 2022-05-11 2:14 ` [PATCH v6 3/5] ethdev: format module EEPROM for SFF-8079 Robin Zhang @ 2022-05-11 2:14 ` Robin Zhang 2022-05-19 8:33 ` Andrew Rybchenko 2022-05-11 2:14 ` [PATCH v6 5/5] ethdev: format module EEPROM for SFF-8636 Robin Zhang 2022-05-24 6:24 ` [PATCH v7 0/5] add telemetry command for show module EEPROM Robin Zhang 5 siblings, 1 reply; 77+ messages in thread From: Robin Zhang @ 2022-05-11 2:14 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon, Ferruh Yigit, Andrew Rybchenko, Robin Zhang This patch implements format module EEPROM information for SFF-8472 Rev 12.0 Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/ethdev_sff_telemetry.c | 4 + lib/ethdev/meson.build | 1 + lib/ethdev/sff_8472.c | 287 ++++++++++++++++++++++++++++++ 3 files changed, 292 insertions(+) create mode 100644 lib/ethdev/sff_8472.c diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c index 63b0d21786..c3b13b1cb1 100644 --- a/lib/ethdev/ethdev_sff_telemetry.c +++ b/lib/ethdev/ethdev_sff_telemetry.c @@ -73,6 +73,10 @@ sff_port_module_eeprom_parse(uint16_t port_id, struct rte_tel_data *d) case RTE_ETH_MODULE_SFF_8079: sff_8079_show_all(einfo.data, d); break; + case RTE_ETH_MODULE_SFF_8472: + sff_8079_show_all(einfo.data, d); + sff_8472_show_all(einfo.data, d); + break; default: RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); break; diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index d94860da0c..4d81a35c09 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -14,6 +14,7 @@ sources = files( 'ethdev_sff_telemetry.c', 'sff_common.c', 'sff_8079.c', + 'sff_8472.c', ) headers = files( diff --git a/lib/ethdev/sff_8472.c b/lib/ethdev/sff_8472.c new file mode 100644 index 0000000000..1bbabbde1a --- /dev/null +++ b/lib/ethdev/sff_8472.c @@ -0,0 +1,287 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8472 optics diagnostics. + * + */ + +#include <stdio.h> +#include <math.h> +#include <arpa/inet.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "ethdev_sff_telemetry.h" + +/* Offsets in decimal, for direct comparison with the SFF specs */ + +/* A0-based EEPROM offsets for DOM support checks */ +#define SFF_A0_DOM 92 +#define SFF_A0_OPTIONS 93 +#define SFF_A0_COMP 94 + +/* EEPROM bit values for various registers */ +#define SFF_A0_DOM_EXTCAL (1 << 4) +#define SFF_A0_DOM_INTCAL (1 << 5) +#define SFF_A0_DOM_IMPL (1 << 6) +#define SFF_A0_DOM_PWRT (1 << 3) + +#define SFF_A0_OPTIONS_AW (1 << 7) + +/* + * This is the offset at which the A2 page is in the EEPROM + * blob returned by the kernel. + */ +#define SFF_A2_BASE 0x100 + +/* A2-based offsets for DOM */ +#define SFF_A2_TEMP 96 +#define SFF_A2_TEMP_HALRM 0 +#define SFF_A2_TEMP_LALRM 2 +#define SFF_A2_TEMP_HWARN 4 +#define SFF_A2_TEMP_LWARN 6 + +#define SFF_A2_VCC 98 +#define SFF_A2_VCC_HALRM 8 +#define SFF_A2_VCC_LALRM 10 +#define SFF_A2_VCC_HWARN 12 +#define SFF_A2_VCC_LWARN 14 + +#define SFF_A2_BIAS 100 +#define SFF_A2_BIAS_HALRM 16 +#define SFF_A2_BIAS_LALRM 18 +#define SFF_A2_BIAS_HWARN 20 +#define SFF_A2_BIAS_LWARN 22 + +#define SFF_A2_TX_PWR 102 +#define SFF_A2_TX_PWR_HALRM 24 +#define SFF_A2_TX_PWR_LALRM 26 +#define SFF_A2_TX_PWR_HWARN 28 +#define SFF_A2_TX_PWR_LWARN 30 + +#define SFF_A2_RX_PWR 104 +#define SFF_A2_RX_PWR_HALRM 32 +#define SFF_A2_RX_PWR_LALRM 34 +#define SFF_A2_RX_PWR_HWARN 36 +#define SFF_A2_RX_PWR_LWARN 38 + +#define SFF_A2_ALRM_FLG 112 +#define SFF_A2_WARN_FLG 116 + +/* 32-bit little-endian calibration constants */ +#define SFF_A2_CAL_RXPWR4 56 +#define SFF_A2_CAL_RXPWR3 60 +#define SFF_A2_CAL_RXPWR2 64 +#define SFF_A2_CAL_RXPWR1 68 +#define SFF_A2_CAL_RXPWR0 72 + +/* 16-bit little endian calibration constants */ +#define SFF_A2_CAL_TXI_SLP 76 +#define SFF_A2_CAL_TXI_OFF 78 +#define SFF_A2_CAL_TXPWR_SLP 80 +#define SFF_A2_CAL_TXPWR_OFF 82 +#define SFF_A2_CAL_T_SLP 84 +#define SFF_A2_CAL_T_OFF 86 +#define SFF_A2_CAL_V_SLP 88 +#define SFF_A2_CAL_V_OFF 90 + +static struct sff_8472_aw_flags { + const char *str; /* Human-readable string, null at the end */ + int offset; /* A2-relative address offset */ + uint8_t value; /* Alarm is on if (offset & value) != 0. */ +} sff_8472_aw_flags[] = { + { "Laser bias current high alarm", SFF_A2_ALRM_FLG, (1 << 3) }, + { "Laser bias current low alarm", SFF_A2_ALRM_FLG, (1 << 2) }, + { "Laser bias current high warning", SFF_A2_WARN_FLG, (1 << 3) }, + { "Laser bias current low warning", SFF_A2_WARN_FLG, (1 << 2) }, + + { "Laser output power high alarm", SFF_A2_ALRM_FLG, (1 << 1) }, + { "Laser output power low alarm", SFF_A2_ALRM_FLG, (1 << 0) }, + { "Laser output power high warning", SFF_A2_WARN_FLG, (1 << 1) }, + { "Laser output power low warning", SFF_A2_WARN_FLG, (1 << 0) }, + + { "Module temperature high alarm", SFF_A2_ALRM_FLG, (1 << 7) }, + { "Module temperature low alarm", SFF_A2_ALRM_FLG, (1 << 6) }, + { "Module temperature high warning", SFF_A2_WARN_FLG, (1 << 7) }, + { "Module temperature low warning", SFF_A2_WARN_FLG, (1 << 6) }, + + { "Module voltage high alarm", SFF_A2_ALRM_FLG, (1 << 5) }, + { "Module voltage low alarm", SFF_A2_ALRM_FLG, (1 << 4) }, + { "Module voltage high warning", SFF_A2_WARN_FLG, (1 << 5) }, + { "Module voltage low warning", SFF_A2_WARN_FLG, (1 << 4) }, + + { "Laser rx power high alarm", SFF_A2_ALRM_FLG + 1, (1 << 7) }, + { "Laser rx power low alarm", SFF_A2_ALRM_FLG + 1, (1 << 6) }, + { "Laser rx power high warning", SFF_A2_WARN_FLG + 1, (1 << 7) }, + { "Laser rx power low warning", SFF_A2_WARN_FLG + 1, (1 << 6) }, + + { NULL, 0, 0 }, +}; + +/* Most common case: 16-bit unsigned integer in a certain unit */ +#define A2_OFFSET_TO_U16(offset) \ + (data[SFF_A2_BASE + (offset)] << 8 | data[SFF_A2_BASE + (offset) + 1]) + +/* Calibration slope is a number between 0.0 included and 256.0 excluded. */ +#define A2_OFFSET_TO_SLP(offset) \ + (data[SFF_A2_BASE + (offset)] + data[SFF_A2_BASE + (offset) + 1] / 256.) + +/* Calibration offset is an integer from -32768 to 32767 */ +#define A2_OFFSET_TO_OFF(offset) \ + ((int16_t)A2_OFFSET_TO_U16(offset)) + +/* RXPWR(x) are IEEE-754 floating point numbers in big-endian format */ +#define A2_OFFSET_TO_RXPWRx(offset) \ + (befloattoh((const uint32_t *)(data + SFF_A2_BASE + (offset)))) + +/* + * 2-byte internal temperature conversions: + * First byte is a signed 8-bit integer, which is the temp decimal part + * Second byte are 1/256th of degree, which are added to the dec part. + */ +#define A2_OFFSET_TO_TEMP(offset) ((int16_t)A2_OFFSET_TO_U16(offset)) + +static void sff_8472_dom_parse(const uint8_t *data, struct sff_diags *sd) +{ + sd->bias_cur[MCURR] = A2_OFFSET_TO_U16(SFF_A2_BIAS); + sd->bias_cur[HALRM] = A2_OFFSET_TO_U16(SFF_A2_BIAS_HALRM); + sd->bias_cur[LALRM] = A2_OFFSET_TO_U16(SFF_A2_BIAS_LALRM); + sd->bias_cur[HWARN] = A2_OFFSET_TO_U16(SFF_A2_BIAS_HWARN); + sd->bias_cur[LWARN] = A2_OFFSET_TO_U16(SFF_A2_BIAS_LWARN); + + sd->sfp_voltage[MCURR] = A2_OFFSET_TO_U16(SFF_A2_VCC); + sd->sfp_voltage[HALRM] = A2_OFFSET_TO_U16(SFF_A2_VCC_HALRM); + sd->sfp_voltage[LALRM] = A2_OFFSET_TO_U16(SFF_A2_VCC_LALRM); + sd->sfp_voltage[HWARN] = A2_OFFSET_TO_U16(SFF_A2_VCC_HWARN); + sd->sfp_voltage[LWARN] = A2_OFFSET_TO_U16(SFF_A2_VCC_LWARN); + + sd->tx_power[MCURR] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR); + sd->tx_power[HALRM] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_HALRM); + sd->tx_power[LALRM] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_LALRM); + sd->tx_power[HWARN] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_HWARN); + sd->tx_power[LWARN] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_LWARN); + + sd->rx_power[MCURR] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR); + sd->rx_power[HALRM] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_HALRM); + sd->rx_power[LALRM] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_LALRM); + sd->rx_power[HWARN] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_HWARN); + sd->rx_power[LWARN] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_LWARN); + + sd->sfp_temp[MCURR] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP); + sd->sfp_temp[HALRM] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_HALRM); + sd->sfp_temp[LALRM] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_LALRM); + sd->sfp_temp[HWARN] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_HWARN); + sd->sfp_temp[LWARN] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_LWARN); +} + +/* Converts to a float from a big-endian 4-byte source buffer. */ +static float befloattoh(const uint32_t *source) +{ + union { + uint32_t src; + float dst; + } converter; + + converter.src = ntohl(*source); + return converter.dst; +} + +static void sff_8472_calibration(const uint8_t *data, struct sff_diags *sd) +{ + unsigned long i; + uint16_t rx_reading; + + /* Calibration should occur for all values (threshold and current) */ + for (i = 0; i < RTE_DIM(sd->bias_cur); ++i) { + /* + * Apply calibration formula 1 (Temp., Voltage, Bias, Tx Power) + */ + sd->bias_cur[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_TXI_SLP); + sd->tx_power[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_TXPWR_SLP); + sd->sfp_voltage[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_V_SLP); + sd->sfp_temp[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_T_SLP); + + sd->bias_cur[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_TXI_OFF); + sd->tx_power[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_TXPWR_OFF); + sd->sfp_voltage[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_V_OFF); + sd->sfp_temp[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_T_OFF); + + /* + * Apply calibration formula 2 (Rx Power only) + */ + rx_reading = sd->rx_power[i]; + sd->rx_power[i] = A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR0); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR1); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR2); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR3); + } +} + +static void sff_8472_parse_eeprom(const uint8_t *data, struct sff_diags *sd) +{ + sd->supports_dom = data[SFF_A0_DOM] & SFF_A0_DOM_IMPL; + sd->supports_alarms = data[SFF_A0_OPTIONS] & SFF_A0_OPTIONS_AW; + sd->calibrated_ext = data[SFF_A0_DOM] & SFF_A0_DOM_EXTCAL; + sd->rx_power_type = data[SFF_A0_DOM] & SFF_A0_DOM_PWRT; + + sff_8472_dom_parse(data, sd); + + /* + * If the SFP is externally calibrated, we need to read calibration data + * and compensate the already stored readings. + */ + if (sd->calibrated_ext) + sff_8472_calibration(data, sd); +} + +void sff_8472_show_all(const uint8_t *data, struct rte_tel_data *d) +{ + struct sff_diags sd = {0}; + const char *rx_power_string = NULL; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + int i; + + sff_8472_parse_eeprom(data, &sd); + + if (!sd.supports_dom) { + ssf_add_dict_string(d, "Optical diagnostics support", "No"); + return; + } + ssf_add_dict_string(d, "Optical diagnostics support", "Yes"); + + SPRINT_BIAS(val_string, sd.bias_cur[MCURR]); + ssf_add_dict_string(d, "Laser bias current", val_string); + + SPRINT_xX_PWR(val_string, sd.tx_power[MCURR]); + ssf_add_dict_string(d, "Laser output power", val_string); + + if (!sd.rx_power_type) + rx_power_string = "Receiver signal OMA"; + else + rx_power_string = "Receiver signal average optical power"; + + SPRINT_xX_PWR(val_string, sd.rx_power[MCURR]); + ssf_add_dict_string(d, rx_power_string, val_string); + + SPRINT_TEMP(val_string, sd.sfp_temp[MCURR]); + ssf_add_dict_string(d, "Module temperature", val_string); + + SPRINT_VCC(val_string, sd.sfp_voltage[MCURR]); + ssf_add_dict_string(d, "Module voltage", val_string); + + ssf_add_dict_string(d, "Alarm/warning flags implemented", + (sd.supports_alarms ? "Yes" : "No")); + + if (sd.supports_alarms) { + for (i = 0; sff_8472_aw_flags[i].str; ++i) { + ssf_add_dict_string(d, sff_8472_aw_flags[i].str, + data[SFF_A2_BASE + sff_8472_aw_flags[i].offset] + & sff_8472_aw_flags[i].value ? "On" : "Off"); + } + sff_show_thresholds(sd, d); + } +} -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v6 4/5] ethdev: format module EEPROM for SFF-8472 2022-05-11 2:14 ` [PATCH v6 4/5] ethdev: format module EEPROM for SFF-8472 Robin Zhang @ 2022-05-19 8:33 ` Andrew Rybchenko 0 siblings, 0 replies; 77+ messages in thread From: Andrew Rybchenko @ 2022-05-19 8:33 UTC (permalink / raw) To: Robin Zhang, dev; +Cc: Thomas Monjalon, Ferruh Yigit On 5/11/22 05:14, Robin Zhang wrote: > This patch implements format module EEPROM information for > SFF-8472 Rev 12.0 > > Signed-off-by: Robin Zhang <robinx.zhang@intel.com> [snip] > diff --git a/lib/ethdev/sff_8472.c b/lib/ethdev/sff_8472.c > new file mode 100644 > index 0000000000..1bbabbde1a > --- /dev/null > +++ b/lib/ethdev/sff_8472.c > @@ -0,0 +1,287 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2022 Intel Corporation > + * > + * Implements SFF-8472 optics diagnostics. > + * > + */ > + > +#include <stdio.h> > +#include <math.h> > +#include <arpa/inet.h> The patch still breaks Windows build because of the above header [1] and [2]. Including mingw build. [snip] [1] http://mails.dpdk.org/archives/test-report/2022-May/279975.html [2] http://mails.dpdk.org/archives/test-report/2022-May/279929.html ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v6 5/5] ethdev: format module EEPROM for SFF-8636 2022-05-11 2:14 ` [PATCH v6 " Robin Zhang ` (3 preceding siblings ...) 2022-05-11 2:14 ` [PATCH v6 4/5] ethdev: format module EEPROM for SFF-8472 Robin Zhang @ 2022-05-11 2:14 ` Robin Zhang 2022-05-24 6:24 ` [PATCH v7 0/5] add telemetry command for show module EEPROM Robin Zhang 5 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-05-11 2:14 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon, Ferruh Yigit, Andrew Rybchenko, Robin Zhang This patch implements format module EEPROM information for SFF-8636 Rev 2.7 Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/ethdev_sff_telemetry.c | 4 + lib/ethdev/meson.build | 1 + lib/ethdev/sff_8636.c | 775 ++++++++++++++++++++++++++++++ lib/ethdev/sff_8636.h | 592 +++++++++++++++++++++++ 4 files changed, 1372 insertions(+) create mode 100644 lib/ethdev/sff_8636.c create mode 100644 lib/ethdev/sff_8636.h diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c index c3b13b1cb1..b7d14219ef 100644 --- a/lib/ethdev/ethdev_sff_telemetry.c +++ b/lib/ethdev/ethdev_sff_telemetry.c @@ -77,6 +77,10 @@ sff_port_module_eeprom_parse(uint16_t port_id, struct rte_tel_data *d) sff_8079_show_all(einfo.data, d); sff_8472_show_all(einfo.data, d); break; + case RTE_ETH_MODULE_SFF_8436: + case RTE_ETH_MODULE_SFF_8636: + sff_8636_show_all(einfo.data, einfo.length, d); + break; default: RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); break; diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index 4d81a35c09..88ceeb12b9 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -15,6 +15,7 @@ sources = files( 'sff_common.c', 'sff_8079.c', 'sff_8472.c', + 'sff_8636.c', ) headers = files( diff --git a/lib/ethdev/sff_8636.c b/lib/ethdev/sff_8636.c new file mode 100644 index 0000000000..93ef8bde2b --- /dev/null +++ b/lib/ethdev/sff_8636.c @@ -0,0 +1,775 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8636 based QSFP+/QSFP28 Diagnostics Memory map. + * + */ + +#include <stdio.h> +#include <math.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "sff_8636.h" +#include "ethdev_sff_telemetry.h" + +#define MAX_DESC_SIZE 42 + +static struct sff_8636_aw_flags { + const char *str; /* Human-readable string, null at the end */ + int offset; /* A2-relative address offset */ + uint8_t value; /* Alarm is on if (offset & value) != 0. */ +} sff_8636_aw_flags[] = { + { "Laser bias current high alarm (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_HALARM) }, + { "Laser bias current low alarm (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_LALARM) }, + { "Laser bias current high warning (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_HWARN) }, + { "Laser bias current low warning (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_LWARN) }, + + { "Laser bias current high alarm (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_HALARM) }, + { "Laser bias current low alarm (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_LALARM) }, + { "Laser bias current high warning (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_HWARN) }, + { "Laser bias current low warning (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_LWARN) }, + + { "Laser bias current high alarm (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_HALARM) }, + { "Laser bias current low alarm (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_LALARM) }, + { "Laser bias current high warning (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_HWARN) }, + { "Laser bias current low warning (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_LWARN) }, + + { "Laser bias current high alarm (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_HALARM) }, + { "Laser bias current low alarm (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_LALARM) }, + { "Laser bias current high warning (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_HWARN) }, + { "Laser bias current low warning (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_LWARN) }, + + { "Module temperature high alarm", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_HALARM_STATUS) }, + { "Module temperature low alarm", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_LALARM_STATUS) }, + { "Module temperature high warning", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_HWARN_STATUS) }, + { "Module temperature low warning", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_LWARN_STATUS) }, + + { "Module voltage high alarm", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_HALARM_STATUS) }, + { "Module voltage low alarm", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_LALARM_STATUS) }, + { "Module voltage high warning", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_HWARN_STATUS) }, + { "Module voltage low warning", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_LWARN_STATUS) }, + + { "Laser tx power high alarm (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_HALARM) }, + { "Laser tx power low alarm (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_LALARM) }, + { "Laser tx power high warning (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_HWARN) }, + { "Laser tx power low warning (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_LWARN) }, + + { "Laser tx power high alarm (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_HALARM) }, + { "Laser tx power low alarm (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_LALARM) }, + { "Laser tx power high warning (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_HWARN) }, + { "Laser tx power low warning (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_LWARN) }, + + { "Laser tx power high alarm (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_HALARM) }, + { "Laser tx power low alarm (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_LALARM) }, + { "Laser tx power high warning (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_HWARN) }, + { "Laser tx power low warning (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_LWARN) }, + + { "Laser tx power high alarm (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_HALARM) }, + { "Laser tx power low alarm (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_LALARM) }, + { "Laser tx power high warning (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_HWARN) }, + { "Laser tx power low warning (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_LWARN) }, + + { "Laser rx power high alarm (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_HALARM) }, + { "Laser rx power low alarm (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_LALARM) }, + { "Laser rx power high warning (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_HWARN) }, + { "Laser rx power low warning (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_LWARN) }, + + { "Laser rx power high alarm (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_HALARM) }, + { "Laser rx power low alarm (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_LALARM) }, + { "Laser rx power high warning (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_HWARN) }, + { "Laser rx power low warning (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_LWARN) }, + + { "Laser rx power high alarm (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_HALARM) }, + { "Laser rx power low alarm (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_LALARM) }, + { "Laser rx power high warning (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_HWARN) }, + { "Laser rx power low warning (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_LWARN) }, + + { "Laser rx power high alarm (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_HALARM) }, + { "Laser rx power low alarm (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_LALARM) }, + { "Laser rx power high warning (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_HWARN) }, + { "Laser rx power low warning (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_LWARN) }, + + { NULL, 0, 0 }, +}; + +static void sff_8636_show_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_identifier(data, SFF_8636_ID_OFFSET, d); +} + +static void sff_8636_show_ext_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + static const char *name = "Extended identifier description"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + snprintf(val_string, sizeof(val_string), "0x%02x", data[SFF_8636_EXT_ID_OFFSET]); + ssf_add_dict_string(d, "Extended identifier", val_string); + + switch (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_PWR_CLASS_MASK) { + case SFF_8636_EXT_ID_PWR_CLASS_1: + ssf_add_dict_string(d, name, "1.5W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_2: + ssf_add_dict_string(d, name, "2.0W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_3: + ssf_add_dict_string(d, name, "2.5W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_4: + ssf_add_dict_string(d, name, "3.5W max. Power consumption"); + break; + } + + if (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_CDR_TX_MASK) + ssf_add_dict_string(d, name, "CDR present in TX"); + else + ssf_add_dict_string(d, name, "No CDR in TX"); + + if (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_CDR_RX_MASK) + ssf_add_dict_string(d, name, "CDR present in RX"); + else + ssf_add_dict_string(d, name, "No CDR in RX"); + + switch (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_EPWR_CLASS_MASK) { + case SFF_8636_EXT_ID_PWR_CLASS_LEGACY: + snprintf(val_string, sizeof(val_string), "%s", ""); + break; + case SFF_8636_EXT_ID_PWR_CLASS_5: + snprintf(val_string, sizeof(val_string), "%s", "4.0W max. Power consumption, "); + break; + case SFF_8636_EXT_ID_PWR_CLASS_6: + snprintf(val_string, sizeof(val_string), "%s", "4.5W max. Power consumption, "); + break; + case SFF_8636_EXT_ID_PWR_CLASS_7: + snprintf(val_string, sizeof(val_string), "%s", "5.0W max. Power consumption, "); + break; + } + + if (data[SFF_8636_PWR_MODE_OFFSET] & SFF_8636_HIGH_PWR_ENABLE) + strlcat(val_string, "High Power Class (> 3.5 W) enabled", sizeof(val_string)); + else + strlcat(val_string, "High Power Class (> 3.5 W) not enabled", sizeof(val_string)); + + ssf_add_dict_string(d, name, val_string); +} + +static void sff_8636_show_connector(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_connector(data, SFF_8636_CTOR_OFFSET, d); +} + +static void sff_8636_show_transceiver(const uint8_t *data, struct rte_tel_data *d) +{ + static const char *name = "Transceiver type"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + data[SFF_8636_ETHERNET_COMP_OFFSET], + data[SFF_8636_SONET_COMP_OFFSET], + data[SFF_8636_SAS_COMP_OFFSET], + data[SFF_8636_GIGE_COMP_OFFSET], + data[SFF_8636_FC_LEN_OFFSET], + data[SFF_8636_FC_TECH_OFFSET], + data[SFF_8636_FC_TRANS_MEDIA_OFFSET], + data[SFF_8636_FC_SPEED_OFFSET]); + ssf_add_dict_string(d, "Transceiver codes", val_string); + + /* 10G/40G Ethernet Compliance Codes */ + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_LRM) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-LRM"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_LR) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-LR"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_SR) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-SR"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_CR4) + ssf_add_dict_string(d, name, "40G Ethernet: 40G Base-CR4"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_SR4) + ssf_add_dict_string(d, name, "40G Ethernet: 40G Base-SR4"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_LR4) + ssf_add_dict_string(d, name, "40G Ethernet: 40G Base-LR4"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_ACTIVE) + ssf_add_dict_string(d, name, "40G Ethernet: 40G Active Cable (XLPPI)"); + + /* Extended Specification Compliance Codes from SFF-8024 */ + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_RSRVD) { + switch (data[SFF_8636_OPTION_1_OFFSET]) { + case SFF_8636_ETHERNET_UNSPECIFIED: + ssf_add_dict_string(d, name, "(reserved or unknown)"); + break; + case SFF_8636_ETHERNET_100G_AOC: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)"); + break; + case SFF_8636_ETHERNET_100G_SR4: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G Base-SR4 or 25GBase-SR"); + break; + case SFF_8636_ETHERNET_100G_LR4: + ssf_add_dict_string(d, name, "100G Ethernet: 100G Base-LR4"); + break; + case SFF_8636_ETHERNET_100G_ER4: + ssf_add_dict_string(d, name, "100G Ethernet: 100G Base-ER4"); + break; + case SFF_8636_ETHERNET_100G_SR10: + ssf_add_dict_string(d, name, "100G Ethernet: 100G Base-SR10"); + break; + case SFF_8636_ETHERNET_100G_CWDM4_FEC: + ssf_add_dict_string(d, name, "100G Ethernet: 100G CWDM4 MSA with FEC"); + break; + case SFF_8636_ETHERNET_100G_PSM4: + ssf_add_dict_string(d, name, "100G Ethernet: 100G PSM4 Parallel SMF"); + break; + case SFF_8636_ETHERNET_100G_ACC: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)"); + break; + case SFF_8636_ETHERNET_100G_CWDM4_NO_FEC: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G CWDM4 MSA without FEC"); + break; + case SFF_8636_ETHERNET_100G_RSVD1: + ssf_add_dict_string(d, name, "(reserved or unknown)"); + break; + case SFF_8636_ETHERNET_100G_CR4: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G Base-CR4 or 25G Base-CR CA-L"); + break; + case SFF_8636_ETHERNET_25G_CR_CA_S: + ssf_add_dict_string(d, name, "25G Ethernet: 25G Base-CR CA-S"); + break; + case SFF_8636_ETHERNET_25G_CR_CA_N: + ssf_add_dict_string(d, name, "25G Ethernet: 25G Base-CR CA-N"); + break; + case SFF_8636_ETHERNET_40G_ER4: + ssf_add_dict_string(d, name, "40G Ethernet: 40G Base-ER4"); + break; + case SFF_8636_ETHERNET_4X10_SR: + ssf_add_dict_string(d, name, "4x10G Ethernet: 10G Base-SR"); + break; + case SFF_8636_ETHERNET_40G_PSM4: + ssf_add_dict_string(d, name, "40G Ethernet: 40G PSM4 Parallel SMF"); + break; + case SFF_8636_ETHERNET_G959_P1I1_2D1: + ssf_add_dict_string(d, name, + "Ethernet: G959.1 profile P1I1-2D1 (10709 MBd, 2km, 1310nm SM)"); + break; + case SFF_8636_ETHERNET_G959_P1S1_2D2: + ssf_add_dict_string(d, name, + "Ethernet: G959.1 profile P1S1-2D2 (10709 MBd, 40km, 1550nm SM)"); + break; + case SFF_8636_ETHERNET_G959_P1L1_2D2: + ssf_add_dict_string(d, name, + "Ethernet: G959.1 profile P1L1-2D2 (10709 MBd, 80km, 1550nm SM)"); + break; + case SFF_8636_ETHERNET_10GT_SFI: + ssf_add_dict_string(d, name, + "10G Ethernet: 10G Base-T with SFI electrical interface"); + break; + case SFF_8636_ETHERNET_100G_CLR4: + ssf_add_dict_string(d, name, "100G Ethernet: 100G CLR4"); + break; + case SFF_8636_ETHERNET_100G_AOC2: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)"); + break; + case SFF_8636_ETHERNET_100G_ACC2: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)"); + break; + default: + ssf_add_dict_string(d, name, "(reserved or unknown)"); + break; + } + } + + /* SONET Compliance Codes */ + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_40G_OTN) + ssf_add_dict_string(d, name, "40G OTN (OTU3B/OTU3C)"); + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_LR) + ssf_add_dict_string(d, name, "SONET: OC-48, long reach"); + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_IR) + ssf_add_dict_string(d, name, "SONET: OC-48, intermediate reach"); + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_SR) + ssf_add_dict_string(d, name, "SONET: OC-48, short reach"); + + /* SAS/SATA Compliance Codes */ + if (data[SFF_8636_SAS_COMP_OFFSET] & SFF_8636_SAS_6G) + ssf_add_dict_string(d, name, "SAS 6.0G"); + if (data[SFF_8636_SAS_COMP_OFFSET] & SFF_8636_SAS_3G) + ssf_add_dict_string(d, name, "SAS 3.0G"); + + /* Ethernet Compliance Codes */ + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_T) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-T"); + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_CX) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-CX"); + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_LX) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-LX"); + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_SX) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-SX"); + + /* Fibre Channel link length */ + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_VERY_LONG) + ssf_add_dict_string(d, name, "FC: very long distance (V)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_SHORT) + ssf_add_dict_string(d, name, "FC: short distance (S)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_INT) + ssf_add_dict_string(d, name, "FC: intermediate distance (I)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_LONG) + ssf_add_dict_string(d, name, "FC: long distance (L)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_MED) + ssf_add_dict_string(d, name, "FC: medium distance (M)"); + + /* Fibre Channel transmitter technology */ + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_TECH_LONG_LC) + ssf_add_dict_string(d, name, "FC: Longwave laser (LC)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_TECH_ELEC_INTER) + ssf_add_dict_string(d, name, "FC: Electrical inter-enclosure (EL)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_ELEC_INTRA) + ssf_add_dict_string(d, name, "FC: Electrical intra-enclosure (EL)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_SHORT_WO_OFC) + ssf_add_dict_string(d, name, "FC: Shortwave laser w/o OFC (SN)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_SHORT_W_OFC) + ssf_add_dict_string(d, name, "FC: Shortwave laser with OFC (SL)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_LONG_LL) + ssf_add_dict_string(d, name, "FC: Longwave laser (LL)"); + + /* Fibre Channel transmission media */ + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TW) + ssf_add_dict_string(d, name, "FC: Twin Axial Pair (TW)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TP) + ssf_add_dict_string(d, name, "FC: Twisted Pair (TP)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_MI) + ssf_add_dict_string(d, name, "FC: Miniature Coax (MI)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TV) + ssf_add_dict_string(d, name, "FC: Video Coax (TV)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_M6) + ssf_add_dict_string(d, name, "FC: Multimode, 62.5m (M6)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_M5) + ssf_add_dict_string(d, name, "FC: Multimode, 50m (M5)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_OM3) + ssf_add_dict_string(d, name, "FC: Multimode, 50um (OM3)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_SM) + ssf_add_dict_string(d, name, "FC: Single Mode (SM)"); + + /* Fibre Channel speed */ + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_1200_MBPS) + ssf_add_dict_string(d, name, "FC: 1200 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_800_MBPS) + ssf_add_dict_string(d, name, "FC: 800 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_1600_MBPS) + ssf_add_dict_string(d, name, "FC: 1600 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_400_MBPS) + ssf_add_dict_string(d, name, "FC: 400 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_200_MBPS) + ssf_add_dict_string(d, name, "FC: 200 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_100_MBPS) + ssf_add_dict_string(d, name, "FC: 100 MBytes/sec"); +} + +static void sff_8636_show_encoding(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_encoding(data, SFF_8636_ENCODING_OFFSET, + RTE_ETH_MODULE_SFF_8636, d); +} + +static void sff_8636_show_rate_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + char val_string[20]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[SFF_8636_EXT_RS_OFFSET]); + ssf_add_dict_string(d, "Rate identifier", val_string); +} + +static void sff_8636_show_oui(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_oui(data, SFF_8636_VENDOR_OUI_OFFSET, d); +} + +static void sff_8636_show_wavelength_or_copper_compliance(const uint8_t *data, + struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + snprintf(val_string, sizeof(val_string), "0x%02x", + (data[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK)); + + switch (data[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK) { + case SFF_8636_TRANS_850_VCSEL: + strlcat(val_string, " (850 nm VCSEL)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_VCSEL: + strlcat(val_string, " (1310 nm VCSEL)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1550_VCSEL: + strlcat(val_string, " (1550 nm VCSEL)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_FP: + strlcat(val_string, " (1310 nm FP)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_DFB: + strlcat(val_string, " (1310 nm DFB)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1550_DFB: + strlcat(val_string, " (1550 nm DFB)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_EML: + strlcat(val_string, " (1310 nm EML)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1550_EML: + strlcat(val_string, " (1550 nm EML)", sizeof(val_string)); + break; + case SFF_8636_TRANS_OTHERS: + strlcat(val_string, " (Others/Undefined)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1490_DFB: + strlcat(val_string, " (1490 nm DFB)", sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_PAS_UNEQUAL: + strlcat(val_string, " (Copper cable unequalized)", sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_PAS_EQUAL: + strlcat(val_string, " (Copper cable passive equalized)", sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_LNR_FAR_EQUAL: + strlcat(val_string, + " (Copper cable, near and far end limiting active equalizers)", + sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_FAR_EQUAL: + strlcat(val_string, + " (Copper cable, far end limiting active equalizers)", + sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_NEAR_EQUAL: + strlcat(val_string, + " (Copper cable, near end limiting active equalizers)", + sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_LNR_EQUAL: + strlcat(val_string, + " (Copper cable, linear active equalizers)", + sizeof(val_string)); + break; + } + ssf_add_dict_string(d, "Transmitter technology", val_string); + + if ((data[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK) + >= SFF_8636_TRANS_COPPER_PAS_UNEQUAL) { + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + ssf_add_dict_string(d, "Attenuation at 2.5GHz", val_string); + + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + ssf_add_dict_string(d, "Attenuation at 5.0GHz", val_string); + + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + ssf_add_dict_string(d, "Attenuation at 7.0GHz", val_string); + + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + ssf_add_dict_string(d, "Attenuation at 12.9GHz", val_string); + } else { + snprintf(val_string, sizeof(val_string), "%.3lfnm", + (((data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET] << 8) | + data[SFF_8636_WAVELEN_LOW_BYTE_OFFSET])*0.05)); + ssf_add_dict_string(d, "Laser wavelength", val_string); + + snprintf(val_string, sizeof(val_string), "%.3lfnm", + (((data[SFF_8636_WAVE_TOL_HIGH_BYTE_OFFSET] << 8) | + data[SFF_8636_WAVE_TOL_LOW_BYTE_OFFSET])*0.005)); + ssf_add_dict_string(d, "Laser wavelength tolerance", val_string); + } +} + +static void sff_8636_show_revision_compliance(const uint8_t *data, struct rte_tel_data *d) +{ + static const char *name = "Revision Compliance"; + + switch (data[SFF_8636_REV_COMPLIANCE_OFFSET]) { + case SFF_8636_REV_UNSPECIFIED: + ssf_add_dict_string(d, name, "Revision not specified"); + break; + case SFF_8636_REV_8436_48: + ssf_add_dict_string(d, name, "SFF-8436 Rev 4.8 or earlier"); + break; + case SFF_8636_REV_8436_8636: + ssf_add_dict_string(d, name, "SFF-8436 Rev 4.8 or earlier"); + break; + case SFF_8636_REV_8636_13: + ssf_add_dict_string(d, name, "SFF-8636 Rev 1.3 or earlier"); + break; + case SFF_8636_REV_8636_14: + ssf_add_dict_string(d, name, "SFF-8636 Rev 1.4"); + break; + case SFF_8636_REV_8636_15: + ssf_add_dict_string(d, name, "SFF-8636 Rev 1.5"); + break; + case SFF_8636_REV_8636_20: + ssf_add_dict_string(d, name, "SFF-8636 Rev 2.0"); + break; + case SFF_8636_REV_8636_27: + ssf_add_dict_string(d, name, "SFF-8636 Rev 2.5/2.6/2.7"); + break; + default: + ssf_add_dict_string(d, name, "Unallocated"); + break; + } +} + +/* + * 2-byte internal temperature conversions: + * First byte is a signed 8-bit integer, which is the temp decimal part + * Second byte are 1/256th of degree, which are added to the dec part. + */ +#define SFF_8636_OFFSET_TO_TEMP(offset) ((int16_t)OFFSET_TO_U16(offset)) + +static void sff_8636_dom_parse(const uint8_t *data, struct sff_diags *sd) +{ + int i = 0; + + /* Monitoring Thresholds for Alarms and Warnings */ + sd->sfp_voltage[MCURR] = OFFSET_TO_U16(SFF_8636_VCC_CURR); + sd->sfp_voltage[HALRM] = OFFSET_TO_U16(SFF_8636_VCC_HALRM); + sd->sfp_voltage[LALRM] = OFFSET_TO_U16(SFF_8636_VCC_LALRM); + sd->sfp_voltage[HWARN] = OFFSET_TO_U16(SFF_8636_VCC_HWARN); + sd->sfp_voltage[LWARN] = OFFSET_TO_U16(SFF_8636_VCC_LWARN); + + sd->sfp_temp[MCURR] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_CURR); + sd->sfp_temp[HALRM] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_HALRM); + sd->sfp_temp[LALRM] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_LALRM); + sd->sfp_temp[HWARN] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_HWARN); + sd->sfp_temp[LWARN] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_LWARN); + + sd->bias_cur[HALRM] = OFFSET_TO_U16(SFF_8636_TX_BIAS_HALRM); + sd->bias_cur[LALRM] = OFFSET_TO_U16(SFF_8636_TX_BIAS_LALRM); + sd->bias_cur[HWARN] = OFFSET_TO_U16(SFF_8636_TX_BIAS_HWARN); + sd->bias_cur[LWARN] = OFFSET_TO_U16(SFF_8636_TX_BIAS_LWARN); + + sd->tx_power[HALRM] = OFFSET_TO_U16(SFF_8636_TX_PWR_HALRM); + sd->tx_power[LALRM] = OFFSET_TO_U16(SFF_8636_TX_PWR_LALRM); + sd->tx_power[HWARN] = OFFSET_TO_U16(SFF_8636_TX_PWR_HWARN); + sd->tx_power[LWARN] = OFFSET_TO_U16(SFF_8636_TX_PWR_LWARN); + + sd->rx_power[HALRM] = OFFSET_TO_U16(SFF_8636_RX_PWR_HALRM); + sd->rx_power[LALRM] = OFFSET_TO_U16(SFF_8636_RX_PWR_LALRM); + sd->rx_power[HWARN] = OFFSET_TO_U16(SFF_8636_RX_PWR_HWARN); + sd->rx_power[LWARN] = OFFSET_TO_U16(SFF_8636_RX_PWR_LWARN); + + + /* Channel Specific Data */ + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + uint8_t rx_power_offset, tx_bias_offset; + uint8_t tx_power_offset; + + switch (i) { + case 0: + rx_power_offset = SFF_8636_RX_PWR_1_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_1_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_1_OFFSET; + break; + case 1: + rx_power_offset = SFF_8636_RX_PWR_2_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_2_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_2_OFFSET; + break; + case 2: + rx_power_offset = SFF_8636_RX_PWR_3_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_3_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_3_OFFSET; + break; + case 3: + rx_power_offset = SFF_8636_RX_PWR_4_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_4_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_4_OFFSET; + break; + } + sd->scd[i].bias_cur = OFFSET_TO_U16(tx_bias_offset); + sd->scd[i].rx_power = OFFSET_TO_U16(rx_power_offset); + sd->scd[i].tx_power = OFFSET_TO_U16(tx_power_offset); + } + +} + +static void sff_8636_show_dom(const uint8_t *data, uint32_t eeprom_len, struct rte_tel_data *d) +{ + struct sff_diags sd = {0}; + const char *rx_power_string = NULL; + char power_string[MAX_DESC_SIZE]; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + int i; + + /* + * There is no clear identifier to signify the existence of + * optical diagnostics similar to SFF-8472. So checking existence + * of page 3, will provide the gurantee for existence of alarms + * and thresholds + * If pagging support exists, then supports_alarms is marked as 1 + */ + + if (eeprom_len == RTE_ETH_MODULE_SFF_8636_MAX_LEN) { + if (!(data[SFF_8636_STATUS_2_OFFSET] & + SFF_8636_STATUS_PAGE_3_PRESENT)) { + sd.supports_alarms = 1; + } + } + + sd.rx_power_type = data[SFF_8636_DIAG_TYPE_OFFSET] & + SFF_8636_RX_PWR_TYPE_MASK; + sd.tx_power_type = data[SFF_8636_DIAG_TYPE_OFFSET] & + SFF_8636_RX_PWR_TYPE_MASK; + + sff_8636_dom_parse(data, &sd); + + SPRINT_TEMP(val_string, sd.sfp_temp[MCURR]); + ssf_add_dict_string(d, "Module temperature", val_string); + + SPRINT_VCC(val_string, sd.sfp_voltage[MCURR]); + ssf_add_dict_string(d, "Module voltage", val_string); + + /* + * SFF-8636/8436 spec is not clear whether RX power/ TX bias + * current fields are supported or not. A valid temperature + * reading is used as existence for TX/RX power. + */ + if ((sd.sfp_temp[MCURR] == 0x0) || + (sd.sfp_temp[MCURR] == (int16_t)0xFFFF)) + return; + + ssf_add_dict_string(d, "Alarm/warning flags implemented", + (sd.supports_alarms ? "Yes" : "No")); + + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + snprintf(power_string, MAX_DESC_SIZE, "%s (Channel %d)", + "Laser tx bias current", i+1); + SPRINT_BIAS(val_string, sd.scd[i].bias_cur); + ssf_add_dict_string(d, power_string, val_string); + } + + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + snprintf(power_string, MAX_DESC_SIZE, "%s (Channel %d)", + "Transmit avg optical power", i+1); + SPRINT_xX_PWR(val_string, sd.scd[i].tx_power); + ssf_add_dict_string(d, power_string, val_string); + } + + if (!sd.rx_power_type) + rx_power_string = "Receiver signal OMA"; + else + rx_power_string = "Rcvr signal avg optical power"; + + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + snprintf(power_string, MAX_DESC_SIZE, "%s(Channel %d)", + rx_power_string, i+1); + SPRINT_xX_PWR(val_string, sd.scd[i].rx_power); + ssf_add_dict_string(d, power_string, val_string); + } + + if (sd.supports_alarms) { + for (i = 0; sff_8636_aw_flags[i].str; ++i) { + ssf_add_dict_string(d, sff_8636_aw_flags[i].str, + data[sff_8636_aw_flags[i].offset] + & sff_8636_aw_flags[i].value ? "On" : "Off"); + } + + sff_show_thresholds(sd, d); + } + +} +void sff_8636_show_all(const uint8_t *data, uint32_t eeprom_len, struct rte_tel_data *d) +{ + sff_8636_show_identifier(data, d); + if ((data[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP) || + (data[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP_PLUS) || + (data[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP28)) { + sff_8636_show_ext_identifier(data, d); + sff_8636_show_connector(data, d); + sff_8636_show_transceiver(data, d); + sff_8636_show_encoding(data, d); + sff_show_value_with_unit(data, SFF_8636_BR_NOMINAL_OFFSET, + "BR, Nominal", 100, "Mbps", d); + sff_8636_show_rate_identifier(data, d); + sff_show_value_with_unit(data, SFF_8636_SM_LEN_OFFSET, + "Length (SMF,km)", 1, "km", d); + sff_show_value_with_unit(data, SFF_8636_OM3_LEN_OFFSET, + "Length (OM3 50um)", 2, "m", d); + sff_show_value_with_unit(data, SFF_8636_OM2_LEN_OFFSET, + "Length (OM2 50um)", 1, "m", d); + sff_show_value_with_unit(data, SFF_8636_OM1_LEN_OFFSET, + "Length (OM1 62.5um)", 1, "m", d); + sff_show_value_with_unit(data, SFF_8636_CBL_LEN_OFFSET, + "Length (Copper or Active cable)", 1, "m", d); + sff_8636_show_wavelength_or_copper_compliance(data, d); + sff_show_ascii(data, SFF_8636_VENDOR_NAME_START_OFFSET, + SFF_8636_VENDOR_NAME_END_OFFSET, "Vendor name", d); + sff_8636_show_oui(data, d); + sff_show_ascii(data, SFF_8636_VENDOR_PN_START_OFFSET, + SFF_8636_VENDOR_PN_END_OFFSET, "Vendor PN", d); + sff_show_ascii(data, SFF_8636_VENDOR_REV_START_OFFSET, + SFF_8636_VENDOR_REV_END_OFFSET, "Vendor rev", d); + sff_show_ascii(data, SFF_8636_VENDOR_SN_START_OFFSET, + SFF_8636_VENDOR_SN_END_OFFSET, "Vendor SN", d); + sff_show_ascii(data, SFF_8636_DATE_YEAR_OFFSET, + SFF_8636_DATE_VENDOR_LOT_OFFSET + 1, "Date code", d); + sff_8636_show_revision_compliance(data, d); + sff_8636_show_dom(data, eeprom_len, d); + } +} diff --git a/lib/ethdev/sff_8636.h b/lib/ethdev/sff_8636.h new file mode 100644 index 0000000000..fc656775f9 --- /dev/null +++ b/lib/ethdev/sff_8636.h @@ -0,0 +1,592 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * SFF-8636 standards based QSFP EEPROM Field Definitions + * + */ + +#ifndef _SFF_8636_H_ +#define _SFF_8636_H_ + +/*------------------------------------------------------------------------------ + * + * QSFP EEPROM data structures + * + * register info from SFF-8636 Rev 2.7 + */ + +/*------------------------------------------------------------------------------ + * + * Lower Memory Page 00h + * Measurement, Diagnostic and Control Functions + * + */ +/* Identifier - 0 */ +/* Values are defined under SFF_8024_ID_OFFSET */ +#define SFF_8636_ID_OFFSET 0x00 + +#define SFF_8636_REV_COMPLIANCE_OFFSET 0x01 +#define SFF_8636_REV_UNSPECIFIED 0x00 +#define SFF_8636_REV_8436_48 0x01 +#define SFF_8636_REV_8436_8636 0x02 +#define SFF_8636_REV_8636_13 0x03 +#define SFF_8636_REV_8636_14 0x04 +#define SFF_8636_REV_8636_15 0x05 +#define SFF_8636_REV_8636_20 0x06 +#define SFF_8636_REV_8636_27 0x07 + +#define SFF_8636_STATUS_2_OFFSET 0x02 +/* Flat Memory:0- Paging, 1- Page 0 only */ +#define SFF_8636_STATUS_PAGE_3_PRESENT (1 << 2) +#define SFF_8636_STATUS_INTL_OUTPUT (1 << 1) +#define SFF_8636_STATUS_DATA_NOT_READY (1 << 0) + +/* Channel Status Interrupt Flags - 3-5 */ +#define SFF_8636_LOS_AW_OFFSET 0x03 +#define SFF_8636_TX4_LOS_AW (1 << 7) +#define SFF_8636_TX3_LOS_AW (1 << 6) +#define SFF_8636_TX2_LOS_AW (1 << 5) +#define SFF_8636_TX1_LOS_AW (1 << 4) +#define SFF_8636_RX4_LOS_AW (1 << 3) +#define SFF_8636_RX3_LOS_AW (1 << 2) +#define SFF_8636_RX2_LOS_AW (1 << 1) +#define SFF_8636_RX1_LOS_AW (1 << 0) + +#define SFF_8636_FAULT_AW_OFFSET 0x04 +#define SFF_8636_TX4_FAULT_AW (1 << 3) +#define SFF_8636_TX3_FAULT_AW (1 << 2) +#define SFF_8636_TX2_FAULT_AW (1 << 1) +#define SFF_8636_TX1_FAULT_AW (1 << 0) + +/* Module Monitor Interrupt Flags - 6-8 */ +#define SFF_8636_TEMP_AW_OFFSET 0x06 +#define SFF_8636_TEMP_HALARM_STATUS (1 << 7) +#define SFF_8636_TEMP_LALARM_STATUS (1 << 6) +#define SFF_8636_TEMP_HWARN_STATUS (1 << 5) +#define SFF_8636_TEMP_LWARN_STATUS (1 << 4) + +#define SFF_8636_VCC_AW_OFFSET 0x07 +#define SFF_8636_VCC_HALARM_STATUS (1 << 7) +#define SFF_8636_VCC_LALARM_STATUS (1 << 6) +#define SFF_8636_VCC_HWARN_STATUS (1 << 5) +#define SFF_8636_VCC_LWARN_STATUS (1 << 4) + +/* Channel Monitor Interrupt Flags - 9-21 */ +#define SFF_8636_RX_PWR_12_AW_OFFSET 0x09 +#define SFF_8636_RX_PWR_1_HALARM (1 << 7) +#define SFF_8636_RX_PWR_1_LALARM (1 << 6) +#define SFF_8636_RX_PWR_1_HWARN (1 << 5) +#define SFF_8636_RX_PWR_1_LWARN (1 << 4) +#define SFF_8636_RX_PWR_2_HALARM (1 << 3) +#define SFF_8636_RX_PWR_2_LALARM (1 << 2) +#define SFF_8636_RX_PWR_2_HWARN (1 << 1) +#define SFF_8636_RX_PWR_2_LWARN (1 << 0) + +#define SFF_8636_RX_PWR_34_AW_OFFSET 0x0A +#define SFF_8636_RX_PWR_3_HALARM (1 << 7) +#define SFF_8636_RX_PWR_3_LALARM (1 << 6) +#define SFF_8636_RX_PWR_3_HWARN (1 << 5) +#define SFF_8636_RX_PWR_3_LWARN (1 << 4) +#define SFF_8636_RX_PWR_4_HALARM (1 << 3) +#define SFF_8636_RX_PWR_4_LALARM (1 << 2) +#define SFF_8636_RX_PWR_4_HWARN (1 << 1) +#define SFF_8636_RX_PWR_4_LWARN (1 << 0) + +#define SFF_8636_TX_BIAS_12_AW_OFFSET 0x0B +#define SFF_8636_TX_BIAS_1_HALARM (1 << 7) +#define SFF_8636_TX_BIAS_1_LALARM (1 << 6) +#define SFF_8636_TX_BIAS_1_HWARN (1 << 5) +#define SFF_8636_TX_BIAS_1_LWARN (1 << 4) +#define SFF_8636_TX_BIAS_2_HALARM (1 << 3) +#define SFF_8636_TX_BIAS_2_LALARM (1 << 2) +#define SFF_8636_TX_BIAS_2_HWARN (1 << 1) +#define SFF_8636_TX_BIAS_2_LWARN (1 << 0) + +#define SFF_8636_TX_BIAS_34_AW_OFFSET 0xC +#define SFF_8636_TX_BIAS_3_HALARM (1 << 7) +#define SFF_8636_TX_BIAS_3_LALARM (1 << 6) +#define SFF_8636_TX_BIAS_3_HWARN (1 << 5) +#define SFF_8636_TX_BIAS_3_LWARN (1 << 4) +#define SFF_8636_TX_BIAS_4_HALARM (1 << 3) +#define SFF_8636_TX_BIAS_4_LALARM (1 << 2) +#define SFF_8636_TX_BIAS_4_HWARN (1 << 1) +#define SFF_8636_TX_BIAS_4_LWARN (1 << 0) + +#define SFF_8636_TX_PWR_12_AW_OFFSET 0x0D +#define SFF_8636_TX_PWR_1_HALARM (1 << 7) +#define SFF_8636_TX_PWR_1_LALARM (1 << 6) +#define SFF_8636_TX_PWR_1_HWARN (1 << 5) +#define SFF_8636_TX_PWR_1_LWARN (1 << 4) +#define SFF_8636_TX_PWR_2_HALARM (1 << 3) +#define SFF_8636_TX_PWR_2_LALARM (1 << 2) +#define SFF_8636_TX_PWR_2_HWARN (1 << 1) +#define SFF_8636_TX_PWR_2_LWARN (1 << 0) + +#define SFF_8636_TX_PWR_34_AW_OFFSET 0x0E +#define SFF_8636_TX_PWR_3_HALARM (1 << 7) +#define SFF_8636_TX_PWR_3_LALARM (1 << 6) +#define SFF_8636_TX_PWR_3_HWARN (1 << 5) +#define SFF_8636_TX_PWR_3_LWARN (1 << 4) +#define SFF_8636_TX_PWR_4_HALARM (1 << 3) +#define SFF_8636_TX_PWR_4_LALARM (1 << 2) +#define SFF_8636_TX_PWR_4_HWARN (1 << 1) +#define SFF_8636_TX_PWR_4_LWARN (1 << 0) + +/* Module Monitoring Values - 22-33 */ +#define SFF_8636_TEMP_CURR 0x16 +#define SFF_8636_TEMP_MSB_OFFSET 0x16 +#define SFF_8636_TEMP_LSB_OFFSET 0x17 + +#define SFF_8636_VCC_CURR 0x1A +#define SFF_8636_VCC_MSB_OFFSET 0x1A +#define SFF_8636_VCC_LSB_OFFSET 0x1B + +/* Channel Monitoring Values - 34-81 */ +#define SFF_8636_RX_PWR_1_OFFSET 0x22 +#define SFF_8636_RX_PWR_2_OFFSET 0x24 +#define SFF_8636_RX_PWR_3_OFFSET 0x26 +#define SFF_8636_RX_PWR_4_OFFSET 0x28 + +#define SFF_8636_TX_BIAS_1_OFFSET 0x2A +#define SFF_8636_TX_BIAS_2_OFFSET 0x2C +#define SFF_8636_TX_BIAS_3_OFFSET 0x2E +#define SFF_8636_TX_BIAS_4_OFFSET 0x30 + +#define SFF_8636_TX_PWR_1_OFFSET 0x32 +#define SFF_8636_TX_PWR_2_OFFSET 0x34 +#define SFF_8636_TX_PWR_3_OFFSET 0x36 +#define SFF_8636_TX_PWR_4_OFFSET 0x38 + +/* Control Bytes - 86 - 99 */ +#define SFF_8636_TX_DISABLE_OFFSET 0x56 +#define SFF_8636_TX_DISABLE_4 (1 << 3) +#define SFF_8636_TX_DISABLE_3 (1 << 2) +#define SFF_8636_TX_DISABLE_2 (1 << 1) +#define SFF_8636_TX_DISABLE_1 (1 << 0) + +#define SFF_8636_RX_RATE_SELECT_OFFSET 0x57 +#define SFF_8636_RX_RATE_SELECT_4_MASK (3 << 6) +#define SFF_8636_RX_RATE_SELECT_3_MASK (3 << 4) +#define SFF_8636_RX_RATE_SELECT_2_MASK (3 << 2) +#define SFF_8636_RX_RATE_SELECT_1_MASK (3 << 0) + +#define SFF_8636_TX_RATE_SELECT_OFFSET 0x58 +#define SFF_8636_TX_RATE_SELECT_4_MASK (3 << 6) +#define SFF_8636_TX_RATE_SELECT_3_MASK (3 << 4) +#define SFF_8636_TX_RATE_SELECT_2_MASK (3 << 2) +#define SFF_8636_TX_RATE_SELECT_1_MASK (3 << 0) + +#define SFF_8636_RX_APP_SELECT_4_OFFSET 0x58 +#define SFF_8636_RX_APP_SELECT_3_OFFSET 0x59 +#define SFF_8636_RX_APP_SELECT_2_OFFSET 0x5A +#define SFF_8636_RX_APP_SELECT_1_OFFSET 0x5B + +#define SFF_8636_PWR_MODE_OFFSET 0x5D +#define SFF_8636_HIGH_PWR_ENABLE (1 << 2) +#define SFF_8636_LOW_PWR_MODE (1 << 1) +#define SFF_8636_PWR_OVERRIDE (1 << 0) + +#define SFF_8636_TX_APP_SELECT_4_OFFSET 0x5E +#define SFF_8636_TX_APP_SELECT_3_OFFSET 0x5F +#define SFF_8636_TX_APP_SELECT_2_OFFSET 0x60 +#define SFF_8636_TX_APP_SELECT_1_OFFSET 0x61 + +#define SFF_8636_LOS_MASK_OFFSET 0x64 +#define SFF_8636_TX_LOS_4_MASK (1 << 7) +#define SFF_8636_TX_LOS_3_MASK (1 << 6) +#define SFF_8636_TX_LOS_2_MASK (1 << 5) +#define SFF_8636_TX_LOS_1_MASK (1 << 4) +#define SFF_8636_RX_LOS_4_MASK (1 << 3) +#define SFF_8636_RX_LOS_3_MASK (1 << 2) +#define SFF_8636_RX_LOS_2_MASK (1 << 1) +#define SFF_8636_RX_LOS_1_MASK (1 << 0) + +#define SFF_8636_FAULT_MASK_OFFSET 0x65 +#define SFF_8636_TX_FAULT_1_MASK (1 << 3) +#define SFF_8636_TX_FAULT_2_MASK (1 << 2) +#define SFF_8636_TX_FAULT_3_MASK (1 << 1) +#define SFF_8636_TX_FAULT_4_MASK (1 << 0) + +#define SFF_8636_TEMP_MASK_OFFSET 0x67 +#define SFF_8636_TEMP_HALARM_MASK (1 << 7) +#define SFF_8636_TEMP_LALARM_MASK (1 << 6) +#define SFF_8636_TEMP_HWARN_MASK (1 << 5) +#define SFF_8636_TEMP_LWARN_MASK (1 << 4) + +#define SFF_8636_VCC_MASK_OFFSET 0x68 +#define SFF_8636_VCC_HALARM_MASK (1 << 7) +#define SFF_8636_VCC_LALARM_MASK (1 << 6) +#define SFF_8636_VCC_HWARN_MASK (1 << 5) +#define SFF_8636_VCC_LWARN_MASK (1 << 4) + +/*------------------------------------------------------------------------------ + * + * Upper Memory Page 00h + * Serial ID - Base ID, Extended ID and Vendor Specific ID fields + * + */ +/* Identifier - 128 */ +/* Identifier values same as Lower Memory Page 00h */ +#define SFF_8636_UPPER_PAGE_0_ID_OFFSET 0x80 + +/* Extended Identifier - 128 */ +#define SFF_8636_EXT_ID_OFFSET 0x81 +#define SFF_8636_EXT_ID_PWR_CLASS_MASK 0xC0 +#define SFF_8636_EXT_ID_PWR_CLASS_1 (0 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_2 (1 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_3 (2 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_4 (3 << 6) +#define SFF_8636_EXT_ID_CLIE_MASK 0x10 +#define SFF_8636_EXT_ID_CLIEI_CODE_PRESENT (1 << 4) +#define SFF_8636_EXT_ID_CDR_TX_MASK 0x08 +#define SFF_8636_EXT_ID_CDR_TX_PRESENT (1 << 3) +#define SFF_8636_EXT_ID_CDR_RX_MASK 0x04 +#define SFF_8636_EXT_ID_CDR_RX_PRESENT (1 << 2) +#define SFF_8636_EXT_ID_EPWR_CLASS_MASK 0x03 +#define SFF_8636_EXT_ID_PWR_CLASS_LEGACY 0 +#define SFF_8636_EXT_ID_PWR_CLASS_5 1 +#define SFF_8636_EXT_ID_PWR_CLASS_6 2 +#define SFF_8636_EXT_ID_PWR_CLASS_7 3 + +/* Connector Values offset - 130 */ +/* Values are defined under SFF_8024_CTOR */ +#define SFF_8636_CTOR_OFFSET 0x82 +#define SFF_8636_CTOR_UNKNOWN 0x00 +#define SFF_8636_CTOR_SC 0x01 +#define SFF_8636_CTOR_FC_STYLE_1 0x02 +#define SFF_8636_CTOR_FC_STYLE_2 0x03 +#define SFF_8636_CTOR_BNC_TNC 0x04 +#define SFF_8636_CTOR_FC_COAX 0x05 +#define SFF_8636_CTOR_FIBER_JACK 0x06 +#define SFF_8636_CTOR_LC 0x07 +#define SFF_8636_CTOR_MT_RJ 0x08 +#define SFF_8636_CTOR_MU 0x09 +#define SFF_8636_CTOR_SG 0x0A +#define SFF_8636_CTOR_OPT_PT 0x0B +#define SFF_8636_CTOR_MPO 0x0C +/* 0D-1Fh --- Reserved */ +#define SFF_8636_CTOR_HSDC_II 0x20 +#define SFF_8636_CTOR_COPPER_PT 0x21 +#define SFF_8636_CTOR_RJ45 0x22 +#define SFF_8636_CTOR_NO_SEPARABLE 0x23 +#define SFF_8636_CTOR_MXC_2X16 0x24 + +/* Specification Compliance - 131-138 */ +/* Ethernet Compliance Codes - 131 */ +#define SFF_8636_ETHERNET_COMP_OFFSET 0x83 +#define SFF_8636_ETHERNET_RSRVD (1 << 7) +#define SFF_8636_ETHERNET_10G_LRM (1 << 6) +#define SFF_8636_ETHERNET_10G_LR (1 << 5) +#define SFF_8636_ETHERNET_10G_SR (1 << 4) +#define SFF_8636_ETHERNET_40G_CR4 (1 << 3) +#define SFF_8636_ETHERNET_40G_SR4 (1 << 2) +#define SFF_8636_ETHERNET_40G_LR4 (1 << 1) +#define SFF_8636_ETHERNET_40G_ACTIVE (1 << 0) + +/* SONET Compliance Codes - 132 */ +#define SFF_8636_SONET_COMP_OFFSET 0x84 +#define SFF_8636_SONET_40G_OTN (1 << 3) +#define SFF_8636_SONET_OC48_LR (1 << 2) +#define SFF_8636_SONET_OC48_IR (1 << 1) +#define SFF_8636_SONET_OC48_SR (1 << 0) + +/* SAS/SATA Complaince Codes - 133 */ +#define SFF_8636_SAS_COMP_OFFSET 0x85 +#define SFF_8636_SAS_12G (1 << 6) +#define SFF_8636_SAS_6G (1 << 5) +#define SFF_8636_SAS_3G (1 << 4) + +/* Gigabit Ethernet Compliance Codes - 134 */ +#define SFF_8636_GIGE_COMP_OFFSET 0x86 +#define SFF_8636_GIGE_1000_BASE_T (1 << 3) +#define SFF_8636_GIGE_1000_BASE_CX (1 << 2) +#define SFF_8636_GIGE_1000_BASE_LX (1 << 1) +#define SFF_8636_GIGE_1000_BASE_SX (1 << 0) + +/* Fibre Channel Link length/Transmitter Tech. - 135,136 */ +#define SFF_8636_FC_LEN_OFFSET 0x87 +#define SFF_8636_FC_LEN_VERY_LONG (1 << 7) +#define SFF_8636_FC_LEN_SHORT (1 << 6) +#define SFF_8636_FC_LEN_INT (1 << 5) +#define SFF_8636_FC_LEN_LONG (1 << 4) +#define SFF_8636_FC_LEN_MED (1 << 3) +#define SFF_8636_FC_TECH_LONG_LC (1 << 1) +#define SFF_8636_FC_TECH_ELEC_INTER (1 << 0) + +#define SFF_8636_FC_TECH_OFFSET 0x88 +#define SFF_8636_FC_TECH_ELEC_INTRA (1 << 7) +#define SFF_8636_FC_TECH_SHORT_WO_OFC (1 << 6) +#define SFF_8636_FC_TECH_SHORT_W_OFC (1 << 5) +#define SFF_8636_FC_TECH_LONG_LL (1 << 4) + +/* Fibre Channel Transmitter Media - 137 */ +#define SFF_8636_FC_TRANS_MEDIA_OFFSET 0x89 +/* Twin Axial Pair */ +#define SFF_8636_FC_TRANS_MEDIA_TW (1 << 7) +/* Shielded Twisted Pair */ +#define SFF_8636_FC_TRANS_MEDIA_TP (1 << 6) +/* Miniature Coax */ +#define SFF_8636_FC_TRANS_MEDIA_MI (1 << 5) +/* Video Coax */ +#define SFF_8636_FC_TRANS_MEDIA_TV (1 << 4) +/* Multi-mode 62.5m */ +#define SFF_8636_FC_TRANS_MEDIA_M6 (1 << 3) +/* Multi-mode 50m */ +#define SFF_8636_FC_TRANS_MEDIA_M5 (1 << 2) +/* Multi-mode 50um */ +#define SFF_8636_FC_TRANS_MEDIA_OM3 (1 << 1) +/* Single Mode */ +#define SFF_8636_FC_TRANS_MEDIA_SM (1 << 0) + +/* Fibre Channel Speed - 138 */ +#define SFF_8636_FC_SPEED_OFFSET 0x8A +#define SFF_8636_FC_SPEED_1200_MBPS (1 << 7) +#define SFF_8636_FC_SPEED_800_MBPS (1 << 6) +#define SFF_8636_FC_SPEED_1600_MBPS (1 << 5) +#define SFF_8636_FC_SPEED_400_MBPS (1 << 4) +#define SFF_8636_FC_SPEED_200_MBPS (1 << 2) +#define SFF_8636_FC_SPEED_100_MBPS (1 << 0) + +/* Encoding - 139 */ +/* Values are defined under SFF_8024_ENCODING */ +#define SFF_8636_ENCODING_OFFSET 0x8B +#define SFF_8636_ENCODING_MANCHESTER 0x06 +#define SFF_8636_ENCODING_64B66B 0x05 +#define SFF_8636_ENCODING_SONET 0x04 +#define SFF_8636_ENCODING_NRZ 0x03 +#define SFF_8636_ENCODING_4B5B 0x02 +#define SFF_8636_ENCODING_8B10B 0x01 +#define SFF_8636_ENCODING_UNSPEC 0x00 + +/* BR, Nominal - 140 */ +#define SFF_8636_BR_NOMINAL_OFFSET 0x8C + +/* Extended RateSelect - 141 */ +#define SFF_8636_EXT_RS_OFFSET 0x8D +#define SFF_8636_EXT_RS_V1 (1 << 0) + +/* Length (Standard SM Fiber)-km - 142 */ +#define SFF_8636_SM_LEN_OFFSET 0x8E + +/* Length (OM3)-Unit 2m - 143 */ +#define SFF_8636_OM3_LEN_OFFSET 0x8F + +/* Length (OM2)-Unit 1m - 144 */ +#define SFF_8636_OM2_LEN_OFFSET 0x90 + +/* Length (OM1)-Unit 1m - 145 */ +#define SFF_8636_OM1_LEN_OFFSET 0x91 + +/* Cable Assembly Length -Unit 1m - 146 */ +#define SFF_8636_CBL_LEN_OFFSET 0x92 + +/* Device Technology - 147 */ +#define SFF_8636_DEVICE_TECH_OFFSET 0x93 +/* Transmitter Technology */ +#define SFF_8636_TRANS_TECH_MASK 0xF0 +/* Copper cable, linear active equalizers */ +#define SFF_8636_TRANS_COPPER_LNR_EQUAL (15 << 4) +/* Copper cable, near end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_NEAR_EQUAL (14 << 4) +/* Copper cable, far end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_FAR_EQUAL (13 << 4) +/* Copper cable, near & far end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_LNR_FAR_EQUAL (12 << 4) +/* Copper cable, passive equalized */ +#define SFF_8636_TRANS_COPPER_PAS_EQUAL (11 << 4) +/* Copper cable, unequalized */ +#define SFF_8636_TRANS_COPPER_PAS_UNEQUAL (10 << 4) +/* 1490 nm DFB */ +#define SFF_8636_TRANS_1490_DFB (9 << 4) +/* Others */ +#define SFF_8636_TRANS_OTHERS (8 << 4) +/* 1550 nm EML */ +#define SFF_8636_TRANS_1550_EML (7 << 4) +/* 1310 nm EML */ +#define SFF_8636_TRANS_1310_EML (6 << 4) +/* 1550 nm DFB */ +#define SFF_8636_TRANS_1550_DFB (5 << 4) +/* 1310 nm DFB */ +#define SFF_8636_TRANS_1310_DFB (4 << 4) +/* 1310 nm FP */ +#define SFF_8636_TRANS_1310_FP (3 << 4) +/* 1550 nm VCSEL */ +#define SFF_8636_TRANS_1550_VCSEL (2 << 4) +/* 1310 nm VCSEL */ +#define SFF_8636_TRANS_1310_VCSEL (1 << 4) +/* 850 nm VCSEL */ +#define SFF_8636_TRANS_850_VCSEL (0 << 4) + + /* Active/No wavelength control */ +#define SFF_8636_DEV_TECH_ACTIVE_WAVE_LEN (1 << 3) +/* Cooled transmitter */ +#define SFF_8636_DEV_TECH_COOL_TRANS (1 << 2) +/* APD/Pin Detector */ +#define SFF_8636_DEV_TECH_APD_DETECTOR (1 << 1) +/* Transmitter tunable */ +#define SFF_8636_DEV_TECH_TUNABLE (1 << 0) + +/* Vendor Name - 148-163 */ +#define SFF_8636_VENDOR_NAME_START_OFFSET 0x94 +#define SFF_8636_VENDOR_NAME_END_OFFSET 0xA3 + +/* Extended Module Codes - 164 */ +#define SFF_8636_EXT_MOD_CODE_OFFSET 0xA4 +#define SFF_8636_EXT_MOD_INFINIBAND_EDR (1 << 4) +#define SFF_8636_EXT_MOD_INFINIBAND_FDR (1 << 3) +#define SFF_8636_EXT_MOD_INFINIBAND_QDR (1 << 2) +#define SFF_8636_EXT_MOD_INFINIBAND_DDR (1 << 1) +#define SFF_8636_EXT_MOD_INFINIBAND_SDR (1 << 0) + +/* Vendor OUI - 165-167 */ +#define SFF_8636_VENDOR_OUI_OFFSET 0xA5 +#define SFF_8636_VENDOR_OUI_LEN 3 + +/* Vendor OUI - 165-167 */ +#define SFF_8636_VENDOR_PN_START_OFFSET 0xA8 +#define SFF_8636_VENDOR_PN_END_OFFSET 0xB7 + +/* Vendor Revision - 184-185 */ +#define SFF_8636_VENDOR_REV_START_OFFSET 0xB8 +#define SFF_8636_VENDOR_REV_END_OFFSET 0xB9 + +/* Wavelength - 186-187 */ +#define SFF_8636_WAVELEN_HIGH_BYTE_OFFSET 0xBA +#define SFF_8636_WAVELEN_LOW_BYTE_OFFSET 0xBB + +/* Wavelength Tolerance- 188-189 */ +#define SFF_8636_WAVE_TOL_HIGH_BYTE_OFFSET 0xBC +#define SFF_8636_WAVE_TOL_LOW_BYTE_OFFSET 0xBD + +/* Max case temp - Other than 70 C - 190 */ +#define SFF_8636_MAXCASE_TEMP_OFFSET 0xBE + +/* CC_BASE - 191 */ +#define SFF_8636_CC_BASE_OFFSET 0xBF + +/* Option Values - 192-195 */ +#define SFF_8636_OPTION_1_OFFSET 0xC0 +#define SFF_8636_ETHERNET_UNSPECIFIED 0x00 +#define SFF_8636_ETHERNET_100G_AOC 0x01 +#define SFF_8636_ETHERNET_100G_SR4 0x02 +#define SFF_8636_ETHERNET_100G_LR4 0x03 +#define SFF_8636_ETHERNET_100G_ER4 0x04 +#define SFF_8636_ETHERNET_100G_SR10 0x05 +#define SFF_8636_ETHERNET_100G_CWDM4_FEC 0x06 +#define SFF_8636_ETHERNET_100G_PSM4 0x07 +#define SFF_8636_ETHERNET_100G_ACC 0x08 +#define SFF_8636_ETHERNET_100G_CWDM4_NO_FEC 0x09 +#define SFF_8636_ETHERNET_100G_RSVD1 0x0A +#define SFF_8636_ETHERNET_100G_CR4 0x0B +#define SFF_8636_ETHERNET_25G_CR_CA_S 0x0C +#define SFF_8636_ETHERNET_25G_CR_CA_N 0x0D +#define SFF_8636_ETHERNET_40G_ER4 0x10 +#define SFF_8636_ETHERNET_4X10_SR 0x11 +#define SFF_8636_ETHERNET_40G_PSM4 0x12 +#define SFF_8636_ETHERNET_G959_P1I1_2D1 0x13 +#define SFF_8636_ETHERNET_G959_P1S1_2D2 0x14 +#define SFF_8636_ETHERNET_G959_P1L1_2D2 0x15 +#define SFF_8636_ETHERNET_10GT_SFI 0x16 +#define SFF_8636_ETHERNET_100G_CLR4 0x17 +#define SFF_8636_ETHERNET_100G_AOC2 0x18 +#define SFF_8636_ETHERNET_100G_ACC2 0x19 + +#define SFF_8636_OPTION_2_OFFSET 0xC1 +/* Rx output amplitude */ +#define SFF_8636_O2_RX_OUTPUT_AMP (1 << 0) +#define SFF_8636_OPTION_3_OFFSET 0xC2 +/* Rx Squelch Disable */ +#define SFF_8636_O3_RX_SQL_DSBL (1 << 3) +/* Rx Output Disable capable */ +#define SFF_8636_O3_RX_OUTPUT_DSBL (1 << 2) +/* Tx Squelch Disable */ +#define SFF_8636_O3_TX_SQL_DSBL (1 << 1) +/* Tx Squelch Impl */ +#define SFF_8636_O3_TX_SQL_IMPL (1 << 0) +#define SFF_8636_OPTION_4_OFFSET 0xC3 +/* Memory Page 02 present */ +#define SFF_8636_O4_PAGE_02_PRESENT (1 << 7) +/* Memory Page 01 present */ +#define SFF_8636_O4_PAGE_01_PRESENT (1 << 6) +/* Rate Select implemented */ +#define SFF_8636_O4_RATE_SELECT (1 << 5) +/* Tx_DISABLE implemented */ +#define SFF_8636_O4_TX_DISABLE (1 << 4) +/* Tx_FAULT implemented */ +#define SFF_8636_O4_TX_FAULT (1 << 3) +/* Tx Squelch implemented */ +#define SFF_8636_O4_TX_SQUELCH (1 << 2) +/* Tx Loss of Signal */ +#define SFF_8636_O4_TX_LOS (1 << 1) + +/* Vendor SN - 196-211 */ +#define SFF_8636_VENDOR_SN_START_OFFSET 0xC4 +#define SFF_8636_VENDOR_SN_END_OFFSET 0xD3 + +/* Vendor Date - 212-219 */ +#define SFF_8636_DATE_YEAR_OFFSET 0xD4 +#define SFF_8636_DATE_YEAR_LEN 2 +#define SFF_8636_DATE_MONTH_OFFSET 0xD6 +#define SFF_8636_DATE_MONTH_LEN 2 +#define SFF_8636_DATE_DAY_OFFSET 0xD8 +#define SFF_8636_DATE_DAY_LEN 2 +#define SFF_8636_DATE_VENDOR_LOT_OFFSET 0xDA +#define SFF_8636_DATE_VENDOR_LOT_LEN 2 + +/* Diagnostic Monitoring Type - 220 */ +#define SFF_8636_DIAG_TYPE_OFFSET 0xDC +#define SFF_8636_RX_PWR_TYPE_MASK 0x8 +#define SFF_8636_RX_PWR_TYPE_AVG_PWR (1 << 3) +#define SFF_8636_RX_PWR_TYPE_OMA (0 << 3) +#define SFF_8636_TX_PWR_TYPE_MASK 0x4 +#define SFF_8636_TX_PWR_TYPE_AVG_PWR (1 << 2) + +/* Enhanced Options - 221 */ +#define SFF_8636_ENH_OPTIONS_OFFSET 0xDD +#define SFF_8636_RATE_SELECT_EXT_SUPPORT (1 << 3) +#define SFF_8636_RATE_SELECT_APP_TABLE_SUPPORT (1 << 2) + +/* Check code - 223 */ +#define SFF_8636_CC_EXT_OFFSET 0xDF +#define SFF_8636_CC_EXT_LEN 1 + +/*------------------------------------------------------------------------------ + * + * Upper Memory Page 03h + * Contains module thresholds, channel thresholds and masks, + * and optional channel controls + * + * Offset - Page Num(3) * PageSize(0x80) + Page offset + */ + +/* Module Thresholds (48 Bytes) 128-175 */ +/* MSB at low address, LSB at high address */ +#define SFF_8636_TEMP_HALRM 0x200 +#define SFF_8636_TEMP_LALRM 0x202 +#define SFF_8636_TEMP_HWARN 0x204 +#define SFF_8636_TEMP_LWARN 0x206 + +#define SFF_8636_VCC_HALRM 0x210 +#define SFF_8636_VCC_LALRM 0x212 +#define SFF_8636_VCC_HWARN 0x214 +#define SFF_8636_VCC_LWARN 0x216 + +#define SFF_8636_RX_PWR_HALRM 0x230 +#define SFF_8636_RX_PWR_LALRM 0x232 +#define SFF_8636_RX_PWR_HWARN 0x234 +#define SFF_8636_RX_PWR_LWARN 0x236 + +#define SFF_8636_TX_BIAS_HALRM 0x238 +#define SFF_8636_TX_BIAS_LALRM 0x23A +#define SFF_8636_TX_BIAS_HWARN 0x23C +#define SFF_8636_TX_BIAS_LWARN 0x23E + +#define SFF_8636_TX_PWR_HALRM 0x240 +#define SFF_8636_TX_PWR_LALRM 0x242 +#define SFF_8636_TX_PWR_HWARN 0x244 +#define SFF_8636_TX_PWR_LWARN 0x246 + +#define ETH_MODULE_SFF_8636_MAX_LEN 640 +#define ETH_MODULE_SFF_8436_MAX_LEN 640 + +#endif /* _SFF_8636_H_ */ -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v7 0/5] add telemetry command for show module EEPROM 2022-05-11 2:14 ` [PATCH v6 " Robin Zhang ` (4 preceding siblings ...) 2022-05-11 2:14 ` [PATCH v6 5/5] ethdev: format module EEPROM for SFF-8636 Robin Zhang @ 2022-05-24 6:24 ` Robin Zhang 2022-05-24 6:24 ` [PATCH v7 1/5] ethdev: add telemetry command for " Robin Zhang ` (5 more replies) 5 siblings, 6 replies; 77+ messages in thread From: Robin Zhang @ 2022-05-24 6:24 UTC (permalink / raw) To: dev; +Cc: thomas, andrew.rybchenko, kevinx.liu, Robin Zhang Introduce a new telemetry command /ethdev/module_eeprom to show module EEPROM for each port. The format of module EEPROM information follows the SFF(Small Form Factor) Committee specifications. Current the format support SFP(Small Formfactor Pluggable)/SFP+/ QSFP+(Quad Small Formfactor Pluggable)/QSFP28 with specs SFF-8079/ SFF-8472/SFF-8024/SFF-8636. Afther run the /ethdev/module_eeprom command, telemetry client will show the module EEPROM information. We keep the same information content compare with Linux utility ethtool, refer to command 'ethtool -m' of ethtool v5.4. v7: - remove "#include <arpa/inet.h>" in lib/ethdev/sff_8472.c v6: - refine code v5: - fix CI robot compile fail issue v4: - remove all printf in primary application, only show information in tememetry client - refine codes v3: - split up codes into several patches for better reivew Robin Zhang (5): ethdev: add telemetry command for module EEPROM ethdev: common utilities for different SFF specs ethdev: format module EEPROM for SFF-8079 ethdev: format module EEPROM for SFF-8472 ethdev: format module EEPROM for SFF-8636 lib/ethdev/ethdev_sff_telemetry.c | 149 ++++++ lib/ethdev/ethdev_sff_telemetry.h | 27 ++ lib/ethdev/meson.build | 5 + lib/ethdev/rte_ethdev.c | 3 + lib/ethdev/sff_8079.c | 406 ++++++++++++++++ lib/ethdev/sff_8472.c | 286 +++++++++++ lib/ethdev/sff_8636.c | 775 ++++++++++++++++++++++++++++++ lib/ethdev/sff_8636.h | 592 +++++++++++++++++++++++ lib/ethdev/sff_common.c | 326 +++++++++++++ lib/ethdev/sff_common.h | 174 +++++++ 10 files changed, 2743 insertions(+) create mode 100644 lib/ethdev/ethdev_sff_telemetry.c create mode 100644 lib/ethdev/ethdev_sff_telemetry.h create mode 100644 lib/ethdev/sff_8079.c create mode 100644 lib/ethdev/sff_8472.c create mode 100644 lib/ethdev/sff_8636.c create mode 100644 lib/ethdev/sff_8636.h create mode 100644 lib/ethdev/sff_common.c create mode 100644 lib/ethdev/sff_common.h -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v7 1/5] ethdev: add telemetry command for module EEPROM 2022-05-24 6:24 ` [PATCH v7 0/5] add telemetry command for show module EEPROM Robin Zhang @ 2022-05-24 6:24 ` Robin Zhang 2022-05-24 6:24 ` [PATCH v7 2/5] ethdev: common utilities for different SFF specs Robin Zhang ` (4 subsequent siblings) 5 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-05-24 6:24 UTC (permalink / raw) To: dev; +Cc: thomas, andrew.rybchenko, kevinx.liu, Robin Zhang Add a new telemetry command /ethdev/module_eeprom to dump the module EEPROM of each port. The format of module EEPROM information follows the SFF(Small Form Factor) Committee specifications. Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/ethdev_sff_telemetry.c | 138 ++++++++++++++++++++++++++++++ lib/ethdev/ethdev_sff_telemetry.h | 27 ++++++ lib/ethdev/meson.build | 1 + lib/ethdev/rte_ethdev.c | 3 + 4 files changed, 169 insertions(+) create mode 100644 lib/ethdev/ethdev_sff_telemetry.c create mode 100644 lib/ethdev/ethdev_sff_telemetry.h diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c new file mode 100644 index 0000000000..f756b9643f --- /dev/null +++ b/lib/ethdev/ethdev_sff_telemetry.c @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + */ + +#include <errno.h> + +#include <rte_ethdev.h> +#include <rte_common.h> +#include "ethdev_sff_telemetry.h" +#include "telemetry_data.h" + +static void +sff_port_module_eeprom_parse(uint16_t port_id, struct rte_tel_data *d) +{ + struct rte_eth_dev_module_info minfo; + struct rte_dev_eeprom_info einfo; + int ret; + + if (d == NULL) { + RTE_ETHDEV_LOG(ERR, "Dict invalid\n"); + return; + } + + ret = rte_eth_dev_get_module_info(port_id, &minfo); + if (ret != 0) { + switch (ret) { + case -ENODEV: + RTE_ETHDEV_LOG(ERR, "port index %d invalid\n", port_id); + break; + case -ENOTSUP: + RTE_ETHDEV_LOG(ERR, "operation not supported by device\n"); + break; + case -EIO: + RTE_ETHDEV_LOG(ERR, "device is removed\n"); + break; + default: + RTE_ETHDEV_LOG(ERR, "Unable to get port module info, %d\n", ret); + break; + } + return; + } + + einfo.offset = 0; + einfo.length = minfo.eeprom_len; + einfo.data = calloc(1, minfo.eeprom_len); + if (einfo.data == NULL) { + RTE_ETHDEV_LOG(ERR, "Allocation of port %u eeprom data failed\n", port_id); + return; + } + + ret = rte_eth_dev_get_module_eeprom(port_id, &einfo); + if (ret != 0) { + switch (ret) { + case -ENODEV: + RTE_ETHDEV_LOG(ERR, "port index %d invalid\n", port_id); + break; + case -ENOTSUP: + RTE_ETHDEV_LOG(ERR, "operation not supported by device\n"); + break; + case -EIO: + RTE_ETHDEV_LOG(ERR, "device is removed\n"); + break; + default: + RTE_ETHDEV_LOG(ERR, "Unable to get port module EEPROM, %d\n", ret); + break; + } + free(einfo.data); + return; + } + + switch (minfo.type) { + /* parsing module EEPROM data base on different module type */ + default: + RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); + break; + } + + free(einfo.data); +} + +void +ssf_add_dict_string(struct rte_tel_data *d, const char *name_str, const char *value_str) +{ + struct tel_dict_entry *e = &d->data.dict[d->data_len]; + + if (d->type != RTE_TEL_DICT) + return; + if (d->data_len >= RTE_TEL_MAX_DICT_ENTRIES) { + RTE_ETHDEV_LOG(ERR, "data_len has exceeded the maximum number of inserts\n"); + return; + } + + e->type = RTE_TEL_STRING_VAL; + /* append different values for same keys */ + if (d->data_len > 0) { + struct tel_dict_entry *previous = &d->data.dict[d->data_len - 1]; + if (strcmp(previous->name, name_str) == 0) { + strlcat(previous->value.sval, "; ", RTE_TEL_MAX_STRING_LEN); + strlcat(previous->value.sval, value_str, RTE_TEL_MAX_STRING_LEN); + goto end; + } + } + strlcpy(e->value.sval, value_str, RTE_TEL_MAX_STRING_LEN); + strlcpy(e->name, name_str, RTE_TEL_MAX_STRING_LEN); + d->data_len++; + +end: + return; +} + +int +eth_dev_handle_port_module_eeprom(const char *cmd __rte_unused, const char *params, + struct rte_tel_data *d) +{ + char *end_param; + int port_id; + + if (params == NULL || strlen(params) == 0 || !isdigit(*params)) + return -1; + + errno = 0; + port_id = strtoul(params, &end_param, 0); + + if (errno != 0) { + RTE_ETHDEV_LOG(ERR, "Invalid argument\n"); + return -1; + } + + if (*end_param != '\0') + RTE_ETHDEV_LOG(NOTICE, + "Extra parameters passed to ethdev telemetry command, ignoring\n"); + + rte_tel_data_start_dict(d); + + sff_port_module_eeprom_parse(port_id, d); + + return 0; +} diff --git a/lib/ethdev/ethdev_sff_telemetry.h b/lib/ethdev/ethdev_sff_telemetry.h new file mode 100644 index 0000000000..1fd870e0ef --- /dev/null +++ b/lib/ethdev/ethdev_sff_telemetry.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + */ + +#ifndef _ETHDEV_SFF_TELEMETRY_H_ +#define _ETHDEV_SFF_TELEMETRY_H_ + +#include <rte_telemetry.h> + +#define SFF_ITEM_VAL_COMPOSE_SIZE 64 + +/* SFF-8079 Optics diagnostics */ +void sff_8079_show_all(const uint8_t *data, struct rte_tel_data *d); + +/* SFF-8472 Optics diagnostics */ +void sff_8472_show_all(const uint8_t *data, struct rte_tel_data *d); + +/* SFF-8636 Optics diagnostics */ +void sff_8636_show_all(const uint8_t *data, uint32_t eeprom_len, struct rte_tel_data *d); + +int eth_dev_handle_port_module_eeprom(const char *cmd __rte_unused, + const char *params, + struct rte_tel_data *d); + +void ssf_add_dict_string(struct rte_tel_data *d, const char *name_str, const char *value_str); + +#endif /* _ETHDEV_SFF_TELEMETRY_H_ */ diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index a094585bf7..49c77acb3f 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -11,6 +11,7 @@ sources = files( 'rte_flow.c', 'rte_mtr.c', 'rte_tm.c', + 'ethdev_sff_telemetry.c', ) headers = files( diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c index 29a3d80466..2b87df1b32 100644 --- a/lib/ethdev/rte_ethdev.c +++ b/lib/ethdev/rte_ethdev.c @@ -39,6 +39,7 @@ #include "ethdev_driver.h" #include "ethdev_profile.h" #include "ethdev_private.h" +#include "ethdev_sff_telemetry.h" struct rte_eth_dev rte_eth_devices[RTE_MAX_ETHPORTS]; @@ -5876,4 +5877,6 @@ RTE_INIT(ethdev_init_telemetry) "Returns the link status for a port. Parameters: int port_id"); rte_telemetry_register_cmd("/ethdev/info", eth_dev_handle_port_info, "Returns the device info for a port. Parameters: int port_id"); + rte_telemetry_register_cmd("/ethdev/module_eeprom", eth_dev_handle_port_module_eeprom, + "Returns module EEPROM info with SFF specs. Parameters: int port_id"); } -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v7 2/5] ethdev: common utilities for different SFF specs 2022-05-24 6:24 ` [PATCH v7 0/5] add telemetry command for show module EEPROM Robin Zhang 2022-05-24 6:24 ` [PATCH v7 1/5] ethdev: add telemetry command for " Robin Zhang @ 2022-05-24 6:24 ` Robin Zhang 2022-05-24 6:24 ` [PATCH v7 3/5] ethdev: format module EEPROM for SFF-8079 Robin Zhang ` (3 subsequent siblings) 5 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-05-24 6:24 UTC (permalink / raw) To: dev; +Cc: thomas, andrew.rybchenko, kevinx.liu, Robin Zhang This patch implements SFF-8024 Rev 4.0 of pluggable I/O configuration and some common utilities for SFF-8436/8636 and SFF-8472/8079. Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/meson.build | 1 + lib/ethdev/sff_common.c | 326 ++++++++++++++++++++++++++++++++++++++++ lib/ethdev/sff_common.h | 174 +++++++++++++++++++++ 3 files changed, 501 insertions(+) create mode 100644 lib/ethdev/sff_common.c create mode 100644 lib/ethdev/sff_common.h diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index 49c77acb3f..8f39739e43 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -12,6 +12,7 @@ sources = files( 'rte_mtr.c', 'rte_tm.c', 'ethdev_sff_telemetry.c', + 'sff_common.c', ) headers = files( diff --git a/lib/ethdev/sff_common.c b/lib/ethdev/sff_common.c new file mode 100644 index 0000000000..06d96fac72 --- /dev/null +++ b/lib/ethdev/sff_common.c @@ -0,0 +1,326 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8024 Rev 4.0 of pluggable I/O configuration and some + * common utilities for SFF-8436/8636 and SFF-8472/8079 + * + */ + +#include <stdio.h> +#include <math.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "ethdev_sff_telemetry.h" + + +double convert_mw_to_dbm(double mw) +{ + return (10. * log10(mw / 1000.)) + 30.; +} + +void sff_show_value_with_unit(const uint8_t *data, unsigned int reg, + const char *name, unsigned int mult, + const char *unit, struct rte_tel_data *d) +{ + unsigned int val = data[reg]; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "%u%s", val * mult, unit); + ssf_add_dict_string(d, name, val_string); +} + +void sff_show_ascii(const uint8_t *data, unsigned int first_reg, + unsigned int last_reg, const char *name, struct rte_tel_data *d) +{ + unsigned int reg, val; + char tmp[3]; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + memset(val_string, 0, sizeof(val_string)); + + while (first_reg <= last_reg && data[last_reg] == ' ') + last_reg--; + for (reg = first_reg; reg <= last_reg; reg++) { + val = data[reg]; + if ((val >= 32) && (val <= 126)) { + snprintf(tmp, sizeof(tmp), "%c", val); + strlcat(val_string, tmp, sizeof(val_string)); + } else { + strlcat(val_string, "_", sizeof(val_string)); + } + } + ssf_add_dict_string(d, name, val_string); +} + +void sff_8024_show_oui(const uint8_t *data, int id_offset, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "%02x:%02x:%02x", + data[id_offset], data[(id_offset) + 1], data[(id_offset) + 2]); + ssf_add_dict_string(d, "Vendor OUI", val_string); +} + +void sff_8024_show_identifier(const uint8_t *data, int id_offset, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[id_offset]); + + switch (data[id_offset]) { + case SFF_8024_ID_UNKNOWN: + strlcat(val_string, " (no module present, unknown, or unspecified)", + sizeof(val_string)); + break; + case SFF_8024_ID_GBIC: + strlcat(val_string, " (GBIC)", sizeof(val_string)); + break; + case SFF_8024_ID_SOLDERED_MODULE: + strlcat(val_string, " (module soldered to motherboard)", sizeof(val_string)); + break; + case SFF_8024_ID_SFP: + strlcat(val_string, " (SFP)", sizeof(val_string)); + break; + case SFF_8024_ID_300_PIN_XBI: + strlcat(val_string, " (300 pin XBI)", sizeof(val_string)); + break; + case SFF_8024_ID_XENPAK: + strlcat(val_string, " (XENPAK)", sizeof(val_string)); + break; + case SFF_8024_ID_XFP: + strlcat(val_string, " (XFP)", sizeof(val_string)); + break; + case SFF_8024_ID_XFF: + strlcat(val_string, " (XFF)", sizeof(val_string)); + break; + case SFF_8024_ID_XFP_E: + strlcat(val_string, " (XFP-E)", sizeof(val_string)); + break; + case SFF_8024_ID_XPAK: + strlcat(val_string, " (XPAK)", sizeof(val_string)); + break; + case SFF_8024_ID_X2: + strlcat(val_string, " (X2)", sizeof(val_string)); + break; + case SFF_8024_ID_DWDM_SFP: + strlcat(val_string, " (DWDM-SFP)", sizeof(val_string)); + break; + case SFF_8024_ID_QSFP: + strlcat(val_string, " (QSFP)", sizeof(val_string)); + break; + case SFF_8024_ID_QSFP_PLUS: + strlcat(val_string, " (QSFP+)", sizeof(val_string)); + break; + case SFF_8024_ID_CXP: + strlcat(val_string, " (CXP)", sizeof(val_string)); + break; + case SFF_8024_ID_HD4X: + strlcat(val_string, " (Shielded Mini Multilane HD 4X)", sizeof(val_string)); + break; + case SFF_8024_ID_HD8X: + strlcat(val_string, " (Shielded Mini Multilane HD 8X)", sizeof(val_string)); + break; + case SFF_8024_ID_QSFP28: + strlcat(val_string, " (QSFP28)", sizeof(val_string)); + break; + case SFF_8024_ID_CXP2: + strlcat(val_string, " (CXP2/CXP28)", sizeof(val_string)); + break; + case SFF_8024_ID_CDFP: + strlcat(val_string, " (CDFP Style 1/Style 2)", sizeof(val_string)); + break; + case SFF_8024_ID_HD4X_FANOUT: + strlcat(val_string, " (Shielded Mini Multilane HD 4X Fanout Cable)", + sizeof(val_string)); + break; + case SFF_8024_ID_HD8X_FANOUT: + strlcat(val_string, " (Shielded Mini Multilane HD 8X Fanout Cable)", + sizeof(val_string)); + break; + case SFF_8024_ID_CDFP_S3: + strlcat(val_string, " (CDFP Style 3)", sizeof(val_string)); + break; + case SFF_8024_ID_MICRO_QSFP: + strlcat(val_string, " (microQSFP)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + ssf_add_dict_string(d, "Identifier", val_string); +} + +void sff_8024_show_connector(const uint8_t *data, int ctor_offset, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[ctor_offset]); + + switch (data[ctor_offset]) { + case SFF_8024_CTOR_UNKNOWN: + strlcat(val_string, " (unknown or unspecified)", sizeof(val_string)); + break; + case SFF_8024_CTOR_SC: + strlcat(val_string, " (SC)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FC_STYLE_1: + strlcat(val_string, " (Fibre Channel Style 1 copper)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FC_STYLE_2: + strlcat(val_string, " (Fibre Channel Style 2 copper)", sizeof(val_string)); + break; + case SFF_8024_CTOR_BNC_TNC: + strlcat(val_string, " (BNC/TNC)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FC_COAX: + strlcat(val_string, " (Fibre Channel coaxial headers)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FIBER_JACK: + strlcat(val_string, " (FibreJack)", sizeof(val_string)); + break; + case SFF_8024_CTOR_LC: + strlcat(val_string, " (LC)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MT_RJ: + strlcat(val_string, " (MT-RJ)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MU: + strlcat(val_string, " (MU)", sizeof(val_string)); + break; + case SFF_8024_CTOR_SG: + strlcat(val_string, " (SG)", sizeof(val_string)); + break; + case SFF_8024_CTOR_OPT_PT: + strlcat(val_string, " (Optical pigtail)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MPO: + strlcat(val_string, " (MPO Parallel Optic)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MPO_2: + strlcat(val_string, " (MPO Parallel Optic - 2x16)", sizeof(val_string)); + break; + case SFF_8024_CTOR_HSDC_II: + strlcat(val_string, " (HSSDC II)", sizeof(val_string)); + break; + case SFF_8024_CTOR_COPPER_PT: + strlcat(val_string, " (Copper pigtail)", sizeof(val_string)); + break; + case SFF_8024_CTOR_RJ45: + strlcat(val_string, " (RJ45)", sizeof(val_string)); + break; + case SFF_8024_CTOR_NO_SEPARABLE: + strlcat(val_string, " (No separable connector)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MXC_2x16: + strlcat(val_string, " (MXC 2x16)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + ssf_add_dict_string(d, "Connector", val_string); +} + +void sff_8024_show_encoding(const uint8_t *data, int encoding_offset, + int sff_type, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[encoding_offset]); + + switch (data[encoding_offset]) { + case SFF_8024_ENCODING_UNSPEC: + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_8B10B: + strlcat(val_string, " (8B/10B)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_4B5B: + strlcat(val_string, " (4B/5B)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_NRZ: + strlcat(val_string, " (NRZ)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_4h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) + strlcat(val_string, " (Manchester)", sizeof(val_string)); + else if (sff_type == RTE_ETH_MODULE_SFF_8636) + strlcat(val_string, " (SONET Scrambled)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_5h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) + strlcat(val_string, " (SONET Scrambled)", sizeof(val_string)); + else if (sff_type == RTE_ETH_MODULE_SFF_8636) + strlcat(val_string, " (64B/66B)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_6h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) + strlcat(val_string, " (64B/66B)", sizeof(val_string)); + else if (sff_type == RTE_ETH_MODULE_SFF_8636) + strlcat(val_string, " (Manchester)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_256B: + strlcat(val_string, + " ((256B/257B (transcoded FEC-enabled data))", sizeof(val_string)); + break; + case SFF_8024_ENCODING_PAM4: + strlcat(val_string, " (PAM4)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + ssf_add_dict_string(d, "Encoding", val_string); +} + +void sff_show_thresholds(struct sff_diags sd, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + SPRINT_BIAS(val_string, sd.bias_cur[HALRM]); + ssf_add_dict_string(d, "Laser bias current high alarm threshold", val_string); + SPRINT_BIAS(val_string, sd.bias_cur[LALRM]); + ssf_add_dict_string(d, "Laser bias current low alarm threshold", val_string); + SPRINT_BIAS(val_string, sd.bias_cur[HWARN]); + ssf_add_dict_string(d, "Laser bias current high warning threshold", val_string); + SPRINT_BIAS(val_string, sd.bias_cur[LWARN]); + ssf_add_dict_string(d, "Laser bias current low warning threshold", val_string); + + SPRINT_xX_PWR(val_string, sd.tx_power[HALRM]); + ssf_add_dict_string(d, "Laser output power high alarm threshold", val_string); + SPRINT_xX_PWR(val_string, sd.tx_power[LALRM]); + ssf_add_dict_string(d, "Laser output power low alarm threshold", val_string); + SPRINT_xX_PWR(val_string, sd.tx_power[HWARN]); + ssf_add_dict_string(d, "Laser output power high warning threshold", val_string); + SPRINT_xX_PWR(val_string, sd.tx_power[LWARN]); + ssf_add_dict_string(d, "Laser output power low warning threshold", val_string); + + SPRINT_TEMP(val_string, sd.sfp_temp[HALRM]); + ssf_add_dict_string(d, "Module temperature high alarm threshold", val_string); + SPRINT_TEMP(val_string, sd.sfp_temp[LALRM]); + ssf_add_dict_string(d, "Module temperature low alarm threshold", val_string); + SPRINT_TEMP(val_string, sd.sfp_temp[HWARN]); + ssf_add_dict_string(d, "Module temperature high warning threshold", val_string); + SPRINT_TEMP(val_string, sd.sfp_temp[LWARN]); + ssf_add_dict_string(d, "Module temperature low warning threshold", val_string); + + SPRINT_VCC(val_string, sd.sfp_voltage[HALRM]); + ssf_add_dict_string(d, "Module voltage high alarm threshold", val_string); + SPRINT_VCC(val_string, sd.sfp_voltage[LALRM]); + ssf_add_dict_string(d, "Module voltage low alarm threshold", val_string); + SPRINT_VCC(val_string, sd.sfp_voltage[HWARN]); + ssf_add_dict_string(d, "Module voltage high warning threshold", val_string); + SPRINT_VCC(val_string, sd.sfp_voltage[LWARN]); + ssf_add_dict_string(d, "Module voltage low alarm threshold", val_string); + + SPRINT_xX_PWR(val_string, sd.rx_power[HALRM]); + ssf_add_dict_string(d, "Laser rx power high alarm threshold", val_string); + SPRINT_xX_PWR(val_string, sd.rx_power[LALRM]); + ssf_add_dict_string(d, "Laser rx power low alarm threshold", val_string); + SPRINT_xX_PWR(val_string, sd.rx_power[HWARN]); + ssf_add_dict_string(d, "Laser rx power high warning threshold", val_string); + SPRINT_xX_PWR(val_string, sd.rx_power[LWARN]); + ssf_add_dict_string(d, "Laser rx power low warning threshold", val_string); +} diff --git a/lib/ethdev/sff_common.h b/lib/ethdev/sff_common.h new file mode 100644 index 0000000000..264fb915cd --- /dev/null +++ b/lib/ethdev/sff_common.h @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8024 Rev 4.0 of pluggable I/O configuration and some + * common utilities for SFF-8436/8636 and SFF-8472/8079 + * + */ + +#ifndef _SFF_COMMON_H_ +#define _SFF_COMMON_H_ + +#include <stdio.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "ethdev_sff_telemetry.h" + +#define SFF_8024_ID_OFFSET 0x00 +#define SFF_8024_ID_UNKNOWN 0x00 +#define SFF_8024_ID_GBIC 0x01 +#define SFF_8024_ID_SOLDERED_MODULE 0x02 +#define SFF_8024_ID_SFP 0x03 +#define SFF_8024_ID_300_PIN_XBI 0x04 +#define SFF_8024_ID_XENPAK 0x05 +#define SFF_8024_ID_XFP 0x06 +#define SFF_8024_ID_XFF 0x07 +#define SFF_8024_ID_XFP_E 0x08 +#define SFF_8024_ID_XPAK 0x09 +#define SFF_8024_ID_X2 0x0A +#define SFF_8024_ID_DWDM_SFP 0x0B +#define SFF_8024_ID_QSFP 0x0C +#define SFF_8024_ID_QSFP_PLUS 0x0D +#define SFF_8024_ID_CXP 0x0E +#define SFF_8024_ID_HD4X 0x0F +#define SFF_8024_ID_HD8X 0x10 +#define SFF_8024_ID_QSFP28 0x11 +#define SFF_8024_ID_CXP2 0x12 +#define SFF_8024_ID_CDFP 0x13 +#define SFF_8024_ID_HD4X_FANOUT 0x14 +#define SFF_8024_ID_HD8X_FANOUT 0x15 +#define SFF_8024_ID_CDFP_S3 0x16 +#define SFF_8024_ID_MICRO_QSFP 0x17 +#define SFF_8024_ID_LAST SFF_8024_ID_MICRO_QSFP +#define SFF_8024_ID_UNALLOCATED_LAST 0x7F +#define SFF_8024_ID_VENDOR_START 0x80 +#define SFF_8024_ID_VENDOR_LAST 0xFF + +#define SFF_8024_CTOR_UNKNOWN 0x00 +#define SFF_8024_CTOR_SC 0x01 +#define SFF_8024_CTOR_FC_STYLE_1 0x02 +#define SFF_8024_CTOR_FC_STYLE_2 0x03 +#define SFF_8024_CTOR_BNC_TNC 0x04 +#define SFF_8024_CTOR_FC_COAX 0x05 +#define SFF_8024_CTOR_FIBER_JACK 0x06 +#define SFF_8024_CTOR_LC 0x07 +#define SFF_8024_CTOR_MT_RJ 0x08 +#define SFF_8024_CTOR_MU 0x09 +#define SFF_8024_CTOR_SG 0x0A +#define SFF_8024_CTOR_OPT_PT 0x0B +#define SFF_8024_CTOR_MPO 0x0C +#define SFF_8024_CTOR_MPO_2 0x0D +/* 0E-1Fh --- Reserved */ +#define SFF_8024_CTOR_HSDC_II 0x20 +#define SFF_8024_CTOR_COPPER_PT 0x21 +#define SFF_8024_CTOR_RJ45 0x22 +#define SFF_8024_CTOR_NO_SEPARABLE 0x23 +#define SFF_8024_CTOR_MXC_2x16 0x24 +#define SFF_8024_CTOR_LAST SFF_8024_CTOR_MXC_2x16 +#define SFF_8024_CTOR_UNALLOCATED_LAST 0x7F +#define SFF_8024_CTOR_VENDOR_START 0x80 +#define SFF_8024_CTOR_VENDOR_LAST 0xFF + +/* ENCODING Values */ +#define SFF_8024_ENCODING_UNSPEC 0x00 +#define SFF_8024_ENCODING_8B10B 0x01 +#define SFF_8024_ENCODING_4B5B 0x02 +#define SFF_8024_ENCODING_NRZ 0x03 +/* + * Value: 04h + * SFF-8472 - Manchester + * SFF-8436/8636 - SONET Scrambled + */ +#define SFF_8024_ENCODING_4h 0x04 +/* + * Value: 05h + * SFF-8472 - SONET Scrambled + * SFF-8436/8636 - 64B/66B + */ +#define SFF_8024_ENCODING_5h 0x05 +/* + * Value: 06h + * SFF-8472 - 64B/66B + * SFF-8436/8636 - Manchester + */ +#define SFF_8024_ENCODING_6h 0x06 +#define SFF_8024_ENCODING_256B 0x07 +#define SFF_8024_ENCODING_PAM4 0x08 + +/* Most common case: 16-bit unsigned integer in a certain unit */ +#define OFFSET_TO_U16(offset) \ + (data[offset] << 8 | data[(offset) + 1]) + +#define SPRINT_xX_PWR(str, var) \ + snprintf(str, sizeof(str), "%.4f mW / %.2f dBm", \ + (double)((var) / 10000.), \ + convert_mw_to_dbm((double)((var) / 10000.))) + +#define SPRINT_BIAS(str, bias_cur) \ + snprintf(str, sizeof(str), "%.3f mA", (double)(bias_cur / 500.)) + +#define SPRINT_TEMP(str, temp) \ + snprintf(str, sizeof(str), "%.2f degrees C / %.2f degrees F", \ + (double)(temp / 256.), \ + (double)(temp / 256. * 1.8 + 32.)) + +#define SPRINT_VCC(str, sfp_voltage) \ + snprintf(str, sizeof(str), "%.4f V", (double)(sfp_voltage / 10000.)) + +/* Channel Monitoring Fields */ +struct sff_channel_diags { + uint16_t bias_cur; /* Measured bias current in 2uA units */ + uint16_t rx_power; /* Measured RX Power */ + uint16_t tx_power; /* Measured TX Power */ +}; + +/* Module Monitoring Fields */ +struct sff_diags { + +#define MAX_CHANNEL_NUM 4 +#define LWARN 0 +#define HWARN 1 +#define LALRM 2 +#define HALRM 3 +#define MCURR 4 + + /* Supports DOM */ + uint8_t supports_dom; + /* Supports alarm/warning thold */ + uint8_t supports_alarms; + /* RX Power: 0 = OMA, 1 = Average power */ + uint8_t rx_power_type; + /* TX Power: 0 = Not supported, 1 = Average power */ + uint8_t tx_power_type; + + uint8_t calibrated_ext; /* Is externally calibrated */ + /* [5] tables are low/high warn, low/high alarm, current */ + /* SFP voltage in 0.1mV units */ + uint16_t sfp_voltage[5]; + /* SFP Temp in 16-bit signed 1/256 Celcius */ + int16_t sfp_temp[5]; + /* Measured bias current in 2uA units */ + uint16_t bias_cur[5]; + /* Measured TX Power */ + uint16_t tx_power[5]; + /* Measured RX Power */ + uint16_t rx_power[5]; + struct sff_channel_diags scd[MAX_CHANNEL_NUM]; +}; + +double convert_mw_to_dbm(double mw); +void sff_show_value_with_unit(const uint8_t *data, unsigned int reg, + const char *name, unsigned int mult, + const char *unit, struct rte_tel_data *d); +void sff_show_ascii(const uint8_t *data, unsigned int first_reg, + unsigned int last_reg, const char *name, struct rte_tel_data *d); +void sff_show_thresholds(struct sff_diags sd, struct rte_tel_data *d); + +void sff_8024_show_oui(const uint8_t *data, int id_offset, struct rte_tel_data *d); +void sff_8024_show_identifier(const uint8_t *data, int id_offset, struct rte_tel_data *d); +void sff_8024_show_connector(const uint8_t *data, int ctor_offset, struct rte_tel_data *d); +void sff_8024_show_encoding(const uint8_t *data, int encoding_offset, + int sff_type, struct rte_tel_data *d); + +#endif /* _SFF_COMMON_H_ */ -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v7 3/5] ethdev: format module EEPROM for SFF-8079 2022-05-24 6:24 ` [PATCH v7 0/5] add telemetry command for show module EEPROM Robin Zhang 2022-05-24 6:24 ` [PATCH v7 1/5] ethdev: add telemetry command for " Robin Zhang 2022-05-24 6:24 ` [PATCH v7 2/5] ethdev: common utilities for different SFF specs Robin Zhang @ 2022-05-24 6:24 ` Robin Zhang 2022-05-24 6:24 ` [PATCH v7 4/5] ethdev: format module EEPROM for SFF-8472 Robin Zhang ` (2 subsequent siblings) 5 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-05-24 6:24 UTC (permalink / raw) To: dev; +Cc: thomas, andrew.rybchenko, kevinx.liu, Robin Zhang This patch implements format module EEPROM information for SFF-8079 Rev 1.7 Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/ethdev_sff_telemetry.c | 3 + lib/ethdev/meson.build | 1 + lib/ethdev/sff_8079.c | 406 ++++++++++++++++++++++++++++++ 3 files changed, 410 insertions(+) create mode 100644 lib/ethdev/sff_8079.c diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c index f756b9643f..63b0d21786 100644 --- a/lib/ethdev/ethdev_sff_telemetry.c +++ b/lib/ethdev/ethdev_sff_telemetry.c @@ -70,6 +70,9 @@ sff_port_module_eeprom_parse(uint16_t port_id, struct rte_tel_data *d) switch (minfo.type) { /* parsing module EEPROM data base on different module type */ + case RTE_ETH_MODULE_SFF_8079: + sff_8079_show_all(einfo.data, d); + break; default: RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); break; diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index 8f39739e43..d94860da0c 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -13,6 +13,7 @@ sources = files( 'rte_tm.c', 'ethdev_sff_telemetry.c', 'sff_common.c', + 'sff_8079.c', ) headers = files( diff --git a/lib/ethdev/sff_8079.c b/lib/ethdev/sff_8079.c new file mode 100644 index 0000000000..cfa20bd3cb --- /dev/null +++ b/lib/ethdev/sff_8079.c @@ -0,0 +1,406 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8079 optics diagnostics. + * + */ + +#include <stdio.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "ethdev_sff_telemetry.h" + +static void sff_8079_show_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_identifier(data, 0, d); +} + +static void sff_8079_show_ext_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[1]); + if (data[1] == 0x00) + strlcat(val_string, " (GBIC not specified / not MOD_DEF compliant)", + sizeof(val_string)); + else if (data[1] == 0x04) + strlcat(val_string, " (GBIC/SFP defined by 2-wire interface ID)", + sizeof(val_string)); + else if (data[1] <= 0x07) { + char tmp[SFF_ITEM_VAL_COMPOSE_SIZE]; + snprintf(tmp, sizeof(tmp), " (GBIC compliant with MOD_DEF %u)", data[1]); + strlcat(val_string, tmp, sizeof(val_string)); + } else + strlcat(val_string, " (unknown)", sizeof(val_string)); + ssf_add_dict_string(d, "Extended identifier", val_string); +} + +static void sff_8079_show_connector(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_connector(data, 2, d); +} + +static void sff_8079_show_transceiver(const uint8_t *data, struct rte_tel_data *d) +{ + static const char *name = "Transceiver type"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), + "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[36]); + ssf_add_dict_string(d, "Transceiver codes", val_string); + + /* 10G Ethernet Compliance Codes */ + if (data[3] & (1 << 7)) + ssf_add_dict_string(d, "10G Ethernet transceiver type", + "10G Ethernet: 10G Base-ER [SFF-8472 rev10.4 onwards]"); + if (data[3] & (1 << 6)) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-LRM"); + if (data[3] & (1 << 5)) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-LR"); + if (data[3] & (1 << 4)) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-SR"); + + /* Infiniband Compliance Codes */ + if (data[3] & (1 << 3)) + ssf_add_dict_string(d, name, "Infiniband: 1X SX"); + if (data[3] & (1 << 2)) + ssf_add_dict_string(d, name, "Infiniband: 1X LX"); + if (data[3] & (1 << 1)) + ssf_add_dict_string(d, name, "Infiniband: 1X Copper Active"); + if (data[3] & (1 << 0)) + ssf_add_dict_string(d, name, "Infiniband: 1X Copper Passive"); + + /* ESCON Compliance Codes */ + if (data[4] & (1 << 7)) + ssf_add_dict_string(d, name, "ESCON: ESCON MMF, 1310nm LED"); + if (data[4] & (1 << 6)) + ssf_add_dict_string(d, name, "ESCON: ESCON SMF, 1310nm Laser"); + + /* SONET Compliance Codes */ + if (data[4] & (1 << 5)) + ssf_add_dict_string(d, name, "SONET: OC-192, short reach"); + if (data[4] & (1 << 4)) + ssf_add_dict_string(d, name, "SONET: SONET reach specifier bit 1"); + if (data[4] & (1 << 3)) + ssf_add_dict_string(d, name, "SONET: SONET reach specifier bit 2"); + if (data[4] & (1 << 2)) + ssf_add_dict_string(d, name, "SONET: OC-48, long reach"); + if (data[4] & (1 << 1)) + ssf_add_dict_string(d, name, "SONET: OC-48, intermediate reach"); + if (data[4] & (1 << 0)) + ssf_add_dict_string(d, name, "SONET: OC-48, short reach"); + if (data[5] & (1 << 6)) + ssf_add_dict_string(d, name, "SONET: OC-12, single mode, long reach"); + if (data[5] & (1 << 5)) + ssf_add_dict_string(d, name, "SONET: OC-12, single mode, inter. reach"); + if (data[5] & (1 << 4)) + ssf_add_dict_string(d, name, "SONET: OC-12, short reach"); + if (data[5] & (1 << 2)) + ssf_add_dict_string(d, name, "SONET: OC-3, single mode, long reach"); + if (data[5] & (1 << 1)) + ssf_add_dict_string(d, name, "SONET: OC-3, single mode, inter. reach"); + if (data[5] & (1 << 0)) + ssf_add_dict_string(d, name, "SONET: OC-3, short reach"); + + /* Ethernet Compliance Codes */ + if (data[6] & (1 << 7)) + ssf_add_dict_string(d, name, "Ethernet: BASE-PX"); + if (data[6] & (1 << 6)) + ssf_add_dict_string(d, name, "Ethernet: BASE-BX10"); + if (data[6] & (1 << 5)) + ssf_add_dict_string(d, name, "Ethernet: 100BASE-FX"); + if (data[6] & (1 << 4)) + ssf_add_dict_string(d, name, "Ethernet: 100BASE-LX/LX10"); + if (data[6] & (1 << 3)) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-T"); + if (data[6] & (1 << 2)) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-CX"); + if (data[6] & (1 << 1)) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-LX"); + if (data[6] & (1 << 0)) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-SX"); + + /* Fibre Channel link length */ + if (data[7] & (1 << 7)) + ssf_add_dict_string(d, name, "FC: very long distance (V)"); + if (data[7] & (1 << 6)) + ssf_add_dict_string(d, name, "FC: short distance (S)"); + if (data[7] & (1 << 5)) + ssf_add_dict_string(d, name, "FC: intermediate distance (I)"); + if (data[7] & (1 << 4)) + ssf_add_dict_string(d, name, "FC: long distance (L)"); + if (data[7] & (1 << 3)) + ssf_add_dict_string(d, name, "FC: medium distance (M)"); + + /* Fibre Channel transmitter technology */ + if (data[7] & (1 << 2)) + ssf_add_dict_string(d, name, "FC: Shortwave laser, linear Rx (SA)"); + if (data[7] & (1 << 1)) + ssf_add_dict_string(d, name, "FC: Longwave laser (LC)"); + if (data[7] & (1 << 0)) + ssf_add_dict_string(d, name, "FC: Electrical inter-enclosure (EL)"); + if (data[8] & (1 << 7)) + ssf_add_dict_string(d, name, "FC: Electrical intra-enclosure (EL)"); + if (data[8] & (1 << 6)) + ssf_add_dict_string(d, name, "FC: Shortwave laser w/o OFC (SN)"); + if (data[8] & (1 << 5)) + ssf_add_dict_string(d, name, "FC: Shortwave laser with OFC (SL)"); + if (data[8] & (1 << 4)) + ssf_add_dict_string(d, name, "FC: Longwave laser (LL)"); + if (data[8] & (1 << 3)) + ssf_add_dict_string(d, name, "Active Cable"); + if (data[8] & (1 << 2)) + ssf_add_dict_string(d, name, "Passive Cable"); + if (data[8] & (1 << 1)) + ssf_add_dict_string(d, name, "FC: Copper FC-BaseT"); + + /* Fibre Channel transmission media */ + if (data[9] & (1 << 7)) + ssf_add_dict_string(d, name, "FC: Twin Axial Pair (TW)"); + if (data[9] & (1 << 6)) + ssf_add_dict_string(d, name, "FC: Twisted Pair (TP)"); + if (data[9] & (1 << 5)) + ssf_add_dict_string(d, name, "FC: Miniature Coax (MI)"); + if (data[9] & (1 << 4)) + ssf_add_dict_string(d, name, "FC: Video Coax (TV)"); + if (data[9] & (1 << 3)) + ssf_add_dict_string(d, name, "FC: Multimode, 62.5um (M6)"); + if (data[9] & (1 << 2)) + ssf_add_dict_string(d, name, "FC: Multimode, 50um (M5)"); + if (data[9] & (1 << 0)) + ssf_add_dict_string(d, name, "FC: Single Mode (SM)"); + + /* Fibre Channel speed */ + if (data[10] & (1 << 7)) + ssf_add_dict_string(d, name, "FC: 1200 MBytes/sec"); + if (data[10] & (1 << 6)) + ssf_add_dict_string(d, name, "FC: 800 MBytes/sec"); + if (data[10] & (1 << 4)) + ssf_add_dict_string(d, name, "FC: 400 MBytes/sec"); + if (data[10] & (1 << 2)) + ssf_add_dict_string(d, name, "FC: 200 MBytes/sec"); + if (data[10] & (1 << 0)) + ssf_add_dict_string(d, name, "FC: 100 MBytes/sec"); + + /* Extended Specification Compliance Codes from SFF-8024 */ + switch (data[36]) { + case 0x1: + ssf_add_dict_string(d, name, + "Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)"); + break; + case 0x2: + ssf_add_dict_string(d, name, "Extended: 100G Base-SR4 or 25GBase-SR"); + break; + case 0x3: + ssf_add_dict_string(d, name, "Extended: 100G Base-LR4 or 25GBase-LR"); + break; + case 0x4: + ssf_add_dict_string(d, name, "Extended: 100G Base-ER4 or 25GBase-ER"); + break; + case 0x8: + ssf_add_dict_string(d, name, + "Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)"); + break; + case 0xb: + ssf_add_dict_string(d, name, "Extended: 100G Base-CR4 or 25G Base-CR CA-L"); + break; + case 0xc: + ssf_add_dict_string(d, name, "Extended: 25G Base-CR CA-S"); + break; + case 0xd: + ssf_add_dict_string(d, name, "Extended: 25G Base-CR CA-N"); + break; + case 0x16: + ssf_add_dict_string(d, name, "Extended: 10Gbase-T with SFI electrical interface"); + break; + case 0x18: + ssf_add_dict_string(d, name, + "Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)"); + break; + case 0x19: + ssf_add_dict_string(d, name, + "Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)"); + break; + case 0x1c: + ssf_add_dict_string(d, name, "Extended: 10Gbase-T Short Reach"); + break; + default: + break; + } +} + +static void sff_8079_show_encoding(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_encoding(data, 11, RTE_ETH_MODULE_SFF_8472, d); +} + +static void sff_8079_show_rate_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[13]); + + switch (data[13]) { + case 0x00: + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case 0x01: + strlcat(val_string, " (4/2/1G Rate_Select & AS0/AS1)", sizeof(val_string)); + break; + case 0x02: + strlcat(val_string, " (8/4/2G Rx Rate_Select only)", sizeof(val_string)); + break; + case 0x03: + strlcat(val_string, " (8/4/2G Independent Rx & Tx Rate_Select)", + sizeof(val_string)); + break; + case 0x04: + strlcat(val_string, " (8/4/2G Tx Rate_Select only)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + ssf_add_dict_string(d, "Rate identifier", val_string); +} + +static void sff_8079_show_oui(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_oui(data, 37, d); +} + +static void +sff_8079_show_wavelength_or_copper_compliance(const uint8_t *data, + struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + if (data[8] & (1 << 2)) { + snprintf(val_string, sizeof(val_string), "0x%02x", data[60]); + switch (data[60]) { + case 0x00: + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case 0x01: + strlcat(val_string, " (SFF-8431 appendix E)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (unknown)", sizeof(val_string)); + break; + } + strlcat(val_string, " [SFF-8472 rev10.4 only]", sizeof(val_string)); + ssf_add_dict_string(d, "Passive Cu cmplnce.", val_string); + } else if (data[8] & (1 << 3)) { + snprintf(val_string, sizeof(val_string), "0x%02x", data[60]); + switch (data[60]) { + case 0x00: + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case 0x01: + strlcat(val_string, " (SFF-8431 appendix E)", sizeof(val_string)); + break; + case 0x04: + strlcat(val_string, " (SFF-8431 limiting)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (unknown)", sizeof(val_string)); + break; + } + strlcat(val_string, " [SFF-8472 rev10.4 only]", sizeof(val_string)); + ssf_add_dict_string(d, "Active Cu cmplnce.", val_string); + } else { + snprintf(val_string, sizeof(val_string), "%unm", (data[60] << 8) | data[61]); + ssf_add_dict_string(d, "Laser wavelength", val_string); + } +} + +static void sff_8079_show_options(const uint8_t *data, struct rte_tel_data *d) +{ + static const char *name = "Option"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x 0x%02x", data[64], data[65]); + ssf_add_dict_string(d, "Option values", val_string); + + if (data[65] & (1 << 1)) + ssf_add_dict_string(d, name, "RX_LOS implemented"); + if (data[65] & (1 << 2)) + ssf_add_dict_string(d, name, "RX_LOS implemented, inverted"); + if (data[65] & (1 << 3)) + ssf_add_dict_string(d, name, "TX_FAULT implemented"); + if (data[65] & (1 << 4)) + ssf_add_dict_string(d, name, "TX_DISABLE implemented"); + if (data[65] & (1 << 5)) + ssf_add_dict_string(d, name, "RATE_SELECT implemented"); + if (data[65] & (1 << 6)) + ssf_add_dict_string(d, name, "Tunable transmitter technology"); + if (data[65] & (1 << 7)) + ssf_add_dict_string(d, name, "Receiver decision threshold implemented"); + if (data[64] & (1 << 0)) + ssf_add_dict_string(d, name, "Linear receiver output implemented"); + if (data[64] & (1 << 1)) + ssf_add_dict_string(d, name, "Power level 2 requirement"); + if (data[64] & (1 << 2)) + ssf_add_dict_string(d, name, "Cooled transceiver implemented"); + if (data[64] & (1 << 3)) + ssf_add_dict_string(d, name, "Retimer or CDR implemented"); + if (data[64] & (1 << 4)) + ssf_add_dict_string(d, name, "Paging implemented"); + if (data[64] & (1 << 5)) + ssf_add_dict_string(d, name, "Power level 3 requirement"); +} + +void sff_8079_show_all(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8079_show_identifier(data, d); + if (((data[0] == 0x02) || (data[0] == 0x03)) && (data[1] == 0x04)) { + unsigned int br_nom, br_min, br_max; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + if (data[12] == 0) { + br_nom = br_min = br_max = 0; + } else if (data[12] == 255) { + br_nom = data[66] * 250; + br_max = data[67]; + br_min = data[67]; + } else { + br_nom = data[12] * 100; + br_max = data[66]; + br_min = data[67]; + } + sff_8079_show_ext_identifier(data, d); + sff_8079_show_connector(data, d); + sff_8079_show_transceiver(data, d); + sff_8079_show_encoding(data, d); + + snprintf(val_string, sizeof(val_string), "%uMBd", br_nom); + ssf_add_dict_string(d, "BR, Nominal", val_string); + + sff_8079_show_rate_identifier(data, d); + sff_show_value_with_unit(data, 14, + "Length (SMF,km)", 1, "km", d); + sff_show_value_with_unit(data, 15, "Length (SMF)", 100, "m", d); + sff_show_value_with_unit(data, 16, "Length (50um)", 10, "m", d); + sff_show_value_with_unit(data, 17, + "Length (62.5um)", 10, "m", d); + sff_show_value_with_unit(data, 18, "Length (Copper)", 1, "m", d); + sff_show_value_with_unit(data, 19, "Length (OM3)", 10, "m", d); + sff_8079_show_wavelength_or_copper_compliance(data, d); + sff_show_ascii(data, 20, 35, "Vendor name", d); + sff_8079_show_oui(data, d); + sff_show_ascii(data, 40, 55, "Vendor PN", d); + sff_show_ascii(data, 56, 59, "Vendor rev", d); + sff_8079_show_options(data, d); + + snprintf(val_string, sizeof(val_string), "%u%%", br_max); + ssf_add_dict_string(d, "BR margin, max", val_string); + snprintf(val_string, sizeof(val_string), "%u%%", br_min); + ssf_add_dict_string(d, "BR margin, min", val_string); + + sff_show_ascii(data, 68, 83, "Vendor SN", d); + sff_show_ascii(data, 84, 91, "Date code", d); + } +} -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v7 4/5] ethdev: format module EEPROM for SFF-8472 2022-05-24 6:24 ` [PATCH v7 0/5] add telemetry command for show module EEPROM Robin Zhang ` (2 preceding siblings ...) 2022-05-24 6:24 ` [PATCH v7 3/5] ethdev: format module EEPROM for SFF-8079 Robin Zhang @ 2022-05-24 6:24 ` Robin Zhang 2022-05-24 6:24 ` [PATCH v7 5/5] ethdev: format module EEPROM for SFF-8636 Robin Zhang 2022-05-25 3:14 ` [PATCH v8 0/5] add telemetry command for show module EEPROM Robin Zhang 5 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-05-24 6:24 UTC (permalink / raw) To: dev; +Cc: thomas, andrew.rybchenko, kevinx.liu, Robin Zhang This patch implements format module EEPROM information for SFF-8472 Rev 12.0 Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/ethdev_sff_telemetry.c | 4 + lib/ethdev/meson.build | 1 + lib/ethdev/sff_8472.c | 286 ++++++++++++++++++++++++++++++ 3 files changed, 291 insertions(+) create mode 100644 lib/ethdev/sff_8472.c diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c index 63b0d21786..c3b13b1cb1 100644 --- a/lib/ethdev/ethdev_sff_telemetry.c +++ b/lib/ethdev/ethdev_sff_telemetry.c @@ -73,6 +73,10 @@ sff_port_module_eeprom_parse(uint16_t port_id, struct rte_tel_data *d) case RTE_ETH_MODULE_SFF_8079: sff_8079_show_all(einfo.data, d); break; + case RTE_ETH_MODULE_SFF_8472: + sff_8079_show_all(einfo.data, d); + sff_8472_show_all(einfo.data, d); + break; default: RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); break; diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index d94860da0c..4d81a35c09 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -14,6 +14,7 @@ sources = files( 'ethdev_sff_telemetry.c', 'sff_common.c', 'sff_8079.c', + 'sff_8472.c', ) headers = files( diff --git a/lib/ethdev/sff_8472.c b/lib/ethdev/sff_8472.c new file mode 100644 index 0000000000..98e31e9262 --- /dev/null +++ b/lib/ethdev/sff_8472.c @@ -0,0 +1,286 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8472 optics diagnostics. + * + */ + +#include <stdio.h> +#include <math.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "ethdev_sff_telemetry.h" + +/* Offsets in decimal, for direct comparison with the SFF specs */ + +/* A0-based EEPROM offsets for DOM support checks */ +#define SFF_A0_DOM 92 +#define SFF_A0_OPTIONS 93 +#define SFF_A0_COMP 94 + +/* EEPROM bit values for various registers */ +#define SFF_A0_DOM_EXTCAL (1 << 4) +#define SFF_A0_DOM_INTCAL (1 << 5) +#define SFF_A0_DOM_IMPL (1 << 6) +#define SFF_A0_DOM_PWRT (1 << 3) + +#define SFF_A0_OPTIONS_AW (1 << 7) + +/* + * This is the offset at which the A2 page is in the EEPROM + * blob returned by the kernel. + */ +#define SFF_A2_BASE 0x100 + +/* A2-based offsets for DOM */ +#define SFF_A2_TEMP 96 +#define SFF_A2_TEMP_HALRM 0 +#define SFF_A2_TEMP_LALRM 2 +#define SFF_A2_TEMP_HWARN 4 +#define SFF_A2_TEMP_LWARN 6 + +#define SFF_A2_VCC 98 +#define SFF_A2_VCC_HALRM 8 +#define SFF_A2_VCC_LALRM 10 +#define SFF_A2_VCC_HWARN 12 +#define SFF_A2_VCC_LWARN 14 + +#define SFF_A2_BIAS 100 +#define SFF_A2_BIAS_HALRM 16 +#define SFF_A2_BIAS_LALRM 18 +#define SFF_A2_BIAS_HWARN 20 +#define SFF_A2_BIAS_LWARN 22 + +#define SFF_A2_TX_PWR 102 +#define SFF_A2_TX_PWR_HALRM 24 +#define SFF_A2_TX_PWR_LALRM 26 +#define SFF_A2_TX_PWR_HWARN 28 +#define SFF_A2_TX_PWR_LWARN 30 + +#define SFF_A2_RX_PWR 104 +#define SFF_A2_RX_PWR_HALRM 32 +#define SFF_A2_RX_PWR_LALRM 34 +#define SFF_A2_RX_PWR_HWARN 36 +#define SFF_A2_RX_PWR_LWARN 38 + +#define SFF_A2_ALRM_FLG 112 +#define SFF_A2_WARN_FLG 116 + +/* 32-bit little-endian calibration constants */ +#define SFF_A2_CAL_RXPWR4 56 +#define SFF_A2_CAL_RXPWR3 60 +#define SFF_A2_CAL_RXPWR2 64 +#define SFF_A2_CAL_RXPWR1 68 +#define SFF_A2_CAL_RXPWR0 72 + +/* 16-bit little endian calibration constants */ +#define SFF_A2_CAL_TXI_SLP 76 +#define SFF_A2_CAL_TXI_OFF 78 +#define SFF_A2_CAL_TXPWR_SLP 80 +#define SFF_A2_CAL_TXPWR_OFF 82 +#define SFF_A2_CAL_T_SLP 84 +#define SFF_A2_CAL_T_OFF 86 +#define SFF_A2_CAL_V_SLP 88 +#define SFF_A2_CAL_V_OFF 90 + +static struct sff_8472_aw_flags { + const char *str; /* Human-readable string, null at the end */ + int offset; /* A2-relative address offset */ + uint8_t value; /* Alarm is on if (offset & value) != 0. */ +} sff_8472_aw_flags[] = { + { "Laser bias current high alarm", SFF_A2_ALRM_FLG, (1 << 3) }, + { "Laser bias current low alarm", SFF_A2_ALRM_FLG, (1 << 2) }, + { "Laser bias current high warning", SFF_A2_WARN_FLG, (1 << 3) }, + { "Laser bias current low warning", SFF_A2_WARN_FLG, (1 << 2) }, + + { "Laser output power high alarm", SFF_A2_ALRM_FLG, (1 << 1) }, + { "Laser output power low alarm", SFF_A2_ALRM_FLG, (1 << 0) }, + { "Laser output power high warning", SFF_A2_WARN_FLG, (1 << 1) }, + { "Laser output power low warning", SFF_A2_WARN_FLG, (1 << 0) }, + + { "Module temperature high alarm", SFF_A2_ALRM_FLG, (1 << 7) }, + { "Module temperature low alarm", SFF_A2_ALRM_FLG, (1 << 6) }, + { "Module temperature high warning", SFF_A2_WARN_FLG, (1 << 7) }, + { "Module temperature low warning", SFF_A2_WARN_FLG, (1 << 6) }, + + { "Module voltage high alarm", SFF_A2_ALRM_FLG, (1 << 5) }, + { "Module voltage low alarm", SFF_A2_ALRM_FLG, (1 << 4) }, + { "Module voltage high warning", SFF_A2_WARN_FLG, (1 << 5) }, + { "Module voltage low warning", SFF_A2_WARN_FLG, (1 << 4) }, + + { "Laser rx power high alarm", SFF_A2_ALRM_FLG + 1, (1 << 7) }, + { "Laser rx power low alarm", SFF_A2_ALRM_FLG + 1, (1 << 6) }, + { "Laser rx power high warning", SFF_A2_WARN_FLG + 1, (1 << 7) }, + { "Laser rx power low warning", SFF_A2_WARN_FLG + 1, (1 << 6) }, + + { NULL, 0, 0 }, +}; + +/* Most common case: 16-bit unsigned integer in a certain unit */ +#define A2_OFFSET_TO_U16(offset) \ + (data[SFF_A2_BASE + (offset)] << 8 | data[SFF_A2_BASE + (offset) + 1]) + +/* Calibration slope is a number between 0.0 included and 256.0 excluded. */ +#define A2_OFFSET_TO_SLP(offset) \ + (data[SFF_A2_BASE + (offset)] + data[SFF_A2_BASE + (offset) + 1] / 256.) + +/* Calibration offset is an integer from -32768 to 32767 */ +#define A2_OFFSET_TO_OFF(offset) \ + ((int16_t)A2_OFFSET_TO_U16(offset)) + +/* RXPWR(x) are IEEE-754 floating point numbers in big-endian format */ +#define A2_OFFSET_TO_RXPWRx(offset) \ + (befloattoh((const uint32_t *)(data + SFF_A2_BASE + (offset)))) + +/* + * 2-byte internal temperature conversions: + * First byte is a signed 8-bit integer, which is the temp decimal part + * Second byte are 1/256th of degree, which are added to the dec part. + */ +#define A2_OFFSET_TO_TEMP(offset) ((int16_t)A2_OFFSET_TO_U16(offset)) + +static void sff_8472_dom_parse(const uint8_t *data, struct sff_diags *sd) +{ + sd->bias_cur[MCURR] = A2_OFFSET_TO_U16(SFF_A2_BIAS); + sd->bias_cur[HALRM] = A2_OFFSET_TO_U16(SFF_A2_BIAS_HALRM); + sd->bias_cur[LALRM] = A2_OFFSET_TO_U16(SFF_A2_BIAS_LALRM); + sd->bias_cur[HWARN] = A2_OFFSET_TO_U16(SFF_A2_BIAS_HWARN); + sd->bias_cur[LWARN] = A2_OFFSET_TO_U16(SFF_A2_BIAS_LWARN); + + sd->sfp_voltage[MCURR] = A2_OFFSET_TO_U16(SFF_A2_VCC); + sd->sfp_voltage[HALRM] = A2_OFFSET_TO_U16(SFF_A2_VCC_HALRM); + sd->sfp_voltage[LALRM] = A2_OFFSET_TO_U16(SFF_A2_VCC_LALRM); + sd->sfp_voltage[HWARN] = A2_OFFSET_TO_U16(SFF_A2_VCC_HWARN); + sd->sfp_voltage[LWARN] = A2_OFFSET_TO_U16(SFF_A2_VCC_LWARN); + + sd->tx_power[MCURR] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR); + sd->tx_power[HALRM] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_HALRM); + sd->tx_power[LALRM] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_LALRM); + sd->tx_power[HWARN] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_HWARN); + sd->tx_power[LWARN] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_LWARN); + + sd->rx_power[MCURR] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR); + sd->rx_power[HALRM] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_HALRM); + sd->rx_power[LALRM] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_LALRM); + sd->rx_power[HWARN] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_HWARN); + sd->rx_power[LWARN] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_LWARN); + + sd->sfp_temp[MCURR] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP); + sd->sfp_temp[HALRM] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_HALRM); + sd->sfp_temp[LALRM] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_LALRM); + sd->sfp_temp[HWARN] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_HWARN); + sd->sfp_temp[LWARN] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_LWARN); +} + +/* Converts to a float from a big-endian 4-byte source buffer. */ +static float befloattoh(const uint32_t *source) +{ + union { + uint32_t src; + float dst; + } converter; + + converter.src = ntohl(*source); + return converter.dst; +} + +static void sff_8472_calibration(const uint8_t *data, struct sff_diags *sd) +{ + unsigned long i; + uint16_t rx_reading; + + /* Calibration should occur for all values (threshold and current) */ + for (i = 0; i < RTE_DIM(sd->bias_cur); ++i) { + /* + * Apply calibration formula 1 (Temp., Voltage, Bias, Tx Power) + */ + sd->bias_cur[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_TXI_SLP); + sd->tx_power[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_TXPWR_SLP); + sd->sfp_voltage[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_V_SLP); + sd->sfp_temp[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_T_SLP); + + sd->bias_cur[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_TXI_OFF); + sd->tx_power[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_TXPWR_OFF); + sd->sfp_voltage[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_V_OFF); + sd->sfp_temp[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_T_OFF); + + /* + * Apply calibration formula 2 (Rx Power only) + */ + rx_reading = sd->rx_power[i]; + sd->rx_power[i] = A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR0); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR1); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR2); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR3); + } +} + +static void sff_8472_parse_eeprom(const uint8_t *data, struct sff_diags *sd) +{ + sd->supports_dom = data[SFF_A0_DOM] & SFF_A0_DOM_IMPL; + sd->supports_alarms = data[SFF_A0_OPTIONS] & SFF_A0_OPTIONS_AW; + sd->calibrated_ext = data[SFF_A0_DOM] & SFF_A0_DOM_EXTCAL; + sd->rx_power_type = data[SFF_A0_DOM] & SFF_A0_DOM_PWRT; + + sff_8472_dom_parse(data, sd); + + /* + * If the SFP is externally calibrated, we need to read calibration data + * and compensate the already stored readings. + */ + if (sd->calibrated_ext) + sff_8472_calibration(data, sd); +} + +void sff_8472_show_all(const uint8_t *data, struct rte_tel_data *d) +{ + struct sff_diags sd = {0}; + const char *rx_power_string = NULL; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + int i; + + sff_8472_parse_eeprom(data, &sd); + + if (!sd.supports_dom) { + ssf_add_dict_string(d, "Optical diagnostics support", "No"); + return; + } + ssf_add_dict_string(d, "Optical diagnostics support", "Yes"); + + SPRINT_BIAS(val_string, sd.bias_cur[MCURR]); + ssf_add_dict_string(d, "Laser bias current", val_string); + + SPRINT_xX_PWR(val_string, sd.tx_power[MCURR]); + ssf_add_dict_string(d, "Laser output power", val_string); + + if (!sd.rx_power_type) + rx_power_string = "Receiver signal OMA"; + else + rx_power_string = "Receiver signal average optical power"; + + SPRINT_xX_PWR(val_string, sd.rx_power[MCURR]); + ssf_add_dict_string(d, rx_power_string, val_string); + + SPRINT_TEMP(val_string, sd.sfp_temp[MCURR]); + ssf_add_dict_string(d, "Module temperature", val_string); + + SPRINT_VCC(val_string, sd.sfp_voltage[MCURR]); + ssf_add_dict_string(d, "Module voltage", val_string); + + ssf_add_dict_string(d, "Alarm/warning flags implemented", + (sd.supports_alarms ? "Yes" : "No")); + + if (sd.supports_alarms) { + for (i = 0; sff_8472_aw_flags[i].str; ++i) { + ssf_add_dict_string(d, sff_8472_aw_flags[i].str, + data[SFF_A2_BASE + sff_8472_aw_flags[i].offset] + & sff_8472_aw_flags[i].value ? "On" : "Off"); + } + sff_show_thresholds(sd, d); + } +} -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v7 5/5] ethdev: format module EEPROM for SFF-8636 2022-05-24 6:24 ` [PATCH v7 0/5] add telemetry command for show module EEPROM Robin Zhang ` (3 preceding siblings ...) 2022-05-24 6:24 ` [PATCH v7 4/5] ethdev: format module EEPROM for SFF-8472 Robin Zhang @ 2022-05-24 6:24 ` Robin Zhang 2022-05-24 9:03 ` David Marchand 2022-05-25 3:14 ` [PATCH v8 0/5] add telemetry command for show module EEPROM Robin Zhang 5 siblings, 1 reply; 77+ messages in thread From: Robin Zhang @ 2022-05-24 6:24 UTC (permalink / raw) To: dev; +Cc: thomas, andrew.rybchenko, kevinx.liu, Robin Zhang This patch implements format module EEPROM information for SFF-8636 Rev 2.7 Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/ethdev_sff_telemetry.c | 4 + lib/ethdev/meson.build | 1 + lib/ethdev/sff_8636.c | 775 ++++++++++++++++++++++++++++++ lib/ethdev/sff_8636.h | 592 +++++++++++++++++++++++ 4 files changed, 1372 insertions(+) create mode 100644 lib/ethdev/sff_8636.c create mode 100644 lib/ethdev/sff_8636.h diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c index c3b13b1cb1..b7d14219ef 100644 --- a/lib/ethdev/ethdev_sff_telemetry.c +++ b/lib/ethdev/ethdev_sff_telemetry.c @@ -77,6 +77,10 @@ sff_port_module_eeprom_parse(uint16_t port_id, struct rte_tel_data *d) sff_8079_show_all(einfo.data, d); sff_8472_show_all(einfo.data, d); break; + case RTE_ETH_MODULE_SFF_8436: + case RTE_ETH_MODULE_SFF_8636: + sff_8636_show_all(einfo.data, einfo.length, d); + break; default: RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); break; diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index 4d81a35c09..88ceeb12b9 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -15,6 +15,7 @@ sources = files( 'sff_common.c', 'sff_8079.c', 'sff_8472.c', + 'sff_8636.c', ) headers = files( diff --git a/lib/ethdev/sff_8636.c b/lib/ethdev/sff_8636.c new file mode 100644 index 0000000000..93ef8bde2b --- /dev/null +++ b/lib/ethdev/sff_8636.c @@ -0,0 +1,775 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8636 based QSFP+/QSFP28 Diagnostics Memory map. + * + */ + +#include <stdio.h> +#include <math.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "sff_8636.h" +#include "ethdev_sff_telemetry.h" + +#define MAX_DESC_SIZE 42 + +static struct sff_8636_aw_flags { + const char *str; /* Human-readable string, null at the end */ + int offset; /* A2-relative address offset */ + uint8_t value; /* Alarm is on if (offset & value) != 0. */ +} sff_8636_aw_flags[] = { + { "Laser bias current high alarm (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_HALARM) }, + { "Laser bias current low alarm (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_LALARM) }, + { "Laser bias current high warning (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_HWARN) }, + { "Laser bias current low warning (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_LWARN) }, + + { "Laser bias current high alarm (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_HALARM) }, + { "Laser bias current low alarm (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_LALARM) }, + { "Laser bias current high warning (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_HWARN) }, + { "Laser bias current low warning (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_LWARN) }, + + { "Laser bias current high alarm (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_HALARM) }, + { "Laser bias current low alarm (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_LALARM) }, + { "Laser bias current high warning (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_HWARN) }, + { "Laser bias current low warning (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_LWARN) }, + + { "Laser bias current high alarm (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_HALARM) }, + { "Laser bias current low alarm (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_LALARM) }, + { "Laser bias current high warning (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_HWARN) }, + { "Laser bias current low warning (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_LWARN) }, + + { "Module temperature high alarm", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_HALARM_STATUS) }, + { "Module temperature low alarm", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_LALARM_STATUS) }, + { "Module temperature high warning", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_HWARN_STATUS) }, + { "Module temperature low warning", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_LWARN_STATUS) }, + + { "Module voltage high alarm", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_HALARM_STATUS) }, + { "Module voltage low alarm", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_LALARM_STATUS) }, + { "Module voltage high warning", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_HWARN_STATUS) }, + { "Module voltage low warning", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_LWARN_STATUS) }, + + { "Laser tx power high alarm (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_HALARM) }, + { "Laser tx power low alarm (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_LALARM) }, + { "Laser tx power high warning (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_HWARN) }, + { "Laser tx power low warning (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_LWARN) }, + + { "Laser tx power high alarm (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_HALARM) }, + { "Laser tx power low alarm (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_LALARM) }, + { "Laser tx power high warning (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_HWARN) }, + { "Laser tx power low warning (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_LWARN) }, + + { "Laser tx power high alarm (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_HALARM) }, + { "Laser tx power low alarm (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_LALARM) }, + { "Laser tx power high warning (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_HWARN) }, + { "Laser tx power low warning (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_LWARN) }, + + { "Laser tx power high alarm (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_HALARM) }, + { "Laser tx power low alarm (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_LALARM) }, + { "Laser tx power high warning (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_HWARN) }, + { "Laser tx power low warning (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_LWARN) }, + + { "Laser rx power high alarm (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_HALARM) }, + { "Laser rx power low alarm (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_LALARM) }, + { "Laser rx power high warning (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_HWARN) }, + { "Laser rx power low warning (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_LWARN) }, + + { "Laser rx power high alarm (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_HALARM) }, + { "Laser rx power low alarm (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_LALARM) }, + { "Laser rx power high warning (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_HWARN) }, + { "Laser rx power low warning (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_LWARN) }, + + { "Laser rx power high alarm (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_HALARM) }, + { "Laser rx power low alarm (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_LALARM) }, + { "Laser rx power high warning (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_HWARN) }, + { "Laser rx power low warning (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_LWARN) }, + + { "Laser rx power high alarm (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_HALARM) }, + { "Laser rx power low alarm (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_LALARM) }, + { "Laser rx power high warning (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_HWARN) }, + { "Laser rx power low warning (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_LWARN) }, + + { NULL, 0, 0 }, +}; + +static void sff_8636_show_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_identifier(data, SFF_8636_ID_OFFSET, d); +} + +static void sff_8636_show_ext_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + static const char *name = "Extended identifier description"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + snprintf(val_string, sizeof(val_string), "0x%02x", data[SFF_8636_EXT_ID_OFFSET]); + ssf_add_dict_string(d, "Extended identifier", val_string); + + switch (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_PWR_CLASS_MASK) { + case SFF_8636_EXT_ID_PWR_CLASS_1: + ssf_add_dict_string(d, name, "1.5W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_2: + ssf_add_dict_string(d, name, "2.0W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_3: + ssf_add_dict_string(d, name, "2.5W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_4: + ssf_add_dict_string(d, name, "3.5W max. Power consumption"); + break; + } + + if (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_CDR_TX_MASK) + ssf_add_dict_string(d, name, "CDR present in TX"); + else + ssf_add_dict_string(d, name, "No CDR in TX"); + + if (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_CDR_RX_MASK) + ssf_add_dict_string(d, name, "CDR present in RX"); + else + ssf_add_dict_string(d, name, "No CDR in RX"); + + switch (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_EPWR_CLASS_MASK) { + case SFF_8636_EXT_ID_PWR_CLASS_LEGACY: + snprintf(val_string, sizeof(val_string), "%s", ""); + break; + case SFF_8636_EXT_ID_PWR_CLASS_5: + snprintf(val_string, sizeof(val_string), "%s", "4.0W max. Power consumption, "); + break; + case SFF_8636_EXT_ID_PWR_CLASS_6: + snprintf(val_string, sizeof(val_string), "%s", "4.5W max. Power consumption, "); + break; + case SFF_8636_EXT_ID_PWR_CLASS_7: + snprintf(val_string, sizeof(val_string), "%s", "5.0W max. Power consumption, "); + break; + } + + if (data[SFF_8636_PWR_MODE_OFFSET] & SFF_8636_HIGH_PWR_ENABLE) + strlcat(val_string, "High Power Class (> 3.5 W) enabled", sizeof(val_string)); + else + strlcat(val_string, "High Power Class (> 3.5 W) not enabled", sizeof(val_string)); + + ssf_add_dict_string(d, name, val_string); +} + +static void sff_8636_show_connector(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_connector(data, SFF_8636_CTOR_OFFSET, d); +} + +static void sff_8636_show_transceiver(const uint8_t *data, struct rte_tel_data *d) +{ + static const char *name = "Transceiver type"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + data[SFF_8636_ETHERNET_COMP_OFFSET], + data[SFF_8636_SONET_COMP_OFFSET], + data[SFF_8636_SAS_COMP_OFFSET], + data[SFF_8636_GIGE_COMP_OFFSET], + data[SFF_8636_FC_LEN_OFFSET], + data[SFF_8636_FC_TECH_OFFSET], + data[SFF_8636_FC_TRANS_MEDIA_OFFSET], + data[SFF_8636_FC_SPEED_OFFSET]); + ssf_add_dict_string(d, "Transceiver codes", val_string); + + /* 10G/40G Ethernet Compliance Codes */ + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_LRM) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-LRM"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_LR) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-LR"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_SR) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-SR"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_CR4) + ssf_add_dict_string(d, name, "40G Ethernet: 40G Base-CR4"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_SR4) + ssf_add_dict_string(d, name, "40G Ethernet: 40G Base-SR4"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_LR4) + ssf_add_dict_string(d, name, "40G Ethernet: 40G Base-LR4"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_ACTIVE) + ssf_add_dict_string(d, name, "40G Ethernet: 40G Active Cable (XLPPI)"); + + /* Extended Specification Compliance Codes from SFF-8024 */ + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_RSRVD) { + switch (data[SFF_8636_OPTION_1_OFFSET]) { + case SFF_8636_ETHERNET_UNSPECIFIED: + ssf_add_dict_string(d, name, "(reserved or unknown)"); + break; + case SFF_8636_ETHERNET_100G_AOC: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)"); + break; + case SFF_8636_ETHERNET_100G_SR4: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G Base-SR4 or 25GBase-SR"); + break; + case SFF_8636_ETHERNET_100G_LR4: + ssf_add_dict_string(d, name, "100G Ethernet: 100G Base-LR4"); + break; + case SFF_8636_ETHERNET_100G_ER4: + ssf_add_dict_string(d, name, "100G Ethernet: 100G Base-ER4"); + break; + case SFF_8636_ETHERNET_100G_SR10: + ssf_add_dict_string(d, name, "100G Ethernet: 100G Base-SR10"); + break; + case SFF_8636_ETHERNET_100G_CWDM4_FEC: + ssf_add_dict_string(d, name, "100G Ethernet: 100G CWDM4 MSA with FEC"); + break; + case SFF_8636_ETHERNET_100G_PSM4: + ssf_add_dict_string(d, name, "100G Ethernet: 100G PSM4 Parallel SMF"); + break; + case SFF_8636_ETHERNET_100G_ACC: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)"); + break; + case SFF_8636_ETHERNET_100G_CWDM4_NO_FEC: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G CWDM4 MSA without FEC"); + break; + case SFF_8636_ETHERNET_100G_RSVD1: + ssf_add_dict_string(d, name, "(reserved or unknown)"); + break; + case SFF_8636_ETHERNET_100G_CR4: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G Base-CR4 or 25G Base-CR CA-L"); + break; + case SFF_8636_ETHERNET_25G_CR_CA_S: + ssf_add_dict_string(d, name, "25G Ethernet: 25G Base-CR CA-S"); + break; + case SFF_8636_ETHERNET_25G_CR_CA_N: + ssf_add_dict_string(d, name, "25G Ethernet: 25G Base-CR CA-N"); + break; + case SFF_8636_ETHERNET_40G_ER4: + ssf_add_dict_string(d, name, "40G Ethernet: 40G Base-ER4"); + break; + case SFF_8636_ETHERNET_4X10_SR: + ssf_add_dict_string(d, name, "4x10G Ethernet: 10G Base-SR"); + break; + case SFF_8636_ETHERNET_40G_PSM4: + ssf_add_dict_string(d, name, "40G Ethernet: 40G PSM4 Parallel SMF"); + break; + case SFF_8636_ETHERNET_G959_P1I1_2D1: + ssf_add_dict_string(d, name, + "Ethernet: G959.1 profile P1I1-2D1 (10709 MBd, 2km, 1310nm SM)"); + break; + case SFF_8636_ETHERNET_G959_P1S1_2D2: + ssf_add_dict_string(d, name, + "Ethernet: G959.1 profile P1S1-2D2 (10709 MBd, 40km, 1550nm SM)"); + break; + case SFF_8636_ETHERNET_G959_P1L1_2D2: + ssf_add_dict_string(d, name, + "Ethernet: G959.1 profile P1L1-2D2 (10709 MBd, 80km, 1550nm SM)"); + break; + case SFF_8636_ETHERNET_10GT_SFI: + ssf_add_dict_string(d, name, + "10G Ethernet: 10G Base-T with SFI electrical interface"); + break; + case SFF_8636_ETHERNET_100G_CLR4: + ssf_add_dict_string(d, name, "100G Ethernet: 100G CLR4"); + break; + case SFF_8636_ETHERNET_100G_AOC2: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)"); + break; + case SFF_8636_ETHERNET_100G_ACC2: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)"); + break; + default: + ssf_add_dict_string(d, name, "(reserved or unknown)"); + break; + } + } + + /* SONET Compliance Codes */ + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_40G_OTN) + ssf_add_dict_string(d, name, "40G OTN (OTU3B/OTU3C)"); + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_LR) + ssf_add_dict_string(d, name, "SONET: OC-48, long reach"); + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_IR) + ssf_add_dict_string(d, name, "SONET: OC-48, intermediate reach"); + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_SR) + ssf_add_dict_string(d, name, "SONET: OC-48, short reach"); + + /* SAS/SATA Compliance Codes */ + if (data[SFF_8636_SAS_COMP_OFFSET] & SFF_8636_SAS_6G) + ssf_add_dict_string(d, name, "SAS 6.0G"); + if (data[SFF_8636_SAS_COMP_OFFSET] & SFF_8636_SAS_3G) + ssf_add_dict_string(d, name, "SAS 3.0G"); + + /* Ethernet Compliance Codes */ + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_T) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-T"); + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_CX) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-CX"); + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_LX) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-LX"); + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_SX) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-SX"); + + /* Fibre Channel link length */ + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_VERY_LONG) + ssf_add_dict_string(d, name, "FC: very long distance (V)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_SHORT) + ssf_add_dict_string(d, name, "FC: short distance (S)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_INT) + ssf_add_dict_string(d, name, "FC: intermediate distance (I)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_LONG) + ssf_add_dict_string(d, name, "FC: long distance (L)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_MED) + ssf_add_dict_string(d, name, "FC: medium distance (M)"); + + /* Fibre Channel transmitter technology */ + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_TECH_LONG_LC) + ssf_add_dict_string(d, name, "FC: Longwave laser (LC)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_TECH_ELEC_INTER) + ssf_add_dict_string(d, name, "FC: Electrical inter-enclosure (EL)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_ELEC_INTRA) + ssf_add_dict_string(d, name, "FC: Electrical intra-enclosure (EL)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_SHORT_WO_OFC) + ssf_add_dict_string(d, name, "FC: Shortwave laser w/o OFC (SN)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_SHORT_W_OFC) + ssf_add_dict_string(d, name, "FC: Shortwave laser with OFC (SL)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_LONG_LL) + ssf_add_dict_string(d, name, "FC: Longwave laser (LL)"); + + /* Fibre Channel transmission media */ + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TW) + ssf_add_dict_string(d, name, "FC: Twin Axial Pair (TW)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TP) + ssf_add_dict_string(d, name, "FC: Twisted Pair (TP)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_MI) + ssf_add_dict_string(d, name, "FC: Miniature Coax (MI)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TV) + ssf_add_dict_string(d, name, "FC: Video Coax (TV)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_M6) + ssf_add_dict_string(d, name, "FC: Multimode, 62.5m (M6)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_M5) + ssf_add_dict_string(d, name, "FC: Multimode, 50m (M5)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_OM3) + ssf_add_dict_string(d, name, "FC: Multimode, 50um (OM3)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_SM) + ssf_add_dict_string(d, name, "FC: Single Mode (SM)"); + + /* Fibre Channel speed */ + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_1200_MBPS) + ssf_add_dict_string(d, name, "FC: 1200 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_800_MBPS) + ssf_add_dict_string(d, name, "FC: 800 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_1600_MBPS) + ssf_add_dict_string(d, name, "FC: 1600 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_400_MBPS) + ssf_add_dict_string(d, name, "FC: 400 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_200_MBPS) + ssf_add_dict_string(d, name, "FC: 200 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_100_MBPS) + ssf_add_dict_string(d, name, "FC: 100 MBytes/sec"); +} + +static void sff_8636_show_encoding(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_encoding(data, SFF_8636_ENCODING_OFFSET, + RTE_ETH_MODULE_SFF_8636, d); +} + +static void sff_8636_show_rate_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + char val_string[20]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[SFF_8636_EXT_RS_OFFSET]); + ssf_add_dict_string(d, "Rate identifier", val_string); +} + +static void sff_8636_show_oui(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_oui(data, SFF_8636_VENDOR_OUI_OFFSET, d); +} + +static void sff_8636_show_wavelength_or_copper_compliance(const uint8_t *data, + struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + snprintf(val_string, sizeof(val_string), "0x%02x", + (data[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK)); + + switch (data[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK) { + case SFF_8636_TRANS_850_VCSEL: + strlcat(val_string, " (850 nm VCSEL)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_VCSEL: + strlcat(val_string, " (1310 nm VCSEL)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1550_VCSEL: + strlcat(val_string, " (1550 nm VCSEL)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_FP: + strlcat(val_string, " (1310 nm FP)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_DFB: + strlcat(val_string, " (1310 nm DFB)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1550_DFB: + strlcat(val_string, " (1550 nm DFB)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_EML: + strlcat(val_string, " (1310 nm EML)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1550_EML: + strlcat(val_string, " (1550 nm EML)", sizeof(val_string)); + break; + case SFF_8636_TRANS_OTHERS: + strlcat(val_string, " (Others/Undefined)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1490_DFB: + strlcat(val_string, " (1490 nm DFB)", sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_PAS_UNEQUAL: + strlcat(val_string, " (Copper cable unequalized)", sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_PAS_EQUAL: + strlcat(val_string, " (Copper cable passive equalized)", sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_LNR_FAR_EQUAL: + strlcat(val_string, + " (Copper cable, near and far end limiting active equalizers)", + sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_FAR_EQUAL: + strlcat(val_string, + " (Copper cable, far end limiting active equalizers)", + sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_NEAR_EQUAL: + strlcat(val_string, + " (Copper cable, near end limiting active equalizers)", + sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_LNR_EQUAL: + strlcat(val_string, + " (Copper cable, linear active equalizers)", + sizeof(val_string)); + break; + } + ssf_add_dict_string(d, "Transmitter technology", val_string); + + if ((data[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK) + >= SFF_8636_TRANS_COPPER_PAS_UNEQUAL) { + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + ssf_add_dict_string(d, "Attenuation at 2.5GHz", val_string); + + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + ssf_add_dict_string(d, "Attenuation at 5.0GHz", val_string); + + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + ssf_add_dict_string(d, "Attenuation at 7.0GHz", val_string); + + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + ssf_add_dict_string(d, "Attenuation at 12.9GHz", val_string); + } else { + snprintf(val_string, sizeof(val_string), "%.3lfnm", + (((data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET] << 8) | + data[SFF_8636_WAVELEN_LOW_BYTE_OFFSET])*0.05)); + ssf_add_dict_string(d, "Laser wavelength", val_string); + + snprintf(val_string, sizeof(val_string), "%.3lfnm", + (((data[SFF_8636_WAVE_TOL_HIGH_BYTE_OFFSET] << 8) | + data[SFF_8636_WAVE_TOL_LOW_BYTE_OFFSET])*0.005)); + ssf_add_dict_string(d, "Laser wavelength tolerance", val_string); + } +} + +static void sff_8636_show_revision_compliance(const uint8_t *data, struct rte_tel_data *d) +{ + static const char *name = "Revision Compliance"; + + switch (data[SFF_8636_REV_COMPLIANCE_OFFSET]) { + case SFF_8636_REV_UNSPECIFIED: + ssf_add_dict_string(d, name, "Revision not specified"); + break; + case SFF_8636_REV_8436_48: + ssf_add_dict_string(d, name, "SFF-8436 Rev 4.8 or earlier"); + break; + case SFF_8636_REV_8436_8636: + ssf_add_dict_string(d, name, "SFF-8436 Rev 4.8 or earlier"); + break; + case SFF_8636_REV_8636_13: + ssf_add_dict_string(d, name, "SFF-8636 Rev 1.3 or earlier"); + break; + case SFF_8636_REV_8636_14: + ssf_add_dict_string(d, name, "SFF-8636 Rev 1.4"); + break; + case SFF_8636_REV_8636_15: + ssf_add_dict_string(d, name, "SFF-8636 Rev 1.5"); + break; + case SFF_8636_REV_8636_20: + ssf_add_dict_string(d, name, "SFF-8636 Rev 2.0"); + break; + case SFF_8636_REV_8636_27: + ssf_add_dict_string(d, name, "SFF-8636 Rev 2.5/2.6/2.7"); + break; + default: + ssf_add_dict_string(d, name, "Unallocated"); + break; + } +} + +/* + * 2-byte internal temperature conversions: + * First byte is a signed 8-bit integer, which is the temp decimal part + * Second byte are 1/256th of degree, which are added to the dec part. + */ +#define SFF_8636_OFFSET_TO_TEMP(offset) ((int16_t)OFFSET_TO_U16(offset)) + +static void sff_8636_dom_parse(const uint8_t *data, struct sff_diags *sd) +{ + int i = 0; + + /* Monitoring Thresholds for Alarms and Warnings */ + sd->sfp_voltage[MCURR] = OFFSET_TO_U16(SFF_8636_VCC_CURR); + sd->sfp_voltage[HALRM] = OFFSET_TO_U16(SFF_8636_VCC_HALRM); + sd->sfp_voltage[LALRM] = OFFSET_TO_U16(SFF_8636_VCC_LALRM); + sd->sfp_voltage[HWARN] = OFFSET_TO_U16(SFF_8636_VCC_HWARN); + sd->sfp_voltage[LWARN] = OFFSET_TO_U16(SFF_8636_VCC_LWARN); + + sd->sfp_temp[MCURR] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_CURR); + sd->sfp_temp[HALRM] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_HALRM); + sd->sfp_temp[LALRM] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_LALRM); + sd->sfp_temp[HWARN] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_HWARN); + sd->sfp_temp[LWARN] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_LWARN); + + sd->bias_cur[HALRM] = OFFSET_TO_U16(SFF_8636_TX_BIAS_HALRM); + sd->bias_cur[LALRM] = OFFSET_TO_U16(SFF_8636_TX_BIAS_LALRM); + sd->bias_cur[HWARN] = OFFSET_TO_U16(SFF_8636_TX_BIAS_HWARN); + sd->bias_cur[LWARN] = OFFSET_TO_U16(SFF_8636_TX_BIAS_LWARN); + + sd->tx_power[HALRM] = OFFSET_TO_U16(SFF_8636_TX_PWR_HALRM); + sd->tx_power[LALRM] = OFFSET_TO_U16(SFF_8636_TX_PWR_LALRM); + sd->tx_power[HWARN] = OFFSET_TO_U16(SFF_8636_TX_PWR_HWARN); + sd->tx_power[LWARN] = OFFSET_TO_U16(SFF_8636_TX_PWR_LWARN); + + sd->rx_power[HALRM] = OFFSET_TO_U16(SFF_8636_RX_PWR_HALRM); + sd->rx_power[LALRM] = OFFSET_TO_U16(SFF_8636_RX_PWR_LALRM); + sd->rx_power[HWARN] = OFFSET_TO_U16(SFF_8636_RX_PWR_HWARN); + sd->rx_power[LWARN] = OFFSET_TO_U16(SFF_8636_RX_PWR_LWARN); + + + /* Channel Specific Data */ + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + uint8_t rx_power_offset, tx_bias_offset; + uint8_t tx_power_offset; + + switch (i) { + case 0: + rx_power_offset = SFF_8636_RX_PWR_1_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_1_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_1_OFFSET; + break; + case 1: + rx_power_offset = SFF_8636_RX_PWR_2_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_2_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_2_OFFSET; + break; + case 2: + rx_power_offset = SFF_8636_RX_PWR_3_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_3_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_3_OFFSET; + break; + case 3: + rx_power_offset = SFF_8636_RX_PWR_4_OFFSET; + tx_power_offset = SFF_8636_TX_PWR_4_OFFSET; + tx_bias_offset = SFF_8636_TX_BIAS_4_OFFSET; + break; + } + sd->scd[i].bias_cur = OFFSET_TO_U16(tx_bias_offset); + sd->scd[i].rx_power = OFFSET_TO_U16(rx_power_offset); + sd->scd[i].tx_power = OFFSET_TO_U16(tx_power_offset); + } + +} + +static void sff_8636_show_dom(const uint8_t *data, uint32_t eeprom_len, struct rte_tel_data *d) +{ + struct sff_diags sd = {0}; + const char *rx_power_string = NULL; + char power_string[MAX_DESC_SIZE]; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + int i; + + /* + * There is no clear identifier to signify the existence of + * optical diagnostics similar to SFF-8472. So checking existence + * of page 3, will provide the gurantee for existence of alarms + * and thresholds + * If pagging support exists, then supports_alarms is marked as 1 + */ + + if (eeprom_len == RTE_ETH_MODULE_SFF_8636_MAX_LEN) { + if (!(data[SFF_8636_STATUS_2_OFFSET] & + SFF_8636_STATUS_PAGE_3_PRESENT)) { + sd.supports_alarms = 1; + } + } + + sd.rx_power_type = data[SFF_8636_DIAG_TYPE_OFFSET] & + SFF_8636_RX_PWR_TYPE_MASK; + sd.tx_power_type = data[SFF_8636_DIAG_TYPE_OFFSET] & + SFF_8636_RX_PWR_TYPE_MASK; + + sff_8636_dom_parse(data, &sd); + + SPRINT_TEMP(val_string, sd.sfp_temp[MCURR]); + ssf_add_dict_string(d, "Module temperature", val_string); + + SPRINT_VCC(val_string, sd.sfp_voltage[MCURR]); + ssf_add_dict_string(d, "Module voltage", val_string); + + /* + * SFF-8636/8436 spec is not clear whether RX power/ TX bias + * current fields are supported or not. A valid temperature + * reading is used as existence for TX/RX power. + */ + if ((sd.sfp_temp[MCURR] == 0x0) || + (sd.sfp_temp[MCURR] == (int16_t)0xFFFF)) + return; + + ssf_add_dict_string(d, "Alarm/warning flags implemented", + (sd.supports_alarms ? "Yes" : "No")); + + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + snprintf(power_string, MAX_DESC_SIZE, "%s (Channel %d)", + "Laser tx bias current", i+1); + SPRINT_BIAS(val_string, sd.scd[i].bias_cur); + ssf_add_dict_string(d, power_string, val_string); + } + + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + snprintf(power_string, MAX_DESC_SIZE, "%s (Channel %d)", + "Transmit avg optical power", i+1); + SPRINT_xX_PWR(val_string, sd.scd[i].tx_power); + ssf_add_dict_string(d, power_string, val_string); + } + + if (!sd.rx_power_type) + rx_power_string = "Receiver signal OMA"; + else + rx_power_string = "Rcvr signal avg optical power"; + + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + snprintf(power_string, MAX_DESC_SIZE, "%s(Channel %d)", + rx_power_string, i+1); + SPRINT_xX_PWR(val_string, sd.scd[i].rx_power); + ssf_add_dict_string(d, power_string, val_string); + } + + if (sd.supports_alarms) { + for (i = 0; sff_8636_aw_flags[i].str; ++i) { + ssf_add_dict_string(d, sff_8636_aw_flags[i].str, + data[sff_8636_aw_flags[i].offset] + & sff_8636_aw_flags[i].value ? "On" : "Off"); + } + + sff_show_thresholds(sd, d); + } + +} +void sff_8636_show_all(const uint8_t *data, uint32_t eeprom_len, struct rte_tel_data *d) +{ + sff_8636_show_identifier(data, d); + if ((data[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP) || + (data[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP_PLUS) || + (data[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP28)) { + sff_8636_show_ext_identifier(data, d); + sff_8636_show_connector(data, d); + sff_8636_show_transceiver(data, d); + sff_8636_show_encoding(data, d); + sff_show_value_with_unit(data, SFF_8636_BR_NOMINAL_OFFSET, + "BR, Nominal", 100, "Mbps", d); + sff_8636_show_rate_identifier(data, d); + sff_show_value_with_unit(data, SFF_8636_SM_LEN_OFFSET, + "Length (SMF,km)", 1, "km", d); + sff_show_value_with_unit(data, SFF_8636_OM3_LEN_OFFSET, + "Length (OM3 50um)", 2, "m", d); + sff_show_value_with_unit(data, SFF_8636_OM2_LEN_OFFSET, + "Length (OM2 50um)", 1, "m", d); + sff_show_value_with_unit(data, SFF_8636_OM1_LEN_OFFSET, + "Length (OM1 62.5um)", 1, "m", d); + sff_show_value_with_unit(data, SFF_8636_CBL_LEN_OFFSET, + "Length (Copper or Active cable)", 1, "m", d); + sff_8636_show_wavelength_or_copper_compliance(data, d); + sff_show_ascii(data, SFF_8636_VENDOR_NAME_START_OFFSET, + SFF_8636_VENDOR_NAME_END_OFFSET, "Vendor name", d); + sff_8636_show_oui(data, d); + sff_show_ascii(data, SFF_8636_VENDOR_PN_START_OFFSET, + SFF_8636_VENDOR_PN_END_OFFSET, "Vendor PN", d); + sff_show_ascii(data, SFF_8636_VENDOR_REV_START_OFFSET, + SFF_8636_VENDOR_REV_END_OFFSET, "Vendor rev", d); + sff_show_ascii(data, SFF_8636_VENDOR_SN_START_OFFSET, + SFF_8636_VENDOR_SN_END_OFFSET, "Vendor SN", d); + sff_show_ascii(data, SFF_8636_DATE_YEAR_OFFSET, + SFF_8636_DATE_VENDOR_LOT_OFFSET + 1, "Date code", d); + sff_8636_show_revision_compliance(data, d); + sff_8636_show_dom(data, eeprom_len, d); + } +} diff --git a/lib/ethdev/sff_8636.h b/lib/ethdev/sff_8636.h new file mode 100644 index 0000000000..fc656775f9 --- /dev/null +++ b/lib/ethdev/sff_8636.h @@ -0,0 +1,592 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * SFF-8636 standards based QSFP EEPROM Field Definitions + * + */ + +#ifndef _SFF_8636_H_ +#define _SFF_8636_H_ + +/*------------------------------------------------------------------------------ + * + * QSFP EEPROM data structures + * + * register info from SFF-8636 Rev 2.7 + */ + +/*------------------------------------------------------------------------------ + * + * Lower Memory Page 00h + * Measurement, Diagnostic and Control Functions + * + */ +/* Identifier - 0 */ +/* Values are defined under SFF_8024_ID_OFFSET */ +#define SFF_8636_ID_OFFSET 0x00 + +#define SFF_8636_REV_COMPLIANCE_OFFSET 0x01 +#define SFF_8636_REV_UNSPECIFIED 0x00 +#define SFF_8636_REV_8436_48 0x01 +#define SFF_8636_REV_8436_8636 0x02 +#define SFF_8636_REV_8636_13 0x03 +#define SFF_8636_REV_8636_14 0x04 +#define SFF_8636_REV_8636_15 0x05 +#define SFF_8636_REV_8636_20 0x06 +#define SFF_8636_REV_8636_27 0x07 + +#define SFF_8636_STATUS_2_OFFSET 0x02 +/* Flat Memory:0- Paging, 1- Page 0 only */ +#define SFF_8636_STATUS_PAGE_3_PRESENT (1 << 2) +#define SFF_8636_STATUS_INTL_OUTPUT (1 << 1) +#define SFF_8636_STATUS_DATA_NOT_READY (1 << 0) + +/* Channel Status Interrupt Flags - 3-5 */ +#define SFF_8636_LOS_AW_OFFSET 0x03 +#define SFF_8636_TX4_LOS_AW (1 << 7) +#define SFF_8636_TX3_LOS_AW (1 << 6) +#define SFF_8636_TX2_LOS_AW (1 << 5) +#define SFF_8636_TX1_LOS_AW (1 << 4) +#define SFF_8636_RX4_LOS_AW (1 << 3) +#define SFF_8636_RX3_LOS_AW (1 << 2) +#define SFF_8636_RX2_LOS_AW (1 << 1) +#define SFF_8636_RX1_LOS_AW (1 << 0) + +#define SFF_8636_FAULT_AW_OFFSET 0x04 +#define SFF_8636_TX4_FAULT_AW (1 << 3) +#define SFF_8636_TX3_FAULT_AW (1 << 2) +#define SFF_8636_TX2_FAULT_AW (1 << 1) +#define SFF_8636_TX1_FAULT_AW (1 << 0) + +/* Module Monitor Interrupt Flags - 6-8 */ +#define SFF_8636_TEMP_AW_OFFSET 0x06 +#define SFF_8636_TEMP_HALARM_STATUS (1 << 7) +#define SFF_8636_TEMP_LALARM_STATUS (1 << 6) +#define SFF_8636_TEMP_HWARN_STATUS (1 << 5) +#define SFF_8636_TEMP_LWARN_STATUS (1 << 4) + +#define SFF_8636_VCC_AW_OFFSET 0x07 +#define SFF_8636_VCC_HALARM_STATUS (1 << 7) +#define SFF_8636_VCC_LALARM_STATUS (1 << 6) +#define SFF_8636_VCC_HWARN_STATUS (1 << 5) +#define SFF_8636_VCC_LWARN_STATUS (1 << 4) + +/* Channel Monitor Interrupt Flags - 9-21 */ +#define SFF_8636_RX_PWR_12_AW_OFFSET 0x09 +#define SFF_8636_RX_PWR_1_HALARM (1 << 7) +#define SFF_8636_RX_PWR_1_LALARM (1 << 6) +#define SFF_8636_RX_PWR_1_HWARN (1 << 5) +#define SFF_8636_RX_PWR_1_LWARN (1 << 4) +#define SFF_8636_RX_PWR_2_HALARM (1 << 3) +#define SFF_8636_RX_PWR_2_LALARM (1 << 2) +#define SFF_8636_RX_PWR_2_HWARN (1 << 1) +#define SFF_8636_RX_PWR_2_LWARN (1 << 0) + +#define SFF_8636_RX_PWR_34_AW_OFFSET 0x0A +#define SFF_8636_RX_PWR_3_HALARM (1 << 7) +#define SFF_8636_RX_PWR_3_LALARM (1 << 6) +#define SFF_8636_RX_PWR_3_HWARN (1 << 5) +#define SFF_8636_RX_PWR_3_LWARN (1 << 4) +#define SFF_8636_RX_PWR_4_HALARM (1 << 3) +#define SFF_8636_RX_PWR_4_LALARM (1 << 2) +#define SFF_8636_RX_PWR_4_HWARN (1 << 1) +#define SFF_8636_RX_PWR_4_LWARN (1 << 0) + +#define SFF_8636_TX_BIAS_12_AW_OFFSET 0x0B +#define SFF_8636_TX_BIAS_1_HALARM (1 << 7) +#define SFF_8636_TX_BIAS_1_LALARM (1 << 6) +#define SFF_8636_TX_BIAS_1_HWARN (1 << 5) +#define SFF_8636_TX_BIAS_1_LWARN (1 << 4) +#define SFF_8636_TX_BIAS_2_HALARM (1 << 3) +#define SFF_8636_TX_BIAS_2_LALARM (1 << 2) +#define SFF_8636_TX_BIAS_2_HWARN (1 << 1) +#define SFF_8636_TX_BIAS_2_LWARN (1 << 0) + +#define SFF_8636_TX_BIAS_34_AW_OFFSET 0xC +#define SFF_8636_TX_BIAS_3_HALARM (1 << 7) +#define SFF_8636_TX_BIAS_3_LALARM (1 << 6) +#define SFF_8636_TX_BIAS_3_HWARN (1 << 5) +#define SFF_8636_TX_BIAS_3_LWARN (1 << 4) +#define SFF_8636_TX_BIAS_4_HALARM (1 << 3) +#define SFF_8636_TX_BIAS_4_LALARM (1 << 2) +#define SFF_8636_TX_BIAS_4_HWARN (1 << 1) +#define SFF_8636_TX_BIAS_4_LWARN (1 << 0) + +#define SFF_8636_TX_PWR_12_AW_OFFSET 0x0D +#define SFF_8636_TX_PWR_1_HALARM (1 << 7) +#define SFF_8636_TX_PWR_1_LALARM (1 << 6) +#define SFF_8636_TX_PWR_1_HWARN (1 << 5) +#define SFF_8636_TX_PWR_1_LWARN (1 << 4) +#define SFF_8636_TX_PWR_2_HALARM (1 << 3) +#define SFF_8636_TX_PWR_2_LALARM (1 << 2) +#define SFF_8636_TX_PWR_2_HWARN (1 << 1) +#define SFF_8636_TX_PWR_2_LWARN (1 << 0) + +#define SFF_8636_TX_PWR_34_AW_OFFSET 0x0E +#define SFF_8636_TX_PWR_3_HALARM (1 << 7) +#define SFF_8636_TX_PWR_3_LALARM (1 << 6) +#define SFF_8636_TX_PWR_3_HWARN (1 << 5) +#define SFF_8636_TX_PWR_3_LWARN (1 << 4) +#define SFF_8636_TX_PWR_4_HALARM (1 << 3) +#define SFF_8636_TX_PWR_4_LALARM (1 << 2) +#define SFF_8636_TX_PWR_4_HWARN (1 << 1) +#define SFF_8636_TX_PWR_4_LWARN (1 << 0) + +/* Module Monitoring Values - 22-33 */ +#define SFF_8636_TEMP_CURR 0x16 +#define SFF_8636_TEMP_MSB_OFFSET 0x16 +#define SFF_8636_TEMP_LSB_OFFSET 0x17 + +#define SFF_8636_VCC_CURR 0x1A +#define SFF_8636_VCC_MSB_OFFSET 0x1A +#define SFF_8636_VCC_LSB_OFFSET 0x1B + +/* Channel Monitoring Values - 34-81 */ +#define SFF_8636_RX_PWR_1_OFFSET 0x22 +#define SFF_8636_RX_PWR_2_OFFSET 0x24 +#define SFF_8636_RX_PWR_3_OFFSET 0x26 +#define SFF_8636_RX_PWR_4_OFFSET 0x28 + +#define SFF_8636_TX_BIAS_1_OFFSET 0x2A +#define SFF_8636_TX_BIAS_2_OFFSET 0x2C +#define SFF_8636_TX_BIAS_3_OFFSET 0x2E +#define SFF_8636_TX_BIAS_4_OFFSET 0x30 + +#define SFF_8636_TX_PWR_1_OFFSET 0x32 +#define SFF_8636_TX_PWR_2_OFFSET 0x34 +#define SFF_8636_TX_PWR_3_OFFSET 0x36 +#define SFF_8636_TX_PWR_4_OFFSET 0x38 + +/* Control Bytes - 86 - 99 */ +#define SFF_8636_TX_DISABLE_OFFSET 0x56 +#define SFF_8636_TX_DISABLE_4 (1 << 3) +#define SFF_8636_TX_DISABLE_3 (1 << 2) +#define SFF_8636_TX_DISABLE_2 (1 << 1) +#define SFF_8636_TX_DISABLE_1 (1 << 0) + +#define SFF_8636_RX_RATE_SELECT_OFFSET 0x57 +#define SFF_8636_RX_RATE_SELECT_4_MASK (3 << 6) +#define SFF_8636_RX_RATE_SELECT_3_MASK (3 << 4) +#define SFF_8636_RX_RATE_SELECT_2_MASK (3 << 2) +#define SFF_8636_RX_RATE_SELECT_1_MASK (3 << 0) + +#define SFF_8636_TX_RATE_SELECT_OFFSET 0x58 +#define SFF_8636_TX_RATE_SELECT_4_MASK (3 << 6) +#define SFF_8636_TX_RATE_SELECT_3_MASK (3 << 4) +#define SFF_8636_TX_RATE_SELECT_2_MASK (3 << 2) +#define SFF_8636_TX_RATE_SELECT_1_MASK (3 << 0) + +#define SFF_8636_RX_APP_SELECT_4_OFFSET 0x58 +#define SFF_8636_RX_APP_SELECT_3_OFFSET 0x59 +#define SFF_8636_RX_APP_SELECT_2_OFFSET 0x5A +#define SFF_8636_RX_APP_SELECT_1_OFFSET 0x5B + +#define SFF_8636_PWR_MODE_OFFSET 0x5D +#define SFF_8636_HIGH_PWR_ENABLE (1 << 2) +#define SFF_8636_LOW_PWR_MODE (1 << 1) +#define SFF_8636_PWR_OVERRIDE (1 << 0) + +#define SFF_8636_TX_APP_SELECT_4_OFFSET 0x5E +#define SFF_8636_TX_APP_SELECT_3_OFFSET 0x5F +#define SFF_8636_TX_APP_SELECT_2_OFFSET 0x60 +#define SFF_8636_TX_APP_SELECT_1_OFFSET 0x61 + +#define SFF_8636_LOS_MASK_OFFSET 0x64 +#define SFF_8636_TX_LOS_4_MASK (1 << 7) +#define SFF_8636_TX_LOS_3_MASK (1 << 6) +#define SFF_8636_TX_LOS_2_MASK (1 << 5) +#define SFF_8636_TX_LOS_1_MASK (1 << 4) +#define SFF_8636_RX_LOS_4_MASK (1 << 3) +#define SFF_8636_RX_LOS_3_MASK (1 << 2) +#define SFF_8636_RX_LOS_2_MASK (1 << 1) +#define SFF_8636_RX_LOS_1_MASK (1 << 0) + +#define SFF_8636_FAULT_MASK_OFFSET 0x65 +#define SFF_8636_TX_FAULT_1_MASK (1 << 3) +#define SFF_8636_TX_FAULT_2_MASK (1 << 2) +#define SFF_8636_TX_FAULT_3_MASK (1 << 1) +#define SFF_8636_TX_FAULT_4_MASK (1 << 0) + +#define SFF_8636_TEMP_MASK_OFFSET 0x67 +#define SFF_8636_TEMP_HALARM_MASK (1 << 7) +#define SFF_8636_TEMP_LALARM_MASK (1 << 6) +#define SFF_8636_TEMP_HWARN_MASK (1 << 5) +#define SFF_8636_TEMP_LWARN_MASK (1 << 4) + +#define SFF_8636_VCC_MASK_OFFSET 0x68 +#define SFF_8636_VCC_HALARM_MASK (1 << 7) +#define SFF_8636_VCC_LALARM_MASK (1 << 6) +#define SFF_8636_VCC_HWARN_MASK (1 << 5) +#define SFF_8636_VCC_LWARN_MASK (1 << 4) + +/*------------------------------------------------------------------------------ + * + * Upper Memory Page 00h + * Serial ID - Base ID, Extended ID and Vendor Specific ID fields + * + */ +/* Identifier - 128 */ +/* Identifier values same as Lower Memory Page 00h */ +#define SFF_8636_UPPER_PAGE_0_ID_OFFSET 0x80 + +/* Extended Identifier - 128 */ +#define SFF_8636_EXT_ID_OFFSET 0x81 +#define SFF_8636_EXT_ID_PWR_CLASS_MASK 0xC0 +#define SFF_8636_EXT_ID_PWR_CLASS_1 (0 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_2 (1 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_3 (2 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_4 (3 << 6) +#define SFF_8636_EXT_ID_CLIE_MASK 0x10 +#define SFF_8636_EXT_ID_CLIEI_CODE_PRESENT (1 << 4) +#define SFF_8636_EXT_ID_CDR_TX_MASK 0x08 +#define SFF_8636_EXT_ID_CDR_TX_PRESENT (1 << 3) +#define SFF_8636_EXT_ID_CDR_RX_MASK 0x04 +#define SFF_8636_EXT_ID_CDR_RX_PRESENT (1 << 2) +#define SFF_8636_EXT_ID_EPWR_CLASS_MASK 0x03 +#define SFF_8636_EXT_ID_PWR_CLASS_LEGACY 0 +#define SFF_8636_EXT_ID_PWR_CLASS_5 1 +#define SFF_8636_EXT_ID_PWR_CLASS_6 2 +#define SFF_8636_EXT_ID_PWR_CLASS_7 3 + +/* Connector Values offset - 130 */ +/* Values are defined under SFF_8024_CTOR */ +#define SFF_8636_CTOR_OFFSET 0x82 +#define SFF_8636_CTOR_UNKNOWN 0x00 +#define SFF_8636_CTOR_SC 0x01 +#define SFF_8636_CTOR_FC_STYLE_1 0x02 +#define SFF_8636_CTOR_FC_STYLE_2 0x03 +#define SFF_8636_CTOR_BNC_TNC 0x04 +#define SFF_8636_CTOR_FC_COAX 0x05 +#define SFF_8636_CTOR_FIBER_JACK 0x06 +#define SFF_8636_CTOR_LC 0x07 +#define SFF_8636_CTOR_MT_RJ 0x08 +#define SFF_8636_CTOR_MU 0x09 +#define SFF_8636_CTOR_SG 0x0A +#define SFF_8636_CTOR_OPT_PT 0x0B +#define SFF_8636_CTOR_MPO 0x0C +/* 0D-1Fh --- Reserved */ +#define SFF_8636_CTOR_HSDC_II 0x20 +#define SFF_8636_CTOR_COPPER_PT 0x21 +#define SFF_8636_CTOR_RJ45 0x22 +#define SFF_8636_CTOR_NO_SEPARABLE 0x23 +#define SFF_8636_CTOR_MXC_2X16 0x24 + +/* Specification Compliance - 131-138 */ +/* Ethernet Compliance Codes - 131 */ +#define SFF_8636_ETHERNET_COMP_OFFSET 0x83 +#define SFF_8636_ETHERNET_RSRVD (1 << 7) +#define SFF_8636_ETHERNET_10G_LRM (1 << 6) +#define SFF_8636_ETHERNET_10G_LR (1 << 5) +#define SFF_8636_ETHERNET_10G_SR (1 << 4) +#define SFF_8636_ETHERNET_40G_CR4 (1 << 3) +#define SFF_8636_ETHERNET_40G_SR4 (1 << 2) +#define SFF_8636_ETHERNET_40G_LR4 (1 << 1) +#define SFF_8636_ETHERNET_40G_ACTIVE (1 << 0) + +/* SONET Compliance Codes - 132 */ +#define SFF_8636_SONET_COMP_OFFSET 0x84 +#define SFF_8636_SONET_40G_OTN (1 << 3) +#define SFF_8636_SONET_OC48_LR (1 << 2) +#define SFF_8636_SONET_OC48_IR (1 << 1) +#define SFF_8636_SONET_OC48_SR (1 << 0) + +/* SAS/SATA Complaince Codes - 133 */ +#define SFF_8636_SAS_COMP_OFFSET 0x85 +#define SFF_8636_SAS_12G (1 << 6) +#define SFF_8636_SAS_6G (1 << 5) +#define SFF_8636_SAS_3G (1 << 4) + +/* Gigabit Ethernet Compliance Codes - 134 */ +#define SFF_8636_GIGE_COMP_OFFSET 0x86 +#define SFF_8636_GIGE_1000_BASE_T (1 << 3) +#define SFF_8636_GIGE_1000_BASE_CX (1 << 2) +#define SFF_8636_GIGE_1000_BASE_LX (1 << 1) +#define SFF_8636_GIGE_1000_BASE_SX (1 << 0) + +/* Fibre Channel Link length/Transmitter Tech. - 135,136 */ +#define SFF_8636_FC_LEN_OFFSET 0x87 +#define SFF_8636_FC_LEN_VERY_LONG (1 << 7) +#define SFF_8636_FC_LEN_SHORT (1 << 6) +#define SFF_8636_FC_LEN_INT (1 << 5) +#define SFF_8636_FC_LEN_LONG (1 << 4) +#define SFF_8636_FC_LEN_MED (1 << 3) +#define SFF_8636_FC_TECH_LONG_LC (1 << 1) +#define SFF_8636_FC_TECH_ELEC_INTER (1 << 0) + +#define SFF_8636_FC_TECH_OFFSET 0x88 +#define SFF_8636_FC_TECH_ELEC_INTRA (1 << 7) +#define SFF_8636_FC_TECH_SHORT_WO_OFC (1 << 6) +#define SFF_8636_FC_TECH_SHORT_W_OFC (1 << 5) +#define SFF_8636_FC_TECH_LONG_LL (1 << 4) + +/* Fibre Channel Transmitter Media - 137 */ +#define SFF_8636_FC_TRANS_MEDIA_OFFSET 0x89 +/* Twin Axial Pair */ +#define SFF_8636_FC_TRANS_MEDIA_TW (1 << 7) +/* Shielded Twisted Pair */ +#define SFF_8636_FC_TRANS_MEDIA_TP (1 << 6) +/* Miniature Coax */ +#define SFF_8636_FC_TRANS_MEDIA_MI (1 << 5) +/* Video Coax */ +#define SFF_8636_FC_TRANS_MEDIA_TV (1 << 4) +/* Multi-mode 62.5m */ +#define SFF_8636_FC_TRANS_MEDIA_M6 (1 << 3) +/* Multi-mode 50m */ +#define SFF_8636_FC_TRANS_MEDIA_M5 (1 << 2) +/* Multi-mode 50um */ +#define SFF_8636_FC_TRANS_MEDIA_OM3 (1 << 1) +/* Single Mode */ +#define SFF_8636_FC_TRANS_MEDIA_SM (1 << 0) + +/* Fibre Channel Speed - 138 */ +#define SFF_8636_FC_SPEED_OFFSET 0x8A +#define SFF_8636_FC_SPEED_1200_MBPS (1 << 7) +#define SFF_8636_FC_SPEED_800_MBPS (1 << 6) +#define SFF_8636_FC_SPEED_1600_MBPS (1 << 5) +#define SFF_8636_FC_SPEED_400_MBPS (1 << 4) +#define SFF_8636_FC_SPEED_200_MBPS (1 << 2) +#define SFF_8636_FC_SPEED_100_MBPS (1 << 0) + +/* Encoding - 139 */ +/* Values are defined under SFF_8024_ENCODING */ +#define SFF_8636_ENCODING_OFFSET 0x8B +#define SFF_8636_ENCODING_MANCHESTER 0x06 +#define SFF_8636_ENCODING_64B66B 0x05 +#define SFF_8636_ENCODING_SONET 0x04 +#define SFF_8636_ENCODING_NRZ 0x03 +#define SFF_8636_ENCODING_4B5B 0x02 +#define SFF_8636_ENCODING_8B10B 0x01 +#define SFF_8636_ENCODING_UNSPEC 0x00 + +/* BR, Nominal - 140 */ +#define SFF_8636_BR_NOMINAL_OFFSET 0x8C + +/* Extended RateSelect - 141 */ +#define SFF_8636_EXT_RS_OFFSET 0x8D +#define SFF_8636_EXT_RS_V1 (1 << 0) + +/* Length (Standard SM Fiber)-km - 142 */ +#define SFF_8636_SM_LEN_OFFSET 0x8E + +/* Length (OM3)-Unit 2m - 143 */ +#define SFF_8636_OM3_LEN_OFFSET 0x8F + +/* Length (OM2)-Unit 1m - 144 */ +#define SFF_8636_OM2_LEN_OFFSET 0x90 + +/* Length (OM1)-Unit 1m - 145 */ +#define SFF_8636_OM1_LEN_OFFSET 0x91 + +/* Cable Assembly Length -Unit 1m - 146 */ +#define SFF_8636_CBL_LEN_OFFSET 0x92 + +/* Device Technology - 147 */ +#define SFF_8636_DEVICE_TECH_OFFSET 0x93 +/* Transmitter Technology */ +#define SFF_8636_TRANS_TECH_MASK 0xF0 +/* Copper cable, linear active equalizers */ +#define SFF_8636_TRANS_COPPER_LNR_EQUAL (15 << 4) +/* Copper cable, near end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_NEAR_EQUAL (14 << 4) +/* Copper cable, far end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_FAR_EQUAL (13 << 4) +/* Copper cable, near & far end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_LNR_FAR_EQUAL (12 << 4) +/* Copper cable, passive equalized */ +#define SFF_8636_TRANS_COPPER_PAS_EQUAL (11 << 4) +/* Copper cable, unequalized */ +#define SFF_8636_TRANS_COPPER_PAS_UNEQUAL (10 << 4) +/* 1490 nm DFB */ +#define SFF_8636_TRANS_1490_DFB (9 << 4) +/* Others */ +#define SFF_8636_TRANS_OTHERS (8 << 4) +/* 1550 nm EML */ +#define SFF_8636_TRANS_1550_EML (7 << 4) +/* 1310 nm EML */ +#define SFF_8636_TRANS_1310_EML (6 << 4) +/* 1550 nm DFB */ +#define SFF_8636_TRANS_1550_DFB (5 << 4) +/* 1310 nm DFB */ +#define SFF_8636_TRANS_1310_DFB (4 << 4) +/* 1310 nm FP */ +#define SFF_8636_TRANS_1310_FP (3 << 4) +/* 1550 nm VCSEL */ +#define SFF_8636_TRANS_1550_VCSEL (2 << 4) +/* 1310 nm VCSEL */ +#define SFF_8636_TRANS_1310_VCSEL (1 << 4) +/* 850 nm VCSEL */ +#define SFF_8636_TRANS_850_VCSEL (0 << 4) + + /* Active/No wavelength control */ +#define SFF_8636_DEV_TECH_ACTIVE_WAVE_LEN (1 << 3) +/* Cooled transmitter */ +#define SFF_8636_DEV_TECH_COOL_TRANS (1 << 2) +/* APD/Pin Detector */ +#define SFF_8636_DEV_TECH_APD_DETECTOR (1 << 1) +/* Transmitter tunable */ +#define SFF_8636_DEV_TECH_TUNABLE (1 << 0) + +/* Vendor Name - 148-163 */ +#define SFF_8636_VENDOR_NAME_START_OFFSET 0x94 +#define SFF_8636_VENDOR_NAME_END_OFFSET 0xA3 + +/* Extended Module Codes - 164 */ +#define SFF_8636_EXT_MOD_CODE_OFFSET 0xA4 +#define SFF_8636_EXT_MOD_INFINIBAND_EDR (1 << 4) +#define SFF_8636_EXT_MOD_INFINIBAND_FDR (1 << 3) +#define SFF_8636_EXT_MOD_INFINIBAND_QDR (1 << 2) +#define SFF_8636_EXT_MOD_INFINIBAND_DDR (1 << 1) +#define SFF_8636_EXT_MOD_INFINIBAND_SDR (1 << 0) + +/* Vendor OUI - 165-167 */ +#define SFF_8636_VENDOR_OUI_OFFSET 0xA5 +#define SFF_8636_VENDOR_OUI_LEN 3 + +/* Vendor OUI - 165-167 */ +#define SFF_8636_VENDOR_PN_START_OFFSET 0xA8 +#define SFF_8636_VENDOR_PN_END_OFFSET 0xB7 + +/* Vendor Revision - 184-185 */ +#define SFF_8636_VENDOR_REV_START_OFFSET 0xB8 +#define SFF_8636_VENDOR_REV_END_OFFSET 0xB9 + +/* Wavelength - 186-187 */ +#define SFF_8636_WAVELEN_HIGH_BYTE_OFFSET 0xBA +#define SFF_8636_WAVELEN_LOW_BYTE_OFFSET 0xBB + +/* Wavelength Tolerance- 188-189 */ +#define SFF_8636_WAVE_TOL_HIGH_BYTE_OFFSET 0xBC +#define SFF_8636_WAVE_TOL_LOW_BYTE_OFFSET 0xBD + +/* Max case temp - Other than 70 C - 190 */ +#define SFF_8636_MAXCASE_TEMP_OFFSET 0xBE + +/* CC_BASE - 191 */ +#define SFF_8636_CC_BASE_OFFSET 0xBF + +/* Option Values - 192-195 */ +#define SFF_8636_OPTION_1_OFFSET 0xC0 +#define SFF_8636_ETHERNET_UNSPECIFIED 0x00 +#define SFF_8636_ETHERNET_100G_AOC 0x01 +#define SFF_8636_ETHERNET_100G_SR4 0x02 +#define SFF_8636_ETHERNET_100G_LR4 0x03 +#define SFF_8636_ETHERNET_100G_ER4 0x04 +#define SFF_8636_ETHERNET_100G_SR10 0x05 +#define SFF_8636_ETHERNET_100G_CWDM4_FEC 0x06 +#define SFF_8636_ETHERNET_100G_PSM4 0x07 +#define SFF_8636_ETHERNET_100G_ACC 0x08 +#define SFF_8636_ETHERNET_100G_CWDM4_NO_FEC 0x09 +#define SFF_8636_ETHERNET_100G_RSVD1 0x0A +#define SFF_8636_ETHERNET_100G_CR4 0x0B +#define SFF_8636_ETHERNET_25G_CR_CA_S 0x0C +#define SFF_8636_ETHERNET_25G_CR_CA_N 0x0D +#define SFF_8636_ETHERNET_40G_ER4 0x10 +#define SFF_8636_ETHERNET_4X10_SR 0x11 +#define SFF_8636_ETHERNET_40G_PSM4 0x12 +#define SFF_8636_ETHERNET_G959_P1I1_2D1 0x13 +#define SFF_8636_ETHERNET_G959_P1S1_2D2 0x14 +#define SFF_8636_ETHERNET_G959_P1L1_2D2 0x15 +#define SFF_8636_ETHERNET_10GT_SFI 0x16 +#define SFF_8636_ETHERNET_100G_CLR4 0x17 +#define SFF_8636_ETHERNET_100G_AOC2 0x18 +#define SFF_8636_ETHERNET_100G_ACC2 0x19 + +#define SFF_8636_OPTION_2_OFFSET 0xC1 +/* Rx output amplitude */ +#define SFF_8636_O2_RX_OUTPUT_AMP (1 << 0) +#define SFF_8636_OPTION_3_OFFSET 0xC2 +/* Rx Squelch Disable */ +#define SFF_8636_O3_RX_SQL_DSBL (1 << 3) +/* Rx Output Disable capable */ +#define SFF_8636_O3_RX_OUTPUT_DSBL (1 << 2) +/* Tx Squelch Disable */ +#define SFF_8636_O3_TX_SQL_DSBL (1 << 1) +/* Tx Squelch Impl */ +#define SFF_8636_O3_TX_SQL_IMPL (1 << 0) +#define SFF_8636_OPTION_4_OFFSET 0xC3 +/* Memory Page 02 present */ +#define SFF_8636_O4_PAGE_02_PRESENT (1 << 7) +/* Memory Page 01 present */ +#define SFF_8636_O4_PAGE_01_PRESENT (1 << 6) +/* Rate Select implemented */ +#define SFF_8636_O4_RATE_SELECT (1 << 5) +/* Tx_DISABLE implemented */ +#define SFF_8636_O4_TX_DISABLE (1 << 4) +/* Tx_FAULT implemented */ +#define SFF_8636_O4_TX_FAULT (1 << 3) +/* Tx Squelch implemented */ +#define SFF_8636_O4_TX_SQUELCH (1 << 2) +/* Tx Loss of Signal */ +#define SFF_8636_O4_TX_LOS (1 << 1) + +/* Vendor SN - 196-211 */ +#define SFF_8636_VENDOR_SN_START_OFFSET 0xC4 +#define SFF_8636_VENDOR_SN_END_OFFSET 0xD3 + +/* Vendor Date - 212-219 */ +#define SFF_8636_DATE_YEAR_OFFSET 0xD4 +#define SFF_8636_DATE_YEAR_LEN 2 +#define SFF_8636_DATE_MONTH_OFFSET 0xD6 +#define SFF_8636_DATE_MONTH_LEN 2 +#define SFF_8636_DATE_DAY_OFFSET 0xD8 +#define SFF_8636_DATE_DAY_LEN 2 +#define SFF_8636_DATE_VENDOR_LOT_OFFSET 0xDA +#define SFF_8636_DATE_VENDOR_LOT_LEN 2 + +/* Diagnostic Monitoring Type - 220 */ +#define SFF_8636_DIAG_TYPE_OFFSET 0xDC +#define SFF_8636_RX_PWR_TYPE_MASK 0x8 +#define SFF_8636_RX_PWR_TYPE_AVG_PWR (1 << 3) +#define SFF_8636_RX_PWR_TYPE_OMA (0 << 3) +#define SFF_8636_TX_PWR_TYPE_MASK 0x4 +#define SFF_8636_TX_PWR_TYPE_AVG_PWR (1 << 2) + +/* Enhanced Options - 221 */ +#define SFF_8636_ENH_OPTIONS_OFFSET 0xDD +#define SFF_8636_RATE_SELECT_EXT_SUPPORT (1 << 3) +#define SFF_8636_RATE_SELECT_APP_TABLE_SUPPORT (1 << 2) + +/* Check code - 223 */ +#define SFF_8636_CC_EXT_OFFSET 0xDF +#define SFF_8636_CC_EXT_LEN 1 + +/*------------------------------------------------------------------------------ + * + * Upper Memory Page 03h + * Contains module thresholds, channel thresholds and masks, + * and optional channel controls + * + * Offset - Page Num(3) * PageSize(0x80) + Page offset + */ + +/* Module Thresholds (48 Bytes) 128-175 */ +/* MSB at low address, LSB at high address */ +#define SFF_8636_TEMP_HALRM 0x200 +#define SFF_8636_TEMP_LALRM 0x202 +#define SFF_8636_TEMP_HWARN 0x204 +#define SFF_8636_TEMP_LWARN 0x206 + +#define SFF_8636_VCC_HALRM 0x210 +#define SFF_8636_VCC_LALRM 0x212 +#define SFF_8636_VCC_HWARN 0x214 +#define SFF_8636_VCC_LWARN 0x216 + +#define SFF_8636_RX_PWR_HALRM 0x230 +#define SFF_8636_RX_PWR_LALRM 0x232 +#define SFF_8636_RX_PWR_HWARN 0x234 +#define SFF_8636_RX_PWR_LWARN 0x236 + +#define SFF_8636_TX_BIAS_HALRM 0x238 +#define SFF_8636_TX_BIAS_LALRM 0x23A +#define SFF_8636_TX_BIAS_HWARN 0x23C +#define SFF_8636_TX_BIAS_LWARN 0x23E + +#define SFF_8636_TX_PWR_HALRM 0x240 +#define SFF_8636_TX_PWR_LALRM 0x242 +#define SFF_8636_TX_PWR_HWARN 0x244 +#define SFF_8636_TX_PWR_LWARN 0x246 + +#define ETH_MODULE_SFF_8636_MAX_LEN 640 +#define ETH_MODULE_SFF_8436_MAX_LEN 640 + +#endif /* _SFF_8636_H_ */ -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v7 5/5] ethdev: format module EEPROM for SFF-8636 2022-05-24 6:24 ` [PATCH v7 5/5] ethdev: format module EEPROM for SFF-8636 Robin Zhang @ 2022-05-24 9:03 ` David Marchand 2022-05-25 2:43 ` Zhang, RobinX 0 siblings, 1 reply; 77+ messages in thread From: David Marchand @ 2022-05-24 9:03 UTC (permalink / raw) To: Robin Zhang; +Cc: dev, Thomas Monjalon, Andrew Rybchenko, kevinx.liu Hello, I see a lot of switch / case where tables could do the job. In any case, I'll focus only on one part of the code, that triggers a build warning witch clang 14 (+ ASan): On Tue, May 24, 2022 at 8:31 AM Robin Zhang <robinx.zhang@intel.com> wrote: > + /* Channel Specific Data */ > + for (i = 0; i < MAX_CHANNEL_NUM; i++) { > + uint8_t rx_power_offset, tx_bias_offset; > + uint8_t tx_power_offset; > + > + switch (i) { > + case 0: > + rx_power_offset = SFF_8636_RX_PWR_1_OFFSET; > + tx_power_offset = SFF_8636_TX_PWR_1_OFFSET; > + tx_bias_offset = SFF_8636_TX_BIAS_1_OFFSET; > + break; > + case 1: > + rx_power_offset = SFF_8636_RX_PWR_2_OFFSET; > + tx_power_offset = SFF_8636_TX_PWR_2_OFFSET; > + tx_bias_offset = SFF_8636_TX_BIAS_2_OFFSET; > + break; > + case 2: > + rx_power_offset = SFF_8636_RX_PWR_3_OFFSET; > + tx_power_offset = SFF_8636_TX_PWR_3_OFFSET; > + tx_bias_offset = SFF_8636_TX_BIAS_3_OFFSET; > + break; > + case 3: > + rx_power_offset = SFF_8636_RX_PWR_4_OFFSET; > + tx_power_offset = SFF_8636_TX_PWR_4_OFFSET; > + tx_bias_offset = SFF_8636_TX_BIAS_4_OFFSET; > + break; > + } > + sd->scd[i].bias_cur = OFFSET_TO_U16(tx_bias_offset); > + sd->scd[i].rx_power = OFFSET_TO_U16(rx_power_offset); > + sd->scd[i].tx_power = OFFSET_TO_U16(tx_power_offset); > + } [15/442] Compiling C object lib/librte_ethdev.a.p/ethdev_sff_8636.c.o In file included from ../lib/ethdev/sff_8636.c:13: ../lib/ethdev/sff_common.h: In function ‘sff_8636_show_all’: ../lib/ethdev/sff_common.h:101:22: warning: ‘tx_power_offset’ may be used uninitialized [-Wmaybe-uninitialized] 101 | (data[offset] << 8 | data[(offset) + 1]) | ^ ../lib/ethdev/sff_8636.c:621:25: note: ‘tx_power_offset’ was declared here 621 | uint8_t tx_power_offset; | ^~~~~~~~~~~~~~~ ../lib/ethdev/sff_common.h:101:22: warning: ‘tx_bias_offset’ may be used uninitialized [-Wmaybe-uninitialized] 101 | (data[offset] << 8 | data[(offset) + 1]) | ^ ../lib/ethdev/sff_8636.c:620:42: note: ‘tx_bias_offset’ was declared here 620 | uint8_t rx_power_offset, tx_bias_offset; | ^~~~~~~~~~~~~~ ../lib/ethdev/sff_common.h:101:22: warning: ‘rx_power_offset’ may be used uninitialized [-Wmaybe-uninitialized] 101 | (data[offset] << 8 | data[(offset) + 1]) | ^ ../lib/ethdev/sff_8636.c:620:25: note: ‘rx_power_offset’ was declared here 620 | uint8_t rx_power_offset, tx_bias_offset; | ^~~~~~~~~~~~~~~ [268/268] Linking target app/test/dpdk-test This is a false positive. This can be avoided using some tables: + const uint8_t rx_power_offset[MAX_CHANNEL_NUM] = { + SFF_8636_RX_PWR_1_OFFSET, + SFF_8636_RX_PWR_2_OFFSET, + SFF_8636_RX_PWR_3_OFFSET, + SFF_8636_RX_PWR_4_OFFSET, + }; + const uint8_t tx_power_offset[MAX_CHANNEL_NUM] = { + SFF_8636_TX_PWR_1_OFFSET, + SFF_8636_TX_PWR_2_OFFSET, + SFF_8636_TX_PWR_3_OFFSET, + SFF_8636_TX_PWR_4_OFFSET, + }; + const uint8_t tx_bias_offset[MAX_CHANNEL_NUM] = { + SFF_8636_TX_BIAS_1_OFFSET, + SFF_8636_TX_BIAS_2_OFFSET, + SFF_8636_TX_BIAS_3_OFFSET, + SFF_8636_TX_BIAS_4_OFFSET, + }; + sd->scd[i].bias_cur = OFFSET_TO_U16(tx_bias_offset[i]); + sd->scd[i].rx_power = OFFSET_TO_U16(rx_power_offset[i]); + sd->scd[i].tx_power = OFFSET_TO_U16(tx_power_offset[i]); -- David Marchand ^ permalink raw reply [flat|nested] 77+ messages in thread
* RE: [PATCH v7 5/5] ethdev: format module EEPROM for SFF-8636 2022-05-24 9:03 ` David Marchand @ 2022-05-25 2:43 ` Zhang, RobinX 0 siblings, 0 replies; 77+ messages in thread From: Zhang, RobinX @ 2022-05-25 2:43 UTC (permalink / raw) To: David Marchand; +Cc: dev, Thomas Monjalon, Andrew Rybchenko, Liu, KevinX Hi, David This is a good suggestion and I will adopt it, send v8. Thanks! > -----Original Message----- > From: David Marchand <david.marchand@redhat.com> > Sent: Tuesday, May 24, 2022 5:04 PM > To: Zhang, RobinX <robinx.zhang@intel.com> > Cc: dev <dev@dpdk.org>; Thomas Monjalon <thomas@monjalon.net>; > Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>; Liu, KevinX > <kevinx.liu@intel.com> > Subject: Re: [PATCH v7 5/5] ethdev: format module EEPROM for SFF-8636 > > Hello, > > I see a lot of switch / case where tables could do the job. > In any case, I'll focus only on one part of the code, that triggers a build > warning witch clang 14 (+ ASan): > > On Tue, May 24, 2022 at 8:31 AM Robin Zhang <robinx.zhang@intel.com> > wrote: > > + /* Channel Specific Data */ > > + for (i = 0; i < MAX_CHANNEL_NUM; i++) { > > + uint8_t rx_power_offset, tx_bias_offset; > > + uint8_t tx_power_offset; > > + > > + switch (i) { > > + case 0: > > + rx_power_offset = SFF_8636_RX_PWR_1_OFFSET; > > + tx_power_offset = SFF_8636_TX_PWR_1_OFFSET; > > + tx_bias_offset = SFF_8636_TX_BIAS_1_OFFSET; > > + break; > > + case 1: > > + rx_power_offset = SFF_8636_RX_PWR_2_OFFSET; > > + tx_power_offset = SFF_8636_TX_PWR_2_OFFSET; > > + tx_bias_offset = SFF_8636_TX_BIAS_2_OFFSET; > > + break; > > + case 2: > > + rx_power_offset = SFF_8636_RX_PWR_3_OFFSET; > > + tx_power_offset = SFF_8636_TX_PWR_3_OFFSET; > > + tx_bias_offset = SFF_8636_TX_BIAS_3_OFFSET; > > + break; > > + case 3: > > + rx_power_offset = SFF_8636_RX_PWR_4_OFFSET; > > + tx_power_offset = SFF_8636_TX_PWR_4_OFFSET; > > + tx_bias_offset = SFF_8636_TX_BIAS_4_OFFSET; > > + break; > > + } > > + sd->scd[i].bias_cur = OFFSET_TO_U16(tx_bias_offset); > > + sd->scd[i].rx_power = OFFSET_TO_U16(rx_power_offset); > > + sd->scd[i].tx_power = OFFSET_TO_U16(tx_power_offset); > > + } > > [15/442] Compiling C object lib/librte_ethdev.a.p/ethdev_sff_8636.c.o > In file included from ../lib/ethdev/sff_8636.c:13: > ../lib/ethdev/sff_common.h: In function ‘sff_8636_show_all’: > ../lib/ethdev/sff_common.h:101:22: warning: ‘tx_power_offset’ may be > used uninitialized [-Wmaybe-uninitialized] > 101 | (data[offset] << 8 | data[(offset) + 1]) > | ^ > ../lib/ethdev/sff_8636.c:621:25: note: ‘tx_power_offset’ was declared here > 621 | uint8_t tx_power_offset; > | ^~~~~~~~~~~~~~~ > ../lib/ethdev/sff_common.h:101:22: warning: ‘tx_bias_offset’ may be used > uninitialized [-Wmaybe-uninitialized] > 101 | (data[offset] << 8 | data[(offset) + 1]) > | ^ > ../lib/ethdev/sff_8636.c:620:42: note: ‘tx_bias_offset’ was declared here > 620 | uint8_t rx_power_offset, tx_bias_offset; > | ^~~~~~~~~~~~~~ > ../lib/ethdev/sff_common.h:101:22: warning: ‘rx_power_offset’ may be > used uninitialized [-Wmaybe-uninitialized] > 101 | (data[offset] << 8 | data[(offset) + 1]) > | ^ > ../lib/ethdev/sff_8636.c:620:25: note: ‘rx_power_offset’ was declared here > 620 | uint8_t rx_power_offset, tx_bias_offset; > | ^~~~~~~~~~~~~~~ > [268/268] Linking target app/test/dpdk-test > > > This is a false positive. > This can be avoided using some tables: > > + const uint8_t rx_power_offset[MAX_CHANNEL_NUM] = { > + SFF_8636_RX_PWR_1_OFFSET, > + SFF_8636_RX_PWR_2_OFFSET, > + SFF_8636_RX_PWR_3_OFFSET, > + SFF_8636_RX_PWR_4_OFFSET, > + }; > + const uint8_t tx_power_offset[MAX_CHANNEL_NUM] = { > + SFF_8636_TX_PWR_1_OFFSET, > + SFF_8636_TX_PWR_2_OFFSET, > + SFF_8636_TX_PWR_3_OFFSET, > + SFF_8636_TX_PWR_4_OFFSET, > + }; > + const uint8_t tx_bias_offset[MAX_CHANNEL_NUM] = { > + SFF_8636_TX_BIAS_1_OFFSET, > + SFF_8636_TX_BIAS_2_OFFSET, > + SFF_8636_TX_BIAS_3_OFFSET, > + SFF_8636_TX_BIAS_4_OFFSET, > + }; > + sd->scd[i].bias_cur = OFFSET_TO_U16(tx_bias_offset[i]); > + sd->scd[i].rx_power = OFFSET_TO_U16(rx_power_offset[i]); > + sd->scd[i].tx_power = OFFSET_TO_U16(tx_power_offset[i]); > > > -- > David Marchand ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v8 0/5] add telemetry command for show module EEPROM 2022-05-24 6:24 ` [PATCH v7 0/5] add telemetry command for show module EEPROM Robin Zhang ` (4 preceding siblings ...) 2022-05-24 6:24 ` [PATCH v7 5/5] ethdev: format module EEPROM for SFF-8636 Robin Zhang @ 2022-05-25 3:14 ` Robin Zhang 2022-05-25 3:14 ` [PATCH v8 1/5] ethdev: add telemetry command for " Robin Zhang ` (5 more replies) 5 siblings, 6 replies; 77+ messages in thread From: Robin Zhang @ 2022-05-25 3:14 UTC (permalink / raw) To: dev; +Cc: thomas, andrew.rybchenko, kevinx.liu, Robin Zhang Introduce a new telemetry command /ethdev/module_eeprom to show module EEPROM for each port. The format of module EEPROM information follows the SFF(Small Form Factor) Committee specifications. Current the format support SFP(Small Formfactor Pluggable)/SFP+/ QSFP+(Quad Small Formfactor Pluggable)/QSFP28 with specs SFF-8079/ SFF-8472/SFF-8024/SFF-8636. Afther run the /ethdev/module_eeprom command, telemetry client will show the module EEPROM information. We keep the same information content compare with Linux utility ethtool, refer to command 'ethtool -m' of ethtool v5.4. v8: - refine code v7: - remove "#include <arpa/inet.h>" in lib/ethdev/sff_8472.c v6: - refine code v5: - fix CI robot compile fail issue v4: - remove all printf in primary application, only show information in tememetry client - refine codes v3: - split up codes into several patches for better reivew Robin Zhang (5): ethdev: add telemetry command for module EEPROM ethdev: common utilities for different SFF specs ethdev: format module EEPROM for SFF-8079 ethdev: format module EEPROM for SFF-8472 ethdev: format module EEPROM for SFF-8636 lib/ethdev/ethdev_sff_telemetry.c | 149 ++++++ lib/ethdev/ethdev_sff_telemetry.h | 27 ++ lib/ethdev/meson.build | 5 + lib/ethdev/rte_ethdev.c | 3 + lib/ethdev/sff_8079.c | 406 ++++++++++++++++ lib/ethdev/sff_8472.c | 286 ++++++++++++ lib/ethdev/sff_8636.c | 750 ++++++++++++++++++++++++++++++ lib/ethdev/sff_8636.h | 611 ++++++++++++++++++++++++ lib/ethdev/sff_common.c | 326 +++++++++++++ lib/ethdev/sff_common.h | 174 +++++++ 10 files changed, 2737 insertions(+) create mode 100644 lib/ethdev/ethdev_sff_telemetry.c create mode 100644 lib/ethdev/ethdev_sff_telemetry.h create mode 100644 lib/ethdev/sff_8079.c create mode 100644 lib/ethdev/sff_8472.c create mode 100644 lib/ethdev/sff_8636.c create mode 100644 lib/ethdev/sff_8636.h create mode 100644 lib/ethdev/sff_common.c create mode 100644 lib/ethdev/sff_common.h -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v8 1/5] ethdev: add telemetry command for module EEPROM 2022-05-25 3:14 ` [PATCH v8 0/5] add telemetry command for show module EEPROM Robin Zhang @ 2022-05-25 3:14 ` Robin Zhang 2022-05-25 9:24 ` Andrew Rybchenko 2022-05-25 3:14 ` [PATCH v8 2/5] ethdev: common utilities for different SFF specs Robin Zhang ` (4 subsequent siblings) 5 siblings, 1 reply; 77+ messages in thread From: Robin Zhang @ 2022-05-25 3:14 UTC (permalink / raw) To: dev; +Cc: thomas, andrew.rybchenko, kevinx.liu, Robin Zhang Add a new telemetry command /ethdev/module_eeprom to dump the module EEPROM of each port. The format of module EEPROM information follows the SFF(Small Form Factor) Committee specifications. Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/ethdev_sff_telemetry.c | 138 ++++++++++++++++++++++++++++++ lib/ethdev/ethdev_sff_telemetry.h | 27 ++++++ lib/ethdev/meson.build | 1 + lib/ethdev/rte_ethdev.c | 3 + 4 files changed, 169 insertions(+) create mode 100644 lib/ethdev/ethdev_sff_telemetry.c create mode 100644 lib/ethdev/ethdev_sff_telemetry.h diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c new file mode 100644 index 0000000000..f756b9643f --- /dev/null +++ b/lib/ethdev/ethdev_sff_telemetry.c @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + */ + +#include <errno.h> + +#include <rte_ethdev.h> +#include <rte_common.h> +#include "ethdev_sff_telemetry.h" +#include "telemetry_data.h" + +static void +sff_port_module_eeprom_parse(uint16_t port_id, struct rte_tel_data *d) +{ + struct rte_eth_dev_module_info minfo; + struct rte_dev_eeprom_info einfo; + int ret; + + if (d == NULL) { + RTE_ETHDEV_LOG(ERR, "Dict invalid\n"); + return; + } + + ret = rte_eth_dev_get_module_info(port_id, &minfo); + if (ret != 0) { + switch (ret) { + case -ENODEV: + RTE_ETHDEV_LOG(ERR, "port index %d invalid\n", port_id); + break; + case -ENOTSUP: + RTE_ETHDEV_LOG(ERR, "operation not supported by device\n"); + break; + case -EIO: + RTE_ETHDEV_LOG(ERR, "device is removed\n"); + break; + default: + RTE_ETHDEV_LOG(ERR, "Unable to get port module info, %d\n", ret); + break; + } + return; + } + + einfo.offset = 0; + einfo.length = minfo.eeprom_len; + einfo.data = calloc(1, minfo.eeprom_len); + if (einfo.data == NULL) { + RTE_ETHDEV_LOG(ERR, "Allocation of port %u eeprom data failed\n", port_id); + return; + } + + ret = rte_eth_dev_get_module_eeprom(port_id, &einfo); + if (ret != 0) { + switch (ret) { + case -ENODEV: + RTE_ETHDEV_LOG(ERR, "port index %d invalid\n", port_id); + break; + case -ENOTSUP: + RTE_ETHDEV_LOG(ERR, "operation not supported by device\n"); + break; + case -EIO: + RTE_ETHDEV_LOG(ERR, "device is removed\n"); + break; + default: + RTE_ETHDEV_LOG(ERR, "Unable to get port module EEPROM, %d\n", ret); + break; + } + free(einfo.data); + return; + } + + switch (minfo.type) { + /* parsing module EEPROM data base on different module type */ + default: + RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); + break; + } + + free(einfo.data); +} + +void +ssf_add_dict_string(struct rte_tel_data *d, const char *name_str, const char *value_str) +{ + struct tel_dict_entry *e = &d->data.dict[d->data_len]; + + if (d->type != RTE_TEL_DICT) + return; + if (d->data_len >= RTE_TEL_MAX_DICT_ENTRIES) { + RTE_ETHDEV_LOG(ERR, "data_len has exceeded the maximum number of inserts\n"); + return; + } + + e->type = RTE_TEL_STRING_VAL; + /* append different values for same keys */ + if (d->data_len > 0) { + struct tel_dict_entry *previous = &d->data.dict[d->data_len - 1]; + if (strcmp(previous->name, name_str) == 0) { + strlcat(previous->value.sval, "; ", RTE_TEL_MAX_STRING_LEN); + strlcat(previous->value.sval, value_str, RTE_TEL_MAX_STRING_LEN); + goto end; + } + } + strlcpy(e->value.sval, value_str, RTE_TEL_MAX_STRING_LEN); + strlcpy(e->name, name_str, RTE_TEL_MAX_STRING_LEN); + d->data_len++; + +end: + return; +} + +int +eth_dev_handle_port_module_eeprom(const char *cmd __rte_unused, const char *params, + struct rte_tel_data *d) +{ + char *end_param; + int port_id; + + if (params == NULL || strlen(params) == 0 || !isdigit(*params)) + return -1; + + errno = 0; + port_id = strtoul(params, &end_param, 0); + + if (errno != 0) { + RTE_ETHDEV_LOG(ERR, "Invalid argument\n"); + return -1; + } + + if (*end_param != '\0') + RTE_ETHDEV_LOG(NOTICE, + "Extra parameters passed to ethdev telemetry command, ignoring\n"); + + rte_tel_data_start_dict(d); + + sff_port_module_eeprom_parse(port_id, d); + + return 0; +} diff --git a/lib/ethdev/ethdev_sff_telemetry.h b/lib/ethdev/ethdev_sff_telemetry.h new file mode 100644 index 0000000000..1fd870e0ef --- /dev/null +++ b/lib/ethdev/ethdev_sff_telemetry.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + */ + +#ifndef _ETHDEV_SFF_TELEMETRY_H_ +#define _ETHDEV_SFF_TELEMETRY_H_ + +#include <rte_telemetry.h> + +#define SFF_ITEM_VAL_COMPOSE_SIZE 64 + +/* SFF-8079 Optics diagnostics */ +void sff_8079_show_all(const uint8_t *data, struct rte_tel_data *d); + +/* SFF-8472 Optics diagnostics */ +void sff_8472_show_all(const uint8_t *data, struct rte_tel_data *d); + +/* SFF-8636 Optics diagnostics */ +void sff_8636_show_all(const uint8_t *data, uint32_t eeprom_len, struct rte_tel_data *d); + +int eth_dev_handle_port_module_eeprom(const char *cmd __rte_unused, + const char *params, + struct rte_tel_data *d); + +void ssf_add_dict_string(struct rte_tel_data *d, const char *name_str, const char *value_str); + +#endif /* _ETHDEV_SFF_TELEMETRY_H_ */ diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index a094585bf7..49c77acb3f 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -11,6 +11,7 @@ sources = files( 'rte_flow.c', 'rte_mtr.c', 'rte_tm.c', + 'ethdev_sff_telemetry.c', ) headers = files( diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c index 29a3d80466..2b87df1b32 100644 --- a/lib/ethdev/rte_ethdev.c +++ b/lib/ethdev/rte_ethdev.c @@ -39,6 +39,7 @@ #include "ethdev_driver.h" #include "ethdev_profile.h" #include "ethdev_private.h" +#include "ethdev_sff_telemetry.h" struct rte_eth_dev rte_eth_devices[RTE_MAX_ETHPORTS]; @@ -5876,4 +5877,6 @@ RTE_INIT(ethdev_init_telemetry) "Returns the link status for a port. Parameters: int port_id"); rte_telemetry_register_cmd("/ethdev/info", eth_dev_handle_port_info, "Returns the device info for a port. Parameters: int port_id"); + rte_telemetry_register_cmd("/ethdev/module_eeprom", eth_dev_handle_port_module_eeprom, + "Returns module EEPROM info with SFF specs. Parameters: int port_id"); } -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v8 1/5] ethdev: add telemetry command for module EEPROM 2022-05-25 3:14 ` [PATCH v8 1/5] ethdev: add telemetry command for " Robin Zhang @ 2022-05-25 9:24 ` Andrew Rybchenko 0 siblings, 0 replies; 77+ messages in thread From: Andrew Rybchenko @ 2022-05-25 9:24 UTC (permalink / raw) To: Robin Zhang, dev; +Cc: thomas, kevinx.liu On 5/25/22 06:14, Robin Zhang wrote: > Add a new telemetry command /ethdev/module_eeprom to dump the module > EEPROM of each port. The format of module EEPROM information follows > the SFF(Small Form Factor) Committee specifications. Please, add SFF to devtools/words-case.txt > > Signed-off-by: Robin Zhang <robinx.zhang@intel.com> > --- > lib/ethdev/ethdev_sff_telemetry.c | 138 ++++++++++++++++++++++++++++++ > lib/ethdev/ethdev_sff_telemetry.h | 27 ++++++ I think we should be consistent with naming. Other patches name added files as sff_*.[ch]. I see no strong reason to have ethdev_ prefix here. sff_ prefix should be sufficient. > lib/ethdev/meson.build | 1 + > lib/ethdev/rte_ethdev.c | 3 + > 4 files changed, 169 insertions(+) > create mode 100644 lib/ethdev/ethdev_sff_telemetry.c > create mode 100644 lib/ethdev/ethdev_sff_telemetry.h > > diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c > new file mode 100644 > index 0000000000..f756b9643f > --- /dev/null > +++ b/lib/ethdev/ethdev_sff_telemetry.c > @@ -0,0 +1,138 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2022 Intel Corporation > + */ > + > +#include <errno.h> > + > +#include <rte_ethdev.h> Other C files in ethdev use double-quotes to include headers provided by the library itself. Also it should go after headers provided by other DPDK libraries. > +#include <rte_common.h> > +#include "ethdev_sff_telemetry.h" > +#include "telemetry_data.h" Why are double quotes used for the include? It is a header from other DPDK library similar to rte_common.h. > + > +static void > +sff_port_module_eeprom_parse(uint16_t port_id, struct rte_tel_data *d) > +{ > + struct rte_eth_dev_module_info minfo; > + struct rte_dev_eeprom_info einfo; > + int ret; > + > + if (d == NULL) { > + RTE_ETHDEV_LOG(ERR, "Dict invalid\n"); > + return; > + } > + > + ret = rte_eth_dev_get_module_info(port_id, &minfo); > + if (ret != 0) { > + switch (ret) { > + case -ENODEV: > + RTE_ETHDEV_LOG(ERR, "port index %d invalid\n", port_id); The majority of ethdev logs start from capital letter. Please, be consistent. > + break; > + case -ENOTSUP: > + RTE_ETHDEV_LOG(ERR, "operation not supported by device\n"); same here > + break; > + case -EIO: > + RTE_ETHDEV_LOG(ERR, "device is removed\n"); same here > + break; > + default: > + RTE_ETHDEV_LOG(ERR, "Unable to get port module info, %d\n", ret); > + break; > + } > + return; > + } > + > + einfo.offset = 0; > + einfo.length = minfo.eeprom_len; > + einfo.data = calloc(1, minfo.eeprom_len); > + if (einfo.data == NULL) { > + RTE_ETHDEV_LOG(ERR, "Allocation of port %u eeprom data failed\n", port_id); Please, be consistent in logging: eeprom -> EEPROM as below > + errno = 0; > + port_id = strtoul(params, &end_param, 0); > + > + if (errno != 0) { > + RTE_ETHDEV_LOG(ERR, "Invalid argument\n"); Please, log the invalid argument (params). > + return -1; > + } > + > + if (*end_param != '\0') > + RTE_ETHDEV_LOG(NOTICE, > + "Extra parameters passed to ethdev telemetry command, ignoring\n"); I think it would be very useful to log these extra parameters. > + > + rte_tel_data_start_dict(d); > + > + sff_port_module_eeprom_parse(port_id, d); > + > + return 0; > +} [snip] ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v8 2/5] ethdev: common utilities for different SFF specs 2022-05-25 3:14 ` [PATCH v8 0/5] add telemetry command for show module EEPROM Robin Zhang 2022-05-25 3:14 ` [PATCH v8 1/5] ethdev: add telemetry command for " Robin Zhang @ 2022-05-25 3:14 ` Robin Zhang 2022-05-25 8:51 ` Andrew Rybchenko 2022-05-25 9:40 ` Andrew Rybchenko 2022-05-25 3:14 ` [PATCH v8 3/5] ethdev: format module EEPROM for SFF-8079 Robin Zhang ` (3 subsequent siblings) 5 siblings, 2 replies; 77+ messages in thread From: Robin Zhang @ 2022-05-25 3:14 UTC (permalink / raw) To: dev; +Cc: thomas, andrew.rybchenko, kevinx.liu, Robin Zhang This patch implements SFF-8024 Rev 4.0 of pluggable I/O configuration and some common utilities for SFF-8436/8636 and SFF-8472/8079. Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/meson.build | 1 + lib/ethdev/sff_common.c | 326 ++++++++++++++++++++++++++++++++++++++++ lib/ethdev/sff_common.h | 174 +++++++++++++++++++++ 3 files changed, 501 insertions(+) create mode 100644 lib/ethdev/sff_common.c create mode 100644 lib/ethdev/sff_common.h diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index 49c77acb3f..8f39739e43 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -12,6 +12,7 @@ sources = files( 'rte_mtr.c', 'rte_tm.c', 'ethdev_sff_telemetry.c', + 'sff_common.c', ) headers = files( diff --git a/lib/ethdev/sff_common.c b/lib/ethdev/sff_common.c new file mode 100644 index 0000000000..06d96fac72 --- /dev/null +++ b/lib/ethdev/sff_common.c @@ -0,0 +1,326 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8024 Rev 4.0 of pluggable I/O configuration and some + * common utilities for SFF-8436/8636 and SFF-8472/8079 + * + */ + +#include <stdio.h> +#include <math.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "ethdev_sff_telemetry.h" + + +double convert_mw_to_dbm(double mw) +{ + return (10. * log10(mw / 1000.)) + 30.; +} + +void sff_show_value_with_unit(const uint8_t *data, unsigned int reg, + const char *name, unsigned int mult, + const char *unit, struct rte_tel_data *d) +{ + unsigned int val = data[reg]; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "%u%s", val * mult, unit); + ssf_add_dict_string(d, name, val_string); +} + +void sff_show_ascii(const uint8_t *data, unsigned int first_reg, + unsigned int last_reg, const char *name, struct rte_tel_data *d) +{ + unsigned int reg, val; + char tmp[3]; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + memset(val_string, 0, sizeof(val_string)); + + while (first_reg <= last_reg && data[last_reg] == ' ') + last_reg--; + for (reg = first_reg; reg <= last_reg; reg++) { + val = data[reg]; + if ((val >= 32) && (val <= 126)) { + snprintf(tmp, sizeof(tmp), "%c", val); + strlcat(val_string, tmp, sizeof(val_string)); + } else { + strlcat(val_string, "_", sizeof(val_string)); + } + } + ssf_add_dict_string(d, name, val_string); +} + +void sff_8024_show_oui(const uint8_t *data, int id_offset, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "%02x:%02x:%02x", + data[id_offset], data[(id_offset) + 1], data[(id_offset) + 2]); + ssf_add_dict_string(d, "Vendor OUI", val_string); +} + +void sff_8024_show_identifier(const uint8_t *data, int id_offset, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[id_offset]); + + switch (data[id_offset]) { + case SFF_8024_ID_UNKNOWN: + strlcat(val_string, " (no module present, unknown, or unspecified)", + sizeof(val_string)); + break; + case SFF_8024_ID_GBIC: + strlcat(val_string, " (GBIC)", sizeof(val_string)); + break; + case SFF_8024_ID_SOLDERED_MODULE: + strlcat(val_string, " (module soldered to motherboard)", sizeof(val_string)); + break; + case SFF_8024_ID_SFP: + strlcat(val_string, " (SFP)", sizeof(val_string)); + break; + case SFF_8024_ID_300_PIN_XBI: + strlcat(val_string, " (300 pin XBI)", sizeof(val_string)); + break; + case SFF_8024_ID_XENPAK: + strlcat(val_string, " (XENPAK)", sizeof(val_string)); + break; + case SFF_8024_ID_XFP: + strlcat(val_string, " (XFP)", sizeof(val_string)); + break; + case SFF_8024_ID_XFF: + strlcat(val_string, " (XFF)", sizeof(val_string)); + break; + case SFF_8024_ID_XFP_E: + strlcat(val_string, " (XFP-E)", sizeof(val_string)); + break; + case SFF_8024_ID_XPAK: + strlcat(val_string, " (XPAK)", sizeof(val_string)); + break; + case SFF_8024_ID_X2: + strlcat(val_string, " (X2)", sizeof(val_string)); + break; + case SFF_8024_ID_DWDM_SFP: + strlcat(val_string, " (DWDM-SFP)", sizeof(val_string)); + break; + case SFF_8024_ID_QSFP: + strlcat(val_string, " (QSFP)", sizeof(val_string)); + break; + case SFF_8024_ID_QSFP_PLUS: + strlcat(val_string, " (QSFP+)", sizeof(val_string)); + break; + case SFF_8024_ID_CXP: + strlcat(val_string, " (CXP)", sizeof(val_string)); + break; + case SFF_8024_ID_HD4X: + strlcat(val_string, " (Shielded Mini Multilane HD 4X)", sizeof(val_string)); + break; + case SFF_8024_ID_HD8X: + strlcat(val_string, " (Shielded Mini Multilane HD 8X)", sizeof(val_string)); + break; + case SFF_8024_ID_QSFP28: + strlcat(val_string, " (QSFP28)", sizeof(val_string)); + break; + case SFF_8024_ID_CXP2: + strlcat(val_string, " (CXP2/CXP28)", sizeof(val_string)); + break; + case SFF_8024_ID_CDFP: + strlcat(val_string, " (CDFP Style 1/Style 2)", sizeof(val_string)); + break; + case SFF_8024_ID_HD4X_FANOUT: + strlcat(val_string, " (Shielded Mini Multilane HD 4X Fanout Cable)", + sizeof(val_string)); + break; + case SFF_8024_ID_HD8X_FANOUT: + strlcat(val_string, " (Shielded Mini Multilane HD 8X Fanout Cable)", + sizeof(val_string)); + break; + case SFF_8024_ID_CDFP_S3: + strlcat(val_string, " (CDFP Style 3)", sizeof(val_string)); + break; + case SFF_8024_ID_MICRO_QSFP: + strlcat(val_string, " (microQSFP)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + ssf_add_dict_string(d, "Identifier", val_string); +} + +void sff_8024_show_connector(const uint8_t *data, int ctor_offset, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[ctor_offset]); + + switch (data[ctor_offset]) { + case SFF_8024_CTOR_UNKNOWN: + strlcat(val_string, " (unknown or unspecified)", sizeof(val_string)); + break; + case SFF_8024_CTOR_SC: + strlcat(val_string, " (SC)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FC_STYLE_1: + strlcat(val_string, " (Fibre Channel Style 1 copper)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FC_STYLE_2: + strlcat(val_string, " (Fibre Channel Style 2 copper)", sizeof(val_string)); + break; + case SFF_8024_CTOR_BNC_TNC: + strlcat(val_string, " (BNC/TNC)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FC_COAX: + strlcat(val_string, " (Fibre Channel coaxial headers)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FIBER_JACK: + strlcat(val_string, " (FibreJack)", sizeof(val_string)); + break; + case SFF_8024_CTOR_LC: + strlcat(val_string, " (LC)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MT_RJ: + strlcat(val_string, " (MT-RJ)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MU: + strlcat(val_string, " (MU)", sizeof(val_string)); + break; + case SFF_8024_CTOR_SG: + strlcat(val_string, " (SG)", sizeof(val_string)); + break; + case SFF_8024_CTOR_OPT_PT: + strlcat(val_string, " (Optical pigtail)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MPO: + strlcat(val_string, " (MPO Parallel Optic)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MPO_2: + strlcat(val_string, " (MPO Parallel Optic - 2x16)", sizeof(val_string)); + break; + case SFF_8024_CTOR_HSDC_II: + strlcat(val_string, " (HSSDC II)", sizeof(val_string)); + break; + case SFF_8024_CTOR_COPPER_PT: + strlcat(val_string, " (Copper pigtail)", sizeof(val_string)); + break; + case SFF_8024_CTOR_RJ45: + strlcat(val_string, " (RJ45)", sizeof(val_string)); + break; + case SFF_8024_CTOR_NO_SEPARABLE: + strlcat(val_string, " (No separable connector)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MXC_2x16: + strlcat(val_string, " (MXC 2x16)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + ssf_add_dict_string(d, "Connector", val_string); +} + +void sff_8024_show_encoding(const uint8_t *data, int encoding_offset, + int sff_type, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[encoding_offset]); + + switch (data[encoding_offset]) { + case SFF_8024_ENCODING_UNSPEC: + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_8B10B: + strlcat(val_string, " (8B/10B)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_4B5B: + strlcat(val_string, " (4B/5B)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_NRZ: + strlcat(val_string, " (NRZ)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_4h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) + strlcat(val_string, " (Manchester)", sizeof(val_string)); + else if (sff_type == RTE_ETH_MODULE_SFF_8636) + strlcat(val_string, " (SONET Scrambled)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_5h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) + strlcat(val_string, " (SONET Scrambled)", sizeof(val_string)); + else if (sff_type == RTE_ETH_MODULE_SFF_8636) + strlcat(val_string, " (64B/66B)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_6h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) + strlcat(val_string, " (64B/66B)", sizeof(val_string)); + else if (sff_type == RTE_ETH_MODULE_SFF_8636) + strlcat(val_string, " (Manchester)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_256B: + strlcat(val_string, + " ((256B/257B (transcoded FEC-enabled data))", sizeof(val_string)); + break; + case SFF_8024_ENCODING_PAM4: + strlcat(val_string, " (PAM4)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + ssf_add_dict_string(d, "Encoding", val_string); +} + +void sff_show_thresholds(struct sff_diags sd, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + SPRINT_BIAS(val_string, sd.bias_cur[HALRM]); + ssf_add_dict_string(d, "Laser bias current high alarm threshold", val_string); + SPRINT_BIAS(val_string, sd.bias_cur[LALRM]); + ssf_add_dict_string(d, "Laser bias current low alarm threshold", val_string); + SPRINT_BIAS(val_string, sd.bias_cur[HWARN]); + ssf_add_dict_string(d, "Laser bias current high warning threshold", val_string); + SPRINT_BIAS(val_string, sd.bias_cur[LWARN]); + ssf_add_dict_string(d, "Laser bias current low warning threshold", val_string); + + SPRINT_xX_PWR(val_string, sd.tx_power[HALRM]); + ssf_add_dict_string(d, "Laser output power high alarm threshold", val_string); + SPRINT_xX_PWR(val_string, sd.tx_power[LALRM]); + ssf_add_dict_string(d, "Laser output power low alarm threshold", val_string); + SPRINT_xX_PWR(val_string, sd.tx_power[HWARN]); + ssf_add_dict_string(d, "Laser output power high warning threshold", val_string); + SPRINT_xX_PWR(val_string, sd.tx_power[LWARN]); + ssf_add_dict_string(d, "Laser output power low warning threshold", val_string); + + SPRINT_TEMP(val_string, sd.sfp_temp[HALRM]); + ssf_add_dict_string(d, "Module temperature high alarm threshold", val_string); + SPRINT_TEMP(val_string, sd.sfp_temp[LALRM]); + ssf_add_dict_string(d, "Module temperature low alarm threshold", val_string); + SPRINT_TEMP(val_string, sd.sfp_temp[HWARN]); + ssf_add_dict_string(d, "Module temperature high warning threshold", val_string); + SPRINT_TEMP(val_string, sd.sfp_temp[LWARN]); + ssf_add_dict_string(d, "Module temperature low warning threshold", val_string); + + SPRINT_VCC(val_string, sd.sfp_voltage[HALRM]); + ssf_add_dict_string(d, "Module voltage high alarm threshold", val_string); + SPRINT_VCC(val_string, sd.sfp_voltage[LALRM]); + ssf_add_dict_string(d, "Module voltage low alarm threshold", val_string); + SPRINT_VCC(val_string, sd.sfp_voltage[HWARN]); + ssf_add_dict_string(d, "Module voltage high warning threshold", val_string); + SPRINT_VCC(val_string, sd.sfp_voltage[LWARN]); + ssf_add_dict_string(d, "Module voltage low alarm threshold", val_string); + + SPRINT_xX_PWR(val_string, sd.rx_power[HALRM]); + ssf_add_dict_string(d, "Laser rx power high alarm threshold", val_string); + SPRINT_xX_PWR(val_string, sd.rx_power[LALRM]); + ssf_add_dict_string(d, "Laser rx power low alarm threshold", val_string); + SPRINT_xX_PWR(val_string, sd.rx_power[HWARN]); + ssf_add_dict_string(d, "Laser rx power high warning threshold", val_string); + SPRINT_xX_PWR(val_string, sd.rx_power[LWARN]); + ssf_add_dict_string(d, "Laser rx power low warning threshold", val_string); +} diff --git a/lib/ethdev/sff_common.h b/lib/ethdev/sff_common.h new file mode 100644 index 0000000000..264fb915cd --- /dev/null +++ b/lib/ethdev/sff_common.h @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8024 Rev 4.0 of pluggable I/O configuration and some + * common utilities for SFF-8436/8636 and SFF-8472/8079 + * + */ + +#ifndef _SFF_COMMON_H_ +#define _SFF_COMMON_H_ + +#include <stdio.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "ethdev_sff_telemetry.h" + +#define SFF_8024_ID_OFFSET 0x00 +#define SFF_8024_ID_UNKNOWN 0x00 +#define SFF_8024_ID_GBIC 0x01 +#define SFF_8024_ID_SOLDERED_MODULE 0x02 +#define SFF_8024_ID_SFP 0x03 +#define SFF_8024_ID_300_PIN_XBI 0x04 +#define SFF_8024_ID_XENPAK 0x05 +#define SFF_8024_ID_XFP 0x06 +#define SFF_8024_ID_XFF 0x07 +#define SFF_8024_ID_XFP_E 0x08 +#define SFF_8024_ID_XPAK 0x09 +#define SFF_8024_ID_X2 0x0A +#define SFF_8024_ID_DWDM_SFP 0x0B +#define SFF_8024_ID_QSFP 0x0C +#define SFF_8024_ID_QSFP_PLUS 0x0D +#define SFF_8024_ID_CXP 0x0E +#define SFF_8024_ID_HD4X 0x0F +#define SFF_8024_ID_HD8X 0x10 +#define SFF_8024_ID_QSFP28 0x11 +#define SFF_8024_ID_CXP2 0x12 +#define SFF_8024_ID_CDFP 0x13 +#define SFF_8024_ID_HD4X_FANOUT 0x14 +#define SFF_8024_ID_HD8X_FANOUT 0x15 +#define SFF_8024_ID_CDFP_S3 0x16 +#define SFF_8024_ID_MICRO_QSFP 0x17 +#define SFF_8024_ID_LAST SFF_8024_ID_MICRO_QSFP +#define SFF_8024_ID_UNALLOCATED_LAST 0x7F +#define SFF_8024_ID_VENDOR_START 0x80 +#define SFF_8024_ID_VENDOR_LAST 0xFF + +#define SFF_8024_CTOR_UNKNOWN 0x00 +#define SFF_8024_CTOR_SC 0x01 +#define SFF_8024_CTOR_FC_STYLE_1 0x02 +#define SFF_8024_CTOR_FC_STYLE_2 0x03 +#define SFF_8024_CTOR_BNC_TNC 0x04 +#define SFF_8024_CTOR_FC_COAX 0x05 +#define SFF_8024_CTOR_FIBER_JACK 0x06 +#define SFF_8024_CTOR_LC 0x07 +#define SFF_8024_CTOR_MT_RJ 0x08 +#define SFF_8024_CTOR_MU 0x09 +#define SFF_8024_CTOR_SG 0x0A +#define SFF_8024_CTOR_OPT_PT 0x0B +#define SFF_8024_CTOR_MPO 0x0C +#define SFF_8024_CTOR_MPO_2 0x0D +/* 0E-1Fh --- Reserved */ +#define SFF_8024_CTOR_HSDC_II 0x20 +#define SFF_8024_CTOR_COPPER_PT 0x21 +#define SFF_8024_CTOR_RJ45 0x22 +#define SFF_8024_CTOR_NO_SEPARABLE 0x23 +#define SFF_8024_CTOR_MXC_2x16 0x24 +#define SFF_8024_CTOR_LAST SFF_8024_CTOR_MXC_2x16 +#define SFF_8024_CTOR_UNALLOCATED_LAST 0x7F +#define SFF_8024_CTOR_VENDOR_START 0x80 +#define SFF_8024_CTOR_VENDOR_LAST 0xFF + +/* ENCODING Values */ +#define SFF_8024_ENCODING_UNSPEC 0x00 +#define SFF_8024_ENCODING_8B10B 0x01 +#define SFF_8024_ENCODING_4B5B 0x02 +#define SFF_8024_ENCODING_NRZ 0x03 +/* + * Value: 04h + * SFF-8472 - Manchester + * SFF-8436/8636 - SONET Scrambled + */ +#define SFF_8024_ENCODING_4h 0x04 +/* + * Value: 05h + * SFF-8472 - SONET Scrambled + * SFF-8436/8636 - 64B/66B + */ +#define SFF_8024_ENCODING_5h 0x05 +/* + * Value: 06h + * SFF-8472 - 64B/66B + * SFF-8436/8636 - Manchester + */ +#define SFF_8024_ENCODING_6h 0x06 +#define SFF_8024_ENCODING_256B 0x07 +#define SFF_8024_ENCODING_PAM4 0x08 + +/* Most common case: 16-bit unsigned integer in a certain unit */ +#define OFFSET_TO_U16(offset) \ + (data[offset] << 8 | data[(offset) + 1]) + +#define SPRINT_xX_PWR(str, var) \ + snprintf(str, sizeof(str), "%.4f mW / %.2f dBm", \ + (double)((var) / 10000.), \ + convert_mw_to_dbm((double)((var) / 10000.))) + +#define SPRINT_BIAS(str, bias_cur) \ + snprintf(str, sizeof(str), "%.3f mA", (double)(bias_cur / 500.)) + +#define SPRINT_TEMP(str, temp) \ + snprintf(str, sizeof(str), "%.2f degrees C / %.2f degrees F", \ + (double)(temp / 256.), \ + (double)(temp / 256. * 1.8 + 32.)) + +#define SPRINT_VCC(str, sfp_voltage) \ + snprintf(str, sizeof(str), "%.4f V", (double)(sfp_voltage / 10000.)) + +/* Channel Monitoring Fields */ +struct sff_channel_diags { + uint16_t bias_cur; /* Measured bias current in 2uA units */ + uint16_t rx_power; /* Measured RX Power */ + uint16_t tx_power; /* Measured TX Power */ +}; + +/* Module Monitoring Fields */ +struct sff_diags { + +#define MAX_CHANNEL_NUM 4 +#define LWARN 0 +#define HWARN 1 +#define LALRM 2 +#define HALRM 3 +#define MCURR 4 + + /* Supports DOM */ + uint8_t supports_dom; + /* Supports alarm/warning thold */ + uint8_t supports_alarms; + /* RX Power: 0 = OMA, 1 = Average power */ + uint8_t rx_power_type; + /* TX Power: 0 = Not supported, 1 = Average power */ + uint8_t tx_power_type; + + uint8_t calibrated_ext; /* Is externally calibrated */ + /* [5] tables are low/high warn, low/high alarm, current */ + /* SFP voltage in 0.1mV units */ + uint16_t sfp_voltage[5]; + /* SFP Temp in 16-bit signed 1/256 Celcius */ + int16_t sfp_temp[5]; + /* Measured bias current in 2uA units */ + uint16_t bias_cur[5]; + /* Measured TX Power */ + uint16_t tx_power[5]; + /* Measured RX Power */ + uint16_t rx_power[5]; + struct sff_channel_diags scd[MAX_CHANNEL_NUM]; +}; + +double convert_mw_to_dbm(double mw); +void sff_show_value_with_unit(const uint8_t *data, unsigned int reg, + const char *name, unsigned int mult, + const char *unit, struct rte_tel_data *d); +void sff_show_ascii(const uint8_t *data, unsigned int first_reg, + unsigned int last_reg, const char *name, struct rte_tel_data *d); +void sff_show_thresholds(struct sff_diags sd, struct rte_tel_data *d); + +void sff_8024_show_oui(const uint8_t *data, int id_offset, struct rte_tel_data *d); +void sff_8024_show_identifier(const uint8_t *data, int id_offset, struct rte_tel_data *d); +void sff_8024_show_connector(const uint8_t *data, int ctor_offset, struct rte_tel_data *d); +void sff_8024_show_encoding(const uint8_t *data, int encoding_offset, + int sff_type, struct rte_tel_data *d); + +#endif /* _SFF_COMMON_H_ */ -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v8 2/5] ethdev: common utilities for different SFF specs 2022-05-25 3:14 ` [PATCH v8 2/5] ethdev: common utilities for different SFF specs Robin Zhang @ 2022-05-25 8:51 ` Andrew Rybchenko 2022-05-25 9:40 ` Andrew Rybchenko 1 sibling, 0 replies; 77+ messages in thread From: Andrew Rybchenko @ 2022-05-25 8:51 UTC (permalink / raw) To: Robin Zhang, dev; +Cc: thomas, kevinx.liu On 5/25/22 06:14, Robin Zhang wrote: > This patch implements SFF-8024 Rev 4.0 of pluggable I/O configuration > and some common utilities for SFF-8436/8636 and SFF-8472/8079. > > Signed-off-by: Robin Zhang <robinx.zhang@intel.com> [snip] checkpatches.sh complains on the following, please, fix: > + /* SFP Temp in 16-bit signed 1/256 Celcius */ Celcius -> Celsius ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v8 2/5] ethdev: common utilities for different SFF specs 2022-05-25 3:14 ` [PATCH v8 2/5] ethdev: common utilities for different SFF specs Robin Zhang 2022-05-25 8:51 ` Andrew Rybchenko @ 2022-05-25 9:40 ` Andrew Rybchenko 1 sibling, 0 replies; 77+ messages in thread From: Andrew Rybchenko @ 2022-05-25 9:40 UTC (permalink / raw) To: Robin Zhang, dev; +Cc: thomas, kevinx.liu Summary must not be a statement. Consider: "add common code for different SFF specs" or something like this. On 5/25/22 06:14, Robin Zhang wrote: > This patch implements SFF-8024 Rev 4.0 of pluggable I/O configuration "This patch implements" -> "Add support for" Basicaly "This patches" does not make sense. It the description of the patch in any case. > and some common utilities for SFF-8436/8636 and SFF-8472/8079. > > Signed-off-by: Robin Zhang <robinx.zhang@intel.com> > --- > lib/ethdev/meson.build | 1 + > lib/ethdev/sff_common.c | 326 ++++++++++++++++++++++++++++++++++++++++ > lib/ethdev/sff_common.h | 174 +++++++++++++++++++++ > 3 files changed, 501 insertions(+) > create mode 100644 lib/ethdev/sff_common.c > create mode 100644 lib/ethdev/sff_common.h > > diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build > index 49c77acb3f..8f39739e43 100644 > --- a/lib/ethdev/meson.build > +++ b/lib/ethdev/meson.build > @@ -12,6 +12,7 @@ sources = files( > 'rte_mtr.c', > 'rte_tm.c', > 'ethdev_sff_telemetry.c', > + 'sff_common.c', > ) > > headers = files( > diff --git a/lib/ethdev/sff_common.c b/lib/ethdev/sff_common.c > new file mode 100644 > index 0000000000..06d96fac72 > --- /dev/null > +++ b/lib/ethdev/sff_common.c > @@ -0,0 +1,326 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2022 Intel Corporation > + * > + * Implements SFF-8024 Rev 4.0 of pluggable I/O configuration and some > + * common utilities for SFF-8436/8636 and SFF-8472/8079 > + * Please, remove above extra empty line. > + */ > + > +#include <stdio.h> > +#include <math.h> Please, add empty line after system headers. > +#include <rte_mbuf.h> Why do you need rte_mbuf.h? > +#include <rte_ethdev.h> Do you really need it? Looks like no. > +#include <rte_flow.h> Why do you need rte_flow.h? > +#include "sff_common.h" > +#include "ethdev_sff_telemetry.h" Library headers should go last and should be included using double quotes. [snip] > diff --git a/lib/ethdev/sff_common.h b/lib/ethdev/sff_common.h > new file mode 100644 > index 0000000000..264fb915cd > --- /dev/null > +++ b/lib/ethdev/sff_common.h > @@ -0,0 +1,174 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2022 Intel Corporation > + * > + * Implements SFF-8024 Rev 4.0 of pluggable I/O configuration and some > + * common utilities for SFF-8436/8636 and SFF-8472/8079 > + * > + */ > + > +#ifndef _SFF_COMMON_H_ > +#define _SFF_COMMON_H_ > + > +#include <stdio.h> > +#include <rte_mbuf.h> > +#include <rte_ethdev.h> > +#include <rte_flow.h> > +#include "ethdev_sff_telemetry.h" same comments about headers > +/* Most common case: 16-bit unsigned integer in a certain unit */ > +#define OFFSET_TO_U16(offset) \ > + (data[offset] << 8 | data[(offset) + 1]) Please, add SFF_ prefix to all these macros. It will match sff_ prefix of the header name and make it clear in the code which uses these macros. > + > +#define SPRINT_xX_PWR(str, var) \ SNPRINT_xX_PWR to highlight that it should be safe printing to a string > + snprintf(str, sizeof(str), "%.4f mW / %.2f dBm", \ > + (double)((var) / 10000.), \ > + convert_mw_to_dbm((double)((var) / 10000.))) > + > +#define SPRINT_BIAS(str, bias_cur) \ same here > + snprintf(str, sizeof(str), "%.3f mA", (double)(bias_cur / 500.)) > + > +#define SPRINT_TEMP(str, temp) \ same here > + snprintf(str, sizeof(str), "%.2f degrees C / %.2f degrees F", \ > + (double)(temp / 256.), \ > + (double)(temp / 256. * 1.8 + 32.)) > + > +#define SPRINT_VCC(str, sfp_voltage) \ same here > + snprintf(str, sizeof(str), "%.4f V", (double)(sfp_voltage / 10000.)) > + > +/* Channel Monitoring Fields */ > +struct sff_channel_diags { > + uint16_t bias_cur; /* Measured bias current in 2uA units */ > + uint16_t rx_power; /* Measured RX Power */ > + uint16_t tx_power; /* Measured TX Power */ > +}; > + > +/* Module Monitoring Fields */ > +struct sff_diags { > + > +#define MAX_CHANNEL_NUM 4 > +#define LWARN 0 > +#define HWARN 1 > +#define LALRM 2 > +#define HALRM 3 > +#define MCURR 4 Please, add prefix to these defines as well. > + > + /* Supports DOM */ > + uint8_t supports_dom; > + /* Supports alarm/warning thold */ > + uint8_t supports_alarms; > + /* RX Power: 0 = OMA, 1 = Average power */ > + uint8_t rx_power_type; > + /* TX Power: 0 = Not supported, 1 = Average power */ > + uint8_t tx_power_type; > + > + uint8_t calibrated_ext; /* Is externally calibrated */ > + /* [5] tables are low/high warn, low/high alarm, current */ > + /* SFP voltage in 0.1mV units */ > + uint16_t sfp_voltage[5]; > + /* SFP Temp in 16-bit signed 1/256 Celcius */ > + int16_t sfp_temp[5]; > + /* Measured bias current in 2uA units */ > + uint16_t bias_cur[5]; > + /* Measured TX Power */ > + uint16_t tx_power[5]; > + /* Measured RX Power */ > + uint16_t rx_power[5]; > + struct sff_channel_diags scd[MAX_CHANNEL_NUM]; > +}; > + > +double convert_mw_to_dbm(double mw); Please, add sff_ prefix > +void sff_show_value_with_unit(const uint8_t *data, unsigned int reg, > + const char *name, unsigned int mult, > + const char *unit, struct rte_tel_data *d); > +void sff_show_ascii(const uint8_t *data, unsigned int first_reg, > + unsigned int last_reg, const char *name, struct rte_tel_data *d); > +void sff_show_thresholds(struct sff_diags sd, struct rte_tel_data *d); > + > +void sff_8024_show_oui(const uint8_t *data, int id_offset, struct rte_tel_data *d); > +void sff_8024_show_identifier(const uint8_t *data, int id_offset, struct rte_tel_data *d); > +void sff_8024_show_connector(const uint8_t *data, int ctor_offset, struct rte_tel_data *d); > +void sff_8024_show_encoding(const uint8_t *data, int encoding_offset, > + int sff_type, struct rte_tel_data *d); > + > +#endif /* _SFF_COMMON_H_ */ ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v8 3/5] ethdev: format module EEPROM for SFF-8079 2022-05-25 3:14 ` [PATCH v8 0/5] add telemetry command for show module EEPROM Robin Zhang 2022-05-25 3:14 ` [PATCH v8 1/5] ethdev: add telemetry command for " Robin Zhang 2022-05-25 3:14 ` [PATCH v8 2/5] ethdev: common utilities for different SFF specs Robin Zhang @ 2022-05-25 3:14 ` Robin Zhang 2022-05-25 9:55 ` Andrew Rybchenko 2022-05-25 3:14 ` [PATCH v8 4/5] ethdev: format module EEPROM for SFF-8472 Robin Zhang ` (2 subsequent siblings) 5 siblings, 1 reply; 77+ messages in thread From: Robin Zhang @ 2022-05-25 3:14 UTC (permalink / raw) To: dev; +Cc: thomas, andrew.rybchenko, kevinx.liu, Robin Zhang This patch implements format module EEPROM information for SFF-8079 Rev 1.7 Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/ethdev_sff_telemetry.c | 3 + lib/ethdev/meson.build | 1 + lib/ethdev/sff_8079.c | 406 ++++++++++++++++++++++++++++++ 3 files changed, 410 insertions(+) create mode 100644 lib/ethdev/sff_8079.c diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c index f756b9643f..63b0d21786 100644 --- a/lib/ethdev/ethdev_sff_telemetry.c +++ b/lib/ethdev/ethdev_sff_telemetry.c @@ -70,6 +70,9 @@ sff_port_module_eeprom_parse(uint16_t port_id, struct rte_tel_data *d) switch (minfo.type) { /* parsing module EEPROM data base on different module type */ + case RTE_ETH_MODULE_SFF_8079: + sff_8079_show_all(einfo.data, d); + break; default: RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); break; diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index 8f39739e43..d94860da0c 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -13,6 +13,7 @@ sources = files( 'rte_tm.c', 'ethdev_sff_telemetry.c', 'sff_common.c', + 'sff_8079.c', ) headers = files( diff --git a/lib/ethdev/sff_8079.c b/lib/ethdev/sff_8079.c new file mode 100644 index 0000000000..cfa20bd3cb --- /dev/null +++ b/lib/ethdev/sff_8079.c @@ -0,0 +1,406 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8079 optics diagnostics. + * + */ + +#include <stdio.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "ethdev_sff_telemetry.h" + +static void sff_8079_show_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_identifier(data, 0, d); +} + +static void sff_8079_show_ext_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[1]); + if (data[1] == 0x00) + strlcat(val_string, " (GBIC not specified / not MOD_DEF compliant)", + sizeof(val_string)); + else if (data[1] == 0x04) + strlcat(val_string, " (GBIC/SFP defined by 2-wire interface ID)", + sizeof(val_string)); + else if (data[1] <= 0x07) { + char tmp[SFF_ITEM_VAL_COMPOSE_SIZE]; + snprintf(tmp, sizeof(tmp), " (GBIC compliant with MOD_DEF %u)", data[1]); + strlcat(val_string, tmp, sizeof(val_string)); + } else + strlcat(val_string, " (unknown)", sizeof(val_string)); + ssf_add_dict_string(d, "Extended identifier", val_string); +} + +static void sff_8079_show_connector(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_connector(data, 2, d); +} + +static void sff_8079_show_transceiver(const uint8_t *data, struct rte_tel_data *d) +{ + static const char *name = "Transceiver type"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), + "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[36]); + ssf_add_dict_string(d, "Transceiver codes", val_string); + + /* 10G Ethernet Compliance Codes */ + if (data[3] & (1 << 7)) + ssf_add_dict_string(d, "10G Ethernet transceiver type", + "10G Ethernet: 10G Base-ER [SFF-8472 rev10.4 onwards]"); + if (data[3] & (1 << 6)) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-LRM"); + if (data[3] & (1 << 5)) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-LR"); + if (data[3] & (1 << 4)) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-SR"); + + /* Infiniband Compliance Codes */ + if (data[3] & (1 << 3)) + ssf_add_dict_string(d, name, "Infiniband: 1X SX"); + if (data[3] & (1 << 2)) + ssf_add_dict_string(d, name, "Infiniband: 1X LX"); + if (data[3] & (1 << 1)) + ssf_add_dict_string(d, name, "Infiniband: 1X Copper Active"); + if (data[3] & (1 << 0)) + ssf_add_dict_string(d, name, "Infiniband: 1X Copper Passive"); + + /* ESCON Compliance Codes */ + if (data[4] & (1 << 7)) + ssf_add_dict_string(d, name, "ESCON: ESCON MMF, 1310nm LED"); + if (data[4] & (1 << 6)) + ssf_add_dict_string(d, name, "ESCON: ESCON SMF, 1310nm Laser"); + + /* SONET Compliance Codes */ + if (data[4] & (1 << 5)) + ssf_add_dict_string(d, name, "SONET: OC-192, short reach"); + if (data[4] & (1 << 4)) + ssf_add_dict_string(d, name, "SONET: SONET reach specifier bit 1"); + if (data[4] & (1 << 3)) + ssf_add_dict_string(d, name, "SONET: SONET reach specifier bit 2"); + if (data[4] & (1 << 2)) + ssf_add_dict_string(d, name, "SONET: OC-48, long reach"); + if (data[4] & (1 << 1)) + ssf_add_dict_string(d, name, "SONET: OC-48, intermediate reach"); + if (data[4] & (1 << 0)) + ssf_add_dict_string(d, name, "SONET: OC-48, short reach"); + if (data[5] & (1 << 6)) + ssf_add_dict_string(d, name, "SONET: OC-12, single mode, long reach"); + if (data[5] & (1 << 5)) + ssf_add_dict_string(d, name, "SONET: OC-12, single mode, inter. reach"); + if (data[5] & (1 << 4)) + ssf_add_dict_string(d, name, "SONET: OC-12, short reach"); + if (data[5] & (1 << 2)) + ssf_add_dict_string(d, name, "SONET: OC-3, single mode, long reach"); + if (data[5] & (1 << 1)) + ssf_add_dict_string(d, name, "SONET: OC-3, single mode, inter. reach"); + if (data[5] & (1 << 0)) + ssf_add_dict_string(d, name, "SONET: OC-3, short reach"); + + /* Ethernet Compliance Codes */ + if (data[6] & (1 << 7)) + ssf_add_dict_string(d, name, "Ethernet: BASE-PX"); + if (data[6] & (1 << 6)) + ssf_add_dict_string(d, name, "Ethernet: BASE-BX10"); + if (data[6] & (1 << 5)) + ssf_add_dict_string(d, name, "Ethernet: 100BASE-FX"); + if (data[6] & (1 << 4)) + ssf_add_dict_string(d, name, "Ethernet: 100BASE-LX/LX10"); + if (data[6] & (1 << 3)) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-T"); + if (data[6] & (1 << 2)) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-CX"); + if (data[6] & (1 << 1)) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-LX"); + if (data[6] & (1 << 0)) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-SX"); + + /* Fibre Channel link length */ + if (data[7] & (1 << 7)) + ssf_add_dict_string(d, name, "FC: very long distance (V)"); + if (data[7] & (1 << 6)) + ssf_add_dict_string(d, name, "FC: short distance (S)"); + if (data[7] & (1 << 5)) + ssf_add_dict_string(d, name, "FC: intermediate distance (I)"); + if (data[7] & (1 << 4)) + ssf_add_dict_string(d, name, "FC: long distance (L)"); + if (data[7] & (1 << 3)) + ssf_add_dict_string(d, name, "FC: medium distance (M)"); + + /* Fibre Channel transmitter technology */ + if (data[7] & (1 << 2)) + ssf_add_dict_string(d, name, "FC: Shortwave laser, linear Rx (SA)"); + if (data[7] & (1 << 1)) + ssf_add_dict_string(d, name, "FC: Longwave laser (LC)"); + if (data[7] & (1 << 0)) + ssf_add_dict_string(d, name, "FC: Electrical inter-enclosure (EL)"); + if (data[8] & (1 << 7)) + ssf_add_dict_string(d, name, "FC: Electrical intra-enclosure (EL)"); + if (data[8] & (1 << 6)) + ssf_add_dict_string(d, name, "FC: Shortwave laser w/o OFC (SN)"); + if (data[8] & (1 << 5)) + ssf_add_dict_string(d, name, "FC: Shortwave laser with OFC (SL)"); + if (data[8] & (1 << 4)) + ssf_add_dict_string(d, name, "FC: Longwave laser (LL)"); + if (data[8] & (1 << 3)) + ssf_add_dict_string(d, name, "Active Cable"); + if (data[8] & (1 << 2)) + ssf_add_dict_string(d, name, "Passive Cable"); + if (data[8] & (1 << 1)) + ssf_add_dict_string(d, name, "FC: Copper FC-BaseT"); + + /* Fibre Channel transmission media */ + if (data[9] & (1 << 7)) + ssf_add_dict_string(d, name, "FC: Twin Axial Pair (TW)"); + if (data[9] & (1 << 6)) + ssf_add_dict_string(d, name, "FC: Twisted Pair (TP)"); + if (data[9] & (1 << 5)) + ssf_add_dict_string(d, name, "FC: Miniature Coax (MI)"); + if (data[9] & (1 << 4)) + ssf_add_dict_string(d, name, "FC: Video Coax (TV)"); + if (data[9] & (1 << 3)) + ssf_add_dict_string(d, name, "FC: Multimode, 62.5um (M6)"); + if (data[9] & (1 << 2)) + ssf_add_dict_string(d, name, "FC: Multimode, 50um (M5)"); + if (data[9] & (1 << 0)) + ssf_add_dict_string(d, name, "FC: Single Mode (SM)"); + + /* Fibre Channel speed */ + if (data[10] & (1 << 7)) + ssf_add_dict_string(d, name, "FC: 1200 MBytes/sec"); + if (data[10] & (1 << 6)) + ssf_add_dict_string(d, name, "FC: 800 MBytes/sec"); + if (data[10] & (1 << 4)) + ssf_add_dict_string(d, name, "FC: 400 MBytes/sec"); + if (data[10] & (1 << 2)) + ssf_add_dict_string(d, name, "FC: 200 MBytes/sec"); + if (data[10] & (1 << 0)) + ssf_add_dict_string(d, name, "FC: 100 MBytes/sec"); + + /* Extended Specification Compliance Codes from SFF-8024 */ + switch (data[36]) { + case 0x1: + ssf_add_dict_string(d, name, + "Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)"); + break; + case 0x2: + ssf_add_dict_string(d, name, "Extended: 100G Base-SR4 or 25GBase-SR"); + break; + case 0x3: + ssf_add_dict_string(d, name, "Extended: 100G Base-LR4 or 25GBase-LR"); + break; + case 0x4: + ssf_add_dict_string(d, name, "Extended: 100G Base-ER4 or 25GBase-ER"); + break; + case 0x8: + ssf_add_dict_string(d, name, + "Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)"); + break; + case 0xb: + ssf_add_dict_string(d, name, "Extended: 100G Base-CR4 or 25G Base-CR CA-L"); + break; + case 0xc: + ssf_add_dict_string(d, name, "Extended: 25G Base-CR CA-S"); + break; + case 0xd: + ssf_add_dict_string(d, name, "Extended: 25G Base-CR CA-N"); + break; + case 0x16: + ssf_add_dict_string(d, name, "Extended: 10Gbase-T with SFI electrical interface"); + break; + case 0x18: + ssf_add_dict_string(d, name, + "Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)"); + break; + case 0x19: + ssf_add_dict_string(d, name, + "Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)"); + break; + case 0x1c: + ssf_add_dict_string(d, name, "Extended: 10Gbase-T Short Reach"); + break; + default: + break; + } +} + +static void sff_8079_show_encoding(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_encoding(data, 11, RTE_ETH_MODULE_SFF_8472, d); +} + +static void sff_8079_show_rate_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[13]); + + switch (data[13]) { + case 0x00: + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case 0x01: + strlcat(val_string, " (4/2/1G Rate_Select & AS0/AS1)", sizeof(val_string)); + break; + case 0x02: + strlcat(val_string, " (8/4/2G Rx Rate_Select only)", sizeof(val_string)); + break; + case 0x03: + strlcat(val_string, " (8/4/2G Independent Rx & Tx Rate_Select)", + sizeof(val_string)); + break; + case 0x04: + strlcat(val_string, " (8/4/2G Tx Rate_Select only)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + ssf_add_dict_string(d, "Rate identifier", val_string); +} + +static void sff_8079_show_oui(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_oui(data, 37, d); +} + +static void +sff_8079_show_wavelength_or_copper_compliance(const uint8_t *data, + struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + if (data[8] & (1 << 2)) { + snprintf(val_string, sizeof(val_string), "0x%02x", data[60]); + switch (data[60]) { + case 0x00: + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case 0x01: + strlcat(val_string, " (SFF-8431 appendix E)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (unknown)", sizeof(val_string)); + break; + } + strlcat(val_string, " [SFF-8472 rev10.4 only]", sizeof(val_string)); + ssf_add_dict_string(d, "Passive Cu cmplnce.", val_string); + } else if (data[8] & (1 << 3)) { + snprintf(val_string, sizeof(val_string), "0x%02x", data[60]); + switch (data[60]) { + case 0x00: + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case 0x01: + strlcat(val_string, " (SFF-8431 appendix E)", sizeof(val_string)); + break; + case 0x04: + strlcat(val_string, " (SFF-8431 limiting)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (unknown)", sizeof(val_string)); + break; + } + strlcat(val_string, " [SFF-8472 rev10.4 only]", sizeof(val_string)); + ssf_add_dict_string(d, "Active Cu cmplnce.", val_string); + } else { + snprintf(val_string, sizeof(val_string), "%unm", (data[60] << 8) | data[61]); + ssf_add_dict_string(d, "Laser wavelength", val_string); + } +} + +static void sff_8079_show_options(const uint8_t *data, struct rte_tel_data *d) +{ + static const char *name = "Option"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x 0x%02x", data[64], data[65]); + ssf_add_dict_string(d, "Option values", val_string); + + if (data[65] & (1 << 1)) + ssf_add_dict_string(d, name, "RX_LOS implemented"); + if (data[65] & (1 << 2)) + ssf_add_dict_string(d, name, "RX_LOS implemented, inverted"); + if (data[65] & (1 << 3)) + ssf_add_dict_string(d, name, "TX_FAULT implemented"); + if (data[65] & (1 << 4)) + ssf_add_dict_string(d, name, "TX_DISABLE implemented"); + if (data[65] & (1 << 5)) + ssf_add_dict_string(d, name, "RATE_SELECT implemented"); + if (data[65] & (1 << 6)) + ssf_add_dict_string(d, name, "Tunable transmitter technology"); + if (data[65] & (1 << 7)) + ssf_add_dict_string(d, name, "Receiver decision threshold implemented"); + if (data[64] & (1 << 0)) + ssf_add_dict_string(d, name, "Linear receiver output implemented"); + if (data[64] & (1 << 1)) + ssf_add_dict_string(d, name, "Power level 2 requirement"); + if (data[64] & (1 << 2)) + ssf_add_dict_string(d, name, "Cooled transceiver implemented"); + if (data[64] & (1 << 3)) + ssf_add_dict_string(d, name, "Retimer or CDR implemented"); + if (data[64] & (1 << 4)) + ssf_add_dict_string(d, name, "Paging implemented"); + if (data[64] & (1 << 5)) + ssf_add_dict_string(d, name, "Power level 3 requirement"); +} + +void sff_8079_show_all(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8079_show_identifier(data, d); + if (((data[0] == 0x02) || (data[0] == 0x03)) && (data[1] == 0x04)) { + unsigned int br_nom, br_min, br_max; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + if (data[12] == 0) { + br_nom = br_min = br_max = 0; + } else if (data[12] == 255) { + br_nom = data[66] * 250; + br_max = data[67]; + br_min = data[67]; + } else { + br_nom = data[12] * 100; + br_max = data[66]; + br_min = data[67]; + } + sff_8079_show_ext_identifier(data, d); + sff_8079_show_connector(data, d); + sff_8079_show_transceiver(data, d); + sff_8079_show_encoding(data, d); + + snprintf(val_string, sizeof(val_string), "%uMBd", br_nom); + ssf_add_dict_string(d, "BR, Nominal", val_string); + + sff_8079_show_rate_identifier(data, d); + sff_show_value_with_unit(data, 14, + "Length (SMF,km)", 1, "km", d); + sff_show_value_with_unit(data, 15, "Length (SMF)", 100, "m", d); + sff_show_value_with_unit(data, 16, "Length (50um)", 10, "m", d); + sff_show_value_with_unit(data, 17, + "Length (62.5um)", 10, "m", d); + sff_show_value_with_unit(data, 18, "Length (Copper)", 1, "m", d); + sff_show_value_with_unit(data, 19, "Length (OM3)", 10, "m", d); + sff_8079_show_wavelength_or_copper_compliance(data, d); + sff_show_ascii(data, 20, 35, "Vendor name", d); + sff_8079_show_oui(data, d); + sff_show_ascii(data, 40, 55, "Vendor PN", d); + sff_show_ascii(data, 56, 59, "Vendor rev", d); + sff_8079_show_options(data, d); + + snprintf(val_string, sizeof(val_string), "%u%%", br_max); + ssf_add_dict_string(d, "BR margin, max", val_string); + snprintf(val_string, sizeof(val_string), "%u%%", br_min); + ssf_add_dict_string(d, "BR margin, min", val_string); + + sff_show_ascii(data, 68, 83, "Vendor SN", d); + sff_show_ascii(data, 84, 91, "Date code", d); + } +} -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v8 3/5] ethdev: format module EEPROM for SFF-8079 2022-05-25 3:14 ` [PATCH v8 3/5] ethdev: format module EEPROM for SFF-8079 Robin Zhang @ 2022-05-25 9:55 ` Andrew Rybchenko 0 siblings, 0 replies; 77+ messages in thread From: Andrew Rybchenko @ 2022-05-25 9:55 UTC (permalink / raw) To: Robin Zhang, dev; +Cc: thomas, kevinx.liu Consider: "support SFF-8079 module information telemetry" (if it fits in required number of symbols) On 5/25/22 06:14, Robin Zhang wrote: > This patch implements format module EEPROM information for > SFF-8079 Rev 1.7 Add support for module EEPROM information format defined in SFF-8079 Rev 1.7. > diff --git a/lib/ethdev/sff_8079.c b/lib/ethdev/sff_8079.c > new file mode 100644 > index 0000000000..cfa20bd3cb > --- /dev/null > +++ b/lib/ethdev/sff_8079.c > @@ -0,0 +1,406 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2022 Intel Corporation > + * > + * Implements SFF-8079 optics diagnostics. > + * Please, remove extra empty line. > + */ > + > +#include <stdio.h> > +#include <rte_mbuf.h> > +#include <rte_ethdev.h> > +#include <rte_flow.h> > +#include "sff_common.h" > +#include "ethdev_sff_telemetry.h" Please, separate system, other DPDK and local headers. Use double quotes for local headers. Remove unnecessary includes. > + if (data[3] & (1 << 7)) Use RTE_BIT32 here and in similar cases below > + if (data[65] & (1 << 1)) Use RTE_BIT32 here as well. > + ssf_add_dict_string(d, name, "RX_LOS implemented"); ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v8 4/5] ethdev: format module EEPROM for SFF-8472 2022-05-25 3:14 ` [PATCH v8 0/5] add telemetry command for show module EEPROM Robin Zhang ` (2 preceding siblings ...) 2022-05-25 3:14 ` [PATCH v8 3/5] ethdev: format module EEPROM for SFF-8079 Robin Zhang @ 2022-05-25 3:14 ` Robin Zhang 2022-05-25 11:58 ` Andrew Rybchenko 2022-05-25 3:14 ` [PATCH v8 5/5] ethdev: format module EEPROM for SFF-8636 Robin Zhang 2022-05-26 7:32 ` [PATCH v9 0/5] add telemetry command for show module EEPROM Robin Zhang 5 siblings, 1 reply; 77+ messages in thread From: Robin Zhang @ 2022-05-25 3:14 UTC (permalink / raw) To: dev; +Cc: thomas, andrew.rybchenko, kevinx.liu, Robin Zhang This patch implements format module EEPROM information for SFF-8472 Rev 12.0 Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/ethdev_sff_telemetry.c | 4 + lib/ethdev/meson.build | 1 + lib/ethdev/sff_8472.c | 286 ++++++++++++++++++++++++++++++ 3 files changed, 291 insertions(+) create mode 100644 lib/ethdev/sff_8472.c diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c index 63b0d21786..c3b13b1cb1 100644 --- a/lib/ethdev/ethdev_sff_telemetry.c +++ b/lib/ethdev/ethdev_sff_telemetry.c @@ -73,6 +73,10 @@ sff_port_module_eeprom_parse(uint16_t port_id, struct rte_tel_data *d) case RTE_ETH_MODULE_SFF_8079: sff_8079_show_all(einfo.data, d); break; + case RTE_ETH_MODULE_SFF_8472: + sff_8079_show_all(einfo.data, d); + sff_8472_show_all(einfo.data, d); + break; default: RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); break; diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index d94860da0c..4d81a35c09 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -14,6 +14,7 @@ sources = files( 'ethdev_sff_telemetry.c', 'sff_common.c', 'sff_8079.c', + 'sff_8472.c', ) headers = files( diff --git a/lib/ethdev/sff_8472.c b/lib/ethdev/sff_8472.c new file mode 100644 index 0000000000..98e31e9262 --- /dev/null +++ b/lib/ethdev/sff_8472.c @@ -0,0 +1,286 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8472 optics diagnostics. + * + */ + +#include <stdio.h> +#include <math.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "ethdev_sff_telemetry.h" + +/* Offsets in decimal, for direct comparison with the SFF specs */ + +/* A0-based EEPROM offsets for DOM support checks */ +#define SFF_A0_DOM 92 +#define SFF_A0_OPTIONS 93 +#define SFF_A0_COMP 94 + +/* EEPROM bit values for various registers */ +#define SFF_A0_DOM_EXTCAL (1 << 4) +#define SFF_A0_DOM_INTCAL (1 << 5) +#define SFF_A0_DOM_IMPL (1 << 6) +#define SFF_A0_DOM_PWRT (1 << 3) + +#define SFF_A0_OPTIONS_AW (1 << 7) + +/* + * This is the offset at which the A2 page is in the EEPROM + * blob returned by the kernel. + */ +#define SFF_A2_BASE 0x100 + +/* A2-based offsets for DOM */ +#define SFF_A2_TEMP 96 +#define SFF_A2_TEMP_HALRM 0 +#define SFF_A2_TEMP_LALRM 2 +#define SFF_A2_TEMP_HWARN 4 +#define SFF_A2_TEMP_LWARN 6 + +#define SFF_A2_VCC 98 +#define SFF_A2_VCC_HALRM 8 +#define SFF_A2_VCC_LALRM 10 +#define SFF_A2_VCC_HWARN 12 +#define SFF_A2_VCC_LWARN 14 + +#define SFF_A2_BIAS 100 +#define SFF_A2_BIAS_HALRM 16 +#define SFF_A2_BIAS_LALRM 18 +#define SFF_A2_BIAS_HWARN 20 +#define SFF_A2_BIAS_LWARN 22 + +#define SFF_A2_TX_PWR 102 +#define SFF_A2_TX_PWR_HALRM 24 +#define SFF_A2_TX_PWR_LALRM 26 +#define SFF_A2_TX_PWR_HWARN 28 +#define SFF_A2_TX_PWR_LWARN 30 + +#define SFF_A2_RX_PWR 104 +#define SFF_A2_RX_PWR_HALRM 32 +#define SFF_A2_RX_PWR_LALRM 34 +#define SFF_A2_RX_PWR_HWARN 36 +#define SFF_A2_RX_PWR_LWARN 38 + +#define SFF_A2_ALRM_FLG 112 +#define SFF_A2_WARN_FLG 116 + +/* 32-bit little-endian calibration constants */ +#define SFF_A2_CAL_RXPWR4 56 +#define SFF_A2_CAL_RXPWR3 60 +#define SFF_A2_CAL_RXPWR2 64 +#define SFF_A2_CAL_RXPWR1 68 +#define SFF_A2_CAL_RXPWR0 72 + +/* 16-bit little endian calibration constants */ +#define SFF_A2_CAL_TXI_SLP 76 +#define SFF_A2_CAL_TXI_OFF 78 +#define SFF_A2_CAL_TXPWR_SLP 80 +#define SFF_A2_CAL_TXPWR_OFF 82 +#define SFF_A2_CAL_T_SLP 84 +#define SFF_A2_CAL_T_OFF 86 +#define SFF_A2_CAL_V_SLP 88 +#define SFF_A2_CAL_V_OFF 90 + +static struct sff_8472_aw_flags { + const char *str; /* Human-readable string, null at the end */ + int offset; /* A2-relative address offset */ + uint8_t value; /* Alarm is on if (offset & value) != 0. */ +} sff_8472_aw_flags[] = { + { "Laser bias current high alarm", SFF_A2_ALRM_FLG, (1 << 3) }, + { "Laser bias current low alarm", SFF_A2_ALRM_FLG, (1 << 2) }, + { "Laser bias current high warning", SFF_A2_WARN_FLG, (1 << 3) }, + { "Laser bias current low warning", SFF_A2_WARN_FLG, (1 << 2) }, + + { "Laser output power high alarm", SFF_A2_ALRM_FLG, (1 << 1) }, + { "Laser output power low alarm", SFF_A2_ALRM_FLG, (1 << 0) }, + { "Laser output power high warning", SFF_A2_WARN_FLG, (1 << 1) }, + { "Laser output power low warning", SFF_A2_WARN_FLG, (1 << 0) }, + + { "Module temperature high alarm", SFF_A2_ALRM_FLG, (1 << 7) }, + { "Module temperature low alarm", SFF_A2_ALRM_FLG, (1 << 6) }, + { "Module temperature high warning", SFF_A2_WARN_FLG, (1 << 7) }, + { "Module temperature low warning", SFF_A2_WARN_FLG, (1 << 6) }, + + { "Module voltage high alarm", SFF_A2_ALRM_FLG, (1 << 5) }, + { "Module voltage low alarm", SFF_A2_ALRM_FLG, (1 << 4) }, + { "Module voltage high warning", SFF_A2_WARN_FLG, (1 << 5) }, + { "Module voltage low warning", SFF_A2_WARN_FLG, (1 << 4) }, + + { "Laser rx power high alarm", SFF_A2_ALRM_FLG + 1, (1 << 7) }, + { "Laser rx power low alarm", SFF_A2_ALRM_FLG + 1, (1 << 6) }, + { "Laser rx power high warning", SFF_A2_WARN_FLG + 1, (1 << 7) }, + { "Laser rx power low warning", SFF_A2_WARN_FLG + 1, (1 << 6) }, + + { NULL, 0, 0 }, +}; + +/* Most common case: 16-bit unsigned integer in a certain unit */ +#define A2_OFFSET_TO_U16(offset) \ + (data[SFF_A2_BASE + (offset)] << 8 | data[SFF_A2_BASE + (offset) + 1]) + +/* Calibration slope is a number between 0.0 included and 256.0 excluded. */ +#define A2_OFFSET_TO_SLP(offset) \ + (data[SFF_A2_BASE + (offset)] + data[SFF_A2_BASE + (offset) + 1] / 256.) + +/* Calibration offset is an integer from -32768 to 32767 */ +#define A2_OFFSET_TO_OFF(offset) \ + ((int16_t)A2_OFFSET_TO_U16(offset)) + +/* RXPWR(x) are IEEE-754 floating point numbers in big-endian format */ +#define A2_OFFSET_TO_RXPWRx(offset) \ + (befloattoh((const uint32_t *)(data + SFF_A2_BASE + (offset)))) + +/* + * 2-byte internal temperature conversions: + * First byte is a signed 8-bit integer, which is the temp decimal part + * Second byte are 1/256th of degree, which are added to the dec part. + */ +#define A2_OFFSET_TO_TEMP(offset) ((int16_t)A2_OFFSET_TO_U16(offset)) + +static void sff_8472_dom_parse(const uint8_t *data, struct sff_diags *sd) +{ + sd->bias_cur[MCURR] = A2_OFFSET_TO_U16(SFF_A2_BIAS); + sd->bias_cur[HALRM] = A2_OFFSET_TO_U16(SFF_A2_BIAS_HALRM); + sd->bias_cur[LALRM] = A2_OFFSET_TO_U16(SFF_A2_BIAS_LALRM); + sd->bias_cur[HWARN] = A2_OFFSET_TO_U16(SFF_A2_BIAS_HWARN); + sd->bias_cur[LWARN] = A2_OFFSET_TO_U16(SFF_A2_BIAS_LWARN); + + sd->sfp_voltage[MCURR] = A2_OFFSET_TO_U16(SFF_A2_VCC); + sd->sfp_voltage[HALRM] = A2_OFFSET_TO_U16(SFF_A2_VCC_HALRM); + sd->sfp_voltage[LALRM] = A2_OFFSET_TO_U16(SFF_A2_VCC_LALRM); + sd->sfp_voltage[HWARN] = A2_OFFSET_TO_U16(SFF_A2_VCC_HWARN); + sd->sfp_voltage[LWARN] = A2_OFFSET_TO_U16(SFF_A2_VCC_LWARN); + + sd->tx_power[MCURR] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR); + sd->tx_power[HALRM] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_HALRM); + sd->tx_power[LALRM] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_LALRM); + sd->tx_power[HWARN] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_HWARN); + sd->tx_power[LWARN] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_LWARN); + + sd->rx_power[MCURR] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR); + sd->rx_power[HALRM] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_HALRM); + sd->rx_power[LALRM] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_LALRM); + sd->rx_power[HWARN] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_HWARN); + sd->rx_power[LWARN] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_LWARN); + + sd->sfp_temp[MCURR] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP); + sd->sfp_temp[HALRM] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_HALRM); + sd->sfp_temp[LALRM] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_LALRM); + sd->sfp_temp[HWARN] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_HWARN); + sd->sfp_temp[LWARN] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_LWARN); +} + +/* Converts to a float from a big-endian 4-byte source buffer. */ +static float befloattoh(const uint32_t *source) +{ + union { + uint32_t src; + float dst; + } converter; + + converter.src = ntohl(*source); + return converter.dst; +} + +static void sff_8472_calibration(const uint8_t *data, struct sff_diags *sd) +{ + unsigned long i; + uint16_t rx_reading; + + /* Calibration should occur for all values (threshold and current) */ + for (i = 0; i < RTE_DIM(sd->bias_cur); ++i) { + /* + * Apply calibration formula 1 (Temp., Voltage, Bias, Tx Power) + */ + sd->bias_cur[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_TXI_SLP); + sd->tx_power[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_TXPWR_SLP); + sd->sfp_voltage[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_V_SLP); + sd->sfp_temp[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_T_SLP); + + sd->bias_cur[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_TXI_OFF); + sd->tx_power[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_TXPWR_OFF); + sd->sfp_voltage[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_V_OFF); + sd->sfp_temp[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_T_OFF); + + /* + * Apply calibration formula 2 (Rx Power only) + */ + rx_reading = sd->rx_power[i]; + sd->rx_power[i] = A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR0); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR1); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR2); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR3); + } +} + +static void sff_8472_parse_eeprom(const uint8_t *data, struct sff_diags *sd) +{ + sd->supports_dom = data[SFF_A0_DOM] & SFF_A0_DOM_IMPL; + sd->supports_alarms = data[SFF_A0_OPTIONS] & SFF_A0_OPTIONS_AW; + sd->calibrated_ext = data[SFF_A0_DOM] & SFF_A0_DOM_EXTCAL; + sd->rx_power_type = data[SFF_A0_DOM] & SFF_A0_DOM_PWRT; + + sff_8472_dom_parse(data, sd); + + /* + * If the SFP is externally calibrated, we need to read calibration data + * and compensate the already stored readings. + */ + if (sd->calibrated_ext) + sff_8472_calibration(data, sd); +} + +void sff_8472_show_all(const uint8_t *data, struct rte_tel_data *d) +{ + struct sff_diags sd = {0}; + const char *rx_power_string = NULL; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + int i; + + sff_8472_parse_eeprom(data, &sd); + + if (!sd.supports_dom) { + ssf_add_dict_string(d, "Optical diagnostics support", "No"); + return; + } + ssf_add_dict_string(d, "Optical diagnostics support", "Yes"); + + SPRINT_BIAS(val_string, sd.bias_cur[MCURR]); + ssf_add_dict_string(d, "Laser bias current", val_string); + + SPRINT_xX_PWR(val_string, sd.tx_power[MCURR]); + ssf_add_dict_string(d, "Laser output power", val_string); + + if (!sd.rx_power_type) + rx_power_string = "Receiver signal OMA"; + else + rx_power_string = "Receiver signal average optical power"; + + SPRINT_xX_PWR(val_string, sd.rx_power[MCURR]); + ssf_add_dict_string(d, rx_power_string, val_string); + + SPRINT_TEMP(val_string, sd.sfp_temp[MCURR]); + ssf_add_dict_string(d, "Module temperature", val_string); + + SPRINT_VCC(val_string, sd.sfp_voltage[MCURR]); + ssf_add_dict_string(d, "Module voltage", val_string); + + ssf_add_dict_string(d, "Alarm/warning flags implemented", + (sd.supports_alarms ? "Yes" : "No")); + + if (sd.supports_alarms) { + for (i = 0; sff_8472_aw_flags[i].str; ++i) { + ssf_add_dict_string(d, sff_8472_aw_flags[i].str, + data[SFF_A2_BASE + sff_8472_aw_flags[i].offset] + & sff_8472_aw_flags[i].value ? "On" : "Off"); + } + sff_show_thresholds(sd, d); + } +} -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v8 4/5] ethdev: format module EEPROM for SFF-8472 2022-05-25 3:14 ` [PATCH v8 4/5] ethdev: format module EEPROM for SFF-8472 Robin Zhang @ 2022-05-25 11:58 ` Andrew Rybchenko 0 siblings, 0 replies; 77+ messages in thread From: Andrew Rybchenko @ 2022-05-25 11:58 UTC (permalink / raw) To: Robin Zhang, dev; +Cc: thomas, kevinx.liu On 5/25/22 06:14, Robin Zhang wrote: > This patch implements format module EEPROM information for > SFF-8472 Rev 12.0 > > Signed-off-by: Robin Zhang <robinx.zhang@intel.com> [snip] > diff --git a/lib/ethdev/sff_8472.c b/lib/ethdev/sff_8472.c > new file mode 100644 > index 0000000000..98e31e9262 > --- /dev/null > +++ b/lib/ethdev/sff_8472.c > @@ -0,0 +1,286 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2022 Intel Corporation > + * > + * Implements SFF-8472 optics diagnostics. > + * > + */ > + > +#include <stdio.h> > +#include <math.h> > +#include <rte_mbuf.h> > +#include <rte_ethdev.h> > +#include <rte_flow.h> > +#include "sff_common.h" > +#include "ethdev_sff_telemetry.h" Please, fix includes in accordance with previous patches review notes. > + > +/* Offsets in decimal, for direct comparison with the SFF specs */ > + > +/* A0-based EEPROM offsets for DOM support checks */ > +#define SFF_A0_DOM 92 > +#define SFF_A0_OPTIONS 93 > +#define SFF_A0_COMP 94 > + > +/* EEPROM bit values for various registers */ > +#define SFF_A0_DOM_EXTCAL (1 << 4) > +#define SFF_A0_DOM_INTCAL (1 << 5) > +#define SFF_A0_DOM_IMPL (1 << 6) > +#define SFF_A0_DOM_PWRT (1 << 3) > + > +#define SFF_A0_OPTIONS_AW (1 << 7) RTE_BIT32 ? > + > +/* > + * This is the offset at which the A2 page is in the EEPROM > + * blob returned by the kernel. > + */ > +#define SFF_A2_BASE 0x100 > + > +/* A2-based offsets for DOM */ > +#define SFF_A2_TEMP 96 > +#define SFF_A2_TEMP_HALRM 0 > +#define SFF_A2_TEMP_LALRM 2 > +#define SFF_A2_TEMP_HWARN 4 > +#define SFF_A2_TEMP_LWARN 6 > + > +#define SFF_A2_VCC 98 > +#define SFF_A2_VCC_HALRM 8 > +#define SFF_A2_VCC_LALRM 10 > +#define SFF_A2_VCC_HWARN 12 > +#define SFF_A2_VCC_LWARN 14 > + > +#define SFF_A2_BIAS 100 > +#define SFF_A2_BIAS_HALRM 16 > +#define SFF_A2_BIAS_LALRM 18 > +#define SFF_A2_BIAS_HWARN 20 > +#define SFF_A2_BIAS_LWARN 22 > + > +#define SFF_A2_TX_PWR 102 > +#define SFF_A2_TX_PWR_HALRM 24 > +#define SFF_A2_TX_PWR_LALRM 26 > +#define SFF_A2_TX_PWR_HWARN 28 > +#define SFF_A2_TX_PWR_LWARN 30 > + > +#define SFF_A2_RX_PWR 104 > +#define SFF_A2_RX_PWR_HALRM 32 > +#define SFF_A2_RX_PWR_LALRM 34 > +#define SFF_A2_RX_PWR_HWARN 36 > +#define SFF_A2_RX_PWR_LWARN 38 > + > +#define SFF_A2_ALRM_FLG 112 > +#define SFF_A2_WARN_FLG 116 > + > +/* 32-bit little-endian calibration constants */ > +#define SFF_A2_CAL_RXPWR4 56 > +#define SFF_A2_CAL_RXPWR3 60 > +#define SFF_A2_CAL_RXPWR2 64 > +#define SFF_A2_CAL_RXPWR1 68 > +#define SFF_A2_CAL_RXPWR0 72 > + > +/* 16-bit little endian calibration constants */ > +#define SFF_A2_CAL_TXI_SLP 76 > +#define SFF_A2_CAL_TXI_OFF 78 > +#define SFF_A2_CAL_TXPWR_SLP 80 > +#define SFF_A2_CAL_TXPWR_OFF 82 > +#define SFF_A2_CAL_T_SLP 84 > +#define SFF_A2_CAL_T_OFF 86 > +#define SFF_A2_CAL_V_SLP 88 > +#define SFF_A2_CAL_V_OFF 90 > + > +static struct sff_8472_aw_flags { > + const char *str; /* Human-readable string, null at the end */ > + int offset; /* A2-relative address offset */ > + uint8_t value; /* Alarm is on if (offset & value) != 0. */ > +} sff_8472_aw_flags[] = { > + { "Laser bias current high alarm", SFF_A2_ALRM_FLG, (1 << 3) }, RTE_BIT32 here and below? > + { "Laser bias current low alarm", SFF_A2_ALRM_FLG, (1 << 2) }, > + { "Laser bias current high warning", SFF_A2_WARN_FLG, (1 << 3) }, > + { "Laser bias current low warning", SFF_A2_WARN_FLG, (1 << 2) }, > + > + { "Laser output power high alarm", SFF_A2_ALRM_FLG, (1 << 1) }, > + { "Laser output power low alarm", SFF_A2_ALRM_FLG, (1 << 0) }, > + { "Laser output power high warning", SFF_A2_WARN_FLG, (1 << 1) }, > + { "Laser output power low warning", SFF_A2_WARN_FLG, (1 << 0) }, > + > + { "Module temperature high alarm", SFF_A2_ALRM_FLG, (1 << 7) }, > + { "Module temperature low alarm", SFF_A2_ALRM_FLG, (1 << 6) }, > + { "Module temperature high warning", SFF_A2_WARN_FLG, (1 << 7) }, > + { "Module temperature low warning", SFF_A2_WARN_FLG, (1 << 6) }, > + > + { "Module voltage high alarm", SFF_A2_ALRM_FLG, (1 << 5) }, > + { "Module voltage low alarm", SFF_A2_ALRM_FLG, (1 << 4) }, > + { "Module voltage high warning", SFF_A2_WARN_FLG, (1 << 5) }, > + { "Module voltage low warning", SFF_A2_WARN_FLG, (1 << 4) }, > + > + { "Laser rx power high alarm", SFF_A2_ALRM_FLG + 1, (1 << 7) }, > + { "Laser rx power low alarm", SFF_A2_ALRM_FLG + 1, (1 << 6) }, > + { "Laser rx power high warning", SFF_A2_WARN_FLG + 1, (1 << 7) }, > + { "Laser rx power low warning", SFF_A2_WARN_FLG + 1, (1 << 6) }, > + > + { NULL, 0, 0 }, > +}; ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v8 5/5] ethdev: format module EEPROM for SFF-8636 2022-05-25 3:14 ` [PATCH v8 0/5] add telemetry command for show module EEPROM Robin Zhang ` (3 preceding siblings ...) 2022-05-25 3:14 ` [PATCH v8 4/5] ethdev: format module EEPROM for SFF-8472 Robin Zhang @ 2022-05-25 3:14 ` Robin Zhang 2022-05-25 9:01 ` Andrew Rybchenko 2022-05-25 12:01 ` Andrew Rybchenko 2022-05-26 7:32 ` [PATCH v9 0/5] add telemetry command for show module EEPROM Robin Zhang 5 siblings, 2 replies; 77+ messages in thread From: Robin Zhang @ 2022-05-25 3:14 UTC (permalink / raw) To: dev; +Cc: thomas, andrew.rybchenko, kevinx.liu, Robin Zhang This patch implements format module EEPROM information for SFF-8636 Rev 2.7 Signed-off-by: Robin Zhang <robinx.zhang@intel.com> --- lib/ethdev/ethdev_sff_telemetry.c | 4 + lib/ethdev/meson.build | 1 + lib/ethdev/sff_8636.c | 750 ++++++++++++++++++++++++++++++ lib/ethdev/sff_8636.h | 611 ++++++++++++++++++++++++ 4 files changed, 1366 insertions(+) create mode 100644 lib/ethdev/sff_8636.c create mode 100644 lib/ethdev/sff_8636.h diff --git a/lib/ethdev/ethdev_sff_telemetry.c b/lib/ethdev/ethdev_sff_telemetry.c index c3b13b1cb1..b7d14219ef 100644 --- a/lib/ethdev/ethdev_sff_telemetry.c +++ b/lib/ethdev/ethdev_sff_telemetry.c @@ -77,6 +77,10 @@ sff_port_module_eeprom_parse(uint16_t port_id, struct rte_tel_data *d) sff_8079_show_all(einfo.data, d); sff_8472_show_all(einfo.data, d); break; + case RTE_ETH_MODULE_SFF_8436: + case RTE_ETH_MODULE_SFF_8636: + sff_8636_show_all(einfo.data, einfo.length, d); + break; default: RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); break; diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index 4d81a35c09..88ceeb12b9 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -15,6 +15,7 @@ sources = files( 'sff_common.c', 'sff_8079.c', 'sff_8472.c', + 'sff_8636.c', ) headers = files( diff --git a/lib/ethdev/sff_8636.c b/lib/ethdev/sff_8636.c new file mode 100644 index 0000000000..ad625fc73b --- /dev/null +++ b/lib/ethdev/sff_8636.c @@ -0,0 +1,750 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8636 based QSFP+/QSFP28 Diagnostics Memory map. + * + */ + +#include <stdio.h> +#include <math.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include "sff_common.h" +#include "sff_8636.h" +#include "ethdev_sff_telemetry.h" + +#define MAX_DESC_SIZE 42 + +static struct sff_8636_aw_flags { + const char *str; /* Human-readable string, null at the end */ + int offset; /* A2-relative address offset */ + uint8_t value; /* Alarm is on if (offset & value) != 0. */ +} sff_8636_aw_flags[] = { + { "Laser bias current high alarm (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_HALARM) }, + { "Laser bias current low alarm (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_LALARM) }, + { "Laser bias current high warning (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_HWARN) }, + { "Laser bias current low warning (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_LWARN) }, + + { "Laser bias current high alarm (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_HALARM) }, + { "Laser bias current low alarm (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_LALARM) }, + { "Laser bias current high warning (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_HWARN) }, + { "Laser bias current low warning (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_LWARN) }, + + { "Laser bias current high alarm (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_HALARM) }, + { "Laser bias current low alarm (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_LALARM) }, + { "Laser bias current high warning (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_HWARN) }, + { "Laser bias current low warning (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_LWARN) }, + + { "Laser bias current high alarm (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_HALARM) }, + { "Laser bias current low alarm (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_LALARM) }, + { "Laser bias current high warning (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_HWARN) }, + { "Laser bias current low warning (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_LWARN) }, + + { "Module temperature high alarm", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_HALARM_STATUS) }, + { "Module temperature low alarm", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_LALARM_STATUS) }, + { "Module temperature high warning", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_HWARN_STATUS) }, + { "Module temperature low warning", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_LWARN_STATUS) }, + + { "Module voltage high alarm", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_HALARM_STATUS) }, + { "Module voltage low alarm", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_LALARM_STATUS) }, + { "Module voltage high warning", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_HWARN_STATUS) }, + { "Module voltage low warning", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_LWARN_STATUS) }, + + { "Laser tx power high alarm (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_HALARM) }, + { "Laser tx power low alarm (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_LALARM) }, + { "Laser tx power high warning (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_HWARN) }, + { "Laser tx power low warning (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_LWARN) }, + + { "Laser tx power high alarm (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_HALARM) }, + { "Laser tx power low alarm (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_LALARM) }, + { "Laser tx power high warning (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_HWARN) }, + { "Laser tx power low warning (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_LWARN) }, + + { "Laser tx power high alarm (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_HALARM) }, + { "Laser tx power low alarm (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_LALARM) }, + { "Laser tx power high warning (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_HWARN) }, + { "Laser tx power low warning (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_LWARN) }, + + { "Laser tx power high alarm (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_HALARM) }, + { "Laser tx power low alarm (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_LALARM) }, + { "Laser tx power high warning (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_HWARN) }, + { "Laser tx power low warning (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_LWARN) }, + + { "Laser rx power high alarm (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_HALARM) }, + { "Laser rx power low alarm (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_LALARM) }, + { "Laser rx power high warning (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_HWARN) }, + { "Laser rx power low warning (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_LWARN) }, + + { "Laser rx power high alarm (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_HALARM) }, + { "Laser rx power low alarm (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_LALARM) }, + { "Laser rx power high warning (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_HWARN) }, + { "Laser rx power low warning (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_LWARN) }, + + { "Laser rx power high alarm (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_HALARM) }, + { "Laser rx power low alarm (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_LALARM) }, + { "Laser rx power high warning (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_HWARN) }, + { "Laser rx power low warning (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_LWARN) }, + + { "Laser rx power high alarm (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_HALARM) }, + { "Laser rx power low alarm (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_LALARM) }, + { "Laser rx power high warning (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_HWARN) }, + { "Laser rx power low warning (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_LWARN) }, + + { NULL, 0, 0 }, +}; + +static void sff_8636_show_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_identifier(data, SFF_8636_ID_OFFSET, d); +} + +static void sff_8636_show_ext_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + static const char *name = "Extended identifier description"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + snprintf(val_string, sizeof(val_string), "0x%02x", data[SFF_8636_EXT_ID_OFFSET]); + ssf_add_dict_string(d, "Extended identifier", val_string); + + switch (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_PWR_CLASS_MASK) { + case SFF_8636_EXT_ID_PWR_CLASS_1: + ssf_add_dict_string(d, name, "1.5W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_2: + ssf_add_dict_string(d, name, "2.0W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_3: + ssf_add_dict_string(d, name, "2.5W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_4: + ssf_add_dict_string(d, name, "3.5W max. Power consumption"); + break; + } + + if (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_CDR_TX_MASK) + ssf_add_dict_string(d, name, "CDR present in TX"); + else + ssf_add_dict_string(d, name, "No CDR in TX"); + + if (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_CDR_RX_MASK) + ssf_add_dict_string(d, name, "CDR present in RX"); + else + ssf_add_dict_string(d, name, "No CDR in RX"); + + switch (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_EPWR_CLASS_MASK) { + case SFF_8636_EXT_ID_PWR_CLASS_LEGACY: + snprintf(val_string, sizeof(val_string), "%s", ""); + break; + case SFF_8636_EXT_ID_PWR_CLASS_5: + snprintf(val_string, sizeof(val_string), "%s", "4.0W max. Power consumption, "); + break; + case SFF_8636_EXT_ID_PWR_CLASS_6: + snprintf(val_string, sizeof(val_string), "%s", "4.5W max. Power consumption, "); + break; + case SFF_8636_EXT_ID_PWR_CLASS_7: + snprintf(val_string, sizeof(val_string), "%s", "5.0W max. Power consumption, "); + break; + } + + if (data[SFF_8636_PWR_MODE_OFFSET] & SFF_8636_HIGH_PWR_ENABLE) + strlcat(val_string, "High Power Class (> 3.5 W) enabled", sizeof(val_string)); + else + strlcat(val_string, "High Power Class (> 3.5 W) not enabled", sizeof(val_string)); + + ssf_add_dict_string(d, name, val_string); +} + +static void sff_8636_show_connector(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_connector(data, SFF_8636_CTOR_OFFSET, d); +} + +static void sff_8636_show_transceiver(const uint8_t *data, struct rte_tel_data *d) +{ + static const char *name = "Transceiver type"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + data[SFF_8636_ETHERNET_COMP_OFFSET], + data[SFF_8636_SONET_COMP_OFFSET], + data[SFF_8636_SAS_COMP_OFFSET], + data[SFF_8636_GIGE_COMP_OFFSET], + data[SFF_8636_FC_LEN_OFFSET], + data[SFF_8636_FC_TECH_OFFSET], + data[SFF_8636_FC_TRANS_MEDIA_OFFSET], + data[SFF_8636_FC_SPEED_OFFSET]); + ssf_add_dict_string(d, "Transceiver codes", val_string); + + /* 10G/40G Ethernet Compliance Codes */ + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_LRM) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-LRM"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_LR) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-LR"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_SR) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-SR"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_CR4) + ssf_add_dict_string(d, name, "40G Ethernet: 40G Base-CR4"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_SR4) + ssf_add_dict_string(d, name, "40G Ethernet: 40G Base-SR4"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_LR4) + ssf_add_dict_string(d, name, "40G Ethernet: 40G Base-LR4"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_ACTIVE) + ssf_add_dict_string(d, name, "40G Ethernet: 40G Active Cable (XLPPI)"); + + /* Extended Specification Compliance Codes from SFF-8024 */ + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_RSRVD) { + switch (data[SFF_8636_OPTION_1_OFFSET]) { + case SFF_8636_ETHERNET_UNSPECIFIED: + ssf_add_dict_string(d, name, "(reserved or unknown)"); + break; + case SFF_8636_ETHERNET_100G_AOC: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)"); + break; + case SFF_8636_ETHERNET_100G_SR4: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G Base-SR4 or 25GBase-SR"); + break; + case SFF_8636_ETHERNET_100G_LR4: + ssf_add_dict_string(d, name, "100G Ethernet: 100G Base-LR4"); + break; + case SFF_8636_ETHERNET_100G_ER4: + ssf_add_dict_string(d, name, "100G Ethernet: 100G Base-ER4"); + break; + case SFF_8636_ETHERNET_100G_SR10: + ssf_add_dict_string(d, name, "100G Ethernet: 100G Base-SR10"); + break; + case SFF_8636_ETHERNET_100G_CWDM4_FEC: + ssf_add_dict_string(d, name, "100G Ethernet: 100G CWDM4 MSA with FEC"); + break; + case SFF_8636_ETHERNET_100G_PSM4: + ssf_add_dict_string(d, name, "100G Ethernet: 100G PSM4 Parallel SMF"); + break; + case SFF_8636_ETHERNET_100G_ACC: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)"); + break; + case SFF_8636_ETHERNET_100G_CWDM4_NO_FEC: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G CWDM4 MSA without FEC"); + break; + case SFF_8636_ETHERNET_100G_RSVD1: + ssf_add_dict_string(d, name, "(reserved or unknown)"); + break; + case SFF_8636_ETHERNET_100G_CR4: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G Base-CR4 or 25G Base-CR CA-L"); + break; + case SFF_8636_ETHERNET_25G_CR_CA_S: + ssf_add_dict_string(d, name, "25G Ethernet: 25G Base-CR CA-S"); + break; + case SFF_8636_ETHERNET_25G_CR_CA_N: + ssf_add_dict_string(d, name, "25G Ethernet: 25G Base-CR CA-N"); + break; + case SFF_8636_ETHERNET_40G_ER4: + ssf_add_dict_string(d, name, "40G Ethernet: 40G Base-ER4"); + break; + case SFF_8636_ETHERNET_4X10_SR: + ssf_add_dict_string(d, name, "4x10G Ethernet: 10G Base-SR"); + break; + case SFF_8636_ETHERNET_40G_PSM4: + ssf_add_dict_string(d, name, "40G Ethernet: 40G PSM4 Parallel SMF"); + break; + case SFF_8636_ETHERNET_G959_P1I1_2D1: + ssf_add_dict_string(d, name, + "Ethernet: G959.1 profile P1I1-2D1 (10709 MBd, 2km, 1310nm SM)"); + break; + case SFF_8636_ETHERNET_G959_P1S1_2D2: + ssf_add_dict_string(d, name, + "Ethernet: G959.1 profile P1S1-2D2 (10709 MBd, 40km, 1550nm SM)"); + break; + case SFF_8636_ETHERNET_G959_P1L1_2D2: + ssf_add_dict_string(d, name, + "Ethernet: G959.1 profile P1L1-2D2 (10709 MBd, 80km, 1550nm SM)"); + break; + case SFF_8636_ETHERNET_10GT_SFI: + ssf_add_dict_string(d, name, + "10G Ethernet: 10G Base-T with SFI electrical interface"); + break; + case SFF_8636_ETHERNET_100G_CLR4: + ssf_add_dict_string(d, name, "100G Ethernet: 100G CLR4"); + break; + case SFF_8636_ETHERNET_100G_AOC2: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)"); + break; + case SFF_8636_ETHERNET_100G_ACC2: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)"); + break; + default: + ssf_add_dict_string(d, name, "(reserved or unknown)"); + break; + } + } + + /* SONET Compliance Codes */ + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_40G_OTN) + ssf_add_dict_string(d, name, "40G OTN (OTU3B/OTU3C)"); + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_LR) + ssf_add_dict_string(d, name, "SONET: OC-48, long reach"); + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_IR) + ssf_add_dict_string(d, name, "SONET: OC-48, intermediate reach"); + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_SR) + ssf_add_dict_string(d, name, "SONET: OC-48, short reach"); + + /* SAS/SATA Compliance Codes */ + if (data[SFF_8636_SAS_COMP_OFFSET] & SFF_8636_SAS_6G) + ssf_add_dict_string(d, name, "SAS 6.0G"); + if (data[SFF_8636_SAS_COMP_OFFSET] & SFF_8636_SAS_3G) + ssf_add_dict_string(d, name, "SAS 3.0G"); + + /* Ethernet Compliance Codes */ + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_T) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-T"); + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_CX) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-CX"); + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_LX) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-LX"); + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_SX) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-SX"); + + /* Fibre Channel link length */ + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_VERY_LONG) + ssf_add_dict_string(d, name, "FC: very long distance (V)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_SHORT) + ssf_add_dict_string(d, name, "FC: short distance (S)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_INT) + ssf_add_dict_string(d, name, "FC: intermediate distance (I)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_LONG) + ssf_add_dict_string(d, name, "FC: long distance (L)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_MED) + ssf_add_dict_string(d, name, "FC: medium distance (M)"); + + /* Fibre Channel transmitter technology */ + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_TECH_LONG_LC) + ssf_add_dict_string(d, name, "FC: Longwave laser (LC)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_TECH_ELEC_INTER) + ssf_add_dict_string(d, name, "FC: Electrical inter-enclosure (EL)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_ELEC_INTRA) + ssf_add_dict_string(d, name, "FC: Electrical intra-enclosure (EL)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_SHORT_WO_OFC) + ssf_add_dict_string(d, name, "FC: Shortwave laser w/o OFC (SN)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_SHORT_W_OFC) + ssf_add_dict_string(d, name, "FC: Shortwave laser with OFC (SL)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_LONG_LL) + ssf_add_dict_string(d, name, "FC: Longwave laser (LL)"); + + /* Fibre Channel transmission media */ + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TW) + ssf_add_dict_string(d, name, "FC: Twin Axial Pair (TW)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TP) + ssf_add_dict_string(d, name, "FC: Twisted Pair (TP)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_MI) + ssf_add_dict_string(d, name, "FC: Miniature Coax (MI)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TV) + ssf_add_dict_string(d, name, "FC: Video Coax (TV)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_M6) + ssf_add_dict_string(d, name, "FC: Multimode, 62.5m (M6)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_M5) + ssf_add_dict_string(d, name, "FC: Multimode, 50m (M5)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_OM3) + ssf_add_dict_string(d, name, "FC: Multimode, 50um (OM3)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_SM) + ssf_add_dict_string(d, name, "FC: Single Mode (SM)"); + + /* Fibre Channel speed */ + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_1200_MBPS) + ssf_add_dict_string(d, name, "FC: 1200 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_800_MBPS) + ssf_add_dict_string(d, name, "FC: 800 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_1600_MBPS) + ssf_add_dict_string(d, name, "FC: 1600 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_400_MBPS) + ssf_add_dict_string(d, name, "FC: 400 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_200_MBPS) + ssf_add_dict_string(d, name, "FC: 200 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_100_MBPS) + ssf_add_dict_string(d, name, "FC: 100 MBytes/sec"); +} + +static void sff_8636_show_encoding(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_encoding(data, SFF_8636_ENCODING_OFFSET, + RTE_ETH_MODULE_SFF_8636, d); +} + +static void sff_8636_show_rate_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + char val_string[20]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[SFF_8636_EXT_RS_OFFSET]); + ssf_add_dict_string(d, "Rate identifier", val_string); +} + +static void sff_8636_show_oui(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_oui(data, SFF_8636_VENDOR_OUI_OFFSET, d); +} + +static void sff_8636_show_wavelength_or_copper_compliance(const uint8_t *data, + struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + snprintf(val_string, sizeof(val_string), "0x%02x", + (data[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK)); + + switch (data[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK) { + case SFF_8636_TRANS_850_VCSEL: + strlcat(val_string, " (850 nm VCSEL)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_VCSEL: + strlcat(val_string, " (1310 nm VCSEL)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1550_VCSEL: + strlcat(val_string, " (1550 nm VCSEL)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_FP: + strlcat(val_string, " (1310 nm FP)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_DFB: + strlcat(val_string, " (1310 nm DFB)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1550_DFB: + strlcat(val_string, " (1550 nm DFB)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_EML: + strlcat(val_string, " (1310 nm EML)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1550_EML: + strlcat(val_string, " (1550 nm EML)", sizeof(val_string)); + break; + case SFF_8636_TRANS_OTHERS: + strlcat(val_string, " (Others/Undefined)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1490_DFB: + strlcat(val_string, " (1490 nm DFB)", sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_PAS_UNEQUAL: + strlcat(val_string, " (Copper cable unequalized)", sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_PAS_EQUAL: + strlcat(val_string, " (Copper cable passive equalized)", sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_LNR_FAR_EQUAL: + strlcat(val_string, + " (Copper cable, near and far end limiting active equalizers)", + sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_FAR_EQUAL: + strlcat(val_string, + " (Copper cable, far end limiting active equalizers)", + sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_NEAR_EQUAL: + strlcat(val_string, + " (Copper cable, near end limiting active equalizers)", + sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_LNR_EQUAL: + strlcat(val_string, + " (Copper cable, linear active equalizers)", + sizeof(val_string)); + break; + } + ssf_add_dict_string(d, "Transmitter technology", val_string); + + if ((data[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK) + >= SFF_8636_TRANS_COPPER_PAS_UNEQUAL) { + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + ssf_add_dict_string(d, "Attenuation at 2.5GHz", val_string); + + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + ssf_add_dict_string(d, "Attenuation at 5.0GHz", val_string); + + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + ssf_add_dict_string(d, "Attenuation at 7.0GHz", val_string); + + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + ssf_add_dict_string(d, "Attenuation at 12.9GHz", val_string); + } else { + snprintf(val_string, sizeof(val_string), "%.3lfnm", + (((data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET] << 8) | + data[SFF_8636_WAVELEN_LOW_BYTE_OFFSET])*0.05)); + ssf_add_dict_string(d, "Laser wavelength", val_string); + + snprintf(val_string, sizeof(val_string), "%.3lfnm", + (((data[SFF_8636_WAVE_TOL_HIGH_BYTE_OFFSET] << 8) | + data[SFF_8636_WAVE_TOL_LOW_BYTE_OFFSET])*0.005)); + ssf_add_dict_string(d, "Laser wavelength tolerance", val_string); + } +} + +static void sff_8636_show_revision_compliance(const uint8_t *data, struct rte_tel_data *d) +{ + static const char *name = "Revision Compliance"; + + switch (data[SFF_8636_REV_COMPLIANCE_OFFSET]) { + case SFF_8636_REV_UNSPECIFIED: + ssf_add_dict_string(d, name, "Revision not specified"); + break; + case SFF_8636_REV_8436_48: + ssf_add_dict_string(d, name, "SFF-8436 Rev 4.8 or earlier"); + break; + case SFF_8636_REV_8436_8636: + ssf_add_dict_string(d, name, "SFF-8436 Rev 4.8 or earlier"); + break; + case SFF_8636_REV_8636_13: + ssf_add_dict_string(d, name, "SFF-8636 Rev 1.3 or earlier"); + break; + case SFF_8636_REV_8636_14: + ssf_add_dict_string(d, name, "SFF-8636 Rev 1.4"); + break; + case SFF_8636_REV_8636_15: + ssf_add_dict_string(d, name, "SFF-8636 Rev 1.5"); + break; + case SFF_8636_REV_8636_20: + ssf_add_dict_string(d, name, "SFF-8636 Rev 2.0"); + break; + case SFF_8636_REV_8636_27: + ssf_add_dict_string(d, name, "SFF-8636 Rev 2.5/2.6/2.7"); + break; + default: + ssf_add_dict_string(d, name, "Unallocated"); + break; + } +} + +/* + * 2-byte internal temperature conversions: + * First byte is a signed 8-bit integer, which is the temp decimal part + * Second byte are 1/256th of degree, which are added to the dec part. + */ +#define SFF_8636_OFFSET_TO_TEMP(offset) ((int16_t)OFFSET_TO_U16(offset)) + +static void sff_8636_dom_parse(const uint8_t *data, struct sff_diags *sd) +{ + int i = 0; + + /* Monitoring Thresholds for Alarms and Warnings */ + sd->sfp_voltage[MCURR] = OFFSET_TO_U16(SFF_8636_VCC_CURR); + sd->sfp_voltage[HALRM] = OFFSET_TO_U16(SFF_8636_VCC_HALRM); + sd->sfp_voltage[LALRM] = OFFSET_TO_U16(SFF_8636_VCC_LALRM); + sd->sfp_voltage[HWARN] = OFFSET_TO_U16(SFF_8636_VCC_HWARN); + sd->sfp_voltage[LWARN] = OFFSET_TO_U16(SFF_8636_VCC_LWARN); + + sd->sfp_temp[MCURR] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_CURR); + sd->sfp_temp[HALRM] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_HALRM); + sd->sfp_temp[LALRM] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_LALRM); + sd->sfp_temp[HWARN] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_HWARN); + sd->sfp_temp[LWARN] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_LWARN); + + sd->bias_cur[HALRM] = OFFSET_TO_U16(SFF_8636_TX_BIAS_HALRM); + sd->bias_cur[LALRM] = OFFSET_TO_U16(SFF_8636_TX_BIAS_LALRM); + sd->bias_cur[HWARN] = OFFSET_TO_U16(SFF_8636_TX_BIAS_HWARN); + sd->bias_cur[LWARN] = OFFSET_TO_U16(SFF_8636_TX_BIAS_LWARN); + + sd->tx_power[HALRM] = OFFSET_TO_U16(SFF_8636_TX_PWR_HALRM); + sd->tx_power[LALRM] = OFFSET_TO_U16(SFF_8636_TX_PWR_LALRM); + sd->tx_power[HWARN] = OFFSET_TO_U16(SFF_8636_TX_PWR_HWARN); + sd->tx_power[LWARN] = OFFSET_TO_U16(SFF_8636_TX_PWR_LWARN); + + sd->rx_power[HALRM] = OFFSET_TO_U16(SFF_8636_RX_PWR_HALRM); + sd->rx_power[LALRM] = OFFSET_TO_U16(SFF_8636_RX_PWR_LALRM); + sd->rx_power[HWARN] = OFFSET_TO_U16(SFF_8636_RX_PWR_HWARN); + sd->rx_power[LWARN] = OFFSET_TO_U16(SFF_8636_RX_PWR_LWARN); + + + /* Channel Specific Data */ + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + sd->scd[i].bias_cur = OFFSET_TO_U16(tx_bias_offset[i]); + sd->scd[i].rx_power = OFFSET_TO_U16(rx_power_offset[i]); + sd->scd[i].tx_power = OFFSET_TO_U16(tx_power_offset[i]); + } + +} + +static void sff_8636_show_dom(const uint8_t *data, uint32_t eeprom_len, struct rte_tel_data *d) +{ + struct sff_diags sd = {0}; + const char *rx_power_string = NULL; + char power_string[MAX_DESC_SIZE]; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + int i; + + /* + * There is no clear identifier to signify the existence of + * optical diagnostics similar to SFF-8472. So checking existence + * of page 3, will provide the gurantee for existence of alarms + * and thresholds + * If pagging support exists, then supports_alarms is marked as 1 + */ + + if (eeprom_len == RTE_ETH_MODULE_SFF_8636_MAX_LEN) { + if (!(data[SFF_8636_STATUS_2_OFFSET] & + SFF_8636_STATUS_PAGE_3_PRESENT)) { + sd.supports_alarms = 1; + } + } + + sd.rx_power_type = data[SFF_8636_DIAG_TYPE_OFFSET] & + SFF_8636_RX_PWR_TYPE_MASK; + sd.tx_power_type = data[SFF_8636_DIAG_TYPE_OFFSET] & + SFF_8636_RX_PWR_TYPE_MASK; + + sff_8636_dom_parse(data, &sd); + + SPRINT_TEMP(val_string, sd.sfp_temp[MCURR]); + ssf_add_dict_string(d, "Module temperature", val_string); + + SPRINT_VCC(val_string, sd.sfp_voltage[MCURR]); + ssf_add_dict_string(d, "Module voltage", val_string); + + /* + * SFF-8636/8436 spec is not clear whether RX power/ TX bias + * current fields are supported or not. A valid temperature + * reading is used as existence for TX/RX power. + */ + if ((sd.sfp_temp[MCURR] == 0x0) || + (sd.sfp_temp[MCURR] == (int16_t)0xFFFF)) + return; + + ssf_add_dict_string(d, "Alarm/warning flags implemented", + (sd.supports_alarms ? "Yes" : "No")); + + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + snprintf(power_string, MAX_DESC_SIZE, "%s (Channel %d)", + "Laser tx bias current", i+1); + SPRINT_BIAS(val_string, sd.scd[i].bias_cur); + ssf_add_dict_string(d, power_string, val_string); + } + + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + snprintf(power_string, MAX_DESC_SIZE, "%s (Channel %d)", + "Transmit avg optical power", i+1); + SPRINT_xX_PWR(val_string, sd.scd[i].tx_power); + ssf_add_dict_string(d, power_string, val_string); + } + + if (!sd.rx_power_type) + rx_power_string = "Receiver signal OMA"; + else + rx_power_string = "Rcvr signal avg optical power"; + + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + snprintf(power_string, MAX_DESC_SIZE, "%s(Channel %d)", + rx_power_string, i+1); + SPRINT_xX_PWR(val_string, sd.scd[i].rx_power); + ssf_add_dict_string(d, power_string, val_string); + } + + if (sd.supports_alarms) { + for (i = 0; sff_8636_aw_flags[i].str; ++i) { + ssf_add_dict_string(d, sff_8636_aw_flags[i].str, + data[sff_8636_aw_flags[i].offset] + & sff_8636_aw_flags[i].value ? "On" : "Off"); + } + + sff_show_thresholds(sd, d); + } + +} +void sff_8636_show_all(const uint8_t *data, uint32_t eeprom_len, struct rte_tel_data *d) +{ + sff_8636_show_identifier(data, d); + if ((data[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP) || + (data[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP_PLUS) || + (data[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP28)) { + sff_8636_show_ext_identifier(data, d); + sff_8636_show_connector(data, d); + sff_8636_show_transceiver(data, d); + sff_8636_show_encoding(data, d); + sff_show_value_with_unit(data, SFF_8636_BR_NOMINAL_OFFSET, + "BR, Nominal", 100, "Mbps", d); + sff_8636_show_rate_identifier(data, d); + sff_show_value_with_unit(data, SFF_8636_SM_LEN_OFFSET, + "Length (SMF,km)", 1, "km", d); + sff_show_value_with_unit(data, SFF_8636_OM3_LEN_OFFSET, + "Length (OM3 50um)", 2, "m", d); + sff_show_value_with_unit(data, SFF_8636_OM2_LEN_OFFSET, + "Length (OM2 50um)", 1, "m", d); + sff_show_value_with_unit(data, SFF_8636_OM1_LEN_OFFSET, + "Length (OM1 62.5um)", 1, "m", d); + sff_show_value_with_unit(data, SFF_8636_CBL_LEN_OFFSET, + "Length (Copper or Active cable)", 1, "m", d); + sff_8636_show_wavelength_or_copper_compliance(data, d); + sff_show_ascii(data, SFF_8636_VENDOR_NAME_START_OFFSET, + SFF_8636_VENDOR_NAME_END_OFFSET, "Vendor name", d); + sff_8636_show_oui(data, d); + sff_show_ascii(data, SFF_8636_VENDOR_PN_START_OFFSET, + SFF_8636_VENDOR_PN_END_OFFSET, "Vendor PN", d); + sff_show_ascii(data, SFF_8636_VENDOR_REV_START_OFFSET, + SFF_8636_VENDOR_REV_END_OFFSET, "Vendor rev", d); + sff_show_ascii(data, SFF_8636_VENDOR_SN_START_OFFSET, + SFF_8636_VENDOR_SN_END_OFFSET, "Vendor SN", d); + sff_show_ascii(data, SFF_8636_DATE_YEAR_OFFSET, + SFF_8636_DATE_VENDOR_LOT_OFFSET + 1, "Date code", d); + sff_8636_show_revision_compliance(data, d); + sff_8636_show_dom(data, eeprom_len, d); + } +} diff --git a/lib/ethdev/sff_8636.h b/lib/ethdev/sff_8636.h new file mode 100644 index 0000000000..49e5feb35f --- /dev/null +++ b/lib/ethdev/sff_8636.h @@ -0,0 +1,611 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * SFF-8636 standards based QSFP EEPROM Field Definitions + * + */ + +#ifndef _SFF_8636_H_ +#define _SFF_8636_H_ + +/*------------------------------------------------------------------------------ + * + * QSFP EEPROM data structures + * + * register info from SFF-8636 Rev 2.7 + */ + +/*------------------------------------------------------------------------------ + * + * Lower Memory Page 00h + * Measurement, Diagnostic and Control Functions + * + */ +/* Identifier - 0 */ +/* Values are defined under SFF_8024_ID_OFFSET */ +#define SFF_8636_ID_OFFSET 0x00 + +#define SFF_8636_REV_COMPLIANCE_OFFSET 0x01 +#define SFF_8636_REV_UNSPECIFIED 0x00 +#define SFF_8636_REV_8436_48 0x01 +#define SFF_8636_REV_8436_8636 0x02 +#define SFF_8636_REV_8636_13 0x03 +#define SFF_8636_REV_8636_14 0x04 +#define SFF_8636_REV_8636_15 0x05 +#define SFF_8636_REV_8636_20 0x06 +#define SFF_8636_REV_8636_27 0x07 + +#define SFF_8636_STATUS_2_OFFSET 0x02 +/* Flat Memory:0- Paging, 1- Page 0 only */ +#define SFF_8636_STATUS_PAGE_3_PRESENT (1 << 2) +#define SFF_8636_STATUS_INTL_OUTPUT (1 << 1) +#define SFF_8636_STATUS_DATA_NOT_READY (1 << 0) + +/* Channel Status Interrupt Flags - 3-5 */ +#define SFF_8636_LOS_AW_OFFSET 0x03 +#define SFF_8636_TX4_LOS_AW (1 << 7) +#define SFF_8636_TX3_LOS_AW (1 << 6) +#define SFF_8636_TX2_LOS_AW (1 << 5) +#define SFF_8636_TX1_LOS_AW (1 << 4) +#define SFF_8636_RX4_LOS_AW (1 << 3) +#define SFF_8636_RX3_LOS_AW (1 << 2) +#define SFF_8636_RX2_LOS_AW (1 << 1) +#define SFF_8636_RX1_LOS_AW (1 << 0) + +#define SFF_8636_FAULT_AW_OFFSET 0x04 +#define SFF_8636_TX4_FAULT_AW (1 << 3) +#define SFF_8636_TX3_FAULT_AW (1 << 2) +#define SFF_8636_TX2_FAULT_AW (1 << 1) +#define SFF_8636_TX1_FAULT_AW (1 << 0) + +/* Module Monitor Interrupt Flags - 6-8 */ +#define SFF_8636_TEMP_AW_OFFSET 0x06 +#define SFF_8636_TEMP_HALARM_STATUS (1 << 7) +#define SFF_8636_TEMP_LALARM_STATUS (1 << 6) +#define SFF_8636_TEMP_HWARN_STATUS (1 << 5) +#define SFF_8636_TEMP_LWARN_STATUS (1 << 4) + +#define SFF_8636_VCC_AW_OFFSET 0x07 +#define SFF_8636_VCC_HALARM_STATUS (1 << 7) +#define SFF_8636_VCC_LALARM_STATUS (1 << 6) +#define SFF_8636_VCC_HWARN_STATUS (1 << 5) +#define SFF_8636_VCC_LWARN_STATUS (1 << 4) + +/* Channel Monitor Interrupt Flags - 9-21 */ +#define SFF_8636_RX_PWR_12_AW_OFFSET 0x09 +#define SFF_8636_RX_PWR_1_HALARM (1 << 7) +#define SFF_8636_RX_PWR_1_LALARM (1 << 6) +#define SFF_8636_RX_PWR_1_HWARN (1 << 5) +#define SFF_8636_RX_PWR_1_LWARN (1 << 4) +#define SFF_8636_RX_PWR_2_HALARM (1 << 3) +#define SFF_8636_RX_PWR_2_LALARM (1 << 2) +#define SFF_8636_RX_PWR_2_HWARN (1 << 1) +#define SFF_8636_RX_PWR_2_LWARN (1 << 0) + +#define SFF_8636_RX_PWR_34_AW_OFFSET 0x0A +#define SFF_8636_RX_PWR_3_HALARM (1 << 7) +#define SFF_8636_RX_PWR_3_LALARM (1 << 6) +#define SFF_8636_RX_PWR_3_HWARN (1 << 5) +#define SFF_8636_RX_PWR_3_LWARN (1 << 4) +#define SFF_8636_RX_PWR_4_HALARM (1 << 3) +#define SFF_8636_RX_PWR_4_LALARM (1 << 2) +#define SFF_8636_RX_PWR_4_HWARN (1 << 1) +#define SFF_8636_RX_PWR_4_LWARN (1 << 0) + +#define SFF_8636_TX_BIAS_12_AW_OFFSET 0x0B +#define SFF_8636_TX_BIAS_1_HALARM (1 << 7) +#define SFF_8636_TX_BIAS_1_LALARM (1 << 6) +#define SFF_8636_TX_BIAS_1_HWARN (1 << 5) +#define SFF_8636_TX_BIAS_1_LWARN (1 << 4) +#define SFF_8636_TX_BIAS_2_HALARM (1 << 3) +#define SFF_8636_TX_BIAS_2_LALARM (1 << 2) +#define SFF_8636_TX_BIAS_2_HWARN (1 << 1) +#define SFF_8636_TX_BIAS_2_LWARN (1 << 0) + +#define SFF_8636_TX_BIAS_34_AW_OFFSET 0xC +#define SFF_8636_TX_BIAS_3_HALARM (1 << 7) +#define SFF_8636_TX_BIAS_3_LALARM (1 << 6) +#define SFF_8636_TX_BIAS_3_HWARN (1 << 5) +#define SFF_8636_TX_BIAS_3_LWARN (1 << 4) +#define SFF_8636_TX_BIAS_4_HALARM (1 << 3) +#define SFF_8636_TX_BIAS_4_LALARM (1 << 2) +#define SFF_8636_TX_BIAS_4_HWARN (1 << 1) +#define SFF_8636_TX_BIAS_4_LWARN (1 << 0) + +#define SFF_8636_TX_PWR_12_AW_OFFSET 0x0D +#define SFF_8636_TX_PWR_1_HALARM (1 << 7) +#define SFF_8636_TX_PWR_1_LALARM (1 << 6) +#define SFF_8636_TX_PWR_1_HWARN (1 << 5) +#define SFF_8636_TX_PWR_1_LWARN (1 << 4) +#define SFF_8636_TX_PWR_2_HALARM (1 << 3) +#define SFF_8636_TX_PWR_2_LALARM (1 << 2) +#define SFF_8636_TX_PWR_2_HWARN (1 << 1) +#define SFF_8636_TX_PWR_2_LWARN (1 << 0) + +#define SFF_8636_TX_PWR_34_AW_OFFSET 0x0E +#define SFF_8636_TX_PWR_3_HALARM (1 << 7) +#define SFF_8636_TX_PWR_3_LALARM (1 << 6) +#define SFF_8636_TX_PWR_3_HWARN (1 << 5) +#define SFF_8636_TX_PWR_3_LWARN (1 << 4) +#define SFF_8636_TX_PWR_4_HALARM (1 << 3) +#define SFF_8636_TX_PWR_4_LALARM (1 << 2) +#define SFF_8636_TX_PWR_4_HWARN (1 << 1) +#define SFF_8636_TX_PWR_4_LWARN (1 << 0) + +/* Module Monitoring Values - 22-33 */ +#define SFF_8636_TEMP_CURR 0x16 +#define SFF_8636_TEMP_MSB_OFFSET 0x16 +#define SFF_8636_TEMP_LSB_OFFSET 0x17 + +#define SFF_8636_VCC_CURR 0x1A +#define SFF_8636_VCC_MSB_OFFSET 0x1A +#define SFF_8636_VCC_LSB_OFFSET 0x1B + +/* Channel Monitoring Values - 34-81 */ +#define SFF_8636_RX_PWR_1_OFFSET 0x22 +#define SFF_8636_RX_PWR_2_OFFSET 0x24 +#define SFF_8636_RX_PWR_3_OFFSET 0x26 +#define SFF_8636_RX_PWR_4_OFFSET 0x28 + +#define SFF_8636_TX_BIAS_1_OFFSET 0x2A +#define SFF_8636_TX_BIAS_2_OFFSET 0x2C +#define SFF_8636_TX_BIAS_3_OFFSET 0x2E +#define SFF_8636_TX_BIAS_4_OFFSET 0x30 + +#define SFF_8636_TX_PWR_1_OFFSET 0x32 +#define SFF_8636_TX_PWR_2_OFFSET 0x34 +#define SFF_8636_TX_PWR_3_OFFSET 0x36 +#define SFF_8636_TX_PWR_4_OFFSET 0x38 + +/* Control Bytes - 86 - 99 */ +#define SFF_8636_TX_DISABLE_OFFSET 0x56 +#define SFF_8636_TX_DISABLE_4 (1 << 3) +#define SFF_8636_TX_DISABLE_3 (1 << 2) +#define SFF_8636_TX_DISABLE_2 (1 << 1) +#define SFF_8636_TX_DISABLE_1 (1 << 0) + +#define SFF_8636_RX_RATE_SELECT_OFFSET 0x57 +#define SFF_8636_RX_RATE_SELECT_4_MASK (3 << 6) +#define SFF_8636_RX_RATE_SELECT_3_MASK (3 << 4) +#define SFF_8636_RX_RATE_SELECT_2_MASK (3 << 2) +#define SFF_8636_RX_RATE_SELECT_1_MASK (3 << 0) + +#define SFF_8636_TX_RATE_SELECT_OFFSET 0x58 +#define SFF_8636_TX_RATE_SELECT_4_MASK (3 << 6) +#define SFF_8636_TX_RATE_SELECT_3_MASK (3 << 4) +#define SFF_8636_TX_RATE_SELECT_2_MASK (3 << 2) +#define SFF_8636_TX_RATE_SELECT_1_MASK (3 << 0) + +#define SFF_8636_RX_APP_SELECT_4_OFFSET 0x58 +#define SFF_8636_RX_APP_SELECT_3_OFFSET 0x59 +#define SFF_8636_RX_APP_SELECT_2_OFFSET 0x5A +#define SFF_8636_RX_APP_SELECT_1_OFFSET 0x5B + +#define SFF_8636_PWR_MODE_OFFSET 0x5D +#define SFF_8636_HIGH_PWR_ENABLE (1 << 2) +#define SFF_8636_LOW_PWR_MODE (1 << 1) +#define SFF_8636_PWR_OVERRIDE (1 << 0) + +#define SFF_8636_TX_APP_SELECT_4_OFFSET 0x5E +#define SFF_8636_TX_APP_SELECT_3_OFFSET 0x5F +#define SFF_8636_TX_APP_SELECT_2_OFFSET 0x60 +#define SFF_8636_TX_APP_SELECT_1_OFFSET 0x61 + +#define SFF_8636_LOS_MASK_OFFSET 0x64 +#define SFF_8636_TX_LOS_4_MASK (1 << 7) +#define SFF_8636_TX_LOS_3_MASK (1 << 6) +#define SFF_8636_TX_LOS_2_MASK (1 << 5) +#define SFF_8636_TX_LOS_1_MASK (1 << 4) +#define SFF_8636_RX_LOS_4_MASK (1 << 3) +#define SFF_8636_RX_LOS_3_MASK (1 << 2) +#define SFF_8636_RX_LOS_2_MASK (1 << 1) +#define SFF_8636_RX_LOS_1_MASK (1 << 0) + +#define SFF_8636_FAULT_MASK_OFFSET 0x65 +#define SFF_8636_TX_FAULT_1_MASK (1 << 3) +#define SFF_8636_TX_FAULT_2_MASK (1 << 2) +#define SFF_8636_TX_FAULT_3_MASK (1 << 1) +#define SFF_8636_TX_FAULT_4_MASK (1 << 0) + +#define SFF_8636_TEMP_MASK_OFFSET 0x67 +#define SFF_8636_TEMP_HALARM_MASK (1 << 7) +#define SFF_8636_TEMP_LALARM_MASK (1 << 6) +#define SFF_8636_TEMP_HWARN_MASK (1 << 5) +#define SFF_8636_TEMP_LWARN_MASK (1 << 4) + +#define SFF_8636_VCC_MASK_OFFSET 0x68 +#define SFF_8636_VCC_HALARM_MASK (1 << 7) +#define SFF_8636_VCC_LALARM_MASK (1 << 6) +#define SFF_8636_VCC_HWARN_MASK (1 << 5) +#define SFF_8636_VCC_LWARN_MASK (1 << 4) + +/*------------------------------------------------------------------------------ + * + * Upper Memory Page 00h + * Serial ID - Base ID, Extended ID and Vendor Specific ID fields + * + */ +/* Identifier - 128 */ +/* Identifier values same as Lower Memory Page 00h */ +#define SFF_8636_UPPER_PAGE_0_ID_OFFSET 0x80 + +/* Extended Identifier - 128 */ +#define SFF_8636_EXT_ID_OFFSET 0x81 +#define SFF_8636_EXT_ID_PWR_CLASS_MASK 0xC0 +#define SFF_8636_EXT_ID_PWR_CLASS_1 (0 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_2 (1 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_3 (2 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_4 (3 << 6) +#define SFF_8636_EXT_ID_CLIE_MASK 0x10 +#define SFF_8636_EXT_ID_CLIEI_CODE_PRESENT (1 << 4) +#define SFF_8636_EXT_ID_CDR_TX_MASK 0x08 +#define SFF_8636_EXT_ID_CDR_TX_PRESENT (1 << 3) +#define SFF_8636_EXT_ID_CDR_RX_MASK 0x04 +#define SFF_8636_EXT_ID_CDR_RX_PRESENT (1 << 2) +#define SFF_8636_EXT_ID_EPWR_CLASS_MASK 0x03 +#define SFF_8636_EXT_ID_PWR_CLASS_LEGACY 0 +#define SFF_8636_EXT_ID_PWR_CLASS_5 1 +#define SFF_8636_EXT_ID_PWR_CLASS_6 2 +#define SFF_8636_EXT_ID_PWR_CLASS_7 3 + +/* Connector Values offset - 130 */ +/* Values are defined under SFF_8024_CTOR */ +#define SFF_8636_CTOR_OFFSET 0x82 +#define SFF_8636_CTOR_UNKNOWN 0x00 +#define SFF_8636_CTOR_SC 0x01 +#define SFF_8636_CTOR_FC_STYLE_1 0x02 +#define SFF_8636_CTOR_FC_STYLE_2 0x03 +#define SFF_8636_CTOR_BNC_TNC 0x04 +#define SFF_8636_CTOR_FC_COAX 0x05 +#define SFF_8636_CTOR_FIBER_JACK 0x06 +#define SFF_8636_CTOR_LC 0x07 +#define SFF_8636_CTOR_MT_RJ 0x08 +#define SFF_8636_CTOR_MU 0x09 +#define SFF_8636_CTOR_SG 0x0A +#define SFF_8636_CTOR_OPT_PT 0x0B +#define SFF_8636_CTOR_MPO 0x0C +/* 0D-1Fh --- Reserved */ +#define SFF_8636_CTOR_HSDC_II 0x20 +#define SFF_8636_CTOR_COPPER_PT 0x21 +#define SFF_8636_CTOR_RJ45 0x22 +#define SFF_8636_CTOR_NO_SEPARABLE 0x23 +#define SFF_8636_CTOR_MXC_2X16 0x24 + +/* Specification Compliance - 131-138 */ +/* Ethernet Compliance Codes - 131 */ +#define SFF_8636_ETHERNET_COMP_OFFSET 0x83 +#define SFF_8636_ETHERNET_RSRVD (1 << 7) +#define SFF_8636_ETHERNET_10G_LRM (1 << 6) +#define SFF_8636_ETHERNET_10G_LR (1 << 5) +#define SFF_8636_ETHERNET_10G_SR (1 << 4) +#define SFF_8636_ETHERNET_40G_CR4 (1 << 3) +#define SFF_8636_ETHERNET_40G_SR4 (1 << 2) +#define SFF_8636_ETHERNET_40G_LR4 (1 << 1) +#define SFF_8636_ETHERNET_40G_ACTIVE (1 << 0) + +/* SONET Compliance Codes - 132 */ +#define SFF_8636_SONET_COMP_OFFSET 0x84 +#define SFF_8636_SONET_40G_OTN (1 << 3) +#define SFF_8636_SONET_OC48_LR (1 << 2) +#define SFF_8636_SONET_OC48_IR (1 << 1) +#define SFF_8636_SONET_OC48_SR (1 << 0) + +/* SAS/SATA Complaince Codes - 133 */ +#define SFF_8636_SAS_COMP_OFFSET 0x85 +#define SFF_8636_SAS_12G (1 << 6) +#define SFF_8636_SAS_6G (1 << 5) +#define SFF_8636_SAS_3G (1 << 4) + +/* Gigabit Ethernet Compliance Codes - 134 */ +#define SFF_8636_GIGE_COMP_OFFSET 0x86 +#define SFF_8636_GIGE_1000_BASE_T (1 << 3) +#define SFF_8636_GIGE_1000_BASE_CX (1 << 2) +#define SFF_8636_GIGE_1000_BASE_LX (1 << 1) +#define SFF_8636_GIGE_1000_BASE_SX (1 << 0) + +/* Fibre Channel Link length/Transmitter Tech. - 135,136 */ +#define SFF_8636_FC_LEN_OFFSET 0x87 +#define SFF_8636_FC_LEN_VERY_LONG (1 << 7) +#define SFF_8636_FC_LEN_SHORT (1 << 6) +#define SFF_8636_FC_LEN_INT (1 << 5) +#define SFF_8636_FC_LEN_LONG (1 << 4) +#define SFF_8636_FC_LEN_MED (1 << 3) +#define SFF_8636_FC_TECH_LONG_LC (1 << 1) +#define SFF_8636_FC_TECH_ELEC_INTER (1 << 0) + +#define SFF_8636_FC_TECH_OFFSET 0x88 +#define SFF_8636_FC_TECH_ELEC_INTRA (1 << 7) +#define SFF_8636_FC_TECH_SHORT_WO_OFC (1 << 6) +#define SFF_8636_FC_TECH_SHORT_W_OFC (1 << 5) +#define SFF_8636_FC_TECH_LONG_LL (1 << 4) + +/* Fibre Channel Transmitter Media - 137 */ +#define SFF_8636_FC_TRANS_MEDIA_OFFSET 0x89 +/* Twin Axial Pair */ +#define SFF_8636_FC_TRANS_MEDIA_TW (1 << 7) +/* Shielded Twisted Pair */ +#define SFF_8636_FC_TRANS_MEDIA_TP (1 << 6) +/* Miniature Coax */ +#define SFF_8636_FC_TRANS_MEDIA_MI (1 << 5) +/* Video Coax */ +#define SFF_8636_FC_TRANS_MEDIA_TV (1 << 4) +/* Multi-mode 62.5m */ +#define SFF_8636_FC_TRANS_MEDIA_M6 (1 << 3) +/* Multi-mode 50m */ +#define SFF_8636_FC_TRANS_MEDIA_M5 (1 << 2) +/* Multi-mode 50um */ +#define SFF_8636_FC_TRANS_MEDIA_OM3 (1 << 1) +/* Single Mode */ +#define SFF_8636_FC_TRANS_MEDIA_SM (1 << 0) + +/* Fibre Channel Speed - 138 */ +#define SFF_8636_FC_SPEED_OFFSET 0x8A +#define SFF_8636_FC_SPEED_1200_MBPS (1 << 7) +#define SFF_8636_FC_SPEED_800_MBPS (1 << 6) +#define SFF_8636_FC_SPEED_1600_MBPS (1 << 5) +#define SFF_8636_FC_SPEED_400_MBPS (1 << 4) +#define SFF_8636_FC_SPEED_200_MBPS (1 << 2) +#define SFF_8636_FC_SPEED_100_MBPS (1 << 0) + +/* Encoding - 139 */ +/* Values are defined under SFF_8024_ENCODING */ +#define SFF_8636_ENCODING_OFFSET 0x8B +#define SFF_8636_ENCODING_MANCHESTER 0x06 +#define SFF_8636_ENCODING_64B66B 0x05 +#define SFF_8636_ENCODING_SONET 0x04 +#define SFF_8636_ENCODING_NRZ 0x03 +#define SFF_8636_ENCODING_4B5B 0x02 +#define SFF_8636_ENCODING_8B10B 0x01 +#define SFF_8636_ENCODING_UNSPEC 0x00 + +/* BR, Nominal - 140 */ +#define SFF_8636_BR_NOMINAL_OFFSET 0x8C + +/* Extended RateSelect - 141 */ +#define SFF_8636_EXT_RS_OFFSET 0x8D +#define SFF_8636_EXT_RS_V1 (1 << 0) + +/* Length (Standard SM Fiber)-km - 142 */ +#define SFF_8636_SM_LEN_OFFSET 0x8E + +/* Length (OM3)-Unit 2m - 143 */ +#define SFF_8636_OM3_LEN_OFFSET 0x8F + +/* Length (OM2)-Unit 1m - 144 */ +#define SFF_8636_OM2_LEN_OFFSET 0x90 + +/* Length (OM1)-Unit 1m - 145 */ +#define SFF_8636_OM1_LEN_OFFSET 0x91 + +/* Cable Assembly Length -Unit 1m - 146 */ +#define SFF_8636_CBL_LEN_OFFSET 0x92 + +/* Device Technology - 147 */ +#define SFF_8636_DEVICE_TECH_OFFSET 0x93 +/* Transmitter Technology */ +#define SFF_8636_TRANS_TECH_MASK 0xF0 +/* Copper cable, linear active equalizers */ +#define SFF_8636_TRANS_COPPER_LNR_EQUAL (15 << 4) +/* Copper cable, near end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_NEAR_EQUAL (14 << 4) +/* Copper cable, far end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_FAR_EQUAL (13 << 4) +/* Copper cable, near & far end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_LNR_FAR_EQUAL (12 << 4) +/* Copper cable, passive equalized */ +#define SFF_8636_TRANS_COPPER_PAS_EQUAL (11 << 4) +/* Copper cable, unequalized */ +#define SFF_8636_TRANS_COPPER_PAS_UNEQUAL (10 << 4) +/* 1490 nm DFB */ +#define SFF_8636_TRANS_1490_DFB (9 << 4) +/* Others */ +#define SFF_8636_TRANS_OTHERS (8 << 4) +/* 1550 nm EML */ +#define SFF_8636_TRANS_1550_EML (7 << 4) +/* 1310 nm EML */ +#define SFF_8636_TRANS_1310_EML (6 << 4) +/* 1550 nm DFB */ +#define SFF_8636_TRANS_1550_DFB (5 << 4) +/* 1310 nm DFB */ +#define SFF_8636_TRANS_1310_DFB (4 << 4) +/* 1310 nm FP */ +#define SFF_8636_TRANS_1310_FP (3 << 4) +/* 1550 nm VCSEL */ +#define SFF_8636_TRANS_1550_VCSEL (2 << 4) +/* 1310 nm VCSEL */ +#define SFF_8636_TRANS_1310_VCSEL (1 << 4) +/* 850 nm VCSEL */ +#define SFF_8636_TRANS_850_VCSEL (0 << 4) + + /* Active/No wavelength control */ +#define SFF_8636_DEV_TECH_ACTIVE_WAVE_LEN (1 << 3) +/* Cooled transmitter */ +#define SFF_8636_DEV_TECH_COOL_TRANS (1 << 2) +/* APD/Pin Detector */ +#define SFF_8636_DEV_TECH_APD_DETECTOR (1 << 1) +/* Transmitter tunable */ +#define SFF_8636_DEV_TECH_TUNABLE (1 << 0) + +/* Vendor Name - 148-163 */ +#define SFF_8636_VENDOR_NAME_START_OFFSET 0x94 +#define SFF_8636_VENDOR_NAME_END_OFFSET 0xA3 + +/* Extended Module Codes - 164 */ +#define SFF_8636_EXT_MOD_CODE_OFFSET 0xA4 +#define SFF_8636_EXT_MOD_INFINIBAND_EDR (1 << 4) +#define SFF_8636_EXT_MOD_INFINIBAND_FDR (1 << 3) +#define SFF_8636_EXT_MOD_INFINIBAND_QDR (1 << 2) +#define SFF_8636_EXT_MOD_INFINIBAND_DDR (1 << 1) +#define SFF_8636_EXT_MOD_INFINIBAND_SDR (1 << 0) + +/* Vendor OUI - 165-167 */ +#define SFF_8636_VENDOR_OUI_OFFSET 0xA5 +#define SFF_8636_VENDOR_OUI_LEN 3 + +/* Vendor OUI - 165-167 */ +#define SFF_8636_VENDOR_PN_START_OFFSET 0xA8 +#define SFF_8636_VENDOR_PN_END_OFFSET 0xB7 + +/* Vendor Revision - 184-185 */ +#define SFF_8636_VENDOR_REV_START_OFFSET 0xB8 +#define SFF_8636_VENDOR_REV_END_OFFSET 0xB9 + +/* Wavelength - 186-187 */ +#define SFF_8636_WAVELEN_HIGH_BYTE_OFFSET 0xBA +#define SFF_8636_WAVELEN_LOW_BYTE_OFFSET 0xBB + +/* Wavelength Tolerance- 188-189 */ +#define SFF_8636_WAVE_TOL_HIGH_BYTE_OFFSET 0xBC +#define SFF_8636_WAVE_TOL_LOW_BYTE_OFFSET 0xBD + +/* Max case temp - Other than 70 C - 190 */ +#define SFF_8636_MAXCASE_TEMP_OFFSET 0xBE + +/* CC_BASE - 191 */ +#define SFF_8636_CC_BASE_OFFSET 0xBF + +/* Option Values - 192-195 */ +#define SFF_8636_OPTION_1_OFFSET 0xC0 +#define SFF_8636_ETHERNET_UNSPECIFIED 0x00 +#define SFF_8636_ETHERNET_100G_AOC 0x01 +#define SFF_8636_ETHERNET_100G_SR4 0x02 +#define SFF_8636_ETHERNET_100G_LR4 0x03 +#define SFF_8636_ETHERNET_100G_ER4 0x04 +#define SFF_8636_ETHERNET_100G_SR10 0x05 +#define SFF_8636_ETHERNET_100G_CWDM4_FEC 0x06 +#define SFF_8636_ETHERNET_100G_PSM4 0x07 +#define SFF_8636_ETHERNET_100G_ACC 0x08 +#define SFF_8636_ETHERNET_100G_CWDM4_NO_FEC 0x09 +#define SFF_8636_ETHERNET_100G_RSVD1 0x0A +#define SFF_8636_ETHERNET_100G_CR4 0x0B +#define SFF_8636_ETHERNET_25G_CR_CA_S 0x0C +#define SFF_8636_ETHERNET_25G_CR_CA_N 0x0D +#define SFF_8636_ETHERNET_40G_ER4 0x10 +#define SFF_8636_ETHERNET_4X10_SR 0x11 +#define SFF_8636_ETHERNET_40G_PSM4 0x12 +#define SFF_8636_ETHERNET_G959_P1I1_2D1 0x13 +#define SFF_8636_ETHERNET_G959_P1S1_2D2 0x14 +#define SFF_8636_ETHERNET_G959_P1L1_2D2 0x15 +#define SFF_8636_ETHERNET_10GT_SFI 0x16 +#define SFF_8636_ETHERNET_100G_CLR4 0x17 +#define SFF_8636_ETHERNET_100G_AOC2 0x18 +#define SFF_8636_ETHERNET_100G_ACC2 0x19 + +#define SFF_8636_OPTION_2_OFFSET 0xC1 +/* Rx output amplitude */ +#define SFF_8636_O2_RX_OUTPUT_AMP (1 << 0) +#define SFF_8636_OPTION_3_OFFSET 0xC2 +/* Rx Squelch Disable */ +#define SFF_8636_O3_RX_SQL_DSBL (1 << 3) +/* Rx Output Disable capable */ +#define SFF_8636_O3_RX_OUTPUT_DSBL (1 << 2) +/* Tx Squelch Disable */ +#define SFF_8636_O3_TX_SQL_DSBL (1 << 1) +/* Tx Squelch Impl */ +#define SFF_8636_O3_TX_SQL_IMPL (1 << 0) +#define SFF_8636_OPTION_4_OFFSET 0xC3 +/* Memory Page 02 present */ +#define SFF_8636_O4_PAGE_02_PRESENT (1 << 7) +/* Memory Page 01 present */ +#define SFF_8636_O4_PAGE_01_PRESENT (1 << 6) +/* Rate Select implemented */ +#define SFF_8636_O4_RATE_SELECT (1 << 5) +/* Tx_DISABLE implemented */ +#define SFF_8636_O4_TX_DISABLE (1 << 4) +/* Tx_FAULT implemented */ +#define SFF_8636_O4_TX_FAULT (1 << 3) +/* Tx Squelch implemented */ +#define SFF_8636_O4_TX_SQUELCH (1 << 2) +/* Tx Loss of Signal */ +#define SFF_8636_O4_TX_LOS (1 << 1) + +/* Vendor SN - 196-211 */ +#define SFF_8636_VENDOR_SN_START_OFFSET 0xC4 +#define SFF_8636_VENDOR_SN_END_OFFSET 0xD3 + +/* Vendor Date - 212-219 */ +#define SFF_8636_DATE_YEAR_OFFSET 0xD4 +#define SFF_8636_DATE_YEAR_LEN 2 +#define SFF_8636_DATE_MONTH_OFFSET 0xD6 +#define SFF_8636_DATE_MONTH_LEN 2 +#define SFF_8636_DATE_DAY_OFFSET 0xD8 +#define SFF_8636_DATE_DAY_LEN 2 +#define SFF_8636_DATE_VENDOR_LOT_OFFSET 0xDA +#define SFF_8636_DATE_VENDOR_LOT_LEN 2 + +/* Diagnostic Monitoring Type - 220 */ +#define SFF_8636_DIAG_TYPE_OFFSET 0xDC +#define SFF_8636_RX_PWR_TYPE_MASK 0x8 +#define SFF_8636_RX_PWR_TYPE_AVG_PWR (1 << 3) +#define SFF_8636_RX_PWR_TYPE_OMA (0 << 3) +#define SFF_8636_TX_PWR_TYPE_MASK 0x4 +#define SFF_8636_TX_PWR_TYPE_AVG_PWR (1 << 2) + +/* Enhanced Options - 221 */ +#define SFF_8636_ENH_OPTIONS_OFFSET 0xDD +#define SFF_8636_RATE_SELECT_EXT_SUPPORT (1 << 3) +#define SFF_8636_RATE_SELECT_APP_TABLE_SUPPORT (1 << 2) + +/* Check code - 223 */ +#define SFF_8636_CC_EXT_OFFSET 0xDF +#define SFF_8636_CC_EXT_LEN 1 + +/*------------------------------------------------------------------------------ + * + * Upper Memory Page 03h + * Contains module thresholds, channel thresholds and masks, + * and optional channel controls + * + * Offset - Page Num(3) * PageSize(0x80) + Page offset + */ + +/* Module Thresholds (48 Bytes) 128-175 */ +/* MSB at low address, LSB at high address */ +#define SFF_8636_TEMP_HALRM 0x200 +#define SFF_8636_TEMP_LALRM 0x202 +#define SFF_8636_TEMP_HWARN 0x204 +#define SFF_8636_TEMP_LWARN 0x206 + +#define SFF_8636_VCC_HALRM 0x210 +#define SFF_8636_VCC_LALRM 0x212 +#define SFF_8636_VCC_HWARN 0x214 +#define SFF_8636_VCC_LWARN 0x216 + +#define SFF_8636_RX_PWR_HALRM 0x230 +#define SFF_8636_RX_PWR_LALRM 0x232 +#define SFF_8636_RX_PWR_HWARN 0x234 +#define SFF_8636_RX_PWR_LWARN 0x236 + +#define SFF_8636_TX_BIAS_HALRM 0x238 +#define SFF_8636_TX_BIAS_LALRM 0x23A +#define SFF_8636_TX_BIAS_HWARN 0x23C +#define SFF_8636_TX_BIAS_LWARN 0x23E + +#define SFF_8636_TX_PWR_HALRM 0x240 +#define SFF_8636_TX_PWR_LALRM 0x242 +#define SFF_8636_TX_PWR_HWARN 0x244 +#define SFF_8636_TX_PWR_LWARN 0x246 + +#define ETH_MODULE_SFF_8636_MAX_LEN 640 +#define ETH_MODULE_SFF_8436_MAX_LEN 640 + +const uint8_t rx_power_offset[MAX_CHANNEL_NUM] = { + SFF_8636_RX_PWR_1_OFFSET, + SFF_8636_RX_PWR_2_OFFSET, + SFF_8636_RX_PWR_3_OFFSET, + SFF_8636_RX_PWR_4_OFFSET, +}; +const uint8_t tx_power_offset[MAX_CHANNEL_NUM] = { + SFF_8636_TX_PWR_1_OFFSET, + SFF_8636_TX_PWR_2_OFFSET, + SFF_8636_TX_PWR_3_OFFSET, + SFF_8636_TX_PWR_4_OFFSET, +}; +const uint8_t tx_bias_offset[MAX_CHANNEL_NUM] = { + SFF_8636_TX_BIAS_1_OFFSET, + SFF_8636_TX_BIAS_2_OFFSET, + SFF_8636_TX_BIAS_3_OFFSET, + SFF_8636_TX_BIAS_4_OFFSET, +}; + +#endif /* _SFF_8636_H_ */ -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v8 5/5] ethdev: format module EEPROM for SFF-8636 2022-05-25 3:14 ` [PATCH v8 5/5] ethdev: format module EEPROM for SFF-8636 Robin Zhang @ 2022-05-25 9:01 ` Andrew Rybchenko 2022-05-25 12:01 ` Andrew Rybchenko 1 sibling, 0 replies; 77+ messages in thread From: Andrew Rybchenko @ 2022-05-25 9:01 UTC (permalink / raw) To: Robin Zhang, dev; +Cc: thomas, kevinx.liu On 5/25/22 06:14, Robin Zhang wrote: > This patch implements format module EEPROM information for > SFF-8636 Rev 2.7 > > Signed-off-by: Robin Zhang <robinx.zhang@intel.com> [snip] > + /* > + * There is no clear identifier to signify the existence of > + * optical diagnostics similar to SFF-8472. So checking existence > + * of page 3, will provide the gurantee for existence of alarms typo: gurantee -> guarantee (found by checkpatches.sh) > +const uint8_t rx_power_offset[MAX_CHANNEL_NUM] = { I think it should be "static". You don't need it outside of corresponding C file. Also, please, add a namespace prefix "sff_8636_" to make it easier in the code to understand that the symbol is global (not function/block local). > + SFF_8636_RX_PWR_1_OFFSET, TAB must be used to indent. checkpatches.sh complains on it. Please, run sanity checks yourself before sending patches upstream as contributor guidelines say. > + SFF_8636_RX_PWR_2_OFFSET, > + SFF_8636_RX_PWR_3_OFFSET, > + SFF_8636_RX_PWR_4_OFFSET, > +}; > +const uint8_t tx_power_offset[MAX_CHANNEL_NUM] = { > + SFF_8636_TX_PWR_1_OFFSET, > + SFF_8636_TX_PWR_2_OFFSET, > + SFF_8636_TX_PWR_3_OFFSET, > + SFF_8636_TX_PWR_4_OFFSET, > +}; > +const uint8_t tx_bias_offset[MAX_CHANNEL_NUM] = { > + SFF_8636_TX_BIAS_1_OFFSET, > + SFF_8636_TX_BIAS_2_OFFSET, > + SFF_8636_TX_BIAS_3_OFFSET, > + SFF_8636_TX_BIAS_4_OFFSET, > +}; It is wrong to define it in the header. You'll have copies if the header is included in many C files and linker will dislike it. So, it should be moved to sff_8636.c ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v8 5/5] ethdev: format module EEPROM for SFF-8636 2022-05-25 3:14 ` [PATCH v8 5/5] ethdev: format module EEPROM for SFF-8636 Robin Zhang 2022-05-25 9:01 ` Andrew Rybchenko @ 2022-05-25 12:01 ` Andrew Rybchenko 1 sibling, 0 replies; 77+ messages in thread From: Andrew Rybchenko @ 2022-05-25 12:01 UTC (permalink / raw) To: Robin Zhang, dev; +Cc: thomas, kevinx.liu On 5/25/22 06:14, Robin Zhang wrote: > This patch implements format module EEPROM information for > SFF-8636 Rev 2.7 > > Signed-off-by: Robin Zhang <robinx.zhang@intel.com> [snip] > diff --git a/lib/ethdev/sff_8636.c b/lib/ethdev/sff_8636.c > new file mode 100644 > index 0000000000..ad625fc73b > --- /dev/null > +++ b/lib/ethdev/sff_8636.c > @@ -0,0 +1,750 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2022 Intel Corporation > + * > + * Implements SFF-8636 based QSFP+/QSFP28 Diagnostics Memory map. > + * > + */ > + > +#include <stdio.h> > +#include <math.h> > +#include <rte_mbuf.h> > +#include <rte_ethdev.h> > +#include <rte_flow.h> > +#include "sff_common.h" > +#include "sff_8636.h" > +#include "ethdev_sff_telemetry.h" Please, fix includes > +/* Flat Memory:0- Paging, 1- Page 0 only */ > +#define SFF_8636_STATUS_PAGE_3_PRESENT (1 << 2) RTE_BIT32 here and in many cases below? ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v9 0/5] add telemetry command for show module EEPROM 2022-05-25 3:14 ` [PATCH v8 0/5] add telemetry command for show module EEPROM Robin Zhang ` (4 preceding siblings ...) 2022-05-25 3:14 ` [PATCH v8 5/5] ethdev: format module EEPROM for SFF-8636 Robin Zhang @ 2022-05-26 7:32 ` Robin Zhang 2022-05-26 7:32 ` [PATCH v9 1/5] ethdev: add telemetry command for " Robin Zhang ` (5 more replies) 5 siblings, 6 replies; 77+ messages in thread From: Robin Zhang @ 2022-05-26 7:32 UTC (permalink / raw) To: dev; +Cc: thomas, andrew.rybchenko, kevinx.liu, Robin Zhang Introduce a new telemetry command /ethdev/module_eeprom to show module EEPROM for each port. The format of module EEPROM information follows the SFF(Small Form Factor) Committee specifications. Current the format support SFP(Small Formfactor Pluggable)/SFP+/ QSFP+(Quad Small Formfactor Pluggable)/QSFP28 with specs SFF-8079/ SFF-8472/SFF-8024/SFF-8636. Afther run the /ethdev/module_eeprom command, telemetry client will show the module EEPROM information. We keep the same information content compare with Linux utility ethtool, refer to command 'ethtool -m' of ethtool v5.4. v9: - Optimize code format and commit log v8: - refine code v7: - remove "#include <arpa/inet.h>" in lib/ethdev/sff_8472.c v6: - refine code v5: - fix CI robot compile fail issue v4: - remove all printf in primary application, only show information in tememetry client - refine codes v3: - split up codes into several patches for better reivew Robin Zhang (5): ethdev: add telemetry command for module EEPROM ethdev: add common code for different SFF specs ethdev: support SFF-8079 module information telemetry ethdev: support SFF-8472 module information telemetry ethdev: support SFF-8636 module information telemetry devtools/words-case.txt | 1 + lib/ethdev/meson.build | 5 + lib/ethdev/rte_ethdev.c | 3 + lib/ethdev/sff_8079.c | 401 +++++++++++++++++++ lib/ethdev/sff_8472.c | 280 ++++++++++++++ lib/ethdev/sff_8636.c | 764 +++++++++++++++++++++++++++++++++++++ lib/ethdev/sff_8636.h | 590 ++++++++++++++++++++++++++++ lib/ethdev/sff_common.c | 319 ++++++++++++++++ lib/ethdev/sff_common.h | 173 +++++++++ lib/ethdev/sff_telemetry.c | 150 ++++++++ lib/ethdev/sff_telemetry.h | 27 ++ 11 files changed, 2713 insertions(+) create mode 100644 lib/ethdev/sff_8079.c create mode 100644 lib/ethdev/sff_8472.c create mode 100644 lib/ethdev/sff_8636.c create mode 100644 lib/ethdev/sff_8636.h create mode 100644 lib/ethdev/sff_common.c create mode 100644 lib/ethdev/sff_common.h create mode 100644 lib/ethdev/sff_telemetry.c create mode 100644 lib/ethdev/sff_telemetry.h -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v9 1/5] ethdev: add telemetry command for module EEPROM 2022-05-26 7:32 ` [PATCH v9 0/5] add telemetry command for show module EEPROM Robin Zhang @ 2022-05-26 7:32 ` Robin Zhang 2022-05-26 7:32 ` [PATCH v9 2/5] ethdev: add common code for different SFF specs Robin Zhang ` (4 subsequent siblings) 5 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-05-26 7:32 UTC (permalink / raw) To: dev; +Cc: thomas, andrew.rybchenko, kevinx.liu, Robin Zhang Add a new telemetry command /ethdev/module_eeprom to dump the module EEPROM of each port. The format of module EEPROM information follows the SFF(Small Form Factor) Committee specifications. Signed-off-by: Robin Zhang <robinx.zhang@intel.com> Signed-off-by: Kevin Liu <kevinx.liu@intel.com> --- devtools/words-case.txt | 1 + lib/ethdev/meson.build | 1 + lib/ethdev/rte_ethdev.c | 3 + lib/ethdev/sff_telemetry.c | 139 +++++++++++++++++++++++++++++++++++++ lib/ethdev/sff_telemetry.h | 27 +++++++ 5 files changed, 171 insertions(+) create mode 100644 lib/ethdev/sff_telemetry.c create mode 100644 lib/ethdev/sff_telemetry.h diff --git a/devtools/words-case.txt b/devtools/words-case.txt index bc33470532..2f1753bdc8 100644 --- a/devtools/words-case.txt +++ b/devtools/words-case.txt @@ -76,6 +76,7 @@ RSS RVU Rx SCTP +SFF SMP SoC SQ diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index a094585bf7..6a14d0b402 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -11,6 +11,7 @@ sources = files( 'rte_flow.c', 'rte_mtr.c', 'rte_tm.c', + 'sff_telemetry.c', ) headers = files( diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c index 29a3d80466..56814d2e54 100644 --- a/lib/ethdev/rte_ethdev.c +++ b/lib/ethdev/rte_ethdev.c @@ -39,6 +39,7 @@ #include "ethdev_driver.h" #include "ethdev_profile.h" #include "ethdev_private.h" +#include "sff_telemetry.h" struct rte_eth_dev rte_eth_devices[RTE_MAX_ETHPORTS]; @@ -5876,4 +5877,6 @@ RTE_INIT(ethdev_init_telemetry) "Returns the link status for a port. Parameters: int port_id"); rte_telemetry_register_cmd("/ethdev/info", eth_dev_handle_port_info, "Returns the device info for a port. Parameters: int port_id"); + rte_telemetry_register_cmd("/ethdev/module_eeprom", eth_dev_handle_port_module_eeprom, + "Returns module EEPROM info with SFF specs. Parameters: int port_id"); } diff --git a/lib/ethdev/sff_telemetry.c b/lib/ethdev/sff_telemetry.c new file mode 100644 index 0000000000..7da4385223 --- /dev/null +++ b/lib/ethdev/sff_telemetry.c @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + */ + +#include <errno.h> + +#include "rte_ethdev.h" +#include <rte_common.h> +#include "sff_telemetry.h" +#include <telemetry_data.h> + +static void +sff_port_module_eeprom_parse(uint16_t port_id, struct rte_tel_data *d) +{ + struct rte_eth_dev_module_info minfo; + struct rte_dev_eeprom_info einfo; + int ret; + + if (d == NULL) { + RTE_ETHDEV_LOG(ERR, "Dict invalid\n"); + return; + } + + ret = rte_eth_dev_get_module_info(port_id, &minfo); + if (ret != 0) { + switch (ret) { + case -ENODEV: + RTE_ETHDEV_LOG(ERR, "Port index %d invalid\n", port_id); + break; + case -ENOTSUP: + RTE_ETHDEV_LOG(ERR, "Operation not supported by device\n"); + break; + case -EIO: + RTE_ETHDEV_LOG(ERR, "Device is removed\n"); + break; + default: + RTE_ETHDEV_LOG(ERR, "Unable to get port module info, %d\n", ret); + break; + } + return; + } + + einfo.offset = 0; + einfo.length = minfo.eeprom_len; + einfo.data = calloc(1, minfo.eeprom_len); + if (einfo.data == NULL) { + RTE_ETHDEV_LOG(ERR, "Allocation of port %u EEPROM data failed\n", port_id); + return; + } + + ret = rte_eth_dev_get_module_eeprom(port_id, &einfo); + if (ret != 0) { + switch (ret) { + case -ENODEV: + RTE_ETHDEV_LOG(ERR, "Port index %d invalid\n", port_id); + break; + case -ENOTSUP: + RTE_ETHDEV_LOG(ERR, "Operation not supported by device\n"); + break; + case -EIO: + RTE_ETHDEV_LOG(ERR, "Device is removed\n"); + break; + default: + RTE_ETHDEV_LOG(ERR, "Unable to get port module EEPROM, %d\n", ret); + break; + } + free(einfo.data); + return; + } + + switch (minfo.type) { + /* parsing module EEPROM data base on different module type */ + default: + RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); + break; + } + + free(einfo.data); +} + +void +ssf_add_dict_string(struct rte_tel_data *d, const char *name_str, const char *value_str) +{ + struct tel_dict_entry *e = &d->data.dict[d->data_len]; + + if (d->type != RTE_TEL_DICT) + return; + if (d->data_len >= RTE_TEL_MAX_DICT_ENTRIES) { + RTE_ETHDEV_LOG(ERR, "data_len has exceeded the maximum number of inserts\n"); + return; + } + + e->type = RTE_TEL_STRING_VAL; + /* append different values for same keys */ + if (d->data_len > 0) { + struct tel_dict_entry *previous = &d->data.dict[d->data_len - 1]; + if (strcmp(previous->name, name_str) == 0) { + strlcat(previous->value.sval, "; ", RTE_TEL_MAX_STRING_LEN); + strlcat(previous->value.sval, value_str, RTE_TEL_MAX_STRING_LEN); + goto end; + } + } + strlcpy(e->value.sval, value_str, RTE_TEL_MAX_STRING_LEN); + strlcpy(e->name, name_str, RTE_TEL_MAX_STRING_LEN); + d->data_len++; + +end: + return; +} + +int +eth_dev_handle_port_module_eeprom(const char *cmd __rte_unused, const char *params, + struct rte_tel_data *d) +{ + char *end_param; + int port_id; + + if (params == NULL || strlen(params) == 0 || !isdigit(*params)) + return -1; + + errno = 0; + port_id = strtoul(params, &end_param, 0); + + if (errno != 0) { + RTE_ETHDEV_LOG(ERR, "Invalid argument, %d\n", errno); + return -1; + } + + if (*end_param != '\0') + RTE_ETHDEV_LOG(NOTICE, + "Extra parameters [%s] passed to ethdev telemetry command, ignoring\n", + end_param); + + rte_tel_data_start_dict(d); + + sff_port_module_eeprom_parse(port_id, d); + + return 0; +} diff --git a/lib/ethdev/sff_telemetry.h b/lib/ethdev/sff_telemetry.h new file mode 100644 index 0000000000..1fd870e0ef --- /dev/null +++ b/lib/ethdev/sff_telemetry.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + */ + +#ifndef _ETHDEV_SFF_TELEMETRY_H_ +#define _ETHDEV_SFF_TELEMETRY_H_ + +#include <rte_telemetry.h> + +#define SFF_ITEM_VAL_COMPOSE_SIZE 64 + +/* SFF-8079 Optics diagnostics */ +void sff_8079_show_all(const uint8_t *data, struct rte_tel_data *d); + +/* SFF-8472 Optics diagnostics */ +void sff_8472_show_all(const uint8_t *data, struct rte_tel_data *d); + +/* SFF-8636 Optics diagnostics */ +void sff_8636_show_all(const uint8_t *data, uint32_t eeprom_len, struct rte_tel_data *d); + +int eth_dev_handle_port_module_eeprom(const char *cmd __rte_unused, + const char *params, + struct rte_tel_data *d); + +void ssf_add_dict_string(struct rte_tel_data *d, const char *name_str, const char *value_str); + +#endif /* _ETHDEV_SFF_TELEMETRY_H_ */ -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v9 2/5] ethdev: add common code for different SFF specs 2022-05-26 7:32 ` [PATCH v9 0/5] add telemetry command for show module EEPROM Robin Zhang 2022-05-26 7:32 ` [PATCH v9 1/5] ethdev: add telemetry command for " Robin Zhang @ 2022-05-26 7:32 ` Robin Zhang 2022-05-26 7:32 ` [PATCH v9 3/5] ethdev: support SFF-8079 module information telemetry Robin Zhang ` (3 subsequent siblings) 5 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-05-26 7:32 UTC (permalink / raw) To: dev; +Cc: thomas, andrew.rybchenko, kevinx.liu, Robin Zhang Add support for SFF-8024 Rev 4.0 of pluggable I/O configuration and some common utilities for SFF-8436/8636 and SFF-8472/8079. Signed-off-by: Robin Zhang <robinx.zhang@intel.com> Signed-off-by: Kevin Liu <kevinx.liu@intel.com> --- lib/ethdev/meson.build | 1 + lib/ethdev/sff_common.c | 319 ++++++++++++++++++++++++++++++++++++++++ lib/ethdev/sff_common.h | 173 ++++++++++++++++++++++ 3 files changed, 493 insertions(+) create mode 100644 lib/ethdev/sff_common.c create mode 100644 lib/ethdev/sff_common.h diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index 6a14d0b402..4ec21789f5 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -12,6 +12,7 @@ sources = files( 'rte_mtr.c', 'rte_tm.c', 'sff_telemetry.c', + 'sff_common.c', ) headers = files( diff --git a/lib/ethdev/sff_common.c b/lib/ethdev/sff_common.c new file mode 100644 index 0000000000..bd425274e3 --- /dev/null +++ b/lib/ethdev/sff_common.c @@ -0,0 +1,319 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * Implements SFF-8024 Rev 4.0 of pluggable I/O configuration and some + * common utilities for SFF-8436/8636 and SFF-8472/8079 + */ + +#include <math.h> + +#include "sff_common.h" + +double sff_convert_mw_to_dbm(double mw) +{ + return (10. * log10(mw / 1000.)) + 30.; +} + +void sff_show_value_with_unit(const uint8_t *data, unsigned int reg, + const char *name, unsigned int mult, + const char *unit, struct rte_tel_data *d) +{ + unsigned int val = data[reg]; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "%u%s", val * mult, unit); + ssf_add_dict_string(d, name, val_string); +} + +void sff_show_ascii(const uint8_t *data, unsigned int first_reg, + unsigned int last_reg, const char *name, struct rte_tel_data *d) +{ + unsigned int reg, val; + char tmp[3]; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + memset(val_string, 0, sizeof(val_string)); + + while (first_reg <= last_reg && data[last_reg] == ' ') + last_reg--; + for (reg = first_reg; reg <= last_reg; reg++) { + val = data[reg]; + if ((val >= 32) && (val <= 126)) { + snprintf(tmp, sizeof(tmp), "%c", val); + strlcat(val_string, tmp, sizeof(val_string)); + } else { + strlcat(val_string, "_", sizeof(val_string)); + } + } + ssf_add_dict_string(d, name, val_string); +} + +void sff_8024_show_oui(const uint8_t *data, int id_offset, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "%02x:%02x:%02x", + data[id_offset], data[(id_offset) + 1], data[(id_offset) + 2]); + ssf_add_dict_string(d, "Vendor OUI", val_string); +} + +void sff_8024_show_identifier(const uint8_t *data, int id_offset, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[id_offset]); + + switch (data[id_offset]) { + case SFF_8024_ID_UNKNOWN: + strlcat(val_string, " (no module present, unknown, or unspecified)", + sizeof(val_string)); + break; + case SFF_8024_ID_GBIC: + strlcat(val_string, " (GBIC)", sizeof(val_string)); + break; + case SFF_8024_ID_SOLDERED_MODULE: + strlcat(val_string, " (module soldered to motherboard)", sizeof(val_string)); + break; + case SFF_8024_ID_SFP: + strlcat(val_string, " (SFP)", sizeof(val_string)); + break; + case SFF_8024_ID_300_PIN_XBI: + strlcat(val_string, " (300 pin XBI)", sizeof(val_string)); + break; + case SFF_8024_ID_XENPAK: + strlcat(val_string, " (XENPAK)", sizeof(val_string)); + break; + case SFF_8024_ID_XFP: + strlcat(val_string, " (XFP)", sizeof(val_string)); + break; + case SFF_8024_ID_XFF: + strlcat(val_string, " (XFF)", sizeof(val_string)); + break; + case SFF_8024_ID_XFP_E: + strlcat(val_string, " (XFP-E)", sizeof(val_string)); + break; + case SFF_8024_ID_XPAK: + strlcat(val_string, " (XPAK)", sizeof(val_string)); + break; + case SFF_8024_ID_X2: + strlcat(val_string, " (X2)", sizeof(val_string)); + break; + case SFF_8024_ID_DWDM_SFP: + strlcat(val_string, " (DWDM-SFP)", sizeof(val_string)); + break; + case SFF_8024_ID_QSFP: + strlcat(val_string, " (QSFP)", sizeof(val_string)); + break; + case SFF_8024_ID_QSFP_PLUS: + strlcat(val_string, " (QSFP+)", sizeof(val_string)); + break; + case SFF_8024_ID_CXP: + strlcat(val_string, " (CXP)", sizeof(val_string)); + break; + case SFF_8024_ID_HD4X: + strlcat(val_string, " (Shielded Mini Multilane HD 4X)", sizeof(val_string)); + break; + case SFF_8024_ID_HD8X: + strlcat(val_string, " (Shielded Mini Multilane HD 8X)", sizeof(val_string)); + break; + case SFF_8024_ID_QSFP28: + strlcat(val_string, " (QSFP28)", sizeof(val_string)); + break; + case SFF_8024_ID_CXP2: + strlcat(val_string, " (CXP2/CXP28)", sizeof(val_string)); + break; + case SFF_8024_ID_CDFP: + strlcat(val_string, " (CDFP Style 1/Style 2)", sizeof(val_string)); + break; + case SFF_8024_ID_HD4X_FANOUT: + strlcat(val_string, " (Shielded Mini Multilane HD 4X Fanout Cable)", + sizeof(val_string)); + break; + case SFF_8024_ID_HD8X_FANOUT: + strlcat(val_string, " (Shielded Mini Multilane HD 8X Fanout Cable)", + sizeof(val_string)); + break; + case SFF_8024_ID_CDFP_S3: + strlcat(val_string, " (CDFP Style 3)", sizeof(val_string)); + break; + case SFF_8024_ID_MICRO_QSFP: + strlcat(val_string, " (microQSFP)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + ssf_add_dict_string(d, "Identifier", val_string); +} + +void sff_8024_show_connector(const uint8_t *data, int ctor_offset, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[ctor_offset]); + + switch (data[ctor_offset]) { + case SFF_8024_CTOR_UNKNOWN: + strlcat(val_string, " (unknown or unspecified)", sizeof(val_string)); + break; + case SFF_8024_CTOR_SC: + strlcat(val_string, " (SC)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FC_STYLE_1: + strlcat(val_string, " (Fibre Channel Style 1 copper)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FC_STYLE_2: + strlcat(val_string, " (Fibre Channel Style 2 copper)", sizeof(val_string)); + break; + case SFF_8024_CTOR_BNC_TNC: + strlcat(val_string, " (BNC/TNC)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FC_COAX: + strlcat(val_string, " (Fibre Channel coaxial headers)", sizeof(val_string)); + break; + case SFF_8024_CTOR_FIBER_JACK: + strlcat(val_string, " (FibreJack)", sizeof(val_string)); + break; + case SFF_8024_CTOR_LC: + strlcat(val_string, " (LC)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MT_RJ: + strlcat(val_string, " (MT-RJ)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MU: + strlcat(val_string, " (MU)", sizeof(val_string)); + break; + case SFF_8024_CTOR_SG: + strlcat(val_string, " (SG)", sizeof(val_string)); + break; + case SFF_8024_CTOR_OPT_PT: + strlcat(val_string, " (Optical pigtail)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MPO: + strlcat(val_string, " (MPO Parallel Optic)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MPO_2: + strlcat(val_string, " (MPO Parallel Optic - 2x16)", sizeof(val_string)); + break; + case SFF_8024_CTOR_HSDC_II: + strlcat(val_string, " (HSSDC II)", sizeof(val_string)); + break; + case SFF_8024_CTOR_COPPER_PT: + strlcat(val_string, " (Copper pigtail)", sizeof(val_string)); + break; + case SFF_8024_CTOR_RJ45: + strlcat(val_string, " (RJ45)", sizeof(val_string)); + break; + case SFF_8024_CTOR_NO_SEPARABLE: + strlcat(val_string, " (No separable connector)", sizeof(val_string)); + break; + case SFF_8024_CTOR_MXC_2x16: + strlcat(val_string, " (MXC 2x16)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + ssf_add_dict_string(d, "Connector", val_string); +} + +void sff_8024_show_encoding(const uint8_t *data, int encoding_offset, + int sff_type, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[encoding_offset]); + + switch (data[encoding_offset]) { + case SFF_8024_ENCODING_UNSPEC: + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_8B10B: + strlcat(val_string, " (8B/10B)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_4B5B: + strlcat(val_string, " (4B/5B)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_NRZ: + strlcat(val_string, " (NRZ)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_4h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) + strlcat(val_string, " (Manchester)", sizeof(val_string)); + else if (sff_type == RTE_ETH_MODULE_SFF_8636) + strlcat(val_string, " (SONET Scrambled)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_5h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) + strlcat(val_string, " (SONET Scrambled)", sizeof(val_string)); + else if (sff_type == RTE_ETH_MODULE_SFF_8636) + strlcat(val_string, " (64B/66B)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_6h: + if (sff_type == RTE_ETH_MODULE_SFF_8472) + strlcat(val_string, " (64B/66B)", sizeof(val_string)); + else if (sff_type == RTE_ETH_MODULE_SFF_8636) + strlcat(val_string, " (Manchester)", sizeof(val_string)); + break; + case SFF_8024_ENCODING_256B: + strlcat(val_string, + " ((256B/257B (transcoded FEC-enabled data))", sizeof(val_string)); + break; + case SFF_8024_ENCODING_PAM4: + strlcat(val_string, " (PAM4)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + ssf_add_dict_string(d, "Encoding", val_string); +} + +void sff_show_thresholds(struct sff_diags sd, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + SFF_SPRINT_BIAS(val_string, sd.bias_cur[SFF_HALRM]); + ssf_add_dict_string(d, "Laser bias current high alarm threshold", val_string); + SFF_SPRINT_BIAS(val_string, sd.bias_cur[SFF_LALRM]); + ssf_add_dict_string(d, "Laser bias current low alarm threshold", val_string); + SFF_SPRINT_BIAS(val_string, sd.bias_cur[SFF_HWARN]); + ssf_add_dict_string(d, "Laser bias current high warning threshold", val_string); + SFF_SPRINT_BIAS(val_string, sd.bias_cur[SFF_LWARN]); + ssf_add_dict_string(d, "Laser bias current low warning threshold", val_string); + + SFF_SPRINT_xX_PWR(val_string, sd.tx_power[SFF_HALRM]); + ssf_add_dict_string(d, "Laser output power high alarm threshold", val_string); + SFF_SPRINT_xX_PWR(val_string, sd.tx_power[SFF_LALRM]); + ssf_add_dict_string(d, "Laser output power low alarm threshold", val_string); + SFF_SPRINT_xX_PWR(val_string, sd.tx_power[SFF_HWARN]); + ssf_add_dict_string(d, "Laser output power high warning threshold", val_string); + SFF_SPRINT_xX_PWR(val_string, sd.tx_power[SFF_LWARN]); + ssf_add_dict_string(d, "Laser output power low warning threshold", val_string); + + SFF_SPRINT_TEMP(val_string, sd.sfp_temp[SFF_HALRM]); + ssf_add_dict_string(d, "Module temperature high alarm threshold", val_string); + SFF_SPRINT_TEMP(val_string, sd.sfp_temp[SFF_LALRM]); + ssf_add_dict_string(d, "Module temperature low alarm threshold", val_string); + SFF_SPRINT_TEMP(val_string, sd.sfp_temp[SFF_HWARN]); + ssf_add_dict_string(d, "Module temperature high warning threshold", val_string); + SFF_SPRINT_TEMP(val_string, sd.sfp_temp[SFF_LWARN]); + ssf_add_dict_string(d, "Module temperature low warning threshold", val_string); + + SFF_SPRINT_VCC(val_string, sd.sfp_voltage[SFF_HALRM]); + ssf_add_dict_string(d, "Module voltage high alarm threshold", val_string); + SFF_SPRINT_VCC(val_string, sd.sfp_voltage[SFF_LALRM]); + ssf_add_dict_string(d, "Module voltage low alarm threshold", val_string); + SFF_SPRINT_VCC(val_string, sd.sfp_voltage[SFF_HWARN]); + ssf_add_dict_string(d, "Module voltage high warning threshold", val_string); + SFF_SPRINT_VCC(val_string, sd.sfp_voltage[SFF_LWARN]); + ssf_add_dict_string(d, "Module voltage low alarm threshold", val_string); + + SFF_SPRINT_xX_PWR(val_string, sd.rx_power[SFF_HALRM]); + ssf_add_dict_string(d, "Laser rx power high alarm threshold", val_string); + SFF_SPRINT_xX_PWR(val_string, sd.rx_power[SFF_LALRM]); + ssf_add_dict_string(d, "Laser rx power low alarm threshold", val_string); + SFF_SPRINT_xX_PWR(val_string, sd.rx_power[SFF_HWARN]); + ssf_add_dict_string(d, "Laser rx power high warning threshold", val_string); + SFF_SPRINT_xX_PWR(val_string, sd.rx_power[SFF_LWARN]); + ssf_add_dict_string(d, "Laser rx power low warning threshold", val_string); +} diff --git a/lib/ethdev/sff_common.h b/lib/ethdev/sff_common.h new file mode 100644 index 0000000000..e44f3c7bf3 --- /dev/null +++ b/lib/ethdev/sff_common.h @@ -0,0 +1,173 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * + * Implements SFF-8024 Rev 4.0 of pluggable I/O configuration and some + * common utilities for SFF-8436/8636 and SFF-8472/8079 + * + */ + +#ifndef _SFF_COMMON_H_ +#define _SFF_COMMON_H_ + +#include <stdio.h> + +#include "rte_ethdev.h" +#include "sff_telemetry.h" + +#define SFF_8024_ID_OFFSET 0x00 +#define SFF_8024_ID_UNKNOWN 0x00 +#define SFF_8024_ID_GBIC 0x01 +#define SFF_8024_ID_SOLDERED_MODULE 0x02 +#define SFF_8024_ID_SFP 0x03 +#define SFF_8024_ID_300_PIN_XBI 0x04 +#define SFF_8024_ID_XENPAK 0x05 +#define SFF_8024_ID_XFP 0x06 +#define SFF_8024_ID_XFF 0x07 +#define SFF_8024_ID_XFP_E 0x08 +#define SFF_8024_ID_XPAK 0x09 +#define SFF_8024_ID_X2 0x0A +#define SFF_8024_ID_DWDM_SFP 0x0B +#define SFF_8024_ID_QSFP 0x0C +#define SFF_8024_ID_QSFP_PLUS 0x0D +#define SFF_8024_ID_CXP 0x0E +#define SFF_8024_ID_HD4X 0x0F +#define SFF_8024_ID_HD8X 0x10 +#define SFF_8024_ID_QSFP28 0x11 +#define SFF_8024_ID_CXP2 0x12 +#define SFF_8024_ID_CDFP 0x13 +#define SFF_8024_ID_HD4X_FANOUT 0x14 +#define SFF_8024_ID_HD8X_FANOUT 0x15 +#define SFF_8024_ID_CDFP_S3 0x16 +#define SFF_8024_ID_MICRO_QSFP 0x17 +#define SFF_8024_ID_LAST SFF_8024_ID_MICRO_QSFP +#define SFF_8024_ID_UNALLOCATED_LAST 0x7F +#define SFF_8024_ID_VENDOR_START 0x80 +#define SFF_8024_ID_VENDOR_LAST 0xFF + +#define SFF_8024_CTOR_UNKNOWN 0x00 +#define SFF_8024_CTOR_SC 0x01 +#define SFF_8024_CTOR_FC_STYLE_1 0x02 +#define SFF_8024_CTOR_FC_STYLE_2 0x03 +#define SFF_8024_CTOR_BNC_TNC 0x04 +#define SFF_8024_CTOR_FC_COAX 0x05 +#define SFF_8024_CTOR_FIBER_JACK 0x06 +#define SFF_8024_CTOR_LC 0x07 +#define SFF_8024_CTOR_MT_RJ 0x08 +#define SFF_8024_CTOR_MU 0x09 +#define SFF_8024_CTOR_SG 0x0A +#define SFF_8024_CTOR_OPT_PT 0x0B +#define SFF_8024_CTOR_MPO 0x0C +#define SFF_8024_CTOR_MPO_2 0x0D +/* 0E-1Fh --- Reserved */ +#define SFF_8024_CTOR_HSDC_II 0x20 +#define SFF_8024_CTOR_COPPER_PT 0x21 +#define SFF_8024_CTOR_RJ45 0x22 +#define SFF_8024_CTOR_NO_SEPARABLE 0x23 +#define SFF_8024_CTOR_MXC_2x16 0x24 +#define SFF_8024_CTOR_LAST SFF_8024_CTOR_MXC_2x16 +#define SFF_8024_CTOR_UNALLOCATED_LAST 0x7F +#define SFF_8024_CTOR_VENDOR_START 0x80 +#define SFF_8024_CTOR_VENDOR_LAST 0xFF + +/* ENCODING Values */ +#define SFF_8024_ENCODING_UNSPEC 0x00 +#define SFF_8024_ENCODING_8B10B 0x01 +#define SFF_8024_ENCODING_4B5B 0x02 +#define SFF_8024_ENCODING_NRZ 0x03 +/* + * Value: 04h + * SFF-8472 - Manchester + * SFF-8436/8636 - SONET Scrambled + */ +#define SFF_8024_ENCODING_4h 0x04 +/* + * Value: 05h + * SFF-8472 - SONET Scrambled + * SFF-8436/8636 - 64B/66B + */ +#define SFF_8024_ENCODING_5h 0x05 +/* + * Value: 06h + * SFF-8472 - 64B/66B + * SFF-8436/8636 - Manchester + */ +#define SFF_8024_ENCODING_6h 0x06 +#define SFF_8024_ENCODING_256B 0x07 +#define SFF_8024_ENCODING_PAM4 0x08 + +/* Most common case: 16-bit unsigned integer in a certain unit */ +#define SFF_OFFSET_TO_U16(offset) \ + (data[offset] << 8 | data[(offset) + 1]) + +#define SFF_SPRINT_xX_PWR(str, var) \ + snprintf(str, sizeof(str), "%.4f mW / %.2f dBm", \ + (double)((var) / 10000.), \ + sff_convert_mw_to_dbm((double)((var) / 10000.))) + +#define SFF_SPRINT_BIAS(str, bias_cur) \ + snprintf(str, sizeof(str), "%.3f mA", (double)(bias_cur / 500.)) + +#define SFF_SPRINT_TEMP(str, temp) \ + snprintf(str, sizeof(str), "%.2f degrees C / %.2f degrees F", \ + (double)(temp / 256.), \ + (double)(temp / 256. * 1.8 + 32.)) + +#define SFF_SPRINT_VCC(str, sfp_voltage) \ + snprintf(str, sizeof(str), "%.4f V", (double)(sfp_voltage / 10000.)) + +/* Channel Monitoring Fields */ +struct sff_channel_diags { + uint16_t bias_cur; /* Measured bias current in 2uA units */ + uint16_t rx_power; /* Measured RX Power */ + uint16_t tx_power; /* Measured TX Power */ +}; + +/* Module Monitoring Fields */ +struct sff_diags { + +#define SFF_MAX_CHANNEL_NUM 4 +#define SFF_LWARN 0 +#define SFF_HWARN 1 +#define SFF_LALRM 2 +#define SFF_HALRM 3 +#define SFF_MCURR 4 + + /* Supports DOM */ + uint8_t supports_dom; + /* Supports alarm/warning thold */ + uint8_t supports_alarms; + /* RX Power: 0 = OMA, 1 = Average power */ + uint8_t rx_power_type; + /* TX Power: 0 = Not supported, 1 = Average power */ + uint8_t tx_power_type; + + uint8_t calibrated_ext; /* Is externally calibrated */ + /* [5] tables are low/high warn, low/high alarm, current */ + /* SFP voltage in 0.1mV units */ + uint16_t sfp_voltage[5]; + /* SFP Temp in 16-bit signed 1/256 Celsius */ + int16_t sfp_temp[5]; + /* Measured bias current in 2uA units */ + uint16_t bias_cur[5]; + /* Measured TX Power */ + uint16_t tx_power[5]; + /* Measured RX Power */ + uint16_t rx_power[5]; + struct sff_channel_diags scd[SFF_MAX_CHANNEL_NUM]; +}; + +double sff_convert_mw_to_dbm(double mw); +void sff_show_value_with_unit(const uint8_t *data, unsigned int reg, + const char *name, unsigned int mult, + const char *unit, struct rte_tel_data *d); +void sff_show_ascii(const uint8_t *data, unsigned int first_reg, + unsigned int last_reg, const char *name, struct rte_tel_data *d); +void sff_show_thresholds(struct sff_diags sd, struct rte_tel_data *d); + +void sff_8024_show_oui(const uint8_t *data, int id_offset, struct rte_tel_data *d); +void sff_8024_show_identifier(const uint8_t *data, int id_offset, struct rte_tel_data *d); +void sff_8024_show_connector(const uint8_t *data, int ctor_offset, struct rte_tel_data *d); +void sff_8024_show_encoding(const uint8_t *data, int encoding_offset, + int sff_type, struct rte_tel_data *d); + +#endif /* _SFF_COMMON_H_ */ -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v9 3/5] ethdev: support SFF-8079 module information telemetry 2022-05-26 7:32 ` [PATCH v9 0/5] add telemetry command for show module EEPROM Robin Zhang 2022-05-26 7:32 ` [PATCH v9 1/5] ethdev: add telemetry command for " Robin Zhang 2022-05-26 7:32 ` [PATCH v9 2/5] ethdev: add common code for different SFF specs Robin Zhang @ 2022-05-26 7:32 ` Robin Zhang 2022-05-26 7:32 ` [PATCH v9 4/5] ethdev: support SFF-8472 " Robin Zhang ` (2 subsequent siblings) 5 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-05-26 7:32 UTC (permalink / raw) To: dev; +Cc: thomas, andrew.rybchenko, kevinx.liu, Robin Zhang Add support for module EEPROM information format defined in SFF-8079 Rev 1.7. Signed-off-by: Robin Zhang <robinx.zhang@intel.com> Signed-off-by: Kevin Liu <kevinx.liu@intel.com> --- lib/ethdev/meson.build | 1 + lib/ethdev/sff_8079.c | 401 +++++++++++++++++++++++++++++++++++++ lib/ethdev/sff_telemetry.c | 3 + 3 files changed, 405 insertions(+) create mode 100644 lib/ethdev/sff_8079.c diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index 4ec21789f5..5823fa0375 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -13,6 +13,7 @@ sources = files( 'rte_tm.c', 'sff_telemetry.c', 'sff_common.c', + 'sff_8079.c', ) headers = files( diff --git a/lib/ethdev/sff_8079.c b/lib/ethdev/sff_8079.c new file mode 100644 index 0000000000..91ad25ffcd --- /dev/null +++ b/lib/ethdev/sff_8079.c @@ -0,0 +1,401 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * Implements SFF-8079 optics diagnostics. + */ + +#include <stdio.h> + +#include "sff_common.h" + +static void sff_8079_show_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_identifier(data, 0, d); +} + +static void sff_8079_show_ext_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[1]); + if (data[1] == 0x00) + strlcat(val_string, " (GBIC not specified / not MOD_DEF compliant)", + sizeof(val_string)); + else if (data[1] == 0x04) + strlcat(val_string, " (GBIC/SFP defined by 2-wire interface ID)", + sizeof(val_string)); + else if (data[1] <= 0x07) { + char tmp[SFF_ITEM_VAL_COMPOSE_SIZE]; + snprintf(tmp, sizeof(tmp), " (GBIC compliant with MOD_DEF %u)", data[1]); + strlcat(val_string, tmp, sizeof(val_string)); + } else + strlcat(val_string, " (unknown)", sizeof(val_string)); + ssf_add_dict_string(d, "Extended identifier", val_string); +} + +static void sff_8079_show_connector(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_connector(data, 2, d); +} + +static void sff_8079_show_transceiver(const uint8_t *data, struct rte_tel_data *d) +{ + static const char *name = "Transceiver type"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), + "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[36]); + ssf_add_dict_string(d, "Transceiver codes", val_string); + + /* 10G Ethernet Compliance Codes */ + if (data[3] & (1 << 7)) + ssf_add_dict_string(d, "10G Ethernet transceiver type", + "10G Ethernet: 10G Base-ER [SFF-8472 rev10.4 onwards]"); + if (data[3] & (1 << 6)) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-LRM"); + if (data[3] & (1 << 5)) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-LR"); + if (data[3] & (1 << 4)) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-SR"); + + /* Infiniband Compliance Codes */ + if (data[3] & (1 << 3)) + ssf_add_dict_string(d, name, "Infiniband: 1X SX"); + if (data[3] & (1 << 2)) + ssf_add_dict_string(d, name, "Infiniband: 1X LX"); + if (data[3] & (1 << 1)) + ssf_add_dict_string(d, name, "Infiniband: 1X Copper Active"); + if (data[3] & (1 << 0)) + ssf_add_dict_string(d, name, "Infiniband: 1X Copper Passive"); + + /* ESCON Compliance Codes */ + if (data[4] & (1 << 7)) + ssf_add_dict_string(d, name, "ESCON: ESCON MMF, 1310nm LED"); + if (data[4] & (1 << 6)) + ssf_add_dict_string(d, name, "ESCON: ESCON SMF, 1310nm Laser"); + + /* SONET Compliance Codes */ + if (data[4] & (1 << 5)) + ssf_add_dict_string(d, name, "SONET: OC-192, short reach"); + if (data[4] & (1 << 4)) + ssf_add_dict_string(d, name, "SONET: SONET reach specifier bit 1"); + if (data[4] & (1 << 3)) + ssf_add_dict_string(d, name, "SONET: SONET reach specifier bit 2"); + if (data[4] & (1 << 2)) + ssf_add_dict_string(d, name, "SONET: OC-48, long reach"); + if (data[4] & (1 << 1)) + ssf_add_dict_string(d, name, "SONET: OC-48, intermediate reach"); + if (data[4] & (1 << 0)) + ssf_add_dict_string(d, name, "SONET: OC-48, short reach"); + if (data[5] & (1 << 6)) + ssf_add_dict_string(d, name, "SONET: OC-12, single mode, long reach"); + if (data[5] & (1 << 5)) + ssf_add_dict_string(d, name, "SONET: OC-12, single mode, inter. reach"); + if (data[5] & (1 << 4)) + ssf_add_dict_string(d, name, "SONET: OC-12, short reach"); + if (data[5] & (1 << 2)) + ssf_add_dict_string(d, name, "SONET: OC-3, single mode, long reach"); + if (data[5] & (1 << 1)) + ssf_add_dict_string(d, name, "SONET: OC-3, single mode, inter. reach"); + if (data[5] & (1 << 0)) + ssf_add_dict_string(d, name, "SONET: OC-3, short reach"); + + /* Ethernet Compliance Codes */ + if (data[6] & (1 << 7)) + ssf_add_dict_string(d, name, "Ethernet: BASE-PX"); + if (data[6] & (1 << 6)) + ssf_add_dict_string(d, name, "Ethernet: BASE-BX10"); + if (data[6] & (1 << 5)) + ssf_add_dict_string(d, name, "Ethernet: 100BASE-FX"); + if (data[6] & (1 << 4)) + ssf_add_dict_string(d, name, "Ethernet: 100BASE-LX/LX10"); + if (data[6] & (1 << 3)) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-T"); + if (data[6] & (1 << 2)) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-CX"); + if (data[6] & (1 << 1)) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-LX"); + if (data[6] & (1 << 0)) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-SX"); + + /* Fibre Channel link length */ + if (data[7] & (1 << 7)) + ssf_add_dict_string(d, name, "FC: very long distance (V)"); + if (data[7] & (1 << 6)) + ssf_add_dict_string(d, name, "FC: short distance (S)"); + if (data[7] & (1 << 5)) + ssf_add_dict_string(d, name, "FC: intermediate distance (I)"); + if (data[7] & (1 << 4)) + ssf_add_dict_string(d, name, "FC: long distance (L)"); + if (data[7] & (1 << 3)) + ssf_add_dict_string(d, name, "FC: medium distance (M)"); + + /* Fibre Channel transmitter technology */ + if (data[7] & (1 << 2)) + ssf_add_dict_string(d, name, "FC: Shortwave laser, linear Rx (SA)"); + if (data[7] & (1 << 1)) + ssf_add_dict_string(d, name, "FC: Longwave laser (LC)"); + if (data[7] & (1 << 0)) + ssf_add_dict_string(d, name, "FC: Electrical inter-enclosure (EL)"); + if (data[8] & (1 << 7)) + ssf_add_dict_string(d, name, "FC: Electrical intra-enclosure (EL)"); + if (data[8] & (1 << 6)) + ssf_add_dict_string(d, name, "FC: Shortwave laser w/o OFC (SN)"); + if (data[8] & (1 << 5)) + ssf_add_dict_string(d, name, "FC: Shortwave laser with OFC (SL)"); + if (data[8] & (1 << 4)) + ssf_add_dict_string(d, name, "FC: Longwave laser (LL)"); + if (data[8] & (1 << 3)) + ssf_add_dict_string(d, name, "Active Cable"); + if (data[8] & (1 << 2)) + ssf_add_dict_string(d, name, "Passive Cable"); + if (data[8] & (1 << 1)) + ssf_add_dict_string(d, name, "FC: Copper FC-BaseT"); + + /* Fibre Channel transmission media */ + if (data[9] & (1 << 7)) + ssf_add_dict_string(d, name, "FC: Twin Axial Pair (TW)"); + if (data[9] & (1 << 6)) + ssf_add_dict_string(d, name, "FC: Twisted Pair (TP)"); + if (data[9] & (1 << 5)) + ssf_add_dict_string(d, name, "FC: Miniature Coax (MI)"); + if (data[9] & (1 << 4)) + ssf_add_dict_string(d, name, "FC: Video Coax (TV)"); + if (data[9] & (1 << 3)) + ssf_add_dict_string(d, name, "FC: Multimode, 62.5um (M6)"); + if (data[9] & (1 << 2)) + ssf_add_dict_string(d, name, "FC: Multimode, 50um (M5)"); + if (data[9] & (1 << 0)) + ssf_add_dict_string(d, name, "FC: Single Mode (SM)"); + + /* Fibre Channel speed */ + if (data[10] & (1 << 7)) + ssf_add_dict_string(d, name, "FC: 1200 MBytes/sec"); + if (data[10] & (1 << 6)) + ssf_add_dict_string(d, name, "FC: 800 MBytes/sec"); + if (data[10] & (1 << 4)) + ssf_add_dict_string(d, name, "FC: 400 MBytes/sec"); + if (data[10] & (1 << 2)) + ssf_add_dict_string(d, name, "FC: 200 MBytes/sec"); + if (data[10] & (1 << 0)) + ssf_add_dict_string(d, name, "FC: 100 MBytes/sec"); + + /* Extended Specification Compliance Codes from SFF-8024 */ + switch (data[36]) { + case 0x1: + ssf_add_dict_string(d, name, + "Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)"); + break; + case 0x2: + ssf_add_dict_string(d, name, "Extended: 100G Base-SR4 or 25GBase-SR"); + break; + case 0x3: + ssf_add_dict_string(d, name, "Extended: 100G Base-LR4 or 25GBase-LR"); + break; + case 0x4: + ssf_add_dict_string(d, name, "Extended: 100G Base-ER4 or 25GBase-ER"); + break; + case 0x8: + ssf_add_dict_string(d, name, + "Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)"); + break; + case 0xb: + ssf_add_dict_string(d, name, "Extended: 100G Base-CR4 or 25G Base-CR CA-L"); + break; + case 0xc: + ssf_add_dict_string(d, name, "Extended: 25G Base-CR CA-S"); + break; + case 0xd: + ssf_add_dict_string(d, name, "Extended: 25G Base-CR CA-N"); + break; + case 0x16: + ssf_add_dict_string(d, name, "Extended: 10Gbase-T with SFI electrical interface"); + break; + case 0x18: + ssf_add_dict_string(d, name, + "Extended: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)"); + break; + case 0x19: + ssf_add_dict_string(d, name, + "Extended: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)"); + break; + case 0x1c: + ssf_add_dict_string(d, name, "Extended: 10Gbase-T Short Reach"); + break; + default: + break; + } +} + +static void sff_8079_show_encoding(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_encoding(data, 11, RTE_ETH_MODULE_SFF_8472, d); +} + +static void sff_8079_show_rate_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[13]); + + switch (data[13]) { + case 0x00: + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case 0x01: + strlcat(val_string, " (4/2/1G Rate_Select & AS0/AS1)", sizeof(val_string)); + break; + case 0x02: + strlcat(val_string, " (8/4/2G Rx Rate_Select only)", sizeof(val_string)); + break; + case 0x03: + strlcat(val_string, " (8/4/2G Independent Rx & Tx Rate_Select)", + sizeof(val_string)); + break; + case 0x04: + strlcat(val_string, " (8/4/2G Tx Rate_Select only)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (reserved or unknown)", sizeof(val_string)); + break; + } + ssf_add_dict_string(d, "Rate identifier", val_string); +} + +static void sff_8079_show_oui(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_oui(data, 37, d); +} + +static void +sff_8079_show_wavelength_or_copper_compliance(const uint8_t *data, + struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + if (data[8] & (1 << 2)) { + snprintf(val_string, sizeof(val_string), "0x%02x", data[60]); + switch (data[60]) { + case 0x00: + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case 0x01: + strlcat(val_string, " (SFF-8431 appendix E)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (unknown)", sizeof(val_string)); + break; + } + strlcat(val_string, " [SFF-8472 rev10.4 only]", sizeof(val_string)); + ssf_add_dict_string(d, "Passive Cu cmplnce.", val_string); + } else if (data[8] & (1 << 3)) { + snprintf(val_string, sizeof(val_string), "0x%02x", data[60]); + switch (data[60]) { + case 0x00: + strlcat(val_string, " (unspecified)", sizeof(val_string)); + break; + case 0x01: + strlcat(val_string, " (SFF-8431 appendix E)", sizeof(val_string)); + break; + case 0x04: + strlcat(val_string, " (SFF-8431 limiting)", sizeof(val_string)); + break; + default: + strlcat(val_string, " (unknown)", sizeof(val_string)); + break; + } + strlcat(val_string, " [SFF-8472 rev10.4 only]", sizeof(val_string)); + ssf_add_dict_string(d, "Active Cu cmplnce.", val_string); + } else { + snprintf(val_string, sizeof(val_string), "%unm", (data[60] << 8) | data[61]); + ssf_add_dict_string(d, "Laser wavelength", val_string); + } +} + +static void sff_8079_show_options(const uint8_t *data, struct rte_tel_data *d) +{ + static const char *name = "Option"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x 0x%02x", data[64], data[65]); + ssf_add_dict_string(d, "Option values", val_string); + + if (data[65] & (1 << 1)) + ssf_add_dict_string(d, name, "RX_LOS implemented"); + if (data[65] & (1 << 2)) + ssf_add_dict_string(d, name, "RX_LOS implemented, inverted"); + if (data[65] & (1 << 3)) + ssf_add_dict_string(d, name, "TX_FAULT implemented"); + if (data[65] & (1 << 4)) + ssf_add_dict_string(d, name, "TX_DISABLE implemented"); + if (data[65] & (1 << 5)) + ssf_add_dict_string(d, name, "RATE_SELECT implemented"); + if (data[65] & (1 << 6)) + ssf_add_dict_string(d, name, "Tunable transmitter technology"); + if (data[65] & (1 << 7)) + ssf_add_dict_string(d, name, "Receiver decision threshold implemented"); + if (data[64] & (1 << 0)) + ssf_add_dict_string(d, name, "Linear receiver output implemented"); + if (data[64] & (1 << 1)) + ssf_add_dict_string(d, name, "Power level 2 requirement"); + if (data[64] & (1 << 2)) + ssf_add_dict_string(d, name, "Cooled transceiver implemented"); + if (data[64] & (1 << 3)) + ssf_add_dict_string(d, name, "Retimer or CDR implemented"); + if (data[64] & (1 << 4)) + ssf_add_dict_string(d, name, "Paging implemented"); + if (data[64] & (1 << 5)) + ssf_add_dict_string(d, name, "Power level 3 requirement"); +} + +void sff_8079_show_all(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8079_show_identifier(data, d); + if (((data[0] == 0x02) || (data[0] == 0x03)) && (data[1] == 0x04)) { + unsigned int br_nom, br_min, br_max; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + if (data[12] == 0) { + br_nom = br_min = br_max = 0; + } else if (data[12] == 255) { + br_nom = data[66] * 250; + br_max = data[67]; + br_min = data[67]; + } else { + br_nom = data[12] * 100; + br_max = data[66]; + br_min = data[67]; + } + sff_8079_show_ext_identifier(data, d); + sff_8079_show_connector(data, d); + sff_8079_show_transceiver(data, d); + sff_8079_show_encoding(data, d); + + snprintf(val_string, sizeof(val_string), "%uMBd", br_nom); + ssf_add_dict_string(d, "BR, Nominal", val_string); + + sff_8079_show_rate_identifier(data, d); + sff_show_value_with_unit(data, 14, + "Length (SMF,km)", 1, "km", d); + sff_show_value_with_unit(data, 15, "Length (SMF)", 100, "m", d); + sff_show_value_with_unit(data, 16, "Length (50um)", 10, "m", d); + sff_show_value_with_unit(data, 17, + "Length (62.5um)", 10, "m", d); + sff_show_value_with_unit(data, 18, "Length (Copper)", 1, "m", d); + sff_show_value_with_unit(data, 19, "Length (OM3)", 10, "m", d); + sff_8079_show_wavelength_or_copper_compliance(data, d); + sff_show_ascii(data, 20, 35, "Vendor name", d); + sff_8079_show_oui(data, d); + sff_show_ascii(data, 40, 55, "Vendor PN", d); + sff_show_ascii(data, 56, 59, "Vendor rev", d); + sff_8079_show_options(data, d); + + snprintf(val_string, sizeof(val_string), "%u%%", br_max); + ssf_add_dict_string(d, "BR margin, max", val_string); + snprintf(val_string, sizeof(val_string), "%u%%", br_min); + ssf_add_dict_string(d, "BR margin, min", val_string); + + sff_show_ascii(data, 68, 83, "Vendor SN", d); + sff_show_ascii(data, 84, 91, "Date code", d); + } +} diff --git a/lib/ethdev/sff_telemetry.c b/lib/ethdev/sff_telemetry.c index 7da4385223..bc458af532 100644 --- a/lib/ethdev/sff_telemetry.c +++ b/lib/ethdev/sff_telemetry.c @@ -70,6 +70,9 @@ sff_port_module_eeprom_parse(uint16_t port_id, struct rte_tel_data *d) switch (minfo.type) { /* parsing module EEPROM data base on different module type */ + case RTE_ETH_MODULE_SFF_8079: + sff_8079_show_all(einfo.data, d); + break; default: RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); break; -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v9 4/5] ethdev: support SFF-8472 module information telemetry 2022-05-26 7:32 ` [PATCH v9 0/5] add telemetry command for show module EEPROM Robin Zhang ` (2 preceding siblings ...) 2022-05-26 7:32 ` [PATCH v9 3/5] ethdev: support SFF-8079 module information telemetry Robin Zhang @ 2022-05-26 7:32 ` Robin Zhang 2022-05-26 7:32 ` [PATCH v9 5/5] ethdev: support SFF-8636 " Robin Zhang 2022-05-31 14:43 ` [PATCH v9 0/5] add telemetry command for show module EEPROM Andrew Rybchenko 5 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-05-26 7:32 UTC (permalink / raw) To: dev; +Cc: thomas, andrew.rybchenko, kevinx.liu, Robin Zhang Add support for module EEPROM information format defined in SFF-8472 Rev 12.0 Signed-off-by: Robin Zhang <robinx.zhang@intel.com> Signed-off-by: Kevin Liu <kevinx.liu@intel.com> --- lib/ethdev/meson.build | 1 + lib/ethdev/sff_8472.c | 280 +++++++++++++++++++++++++++++++++++++ lib/ethdev/sff_telemetry.c | 4 + 3 files changed, 285 insertions(+) create mode 100644 lib/ethdev/sff_8472.c diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index 5823fa0375..6c24c0b715 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -14,6 +14,7 @@ sources = files( 'sff_telemetry.c', 'sff_common.c', 'sff_8079.c', + 'sff_8472.c', ) headers = files( diff --git a/lib/ethdev/sff_8472.c b/lib/ethdev/sff_8472.c new file mode 100644 index 0000000000..97f231854c --- /dev/null +++ b/lib/ethdev/sff_8472.c @@ -0,0 +1,280 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * Implements SFF-8472 optics diagnostics. + */ + +#include <stdio.h> + +#include "sff_common.h" + +/* Offsets in decimal, for direct comparison with the SFF specs */ + +/* A0-based EEPROM offsets for DOM support checks */ +#define SFF_A0_DOM 92 +#define SFF_A0_OPTIONS 93 +#define SFF_A0_COMP 94 + +/* EEPROM bit values for various registers */ +#define SFF_A0_DOM_EXTCAL RTE_BIT32(4) +#define SFF_A0_DOM_INTCAL RTE_BIT32(5) +#define SFF_A0_DOM_IMPL RTE_BIT32(6) +#define SFF_A0_DOM_PWRT RTE_BIT32(3) + +#define SFF_A0_OPTIONS_AW RTE_BIT32(7) + +/* + * This is the offset at which the A2 page is in the EEPROM + * blob returned by the kernel. + */ +#define SFF_A2_BASE 0x100 + +/* A2-based offsets for DOM */ +#define SFF_A2_TEMP 96 +#define SFF_A2_TEMP_HALRM 0 +#define SFF_A2_TEMP_LALRM 2 +#define SFF_A2_TEMP_HWARN 4 +#define SFF_A2_TEMP_LWARN 6 + +#define SFF_A2_VCC 98 +#define SFF_A2_VCC_HALRM 8 +#define SFF_A2_VCC_LALRM 10 +#define SFF_A2_VCC_HWARN 12 +#define SFF_A2_VCC_LWARN 14 + +#define SFF_A2_BIAS 100 +#define SFF_A2_BIAS_HALRM 16 +#define SFF_A2_BIAS_LALRM 18 +#define SFF_A2_BIAS_HWARN 20 +#define SFF_A2_BIAS_LWARN 22 + +#define SFF_A2_TX_PWR 102 +#define SFF_A2_TX_PWR_HALRM 24 +#define SFF_A2_TX_PWR_LALRM 26 +#define SFF_A2_TX_PWR_HWARN 28 +#define SFF_A2_TX_PWR_LWARN 30 + +#define SFF_A2_RX_PWR 104 +#define SFF_A2_RX_PWR_HALRM 32 +#define SFF_A2_RX_PWR_LALRM 34 +#define SFF_A2_RX_PWR_HWARN 36 +#define SFF_A2_RX_PWR_LWARN 38 + +#define SFF_A2_ALRM_FLG 112 +#define SFF_A2_WARN_FLG 116 + +/* 32-bit little-endian calibration constants */ +#define SFF_A2_CAL_RXPWR4 56 +#define SFF_A2_CAL_RXPWR3 60 +#define SFF_A2_CAL_RXPWR2 64 +#define SFF_A2_CAL_RXPWR1 68 +#define SFF_A2_CAL_RXPWR0 72 + +/* 16-bit little endian calibration constants */ +#define SFF_A2_CAL_TXI_SLP 76 +#define SFF_A2_CAL_TXI_OFF 78 +#define SFF_A2_CAL_TXPWR_SLP 80 +#define SFF_A2_CAL_TXPWR_OFF 82 +#define SFF_A2_CAL_T_SLP 84 +#define SFF_A2_CAL_T_OFF 86 +#define SFF_A2_CAL_V_SLP 88 +#define SFF_A2_CAL_V_OFF 90 + +static struct sff_8472_aw_flags { + const char *str; /* Human-readable string, null at the end */ + int offset; /* A2-relative address offset */ + uint8_t value; /* Alarm is on if (offset & value) != 0. */ +} sff_8472_aw_flags[] = { + { "Laser bias current high alarm", SFF_A2_ALRM_FLG, RTE_BIT32(3) }, + { "Laser bias current low alarm", SFF_A2_ALRM_FLG, RTE_BIT32(2) }, + { "Laser bias current high warning", SFF_A2_WARN_FLG, RTE_BIT32(3) }, + { "Laser bias current low warning", SFF_A2_WARN_FLG, RTE_BIT32(2) }, + + { "Laser output power high alarm", SFF_A2_ALRM_FLG, RTE_BIT32(1) }, + { "Laser output power low alarm", SFF_A2_ALRM_FLG, RTE_BIT32(0) }, + { "Laser output power high warning", SFF_A2_WARN_FLG, RTE_BIT32(1) }, + { "Laser output power low warning", SFF_A2_WARN_FLG, RTE_BIT32(0) }, + + { "Module temperature high alarm", SFF_A2_ALRM_FLG, RTE_BIT32(7) }, + { "Module temperature low alarm", SFF_A2_ALRM_FLG, RTE_BIT32(6) }, + { "Module temperature high warning", SFF_A2_WARN_FLG, RTE_BIT32(7) }, + { "Module temperature low warning", SFF_A2_WARN_FLG, RTE_BIT32(6) }, + + { "Module voltage high alarm", SFF_A2_ALRM_FLG, RTE_BIT32(5) }, + { "Module voltage low alarm", SFF_A2_ALRM_FLG, RTE_BIT32(4) }, + { "Module voltage high warning", SFF_A2_WARN_FLG, RTE_BIT32(5) }, + { "Module voltage low warning", SFF_A2_WARN_FLG, RTE_BIT32(4) }, + + { "Laser rx power high alarm", SFF_A2_ALRM_FLG + 1, RTE_BIT32(7) }, + { "Laser rx power low alarm", SFF_A2_ALRM_FLG + 1, RTE_BIT32(6) }, + { "Laser rx power high warning", SFF_A2_WARN_FLG + 1, RTE_BIT32(7) }, + { "Laser rx power low warning", SFF_A2_WARN_FLG + 1, RTE_BIT32(6) }, + + { NULL, 0, 0 }, +}; + +/* Most common case: 16-bit unsigned integer in a certain unit */ +#define A2_OFFSET_TO_U16(offset) \ + (data[SFF_A2_BASE + (offset)] << 8 | data[SFF_A2_BASE + (offset) + 1]) + +/* Calibration slope is a number between 0.0 included and 256.0 excluded. */ +#define A2_OFFSET_TO_SLP(offset) \ + (data[SFF_A2_BASE + (offset)] + data[SFF_A2_BASE + (offset) + 1] / 256.) + +/* Calibration offset is an integer from -32768 to 32767 */ +#define A2_OFFSET_TO_OFF(offset) \ + ((int16_t)A2_OFFSET_TO_U16(offset)) + +/* RXPWR(x) are IEEE-754 floating point numbers in big-endian format */ +#define A2_OFFSET_TO_RXPWRx(offset) \ + (befloattoh((const uint32_t *)(data + SFF_A2_BASE + (offset)))) + +/* + * 2-byte internal temperature conversions: + * First byte is a signed 8-bit integer, which is the temp decimal part + * Second byte are 1/256th of degree, which are added to the dec part. + */ +#define A2_OFFSET_TO_TEMP(offset) ((int16_t)A2_OFFSET_TO_U16(offset)) + +static void sff_8472_dom_parse(const uint8_t *data, struct sff_diags *sd) +{ + sd->bias_cur[SFF_MCURR] = A2_OFFSET_TO_U16(SFF_A2_BIAS); + sd->bias_cur[SFF_HALRM] = A2_OFFSET_TO_U16(SFF_A2_BIAS_HALRM); + sd->bias_cur[SFF_LALRM] = A2_OFFSET_TO_U16(SFF_A2_BIAS_LALRM); + sd->bias_cur[SFF_HWARN] = A2_OFFSET_TO_U16(SFF_A2_BIAS_HWARN); + sd->bias_cur[SFF_LWARN] = A2_OFFSET_TO_U16(SFF_A2_BIAS_LWARN); + + sd->sfp_voltage[SFF_MCURR] = A2_OFFSET_TO_U16(SFF_A2_VCC); + sd->sfp_voltage[SFF_HALRM] = A2_OFFSET_TO_U16(SFF_A2_VCC_HALRM); + sd->sfp_voltage[SFF_LALRM] = A2_OFFSET_TO_U16(SFF_A2_VCC_LALRM); + sd->sfp_voltage[SFF_HWARN] = A2_OFFSET_TO_U16(SFF_A2_VCC_HWARN); + sd->sfp_voltage[SFF_LWARN] = A2_OFFSET_TO_U16(SFF_A2_VCC_LWARN); + + sd->tx_power[SFF_MCURR] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR); + sd->tx_power[SFF_HALRM] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_HALRM); + sd->tx_power[SFF_LALRM] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_LALRM); + sd->tx_power[SFF_HWARN] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_HWARN); + sd->tx_power[SFF_LWARN] = A2_OFFSET_TO_U16(SFF_A2_TX_PWR_LWARN); + + sd->rx_power[SFF_MCURR] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR); + sd->rx_power[SFF_HALRM] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_HALRM); + sd->rx_power[SFF_LALRM] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_LALRM); + sd->rx_power[SFF_HWARN] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_HWARN); + sd->rx_power[SFF_LWARN] = A2_OFFSET_TO_U16(SFF_A2_RX_PWR_LWARN); + + sd->sfp_temp[SFF_MCURR] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP); + sd->sfp_temp[SFF_HALRM] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_HALRM); + sd->sfp_temp[SFF_LALRM] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_LALRM); + sd->sfp_temp[SFF_HWARN] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_HWARN); + sd->sfp_temp[SFF_LWARN] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_LWARN); +} + +/* Converts to a float from a big-endian 4-byte source buffer. */ +static float befloattoh(const uint32_t *source) +{ + union { + uint32_t src; + float dst; + } converter; + + converter.src = ntohl(*source); + return converter.dst; +} + +static void sff_8472_calibration(const uint8_t *data, struct sff_diags *sd) +{ + unsigned long i; + uint16_t rx_reading; + + /* Calibration should occur for all values (threshold and current) */ + for (i = 0; i < RTE_DIM(sd->bias_cur); ++i) { + /* + * Apply calibration formula 1 (Temp., Voltage, Bias, Tx Power) + */ + sd->bias_cur[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_TXI_SLP); + sd->tx_power[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_TXPWR_SLP); + sd->sfp_voltage[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_V_SLP); + sd->sfp_temp[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_T_SLP); + + sd->bias_cur[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_TXI_OFF); + sd->tx_power[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_TXPWR_OFF); + sd->sfp_voltage[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_V_OFF); + sd->sfp_temp[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_T_OFF); + + /* + * Apply calibration formula 2 (Rx Power only) + */ + rx_reading = sd->rx_power[i]; + sd->rx_power[i] = A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR0); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR1); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR2); + sd->rx_power[i] += rx_reading * + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR3); + } +} + +static void sff_8472_parse_eeprom(const uint8_t *data, struct sff_diags *sd) +{ + sd->supports_dom = data[SFF_A0_DOM] & SFF_A0_DOM_IMPL; + sd->supports_alarms = data[SFF_A0_OPTIONS] & SFF_A0_OPTIONS_AW; + sd->calibrated_ext = data[SFF_A0_DOM] & SFF_A0_DOM_EXTCAL; + sd->rx_power_type = data[SFF_A0_DOM] & SFF_A0_DOM_PWRT; + + sff_8472_dom_parse(data, sd); + + /* + * If the SFP is externally calibrated, we need to read calibration data + * and compensate the already stored readings. + */ + if (sd->calibrated_ext) + sff_8472_calibration(data, sd); +} + +void sff_8472_show_all(const uint8_t *data, struct rte_tel_data *d) +{ + struct sff_diags sd = {0}; + const char *rx_power_string = NULL; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + int i; + + sff_8472_parse_eeprom(data, &sd); + + if (!sd.supports_dom) { + ssf_add_dict_string(d, "Optical diagnostics support", "No"); + return; + } + ssf_add_dict_string(d, "Optical diagnostics support", "Yes"); + + SFF_SPRINT_BIAS(val_string, sd.bias_cur[SFF_MCURR]); + ssf_add_dict_string(d, "Laser bias current", val_string); + + SFF_SPRINT_xX_PWR(val_string, sd.tx_power[SFF_MCURR]); + ssf_add_dict_string(d, "Laser output power", val_string); + + if (!sd.rx_power_type) + rx_power_string = "Receiver signal OMA"; + else + rx_power_string = "Receiver signal average optical power"; + + SFF_SPRINT_xX_PWR(val_string, sd.rx_power[SFF_MCURR]); + ssf_add_dict_string(d, rx_power_string, val_string); + + SFF_SPRINT_TEMP(val_string, sd.sfp_temp[SFF_MCURR]); + ssf_add_dict_string(d, "Module temperature", val_string); + + SFF_SPRINT_VCC(val_string, sd.sfp_voltage[SFF_MCURR]); + ssf_add_dict_string(d, "Module voltage", val_string); + + ssf_add_dict_string(d, "Alarm/warning flags implemented", + (sd.supports_alarms ? "Yes" : "No")); + + if (sd.supports_alarms) { + for (i = 0; sff_8472_aw_flags[i].str; ++i) { + ssf_add_dict_string(d, sff_8472_aw_flags[i].str, + data[SFF_A2_BASE + sff_8472_aw_flags[i].offset] + & sff_8472_aw_flags[i].value ? "On" : "Off"); + } + sff_show_thresholds(sd, d); + } +} diff --git a/lib/ethdev/sff_telemetry.c b/lib/ethdev/sff_telemetry.c index bc458af532..babb9418b2 100644 --- a/lib/ethdev/sff_telemetry.c +++ b/lib/ethdev/sff_telemetry.c @@ -73,6 +73,10 @@ sff_port_module_eeprom_parse(uint16_t port_id, struct rte_tel_data *d) case RTE_ETH_MODULE_SFF_8079: sff_8079_show_all(einfo.data, d); break; + case RTE_ETH_MODULE_SFF_8472: + sff_8079_show_all(einfo.data, d); + sff_8472_show_all(einfo.data, d); + break; default: RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); break; -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v9 5/5] ethdev: support SFF-8636 module information telemetry 2022-05-26 7:32 ` [PATCH v9 0/5] add telemetry command for show module EEPROM Robin Zhang ` (3 preceding siblings ...) 2022-05-26 7:32 ` [PATCH v9 4/5] ethdev: support SFF-8472 " Robin Zhang @ 2022-05-26 7:32 ` Robin Zhang 2022-05-31 14:43 ` [PATCH v9 0/5] add telemetry command for show module EEPROM Andrew Rybchenko 5 siblings, 0 replies; 77+ messages in thread From: Robin Zhang @ 2022-05-26 7:32 UTC (permalink / raw) To: dev; +Cc: thomas, andrew.rybchenko, kevinx.liu, Robin Zhang Add support for module EEPROM information format defined in SFF-8636 Rev 2.7. Signed-off-by: Robin Zhang <robinx.zhang@intel.com> Signed-off-by: Kevin Liu <kevinx.liu@intel.com> --- lib/ethdev/meson.build | 1 + lib/ethdev/sff_8636.c | 764 +++++++++++++++++++++++++++++++++++++ lib/ethdev/sff_8636.h | 590 ++++++++++++++++++++++++++++ lib/ethdev/sff_telemetry.c | 4 + 4 files changed, 1359 insertions(+) create mode 100644 lib/ethdev/sff_8636.c create mode 100644 lib/ethdev/sff_8636.h diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build index 6c24c0b715..47bb2625b0 100644 --- a/lib/ethdev/meson.build +++ b/lib/ethdev/meson.build @@ -15,6 +15,7 @@ sources = files( 'sff_common.c', 'sff_8079.c', 'sff_8472.c', + 'sff_8636.c', ) headers = files( diff --git a/lib/ethdev/sff_8636.c b/lib/ethdev/sff_8636.c new file mode 100644 index 0000000000..6b65f47efe --- /dev/null +++ b/lib/ethdev/sff_8636.c @@ -0,0 +1,764 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * Implements SFF-8636 based QSFP+/QSFP28 Diagnostics Memory map. + */ + +#include <stdio.h> +#include <math.h> + +#include "sff_common.h" +#include "sff_8636.h" + +#define SFF_MAX_DESC_SIZE 42 + +static const uint8_t sff_8636_rx_power_offset[SFF_MAX_CHANNEL_NUM] = { + SFF_8636_RX_PWR_1_OFFSET, + SFF_8636_RX_PWR_2_OFFSET, + SFF_8636_RX_PWR_3_OFFSET, + SFF_8636_RX_PWR_4_OFFSET, +}; +static const uint8_t sff_8636_tx_power_offset[SFF_MAX_CHANNEL_NUM] = { + SFF_8636_TX_PWR_1_OFFSET, + SFF_8636_TX_PWR_2_OFFSET, + SFF_8636_TX_PWR_3_OFFSET, + SFF_8636_TX_PWR_4_OFFSET, +}; +static const uint8_t sff_8636_tx_bias_offset[SFF_MAX_CHANNEL_NUM] = { + SFF_8636_TX_BIAS_1_OFFSET, + SFF_8636_TX_BIAS_2_OFFSET, + SFF_8636_TX_BIAS_3_OFFSET, + SFF_8636_TX_BIAS_4_OFFSET, +}; + +static struct sff_8636_aw_flags { + const char *str; /* Human-readable string, null at the end */ + int offset; /* A2-relative address offset */ + uint8_t value; /* Alarm is on if (offset & value) != 0. */ +} sff_8636_aw_flags[] = { + { "Laser bias current high alarm (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_HALARM) }, + { "Laser bias current low alarm (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_LALARM) }, + { "Laser bias current high warning (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_HWARN) }, + { "Laser bias current low warning (Chan 1)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_1_LWARN) }, + + { "Laser bias current high alarm (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_HALARM) }, + { "Laser bias current low alarm (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_LALARM) }, + { "Laser bias current high warning (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_HWARN) }, + { "Laser bias current low warning (Chan 2)", + SFF_8636_TX_BIAS_12_AW_OFFSET, (SFF_8636_TX_BIAS_2_LWARN) }, + + { "Laser bias current high alarm (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_HALARM) }, + { "Laser bias current low alarm (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_LALARM) }, + { "Laser bias current high warning (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_HWARN) }, + { "Laser bias current low warning (Chan 3)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_3_LWARN) }, + + { "Laser bias current high alarm (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_HALARM) }, + { "Laser bias current low alarm (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_LALARM) }, + { "Laser bias current high warning (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_HWARN) }, + { "Laser bias current low warning (Chan 4)", + SFF_8636_TX_BIAS_34_AW_OFFSET, (SFF_8636_TX_BIAS_4_LWARN) }, + + { "Module temperature high alarm", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_HALARM_STATUS) }, + { "Module temperature low alarm", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_LALARM_STATUS) }, + { "Module temperature high warning", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_HWARN_STATUS) }, + { "Module temperature low warning", + SFF_8636_TEMP_AW_OFFSET, (SFF_8636_TEMP_LWARN_STATUS) }, + + { "Module voltage high alarm", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_HALARM_STATUS) }, + { "Module voltage low alarm", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_LALARM_STATUS) }, + { "Module voltage high warning", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_HWARN_STATUS) }, + { "Module voltage low warning", + SFF_8636_VCC_AW_OFFSET, (SFF_8636_VCC_LWARN_STATUS) }, + + { "Laser tx power high alarm (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_HALARM) }, + { "Laser tx power low alarm (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_LALARM) }, + { "Laser tx power high warning (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_HWARN) }, + { "Laser tx power low warning (Channel 1)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_1_LWARN) }, + + { "Laser tx power high alarm (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_HALARM) }, + { "Laser tx power low alarm (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_LALARM) }, + { "Laser tx power high warning (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_HWARN) }, + { "Laser tx power low warning (Channel 2)", + SFF_8636_TX_PWR_12_AW_OFFSET, (SFF_8636_TX_PWR_2_LWARN) }, + + { "Laser tx power high alarm (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_HALARM) }, + { "Laser tx power low alarm (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_LALARM) }, + { "Laser tx power high warning (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_HWARN) }, + { "Laser tx power low warning (Channel 3)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_3_LWARN) }, + + { "Laser tx power high alarm (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_HALARM) }, + { "Laser tx power low alarm (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_LALARM) }, + { "Laser tx power high warning (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_HWARN) }, + { "Laser tx power low warning (Channel 4)", + SFF_8636_TX_PWR_34_AW_OFFSET, (SFF_8636_TX_PWR_4_LWARN) }, + + { "Laser rx power high alarm (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_HALARM) }, + { "Laser rx power low alarm (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_LALARM) }, + { "Laser rx power high warning (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_HWARN) }, + { "Laser rx power low warning (Channel 1)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_1_LWARN) }, + + { "Laser rx power high alarm (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_HALARM) }, + { "Laser rx power low alarm (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_LALARM) }, + { "Laser rx power high warning (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_HWARN) }, + { "Laser rx power low warning (Channel 2)", + SFF_8636_RX_PWR_12_AW_OFFSET, (SFF_8636_RX_PWR_2_LWARN) }, + + { "Laser rx power high alarm (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_HALARM) }, + { "Laser rx power low alarm (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_LALARM) }, + { "Laser rx power high warning (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_HWARN) }, + { "Laser rx power low warning (Channel 3)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_3_LWARN) }, + + { "Laser rx power high alarm (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_HALARM) }, + { "Laser rx power low alarm (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_LALARM) }, + { "Laser rx power high warning (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_HWARN) }, + { "Laser rx power low warning (Channel 4)", + SFF_8636_RX_PWR_34_AW_OFFSET, (SFF_8636_RX_PWR_4_LWARN) }, + + { NULL, 0, 0 }, +}; + +static void sff_8636_show_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_identifier(data, SFF_8636_ID_OFFSET, d); +} + +static void sff_8636_show_ext_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + static const char *name = "Extended identifier description"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + snprintf(val_string, sizeof(val_string), "0x%02x", data[SFF_8636_EXT_ID_OFFSET]); + ssf_add_dict_string(d, "Extended identifier", val_string); + + switch (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_PWR_CLASS_MASK) { + case SFF_8636_EXT_ID_PWR_CLASS_1: + ssf_add_dict_string(d, name, "1.5W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_2: + ssf_add_dict_string(d, name, "2.0W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_3: + ssf_add_dict_string(d, name, "2.5W max. Power consumption"); + break; + case SFF_8636_EXT_ID_PWR_CLASS_4: + ssf_add_dict_string(d, name, "3.5W max. Power consumption"); + break; + } + + if (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_CDR_TX_MASK) + ssf_add_dict_string(d, name, "CDR present in TX"); + else + ssf_add_dict_string(d, name, "No CDR in TX"); + + if (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_CDR_RX_MASK) + ssf_add_dict_string(d, name, "CDR present in RX"); + else + ssf_add_dict_string(d, name, "No CDR in RX"); + + switch (data[SFF_8636_EXT_ID_OFFSET] & SFF_8636_EXT_ID_EPWR_CLASS_MASK) { + case SFF_8636_EXT_ID_PWR_CLASS_LEGACY: + snprintf(val_string, sizeof(val_string), "%s", ""); + break; + case SFF_8636_EXT_ID_PWR_CLASS_5: + snprintf(val_string, sizeof(val_string), "%s", "4.0W max. Power consumption, "); + break; + case SFF_8636_EXT_ID_PWR_CLASS_6: + snprintf(val_string, sizeof(val_string), "%s", "4.5W max. Power consumption, "); + break; + case SFF_8636_EXT_ID_PWR_CLASS_7: + snprintf(val_string, sizeof(val_string), "%s", "5.0W max. Power consumption, "); + break; + } + + if (data[SFF_8636_PWR_MODE_OFFSET] & SFF_8636_HIGH_PWR_ENABLE) + strlcat(val_string, "High Power Class (> 3.5 W) enabled", sizeof(val_string)); + else + strlcat(val_string, "High Power Class (> 3.5 W) not enabled", sizeof(val_string)); + + ssf_add_dict_string(d, name, val_string); +} + +static void sff_8636_show_connector(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_connector(data, SFF_8636_CTOR_OFFSET, d); +} + +static void sff_8636_show_transceiver(const uint8_t *data, struct rte_tel_data *d) +{ + static const char *name = "Transceiver type"; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + + snprintf(val_string, sizeof(val_string), "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + data[SFF_8636_ETHERNET_COMP_OFFSET], + data[SFF_8636_SONET_COMP_OFFSET], + data[SFF_8636_SAS_COMP_OFFSET], + data[SFF_8636_GIGE_COMP_OFFSET], + data[SFF_8636_FC_LEN_OFFSET], + data[SFF_8636_FC_TECH_OFFSET], + data[SFF_8636_FC_TRANS_MEDIA_OFFSET], + data[SFF_8636_FC_SPEED_OFFSET]); + ssf_add_dict_string(d, "Transceiver codes", val_string); + + /* 10G/40G Ethernet Compliance Codes */ + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_LRM) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-LRM"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_LR) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-LR"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_10G_SR) + ssf_add_dict_string(d, name, "10G Ethernet: 10G Base-SR"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_CR4) + ssf_add_dict_string(d, name, "40G Ethernet: 40G Base-CR4"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_SR4) + ssf_add_dict_string(d, name, "40G Ethernet: 40G Base-SR4"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_LR4) + ssf_add_dict_string(d, name, "40G Ethernet: 40G Base-LR4"); + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_40G_ACTIVE) + ssf_add_dict_string(d, name, "40G Ethernet: 40G Active Cable (XLPPI)"); + + /* Extended Specification Compliance Codes from SFF-8024 */ + if (data[SFF_8636_ETHERNET_COMP_OFFSET] & SFF_8636_ETHERNET_RSRVD) { + switch (data[SFF_8636_OPTION_1_OFFSET]) { + case SFF_8636_ETHERNET_UNSPECIFIED: + ssf_add_dict_string(d, name, "(reserved or unknown)"); + break; + case SFF_8636_ETHERNET_100G_AOC: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)"); + break; + case SFF_8636_ETHERNET_100G_SR4: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G Base-SR4 or 25GBase-SR"); + break; + case SFF_8636_ETHERNET_100G_LR4: + ssf_add_dict_string(d, name, "100G Ethernet: 100G Base-LR4"); + break; + case SFF_8636_ETHERNET_100G_ER4: + ssf_add_dict_string(d, name, "100G Ethernet: 100G Base-ER4"); + break; + case SFF_8636_ETHERNET_100G_SR10: + ssf_add_dict_string(d, name, "100G Ethernet: 100G Base-SR10"); + break; + case SFF_8636_ETHERNET_100G_CWDM4_FEC: + ssf_add_dict_string(d, name, "100G Ethernet: 100G CWDM4 MSA with FEC"); + break; + case SFF_8636_ETHERNET_100G_PSM4: + ssf_add_dict_string(d, name, "100G Ethernet: 100G PSM4 Parallel SMF"); + break; + case SFF_8636_ETHERNET_100G_ACC: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)"); + break; + case SFF_8636_ETHERNET_100G_CWDM4_NO_FEC: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G CWDM4 MSA without FEC"); + break; + case SFF_8636_ETHERNET_100G_RSVD1: + ssf_add_dict_string(d, name, "(reserved or unknown)"); + break; + case SFF_8636_ETHERNET_100G_CR4: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G Base-CR4 or 25G Base-CR CA-L"); + break; + case SFF_8636_ETHERNET_25G_CR_CA_S: + ssf_add_dict_string(d, name, "25G Ethernet: 25G Base-CR CA-S"); + break; + case SFF_8636_ETHERNET_25G_CR_CA_N: + ssf_add_dict_string(d, name, "25G Ethernet: 25G Base-CR CA-N"); + break; + case SFF_8636_ETHERNET_40G_ER4: + ssf_add_dict_string(d, name, "40G Ethernet: 40G Base-ER4"); + break; + case SFF_8636_ETHERNET_4X10_SR: + ssf_add_dict_string(d, name, "4x10G Ethernet: 10G Base-SR"); + break; + case SFF_8636_ETHERNET_40G_PSM4: + ssf_add_dict_string(d, name, "40G Ethernet: 40G PSM4 Parallel SMF"); + break; + case SFF_8636_ETHERNET_G959_P1I1_2D1: + ssf_add_dict_string(d, name, + "Ethernet: G959.1 profile P1I1-2D1 (10709 MBd, 2km, 1310nm SM)"); + break; + case SFF_8636_ETHERNET_G959_P1S1_2D2: + ssf_add_dict_string(d, name, + "Ethernet: G959.1 profile P1S1-2D2 (10709 MBd, 40km, 1550nm SM)"); + break; + case SFF_8636_ETHERNET_G959_P1L1_2D2: + ssf_add_dict_string(d, name, + "Ethernet: G959.1 profile P1L1-2D2 (10709 MBd, 80km, 1550nm SM)"); + break; + case SFF_8636_ETHERNET_10GT_SFI: + ssf_add_dict_string(d, name, + "10G Ethernet: 10G Base-T with SFI electrical interface"); + break; + case SFF_8636_ETHERNET_100G_CLR4: + ssf_add_dict_string(d, name, "100G Ethernet: 100G CLR4"); + break; + case SFF_8636_ETHERNET_100G_AOC2: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)"); + break; + case SFF_8636_ETHERNET_100G_ACC2: + ssf_add_dict_string(d, name, + "100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)"); + break; + default: + ssf_add_dict_string(d, name, "(reserved or unknown)"); + break; + } + } + + /* SONET Compliance Codes */ + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_40G_OTN) + ssf_add_dict_string(d, name, "40G OTN (OTU3B/OTU3C)"); + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_LR) + ssf_add_dict_string(d, name, "SONET: OC-48, long reach"); + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_IR) + ssf_add_dict_string(d, name, "SONET: OC-48, intermediate reach"); + if (data[SFF_8636_SONET_COMP_OFFSET] & SFF_8636_SONET_OC48_SR) + ssf_add_dict_string(d, name, "SONET: OC-48, short reach"); + + /* SAS/SATA Compliance Codes */ + if (data[SFF_8636_SAS_COMP_OFFSET] & SFF_8636_SAS_6G) + ssf_add_dict_string(d, name, "SAS 6.0G"); + if (data[SFF_8636_SAS_COMP_OFFSET] & SFF_8636_SAS_3G) + ssf_add_dict_string(d, name, "SAS 3.0G"); + + /* Ethernet Compliance Codes */ + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_T) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-T"); + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_CX) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-CX"); + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_LX) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-LX"); + if (data[SFF_8636_GIGE_COMP_OFFSET] & SFF_8636_GIGE_1000_BASE_SX) + ssf_add_dict_string(d, name, "Ethernet: 1000BASE-SX"); + + /* Fibre Channel link length */ + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_VERY_LONG) + ssf_add_dict_string(d, name, "FC: very long distance (V)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_SHORT) + ssf_add_dict_string(d, name, "FC: short distance (S)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_INT) + ssf_add_dict_string(d, name, "FC: intermediate distance (I)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_LONG) + ssf_add_dict_string(d, name, "FC: long distance (L)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_LEN_MED) + ssf_add_dict_string(d, name, "FC: medium distance (M)"); + + /* Fibre Channel transmitter technology */ + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_TECH_LONG_LC) + ssf_add_dict_string(d, name, "FC: Longwave laser (LC)"); + if (data[SFF_8636_FC_LEN_OFFSET] & SFF_8636_FC_TECH_ELEC_INTER) + ssf_add_dict_string(d, name, "FC: Electrical inter-enclosure (EL)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_ELEC_INTRA) + ssf_add_dict_string(d, name, "FC: Electrical intra-enclosure (EL)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_SHORT_WO_OFC) + ssf_add_dict_string(d, name, "FC: Shortwave laser w/o OFC (SN)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_SHORT_W_OFC) + ssf_add_dict_string(d, name, "FC: Shortwave laser with OFC (SL)"); + if (data[SFF_8636_FC_TECH_OFFSET] & SFF_8636_FC_TECH_LONG_LL) + ssf_add_dict_string(d, name, "FC: Longwave laser (LL)"); + + /* Fibre Channel transmission media */ + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TW) + ssf_add_dict_string(d, name, "FC: Twin Axial Pair (TW)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TP) + ssf_add_dict_string(d, name, "FC: Twisted Pair (TP)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_MI) + ssf_add_dict_string(d, name, "FC: Miniature Coax (MI)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_TV) + ssf_add_dict_string(d, name, "FC: Video Coax (TV)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_M6) + ssf_add_dict_string(d, name, "FC: Multimode, 62.5m (M6)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_M5) + ssf_add_dict_string(d, name, "FC: Multimode, 50m (M5)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_OM3) + ssf_add_dict_string(d, name, "FC: Multimode, 50um (OM3)"); + if (data[SFF_8636_FC_TRANS_MEDIA_OFFSET] & SFF_8636_FC_TRANS_MEDIA_SM) + ssf_add_dict_string(d, name, "FC: Single Mode (SM)"); + + /* Fibre Channel speed */ + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_1200_MBPS) + ssf_add_dict_string(d, name, "FC: 1200 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_800_MBPS) + ssf_add_dict_string(d, name, "FC: 800 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_1600_MBPS) + ssf_add_dict_string(d, name, "FC: 1600 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_400_MBPS) + ssf_add_dict_string(d, name, "FC: 400 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_200_MBPS) + ssf_add_dict_string(d, name, "FC: 200 MBytes/sec"); + if (data[SFF_8636_FC_SPEED_OFFSET] & SFF_8636_FC_SPEED_100_MBPS) + ssf_add_dict_string(d, name, "FC: 100 MBytes/sec"); +} + +static void sff_8636_show_encoding(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_encoding(data, SFF_8636_ENCODING_OFFSET, + RTE_ETH_MODULE_SFF_8636, d); +} + +static void sff_8636_show_rate_identifier(const uint8_t *data, struct rte_tel_data *d) +{ + char val_string[20]; + + snprintf(val_string, sizeof(val_string), "0x%02x", data[SFF_8636_EXT_RS_OFFSET]); + ssf_add_dict_string(d, "Rate identifier", val_string); +} + +static void sff_8636_show_oui(const uint8_t *data, struct rte_tel_data *d) +{ + sff_8024_show_oui(data, SFF_8636_VENDOR_OUI_OFFSET, d); +} + +static void sff_8636_show_wavelength_or_copper_compliance(const uint8_t *data, + struct rte_tel_data *d) +{ + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + snprintf(val_string, sizeof(val_string), "0x%02x", + (data[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK)); + + switch (data[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK) { + case SFF_8636_TRANS_850_VCSEL: + strlcat(val_string, " (850 nm VCSEL)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_VCSEL: + strlcat(val_string, " (1310 nm VCSEL)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1550_VCSEL: + strlcat(val_string, " (1550 nm VCSEL)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_FP: + strlcat(val_string, " (1310 nm FP)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_DFB: + strlcat(val_string, " (1310 nm DFB)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1550_DFB: + strlcat(val_string, " (1550 nm DFB)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1310_EML: + strlcat(val_string, " (1310 nm EML)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1550_EML: + strlcat(val_string, " (1550 nm EML)", sizeof(val_string)); + break; + case SFF_8636_TRANS_OTHERS: + strlcat(val_string, " (Others/Undefined)", sizeof(val_string)); + break; + case SFF_8636_TRANS_1490_DFB: + strlcat(val_string, " (1490 nm DFB)", sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_PAS_UNEQUAL: + strlcat(val_string, " (Copper cable unequalized)", sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_PAS_EQUAL: + strlcat(val_string, " (Copper cable passive equalized)", sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_LNR_FAR_EQUAL: + strlcat(val_string, + " (Copper cable, near and far end limiting active equalizers)", + sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_FAR_EQUAL: + strlcat(val_string, + " (Copper cable, far end limiting active equalizers)", + sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_NEAR_EQUAL: + strlcat(val_string, + " (Copper cable, near end limiting active equalizers)", + sizeof(val_string)); + break; + case SFF_8636_TRANS_COPPER_LNR_EQUAL: + strlcat(val_string, + " (Copper cable, linear active equalizers)", + sizeof(val_string)); + break; + } + ssf_add_dict_string(d, "Transmitter technology", val_string); + + if ((data[SFF_8636_DEVICE_TECH_OFFSET] & SFF_8636_TRANS_TECH_MASK) + >= SFF_8636_TRANS_COPPER_PAS_UNEQUAL) { + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + ssf_add_dict_string(d, "Attenuation at 2.5GHz", val_string); + + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + ssf_add_dict_string(d, "Attenuation at 5.0GHz", val_string); + + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + ssf_add_dict_string(d, "Attenuation at 7.0GHz", val_string); + + snprintf(val_string, sizeof(val_string), "%udb", + data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET]); + ssf_add_dict_string(d, "Attenuation at 12.9GHz", val_string); + } else { + snprintf(val_string, sizeof(val_string), "%.3lfnm", + (((data[SFF_8636_WAVELEN_HIGH_BYTE_OFFSET] << 8) | + data[SFF_8636_WAVELEN_LOW_BYTE_OFFSET])*0.05)); + ssf_add_dict_string(d, "Laser wavelength", val_string); + + snprintf(val_string, sizeof(val_string), "%.3lfnm", + (((data[SFF_8636_WAVE_TOL_HIGH_BYTE_OFFSET] << 8) | + data[SFF_8636_WAVE_TOL_LOW_BYTE_OFFSET])*0.005)); + ssf_add_dict_string(d, "Laser wavelength tolerance", val_string); + } +} + +static void sff_8636_show_revision_compliance(const uint8_t *data, struct rte_tel_data *d) +{ + static const char *name = "Revision Compliance"; + + switch (data[SFF_8636_REV_COMPLIANCE_OFFSET]) { + case SFF_8636_REV_UNSPECIFIED: + ssf_add_dict_string(d, name, "Revision not specified"); + break; + case SFF_8636_REV_8436_48: + ssf_add_dict_string(d, name, "SFF-8436 Rev 4.8 or earlier"); + break; + case SFF_8636_REV_8436_8636: + ssf_add_dict_string(d, name, "SFF-8436 Rev 4.8 or earlier"); + break; + case SFF_8636_REV_8636_13: + ssf_add_dict_string(d, name, "SFF-8636 Rev 1.3 or earlier"); + break; + case SFF_8636_REV_8636_14: + ssf_add_dict_string(d, name, "SFF-8636 Rev 1.4"); + break; + case SFF_8636_REV_8636_15: + ssf_add_dict_string(d, name, "SFF-8636 Rev 1.5"); + break; + case SFF_8636_REV_8636_20: + ssf_add_dict_string(d, name, "SFF-8636 Rev 2.0"); + break; + case SFF_8636_REV_8636_27: + ssf_add_dict_string(d, name, "SFF-8636 Rev 2.5/2.6/2.7"); + break; + default: + ssf_add_dict_string(d, name, "Unallocated"); + break; + } +} + +/* + * 2-byte internal temperature conversions: + * First byte is a signed 8-bit integer, which is the temp decimal part + * Second byte are 1/256th of degree, which are added to the dec part. + */ +#define SFF_8636_OFFSET_TO_TEMP(offset) ((int16_t)SFF_OFFSET_TO_U16(offset)) + +static void sff_8636_dom_parse(const uint8_t *data, struct sff_diags *sd) +{ + int i = 0; + + /* Monitoring Thresholds for Alarms and Warnings */ + sd->sfp_voltage[SFF_MCURR] = SFF_OFFSET_TO_U16(SFF_8636_VCC_CURR); + sd->sfp_voltage[SFF_HALRM] = SFF_OFFSET_TO_U16(SFF_8636_VCC_HALRM); + sd->sfp_voltage[SFF_LALRM] = SFF_OFFSET_TO_U16(SFF_8636_VCC_LALRM); + sd->sfp_voltage[SFF_HWARN] = SFF_OFFSET_TO_U16(SFF_8636_VCC_HWARN); + sd->sfp_voltage[SFF_LWARN] = SFF_OFFSET_TO_U16(SFF_8636_VCC_LWARN); + + sd->sfp_temp[SFF_MCURR] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_CURR); + sd->sfp_temp[SFF_HALRM] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_HALRM); + sd->sfp_temp[SFF_LALRM] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_LALRM); + sd->sfp_temp[SFF_HWARN] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_HWARN); + sd->sfp_temp[SFF_LWARN] = SFF_8636_OFFSET_TO_TEMP(SFF_8636_TEMP_LWARN); + + sd->bias_cur[SFF_HALRM] = SFF_OFFSET_TO_U16(SFF_8636_TX_BIAS_HALRM); + sd->bias_cur[SFF_LALRM] = SFF_OFFSET_TO_U16(SFF_8636_TX_BIAS_LALRM); + sd->bias_cur[SFF_HWARN] = SFF_OFFSET_TO_U16(SFF_8636_TX_BIAS_HWARN); + sd->bias_cur[SFF_LWARN] = SFF_OFFSET_TO_U16(SFF_8636_TX_BIAS_LWARN); + + sd->tx_power[SFF_HALRM] = SFF_OFFSET_TO_U16(SFF_8636_TX_PWR_HALRM); + sd->tx_power[SFF_LALRM] = SFF_OFFSET_TO_U16(SFF_8636_TX_PWR_LALRM); + sd->tx_power[SFF_HWARN] = SFF_OFFSET_TO_U16(SFF_8636_TX_PWR_HWARN); + sd->tx_power[SFF_LWARN] = SFF_OFFSET_TO_U16(SFF_8636_TX_PWR_LWARN); + + sd->rx_power[SFF_HALRM] = SFF_OFFSET_TO_U16(SFF_8636_RX_PWR_HALRM); + sd->rx_power[SFF_LALRM] = SFF_OFFSET_TO_U16(SFF_8636_RX_PWR_LALRM); + sd->rx_power[SFF_HWARN] = SFF_OFFSET_TO_U16(SFF_8636_RX_PWR_HWARN); + sd->rx_power[SFF_LWARN] = SFF_OFFSET_TO_U16(SFF_8636_RX_PWR_LWARN); + + + /* Channel Specific Data */ + for (i = 0; i < SFF_MAX_CHANNEL_NUM; i++) { + sd->scd[i].bias_cur = SFF_OFFSET_TO_U16(sff_8636_tx_bias_offset[i]); + sd->scd[i].rx_power = SFF_OFFSET_TO_U16(sff_8636_rx_power_offset[i]); + sd->scd[i].tx_power = SFF_OFFSET_TO_U16(sff_8636_tx_power_offset[i]); + } + +} + +static void sff_8636_show_dom(const uint8_t *data, uint32_t eeprom_len, struct rte_tel_data *d) +{ + struct sff_diags sd = {0}; + const char *rx_power_string = NULL; + char power_string[SFF_MAX_DESC_SIZE]; + char val_string[SFF_ITEM_VAL_COMPOSE_SIZE]; + int i; + + /* + * There is no clear identifier to signify the existence of + * optical diagnostics similar to SFF-8472. So checking existence + * of page 3, will provide the guarantee for existence of alarms + * and thresholds + * If pagging support exists, then supports_alarms is marked as 1 + */ + + if (eeprom_len == RTE_ETH_MODULE_SFF_8636_MAX_LEN) { + if (!(data[SFF_8636_STATUS_2_OFFSET] & + SFF_8636_STATUS_PAGE_3_PRESENT)) { + sd.supports_alarms = 1; + } + } + + sd.rx_power_type = data[SFF_8636_DIAG_TYPE_OFFSET] & + SFF_8636_RX_PWR_TYPE_MASK; + sd.tx_power_type = data[SFF_8636_DIAG_TYPE_OFFSET] & + SFF_8636_RX_PWR_TYPE_MASK; + + sff_8636_dom_parse(data, &sd); + + SFF_SPRINT_TEMP(val_string, sd.sfp_temp[SFF_MCURR]); + ssf_add_dict_string(d, "Module temperature", val_string); + + SFF_SPRINT_VCC(val_string, sd.sfp_voltage[SFF_MCURR]); + ssf_add_dict_string(d, "Module voltage", val_string); + + /* + * SFF-8636/8436 spec is not clear whether RX power/ TX bias + * current fields are supported or not. A valid temperature + * reading is used as existence for TX/RX power. + */ + if ((sd.sfp_temp[SFF_MCURR] == 0x0) || + (sd.sfp_temp[SFF_MCURR] == (int16_t)0xFFFF)) + return; + + ssf_add_dict_string(d, "Alarm/warning flags implemented", + (sd.supports_alarms ? "Yes" : "No")); + + for (i = 0; i < SFF_MAX_CHANNEL_NUM; i++) { + snprintf(power_string, SFF_MAX_DESC_SIZE, "%s (Channel %d)", + "Laser tx bias current", i+1); + SFF_SPRINT_BIAS(val_string, sd.scd[i].bias_cur); + ssf_add_dict_string(d, power_string, val_string); + } + + for (i = 0; i < SFF_MAX_CHANNEL_NUM; i++) { + snprintf(power_string, SFF_MAX_DESC_SIZE, "%s (Channel %d)", + "Transmit avg optical power", i+1); + SFF_SPRINT_xX_PWR(val_string, sd.scd[i].tx_power); + ssf_add_dict_string(d, power_string, val_string); + } + + if (!sd.rx_power_type) + rx_power_string = "Receiver signal OMA"; + else + rx_power_string = "Rcvr signal avg optical power"; + + for (i = 0; i < SFF_MAX_CHANNEL_NUM; i++) { + snprintf(power_string, SFF_MAX_DESC_SIZE, "%s(Channel %d)", + rx_power_string, i+1); + SFF_SPRINT_xX_PWR(val_string, sd.scd[i].rx_power); + ssf_add_dict_string(d, power_string, val_string); + } + + if (sd.supports_alarms) { + for (i = 0; sff_8636_aw_flags[i].str; ++i) { + ssf_add_dict_string(d, sff_8636_aw_flags[i].str, + data[sff_8636_aw_flags[i].offset] + & sff_8636_aw_flags[i].value ? "On" : "Off"); + } + + sff_show_thresholds(sd, d); + } + +} +void sff_8636_show_all(const uint8_t *data, uint32_t eeprom_len, struct rte_tel_data *d) +{ + sff_8636_show_identifier(data, d); + if ((data[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP) || + (data[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP_PLUS) || + (data[SFF_8636_ID_OFFSET] == SFF_8024_ID_QSFP28)) { + sff_8636_show_ext_identifier(data, d); + sff_8636_show_connector(data, d); + sff_8636_show_transceiver(data, d); + sff_8636_show_encoding(data, d); + sff_show_value_with_unit(data, SFF_8636_BR_NOMINAL_OFFSET, + "BR, Nominal", 100, "Mbps", d); + sff_8636_show_rate_identifier(data, d); + sff_show_value_with_unit(data, SFF_8636_SM_LEN_OFFSET, + "Length (SMF,km)", 1, "km", d); + sff_show_value_with_unit(data, SFF_8636_OM3_LEN_OFFSET, + "Length (OM3 50um)", 2, "m", d); + sff_show_value_with_unit(data, SFF_8636_OM2_LEN_OFFSET, + "Length (OM2 50um)", 1, "m", d); + sff_show_value_with_unit(data, SFF_8636_OM1_LEN_OFFSET, + "Length (OM1 62.5um)", 1, "m", d); + sff_show_value_with_unit(data, SFF_8636_CBL_LEN_OFFSET, + "Length (Copper or Active cable)", 1, "m", d); + sff_8636_show_wavelength_or_copper_compliance(data, d); + sff_show_ascii(data, SFF_8636_VENDOR_NAME_START_OFFSET, + SFF_8636_VENDOR_NAME_END_OFFSET, "Vendor name", d); + sff_8636_show_oui(data, d); + sff_show_ascii(data, SFF_8636_VENDOR_PN_START_OFFSET, + SFF_8636_VENDOR_PN_END_OFFSET, "Vendor PN", d); + sff_show_ascii(data, SFF_8636_VENDOR_REV_START_OFFSET, + SFF_8636_VENDOR_REV_END_OFFSET, "Vendor rev", d); + sff_show_ascii(data, SFF_8636_VENDOR_SN_START_OFFSET, + SFF_8636_VENDOR_SN_END_OFFSET, "Vendor SN", d); + sff_show_ascii(data, SFF_8636_DATE_YEAR_OFFSET, + SFF_8636_DATE_VENDOR_LOT_OFFSET + 1, "Date code", d); + sff_8636_show_revision_compliance(data, d); + sff_8636_show_dom(data, eeprom_len, d); + } +} diff --git a/lib/ethdev/sff_8636.h b/lib/ethdev/sff_8636.h new file mode 100644 index 0000000000..70f70353d0 --- /dev/null +++ b/lib/ethdev/sff_8636.h @@ -0,0 +1,590 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * SFF-8636 standards based QSFP EEPROM Field Definitions + */ + +#ifndef _SFF_8636_H_ +#define _SFF_8636_H_ + +/*------------------------------------------------------------------------------ + * + * QSFP EEPROM data structures + * + * register info from SFF-8636 Rev 2.7 + */ + +/*------------------------------------------------------------------------------ + * + * Lower Memory Page 00h + * Measurement, Diagnostic and Control Functions + * + */ +/* Identifier - 0 */ +/* Values are defined under SFF_8024_ID_OFFSET */ +#define SFF_8636_ID_OFFSET 0x00 + +#define SFF_8636_REV_COMPLIANCE_OFFSET 0x01 +#define SFF_8636_REV_UNSPECIFIED 0x00 +#define SFF_8636_REV_8436_48 0x01 +#define SFF_8636_REV_8436_8636 0x02 +#define SFF_8636_REV_8636_13 0x03 +#define SFF_8636_REV_8636_14 0x04 +#define SFF_8636_REV_8636_15 0x05 +#define SFF_8636_REV_8636_20 0x06 +#define SFF_8636_REV_8636_27 0x07 + +#define SFF_8636_STATUS_2_OFFSET 0x02 +/* Flat Memory:0- Paging, 1- Page 0 only */ +#define SFF_8636_STATUS_PAGE_3_PRESENT RTE_BIT32(2) +#define SFF_8636_STATUS_INTL_OUTPUT RTE_BIT32(1) +#define SFF_8636_STATUS_DATA_NOT_READY RTE_BIT32(0) + +/* Channel Status Interrupt Flags - 3-5 */ +#define SFF_8636_LOS_AW_OFFSET 0x03 +#define SFF_8636_TX4_LOS_AW RTE_BIT32(7) +#define SFF_8636_TX3_LOS_AW RTE_BIT32(6) +#define SFF_8636_TX2_LOS_AW RTE_BIT32(5) +#define SFF_8636_TX1_LOS_AW RTE_BIT32(4) +#define SFF_8636_RX4_LOS_AW RTE_BIT32(3) +#define SFF_8636_RX3_LOS_AW RTE_BIT32(2) +#define SFF_8636_RX2_LOS_AW RTE_BIT32(1) +#define SFF_8636_RX1_LOS_AW RTE_BIT32(0) + +#define SFF_8636_FAULT_AW_OFFSET 0x04 +#define SFF_8636_TX4_FAULT_AW RTE_BIT32(3) +#define SFF_8636_TX3_FAULT_AW RTE_BIT32(2) +#define SFF_8636_TX2_FAULT_AW RTE_BIT32(1) +#define SFF_8636_TX1_FAULT_AW RTE_BIT32(0) + +/* Module Monitor Interrupt Flags - 6-8 */ +#define SFF_8636_TEMP_AW_OFFSET 0x06 +#define SFF_8636_TEMP_HALARM_STATUS RTE_BIT32(7) +#define SFF_8636_TEMP_LALARM_STATUS RTE_BIT32(6) +#define SFF_8636_TEMP_HWARN_STATUS RTE_BIT32(5) +#define SFF_8636_TEMP_LWARN_STATUS RTE_BIT32(4) + +#define SFF_8636_VCC_AW_OFFSET 0x07 +#define SFF_8636_VCC_HALARM_STATUS RTE_BIT32(7) +#define SFF_8636_VCC_LALARM_STATUS RTE_BIT32(6) +#define SFF_8636_VCC_HWARN_STATUS RTE_BIT32(5) +#define SFF_8636_VCC_LWARN_STATUS RTE_BIT32(4) + +/* Channel Monitor Interrupt Flags - 9-21 */ +#define SFF_8636_RX_PWR_12_AW_OFFSET 0x09 +#define SFF_8636_RX_PWR_1_HALARM RTE_BIT32(7) +#define SFF_8636_RX_PWR_1_LALARM RTE_BIT32(6) +#define SFF_8636_RX_PWR_1_HWARN RTE_BIT32(5) +#define SFF_8636_RX_PWR_1_LWARN RTE_BIT32(4) +#define SFF_8636_RX_PWR_2_HALARM RTE_BIT32(3) +#define SFF_8636_RX_PWR_2_LALARM RTE_BIT32(2) +#define SFF_8636_RX_PWR_2_HWARN RTE_BIT32(1) +#define SFF_8636_RX_PWR_2_LWARN RTE_BIT32(0) + +#define SFF_8636_RX_PWR_34_AW_OFFSET 0x0A +#define SFF_8636_RX_PWR_3_HALARM RTE_BIT32(7) +#define SFF_8636_RX_PWR_3_LALARM RTE_BIT32(6) +#define SFF_8636_RX_PWR_3_HWARN RTE_BIT32(5) +#define SFF_8636_RX_PWR_3_LWARN RTE_BIT32(4) +#define SFF_8636_RX_PWR_4_HALARM RTE_BIT32(3) +#define SFF_8636_RX_PWR_4_LALARM RTE_BIT32(2) +#define SFF_8636_RX_PWR_4_HWARN RTE_BIT32(1) +#define SFF_8636_RX_PWR_4_LWARN RTE_BIT32(0) + +#define SFF_8636_TX_BIAS_12_AW_OFFSET 0x0B +#define SFF_8636_TX_BIAS_1_HALARM RTE_BIT32(7) +#define SFF_8636_TX_BIAS_1_LALARM RTE_BIT32(6) +#define SFF_8636_TX_BIAS_1_HWARN RTE_BIT32(5) +#define SFF_8636_TX_BIAS_1_LWARN RTE_BIT32(4) +#define SFF_8636_TX_BIAS_2_HALARM RTE_BIT32(3) +#define SFF_8636_TX_BIAS_2_LALARM RTE_BIT32(2) +#define SFF_8636_TX_BIAS_2_HWARN RTE_BIT32(1) +#define SFF_8636_TX_BIAS_2_LWARN RTE_BIT32(0) + +#define SFF_8636_TX_BIAS_34_AW_OFFSET 0xC +#define SFF_8636_TX_BIAS_3_HALARM RTE_BIT32(7) +#define SFF_8636_TX_BIAS_3_LALARM RTE_BIT32(6) +#define SFF_8636_TX_BIAS_3_HWARN RTE_BIT32(5) +#define SFF_8636_TX_BIAS_3_LWARN RTE_BIT32(4) +#define SFF_8636_TX_BIAS_4_HALARM RTE_BIT32(3) +#define SFF_8636_TX_BIAS_4_LALARM RTE_BIT32(2) +#define SFF_8636_TX_BIAS_4_HWARN RTE_BIT32(1) +#define SFF_8636_TX_BIAS_4_LWARN RTE_BIT32(0) + +#define SFF_8636_TX_PWR_12_AW_OFFSET 0x0D +#define SFF_8636_TX_PWR_1_HALARM RTE_BIT32(7) +#define SFF_8636_TX_PWR_1_LALARM RTE_BIT32(6) +#define SFF_8636_TX_PWR_1_HWARN RTE_BIT32(5) +#define SFF_8636_TX_PWR_1_LWARN RTE_BIT32(4) +#define SFF_8636_TX_PWR_2_HALARM RTE_BIT32(3) +#define SFF_8636_TX_PWR_2_LALARM RTE_BIT32(2) +#define SFF_8636_TX_PWR_2_HWARN RTE_BIT32(1) +#define SFF_8636_TX_PWR_2_LWARN RTE_BIT32(0) + +#define SFF_8636_TX_PWR_34_AW_OFFSET 0x0E +#define SFF_8636_TX_PWR_3_HALARM RTE_BIT32(7) +#define SFF_8636_TX_PWR_3_LALARM RTE_BIT32(6) +#define SFF_8636_TX_PWR_3_HWARN RTE_BIT32(5) +#define SFF_8636_TX_PWR_3_LWARN RTE_BIT32(4) +#define SFF_8636_TX_PWR_4_HALARM RTE_BIT32(3) +#define SFF_8636_TX_PWR_4_LALARM RTE_BIT32(2) +#define SFF_8636_TX_PWR_4_HWARN RTE_BIT32(1) +#define SFF_8636_TX_PWR_4_LWARN RTE_BIT32(0) + +/* Module Monitoring Values - 22-33 */ +#define SFF_8636_TEMP_CURR 0x16 +#define SFF_8636_TEMP_MSB_OFFSET 0x16 +#define SFF_8636_TEMP_LSB_OFFSET 0x17 + +#define SFF_8636_VCC_CURR 0x1A +#define SFF_8636_VCC_MSB_OFFSET 0x1A +#define SFF_8636_VCC_LSB_OFFSET 0x1B + +/* Channel Monitoring Values - 34-81 */ +#define SFF_8636_RX_PWR_1_OFFSET 0x22 +#define SFF_8636_RX_PWR_2_OFFSET 0x24 +#define SFF_8636_RX_PWR_3_OFFSET 0x26 +#define SFF_8636_RX_PWR_4_OFFSET 0x28 + +#define SFF_8636_TX_BIAS_1_OFFSET 0x2A +#define SFF_8636_TX_BIAS_2_OFFSET 0x2C +#define SFF_8636_TX_BIAS_3_OFFSET 0x2E +#define SFF_8636_TX_BIAS_4_OFFSET 0x30 + +#define SFF_8636_TX_PWR_1_OFFSET 0x32 +#define SFF_8636_TX_PWR_2_OFFSET 0x34 +#define SFF_8636_TX_PWR_3_OFFSET 0x36 +#define SFF_8636_TX_PWR_4_OFFSET 0x38 + +/* Control Bytes - 86 - 99 */ +#define SFF_8636_TX_DISABLE_OFFSET 0x56 +#define SFF_8636_TX_DISABLE_4 RTE_BIT32(3) +#define SFF_8636_TX_DISABLE_3 RTE_BIT32(2) +#define SFF_8636_TX_DISABLE_2 RTE_BIT32(1) +#define SFF_8636_TX_DISABLE_1 RTE_BIT32(0) + +#define SFF_8636_RX_RATE_SELECT_OFFSET 0x57 +#define SFF_8636_RX_RATE_SELECT_4_MASK (3 << 6) +#define SFF_8636_RX_RATE_SELECT_3_MASK (3 << 4) +#define SFF_8636_RX_RATE_SELECT_2_MASK (3 << 2) +#define SFF_8636_RX_RATE_SELECT_1_MASK (3 << 0) + +#define SFF_8636_TX_RATE_SELECT_OFFSET 0x58 +#define SFF_8636_TX_RATE_SELECT_4_MASK (3 << 6) +#define SFF_8636_TX_RATE_SELECT_3_MASK (3 << 4) +#define SFF_8636_TX_RATE_SELECT_2_MASK (3 << 2) +#define SFF_8636_TX_RATE_SELECT_1_MASK (3 << 0) + +#define SFF_8636_RX_APP_SELECT_4_OFFSET 0x58 +#define SFF_8636_RX_APP_SELECT_3_OFFSET 0x59 +#define SFF_8636_RX_APP_SELECT_2_OFFSET 0x5A +#define SFF_8636_RX_APP_SELECT_1_OFFSET 0x5B + +#define SFF_8636_PWR_MODE_OFFSET 0x5D +#define SFF_8636_HIGH_PWR_ENABLE RTE_BIT32(2) +#define SFF_8636_LOW_PWR_MODE RTE_BIT32(1) +#define SFF_8636_PWR_OVERRIDE RTE_BIT32(0) + +#define SFF_8636_TX_APP_SELECT_4_OFFSET 0x5E +#define SFF_8636_TX_APP_SELECT_3_OFFSET 0x5F +#define SFF_8636_TX_APP_SELECT_2_OFFSET 0x60 +#define SFF_8636_TX_APP_SELECT_1_OFFSET 0x61 + +#define SFF_8636_LOS_MASK_OFFSET 0x64 +#define SFF_8636_TX_LOS_4_MASK RTE_BIT32(7) +#define SFF_8636_TX_LOS_3_MASK RTE_BIT32(6) +#define SFF_8636_TX_LOS_2_MASK RTE_BIT32(5) +#define SFF_8636_TX_LOS_1_MASK RTE_BIT32(4) +#define SFF_8636_RX_LOS_4_MASK RTE_BIT32(3) +#define SFF_8636_RX_LOS_3_MASK RTE_BIT32(2) +#define SFF_8636_RX_LOS_2_MASK RTE_BIT32(1) +#define SFF_8636_RX_LOS_1_MASK RTE_BIT32(0) + +#define SFF_8636_FAULT_MASK_OFFSET 0x65 +#define SFF_8636_TX_FAULT_1_MASK RTE_BIT32(3) +#define SFF_8636_TX_FAULT_2_MASK RTE_BIT32(2) +#define SFF_8636_TX_FAULT_3_MASK RTE_BIT32(1) +#define SFF_8636_TX_FAULT_4_MASK RTE_BIT32(0) + +#define SFF_8636_TEMP_MASK_OFFSET 0x67 +#define SFF_8636_TEMP_HALARM_MASK RTE_BIT32(7) +#define SFF_8636_TEMP_LALARM_MASK RTE_BIT32(6) +#define SFF_8636_TEMP_HWARN_MASK RTE_BIT32(5) +#define SFF_8636_TEMP_LWARN_MASK RTE_BIT32(4) + +#define SFF_8636_VCC_MASK_OFFSET 0x68 +#define SFF_8636_VCC_HALARM_MASK RTE_BIT32(7) +#define SFF_8636_VCC_LALARM_MASK RTE_BIT32(6) +#define SFF_8636_VCC_HWARN_MASK RTE_BIT32(5) +#define SFF_8636_VCC_LWARN_MASK RTE_BIT32(4) + +/*------------------------------------------------------------------------------ + * + * Upper Memory Page 00h + * Serial ID - Base ID, Extended ID and Vendor Specific ID fields + * + */ +/* Identifier - 128 */ +/* Identifier values same as Lower Memory Page 00h */ +#define SFF_8636_UPPER_PAGE_0_ID_OFFSET 0x80 + +/* Extended Identifier - 128 */ +#define SFF_8636_EXT_ID_OFFSET 0x81 +#define SFF_8636_EXT_ID_PWR_CLASS_MASK 0xC0 +#define SFF_8636_EXT_ID_PWR_CLASS_1 (0 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_2 (1 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_3 (2 << 6) +#define SFF_8636_EXT_ID_PWR_CLASS_4 (3 << 6) +#define SFF_8636_EXT_ID_CLIE_MASK 0x10 +#define SFF_8636_EXT_ID_CLIEI_CODE_PRESENT (1 << 4) +#define SFF_8636_EXT_ID_CDR_TX_MASK 0x08 +#define SFF_8636_EXT_ID_CDR_TX_PRESENT (1 << 3) +#define SFF_8636_EXT_ID_CDR_RX_MASK 0x04 +#define SFF_8636_EXT_ID_CDR_RX_PRESENT (1 << 2) +#define SFF_8636_EXT_ID_EPWR_CLASS_MASK 0x03 +#define SFF_8636_EXT_ID_PWR_CLASS_LEGACY 0 +#define SFF_8636_EXT_ID_PWR_CLASS_5 1 +#define SFF_8636_EXT_ID_PWR_CLASS_6 2 +#define SFF_8636_EXT_ID_PWR_CLASS_7 3 + +/* Connector Values offset - 130 */ +/* Values are defined under SFF_8024_CTOR */ +#define SFF_8636_CTOR_OFFSET 0x82 +#define SFF_8636_CTOR_UNKNOWN 0x00 +#define SFF_8636_CTOR_SC 0x01 +#define SFF_8636_CTOR_FC_STYLE_1 0x02 +#define SFF_8636_CTOR_FC_STYLE_2 0x03 +#define SFF_8636_CTOR_BNC_TNC 0x04 +#define SFF_8636_CTOR_FC_COAX 0x05 +#define SFF_8636_CTOR_FIBER_JACK 0x06 +#define SFF_8636_CTOR_LC 0x07 +#define SFF_8636_CTOR_MT_RJ 0x08 +#define SFF_8636_CTOR_MU 0x09 +#define SFF_8636_CTOR_SG 0x0A +#define SFF_8636_CTOR_OPT_PT 0x0B +#define SFF_8636_CTOR_MPO 0x0C +/* 0D-1Fh --- Reserved */ +#define SFF_8636_CTOR_HSDC_II 0x20 +#define SFF_8636_CTOR_COPPER_PT 0x21 +#define SFF_8636_CTOR_RJ45 0x22 +#define SFF_8636_CTOR_NO_SEPARABLE 0x23 +#define SFF_8636_CTOR_MXC_2X16 0x24 + +/* Specification Compliance - 131-138 */ +/* Ethernet Compliance Codes - 131 */ +#define SFF_8636_ETHERNET_COMP_OFFSET 0x83 +#define SFF_8636_ETHERNET_RSRVD RTE_BIT32(7) +#define SFF_8636_ETHERNET_10G_LRM RTE_BIT32(6) +#define SFF_8636_ETHERNET_10G_LR RTE_BIT32(5) +#define SFF_8636_ETHERNET_10G_SR RTE_BIT32(4) +#define SFF_8636_ETHERNET_40G_CR4 RTE_BIT32(3) +#define SFF_8636_ETHERNET_40G_SR4 RTE_BIT32(2) +#define SFF_8636_ETHERNET_40G_LR4 RTE_BIT32(1) +#define SFF_8636_ETHERNET_40G_ACTIVE RTE_BIT32(0) + +/* SONET Compliance Codes - 132 */ +#define SFF_8636_SONET_COMP_OFFSET 0x84 +#define SFF_8636_SONET_40G_OTN RTE_BIT32(3) +#define SFF_8636_SONET_OC48_LR RTE_BIT32(2) +#define SFF_8636_SONET_OC48_IR RTE_BIT32(1) +#define SFF_8636_SONET_OC48_SR RTE_BIT32(0) + +/* SAS/SATA Complaince Codes - 133 */ +#define SFF_8636_SAS_COMP_OFFSET 0x85 +#define SFF_8636_SAS_12G RTE_BIT32(6) +#define SFF_8636_SAS_6G RTE_BIT32(5) +#define SFF_8636_SAS_3G RTE_BIT32(4) + +/* Gigabit Ethernet Compliance Codes - 134 */ +#define SFF_8636_GIGE_COMP_OFFSET 0x86 +#define SFF_8636_GIGE_1000_BASE_T RTE_BIT32(3) +#define SFF_8636_GIGE_1000_BASE_CX RTE_BIT32(2) +#define SFF_8636_GIGE_1000_BASE_LX RTE_BIT32(1) +#define SFF_8636_GIGE_1000_BASE_SX RTE_BIT32(0) + +/* Fibre Channel Link length/Transmitter Tech. - 135,136 */ +#define SFF_8636_FC_LEN_OFFSET 0x87 +#define SFF_8636_FC_LEN_VERY_LONG RTE_BIT32(7) +#define SFF_8636_FC_LEN_SHORT RTE_BIT32(6) +#define SFF_8636_FC_LEN_INT RTE_BIT32(5) +#define SFF_8636_FC_LEN_LONG RTE_BIT32(4) +#define SFF_8636_FC_LEN_MED RTE_BIT32(3) +#define SFF_8636_FC_TECH_LONG_LC RTE_BIT32(1) +#define SFF_8636_FC_TECH_ELEC_INTER RTE_BIT32(0) + +#define SFF_8636_FC_TECH_OFFSET 0x88 +#define SFF_8636_FC_TECH_ELEC_INTRA RTE_BIT32(7) +#define SFF_8636_FC_TECH_SHORT_WO_OFC RTE_BIT32(6) +#define SFF_8636_FC_TECH_SHORT_W_OFC RTE_BIT32(5) +#define SFF_8636_FC_TECH_LONG_LL RTE_BIT32(4) + +/* Fibre Channel Transmitter Media - 137 */ +#define SFF_8636_FC_TRANS_MEDIA_OFFSET 0x89 +/* Twin Axial Pair */ +#define SFF_8636_FC_TRANS_MEDIA_TW RTE_BIT32(7) +/* Shielded Twisted Pair */ +#define SFF_8636_FC_TRANS_MEDIA_TP RTE_BIT32(6) +/* Miniature Coax */ +#define SFF_8636_FC_TRANS_MEDIA_MI RTE_BIT32(5) +/* Video Coax */ +#define SFF_8636_FC_TRANS_MEDIA_TV RTE_BIT32(4) +/* Multi-mode 62.5m */ +#define SFF_8636_FC_TRANS_MEDIA_M6 RTE_BIT32(3) +/* Multi-mode 50m */ +#define SFF_8636_FC_TRANS_MEDIA_M5 RTE_BIT32(2) +/* Multi-mode 50um */ +#define SFF_8636_FC_TRANS_MEDIA_OM3 RTE_BIT32(1) +/* Single Mode */ +#define SFF_8636_FC_TRANS_MEDIA_SM RTE_BIT32(0) + +/* Fibre Channel Speed - 138 */ +#define SFF_8636_FC_SPEED_OFFSET 0x8A +#define SFF_8636_FC_SPEED_1200_MBPS RTE_BIT32(7) +#define SFF_8636_FC_SPEED_800_MBPS RTE_BIT32(6) +#define SFF_8636_FC_SPEED_1600_MBPS RTE_BIT32(5) +#define SFF_8636_FC_SPEED_400_MBPS RTE_BIT32(4) +#define SFF_8636_FC_SPEED_200_MBPS RTE_BIT32(2) +#define SFF_8636_FC_SPEED_100_MBPS RTE_BIT32(0) + +/* Encoding - 139 */ +/* Values are defined under SFF_8024_ENCODING */ +#define SFF_8636_ENCODING_OFFSET 0x8B +#define SFF_8636_ENCODING_MANCHESTER 0x06 +#define SFF_8636_ENCODING_64B66B 0x05 +#define SFF_8636_ENCODING_SONET 0x04 +#define SFF_8636_ENCODING_NRZ 0x03 +#define SFF_8636_ENCODING_4B5B 0x02 +#define SFF_8636_ENCODING_8B10B 0x01 +#define SFF_8636_ENCODING_UNSPEC 0x00 + +/* BR, Nominal - 140 */ +#define SFF_8636_BR_NOMINAL_OFFSET 0x8C + +/* Extended RateSelect - 141 */ +#define SFF_8636_EXT_RS_OFFSET 0x8D +#define SFF_8636_EXT_RS_V1 RTE_BIT32(0) + +/* Length (Standard SM Fiber)-km - 142 */ +#define SFF_8636_SM_LEN_OFFSET 0x8E + +/* Length (OM3)-Unit 2m - 143 */ +#define SFF_8636_OM3_LEN_OFFSET 0x8F + +/* Length (OM2)-Unit 1m - 144 */ +#define SFF_8636_OM2_LEN_OFFSET 0x90 + +/* Length (OM1)-Unit 1m - 145 */ +#define SFF_8636_OM1_LEN_OFFSET 0x91 + +/* Cable Assembly Length -Unit 1m - 146 */ +#define SFF_8636_CBL_LEN_OFFSET 0x92 + +/* Device Technology - 147 */ +#define SFF_8636_DEVICE_TECH_OFFSET 0x93 +/* Transmitter Technology */ +#define SFF_8636_TRANS_TECH_MASK 0xF0 +/* Copper cable, linear active equalizers */ +#define SFF_8636_TRANS_COPPER_LNR_EQUAL (15 << 4) +/* Copper cable, near end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_NEAR_EQUAL (14 << 4) +/* Copper cable, far end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_FAR_EQUAL (13 << 4) +/* Copper cable, near & far end limiting active equalizers */ +#define SFF_8636_TRANS_COPPER_LNR_FAR_EQUAL (12 << 4) +/* Copper cable, passive equalized */ +#define SFF_8636_TRANS_COPPER_PAS_EQUAL (11 << 4) +/* Copper cable, unequalized */ +#define SFF_8636_TRANS_COPPER_PAS_UNEQUAL (10 << 4) +/* 1490 nm DFB */ +#define SFF_8636_TRANS_1490_DFB (9 << 4) +/* Others */ +#define SFF_8636_TRANS_OTHERS (8 << 4) +/* 1550 nm EML */ +#define SFF_8636_TRANS_1550_EML (7 << 4) +/* 1310 nm EML */ +#define SFF_8636_TRANS_1310_EML (6 << 4) +/* 1550 nm DFB */ +#define SFF_8636_TRANS_1550_DFB (5 << 4) +/* 1310 nm DFB */ +#define SFF_8636_TRANS_1310_DFB (4 << 4) +/* 1310 nm FP */ +#define SFF_8636_TRANS_1310_FP (3 << 4) +/* 1550 nm VCSEL */ +#define SFF_8636_TRANS_1550_VCSEL (2 << 4) +/* 1310 nm VCSEL */ +#define SFF_8636_TRANS_1310_VCSEL (1 << 4) +/* 850 nm VCSEL */ +#define SFF_8636_TRANS_850_VCSEL (0 << 4) + + /* Active/No wavelength control */ +#define SFF_8636_DEV_TECH_ACTIVE_WAVE_LEN RTE_BIT32(3) +/* Cooled transmitter */ +#define SFF_8636_DEV_TECH_COOL_TRANS RTE_BIT32(2) +/* APD/Pin Detector */ +#define SFF_8636_DEV_TECH_APD_DETECTOR RTE_BIT32(1) +/* Transmitter tunable */ +#define SFF_8636_DEV_TECH_TUNABLE RTE_BIT32(0) + +/* Vendor Name - 148-163 */ +#define SFF_8636_VENDOR_NAME_START_OFFSET 0x94 +#define SFF_8636_VENDOR_NAME_END_OFFSET 0xA3 + +/* Extended Module Codes - 164 */ +#define SFF_8636_EXT_MOD_CODE_OFFSET 0xA4 +#define SFF_8636_EXT_MOD_INFINIBAND_EDR RTE_BIT32(4) +#define SFF_8636_EXT_MOD_INFINIBAND_FDR RTE_BIT32(3) +#define SFF_8636_EXT_MOD_INFINIBAND_QDR RTE_BIT32(2) +#define SFF_8636_EXT_MOD_INFINIBAND_DDR RTE_BIT32(1) +#define SFF_8636_EXT_MOD_INFINIBAND_SDR RTE_BIT32(0) + +/* Vendor OUI - 165-167 */ +#define SFF_8636_VENDOR_OUI_OFFSET 0xA5 +#define SFF_8636_VENDOR_OUI_LEN 3 + +/* Vendor OUI - 165-167 */ +#define SFF_8636_VENDOR_PN_START_OFFSET 0xA8 +#define SFF_8636_VENDOR_PN_END_OFFSET 0xB7 + +/* Vendor Revision - 184-185 */ +#define SFF_8636_VENDOR_REV_START_OFFSET 0xB8 +#define SFF_8636_VENDOR_REV_END_OFFSET 0xB9 + +/* Wavelength - 186-187 */ +#define SFF_8636_WAVELEN_HIGH_BYTE_OFFSET 0xBA +#define SFF_8636_WAVELEN_LOW_BYTE_OFFSET 0xBB + +/* Wavelength Tolerance- 188-189 */ +#define SFF_8636_WAVE_TOL_HIGH_BYTE_OFFSET 0xBC +#define SFF_8636_WAVE_TOL_LOW_BYTE_OFFSET 0xBD + +/* Max case temp - Other than 70 C - 190 */ +#define SFF_8636_MAXCASE_TEMP_OFFSET 0xBE + +/* CC_BASE - 191 */ +#define SFF_8636_CC_BASE_OFFSET 0xBF + +/* Option Values - 192-195 */ +#define SFF_8636_OPTION_1_OFFSET 0xC0 +#define SFF_8636_ETHERNET_UNSPECIFIED 0x00 +#define SFF_8636_ETHERNET_100G_AOC 0x01 +#define SFF_8636_ETHERNET_100G_SR4 0x02 +#define SFF_8636_ETHERNET_100G_LR4 0x03 +#define SFF_8636_ETHERNET_100G_ER4 0x04 +#define SFF_8636_ETHERNET_100G_SR10 0x05 +#define SFF_8636_ETHERNET_100G_CWDM4_FEC 0x06 +#define SFF_8636_ETHERNET_100G_PSM4 0x07 +#define SFF_8636_ETHERNET_100G_ACC 0x08 +#define SFF_8636_ETHERNET_100G_CWDM4_NO_FEC 0x09 +#define SFF_8636_ETHERNET_100G_RSVD1 0x0A +#define SFF_8636_ETHERNET_100G_CR4 0x0B +#define SFF_8636_ETHERNET_25G_CR_CA_S 0x0C +#define SFF_8636_ETHERNET_25G_CR_CA_N 0x0D +#define SFF_8636_ETHERNET_40G_ER4 0x10 +#define SFF_8636_ETHERNET_4X10_SR 0x11 +#define SFF_8636_ETHERNET_40G_PSM4 0x12 +#define SFF_8636_ETHERNET_G959_P1I1_2D1 0x13 +#define SFF_8636_ETHERNET_G959_P1S1_2D2 0x14 +#define SFF_8636_ETHERNET_G959_P1L1_2D2 0x15 +#define SFF_8636_ETHERNET_10GT_SFI 0x16 +#define SFF_8636_ETHERNET_100G_CLR4 0x17 +#define SFF_8636_ETHERNET_100G_AOC2 0x18 +#define SFF_8636_ETHERNET_100G_ACC2 0x19 + +#define SFF_8636_OPTION_2_OFFSET 0xC1 +/* Rx output amplitude */ +#define SFF_8636_O2_RX_OUTPUT_AMP RTE_BIT32(0) +#define SFF_8636_OPTION_3_OFFSET 0xC2 +/* Rx Squelch Disable */ +#define SFF_8636_O3_RX_SQL_DSBL RTE_BIT32(3) +/* Rx Output Disable capable */ +#define SFF_8636_O3_RX_OUTPUT_DSBL RTE_BIT32(2) +/* Tx Squelch Disable */ +#define SFF_8636_O3_TX_SQL_DSBL RTE_BIT32(1) +/* Tx Squelch Impl */ +#define SFF_8636_O3_TX_SQL_IMPL RTE_BIT32(0) +#define SFF_8636_OPTION_4_OFFSET 0xC3 +/* Memory Page 02 present */ +#define SFF_8636_O4_PAGE_02_PRESENT RTE_BIT32(7) +/* Memory Page 01 present */ +#define SFF_8636_O4_PAGE_01_PRESENT RTE_BIT32(6) +/* Rate Select implemented */ +#define SFF_8636_O4_RATE_SELECT RTE_BIT32(5) +/* Tx_DISABLE implemented */ +#define SFF_8636_O4_TX_DISABLE RTE_BIT32(4) +/* Tx_FAULT implemented */ +#define SFF_8636_O4_TX_FAULT RTE_BIT32(3) +/* Tx Squelch implemented */ +#define SFF_8636_O4_TX_SQUELCH RTE_BIT32(2) +/* Tx Loss of Signal */ +#define SFF_8636_O4_TX_LOS RTE_BIT32(1) + +/* Vendor SN - 196-211 */ +#define SFF_8636_VENDOR_SN_START_OFFSET 0xC4 +#define SFF_8636_VENDOR_SN_END_OFFSET 0xD3 + +/* Vendor Date - 212-219 */ +#define SFF_8636_DATE_YEAR_OFFSET 0xD4 +#define SFF_8636_DATE_YEAR_LEN 2 +#define SFF_8636_DATE_MONTH_OFFSET 0xD6 +#define SFF_8636_DATE_MONTH_LEN 2 +#define SFF_8636_DATE_DAY_OFFSET 0xD8 +#define SFF_8636_DATE_DAY_LEN 2 +#define SFF_8636_DATE_VENDOR_LOT_OFFSET 0xDA +#define SFF_8636_DATE_VENDOR_LOT_LEN 2 + +/* Diagnostic Monitoring Type - 220 */ +#define SFF_8636_DIAG_TYPE_OFFSET 0xDC +#define SFF_8636_RX_PWR_TYPE_MASK 0x8 +#define SFF_8636_RX_PWR_TYPE_AVG_PWR RTE_BIT32(3) +#define SFF_8636_RX_PWR_TYPE_OMA (0 << 3) +#define SFF_8636_TX_PWR_TYPE_MASK 0x4 +#define SFF_8636_TX_PWR_TYPE_AVG_PWR RTE_BIT32(2) + +/* Enhanced Options - 221 */ +#define SFF_8636_ENH_OPTIONS_OFFSET 0xDD +#define SFF_8636_RATE_SELECT_EXT_SUPPORT RTE_BIT32(3) +#define SFF_8636_RATE_SELECT_APP_TABLE_SUPPORT RTE_BIT32(2) + +/* Check code - 223 */ +#define SFF_8636_CC_EXT_OFFSET 0xDF +#define SFF_8636_CC_EXT_LEN 1 + +/*------------------------------------------------------------------------------ + * + * Upper Memory Page 03h + * Contains module thresholds, channel thresholds and masks, + * and optional channel controls + * + * Offset - Page Num(3) * PageSize(0x80) + Page offset + */ + +/* Module Thresholds (48 Bytes) 128-175 */ +/* MSB at low address, LSB at high address */ +#define SFF_8636_TEMP_HALRM 0x200 +#define SFF_8636_TEMP_LALRM 0x202 +#define SFF_8636_TEMP_HWARN 0x204 +#define SFF_8636_TEMP_LWARN 0x206 + +#define SFF_8636_VCC_HALRM 0x210 +#define SFF_8636_VCC_LALRM 0x212 +#define SFF_8636_VCC_HWARN 0x214 +#define SFF_8636_VCC_LWARN 0x216 + +#define SFF_8636_RX_PWR_HALRM 0x230 +#define SFF_8636_RX_PWR_LALRM 0x232 +#define SFF_8636_RX_PWR_HWARN 0x234 +#define SFF_8636_RX_PWR_LWARN 0x236 + +#define SFF_8636_TX_BIAS_HALRM 0x238 +#define SFF_8636_TX_BIAS_LALRM 0x23A +#define SFF_8636_TX_BIAS_HWARN 0x23C +#define SFF_8636_TX_BIAS_LWARN 0x23E + +#define SFF_8636_TX_PWR_HALRM 0x240 +#define SFF_8636_TX_PWR_LALRM 0x242 +#define SFF_8636_TX_PWR_HWARN 0x244 +#define SFF_8636_TX_PWR_LWARN 0x246 + +#define ETH_MODULE_SFF_8636_MAX_LEN 640 +#define ETH_MODULE_SFF_8436_MAX_LEN 640 + +#endif /* _SFF_8636_H_ */ diff --git a/lib/ethdev/sff_telemetry.c b/lib/ethdev/sff_telemetry.c index babb9418b2..887f07c47e 100644 --- a/lib/ethdev/sff_telemetry.c +++ b/lib/ethdev/sff_telemetry.c @@ -77,6 +77,10 @@ sff_port_module_eeprom_parse(uint16_t port_id, struct rte_tel_data *d) sff_8079_show_all(einfo.data, d); sff_8472_show_all(einfo.data, d); break; + case RTE_ETH_MODULE_SFF_8436: + case RTE_ETH_MODULE_SFF_8636: + sff_8636_show_all(einfo.data, einfo.length, d); + break; default: RTE_ETHDEV_LOG(NOTICE, "Unsupported module type: %u\n", minfo.type); break; -- 2.25.1 ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v9 0/5] add telemetry command for show module EEPROM 2022-05-26 7:32 ` [PATCH v9 0/5] add telemetry command for show module EEPROM Robin Zhang ` (4 preceding siblings ...) 2022-05-26 7:32 ` [PATCH v9 5/5] ethdev: support SFF-8636 " Robin Zhang @ 2022-05-31 14:43 ` Andrew Rybchenko 5 siblings, 0 replies; 77+ messages in thread From: Andrew Rybchenko @ 2022-05-31 14:43 UTC (permalink / raw) To: Robin Zhang, dev; +Cc: thomas, kevinx.liu On 5/26/22 10:32, Robin Zhang wrote: > Introduce a new telemetry command /ethdev/module_eeprom to show module > EEPROM for each port. The format of module EEPROM information follows > the SFF(Small Form Factor) Committee specifications. > > Current the format support SFP(Small Formfactor Pluggable)/SFP+/ > QSFP+(Quad Small Formfactor Pluggable)/QSFP28 with specs SFF-8079/ > SFF-8472/SFF-8024/SFF-8636. > > Afther run the /ethdev/module_eeprom command, telemetry client will > show the module EEPROM information. We keep the same information content > compare with Linux utility ethtool, refer to command 'ethtool -m' of > ethtool v5.4. > > v9: > - Optimize code format and commit log > > v8: > - refine code > > v7: > - remove "#include <arpa/inet.h>" in lib/ethdev/sff_8472.c > > v6: > - refine code > > v5: > - fix CI robot compile fail issue > > v4: > - remove all printf in primary application, only show information > in tememetry client > - refine codes > > v3: > - split up codes into several patches for better reivew > > Robin Zhang (5): > ethdev: add telemetry command for module EEPROM > ethdev: add common code for different SFF specs > ethdev: support SFF-8079 module information telemetry > ethdev: support SFF-8472 module information telemetry > ethdev: support SFF-8636 module information telemetry > > devtools/words-case.txt | 1 + > lib/ethdev/meson.build | 5 + > lib/ethdev/rte_ethdev.c | 3 + > lib/ethdev/sff_8079.c | 401 +++++++++++++++++++ > lib/ethdev/sff_8472.c | 280 ++++++++++++++ > lib/ethdev/sff_8636.c | 764 +++++++++++++++++++++++++++++++++++++ > lib/ethdev/sff_8636.h | 590 ++++++++++++++++++++++++++++ > lib/ethdev/sff_common.c | 319 ++++++++++++++++ > lib/ethdev/sff_common.h | 173 +++++++++ > lib/ethdev/sff_telemetry.c | 150 ++++++++ > lib/ethdev/sff_telemetry.h | 27 ++ > 11 files changed, 2713 insertions(+) > create mode 100644 lib/ethdev/sff_8079.c > create mode 100644 lib/ethdev/sff_8472.c > create mode 100644 lib/ethdev/sff_8636.c > create mode 100644 lib/ethdev/sff_8636.h > create mode 100644 lib/ethdev/sff_common.c > create mode 100644 lib/ethdev/sff_common.h > create mode 100644 lib/ethdev/sff_telemetry.c > create mode 100644 lib/ethdev/sff_telemetry.h > Series-acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru> I've updated the patch series a bit to remove unused/undefined functions from the first patch to move corresponding code to subsequent patches. Also I've added release notes. Please, take a look. Applied to dpdk-next-net/main, thanks. ^ permalink raw reply [flat|nested] 77+ messages in thread
end of thread, other threads:[~2022-05-31 14:43 UTC | newest] Thread overview: 77+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-02-15 10:18 [PATCH] app/testpmd: format dump information of module EEPROM Robin Zhang 2022-02-15 13:28 ` Ferruh Yigit 2022-02-15 15:07 ` Thomas Monjalon 2022-02-16 2:26 ` Zhang, RobinX 2022-02-16 8:03 ` David Marchand 2022-02-16 8:45 ` Thomas Monjalon 2022-02-16 9:30 ` Bruce Richardson 2022-02-16 9:41 ` David Marchand 2022-02-16 10:02 ` Bruce Richardson 2022-02-16 10:15 ` David Marchand 2022-04-08 10:23 ` [PATCH v2] common/sff_module: add telemetry command to dump " Robin Zhang 2022-04-08 10:33 ` Bruce Richardson 2022-04-08 10:55 ` Zhang, RobinX 2022-04-08 11:00 ` Bruce Richardson 2022-04-08 11:20 ` Zhang, RobinX 2022-04-08 11:26 ` Bruce Richardson 2022-04-11 8:13 ` Zhang, RobinX 2022-04-11 9:13 ` Bruce Richardson 2022-04-13 12:13 ` Thomas Monjalon 2022-04-14 7:41 ` David Marchand 2022-04-20 7:00 ` [PATCH v3 0/5] add telemetry command for show " Robin Zhang 2022-04-20 7:00 ` [PATCH v3 1/5] ethdev: add telemetry command for " Robin Zhang 2022-04-20 9:16 ` Andrew Rybchenko 2022-04-20 7:00 ` [PATCH v3 2/5] ethdev: common utilities for different SFF specs Robin Zhang 2022-04-20 7:00 ` [PATCH v3 3/5] ethdev: format module EEPROM for SFF-8079 Robin Zhang 2022-04-20 7:00 ` [PATCH v3 4/5] ethdev: format module EEPROM for SFF-8472 Robin Zhang 2022-04-20 7:00 ` [PATCH v3 5/5] ethdev: format module EEPROM for SFF-8636 Robin Zhang 2022-04-20 8:49 ` [PATCH v3 0/5] add telemetry command for show module EEPROM Morten Brørup 2022-04-25 5:34 ` [PATCH v4 " Robin Zhang 2022-04-25 5:34 ` [PATCH v4 1/5] ethdev: add telemetry command for " Robin Zhang 2022-04-25 5:34 ` [PATCH v4 2/5] ethdev: common utilities for different SFF specs Robin Zhang 2022-04-25 5:34 ` [PATCH v4 3/5] ethdev: format module EEPROM for SFF-8079 Robin Zhang 2022-04-25 5:34 ` [PATCH v4 4/5] ethdev: format module EEPROM for SFF-8472 Robin Zhang 2022-04-25 5:34 ` [PATCH v4 5/5] ethdev: format module EEPROM for SFF-8636 Robin Zhang 2022-04-26 2:43 ` [PATCH v5 0/5] add telemetry command for show module EEPROM Robin Zhang 2022-04-26 2:43 ` [PATCH v5 1/5] ethdev: add telemetry command for " Robin Zhang 2022-05-04 10:16 ` Andrew Rybchenko 2022-04-26 2:43 ` [PATCH v5 2/5] ethdev: common utilities for different SFF specs Robin Zhang 2022-04-26 2:43 ` [PATCH v5 3/5] ethdev: format module EEPROM for SFF-8079 Robin Zhang 2022-04-26 2:43 ` [PATCH v5 4/5] ethdev: format module EEPROM for SFF-8472 Robin Zhang 2022-04-26 2:43 ` [PATCH v5 5/5] ethdev: format module EEPROM for SFF-8636 Robin Zhang 2022-05-04 8:13 ` [PATCH v5 0/5] add telemetry command for show module EEPROM Andrew Rybchenko 2022-05-11 2:14 ` [PATCH v6 " Robin Zhang 2022-05-11 2:14 ` [PATCH v6 1/5] ethdev: add telemetry command for " Robin Zhang 2022-05-11 2:14 ` [PATCH v6 2/5] ethdev: common utilities for different SFF specs Robin Zhang 2022-05-11 2:14 ` [PATCH v6 3/5] ethdev: format module EEPROM for SFF-8079 Robin Zhang 2022-05-11 2:14 ` [PATCH v6 4/5] ethdev: format module EEPROM for SFF-8472 Robin Zhang 2022-05-19 8:33 ` Andrew Rybchenko 2022-05-11 2:14 ` [PATCH v6 5/5] ethdev: format module EEPROM for SFF-8636 Robin Zhang 2022-05-24 6:24 ` [PATCH v7 0/5] add telemetry command for show module EEPROM Robin Zhang 2022-05-24 6:24 ` [PATCH v7 1/5] ethdev: add telemetry command for " Robin Zhang 2022-05-24 6:24 ` [PATCH v7 2/5] ethdev: common utilities for different SFF specs Robin Zhang 2022-05-24 6:24 ` [PATCH v7 3/5] ethdev: format module EEPROM for SFF-8079 Robin Zhang 2022-05-24 6:24 ` [PATCH v7 4/5] ethdev: format module EEPROM for SFF-8472 Robin Zhang 2022-05-24 6:24 ` [PATCH v7 5/5] ethdev: format module EEPROM for SFF-8636 Robin Zhang 2022-05-24 9:03 ` David Marchand 2022-05-25 2:43 ` Zhang, RobinX 2022-05-25 3:14 ` [PATCH v8 0/5] add telemetry command for show module EEPROM Robin Zhang 2022-05-25 3:14 ` [PATCH v8 1/5] ethdev: add telemetry command for " Robin Zhang 2022-05-25 9:24 ` Andrew Rybchenko 2022-05-25 3:14 ` [PATCH v8 2/5] ethdev: common utilities for different SFF specs Robin Zhang 2022-05-25 8:51 ` Andrew Rybchenko 2022-05-25 9:40 ` Andrew Rybchenko 2022-05-25 3:14 ` [PATCH v8 3/5] ethdev: format module EEPROM for SFF-8079 Robin Zhang 2022-05-25 9:55 ` Andrew Rybchenko 2022-05-25 3:14 ` [PATCH v8 4/5] ethdev: format module EEPROM for SFF-8472 Robin Zhang 2022-05-25 11:58 ` Andrew Rybchenko 2022-05-25 3:14 ` [PATCH v8 5/5] ethdev: format module EEPROM for SFF-8636 Robin Zhang 2022-05-25 9:01 ` Andrew Rybchenko 2022-05-25 12:01 ` Andrew Rybchenko 2022-05-26 7:32 ` [PATCH v9 0/5] add telemetry command for show module EEPROM Robin Zhang 2022-05-26 7:32 ` [PATCH v9 1/5] ethdev: add telemetry command for " Robin Zhang 2022-05-26 7:32 ` [PATCH v9 2/5] ethdev: add common code for different SFF specs Robin Zhang 2022-05-26 7:32 ` [PATCH v9 3/5] ethdev: support SFF-8079 module information telemetry Robin Zhang 2022-05-26 7:32 ` [PATCH v9 4/5] ethdev: support SFF-8472 " Robin Zhang 2022-05-26 7:32 ` [PATCH v9 5/5] ethdev: support SFF-8636 " Robin Zhang 2022-05-31 14:43 ` [PATCH v9 0/5] add telemetry command for show module EEPROM Andrew Rybchenko
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).