diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/common/uengine.c | 6 | ||||
-rw-r--r-- | arch/arm/kernel/entry-armv.S | 96 | ||||
-rw-r--r-- | arch/arm/kernel/traps.c | 5 | ||||
-rw-r--r-- | arch/arm/mach-imx/irq.c | 51 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa27x.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa320.c | 7 | ||||
-rw-r--r-- | arch/arm/mach-pxa/ssp.c | 1 |
7 files changed, 114 insertions, 54 deletions
diff --git a/arch/arm/common/uengine.c b/arch/arm/common/uengine.c index 95c8508c29b..117cab30bd3 100644 --- a/arch/arm/common/uengine.c +++ b/arch/arm/common/uengine.c @@ -374,8 +374,8 @@ static int set_initial_registers(int uengine, struct ixp2000_uengine_code *c) u8 *ucode; int i; - gpr_a = kmalloc(128 * sizeof(u32), GFP_KERNEL); - gpr_b = kmalloc(128 * sizeof(u32), GFP_KERNEL); + gpr_a = kzalloc(128 * sizeof(u32), GFP_KERNEL); + gpr_b = kzalloc(128 * sizeof(u32), GFP_KERNEL); ucode = kmalloc(513 * 5, GFP_KERNEL); if (gpr_a == NULL || gpr_b == NULL || ucode == NULL) { kfree(ucode); @@ -388,8 +388,6 @@ static int set_initial_registers(int uengine, struct ixp2000_uengine_code *c) if (c->uengine_parameters & IXP2000_UENGINE_4_CONTEXTS) per_ctx_regs = 32; - memset(gpr_a, 0, sizeof(gpr_a)); - memset(gpr_b, 0, sizeof(gpr_b)); for (i = 0; i < 256; i++) { struct ixp2000_reg_value *r = c->initial_reg_values + i; u32 *bank; diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index d645897652c..29dec080a60 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -339,16 +339,6 @@ __pabt_svc: str r1, [sp] @ save the "real" r0 copied @ from the exception stack -#if __LINUX_ARM_ARCH__ < 6 && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) -#ifndef CONFIG_MMU -#warning "NPTL on non MMU needs fixing" -#else - @ make sure our user space atomic helper is aborted - cmp r2, #TASK_SIZE - bichs r3, r3, #PSR_Z_BIT -#endif -#endif - @ @ We are now ready to fill in the remaining blanks on the stack: @ @@ -372,9 +362,25 @@ __pabt_svc: zero_fp .endm + .macro kuser_cmpxchg_check +#if __LINUX_ARM_ARCH__ < 6 && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) +#ifndef CONFIG_MMU +#warning "NPTL on non MMU needs fixing" +#else + @ Make sure our user space atomic helper is restarted + @ if it was interrupted in a critical region. Here we + @ perform a quick test inline since it should be false + @ 99.9999% of the time. The rest is done out of line. + cmp r2, #TASK_SIZE + blhs kuser_cmpxchg_fixup +#endif +#endif + .endm + .align 5 __dabt_usr: usr_entry + kuser_cmpxchg_check @ @ Call the processor-specific abort handler: @@ -404,6 +410,7 @@ __dabt_usr: .align 5 __irq_usr: usr_entry + kuser_cmpxchg_check #ifdef CONFIG_TRACE_IRQFLAGS bl trace_hardirqs_off @@ -446,9 +453,9 @@ __und_usr: @ @ r0 - instruction @ -1: ldrt r0, [r4] adr r9, ret_from_exception adr lr, __und_usr_unknown +1: ldrt r0, [r4] @ @ fallthrough to call_fpe @ @@ -669,7 +676,7 @@ __kuser_helper_start: * * Clobbered: * - * the Z flag might be lost + * none * * Definition and user space usage example: * @@ -730,9 +737,6 @@ __kuser_memory_barrier: @ 0xffff0fa0 * * - This routine already includes memory barriers as needed. * - * - A failure might be transient, i.e. it is possible, although unlikely, - * that "failure" be returned even if *ptr == oldval. - * * For example, a user space atomic_add implementation could look like this: * * #define atomic_add(ptr, val) \ @@ -769,46 +773,62 @@ __kuser_cmpxchg: @ 0xffff0fc0 #elif __LINUX_ARM_ARCH__ < 6 +#ifdef CONFIG_MMU + /* - * Theory of operation: - * - * We set the Z flag before loading oldval. If ever an exception - * occurs we can not be sure the loaded value will still be the same - * when the exception returns, therefore the user exception handler - * will clear the Z flag whenever the interrupted user code was - * actually from the kernel address space (see the usr_entry macro). - * - * The post-increment on the str is used to prevent a race with an - * exception happening just after the str instruction which would - * clear the Z flag although the exchange was done. + * The only thing that can break atomicity in this cmpxchg + * implementation is either an IRQ or a data abort exception + * causing another process/thread to be scheduled in the middle + * of the critical sequence. To prevent this, code is added to + * the IRQ and data abort exception handlers to set the pc back + * to the beginning of the critical section if it is found to be + * within that critical section (see kuser_cmpxchg_fixup). */ -#ifdef CONFIG_MMU - teq ip, ip @ set Z flag - ldr ip, [r2] @ load current val - add r3, r2, #1 @ prepare store ptr - teqeq ip, r0 @ compare with oldval if still allowed - streq r1, [r3, #-1]! @ store newval if still allowed - subs r0, r2, r3 @ if r2 == r3 the str occured +1: ldr r3, [r2] @ load current val + subs r3, r3, r0 @ compare with oldval +2: streq r1, [r2] @ store newval if eq + rsbs r0, r3, #0 @ set return val and C flag + usr_ret lr + + .text +kuser_cmpxchg_fixup: + @ Called from kuser_cmpxchg_check macro. + @ r2 = address of interrupted insn (must be preserved). + @ sp = saved regs. r7 and r8 are clobbered. + @ 1b = first critical insn, 2b = last critical insn. + @ If r2 >= 1b and r2 <= 2b then saved pc_usr is set to 1b. + mov r7, #0xffff0fff + sub r7, r7, #(0xffff0fff - (0xffff0fc0 + (1b - __kuser_cmpxchg))) + subs r8, r2, r7 + rsbcss r8, r8, #(2b - 1b) + strcs r7, [sp, #S_PC] + mov pc, lr + .previous + #else #warning "NPTL on non MMU needs fixing" mov r0, #-1 adds r0, r0, #0 -#endif usr_ret lr +#endif #else #ifdef CONFIG_SMP mcr p15, 0, r0, c7, c10, 5 @ dmb #endif - ldrex r3, [r2] +1: ldrex r3, [r2] subs r3, r3, r0 strexeq r3, r1, [r2] + teqeq r3, #1 + beq 1b rsbs r0, r3, #0 + /* beware -- each __kuser slot must be 8 instructions max */ #ifdef CONFIG_SMP - mcr p15, 0, r0, c7, c10, 5 @ dmb -#endif + b __kuser_memory_barrier +#else usr_ret lr +#endif #endif @@ -829,7 +849,7 @@ __kuser_cmpxchg: @ 0xffff0fc0 * * Clobbered: * - * the Z flag might be lost + * none * * Definition and user space usage example: * diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 4764bd9ccee..c34db4e868f 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -327,7 +327,7 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) if ((instr & hook->instr_mask) == hook->instr_val && (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val) { if (hook->fn(regs, instr) == 0) { - spin_unlock_irq(&undef_lock); + spin_unlock_irqrestore(&undef_lock, flags); return; } } @@ -509,7 +509,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) * existence. Don't ever use this from user code. */ case 0xfff0: - { + for (;;) { extern void do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs); unsigned long val; @@ -545,7 +545,6 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) up_read(&mm->mmap_sem); /* simulate a write access fault */ do_DataAbort(addr, 15 + (1 << 11), regs); - return -1; } #endif diff --git a/arch/arm/mach-imx/irq.c b/arch/arm/mach-imx/irq.c index 0791b56caec..a7465db8489 100644 --- a/arch/arm/mach-imx/irq.c +++ b/arch/arm/mach-imx/irq.c @@ -43,12 +43,46 @@ * */ -#define INTENNUM_OFF 0x8 -#define INTDISNUM_OFF 0xC +#define INTCNTL_OFF 0x00 +#define NIMASK_OFF 0x04 +#define INTENNUM_OFF 0x08 +#define INTDISNUM_OFF 0x0C +#define INTENABLEH_OFF 0x10 +#define INTENABLEL_OFF 0x14 +#define INTTYPEH_OFF 0x18 +#define INTTYPEL_OFF 0x1C +#define NIPRIORITY_OFF(x) (0x20+4*(7-(x))) +#define NIVECSR_OFF 0x40 +#define FIVECSR_OFF 0x44 +#define INTSRCH_OFF 0x48 +#define INTSRCL_OFF 0x4C +#define INTFRCH_OFF 0x50 +#define INTFRCL_OFF 0x54 +#define NIPNDH_OFF 0x58 +#define NIPNDL_OFF 0x5C +#define FIPNDH_OFF 0x60 +#define FIPNDL_OFF 0x64 #define VA_AITC_BASE IO_ADDRESS(IMX_AITC_BASE) -#define IMX_AITC_INTDISNUM (VA_AITC_BASE + INTDISNUM_OFF) +#define IMX_AITC_INTCNTL (VA_AITC_BASE + INTCNTL_OFF) +#define IMX_AITC_NIMASK (VA_AITC_BASE + NIMASK_OFF) #define IMX_AITC_INTENNUM (VA_AITC_BASE + INTENNUM_OFF) +#define IMX_AITC_INTDISNUM (VA_AITC_BASE + INTDISNUM_OFF) +#define IMX_AITC_INTENABLEH (VA_AITC_BASE + INTENABLEH_OFF) +#define IMX_AITC_INTENABLEL (VA_AITC_BASE + INTENABLEL_OFF) +#define IMX_AITC_INTTYPEH (VA_AITC_BASE + INTTYPEH_OFF) +#define IMX_AITC_INTTYPEL (VA_AITC_BASE + INTTYPEL_OFF) +#define IMX_AITC_NIPRIORITY(x) (VA_AITC_BASE + NIPRIORITY_OFF(x)) +#define IMX_AITC_NIVECSR (VA_AITC_BASE + NIVECSR_OFF) +#define IMX_AITC_FIVECSR (VA_AITC_BASE + FIVECSR_OFF) +#define IMX_AITC_INTSRCH (VA_AITC_BASE + INTSRCH_OFF) +#define IMX_AITC_INTSRCL (VA_AITC_BASE + INTSRCL_OFF) +#define IMX_AITC_INTFRCH (VA_AITC_BASE + INTFRCH_OFF) +#define IMX_AITC_INTFRCL (VA_AITC_BASE + INTFRCL_OFF) +#define IMX_AITC_NIPNDH (VA_AITC_BASE + NIPNDH_OFF) +#define IMX_AITC_NIPNDL (VA_AITC_BASE + NIPNDL_OFF) +#define IMX_AITC_FIPNDH (VA_AITC_BASE + FIPNDH_OFF) +#define IMX_AITC_FIPNDL (VA_AITC_BASE + FIPNDL_OFF) #if 0 #define DEBUG_IRQ(fmt...) printk(fmt) @@ -222,7 +256,12 @@ imx_init_irq(void) DEBUG_IRQ("Initializing imx interrupts\n"); - /* Mask all interrupts initially */ + /* Disable all interrupts initially. */ + /* Do not rely on the bootloader. */ + __raw_writel(0, IMX_AITC_INTENABLEH); + __raw_writel(0, IMX_AITC_INTENABLEL); + + /* Mask all GPIO interrupts as well */ IMR(0) = 0; IMR(1) = 0; IMR(2) = 0; @@ -245,6 +284,6 @@ imx_init_irq(void) set_irq_chained_handler(GPIO_INT_PORTC, imx_gpioc_demux_handler); set_irq_chained_handler(GPIO_INT_PORTD, imx_gpiod_demux_handler); - /* Disable all interrupts initially. */ - /* In IMX this is done in the bootloader. */ + /* Release masking of interrupts according to priority */ + __raw_writel(-1, IMX_AITC_NIMASK); } diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index d0f2b597db1..8e126e6b74c 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -146,7 +146,7 @@ static struct clk pxa27x_clks[] = { INIT_CKEN("MMCCLK", MMC, 19500000, 0, &pxa_device_mci.dev), INIT_CKEN("FICPCLK", FICP, 48000000, 0, &pxa_device_ficp.dev), - INIT_CKEN("USBCLK", USB, 48000000, 0, &pxa27x_device_ohci.dev), + INIT_CKEN("USBCLK", USBHOST, 48000000, 0, &pxa27x_device_ohci.dev), INIT_CKEN("I2CCLK", PWRI2C, 13000000, 0, &pxa27x_device_i2c_power.dev), INIT_CKEN("KBDCLK", KEYPAD, 32768, 0, NULL), diff --git a/arch/arm/mach-pxa/pxa320.c b/arch/arm/mach-pxa/pxa320.c index 1010f77d977..74128eb8f8d 100644 --- a/arch/arm/mach-pxa/pxa320.c +++ b/arch/arm/mach-pxa/pxa320.c @@ -23,8 +23,11 @@ static struct pxa3xx_mfp_addr_map pxa320_mfp_addr_map[] __initdata = { MFP_ADDR_X(GPIO0, GPIO4, 0x0124), - MFP_ADDR_X(GPIO5, GPIO26, 0x028C), - MFP_ADDR_X(GPIO27, GPIO62, 0x0400), + MFP_ADDR_X(GPIO5, GPIO9, 0x028C), + MFP_ADDR(GPIO10, 0x0458), + MFP_ADDR_X(GPIO11, GPIO26, 0x02A0), + MFP_ADDR_X(GPIO27, GPIO48, 0x0400), + MFP_ADDR_X(GPIO49, GPIO62, 0x045C), MFP_ADDR_X(GPIO63, GPIO73, 0x04B4), MFP_ADDR_X(GPIO74, GPIO98, 0x04F0), MFP_ADDR_X(GPIO99, GPIO127, 0x0600), diff --git a/arch/arm/mach-pxa/ssp.c b/arch/arm/mach-pxa/ssp.c index 71766ac0328..422afee8816 100644 --- a/arch/arm/mach-pxa/ssp.c +++ b/arch/arm/mach-pxa/ssp.c @@ -309,6 +309,7 @@ void ssp_exit(struct ssp_dev *dev) if (dev->port > PXA_SSP_PORTS || dev->port == 0) { printk(KERN_WARNING "SSP: tried to close invalid port\n"); + mutex_unlock(&mutex); return; } |