# DF-5421 — uchcom cfg-chain EP0 stall (evil CH340/CH341)

## What (human-readable)

`sys/bus/u4b/serial/uchcom.c` issues **sequential synchronous EP0 vendor control
requests** from its ucom cfg callbacks and **discards every result**:

* `uchcom_cfg_param()` (uchcom.c:652-666) — fired on **every tcsetattr** of an
  open tty — chains **12** requests: version read (656→438), RESET write (657),
  2 baud writes (658→578-583), LCR read (659→419), LCR write (660), status read
  (661→488), RESET write (662), 2 baud writes (663), DTR/RTS write (664→453/459),
  status read (665).
* `uchcom_cfg_open()` (uchcom.c:622-631) — every open(2) — chains **2** more.
* Every request is `uchcom_ctrl_read`/`uchcom_ctrl_write` → `ucom_cfg_do_request(...,1000)`
  (uchcom.c:381-382, 397-398) with a **1000 ms timeout**, and both helpers are
  `void` — the `usb_error_t` is thrown away, so **no chain step ever aborts**.

An evil CH340/CH341 (VID 0x1a86/0x1a2d, uchcom.c:193-196 — probe only checks
VID/PID, uchcom.c:293) that simply never answers the control data stage makes
each request eat its full timeout (usb_request.c:642-644 "WXFER" sleep,
699-704 timeout) and the chain marches on: **~12.1 s per tcsetattr, ~2.1 s per
open**. A device that answers just-under-timeout makes every request *succeed*
slowly — same cost, and not even an error to abort on.

## Who blocks

* The chain runs on the per-adapter ucom taskqueue (`sc_super_ucom.sc_tq`,
  usb_serial.c:322) holding `sc->sc_lock`.
* **close(2) is synchronous against that queue**: `ucom_close()` →
  `ucom_queue_command(ucom_cfg_close)` → `usb_proc_mwait()` (usb_serial.c:671-672,
  955-957), an **uninterruptible** cv_wait (usb_process.c:385-393); a message
  stays head-of-queue for its whole callback (usb_process.c:146-158).
* **Unplug** stalls the USB hub event thread the same way via `ucom_detach()` →
  `usb_proc_drain()` (usb_serial.c:394) — DF-5367 mechanism, uchcom instance.
* Any local user with the tty open **multiplies** the occupancy: each tcsetattr
  re-queues the param task into ucom's double buffer (usb_serial.c:1691-1693) —
  two outstanding tasks ≈ **~24 s** of uninterruptible close(2)/unplug block,
  repeatable indefinitely.

## Reproduce (no CH341 device model exists on the QEMU guest → KLD harness)

```
# build (in-tree kmod, -Werror clean)
mkdir -p /usr/src/sys/bus/u4b/serial/hx5421
cp uchcom_cfgstall_harness.c Makefile /usr/src/sys/bus/u4b/serial/hx5421/
sh build.sh

# run
sh run.sh     # kldload uchcomcfgstall.ko; kldunload; dmesg
```

### Expected (dmesg)

```
HX5421[A]: closer: unblocked  ELAPSED=~13,900 ms   (open + 1 tcsetattr + close)
HX5421[2]: closer: unblocked  ELAPSED=~25,800 ms   (open + 2 tcsetattr + close)
HX5421[B]: closer: unblocked  ELAPSED=~2,100 ms    (fix.diff: abort on 1st error)
```

Measured (3 kldload runs of the final module): A = 13888/13887 ms,
A2 = 25772/25767 ms, B = 2101/2132 ms.

## Fix

`fix.diff` — propagate `usb_error_t` through the vendor-request helpers and
abort each cfg chain on the first failed request (silent device then costs 1
timeout ≈ 1 s per chain, not 12). `git apply --check` passes against `sys/`;
the patched driver compiles `-Werror`-clean as the production `uchcom.ko` kmod
on the guest (fix_compile.log).

Severity: **Low** (evil-USB-adapter precondition; family-consistent with
DF-5367/DF-5383). Bucket: base:hw.
