# DF-3910 — Tonga fan-table slope divide-by-zero (usTMed == usTMin) → kernel #DE panic

**File:** `sys/dev/drm/amd/powerplay/smumgr/tonga_smumgr.c`
**Lines:** 2502-2513 (`tonga_thermal_setup_fan_table`)
**Severity:** Medium (local DoS at GPU/DPM enable) — **hardware-gated** (Tonga/Fiji + crafted VBIOS fan table)
**Class:** base:dev / CWE-369 (divide-by-zero), pass 2 (the fan table — not covered by DF-1274, which fixed only SCLK/MCLK SS rates at :591/:883)

## Build / Run
```
./build.sh && ./run.sh
```

## Expected output
```
duty100=200 pwm_diff1=1234 usTMin=4000 usTMed=4000 -> t_diff1=0
evaluating (50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100 ...
Illegal instruction (core dumped)          <- SIGFPE == kernel #DE
trigger rc=132 (42 == SIGFPE/#DE fault demonstrated)
```
(The userspace division raises SIGFPE exactly the way the kernel path raises
a divide-error fault → panic. run.log on the guest shows the actual fault.)

## Root cause
`process_pptables_v1_0.c:941-986` copies usTMin/usTMed/usTHigh verbatim from
the VBIOS fan table with no distinctness check. `tonga_thermal_setup_fan_table`
computes `t_diff1 = usTMed - usTMin` (:2502-2503), `t_diff2 = usTHigh - usTMed`
(:2504-2505) and divides by both at :2512-2513 without a zero check. A crafted
VBIOS with usTMed == usTMin (or usTHigh == usTMed) panics the kernel during
DPM enable (MicrocodeFanControl cap set, fan present, duty100 != 0 — all
satisfied on real fan-equipped boards).

## Fix
`fix.diff` adds the same guard the sibling drivers' fixes use (cf. DF-1297 ci,
DF-1323 iceland, DF-1325 fiji, DF-1345 polaris10): if either delta is zero,
unset PHM_PlatformCaps_MicrocodeFanControl and return 0. Validated in the
batch nativekernel rebuild: rc=0, `-Werror` clean (fix_build.log).
