From: Jiri Slaby <jirislaby@kernel.org>
To: phasta@kernel.org,
"Christian König" <ckoenig.leichtzumerken@gmail.com>,
tursulin@ursulin.net, matthew.brost@intel.com,
sumit.semwal@linaro.org
Cc: dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org
Subject: Re: [PATCH 1/9] dma-buf: add dma_fence_was_initialized function v2
Date: Fri, 28 Aug 2026 09:46:18 +0200 [thread overview]
Message-ID: <f8b941a8-a468-4243-836e-aa6cebf6f3b3@kernel.org> (raw)
In-Reply-To: <0df59c80-ae58-47d3-a96b-e878a17766a7@kernel.org>
On 28. 08. 26, 9:29, Jiri Slaby wrote:
> On 19. 08. 26, 14:51, Philipp Stanner wrote:
>> On Wed, 2026-08-19 at 14:33 +0200, Philipp Stanner wrote:
>>
>>
>> […]
>>
>>>
>>> Regardless, looking at the code again, I would say that this might be a
>>> race, but I don't know enough about QXL to say for sure.
>>>
>>> dma_fence_init() is (of course) not ordered:
>>>
>>>
>>> static void
>>> __dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops
>>> *ops,
>>> spinlock_t *lock, u64 context, u64 seqno, unsigned long
>>> flags)
>>> {
>>> BUG_ON(!ops || !ops->get_driver_name || !ops->get_timeline_name);
>>>
>>> kref_init(&fence->refcount);
>>> /*
>>> * While it is counter intuitive to protect a constant function
>>> pointer
>>> * table by RCU it allows modules to wait for an RCU grace period
>>> * before they unload, to make sure that nobody is executing their
>>> * functions any more.
>>> */
>>> RCU_INIT_POINTER(fence->ops, ops);
>>> INIT_LIST_HEAD(&fence->cb_list);
>>> fence->context = context;
>>> fence->seqno = seqno;
>>> fence->flags = flags | BIT(DMA_FENCE_FLAG_INITIALIZED_BIT);
>>>
>>> (Should this maybe be set_bit() btw?)
>>>
>>>
>>> The fact that QXL could run into qxl_release_free() with an
>>> uninitialized fence hints at the fact that this might race, so
>>> DMA_FENCE_FLAG_INITIALIZED_BIT could be set / read before kref_init()
>>> ran.
>>>
>>>
>>> Maybe one way to verify / debug that would be to move
>>> spin_unlock(&qdev->release_idr_lock) downwards so it also guards
>>> dma_fence_was_initialized(), and also lock the initialization of the
>>> fence (in qxl_release_fence_buffer_objects() ?) with said lock.
>>>
>>> If that's possible. Just brainstorming a bit for ways how to debug.
>>>
>>> QXL does a few tricky things with the release->base.ops pointer.
>>> qxl_release_alloc() sets it to NULL, and only
>>> qxl_release_fence_buffer_objects() then actually sets it. So this could
>>> be the race? Setting of the ops pointer got replaced by setting of the
>>> fence-flag.
>>>
>>>
>>> P.
>>
>> Could you test something like this? (not even compile-tested, just an
>> idea)
>
> It makes the system dead during early boot :P.
>
>> diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c
>> index 87797bea91cb..df1aa48b2809 100644
>> --- a/drivers/dma-buf/dma-fence.c
>> +++ b/drivers/dma-buf/dma-fence.c
>> @@ -1075,7 +1075,6 @@ __dma_fence_init(struct dma_fence *fence, const
>> struct dma_fence_ops *ops,
>> INIT_LIST_HEAD(&fence->cb_list);
>> fence->context = context;
>> fence->seqno = seqno;
>> - fence->flags = flags | BIT(DMA_FENCE_FLAG_INITIALIZED_BIT);
>> if (lock) {
>> fence->extern_lock = lock;
>> } else {
>> @@ -1084,6 +1083,8 @@ __dma_fence_init(struct dma_fence *fence, const
>> struct dma_fence_ops *ops,
>
> This missing piece was here:
> - fence->flags |= BIT(DMA_FENCE_FLAG_INLINE_LOCK_BIT);
> + flags |= BIT(DMA_FENCE_FLAG_INLINE_LOCK_BIT);
>
>
>> }
>> fence->error = 0;
>> + smp_mb();
>> + fence->flags = flags | BIT(DMA_FENCE_FLAG_INITIALIZED_BIT);
>> trace_dma_fence_init(fence);
>> }
>
> But it does not help either...
What helps is indeed the revert back to:
--- a/drivers/gpu/drm/qxl/qxl_release.c
+++ b/drivers/gpu/drm/qxl/qxl_release.c
@@ -147,7 +147,7 @@ qxl_release_free(struct qxl_device *qdev,
idr_remove(&qdev->release_idr, release->id);
spin_unlock(&qdev->release_idr_lock);
- if (dma_fence_was_initialized(&release->base)) {
+ if (release->base.ops) {
WARN_ON(list_empty(&release->bos));
qxl_release_free_list(release);
Or the bool flag appears to help too:
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -144,6 +144,7 @@ enum {
#define QXL_MAX_RES 96
struct qxl_release {
struct dma_fence base;
+ bool uses_fence;
int id;
int type;
--- a/drivers/gpu/drm/qxl/qxl_release.c
+++ b/drivers/gpu/drm/qxl/qxl_release.c
@@ -97,6 +97,7 @@ qxl_release_alloc(struct qxl_device *qdev, int type,
return -ENOMEM;
}
release->base.ops = NULL;
+ release->uses_fence = false;
release->type = type;
release->release_offset = 0;
release->surface_release_id = 0;
@@ -147,7 +148,7 @@ qxl_release_free(struct qxl_device *qdev,
idr_remove(&qdev->release_idr, release->id);
spin_unlock(&qdev->release_idr_lock);
- if (dma_fence_was_initialized(&release->base)) {
+ if (release->uses_fence) {
WARN_ON(list_empty(&release->bos));
qxl_release_free_list(release);
@@ -431,6 +432,7 @@ void qxl_release_fence_buffer_objects(struct
qxl_release *release)
*/
dma_fence_init(&release->base, &qxl_fence_ops, &qdev->release_lock,
release->id | 0xf0000000, release->base.seqno);
+ release->uses_fence = true;
trace_dma_fence_emit(&release->base);
list_for_each_entry(entry, &release->bos, list) {
thanks,
--
js
suse labs
next prev parent reply other threads:[~2026-08-28 7:46 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-20 10:54 Independence for dma_fences! v6 Christian König
2026-01-20 10:54 ` [PATCH 1/9] dma-buf: add dma_fence_was_initialized function v2 Christian König
2026-01-20 11:33 ` Tvrtko Ursulin
2026-07-13 8:58 ` Jiri Slaby
2026-07-14 7:53 ` Philipp Stanner
2026-07-14 8:43 ` Philipp Stanner
2026-08-19 8:59 ` Jiri Slaby
2026-08-19 12:33 ` Philipp Stanner
2026-08-19 12:51 ` Philipp Stanner
2026-08-28 7:29 ` Jiri Slaby
2026-08-28 7:46 ` Jiri Slaby [this message]
2026-08-28 8:32 ` Jiri Slaby
2026-09-02 6:52 ` Philipp Stanner
2026-09-02 6:56 ` Jiri Slaby
2026-09-02 7:03 ` Philipp Stanner
2026-09-02 10:47 ` Jiri Slaby
2026-01-20 10:54 ` [PATCH 2/9] dma-buf: protected fence ops by RCU v5 Christian König
2026-01-20 10:54 ` [PATCH 3/9] dma-buf: detach fence ops on signal v2 Christian König
2026-01-20 10:54 ` [PATCH 4/9] dma-buf: abstract fence locking Christian König
2026-01-20 10:54 ` [PATCH 5/9] dma-buf: inline spinlock for fence protection v4 Christian König
2026-01-20 11:41 ` Tvrtko Ursulin
2026-01-21 8:48 ` Christian König
2026-01-21 9:03 ` Tvrtko Ursulin
2026-01-27 4:56 ` kernel test robot
2026-01-20 10:54 ` [PATCH 6/9] dma-buf/selftests: test RCU ops and inline lock v2 Christian König
2026-01-20 10:54 ` [PATCH 7/9] dma-buf: use inline lock for the stub fence v2 Christian König
2026-01-21 9:29 ` Philipp Stanner
2026-01-20 10:54 ` [PATCH 8/9] dma-buf: use inline lock for the dma-fence-array Christian König
2026-01-20 10:54 ` [PATCH 9/9] dma-buf: use inline lock for the dma-fence-chain Christian König
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=f8b941a8-a468-4243-836e-aa6cebf6f3b3@kernel.org \
--to=jirislaby@kernel.org \
--cc=ckoenig.leichtzumerken@gmail.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=linaro-mm-sig@lists.linaro.org \
--cc=matthew.brost@intel.com \
--cc=phasta@kernel.org \
--cc=sumit.semwal@linaro.org \
--cc=tursulin@ursulin.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox