Jelajahi Sumber

Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git

Signed-off-by: Steve French <sfrench@us.ibm.com>
Steve French 19 tahun lalu
induk
melakukan
4c8af5254e
45 mengubah file dengan 540 tambahan dan 656 penghapusan
  1. 12 16
      arch/ia64/ia32/sys_ia32.c
  2. 6 5
      arch/ia64/kernel/perfmon.c
  3. 1 0
      arch/ia64/kernel/uncached.c
  4. 9 0
      arch/ia64/sn/include/xtalk/hubdev.h
  5. 51 3
      arch/ia64/sn/kernel/io_init.c
  6. 4 3
      arch/ia64/sn/kernel/mca.c
  7. 9 8
      arch/ia64/sn/kernel/xp_main.c
  8. 14 20
      arch/ia64/sn/kernel/xpc_channel.c
  9. 9 8
      arch/ia64/sn/kernel/xpc_main.c
  10. 8 4
      arch/ia64/sn/pci/pcibr/pcibr_provider.c
  11. 0 56
      arch/sparc/kernel/entry.S
  12. 4 5
      arch/sparc/kernel/rtrap.S
  13. 31 86
      arch/sparc/kernel/signal.c
  14. 0 2
      arch/sparc/kernel/sparc_ksyms.c
  15. 9 1
      arch/sparc/kernel/systbls.S
  16. 0 23
      arch/sparc64/kernel/entry.S
  17. 15 18
      arch/sparc64/kernel/rtrap.S
  18. 40 111
      arch/sparc64/kernel/signal.c
  19. 19 103
      arch/sparc64/kernel/signal32.c
  20. 2 2
      arch/sparc64/kernel/sparc64_ksyms.c
  21. 17 4
      arch/sparc64/kernel/systbls.S
  22. 2 0
      arch/sparc64/solaris/entry64.S
  23. 58 71
      drivers/serial/sn_console.c
  24. 2 2
      fs/compat.c
  25. 4 4
      include/asm-ia64/semaphore.h
  26. 2 1
      include/asm-ia64/sn/xp.h
  27. 5 4
      include/asm-ia64/sn/xpc.h
  28. 4 0
      include/asm-ia64/topology.h
  29. 2 0
      include/asm-sparc/oplib.h
  30. 3 2
      include/asm-sparc/thread_info.h
  31. 19 3
      include/asm-sparc/unistd.h
  32. 3 3
      include/asm-sparc64/thread_info.h
  33. 20 3
      include/asm-sparc64/unistd.h
  34. 1 1
      include/linux/netfilter/x_tables.h
  35. 2 0
      include/net/sctp/sctp.h
  36. 51 38
      include/net/sctp/structs.h
  37. 62 13
      net/sctp/input.c
  38. 3 1
      net/sctp/inqueue.c
  39. 12 20
      net/sctp/proc.c
  40. 13 3
      net/sctp/sm_make_chunk.c
  41. 2 2
      net/sctp/sm_sideeffect.c
  42. 2 0
      net/sctp/sm_statefuns.c
  43. 5 1
      net/sctp/socket.c
  44. 2 5
      net/sctp/sysctl.c
  45. 1 1
      net/sctp/transport.c

+ 12 - 16
arch/ia64/ia32/sys_ia32.c

@@ -52,9 +52,9 @@
 #include <linux/compat.h>
 #include <linux/compat.h>
 #include <linux/vfs.h>
 #include <linux/vfs.h>
 #include <linux/mman.h>
 #include <linux/mman.h>
+#include <linux/mutex.h>
 
 
 #include <asm/intrinsics.h>
 #include <asm/intrinsics.h>
-#include <asm/semaphore.h>
 #include <asm/types.h>
 #include <asm/types.h>
 #include <asm/uaccess.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 #include <asm/unistd.h>
@@ -86,7 +86,7 @@
  * while doing so.
  * while doing so.
  */
  */
 /* XXX make per-mm: */
 /* XXX make per-mm: */
-static DECLARE_MUTEX(ia32_mmap_sem);
+static DEFINE_MUTEX(ia32_mmap_mutex);
 
 
 asmlinkage long
 asmlinkage long
 sys32_execve (char __user *name, compat_uptr_t __user *argv, compat_uptr_t __user *envp,
 sys32_execve (char __user *name, compat_uptr_t __user *argv, compat_uptr_t __user *envp,
@@ -895,11 +895,11 @@ ia32_do_mmap (struct file *file, unsigned long addr, unsigned long len, int prot
 	prot = get_prot32(prot);
 	prot = get_prot32(prot);
 
 
 #if PAGE_SHIFT > IA32_PAGE_SHIFT
 #if PAGE_SHIFT > IA32_PAGE_SHIFT
-	down(&ia32_mmap_sem);
+	mutex_lock(&ia32_mmap_mutex);
 	{
 	{
 		addr = emulate_mmap(file, addr, len, prot, flags, offset);
 		addr = emulate_mmap(file, addr, len, prot, flags, offset);
 	}
 	}
-	up(&ia32_mmap_sem);
+	mutex_unlock(&ia32_mmap_mutex);
 #else
 #else
 	down_write(&current->mm->mmap_sem);
 	down_write(&current->mm->mmap_sem);
 	{
 	{
@@ -1000,11 +1000,9 @@ sys32_munmap (unsigned int start, unsigned int len)
 	if (start >= end)
 	if (start >= end)
 		return 0;
 		return 0;
 
 
-	down(&ia32_mmap_sem);
-	{
-		ret = sys_munmap(start, end - start);
-	}
-	up(&ia32_mmap_sem);
+	mutex_lock(&ia32_mmap_mutex);
+	ret = sys_munmap(start, end - start);
+	mutex_unlock(&ia32_mmap_mutex);
 #endif
 #endif
 	return ret;
 	return ret;
 }
 }
@@ -1056,7 +1054,7 @@ sys32_mprotect (unsigned int start, unsigned int len, int prot)
 	if (retval < 0)
 	if (retval < 0)
 		return retval;
 		return retval;
 
 
-	down(&ia32_mmap_sem);
+	mutex_lock(&ia32_mmap_mutex);
 	{
 	{
 		if (offset_in_page(start)) {
 		if (offset_in_page(start)) {
 			/* start address is 4KB aligned but not page aligned. */
 			/* start address is 4KB aligned but not page aligned. */
@@ -1080,7 +1078,7 @@ sys32_mprotect (unsigned int start, unsigned int len, int prot)
 		retval = sys_mprotect(start, end - start, prot);
 		retval = sys_mprotect(start, end - start, prot);
 	}
 	}
   out:
   out:
-	up(&ia32_mmap_sem);
+	mutex_unlock(&ia32_mmap_mutex);
 	return retval;
 	return retval;
 #endif
 #endif
 }
 }
@@ -1124,11 +1122,9 @@ sys32_mremap (unsigned int addr, unsigned int old_len, unsigned int new_len,
 	old_len = PAGE_ALIGN(old_end) - addr;
 	old_len = PAGE_ALIGN(old_end) - addr;
 	new_len = PAGE_ALIGN(new_end) - addr;
 	new_len = PAGE_ALIGN(new_end) - addr;
 
 
-	down(&ia32_mmap_sem);
-	{
-		ret = sys_mremap(addr, old_len, new_len, flags, new_addr);
-	}
-	up(&ia32_mmap_sem);
+	mutex_lock(&ia32_mmap_mutex);
+	ret = sys_mremap(addr, old_len, new_len, flags, new_addr);
+	mutex_unlock(&ia32_mmap_mutex);
 
 
 	if ((ret >= 0) && (old_len < new_len)) {
 	if ((ret >= 0) && (old_len < new_len)) {
 		/* mremap expanded successfully */
 		/* mremap expanded successfully */

+ 6 - 5
arch/ia64/kernel/perfmon.c

@@ -40,6 +40,7 @@
 #include <linux/bitops.h>
 #include <linux/bitops.h>
 #include <linux/capability.h>
 #include <linux/capability.h>
 #include <linux/rcupdate.h>
 #include <linux/rcupdate.h>
+#include <linux/completion.h>
 
 
 #include <asm/errno.h>
 #include <asm/errno.h>
 #include <asm/intrinsics.h>
 #include <asm/intrinsics.h>
@@ -286,7 +287,7 @@ typedef struct pfm_context {
 
 
 	unsigned long		ctx_ovfl_regs[4];	/* which registers overflowed (notification) */
 	unsigned long		ctx_ovfl_regs[4];	/* which registers overflowed (notification) */
 
 
-	struct semaphore	ctx_restart_sem;   	/* use for blocking notification mode */
+	struct completion	ctx_restart_done;  	/* use for blocking notification mode */
 
 
 	unsigned long		ctx_used_pmds[4];	/* bitmask of PMD used            */
 	unsigned long		ctx_used_pmds[4];	/* bitmask of PMD used            */
 	unsigned long		ctx_all_pmds[4];	/* bitmask of all accessible PMDs */
 	unsigned long		ctx_all_pmds[4];	/* bitmask of all accessible PMDs */
@@ -1991,7 +1992,7 @@ pfm_close(struct inode *inode, struct file *filp)
 		/*
 		/*
 		 * force task to wake up from MASKED state
 		 * force task to wake up from MASKED state
 		 */
 		 */
-		up(&ctx->ctx_restart_sem);
+		complete(&ctx->ctx_restart_done);
 
 
 		DPRINT(("waking up ctx_state=%d\n", state));
 		DPRINT(("waking up ctx_state=%d\n", state));
 
 
@@ -2706,7 +2707,7 @@ pfm_context_create(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg
 	/*
 	/*
 	 * init restart semaphore to locked
 	 * init restart semaphore to locked
 	 */
 	 */
-	sema_init(&ctx->ctx_restart_sem, 0);
+	init_completion(&ctx->ctx_restart_done);
 
 
 	/*
 	/*
 	 * activation is used in SMP only
 	 * activation is used in SMP only
@@ -3687,7 +3688,7 @@ pfm_restart(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
 	 */
 	 */
 	if (CTX_OVFL_NOBLOCK(ctx) == 0 && state == PFM_CTX_MASKED) {
 	if (CTX_OVFL_NOBLOCK(ctx) == 0 && state == PFM_CTX_MASKED) {
 		DPRINT(("unblocking [%d] \n", task->pid));
 		DPRINT(("unblocking [%d] \n", task->pid));
-		up(&ctx->ctx_restart_sem);
+		complete(&ctx->ctx_restart_done);
 	} else {
 	} else {
 		DPRINT(("[%d] armed exit trap\n", task->pid));
 		DPRINT(("[%d] armed exit trap\n", task->pid));
 
 
@@ -5089,7 +5090,7 @@ pfm_handle_work(void)
 	 * may go through without blocking on SMP systems
 	 * may go through without blocking on SMP systems
 	 * if restart has been received already by the time we call down()
 	 * if restart has been received already by the time we call down()
 	 */
 	 */
-	ret = down_interruptible(&ctx->ctx_restart_sem);
+	ret = wait_for_completion_interruptible(&ctx->ctx_restart_done);
 
 
 	DPRINT(("after block sleeping ret=%d\n", ret));
 	DPRINT(("after block sleeping ret=%d\n", ret));
 
 

+ 1 - 0
arch/ia64/kernel/uncached.c

@@ -210,6 +210,7 @@ uncached_build_memmap(unsigned long start, unsigned long end, void *arg)
 
 
 	dprintk(KERN_ERR "uncached_build_memmap(%lx %lx)\n", start, end);
 	dprintk(KERN_ERR "uncached_build_memmap(%lx %lx)\n", start, end);
 
 
+	touch_softlockup_watchdog();
 	memset((char *)start, 0, length);
 	memset((char *)start, 0, length);
 
 
 	node = paddr_to_nid(start - __IA64_UNCACHED_OFFSET);
 	node = paddr_to_nid(start - __IA64_UNCACHED_OFFSET);

+ 9 - 0
arch/ia64/sn/include/xtalk/hubdev.h

@@ -51,6 +51,15 @@ struct sn_flush_device_kernel {
 	struct sn_flush_device_common *common;
 	struct sn_flush_device_common *common;
 };
 };
 
 
+/* 01/16/06 This struct is the old PROM/kernel struct and needs to be included
+ * for older official PROMs to function on the new kernel base.  This struct
+ * will be removed when the next official PROM release occurs. */
+
+struct sn_flush_device_war {
+	struct sn_flush_device_common common;
+	u32 filler; /* older PROMs expect the default size of a spinlock_t */
+};
+
 /*
 /*
  * **widget_p - Used as an array[wid_num][device] of sn_flush_device_kernel.
  * **widget_p - Used as an array[wid_num][device] of sn_flush_device_kernel.
  */
  */

+ 51 - 3
arch/ia64/sn/kernel/io_init.c

@@ -165,8 +165,45 @@ sn_pcidev_info_get(struct pci_dev *dev)
 	return NULL;
 	return NULL;
 }
 }
 
 
+/* Older PROM flush WAR
+ *
+ * 01/16/06 -- This war will be in place until a new official PROM is released.
+ * Additionally note that the struct sn_flush_device_war also has to be
+ * removed from arch/ia64/sn/include/xtalk/hubdev.h
+ */
+static u8 war_implemented = 0;
+
+static void sn_device_fixup_war(u64 nasid, u64 widget, int device,
+				struct sn_flush_device_common *common)
+{
+	struct sn_flush_device_war *war_list;
+	struct sn_flush_device_war *dev_entry;
+	struct ia64_sal_retval isrv = {0,0,0,0};
+
+	if (!war_implemented) {
+		printk(KERN_WARNING "PROM version < 4.50 -- implementing old "
+		       "PROM flush WAR\n");
+		war_implemented = 1;
+	}
+
+	war_list = kzalloc(DEV_PER_WIDGET * sizeof(*war_list), GFP_KERNEL);
+	if (!war_list)
+		BUG();
+
+	SAL_CALL_NOLOCK(isrv, SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST,
+			nasid, widget, __pa(war_list), 0, 0, 0 ,0);
+	if (isrv.status)
+		panic("sn_device_fixup_war failed: %s\n",
+		      ia64_sal_strerror(isrv.status));
+
+	dev_entry = war_list + device;
+	memcpy(common,dev_entry, sizeof(*common));
+
+	kfree(war_list);
+}
+
 /*
 /*
- * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for 
+ * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for
  *	each node in the system.
  *	each node in the system.
  */
  */
 static void sn_fixup_ionodes(void)
 static void sn_fixup_ionodes(void)
@@ -246,8 +283,19 @@ static void sn_fixup_ionodes(void)
 									widget,
 									widget,
 								       	device,
 								       	device,
 						      (u64)(dev_entry->common));
 						      (u64)(dev_entry->common));
-				if (status)
-					BUG();
+				if (status) {
+					if (sn_sal_rev() < 0x0450) {
+						/* shortlived WAR for older
+						 * PROM images
+						 */
+						sn_device_fixup_war(nasid,
+								    widget,
+								    device,
+							     dev_entry->common);
+					}
+					else
+						BUG();
+				}
 
 
 				spin_lock_init(&dev_entry->sfdl_flush_lock);
 				spin_lock_init(&dev_entry->sfdl_flush_lock);
 			}
 			}

+ 4 - 3
arch/ia64/sn/kernel/mca.c

@@ -10,6 +10,7 @@
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/timer.h>
 #include <linux/timer.h>
 #include <linux/vmalloc.h>
 #include <linux/vmalloc.h>
+#include <linux/mutex.h>
 #include <asm/mca.h>
 #include <asm/mca.h>
 #include <asm/sal.h>
 #include <asm/sal.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/sn_sal.h>
@@ -27,7 +28,7 @@ void sn_init_cpei_timer(void);
 /* Printing oemdata from mca uses data that is not passed through SAL, it is
 /* Printing oemdata from mca uses data that is not passed through SAL, it is
  * global.  Only one user at a time.
  * global.  Only one user at a time.
  */
  */
-static DECLARE_MUTEX(sn_oemdata_mutex);
+static DEFINE_MUTEX(sn_oemdata_mutex);
 static u8 **sn_oemdata;
 static u8 **sn_oemdata;
 static u64 *sn_oemdata_size, sn_oemdata_bufsize;
 static u64 *sn_oemdata_size, sn_oemdata_bufsize;
 
 
@@ -89,7 +90,7 @@ static int
 sn_platform_plat_specific_err_print(const u8 * sect_header, u8 ** oemdata,
 sn_platform_plat_specific_err_print(const u8 * sect_header, u8 ** oemdata,
 				    u64 * oemdata_size)
 				    u64 * oemdata_size)
 {
 {
-	down(&sn_oemdata_mutex);
+	mutex_lock(&sn_oemdata_mutex);
 	sn_oemdata = oemdata;
 	sn_oemdata = oemdata;
 	sn_oemdata_size = oemdata_size;
 	sn_oemdata_size = oemdata_size;
 	sn_oemdata_bufsize = 0;
 	sn_oemdata_bufsize = 0;
@@ -107,7 +108,7 @@ sn_platform_plat_specific_err_print(const u8 * sect_header, u8 ** oemdata,
 		*sn_oemdata_size = 0;
 		*sn_oemdata_size = 0;
 		ia64_sn_plat_specific_err_print(print_hook, (char *)sect_header);
 		ia64_sn_plat_specific_err_print(print_hook, (char *)sect_header);
 	}
 	}
-	up(&sn_oemdata_mutex);
+	mutex_unlock(&sn_oemdata_mutex);
 	return 0;
 	return 0;
 }
 }
 
 

+ 9 - 8
arch/ia64/sn/kernel/xp_main.c

@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 #include <asm/sn/intr.h>
 #include <asm/sn/intr.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/xp.h>
 #include <asm/sn/xp.h>
@@ -136,13 +137,13 @@ xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
 
 
 	registration = &xpc_registrations[ch_number];
 	registration = &xpc_registrations[ch_number];
 
 
-	if (down_interruptible(&registration->sema) != 0) {
+	if (mutex_lock_interruptible(&registration->mutex) != 0) {
 		return xpcInterrupted;
 		return xpcInterrupted;
 	}
 	}
 
 
 	/* if XPC_CHANNEL_REGISTERED(ch_number) */
 	/* if XPC_CHANNEL_REGISTERED(ch_number) */
 	if (registration->func != NULL) {
 	if (registration->func != NULL) {
-		up(&registration->sema);
+		mutex_unlock(&registration->mutex);
 		return xpcAlreadyRegistered;
 		return xpcAlreadyRegistered;
 	}
 	}
 
 
@@ -154,7 +155,7 @@ xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
 	registration->key = key;
 	registration->key = key;
 	registration->func = func;
 	registration->func = func;
 
 
-	up(&registration->sema);
+	mutex_unlock(&registration->mutex);
 
 
 	xpc_interface.connect(ch_number);
 	xpc_interface.connect(ch_number);
 
 
@@ -190,11 +191,11 @@ xpc_disconnect(int ch_number)
 	 * figured XPC's users will just turn around and call xpc_disconnect()
 	 * figured XPC's users will just turn around and call xpc_disconnect()
 	 * again anyways, so we might as well wait, if need be.
 	 * again anyways, so we might as well wait, if need be.
 	 */
 	 */
-	down(&registration->sema);
+	mutex_lock(&registration->mutex);
 
 
 	/* if !XPC_CHANNEL_REGISTERED(ch_number) */
 	/* if !XPC_CHANNEL_REGISTERED(ch_number) */
 	if (registration->func == NULL) {
 	if (registration->func == NULL) {
-		up(&registration->sema);
+		mutex_unlock(&registration->mutex);
 		return;
 		return;
 	}
 	}
 
 
@@ -208,7 +209,7 @@ xpc_disconnect(int ch_number)
 
 
 	xpc_interface.disconnect(ch_number);
 	xpc_interface.disconnect(ch_number);
 
 
-	up(&registration->sema);
+	mutex_unlock(&registration->mutex);
 
 
 	return;
 	return;
 }
 }
@@ -250,9 +251,9 @@ xp_init(void)
 		xp_nofault_PIOR_target = SH1_IPI_ACCESS;
 		xp_nofault_PIOR_target = SH1_IPI_ACCESS;
 	}
 	}
 
 
-	/* initialize the connection registration semaphores */
+	/* initialize the connection registration mutex */
 	for (ch_number = 0; ch_number < XPC_NCHANNELS; ch_number++) {
 	for (ch_number = 0; ch_number < XPC_NCHANNELS; ch_number++) {
-		sema_init(&xpc_registrations[ch_number].sema, 1);  /* mutex */
+		mutex_init(&xpc_registrations[ch_number].mutex);
 	}
 	}
 
 
 	return 0;
 	return 0;

+ 14 - 20
arch/ia64/sn/kernel/xpc_channel.c

@@ -22,6 +22,8 @@
 #include <linux/cache.h>
 #include <linux/cache.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
 #include <asm/sn/bte.h>
 #include <asm/sn/bte.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/xpc.h>
 #include <asm/sn/xpc.h>
@@ -56,8 +58,8 @@ xpc_initialize_channels(struct xpc_partition *part, partid_t partid)
 		atomic_set(&ch->n_to_notify, 0);
 		atomic_set(&ch->n_to_notify, 0);
 
 
 		spin_lock_init(&ch->lock);
 		spin_lock_init(&ch->lock);
-		sema_init(&ch->msg_to_pull_sema, 1);	/* mutex */
-		sema_init(&ch->wdisconnect_sema, 0);	/* event wait */
+		mutex_init(&ch->msg_to_pull_mutex);
+		init_completion(&ch->wdisconnect_wait);
 
 
 		atomic_set(&ch->n_on_msg_allocate_wq, 0);
 		atomic_set(&ch->n_on_msg_allocate_wq, 0);
 		init_waitqueue_head(&ch->msg_allocate_wq);
 		init_waitqueue_head(&ch->msg_allocate_wq);
@@ -534,7 +536,6 @@ static enum xpc_retval
 xpc_allocate_msgqueues(struct xpc_channel *ch)
 xpc_allocate_msgqueues(struct xpc_channel *ch)
 {
 {
 	unsigned long irq_flags;
 	unsigned long irq_flags;
-	int i;
 	enum xpc_retval ret;
 	enum xpc_retval ret;
 
 
 
 
@@ -552,11 +553,6 @@ xpc_allocate_msgqueues(struct xpc_channel *ch)
 		return ret;
 		return ret;
 	}
 	}
 
 
-	for (i = 0; i < ch->local_nentries; i++) {
-		/* use a semaphore as an event wait queue */
-		sema_init(&ch->notify_queue[i].sema, 0);
-	}
-
 	spin_lock_irqsave(&ch->lock, irq_flags);
 	spin_lock_irqsave(&ch->lock, irq_flags);
 	ch->flags |= XPC_C_SETUP;
 	ch->flags |= XPC_C_SETUP;
 	spin_unlock_irqrestore(&ch->lock, irq_flags);
 	spin_unlock_irqrestore(&ch->lock, irq_flags);
@@ -799,10 +795,8 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
 	}
 	}
 
 
 	if (ch->flags & XPC_C_WDISCONNECT) {
 	if (ch->flags & XPC_C_WDISCONNECT) {
-		spin_unlock_irqrestore(&ch->lock, *irq_flags);
-		up(&ch->wdisconnect_sema);
-		spin_lock_irqsave(&ch->lock, *irq_flags);
-
+		/* we won't lose the CPU since we're holding ch->lock */
+		complete(&ch->wdisconnect_wait);
 	} else if (ch->delayed_IPI_flags) {
 	} else if (ch->delayed_IPI_flags) {
 		if (part->act_state != XPC_P_DEACTIVATING) {
 		if (part->act_state != XPC_P_DEACTIVATING) {
 			/* time to take action on any delayed IPI flags */
 			/* time to take action on any delayed IPI flags */
@@ -1092,12 +1086,12 @@ xpc_connect_channel(struct xpc_channel *ch)
 	struct xpc_registration *registration = &xpc_registrations[ch->number];
 	struct xpc_registration *registration = &xpc_registrations[ch->number];
 
 
 
 
-	if (down_trylock(&registration->sema) != 0) {
+	if (mutex_trylock(&registration->mutex) == 0) {
 		return xpcRetry;
 		return xpcRetry;
 	}
 	}
 
 
 	if (!XPC_CHANNEL_REGISTERED(ch->number)) {
 	if (!XPC_CHANNEL_REGISTERED(ch->number)) {
-		up(&registration->sema);
+		mutex_unlock(&registration->mutex);
 		return xpcUnregistered;
 		return xpcUnregistered;
 	}
 	}
 
 
@@ -1108,7 +1102,7 @@ xpc_connect_channel(struct xpc_channel *ch)
 
 
 	if (ch->flags & XPC_C_DISCONNECTING) {
 	if (ch->flags & XPC_C_DISCONNECTING) {
 		spin_unlock_irqrestore(&ch->lock, irq_flags);
 		spin_unlock_irqrestore(&ch->lock, irq_flags);
-		up(&registration->sema);
+		mutex_unlock(&registration->mutex);
 		return ch->reason;
 		return ch->reason;
 	}
 	}
 
 
@@ -1140,7 +1134,7 @@ xpc_connect_channel(struct xpc_channel *ch)
 			 * channel lock be locked and will unlock and relock
 			 * channel lock be locked and will unlock and relock
 			 * the channel lock as needed.
 			 * the channel lock as needed.
 			 */
 			 */
-			up(&registration->sema);
+			mutex_unlock(&registration->mutex);
 			XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes,
 			XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes,
 								&irq_flags);
 								&irq_flags);
 			spin_unlock_irqrestore(&ch->lock, irq_flags);
 			spin_unlock_irqrestore(&ch->lock, irq_flags);
@@ -1155,7 +1149,7 @@ xpc_connect_channel(struct xpc_channel *ch)
 		atomic_inc(&xpc_partitions[ch->partid].nchannels_active);
 		atomic_inc(&xpc_partitions[ch->partid].nchannels_active);
 	}
 	}
 
 
-	up(&registration->sema);
+	mutex_unlock(&registration->mutex);
 
 
 
 
 	/* initiate the connection */
 	/* initiate the connection */
@@ -2089,7 +2083,7 @@ xpc_pull_remote_msg(struct xpc_channel *ch, s64 get)
 	enum xpc_retval ret;
 	enum xpc_retval ret;
 
 
 
 
-	if (down_interruptible(&ch->msg_to_pull_sema) != 0) {
+	if (mutex_lock_interruptible(&ch->msg_to_pull_mutex) != 0) {
 		/* we were interrupted by a signal */
 		/* we were interrupted by a signal */
 		return NULL;
 		return NULL;
 	}
 	}
@@ -2125,7 +2119,7 @@ xpc_pull_remote_msg(struct xpc_channel *ch, s64 get)
 
 
 			XPC_DEACTIVATE_PARTITION(part, ret);
 			XPC_DEACTIVATE_PARTITION(part, ret);
 
 
-			up(&ch->msg_to_pull_sema);
+			mutex_unlock(&ch->msg_to_pull_mutex);
 			return NULL;
 			return NULL;
 		}
 		}
 
 
@@ -2134,7 +2128,7 @@ xpc_pull_remote_msg(struct xpc_channel *ch, s64 get)
 		ch->next_msg_to_pull += nmsgs;
 		ch->next_msg_to_pull += nmsgs;
 	}
 	}
 
 
-	up(&ch->msg_to_pull_sema);
+	mutex_unlock(&ch->msg_to_pull_mutex);
 
 
 	/* return the message we were looking for */
 	/* return the message we were looking for */
 	msg_offset = (get % ch->remote_nentries) * ch->msg_size;
 	msg_offset = (get % ch->remote_nentries) * ch->msg_size;

+ 9 - 8
arch/ia64/sn/kernel/xpc_main.c

@@ -55,6 +55,7 @@
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
 #include <linux/reboot.h>
 #include <linux/reboot.h>
+#include <linux/completion.h>
 #include <asm/sn/intr.h>
 #include <asm/sn/intr.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/kdebug.h>
 #include <asm/kdebug.h>
@@ -177,10 +178,10 @@ static DECLARE_WAIT_QUEUE_HEAD(xpc_act_IRQ_wq);
 static unsigned long xpc_hb_check_timeout;
 static unsigned long xpc_hb_check_timeout;
 
 
 /* notification that the xpc_hb_checker thread has exited */
 /* notification that the xpc_hb_checker thread has exited */
-static DECLARE_MUTEX_LOCKED(xpc_hb_checker_exited);
+static DECLARE_COMPLETION(xpc_hb_checker_exited);
 
 
 /* notification that the xpc_discovery thread has exited */
 /* notification that the xpc_discovery thread has exited */
-static DECLARE_MUTEX_LOCKED(xpc_discovery_exited);
+static DECLARE_COMPLETION(xpc_discovery_exited);
 
 
 
 
 static struct timer_list xpc_hb_timer;
 static struct timer_list xpc_hb_timer;
@@ -321,7 +322,7 @@ xpc_hb_checker(void *ignore)
 
 
 
 
 	/* mark this thread as having exited */
 	/* mark this thread as having exited */
-	up(&xpc_hb_checker_exited);
+	complete(&xpc_hb_checker_exited);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -341,7 +342,7 @@ xpc_initiate_discovery(void *ignore)
 	dev_dbg(xpc_part, "discovery thread is exiting\n");
 	dev_dbg(xpc_part, "discovery thread is exiting\n");
 
 
 	/* mark this thread as having exited */
 	/* mark this thread as having exited */
-	up(&xpc_discovery_exited);
+	complete(&xpc_discovery_exited);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -893,7 +894,7 @@ xpc_disconnect_wait(int ch_number)
 			continue;
 			continue;
 		}
 		}
 
 
-		(void) down(&ch->wdisconnect_sema);
+		wait_for_completion(&ch->wdisconnect_wait);
 
 
 		spin_lock_irqsave(&ch->lock, irq_flags);
 		spin_lock_irqsave(&ch->lock, irq_flags);
 		DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED));
 		DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED));
@@ -946,10 +947,10 @@ xpc_do_exit(enum xpc_retval reason)
 	free_irq(SGI_XPC_ACTIVATE, NULL);
 	free_irq(SGI_XPC_ACTIVATE, NULL);
 
 
 	/* wait for the discovery thread to exit */
 	/* wait for the discovery thread to exit */
-	down(&xpc_discovery_exited);
+	wait_for_completion(&xpc_discovery_exited);
 
 
 	/* wait for the heartbeat checker thread to exit */
 	/* wait for the heartbeat checker thread to exit */
-	down(&xpc_hb_checker_exited);
+	wait_for_completion(&xpc_hb_checker_exited);
 
 
 
 
 	/* sleep for a 1/3 of a second or so */
 	/* sleep for a 1/3 of a second or so */
@@ -1367,7 +1368,7 @@ xpc_init(void)
 		dev_err(xpc_part, "failed while forking discovery thread\n");
 		dev_err(xpc_part, "failed while forking discovery thread\n");
 
 
 		/* mark this new thread as a non-starter */
 		/* mark this new thread as a non-starter */
-		up(&xpc_discovery_exited);
+		complete(&xpc_discovery_exited);
 
 
 		xpc_do_exit(xpcUnloading);
 		xpc_do_exit(xpcUnloading);
 		return -EBUSY;
 		return -EBUSY;

+ 8 - 4
arch/ia64/sn/pci/pcibr/pcibr_provider.c

@@ -24,13 +24,15 @@ sal_pcibr_slot_enable(struct pcibus_info *soft, int device, void *resp)
 {
 {
 	struct ia64_sal_retval ret_stuff;
 	struct ia64_sal_retval ret_stuff;
 	u64 busnum;
 	u64 busnum;
+	u64 segment;
 
 
 	ret_stuff.status = 0;
 	ret_stuff.status = 0;
 	ret_stuff.v0 = 0;
 	ret_stuff.v0 = 0;
 
 
+	segment = soft->pbi_buscommon.bs_persist_segment;
 	busnum = soft->pbi_buscommon.bs_persist_busnum;
 	busnum = soft->pbi_buscommon.bs_persist_busnum;
-	SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_ENABLE, (u64) busnum,
-			(u64) device, (u64) resp, 0, 0, 0, 0);
+	SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_ENABLE, segment,
+			busnum, (u64) device, (u64) resp, 0, 0, 0);
 
 
 	return (int)ret_stuff.v0;
 	return (int)ret_stuff.v0;
 }
 }
@@ -41,14 +43,16 @@ sal_pcibr_slot_disable(struct pcibus_info *soft, int device, int action,
 {
 {
 	struct ia64_sal_retval ret_stuff;
 	struct ia64_sal_retval ret_stuff;
 	u64 busnum;
 	u64 busnum;
+	u64 segment;
 
 
 	ret_stuff.status = 0;
 	ret_stuff.status = 0;
 	ret_stuff.v0 = 0;
 	ret_stuff.v0 = 0;
 
 
+	segment = soft->pbi_buscommon.bs_persist_segment;
 	busnum = soft->pbi_buscommon.bs_persist_busnum;
 	busnum = soft->pbi_buscommon.bs_persist_busnum;
 	SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_DISABLE,
 	SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_DISABLE,
-			(u64) busnum, (u64) device, (u64) action,
-			(u64) resp, 0, 0, 0);
+			segment, busnum, (u64) device, (u64) action,
+			(u64) resp, 0, 0);
 
 
 	return (int)ret_stuff.v0;
 	return (int)ret_stuff.v0;
 }
 }

+ 0 - 56
arch/sparc/kernel/entry.S

@@ -1276,62 +1276,6 @@ sys_sigstack:
 	call	do_sys_sigstack
 	call	do_sys_sigstack
 	 mov	%l5, %o7
 	 mov	%l5, %o7
 
 
-	.align	4
-	.globl	sys_sigpause
-sys_sigpause:
-	/* Note: %o0 already has correct value... */
-	call	do_sigpause
-	 add	%sp, STACKFRAME_SZ, %o1
-
-	ld	[%curptr + TI_FLAGS], %l5
-	andcc	%l5, _TIF_SYSCALL_TRACE, %g0
-	be	1f
-	 nop
-
-	call	syscall_trace
-	 nop
-
-1:
-	/* We are returning to a signal handler. */
-	RESTORE_ALL
-
-	.align	4
-	.globl	sys_sigsuspend
-sys_sigsuspend:
-	call	do_sigsuspend
-	 add	%sp, STACKFRAME_SZ, %o0
-
-	ld	[%curptr + TI_FLAGS], %l5
-	andcc	%l5, _TIF_SYSCALL_TRACE, %g0
-	be	1f
-	 nop
-
-	call	syscall_trace
-	 nop
-
-1:
-	/* We are returning to a signal handler. */
-	RESTORE_ALL
-
-	.align	4
-	.globl	sys_rt_sigsuspend
-sys_rt_sigsuspend:
-	/* Note: %o0, %o1 already have correct value... */
-	call	do_rt_sigsuspend
-	 add	%sp, STACKFRAME_SZ, %o2
-
-	ld	[%curptr + TI_FLAGS], %l5
-	andcc	%l5, _TIF_SYSCALL_TRACE, %g0
-	be	1f
-	 nop
-
-	call	syscall_trace
-	 nop
-
-1:
-	/* We are returning to a signal handler. */
-	RESTORE_ALL
-
 	.align	4
 	.align	4
 	.globl	sys_sigreturn
 	.globl	sys_sigreturn
 sys_sigreturn:
 sys_sigreturn:

+ 4 - 5
arch/sparc/kernel/rtrap.S

@@ -68,15 +68,14 @@ ret_trap_lockless_ipi:
 
 
 	ld	[%curptr + TI_FLAGS], %g2
 	ld	[%curptr + TI_FLAGS], %g2
 signal_p:
 signal_p:
-	andcc	%g2, (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING), %g0
+	andcc	%g2, (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %g0
 	bz,a	ret_trap_continue
 	bz,a	ret_trap_continue
 	 ld	[%sp + STACKFRAME_SZ + PT_PSR], %t_psr
 	 ld	[%sp + STACKFRAME_SZ + PT_PSR], %t_psr
 
 
-	clr	%o0
-	mov	%l5, %o2
-	mov	%l6, %o3
+	mov	%l5, %o1
+	mov	%l6, %o2
 	call	do_signal
 	call	do_signal
-	 add	%sp, STACKFRAME_SZ, %o1	! pt_regs ptr
+	 add	%sp, STACKFRAME_SZ, %o0	! pt_regs ptr
 
 
 	/* Fall through. */
 	/* Fall through. */
 	ld	[%sp + STACKFRAME_SZ + PT_PSR], %t_psr
 	ld	[%sp + STACKFRAME_SZ + PT_PSR], %t_psr

+ 31 - 86
arch/sparc/kernel/signal.c

@@ -35,9 +35,6 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
 		   void *fpqueue, unsigned long *fpqdepth);
 		   void *fpqueue, unsigned long *fpqdepth);
 extern void fpload(unsigned long *fpregs, unsigned long *fsr);
 extern void fpload(unsigned long *fpregs, unsigned long *fsr);
 
 
-asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
-			 unsigned long orig_o0, int restart_syscall);
-
 /* Signal frames: the original one (compatible with SunOS):
 /* Signal frames: the original one (compatible with SunOS):
  *
  *
  * Set up a signal frame... Make the stack look the way SunOS
  * Set up a signal frame... Make the stack look the way SunOS
@@ -95,98 +92,30 @@ struct rt_signal_frame {
 #define NF_ALIGNEDSZ  (((sizeof(struct new_signal_frame) + 7) & (~7)))
 #define NF_ALIGNEDSZ  (((sizeof(struct new_signal_frame) + 7) & (~7)))
 #define RT_ALIGNEDSZ  (((sizeof(struct rt_signal_frame) + 7) & (~7)))
 #define RT_ALIGNEDSZ  (((sizeof(struct rt_signal_frame) + 7) & (~7)))
 
 
-/*
- * atomically swap in the new signal mask, and wait for a signal.
- * This is really tricky on the Sparc, watch out...
- */
-asmlinkage void _sigpause_common(old_sigset_t set, struct pt_regs *regs)
+static int _sigpause_common(old_sigset_t set)
 {
 {
-	sigset_t saveset;
-
 	set &= _BLOCKABLE;
 	set &= _BLOCKABLE;
 	spin_lock_irq(&current->sighand->siglock);
 	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
+	current->saved_sigmask = current->blocked;
 	siginitset(&current->blocked, set);
 	siginitset(&current->blocked, set);
 	recalc_sigpending();
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 	spin_unlock_irq(&current->sighand->siglock);
 
 
-	regs->pc = regs->npc;
-	regs->npc += 4;
-
-	/* Condition codes and return value where set here for sigpause,
-	 * and so got used by setup_frame, which again causes sigreturn()
-	 * to return -EINTR.
-	 */
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		/*
-		 * Return -EINTR and set condition code here,
-		 * so the interrupted system call actually returns
-		 * these.
-		 */
-		regs->psr |= PSR_C;
-		regs->u_regs[UREG_I0] = EINTR;
-		if (do_signal(&saveset, regs, 0, 0))
-			return;
-	}
-}
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	set_thread_flag(TIF_RESTORE_SIGMASK);
 
 
-asmlinkage void do_sigpause(unsigned int set, struct pt_regs *regs)
-{
-	_sigpause_common(set, regs);
+	return -ERESTARTNOHAND;
 }
 }
 
 
-asmlinkage void do_sigsuspend (struct pt_regs *regs)
+asmlinkage int sys_sigpause(unsigned int set)
 {
 {
-	_sigpause_common(regs->u_regs[UREG_I0], regs);
+	return _sigpause_common(set);
 }
 }
 
 
-asmlinkage void do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize,
-				 struct pt_regs *regs)
+asmlinkage int sys_sigsuspend(old_sigset_t set)
 {
 {
-	sigset_t oldset, set;
-
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (sigsetsize != sizeof(sigset_t)) {
-		regs->psr |= PSR_C;
-		regs->u_regs[UREG_I0] = EINVAL;
-		return;
-	}
-
-	if (copy_from_user(&set, uset, sizeof(set))) {
-		regs->psr |= PSR_C;
-		regs->u_regs[UREG_I0] = EFAULT;
-		return;
-	}
-
-	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sighand->siglock);
-	oldset = current->blocked;
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	regs->pc = regs->npc;
-	regs->npc += 4;
-
-	/* Condition codes and return value where set here for sigpause,
-	 * and so got used by setup_frame, which again causes sigreturn()
-	 * to return -EINTR.
-	 */
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		/*
-		 * Return -EINTR and set condition code here,
-		 * so the interrupted system call actually returns
-		 * these.
-		 */
-		regs->psr |= PSR_C;
-		regs->u_regs[UREG_I0] = EINTR;
-		if (do_signal(&oldset, regs, 0, 0))
-			return;
-	}
+	return _sigpause_common(set);
 }
 }
 
 
 static inline int
 static inline int
@@ -1067,13 +996,13 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  * mistake.
  */
  */
-asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
-			 unsigned long orig_i0, int restart_syscall)
+asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int restart_syscall)
 {
 {
 	siginfo_t info;
 	siginfo_t info;
 	struct sparc_deliver_cookie cookie;
 	struct sparc_deliver_cookie cookie;
 	struct k_sigaction ka;
 	struct k_sigaction ka;
 	int signr;
 	int signr;
+	sigset_t *oldset;
 
 
 	/*
 	/*
 	 * XXX Disable svr4 signal handling until solaris emulation works.
 	 * XXX Disable svr4 signal handling until solaris emulation works.
@@ -1089,7 +1018,9 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
 	cookie.restart_syscall = restart_syscall;
 	cookie.restart_syscall = restart_syscall;
 	cookie.orig_i0 = orig_i0;
 	cookie.orig_i0 = orig_i0;
 
 
-	if (!oldset)
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else
 		oldset = &current->blocked;
 		oldset = &current->blocked;
 
 
 	signr = get_signal_to_deliver(&info, &ka, regs, &cookie);
 	signr = get_signal_to_deliver(&info, &ka, regs, &cookie);
@@ -1098,7 +1029,14 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
 			syscall_restart(cookie.orig_i0, regs, &ka.sa);
 			syscall_restart(cookie.orig_i0, regs, &ka.sa);
 		handle_signal(signr, &ka, &info, oldset,
 		handle_signal(signr, &ka, &info, oldset,
 			      regs, svr4_signal);
 			      regs, svr4_signal);
-		return 1;
+		/* a signal was successfully delivered; the saved
+		 * sigmask will have been stored in the signal frame,
+		 * and will be restored by sigreturn, so we can simply
+		 * clear the TIF_RESTORE_SIGMASK flag.
+		 */
+		if (test_thread_flag(TIF_RESTORE_SIGMASK))
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+		return;
 	}
 	}
 	if (cookie.restart_syscall &&
 	if (cookie.restart_syscall &&
 	    (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
 	    (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
@@ -1115,7 +1053,14 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
 		regs->pc -= 4;
 		regs->pc -= 4;
 		regs->npc -= 4;
 		regs->npc -= 4;
 	}
 	}
-	return 0;
+
+	/* if there's no signal to deliver, we just put the saved sigmask
+	 * back
+	 */
+	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+	}
 }
 }
 
 
 asmlinkage int
 asmlinkage int

+ 0 - 2
arch/sparc/kernel/sparc_ksyms.c

