# DF-5508 — amdsmb_detach performs no quiesce/drain: kldunload during an in-flight (locked) transaction lockuninit()s a held lock and releases the I/O resource under live MMIO

Trace-proven lifecycle gap (Info, root-gated, hardware-gated — not
executable on any available rig; see verdict.json).

## Trace

`amdsmb_detach` (`sys/bus/smbus/amdsmb/amdsmb.c:175-191`):

1. `device_delete_child(dev, sc->smbus)` tears down the smbus bus and
   its `smb` children. The `/dev/smbN` cdev teardown
   (`sys/dev/smbus/smb/smb.c:151-152`, `dev_ops_remove_minor`) removes
   devfs entries but nothing waits for threads already inside
   `smbioctl` — and this driver's `amdsmb_callback`
   (amdsmb.c:193-207) makes `SMB_REQUEST_BUS` a no-op, so the smbus
   layer provides no serialization either. The only exclusion is the
   driver's own `sc->lock`.
2. A thread in e.g. `amdsmb_bread` holds `AMDSMB_LOCK(sc)` across the
   entire transaction (amdsmb.c:527-544), including the up-to-5.4 s
   `amdsmb_wait` busy spin (amdsmb.c:287-291) — a wide window.
3. `kldunload` then reaches `lockuninit(&sc->lock)` (amdsmb.c:185) on a
   lock that is still held, followed by `bus_release_resource`
   (amdsmb.c:186-188) while the in-flight thread continues
   `bus_read_1`/`bus_write_1` on the released I/O range — use of a
   freed resource / potential I/O to a reassigned device.

Same shape as ichsmb's DF-5460 (Info) — that sibling at least had an
interrupt handler to leak; here the exposure is the lock-state
corruption plus post-release port I/O. Triggering requires an open
`/dev/smbN` fd with an ioctl in flight against stuck/absent hardware
AND concurrent `kldunload amdsmb` — both root-only on a stock system,
hence Info.

Related, folded here (below finding threshold): `amdsmb_attach` ignores
the return of `bus_generic_attach` (amdsmb.c:170) — a failed smbus
child attach is reported as success; harmless bookkeeping.

## Suggested fix (prose)

Before `lockuninit`, drain in-flight ops: e.g. set a `detaching` flag
under the lock, take the lock once (`lockmgr(&sc->lock, LK_EXCLUSIVE |
LK_DRAIN)` style or a state flag checked by the op wrappers), and have
`amdsmb_*` entry points return `ENXIO` once detaching. Check
`bus_generic_attach`'s return in attach.
