diff options
author | Ivan.liu <xiaowen.liu@nxp.com> | 2018-11-13 09:00:17 +0800 |
---|---|---|
committer | Jason Liu <jason.hui.liu@nxp.com> | 2019-02-12 10:35:13 +0800 |
commit | 4a5933513caa18f127ebcc9b0f9d72ebf59975b7 (patch) | |
tree | 5baa4e2a96c33bda34309a63e6a44d18b3f9e00c /drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c | |
parent | 39875c1d0dea9373bda6927a3a2596bac5d5a3a5 (diff) |
MA-13203-2 [#imx-1237] Fix kernel panic when do video plaback with dual display on 8mq.
BUG: scheduling while atomic: swapper/0/0/0x00010002
CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.14.62 #1
Call trace:
[<ffff00000808b2e0>] dump_backtrace+0x0/0x414
[<ffff00000808b708>] show_stack+0x14/0x1c
[<ffff000008fbd00c>] dump_stack+0x90/0xb0
[<ffff00000810b8fc>] __schedule_bug+0x50/0x6c
[<ffff000008fd3b18>] __schedule+0x720/0x8a8
[<ffff000008fd3cd8>] schedule+0x38/0x9c
[<ffff000008fd40f0>] schedule_preempt_disabled+0x20/0x38
[<ffff000008fd51d8>] __mutex_lock.isra.9+0x4dc/0x4fc
[<ffff000008fd5208>] __mutex_lock_slowpath+0x10/0x18
[<ffff000008fd5240>] mutex_lock+0x30/0x38
[<ffff000008b79960>] gckOS_DestroySignal+0x30/0xcc
[<ffff000008baa3b8>] viv_fence_release+0x24/0x38
[<ffff0000087babcc>] dma_fence_release+0x38/0xf4
[<ffff0000087bb55c>] dma_fence_array_release+0x78/0xac
[<ffff0000087babcc>] dma_fence_release+0x38/0xf4
[<ffff0000087bb748>] irq_dma_fence_array_work+0x40/0x4c
[<ffff0000081d2878>] irq_work_run_list+0x68/0xa8
[<ffff0000081d28dc>] irq_work_run+0x24/0x40
[<ffff000008092440>] handle_IPI+0x300/0x330
[<ffff00000808197c>] gic_handle_irq+0x8c/0x184
Replace signal mutex lock with spin lock to handle signal in irq.
Change-Id: Id18e68f03bcb96c2aaf3ca8a0055fe6a64e8d10a
Signed-off-by: Ivan.liu <xiaowen.liu@nxp.com>
Diffstat (limited to 'drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c')
-rw-r--r-- | drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c | 77 |
1 files changed, 29 insertions, 48 deletions
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c index 7be6e7912bc4..7e8eb1dd3838 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c @@ -276,11 +276,12 @@ _AllocateIntegerId( { int result; gctINT next; + unsigned long flags; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) idr_preload(GFP_KERNEL | gcdNOWARN); - spin_lock(&Database->lock); + spin_lock_irqsave(&Database->lock, flags); next = (Database->curr + 1 <= 0) ? 1 : Database->curr + 1; @@ -294,7 +295,7 @@ _AllocateIntegerId( Database->curr = *Id = result; } - spin_unlock(&Database->lock); + spin_unlock_irqrestore(&Database->lock, flags); idr_preload_end(); @@ -309,7 +310,7 @@ again: return gcvSTATUS_OUT_OF_MEMORY; } - spin_lock(&Database->lock); + spin_lock_irqsave(&Database->lock, flags); next = (Database->curr + 1 <= 0) ? 1 : Database->curr + 1; @@ -321,7 +322,7 @@ again: Database->curr = *Id; } - spin_unlock(&Database->lock); + spin_unlock_irqstore(&Database->lock, flags); if (result == -EAGAIN) { @@ -345,12 +346,13 @@ _QueryIntegerId( ) { gctPOINTER pointer; + unsigned long flags; - spin_lock(&Database->lock); + spin_lock_irqsave(&Database->lock, flags); pointer = idr_find(&Database->idr, Id); - spin_unlock(&Database->lock); + spin_unlock_irqrestore(&Database->lock, flags); if (pointer) { @@ -374,12 +376,8 @@ _DestroyIntegerId( IN gctUINT32 Id ) { - spin_lock(&Database->lock); - idr_remove(&Database->idr, Id); - spin_unlock(&Database->lock); - return gcvSTATUS_OK; } @@ -549,9 +547,6 @@ gckOS_Construct( * Initialize the signal manager. */ - /* Initialize mutex. */ - mutex_init(&os->signalMutex); - /* Initialize signal id database lock. */ spin_lock_init(&os->signalDB.lock); @@ -5535,8 +5530,7 @@ gckOS_CreateSignal( init_waitqueue_head(&signal->wait); spin_lock_init(&signal->lock); signal->manualReset = ManualReset; - - atomic_set(&signal->ref, 1); + signal->ref = 1; #if gcdANDROID_NATIVE_FENCE_SYNC #if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0) @@ -5589,7 +5583,7 @@ gckOS_DestroySignal( { gceSTATUS status; gcsSIGNAL_PTR signal; - gctBOOL acquired = gcvFALSE; + unsigned long flags; gcmkHEADER_ARG("Os=0x%X Signal=0x%X", Os, Signal); @@ -5597,35 +5591,26 @@ gckOS_DestroySignal( gcmkVERIFY_OBJECT(Os, gcvOBJ_OS); gcmkVERIFY_ARGUMENT(Signal != gcvNULL); - mutex_lock(&Os->signalMutex); - acquired = gcvTRUE; - gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal)); + spin_lock_irqsave(&Os->signalDB.lock, flags); gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal); + signal->ref--; - if (atomic_dec_and_test(&signal->ref)) + if (signal->ref == 0) { gcmkVERIFY_OK(_DestroyIntegerId(&Os->signalDB, signal->id)); /* Free the sgianl. */ kfree(signal); } - - mutex_unlock(&Os->signalMutex); - acquired = gcvFALSE; + spin_unlock_irqrestore(&Os->signalDB.lock, flags); /* Success. */ gcmkFOOTER_NO(); return gcvSTATUS_OK; OnError: - if (acquired) - { - /* Release the mutex. */ - mutex_unlock(&Os->signalMutex); - } - gcmkFOOTER(); return status; } @@ -5668,6 +5653,7 @@ gckOS_Signal( struct dma_fence * fence = gcvNULL; # endif #endif + unsigned long flags; gcmkHEADER_ARG("Os=0x%X Signal=0x%X State=%d", Os, Signal, State); @@ -5675,30 +5661,25 @@ gckOS_Signal( gcmkVERIFY_OBJECT(Os, gcvOBJ_OS); gcmkVERIFY_ARGUMENT(Signal != gcvNULL); - mutex_lock(&Os->signalMutex); - status = _QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal); if (gcmIS_ERROR(status)) { - mutex_unlock(&Os->signalMutex); gcmkONERROR(status); } + spin_lock_irqsave(&Os->signalDB.lock, flags); /* * Signal saved in event is not referenced. Inc reference here to avoid * concurrent issue: signaling the signal while another thread is destroying * it. */ - atomic_inc(&signal->ref); - - mutex_unlock(&Os->signalMutex); - - gcmkONERROR(status); gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal); + signal->ref++; + spin_unlock_irqrestore(&Os->signalDB.lock, flags); spin_lock(&signal->lock); @@ -5740,17 +5721,17 @@ gckOS_Signal( # endif #endif - mutex_lock(&Os->signalMutex); + spin_lock_irqsave(&Os->signalDB.lock, flags); + signal->ref --; - if (atomic_dec_and_test(&signal->ref)) + if (signal->ref == 0) { gcmkVERIFY_OK(_DestroyIntegerId(&Os->signalDB, signal->id)); /* Free the sgianl. */ kfree(signal); } - - mutex_unlock(&Os->signalMutex); + spin_unlock_irqrestore(&Os->signalDB.lock, flags); /* Success. */ gcmkFOOTER_NO(); @@ -5975,32 +5956,32 @@ gckOS_MapSignal( { gceSTATUS status; gcsSIGNAL_PTR signal = gcvNULL; + unsigned long flags; gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=0x%X", Os, Signal, Process); gcmkVERIFY_ARGUMENT(Signal != gcvNULL); gcmkVERIFY_ARGUMENT(MappedSignal != gcvNULL); - mutex_lock(&Os->signalMutex); - gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal)); - if (atomic_inc_return(&signal->ref) <= 1) + spin_lock_irqsave(&Os->signalDB.lock, flags); + signal->ref++; + + if (signal->ref <= 1) { + spin_unlock_irqrestore(&Os->signalDB.lock, flags); /* The previous value is 0, it has been deleted. */ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } *MappedSignal = (gctSIGNAL) Signal; - - mutex_unlock(&Os->signalMutex); + spin_unlock_irqrestore(&Os->signalDB.lock, flags); /* Success. */ gcmkFOOTER_ARG("*MappedSignal=0x%X", *MappedSignal); return gcvSTATUS_OK; OnError: - mutex_unlock(&Os->signalMutex); - gcmkFOOTER_NO(); return status; } |