@@ -66,7 +66,6 @@ struct poll {
 
 
 extern int svr4_getcontext (svr4_ucontext_t *, struct pt_regs *);
 extern int svr4_getcontext (svr4_ucontext_t *, struct pt_regs *);
 extern int svr4_setcontext (svr4_ucontext_t *, struct pt_regs *);
 extern int svr4_setcontext (svr4_ucontext_t *, struct pt_regs *);
-void _sigpause_common (unsigned int set, struct pt_regs *);
 extern void (*__copy_1page)(void *, const void *);
 extern void (*__copy_1page)(void *, const void *);
 extern void __memmove(void *, const void *, __kernel_size_t);
 extern void __memmove(void *, const void *, __kernel_size_t);
 extern void (*bzero_1page)(void *);
 extern void (*bzero_1page)(void *);
@@ -227,7 +226,6 @@ EXPORT_SYMBOL(kunmap_atomic);
 /* Solaris/SunOS binary compatibility */
 /* Solaris/SunOS binary compatibility */
 EXPORT_SYMBOL(svr4_setcontext);
 EXPORT_SYMBOL(svr4_setcontext);
 EXPORT_SYMBOL(svr4_getcontext);
 EXPORT_SYMBOL(svr4_getcontext);
-EXPORT_SYMBOL(_sigpause_common);
 
 
 EXPORT_SYMBOL(dump_thread);
 EXPORT_SYMBOL(dump_thread);
 
 

+ 9 - 1
arch/sparc/kernel/systbls.S

@@ -75,7 +75,10 @@ sys_call_table:
 /*265*/	.long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy
 /*265*/	.long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy
 /*270*/	.long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
 /*270*/	.long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
 /*275*/	.long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
 /*275*/	.long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
-/*280*/	.long sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl
+/*280*/	.long sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat
+/*285*/	.long sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_newfstatat
+/*290*/	.long sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
+/*295*/	.long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll
 
 
 #ifdef CONFIG_SUNOS_EMUL
 #ifdef CONFIG_SUNOS_EMUL
 	/* Now the SunOS syscall table. */
 	/* Now the SunOS syscall table. */
@@ -181,6 +184,11 @@ sunos_sys_table:
 	.long sunos_nosys, sunos_nosys, sunos_nosys
 	.long sunos_nosys, sunos_nosys, sunos_nosys
 	.long sunos_nosys
 	.long sunos_nosys
 /*280*/	.long sunos_nosys, sunos_nosys, sunos_nosys
 /*280*/	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
 	.long sunos_nosys
 	.long sunos_nosys
+/*290*/	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
 
 
 #endif
 #endif

+ 0 - 23
arch/sparc64/kernel/entry.S

@@ -1416,7 +1416,6 @@ execve_merge:
 	 add		%sp, PTREGS_OFF, %o0
 	 add		%sp, PTREGS_OFF, %o0
 
 
 	.globl	sys_pipe, sys_sigpause, sys_nis_syscall
 	.globl	sys_pipe, sys_sigpause, sys_nis_syscall
-	.globl	sys_sigsuspend, sys_rt_sigsuspend
 	.globl	sys_rt_sigreturn
 	.globl	sys_rt_sigreturn
 	.globl	sys_ptrace
 	.globl	sys_ptrace
 	.globl	sys_sigaltstack
 	.globl	sys_sigaltstack
@@ -1440,28 +1439,6 @@ sys32_sigaltstack:
 		 mov		%i6, %o2
 		 mov		%i6, %o2
 #endif
 #endif
 		.align		32
 		.align		32
-sys_sigsuspend:	add		%sp, PTREGS_OFF, %o0
-		call		do_sigsuspend
-		 add		%o7, 1f-.-4, %o7
-		nop
-sys_rt_sigsuspend: /* NOTE: %o0,%o1 have a correct value already */
-		add		%sp, PTREGS_OFF, %o2
-		call		do_rt_sigsuspend
-		 add		%o7, 1f-.-4, %o7
-		nop
-#ifdef CONFIG_COMPAT
-	.globl	sys32_rt_sigsuspend
-sys32_rt_sigsuspend: /* NOTE: %o0,%o1 have a correct value already */
-		srl		%o0, 0, %o0
-		add		%sp, PTREGS_OFF, %o2
-		call		do_rt_sigsuspend32
-		 add		%o7, 1f-.-4, %o7
-#endif
-		/* NOTE: %o0 has a correct value already */
-sys_sigpause:	add		%sp, PTREGS_OFF, %o1
-		call		do_sigpause
-		 add		%o7, 1f-.-4, %o7
-		nop
 #ifdef CONFIG_COMPAT
 #ifdef CONFIG_COMPAT
 	.globl	sys32_sigreturn
 	.globl	sys32_sigreturn
 sys32_sigreturn:
 sys32_sigreturn:

+ 15 - 18
arch/sparc64/kernel/rtrap.S

@@ -53,14 +53,13 @@ __handle_user_windows:
 		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
 		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
 		ldx			[%g6 + TI_FLAGS], %l0
 		ldx			[%g6 + TI_FLAGS], %l0
 
 
-1:		andcc			%l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0
+1:		andcc			%l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0
 		be,pt			%xcc, __handle_user_windows_continue
 		be,pt			%xcc, __handle_user_windows_continue
 		 nop
 		 nop
-		clr			%o0
-		mov			%l5, %o2
-		mov			%l6, %o3
-		add			%sp, PTREGS_OFF, %o1
-		mov			%l0, %o4
+		mov			%l5, %o1
+		mov			%l6, %o2
+		add			%sp, PTREGS_OFF, %o0
+		mov			%l0, %o3
 
 
 		call			do_notify_resume
 		call			do_notify_resume
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
@@ -96,15 +95,14 @@ __handle_perfctrs:
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
 		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
 		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
 		ldx			[%g6 + TI_FLAGS], %l0
 		ldx			[%g6 + TI_FLAGS], %l0
-1:		andcc			%l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0
+1:		andcc			%l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0
 
 
 		be,pt			%xcc, __handle_perfctrs_continue
 		be,pt			%xcc, __handle_perfctrs_continue
 		 sethi			%hi(TSTATE_PEF), %o0
 		 sethi			%hi(TSTATE_PEF), %o0
-		clr			%o0
-		mov			%l5, %o2
-		mov			%l6, %o3
-		add			%sp, PTREGS_OFF, %o1
-		mov			%l0, %o4
+		mov			%l5, %o1
+		mov			%l6, %o2
+		add			%sp, PTREGS_OFF, %o0
+		mov			%l0, %o3
 		call			do_notify_resume
 		call			do_notify_resume
 
 
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
@@ -129,11 +127,10 @@ __handle_userfpu:
 		ba,a,pt			%xcc, __handle_userfpu_continue
 		ba,a,pt			%xcc, __handle_userfpu_continue
 
 
 __handle_signal:
 __handle_signal:
-		clr			%o0
-		mov			%l5, %o2
-		mov			%l6, %o3
-		add			%sp, PTREGS_OFF, %o1
-		mov			%l0, %o4
+		mov			%l5, %o1
+		mov			%l6, %o2
+		add			%sp, PTREGS_OFF, %o0
+		mov			%l0, %o3
 		call			do_notify_resume
 		call			do_notify_resume
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
 		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
 		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
@@ -200,7 +197,7 @@ __handle_preemption_continue:
 		 andcc			%l1, %o0, %g0
 		 andcc			%l1, %o0, %g0
 		andcc			%l0, _TIF_NEED_RESCHED, %g0
 		andcc			%l0, _TIF_NEED_RESCHED, %g0
 		bne,pn			%xcc, __handle_preemption
 		bne,pn			%xcc, __handle_preemption
-		 andcc			%l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0
+		 andcc			%l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0
 		bne,pn			%xcc, __handle_signal
 		bne,pn			%xcc, __handle_signal
 __handle_signal_continue:
 __handle_signal_continue:
 		 ldub			[%g6 + TI_WSAVED], %o2
 		 ldub			[%g6 + TI_WSAVED], %o2

+ 40 - 111
arch/sparc64/kernel/signal.c

@@ -36,9 +36,6 @@
 
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 
-static int do_signal(sigset_t *oldset, struct pt_regs * regs,
-		     unsigned long orig_o0, int ret_from_syscall);
-
 /* {set, get}context() needed for 64-bit SparcLinux userland. */
 /* {set, get}context() needed for 64-bit SparcLinux userland. */
 asmlinkage void sparc64_set_context(struct pt_regs *regs)
 asmlinkage void sparc64_set_context(struct pt_regs *regs)
 {
 {
@@ -242,114 +239,29 @@ struct rt_signal_frame {
 /* Align macros */
 /* Align macros */
 #define RT_ALIGNEDSZ  (((sizeof(struct rt_signal_frame) + 7) & (~7)))
 #define RT_ALIGNEDSZ  (((sizeof(struct rt_signal_frame) + 7) & (~7)))
 
 
-/*
- * atomically swap in the new signal mask, and wait for a signal.
- * This is really tricky on the Sparc, watch out...
- */
-asmlinkage void _sigpause_common(old_sigset_t set, struct pt_regs *regs)
+static long _sigpause_common(old_sigset_t set)
 {
 {
-	sigset_t saveset;
-
-#ifdef CONFIG_SPARC32_COMPAT
-	if (test_thread_flag(TIF_32BIT)) {
-		extern asmlinkage void _sigpause32_common(compat_old_sigset_t,
-							  struct pt_regs *);
-		_sigpause32_common(set, regs);
-		return;
-	}
-#endif
 	set &= _BLOCKABLE;
 	set &= _BLOCKABLE;
 	spin_lock_irq(&current->sighand->siglock);
 	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
+	current->saved_sigmask = current->blocked;
 	siginitset(&current->blocked, set);
 	siginitset(&current->blocked, set);
 	recalc_sigpending();
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 	spin_unlock_irq(&current->sighand->siglock);
-	
-	if (test_thread_flag(TIF_32BIT)) {
-		regs->tpc = (regs->tnpc & 0xffffffff);
-		regs->tnpc = (regs->tnpc + 4) & 0xffffffff;
-	} else {
-		regs->tpc = regs->tnpc;
-		regs->tnpc += 4;
-	}
 
 
-	/* Condition codes and return value where set here for sigpause,
-	 * and so got used by setup_frame, which again causes sigreturn()
-	 * to return -EINTR.
-	 */
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		/*
-		 * Return -EINTR and set condition code here,
-		 * so the interrupted system call actually returns
-		 * these.
-		 */
-		regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);
-		regs->u_regs[UREG_I0] = EINTR;
-		if (do_signal(&saveset, regs, 0, 0))
-			return;
-	}
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	set_thread_flag(TIF_RESTORE_SIGMASK);
+	return -ERESTARTNOHAND;
 }
 }
 
 
-asmlinkage void do_sigpause(unsigned int set, struct pt_regs *regs)
+asmlinkage long sys_sigpause(unsigned int set)
 {
 {
-	_sigpause_common(set, regs);
+	return _sigpause_common(set);
 }
 }
 
 
-asmlinkage void do_sigsuspend(struct pt_regs *regs)
+asmlinkage long sys_sigsuspend(old_sigset_t set)
 {
 {
-	_sigpause_common(regs->u_regs[UREG_I0], regs);
-}
-
-asmlinkage void do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize, struct pt_regs *regs)
-{
-	sigset_t oldset, set;
-        
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (sigsetsize != sizeof(sigset_t)) {
-		regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);
-		regs->u_regs[UREG_I0] = EINVAL;
-		return;
-	}
-	if (copy_from_user(&set, uset, sizeof(set))) {
-		regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);
-		regs->u_regs[UREG_I0] = EFAULT;
-		return;
-	}
-                                                                
-	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sighand->siglock);
-	oldset = current->blocked;
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-	
-	if (test_thread_flag(TIF_32BIT)) {
-		regs->tpc = (regs->tnpc & 0xffffffff);
-		regs->tnpc = (regs->tnpc + 4) & 0xffffffff;
-	} else {
-		regs->tpc = regs->tnpc;
-		regs->tnpc += 4;
-	}
-
-	/* Condition codes and return value where set here for sigpause,
-	 * and so got used by setup_frame, which again causes sigreturn()
-	 * to return -EINTR.
-	 */
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		/*
-		 * Return -EINTR and set condition code here,
-		 * so the interrupted system call actually returns
-		 * these.
-		 */
-		regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);
-		regs->u_regs[UREG_I0] = EINTR;
-		if (do_signal(&oldset, regs, 0, 0))
-			return;
-	}
+	return _sigpause_common(set);
 }
 }
 
 
 static inline int
 static inline int
@@ -607,26 +519,29 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  * mistake.
  */
  */
-static int do_signal(sigset_t *oldset, struct pt_regs * regs,
-		     unsigned long orig_i0, int restart_syscall)
+static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall)
 {
 {
 	siginfo_t info;
 	siginfo_t info;
 	struct signal_deliver_cookie cookie;
 	struct signal_deliver_cookie cookie;
 	struct k_sigaction ka;
 	struct k_sigaction ka;
 	int signr;
 	int signr;
+	sigset_t *oldset;
 	
 	
 	cookie.restart_syscall = restart_syscall;
 	cookie.restart_syscall = restart_syscall;
 	cookie.orig_i0 = orig_i0;
 	cookie.orig_i0 = orig_i0;
 
 
-	if (!oldset)
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else
 		oldset = &current->blocked;
 		oldset = &current->blocked;
 
 
 #ifdef CONFIG_SPARC32_COMPAT
 #ifdef CONFIG_SPARC32_COMPAT
 	if (test_thread_flag(TIF_32BIT)) {
 	if (test_thread_flag(TIF_32BIT)) {
-		extern int do_signal32(sigset_t *, struct pt_regs *,
-				       unsigned long, int);
-		return do_signal32(oldset, regs, orig_i0,
-				   cookie.restart_syscall);
+		extern void do_signal32(sigset_t *, struct pt_regs *,
+					unsigned long, int);
+		do_signal32(oldset, regs, orig_i0,
+			    cookie.restart_syscall);
+		return;
 	}
 	}
 #endif	
 #endif	
 
 
@@ -635,7 +550,15 @@ static int do_signal(sigset_t *oldset, struct pt_regs * regs,
 		if (cookie.restart_syscall)
 		if (cookie.restart_syscall)
 			syscall_restart(orig_i0, regs, &ka.sa);
 			syscall_restart(orig_i0, regs, &ka.sa);
 		handle_signal(signr, &ka, &info, oldset, regs);
 		handle_signal(signr, &ka, &info, oldset, regs);
-		return 1;
+
+		/* a signal was successfully delivered; the saved
+		 * sigmask will have been stored in the signal frame,
+		 * and will be restored by sigreturn, so we can simply
+		 * clear the TIF_RESTORE_SIGMASK flag.
+		 */
+		if (test_thread_flag(TIF_RESTORE_SIGMASK))
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+		return;
 	}
 	}
 	if (cookie.restart_syscall &&
 	if (cookie.restart_syscall &&
 	    (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
 	    (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
@@ -652,15 +575,21 @@ static int do_signal(sigset_t *oldset, struct pt_regs * regs,
 		regs->tpc -= 4;
 		regs->tpc -= 4;
 		regs->tnpc -= 4;
 		regs->tnpc -= 4;
 	}
 	}
-	return 0;
+
+	/* if there's no signal to deliver, we just put the saved sigmask
+	 * back
+	 */
+	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+	}
 }
 }
 
 
-void do_notify_resume(sigset_t *oldset, struct pt_regs *regs,
-		      unsigned long orig_i0, int restart_syscall,
+void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall,
 		      unsigned long thread_info_flags)
 		      unsigned long thread_info_flags)
 {
 {
-	if (thread_info_flags & _TIF_SIGPENDING)
-		do_signal(oldset, regs, orig_i0, restart_syscall);
+	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+		do_signal(regs, orig_i0, restart_syscall);
 }
 }
 
 
 void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)
 void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)

+ 19 - 103
arch/sparc64/kernel/signal32.c

