瀏覽代碼

Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus

* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus:
  [MIPS] Cleanup memory barriers for weakly ordered systems.
  [MIPS] Alchemy: Automatically enable CONFIG_RESOURCES_64BIT for PCI configs.
  [MIPS] Unify csum_partial.S
  [MIPS] SWARM: Fix a typo in #error directives
  [MIPS] Fix atomic.h build errors.
  [MIPS] Use SYSVIPC_COMPAT to fix various problems on N32
  [MIPS] klconfig add missing bracket
Linus Torvalds 18 年之前
父節點
當前提交
91f433cacc

+ 18 - 0
arch/mips/Kconfig

@@ -16,6 +16,7 @@ config MIPS_MTX1
 	bool "4G Systems MTX-1 board"
 	bool "4G Systems MTX-1 board"
 	select DMA_NONCOHERENT
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select HW_HAS_PCI
+	select RESOURCES_64BIT if PCI
 	select SOC_AU1500
 	select SOC_AU1500
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -32,6 +33,7 @@ config MIPS_PB1000
 	select SOC_AU1000
 	select SOC_AU1000
 	select DMA_NONCOHERENT
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select HW_HAS_PCI
+	select RESOURCES_64BIT if PCI
 	select SWAP_IO_SPACE
 	select SWAP_IO_SPACE
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -41,6 +43,7 @@ config MIPS_PB1100
 	select SOC_AU1100
 	select SOC_AU1100
 	select DMA_NONCOHERENT
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select HW_HAS_PCI
+	select RESOURCES_64BIT if PCI
 	select SWAP_IO_SPACE
 	select SWAP_IO_SPACE
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -50,6 +53,7 @@ config MIPS_PB1500
 	select SOC_AU1500
 	select SOC_AU1500
 	select DMA_NONCOHERENT
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select HW_HAS_PCI
+	select RESOURCES_64BIT if PCI
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 
 
@@ -59,6 +63,7 @@ config MIPS_PB1550
 	select DMA_NONCOHERENT
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select HW_HAS_PCI
 	select MIPS_DISABLE_OBSOLETE_IDE
 	select MIPS_DISABLE_OBSOLETE_IDE
+	select RESOURCES_64BIT if PCI
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 
 
@@ -67,6 +72,7 @@ config MIPS_PB1200
 	select SOC_AU1200
 	select SOC_AU1200
 	select DMA_NONCOHERENT
 	select DMA_NONCOHERENT
 	select MIPS_DISABLE_OBSOLETE_IDE
 	select MIPS_DISABLE_OBSOLETE_IDE
+	select RESOURCES_64BIT if PCI
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 
 
@@ -75,6 +81,7 @@ config MIPS_DB1000
 	select SOC_AU1000
 	select SOC_AU1000
 	select DMA_NONCOHERENT
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select HW_HAS_PCI
+	select RESOURCES_64BIT if PCI
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 
 
@@ -91,6 +98,7 @@ config MIPS_DB1500
 	select DMA_NONCOHERENT
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select HW_HAS_PCI
 	select MIPS_DISABLE_OBSOLETE_IDE
 	select MIPS_DISABLE_OBSOLETE_IDE
+	select RESOURCES_64BIT if PCI
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -101,6 +109,7 @@ config MIPS_DB1550
 	select HW_HAS_PCI
 	select HW_HAS_PCI
 	select DMA_NONCOHERENT
 	select DMA_NONCOHERENT
 	select MIPS_DISABLE_OBSOLETE_IDE
 	select MIPS_DISABLE_OBSOLETE_IDE
+	select RESOURCES_64BIT if PCI
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 
 
@@ -1268,6 +1277,7 @@ config CPU_RM9000
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
 	select CPU_SUPPORTS_HIGHMEM
+	select WEAK_ORDERING
 
 
 config CPU_SB1
 config CPU_SB1
 	bool "SB1"
 	bool "SB1"
@@ -1276,6 +1286,7 @@ config CPU_SB1
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
 	select CPU_SUPPORTS_HIGHMEM
+	select WEAK_ORDERING
 
 
 endchoice
 endchoice
 
 
@@ -1336,6 +1347,8 @@ config SYS_HAS_CPU_RM9000
 config SYS_HAS_CPU_SB1
 config SYS_HAS_CPU_SB1
 	bool
 	bool
 
 
+config WEAK_ORDERING
+	bool
 endmenu
 endmenu
 
 
 #
 #
@@ -1940,6 +1953,11 @@ config COMPAT
 	depends on MIPS32_COMPAT
 	depends on MIPS32_COMPAT
 	default y
 	default y
 
 
+config SYSVIPC_COMPAT
+	bool
+	depends on COMPAT && SYSVIPC
+	default y
+
 config MIPS32_O32
 config MIPS32_O32
 	bool "Kernel support for o32 binaries"
 	bool "Kernel support for o32 binaries"
 	depends on MIPS32_COMPAT
 	depends on MIPS32_COMPAT

+ 23 - 555
arch/mips/kernel/linux32.c

@@ -382,531 +382,6 @@ asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid,
 	return ret;
 	return ret;
 }
 }
 
 
