⬢ DragonFlyBSD Kernel Audit
DF-3828 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/amd/amdgpu/dce_v11_0.c
+++ b/sys/dev/drm/amd/amdgpu/dce_v11_0.c
@@ -905,18 +905,27 @@
 	/* First calculate the latency in ns */
 	u32 mc_latency = 2000; /* 2000 ns. */
 	u32 available_bandwidth = dce_v11_0_available_bandwidth(wm);
-	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 */
-	u32 other_heads_data_return_time = ((wm->num_heads + 1) * worst_chunk_return_time) +
-		(wm->num_heads * cursor_line_pair_return_time);
-	u32 latency = mc_latency + other_heads_data_return_time + dc_latency;
+	u32 worst_chunk_return_time, cursor_line_pair_return_time, dc_latency;
+	u32 other_heads_data_return_time, latency;
 	u32 max_src_lines_per_dst_line, lb_fill_bw, line_fill_time;
 	u32 tmp, dmif_size = 12288;
 	fixed20_12 a, b, c;
 
 	if (wm->num_heads == 0)
 		return 0;
+	/* Zero clocks (e.g. VBIOS reporting ulDefaultEngineClock == 0 with
+	 * DPM disabled) collapse the bandwidth terms to 0; dividing would
+	 * take a #DE and panic the kernel.  Bail out with the conservative
+	 * watermark used for the no-heads case. */
+	if (!available_bandwidth || !wm->disp_clk)
+		return 0;
+
+	worst_chunk_return_time = (512 * 8 * 1000) / available_bandwidth;
+	cursor_line_pair_return_time = (128 * 4 * 1000) / available_bandwidth;
+	dc_latency = 40000000 / wm->disp_clk; /* dc pipe latency */
+	other_heads_data_return_time = ((wm->num_heads + 1) * worst_chunk_return_time) +
+		(wm->num_heads * cursor_line_pair_return_time);
+	latency = mc_latency + other_heads_data_return_time + dc_latency;
 
 	a.full = dfixed_const(2);
 	b.full = dfixed_const(1);
@@ -1048,6 +1057,8 @@
 	u32 tmp, wm_mask, lb_vblank_lead_lines = 0;
 
 	if (amdgpu_crtc->base.enabled && num_heads && mode) {
+		if (!mode->clock)
+			return;
 		active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000,
 					    (u32)mode->clock);
 		line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
--- a/sys/dev/drm/amd/amdgpu/amdgpu_atombios.c
+++ b/sys/dev/drm/amd/amdgpu/amdgpu_atombios.c
@@ -678,6 +678,13 @@
 		    le32_to_cpu(firmware_info->info.ulDefaultEngineClock);
 		adev->clock.default_mclk =
 		    le32_to_cpu(firmware_info->info.ulDefaultMemoryClock);
+		/* Mirror the guards applied to every other clock field in
+		 * this parser: a zero default engine/memory clock collapses
+		 * the DCE watermark bandwidth terms to a divide-by-zero. */
+		if (adev->clock.default_sclk == 0)
+			adev->clock.default_sclk = 10000; /* 100 MHz sanity min */
+		if (adev->clock.default_mclk == 0)
+			adev->clock.default_mclk = 10000; /* 100 MHz sanity min */
 
 		mpll->min_post_div = 1;
 		mpll->max_post_div = 1;