summaryrefslogtreecommitdiff
path: root/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
diff options
context:
space:
mode:
authorIvan.liu <xiaowen.liu@nxp.com>2018-11-13 09:00:17 +0800
committerJason Liu <jason.hui.liu@nxp.com>2019-02-12 10:35:13 +0800
commit4a5933513caa18f127ebcc9b0f9d72ebf59975b7 (patch)
tree5baa4e2a96c33bda34309a63e6a44d18b3f9e00c /drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
parent39875c1d0dea9373bda6927a3a2596bac5d5a3a5 (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.c77
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;
}