-struct msgbuf32 { s32 mtype; char mtext[1]; };
-
-struct ipc_perm32
-{
-	key_t    	  key;
-        __compat_uid_t  uid;
-        __compat_gid_t  gid;
-        __compat_uid_t  cuid;
-        __compat_gid_t  cgid;
-        compat_mode_t	mode;
-        unsigned short  seq;
-};
-
-struct ipc64_perm32 {
-	key_t key;
-	__compat_uid_t uid;
-	__compat_gid_t gid;
-	__compat_uid_t cuid;
-	__compat_gid_t cgid;
-	compat_mode_t	mode;
-	unsigned short	seq;
-	unsigned short __pad1;
-	unsigned int __unused1;
-	unsigned int __unused2;
-};
-
-struct semid_ds32 {
-        struct ipc_perm32 sem_perm;               /* permissions .. see ipc.h */
-        compat_time_t   sem_otime;              /* last semop time */
-        compat_time_t   sem_ctime;              /* last change time */
-        u32 sem_base;              /* ptr to first semaphore in array */
-        u32 sem_pending;          /* pending operations to be processed */
-        u32 sem_pending_last;    /* last pending operation */
-        u32 undo;                  /* undo requests on this array */
-        unsigned short  sem_nsems;              /* no. of semaphores in array */
-};
-
-struct semid64_ds32 {
-	struct ipc64_perm32	sem_perm;
-	compat_time_t	sem_otime;
-	compat_time_t	sem_ctime;
-	unsigned int		sem_nsems;
-	unsigned int		__unused1;
-	unsigned int		__unused2;
-};
-
-struct msqid_ds32
-{
-        struct ipc_perm32 msg_perm;
-        u32 msg_first;
-        u32 msg_last;
-        compat_time_t   msg_stime;
-        compat_time_t   msg_rtime;
-        compat_time_t   msg_ctime;
-        u32 wwait;
-        u32 rwait;
-        unsigned short msg_cbytes;
-        unsigned short msg_qnum;
-        unsigned short msg_qbytes;
-        compat_ipc_pid_t msg_lspid;
-        compat_ipc_pid_t msg_lrpid;
-};
-
-struct msqid64_ds32 {
-	struct ipc64_perm32 msg_perm;
-	compat_time_t msg_stime;
-	unsigned int __unused1;
-	compat_time_t msg_rtime;
-	unsigned int __unused2;
-	compat_time_t msg_ctime;
-	unsigned int __unused3;
-	unsigned int msg_cbytes;
-	unsigned int msg_qnum;
-	unsigned int msg_qbytes;
-	compat_pid_t msg_lspid;
-	compat_pid_t msg_lrpid;
-	unsigned int __unused4;
-	unsigned int __unused5;
-};
-
-struct shmid_ds32 {
-        struct ipc_perm32       shm_perm;
-        int                     shm_segsz;
-        compat_time_t		shm_atime;
-        compat_time_t		shm_dtime;
-        compat_time_t		shm_ctime;
-        compat_ipc_pid_t    shm_cpid;
-        compat_ipc_pid_t    shm_lpid;
-        unsigned short          shm_nattch;
-};
-
-struct shmid64_ds32 {
-	struct ipc64_perm32	shm_perm;
-	compat_size_t		shm_segsz;
-	compat_time_t		shm_atime;
-	compat_time_t		shm_dtime;
-	compat_time_t shm_ctime;
-	compat_pid_t shm_cpid;
-	compat_pid_t shm_lpid;
-	unsigned int shm_nattch;
-	unsigned int __unused1;
-	unsigned int __unused2;
-};
-
-struct ipc_kludge32 {
-	u32 msgp;
-	s32 msgtyp;
-};
-
-static int
-do_sys32_semctl(int first, int second, int third, void __user *uptr)
-{
-	union semun fourth;
-	u32 pad;
-	int err, err2;
-	struct semid64_ds s;
-	mm_segment_t old_fs;
-
-	if (!uptr)
-		return -EINVAL;
-	err = -EFAULT;
-	if (get_user (pad, (u32 __user *)uptr))
-		return err;
-	if ((third & ~IPC_64) == SETVAL)
-		fourth.val = (int)pad;
-	else
-		fourth.__pad = (void __user *)A(pad);
-	switch (third & ~IPC_64) {
-	case IPC_INFO:
-	case IPC_RMID:
-	case IPC_SET:
-	case SEM_INFO:
-	case GETVAL:
-	case GETPID:
-	case GETNCNT:
-	case GETZCNT:
-	case GETALL:
-	case SETVAL:
-	case SETALL:
-		err = sys_semctl (first, second, third, fourth);
-		break;
-
-	case IPC_STAT:
-	case SEM_STAT:
-		fourth.__pad = (struct semid64_ds __user *)&s;
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		err = sys_semctl(first, second, third | IPC_64, fourth);
-		set_fs(old_fs);
-
-		if (third & IPC_64) {
-			struct semid64_ds32 __user *usp64 = (struct semid64_ds32 __user *) A(pad);
-
-			if (!access_ok(VERIFY_WRITE, usp64, sizeof(*usp64))) {
-				err = -EFAULT;
-				break;
-			}
-			err2 = __put_user(s.sem_perm.key, &usp64->sem_perm.key);
-			err2 |= __put_user(s.sem_perm.uid, &usp64->sem_perm.uid);
-			err2 |= __put_user(s.sem_perm.gid, &usp64->sem_perm.gid);
-			err2 |= __put_user(s.sem_perm.cuid, &usp64->sem_perm.cuid);
-			err2 |= __put_user(s.sem_perm.cgid, &usp64->sem_perm.cgid);
-			err2 |= __put_user(s.sem_perm.mode, &usp64->sem_perm.mode);
-			err2 |= __put_user(s.sem_perm.seq, &usp64->sem_perm.seq);
-			err2 |= __put_user(s.sem_otime, &usp64->sem_otime);
-			err2 |= __put_user(s.sem_ctime, &usp64->sem_ctime);
-			err2 |= __put_user(s.sem_nsems, &usp64->sem_nsems);
-		} else {
-			struct semid_ds32 __user *usp32 = (struct semid_ds32 __user *) A(pad);
-
-			if (!access_ok(VERIFY_WRITE, usp32, sizeof(*usp32))) {
-				err = -EFAULT;
-				break;
-			}
-			err2 = __put_user(s.sem_perm.key, &usp32->sem_perm.key);
-			err2 |= __put_user(s.sem_perm.uid, &usp32->sem_perm.uid);
-			err2 |= __put_user(s.sem_perm.gid, &usp32->sem_perm.gid);
-			err2 |= __put_user(s.sem_perm.cuid, &usp32->sem_perm.cuid);
-			err2 |= __put_user(s.sem_perm.cgid, &usp32->sem_perm.cgid);
-			err2 |= __put_user(s.sem_perm.mode, &usp32->sem_perm.mode);
-			err2 |= __put_user(s.sem_perm.seq, &usp32->sem_perm.seq);
-			err2 |= __put_user(s.sem_otime, &usp32->sem_otime);
-			err2 |= __put_user(s.sem_ctime, &usp32->sem_ctime);
-			err2 |= __put_user(s.sem_nsems, &usp32->sem_nsems);
-		}
-		if (err2)
-			err = -EFAULT;
-		break;
-
-	default:
-		err = - EINVAL;
-		break;
-	}
-
-	return err;
-}
-
-static int
-do_sys32_msgsnd (int first, int second, int third, void __user *uptr)
-{
-	struct msgbuf32 __user *up = (struct msgbuf32 __user *)uptr;
-	struct msgbuf *p;
-	mm_segment_t old_fs;
-	int err;
-
-	if (second < 0)
-		return -EINVAL;
-	p = kmalloc (second + sizeof (struct msgbuf)
-				    + 4, GFP_USER);
-	if (!p)
-		return -ENOMEM;
-	err = get_user (p->mtype, &up->mtype);
-	if (err)
-		goto out;
-	err |= __copy_from_user (p->mtext, &up->mtext, second);
-	if (err)
-		goto out;
-	old_fs = get_fs ();
-	set_fs (KERNEL_DS);
-	err = sys_msgsnd (first, (struct msgbuf __user *)p, second, third);
-	set_fs (old_fs);
-out:
-	kfree (p);
-
-	return err;
-}
-
-static int
-do_sys32_msgrcv (int first, int second, int msgtyp, int third,
-		 int version, void __user *uptr)
-{
-	struct msgbuf32 __user *up;
-	struct msgbuf *p;
-	mm_segment_t old_fs;
-	int err;
-
-	if (!version) {
-		struct ipc_kludge32 __user *uipck = (struct ipc_kludge32 __user *)uptr;
-		struct ipc_kludge32 ipck;
-
-		err = -EINVAL;
-		if (!uptr)
-			goto out;
-		err = -EFAULT;
-		if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge32)))
-			goto out;
-		uptr = (void __user *)AA(ipck.msgp);
-		msgtyp = ipck.msgtyp;
-	}
-
-	if (second < 0)
-		return -EINVAL;
-	err = -ENOMEM;
-	p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER);
-	if (!p)
-		goto out;
-	old_fs = get_fs ();
-	set_fs (KERNEL_DS);
-	err = sys_msgrcv (first, (struct msgbuf __user *)p, second + 4, msgtyp, third);
-	set_fs (old_fs);
-	if (err < 0)
-		goto free_then_out;
-	up = (struct msgbuf32 __user *)uptr;
-	if (put_user (p->mtype, &up->mtype) ||
-	    __copy_to_user (&up->mtext, p->mtext, err))
-		err = -EFAULT;
-free_then_out:
-	kfree (p);
-out:
-	return err;
-}
-
-static int
-do_sys32_msgctl (int first, int second, void __user *uptr)
-{
-	int err = -EINVAL, err2;
-	struct msqid64_ds m;
-	struct msqid_ds32 __user *up32 = (struct msqid_ds32 __user *)uptr;
-	struct msqid64_ds32 __user *up64 = (struct msqid64_ds32 __user *)uptr;
-	mm_segment_t old_fs;
-
-	switch (second & ~IPC_64) {
-	case IPC_INFO:
-	case IPC_RMID:
-	case MSG_INFO:
-		err = sys_msgctl (first, second, (struct msqid_ds __user *)uptr);
-		break;
-
-	case IPC_SET:
-		if (second & IPC_64) {
-			if (!access_ok(VERIFY_READ, up64, sizeof(*up64))) {
-				err = -EFAULT;
-				break;
-			}
-			err = __get_user(m.msg_perm.uid, &up64->msg_perm.uid);
-			err |= __get_user(m.msg_perm.gid, &up64->msg_perm.gid);
-			err |= __get_user(m.msg_perm.mode, &up64->msg_perm.mode);
-			err |= __get_user(m.msg_qbytes, &up64->msg_qbytes);
-		} else {
-			if (!access_ok(VERIFY_READ, up32, sizeof(*up32))) {
-				err = -EFAULT;
-				break;
-			}
-			err = __get_user(m.msg_perm.uid, &up32->msg_perm.uid);
-			err |= __get_user(m.msg_perm.gid, &up32->msg_perm.gid);
-			err |= __get_user(m.msg_perm.mode, &up32->msg_perm.mode);
-			err |= __get_user(m.msg_qbytes, &up32->msg_qbytes);
-		}
-		if (err)
-			break;
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		err = sys_msgctl(first, second | IPC_64, (struct msqid_ds __user *)&m);
-		set_fs(old_fs);
-		break;
-
-	case IPC_STAT:
-	case MSG_STAT:
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		err = sys_msgctl(first, second | IPC_64, (struct msqid_ds __user *)&m);
-		set_fs(old_fs);
-		if (second & IPC_64) {
-			if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
-				err = -EFAULT;
-				break;
-			}
-			err2 = __put_user(m.msg_perm.key, &up64->msg_perm.key);
-			err2 |= __put_user(m.msg_perm.uid, &up64->msg_perm.uid);
-			err2 |= __put_user(m.msg_perm.gid, &up64->msg_perm.gid);
-			err2 |= __put_user(m.msg_perm.cuid, &up64->msg_perm.cuid);
-			err2 |= __put_user(m.msg_perm.cgid, &up64->msg_perm.cgid);
-			err2 |= __put_user(m.msg_perm.mode, &up64->msg_perm.mode);
-			err2 |= __put_user(m.msg_perm.seq, &up64->msg_perm.seq);
-			err2 |= __put_user(m.msg_stime, &up64->msg_stime);
-			err2 |= __put_user(m.msg_rtime, &up64->msg_rtime);
-			err2 |= __put_user(m.msg_ctime, &up64->msg_ctime);
-			err2 |= __put_user(m.msg_cbytes, &up64->msg_cbytes);
-			err2 |= __put_user(m.msg_qnum, &up64->msg_qnum);
-			err2 |= __put_user(m.msg_qbytes, &up64->msg_qbytes);
-			err2 |= __put_user(m.msg_lspid, &up64->msg_lspid);
-			err2 |= __put_user(m.msg_lrpid, &up64->msg_lrpid);
-			if (err2)
-				err = -EFAULT;
-		} else {
-			if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
-				err = -EFAULT;
-				break;
-			}
-			err2 = __put_user(m.msg_perm.key, &up32->msg_perm.key);
-			err2 |= __put_user(m.msg_perm.uid, &up32->msg_perm.uid);
-			err2 |= __put_user(m.msg_perm.gid, &up32->msg_perm.gid);
-			err2 |= __put_user(m.msg_perm.cuid, &up32->msg_perm.cuid);
-			err2 |= __put_user(m.msg_perm.cgid, &up32->msg_perm.cgid);
-			err2 |= __put_user(m.msg_perm.mode, &up32->msg_perm.mode);
-			err2 |= __put_user(m.msg_perm.seq, &up32->msg_perm.seq);
-			err2 |= __put_user(m.msg_stime, &up32->msg_stime);
-			err2 |= __put_user(m.msg_rtime, &up32->msg_rtime);
-			err2 |= __put_user(m.msg_ctime, &up32->msg_ctime);
-			err2 |= __put_user(m.msg_cbytes, &up32->msg_cbytes);
-			err2 |= __put_user(m.msg_qnum, &up32->msg_qnum);
-			err2 |= __put_user(m.msg_qbytes, &up32->msg_qbytes);
-			err2 |= __put_user(m.msg_lspid, &up32->msg_lspid);
-			err2 |= __put_user(m.msg_lrpid, &up32->msg_lrpid);
-			if (err2)
-				err = -EFAULT;
-		}
-		break;
-	}
-
-	return err;
-}
-
-static int
-do_sys32_shmat (int first, int second, int third, int version, void __user *uptr)
-{
-	unsigned long raddr;
-	u32 __user *uaddr = (u32 __user *)A((u32)third);
-	int err = -EINVAL;
-
-	if (version == 1)
-		return err;
-	err = do_shmat (first, uptr, second, &raddr);
-	if (err)
-		return err;
-	err = put_user (raddr, uaddr);
-	return err;
-}
-
-struct shm_info32 {
-	int used_ids;
-	u32 shm_tot, shm_rss, shm_swp;
-	u32 swap_attempts, swap_successes;
-};
-
-static int
-do_sys32_shmctl (int first, int second, void __user *uptr)
-{
-	struct shmid64_ds32 __user *up64 = (struct shmid64_ds32 __user *)uptr;
-	struct shmid_ds32 __user *up32 = (struct shmid_ds32 __user *)uptr;
-	struct shm_info32 __user *uip = (struct shm_info32 __user *)uptr;
-	int err = -EFAULT, err2;
-	struct shmid64_ds s64;
-	mm_segment_t old_fs;
-	struct shm_info si;
-	struct shmid_ds s;
-
-	switch (second & ~IPC_64) {
-	case IPC_INFO:
-		second = IPC_INFO; /* So that we don't have to translate it */
-	case IPC_RMID:
-	case SHM_LOCK:
-	case SHM_UNLOCK:
-		err = sys_shmctl(first, second, (struct shmid_ds __user *)uptr);
-		break;
-	case IPC_SET:
-		if (second & IPC_64) {
-			err = get_user(s.shm_perm.uid, &up64->shm_perm.uid);
-			err |= get_user(s.shm_perm.gid, &up64->shm_perm.gid);
-			err |= get_user(s.shm_perm.mode, &up64->shm_perm.mode);
-		} else {
-			err = get_user(s.shm_perm.uid, &up32->shm_perm.uid);
-			err |= get_user(s.shm_perm.gid, &up32->shm_perm.gid);
-			err |= get_user(s.shm_perm.mode, &up32->shm_perm.mode);
-		}
-		if (err)
-			break;
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		err = sys_shmctl(first, second & ~IPC_64, (struct shmid_ds __user *)&s);
-		set_fs(old_fs);
-		break;
-
-	case IPC_STAT:
-	case SHM_STAT:
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		err = sys_shmctl(first, second | IPC_64, (void __user *) &s64);
-		set_fs(old_fs);
-		if (err < 0)
-			break;
-		if (second & IPC_64) {
-			if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
-				err = -EFAULT;
-				break;
-			}
-			err2 = __put_user(s64.shm_perm.key, &up64->shm_perm.key);
-			err2 |= __put_user(s64.shm_perm.uid, &up64->shm_perm.uid);
-			err2 |= __put_user(s64.shm_perm.gid, &up64->shm_perm.gid);
-			err2 |= __put_user(s64.shm_perm.cuid, &up64->shm_perm.cuid);
-			err2 |= __put_user(s64.shm_perm.cgid, &up64->shm_perm.cgid);
-			err2 |= __put_user(s64.shm_perm.mode, &up64->shm_perm.mode);
-			err2 |= __put_user(s64.shm_perm.seq, &up64->shm_perm.seq);
-			err2 |= __put_user(s64.shm_atime, &up64->shm_atime);
-			err2 |= __put_user(s64.shm_dtime, &up64->shm_dtime);
-			err2 |= __put_user(s64.shm_ctime, &up64->shm_ctime);
-			err2 |= __put_user(s64.shm_segsz, &up64->shm_segsz);
-			err2 |= __put_user(s64.shm_nattch, &up64->shm_nattch);
-			err2 |= __put_user(s64.shm_cpid, &up64->shm_cpid);
-			err2 |= __put_user(s64.shm_lpid, &up64->shm_lpid);
-		} else {
-			if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
-				err = -EFAULT;
-				break;
-			}
-			err2 = __put_user(s64.shm_perm.key, &up32->shm_perm.key);
-			err2 |= __put_user(s64.shm_perm.uid, &up32->shm_perm.uid);
-			err2 |= __put_user(s64.shm_perm.gid, &up32->shm_perm.gid);
-			err2 |= __put_user(s64.shm_perm.cuid, &up32->shm_perm.cuid);
-			err2 |= __put_user(s64.shm_perm.cgid, &up32->shm_perm.cgid);
-			err2 |= __put_user(s64.shm_perm.mode, &up32->shm_perm.mode);
-			err2 |= __put_user(s64.shm_perm.seq, &up32->shm_perm.seq);
-			err2 |= __put_user(s64.shm_atime, &up32->shm_atime);
-			err2 |= __put_user(s64.shm_dtime, &up32->shm_dtime);
-			err2 |= __put_user(s64.shm_ctime, &up32->shm_ctime);
-			err2 |= __put_user(s64.shm_segsz, &up32->shm_segsz);
-			err2 |= __put_user(s64.shm_nattch, &up32->shm_nattch);
-			err2 |= __put_user(s64.shm_cpid, &up32->shm_cpid);
-			err2 |= __put_user(s64.shm_lpid, &up32->shm_lpid);
-		}
-		if (err2)
-			err = -EFAULT;
-		break;
-
-	case SHM_INFO:
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		err = sys_shmctl(first, second, (void __user *)&si);
-		set_fs(old_fs);
-		if (err < 0)
-			break;
-		err2 = put_user(si.used_ids, &uip->used_ids);
-		err2 |= __put_user(si.shm_tot, &uip->shm_tot);
-		err2 |= __put_user(si.shm_rss, &uip->shm_rss);
-		err2 |= __put_user(si.shm_swp, &uip->shm_swp);
-		err2 |= __put_user(si.swap_attempts, &uip->swap_attempts);
-		err2 |= __put_user (si.swap_successes, &uip->swap_successes);
-		if (err2)
-			err = -EFAULT;
-		break;
-
-	default:
-		err = -EINVAL;
-		break;
-	}
-
-	return err;
-}
-
-static int sys32_semtimedop(int semid, struct sembuf __user *tsems, int nsems,
-                            const struct compat_timespec __user *timeout32)
-{
-	struct compat_timespec t32;
-	struct timespec __user *t64 = compat_alloc_user_space(sizeof(*t64));
-
-	if (copy_from_user(&t32, timeout32, sizeof(t32)))
-		return -EFAULT;
-
-	if (put_user(t32.tv_sec, &t64->tv_sec) ||
-	    put_user(t32.tv_nsec, &t64->tv_nsec))
-		return -EFAULT;
-
-	return sys_semtimedop(semid, tsems, nsems, t64);
-}
-
 asmlinkage long
 asmlinkage long
 sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
 sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
 {
 {
@@ -918,48 +393,43 @@ sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
 	switch (call) {
 	switch (call) {
 	case SEMOP:
 	case SEMOP:
 		/* struct sembuf is the same on 32 and 64bit :)) */
 		/* struct sembuf is the same on 32 and 64bit :)) */
-		err = sys_semtimedop (first, (struct sembuf __user *)AA(ptr), second,
-		                      NULL);
+		err = sys_semtimedop(first, compat_ptr(ptr), second, NULL);
 		break;
 		break;
 	case SEMTIMEDOP:
 	case SEMTIMEDOP:
-		err = sys32_semtimedop (first, (struct sembuf __user *)AA(ptr), second,
-		                      (const struct compat_timespec __user *)AA(fifth));
+		err = compat_sys_semtimedop(first, compat_ptr(ptr), second,
+					    compat_ptr(fifth));
 		break;
 		break;
 	case SEMGET:
 	case SEMGET:
-		err = sys_semget (first, second, third);
+		err = sys_semget(first, second, third);
 		break;
 		break;
 	case SEMCTL:
 	case SEMCTL:
-		err = do_sys32_semctl (first, second, third,
-				       (void __user *)AA(ptr));
+		err = compat_sys_semctl(first, second, third, compat_ptr(ptr));
 		break;
 		break;
-
 	case MSGSND:
 	case MSGSND:
-		err = do_sys32_msgsnd (first, second, third,
-				       (void __user *)AA(ptr));
+		err = compat_sys_msgsnd(first, second, third, compat_ptr(ptr));
 		break;
 		break;
 	case MSGRCV:
 	case MSGRCV:
-		err = do_sys32_msgrcv (first, second, fifth, third,
-				       version, (void __user *)AA(ptr));
+		err = compat_sys_msgrcv(first, second, fifth, third,
+					version, compat_ptr(ptr));
 		break;
 		break;
 	case MSGGET:
 	case MSGGET:
-		err = sys_msgget ((key_t) first, second);
+		err = sys_msgget((key_t) first, second);
 		break;
 		break;
 	case MSGCTL:
 	case MSGCTL:
-		err = do_sys32_msgctl (first, second, (void __user *)AA(ptr));
+		err = compat_sys_msgctl(first, second, compat_ptr(ptr));
 		break;
 		break;
-
 	case SHMAT:
 	case SHMAT:
-		err = do_sys32_shmat (first, second, third,
-				      version, (void __user *)AA(ptr));
+		err = compat_sys_shmat(first, second, third, version,
+				       compat_ptr(ptr));
 		break;
 		break;
 	case SHMDT:
 	case SHMDT:
-		err = sys_shmdt ((char __user *)A(ptr));
+		err = sys_shmdt(compat_ptr(ptr));
 		break;
 		break;
 	case SHMGET:
 	case SHMGET:
-		err = sys_shmget (first, (unsigned)second, third);
+		err = sys_shmget(first, (unsigned)second, third);
 		break;
 		break;
 	case SHMCTL:
 	case SHMCTL:
-		err = do_sys32_shmctl (first, second, (void __user *)AA(ptr));
+		err = compat_sys_shmctl(first, second, compat_ptr(ptr));
 		break;
 		break;
 	default:
 	default:
 		err = -EINVAL;
 		err = -EINVAL;
@@ -969,18 +439,16 @@ sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
 	return err;
 	return err;
 }
 }
 
 
-asmlinkage long sys32_shmat(int shmid, char __user *shmaddr,
-			  int shmflg, int32_t __user *addr)
+#ifdef CONFIG_MIPS32_N32
+asmlinkage long sysn32_semctl(int semid, int semnum, int cmd, union semun arg)
 {
 {
-	unsigned long raddr;
-	int err;
-
-	err = do_shmat(shmid, shmaddr, shmflg, &raddr);
-	if (err)
-		return err;
-
-	return put_user(raddr, addr);
+	/* compat_sys_semctl expects a pointer to union semun */
+	u32 __user *uptr = compat_alloc_user_space(sizeof(u32));
+	if (put_user(ptr_to_compat(arg.__pad), uptr))
+		return -EFAULT;
+	return compat_sys_semctl(semid, semnum, cmd, uptr);
 }
 }
+#endif
 
 
 struct sysctl_args32
 struct sysctl_args32
 {
 {

+ 7 - 7
arch/mips/kernel/scall64-n32.S

@@ -149,8 +149,8 @@ EXPORT(sysn32_call_table)
 	PTR	sys_mincore
 	PTR	sys_mincore
 	PTR	sys_madvise
 	PTR	sys_madvise
 	PTR	sys_shmget
 	PTR	sys_shmget
-	PTR	sys32_shmat
-	PTR	sys_shmctl			/* 6030 */
+	PTR	sys_shmat
+	PTR	compat_sys_shmctl			/* 6030 */
 	PTR	sys_dup
 	PTR	sys_dup
 	PTR	sys_dup2
 	PTR	sys_dup2
 	PTR	sys_pause
 	PTR	sys_pause
@@ -184,12 +184,12 @@ EXPORT(sysn32_call_table)
 	PTR	sys32_newuname
 	PTR	sys32_newuname
 	PTR	sys_semget
 	PTR	sys_semget
 	PTR	sys_semop
 	PTR	sys_semop
-	PTR	sys_semctl
+	PTR	sysn32_semctl
 	PTR	sys_shmdt			/* 6065 */
 	PTR	sys_shmdt			/* 6065 */
 	PTR	sys_msgget
 	PTR	sys_msgget
-	PTR	sys_msgsnd
-	PTR	sys_msgrcv
-	PTR	sys_msgctl
+	PTR	compat_sys_msgsnd
+	PTR	compat_sys_msgrcv
+	PTR	compat_sys_msgctl
 	PTR	compat_sys_fcntl		/* 6070 */
 	PTR	compat_sys_fcntl		/* 6070 */
 	PTR	sys_flock
 	PTR	sys_flock
 	PTR	sys_fsync
 	PTR	sys_fsync
@@ -335,7 +335,7 @@ EXPORT(sysn32_call_table)
 	PTR	compat_sys_fcntl64
 	PTR	compat_sys_fcntl64
 	PTR	sys_set_tid_address
 	PTR	sys_set_tid_address
 	PTR	sys_restart_syscall
 	PTR	sys_restart_syscall
-	PTR	sys_semtimedop			/* 6215 */
+	PTR	compat_sys_semtimedop			/* 6215 */
 	PTR	sys_fadvise64_64
 	PTR	sys_fadvise64_64
 	PTR	compat_sys_statfs64
 	PTR	compat_sys_statfs64
 	PTR	compat_sys_fstatfs64
 	PTR	compat_sys_fstatfs64

+ 3 - 3
arch/mips/kernel/smp.c

@@ -172,7 +172,7 @@ int smp_call_function (void (*func) (void *info), void *info, int retry,
 
 
 	spin_lock(&smp_call_lock);
 	spin_lock(&smp_call_lock);
 	call_data = &data;
 	call_data = &data;
-	mb();
+	smp_mb();
 
 
 	/* Send a message to all other CPUs and wait for them to respond */
 	/* Send a message to all other CPUs and wait for them to respond */
 	for_each_online_cpu(i)
 	for_each_online_cpu(i)
@@ -204,7 +204,7 @@ void smp_call_function_interrupt(void)
 	 * Notify initiating CPU that I've grabbed the data and am
 	 * Notify initiating CPU that I've grabbed the data and am
 	 * about to execute the function.
 	 * about to execute the function.
 	 */
 	 */
-	mb();
+	smp_mb();
 	atomic_inc(&call_data->started);
 	atomic_inc(&call_data->started);
 
 
 	/*
 	/*
@@ -215,7 +215,7 @@ void smp_call_function_interrupt(void)
 	irq_exit();
 	irq_exit();
 
 
 	if (wait) {
 	if (wait) {
-		mb();
+		smp_mb();
 		atomic_inc(&call_data->finished);
 		atomic_inc(&call_data->finished);
 	}
 	}
 }
 }

+ 1 - 1
arch/mips/lib-32/Makefile

@@ -2,7 +2,7 @@
 # Makefile for MIPS-specific library files..
 # Makefile for MIPS-specific library files..
 #
 #
 
 
-lib-y	+= csum_partial.o memset.o watch.o
+lib-y	+= memset.o watch.o
 
 
 obj-$(CONFIG_CPU_MIPS32)	+= dump_tlb.o
 obj-$(CONFIG_CPU_MIPS32)	+= dump_tlb.o
 obj-$(CONFIG_CPU_MIPS64)	+= dump_tlb.o
 obj-$(CONFIG_CPU_MIPS64)	+= dump_tlb.o

+ 0 - 240
arch/mips/lib-32/csum_partial.S

@@ -1,240 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1998 Ralf Baechle
- */
-#include <asm/asm.h>
-#include <asm/regdef.h>
-
-#define ADDC(sum,reg)			\
-	addu	sum, reg;		\
-	sltu	v1, sum, reg;		\
-	addu	sum, v1
-
-#define CSUM_BIGCHUNK(src, offset, sum, t0, t1, t2, t3) \
-	lw	t0, (offset + 0x00)(src); \
-	lw	t1, (offset + 0x04)(src); \
-	lw	t2, (offset + 0x08)(src); \
-	lw	t3, (offset + 0x0c)(src); \
-	ADDC(sum, t0);                    \
-	ADDC(sum, t1);                    \
-	ADDC(sum, t2);                    \
-	ADDC(sum, t3);                    \
-	lw	t0, (offset + 0x10)(src); \
-	lw	t1, (offset + 0x14)(src); \
-	lw	t2, (offset + 0x18)(src); \
-	lw	t3, (offset + 0x1c)(src); \
-	ADDC(sum, t0);                    \
-	ADDC(sum, t1);                    \
-	ADDC(sum, t2);                    \
-	ADDC(sum, t3);                    \
-
-/*
- * a0: source address
- * a1: length of the area to checksum
- * a2: partial checksum
- */
-
-#define src a0
-#define dest a1
-#define sum v0
-
-	.text
-	.set	noreorder
-
-/* unknown src alignment and < 8 bytes to go  */
-small_csumcpy:
-	move	a1, t2
-
-	andi	t0, a1, 4
-	beqz	t0, 1f
-	 andi	t0, a1, 2
-
-	/* Still a full word to go  */
-	ulw	t1, (src)
-	addiu	src, 4
-	ADDC(sum, t1)
-
-1:	move	t1, zero
-	beqz	t0, 1f
-	 andi	t0, a1, 1
-
-	/* Still a halfword to go  */
-	ulhu	t1, (src)
-	addiu	src, 2
-
-1:	beqz	t0, 1f
-	 sll	t1, t1, 16
-
-	lbu	t2, (src)
-	 nop
-
-#ifdef __MIPSEB__
-	sll	t2, t2, 8
-#endif
-	or	t1, t2
-
-1:	ADDC(sum, t1)
-
-	/* fold checksum */
-	sll	v1, sum, 16
-	addu	sum, v1
-	sltu	v1, sum, v1
-	srl	sum, sum, 16
-	addu	sum, v1
-
-	/* odd buffer alignment? */
-	beqz	t7, 1f
-	 nop
-	sll	v1, sum, 8
-	srl	sum, sum, 8
-	or	sum, v1
-	andi	sum, 0xffff
-1:
-	.set	reorder
-	/* Add the passed partial csum.  */
-	ADDC(sum, a2)
-	jr	ra
-	.set	noreorder
-
-/* ------------------------------------------------------------------------- */
-
-	.align	5
-LEAF(csum_partial)
-	move	sum, zero
-	move	t7, zero
-
-	sltiu	t8, a1, 0x8
-	bnez	t8, small_csumcpy		/* < 8 bytes to copy */
-	 move	t2, a1
-
-	beqz	a1, out
-	 andi	t7, src, 0x1			/* odd buffer? */
-
-hword_align:
-	beqz	t7, word_align
-	 andi	t8, src, 0x2
-
-	lbu	t0, (src)
-	subu	a1, a1, 0x1
-#ifdef __MIPSEL__
-	sll	t0, t0, 8
-#endif
-	ADDC(sum, t0)
-	addu	src, src, 0x1
-	andi	t8, src, 0x2
-
-word_align:
-	beqz	t8, dword_align
-	 sltiu	t8, a1, 56
-
-	lhu	t0, (src)
-	subu	a1, a1, 0x2
-	ADDC(sum, t0)
-	sltiu	t8, a1, 56
-	addu	src, src, 0x2
-
-dword_align:
-	bnez	t8, do_end_words
-	 move	t8, a1
-
-	andi	t8, src, 0x4
-	beqz	t8, qword_align
-	 andi	t8, src, 0x8
-
-	lw	t0, 0x00(src)
-	subu	a1, a1, 0x4
-	ADDC(sum, t0)
-	addu	src, src, 0x4
-	andi	t8, src, 0x8
-
-qword_align:
-	beqz	t8, oword_align
-	 andi	t8, src, 0x10
-
-	lw	t0, 0x00(src)
-	lw	t1, 0x04(src)
-	subu	a1, a1, 0x8
-	ADDC(sum, t0)
-	ADDC(sum, t1)
-	addu	src, src, 0x8
-	andi	t8, src, 0x10
-
-oword_align:
-	beqz	t8, begin_movement
-	 srl	t8, a1, 0x7
-
-	lw	t3, 0x08(src)
-	lw	t4, 0x0c(src)
-	lw	t0, 0x00(src)
-	lw	t1, 0x04(src)
-	ADDC(sum, t3)
-	ADDC(sum, t4)
-	ADDC(sum, t0)
-	ADDC(sum, t1)
-	subu	a1, a1, 0x10
-	addu	src, src, 0x10
-	srl	t8, a1, 0x7
-
-begin_movement:
-	beqz	t8, 1f
-	 andi	t2, a1, 0x40
-
-move_128bytes:
-	CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
-	CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4)
-	CSUM_BIGCHUNK(src, 0x40, sum, t0, t1, t3, t4)
-	CSUM_BIGCHUNK(src, 0x60, sum, t0, t1, t3, t4)
-	subu	t8, t8, 0x01
-	bnez	t8, move_128bytes
-	 addu	src, src, 0x80
-
-1:
-	beqz	t2, 1f
-	 andi	t2, a1, 0x20
-
-move_64bytes:
-	CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
-	CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4)
-	addu	src, src, 0x40
-
-1:
-	beqz	t2, do_end_words
-	 andi	t8, a1, 0x1c
-
-move_32bytes:
-	CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
-	andi	t8, a1, 0x1c
-	addu	src, src, 0x20
-
-do_end_words:
-	beqz	t8, maybe_end_cruft
-	 srl	t8, t8, 0x2
-
-end_words:
-	lw	t0, (src)
-	subu	t8, t8, 0x1
-	ADDC(sum, t0)
-	bnez	t8, end_words
-	 addu	src, src, 0x4
-
-maybe_end_cruft:
-	andi	t2, a1, 0x3
-
-small_memcpy:
- j small_csumcpy; move a1, t2
-	beqz	t2, out
-	 move	a1, t2
-
-end_bytes:
-	lb	t0, (src)
-	subu	a1, a1, 0x1
-	bnez	a2, end_bytes
-	 addu	src, src, 0x1
-
-out:
-	jr	ra
-	 move	v0, sum
-	END(csum_partial)

+ 1 - 1
arch/mips/lib-64/Makefile

@@ -2,7 +2,7 @@
 # Makefile for MIPS-specific library files..
 # Makefile for MIPS-specific library files..
 #
 #
 
 
-lib-y	+= csum_partial.o memset.o watch.o
+lib-y	+= memset.o watch.o
 
 
 obj-$(CONFIG_CPU_MIPS32)	+= dump_tlb.o
 obj-$(CONFIG_CPU_MIPS32)	+= dump_tlb.o
 obj-$(CONFIG_CPU_MIPS64)	+= dump_tlb.o
 obj-$(CONFIG_CPU_MIPS64)	+= dump_tlb.o

+ 0 - 242
arch/mips/lib-64/csum_partial.S

@@ -1,242 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Quick'n'dirty IP checksum ...
- *
- * Copyright (C) 1998, 1999 Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
- */
-#include <asm/asm.h>
-#include <asm/regdef.h>
-
-#define ADDC(sum,reg)						\
-	addu	sum, reg;					\
-	sltu	v1, sum, reg;					\
-	addu	sum, v1
-
-#define CSUM_BIGCHUNK(src, offset, sum, t0, t1, t2, t3)		\
-	lw	t0, (offset + 0x00)(src);			\
-	lw	t1, (offset + 0x04)(src);			\
-	lw	t2, (offset + 0x08)(src); 			\
-	lw	t3, (offset + 0x0c)(src); 			\
-	ADDC(sum, t0);						\
-	ADDC(sum, t1);						\
-	ADDC(sum, t2);						\
-	ADDC(sum, t3);						\
-	lw	t0, (offset + 0x10)(src);			\
-	lw	t1, (offset + 0x14)(src);			\
-	lw	t2, (offset + 0x18)(src);			\
-	lw	t3, (offset + 0x1c)(src);			\
-	ADDC(sum, t0);						\
-	ADDC(sum, t1);						\
-	ADDC(sum, t2);						\
-	ADDC(sum, t3);						\
-
-/*
- * a0: source address
- * a1: length of the area to checksum
- * a2: partial checksum
- */
-
-#define src a0
-#define sum v0
-
-	.text
-	.set	noreorder
-
-/* unknown src alignment and < 8 bytes to go  */
-small_csumcpy:
-	move	a1, ta2
-
-	andi	ta0, a1, 4
-	beqz	ta0, 1f
-	 andi	ta0, a1, 2
-
-	/* Still a full word to go  */
-	ulw	ta1, (src)
-	daddiu	src, 4
-	ADDC(sum, ta1)
-
-1:	move	ta1, zero
-	beqz	ta0, 1f
-	 andi	ta0, a1, 1
-
-	/* Still a halfword to go  */
-	ulhu	ta1, (src)
-	daddiu	src, 2
-
-1:	beqz	ta0, 1f
-	 sll	ta1, ta1, 16
-
-	lbu	ta2, (src)
-	 nop
-
-#ifdef __MIPSEB__
-	sll	ta2, ta2, 8
-#endif
-	or	ta1, ta2
-
-1:	ADDC(sum, ta1)
-
-	/* fold checksum */
-	sll	v1, sum, 16
-	addu	sum, v1
-	sltu	v1, sum, v1
-	srl	sum, sum, 16
-	addu	sum, v1
-
-	/* odd buffer alignment? */
-	beqz	t3, 1f
-	 nop
-	sll	v1, sum, 8
-	srl	sum, sum, 8
-	or	sum, v1
-	andi	sum, 0xffff
-1:
-	.set	reorder
-	/* Add the passed partial csum.  */
-	ADDC(sum, a2)
-	jr	ra
-	.set	noreorder
-
-/* ------------------------------------------------------------------------- */
-
-	.align	5
-LEAF(csum_partial)
-	move	sum, zero
-	move	t3, zero
-
-	sltiu	t8, a1, 0x8
-	bnez	t8, small_csumcpy		/* < 8 bytes to copy */
-	 move	ta2, a1
-
-	beqz	a1, out
-	 andi	t3, src, 0x1			/* odd buffer? */
-
-hword_align:
-	beqz	t3, word_align
-	 andi	t8, src, 0x2
-
-	lbu	ta0, (src)
-	dsubu	a1, a1, 0x1
-#ifdef __MIPSEL__
-	sll	ta0, ta0, 8
-#endif
-	ADDC(sum, ta0)
-	daddu	src, src, 0x1
-	andi	t8, src, 0x2
-
-word_align:
-	beqz	t8, dword_align
-	 sltiu	t8, a1, 56
-
-	lhu	ta0, (src)
-	dsubu	a1, a1, 0x2
-	ADDC(sum, ta0)
-	sltiu	t8, a1, 56
-	daddu	src, src, 0x2
-
-dword_align:
-	bnez	t8, do_end_words
-	 move	t8, a1
-
-	andi	t8, src, 0x4
-	beqz	t8, qword_align
-	 andi	t8, src, 0x8
-
-	lw	ta0, 0x00(src)
-	dsubu	a1, a1, 0x4
-	ADDC(sum, ta0)
-	daddu	src, src, 0x4
-	andi	t8, src, 0x8
-
-qword_align:
-	beqz	t8, oword_align
-	 andi	t8, src, 0x10
-
-	lw	ta0, 0x00(src)
-	lw	ta1, 0x04(src)
-	dsubu	a1, a1, 0x8
-	ADDC(sum, ta0)
-	ADDC(sum, ta1)
-	daddu	src, src, 0x8
-	andi	t8, src, 0x10
-
-oword_align:
-	beqz	t8, begin_movement
-	 dsrl	t8, a1, 0x7
-
-	lw	ta3, 0x08(src)
-	lw	t0, 0x0c(src)
-	lw	ta0, 0x00(src)
-	lw	ta1, 0x04(src)
-	ADDC(sum, ta3)
-	ADDC(sum, t0)
-	ADDC(sum, ta0)
-	ADDC(sum, ta1)
-	dsubu	a1, a1, 0x10
-	daddu	src, src, 0x10
-	dsrl	t8, a1, 0x7
-
-begin_movement:
-	beqz	t8, 1f
-	 andi	ta2, a1, 0x40
-
-move_128bytes:
-	CSUM_BIGCHUNK(src, 0x00, sum, ta0, ta1, ta3, t0)
-	CSUM_BIGCHUNK(src, 0x20, sum, ta0, ta1, ta3, t0)
-	CSUM_BIGCHUNK(src, 0x40, sum, ta0, ta1, ta3, t0)
-	CSUM_BIGCHUNK(src, 0x60, sum, ta0, ta1, ta3, t0)
-	dsubu	t8, t8, 0x01
-	bnez	t8, move_128bytes
-	 daddu	src, src, 0x80
-
-1:
-	beqz	ta2, 1f
-	 andi	ta2, a1, 0x20
-
-move_64bytes:
-	CSUM_BIGCHUNK(src, 0x00, sum, ta0, ta1, ta3, t0)
-	CSUM_BIGCHUNK(src, 0x20, sum, ta0, ta1, ta3, t0)
-	daddu	src, src, 0x40
-
-1:
-	beqz	ta2, do_end_words
-	 andi	t8, a1, 0x1c
-
-move_32bytes:
-	CSUM_BIGCHUNK(src, 0x00, sum, ta0, ta1, ta3, t0)
-	andi	t8, a1, 0x1c
-	daddu	src, src, 0x20
-
-do_end_words:
-	beqz	t8, maybe_end_cruft
-	 dsrl	t8, t8, 0x2
-
-end_words:
-	lw	ta0, (src)
-	dsubu	t8, t8, 0x1
-	ADDC(sum, ta0)
-	bnez	t8, end_words
-	 daddu	src, src, 0x4
-
-maybe_end_cruft:
-	andi	ta2, a1, 0x3
-
-small_memcpy:
- j small_csumcpy; move a1, ta2		/* XXX ??? */
-	beqz	t2, out
-	 move	a1, ta2
-
-end_bytes:
-	lb	ta0, (src)
-	dsubu	a1, a1, 0x1
-	bnez	a2, end_bytes
-	 daddu	src, src, 0x1
-
-out:
-	jr	ra
-	 move	v0, sum
-	END(csum_partial)

+ 2 - 2
arch/mips/lib/Makefile

@@ -2,8 +2,8 @@
 # Makefile for MIPS-specific library files..
 # Makefile for MIPS-specific library files..
 #
 #
 
 
-lib-y	+= csum_partial_copy.o memcpy.o promlib.o strlen_user.o strncpy_user.o \
-	   strnlen_user.o uncached.o
+lib-y	+= csum_partial.o csum_partial_copy.o memcpy.o promlib.o \
+	   strlen_user.o strncpy_user.o strnlen_user.o uncached.o
 
 
 obj-y	+= iomap.o
 obj-y	+= iomap.o
 
 

+ 258 - 0
arch/mips/lib/csum_partial.S

@@ -0,0 +1,258 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Quick'n'dirty IP checksum ...
+ *
+ * Copyright (C) 1998, 1999 Ralf Baechle
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ */
+#include <asm/asm.h>
+#include <asm/regdef.h>
+
+#ifdef CONFIG_64BIT
+#define T0	ta0
+#define T1	ta1
+#define T2	ta2
+#define T3	ta3
+#define T4	t0
+#define T7	t3
+#else
+#define T0	t0
+#define T1	t1
+#define T2	t2
+#define T3	t3
+#define T4	t4
+#define T7	t7
+#endif
+
+#define ADDC(sum,reg)						\
+	addu	sum, reg;					\
+	sltu	v1, sum, reg;					\
+	addu	sum, v1
+
+#define CSUM_BIGCHUNK(src, offset, sum, _t0, _t1, _t2, _t3)	\
+	lw	_t0, (offset + 0x00)(src);			\
+	lw	_t1, (offset + 0x04)(src);			\
+	lw	_t2, (offset + 0x08)(src); 			\
+	lw	_t3, (offset + 0x0c)(src); 			\
+	ADDC(sum, _t0);						\
+	ADDC(sum, _t1);						\
+	ADDC(sum, _t2);						\
+	ADDC(sum, _t3);						\
+	lw	_t0, (offset + 0x10)(src);			\
+	lw	_t1, (offset + 0x14)(src);			\
+	lw	_t2, (offset + 0x18)(src);			\
+	lw	_t3, (offset + 0x1c)(src);			\
+	ADDC(sum, _t0);						\
+	ADDC(sum, _t1);						\
+	ADDC(sum, _t2);						\
+	ADDC(sum, _t3);						\
+
+/*
+ * a0: source address
+ * a1: length of the area to checksum
+ * a2: partial checksum
+ */
+
+#define src a0
+#define sum v0
+
+	.text
+	.set	noreorder
+
+/* unknown src alignment and < 8 bytes to go  */
+small_csumcpy:
+	move	a1, T2
+
+	andi	T0, a1, 4
+	beqz	T0, 1f
+	 andi	T0, a1, 2
+
+	/* Still a full word to go  */
+	ulw	T1, (src)
+	PTR_ADDIU	src, 4
+	ADDC(sum, T1)
+
+1:	move	T1, zero
+	beqz	T0, 1f
+	 andi	T0, a1, 1
+
+	/* Still a halfword to go  */
+	ulhu	T1, (src)
+	PTR_ADDIU	src, 2
+
+1:	beqz	T0, 1f
+	 sll	T1, T1, 16
+
+	lbu	T2, (src)
+	 nop
+
+#ifdef __MIPSEB__
+	sll	T2, T2, 8
+#endif
+	or	T1, T2
+
+1:	ADDC(sum, T1)
+
+	/* fold checksum */
+	sll	v1, sum, 16
+	addu	sum, v1
+	sltu	v1, sum, v1
+	srl	sum, sum, 16
+	addu	sum, v1
+
+	/* odd buffer alignment? */
+	beqz	T7, 1f
+	 nop
+	sll	v1, sum, 8
+	srl	sum, sum, 8
+	or	sum, v1
+	andi	sum, 0xffff
+1:
+	.set	reorder
+	/* Add the passed partial csum.  */
+	ADDC(sum, a2)
+	jr	ra
+	.set	noreorder
+
+/* ------------------------------------------------------------------------- */
+
+	.align	5
+LEAF(csum_partial)
+	move	sum, zero
+	move	T7, zero
+
+	sltiu	t8, a1, 0x8
+	bnez	t8, small_csumcpy		/* < 8 bytes to copy */
+	 move	T2, a1
+
+	beqz	a1, out
+	 andi	T7, src, 0x1			/* odd buffer? */
+
+hword_align:
+	beqz	T7, word_align
+	 andi	t8, src, 0x2
+
+	lbu	T0, (src)
+	LONG_SUBU	a1, a1, 0x1
+#ifdef __MIPSEL__
+	sll	T0, T0, 8
+#endif
+	ADDC(sum, T0)
+	PTR_ADDU	src, src, 0x1
+	andi	t8, src, 0x2
+
+word_align:
+	beqz	t8, dword_align
+	 sltiu	t8, a1, 56
+
+	lhu	T0, (src)
+	LONG_SUBU	a1, a1, 0x2
+	ADDC(sum, T0)
+	sltiu	t8, a1, 56
+	PTR_ADDU	src, src, 0x2
+
+dword_align:
+	bnez	t8, do_end_words
+	 move	t8, a1
+
+	andi	t8, src, 0x4
+	beqz	t8, qword_align
+	 andi	t8, src, 0x8
+
+	lw	T0, 0x00(src)
+	LONG_SUBU	a1, a1, 0x4
+	ADDC(sum, T0)
+	PTR_ADDU	src, src, 0x4
+	andi	t8, src, 0x8
+
+qword_align:
+	beqz	t8, oword_align
+	 andi	t8, src, 0x10
+
+	lw	T0, 0x00(src)
+	lw	T1, 0x04(src)
+	LONG_SUBU	a1, a1, 0x8
+	ADDC(sum, T0)
+	ADDC(sum, T1)
+	PTR_ADDU	src, src, 0x8
+	andi	t8, src, 0x10
+
+oword_align:
+	beqz	t8, begin_movement
+	 LONG_SRL	t8, a1, 0x7
+
+	lw	T3, 0x08(src)
+	lw	T4, 0x0c(src)
+	lw	T0, 0x00(src)
+	lw	T1, 0x04(src)
+	ADDC(sum, T3)
+	ADDC(sum, T4)
+	ADDC(sum, T0)
+	ADDC(sum, T1)
+	LONG_SUBU	a1, a1, 0x10
+	PTR_ADDU	src, src, 0x10
+	LONG_SRL	t8, a1, 0x7
+
+begin_movement:
+	beqz	t8, 1f
+	 andi	T2, a1, 0x40
+
+move_128bytes:
+	CSUM_BIGCHUNK(src, 0x00, sum, T0, T1, T3, T4)
+	CSUM_BIGCHUNK(src, 0x20, sum, T0, T1, T3, T4)
+	CSUM_BIGCHUNK(src, 0x40, sum, T0, T1, T3, T4)
+	CSUM_BIGCHUNK(src, 0x60, sum, T0, T1, T3, T4)
+	LONG_SUBU	t8, t8, 0x01
+	bnez	t8, move_128bytes
+	 PTR_ADDU	src, src, 0x80
+
+1:
+	beqz	T2, 1f
+	 andi	T2, a1, 0x20
+
+move_64bytes:
+	CSUM_BIGCHUNK(src, 0x00, sum, T0, T1, T3, T4)
+	CSUM_BIGCHUNK(src, 0x20, sum, T0, T1, T3, T4)
+	PTR_ADDU	src, src, 0x40
+
+1:
+	beqz	T2, do_end_words
+	 andi	t8, a1, 0x1c
+
+move_32bytes:
+	CSUM_BIGCHUNK(src, 0x00, sum, T0, T1, T3, T4)
+	andi	t8, a1, 0x1c
+	PTR_ADDU	src, src, 0x20
+
+do_end_words:
+	beqz	t8, maybe_end_cruft
+	 LONG_SRL	t8, t8, 0x2
+
+end_words:
+	lw	T0, (src)
+	LONG_SUBU	t8, t8, 0x1
+	ADDC(sum, T0)
+	bnez	t8, end_words
+	 PTR_ADDU	src, src, 0x4
+
+maybe_end_cruft:
+	andi	T2, a1, 0x3
+
+small_memcpy:
+ j small_csumcpy; move a1, T2		/* XXX ??? */
+	beqz	t2, out
+	 move	a1, T2
+
+end_bytes:
+	lb	T0, (src)
+	LONG_SUBU	a1, a1, 0x1
+	bnez	a2, end_bytes
+	 PTR_ADDU	src, src, 0x1
+
+out:
+	jr	ra
+	 move	v0, sum
+	END(csum_partial)

+ 4 - 4
arch/mips/sibyte/swarm/setup.c

@@ -43,7 +43,7 @@
 #elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
 #elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
 #include <asm/sibyte/sb1250_regs.h>
 #include <asm/sibyte/sb1250_regs.h>
 #else
 #else
-#error invalid SiByte board configuation
+#error invalid SiByte board configuration
 #endif
 #endif
 #include <asm/sibyte/sb1250_genbus.h>
 #include <asm/sibyte/sb1250_genbus.h>
 #include <asm/sibyte/board.h>
 #include <asm/sibyte/board.h>
@@ -53,7 +53,7 @@ extern void bcm1480_setup(void);
 #elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
 #elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
 extern void sb1250_setup(void);
 extern void sb1250_setup(void);
 #else
 #else
-#error invalid SiByte board configuation
+#error invalid SiByte board configuration
 #endif
 #endif
 
 
 extern int xicor_probe(void);
 extern int xicor_probe(void);
@@ -90,7 +90,7 @@ void __init plat_timer_setup(struct irqaction *irq)
 #elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
 #elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
 	sb1250_time_init();
 	sb1250_time_init();
 #else
 #else
-#error invalid SiByte board configuation
+#error invalid SiByte board configuration
 #endif
 #endif
 }
 }
 
 
@@ -111,7 +111,7 @@ void __init plat_mem_setup(void)
 #elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
 #elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
 	sb1250_setup();
 	sb1250_setup();
 #else
 #else
-#error invalid SiByte board configuation
+#error invalid SiByte board configuration
 #endif
 #endif
 
 
 	panic_timeout = 5;  /* For debug.  */
 	panic_timeout = 5;  /* For debug.  */

+ 26 - 13
include/asm-mips/atomic.h

@@ -15,6 +15,7 @@
 #define _ASM_ATOMIC_H
 #define _ASM_ATOMIC_H
 
 
 #include <linux/irqflags.h>
 #include <linux/irqflags.h>
+#include <asm/barrier.h>
 #include <asm/cpu-features.h>
 #include <asm/cpu-features.h>
 #include <asm/war.h>
 #include <asm/war.h>
 
 
@@ -130,6 +131,8 @@ static __inline__ int atomic_add_return(int i, atomic_t * v)
 {
 {
 	unsigned long result;
 	unsigned long result;
 
 
+	smp_mb();
+
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
 		unsigned long temp;
 		unsigned long temp;
 
 
@@ -140,7 +143,6 @@ static __inline__ int atomic_add_return(int i, atomic_t * v)
 		"	sc	%0, %2					\n"
 		"	sc	%0, %2					\n"
 		"	beqzl	%0, 1b					\n"
 		"	beqzl	%0, 1b					\n"
 		"	addu	%0, %1, %3				\n"
 		"	addu	%0, %1, %3				\n"
-		"	sync						\n"
 		"	.set	mips0					\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
@@ -155,7 +157,6 @@ static __inline__ int atomic_add_return(int i, atomic_t * v)
 		"	sc	%0, %2					\n"
 		"	sc	%0, %2					\n"
 		"	beqz	%0, 1b					\n"
 		"	beqz	%0, 1b					\n"
 		"	addu	%0, %1, %3				\n"
 		"	addu	%0, %1, %3				\n"
-		"	sync						\n"
 		"	.set	mips0					\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
@@ -170,6 +171,8 @@ static __inline__ int atomic_add_return(int i, atomic_t * v)
 		local_irq_restore(flags);
 		local_irq_restore(flags);
 	}
 	}
 
 
+	smp_mb();
+
 	return result;
 	return result;
 }
 }
 
 
