Rework zyd(4)'s register read/write methods to eliminate race conditions.
authorstsp <stsp@openbsd.org>
Sat, 12 Jul 2014 15:26:54 +0000 (15:26 +0000)
committerstsp <stsp@openbsd.org>
Sat, 12 Jul 2014 15:26:54 +0000 (15:26 +0000)
commit0189c42b2c88e9e027bc3fb40503fe0714fbe022
treedfa5b9f151d06e940d9e50dc871842ae0a0a272f
parent68a272ff45d44b26bcfbf7aac61d5a3b1746d781
Rework zyd(4)'s register read/write methods to eliminate race conditions.

Read commands were issued via asynchronous transfers and replies were
expected after a fixed tsleep() timeout. Upon timeout zyd simply freed
the xfer even if it was still in-flight within the USB stack. This could
cause havoc such as making all USB ports on the system unusable until reboot.
  ehci_freex: xfer=0xfffffe811e63e9d8 not busy, 0x4f4e5155
  ("busy" here would indicate the xfer is done and marked for being freed)

To fix this, issue read commands with synchronous transfers so the xfer
can always complete. Split read/write code paths into separate methods.
Add a flag that tells us if a reply was received in interrupt context
while the read path waited in tsleep().

With and ok mpi@
sys/dev/usb/if_zyd.c
sys/dev/usb/if_zydreg.h