@@ -32,9 +32,6 @@
 
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 
-int do_signal32(sigset_t *oldset, struct pt_regs *regs,
-		unsigned long orig_o0, int ret_from_syscall);
-
 /* Signal frames: the original one (compatible with SunOS):
 /* Signal frames: the original one (compatible with SunOS):
  *
  *
  * Set up a signal frame... Make the stack look the way SunOS
  * Set up a signal frame... Make the stack look the way SunOS
@@ -226,102 +223,6 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
 	return 0;
 	return 0;
 }
 }
 
 
-/*
- * atomically swap in the new signal mask, and wait for a signal.
- * This is really tricky on the Sparc, watch out...
- */
-asmlinkage void _sigpause32_common(compat_old_sigset_t set, struct pt_regs *regs)
-{
-	sigset_t saveset;
-
-	set &= _BLOCKABLE;
-	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
-	siginitset(&current->blocked, set);
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-	
-	regs->tpc = regs->tnpc;
-	regs->tnpc += 4;
-	if (test_thread_flag(TIF_32BIT)) {
-		regs->tpc &= 0xffffffff;
-		regs->tnpc &= 0xffffffff;
-	}
-
-	/* Condition codes and return value where set here for sigpause,
-	 * and so got used by setup_frame, which again causes sigreturn()
-	 * to return -EINTR.
-	 */
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		/*
-		 * Return -EINTR and set condition code here,
-		 * so the interrupted system call actually returns
-		 * these.
-		 */
-		regs->tstate |= TSTATE_ICARRY;
-		regs->u_regs[UREG_I0] = EINTR;
-		if (do_signal32(&saveset, regs, 0, 0))
-			return;
-	}
-}
-
-asmlinkage void do_rt_sigsuspend32(u32 uset, size_t sigsetsize, struct pt_regs *regs)
-{
-	sigset_t oldset, set;
-	compat_sigset_t set32;
-        
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (((compat_size_t)sigsetsize) != sizeof(sigset_t)) {
-		regs->tstate |= TSTATE_ICARRY;
-		regs->u_regs[UREG_I0] = EINVAL;
-		return;
-	}
-	if (copy_from_user(&set32, compat_ptr(uset), sizeof(set32))) {
-		regs->tstate |= TSTATE_ICARRY;
-		regs->u_regs[UREG_I0] = EFAULT;
-		return;
-	}
-	switch (_NSIG_WORDS) {
-	case 4: set.sig[3] = set32.sig[6] + (((long)set32.sig[7]) << 32);
-	case 3: set.sig[2] = set32.sig[4] + (((long)set32.sig[5]) << 32);
-	case 2: set.sig[1] = set32.sig[2] + (((long)set32.sig[3]) << 32);
-	case 1: set.sig[0] = set32.sig[0] + (((long)set32.sig[1]) << 32);
-	}
-	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sighand->siglock);
-	oldset = current->blocked;
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-	
-	regs->tpc = regs->tnpc;
-	regs->tnpc += 4;
-	if (test_thread_flag(TIF_32BIT)) {
-		regs->tpc &= 0xffffffff;
-		regs->tnpc &= 0xffffffff;
-	}
-
-	/* Condition codes and return value where set here for sigpause,
-	 * and so got used by setup_frame, which again causes sigreturn()
-	 * to return -EINTR.
-	 */
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		/*
-		 * Return -EINTR and set condition code here,
-		 * so the interrupted system call actually returns
-		 * these.
-		 */
-		regs->tstate |= TSTATE_ICARRY;
-		regs->u_regs[UREG_I0] = EINTR;
-		if (do_signal32(&oldset, regs, 0, 0))
-			return;
-	}
-}
-
 static int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
 static int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
 {
 {
 	unsigned long *fpregs = current_thread_info()->fpregs;
 	unsigned long *fpregs = current_thread_info()->fpregs;
@@ -1362,8 +1263,8 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  * mistake.
  */
  */
-int do_signal32(sigset_t *oldset, struct pt_regs * regs,
-		unsigned long orig_i0, int restart_syscall)
+void do_signal32(sigset_t *oldset, struct pt_regs * regs,
+		 unsigned long orig_i0, int restart_syscall)
 {
 {
 	siginfo_t info;
 	siginfo_t info;
 	struct signal_deliver_cookie cookie;
 	struct signal_deliver_cookie cookie;
@@ -1380,7 +1281,15 @@ int do_signal32(sigset_t *oldset, struct pt_regs * regs,
 			syscall_restart32(orig_i0, regs, &ka.sa);
 			syscall_restart32(orig_i0, regs, &ka.sa);
 		handle_signal32(signr, &ka, &info, oldset,
 		handle_signal32(signr, &ka, &info, oldset,
 				regs, svr4_signal);
 				regs, svr4_signal);
-		return 1;
+
+		/* a signal was successfully delivered; the saved
+		 * sigmask will have been stored in the signal frame,
+		 * and will be restored by sigreturn, so we can simply
+		 * clear the TIF_RESTORE_SIGMASK flag.
+		 */
+		if (test_thread_flag(TIF_RESTORE_SIGMASK))
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+		return;
 	}
 	}
 	if (cookie.restart_syscall &&
 	if (cookie.restart_syscall &&
 	    (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
 	    (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
@@ -1397,7 +1306,14 @@ int do_signal32(sigset_t *oldset, struct pt_regs * regs,
 		regs->tpc -= 4;
 		regs->tpc -= 4;
 		regs->tnpc -= 4;
 		regs->tnpc -= 4;
 	}
 	}
-	return 0;
+
+	/* if there's no signal to deliver, we just put the saved sigmask
+	 * back
+	 */
+	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+	}
 }
 }
 
 
 struct sigstack32 {
 struct sigstack32 {

+ 2 - 2
arch/sparc64/kernel/sparc64_ksyms.c

@@ -69,7 +69,6 @@ struct poll {
 
 
 extern void die_if_kernel(char *str, struct pt_regs *regs);
 extern void die_if_kernel(char *str, struct pt_regs *regs);
 extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-void _sigpause_common (unsigned int set, struct pt_regs *);
 extern void *__bzero(void *, size_t);
 extern void *__bzero(void *, size_t);
 extern void *__memscan_zero(void *, size_t);
 extern void *__memscan_zero(void *, size_t);
 extern void *__memscan_generic(void *, int, size_t);
 extern void *__memscan_generic(void *, int, size_t);
@@ -236,9 +235,10 @@ EXPORT_SYMBOL(pci_dma_supported);
 /* I/O device mmaping on Sparc64. */
 /* I/O device mmaping on Sparc64. */
 EXPORT_SYMBOL(io_remap_pfn_range);
 EXPORT_SYMBOL(io_remap_pfn_range);
 
 
+#ifdef CONFIG_COMPAT
 /* Solaris/SunOS binary compatibility */
 /* Solaris/SunOS binary compatibility */
-EXPORT_SYMBOL(_sigpause_common);
 EXPORT_SYMBOL(verify_compat_iovec);
 EXPORT_SYMBOL(verify_compat_iovec);
+#endif
 
 
 EXPORT_SYMBOL(dump_fpu);
 EXPORT_SYMBOL(dump_fpu);
 EXPORT_SYMBOL(pte_alloc_one_kernel);
 EXPORT_SYMBOL(pte_alloc_one_kernel);

+ 17 - 4
arch/sparc64/kernel/systbls.S

@@ -41,7 +41,7 @@ sys_call_table32:
 /*90*/	.word sys_dup2, sys_setfsuid, compat_sys_fcntl, sys32_select, sys_setfsgid
 /*90*/	.word sys_dup2, sys_setfsuid, compat_sys_fcntl, sys32_select, sys_setfsgid
 	.word sys_fsync, sys32_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 	.word sys_fsync, sys32_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 /*100*/ .word sys32_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending
 /*100*/ .word sys32_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending
-	.word compat_sys_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_setresuid, sys_getresuid
+	.word compat_sys_rt_sigtimedwait, sys32_rt_sigqueueinfo, compat_sys_rt_sigsuspend, sys_setresuid, sys_getresuid
 /*110*/	.word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall
 /*110*/	.word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall
 	.word sys32_getgroups, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
 	.word sys32_getgroups, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
 /*120*/	.word compat_sys_readv, compat_sys_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod
 /*120*/	.word compat_sys_readv, compat_sys_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod
@@ -76,7 +76,10 @@ sys_call_table32:
 	.word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
 	.word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
 /*270*/	.word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
 /*270*/	.word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
 	.word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
 	.word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
-/*280*/	.word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl
+/*280*/	.word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat
+	.word sys_mkdirat, sys_mknodat, sys_fchownat, compat_sys_futimesat, compat_sys_newfstatat
+/*285*/	.word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
+	.word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll
 
 
 #endif /* CONFIG_COMPAT */
 #endif /* CONFIG_COMPAT */
 
 
@@ -142,7 +145,10 @@ sys_call_table:
 	.word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy
 	.word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy
 /*270*/	.word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
 /*270*/	.word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
 	.word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
 	.word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
-/*280*/	.word sys_nis_syscall, sys_add_key, sys_request_key, sys_keyctl
+/*280*/	.word sys_nis_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat
+	.word sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, compat_sys_newfstatat
+/*285*/	.word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
+	.word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll
 
 
 #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
 #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
     defined(CONFIG_SOLARIS_EMUL_MODULE)
     defined(CONFIG_SOLARIS_EMUL_MODULE)
@@ -239,13 +245,20 @@ sunos_sys_table:
 /*250*/	.word sunos_nosys, sunos_nosys, sunos_nosys
 /*250*/	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
+	.word sunos_nosys
+/*260*/	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
+	.word sunos_nosys
+/*270*/	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
+	.word sunos_nosys
+/*280*/	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
+	.word sunos_nosys
+/*290*/	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sunos_nosys
-	.word sunos_nosys
 #endif
 #endif

+ 2 - 0
arch/sparc64/solaris/entry64.S

@@ -180,6 +180,8 @@ solaris_sigsuspend:
 	 nop
 	 nop
 	call		sys_sigsuspend
 	call		sys_sigsuspend
 	 stx		%o0, [%sp + PTREGS_OFF + PT_V9_I0]
 	 stx		%o0, [%sp + PTREGS_OFF + PT_V9_I0]
+	b,pt		%xcc, ret_from_solaris
+	 nop
 
 
 	.globl		solaris_getpid
 	.globl		solaris_getpid
 solaris_getpid:
 solaris_getpid:

+ 58 - 71
drivers/serial/sn_console.c

@@ -6,7 +6,7 @@
  * driver for that.
  * driver for that.
  *
  *
  *
  *
- * Copyright (c) 2004-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2004-2006 Silicon Graphics, Inc.  All Rights Reserved.
  *
  *
  * This program is free software; you can redistribute it and/or modify it
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
  * under the terms of version 2 of the GNU General Public License
@@ -829,8 +829,8 @@ static int __init sn_sal_module_init(void)
 		misc.name = DEVICE_NAME_DYNAMIC;
 		misc.name = DEVICE_NAME_DYNAMIC;
 		retval = misc_register(&misc);
 		retval = misc_register(&misc);
 		if (retval != 0) {
 		if (retval != 0) {
-			printk
-			    ("Failed to register console device using misc_register.\n");
+			printk(KERN_WARNING "Failed to register console "
+			       "device using misc_register.\n");
 			return -ENODEV;
 			return -ENODEV;
 		}
 		}
 		sal_console_uart.major = MISC_MAJOR;
 		sal_console_uart.major = MISC_MAJOR;
@@ -942,88 +942,75 @@ sn_sal_console_write(struct console *co, const char *s, unsigned count)
 {
 {
 	unsigned long flags = 0;
 	unsigned long flags = 0;
 	struct sn_cons_port *port = &sal_console_port;
 	struct sn_cons_port *port = &sal_console_port;
-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
 	static int stole_lock = 0;
 	static int stole_lock = 0;
-#endif
 
 
 	BUG_ON(!port->sc_is_asynch);
 	BUG_ON(!port->sc_is_asynch);
 
 
 	/* We can't look at the xmit buffer if we're not registered with serial core
 	/* We can't look at the xmit buffer if we're not registered with serial core
 	 *  yet.  So only do the fancy recovery after registering
 	 *  yet.  So only do the fancy recovery after registering
 	 */
 	 */
-	if (port->sc_port.info) {
-
-		/* somebody really wants this output, might be an
-		 * oops, kdb, panic, etc.  make sure they get it. */
-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
-		if (spin_is_locked(&port->sc_port.lock)) {
-			int lhead = port->sc_port.info->xmit.head;
-			int ltail = port->sc_port.info->xmit.tail;
-			int counter, got_lock = 0;
+	if (!port->sc_port.info) {
+		/* Not yet registered with serial core - simple case */
+		puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
+		return;
+	}
 
 
-			/*
-			 * We attempt to determine if someone has died with the
-			 * lock. We wait ~20 secs after the head and tail ptrs
-			 * stop moving and assume the lock holder is not functional
-			 * and plow ahead. If the lock is freed within the time out
-			 * period we re-get the lock and go ahead normally. We also
-			 * remember if we have plowed ahead so that we don't have
-			 * to wait out the time out period again - the asumption
-			 * is that we will time out again.
-			 */
+	/* somebody really wants this output, might be an
+	 * oops, kdb, panic, etc.  make sure they get it. */
+	if (spin_is_locked(&port->sc_port.lock)) {
+		int lhead = port->sc_port.info->xmit.head;
+		int ltail = port->sc_port.info->xmit.tail;
+		int counter, got_lock = 0;
+
+		/*
+		 * We attempt to determine if someone has died with the
+		 * lock. We wait ~20 secs after the head and tail ptrs
+		 * stop moving and assume the lock holder is not functional
+		 * and plow ahead. If the lock is freed within the time out
+		 * period we re-get the lock and go ahead normally. We also
+		 * remember if we have plowed ahead so that we don't have
+		 * to wait out the time out period again - the asumption
+		 * is that we will time out again.
+		 */
 
 
-			for (counter = 0; counter < 150; mdelay(125), counter++) {
-				if (!spin_is_locked(&port->sc_port.lock)
-				    || stole_lock) {
-					if (!stole_lock) {
-						spin_lock_irqsave(&port->
-								  sc_port.lock,
-								  flags);
-						got_lock = 1;
-					}
-					break;
-				} else {
-					/* still locked */
-					if ((lhead !=
-					     port->sc_port.info->xmit.head)
-					    || (ltail !=
-						port->sc_port.info->xmit.
-						tail)) {
-						lhead =
-						    port->sc_port.info->xmit.
-						    head;
-						ltail =
-						    port->sc_port.info->xmit.
-						    tail;
-						counter = 0;
-					}
+		for (counter = 0; counter < 150; mdelay(125), counter++) {
+			if (!spin_is_locked(&port->sc_port.lock)
+			    || stole_lock) {
+				if (!stole_lock) {
+					spin_lock_irqsave(&port->sc_port.lock,
+							  flags);
+					got_lock = 1;
 				}
 				}
-			}
-			/* flush anything in the serial core xmit buffer, raw */
-			sn_transmit_chars(port, 1);
-			if (got_lock) {
-				spin_unlock_irqrestore(&port->sc_port.lock,
-						       flags);
-				stole_lock = 0;
+				break;
 			} else {
 			} else {
-				/* fell thru */
-				stole_lock = 1;
+				/* still locked */
+				if ((lhead != port->sc_port.info->xmit.head)
+				    || (ltail !=
+					port->sc_port.info->xmit.tail)) {
+					lhead =
+						port->sc_port.info->xmit.head;
+					ltail =
+						port->sc_port.info->xmit.tail;
+					counter = 0;
+				}
 			}
 			}
-			puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
-		} else {
-			stole_lock = 0;
-#endif
-			spin_lock_irqsave(&port->sc_port.lock, flags);
-			sn_transmit_chars(port, 1);
+		}
+		/* flush anything in the serial core xmit buffer, raw */
+		sn_transmit_chars(port, 1);
+		if (got_lock) {
 			spin_unlock_irqrestore(&port->sc_port.lock, flags);
 			spin_unlock_irqrestore(&port->sc_port.lock, flags);
-
-			puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
+			stole_lock = 0;
+		} else {
+			/* fell thru */
+			stole_lock = 1;
 		}
 		}
-#endif
-	}
-	else {
-		/* Not yet registered with serial core - simple case */
+		puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
+	} else {
+		stole_lock = 0;
+		spin_lock_irqsave(&port->sc_port.lock, flags);
+		sn_transmit_chars(port, 1);
+		spin_unlock_irqrestore(&port->sc_port.lock, flags);
+
 		puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
 		puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
 	}
 	}
 }
 }

+ 2 - 2
fs/compat.c

@@ -1743,7 +1743,7 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
 		if ((u64)tv.tv_sec >= (u64)MAX_INT64_SECONDS)
 		if ((u64)tv.tv_sec >= (u64)MAX_INT64_SECONDS)
 			timeout = -1;	/* infinite */
 			timeout = -1;	/* infinite */
 		else {
 		else {
-			timeout = ROUND_UP(tv.tv_sec, 1000000/HZ);
+			timeout = ROUND_UP(tv.tv_usec, 1000000/HZ);
 			timeout += tv.tv_sec * HZ;
 			timeout += tv.tv_sec * HZ;
 		}
 		}
 	}
 	}
@@ -1884,7 +1884,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
 		/* We assume that ts.tv_sec is always lower than
 		/* We assume that ts.tv_sec is always lower than
 		   the number of seconds that can be expressed in
 		   the number of seconds that can be expressed in
 		   an s64. Otherwise the compiler bitches at us */
 		   an s64. Otherwise the compiler bitches at us */
-		timeout = ROUND_UP(ts.tv_sec, 1000000000/HZ);
+		timeout = ROUND_UP(ts.tv_nsec, 1000000000/HZ);
 		timeout += ts.tv_sec * HZ;
 		timeout += ts.tv_sec * HZ;
 	}
 	}
 
 

+ 4 - 4
include/asm-ia64/semaphore.h

@@ -61,7 +61,7 @@ static inline void
 down (struct semaphore *sem)
 down (struct semaphore *sem)
 {
 {
 	might_sleep();
 	might_sleep();
-	if (atomic_dec_return(&sem->count) < 0)
+	if (ia64_fetchadd(-1, &sem->count.counter, acq) < 1)
 		__down(sem);
 		__down(sem);
 }
 }
 
 
@@ -75,7 +75,7 @@ down_interruptible (struct semaphore * sem)
 	int ret = 0;
 	int ret = 0;
 
 
 	might_sleep();
 	might_sleep();
-	if (atomic_dec_return(&sem->count) < 0)
+	if (ia64_fetchadd(-1, &sem->count.counter, acq) < 1)
 		ret = __down_interruptible(sem);
 		ret = __down_interruptible(sem);
 	return ret;
 	return ret;
 }
 }
