X520 live as the product NIC: rate buckets re-keyed to read time (one shared clock, one commit per drained batch) with the backward smear as a settled window — each completed bucket enters once, donates excess to the nearest earlier deficits once, locks for display when nothing later can refill it (per-sample recompute double-counted excess and read >20G on a 20G wire); timestamp machinery deleted (ts.go, SO_TIMESTAMPING, rx_filter=ALL check) after the audit confirmed the buckets were its sole consumer; testDriver ixgbe; RollBall mailbox hardened against orphaned-command completions (never sample status before a poll gap, value from the same block read, devad/reg echo required — a killed session's 7.60 read answered a PHY ID as 0x0006); full hardware pass: 20.00G flat both directions, zero errors, ECD 42m, SNR +7.4dB
This commit is contained in:
@@ -535,34 +535,44 @@ func (r *rollball) unlock() error {
|
||||
return r.i2cWrite(rbOffPassword, 0xFF, 0xFF, 0xFF, 0xFF)
|
||||
}
|
||||
|
||||
func (r *rollball) mbox(cmd byte, devad, reg, val uint16) error {
|
||||
if err := r.unlock(); err != nil {
|
||||
return err
|
||||
// The µC can be mid-service of an earlier session's command when this one is
|
||||
// issued: it completes the old one, leaving DONE and a stale value in the
|
||||
// block, and a status sample taken before the new command commits reads them
|
||||
// as this command's (seen live: PHY ID high word answered by an orphaned 7.60
|
||||
// read). So status is never sampled before a full poll gap, the value rides
|
||||
// in the same block read as the status, and a completion only counts when the
|
||||
// block echoes this command's devad/reg.
|
||||
func (r *rollball) mbox(cmd byte, devad, reg, val uint16) (out [2]byte, err error) {
|
||||
if err = r.unlock(); err != nil {
|
||||
return
|
||||
}
|
||||
if err := r.i2cWrite(rbOffDevad, byte(devad), byte(reg>>8), byte(reg)); err != nil {
|
||||
return err
|
||||
if err = r.i2cWrite(rbOffDevad, byte(devad), byte(reg>>8), byte(reg)); err != nil {
|
||||
return
|
||||
}
|
||||
if cmd == rbCmdWrite {
|
||||
if err := r.i2cWrite(rbOffValHi, byte(val>>8), byte(val)); err != nil {
|
||||
return err
|
||||
if err = r.i2cWrite(rbOffValHi, byte(val>>8), byte(val)); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if err := r.i2cWrite(rbOffCmd, cmd); err != nil {
|
||||
return err
|
||||
if err = r.i2cWrite(rbOffCmd, cmd); err != nil {
|
||||
return
|
||||
}
|
||||
deadline := time.Now().Add(rbCmdTimeout)
|
||||
for {
|
||||
d, err := r.i2cRead(rbOffCmd, 1)
|
||||
if err != nil {
|
||||
return err
|
||||
time.Sleep(rbCmdPoll)
|
||||
var d []byte
|
||||
if d, err = r.i2cRead(rbOffCmd, 6); err != nil {
|
||||
return
|
||||
}
|
||||
if d[0] == rbCmdDone {
|
||||
return nil
|
||||
if d[0] == rbCmdDone && d[1] == byte(devad) &&
|
||||
d[2] == byte(reg>>8) && d[3] == byte(reg) {
|
||||
out[0], out[1] = d[4], d[5]
|
||||
return
|
||||
}
|
||||
if time.Now().After(deadline) {
|
||||
return fmt.Errorf("%s: mailbox %d.%#04x stuck at %#02x", r.ifname, devad, reg, d[0])
|
||||
err = fmt.Errorf("%s: mailbox %d.%#04x stuck at %#02x", r.ifname, devad, reg, d[0])
|
||||
return
|
||||
}
|
||||
time.Sleep(rbCmdPoll)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -575,10 +585,7 @@ func rbGuard(safe map[uint16]map[uint16]bool, ifname, what string, devad, reg ui
|
||||
|
||||
func (r *rollball) mdioRead(devad, reg uint16) (uint16, error) {
|
||||
rbGuard(rbReadSafe, r.ifname, "read", devad, reg)
|
||||
if err := r.mbox(rbCmdRead, devad, reg, 0); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
d, err := r.i2cRead(rbOffValHi, 2)
|
||||
d, err := r.mbox(rbCmdRead, devad, reg, 0)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -587,7 +594,8 @@ func (r *rollball) mdioRead(devad, reg uint16) (uint16, error) {
|
||||
|
||||
func (r *rollball) mdioWrite(devad, reg, val uint16) error {
|
||||
rbGuard(rbWriteSafe, r.ifname, "write", devad, reg)
|
||||
return r.mbox(rbCmdWrite, devad, reg, val)
|
||||
_, err := r.mbox(rbCmdWrite, devad, reg, val)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *rollball) identify() (ident string, err error) {
|
||||
|
||||
Reference in New Issue
Block a user