Hello Austin Zheng,

Commit 2fb66192d389 ("drm/amd/display: Move DML Wrapper into its own
Component") from Aug 6, 2026 (linux-next), leads to the following
Smatch static checker warning:

        
drivers/gpu/drm/amd/amdgpu/../display/dc/dml2_wrapper/dml2_mall_phantom.c:613 
subvp_vblank_schedulable()
        warn: unsigned subtraction: 'subvp_active_us - prefetch_us - 
vblank_frame_us - max_vblank_mallregion' use '!='

drivers/gpu/drm/amd/amdgpu/../display/dc/dml2_wrapper/dml2_mall_phantom.c
    533 static bool subvp_vblank_schedulable(struct dml2_context *ctx, struct 
dc_state *context)
    534 {
    535         struct pipe_ctx *pipe = NULL;
    536         struct pipe_ctx *subvp_pipe = NULL;
    537         bool found = false;
    538         bool schedulable = false;
    539         int i = 0;
    540         uint8_t vblank_index = 0;
    541         uint32_t prefetch_us = 0;
    542         uint32_t mall_region_us = 0;
    543         uint32_t vblank_frame_us = 0;
    544         uint32_t subvp_active_us = 0;
    545         uint32_t vblank_blank_us = 0;
    546         uint32_t max_vblank_mallregion = 0;
    547         struct dc_crtc_timing *main_timing = NULL;
    548         struct dc_crtc_timing *phantom_timing = NULL;
    549         struct dc_crtc_timing *vblank_timing = NULL;
    550         struct dc_stream_state *phantom_stream;
    551         enum mall_stream_type pipe_mall_type;
    552 
    553         /* For SubVP + VBLANK/DRR cases, we assume there can only be
    554          * a single VBLANK/DRR display. If DML outputs SubVP + VBLANK
    555          * is supported, it is either a single VBLANK case or two VBLANK
    556          * displays which are synchronized (in which case they have 
identical
    557          * timings).
    558          */
    559         for (i = 0; i < ctx->config.dcn_pipe_count && i < MAX_PIPES ; 
i++) {
    560                 pipe = &context->res_ctx.pipe_ctx[i];
    561                 pipe_mall_type = 
ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, pipe);
    562 
    563                 // We check for master pipe, but it shouldn't matter 
since we only need
    564                 // the pipe for timing info (stream should be same for 
any pipe splits)
    565                 if (!pipe->stream || !pipe->plane_state || 
pipe->top_pipe || pipe->prev_odm_pipe)
    566                         continue;
    567 
    568                 if (!found && pipe_mall_type == SUBVP_NONE) {
    569                         // Found pipe which is not SubVP or Phantom 
(i.e. the VBLANK pipe).
    570                         ASSERT(i <= 0xFF);
    571                         vblank_index = (uint8_t)i;
    572                         found = true;
    573                 }
    574 
    575                 if (!subvp_pipe && pipe_mall_type == SUBVP_MAIN)
    576                         subvp_pipe = pipe;
    577         }
    578 
    579         if (subvp_pipe == NULL) {
    580                 // Defensive: should never happen, catch in debug
    581                 ASSERT(0);
    582                 return false;
    583         }
    584 
    585         // Use ignore_msa_timing_param flag to identify as DRR
    586         if (found && 
context->res_ctx.pipe_ctx[vblank_index].stream->ignore_msa_timing_param) {
    587                 // SUBVP + DRR case
    588                 schedulable = dml2_svp_drr_schedulable(ctx, context, 
&context->res_ctx.pipe_ctx[vblank_index].stream->timing);
    589         } else if (found) {
    590                 phantom_stream = 
ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(context, 
subvp_pipe->stream);
    591                 main_timing = &subvp_pipe->stream->timing;
    592                 phantom_timing = &phantom_stream->timing;
    593                 vblank_timing = 
&context->res_ctx.pipe_ctx[vblank_index].stream->timing;
    594                 // Prefetch time is equal to VACTIVE + BP + VSYNC of 
the phantom pipe
    595                 // Also include the prefetch end to mallstart delay time
    596                 prefetch_us = (uint32_t)((phantom_timing->v_total - 
phantom_timing->v_front_porch) * phantom_timing->h_total /
    597                                 (double)(phantom_timing->pix_clk_100hz 
* 100) * 1000000 +
    598                                 
ctx->config.svp_pstate.subvp_prefetch_end_to_mall_start_us);
    599                 // P-State allow width and FW delays already included 
phantom_timing->v_addressable
    600                 mall_region_us = 
(uint32_t)(phantom_timing->v_addressable * phantom_timing->h_total /
    601                                 (double)(phantom_timing->pix_clk_100hz 
* 100) * 1000000);
    602                 vblank_frame_us = (uint32_t)(vblank_timing->v_total * 
vblank_timing->h_total /
    603                                 (double)(vblank_timing->pix_clk_100hz * 
100) * 1000000);
    604                 vblank_blank_us = (uint32_t)((vblank_timing->v_total - 
vblank_timing->v_addressable) * vblank_timing->h_total /
    605                                 (double)(vblank_timing->pix_clk_100hz * 
100) * 1000000);
    606                 subvp_active_us = (uint32_t)(main_timing->v_addressable 
* main_timing->h_total /
    607                                 (double)(main_timing->pix_clk_100hz * 
100) * 1000000);
    608                 max_vblank_mallregion = vblank_blank_us > 
mall_region_us ? vblank_blank_us : mall_region_us;
    609 
    610                 // Schedulable if VACTIVE region of the SubVP pipe can 
fit the MALL prefetch, VBLANK frame time,
    611                 // and the max of (VBLANK blanking time, MALL region)
    612                 // TODO: Possibly add some margin (i.e. the below 
conditions should be [...] > X instead of [...] > 0)
--> 613                 if (subvp_active_us - prefetch_us - vblank_frame_us - 
max_vblank_mallregion > 0)
                            
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
These variables are unsigned so this is testing if != 0 instead of > 0.

Claude went a bit crazy and made a bunch of unrelated changes and no one
reviewed it.  HashtagSadFace.  There is similar math in
dml2_svp_drr_schedulable() where the math is signed.  I asked ChatGPT's
cheapest model to review this and it said this was a bug.  AI Fight!

    614                         schedulable = true;
    615         }
    616         return schedulable;
    617 }

This email is a free service from the Smatch-CI project [smatch.sf.net].

regards,
dan carpenter

Reply via email to