@@ -85,7 +85,7 @@ down_trylock (struct semaphore *sem)
 {
 {
 	int ret = 0;
 	int ret = 0;
 
 
-	if (atomic_dec_return(&sem->count) < 0)
+	if (ia64_fetchadd(-1, &sem->count.counter, acq) < 1)
 		ret = __down_trylock(sem);
 		ret = __down_trylock(sem);
 	return ret;
 	return ret;
 }
 }
@@ -93,7 +93,7 @@ down_trylock (struct semaphore *sem)
 static inline void
 static inline void
 up (struct semaphore * sem)
 up (struct semaphore * sem)
 {
 {
-	if (atomic_inc_return(&sem->count) <= 0)
+	if (ia64_fetchadd(1, &sem->count.counter, rel) <= -1)
 		__up(sem);
 		__up(sem);
 }
 }
 
 

+ 2 - 1
include/asm-ia64/sn/xp.h

@@ -18,6 +18,7 @@
 
 
 #include <linux/cache.h>
 #include <linux/cache.h>
 #include <linux/hardirq.h>
 #include <linux/hardirq.h>
+#include <linux/mutex.h>
 #include <asm/sn/types.h>
 #include <asm/sn/types.h>
 #include <asm/sn/bte.h>
 #include <asm/sn/bte.h>
 
 
@@ -359,7 +360,7 @@ typedef void (*xpc_notify_func)(enum xpc_retval reason, partid_t partid,
  * the channel.
  * the channel.
  */
  */
 struct xpc_registration {
 struct xpc_registration {
-	struct semaphore sema;
+	struct mutex mutex;
 	xpc_channel_func func;		/* function to call */
 	xpc_channel_func func;		/* function to call */
 	void *key;			/* pointer to user's key */
 	void *key;			/* pointer to user's key */
 	u16 nentries;			/* #of msg entries in local msg queue */
 	u16 nentries;			/* #of msg entries in local msg queue */

+ 5 - 4
include/asm-ia64/sn/xpc.h

@@ -19,6 +19,8 @@
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
 #include <linux/sysctl.h>
 #include <linux/sysctl.h>
 #include <linux/device.h>
 #include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
 #include <asm/pgtable.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/processor.h>
 #include <asm/sn/bte.h>
 #include <asm/sn/bte.h>
@@ -335,8 +337,7 @@ struct xpc_openclose_args {
  * and consumed by the intended recipient.
  * and consumed by the intended recipient.
  */
  */
 struct xpc_notify {
 struct xpc_notify {
-	struct semaphore sema;		/* notify semaphore */
-	volatile u8 type;			/* type of notification */
+	volatile u8 type;		/* type of notification */
 
 
 	/* the following two fields are only used if type == XPC_N_CALL */
 	/* the following two fields are only used if type == XPC_N_CALL */
 	xpc_notify_func func;		/* user's notify function */
 	xpc_notify_func func;		/* user's notify function */
@@ -465,8 +466,8 @@ struct xpc_channel {
 	xpc_channel_func func;		/* user's channel function */
 	xpc_channel_func func;		/* user's channel function */
 	void *key;			/* pointer to user's key */
 	void *key;			/* pointer to user's key */
 
 
-	struct semaphore msg_to_pull_sema; /* next msg to pull serialization */
-	struct semaphore wdisconnect_sema; /* wait for channel disconnect */
+	struct mutex msg_to_pull_mutex;	/* next msg to pull serialization */
+	struct completion wdisconnect_wait; /* wait for channel disconnect */
 
 
 	struct xpc_openclose_args *local_openclose_args; /* args passed on */
 	struct xpc_openclose_args *local_openclose_args; /* args passed on */
 					/* opening or closing of channel */
 					/* opening or closing of channel */

+ 4 - 0
include/asm-ia64/topology.h

@@ -18,6 +18,10 @@
 #include <asm/smp.h>
 #include <asm/smp.h>
 
 
 #ifdef CONFIG_NUMA
 #ifdef CONFIG_NUMA
+
+/* Nodes w/o CPUs are preferred for memory allocations, see build_zonelists */
+#define PENALTY_FOR_NODE_WITH_CPUS 255
+
 /*
 /*
  * Returns the number of the node containing CPU 'cpu'
  * Returns the number of the node containing CPU 'cpu'
  */
  */

+ 2 - 0
include/asm-sparc/oplib.h

@@ -164,6 +164,7 @@ enum prom_input_device {
 	PROMDEV_IKBD,			/* input from keyboard */
 	PROMDEV_IKBD,			/* input from keyboard */
 	PROMDEV_ITTYA,			/* input from ttya */
 	PROMDEV_ITTYA,			/* input from ttya */
 	PROMDEV_ITTYB,			/* input from ttyb */
 	PROMDEV_ITTYB,			/* input from ttyb */
+	PROMDEV_IRSC,			/* input from rsc */
 	PROMDEV_I_UNK,
 	PROMDEV_I_UNK,
 };
 };
 
 
@@ -175,6 +176,7 @@ enum prom_output_device {
 	PROMDEV_OSCREEN,		/* to screen */
 	PROMDEV_OSCREEN,		/* to screen */
 	PROMDEV_OTTYA,			/* to ttya */
 	PROMDEV_OTTYA,			/* to ttya */
 	PROMDEV_OTTYB,			/* to ttyb */
 	PROMDEV_OTTYB,			/* to ttyb */
+	PROMDEV_ORSC,			/* to rsc */
 	PROMDEV_O_UNK,
 	PROMDEV_O_UNK,
 };
 };
 
 

+ 3 - 2
include/asm-sparc/thread_info.h

@@ -128,9 +128,10 @@ BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *)
  * thread information flag bit numbers
  * thread information flag bit numbers
  */
  */
 #define TIF_SYSCALL_TRACE	0	/* syscall trace active */
 #define TIF_SYSCALL_TRACE	0	/* syscall trace active */
-#define TIF_NOTIFY_RESUME	1	/* resumption notification requested */
+/* flag bit 1 is available */
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
+#define TIF_RESTORE_SIGMASK	4	/* restore signal mask in do_signal() */
 #define TIF_USEDFPU		8	/* FPU was used by this task
 #define TIF_USEDFPU		8	/* FPU was used by this task
 					 * this quantum (SMP) */
 					 * this quantum (SMP) */
 #define TIF_POLLING_NRFLAG	9	/* true if poll_idle() is polling
 #define TIF_POLLING_NRFLAG	9	/* true if poll_idle() is polling
@@ -139,9 +140,9 @@ BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *)
 
 
 /* as above, but as bit values */
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
-#define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
+#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
 

+ 19 - 3
include/asm-sparc/unistd.h

@@ -300,11 +300,26 @@
 #define __NR_add_key		281
 #define __NR_add_key		281
 #define __NR_request_key	282
 #define __NR_request_key	282
 #define __NR_keyctl		283
 #define __NR_keyctl		283
+#define __NR_openat		284
+#define __NR_mkdirat		285
+#define __NR_mknodat		286
+#define __NR_fchownat		287
+#define __NR_futimesat		288
+#define __NR_newfstatat		289
+#define __NR_unlinkat		290
+#define __NR_renameat		291
+#define __NR_linkat		292
+#define __NR_symlinkat		293
+#define __NR_readlinkat		294
+#define __NR_fchmodat		295
+#define __NR_faccessat		296
+#define __NR_pselect6		297
+#define __NR_ppoll		298
 
 
-/* WARNING: You MAY NOT add syscall numbers larger than 283, since
+/* WARNING: You MAY NOT add syscall numbers larger than 298, since
  *          all of the syscall tables in the Sparc kernel are
  *          all of the syscall tables in the Sparc kernel are
- *          sized to have 283 entries (starting at zero).  Therefore
- *          find a free slot in the 0-282 range.
+ *          sized to have 298 entries (starting at zero).  Therefore
+ *          find a free slot in the 0-298 range.
  */
  */
 
 
 #define _syscall0(type,name) \
 #define _syscall0(type,name) \
@@ -458,6 +473,7 @@ return -1; \
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_SIGPROCMASK
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #endif
 #endif
 
 
 #ifdef __KERNEL_SYSCALLS__
 #ifdef __KERNEL_SYSCALLS__

+ 3 - 3
include/asm-sparc64/thread_info.h

@@ -221,7 +221,7 @@ register struct thread_info *current_thread_info_reg asm("g6");
  *	 nop
  *	 nop
  */
  */
 #define TIF_SYSCALL_TRACE	0	/* syscall trace active */
 #define TIF_SYSCALL_TRACE	0	/* syscall trace active */
-#define TIF_NOTIFY_RESUME	1	/* resumption notification requested */
+#define TIF_RESTORE_SIGMASK	1	/* restore signal mask in do_signal() */
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_PERFCTR		4	/* performance counters active */
 #define TIF_PERFCTR		4	/* performance counters active */
@@ -241,7 +241,6 @@ register struct thread_info *current_thread_info_reg asm("g6");
 #define TIF_POLLING_NRFLAG	14
 #define TIF_POLLING_NRFLAG	14
 
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
-#define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_PERFCTR		(1<<TIF_PERFCTR)
 #define _TIF_PERFCTR		(1<<TIF_PERFCTR)
@@ -250,11 +249,12 @@ register struct thread_info *current_thread_info_reg asm("g6");
 #define _TIF_32BIT		(1<<TIF_32BIT)
 #define _TIF_32BIT		(1<<TIF_32BIT)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
+#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_ABI_PENDING	(1<<TIF_ABI_PENDING)
 #define _TIF_ABI_PENDING	(1<<TIF_ABI_PENDING)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
 
 #define _TIF_USER_WORK_MASK	((0xff << TI_FLAG_WSAVED_SHIFT) | \
 #define _TIF_USER_WORK_MASK	((0xff << TI_FLAG_WSAVED_SHIFT) | \
-				 (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
+				 (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | \
 				  _TIF_NEED_RESCHED | _TIF_PERFCTR))
 				  _TIF_NEED_RESCHED | _TIF_PERFCTR))
 
 
 #endif /* __KERNEL__ */
 #endif /* __KERNEL__ */

+ 20 - 3
include/asm-sparc64/unistd.h

@@ -302,11 +302,26 @@
 #define __NR_add_key		281
 #define __NR_add_key		281
 #define __NR_request_key	282
 #define __NR_request_key	282
 #define __NR_keyctl		283
 #define __NR_keyctl		283
+#define __NR_openat		284
+#define __NR_mkdirat		285
+#define __NR_mknodat		286
+#define __NR_fchownat		287
+#define __NR_futimesat		288
+#define __NR_newfstatat		289
+#define __NR_unlinkat		290
+#define __NR_renameat		291
+#define __NR_linkat		292
+#define __NR_symlinkat		293
+#define __NR_readlinkat		294
+#define __NR_fchmodat		295
+#define __NR_faccessat		296
+#define __NR_pselect6		297
+#define __NR_ppoll		298
 
 
-/* WARNING: You MAY NOT add syscall numbers larger than 283, since
+/* WARNING: You MAY NOT add syscall numbers larger than 298, since
  *          all of the syscall tables in the Sparc kernel are
  *          all of the syscall tables in the Sparc kernel are
- *          sized to have 283 entries (starting at zero).  Therefore
- *          find a free slot in the 0-282 range.
+ *          sized to have 298 entries (starting at zero).  Therefore
+ *          find a free slot in the 0-298 range.
  */
  */
 
 
 #define _syscall0(type,name) \
 #define _syscall0(type,name) \
@@ -501,6 +516,8 @@ asmlinkage long sys_rt_sigaction(int sig,
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_SIGPROCMASK
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 #endif
 #endif
 
 
 /*
 /*

+ 1 - 1
include/linux/netfilter/x_tables.h

@@ -19,7 +19,7 @@ struct xt_get_revision
 /* For standard target */
 /* For standard target */
 #define XT_RETURN (-NF_REPEAT - 1)
 #define XT_RETURN (-NF_REPEAT - 1)
 
 
-#define XT_ALIGN(s) (((s) + (__alignof__(void *)-1)) & ~(__alignof__(void *)-1))
+#define XT_ALIGN(s) (((s) + (__alignof__(u_int64_t)-1)) & ~(__alignof__(u_int64_t)-1))
 
 
 /* Standard return verdict, or do jump. */
 /* Standard return verdict, or do jump. */
 #define XT_STANDARD_TARGET ""
 #define XT_STANDARD_TARGET ""

+ 2 - 0
include/net/sctp/sctp.h

@@ -175,6 +175,8 @@ void sctp_icmp_frag_needed(struct sock *, struct sctp_association *,
 void sctp_icmp_proto_unreachable(struct sock *sk,
 void sctp_icmp_proto_unreachable(struct sock *sk,
 				 struct sctp_association *asoc,
 				 struct sctp_association *asoc,
 				 struct sctp_transport *t);
 				 struct sctp_transport *t);
+void sctp_backlog_migrate(struct sctp_association *assoc,
+			  struct sock *oldsk, struct sock *newsk);
 
 
 /*
 /*
  *  Section:  Macros, externs, and inlines
  *  Section:  Macros, externs, and inlines

+ 51 - 38
include/net/sctp/structs.h

@@ -127,9 +127,9 @@ extern struct sctp_globals {
 	 * RTO.Alpha		    - 1/8  (3 when converted to right shifts.)
 	 * RTO.Alpha		    - 1/8  (3 when converted to right shifts.)
 	 * RTO.Beta		    - 1/4  (2 when converted to right shifts.)
 	 * RTO.Beta		    - 1/4  (2 when converted to right shifts.)
 	 */
 	 */
-	__u32 rto_initial;
-	__u32 rto_min;
-	__u32 rto_max;
+	unsigned long rto_initial;
+	unsigned long rto_min;
+	unsigned long rto_max;
 
 
 	/* Note: rto_alpha and rto_beta are really defined as inverse
 	/* Note: rto_alpha and rto_beta are really defined as inverse
 	 * powers of two to facilitate integer operations.
 	 * powers of two to facilitate integer operations.
@@ -140,12 +140,18 @@ extern struct sctp_globals {
 	/* Max.Burst		    - 4 */
 	/* Max.Burst		    - 4 */
 	int max_burst;
 	int max_burst;
 
 
-	/* Valid.Cookie.Life	    - 60  seconds  */
-	int valid_cookie_life;
-
 	/* Whether Cookie Preservative is enabled(1) or not(0) */
 	/* Whether Cookie Preservative is enabled(1) or not(0) */
 	int cookie_preserve_enable;
 	int cookie_preserve_enable;
 
 
+	/* Valid.Cookie.Life	    - 60  seconds  */
+	unsigned long valid_cookie_life;
+
+	/* Delayed SACK timeout  200ms default*/
+	unsigned long sack_timeout;
+
+	/* HB.interval		    - 30 seconds  */
+	unsigned long hb_interval;
+
 	/* Association.Max.Retrans  - 10 attempts
 	/* Association.Max.Retrans  - 10 attempts
 	 * Path.Max.Retrans	    - 5	 attempts (per destination address)
 	 * Path.Max.Retrans	    - 5	 attempts (per destination address)
 	 * Max.Init.Retransmits	    - 8	 attempts
 	 * Max.Init.Retransmits	    - 8	 attempts
@@ -168,12 +174,6 @@ extern struct sctp_globals {
 	 */
 	 */
 	int rcvbuf_policy;
 	int rcvbuf_policy;
 
 
-	/* Delayed SACK timeout  200ms default*/
-	int sack_timeout;
-
-	/* HB.interval		    - 30 seconds  */
-	int hb_interval;
-
 	/* The following variables are implementation specific.	 */
 	/* The following variables are implementation specific.	 */
 
 
 	/* Default initialization values to be applied to new associations. */
 	/* Default initialization values to be applied to new associations. */
@@ -405,8 +405,9 @@ struct sctp_cookie {
 /* The format of our cookie that we send to our peer. */
 /* The format of our cookie that we send to our peer. */
 struct sctp_signed_cookie {
 struct sctp_signed_cookie {
 	__u8 signature[SCTP_SECRET_SIZE];
 	__u8 signature[SCTP_SECRET_SIZE];
+	__u32 __pad;		/* force sctp_cookie alignment to 64 bits */
 	struct sctp_cookie c;
 	struct sctp_cookie c;
-};
+} __attribute__((packed));
 
 
 /* This is another convenience type to allocate memory for address
 /* This is another convenience type to allocate memory for address
  * params for the maximum size and pass such structures around
  * params for the maximum size and pass such structures around
@@ -827,7 +828,7 @@ struct sctp_transport {
 	__u32 rtt;		/* This is the most recent RTT.	 */
 	__u32 rtt;		/* This is the most recent RTT.	 */
 
 
 	/* RTO	       : The current retransmission timeout value.  */
 	/* RTO	       : The current retransmission timeout value.  */
-	__u32 rto;
+	unsigned long rto;
 
 
 	/* RTTVAR      : The current RTT variation.  */
 	/* RTTVAR      : The current RTT variation.  */
 	__u32 rttvar;
 	__u32 rttvar;
@@ -877,22 +878,10 @@ struct sctp_transport {
 	/* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
 	/* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
 	 * the destination address every heartbeat interval.
 	 * the destination address every heartbeat interval.
 	 */
 	 */
-	__u32 hbinterval;
-
-	/* This is the max_retrans value for the transport and will
-	 * be initialized from the assocs value.  This can be changed
-	 * using SCTP_SET_PEER_ADDR_PARAMS socket option.
-	 */
-	__u16 pathmaxrxt;
-
-	/* PMTU	      : The current known path MTU.  */
-	__u32 pathmtu;
+	unsigned long hbinterval;
 
 
 	/* SACK delay timeout */
 	/* SACK delay timeout */
-	__u32 sackdelay;
-
-	/* Flags controling Heartbeat, SACK delay, and Path MTU Discovery. */
-	__u32 param_flags;
+	unsigned long sackdelay;
 
 
 	/* When was the last time (in jiffies) that we heard from this
 	/* When was the last time (in jiffies) that we heard from this
 	 * transport?  We use this to pick new active and retran paths.
 	 * transport?  We use this to pick new active and retran paths.
@@ -904,6 +893,18 @@ struct sctp_transport {
 	 */
 	 */
 	unsigned long last_time_ecne_reduced;
 	unsigned long last_time_ecne_reduced;
 
 
+	/* This is the max_retrans value for the transport and will
+	 * be initialized from the assocs value.  This can be changed
+	 * using SCTP_SET_PEER_ADDR_PARAMS socket option.
+	 */
+	__u16 pathmaxrxt;
+
+	/* PMTU	      : The current known path MTU.  */
+	__u32 pathmtu;
+
+	/* Flags controling Heartbeat, SACK delay, and Path MTU Discovery. */
+	__u32 param_flags;
+
 	/* The number of times INIT has been sent on this transport. */
 	/* The number of times INIT has been sent on this transport. */
 	int init_sent_count;
 	int init_sent_count;
 
 
@@ -1249,6 +1250,14 @@ struct sctp_endpoint {
 	int last_key;
 	int last_key;
 	int key_changed_at;
 	int key_changed_at;
 
 
+ 	/* digest:  This is a digest of the sctp cookie.  This field is
+ 	 * 	    only used on the receive path when we try to validate
+ 	 * 	    that the cookie has not been tampered with.  We put
+ 	 * 	    this here so we pre-allocate this once and can re-use
+ 	 * 	    on every receive.
+ 	 */
+ 	__u8 digest[SCTP_SIGNATURE_SIZE];
+ 
 	/* sendbuf acct. policy.	*/
 	/* sendbuf acct. policy.	*/
 	__u32 sndbuf_policy;
 	__u32 sndbuf_policy;
 
 
@@ -1499,9 +1508,9 @@ struct sctp_association {
 	 * These values will be initialized by system defaults, but can
 	 * These values will be initialized by system defaults, but can
 	 * be modified via the SCTP_RTOINFO socket option.
 	 * be modified via the SCTP_RTOINFO socket option.
 	 */
 	 */
-	__u32 rto_initial;
-	__u32 rto_max;
-	__u32 rto_min;
+	unsigned long rto_initial;
+	unsigned long rto_max;
+	unsigned long rto_min;
 
 
 	/* Maximum number of new data packets that can be sent in a burst.  */
 	/* Maximum number of new data packets that can be sent in a burst.  */
 	int max_burst;
 	int max_burst;
@@ -1519,13 +1528,13 @@ struct sctp_association {
 	__u16 init_retries;
 	__u16 init_retries;
 
 
 	/* The largest timeout or RTO value to use in attempting an INIT */
 	/* The largest timeout or RTO value to use in attempting an INIT */
-	__u16 max_init_timeo;
+	unsigned long max_init_timeo;
 
 
 	/* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
 	/* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
 	 * the destination address every heartbeat interval. This value
 	 * the destination address every heartbeat interval. This value
 	 * will be inherited by all new transports.
 	 * will be inherited by all new transports.
 	 */
 	 */
-	__u32 hbinterval;
+	unsigned long hbinterval;
 
 
 	/* This is the max_retrans value for new transports in the
 	/* This is the max_retrans value for new transports in the
 	 * association.
 	 * association.
@@ -1537,13 +1546,14 @@ struct sctp_association {
 	 */
 	 */
 	__u32 pathmtu;
 	__u32 pathmtu;
 
 
-	/* SACK delay timeout */
-	__u32 sackdelay;
-
 	/* Flags controling Heartbeat, SACK delay, and Path MTU Discovery. */
 	/* Flags controling Heartbeat, SACK delay, and Path MTU Discovery. */
 	__u32 param_flags;
 	__u32 param_flags;
 
 
-	int timeouts[SCTP_NUM_TIMEOUT_TYPES];
+	/* SACK delay timeout */
+	unsigned long sackdelay;
+
+
+	unsigned long timeouts[SCTP_NUM_TIMEOUT_TYPES];
 	struct timer_list timers[SCTP_NUM_TIMEOUT_TYPES];
 	struct timer_list timers[SCTP_NUM_TIMEOUT_TYPES];
 
 
 	/* Transport to which SHUTDOWN chunk was last sent.  */
 	/* Transport to which SHUTDOWN chunk was last sent.  */
@@ -1648,7 +1658,10 @@ struct sctp_association {
 	/* How many duplicated TSNs have we seen?  */
 	/* How many duplicated TSNs have we seen?  */
 	int numduptsns;
 	int numduptsns;
 
 
-	/* Number of seconds of idle time before an association is closed.  */
+	/* Number of seconds of idle time before an association is closed.
+	 * In the association context, this is really used as a boolean
+	 * since the real timeout is stored in the timeouts array
+	 */
 	__u32 autoclose;
 	__u32 autoclose;
 
 
 	/* These are to support
 	/* These are to support

+ 62 - 13
net/sctp/input.c

@@ -257,20 +257,26 @@ int sctp_rcv(struct sk_buff *skb)
 	 */
 	 */
 	sctp_bh_lock_sock(sk);
 	sctp_bh_lock_sock(sk);
 
 
+	/* It is possible that the association could have moved to a different
+	 * socket if it is peeled off. If so, update the sk.
+	 */ 
+	if (sk != rcvr->sk) {
+		sctp_bh_lock_sock(rcvr->sk);
+		sctp_bh_unlock_sock(sk);
+		sk = rcvr->sk;
+	}
+
 	if (sock_owned_by_user(sk))
 	if (sock_owned_by_user(sk))
 		sk_add_backlog(sk, skb);
 		sk_add_backlog(sk, skb);
 	else
 	else
 		sctp_backlog_rcv(sk, skb);
 		sctp_backlog_rcv(sk, skb);
 
 
-	/* Release the sock and any reference counts we took in the
-	 * lookup calls.
+	/* Release the sock and the sock ref we took in the lookup calls.
+	 * The asoc/ep ref will be released in sctp_backlog_rcv.
 	 */
 	 */
 	sctp_bh_unlock_sock(sk);
 	sctp_bh_unlock_sock(sk);
-	if (asoc)
-		sctp_association_put(asoc);
-	else
-		sctp_endpoint_put(ep);
 	sock_put(sk);
 	sock_put(sk);
+
 	return ret;
 	return ret;
 
 
 discard_it:
 discard_it:
@@ -296,12 +302,50 @@ discard_release:
 int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 {
 {
 	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
 	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
-	struct sctp_inq *inqueue = &chunk->rcvr->inqueue;
-
-	sctp_inq_push(inqueue, chunk);
+ 	struct sctp_inq *inqueue = NULL;
+ 	struct sctp_ep_common *rcvr = NULL;
+
+ 	rcvr = chunk->rcvr;
+
+	BUG_TRAP(rcvr->sk == sk);
+
+ 	if (rcvr->dead) {
+ 		sctp_chunk_free(chunk);
+ 	} else {
+ 		inqueue = &chunk->rcvr->inqueue;
+ 		sctp_inq_push(inqueue, chunk);
+ 	}
+
+	/* Release the asoc/ep ref we took in the lookup calls in sctp_rcv. */ 
+ 	if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type)
+ 		sctp_association_put(sctp_assoc(rcvr));
+ 	else
+ 		sctp_endpoint_put(sctp_ep(rcvr));
+  
         return 0;
         return 0;
 }
 }
 
 
+void sctp_backlog_migrate(struct sctp_association *assoc, 
+			  struct sock *oldsk, struct sock *newsk)
+{
+	struct sk_buff *skb;
+	struct sctp_chunk *chunk;
+
+	skb = oldsk->sk_backlog.head;
+	oldsk->sk_backlog.head = oldsk->sk_backlog.tail = NULL;
+	while (skb != NULL) {
+		struct sk_buff *next = skb->next;
+
+		chunk = SCTP_INPUT_CB(skb)->chunk;
+		skb->next = NULL;
+		if (&assoc->base == chunk->rcvr)
+			sk_add_backlog(newsk, skb);
+		else
+			sk_add_backlog(oldsk, skb);
+		skb = next;
+	}
+}
+
 /* Handle icmp frag needed error. */
 /* Handle icmp frag needed error. */
 void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
 void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
 			   struct sctp_transport *t, __u32 pmtu)
 			   struct sctp_transport *t, __u32 pmtu)
@@ -544,10 +588,16 @@ int sctp_rcv_ootb(struct sk_buff *skb)
 	sctp_errhdr_t *err;
 	sctp_errhdr_t *err;
 
 
 	ch = (sctp_chunkhdr_t *) skb->data;
 	ch = (sctp_chunkhdr_t *) skb->data;
-	ch_end = ((__u8 *) ch) + WORD_ROUND(ntohs(ch->length));
 
 
 	/* Scan through all the chunks in the packet.  */
 	/* Scan through all the chunks in the packet.  */
-	while (ch_end > (__u8 *)ch && ch_end < skb->tail) {
+	do {
+		/* Break out if chunk length is less then minimal. */
+		if (ntohs(ch->length) < sizeof(sctp_chunkhdr_t))
+			break;
+
+		ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));
+		if (ch_end > skb->tail)
+			break;
 
 
 		/* RFC 8.4, 2) If the OOTB packet contains an ABORT chunk, the
 		/* RFC 8.4, 2) If the OOTB packet contains an ABORT chunk, the
 		 * receiver MUST silently discard the OOTB packet and take no
 		 * receiver MUST silently discard the OOTB packet and take no
@@ -578,8 +628,7 @@ int sctp_rcv_ootb(struct sk_buff *skb)
 		}
 		}
 
 
 		ch = (sctp_chunkhdr_t *) ch_end;
 		ch = (sctp_chunkhdr_t *) ch_end;
-	        ch_end = ((__u8 *) ch) + WORD_ROUND(ntohs(ch->length));
-	}
+	} while (ch_end < skb->tail);
 
 
 	return 0;
 	return 0;
 
 

+ 3 - 1
net/sctp/inqueue.c

@@ -73,8 +73,10 @@ void sctp_inq_free(struct sctp_inq *queue)
 	/* If there is a packet which is currently being worked on,
 	/* If there is a packet which is currently being worked on,
 	 * free it as well.
 	 * free it as well.
 	 */
 	 */
-	if (queue->in_progress)
+	if (queue->in_progress) {
 		sctp_chunk_free(queue->in_progress);
 		sctp_chunk_free(queue->in_progress);
+		queue->in_progress = NULL;
+	}
 
 
 	if (queue->malloced) {
 	if (queue->malloced) {
 		/* Dump the master memory segment.  */
 		/* Dump the master memory segment.  */

+ 12 - 20
net/sctp/proc.c

@@ -176,7 +176,7 @@ static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_associa
 
 
 static void * sctp_eps_seq_start(struct seq_file *seq, loff_t *pos)
 static void * sctp_eps_seq_start(struct seq_file *seq, loff_t *pos)
 {
 {
-	if (*pos > sctp_ep_hashsize)
+	if (*pos >= sctp_ep_hashsize)
 		return NULL;
 		return NULL;
 
 
 	if (*pos < 0)
 	if (*pos < 0)
@@ -185,8 +185,6 @@ static void * sctp_eps_seq_start(struct seq_file *seq, loff_t *pos)
 	if (*pos == 0)
 	if (*pos == 0)
 		seq_printf(seq, " ENDPT     SOCK   STY SST HBKT LPORT   UID INODE LADDRS\n");
 		seq_printf(seq, " ENDPT     SOCK   STY SST HBKT LPORT   UID INODE LADDRS\n");
 
 
-	++*pos;
-
 	return (void *)pos;
 	return (void *)pos;
 }
 }
 
 
@@ -198,11 +196,9 @@ static void sctp_eps_seq_stop(struct seq_file *seq, void *v)
 
 
 static void * sctp_eps_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 static void * sctp_eps_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 {
-	if (*pos > sctp_ep_hashsize)
+	if (++*pos >= sctp_ep_hashsize)
 		return NULL;
 		return NULL;
 
 
-	++*pos;
-
 	return pos;
 	return pos;
 }
 }
 
 
@@ -214,19 +210,19 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v)
 	struct sctp_ep_common *epb;
 	struct sctp_ep_common *epb;
 	struct sctp_endpoint *ep;
 	struct sctp_endpoint *ep;
 	struct sock *sk;
 	struct sock *sk;
-	int    hash = *(int *)v;
+	int    hash = *(loff_t *)v;
 
 
-	if (hash > sctp_ep_hashsize)
+	if (hash >= sctp_ep_hashsize)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	head = &sctp_ep_hashtable[hash-1];
+	head = &sctp_ep_hashtable[hash];
 	sctp_local_bh_disable();
 	sctp_local_bh_disable();
 	read_lock(&head->lock);
 	read_lock(&head->lock);
 	for (epb = head->chain; epb; epb = epb->next) {
 	for (epb = head->chain; epb; epb = epb->next) {
 		ep = sctp_ep(epb);
 		ep = sctp_ep(epb);
 		sk = epb->sk;
 		sk = epb->sk;
 		seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk,
 		seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk,
-			   sctp_sk(sk)->type, sk->sk_state, hash-1,
+			   sctp_sk(sk)->type, sk->sk_state, hash,
 			   epb->bind_addr.port,
 			   epb->bind_addr.port,
 			   sock_i_uid(sk), sock_i_ino(sk));
 			   sock_i_uid(sk), sock_i_ino(sk));
 
 
@@ -283,7 +279,7 @@ void sctp_eps_proc_exit(void)
 
 
 static void * sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos)
 static void * sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos)
 {
 {
-	if (*pos > sctp_assoc_hashsize)
+	if (*pos >= sctp_assoc_hashsize)
 		return NULL;
 		return NULL;
 
 
 	if (*pos < 0)
 	if (*pos < 0)
@@ -293,8 +289,6 @@ static void * sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos)
 		seq_printf(seq, " ASSOC     SOCK   STY SST ST HBKT ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT "
 		seq_printf(seq, " ASSOC     SOCK   STY SST ST HBKT ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT "
 				"RPORT LADDRS <-> RADDRS\n");
 				"RPORT LADDRS <-> RADDRS\n");
 
 
-	++*pos;
-
 	return (void *)pos;
 	return (void *)pos;
 }
 }
 
 
@@ -306,11 +300,9 @@ static void sctp_assocs_seq_stop(struct seq_file *seq, void *v)
 
 
 static void * sctp_assocs_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 static void * sctp_assocs_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 {
-	if (*pos > sctp_assoc_hashsize)
+	if (++*pos >= sctp_assoc_hashsize)
 		return NULL;
 		return NULL;
 
 
-	++*pos;
-
 	return pos;
 	return pos;
 }
 }
 
 
@@ -321,12 +313,12 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
 	struct sctp_ep_common *epb;
 	struct sctp_ep_common *epb;
 	struct sctp_association *assoc;
 	struct sctp_association *assoc;
 	struct sock *sk;
 	struct sock *sk;
-	int    hash = *(int *)v;
+	int    hash = *(loff_t *)v;
 
 
-	if (hash > sctp_assoc_hashsize)
+	if (hash >= sctp_assoc_hashsize)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	head = &sctp_assoc_hashtable[hash-1];
+	head = &sctp_assoc_hashtable[hash];
 	sctp_local_bh_disable();
 	sctp_local_bh_disable();
 	read_lock(&head->lock);
 	read_lock(&head->lock);
 	for (epb = head->chain; epb; epb = epb->next) {
 	for (epb = head->chain; epb; epb = epb->next) {
@@ -335,7 +327,7 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
 		seq_printf(seq,
 		seq_printf(seq,
 			   "%8p %8p %-3d %-3d %-2d %-4d %4d %8d %8d %7d %5lu %-5d %5d ",
 			   "%8p %8p %-3d %-3d %-2d %-4d %4d %8d %8d %7d %5lu %-5d %5d ",
 			   assoc, sk, sctp_sk(sk)->type, sk->sk_state,
 			   assoc, sk, sctp_sk(sk)->type, sk->sk_state,
-			   assoc->state, hash-1, assoc->assoc_id,
+			   assoc->state, hash, assoc->assoc_id,
 			   (sk->sk_rcvbuf - assoc->rwnd),
 			   (sk->sk_rcvbuf - assoc->rwnd),
 			   assoc->sndbuf_used,
 			   assoc->sndbuf_used,
 			   sock_i_uid(sk), sock_i_ino(sk),
 			   sock_i_uid(sk), sock_i_ino(sk),

+ 13 - 3
net/sctp/sm_make_chunk.c

@@ -1275,7 +1275,12 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
 	unsigned int keylen;
 	unsigned int keylen;
 	char *key;
 	char *key;
 
 
-	headersize = sizeof(sctp_paramhdr_t) + SCTP_SECRET_SIZE;
+	/* Header size is static data prior to the actual cookie, including
+	 * any padding.
+	 */
+	headersize = sizeof(sctp_paramhdr_t) + 
+		     (sizeof(struct sctp_signed_cookie) - 
+		      sizeof(struct sctp_cookie));
 	bodysize = sizeof(struct sctp_cookie)
 	bodysize = sizeof(struct sctp_cookie)
 		+ ntohs(init_chunk->chunk_hdr->length) + addrs_len;
 		+ ntohs(init_chunk->chunk_hdr->length) + addrs_len;
 
 
@@ -1354,7 +1359,7 @@ struct sctp_association *sctp_unpack_cookie(
 	struct sctp_signed_cookie *cookie;
 	struct sctp_signed_cookie *cookie;
 	struct sctp_cookie *bear_cookie;
 	struct sctp_cookie *bear_cookie;
 	int headersize, bodysize, fixed_size;
 	int headersize, bodysize, fixed_size;
-	__u8 digest[SCTP_SIGNATURE_SIZE];
+	__u8 *digest = ep->digest;
 	struct scatterlist sg;
 	struct scatterlist sg;
 	unsigned int keylen, len;
 	unsigned int keylen, len;
 	char *key;
 	char *key;
@@ -1362,7 +1367,12 @@ struct sctp_association *sctp_unpack_cookie(
 	struct sk_buff *skb = chunk->skb;
 	struct sk_buff *skb = chunk->skb;
 	struct timeval tv;
 	struct timeval tv;
 
 
-	headersize = sizeof(sctp_chunkhdr_t) + SCTP_SECRET_SIZE;
+	/* Header size is static data prior to the actual cookie, including
+	 * any padding.
+	 */
+	headersize = sizeof(sctp_chunkhdr_t) +
+		     (sizeof(struct sctp_signed_cookie) - 
+		      sizeof(struct sctp_cookie));
 	bodysize = ntohs(chunk->chunk_hdr->length) - headersize;
 	bodysize = ntohs(chunk->chunk_hdr->length) - headersize;
 	fixed_size = headersize + sizeof(struct sctp_cookie);
 	fixed_size = headersize + sizeof(struct sctp_cookie);
 
 

+ 2 - 2
net/sctp/sm_sideeffect.c

@@ -1300,7 +1300,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
 					"T1 INIT Timeout adjustment"
 					"T1 INIT Timeout adjustment"
 					" init_err_counter: %d"
 					" init_err_counter: %d"
 					" cycle: %d"
 					" cycle: %d"
-					" timeout: %d\n",
+					" timeout: %ld\n",
 					asoc->init_err_counter,
 					asoc->init_err_counter,
 					asoc->init_cycle,
 					asoc->init_cycle,
 					asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]);
 					asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]);
@@ -1328,7 +1328,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
 			SCTP_DEBUG_PRINTK(
 			SCTP_DEBUG_PRINTK(
 				"T1 COOKIE Timeout adjustment"
 				"T1 COOKIE Timeout adjustment"
 				" init_err_counter: %d"
 				" init_err_counter: %d"
-				" timeout: %d\n",
+				" timeout: %ld\n",
 				asoc->init_err_counter,
 				asoc->init_err_counter,
 				asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]);
 				asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]);
 
 

+ 2 - 0
net/sctp/sm_statefuns.c

@@ -3090,6 +3090,8 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep,
 			break;
 			break;
 
 
 		ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));
 		ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));
+		if (ch_end > skb->tail)
+			break;
 
 
 		if (SCTP_CID_SHUTDOWN_ACK == ch->type)
 		if (SCTP_CID_SHUTDOWN_ACK == ch->type)
 			ootb_shut_ack = 1;
 			ootb_shut_ack = 1;

+ 5 - 1
net/sctp/socket.c

@@ -2995,7 +2995,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
 	sp->hbinterval  = jiffies_to_msecs(sctp_hb_interval);
 	sp->hbinterval  = jiffies_to_msecs(sctp_hb_interval);
 	sp->pathmaxrxt  = sctp_max_retrans_path;
 	sp->pathmaxrxt  = sctp_max_retrans_path;
 	sp->pathmtu     = 0; // allow default discovery
 	sp->pathmtu     = 0; // allow default discovery
-	sp->sackdelay   = sctp_sack_timeout;
+	sp->sackdelay   = jiffies_to_msecs(sctp_sack_timeout);
 	sp->param_flags = SPP_HB_ENABLE |
 	sp->param_flags = SPP_HB_ENABLE |
 	                  SPP_PMTUD_ENABLE |
 	                  SPP_PMTUD_ENABLE |
 	                  SPP_SACKDELAY_ENABLE;
 	                  SPP_SACKDELAY_ENABLE;
@@ -5602,8 +5602,12 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
 	 */
 	 */
 	newsp->type = type;
 	newsp->type = type;
 
 
+	spin_lock_bh(&oldsk->sk_lock.slock);
+	/* Migrate the backlog from oldsk to newsk. */
+	sctp_backlog_migrate(assoc, oldsk, newsk);
 	/* Migrate the association to the new socket. */
 	/* Migrate the association to the new socket. */
 	sctp_assoc_migrate(assoc, newsk);
 	sctp_assoc_migrate(assoc, newsk);
+	spin_unlock_bh(&oldsk->sk_lock.slock);
 
 
 	/* If the association on the newsk is already closed before accept()
 	/* If the association on the newsk is already closed before accept()
 	 * is called, set RCV_SHUTDOWN flag.
 	 * is called, set RCV_SHUTDOWN flag.

+ 2 - 5
net/sctp/sysctl.c

@@ -159,12 +159,9 @@ static ctl_table sctp_table[] = {
 		.ctl_name	= NET_SCTP_PRESERVE_ENABLE,
 		.ctl_name	= NET_SCTP_PRESERVE_ENABLE,
 		.procname	= "cookie_preserve_enable",
 		.procname	= "cookie_preserve_enable",
 		.data		= &sctp_cookie_preserve_enable,
 		.data		= &sctp_cookie_preserve_enable,
-		.maxlen		= sizeof(long),
+		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.mode		= 0644,
-		.proc_handler	= &proc_doulongvec_ms_jiffies_minmax,
-		.strategy	= &sctp_sysctl_jiffies_ms,
-		.extra1         = &rto_timer_min,
-		.extra2         = &rto_timer_max
+		.proc_handler	= &proc_dointvec
 	},
 	},
 	{
 	{
 		.ctl_name	= NET_SCTP_RTO_ALPHA,
 		.ctl_name	= NET_SCTP_RTO_ALPHA,

+ 1 - 1
net/sctp/transport.c

@@ -350,7 +350,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt)
 	tp->rto_pending = 0;
 	tp->rto_pending = 0;
 
 
 	SCTP_DEBUG_PRINTK("%s: transport: %p, rtt: %d, srtt: %d "
 	SCTP_DEBUG_PRINTK("%s: transport: %p, rtt: %d, srtt: %d "
-			  "rttvar: %d, rto: %d\n", __FUNCTION__,
+			  "rttvar: %d, rto: %ld\n", __FUNCTION__,
 			  tp, rtt, tp->srtt, tp->rttvar, tp->rto);
 			  tp, rtt, tp->srtt, tp->rttvar, tp->rto);
 }
 }