Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 906c033e authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/fence: fix a race where fence->channel can disappear



Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 299bee10
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -147,16 +147,20 @@ nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr)
int
nouveau_fence_sync(struct nouveau_fence *fence, struct nouveau_channel *chan)
{
	struct nouveau_channel *prev = fence ? fence->channel : NULL;
	struct drm_device *dev = chan->dev;
	struct nouveau_fence_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FENCE);
	struct nouveau_channel *prev;
	int ret = 0;

	if (unlikely(prev && prev != chan && !nouveau_fence_done(fence))) {
		ret = priv->sync(fence, chan);
	prev = fence ? nouveau_channel_get_unlocked(fence->channel) : NULL;
	if (prev) {
		if (unlikely(prev != chan && !nouveau_fence_done(fence))) {
			ret = priv->sync(fence, prev, chan);
			if (unlikely(ret))
				ret = nouveau_fence_wait(fence, true, false);
		}
		nouveau_channel_put_unlocked(&prev);
	}

	return ret;
}
+2 −1
Original line number Diff line number Diff line
@@ -34,7 +34,8 @@ struct nouveau_fence_chan {
struct nouveau_fence_priv {
	struct nouveau_exec_engine engine;
	int (*emit)(struct nouveau_fence *);
	int (*sync)(struct nouveau_fence *, struct nouveau_channel *);
	int (*sync)(struct nouveau_fence *, struct nouveau_channel *,
		    struct nouveau_channel *);
	u32 (*read)(struct nouveau_channel *);
};

+2 −1
Original line number Diff line number Diff line
@@ -51,7 +51,8 @@ nv04_fence_emit(struct nouveau_fence *fence)
}

static int
nv04_fence_sync(struct nouveau_fence *fence, struct nouveau_channel *chan)
nv04_fence_sync(struct nouveau_fence *fence,
		struct nouveau_channel *prev, struct nouveau_channel *chan)
{
	return -ENODEV;
}
+5 −3
Original line number Diff line number Diff line
@@ -52,17 +52,19 @@ nv10_fence_emit(struct nouveau_fence *fence)
	return ret;
}


static int
nv10_fence_sync(struct nouveau_fence *fence, struct nouveau_channel *chan)
nv10_fence_sync(struct nouveau_fence *fence,
		struct nouveau_channel *prev, struct nouveau_channel *chan)
{
	return -ENODEV;
}

static int
nv17_fence_sync(struct nouveau_fence *fence, struct nouveau_channel *chan)
nv17_fence_sync(struct nouveau_fence *fence,
		struct nouveau_channel *prev, struct nouveau_channel *chan)
{
	struct nv10_fence_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_FENCE);
	struct nouveau_channel *prev = fence->channel;
	u32 value;
	int ret;

+5 −3
Original line number Diff line number Diff line
@@ -55,16 +55,18 @@ nv84_fence_emit(struct nouveau_fence *fence)
	return ret;
}


static int
nv84_fence_sync(struct nouveau_fence *fence, struct nouveau_channel *chan)
nv84_fence_sync(struct nouveau_fence *fence,
		struct nouveau_channel *prev, struct nouveau_channel *chan)
{
	int ret = RING_SPACE(chan, 7);
	if (ret == 0) {
		BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1);
		OUT_RING  (chan, NvSema);
		BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
		OUT_RING  (chan, upper_32_bits(fence->channel->id * 16));
		OUT_RING  (chan, lower_32_bits(fence->channel->id * 16));
		OUT_RING  (chan, upper_32_bits(prev->id * 16));
		OUT_RING  (chan, lower_32_bits(prev->id * 16));
		OUT_RING  (chan, fence->sequence);
		OUT_RING  (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL);
		FIRE_RING (chan);
Loading