DF-3665 / fix.diff
fix.diff — DF-3665: guard the divide-by-zero in evergreen_latency_watermark() (evergreen.c:2048-2050) available_bandwidth is min(dram, data_return, dmif) fixed-point products and is zero when: (a) a DRM-master user mode has pixel clock <= ~38 kHz (drm_mode_validate_basic() only rejects clock == 0; radeon has no mode_valid hook), (b) mclk/sclk land in the u32 fixed20_12 dfixed_const() wrap windows (e.g. exactly 524288/1048576/1572864 kHz), or (c) VBIOS reports zero clocks. In all three cases evergreen.c:2048/2049 divides by zero -> #DE -> kernel panic. Minimal fix: return the same 'no latency' value the function already returns for num_heads == 0. Also guards wm->disp_clk for the 40000000/wm->disp_clk division. Validated with 'git apply --check' against this tree. NOT applied (sys/ is a read-only audit target). --- a/sys/dev/drm/radeon/evergreen.c +++ b/sys/dev/drm/radeon/evergreen.c @@ -2045,6 +2045,12 @@ /* First calcualte the latency in ns */ u32 mc_latency = 2000; /* 2000 ns. */ u32 available_bandwidth = evergreen_available_bandwidth(wm); + + /* avoid a divide-by-zero (#DE panic) when the bandwidth math + * truncates to zero (tiny mode clocks, u32 fixed-point wrap of + * mclk/sclk, or missing clock info) */ + if (!available_bandwidth || !wm->disp_clk) + return 0; u32 worst_chunk_return_time = (512 * 8 * 1000) / available_bandwidth; u32 cursor_line_pair_return_time = (128 * 4 * 1000) / available_bandwidth; u32 dc_latency = 40000000 / wm->disp_clk; /* dc pipe latency */ |