# DF-5449 — uvscom cfg callbacks chain sequential 1000 ms-timeout EP0 vendor
# requests with discarded errors; evil SUNTAC-VID:PID device stretches the
# open+close cycle to ~6.1 s of uninterruptible ucom-taskqueue occupancy

## The chain (production code)

Every uvscom cfg callback issues synchronous vendor EP0 requests via
`ucom_cfg_do_request(..., 1000)` and **discards the error**
(uvscom.c:706-711, 727-732 — `DPRINTFN(0, "... (ignored)")`):

open(2) of /dev/ttyU0.* queues on the per-adapter ucom taskqueue
(`sc_super_ucom.sc_tq`, usb_serial.c:322), in order:

| # | task | requests | uvscom.c |
|---|------|----------|----------|
| 1 | `ucom_cfg_open` → `uvscom_cfg_open` → `uvscom_cfg_read_status` | 1× READ_STATUS (UT_READ_VENDOR_DEVICE) | 634-641, 714-734 |
| — | core pause `hz/10` after cfg_open | — | usb_serial.c:777 |
| 2 | `ucom_cfg_line_state` → `uvscom_cfg_set_dtr` + `uvscom_cfg_set_rts` (ucom_open:874 `ucom_modem(tp, SER_DTR|SER_RTS, 0)`) | 2× LINE_CTL writes | 470-482, 484-497 |
| 3 | `ucom_cfg_line_state` → `uvscom_cfg_set_break` (ucom_open:878 `ucom_break(sc, 0)`) | 1× LINE_CTL write | 499-512 |

= **4 × 1000 ms + 100 ms ≈ 4.1 s** taskqueue occupancy per open with a device
that NAKs/stalls every vendor data stage (each request eats its full 1000 ms
timeout, usb_request.c:642-644 "WXFER" lksleep + 699-704).

close(2) is **synchronous against the same queue**: `ucom_close()` →
`ucom_shutdown()` (HUPCL default-on) queues a line-state task →
`uvscom_cfg_set_dtr(0)` = 1 write (usb_serial.c:694-696 → uvscom.c:481), then
queues `ucom_cfg_close` → `uvscom_cfg_write(UVSCOM_SHUTDOWN)` = 1 write
(uvscom.c:643-651) and **`usb_proc_mwait()`s uninterruptibly**
(usb_serial.c:671-672, 955-957; usb_process.c cv_wait). A close(2) issued
right after open(2) therefore blocks ~4100 + 2000 = **~6.1 s, SIGKILL-immune**.
Unplug mid-cycle stalls the USB hub event thread identically via
`uvscom_detach()` → `ucom_detach()` → `usb_proc_drain()` (usb_serial.c:394),
and every request additionally serializes behind the per-device enum lock
(usb_request.c:467) the unplug path needs.

(The tcsetattr chain — `uvscom_cfg_param`, 2 more writes — is currently dead
because of the DF-5447 pre_param inversion; with that fixed it adds ~2.1 s
per tcsetattr, user-amplifiable via the double-buffered sc_param_task[2].)

## Evidence class

No SUNTAC VID:PID QEMU device model exists — **KLD-harness-with-production-
code** (same class as DF-5367/5383/5421/5424/5425): the harness drives the
real in-kernel `usb_process` machinery (usb_proc_create / msignal / mwait /
drain) that ucom's synchronous close and detach drain go through, with
uvscom's production request counts (4 per open chain, 2 per close chain) and
1000 ms timeout. One timed-out EP0 request is modeled by its exact production
cost: `lksleep("WXFER", 1000 ms)` (usb_request.c:642-644).

## Reproduce

```
./build.sh   # cd /usr/src/sys/bus/u4b/serial/hx5449 && make
./run.sh     # kldload; dmesg | grep HX5449
```

Expected baseline: `HX5449[A]: closer: unblocked ELAPSED=~6100 ms`
(open chain 4×1000+100 + close chain 2×1000).
Expected fix mechanism (phase B, abort-on-first-error + 250 ms timeout):
`~1350 ms`.

## Files
- `uvscom_cfgstall_harness.c`, `Makefile`, `build.sh`, `run.sh`
- `build.log`, `run.log`, `run.2.log`, `fix_compile.log`
- `fix.diff` — error propagation + chain abort + 250 ms timeout bound
- `VERDICT.md`, `manifest.json`, `verdict.json`
