From 2ed34d6cb9935e2f6f8772d94a6311bda0acfe8f Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Fri, 12 Jun 2026 14:24:56 +0800 Subject: [PATCH 1/3] [Accton] Check TX_DISABLE support before access in onlp_sfpi_control_get/set platform: as7926-40xfb as9716_32d as9817-64nb as9817-64 as9926-24 merge from [Accton][as9726-32d] Check TX_DISABLE support before access in onlp_sfpi_control_get/set (#191) 1. Flat-memory CMIS modules (typically passive DACs / simple AOCs) only have lower memory + page 00h. The page select register is silently discarded, so a request for page 01h or 10h actually still reads page 00h vendor info, returning plausible-looking but meaningless bytes. 2. control_get previously did not check the TX Disable Supported advertising bit at all; it walked straight to page 10h and read byte 0x82. control_set checked the advertising bit but missed the flat-memory case. Both paths now: - Read lower-memory byte 0x02 bit 7 (Flat_mem) first. Flat-memory modules return ONLP_STATUS_E_UNSUPPORTED immediately, without touching the page select registers. - For paged modules, check the TX Disable Supported advertising bit on page 01h byte 0x9B bit 1, mirroring the existing set path. - control_get's restore block preserves E_UNSUPPORTED instead of overwriting it with E_INTERNAL. Verified on a real switch via libonlp.onlp_sfp_control_get(): an unsupported / flat-memory module now returns -10 (E_UNSUPPORTED) instead of a stale lane-mask byte. Signed-off-by: Eric Yang --- .../module/src/sfpi.c | 51 ++++++++++-- .../module/src/sfpi.c | 51 ++++++++++-- .../module/src/sfpi.c | 59 ++++++++++++-- .../x86_64_accton_as9817_64/module/src/sfpi.c | 70 +++++++++++++++-- .../module/src/sfpi.c | 77 +++++++++++++++---- 5 files changed, 267 insertions(+), 41 deletions(-) diff --git a/packages/platforms/accton/x86-64/as7926-40xfb/onlp/builds/x86_64_accton_as7926_40xfb/module/src/sfpi.c b/packages/platforms/accton/x86-64/as7926-40xfb/onlp/builds/x86_64_accton_as7926_40xfb/module/src/sfpi.c index 3062f05ad..37f76d12c 100644 --- a/packages/platforms/accton/x86-64/as7926-40xfb/onlp/builds/x86_64_accton_as7926_40xfb/module/src/sfpi.c +++ b/packages/platforms/accton/x86-64/as7926-40xfb/onlp/builds/x86_64_accton_as7926_40xfb/module/src/sfpi.c @@ -99,6 +99,8 @@ static const int port_bus_index[NUM_OF_SFP_PORT] = { #define QSFP_DD_PAGE_ADMIN_INFO 0x0 #define QSFP_DD_PAGE_ADVERTISING 0x1 #define QSFP_DD_PAGE_LANE_CTRL 0x10 +#define QSFP_DD_LOWER_OFFSET_STATUS 0x02 +#define QSFP_DD_FLAT_MEM 0x80 /* byte 0x02 bit 7 */ #define QSFP_DD_P01H_TX_DISABLE_SUPPORT 0x2 #define QSFP_DD_LPMODE 0x10 @@ -260,6 +262,7 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) int present = 0; int lpmode_value = 0; int identifier = 0; + int status_byte = 0; int eeprom_control; VALIDATE_PORT(port); @@ -287,7 +290,16 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) rv = ONLP_STATUS_E_INTERNAL; } else if (identifier == QSFP_DD_IDENTIFIER) { /*QSFP DD*/ - if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADVERTISING) <0 ){ + /* Flat-memory CMIS modules do not implement page 01h/10h */ + if ((status_byte = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_LOWER_OFFSET_STATUS)) < 0) { + AIM_LOG_ERROR("Failed to read Status byte, unable to write tx_disable status to port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else if (status_byte & QSFP_DD_FLAT_MEM) { + AIM_LOG_ERROR("Setting tx_disable to port(%d) is not supported (flat-memory module)\r\n", port); + rv = ONLP_STATUS_E_UNSUPPORTED; + } + else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADVERTISING) <0 ){ AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write page to eeprom fail\r\n", port); rv = ONLP_STATUS_E_INTERNAL; @@ -458,6 +470,8 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) int present = 0; int lpmode_value = 0; int identifier = 0; + int status_byte = 0; + int support_ctrls = 0; int tx_dis = 0; VALIDATE_PORT(port); @@ -503,14 +517,39 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) rv = ONLP_STATUS_E_INTERNAL; } else if (identifier == QSFP_DD_IDENTIFIER) {/* QSFP DD */ - if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0){ + /* Flat-memory CMIS modules do not implement page 01h/10h */ + if ((status_byte = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_LOWER_OFFSET_STATUS)) < 0) { + AIM_LOG_ERROR("Failed to read Status byte, unable to read tx_disable status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else if (status_byte & QSFP_DD_FLAT_MEM) { + AIM_LOG_ERROR("Getting tx_disable from port(%d) is not supported (flat-memory module)\r\n", port); + rv = ONLP_STATUS_E_UNSUPPORTED; + } + else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0){ AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): write bank to eeprom fail\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } - else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0 ){ - AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): write page to eeprom fail\r\n", - port); + else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADVERTISING) < 0){ + AIM_LOG_ERROR("Failed to switch to Advertising Page on port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else if((support_ctrls = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_P01H_OFFSET_CONTROL_1)) < 0){ + AIM_LOG_ERROR("Failed to read Support Control on port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else if (!(support_ctrls & QSFP_DD_P01H_TX_DISABLE_SUPPORT)) { + AIM_LOG_ERROR("Getting tx_disable from port(%d) is not supported\r\n", port); + rv = ONLP_STATUS_E_UNSUPPORTED; + } + else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0){ + AIM_LOG_ERROR("Failed to set Bank 0 on port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0){ + AIM_LOG_ERROR("Failed to switch to Lane Control Page (Page 0x%02x) on port(%d)\r\n", + QSFP_DD_PAGE_LANE_CTRL, port); rv = ONLP_STATUS_E_INTERNAL; } else { @@ -521,7 +560,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) rv = ONLP_STATUS_E_INTERNAL; } else{ - *value = tx_dis; + *value = (tx_dis & 0xff); rv = ONLP_STATUS_OK; } } diff --git a/packages/platforms/accton/x86-64/as9716_32d/onlp/builds/x86_64_accton_as9716_32d/module/src/sfpi.c b/packages/platforms/accton/x86-64/as9716_32d/onlp/builds/x86_64_accton_as9716_32d/module/src/sfpi.c index e1c0736cf..7607512be 100755 --- a/packages/platforms/accton/x86-64/as9716_32d/onlp/builds/x86_64_accton_as9716_32d/module/src/sfpi.c +++ b/packages/platforms/accton/x86-64/as9716_32d/onlp/builds/x86_64_accton_as9716_32d/module/src/sfpi.c @@ -85,6 +85,8 @@ #define QSFP_DD_PAGE_ADMIN_INFO 0x0 #define QSFP_DD_PAGE_ADVERTISING 0x1 #define QSFP_DD_PAGE_LANE_CTRL 0x10 +#define QSFP_DD_LOWER_OFFSET_STATUS 0x02 +#define QSFP_DD_FLAT_MEM 0x80 /* byte 0x02 bit 7 */ #define QSFP_DD_P01H_TX_DISABLE_SUPPORT 0x2 #define QSFP_DD_LPMODE 0x10 @@ -287,6 +289,7 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) int present = 0; int lpmode_value = 0; int identifier = 0; + int status_byte = 0; int eeprom_control; VALIDATE_PORT(port); @@ -324,7 +327,16 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) rv = ONLP_STATUS_E_INTERNAL; } else if (identifier == QSFP_DD_IDENTIFIER) { /*QSFP DD*/ - if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADVERTISING) <0 ){ + /* Flat-memory CMIS modules do not implement page 01h/10h */ + if ((status_byte = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_LOWER_OFFSET_STATUS)) < 0) { + AIM_LOG_ERROR("Failed to read Status byte, unable to write tx_disable status to port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else if (status_byte & QSFP_DD_FLAT_MEM) { + AIM_LOG_ERROR("Setting tx_disable to port(%d) is not supported (flat-memory module)\r\n", port); + rv = ONLP_STATUS_E_UNSUPPORTED; + } + else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADVERTISING) <0 ){ AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write page to eeprom fail\r\n", port); rv = ONLP_STATUS_E_INTERNAL; @@ -482,6 +494,8 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) int present = 0; int lpmode_value = 0; int identifier = 0; + int status_byte = 0; + int support_ctrls = 0; int tx_dis = 0; VALIDATE_PORT(port); @@ -546,14 +560,39 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) rv = ONLP_STATUS_E_INTERNAL; } else if (identifier == QSFP_DD_IDENTIFIER) {/* QSFP DD */ - if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0){ + /* Flat-memory CMIS modules do not implement page 01h/10h */ + if ((status_byte = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_LOWER_OFFSET_STATUS)) < 0) { + AIM_LOG_ERROR("Failed to read Status byte, unable to read tx_disable status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else if (status_byte & QSFP_DD_FLAT_MEM) { + AIM_LOG_ERROR("Getting tx_disable from port(%d) is not supported (flat-memory module)\r\n", port); + rv = ONLP_STATUS_E_UNSUPPORTED; + } + else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0){ AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): write bank to eeprom fail\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } - else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0 ){ - AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): write page to eeprom fail\r\n", - port); + else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADVERTISING) < 0){ + AIM_LOG_ERROR("Failed to switch to Advertising Page on port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else if((support_ctrls = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_P01H_OFFSET_CONTROL_1)) < 0){ + AIM_LOG_ERROR("Failed to read Support Control on port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else if (!(support_ctrls & QSFP_DD_P01H_TX_DISABLE_SUPPORT)) { + AIM_LOG_ERROR("Getting tx_disable from port(%d) is not supported\r\n", port); + rv = ONLP_STATUS_E_UNSUPPORTED; + } + else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0){ + AIM_LOG_ERROR("Failed to set Bank 0 on port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0){ + AIM_LOG_ERROR("Failed to switch to Lane Control Page (Page 0x%02x) on port(%d)\r\n", + QSFP_DD_PAGE_LANE_CTRL, port); rv = ONLP_STATUS_E_INTERNAL; } else { @@ -564,7 +603,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) rv = ONLP_STATUS_E_INTERNAL; } else{ - *value = tx_dis; + *value = (tx_dis & 0xff); rv = ONLP_STATUS_OK; } } diff --git a/packages/platforms/accton/x86-64/as9817-64-nb/src/x86_64_accton_as9817_64_nb/module/src/sfpi.c b/packages/platforms/accton/x86-64/as9817-64-nb/src/x86_64_accton_as9817_64_nb/module/src/sfpi.c index 9da75efe1..6703721e1 100644 --- a/packages/platforms/accton/x86-64/as9817-64-nb/src/x86_64_accton_as9817_64_nb/module/src/sfpi.c +++ b/packages/platforms/accton/x86-64/as9817-64-nb/src/x86_64_accton_as9817_64_nb/module/src/sfpi.c @@ -81,6 +81,8 @@ #define QSFP_DD_PAGE_ADMIN_INFO 0x0 #define QSFP_DD_PAGE_ADVERTISING 0x1 #define QSFP_DD_PAGE_LANE_CTRL 0x10 +#define QSFP_DD_LOWER_OFFSET_STATUS 0x02 +#define QSFP_DD_FLAT_MEM 0x80 /* byte 0x02 bit 7 */ #define QSFP_DD_P01H_TX_DISABLE_SUPPORT 0x2 /* OSFP IDENTIFIER Specific*/ @@ -232,6 +234,7 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) { int present = 0; int identifier = 0; + int status_byte = 0; int eeprom_control; VALIDATE_PORT(port); @@ -257,6 +260,15 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) switch(identifier) { case QSFP_DD_IDENTIFIER: case OSFP_IDENTIFIER: { + /* Flat-memory CMIS modules do not implement page 01h/10h */ + if ((status_byte = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_LOWER_OFFSET_STATUS)) < 0) { + AIM_LOG_ERROR("Failed to read Status byte, unable to write tx_disable status to port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + if (status_byte & QSFP_DD_FLAT_MEM) { + AIM_LOG_ERROR("Setting tx_disable to port(%d) is not supported (flat-memory module)\r\n", port); + return ONLP_STATUS_E_UNSUPPORTED; + } if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADVERTISING) <0 ){ AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write page to eeprom fail\r\n", port); return ONLP_STATUS_E_INTERNAL; @@ -352,6 +364,8 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) { int present = 0; int identifier = 0; + int status_byte = 0; + int support_ctrls = 0; int tx_disable; VALIDATE_PORT(port); @@ -395,23 +409,58 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) switch(identifier) { case QSFP_DD_IDENTIFIER: case OSFP_IDENTIFIER: { + /* Flat-memory CMIS modules do not implement page 01h/10h */ + if ((status_byte = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_LOWER_OFFSET_STATUS)) < 0) { + AIM_LOG_ERROR("Failed to read Status byte, unable to read tx_disable status from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + if (status_byte & QSFP_DD_FLAT_MEM) { + AIM_LOG_ERROR("Getting tx_disable from port(%d) is not supported (flat-memory module)\r\n", port); + return ONLP_STATUS_E_UNSUPPORTED; + } if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0) { AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : write bank to eeprom fail\r\n", port); return ONLP_STATUS_E_INTERNAL; } - if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0) { + if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADVERTISING) < 0) { AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : write page to eeprom fail\r\n", port); + if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADMIN_INFO) <0){ + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : write page to eeprom fail\r\n", port); + } return ONLP_STATUS_E_INTERNAL; } - tx_disable = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_P10H_OFFSET_OUTPUT_DISABLE_TX); - if(tx_disable < 0){ + support_ctrls = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_P01H_OFFSET_CONTROL_1); + if(support_ctrls < 0){ + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : read control from eeprom fail\r\n", port); if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADMIN_INFO) <0){ AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : write page to eeprom fail\r\n", port); } - AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : read TX disable from eeprom fail\r\n", port); return ONLP_STATUS_E_INTERNAL; } - *value = tx_disable; + if (support_ctrls & QSFP_DD_P01H_TX_DISABLE_SUPPORT) { + if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0) { + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : write page to eeprom fail\r\n", port); + if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADMIN_INFO) <0){ + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : write page to eeprom fail\r\n", port); + } + return ONLP_STATUS_E_INTERNAL; + } + tx_disable = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_P10H_OFFSET_OUTPUT_DISABLE_TX); + if(tx_disable < 0){ + if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADMIN_INFO) <0){ + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : write page to eeprom fail\r\n", port); + } + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : read TX disable from eeprom fail\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + *value = tx_disable; + } else { + AIM_LOG_ERROR("Getting tx_disable from port(%d) is not supported\r\n", port); + if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADMIN_INFO) <0){ + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : write page to eeprom fail\r\n", port); + } + return ONLP_STATUS_E_UNSUPPORTED; + } if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADMIN_INFO) <0){ AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : write page to eeprom fail\r\n", port); return ONLP_STATUS_E_INTERNAL; diff --git a/packages/platforms/accton/x86-64/as9817-64/src/x86_64_accton_as9817_64/module/src/sfpi.c b/packages/platforms/accton/x86-64/as9817-64/src/x86_64_accton_as9817_64/module/src/sfpi.c index 034639c6f..769c903ff 100644 --- a/packages/platforms/accton/x86-64/as9817-64/src/x86_64_accton_as9817_64/module/src/sfpi.c +++ b/packages/platforms/accton/x86-64/as9817-64/src/x86_64_accton_as9817_64/module/src/sfpi.c @@ -92,6 +92,8 @@ static const int port_bus_index[NUM_OF_SFP_PORT] = { #define QSFP_DD_PAGE_ADMIN_INFO 0x0 #define QSFP_DD_PAGE_ADVERTISING 0x1 #define QSFP_DD_PAGE_LANE_CTRL 0x10 +#define QSFP_DD_LOWER_OFFSET_STATUS 0x02 +#define QSFP_DD_FLAT_MEM 0x80 /* byte 0x02 bit 7 */ #define QSFP_DD_P01H_TX_DISABLE_SUPPORT 0x2 @@ -234,6 +236,7 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) { int present = 0; int identifier = 0; + int status_byte = 0; int eeprom_control; VALIDATE_PORT(port); @@ -260,6 +263,15 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) switch(identifier) { case QSFP_DD_IDENTIFIER: //for as9817-64D case OSFP_IDENTIFIER: { //for as9817-64O + /* Flat-memory CMIS modules do not implement page 01h/10h */ + if ((status_byte = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_LOWER_OFFSET_STATUS)) < 0) { + AIM_LOG_ERROR("Failed to read Status byte, unable to write tx_disable status to port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + if (status_byte & QSFP_DD_FLAT_MEM) { + AIM_LOG_ERROR("Setting tx_disable to port(%d) is not supported (flat-memory module)\r\n", port); + return ONLP_STATUS_E_UNSUPPORTED; + } if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADVERTISING) <0 ){ AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write page to eeprom fail\r\n", port); @@ -379,6 +391,8 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) { int present = 0; int identifier = 0; + int status_byte = 0; + int support_ctrls = 0; int tx_disable; VALIDATE_PORT(port); @@ -430,31 +444,71 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) switch(identifier) { case QSFP_DD_IDENTIFIER: //for as9817-64D case OSFP_IDENTIFIER: { //for as9817-64O + /* Flat-memory CMIS modules do not implement page 01h/10h */ + if ((status_byte = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_LOWER_OFFSET_STATUS)) < 0) { + AIM_LOG_ERROR("Failed to read Status byte, unable to read tx_disable status from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + if (status_byte & QSFP_DD_FLAT_MEM) { + AIM_LOG_ERROR("Getting tx_disable from port(%d) is not supported (flat-memory module)\r\n", port); + return ONLP_STATUS_E_UNSUPPORTED; + } if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0) { AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : write bank to eeprom fail\r\n", port); return ONLP_STATUS_E_INTERNAL; } - - if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0) { + if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADVERTISING) < 0) { AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : write page to eeprom fail\r\n", port); + if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADMIN_INFO) <0){ + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : write page to eeprom fail\r\n", + port); + } return ONLP_STATUS_E_INTERNAL; } - - tx_disable = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_P10H_OFFSET_OUTPUT_DISABLE_TX); - if(tx_disable < 0){ + support_ctrls = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_P01H_OFFSET_CONTROL_1); + if(support_ctrls < 0){ + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : read control from eeprom fail\r\n", + port); if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADMIN_INFO) <0){ AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : write page to eeprom fail\r\n", port); } - AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : read TX disable from eeprom fail\r\n", - port); return ONLP_STATUS_E_INTERNAL; } - *value = tx_disable; + if (support_ctrls & QSFP_DD_P01H_TX_DISABLE_SUPPORT) { + if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0) { + + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : write page to eeprom fail\r\n", + port); + if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADMIN_INFO) <0){ + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : write page to eeprom fail\r\n", + port); + } + return ONLP_STATUS_E_INTERNAL; + } + tx_disable = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_P10H_OFFSET_OUTPUT_DISABLE_TX); + if(tx_disable < 0){ + if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADMIN_INFO) <0){ + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : write page to eeprom fail\r\n", + port); + } + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : read TX disable from eeprom fail\r\n", + port); + return ONLP_STATUS_E_INTERNAL; + } + *value = tx_disable; + } else { + AIM_LOG_ERROR("Getting tx_disable from port(%d) is not supported\r\n", port); + if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADMIN_INFO) <0){ + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : write page to eeprom fail\r\n", + port); + } + return ONLP_STATUS_E_UNSUPPORTED; + } if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADMIN_INFO) <0){ AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : write page to eeprom fail\r\n", port); diff --git a/packages/platforms/accton/x86-64/as9926-24d/onlp/builds/x86_64_accton_as9926_24d/module/src/sfpi.c b/packages/platforms/accton/x86-64/as9926-24d/onlp/builds/x86_64_accton_as9926_24d/module/src/sfpi.c index dca56b114..9408ba934 100644 --- a/packages/platforms/accton/x86-64/as9926-24d/onlp/builds/x86_64_accton_as9926_24d/module/src/sfpi.c +++ b/packages/platforms/accton/x86-64/as9926-24d/onlp/builds/x86_64_accton_as9926_24d/module/src/sfpi.c @@ -89,6 +89,8 @@ #define QSFP_DD_PAGE_ADMIN_INFO 0x0 #define QSFP_DD_PAGE_ADVERTISING 0x1 #define QSFP_DD_PAGE_LANE_CTRL 0x10 +#define QSFP_DD_LOWER_OFFSET_STATUS 0x02 +#define QSFP_DD_FLAT_MEM 0x80 /* byte 0x02 bit 7 */ #define QSFP_DD_P01H_TX_DISABLE_SUPPORT 0x2 #define QSFP_DD_LPMODE 0x10 @@ -323,6 +325,7 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) int present = 0; int lpmode_value = 0; int identifier = 0; + int status_byte = 0; int eeprom_control; VALIDATE_PORT(port); @@ -353,7 +356,18 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) rv = ONLP_STATUS_E_INTERNAL; } else if (identifier == QSFP_DD_IDENTIFIER) { /*QSFP DD*/ - if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADVERTISING) <0 ){ + /* Flat-memory CMIS modules do not implement page 01h/10h */ + status_byte = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_LOWER_OFFSET_STATUS); + if (status_byte < 0) { + AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): read status byte from eeprom fail\r\n", + port); + rv = ONLP_STATUS_E_INTERNAL; + } + else if (status_byte & QSFP_DD_FLAT_MEM) { + AIM_LOG_ERROR("Setting tx_disable to port(%d) is not supported (flat-memory module)\r\n", port); + rv = ONLP_STATUS_E_UNSUPPORTED; + } + else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADVERTISING) <0 ){ AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write page to eeprom fail\r\n", port); rv = ONLP_STATUS_E_INTERNAL; @@ -515,6 +529,8 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) int present = 0; int lpmode_value = 0; int identifier = 0; + int status_byte = 0; + int support_ctrls = 0; int tx_dis = 0; VALIDATE_PORT(port); @@ -570,32 +586,61 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) rv = ONLP_STATUS_E_INTERNAL; } else if (identifier == QSFP_DD_IDENTIFIER) {/* QSFP DD */ - if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0){ - AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): write bank to eeprom fail\r\n", + /* Flat-memory CMIS modules do not implement page 01h/10h */ + status_byte = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_LOWER_OFFSET_STATUS); + if (status_byte < 0) { + AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): read status byte from eeprom fail\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } - else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0 ){ - AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): write page to eeprom fail\r\n", + else if (status_byte & QSFP_DD_FLAT_MEM) { + AIM_LOG_ERROR("Getting tx_disable from port(%d) is not supported (flat-memory module)\r\n", port); + rv = ONLP_STATUS_E_UNSUPPORTED; + } + else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADVERTISING) < 0){ + AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): write page to eeprom fail\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } else { - tx_dis = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_P10H_OFFSET_OUTPUT_DISABLE_TX); - if(tx_dis < 0){ - AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): read TX disable from eeprom fail\r\n", + support_ctrls = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_P01H_OFFSET_CONTROL_1); + if (support_ctrls < 0) { + AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): read support control from eeprom fail\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } - else{ - *value = tx_dis; - rv = ONLP_STATUS_OK; + else if (support_ctrls & QSFP_DD_P01H_TX_DISABLE_SUPPORT) { + if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0){ + AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): write bank to eeprom fail\r\n", + port); + rv = ONLP_STATUS_E_INTERNAL; + } + else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0 ){ + AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): write page to eeprom fail\r\n", + port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + tx_dis = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_P10H_OFFSET_OUTPUT_DISABLE_TX); + if(tx_dis < 0){ + AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): read TX disable from eeprom fail\r\n", + port); + rv = ONLP_STATUS_E_INTERNAL; + } + else{ + *value = tx_dis; + rv = ONLP_STATUS_OK; + } + } + } else { + AIM_LOG_ERROR("Getting tx_disable from port(%d) is not supported\r\n", port); + rv = ONLP_STATUS_E_UNSUPPORTED; + } + if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADMIN_INFO) < 0){ + AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): write page to eeprom fail\r\n", + port); + rv = ONLP_STATUS_E_INTERNAL; } - } - if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADMIN_INFO) < 0){ - AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): write page to eeprom fail\r\n", - port); - rv = ONLP_STATUS_E_INTERNAL; } } else { /* QSFP 28 or QSFP+ */ From bf788fc9cd76cccf016a7d0df0410d605d08faab Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Mon, 15 Jun 2026 06:08:03 +0000 Subject: [PATCH 2/3] [Accton] remove redundant CMIS bank setting in control_get/set platform: as7926-40xfb as9716_32d as9817-64nb as9817-64 as9926-24 --- .../module/src/sfpi.c | 16 +++++-------- .../module/src/sfpi.c | 16 +++++-------- .../module/src/sfpi.c | 11 ++++----- .../x86_64_accton_as9817_64/module/src/sfpi.c | 16 ++++--------- .../module/src/sfpi.c | 24 +++++++++---------- 5 files changed, 33 insertions(+), 50 deletions(-) diff --git a/packages/platforms/accton/x86-64/as7926-40xfb/onlp/builds/x86_64_accton_as7926_40xfb/module/src/sfpi.c b/packages/platforms/accton/x86-64/as7926-40xfb/onlp/builds/x86_64_accton_as7926_40xfb/module/src/sfpi.c index 37f76d12c..8ff70af72 100644 --- a/packages/platforms/accton/x86-64/as7926-40xfb/onlp/builds/x86_64_accton_as7926_40xfb/module/src/sfpi.c +++ b/packages/platforms/accton/x86-64/as7926-40xfb/onlp/builds/x86_64_accton_as7926_40xfb/module/src/sfpi.c @@ -299,6 +299,11 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) AIM_LOG_ERROR("Setting tx_disable to port(%d) is not supported (flat-memory module)\r\n", port); rv = ONLP_STATUS_E_UNSUPPORTED; } + else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0){ + AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write bank to eeprom fail\r\n", + port); + rv = ONLP_STATUS_E_INTERNAL; + } else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADVERTISING) <0 ){ AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write page to eeprom fail\r\n", port); @@ -312,12 +317,7 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) rv = ONLP_STATUS_E_INTERNAL; } else if (eeprom_control & QSFP_DD_P01H_TX_DISABLE_SUPPORT){ - if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0) { - AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write bank to eeprom fail\r\n", - port); - rv = ONLP_STATUS_E_INTERNAL; - } - else if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0) { + if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0) { AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write page to eeprom fail\r\n", port); rv = ONLP_STATUS_E_INTERNAL; @@ -543,10 +543,6 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) AIM_LOG_ERROR("Getting tx_disable from port(%d) is not supported\r\n", port); rv = ONLP_STATUS_E_UNSUPPORTED; } - else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0){ - AIM_LOG_ERROR("Failed to set Bank 0 on port(%d)\r\n", port); - rv = ONLP_STATUS_E_INTERNAL; - } else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0){ AIM_LOG_ERROR("Failed to switch to Lane Control Page (Page 0x%02x) on port(%d)\r\n", QSFP_DD_PAGE_LANE_CTRL, port); diff --git a/packages/platforms/accton/x86-64/as9716_32d/onlp/builds/x86_64_accton_as9716_32d/module/src/sfpi.c b/packages/platforms/accton/x86-64/as9716_32d/onlp/builds/x86_64_accton_as9716_32d/module/src/sfpi.c index 7607512be..35a6e7989 100755 --- a/packages/platforms/accton/x86-64/as9716_32d/onlp/builds/x86_64_accton_as9716_32d/module/src/sfpi.c +++ b/packages/platforms/accton/x86-64/as9716_32d/onlp/builds/x86_64_accton_as9716_32d/module/src/sfpi.c @@ -336,6 +336,11 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) AIM_LOG_ERROR("Setting tx_disable to port(%d) is not supported (flat-memory module)\r\n", port); rv = ONLP_STATUS_E_UNSUPPORTED; } + else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0){ + AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write bank to eeprom fail\r\n", + port); + rv = ONLP_STATUS_E_INTERNAL; + } else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADVERTISING) <0 ){ AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write page to eeprom fail\r\n", port); @@ -349,12 +354,7 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) rv = ONLP_STATUS_E_INTERNAL; } else if (eeprom_control & QSFP_DD_P01H_TX_DISABLE_SUPPORT){ - if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0) { - AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write bank to eeprom fail\r\n", - port); - rv = ONLP_STATUS_E_INTERNAL; - } - else if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0) { + if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0) { AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write page to eeprom fail\r\n", port); rv = ONLP_STATUS_E_INTERNAL; @@ -586,10 +586,6 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) AIM_LOG_ERROR("Getting tx_disable from port(%d) is not supported\r\n", port); rv = ONLP_STATUS_E_UNSUPPORTED; } - else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0){ - AIM_LOG_ERROR("Failed to set Bank 0 on port(%d)\r\n", port); - rv = ONLP_STATUS_E_INTERNAL; - } else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0){ AIM_LOG_ERROR("Failed to switch to Lane Control Page (Page 0x%02x) on port(%d)\r\n", QSFP_DD_PAGE_LANE_CTRL, port); diff --git a/packages/platforms/accton/x86-64/as9817-64-nb/src/x86_64_accton_as9817_64_nb/module/src/sfpi.c b/packages/platforms/accton/x86-64/as9817-64-nb/src/x86_64_accton_as9817_64_nb/module/src/sfpi.c index 6703721e1..50e404174 100644 --- a/packages/platforms/accton/x86-64/as9817-64-nb/src/x86_64_accton_as9817_64_nb/module/src/sfpi.c +++ b/packages/platforms/accton/x86-64/as9817-64-nb/src/x86_64_accton_as9817_64_nb/module/src/sfpi.c @@ -269,6 +269,10 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) AIM_LOG_ERROR("Setting tx_disable to port(%d) is not supported (flat-memory module)\r\n", port); return ONLP_STATUS_E_UNSUPPORTED; } + if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0){ + AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write bank to eeprom fail\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADVERTISING) <0 ){ AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write page to eeprom fail\r\n", port); return ONLP_STATUS_E_INTERNAL; @@ -282,13 +286,6 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) return ONLP_STATUS_E_INTERNAL; } if (eeprom_control & QSFP_DD_P01H_TX_DISABLE_SUPPORT){ - if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0) { - AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write bank to eeprom fail\r\n", port); - if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADMIN_INFO) < 0) { - AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write page to eeprom fail\r\n", port); - } - return ONLP_STATUS_E_INTERNAL; - } if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0) { AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write page to eeprom fail\r\n", port); if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADMIN_INFO) < 0) { diff --git a/packages/platforms/accton/x86-64/as9817-64/src/x86_64_accton_as9817_64/module/src/sfpi.c b/packages/platforms/accton/x86-64/as9817-64/src/x86_64_accton_as9817_64/module/src/sfpi.c index 769c903ff..43555d76a 100644 --- a/packages/platforms/accton/x86-64/as9817-64/src/x86_64_accton_as9817_64/module/src/sfpi.c +++ b/packages/platforms/accton/x86-64/as9817-64/src/x86_64_accton_as9817_64/module/src/sfpi.c @@ -272,6 +272,11 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) AIM_LOG_ERROR("Setting tx_disable to port(%d) is not supported (flat-memory module)\r\n", port); return ONLP_STATUS_E_UNSUPPORTED; } + if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0){ + AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write bank to eeprom fail\r\n", + port); + return ONLP_STATUS_E_INTERNAL; + } if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADVERTISING) <0 ){ AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write page to eeprom fail\r\n", port); @@ -290,17 +295,6 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) } if (eeprom_control & QSFP_DD_P01H_TX_DISABLE_SUPPORT){ - if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0) { - - AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write bank to eeprom fail\r\n", port); - - if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADMIN_INFO) < 0) { - AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write page to eeprom fail\r\n", port); - } - - return ONLP_STATUS_E_INTERNAL; - } - if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0) { AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write page to eeprom fail\r\n", port); diff --git a/packages/platforms/accton/x86-64/as9926-24d/onlp/builds/x86_64_accton_as9926_24d/module/src/sfpi.c b/packages/platforms/accton/x86-64/as9926-24d/onlp/builds/x86_64_accton_as9926_24d/module/src/sfpi.c index 9408ba934..9ad54fbbd 100644 --- a/packages/platforms/accton/x86-64/as9926-24d/onlp/builds/x86_64_accton_as9926_24d/module/src/sfpi.c +++ b/packages/platforms/accton/x86-64/as9926-24d/onlp/builds/x86_64_accton_as9926_24d/module/src/sfpi.c @@ -367,6 +367,11 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) AIM_LOG_ERROR("Setting tx_disable to port(%d) is not supported (flat-memory module)\r\n", port); rv = ONLP_STATUS_E_UNSUPPORTED; } + else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0){ + AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write bank to eeprom fail\r\n", + port); + rv = ONLP_STATUS_E_INTERNAL; + } else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADVERTISING) <0 ){ AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write page to eeprom fail\r\n", port); @@ -380,12 +385,7 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) rv = ONLP_STATUS_E_INTERNAL; } else if (eeprom_control & QSFP_DD_P01H_TX_DISABLE_SUPPORT){ - if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0) { - AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write bank to eeprom fail\r\n", - port); - rv = ONLP_STATUS_E_INTERNAL; - } - else if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0) { + if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0) { AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write page to eeprom fail\r\n", port); rv = ONLP_STATUS_E_INTERNAL; @@ -597,6 +597,11 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) AIM_LOG_ERROR("Getting tx_disable from port(%d) is not supported (flat-memory module)\r\n", port); rv = ONLP_STATUS_E_UNSUPPORTED; } + else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0){ + AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): write bank to eeprom fail\r\n", + port); + rv = ONLP_STATUS_E_INTERNAL; + } else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADVERTISING) < 0){ AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): write page to eeprom fail\r\n", port); @@ -610,12 +615,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) rv = ONLP_STATUS_E_INTERNAL; } else if (support_ctrls & QSFP_DD_P01H_TX_DISABLE_SUPPORT) { - if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0){ - AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): write bank to eeprom fail\r\n", - port); - rv = ONLP_STATUS_E_INTERNAL; - } - else if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0 ){ + if(onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0 ){ AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): write page to eeprom fail\r\n", port); rv = ONLP_STATUS_E_INTERNAL; From b68ee0ca524b2d69ccc674c04649fafc201ef4da Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Mon, 15 Jun 2026 07:29:02 +0000 Subject: [PATCH 3/3] [Accton]Add SFP functionality (LP mode, reset, TX disable) platform: as9926-24db Signed-off-by: Eric Yang --- .../module/src/sfpi.c | 392 +++++++++++++++--- 1 file changed, 341 insertions(+), 51 deletions(-) diff --git a/packages/platforms/accton/x86-64/as9926-24db/onlp/builds/x86_64_accton_as9926_24db/module/src/sfpi.c b/packages/platforms/accton/x86-64/as9926-24db/onlp/builds/x86_64_accton_as9926_24db/module/src/sfpi.c index 54e81348b..b2a58500d 100644 --- a/packages/platforms/accton/x86-64/as9926-24db/onlp/builds/x86_64_accton_as9926_24db/module/src/sfpi.c +++ b/packages/platforms/accton/x86-64/as9926-24db/onlp/builds/x86_64_accton_as9926_24db/module/src/sfpi.c @@ -31,6 +31,63 @@ #define PORT_BUS_INDEX(port) (port+9) +#define SFP_PORT_MIN 24 +#define SFP_PORT_MAX 25 +#define QSFP_PORT_MIN 0 +#define QSFP_PORT_MAX 23 +#define MIN_PORT QSFP_PORT_MIN +#define MAX_PORT SFP_PORT_MAX + +#define VALIDATE_SFP(_port) \ + do { \ + if (_port < SFP_PORT_MIN || _port > SFP_PORT_MAX) \ + return ONLP_STATUS_E_UNSUPPORTED; \ + } while(0) + +#define VALIDATE_QSFP(_port) \ + do { \ + if (_port < QSFP_PORT_MIN || _port > QSFP_PORT_MAX) \ + return ONLP_STATUS_E_UNSUPPORTED; \ + } while(0) + +#define VALIDATE_PORT(_port) \ + do { \ + if (_port < MIN_PORT || _port > MAX_PORT) \ + return ONLP_STATUS_E_UNSUPPORTED; \ + } while(0) + +/* QSFP device address of eeprom */ +#define PORT_EEPROM_DEVADDR 0x50 + +/*QSFP identify offsets*/ +#define QSFP_EEPROM_OFFSET_IDENTIFIER 0x0 + +/* QSFP eeprom offsets*/ +#define QSFP_EEPROM_OFFSET_TXDIS 0x56 + +/* QSFP DD eeprom offsets*/ +#define QSFP_DD_EEPROM_OFFSET_BANK_SELECT 0x7E +#define QSFP_DD_EEPROM_OFFSET_PAGE_SELECT 0x7F +#define QSFP_DD_EEPROM_P01H_OFFSET_CONTROL_1 0x9B +#define QSFP_DD_EEPROM_P10H_OFFSET_OUTPUT_DISABLE_TX 0x82 +#define QSFP_DD_EEPROM_OFFSET_LOWPWR_REQUEST_SW 0x1A + +/*QSFP Specific*/ +#define QSFP_EEPROM_OFFSET_LPMODE 0x5D +#define QSFP_LPMODE 0x3 + +/* QSFP DD Specific*/ +#define QSFP_DD_PAGE_ADMIN_INFO 0x0 +#define QSFP_DD_PAGE_ADVERTISING 0x1 +#define QSFP_DD_PAGE_LANE_CTRL 0x10 +#define QSFP_DD_LOWER_OFFSET_STATUS 0x02 +#define QSFP_DD_FLAT_MEM 0x80 /* byte 0x02 bit 7 */ +#define QSFP_DD_P01H_TX_DISABLE_SUPPORT 0x2 +#define QSFP_DD_LPMODE 0x10 + +/* OSFP IDENTIFIER Specific*/ +#define QSFP_DD_IDENTIFIER 0x18 + #define PORT_EEPROM_FORMAT \ "/sys/bus/i2c/devices/%d-0050/eeprom" #define MODULE_PRESENT_FORMAT \ @@ -258,16 +315,108 @@ int onlp_sfpi_dom_read(int port, uint8_t data[256]) int onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) { - int rv; + int rv = ONLP_STATUS_E_INTERNAL; + int present = 0; + int lpmode_value = 0; + int identifier = 0; + int status_byte = 0; + int eeprom_control; + + VALIDATE_PORT(port); switch(control) { case ONLP_SFP_CONTROL_TX_DISABLE: + case ONLP_SFP_CONTROL_TX_DISABLE_CHANNEL: + { + present = onlp_sfpi_is_present(port); + if (present == 1) { + if (port >= SFP_PORT_MIN && port <= SFP_PORT_MAX) { /* SFP */ + if (onlp_file_write_int(value, MODULE_TXDISABLE_FORMAT, + (port+1)) < 0) { + AIM_LOG_ERROR("Unable to write tx_disable status to port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + } + else { /* QSFP */ + identifier = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_EEPROM_OFFSET_IDENTIFIER); + if (identifier < 0) { + AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): read identifier from eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else if (identifier == QSFP_DD_IDENTIFIER) { /* QSFP DD */ + /* Flat-memory CMIS modules do not implement page 01h/10h */ + status_byte = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_LOWER_OFFSET_STATUS); + if (status_byte < 0) { + AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): read status byte from eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else if (status_byte & QSFP_DD_FLAT_MEM) { + AIM_LOG_ERROR("Setting tx_disable to port(%d) is not supported (flat-memory module)\r\n", port); + rv = ONLP_STATUS_E_UNSUPPORTED; + } + else if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0) { + AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write bank to eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADVERTISING) < 0) { + AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write page to eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + eeprom_control = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_P01H_OFFSET_CONTROL_1); + if (eeprom_control < 0) { + AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): read control from eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else if (eeprom_control & QSFP_DD_P01H_TX_DISABLE_SUPPORT) { + if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0) { + AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write page to eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_P10H_OFFSET_OUTPUT_DISABLE_TX, value) < 0) { + AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write TX disable to eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + } else { + AIM_LOG_ERROR("Setting tx disable to port(%d) is not supported\r\n", port); + rv = ONLP_STATUS_E_UNSUPPORTED; + } + if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADMIN_INFO) < 0) { + AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write page to eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + } + } else { /* QSFP 28 or QSFP+ */ + value = value & 0xf; + if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_EEPROM_OFFSET_TXDIS, value) < 0) { + AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write TX disable to eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + } + } + } + else { + rv = ONLP_STATUS_E_INTERNAL; + } + break; + } + + case ONLP_SFP_CONTROL_RESET: { - if (onlp_file_write_int(value, MODULE_TXDISABLE_FORMAT, + VALIDATE_QSFP(port); + if (onlp_file_write_int(value, MODULE_RESET_FORMAT, (port+1)) < 0) { - AIM_LOG_ERROR("Unable to set tx_disable status to \ - port(%d)\r\n", port); + AIM_LOG_ERROR("Unable to set reset to port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } else { @@ -276,22 +425,58 @@ int onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) break; } - case ONLP_SFP_CONTROL_RESET: + case ONLP_SFP_CONTROL_LP_MODE: { - if(port <= 23) - { - if (onlp_file_write_int(value, MODULE_RESET_FORMAT, - (port+1)) < 0) { - AIM_LOG_ERROR("Unable to set reset to \ - port(%d)\r\n", port); + VALIDATE_QSFP(port); + present = onlp_sfpi_is_present(port); + if (present == 1) { + identifier = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_EEPROM_OFFSET_IDENTIFIER); + if (identifier < 0) { + AIM_LOG_ERROR("Unable to write LP mode status to port(%d): read identifier from eeprom fail\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } - else { - rv = ONLP_STATUS_OK; + else if (identifier == QSFP_DD_IDENTIFIER) { /* QSFP DD */ + lpmode_value = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_LOWPWR_REQUEST_SW); + if (lpmode_value < 0) { + AIM_LOG_ERROR("Unable to write LP mode status to port(%d): read LP mode value from eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + if (value) + lpmode_value |= QSFP_DD_LPMODE; + else + lpmode_value &= ~QSFP_DD_LPMODE; + if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_LOWPWR_REQUEST_SW, lpmode_value) < 0) { + AIM_LOG_ERROR("Unable to write LP mode status to port(%d): write LP mode value to eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + } + } else { /* QSFP 28 or QSFP+ */ + lpmode_value = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_EEPROM_OFFSET_LPMODE); + if (lpmode_value < 0) { + AIM_LOG_ERROR("Unable to write LP mode status to port(%d): read LP mode value from eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + if (value) + lpmode_value |= QSFP_LPMODE; + else + lpmode_value &= ~QSFP_LPMODE; + if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_EEPROM_OFFSET_LPMODE, lpmode_value) < 0) { + AIM_LOG_ERROR("Unable to write LP mode status to port(%d): write LP mode value to eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + } } } else { - return ONLP_STATUS_E_UNSUPPORTED; + rv = ONLP_STATUS_E_INTERNAL; } break; } @@ -332,43 +517,37 @@ onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value) int onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) { - int rv; + int rv = ONLP_STATUS_E_INTERNAL; + int present = 0; + int lpmode_value = 0; + int identifier = 0; + int status_byte = 0; + int support_ctrls = 0; + int tx_dis = 0; - if (port < 0) { - return ONLP_STATUS_E_UNSUPPORTED; - } + VALIDATE_PORT(port); switch(control) { case ONLP_SFP_CONTROL_RESET: { - if(port <= 23) - { - if(onlp_file_read_int(value, MODULE_RESET_FORMAT, - (port+1)) < 0) { - AIM_LOG_ERROR("Unable to read reset status \ - from port(%d)\r\n", port); - rv = ONLP_STATUS_E_INTERNAL; - } - else { - rv = ONLP_STATUS_OK; - } + VALIDATE_QSFP(port); + if (onlp_file_read_int(value, MODULE_RESET_FORMAT, + (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read reset status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; } else { - return ONLP_STATUS_E_UNSUPPORTED; + rv = ONLP_STATUS_OK; } break; - } case ONLP_SFP_CONTROL_RX_LOS: { - if (port <= 23) - return ONLP_STATUS_E_UNSUPPORTED; - - if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, + VALIDATE_SFP(port); + if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, (port+1)) < 0) { - AIM_LOG_ERROR("Unable to read rx_loss status \ - from port(%d)\r\n", port); + AIM_LOG_ERROR("Unable to read rx_loss status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } else { @@ -379,13 +558,10 @@ int onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) case ONLP_SFP_CONTROL_TX_FAULT: { - if (port <= 23) - return ONLP_STATUS_E_UNSUPPORTED; - + VALIDATE_SFP(port); if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, (port+1)) < 0) { - AIM_LOG_ERROR("Unable to read tx_fault status \ - from port(%d)\r\n", port); + AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } else { @@ -395,25 +571,139 @@ int onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) } case ONLP_SFP_CONTROL_TX_DISABLE: + case ONLP_SFP_CONTROL_TX_DISABLE_CHANNEL: { - if(port <= 23) - return ONLP_STATUS_E_UNSUPPORTED; - - if (onlp_file_read_int(value, MODULE_TXDISABLE_FORMAT, - (port+1)) < 0) { - AIM_LOG_ERROR("Unable to read tx_disabled status \ - from port(%d)\r\n", port); + present = onlp_sfpi_is_present(port); + if (present == 1) { + if (port >= SFP_PORT_MIN && port <= SFP_PORT_MAX) { /* SFP */ + if (onlp_file_read_int(value, MODULE_TXDISABLE_FORMAT, + (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + } + else { /* QSFP */ + identifier = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_EEPROM_OFFSET_IDENTIFIER); + if (identifier < 0) { + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d): read identifier from eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else if (identifier == QSFP_DD_IDENTIFIER) { /* QSFP DD */ + /* Flat-memory CMIS modules do not implement page 01h/10h */ + status_byte = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_LOWER_OFFSET_STATUS); + if (status_byte < 0) { + AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): read status byte from eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else if (status_byte & QSFP_DD_FLAT_MEM) { + AIM_LOG_ERROR("Getting tx_disable from port(%d) is not supported (flat-memory module)\r\n", port); + rv = ONLP_STATUS_E_UNSUPPORTED; + } + else if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_BANK_SELECT, 0) < 0) { + AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): write bank to eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADVERTISING) < 0) { + AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): write page to eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + support_ctrls = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_P01H_OFFSET_CONTROL_1); + if (support_ctrls < 0) { + AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): read support control from eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else if (support_ctrls & QSFP_DD_P01H_TX_DISABLE_SUPPORT) { + if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_LANE_CTRL) < 0) { + AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): write page to eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + tx_dis = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_P10H_OFFSET_OUTPUT_DISABLE_TX); + if (tx_dis < 0) { + AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): read TX disable from eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + *value = tx_dis; + rv = ONLP_STATUS_OK; + } + } + } else { + AIM_LOG_ERROR("Getting tx_disable from port(%d) is not supported\r\n", port); + rv = ONLP_STATUS_E_UNSUPPORTED; + } + if (onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_PAGE_SELECT, QSFP_DD_PAGE_ADMIN_INFO) < 0) { + AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): write page to eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + } + } + else { /* QSFP 28 or QSFP+ */ + tx_dis = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_EEPROM_OFFSET_TXDIS); + if (tx_dis < 0) { + AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): read TX disable from eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + *value = tx_dis; + rv = ONLP_STATUS_OK; + } + } + } + } + else { rv = ONLP_STATUS_E_INTERNAL; } + break; + } + + case ONLP_SFP_CONTROL_LP_MODE: + { + VALIDATE_QSFP(port); + present = onlp_sfpi_is_present(port); + if (present == 1) { + identifier = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_EEPROM_OFFSET_IDENTIFIER); + if (identifier < 0) { + AIM_LOG_ERROR("Unable to read LP mode status from port(%d): read identifier from eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else if (identifier == QSFP_DD_IDENTIFIER) { /* QSFP DD */ + /* lpmode valid bit(bit4): Low power request sw */ + lpmode_value = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_DD_EEPROM_OFFSET_LOWPWR_REQUEST_SW); + if (lpmode_value < 0) { + AIM_LOG_ERROR("Unable to read LP mode status from port(%d): read LP mode value from eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + *value = !!(lpmode_value & QSFP_DD_LPMODE); + rv = ONLP_STATUS_OK; + } + } else { /* QSFP 28 or QSFP+ */ + /* lpmode valid bit(bit0):set LP/txdis mode bit(bit1):set low/high power mode */ + lpmode_value = onlp_sfpi_dev_readb(port, PORT_EEPROM_DEVADDR, QSFP_EEPROM_OFFSET_LPMODE); + if (lpmode_value < 0) { + AIM_LOG_ERROR("Unable to read LP mode status from port(%d): read LP mode value from eeprom fail\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + *value = ((lpmode_value & QSFP_LPMODE) == QSFP_LPMODE); + rv = ONLP_STATUS_OK; + } + } + } else { - rv = ONLP_STATUS_OK; + rv = ONLP_STATUS_E_INTERNAL; } break; } default: rv = ONLP_STATUS_E_UNSUPPORTED; - } + } return rv; }