diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 05f6e5caffc9d3c31aac2433671f4d082611e7aa..ea603c4820dad555c86bbd588dc10d82cdaae2a4 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -373,12 +373,45 @@ struct shmid64_ds32 {
 	unsigned int		__unused5;
 };
 
-                                                        
-/*
- * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
- *
- * This is really horribly ugly.
- */
+extern int sem_ctls[];
+#define sc_semopm	(sem_ctls[2])
+#define SEMOPM_FAST	64  /* ~ 372 bytes on stack */
+
+static long
+do_sys32_semtimedop (int semid, struct sembuf *tsops, int nsops,
+		     struct compat_timespec *timeout32)
+{
+	struct sembuf *sops, fast_sops[SEMOPM_FAST];
+	struct timespec t;
+	mm_segment_t oldfs;
+	long ret;
+
+	/* parameter checking precedence should mirror sys_semtimedop() */
+	if (nsops < 1 || semid < 0)
+		return -EINVAL;
+	if (nsops > sc_semopm)
+		return -E2BIG;
+	if (nsops <= SEMOPM_FAST)
+		sops = fast_sops;
+	else {
+		sops = kmalloc(nsops * sizeof(*sops), GFP_KERNEL);
+		if (sops == NULL)
+			return -ENOMEM;
+	}
+	if (copy_from_user(sops, tsops, nsops * sizeof(*tsops)) ||
+	    get_compat_timespec(&t, timeout32))
+		ret = -EFAULT;
+	else {
+		oldfs = get_fs();
+		set_fs(KERNEL_DS);
+		ret = sys_semtimedop(semid, sops, nsops, &t);
+		set_fs(oldfs);
+	}
+	if (sops != fast_sops)
+		kfree(sops);
+	return ret;
+}
+
 #define IPCOP_MASK(__x)	(1UL << (__x))
 static int do_sys32_semctl(int first, int second, int third, void *uptr)
 {
@@ -763,7 +796,12 @@ static int do_sys32_shmctl (int first, int second, void *uptr)
 	return err;
 }
 
-asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
+/*
+ * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation.
+ *
+ * This is really horribly ugly.
+ */
+asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr)
 {
 	int version, err;
 
@@ -773,11 +811,22 @@ asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u
 	if(version)
 		return -EINVAL;
 
-	if (call <= SEMCTL)
+	if (call <= SEMTIMEDOP)
 		switch (call) {
+		case SEMTIMEDOP:
+			if (third) {
+				err = do_sys32_semtimedop(first,
+					(struct sembuf *)AA(ptr),
+					second,
+					(struct compat_timespec *)
+						AA((u32)third));
+				goto out;
+			}
+			/* else fall through for normal semop() */
 		case SEMOP:
 			/* struct sembuf is the same on 32 and 64bit :)) */
-			err = sys_semop (first, (struct sembuf *)AA(ptr), second);
+			err = sys_semtimedop (first, (struct sembuf *)AA(ptr),
+					      second, NULL);
 			goto out;
 		case SEMGET:
 			err = sys_semget (first, second, third);
diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c
index b41f095c1a030d1bb16cfb96cc97c6a10d42715b..51038c69733f6d82cc47a29189ccbadf8737071b 100644
--- a/arch/s390/kernel/sys_s390.c
+++ b/arch/s390/kernel/sys_s390.c
@@ -184,8 +184,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
  * This is really horribly ugly.
  */
 asmlinkage __SYS_RETTYPE sys_ipc (uint call, int first, int second, 
-				  unsigned long third, void *ptr,
-				  unsigned long fifth)
+				  unsigned long third, void *ptr)
 {
         struct ipc_kludge tmp;
 	int ret;
@@ -195,8 +194,8 @@ asmlinkage __SYS_RETTYPE sys_ipc (uint call, int first, int second,
 		return sys_semtimedop (first, (struct sembuf *) ptr, second,
 				       NULL);
 	case SEMTIMEDOP:
-		return sys_semtimedop(first, (struct sembuf *) ptr, second,
-				      (const struct timespec *) fifth);
+		return sys_semtimedop (first, (struct sembuf *) ptr, second,
+				       (const struct timespec *) third);
         case SEMGET:
                 return sys_semget (first, second, third);
         case SEMCTL: {