@@ -177,6 +180,8 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v)
 {
 {
 	unsigned long result;
 	unsigned long result;
 
 
+	smp_mb();
+
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
 		unsigned long temp;
 		unsigned long temp;
 
 
@@ -187,7 +192,6 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v)
 		"	sc	%0, %2					\n"
 		"	sc	%0, %2					\n"
 		"	beqzl	%0, 1b					\n"
 		"	beqzl	%0, 1b					\n"
 		"	subu	%0, %1, %3				\n"
 		"	subu	%0, %1, %3				\n"
-		"	sync						\n"
 		"	.set	mips0					\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
@@ -202,7 +206,6 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v)
 		"	sc	%0, %2					\n"
 		"	sc	%0, %2					\n"
 		"	beqz	%0, 1b					\n"
 		"	beqz	%0, 1b					\n"
 		"	subu	%0, %1, %3				\n"
 		"	subu	%0, %1, %3				\n"
-		"	sync						\n"
 		"	.set	mips0					\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
@@ -217,6 +220,8 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v)
 		local_irq_restore(flags);
 		local_irq_restore(flags);
 	}
 	}
 
 
+	smp_mb();
+
 	return result;
 	return result;
 }
 }
 
 
@@ -232,6 +237,8 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
 {
 {
 	unsigned long result;
 	unsigned long result;
 
 
+	smp_mb();
+
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
 		unsigned long temp;
 		unsigned long temp;
 
 
@@ -245,7 +252,6 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
 		"	beqzl	%0, 1b					\n"
 		"	beqzl	%0, 1b					\n"
 		"	 subu	%0, %1, %3				\n"
 		"	 subu	%0, %1, %3				\n"
 		"	.set	reorder					\n"
 		"	.set	reorder					\n"
-		"	sync						\n"
 		"1:							\n"
 		"1:							\n"
 		"	.set	mips0					\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
@@ -264,7 +270,6 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
 		"	beqz	%0, 1b					\n"
 		"	beqz	%0, 1b					\n"
 		"	 subu	%0, %1, %3				\n"
 		"	 subu	%0, %1, %3				\n"
 		"	.set	reorder					\n"
 		"	.set	reorder					\n"
-		"	sync						\n"
 		"1:							\n"
 		"1:							\n"
 		"	.set	mips0					\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
@@ -281,6 +286,8 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
 		local_irq_restore(flags);
 		local_irq_restore(flags);
 	}
 	}
 
 
