diff options
| author | Nick Price <nprice@FreeBSD.org> | 2026-08-09 19:47:31 +0000 |
|---|---|---|
| committer | Nick Price <nprice@FreeBSD.org> | 2026-08-09 19:47:31 +0000 |
| commit | af3f2dd124f07342c273dc017bc5e73639e446a5 (patch) | |
| tree | 2c75025c26a4ecb523b5b3942934eb2e50a9845e /lib/Frontend/(public-mirror) | |
| parent | d38b3a5ead0d3507080da5321144219b13d43aa9 (diff) | |
A link flap left nothing in the log to work from. Both the link up and
link down messages were gated on bootverbose while the message for a
speed change that keeps carrier was not, so a default kernel was silent
about a flap yet loud about a downshift -- the inverse of what an
operator wants. The generic message from if_link_state_change() carries
no speed, so gating the driver's own left the negotiated rate
unrecorded. Report both transitions unconditionally.
Say more than the rate. aq_hw_get_link_state() already negotiates flow
control and throws it away, and Atlantic 2 reports duplex and EEE in the
same link status word the rate comes from; decode them through a new
get_link_info firmware op and name all of it on the up transition. EEE
matters for a flap: low power idle transitions are a common source of
marginal link trouble on multi-gigabit copper, and whether it was active
is otherwise invisible.
Give the down transition a cause. The PHY global fault code was only
consulted from the thermal state machine, so an ordinary link loss
reported nothing at all. Read the fault code, the firmware link state
and the PHY temperature once per transition and append whatever is
available. The firmware raises a fault one poll after it drops the
link, so a thermal trip usually shows only its temperature here and
aq_thermal_poll() names it on the following poll; the temperature alone
is enough to separate a hot PHY from a cable event.
Warn before the PHY trips rather than only after. The Atlantic 2 health
monitor word carries a hot warning bit next to the ready and fault bits
that nothing decoded. Report both edges of it from the thermal poll, so
an adapter that is approaching its shutdown threshold says so while the
link is still up.
Expose the firmware's own link transition counters. The Atlantic 2 A0
statistics layout opens with link_up and link_down, which were read out
of the firmware on every statistics poll and discarded. Publish them as
dev.aq.N.fw_link_up and fw_link_down so a single flap can be told from a
link that has been flapping all night. The B0 layout has no equivalent,
so the op reports ENOTSUP there and the nodes are not created, matching
how the temperature node is handled.
Stop announcing a link state that was never read. The return value of
aq_hw_get_link_state() was discarded, so a failed read would have been
announced as link down. No firmware backend can fail that call today --
all three decode a register with no error path -- but the caller no
longer depends on that, and it says so once if it ever starts failing.
Report the hardware failures that were being discarded. The driver
already reports the errors it keeps, so what stayed quiet was the set of
calls whose result was never examined at all. None of these are
expected to fail, which is precisely why a failure needs to say so: each
one leaves the interface running but misconfigured in a way that
presents as a network problem rather than a driver problem. aq_if_init()
discarded aq_hw_start(), aq_hw_rss_hash_set(), aq_hw_rss_set() and
aq_hw_udp_rss_enable(), so a datapath that never started or an
indirection table that was never programmed showed up only as an
interface that passes no traffic or delivers every flow to one queue.
aq_mc_filter_apply() discarded aq_hw_mac_addr_set(), so a multicast
address the stack believes is programmed could silently not be; report
the address that failed and leave the filter slot for the next one
instead of burning it. aq_update_vlan_filters() reported only the last
of its three register writes. aq_if_stop() discarded both ring stop
calls and the MAC reset, and a MAC that did not reset can still be
mastering the bus. aq_if_detach() and aq_if_suspend() discarded
aq_hw_deinit(). The interrupt moderation update on a link speed change
was dropped as well; it runs only on a transition, so reporting it
cannot become noisy.
aq_if_attach_pre() discarded aq_hw_capabilities(), which is the only
behavioral change here: it now fails the attach rather than continuing
with an unset media type and an empty link speed mask, which would
attach an interface that can never negotiate a link. It returns an
error only for a device the probe table does not cover, so it is not
reachable in practice.
Document the resulting sysctls, along with the existing temperature and
tracing nodes, which had no manual page coverage.
Tested on an AQC113C (Atlantic 2 B0, firmware 1.5.38). Link up reports
"speed=10000, full-duplex, flowcontrol none, EEE off", and "speed=1000"
after a forced renegotiation, so the rate and duplex are read rather
than assumed. A cable pull reports "link DOWN, F/W link state 0, temp
59 C" with the PHY fault clause correctly absent, which is what
separates a cable event from a thermal trip. The B0 interface reports
ENOTSUP for the link counters, so those two nodes are correctly not
created. Traffic is unaffected: ten flows spread over all eight RX
queues with no errors and no drops.
Reviewed by: adrian
Differential Revision: https://reviews.freebsd.org/D58749
Signed-off-by: Nick Price <nprice@FreeBSD.org>
Diffstat (limited to 'lib/Frontend/(public-mirror)')
0 files changed, 0 insertions, 0 deletions
