Merge pull request 'kernel: claim src/dst at device_run, not at buf_done (fixes panic from #7)' (#8) from noether/kernel-claim-bufs-at-device-run into main
Reviewed-on: #8
This commit was merged in pull request #8.
This commit is contained in:
@@ -731,6 +731,7 @@ static void daedalus_device_run(void *priv)
|
||||
size_t blen, payload_len;
|
||||
u32 cookie;
|
||||
int ret;
|
||||
bool claimed = false; /* src/dst removed from m2m rdy_queue */
|
||||
|
||||
src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
|
||||
dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
|
||||
@@ -856,6 +857,28 @@ static void daedalus_device_run(void *priv)
|
||||
inf = kzalloc(sizeof(*inf), GFP_KERNEL);
|
||||
if (!inf)
|
||||
goto fail_buf_error;
|
||||
|
||||
/*
|
||||
* Take both buffers off the m2m ready-queue HERE — before the
|
||||
* inflight list grows. Once src_consumed releases the src side
|
||||
* and the m2m scheduler can dispatch the next device_run, the
|
||||
* NEW device_run mustn't see this dst_buf (which we're still
|
||||
* holding for a future HAS_PIXELS). Without this claim,
|
||||
* v4l2_m2m_next_dst_buf at the next device_run returns the same
|
||||
* parked dst_buf, two inflight entries reference it, and the
|
||||
* later HAS_PIXELS triggers a list_del on an already-removed
|
||||
* vb2_buffer → kernel panic (observed on Pi CM5 hard reboot
|
||||
* during mpv vaapi-copy playback of 720p H.264, 2026-05-21).
|
||||
*
|
||||
* Both helpers are inline list_del+counter-decrement under the
|
||||
* q_ctx rdy_spinlock — safe to call from device_run on the
|
||||
* buffer we just peeked via next_*_buf above. Mirrors the
|
||||
* amphion vdec/venc pattern.
|
||||
*/
|
||||
v4l2_m2m_src_buf_remove_by_buf(ctx->m2m_ctx, src_buf);
|
||||
v4l2_m2m_dst_buf_remove_by_buf(ctx->m2m_ctx, dst_buf);
|
||||
claimed = true;
|
||||
|
||||
cookie = daedalus_next_cookie();
|
||||
inf->cookie = cookie;
|
||||
inf->ctx = ctx;
|
||||
@@ -909,10 +932,12 @@ static void daedalus_device_run(void *priv)
|
||||
|
||||
fail_buf_error:
|
||||
if (src_buf) {
|
||||
if (!claimed)
|
||||
v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
|
||||
v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
|
||||
}
|
||||
if (dst_buf) {
|
||||
if (!claimed)
|
||||
v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
|
||||
v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
|
||||
}
|
||||
@@ -1074,7 +1099,13 @@ void daedalus_complete_resp_frame(u32 cookie,
|
||||
daedalus_pack_pixels_into_dst(dst_to_complete, fr,
|
||||
pixels, pixels_len);
|
||||
dst_to_complete->vb2_buf.timestamp = dst_timestamp;
|
||||
v4l2_m2m_dst_buf_remove_by_buf(ctx->m2m_ctx, dst_to_complete);
|
||||
/*
|
||||
* The buffer was already removed from m2m's rdy_queue at
|
||||
* device_run time (see the "Take both buffers off ..."
|
||||
* block). Just call buf_done here — calling
|
||||
* v4l2_m2m_dst_buf_remove_by_buf again would list_del a
|
||||
* list_head that's no longer linked, smashing the list.
|
||||
*/
|
||||
v4l2_m2m_buf_done(dst_to_complete, state);
|
||||
}
|
||||
|
||||
@@ -1091,7 +1122,7 @@ void daedalus_complete_resp_frame(u32 cookie,
|
||||
if (src_to_complete) {
|
||||
if (req_to_complete)
|
||||
v4l2_ctrl_request_complete(req_to_complete, &ctx->hdl);
|
||||
v4l2_m2m_src_buf_remove_by_buf(ctx->m2m_ctx, src_to_complete);
|
||||
/* Already off the rdy_queue (see device_run claim) — buf_done only. */
|
||||
v4l2_m2m_buf_done(src_to_complete, state);
|
||||
if (req_to_complete)
|
||||
media_request_put(req_to_complete);
|
||||
|
||||
Reference in New Issue
Block a user