Revert "nouveau: push event block/allowing out of the fence context"

This reverts commit eacabb5462.

This commit causes some regressions in desktop usage, this will
reintroduce the original deadlock in DRI_PRIME situations, I've
got an idea to fix it by offloading to a workqueue in a different
spot, however this code has a race condition where we sometimes
miss interrupts so I'd like to fix that as well.

Cc: stable@vger.kernel.org
Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
Dave Airlie 2024-01-27 04:04:34 +10:00
parent 9c4a1126ad
commit 4d7acc8f48
2 changed files with 6 additions and 27 deletions

View file

@ -62,7 +62,7 @@ nouveau_fence_signal(struct nouveau_fence *fence)
if (test_bit(DMA_FENCE_FLAG_USER_BITS, &fence->base.flags)) {
struct nouveau_fence_chan *fctx = nouveau_fctx(fence);
if (atomic_dec_and_test(&fctx->notify_ref))
if (!--fctx->notify_ref)
drop = 1;
}
@ -103,7 +103,6 @@ nouveau_fence_context_kill(struct nouveau_fence_chan *fctx, int error)
void
nouveau_fence_context_del(struct nouveau_fence_chan *fctx)
{
cancel_work_sync(&fctx->allow_block_work);
nouveau_fence_context_kill(fctx, 0);
nvif_event_dtor(&fctx->event);
fctx->dead = 1;
@ -168,18 +167,6 @@ nouveau_fence_wait_uevent_handler(struct nvif_event *event, void *repv, u32 repc
return ret;
}
static void
nouveau_fence_work_allow_block(struct work_struct *work)
{
struct nouveau_fence_chan *fctx = container_of(work, struct nouveau_fence_chan,
allow_block_work);
if (atomic_read(&fctx->notify_ref) == 0)
nvif_event_block(&fctx->event);
else
nvif_event_allow(&fctx->event);
}
void
nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_chan *fctx)
{
@ -191,7 +178,6 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha
} args;
int ret;
INIT_WORK(&fctx->allow_block_work, nouveau_fence_work_allow_block);
INIT_LIST_HEAD(&fctx->flip);
INIT_LIST_HEAD(&fctx->pending);
spin_lock_init(&fctx->lock);
@ -535,19 +521,15 @@ static bool nouveau_fence_enable_signaling(struct dma_fence *f)
struct nouveau_fence *fence = from_fence(f);
struct nouveau_fence_chan *fctx = nouveau_fctx(fence);
bool ret;
bool do_work;
if (atomic_inc_return(&fctx->notify_ref) == 0)
do_work = true;
if (!fctx->notify_ref++)
nvif_event_allow(&fctx->event);
ret = nouveau_fence_no_signaling(f);
if (ret)
set_bit(DMA_FENCE_FLAG_USER_BITS, &fence->base.flags);
else if (atomic_dec_and_test(&fctx->notify_ref))
do_work = true;
if (do_work)
schedule_work(&fctx->allow_block_work);
else if (!--fctx->notify_ref)
nvif_event_block(&fctx->event);
return ret;
}

View file

@ -3,7 +3,6 @@
#define __NOUVEAU_FENCE_H__
#include <linux/dma-fence.h>
#include <linux/workqueue.h>
#include <nvif/event.h>
struct nouveau_drm;
@ -46,9 +45,7 @@ struct nouveau_fence_chan {
char name[32];
struct nvif_event event;
struct work_struct allow_block_work;
atomic_t notify_ref;
int dead, killed;
int notify_ref, dead, killed;
};
struct nouveau_fence_priv {