⬢ DragonFlyBSD Kernel Audit
DF-4583 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/radeon/rs690.c
+++ b/sys/dev/drm/radeon/rs690.c
@@ -365,10 +365,24 @@ static void rs690_crtc_bandwidth_compute(struct radeon_device *rdev,
 	/* Maximun bandwidth is the minimun bandwidth of all component */
 	max_bandwidth = core_bandwidth;
 	if (rdev->mc.igp_sideport_enabled) {
 		if (max_bandwidth.full > rdev->pm.sideport_bandwidth.full &&
 			rdev->pm.sideport_bandwidth.full)
 			max_bandwidth = rdev->pm.sideport_bandwidth;
+		/*
+		 * igp_sideport_mclk comes straight from the VBIOS
+		 * IntegratedSystemInfo table (rs690_pm_info): a zero
+		 * ulBootUpSidePortClock/ulBootUpMemoryClock makes b.full
+		 * zero and dfixed_div() panics with an integer divide
+		 * fault.  Treat a zero sideport clock like "no sideport".
+		 */
+		if (rdev->pm.igp_sideport_mclk.full == 0) {
+			read_delay_latency.full = dfixed_const(5000);
+			goto have_latency;
+		}
 		read_delay_latency.full = dfixed_const(370 * 800);
 		a.full = dfixed_const(1000);
 		b.full = dfixed_div(rdev->pm.igp_sideport_mclk, a);
 		read_delay_latency.full = dfixed_div(read_delay_latency, b);
 		read_delay_latency.full = dfixed_mul(read_delay_latency, a);
@@ -383,9 +397,18 @@ static void rs690_crtc_bandwidth_compute(struct radeon_device *rdev,
 		read_delay_latency.full = dfixed_const(5000);
 	}
+have_latency:
 
 	/* sclk = system clocks(ns) = 1000 / max_bandwidth / 16 */
 	a.full = dfixed_const(16);
 	sclk.full = dfixed_mul(max_bandwidth, a);
 	a.full = dfixed_const(1000);
+	/*
+	 * max_bandwidth is zero when every bandwidth component parsed from
+	 * the VBIOS is zero (e.g. ulDefaultEngineClock == 0 gives
+	 * rdev->pm.sclk == 0 and core_bandwidth == 0; the guards above
+	 * never replace a zero maximum).  Bail instead of dividing by 0.
+	 */
+	if (sclk.full == 0) {
+		wm->lb_request_fifo_depth = 4;
+		return;
+	}
 	sclk.full = dfixed_div(a, sclk);
 	/* Determine chunk time
 	 * ChunkTime = the time it takes the DCP to send one chunk of data