Re: [PATCH] drm/msm/a5xx: Write CP_RB_WPTR under the ring's preempt_lock

From: Dmitry Baryshkov

Date: Mon Nov 02 2026 - 04:56:56 EST


On Sat, Oct 31, 2026 at 11:30:55PM -0300, Fabricio Akio wrote:
> CP_RB_WPTR tells the CP how far the ring has been filled. Two functions
> write it: a5xx_flush(), after a submit is added to the ring, and
> update_wptr(), which a5xx_preempt_trigger() calls from the IRQ handler
> each time a submit completes, whenever there is more than one ring,
> even when no ring switch follows. Both read the ring's wptr holding
> ring->preempt_lock, but write the register after releasing it, so the
> two writes can land in the wrong order:
>
> CPU A, IRQ: update_wptr() reads wptr N
> CPU B, flush: a5xx_flush() reads wptr N+1, writes N+1
> CPU A, IRQ: update_wptr() writes N
>
> CP_RB_WPTR then points behind the last submit. If the CP has already
> read past N, it treats the ring as nearly full and executes the
> commands left over from its previous pass through the ring. This shows
> up as CP opcode errors, and the old submits write old fences, so the
> fence in memptrs goes backwards. Recovery then finds no submit to
> blame and does not reset the GPU, which stays hung until reboot.
>
> Write the register before releasing the lock in both places, so the
> last value written is always the newest, as a6xx_flush() does.
>
> Fixes: b1fc2839d2f9 ("drm/msm: Implement preemption for A5XX targets")
> Signed-off-by: Fabricio Akio <fabricioakio@xxxxxxxxx>
> ---
> Tested on A508 (SDM630), with piglit's texelfetch tests run in
> parallel: CP opcode errors in each of seven one-minute runs, the
> seventh ending in a hang that never recovers; with this, none in 25.
>

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@xxxxxxxxxxxxxxxx>
Tested-by: Dmitry Baryshkov <dmitry.baryshkov@xxxxxxxxxxxxxxxx> # a530, a540


--
With best wishes
Dmitry