+	smp_mb();
+
 	return result;
 	return result;
 }
 }
 
 
@@ -375,7 +382,7 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
 
 
 #ifdef CONFIG_64BIT
 #ifdef CONFIG_64BIT
 
 
-typedef struct { volatile __s64 counter; } atomic64_t;
+typedef struct { volatile long counter; } atomic64_t;
 
 
 #define ATOMIC64_INIT(i)    { (i) }
 #define ATOMIC64_INIT(i)    { (i) }
 
 
@@ -484,6 +491,8 @@ static __inline__ long atomic64_add_return(long i, atomic64_t * v)
 {
 {
 	unsigned long result;
 	unsigned long result;
 
 
+	smp_mb();
+
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
 		unsigned long temp;
 		unsigned long temp;
 
 
@@ -494,7 +503,6 @@ static __inline__ long atomic64_add_return(long i, atomic64_t * v)
 		"	scd	%0, %2					\n"
 		"	scd	%0, %2					\n"
 		"	beqzl	%0, 1b					\n"
 		"	beqzl	%0, 1b					\n"
 		"	addu	%0, %1, %3				\n"
 		"	addu	%0, %1, %3				\n"
-		"	sync						\n"
 		"	.set	mips0					\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
@@ -509,7 +517,6 @@ static __inline__ long atomic64_add_return(long i, atomic64_t * v)
 		"	scd	%0, %2					\n"
 		"	scd	%0, %2					\n"
 		"	beqz	%0, 1b					\n"
 		"	beqz	%0, 1b					\n"
 		"	addu	%0, %1, %3				\n"
 		"	addu	%0, %1, %3				\n"
-		"	sync						\n"
 		"	.set	mips0					\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
@@ -524,6 +531,8 @@ static __inline__ long atomic64_add_return(long i, atomic64_t * v)
 		local_irq_restore(flags);
 		local_irq_restore(flags);
 	}
 	}
 
 
+	smp_mb();
+
 	return result;
 	return result;
 }
 }
 
 
@@ -531,6 +540,8 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
 {
 {
 	unsigned long result;
 	unsigned long result;
 
 
+	smp_mb();
+
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
 		unsigned long temp;
 		unsigned long temp;
 
 
@@ -541,7 +552,6 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
 		"	scd	%0, %2					\n"
 		"	scd	%0, %2					\n"
 		"	beqzl	%0, 1b					\n"
 		"	beqzl	%0, 1b					\n"
 		"	subu	%0, %1, %3				\n"
 		"	subu	%0, %1, %3				\n"
-		"	sync						\n"
 		"	.set	mips0					\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
@@ -556,7 +566,6 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
 		"	scd	%0, %2					\n"
 		"	scd	%0, %2					\n"
 		"	beqz	%0, 1b					\n"
 		"	beqz	%0, 1b					\n"
 		"	subu	%0, %1, %3				\n"
 		"	subu	%0, %1, %3				\n"
-		"	sync						\n"
 		"	.set	mips0					\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
@@ -571,6 +580,8 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
 		local_irq_restore(flags);
 		local_irq_restore(flags);
 	}
 	}
 
 
+	smp_mb();
+
 	return result;
 	return result;
 }
 }
 
 
@@ -586,6 +597,8 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
 {
 {
 	unsigned long result;
 	unsigned long result;
 
 
+	smp_mb();
+
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
 		unsigned long temp;
 		unsigned long temp;
 
 
@@ -599,7 +612,6 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
 		"	beqzl	%0, 1b					\n"
 		"	beqzl	%0, 1b					\n"
 		"	 dsubu	%0, %1, %3				\n"
 		"	 dsubu	%0, %1, %3				\n"
 		"	.set	reorder					\n"
 		"	.set	reorder					\n"
-		"	sync						\n"
 		"1:							\n"
 		"1:							\n"
 		"	.set	mips0					\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
@@ -618,7 +630,6 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
 		"	beqz	%0, 1b					\n"
 		"	beqz	%0, 1b					\n"
 		"	 dsubu	%0, %1, %3				\n"
 		"	 dsubu	%0, %1, %3				\n"
 		"	.set	reorder					\n"
 		"	.set	reorder					\n"
-		"	sync						\n"
 		"1:							\n"
 		"1:							\n"
 		"	.set	mips0					\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
@@ -635,6 +646,8 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
 		local_irq_restore(flags);
 		local_irq_restore(flags);
 	}
 	}
 
 
+	smp_mb();
+
 	return result;
 	return result;
 }
 }
 
 

+ 132 - 0
include/asm-mips/barrier.h

@@ -0,0 +1,132 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006 by Ralf Baechle (ralf@linux-mips.org)
+ */
+#ifndef __ASM_BARRIER_H
+#define __ASM_BARRIER_H
+
+/*
+ * read_barrier_depends - Flush all pending reads that subsequents reads
+ * depend on.
+ *
+ * No data-dependent reads from memory-like regions are ever reordered
+ * over this barrier.  All reads preceding this primitive are guaranteed
+ * to access memory (but not necessarily other CPUs' caches) before any
+ * reads following this primitive that depend on the data return by
+ * any of the preceding reads.  This primitive is much lighter weight than
+ * rmb() on most CPUs, and is never heavier weight than is
+ * rmb().
+ *
+ * These ordering constraints are respected by both the local CPU
+ * and the compiler.
+ *
+ * Ordering is not guaranteed by anything other than these primitives,
+ * not even by data dependencies.  See the documentation for
+ * memory_barrier() for examples and URLs to more information.
+ *
+ * For example, the following code would force ordering (the initial
+ * value of "a" is zero, "b" is one, and "p" is "&a"):
+ *
+ * <programlisting>
+ *	CPU 0				CPU 1
+ *
+ *	b = 2;
+ *	memory_barrier();
+ *	p = &b;				q = p;
+ *					read_barrier_depends();
+ *					d = *q;
+ * </programlisting>
+ *
+ * because the read of "*q" depends on the read of "p" and these
+ * two reads are separated by a read_barrier_depends().  However,
+ * the following code, with the same initial values for "a" and "b":
+ *
+ * <programlisting>
+ *	CPU 0				CPU 1
+ *
+ *	a = 2;
+ *	memory_barrier();
+ *	b = 3;				y = b;
+ *					read_barrier_depends();
+ *					x = a;
+ * </programlisting>
+ *
+ * does not enforce ordering, since there is no data dependency between
+ * the read of "a" and the read of "b".  Therefore, on some CPUs, such
+ * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
+ * in cases like this where there are no data dependencies.
+ */
+
+#define read_barrier_depends()		do { } while(0)
+#define smp_read_barrier_depends()	do { } while(0)
+
+#ifdef CONFIG_CPU_HAS_SYNC
+#define __sync()				\
+	__asm__ __volatile__(			\
+		".set	push\n\t"		\
+		".set	noreorder\n\t"		\
+		".set	mips2\n\t"		\
+		"sync\n\t"			\
+		".set	pop"			\
+		: /* no output */		\
+		: /* no input */		\
+		: "memory")
+#else
+#define __sync()	do { } while(0)
+#endif
+
+#define __fast_iob()				\
+	__asm__ __volatile__(			\
+		".set	push\n\t"		\
+		".set	noreorder\n\t"		\
+		"lw	$0,%0\n\t"		\
+		"nop\n\t"			\
+		".set	pop"			\
+		: /* no output */		\
+		: "m" (*(int *)CKSEG1)		\
+		: "memory")
+
+#define fast_wmb()	__sync()
+#define fast_rmb()	__sync()
+#define fast_mb()	__sync()
+#define fast_iob()				\
+	do {					\
+		__sync();			\
+		__fast_iob();			\
+	} while (0)
+
+#ifdef CONFIG_CPU_HAS_WB
+
+#include <asm/wbflush.h>
+
+#define wmb()		fast_wmb()
+#define rmb()		fast_rmb()
+#define mb()		wbflush()
+#define iob()		wbflush()
+
+#else /* !CONFIG_CPU_HAS_WB */
+
+#define wmb()		fast_wmb()
+#define rmb()		fast_rmb()
+#define mb()		fast_mb()
+#define iob()		fast_iob()
+
+#endif /* !CONFIG_CPU_HAS_WB */
+
+#if defined(CONFIG_WEAK_ORDERING) && defined(CONFIG_SMP)
+#define __WEAK_ORDERING_MB	"       sync	\n"
+#else
+#define __WEAK_ORDERING_MB	"		\n"
+#endif
+
+#define smp_mb()	__asm__ __volatile__(__WEAK_ORDERING_MB : : :"memory")
+#define smp_rmb()	__asm__ __volatile__(__WEAK_ORDERING_MB : : :"memory")
+#define smp_wmb()	__asm__ __volatile__(__WEAK_ORDERING_MB : : :"memory")
+
+#define set_mb(var, value) \
+	do { var = value; smp_mb(); } while (0)
+
+#endif /* __ASM_BARRIER_H */

+ 8 - 19
include/asm-mips/bitops.h

@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  * for more details.
  *
  *
- * Copyright (c) 1994 - 1997, 1999, 2000  Ralf Baechle (ralf@gnu.org)
+ * Copyright (c) 1994 - 1997, 1999, 2000, 06  Ralf Baechle (ralf@linux-mips.org)
  * Copyright (c) 1999, 2000  Silicon Graphics, Inc.
  * Copyright (c) 1999, 2000  Silicon Graphics, Inc.
  */
  */
 #ifndef _ASM_BITOPS_H
 #ifndef _ASM_BITOPS_H
@@ -12,6 +12,7 @@
 #include <linux/compiler.h>
 #include <linux/compiler.h>
 #include <linux/irqflags.h>
 #include <linux/irqflags.h>
 #include <linux/types.h>
 #include <linux/types.h>
+#include <asm/barrier.h>
 #include <asm/bug.h>
 #include <asm/bug.h>
 #include <asm/byteorder.h>		/* sigh ... */
 #include <asm/byteorder.h>		/* sigh ... */
 #include <asm/cpu-features.h>
 #include <asm/cpu-features.h>
@@ -204,9 +205,6 @@ static inline int test_and_set_bit(unsigned long nr,
 		"	" __SC	"%2, %1					\n"
 		"	" __SC	"%2, %1					\n"
 		"	beqzl	%2, 1b					\n"
 		"	beqzl	%2, 1b					\n"
 		"	and	%2, %0, %3				\n"
 		"	and	%2, %0, %3				\n"
-#ifdef CONFIG_SMP
-		"	sync						\n"
-#endif
 		"	.set	mips0					\n"
 		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
 		: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
@@ -226,9 +224,6 @@ static inline int test_and_set_bit(unsigned long nr,
 		"	" __SC	"%2, %1					\n"
 		"	" __SC	"%2, %1					\n"
 		"	beqz	%2, 1b					\n"
 		"	beqz	%2, 1b					\n"
 		"	 and	%2, %0, %3				\n"
 		"	 and	%2, %0, %3				\n"
-#ifdef CONFIG_SMP
-		"	sync						\n"
-#endif
 		"	.set	pop					\n"
 		"	.set	pop					\n"
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
 		: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
@@ -250,6 +245,8 @@ static inline int test_and_set_bit(unsigned long nr,
 
 
 		return retval;
 		return retval;
 	}
 	}
+
+	smp_mb();
 }
 }
 
 
 /*
 /*
@@ -275,9 +272,6 @@ static inline int test_and_clear_bit(unsigned long nr,
 		"	" __SC 	"%2, %1					\n"
 		"	" __SC 	"%2, %1					\n"
 		"	beqzl	%2, 1b					\n"
 		"	beqzl	%2, 1b					\n"
 		"	and	%2, %0, %3				\n"
 		"	and	%2, %0, %3				\n"
-#ifdef CONFIG_SMP
-		"	sync						\n"
-#endif
 		"	.set	mips0					\n"
 		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
 		: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
@@ -298,9 +292,6 @@ static inline int test_and_clear_bit(unsigned long nr,
 		"	" __SC 	"%2, %1					\n"
 		"	" __SC 	"%2, %1					\n"
 		"	beqz	%2, 1b					\n"
 		"	beqz	%2, 1b					\n"
 		"	 and	%2, %0, %3				\n"
 		"	 and	%2, %0, %3				\n"
-#ifdef CONFIG_SMP
-		"	sync						\n"
-#endif
 		"	.set	pop					\n"
 		"	.set	pop					\n"
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
 		: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
@@ -322,6 +313,8 @@ static inline int test_and_clear_bit(unsigned long nr,
 
 
 		return retval;
 		return retval;
 	}
 	}
+
+	smp_mb();
 }
 }
 
 
 /*
 /*
@@ -346,9 +339,6 @@ static inline int test_and_change_bit(unsigned long nr,
 		"	" __SC	"%2, %1					\n"
 		"	" __SC	"%2, %1					\n"
 		"	beqzl	%2, 1b					\n"
 		"	beqzl	%2, 1b					\n"
 		"	and	%2, %0, %3				\n"
 		"	and	%2, %0, %3				\n"
-#ifdef CONFIG_SMP
-		"	sync						\n"
-#endif
 		"	.set	mips0					\n"
 		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
 		: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
@@ -368,9 +358,6 @@ static inline int test_and_change_bit(unsigned long nr,
 		"	" __SC	"\t%2, %1				\n"
 		"	" __SC	"\t%2, %1				\n"
 		"	beqz	%2, 1b					\n"
 		"	beqz	%2, 1b					\n"
 		"	 and	%2, %0, %3				\n"
 		"	 and	%2, %0, %3				\n"
-#ifdef CONFIG_SMP
-		"	sync						\n"
-#endif
 		"	.set	pop					\n"
 		"	.set	pop					\n"
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
 		: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
@@ -391,6 +378,8 @@ static inline int test_and_change_bit(unsigned long nr,
 
 
 		return retval;
 		return retval;
 	}
 	}
+
+	smp_mb();
 }
 }
 
 
 #include <asm-generic/bitops/non-atomic.h>
 #include <asm-generic/bitops/non-atomic.h>

+ 68 - 0
include/asm-mips/compat.h

@@ -32,6 +32,7 @@ typedef struct {
 	s32	val[2];
 	s32	val[2];
 } compat_fsid_t;
 } compat_fsid_t;
 typedef s32		compat_timer_t;
 typedef s32		compat_timer_t;
+typedef s32		compat_key_t;
 
 
 typedef s32		compat_int_t;
 typedef s32		compat_int_t;
 typedef s32		compat_long_t;
 typedef s32		compat_long_t;
@@ -146,4 +147,71 @@ static inline void __user *compat_alloc_user_space(long len)
 	return (void __user *) (regs->regs[29] - len);
 	return (void __user *) (regs->regs[29] - len);
 }
 }
 
 
+struct compat_ipc64_perm {
+	compat_key_t key;
+	__compat_uid32_t uid;
+	__compat_gid32_t gid;
+	__compat_uid32_t cuid;
+	__compat_gid32_t cgid;
+	compat_mode_t mode;
+	unsigned short seq;
+	unsigned short __pad2;
+	compat_ulong_t __unused1;
+	compat_ulong_t __unused2;
+};
+
+struct compat_semid64_ds {
+	struct compat_ipc64_perm sem_perm;
+	compat_time_t	sem_otime;
+	compat_time_t	sem_ctime;
+	compat_ulong_t	sem_nsems;
+	compat_ulong_t	__unused1;
+	compat_ulong_t	__unused2;
+};
+
+struct compat_msqid64_ds {
+	struct compat_ipc64_perm msg_perm;
+#ifndef CONFIG_CPU_LITTLE_ENDIAN
+	compat_ulong_t	__unused1;
+#endif
+	compat_time_t	msg_stime;
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+	compat_ulong_t	__unused1;
+#endif
+#ifndef CONFIG_CPU_LITTLE_ENDIAN
+	compat_ulong_t	__unused2;
+#endif
+	compat_time_t	msg_rtime;
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+	compat_ulong_t	__unused2;
+#endif
+#ifndef CONFIG_CPU_LITTLE_ENDIAN
+	compat_ulong_t	__unused3;
+#endif
+	compat_time_t	msg_ctime;
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+	compat_ulong_t	__unused3;
+#endif
+	compat_ulong_t	msg_cbytes;
+	compat_ulong_t	msg_qnum;
+	compat_ulong_t	msg_qbytes;
+	compat_pid_t	msg_lspid;
+	compat_pid_t	msg_lrpid;
+	compat_ulong_t	__unused4;
+	compat_ulong_t	__unused5;
+};
+
+struct compat_shmid64_ds {
+	struct compat_ipc64_perm shm_perm;
+	compat_size_t	shm_segsz;
+	compat_time_t	shm_atime;
+	compat_time_t	shm_dtime;
+	compat_time_t	shm_ctime;
+	compat_pid_t	shm_cpid;
+	compat_pid_t	shm_lpid;
+	compat_ulong_t	shm_nattch;
+	compat_ulong_t	__unused1;
+	compat_ulong_t	__unused2;
+};
+
 #endif /* _ASM_COMPAT_H */
 #endif /* _ASM_COMPAT_H */

+ 12 - 10
include/asm-mips/futex.h

@@ -1,19 +1,21 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2006  Ralf Baechle (ralf@linux-mips.org)
+ */
 #ifndef _ASM_FUTEX_H
 #ifndef _ASM_FUTEX_H
 #define _ASM_FUTEX_H
 #define _ASM_FUTEX_H
 
 
 #ifdef __KERNEL__
 #ifdef __KERNEL__
 
 
 #include <linux/futex.h>
 #include <linux/futex.h>
+#include <asm/barrier.h>
 #include <asm/errno.h>
 #include <asm/errno.h>
 #include <asm/uaccess.h>
 #include <asm/uaccess.h>
 #include <asm/war.h>
 #include <asm/war.h>
 
 
-#ifdef CONFIG_SMP
-#define __FUTEX_SMP_SYNC "	sync					\n"
-#else
-#define __FUTEX_SMP_SYNC
-#endif
-
 #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)		\
 #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)		\
 {									\
 {									\
 	if (cpu_has_llsc && R10000_LLSC_WAR) {				\
 	if (cpu_has_llsc && R10000_LLSC_WAR) {				\
@@ -27,7 +29,7 @@
 		"	.set	mips3				\n"	\
 		"	.set	mips3				\n"	\
 		"2:	sc	$1, %2				\n"	\
 		"2:	sc	$1, %2				\n"	\
 		"	beqzl	$1, 1b				\n"	\
 		"	beqzl	$1, 1b				\n"	\
-		__FUTEX_SMP_SYNC					\
+		__WEAK_ORDERING_MB					\
 		"3:						\n"	\
 		"3:						\n"	\
 		"	.set	pop				\n"	\
 		"	.set	pop				\n"	\
 		"	.set	mips0				\n"	\
 		"	.set	mips0				\n"	\
@@ -53,7 +55,7 @@
 		"	.set	mips3				\n"	\
 		"	.set	mips3				\n"	\
 		"2:	sc	$1, %2				\n"	\
 		"2:	sc	$1, %2				\n"	\
 		"	beqz	$1, 1b				\n"	\
 		"	beqz	$1, 1b				\n"	\
-		__FUTEX_SMP_SYNC					\
+		__WEAK_ORDERING_MB					\
 		"3:						\n"	\
 		"3:						\n"	\
 		"	.set	pop				\n"	\
 		"	.set	pop				\n"	\
 		"	.set	mips0				\n"	\
 		"	.set	mips0				\n"	\
@@ -150,7 +152,7 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 		"	.set	mips3					\n"
 		"	.set	mips3					\n"
 		"2:	sc	$1, %1					\n"
 		"2:	sc	$1, %1					\n"
 		"	beqzl	$1, 1b					\n"
 		"	beqzl	$1, 1b					\n"
-		__FUTEX_SMP_SYNC
+		__WEAK_ORDERING_MB
 		"3:							\n"
 		"3:							\n"
 		"	.set	pop					\n"
 		"	.set	pop					\n"
 		"	.section .fixup,\"ax\"				\n"
 		"	.section .fixup,\"ax\"				\n"
@@ -177,7 +179,7 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 		"	.set	mips3					\n"
 		"	.set	mips3					\n"
 		"2:	sc	$1, %1					\n"
 		"2:	sc	$1, %1					\n"
 		"	beqz	$1, 1b					\n"
 		"	beqz	$1, 1b					\n"
-		__FUTEX_SMP_SYNC
+		__WEAK_ORDERING_MB
 		"3:							\n"
 		"3:							\n"
 		"	.set	pop					\n"
 		"	.set	pop					\n"
 		"	.section .fixup,\"ax\"				\n"
 		"	.section .fixup,\"ax\"				\n"

+ 1 - 1
include/asm-mips/sn/klconfig.h

@@ -176,7 +176,7 @@ typedef struct kl_config_hdr {
 /* --- New Macros for the changed kl_config_hdr_t structure --- */
 /* --- New Macros for the changed kl_config_hdr_t structure --- */
 
 
 #define PTR_CH_MALLOC_HDR(_k)   ((klc_malloc_hdr_t *)\
 #define PTR_CH_MALLOC_HDR(_k)   ((klc_malloc_hdr_t *)\
-			(unsigned long)_k + (_k->ch_malloc_hdr_off)))
+			((unsigned long)_k + (_k->ch_malloc_hdr_off)))
 
 
 #define KL_CONFIG_CH_MALLOC_HDR(_n)   PTR_CH_MALLOC_HDR(KL_CONFIG_HDR(_n))
 #define KL_CONFIG_CH_MALLOC_HDR(_n)   PTR_CH_MALLOC_HDR(KL_CONFIG_HDR(_n))
 
 

+ 31 - 22
include/asm-mips/spinlock.h

@@ -3,12 +3,13 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  * for more details.
  *
  *
- * Copyright (C) 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000, 06 by Ralf Baechle
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
  */
 #ifndef _ASM_SPINLOCK_H
 #ifndef _ASM_SPINLOCK_H
 #define _ASM_SPINLOCK_H
 #define _ASM_SPINLOCK_H
 
 
+#include <asm/barrier.h>
 #include <asm/war.h>
 #include <asm/war.h>
 
 
 /*
 /*
@@ -40,7 +41,6 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
 		"	sc	%1, %0					\n"
 		"	sc	%1, %0					\n"
 		"	beqzl	%1, 1b					\n"
 		"	beqzl	%1, 1b					\n"
 		"	 nop						\n"
 		"	 nop						\n"
-		"	sync						\n"
 		"	.set	reorder					\n"
 		"	.set	reorder					\n"
 		: "=m" (lock->lock), "=&r" (tmp)
 		: "=m" (lock->lock), "=&r" (tmp)
 		: "m" (lock->lock)
 		: "m" (lock->lock)
@@ -53,19 +53,22 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
 		"	 li	%1, 1					\n"
 		"	 li	%1, 1					\n"
 		"	sc	%1, %0					\n"
 		"	sc	%1, %0					\n"
 		"	beqz	%1, 1b					\n"
 		"	beqz	%1, 1b					\n"
-		"	 sync						\n"
+		"	 nop						\n"
 		"	.set	reorder					\n"
 		"	.set	reorder					\n"
 		: "=m" (lock->lock), "=&r" (tmp)
 		: "=m" (lock->lock), "=&r" (tmp)
 		: "m" (lock->lock)
 		: "m" (lock->lock)
 		: "memory");
 		: "memory");
 	}
 	}
+
+	smp_mb();
 }
 }
 
 
 static inline void __raw_spin_unlock(raw_spinlock_t *lock)
 static inline void __raw_spin_unlock(raw_spinlock_t *lock)
 {
 {
+	smp_mb();
+
 	__asm__ __volatile__(
 	__asm__ __volatile__(
 	"	.set	noreorder	# __raw_spin_unlock	\n"
 	"	.set	noreorder	# __raw_spin_unlock	\n"
-	"	sync						\n"
 	"	sw	$0, %0					\n"
 	"	sw	$0, %0					\n"
 	"	.set\treorder					\n"
 	"	.set\treorder					\n"
 	: "=m" (lock->lock)
 	: "=m" (lock->lock)
@@ -86,7 +89,6 @@ static inline unsigned int __raw_spin_trylock(raw_spinlock_t *lock)
 		"	beqzl	%2, 1b					\n"
 		"	beqzl	%2, 1b					\n"
 		"	 nop						\n"
 		"	 nop						\n"
 		"	andi	%2, %0, 1				\n"
 		"	andi	%2, %0, 1				\n"
-		"	sync						\n"
 		"	.set	reorder"
 		"	.set	reorder"
 		: "=&r" (temp), "=m" (lock->lock), "=&r" (res)
 		: "=&r" (temp), "=m" (lock->lock), "=&r" (res)
 		: "m" (lock->lock)
 		: "m" (lock->lock)
@@ -99,13 +101,14 @@ static inline unsigned int __raw_spin_trylock(raw_spinlock_t *lock)
 		"	sc	%2, %1					\n"
 		"	sc	%2, %1					\n"
 		"	beqz	%2, 1b					\n"
 		"	beqz	%2, 1b					\n"
 		"	 andi	%2, %0, 1				\n"
 		"	 andi	%2, %0, 1				\n"
-		"	sync						\n"
 		"	.set	reorder"
 		"	.set	reorder"
 		: "=&r" (temp), "=m" (lock->lock), "=&r" (res)
 		: "=&r" (temp), "=m" (lock->lock), "=&r" (res)
 		: "m" (lock->lock)
 		: "m" (lock->lock)
 		: "memory");
 		: "memory");
 	}
 	}
 
 
+	smp_mb();
+
 	return res == 0;
 	return res == 0;
 }
 }
 
 
@@ -143,7 +146,6 @@ static inline void __raw_read_lock(raw_rwlock_t *rw)
 		"	sc	%1, %0					\n"
 		"	sc	%1, %0					\n"
 		"	beqzl	%1, 1b					\n"
 		"	beqzl	%1, 1b					\n"
 		"	 nop						\n"
 		"	 nop						\n"
-		"	sync						\n"
 		"	.set	reorder					\n"
 		"	.set	reorder					\n"
 		: "=m" (rw->lock), "=&r" (tmp)
 		: "=m" (rw->lock), "=&r" (tmp)
 		: "m" (rw->lock)
 		: "m" (rw->lock)
@@ -156,12 +158,14 @@ static inline void __raw_read_lock(raw_rwlock_t *rw)
 		"	 addu	%1, 1					\n"
 		"	 addu	%1, 1					\n"
 		"	sc	%1, %0					\n"
 		"	sc	%1, %0					\n"
 		"	beqz	%1, 1b					\n"
 		"	beqz	%1, 1b					\n"
-		"	 sync						\n"
+		"	 nop						\n"
 		"	.set	reorder					\n"
 		"	.set	reorder					\n"
 		: "=m" (rw->lock), "=&r" (tmp)
 		: "=m" (rw->lock), "=&r" (tmp)
 		: "m" (rw->lock)
 		: "m" (rw->lock)
 		: "memory");
 		: "memory");
 	}
 	}
+
+	smp_mb();
 }
 }
 
 
 /* Note the use of sub, not subu which will make the kernel die with an
 /* Note the use of sub, not subu which will make the kernel die with an
@@ -171,13 +175,14 @@ static inline void __raw_read_unlock(raw_rwlock_t *rw)
 {
 {
 	unsigned int tmp;
 	unsigned int tmp;
 
 
+	smp_mb();
+
 	if (R10000_LLSC_WAR) {
 	if (R10000_LLSC_WAR) {
 		__asm__ __volatile__(
 		__asm__ __volatile__(
 		"1:	ll	%1, %2		# __raw_read_unlock	\n"
 		"1:	ll	%1, %2		# __raw_read_unlock	\n"
 		"	sub	%1, 1					\n"
 		"	sub	%1, 1					\n"
 		"	sc	%1, %0					\n"
 		"	sc	%1, %0					\n"
 		"	beqzl	%1, 1b					\n"
 		"	beqzl	%1, 1b					\n"
-		"	sync						\n"
 		: "=m" (rw->lock), "=&r" (tmp)
 		: "=m" (rw->lock), "=&r" (tmp)
 		: "m" (rw->lock)
 		: "m" (rw->lock)
 		: "memory");
 		: "memory");
@@ -188,7 +193,7 @@ static inline void __raw_read_unlock(raw_rwlock_t *rw)
 		"	sub	%1, 1					\n"
 		"	sub	%1, 1					\n"
 		"	sc	%1, %0					\n"
 		"	sc	%1, %0					\n"
 		"	beqz	%1, 1b					\n"
 		"	beqz	%1, 1b					\n"
-		"	 sync						\n"
+		"	 nop						\n"
 		"	.set	reorder					\n"
 		"	.set	reorder					\n"
 		: "=m" (rw->lock), "=&r" (tmp)
 		: "=m" (rw->lock), "=&r" (tmp)
 		: "m" (rw->lock)
 		: "m" (rw->lock)
@@ -208,7 +213,7 @@ static inline void __raw_write_lock(raw_rwlock_t *rw)
 		"	 lui	%1, 0x8000				\n"
 		"	 lui	%1, 0x8000				\n"
 		"	sc	%1, %0					\n"
 		"	sc	%1, %0					\n"
 		"	beqzl	%1, 1b					\n"
 		"	beqzl	%1, 1b					\n"
-		"	 sync						\n"
+		"	 nop						\n"
 		"	.set	reorder					\n"
 		"	.set	reorder					\n"
 		: "=m" (rw->lock), "=&r" (tmp)
 		: "=m" (rw->lock), "=&r" (tmp)
 		: "m" (rw->lock)
 		: "m" (rw->lock)
@@ -221,18 +226,22 @@ static inline void __raw_write_lock(raw_rwlock_t *rw)
 		"	 lui	%1, 0x8000				\n"
 		"	 lui	%1, 0x8000				\n"
 		"	sc	%1, %0					\n"
 		"	sc	%1, %0					\n"
 		"	beqz	%1, 1b					\n"
 		"	beqz	%1, 1b					\n"
-		"	 sync						\n"
+		"	 nop						\n"
 		"	.set	reorder					\n"
 		"	.set	reorder					\n"
 		: "=m" (rw->lock), "=&r" (tmp)
 		: "=m" (rw->lock), "=&r" (tmp)
 		: "m" (rw->lock)
 		: "m" (rw->lock)
 		: "memory");
 		: "memory");
 	}
 	}
+
+	smp_mb();
 }
 }
 
 
 static inline void __raw_write_unlock(raw_rwlock_t *rw)
 static inline void __raw_write_unlock(raw_rwlock_t *rw)
 {
 {
+	smp_mb();
+
 	__asm__ __volatile__(
 	__asm__ __volatile__(
-	"	sync			# __raw_write_unlock	\n"
+	"				# __raw_write_unlock	\n"
 	"	sw	$0, %0					\n"
 	"	sw	$0, %0					\n"
 	: "=m" (rw->lock)
 	: "=m" (rw->lock)
 	: "m" (rw->lock)
 	: "m" (rw->lock)
@@ -252,11 +261,10 @@ static inline int __raw_read_trylock(raw_rwlock_t *rw)
 		"	bnez	%1, 2f					\n"
 		"	bnez	%1, 2f					\n"
 		"	 addu	%1, 1					\n"
 		"	 addu	%1, 1					\n"
 		"	sc	%1, %0					\n"
 		"	sc	%1, %0					\n"
-		"	beqzl	%1, 1b					\n"
 		"	.set	reorder					\n"
 		"	.set	reorder					\n"
-#ifdef CONFIG_SMP
-		"	 sync						\n"
-#endif
+		"	beqzl	%1, 1b					\n"
+		"	 nop						\n"
+		__WEAK_ORDERING_MB
 		"	li	%2, 1					\n"
 		"	li	%2, 1					\n"
 		"2:							\n"
 		"2:							\n"
 		: "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
 		: "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
@@ -271,10 +279,9 @@ static inline int __raw_read_trylock(raw_rwlock_t *rw)
 		"	 addu	%1, 1					\n"
 		"	 addu	%1, 1					\n"
 		"	sc	%1, %0					\n"
 		"	sc	%1, %0					\n"
 		"	beqz	%1, 1b					\n"
 		"	beqz	%1, 1b					\n"
+		"	 nop						\n"
 		"	.set	reorder					\n"
 		"	.set	reorder					\n"
-#ifdef CONFIG_SMP
-		"	 sync						\n"
-#endif
+		__WEAK_ORDERING_MB
 		"	li	%2, 1					\n"
 		"	li	%2, 1					\n"
 		"2:							\n"
 		"2:							\n"
 		: "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
 		: "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
@@ -299,7 +306,8 @@ static inline int __raw_write_trylock(raw_rwlock_t *rw)
 		"	 lui	%1, 0x8000				\n"
 		"	 lui	%1, 0x8000				\n"
 		"	sc	%1, %0					\n"
 		"	sc	%1, %0					\n"
 		"	beqzl	%1, 1b					\n"
 		"	beqzl	%1, 1b					\n"
-		"	 sync						\n"
+		"	 nop						\n"
+		__WEAK_ORDERING_MB
 		"	li	%2, 1					\n"
 		"	li	%2, 1					\n"
 		"	.set	reorder					\n"
 		"	.set	reorder					\n"
 		"2:							\n"
 		"2:							\n"
@@ -315,7 +323,8 @@ static inline int __raw_write_trylock(raw_rwlock_t *rw)
 		"	lui	%1, 0x8000				\n"
 		"	lui	%1, 0x8000				\n"
 		"	sc	%1, %0					\n"
 		"	sc	%1, %0					\n"
 		"	beqz	%1, 1b					\n"
 		"	beqz	%1, 1b					\n"
-		"	 sync						\n"
+		"	 nop						\n"
+		__WEAK_ORDERING_MB
 		"	li	%2, 1					\n"
 		"	li	%2, 1					\n"
 		"	.set	reorder					\n"
 		"	.set	reorder					\n"
 		"2:							\n"
 		"2:							\n"

+ 10 - 146
include/asm-mips/system.h

@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  * for more details.
  *
  *
- * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003 by Ralf Baechle
+ * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003, 06 by Ralf Baechle
  * Copyright (C) 1996 by Paul M. Antoine
  * Copyright (C) 1996 by Paul M. Antoine
  * Copyright (C) 1999 Silicon Graphics
  * Copyright (C) 1999 Silicon Graphics
  * Kevin D. Kissell, kevink@mips.org and Carsten Langgaard, carstenl@mips.com
  * Kevin D. Kissell, kevink@mips.org and Carsten Langgaard, carstenl@mips.com
@@ -16,132 +16,12 @@
 #include <linux/irqflags.h>
 #include <linux/irqflags.h>
 
 
 #include <asm/addrspace.h>
 #include <asm/addrspace.h>
+#include <asm/barrier.h>
 #include <asm/cpu-features.h>
 #include <asm/cpu-features.h>
 #include <asm/dsp.h>
 #include <asm/dsp.h>
 #include <asm/ptrace.h>
 #include <asm/ptrace.h>
 #include <asm/war.h>
 #include <asm/war.h>
 
 
-/*
- * read_barrier_depends - Flush all pending reads that subsequents reads
- * depend on.
- *
- * No data-dependent reads from memory-like regions are ever reordered
- * over this barrier.  All reads preceding this primitive are guaranteed
- * to access memory (but not necessarily other CPUs' caches) before any
- * reads following this primitive that depend on the data return by
- * any of the preceding reads.  This primitive is much lighter weight than
- * rmb() on most CPUs, and is never heavier weight than is
- * rmb().
- *
- * These ordering constraints are respected by both the local CPU
- * and the compiler.
- *
- * Ordering is not guaranteed by anything other than these primitives,
- * not even by data dependencies.  See the documentation for
- * memory_barrier() for examples and URLs to more information.
- *
- * For example, the following code would force ordering (the initial
- * value of "a" is zero, "b" is one, and "p" is "&a"):
- *
- * <programlisting>
- *	CPU 0				CPU 1
- *
- *	b = 2;
- *	memory_barrier();
- *	p = &b;				q = p;
- *					read_barrier_depends();
- *					d = *q;
- * </programlisting>
- *
- * because the read of "*q" depends on the read of "p" and these
- * two reads are separated by a read_barrier_depends().  However,
- * the following code, with the same initial values for "a" and "b":
- *
- * <programlisting>
- *	CPU 0				CPU 1
- *
- *	a = 2;
- *	memory_barrier();
- *	b = 3;				y = b;
- *					read_barrier_depends();
- *					x = a;
- * </programlisting>
- *
- * does not enforce ordering, since there is no data dependency between
- * the read of "a" and the read of "b".  Therefore, on some CPUs, such
- * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
- * in cases like this where there are no data dependencies.
- */
-
-#define read_barrier_depends()	do { } while(0)
-
-#ifdef CONFIG_CPU_HAS_SYNC
-#define __sync()				\
-	__asm__ __volatile__(			\
-		".set	push\n\t"		\
-		".set	noreorder\n\t"		\
-		".set	mips2\n\t"		\
-		"sync\n\t"			\
-		".set	pop"			\
-		: /* no output */		\
-		: /* no input */		\
-		: "memory")
-#else
-#define __sync()	do { } while(0)
-#endif
-
-#define __fast_iob()				\
-	__asm__ __volatile__(			\
-		".set	push\n\t"		\
-		".set	noreorder\n\t"		\
-		"lw	$0,%0\n\t"		\
-		"nop\n\t"			\
-		".set	pop"			\
-		: /* no output */		\
-		: "m" (*(int *)CKSEG1)		\
-		: "memory")
-
-#define fast_wmb()	__sync()
-#define fast_rmb()	__sync()
-#define fast_mb()	__sync()
-#define fast_iob()				\
-	do {					\
-		__sync();			\
-		__fast_iob();			\
-	} while (0)
-
-#ifdef CONFIG_CPU_HAS_WB
-
-#include <asm/wbflush.h>
-
-#define wmb()		fast_wmb()
-#define rmb()		fast_rmb()
-#define mb()		wbflush()
-#define iob()		wbflush()
-
-#else /* !CONFIG_CPU_HAS_WB */
-
-#define wmb()		fast_wmb()
-#define rmb()		fast_rmb()
-#define mb()		fast_mb()
-#define iob()		fast_iob()
-
-#endif /* !CONFIG_CPU_HAS_WB */
-
-#ifdef CONFIG_SMP
-#define smp_mb()	mb()
-#define smp_rmb()	rmb()
-#define smp_wmb()	wmb()
-#define smp_read_barrier_depends()	read_barrier_depends()
-#else
-#define smp_mb()	barrier()
-#define smp_rmb()	barrier()
-#define smp_wmb()	barrier()
-#define smp_read_barrier_depends()	do { } while(0)
-#endif
-
-#define set_mb(var, value) \
-do { var = value; mb(); } while (0)
 
 
 /*
 /*
  * switch_to(n) should switch tasks to task nr n, first
  * switch_to(n) should switch tasks to task nr n, first
@@ -217,9 +97,6 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
 		"	.set	mips3					\n"
 		"	.set	mips3					\n"
 		"	sc	%2, %1					\n"
 		"	sc	%2, %1					\n"
 		"	beqzl	%2, 1b					\n"
 		"	beqzl	%2, 1b					\n"
-#ifdef CONFIG_SMP
-		"	sync						\n"
-#endif
 		"	.set	mips0					\n"
 		"	.set	mips0					\n"
 		: "=&r" (retval), "=m" (*m), "=&r" (dummy)
 		: "=&r" (retval), "=m" (*m), "=&r" (dummy)
 		: "R" (*m), "Jr" (val)
 		: "R" (*m), "Jr" (val)
@@ -235,9 +112,6 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
 		"	.set	mips3					\n"
 		"	.set	mips3					\n"
 		"	sc	%2, %1					\n"
 		"	sc	%2, %1					\n"
 		"	beqz	%2, 1b					\n"
 		"	beqz	%2, 1b					\n"
-#ifdef CONFIG_SMP
-		"	sync						\n"
-#endif
 		"	.set	mips0					\n"
 		"	.set	mips0					\n"
 		: "=&r" (retval), "=m" (*m), "=&r" (dummy)
 		: "=&r" (retval), "=m" (*m), "=&r" (dummy)
 		: "R" (*m), "Jr" (val)
 		: "R" (*m), "Jr" (val)
@@ -251,6 +125,8 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
 		local_irq_restore(flags);	/* implies memory barrier  */
 		local_irq_restore(flags);	/* implies memory barrier  */
 	}
 	}
 
 
+	smp_mb();
+
 	return retval;
 	return retval;
 }
 }
 
 
@@ -268,9 +144,6 @@ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
 		"	move	%2, %z4					\n"
 		"	move	%2, %z4					\n"
 		"	scd	%2, %1					\n"
 		"	scd	%2, %1					\n"
 		"	beqzl	%2, 1b					\n"
 		"	beqzl	%2, 1b					\n"
-#ifdef CONFIG_SMP
-		"	sync						\n"
-#endif
 		"	.set	mips0					\n"
 		"	.set	mips0					\n"
 		: "=&r" (retval), "=m" (*m), "=&r" (dummy)
 		: "=&r" (retval), "=m" (*m), "=&r" (dummy)
 		: "R" (*m), "Jr" (val)
 		: "R" (*m), "Jr" (val)
@@ -284,9 +157,6 @@ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
 		"	move	%2, %z4					\n"
 		"	move	%2, %z4					\n"
 		"	scd	%2, %1					\n"
 		"	scd	%2, %1					\n"
 		"	beqz	%2, 1b					\n"
 		"	beqz	%2, 1b					\n"
-#ifdef CONFIG_SMP
-		"	sync						\n"
-#endif
 		"	.set	mips0					\n"
 		"	.set	mips0					\n"
 		: "=&r" (retval), "=m" (*m), "=&r" (dummy)
 		: "=&r" (retval), "=m" (*m), "=&r" (dummy)
 		: "R" (*m), "Jr" (val)
 		: "R" (*m), "Jr" (val)
@@ -300,6 +170,8 @@ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
 		local_irq_restore(flags);	/* implies memory barrier  */
 		local_irq_restore(flags);	/* implies memory barrier  */
 	}
 	}
 
 
+	smp_mb();
+
 	return retval;
 	return retval;
 }
 }
 #else
 #else
@@ -345,9 +217,6 @@ static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
 		"	.set	mips3					\n"
 		"	.set	mips3					\n"
 		"	sc	$1, %1					\n"
 		"	sc	$1, %1					\n"
 		"	beqzl	$1, 1b					\n"
 		"	beqzl	$1, 1b					\n"
-#ifdef CONFIG_SMP
-		"	sync						\n"
-#endif
 		"2:							\n"
 		"2:							\n"
 		"	.set	pop					\n"
 		"	.set	pop					\n"
 		: "=&r" (retval), "=R" (*m)
 		: "=&r" (retval), "=R" (*m)
@@ -365,9 +234,6 @@ static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
 		"	.set	mips3					\n"
 		"	.set	mips3					\n"
 		"	sc	$1, %1					\n"
 		"	sc	$1, %1					\n"
 		"	beqz	$1, 1b					\n"
 		"	beqz	$1, 1b					\n"
-#ifdef CONFIG_SMP
-		"	sync						\n"
-#endif
 		"2:							\n"
 		"2:							\n"
 		"	.set	pop					\n"
 		"	.set	pop					\n"
 		: "=&r" (retval), "=R" (*m)
 		: "=&r" (retval), "=R" (*m)
@@ -383,6 +249,8 @@ static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
 		local_irq_restore(flags);	/* implies memory barrier  */
 		local_irq_restore(flags);	/* implies memory barrier  */
 	}
 	}
 
 
+	smp_mb();
+
 	return retval;
 	return retval;
 }
 }
 
 
@@ -402,9 +270,6 @@ static inline unsigned long __cmpxchg_u64(volatile int * m, unsigned long old,
 		"	move	$1, %z4					\n"
 		"	move	$1, %z4					\n"
 		"	scd	$1, %1					\n"
 		"	scd	$1, %1					\n"
 		"	beqzl	$1, 1b					\n"
 		"	beqzl	$1, 1b					\n"
-#ifdef CONFIG_SMP
-		"	sync						\n"
-#endif
 		"2:							\n"
 		"2:							\n"
 		"	.set	pop					\n"
 		"	.set	pop					\n"
 		: "=&r" (retval), "=R" (*m)
 		: "=&r" (retval), "=R" (*m)
@@ -420,9 +285,6 @@ static inline unsigned long __cmpxchg_u64(volatile int * m, unsigned long old,
 		"	move	$1, %z4					\n"
 		"	move	$1, %z4					\n"
 		"	scd	$1, %1					\n"
 		"	scd	$1, %1					\n"
 		"	beqz	$1, 1b					\n"
 		"	beqz	$1, 1b					\n"
-#ifdef CONFIG_SMP
-		"	sync						\n"
-#endif
 		"2:							\n"
 		"2:							\n"
 		"	.set	pop					\n"
 		"	.set	pop					\n"
 		: "=&r" (retval), "=R" (*m)
 		: "=&r" (retval), "=R" (*m)
@@ -438,6 +300,8 @@ static inline unsigned long __cmpxchg_u64(volatile int * m, unsigned long old,
 		local_irq_restore(flags);	/* implies memory barrier  */
 		local_irq_restore(flags);	/* implies memory barrier  */
 	}
 	}
 
 
+	smp_mb();
+
 	return retval;
 	return retval;
 }
 }
 #else
 #else