Repository navigation
apcmicrolink: back off failed session starts, don't write from missing pages - #3806
Open
JayToltTech wants to merge 4 commits into
Open
JayToltTech wants to merge 4 commits into
JayToltTech wants to merge 4 commits into
Conversation
Once a session drops into the HID fallback, `upsdrv_updateinfo()` retries the Microlink handshake every `MLINK_SESSION_RETRY_INTERVAL_SEC`, which is 1 s, forever. Every retry is a STOP and an INIT, and every one that gets far enough sends the slave password again. On an SCL500RM1UC (FW UPS 16.5) here the UPS reset every 4-5 minutes for about 20 minutes while the driver logged a failed Microlink startup on each boot. It stopped when I pulled the USB cable. I can't prove the retry loop is what did it, but a device that's already refusing sessions shouldn't get probed once a second. This doubles the wait after each failed retry, 1 s up to `MLINK_SESSION_RETRY_MAX_SEC` (60 s), and resets it once a session comes up. Status still publishes from the HID fallback on every poll in between. Against a fake Microlink device on a pty that goes silent mid-session, master sent 186 INITs in 183 s and this sends 7, at 1/2/4/8/16/32/60 s. It reconnects when the device comes back, up to 60 s later than master would. Signed-off-by: Jay Beavers <jay@tolttechnologies.com>
`microlink_update_blob()` zero-fills any page the device hasn't sent, and the descriptor is parsed from that blob and every write takes its address from it. The SCL500RM1UC here reports 103 pages and never sends 0x5B, so the blob always has a hole in it. Was going to require every page before accepting the descriptor, but on this unit that never completes. So this checks the pages that matter instead. The descriptor's own bytes have to come from received pages, and `microlink_send_descriptor_write()` refuses a write whose field crosses a page or sits on a page that never arrived. It also caps the startup loop in `upsdrv_initinfo()` at `MLINK_STARTUP_MAX_SEC` (60 s) once a session answers. A device that keeps replying but never completes the descriptor holds startup forever otherwise, since `consecutive_timeouts` never climbs. After the cap it drops to the HID fallback like any other failed startup. On the real unit the descriptor comes up with 268 usages despite the missing page. Against a fake device with a missing page outside the descriptor, startup completes, and with the descriptor running into the missing page it stops at 60 s. I haven't seen the write refusal fire on real hardware. Signed-off-by: Jay Beavers <jay@tolttechnologies.com>
The comment in `microlink_authenticate()` already suspects a failed handshake of locking out comms until a device reset. But each new session sends the slave password again, so a device stuck refusing sessions gets one per retry. This sends it at most once per `MLINK_AUTH_MIN_INTERVAL_SEC` (300 s) across sessions. It's skipped when AUTH_STATUS already reads valid, and held off until the pages with the serial number and master password it's computed from have actually been received. On the SCL500RM1UC here the reply goes out once at startup, to page 101, and AUTH_STATUS reads 0x0001 about 3.5 s later. The hold-off paths haven't fired on real hardware, and the fake device I tested against has no auth. Signed-off-by: Jay Beavers <jay@tolttechnologies.com>
|
Preparing a ZIP file with standard source tarball and another tarball with pre-built docs for commit 894469a ... |
Signed-off-by: Jay Beavers <jay@tolttechnologies.com>
JayToltTech
force-pushed
the
apcmicrolink-retry-guards
branch
from
October 29, 2026 18:39
36d26a3 to
894469a
Compare
|
✅ Build nut 2.8.5.5932-master completed (commit b5e55082e1 by @JayToltTech)
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
An SCL500RM1UC (FW UPS 16.5) here on USB reset itself every 4-5 minutes for about 20 minutes this morning, taking everything plugged into it down each time. The driver logged
could not complete Microlink startupon every boot in that window, and the resets stopped when I pulled the USB cable. I can't prove the driver caused it, there's no event log I can get off this unit, but reading the code turned up three things I'd rather not have pointed at a UPS that's already misbehaving.upsdrv_updateinfo()retries the handshake every second forever, and every session that gets far enough sends the slave password again. The comment inmicrolink_authenticate()already suspects a failed handshake of locking out comms until a device reset.microlink_update_blob()zero-fills pages the device never sent, and the descriptor and every write address come from that blob. This unit reports 103 pages and never sends 0x5B.upsdrv_initinfo()never exits, sinceconsecutive_timeoutsnever climbs.A commit for each, plus the version bump. Retries back off 1 to 60 s. The slave password goes out at most once per 5 minutes, not at all if AUTH_STATUS already reads valid, and only once the pages it's computed from have arrived. Writes are refused when their page never arrived, and startup gives up after 60 s and drops to the HID fallback.
Was going to require every page before accepting the descriptor, but on this unit that never completes, so the checks are per page instead.
Ran it on the SCL500RM1UC for 5 minutes in the foreground at
-DD, and it's been in service since. The descriptor comes up with 268 usages despite the missing page. The only write is the 4-byte slave password to page 101, and AUTH_STATUS reads 0x0001 3.5 s later, with no reconnects and no resets. Against a fake Microlink device on a serial pty, master sends 186 INITs in 183 s of silence and this sends 7, then reconnects when the device comes back. A missing page outside the descriptor doesn't block startup, and a descriptor running into a missing page stops at 60 s.I haven't seen the write refusal or the auth hold-off fire on real hardware, and it's one UPS model. Each commit builds on its own and
make spellcheckpasses.Claude Code was used for the code review, the patch and the testing.