DF-3869 / fix.diff
--- dce_calcs.c ----------------------------------------------------------- Guard the two reachable zero divisors and stop computing the horizontal_blank_and_chunk_granularity_factor when its denominator collapses to zero (degenerate-but-UABI-legal modes: hdisplay=1/htotal=3 etc.). Also guard the u32 division at the stutter burst computation. --- a/sys/dev/drm/amd/display/dc/calcs/dce_calcs.c +++ b/sys/dev/drm/amd/display/dc/calcs/dce_calcs.c @@ -836,7 +836,15 @@ static void calculate_bandwidth( if (data->line_buffer_prefetch[i] == 1 || bw_equ(data->lb_lines_in_per_line_out_in_middle_of_frame[i], bw_int_to_fixed(2)) || bw_equ(data->lb_lines_in_per_line_out_in_middle_of_frame[i], bw_int_to_fixed(4))) { data->horizontal_blank_and_chunk_granularity_factor[i] = bw_int_to_fixed(1); } - else { + else { + struct bw_fixed granularity_denominator = + bw_div((bw_add(data->h_total[i], + bw_div((bw_sub(data->source_width_pixels[i], + bw_int_to_fixed(dceip->chunk_width))), + data->hsr[i]))), bw_int_to_fixed(2)); + if (granularity_denominator.value == 0) { + /* degenerate mode: avoid #DE in bw_frc_to_fixed */ + data->horizontal_blank_and_chunk_granularity_factor[i] = bw_int_to_fixed(1); + continue; + } data->horizontal_blank_and_chunk_granularity_factor[i] = bw_div(data->h_total[i], (bw_div((bw_add(data->h_total[i], bw_div((bw_sub(data->source_width_pixels[i], bw_int_to_fixed(dceip->chunk_width))), data->hsr[i]))), bw_int_to_fixed(2)))); } @@ -1942,7 +1950,9 @@ static void calculate_bandwidth( data->stutter_burst_time = bw_div(bw_int_to_fixed(data->total_stutter_dmif_buffer_size), bw_mul(sclk[data->sclk_level], vbios->data_return_bus_width)); - data->num_stutter_bursts = data->total_bytes_requested / data->min_stutter_dmif_buffer_size; + data->num_stutter_bursts = data->min_stutter_dmif_buffer_size != 0 ? + data->total_bytes_requested / data->min_stutter_dmif_buffer_size : 0; --- bw_fixed.c ----------------------------------------------------------- Defense in depth: honor the existing ASSERT contract instead of faulting. --- a/sys/dev/drm/amd/display/dc/calcs/bw_fixed.c +++ b/sys/dev/drm/amd/display/dc/calcs/bw_fixed.c @@ -66,7 +66,12 @@ struct bw_fixed bw_frc_to_fixed(int64_t numerator, int64_t denominator) /* determine integer part */ uint64_t res_value; - ASSERT(denominator != 0); + if (denominator == 0) { + /* release builds compile ASSERT to WARN_ON; a zero divisor + * would raise #DE in div64_u64_rem and panic the kernel */ + ASSERT(0); + return numerator >= 0 ? + (struct bw_fixed){ BW_FIXED_MAX_I32 << BW_FIXED_BITS_PER_FRACTIONAL_PART } : + (struct bw_fixed){ BW_FIXED_MIN_I32 << BW_FIXED_BITS_PER_FRACTIONAL_PART }; + } |