Commit 5e60ee78 authored by Marcin Slusarz's avatar Marcin Slusarz Committed by Ben Skeggs

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.
Signed-off-by: default avatarMarcin Slusarz <marcin.slusarz@gmail.com>
Cc: stable@kernel.org
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 7b4b98fa
...@@ -158,6 +158,7 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, ...@@ -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.vbl_wait);
INIT_LIST_HEAD(&chan->nvsw.flip); INIT_LIST_HEAD(&chan->nvsw.flip);
INIT_LIST_HEAD(&chan->fence.pending); INIT_LIST_HEAD(&chan->fence.pending);
spin_lock_init(&chan->fence.lock);
/* setup channel's memory and vm */ /* setup channel's memory and vm */
ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle); ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle);
......
...@@ -539,8 +539,6 @@ nouveau_fence_channel_init(struct nouveau_channel *chan) ...@@ -539,8 +539,6 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
return ret; return ret;
} }
INIT_LIST_HEAD(&chan->fence.pending);
spin_lock_init(&chan->fence.lock);
atomic_set(&chan->fence.last_sequence_irq, 0); atomic_set(&chan->fence.last_sequence_irq, 0);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment