提交 91f433ca 编写于 作者: L Linus Torvalds

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
......@@ -16,6 +16,7 @@ config MIPS_MTX1
bool "4G Systems MTX-1 board"
select DMA_NONCOHERENT
select HW_HAS_PCI
select RESOURCES_64BIT if PCI
select SOC_AU1500
select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_LITTLE_ENDIAN
......@@ -32,6 +33,7 @@ config MIPS_PB1000
select SOC_AU1000
select DMA_NONCOHERENT
select HW_HAS_PCI
select RESOURCES_64BIT if PCI
select SWAP_IO_SPACE
select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_LITTLE_ENDIAN
......@@ -41,6 +43,7 @@ config MIPS_PB1100
select SOC_AU1100
select DMA_NONCOHERENT
select HW_HAS_PCI
select RESOURCES_64BIT if PCI
select SWAP_IO_SPACE
select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_LITTLE_ENDIAN
......@@ -50,6 +53,7 @@ config MIPS_PB1500
select SOC_AU1500
select DMA_NONCOHERENT
select HW_HAS_PCI
select RESOURCES_64BIT if PCI
select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_LITTLE_ENDIAN
......@@ -59,6 +63,7 @@ config MIPS_PB1550
select DMA_NONCOHERENT
select HW_HAS_PCI
select MIPS_DISABLE_OBSOLETE_IDE
select RESOURCES_64BIT if PCI
select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_LITTLE_ENDIAN
......@@ -67,6 +72,7 @@ config MIPS_PB1200
select SOC_AU1200
select DMA_NONCOHERENT
select MIPS_DISABLE_OBSOLETE_IDE
select RESOURCES_64BIT if PCI
select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_LITTLE_ENDIAN
......@@ -75,6 +81,7 @@ config MIPS_DB1000
select SOC_AU1000
select DMA_NONCOHERENT
select HW_HAS_PCI
select RESOURCES_64BIT if PCI
select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_LITTLE_ENDIAN
......@@ -91,6 +98,7 @@ config MIPS_DB1500
select DMA_NONCOHERENT
select HW_HAS_PCI
select MIPS_DISABLE_OBSOLETE_IDE
select RESOURCES_64BIT if PCI
select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_LITTLE_ENDIAN
......@@ -101,6 +109,7 @@ config MIPS_DB1550
select HW_HAS_PCI
select DMA_NONCOHERENT
select MIPS_DISABLE_OBSOLETE_IDE
select RESOURCES_64BIT if PCI
select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_LITTLE_ENDIAN
......@@ -1268,6 +1277,7 @@ config CPU_RM9000
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
select CPU_SUPPORTS_HIGHMEM
select WEAK_ORDERING
config CPU_SB1
bool "SB1"
......@@ -1276,6 +1286,7 @@ config CPU_SB1
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
select CPU_SUPPORTS_HIGHMEM
select WEAK_ORDERING
endchoice
......@@ -1336,6 +1347,8 @@ config SYS_HAS_CPU_RM9000
config SYS_HAS_CPU_SB1
bool
config WEAK_ORDERING
bool
endmenu
#
......@@ -1940,6 +1953,11 @@ config COMPAT
depends on MIPS32_COMPAT
default y
config SYSVIPC_COMPAT
bool
depends on COMPAT && SYSVIPC
default y
config MIPS32_O32
bool "Kernel support for o32 binaries"
depends on MIPS32_COMPAT
......
......@@ -382,531 +382,6 @@ asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid,
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
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) {
case SEMOP:
/* 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;
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;
case SEMGET:
err = sys_semget (first, second, third);
err = sys_semget(first, second, third);
break;
case SEMCTL:
err = do_sys32_semctl (first, second, third,
(void __user *)AA(ptr));
err = compat_sys_semctl(first, second, third, compat_ptr(ptr));
break;
case MSGSND:
err = do_sys32_msgsnd (first, second, third,
(void __user *)AA(ptr));
err = compat_sys_msgsnd(first, second, third, compat_ptr(ptr));
break;
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;
case MSGGET:
err = sys_msgget ((key_t) first, second);
err = sys_msgget((key_t) first, second);
break;
case MSGCTL:
err = do_sys32_msgctl (first, second, (void __user *)AA(ptr));
err = compat_sys_msgctl(first, second, compat_ptr(ptr));
break;
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;
case SHMDT:
err = sys_shmdt ((char __user *)A(ptr));
err = sys_shmdt(compat_ptr(ptr));
break;
case SHMGET:
err = sys_shmget (first, (unsigned)second, third);
err = sys_shmget(first, (unsigned)second, third);
break;
case SHMCTL:
err = do_sys32_shmctl (first, second, (void __user *)AA(ptr));
err = compat_sys_shmctl(first, second, compat_ptr(ptr));
break;
default:
err = -EINVAL;
......@@ -969,18 +439,16 @@ sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
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
{
......
......@@ -149,8 +149,8 @@ EXPORT(sysn32_call_table)
PTR sys_mincore
PTR sys_madvise
PTR sys_shmget
PTR sys32_shmat
PTR sys_shmctl /* 6030 */
PTR sys_shmat
PTR compat_sys_shmctl /* 6030 */
PTR sys_dup
PTR sys_dup2
PTR sys_pause
......@@ -184,12 +184,12 @@ EXPORT(sysn32_call_table)
PTR sys32_newuname
PTR sys_semget
PTR sys_semop
PTR sys_semctl
PTR sysn32_semctl
PTR sys_shmdt /* 6065 */
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 sys_flock
PTR sys_fsync
......@@ -335,7 +335,7 @@ EXPORT(sysn32_call_table)
PTR compat_sys_fcntl64
PTR sys_set_tid_address
PTR sys_restart_syscall
PTR sys_semtimedop /* 6215 */
PTR compat_sys_semtimedop /* 6215 */
PTR sys_fadvise64_64
PTR compat_sys_statfs64
PTR compat_sys_fstatfs64
......
......@@ -172,7 +172,7 @@ int smp_call_function (void (*func) (void *info), void *info, int retry,
spin_lock(&smp_call_lock);
call_data = &data;
mb();
smp_mb();
/* Send a message to all other CPUs and wait for them to respond */
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
* about to execute the function.
*/
mb();
smp_mb();
atomic_inc(&call_data->started);
/*
......@@ -215,7 +215,7 @@ void smp_call_function_interrupt(void)
irq_exit();
if (wait) {
mb();
smp_mb();
atomic_inc(&call_data->finished);
}
}
......
......@@ -2,7 +2,7 @@
# 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_MIPS64) += dump_tlb.o
......
/*
* 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)
......@@ -2,7 +2,7 @@
# 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_MIPS64) += dump_tlb.o
......
......@@ -2,8 +2,8 @@
# 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
......
......@@ -11,28 +11,44 @@
#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); \
#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
......@@ -48,37 +64,37 @@
/* unknown src alignment and < 8 bytes to go */
small_csumcpy:
move a1, ta2
move a1, T2
andi ta0, a1, 4
beqz ta0, 1f
andi ta0, a1, 2
andi T0, a1, 4
beqz T0, 1f
andi T0, a1, 2
/* Still a full word to go */
ulw ta1, (src)
daddiu src, 4
ADDC(sum, ta1)
ulw T1, (src)
PTR_ADDIU src, 4
ADDC(sum, T1)
1: move ta1, zero
beqz ta0, 1f
andi ta0, a1, 1
1: move T1, zero
beqz T0, 1f
andi T0, a1, 1
/* Still a halfword to go */
ulhu ta1, (src)
daddiu src, 2
ulhu T1, (src)
PTR_ADDIU src, 2
1: beqz ta0, 1f
sll ta1, ta1, 16
1: beqz T0, 1f
sll T1, T1, 16
lbu ta2, (src)
lbu T2, (src)
nop
#ifdef __MIPSEB__
sll ta2, ta2, 8
sll T2, T2, 8
#endif
or ta1, ta2
or T1, T2
1: ADDC(sum, ta1)
1: ADDC(sum, T1)
/* fold checksum */
sll v1, sum, 16
......@@ -88,7 +104,7 @@ small_csumcpy:
addu sum, v1
/* odd buffer alignment? */
beqz t3, 1f
beqz T7, 1f
nop
sll v1, sum, 8
srl sum, sum, 8
......@@ -106,37 +122,37 @@ small_csumcpy:
.align 5
LEAF(csum_partial)
move sum, zero
move t3, zero
move T7, zero
sltiu t8, a1, 0x8
bnez t8, small_csumcpy /* < 8 bytes to copy */
move ta2, a1
move T2, a1
beqz a1, out
andi t3, src, 0x1 /* odd buffer? */
andi T7, src, 0x1 /* odd buffer? */
hword_align:
beqz t3, word_align
beqz T7, word_align
andi t8, src, 0x2
lbu ta0, (src)
dsubu a1, a1, 0x1
lbu T0, (src)
LONG_SUBU a1, a1, 0x1
#ifdef __MIPSEL__
sll ta0, ta0, 8
sll T0, T0, 8
#endif
ADDC(sum, ta0)
daddu src, src, 0x1
ADDC(sum, T0)
PTR_ADDU 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)
lhu T0, (src)
LONG_SUBU a1, a1, 0x2
ADDC(sum, T0)
sltiu t8, a1, 56
daddu src, src, 0x2
PTR_ADDU src, src, 0x2
dword_align:
bnez t8, do_end_words
......@@ -146,95 +162,95 @@ dword_align:
beqz t8, qword_align
andi t8, src, 0x8
lw ta0, 0x00(src)
dsubu a1, a1, 0x4
ADDC(sum, ta0)
daddu src, src, 0x4
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 ta0, 0x00(src)
lw ta1, 0x04(src)
dsubu a1, a1, 0x8
ADDC(sum, ta0)
ADDC(sum, ta1)
daddu src, src, 0x8
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
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
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 ta2, a1, 0x40
andi T2, 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
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
daddu src, src, 0x80
PTR_ADDU src, src, 0x80
1:
beqz ta2, 1f
andi ta2, a1, 0x20
beqz T2, 1f
andi T2, 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
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 ta2, do_end_words
beqz T2, do_end_words
andi t8, a1, 0x1c
move_32bytes:
CSUM_BIGCHUNK(src, 0x00, sum, ta0, ta1, ta3, t0)
CSUM_BIGCHUNK(src, 0x00, sum, T0, T1, T3, T4)
andi t8, a1, 0x1c
daddu src, src, 0x20
PTR_ADDU src, src, 0x20
do_end_words:
beqz t8, maybe_end_cruft
dsrl t8, t8, 0x2
LONG_SRL t8, t8, 0x2
end_words:
lw ta0, (src)
dsubu t8, t8, 0x1
ADDC(sum, ta0)
lw T0, (src)
LONG_SUBU t8, t8, 0x1
ADDC(sum, T0)
bnez t8, end_words
daddu src, src, 0x4
PTR_ADDU src, src, 0x4
maybe_end_cruft:
andi ta2, a1, 0x3
andi T2, a1, 0x3
small_memcpy:
j small_csumcpy; move a1, ta2 /* XXX ??? */
j small_csumcpy; move a1, T2 /* XXX ??? */
beqz t2, out
move a1, ta2
move a1, T2
end_bytes:
lb ta0, (src)
dsubu a1, a1, 0x1
lb T0, (src)
LONG_SUBU a1, a1, 0x1
bnez a2, end_bytes
daddu src, src, 0x1
PTR_ADDU src, src, 0x1
out:
jr ra
......
......@@ -43,7 +43,7 @@
#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
#include <asm/sibyte/sb1250_regs.h>
#else
#error invalid SiByte board configuation
#error invalid SiByte board configuration
#endif
#include <asm/sibyte/sb1250_genbus.h>
#include <asm/sibyte/board.h>
......@@ -53,7 +53,7 @@ extern void bcm1480_setup(void);
#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
extern void sb1250_setup(void);
#else
#error invalid SiByte board configuation
#error invalid SiByte board configuration
#endif
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)
sb1250_time_init();
#else
#error invalid SiByte board configuation
#error invalid SiByte board configuration
#endif
}
......@@ -111,7 +111,7 @@ void __init plat_mem_setup(void)
#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
sb1250_setup();
#else
#error invalid SiByte board configuation
#error invalid SiByte board configuration
#endif
panic_timeout = 5; /* For debug. */
......
......@@ -15,6 +15,7 @@
#define _ASM_ATOMIC_H
#include <linux/irqflags.h>
#include <asm/barrier.h>
#include <asm/cpu-features.h>
#include <asm/war.h>
......@@ -130,6 +131,8 @@ static __inline__ int atomic_add_return(int i, atomic_t * v)
{
unsigned long result;
smp_mb();
if (cpu_has_llsc && R10000_LLSC_WAR) {
unsigned long temp;
......@@ -140,7 +143,6 @@ static __inline__ int atomic_add_return(int i, atomic_t * v)
" sc %0, %2 \n"
" beqzl %0, 1b \n"
" addu %0, %1, %3 \n"
" sync \n"
" .set mips0 \n"
: "=&r" (result), "=&r" (temp), "=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"
" beqz %0, 1b \n"
" addu %0, %1, %3 \n"
" sync \n"
" .set mips0 \n"
: "=&r" (result), "=&r" (temp), "=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);
}
smp_mb();
return result;
}
......@@ -177,6 +180,8 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v)
{
unsigned long result;
smp_mb();
if (cpu_has_llsc && R10000_LLSC_WAR) {
unsigned long temp;
......@@ -187,7 +192,6 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v)
" sc %0, %2 \n"
" beqzl %0, 1b \n"
" subu %0, %1, %3 \n"
" sync \n"
" .set mips0 \n"
: "=&r" (result), "=&r" (temp), "=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"
" beqz %0, 1b \n"
" subu %0, %1, %3 \n"
" sync \n"
" .set mips0 \n"
: "=&r" (result), "=&r" (temp), "=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);
}
smp_mb();
return result;
}
......@@ -232,6 +237,8 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
{
unsigned long result;
smp_mb();
if (cpu_has_llsc && R10000_LLSC_WAR) {
unsigned long temp;
......@@ -245,7 +252,6 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
" beqzl %0, 1b \n"
" subu %0, %1, %3 \n"
" .set reorder \n"
" sync \n"
"1: \n"
" .set mips0 \n"
: "=&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"
" subu %0, %1, %3 \n"
" .set reorder \n"
" sync \n"
"1: \n"
" .set mips0 \n"
: "=&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);
}
smp_mb();
return result;
}
......@@ -375,7 +382,7 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
#ifdef CONFIG_64BIT
typedef struct { volatile __s64 counter; } atomic64_t;
typedef struct { volatile long counter; } atomic64_t;
#define ATOMIC64_INIT(i) { (i) }
......@@ -484,6 +491,8 @@ static __inline__ long atomic64_add_return(long i, atomic64_t * v)
{
unsigned long result;
smp_mb();
if (cpu_has_llsc && R10000_LLSC_WAR) {
unsigned long temp;
......@@ -494,7 +503,6 @@ static __inline__ long atomic64_add_return(long i, atomic64_t * v)
" scd %0, %2 \n"
" beqzl %0, 1b \n"
" addu %0, %1, %3 \n"
" sync \n"
" .set mips0 \n"
: "=&r" (result), "=&r" (temp), "=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"
" beqz %0, 1b \n"
" addu %0, %1, %3 \n"
" sync \n"
" .set mips0 \n"
: "=&r" (result), "=&r" (temp), "=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);
}
smp_mb();
return result;
}
......@@ -531,6 +540,8 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
{
unsigned long result;
smp_mb();
if (cpu_has_llsc && R10000_LLSC_WAR) {
unsigned long temp;
......@@ -541,7 +552,6 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
" scd %0, %2 \n"
" beqzl %0, 1b \n"
" subu %0, %1, %3 \n"
" sync \n"
" .set mips0 \n"
: "=&r" (result), "=&r" (temp), "=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"
" beqz %0, 1b \n"
" subu %0, %1, %3 \n"
" sync \n"
" .set mips0 \n"
: "=&r" (result), "=&r" (temp), "=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);
}
smp_mb();
return result;
}
......@@ -586,6 +597,8 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
{
unsigned long result;
smp_mb();
if (cpu_has_llsc && R10000_LLSC_WAR) {
unsigned long temp;
......@@ -599,7 +612,6 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
" beqzl %0, 1b \n"
" dsubu %0, %1, %3 \n"
" .set reorder \n"
" sync \n"
"1: \n"
" .set mips0 \n"
: "=&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"
" dsubu %0, %1, %3 \n"
" .set reorder \n"
" sync \n"
"1: \n"
" .set mips0 \n"
: "=&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);
}
smp_mb();
return result;
}
......
/*
* 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 */
......@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* 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.
*/
#ifndef _ASM_BITOPS_H
......@@ -12,6 +12,7 @@
#include <linux/compiler.h>
#include <linux/irqflags.h>
#include <linux/types.h>
#include <asm/barrier.h>
#include <asm/bug.h>
#include <asm/byteorder.h> /* sigh ... */
#include <asm/cpu-features.h>
......@@ -204,9 +205,6 @@ static inline int test_and_set_bit(unsigned long nr,
" " __SC "%2, %1 \n"
" beqzl %2, 1b \n"
" and %2, %0, %3 \n"
#ifdef CONFIG_SMP
" sync \n"
#endif
" .set mips0 \n"
: "=&r" (temp), "=m" (*m), "=&r" (res)
: "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"
" beqz %2, 1b \n"
" and %2, %0, %3 \n"
#ifdef CONFIG_SMP
" sync \n"
#endif
" .set pop \n"
: "=&r" (temp), "=m" (*m), "=&r" (res)
: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
......@@ -250,6 +245,8 @@ static inline int test_and_set_bit(unsigned long nr,
return retval;
}
smp_mb();
}
/*
......@@ -275,9 +272,6 @@ static inline int test_and_clear_bit(unsigned long nr,
" " __SC "%2, %1 \n"
" beqzl %2, 1b \n"
" and %2, %0, %3 \n"
#ifdef CONFIG_SMP
" sync \n"
#endif
" .set mips0 \n"
: "=&r" (temp), "=m" (*m), "=&r" (res)
: "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"
" beqz %2, 1b \n"
" and %2, %0, %3 \n"
#ifdef CONFIG_SMP
" sync \n"
#endif
" .set pop \n"
: "=&r" (temp), "=m" (*m), "=&r" (res)
: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
......@@ -322,6 +313,8 @@ static inline int test_and_clear_bit(unsigned long nr,
return retval;
}
smp_mb();
}
/*
......@@ -346,9 +339,6 @@ static inline int test_and_change_bit(unsigned long nr,
" " __SC "%2, %1 \n"
" beqzl %2, 1b \n"
" and %2, %0, %3 \n"
#ifdef CONFIG_SMP
" sync \n"
#endif
" .set mips0 \n"
: "=&r" (temp), "=m" (*m), "=&r" (res)
: "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"
" beqz %2, 1b \n"
" and %2, %0, %3 \n"
#ifdef CONFIG_SMP
" sync \n"
#endif
" .set pop \n"
: "=&r" (temp), "=m" (*m), "=&r" (res)
: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
......@@ -391,6 +378,8 @@ static inline int test_and_change_bit(unsigned long nr,
return retval;
}
smp_mb();
}
#include <asm-generic/bitops/non-atomic.h>
......
......@@ -32,6 +32,7 @@ typedef struct {
s32 val[2];
} compat_fsid_t;
typedef s32 compat_timer_t;
typedef s32 compat_key_t;
typedef s32 compat_int_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);
}
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 */
/*
* 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
#define _ASM_FUTEX_H
#ifdef __KERNEL__
#include <linux/futex.h>
#include <asm/barrier.h>
#include <asm/errno.h>
#include <asm/uaccess.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) \
{ \
if (cpu_has_llsc && R10000_LLSC_WAR) { \
......@@ -27,7 +29,7 @@
" .set mips3 \n" \
"2: sc $1, %2 \n" \
" beqzl $1, 1b \n" \
__FUTEX_SMP_SYNC \
__WEAK_ORDERING_MB \
"3: \n" \
" .set pop \n" \
" .set mips0 \n" \
......@@ -53,7 +55,7 @@
" .set mips3 \n" \
"2: sc $1, %2 \n" \
" beqz $1, 1b \n" \
__FUTEX_SMP_SYNC \
__WEAK_ORDERING_MB \
"3: \n" \
" .set pop \n" \
" .set mips0 \n" \
......@@ -150,7 +152,7 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
" .set mips3 \n"
"2: sc $1, %1 \n"
" beqzl $1, 1b \n"
__FUTEX_SMP_SYNC
__WEAK_ORDERING_MB
"3: \n"
" .set pop \n"
" .section .fixup,\"ax\" \n"
......@@ -177,7 +179,7 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
" .set mips3 \n"
"2: sc $1, %1 \n"
" beqz $1, 1b \n"
__FUTEX_SMP_SYNC
__WEAK_ORDERING_MB
"3: \n"
" .set pop \n"
" .section .fixup,\"ax\" \n"
......
......@@ -176,7 +176,7 @@ typedef struct kl_config_hdr {
/* --- New Macros for the changed kl_config_hdr_t structure --- */
#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))
......
......@@ -3,12 +3,13 @@
* License. See the file "COPYING" in the main directory of this archive
* 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.
*/
#ifndef _ASM_SPINLOCK_H
#define _ASM_SPINLOCK_H
#include <asm/barrier.h>
#include <asm/war.h>
/*
......@@ -40,7 +41,6 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
" sc %1, %0 \n"
" beqzl %1, 1b \n"
" nop \n"
" sync \n"
" .set reorder \n"
: "=m" (lock->lock), "=&r" (tmp)
: "m" (lock->lock)
......@@ -53,19 +53,22 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
" li %1, 1 \n"
" sc %1, %0 \n"
" beqz %1, 1b \n"
" sync \n"
" nop \n"
" .set reorder \n"
: "=m" (lock->lock), "=&r" (tmp)
: "m" (lock->lock)
: "memory");
}
smp_mb();
}
static inline void __raw_spin_unlock(raw_spinlock_t *lock)
{
smp_mb();
__asm__ __volatile__(
" .set noreorder # __raw_spin_unlock \n"
" sync \n"
" sw $0, %0 \n"
" .set\treorder \n"
: "=m" (lock->lock)
......@@ -86,7 +89,6 @@ static inline unsigned int __raw_spin_trylock(raw_spinlock_t *lock)
" beqzl %2, 1b \n"
" nop \n"
" andi %2, %0, 1 \n"
" sync \n"
" .set reorder"
: "=&r" (temp), "=m" (lock->lock), "=&r" (res)
: "m" (lock->lock)
......@@ -99,13 +101,14 @@ static inline unsigned int __raw_spin_trylock(raw_spinlock_t *lock)
" sc %2, %1 \n"
" beqz %2, 1b \n"
" andi %2, %0, 1 \n"
" sync \n"
" .set reorder"
: "=&r" (temp), "=m" (lock->lock), "=&r" (res)
: "m" (lock->lock)
: "memory");
}
smp_mb();
return res == 0;
}
......@@ -143,7 +146,6 @@ static inline void __raw_read_lock(raw_rwlock_t *rw)
" sc %1, %0 \n"
" beqzl %1, 1b \n"
" nop \n"
" sync \n"
" .set reorder \n"
: "=m" (rw->lock), "=&r" (tmp)
: "m" (rw->lock)
......@@ -156,12 +158,14 @@ static inline void __raw_read_lock(raw_rwlock_t *rw)
" addu %1, 1 \n"
" sc %1, %0 \n"
" beqz %1, 1b \n"
" sync \n"
" nop \n"
" .set reorder \n"
: "=m" (rw->lock), "=&r" (tmp)
: "m" (rw->lock)
: "memory");
}
smp_mb();
}
/* 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;
smp_mb();
if (R10000_LLSC_WAR) {
__asm__ __volatile__(
"1: ll %1, %2 # __raw_read_unlock \n"
" sub %1, 1 \n"
" sc %1, %0 \n"
" beqzl %1, 1b \n"
" sync \n"
: "=m" (rw->lock), "=&r" (tmp)
: "m" (rw->lock)
: "memory");
......@@ -188,7 +193,7 @@ static inline void __raw_read_unlock(raw_rwlock_t *rw)
" sub %1, 1 \n"
" sc %1, %0 \n"
" beqz %1, 1b \n"
" sync \n"
" nop \n"
" .set reorder \n"
: "=m" (rw->lock), "=&r" (tmp)
: "m" (rw->lock)
......@@ -208,7 +213,7 @@ static inline void __raw_write_lock(raw_rwlock_t *rw)
" lui %1, 0x8000 \n"
" sc %1, %0 \n"
" beqzl %1, 1b \n"
" sync \n"
" nop \n"
" .set reorder \n"
: "=m" (rw->lock), "=&r" (tmp)
: "m" (rw->lock)
......@@ -221,18 +226,22 @@ static inline void __raw_write_lock(raw_rwlock_t *rw)
" lui %1, 0x8000 \n"
" sc %1, %0 \n"
" beqz %1, 1b \n"
" sync \n"
" nop \n"
" .set reorder \n"
: "=m" (rw->lock), "=&r" (tmp)
: "m" (rw->lock)
: "memory");
}
smp_mb();
}
static inline void __raw_write_unlock(raw_rwlock_t *rw)
{
smp_mb();
__asm__ __volatile__(
" sync # __raw_write_unlock \n"
" # __raw_write_unlock \n"
" sw $0, %0 \n"
: "=m" (rw->lock)
: "m" (rw->lock)
......@@ -252,11 +261,10 @@ static inline int __raw_read_trylock(raw_rwlock_t *rw)
" bnez %1, 2f \n"
" addu %1, 1 \n"
" sc %1, %0 \n"
" beqzl %1, 1b \n"
" .set reorder \n"
#ifdef CONFIG_SMP
" sync \n"
#endif
" beqzl %1, 1b \n"
" nop \n"
__WEAK_ORDERING_MB
" li %2, 1 \n"
"2: \n"
: "=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"
" sc %1, %0 \n"
" beqz %1, 1b \n"
" nop \n"
" .set reorder \n"
#ifdef CONFIG_SMP
" sync \n"
#endif
__WEAK_ORDERING_MB
" li %2, 1 \n"
"2: \n"
: "=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"
" sc %1, %0 \n"
" beqzl %1, 1b \n"
" sync \n"
" nop \n"
__WEAK_ORDERING_MB
" li %2, 1 \n"
" .set reorder \n"
"2: \n"
......@@ -315,7 +323,8 @@ static inline int __raw_write_trylock(raw_rwlock_t *rw)
" lui %1, 0x8000 \n"
" sc %1, %0 \n"
" beqz %1, 1b \n"
" sync \n"
" nop \n"
__WEAK_ORDERING_MB
" li %2, 1 \n"
" .set reorder \n"
"2: \n"
......
......@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* 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) 1999 Silicon Graphics
* Kevin D. Kissell, kevink@mips.org and Carsten Langgaard, carstenl@mips.com
......@@ -16,132 +16,12 @@
#include <linux/irqflags.h>
#include <asm/addrspace.h>
#include <asm/barrier.h>
#include <asm/cpu-features.h>
#include <asm/dsp.h>
#include <asm/ptrace.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
......@@ -217,9 +97,6 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
" .set mips3 \n"
" sc %2, %1 \n"
" beqzl %2, 1b \n"
#ifdef CONFIG_SMP
" sync \n"
#endif
" .set mips0 \n"
: "=&r" (retval), "=m" (*m), "=&r" (dummy)
: "R" (*m), "Jr" (val)
......@@ -235,9 +112,6 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
" .set mips3 \n"
" sc %2, %1 \n"
" beqz %2, 1b \n"
#ifdef CONFIG_SMP
" sync \n"
#endif
" .set mips0 \n"
: "=&r" (retval), "=m" (*m), "=&r" (dummy)
: "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 */
}
smp_mb();
return retval;
}
......@@ -268,9 +144,6 @@ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
" move %2, %z4 \n"
" scd %2, %1 \n"
" beqzl %2, 1b \n"
#ifdef CONFIG_SMP
" sync \n"
#endif
" .set mips0 \n"
: "=&r" (retval), "=m" (*m), "=&r" (dummy)
: "R" (*m), "Jr" (val)
......@@ -284,9 +157,6 @@ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
" move %2, %z4 \n"
" scd %2, %1 \n"
" beqz %2, 1b \n"
#ifdef CONFIG_SMP
" sync \n"
#endif
" .set mips0 \n"
: "=&r" (retval), "=m" (*m), "=&r" (dummy)
: "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 */
}
smp_mb();
return retval;
}
#else
......@@ -345,9 +217,6 @@ static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
" .set mips3 \n"
" sc $1, %1 \n"
" beqzl $1, 1b \n"
#ifdef CONFIG_SMP
" sync \n"
#endif
"2: \n"
" .set pop \n"
: "=&r" (retval), "=R" (*m)
......@@ -365,9 +234,6 @@ static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
" .set mips3 \n"
" sc $1, %1 \n"
" beqz $1, 1b \n"
#ifdef CONFIG_SMP
" sync \n"
#endif
"2: \n"
" .set pop \n"
: "=&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 */
}
smp_mb();
return retval;
}
......@@ -402,9 +270,6 @@ static inline unsigned long __cmpxchg_u64(volatile int * m, unsigned long old,
" move $1, %z4 \n"
" scd $1, %1 \n"
" beqzl $1, 1b \n"
#ifdef CONFIG_SMP
" sync \n"
#endif
"2: \n"
" .set pop \n"
: "=&r" (retval), "=R" (*m)
......@@ -420,9 +285,6 @@ static inline unsigned long __cmpxchg_u64(volatile int * m, unsigned long old,
" move $1, %z4 \n"
" scd $1, %1 \n"
" beqz $1, 1b \n"
#ifdef CONFIG_SMP
" sync \n"
#endif
"2: \n"
" .set pop \n"
: "=&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 */
}
smp_mb();
return retval;
}
#else
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册