[Accton] Check TX_DISABLE support before access in onlp_sfpi_control_…#194
[Accton] Check TX_DISABLE support before access in onlp_sfpi_control_…#194eric271110 wants to merge 6 commits into
Conversation
087b196 to
08284d2
Compare
…get/set platform: as7535_28xb as7926-40xfb as7946-30xb as7946-74xkb as9716_32d as9736_64d as9737-32db as9817-64nb as9817-64 as9926-24 merge from [Accton][as9726-32d] Check TX_DISABLE support before access in onlp_sfpi_control_get/set (accton#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 <eric_yang@accton.com>
platform: as7535_28xb as7926-40xfb as7946-30xb as7946-74xkb as9716_32d as9736_64d as9737-32db as9817-64nb as9817-64 as9726-32d as9926-24 Signed-off-by: Eric Yang <eric_yang@accton.com>
platform: as9926-24db Signed-off-by: Eric Yang <eric_yang@accton.com>
Page 01h (Advertising) is unbanked, so writing the bank-select register before switching to it has no effect. Page 10h (Lane Control) is banked, so the bank-select must be set before switching to it. Move the QSFP_DD_EEPROM_OFFSET_BANK_SELECT write into the TX_DISABLE-supported branch, immediately before the page-select to QSFP_DD_PAGE_LANE_CTRL, in both the set and get paths. platform: as7535-28xb as7926-40xfb as7946-30xb as7946-74xkb as9716_32d as9726-32d as9736-64d as9737-32db as9817-64 as9817-64-nb as9926-24d as9926-24db Signed-off-by: Eric Yang <eric_yang@accton.com>
b1fd057 to
1756289
Compare
…sary error logs merge from [Accton][as9726-32d] Route SFP errors to syslog, drop unsupported-state logs accton#197 platform: as7535-28xb as7926-40xfb as7946-30xb as7946-74xkb as9716_32d as9736-64d as9737-32db as9817-64-nb as9817-64 as9926-24d as9926-24db Changes: - Replace AIM_LOG_ERROR with syslog(LOG_ERR, ...) for consistent logging - Remove flat-memory module unsupported log messages - Remove tx_disable not supported log messages - Add #include <syslog.h> Signed-off-by: Eric Yang <eric_yang@accton.com>
vincentchiang-ec
left a comment
There was a problem hiding this comment.
Nice port overall — flat_mem detection, advertising-bit gating, bank-select order and the syslog cleanup all landed cleanly on most platforms. Two systematic issues showed up during review, and I've left inline notes at each site.
1. Restore-write clobbers E_UNSUPPORTED / OK (5 platforms × set+get = 10 sites). The final writeb(page_select, ADMIN_INFO) in the QSFP-DD block sets rv = E_INTERNAL on failure, which overwrites the rv = E_UNSUPPORTED we just carefully set for flat-memory / non-advertising modules (and also flips a successful write to E_INTERNAL). Regresses the exact behaviour PR #191 was written to introduce. Reference fix pattern is in as9726-32d sfpi.c (restore: label + rv = (rv == E_UNSUPPORTED) ? rv : E_INTERNAL) — please mirror it. Affected: as9716_32d, as9736-64d, as9926-24d, as9926-24db, as7926-40xfb.
2. as9817-64 / as9817-64-nb early-return pattern (2 platforms × set+get = 4 sites). These files use return E_INTERNAL inline in each error branch instead of the restore: label. The E_UNSUPPORTED paths (return E_UNSUPPORTED after restore) are fine — but the final "success" restore does return E_INTERNAL on restore failure, so a successful set/get becomes E_INTERNAL if only the ADMIN_INFO write itself fails. Same fix idea: either preserve the pre-restore return value or drop the failure-→ E_INTERNAL on the restore-only branch.
3. Missing & 0xff mask on *value = tx_disable (as9817-64 / as9817-64-nb only). Everywhere else the port applies *value = (tx_dis & 0xff) to avoid the sign-extension from dev_readb's int return; these two platforms still assign the raw signed int, so a byte with bit7 set will surface as a negative value in value. Trivial mask fix.
Nothing else looks off — flat-mem check offsets, page 01h advertising bit, bank-select-before-page-10h all match the reference on every platform.
| AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write page to eeprom fail\r\n", | ||
| syslog(LOG_ERR, "Unable to write tx_disable status to port(%d): write page to eeprom fail", | ||
| port); | ||
| rv = ONLP_STATUS_E_INTERNAL; |
There was a problem hiding this comment.
Restore write clobbers E_UNSUPPORTED (control_set path). When the TX_DISABLE_SUPPORT advertising bit is clear a few lines above, rv is set to E_UNSUPPORTED; this block then unconditionally overwrites it to E_INTERNAL if the ADMIN_INFO restore itself fails. Same thing happens on the successful write path (turns rv = OK into E_INTERNAL).
Suggested fix — mirror the as9726-32d pattern in this repo:
restore:
if ((onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR,
QSFP_DD_EEPROM_OFFSET_PAGE_SELECT,
QSFP_DD_PAGE_ADMIN_INFO)) < 0) {
syslog(LOG_ERR, "Failed to restore Page Select to Admin Info on port(%d)!", port);
}
if (rv < 0) {
rv = (rv == ONLP_STATUS_E_UNSUPPORTED) ? rv : ONLP_STATUS_E_INTERNAL;
}Fork missed this platform — same pattern as the four flagged in the other comments.
| AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): write page to eeprom fail\r\n", | ||
| syslog(LOG_ERR, "Unable to read tx_disable status from port(%d): write page to eeprom fail", | ||
| port); | ||
| rv = ONLP_STATUS_E_INTERNAL; |
There was a problem hiding this comment.
Same restore-clobber issue on the control_get path — see the control_set comment above for the reference fix.
| AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write page to eeprom fail\r\n", | ||
| syslog(LOG_ERR, "Unable to write tx_disable status to port(%d): write page to eeprom fail", | ||
| port); | ||
| rv = ONLP_STATUS_E_INTERNAL; |
There was a problem hiding this comment.
Restore write clobbers E_UNSUPPORTED (control_set path). When the earlier else { rv = ONLP_STATUS_E_UNSUPPORTED; } fires (advertising bit clear), this block promotes it to E_INTERNAL if the ADMIN_INFO restore itself fails. Also flips a successful write path (rv = OK) to E_INTERNAL.
Suggested fix — mirror the as9726-32d reference:
restore:
if ((onlp_sfpi_dev_writeb(port, PORT_EEPROM_DEVADDR,
QSFP_DD_EEPROM_OFFSET_PAGE_SELECT,
QSFP_DD_PAGE_ADMIN_INFO)) < 0) {
syslog(LOG_ERR, "Failed to restore Page Select to Admin Info on port(%d)!", port);
}
if (rv < 0) {
rv = (rv == ONLP_STATUS_E_UNSUPPORTED) ? rv : ONLP_STATUS_E_INTERNAL;
}| AIM_LOG_ERROR("Unable to read tx_disable status from port(%d): write page to eeprom fail\r\n", | ||
| syslog(LOG_ERR, "Unable to read tx_disable status from port(%d): write page to eeprom fail", | ||
| port); | ||
| rv = ONLP_STATUS_E_INTERNAL; |
There was a problem hiding this comment.
Same restore-clobber issue on the control_get path — see the control_set comment above.
| AIM_LOG_ERROR("Unable to write tx_disable status to port(%d): write page to eeprom fail\r\n", | ||
| syslog(LOG_ERR, "Unable to write tx_disable status to port(%d): write page to eeprom fail", | ||
| port); | ||
| rv = ONLP_STATUS_E_INTERNAL; |
There was a problem hiding this comment.
Restore write clobbers E_UNSUPPORTED (control_set). Please mirror the as9726-32d restore: label + rv = (rv == E_UNSUPPORTED) ? rv : E_INTERNAL pattern — same story as the as9716_32d comment.
| AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d) : write page to eeprom fail\r\n", | ||
| syslog(LOG_ERR, "Unable to read tx_disabled status from port(%d) : write page to eeprom fail", | ||
| port); | ||
| return ONLP_STATUS_E_INTERNAL; |
There was a problem hiding this comment.
Successful control_get reported as E_INTERNAL when the restore write fails — same pattern as line 332 on the set side. Same fix suggestion.
| 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); | ||
| syslog(LOG_ERR, "Unable to write tx_disable status to port(%d): write page to eeprom fail", port); | ||
| return ONLP_STATUS_E_INTERNAL; |
There was a problem hiding this comment.
Successful control_set reported as E_INTERNAL when the restore write fails. Every earlier error branch already return E_INTERNAL after its own restore, so this final restore only runs on the OK path — returning E_INTERNAL here turns a real success into a caller-visible failure. Same fix idea as the as9817-64 comment: either drop the return E_INTERNAL here or adopt the restore: label pattern from as9726-32d.
| syslog(LOG_ERR, "Unable to read tx_disabled status from port(%d) : read TX disable from eeprom fail", port); | ||
| return ONLP_STATUS_E_INTERNAL; | ||
| } | ||
| *value = tx_disable; |
There was a problem hiding this comment.
Missing & 0xff mask on *value = tx_disable. Sign-extension bug — dev_readb returns int and a byte with bit 7 set surfaces as a negative value. Please apply the *value = (tx_disable & 0xff) mask used elsewhere in this PR.
| 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); | ||
| syslog(LOG_ERR, "Unable to read tx_disabled status from port(%d) : write page to eeprom fail", port); | ||
| return ONLP_STATUS_E_INTERNAL; |
There was a problem hiding this comment.
Successful control_get reported as E_INTERNAL when the restore write fails — same pattern as line 314. Same fix suggestion.
| syslog(LOG_ERR, "Unable to read tx_disabled status from port(%d) : read TX disable from eeprom fail", port); | ||
| return ONLP_STATUS_E_INTERNAL; | ||
| } | ||
| *value = tx_disable; |
There was a problem hiding this comment.
Same missing & 0xff mask on *value = tx_disable (QSFP+ path).
|
Follow-up context on the review above — I want to be fair about how much of this bug PR #194 actually introduced, since re-reading the pre-PR code changed my picture: as9726-32d was already safe before PR #191 landed. It has used the The other 11 platforms use a different structure (inline
So the practical takeaway isn't "PR #194 introduced all these bugs" — it's more that porting the flat-memory check via the (as9817-64 / as9817-64-nb are separate — their early-return structure is fine for |
85bbf91 to
42814f4
Compare
…tten by page restore failure The final ADMIN_INFO page restore write could previously mask a successful or E_UNSUPPORTED result. This fix ensures the real result is preserved. Refactored to goto restore pattern: - as7926-40xfb - as9716_32d - as9736-64d - as9926-24d - as9926-24db Preserved rv on final restore (removed return E_INTERNAL on the success-path restore failure, kept syslog): - as9737-32db - as9817-64 - as9817-64-nb Also added value masks to prevent sign extension (QSFP-DD & 0xff, QSFP/QSFP+ & 0xf): - as7926-40xfb - as9716_32d - as9736-64d - as9737-32db - as9817-64 - as9817-64-nb - as9926-24d - as9926-24db Signed-off-by: Eric Yang <eric_yang@accton.com>
42814f4 to
9e430f2
Compare
…get/set
platform:
as7535_28xb
as7926-40xfb
as7946-30xb
as7946-74xkb
as9716_32d
as9736_64d
as9737-32db
as9817-64nb
as9817-64
as9926-24
merge from [Accton][as9726-32d] Check TX_DISABLE support before access in onlp_sfpi_control_get/set (#191)
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.
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:
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.