# DF-4252 — `mprsas_fw_work` IR-event early return leaks the fw_event and the startup refcount

## Where
`sys/dev/raid/mpr/mpr_sas_lsi.c:327-331` (MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST
case):

```c
if ((cm = mpr_alloc_command(sc)) == NULL) {
        kprintf("%s: command alloc failed\n", __func__);
        return;                      /* <-- leaks */
}
```

`mprsas_fw_work` frees the event only at its tail (:780
`mprsas_fw_event_free`), and the IR case drops the startup refcount only at
:455 (`mprsas_startup_decrement`). The early return skips both.

## What
1. `fw_event` + `fw_event->event_data` (kmalloc'd in `mprsas_evt_handler`
   :142-156) leak on every occurrence.
2. The startup refcount taken in `mprsas_evt_handler` (:170-174, whenever
   `wait_for_port_enable` is set — every boot-time discovery) is never
   dropped: `startup_refcount` can never reach 0 → discovery-completion
   callbacks (simq release, mprsas_startup_decrement side effects at
   mpr_sas.c:204-226) never fire for this event → CAM queue stays frozen /
   boot hangs until the `mpr_detach_sas`/reinit forced-drain loops
   (mpr_sas.c:941-942) run.
3. Command-pool exhaustion (which triggers this) is most likely precisely
   during an IR config-change event storm — the leak then amplifies the
   exhaustion (each leaked fw_event holds pool pressure).

## Trigger
mpr(4) HBA in IR mode, IR_CONFIGURATION_CHANGE_LIST event with Hide/PD-Created
reason while the command pool is empty (heavy I/O + event storm). Hardware-gated.

## Fix
`fix.diff` — on alloc failure do what the normal path would have done:
decrement the refcount, free the event, then return.

## Build/run
`build.log` — compile-validated on the audit guest.
