Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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

parents 5131bf5d dcef1f63
Loading
Loading
Loading
Loading
+11 −5
Original line number Diff line number Diff line
@@ -269,7 +269,7 @@ __pabt_svc:
	add	r5, sp, #S_PC
	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
	cmp	r2, #VIRT_OFFSET
	bichs	r3, r3, #PSR_Z_BIT
@@ -616,11 +616,17 @@ __kuser_helper_start:

__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?"
#endif
	/*
	 * Poor you.  No fast solution possible...
	 * 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:
+49 −0
Original line number Diff line number Diff line
@@ -464,6 +464,55 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
#endif
		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:
		/* Calls 9f00xx..9f07ff are defined to return -ENOSYS
		   if not implemented, rather than raising SIGILL.  This
+3 −3
Original line number Diff line number Diff line
@@ -87,9 +87,9 @@ ENTRY(__raw_writesw)
		subs	r2, r2, #2
		orr	ip, ip, r3, push_hbyte1
		strh	ip, [r0]
		bpl	2b
		bpl	1b

3:		tst	r2, #1
2:		movne	ip, r3, lsr #8
		tst	r2, #1
3:		movne	ip, r3, lsr #8
		strneh	ip, [r0]
		mov	pc, lr
+8 −0
Original line number Diff line number Diff line
@@ -422,3 +422,11 @@ config HAS_TLS_REG
	  assume directly accessing that register and always obtain the
	  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.
+2 −0
Original line number Diff line number Diff line
@@ -1296,6 +1296,7 @@
#define GPIO111_MMCDAT3		111	/* MMC DAT3 (PXA27x) */
#define GPIO111_MMCCS1		111	/* MMC Chip Select 1 (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) */

/* GPIO alternate function mode & direction */
@@ -1428,6 +1429,7 @@
#define GPIO111_MMCDAT3_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 GPIO113_I2S_SYSCLK_MD	(113 | GPIO_ALT_FN_1_OUT)
#define GPIO113_AC97_RESET_N_MD	(113 | GPIO_ALT_FN_2_OUT)
#define GPIO117_I2CSCL_MD	(117 | GPIO_ALT_FN_1_OUT)
#define GPIO118_I2CSDA_MD	(118 | GPIO_ALT_FN_1_IN)