summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorZeng Zhaoming <b32542@freescale.com>2010-11-17 16:06:49 +0800
committerJustin Waters <justin.waters@timesys.com>2010-12-13 16:10:48 -0500
commit2b0513aae41857bdef3ce4b9dfa420ab9e7ae1af (patch)
tree7cb9701d7f03426d53f26bb3c9e733bb238f41e2 /arch
parent238be18f638800d0fe0b80c238e57bb48a046bd6 (diff)
ENGR00133737 MXC SDMA: fix system hangs when play audio with irq threaded
When apply rt patch or turn on hardirq threaded in kernel, play audio by application with realtime schedule policy hangs the system. It is caused by: Requesting SDMA channel, a specific channel is used to load script and context from memory. This load phase also uses sdma to transfer, then poll a complete flag within a while(1) loop. When application with realtime schedule policy request sdma channel, it will preempt threaded irqs and prevent complete flag to be set. So a deadlock appears. Signed-off-by: Zeng Zhaoming <b32542@freescale.com> (cherry picked from commit 1d485b5d74d9585677152c3519c8d3308167de54)
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/plat-mxc/sdma/iapi/src/iapiLow.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/arch/arm/plat-mxc/sdma/iapi/src/iapiLow.c b/arch/arm/plat-mxc/sdma/iapi/src/iapiLow.c
index 92d3fa4ebf6e..47611fe52743 100644
--- a/arch/arm/plat-mxc/sdma/iapi/src/iapiLow.c
+++ b/arch/arm/plat-mxc/sdma/iapi/src/iapiLow.c
@@ -33,6 +33,8 @@
/* ****************************************************************************
* Include File Section
*****************************************************************************/
+#include <linux/preempt.h>
+#include <linux/hardirq.h>
#include "epm.h"
#include "iapiLow.h"
@@ -118,8 +120,12 @@ iapi_ChangeCallbackISR(channelDescriptor *cd_p,
*/
void iapi_lowSynchChannel(unsigned char channel)
{
- while (!((1UL << channel) & iapi_SDMAIntr))
- ;
+ if (preempt_count() || in_interrupt()) {
+ while (!((1UL << channel) & iapi_SDMAIntr))
+ ;
+ } else
+ GOTO_SLEEP(channel);
+
iapi_SDMAIntr &= ~(1UL << channel);
}