diff options
author | Vladimir Kondratyev <wulf@FreeBSD.org> | 2022-01-18 20:14:13 +0000 |
---|---|---|
committer | Vladimir Kondratyev <wulf@FreeBSD.org> | 2022-01-18 20:14:13 +0000 |
commit | 89889ab470b9f1a1cd36913dd219b78efbf484df (patch) | |
tree | 50f5f258d68ce764f6c6d83378d86c3f34067802 | |
parent | 02ea6033020e11afec6472bf560b0ddebd0fa97a (diff) | |
download | src-89889ab470b9f1a1cd36913dd219b78efbf484df.tar.gz src-89889ab470b9f1a1cd36913dd219b78efbf484df.zip |
LinuxKPI: Allow wake_up to be executed within a critical section
by replaceing of spin_lock() call with spin_lock_irqsave()
This fixes following panic in drm-kmod:
panic: mi_switch: switch in a critical section
cpuid = 2
time = 1636939794
KDB: stack backtrace:
db_trace_self_wrapper() at db_trace_self_wrapper+0x2b
vpanic() at vpanic+0x187
panic() at panic+0x43
mi_switch() at mi_switch+0x198
__mtx_lock_sleep() at __mtx_lock_sleep+0x1c9
__mtx_lock_flags() at __mtx_lock_flags+0xa2
linux_wake_up() at linux_wake_up+0x38
__active_retire() at __active_retire+0xb7
dma_fence_signal() at dma_fence_signal+0x100
dma_resv_add_shared_fence() at dma_resv_add_shared_fence+0x96
i915_gem_do_execbuffer() at i915_gem_do_execbuffer+0x11d0
i915_gem_execbuffer2_ioctl() at i915_gem_execbuffer2_ioctl+0x19a
drm_ioctl_kernel() at drm_ioctl_kernel+0x72
drm_ioctl() at drm_ioctl+0x2c4
linux_file_ioctl() at linux_file_ioctl+0x297
kern_ioctl() at kern_ioctl+0x1dc
sys_ioctl() at sys_ioctl+0x124
amd64_syscall() at amd64_syscall+0x124
fast_syscall_common() at fast_syscall_common+0xf8
--- syscall (54, FreeBSD ELF64, sys_ioctl)
MFC after: 1 week
Reviewed by: manu
Reported by: Graham Perrin <grahamperrin_AT_gmail_DOT_com>
PR: 261166
Differential Revision: https://reviews.freebsd.org/D33888
-rw-r--r-- | sys/compat/linuxkpi/common/src/linux_schedule.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/sys/compat/linuxkpi/common/src/linux_schedule.c b/sys/compat/linuxkpi/common/src/linux_schedule.c index 656d8697d169..02074be8eb19 100644 --- a/sys/compat/linuxkpi/common/src/linux_schedule.c +++ b/sys/compat/linuxkpi/common/src/linux_schedule.c @@ -202,9 +202,11 @@ void linux_wake_up(wait_queue_head_t *wqh, unsigned int state, int nr, bool locked) { wait_queue_t *pos, *next; + unsigned long flags; if (!locked) - spin_lock(&wqh->lock); + spin_lock_irqsave(&wqh->lock, flags); + list_for_each_entry_safe(pos, next, &wqh->task_list, task_list) { if (pos->func == NULL) { if (wake_up_task(pos->private, state) != 0 && --nr == 0) @@ -215,7 +217,7 @@ linux_wake_up(wait_queue_head_t *wqh, unsigned int state, int nr, bool locked) } } if (!locked) - spin_unlock(&wqh->lock); + spin_unlock_irqrestore(&wqh->lock, flags); } void |