Skip to contentSkip to conversation

drm/nouveau: initialize chan->fence.lock before use

PATCH In review Marcin Slusarz 2 participants 3 messages Sep 9, 2011 – Oct 9, 2011 2 messages not in the archive

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 drm/nouveau: initialize chan->fence.lock before use

Fence lock needs to be initialized before any call to nouveau_channel_put because it calls nouveau_channel_idle->nouveau_fence_update which uses fence lock.

BUG: spinlock bad magic on CPU#0, test/24134
 lock: ffff88019f90dba8, .magic: 00000000, .owner: <none>/-1, .owner_cpu: 0
Pid: 24134, comm: test Not tainted 3.0.0-nv+ #800
Call Trace:
 spin_bug+0x9c/0xa3
 do_raw_spin_lock+0x29/0x13c
 _raw_spin_lock+0x1e/0x22
 nouveau_fence_update+0x2d/0xf1
 nouveau_channel_idle+0x22/0xa0
 nouveau_channel_put_unlocked+0x84/0x1bd
 nouveau_channel_put+0x20/0x24
 nouveau_channel_alloc+0x4ec/0x585
 nouveau_ioctl_fifo_alloc+0x50/0x130
 drm_ioctl+0x289/0x361
 do_vfs_ioctl+0x4dd/0x52c
 sys_ioctl+0x42/0x65
 system_call_fastpath+0x16/0x1b

It's easily triggerable from userspace.

Additionally remove double initialization of chan->fence.pending.

---
 drivers/gpu/drm/nouveau/nouveau_channel.c |    1 +
 drivers/gpu/drm/nouveau/nouveau_fence.c   |    2 --
 2 files changed, 1 insertions(+), 2 deletions(-)
drivers/gpu/drm/nouveau/nouveau_channel.c +1 -0
index 85be745..62c09b0 100644
@@ -158,6 +158,7 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
 	INIT_LIST_HEAD(&chan->nvsw.vbl_wait);
 	INIT_LIST_HEAD(&chan->nvsw.flip);
 	INIT_LIST_HEAD(&chan->fence.pending);
+	spin_lock_init(&chan->fence.lock);
 
 	/* setup channel's memory and vm */
 	ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle);
drivers/gpu/drm/nouveau/nouveau_fence.c +0 -2
index c499591..614e37a 100644
@@ -568,8 +568,6 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
 			return ret;
 	}
 
-	INIT_LIST_HEAD(&chan->fence.pending);
-	spin_lock_init(&chan->fence.lock);
 	atomic_set(&chan->fence.last_sequence_irq, 0);
 	return 0;
 }
Signature · 1 line
1.7.6.1

A message that is not in the archive (sent off-list or not yet received): [email protected]

#2 lore raw
Quoted 51 lines · Marcin Slusarz

Fence lock needs to be initialized before any call to nouveau_channel_put because it calls nouveau_channel_idle->nouveau_fence_update which uses fence lock.

BUG: spinlock bad magic on CPU#0, test/24134
 lock: ffff88019f90dba8, .magic: 00000000, .owner: <none>/-1, .owner_cpu: 0
Pid: 24134, comm: test Not tainted 3.0.0-nv+ #800
Call Trace:
 spin_bug+0x9c/0xa3
 do_raw_spin_lock+0x29/0x13c
 _raw_spin_lock+0x1e/0x22
 nouveau_fence_update+0x2d/0xf1
 nouveau_channel_idle+0x22/0xa0
 nouveau_channel_put_unlocked+0x84/0x1bd
 nouveau_channel_put+0x20/0x24
 nouveau_channel_alloc+0x4ec/0x585
 nouveau_ioctl_fifo_alloc+0x50/0x130
 drm_ioctl+0x289/0x361
 do_vfs_ioctl+0x4dd/0x52c
 sys_ioctl+0x42/0x65
 system_call_fastpath+0x16/0x1b

It's easily triggerable from userspace.

Additionally remove double initialization of chan->fence.pending.

---
 drivers/gpu/drm/nouveau/nouveau_channel.c |    1 +
 drivers/gpu/drm/nouveau/nouveau_fence.c   |    2 --
 2 files changed, 1 insertions(+), 2 deletions(-)
