DF-5138 / fix.diff
--- sys/dev/drm/linux_wwmutex.c.orig +++ sys/dev/drm/linux_wwmutex.c @@ -85,6 +85,26 @@ int flags = LK_EXCLUSIVE; int error; + /* + * The lock is already held with this acquire context (a duplicate + * buffer object in a ttm_eu_reserve_buffers() validation list, or + * a drm_modeset_lock() re-lock). The Linux ww_mutex contract that + * both consumers code against returns -EALREADY here so the caller + * can move the duplicate aside (ttm_execbuf_util.c:119-124) or + * treat the relock as a no-op (drm_modeset_lock.c:270-276). + * + * Without this, the LK_CANRECURSE lockmgr silently succeeds a + * second time and ww_mutex_unlock() then decrements ctx->acquired + * only once (the second unlock sees ww->ctx == NULL), desyncing + * the ticket accounting. + * + * ctx is private to the calling thread, so observing + * ww->ctx == ctx implies we hold the lock; a same-thread store is + * visible to our own load, and no other thread can store our ctx. + */ + if (ctx != NULL && ww->ctx == ctx) + return (-EALREADY); + if (intr) flags |= LK_PCATCH; |