DF-1204 / fix.diff
diff --git a/sys/dev/drm/radeon/radeon_atombios.c b/sys/dev/drm/radeon/radeon_atombios.c --- a/sys/dev/drm/radeon/radeon_atombios.c +++ b/sys/dev/drm/radeon/radeon_atombios.c @@ -1563,10 +1563,21 @@ ss->type = ss_assign->v2.ucSpreadSpectrumMode; ss->rate = le16_to_cpu(ss_assign->v2.usSpreadRateIn10Hz); ss->percentage_divider = 100; + /* + * The table is misnamed: rate is in + * 100 Hz units here, so divide by 100. + * A malformed VBIOS reporting <100 + * truncates to 0 and triggers a #DE + * in ni_calculate_sclk_params() / + * ni_populate_mclk_value() (DF-1204). + */ if ((crev == 2) && ((id == ASIC_INTERNAL_ENGINE_SS) || - (id == ASIC_INTERNAL_MEMORY_SS))) + (id == ASIC_INTERNAL_MEMORY_SS))) { + if (ss->rate < 100) + return false; ss->rate /= 100; + } return true; } ss_assign = (union asic_ss_assignment *) @@ -1589,9 +1600,16 @@ ss->percentage_divider = 1000; else ss->percentage_divider = 100; + /* + * Same divide-by-100 hazard as the v2 + * case above (DF-1204). + */ if ((id == ASIC_INTERNAL_ENGINE_SS) || - (id == ASIC_INTERNAL_MEMORY_SS)) + (id == ASIC_INTERNAL_MEMORY_SS)) { + if (ss->rate < 100) + return false; ss->rate /= 100; + } if (rdev->flags & RADEON_IS_IGP) radeon_atombios_get_igp_ss_overrides(rdev, ss, id); return true; |