drivers/gpu/drm/nouveau/nouveau_channel.c +1 -0
index 85be745..62c09b0 100644
@@ -158,6 +158,7 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
 	INIT_LIST_HEAD(&chan->nvsw.vbl_wait);
 	INIT_LIST_HEAD(&chan->nvsw.flip);
 	INIT_LIST_HEAD(&chan->fence.pending);
+	spin_lock_init(&chan->fence.lock);
 
 	/* setup channel's memory and vm */
 	ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle);
drivers/gpu/drm/nouveau/nouveau_fence.c +0 -0
index c499591..614e37a 100644

drivers/gpu/drm/nouveau/nouveau_fence.c nouveau_fence_channel_init(struct nouveau_channel *chan) · line 573

Quoted 8 lines
drivers/gpu/drm/nouveau/nouveau_fence.c +0 -2
@@ -568,8 +568,6 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
 			return ret;
 	}
 
-	INIT_LIST_HEAD(&chan->fence.pending);
-	spin_lock_init(&chan->fence.lock);
 	atomic_set(&chan->fence.last_sequence_irq, 0);
 	return 0;
 }

ping

A message that is not in the archive (sent off-list or not yet received): [email protected]

#4 lore raw
Quoted 4 lines · Marcin Slusarz
Quoted 3 lines · Marcin Slusarz

Fence lock needs to be initialized before any call to nouveau_channel_put because it calls nouveau_channel_idle->nouveau_fence_update which uses fence lock.

Apologies, I missed this the first time around. I've queued it up and will push today.

Thanks,
Ben.

Quoted 58 lines
Quoted 48 lines
BUG: spinlock bad magic on CPU#0, test/24134
 lock: ffff88019f90dba8, .magic: 00000000, .owner: <none>/-1, .owner_cpu: 0
Pid: 24134, comm: test Not tainted 3.0.0-nv+ #800
Call Trace:
 spin_bug+0x9c/0xa3
 do_raw_spin_lock+0x29/0x13c
 _raw_spin_lock+0x1e/0x22
 nouveau_fence_update+0x2d/0xf1
 nouveau_channel_idle+0x22/0xa0
 nouveau_channel_put_unlocked+0x84/0x1bd
 nouveau_channel_put+0x20/0x24
 nouveau_channel_alloc+0x4ec/0x585
 nouveau_ioctl_fifo_alloc+0x50/0x130
 drm_ioctl+0x289/0x361
 do_vfs_ioctl+0x4dd/0x52c
 sys_ioctl+0x42/0x65
 system_call_fastpath+0x16/0x1b

It's easily triggerable from userspace.

Additionally remove double initialization of chan->fence.pending.

---
 drivers/gpu/drm/nouveau/nouveau_channel.c |    1 +
 drivers/gpu/drm/nouveau/nouveau_fence.c   |    2 --
 2 files changed, 1 insertions(+), 2 deletions(-)
drivers/gpu/drm/nouveau/nouveau_channel.c +1 -0
index 85be745..62c09b0 100644
@@ -158,6 +158,7 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
 	INIT_LIST_HEAD(&chan->nvsw.vbl_wait);
 	INIT_LIST_HEAD(&chan->nvsw.flip);
 	INIT_LIST_HEAD(&chan->fence.pending);
+	spin_lock_init(&chan->fence.lock);
 
 	/* setup channel's memory and vm */
 	ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle);
drivers/gpu/drm/nouveau/nouveau_fence.c +0 -0
index c499591..614e37a 100644

drivers/gpu/drm/nouveau/nouveau_fence.c nouveau_fence_channel_init(struct nouveau_channel *chan) · line 573

Quoted 8 lines
drivers/gpu/drm/nouveau/nouveau_fence.c +0 -2
@@ -568,8 +568,6 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
 			return ret;
 	}
 
-	INIT_LIST_HEAD(&chan->fence.pending);
-	spin_lock_init(&chan->fence.lock);
 	atomic_set(&chan->fence.last_sequence_irq, 0);
 	return 0;
 }

ping