Commit 97d26b80 authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/home/rmk/linux-2.6-arm

parents 5131bf5d dcef1f63
...@@ -269,7 +269,7 @@ __pabt_svc: ...@@ -269,7 +269,7 @@ __pabt_svc:
add r5, sp, #S_PC add r5, sp, #S_PC
ldmia r7, {r2 - r4} @ Get USR pc, cpsr ldmia r7, {r2 - r4} @ Get USR pc, cpsr
#if __LINUX_ARM_ARCH__ < 6 #if __LINUX_ARM_ARCH__ < 6 && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
@ make sure our user space atomic helper is aborted @ make sure our user space atomic helper is aborted
cmp r2, #VIRT_OFFSET cmp r2, #VIRT_OFFSET
bichs r3, r3, #PSR_Z_BIT bichs r3, r3, #PSR_Z_BIT
...@@ -616,11 +616,17 @@ __kuser_helper_start: ...@@ -616,11 +616,17 @@ __kuser_helper_start:
__kuser_cmpxchg: @ 0xffff0fc0 __kuser_cmpxchg: @ 0xffff0fc0
#if __LINUX_ARM_ARCH__ < 6 #if defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
#ifdef CONFIG_SMP /* sanity check */ /*
#error "CONFIG_SMP on a machine supporting pre-ARMv6 processors?" * Poor you. No fast solution possible...
#endif * The kernel itself must perform the operation.
* A special ghost syscall is used for that (see traps.c).
*/
swi #0x9ffff0
mov pc, lr
#elif __LINUX_ARM_ARCH__ < 6
/* /*
* Theory of operation: * Theory of operation:
......
...@@ -464,6 +464,55 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) ...@@ -464,6 +464,55 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
#endif #endif
return 0; return 0;
#ifdef CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG
/*
* Atomically store r1 in *r2 if *r2 is equal to r0 for user space.
* Return zero in r0 if *MEM was changed or non-zero if no exchange
* happened. Also set the user C flag accordingly.
* If access permissions have to be fixed up then non-zero is
* returned and the operation has to be re-attempted.
*
* *NOTE*: This is a ghost syscall private to the kernel. Only the
* __kuser_cmpxchg code in entry-armv.S should be aware of its
* existence. Don't ever use this from user code.
*/
case 0xfff0:
{
extern void do_DataAbort(unsigned long addr, unsigned int fsr,
struct pt_regs *regs);
unsigned long val;
unsigned long addr = regs->ARM_r2;
struct mm_struct *mm = current->mm;
pgd_t *pgd; pmd_t *pmd; pte_t *pte;
regs->ARM_cpsr &= ~PSR_C_BIT;
spin_lock(&mm->page_table_lock);
pgd = pgd_offset(mm, addr);
if (!pgd_present(*pgd))
goto bad_access;
pmd = pmd_offset(pgd, addr);
if (!pmd_present(*pmd))
goto bad_access;
pte = pte_offset_map(pmd, addr);
if (!pte_present(*pte) || !pte_write(*pte))
goto bad_access;
val = *(unsigned long *)addr;
val -= regs->ARM_r0;
if (val == 0) {
*(unsigned long *)addr = regs->ARM_r1;
regs->ARM_cpsr |= PSR_C_BIT;
}
spin_unlock(&mm->page_table_lock);
return val;
bad_access:
spin_unlock(&mm->page_table_lock);
/* simulate a read access fault */
do_DataAbort(addr, 15 + (1 << 11), regs);
return -1;
}
#endif
default: default:
/* Calls 9f00xx..9f07ff are defined to return -ENOSYS /* Calls 9f00xx..9f07ff are defined to return -ENOSYS
if not implemented, rather than raising SIGILL. This if not implemented, rather than raising SIGILL. This
......
...@@ -87,9 +87,9 @@ ENTRY(__raw_writesw) ...@@ -87,9 +87,9 @@ ENTRY(__raw_writesw)
subs r2, r2, #2 subs r2, r2, #2
orr ip, ip, r3, push_hbyte1 orr ip, ip, r3, push_hbyte1
strh ip, [r0] strh ip, [r0]
bpl 2b bpl 1b
3: tst r2, #1 tst r2, #1
2: movne ip, r3, lsr #8 3: movne ip, r3, lsr #8
strneh ip, [r0] strneh ip, [r0]
mov pc, lr mov pc, lr
...@@ -422,3 +422,11 @@ config HAS_TLS_REG ...@@ -422,3 +422,11 @@ config HAS_TLS_REG
assume directly accessing that register and always obtain the assume directly accessing that register and always obtain the
expected value only on ARMv7 and above. expected value only on ARMv7 and above.
config NEEDS_SYSCALL_FOR_CMPXCHG
bool
default y if SMP && (CPU_32v5 || CPU_32v4 || CPU_32v3)
help
SMP on a pre-ARMv6 processor? Well OK then.
Forget about fast user space cmpxchg support.
It is just not possible.
...@@ -1296,6 +1296,7 @@ ...@@ -1296,6 +1296,7 @@
#define GPIO111_MMCDAT3 111 /* MMC DAT3 (PXA27x) */ #define GPIO111_MMCDAT3 111 /* MMC DAT3 (PXA27x) */
#define GPIO111_MMCCS1 111 /* MMC Chip Select 1 (PXA27x) */ #define GPIO111_MMCCS1 111 /* MMC Chip Select 1 (PXA27x) */
#define GPIO112_MMCCMD 112 /* MMC CMD (PXA27x) */ #define GPIO112_MMCCMD 112 /* MMC CMD (PXA27x) */
#define GPIO113_I2S_SYSCLK 113 /* I2S System Clock (PXA27x) */
#define GPIO113_AC97_RESET_N 113 /* AC97 NRESET on (PXA27x) */ #define GPIO113_AC97_RESET_N 113 /* AC97 NRESET on (PXA27x) */
/* GPIO alternate function mode & direction */ /* GPIO alternate function mode & direction */
...@@ -1428,6 +1429,7 @@ ...@@ -1428,6 +1429,7 @@
#define GPIO111_MMCDAT3_MD (111 | GPIO_ALT_FN_1_OUT) #define GPIO111_MMCDAT3_MD (111 | GPIO_ALT_FN_1_OUT)
#define GPIO110_MMCCS1_MD (111 | GPIO_ALT_FN_1_OUT) #define GPIO110_MMCCS1_MD (111 | GPIO_ALT_FN_1_OUT)
#define GPIO112_MMCCMD_MD (112 | GPIO_ALT_FN_1_OUT) #define GPIO112_MMCCMD_MD (112 | GPIO_ALT_FN_1_OUT)
#define GPIO113_I2S_SYSCLK_MD (113 | GPIO_ALT_FN_1_OUT)
#define GPIO113_AC97_RESET_N_MD (113 | GPIO_ALT_FN_2_OUT) #define GPIO113_AC97_RESET_N_MD (113 | GPIO_ALT_FN_2_OUT)
#define GPIO117_I2CSCL_MD (117 | GPIO_ALT_FN_1_OUT) #define GPIO117_I2CSCL_MD (117 | GPIO_ALT_FN_1_OUT)
#define GPIO118_I2CSDA_MD (118 | GPIO_ALT_FN_1_IN) #define GPIO118_I2CSDA_MD (118 | GPIO_ALT_FN_1_IN)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment