Until now we accepted default priority arrangements for GTA02, this has UART 1 at lower priority than the SDI interrupt. That's not good because SDI IRQ service can block lower priority interrupts for 8ms or longer.
The make matters worse, arbiter 4 which holds UART1 also holds USB device and host interrupt arbitration also deals with USB host and device interrupts, meaning that they are also blocked by 8ms or more at a time. Since SDI stuff is fully sycnchronous, allowing preemption inside the interrupt service for it doesn't obviously make trouble. Until now we also used the default of all arbitrators rotating priority. This ensures that one interrupt can't block another forever, but looking at the non-fixed precedence I wonder if that's just making problems less common. So as a test this patch disables rotation. Signed-off-by: Andy Green <[email protected]> --- arch/arm/mach-s3c2440/mach-gta02.c | 13 +++++++++++++ 1 files changed, 13 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c index c9c1a4d..d4e0431 100644 --- a/arch/arm/mach-s3c2440/mach-gta02.c +++ b/arch/arm/mach-s3c2440/mach-gta02.c @@ -1737,6 +1737,19 @@ static void __init gta02_machine_init(void) break; } + /* + * set CPU IRQ priority so that priority arbiter 4 has precedence over + * priority group 3 at arbiter 6. This allows GPS UART1 to interrupt + * SDI interface ISR, it's important for us because there is no + * handshaking on that UART and SDI can block for 8+ ms, causing + * overrun if UART1 is lower priority + * + * disable rotation on all arbitors. + */ + + __raw_writel((__raw_readl(S3C2410_PRIORITY) & ~0x7f) | (3 << 19), + S3C2410_PRIORITY); + spin_lock_init(&motion_irq_lock); INIT_DELAYED_WORK(>a02_charger_work, gta02_charger_worker);
