# DF-3814 — reallocating diag reset tears down all interrupts and never re-establishes them → controller permanently dead (hang/panic DoS)

## What

On a diag reset whose IOC Facts changed (the `reallocating` path),
`mpr_iocfacts_free()` (called from `mpr_iocfacts_allocate()`,
sys/dev/raid/mpr/mpr.c:630-634) ends with:

```c
mpr_pci_free_interrupts(sc);              /* mpr.c:801 */
kfree(sc->queues, M_MPR);                 /* mpr.c:802 */
```

`mpr_pci_free_interrupts()` (sys/dev/raid/mpr/mpr_pci.c:331-349) does a real
teardown: `bus_teardown_intr()` + `bus_release_resource(SYS_RES_IRQ)` for
every queue. The queues array is then rebuilt by `mpr_alloc_queues()`
(mpr.c:650, M_ZERO → `q->irq == NULL`), but the re-establishment is gated on
attach only:

```c
/* mpr.c:714-718 */
/*
 * XXX If the number of MSI-X vectors changes during re-init, this
 * won't see it and adjust.
 */
if (attaching && (error = mpr_pci_setup_interrupts(sc)) != 0) {
```

`mpr_reinit()` calls `mpr_iocfacts_allocate(sc, FALSE)` (mpr.c:861) —
`attaching` is FALSE, so `mpr_pci_setup_interrupts()` is **never** called
again. `mpr_reinit()` then even unmasks interrupts (mpr.c:879
`mpr_unmask_intr`): the firmware now raises interrupts that no longer have a
handler. Every subsequent command completion is lost; synchronous waiters
time out and re-enter `mpr_reinit()` (which cannot fix it), CAM freezes, and
`mpr_wait_command(..., 0, CAN_SLEEP)` users (config-page reads, mpr.c:3740)
sleep **forever** (`timeout*hz == 0` ⇒ infinite lksleep). Realistic end
states: storage subsystem wedge, boot-time hang, or panic via the reinit
failure panics (mpr.c:846, mpr.c:862).

The code comment ("XXX … won't see it and adjust") shows the authors were
aware of the vector-count aspect but missed that the *entire* handler set is
dropped.

## Trigger

Firmware whose IOC Facts differ across a diag reset — most commonly reached
by a firmware download via the management ioctl (`/dev/mprX`) followed by the
reset, or by a controller fault after which the IOC comes back with different
facts (RequestCredit / MaxTargets / IOCCapabilities / MaxVolumes …). The
realloc condition itself is mpr.c:551-576.

## Not runnable here

Audit guest has no SAS3 controller (see probe.log): driver compiled in
(`142 pci/mpr` in `kldstat -v`), no `/dev/mpr0`. Source-level verification
only; fix validation not possible.

## Env

- DragonFly dfbsd 6.5-DEVELOPMENT #0 Thu Jul 2 06:02:54 UTC 2026
  (X86_64_GENERIC), x86_64
