Selaa lähdekoodia

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

Signed-off-by: Steve French <sfrench@us.ibm.com>
Steve French 19 vuotta sitten
vanhempi
commit
4c8af5254e
45 muutettua tiedostoa jossa 540 lisäystä ja 656 poistoa
  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/vfs.h>
 #include <linux/mman.h>
+#include <linux/mutex.h>
 
 #include <asm/intrinsics.h>
-#include <asm/semaphore.h>
 #include <asm/types.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -86,7 +86,7 @@
  * while doing so.
  */
 /* XXX make per-mm: */
-static DECLARE_MUTEX(ia32_mmap_sem);
+static DEFINE_MUTEX(ia32_mmap_mutex);
 
 asmlinkage long
 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);
 
 #if PAGE_SHIFT > IA32_PAGE_SHIFT
-	down(&ia32_mmap_sem);
+	mutex_lock(&ia32_mmap_mutex);
 	{
 		addr = emulate_mmap(file, addr, len, prot, flags, offset);
 	}
-	up(&ia32_mmap_sem);
+	mutex_unlock(&ia32_mmap_mutex);
 #else
 	down_write(&current->mm->mmap_sem);
 	{
@@ -1000,11 +1000,9 @@ sys32_munmap (unsigned int start, unsigned int len)
 	if (start >= end)
 		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
 	return ret;
 }
@@ -1056,7 +1054,7 @@ sys32_mprotect (unsigned int start, unsigned int len, int prot)
 	if (retval < 0)
 		return retval;
 
-	down(&ia32_mmap_sem);
+	mutex_lock(&ia32_mmap_mutex);
 	{
 		if (offset_in_page(start)) {
 			/* 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);
 	}
   out:
-	up(&ia32_mmap_sem);
+	mutex_unlock(&ia32_mmap_mutex);
 	return retval;
 #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;
 	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)) {
 		/* mremap expanded successfully */

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

@@ -40,6 +40,7 @@
 #include <linux/bitops.h>
 #include <linux/capability.h>
 #include <linux/rcupdate.h>
+#include <linux/completion.h>
 
 #include <asm/errno.h>
 #include <asm/intrinsics.h>
@@ -286,7 +287,7 @@ typedef struct pfm_context {
 
 	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_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
 		 */
-		up(&ctx->ctx_restart_sem);
+		complete(&ctx->ctx_restart_done);
 
 		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
 	 */
-	sema_init(&ctx->ctx_restart_sem, 0);
+	init_completion(&ctx->ctx_restart_done);
 
 	/*
 	 * 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) {
 		DPRINT(("unblocking [%d] \n", task->pid));
-		up(&ctx->ctx_restart_sem);
+		complete(&ctx->ctx_restart_done);
 	} else {
 		DPRINT(("[%d] armed exit trap\n", task->pid));
 
@@ -5089,7 +5090,7 @@ pfm_handle_work(void)
 	 * may go through without blocking on SMP systems
 	 * 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));
 

+ 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);
 
+	touch_softlockup_watchdog();
 	memset((char *)start, 0, length);
 
 	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;
 };
 
+/* 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.
  */

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

@@ -165,8 +165,45 @@ sn_pcidev_info_get(struct pci_dev *dev)
 	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.
  */
 static void sn_fixup_ionodes(void)
@@ -246,8 +283,19 @@ static void sn_fixup_ionodes(void)
 									widget,
 								       	device,
 						      (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);
 			}

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

@@ -10,6 +10,7 @@
 #include <linux/kernel.h>
 #include <linux/timer.h>
 #include <linux/vmalloc.h>
+#include <linux/mutex.h>
 #include <asm/mca.h>
 #include <asm/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
  * global.  Only one user at a time.
  */
-static DECLARE_MUTEX(sn_oemdata_mutex);
+static DEFINE_MUTEX(sn_oemdata_mutex);
 static u8 **sn_oemdata;
 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,
 				    u64 * oemdata_size)
 {
-	down(&sn_oemdata_mutex);
+	mutex_lock(&sn_oemdata_mutex);
 	sn_oemdata = oemdata;
 	sn_oemdata_size = oemdata_size;
 	sn_oemdata_bufsize = 0;
@@ -107,7 +108,7 @@ sn_platform_plat_specific_err_print(const u8 * sect_header, u8 ** oemdata,
 		*sn_oemdata_size = 0;
 		ia64_sn_plat_specific_err_print(print_hook, (char *)sect_header);
 	}
-	up(&sn_oemdata_mutex);
+	mutex_unlock(&sn_oemdata_mutex);
 	return 0;
 }
 

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

@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 #include <asm/sn/intr.h>
 #include <asm/sn/sn_sal.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];
 
-	if (down_interruptible(&registration->sema) != 0) {
+	if (mutex_lock_interruptible(&registration->mutex) != 0) {
 		return xpcInterrupted;
 	}
 
 	/* if XPC_CHANNEL_REGISTERED(ch_number) */
 	if (registration->func != NULL) {
-		up(&registration->sema);
+		mutex_unlock(&registration->mutex);
 		return xpcAlreadyRegistered;
 	}
 
@@ -154,7 +155,7 @@ xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
 	registration->key = key;
 	registration->func = func;
 
-	up(&registration->sema);
+	mutex_unlock(&registration->mutex);
 
 	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()
 	 * 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 (registration->func == NULL) {
-		up(&registration->sema);
+		mutex_unlock(&registration->mutex);
 		return;
 	}
 
@@ -208,7 +209,7 @@ xpc_disconnect(int ch_number)
 
 	xpc_interface.disconnect(ch_number);
 
-	up(&registration->sema);
+	mutex_unlock(&registration->mutex);
 
 	return;
 }
@@ -250,9 +251,9 @@ xp_init(void)
 		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++) {
-		sema_init(&xpc_registrations[ch_number].sema, 1);  /* mutex */
+		mutex_init(&xpc_registrations[ch_number].mutex);
 	}
 
 	return 0;

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

@@ -22,6 +22,8 @@
 #include <linux/cache.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
 #include <asm/sn/bte.h>
 #include <asm/sn/sn_sal.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);
 
 		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);
 		init_waitqueue_head(&ch->msg_allocate_wq);
@@ -534,7 +536,6 @@ static enum xpc_retval
 xpc_allocate_msgqueues(struct xpc_channel *ch)
 {
 	unsigned long irq_flags;
-	int i;
 	enum xpc_retval ret;
 
 
@@ -552,11 +553,6 @@ xpc_allocate_msgqueues(struct xpc_channel *ch)
 		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);
 	ch->flags |= XPC_C_SETUP;
 	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) {
-		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) {
 		if (part->act_state != XPC_P_DEACTIVATING) {
 			/* 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];
 
 
-	if (down_trylock(&registration->sema) != 0) {
+	if (mutex_trylock(&registration->mutex) == 0) {
 		return xpcRetry;
 	}
 
 	if (!XPC_CHANNEL_REGISTERED(ch->number)) {
-		up(&registration->sema);
+		mutex_unlock(&registration->mutex);
 		return xpcUnregistered;
 	}
 
@@ -1108,7 +1102,7 @@ xpc_connect_channel(struct xpc_channel *ch)
 
 	if (ch->flags & XPC_C_DISCONNECTING) {
 		spin_unlock_irqrestore(&ch->lock, irq_flags);
-		up(&registration->sema);
+		mutex_unlock(&registration->mutex);
 		return ch->reason;
 	}
 
@@ -1140,7 +1134,7 @@ xpc_connect_channel(struct xpc_channel *ch)
 			 * channel lock be locked and will unlock and relock
 			 * the channel lock as needed.
 			 */
-			up(&registration->sema);
+			mutex_unlock(&registration->mutex);
 			XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes,
 								&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);
 	}
 
-	up(&registration->sema);
+	mutex_unlock(&registration->mutex);
 
 
 	/* initiate the connection */
@@ -2089,7 +2083,7 @@ xpc_pull_remote_msg(struct xpc_channel *ch, s64 get)
 	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 */
 		return NULL;
 	}
@@ -2125,7 +2119,7 @@ xpc_pull_remote_msg(struct xpc_channel *ch, s64 get)
 
 			XPC_DEACTIVATE_PARTITION(part, ret);
 
-			up(&ch->msg_to_pull_sema);
+			mutex_unlock(&ch->msg_to_pull_mutex);
 			return NULL;
 		}
 
@@ -2134,7 +2128,7 @@ xpc_pull_remote_msg(struct xpc_channel *ch, s64 get)
 		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 */
 	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/delay.h>
 #include <linux/reboot.h>
+#include <linux/completion.h>
 #include <asm/sn/intr.h>
 #include <asm/sn/sn_sal.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;
 
 /* 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 */
-static DECLARE_MUTEX_LOCKED(xpc_discovery_exited);
+static DECLARE_COMPLETION(xpc_discovery_exited);
 
 
 static struct timer_list xpc_hb_timer;
@@ -321,7 +322,7 @@ xpc_hb_checker(void *ignore)
 
 
 	/* mark this thread as having exited */
-	up(&xpc_hb_checker_exited);
+	complete(&xpc_hb_checker_exited);
 	return 0;
 }
 
@@ -341,7 +342,7 @@ xpc_initiate_discovery(void *ignore)
 	dev_dbg(xpc_part, "discovery thread is exiting\n");
 
 	/* mark this thread as having exited */
-	up(&xpc_discovery_exited);
+	complete(&xpc_discovery_exited);
 	return 0;
 }
 
@@ -893,7 +894,7 @@ xpc_disconnect_wait(int ch_number)
 			continue;
 		}
 
-		(void) down(&ch->wdisconnect_sema);
+		wait_for_completion(&ch->wdisconnect_wait);
 
 		spin_lock_irqsave(&ch->lock, irq_flags);
 		DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED));
@@ -946,10 +947,10 @@ xpc_do_exit(enum xpc_retval reason)
 	free_irq(SGI_XPC_ACTIVATE, NULL);
 
 	/* 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 */
-	down(&xpc_hb_checker_exited);
+	wait_for_completion(&xpc_hb_checker_exited);
 
 
 	/* 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");
 
 		/* mark this new thread as a non-starter */
-		up(&xpc_discovery_exited);
+		complete(&xpc_discovery_exited);
 
 		xpc_do_exit(xpcUnloading);
 		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;
 	u64 busnum;
+	u64 segment;
 
 	ret_stuff.status = 0;
 	ret_stuff.v0 = 0;
 
+	segment = soft->pbi_buscommon.bs_persist_segment;
 	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;
 }
@@ -41,14 +43,16 @@ sal_pcibr_slot_disable(struct pcibus_info *soft, int device, int action,
 {
 	struct ia64_sal_retval ret_stuff;
 	u64 busnum;
+	u64 segment;
 
 	ret_stuff.status = 0;
 	ret_stuff.v0 = 0;
 
+	segment = soft->pbi_buscommon.bs_persist_segment;
 	busnum = soft->pbi_buscommon.bs_persist_busnum;
 	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;
 }

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

@@ -1276,62 +1276,6 @@ sys_sigstack:
 	call	do_sys_sigstack
 	 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
 	.globl	sys_sigreturn
 sys_sigreturn:

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

@@ -68,15 +68,14 @@ ret_trap_lockless_ipi:
 
 	ld	[%curptr + TI_FLAGS], %g2
 signal_p:
-	andcc	%g2, (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING), %g0
+	andcc	%g2, (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %g0
 	bz,a	ret_trap_continue
 	 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
-	 add	%sp, STACKFRAME_SZ, %o1	! pt_regs ptr
+	 add	%sp, STACKFRAME_SZ, %o0	! pt_regs ptr
 
 	/* Fall through. */
 	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);
 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):
  *
  * 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 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;
 	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
+	current->saved_sigmask = current->blocked;
 	siginitset(&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(&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
@@ -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
  * 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;
 	struct sparc_deliver_cookie cookie;
 	struct k_sigaction ka;
 	int signr;
+	sigset_t *oldset;
 
 	/*
 	 * 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.orig_i0 = orig_i0;
 
-	if (!oldset)
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else
 		oldset = &current->blocked;
 
 	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);
 		handle_signal(signr, &ka, &info, oldset,
 			      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 &&
 	    (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->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

+ 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_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 __memmove(void *, const void *, __kernel_size_t);
 extern void (*bzero_1page)(void *);
@@ -227,7 +226,6 @@ EXPORT_SYMBOL(kunmap_atomic);
 /* Solaris/SunOS binary compatibility */
 EXPORT_SYMBOL(svr4_setcontext);
 EXPORT_SYMBOL(svr4_getcontext);
-EXPORT_SYMBOL(_sigpause_common);
 
 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
 /*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
-/*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
 	/* Now the SunOS syscall table. */
@@ -181,6 +184,11 @@ sunos_sys_table:
 	.long sunos_nosys, sunos_nosys, sunos_nosys
 	.long 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
+/*290*/	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
 
 #endif

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

@@ -1416,7 +1416,6 @@ execve_merge:
 	 add		%sp, PTREGS_OFF, %o0
 
 	.globl	sys_pipe, sys_sigpause, sys_nis_syscall
-	.globl	sys_sigsuspend, sys_rt_sigsuspend
 	.globl	sys_rt_sigreturn
 	.globl	sys_ptrace
 	.globl	sys_sigaltstack
@@ -1440,28 +1439,6 @@ sys32_sigaltstack:
 		 mov		%i6, %o2
 #endif
 		.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
 	.globl	sys32_sigreturn
 sys32_sigreturn:

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

@@ -53,14 +53,13 @@ __handle_user_windows:
 		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
 		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
 		 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
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
@@ -96,15 +95,14 @@ __handle_perfctrs:
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
 		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
 		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
 		 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
 
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
@@ -129,11 +127,10 @@ __handle_userfpu:
 		ba,a,pt			%xcc, __handle_userfpu_continue
 
 __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
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
 		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
@@ -200,7 +197,7 @@ __handle_preemption_continue:
 		 andcc			%l1, %o0, %g0
 		andcc			%l0, _TIF_NEED_RESCHED, %g0
 		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
 __handle_signal_continue:
 		 ldub			[%g6 + TI_WSAVED], %o2

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

@@ -36,9 +36,6 @@
 
 #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. */
 asmlinkage void sparc64_set_context(struct pt_regs *regs)
 {
@@ -242,114 +239,29 @@ struct rt_signal_frame {
 /* Align macros */
 #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;
 	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
+	current->saved_sigmask = current->blocked;
 	siginitset(&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(&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
@@ -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
  * 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;
 	struct signal_deliver_cookie cookie;
 	struct k_sigaction ka;
 	int signr;
+	sigset_t *oldset;
 	
 	cookie.restart_syscall = restart_syscall;
 	cookie.orig_i0 = orig_i0;
 
-	if (!oldset)
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else
 		oldset = &current->blocked;
 
 #ifdef CONFIG_SPARC32_COMPAT
 	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	
 
@@ -635,7 +550,15 @@ static int do_signal(sigset_t *oldset, struct pt_regs * regs,
 		if (cookie.restart_syscall)
 			syscall_restart(orig_i0, regs, &ka.sa);
 		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 &&
 	    (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->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)
 {
-	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)

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

@@ -32,9 +32,6 @@
 
 #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):
  *
  * 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;
 }
 
-/*
- * 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)
 {
 	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
  * 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;
 	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);
 		handle_signal32(signr, &ka, &info, oldset,
 				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 &&
 	    (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
@@ -1397,7 +1306,14 @@ int do_signal32(sigset_t *oldset, struct pt_regs * regs,
 		regs->tpc -= 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 {

+ 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 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 *__memscan_zero(void *, 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. */
 EXPORT_SYMBOL(io_remap_pfn_range);
 
+#ifdef CONFIG_COMPAT
 /* Solaris/SunOS binary compatibility */
-EXPORT_SYMBOL(_sigpause_common);
 EXPORT_SYMBOL(verify_compat_iovec);
+#endif
 
 EXPORT_SYMBOL(dump_fpu);
 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
 	.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
-	.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
 	.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
@@ -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
 /*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
-/*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 */
 
@@ -142,7 +145,10 @@ sys_call_table:
 	.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
 	.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) || \
     defined(CONFIG_SOLARIS_EMUL_MODULE)
@@ -239,13 +245,20 @@ sunos_sys_table:
 /*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
+/*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
+/*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
+/*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
+/*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
 #endif

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

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

+ 58 - 71
drivers/serial/sn_console.c

@@ -6,7 +6,7 @@
  * 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
  * 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;
 		retval = misc_register(&misc);
 		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;
 		}
 		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;
 	struct sn_cons_port *port = &sal_console_port;
-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
 	static int stole_lock = 0;
-#endif
 
 	BUG_ON(!port->sc_is_asynch);
 
 	/* 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
 	 */
-	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 {
-				/* 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);
-
-			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);
 	}
 }

+ 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)
 			timeout = -1;	/* infinite */
 		else {
-			timeout = ROUND_UP(tv.tv_sec, 1000000/HZ);
+			timeout = ROUND_UP(tv.tv_usec, 1000000/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
 		   the number of seconds that can be expressed in
 		   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;
 	}
 

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

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

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

@@ -18,6 +18,7 @@
 
 #include <linux/cache.h>
 #include <linux/hardirq.h>
+#include <linux/mutex.h>
 #include <asm/sn/types.h>
 #include <asm/sn/bte.h>
 
@@ -359,7 +360,7 @@ typedef void (*xpc_notify_func)(enum xpc_retval reason, partid_t partid,
  * the channel.
  */
 struct xpc_registration {
-	struct semaphore sema;
+	struct mutex mutex;
 	xpc_channel_func func;		/* function to call */
 	void *key;			/* pointer to user's key */
 	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/sysctl.h>
 #include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/sn/bte.h>
@@ -335,8 +337,7 @@ struct xpc_openclose_args {
  * and consumed by the intended recipient.
  */
 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 */
 	xpc_notify_func func;		/* user's notify function */
@@ -465,8 +466,8 @@ struct xpc_channel {
 	xpc_channel_func func;		/* user's channel function */
 	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 */
 					/* opening or closing of channel */

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

@@ -18,6 +18,10 @@
 #include <asm/smp.h>
 
 #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'
  */

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

@@ -164,6 +164,7 @@ enum prom_input_device {
 	PROMDEV_IKBD,			/* input from keyboard */
 	PROMDEV_ITTYA,			/* input from ttya */
 	PROMDEV_ITTYB,			/* input from ttyb */
+	PROMDEV_IRSC,			/* input from rsc */
 	PROMDEV_I_UNK,
 };
 
@@ -175,6 +176,7 @@ enum prom_output_device {
 	PROMDEV_OSCREEN,		/* to screen */
 	PROMDEV_OTTYA,			/* to ttya */
 	PROMDEV_OTTYB,			/* to ttyb */
+	PROMDEV_ORSC,			/* to rsc */
 	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
  */
 #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_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
 					 * this quantum (SMP) */
 #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 */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
-#define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
+#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #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_request_key	282
 #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
- *          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) \
@@ -458,6 +473,7 @@ return -1; \
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #endif
 
 #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
  */
 #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_NEED_RESCHED	3	/* rescheduling necessary */
 #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_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
-#define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #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_SECCOMP		(1<<TIF_SECCOMP)
 #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_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
 #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))
 
 #endif /* __KERNEL__ */

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

@@ -302,11 +302,26 @@
 #define __NR_add_key		281
 #define __NR_request_key	282
 #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
- *          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) \
@@ -501,6 +516,8 @@ asmlinkage long sys_rt_sigaction(int sig,
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 #endif
 
 /*

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

@@ -19,7 +19,7 @@ struct xt_get_revision
 /* For standard target */
 #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. */
 #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,
 				 struct sctp_association *asoc,
 				 struct sctp_transport *t);
+void sctp_backlog_migrate(struct sctp_association *assoc,
+			  struct sock *oldsk, struct sock *newsk);
 
 /*
  *  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.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
 	 * powers of two to facilitate integer operations.
@@ -140,12 +140,18 @@ extern struct sctp_globals {
 	/* Max.Burst		    - 4 */
 	int max_burst;
 
-	/* Valid.Cookie.Life	    - 60  seconds  */
-	int valid_cookie_life;
-
 	/* Whether Cookie Preservative is enabled(1) or not(0) */
 	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
 	 * Path.Max.Retrans	    - 5	 attempts (per destination address)
 	 * Max.Init.Retransmits	    - 8	 attempts
@@ -168,12 +174,6 @@ extern struct sctp_globals {
 	 */
 	int rcvbuf_policy;
 
-	/* Delayed SACK timeout  200ms default*/
-	int sack_timeout;
-
-	/* HB.interval		    - 30 seconds  */
-	int hb_interval;
-
 	/* The following variables are implementation specific.	 */
 
 	/* 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. */
 struct sctp_signed_cookie {
 	__u8 signature[SCTP_SECRET_SIZE];
+	__u32 __pad;		/* force sctp_cookie alignment to 64 bits */
 	struct sctp_cookie c;
-};
+} __attribute__((packed));
 
 /* This is another convenience type to allocate memory for address
  * 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.	 */
 
 	/* RTO	       : The current retransmission timeout value.  */
-	__u32 rto;
+	unsigned long rto;
 
 	/* RTTVAR      : The current RTT variation.  */
 	__u32 rttvar;
@@ -877,22 +878,10 @@ struct sctp_transport {
 	/* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
 	 * 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 */
-	__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
 	 * transport?  We use this to pick new active and retran paths.
@@ -904,6 +893,18 @@ struct sctp_transport {
 	 */
 	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. */
 	int init_sent_count;
 
@@ -1249,6 +1250,14 @@ struct sctp_endpoint {
 	int last_key;
 	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.	*/
 	__u32 sndbuf_policy;
 
@@ -1499,9 +1508,9 @@ struct sctp_association {
 	 * These values will be initialized by system defaults, but can
 	 * 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.  */
 	int max_burst;
@@ -1519,13 +1528,13 @@ struct sctp_association {
 	__u16 init_retries;
 
 	/* 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
 	 * the destination address every heartbeat interval. This value
 	 * will be inherited by all new transports.
 	 */
-	__u32 hbinterval;
+	unsigned long hbinterval;
 
 	/* This is the max_retrans value for new transports in the
 	 * association.
@@ -1537,13 +1546,14 @@ struct sctp_association {
 	 */
 	__u32 pathmtu;
 
-	/* SACK delay timeout */
-	__u32 sackdelay;
-
 	/* Flags controling Heartbeat, SACK delay, and Path MTU Discovery. */
 	__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];
 
 	/* Transport to which SHUTDOWN chunk was last sent.  */
@@ -1648,7 +1658,10 @@ struct sctp_association {
 	/* How many duplicated TSNs have we seen?  */
 	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;
 
 	/* 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);
 
+	/* 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))
 		sk_add_backlog(sk, skb);
 	else
 		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);
-	if (asoc)
-		sctp_association_put(asoc);
-	else
-		sctp_endpoint_put(ep);
 	sock_put(sk);
+
 	return ret;
 
 discard_it:
@@ -296,12 +302,50 @@ discard_release:
 int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 {
 	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;
 }
 
+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. */
 void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
 			   struct sctp_transport *t, __u32 pmtu)
@@ -544,10 +588,16 @@ int sctp_rcv_ootb(struct sk_buff *skb)
 	sctp_errhdr_t *err;
 
 	ch = (sctp_chunkhdr_t *) skb->data;
-	ch_end = ((__u8 *) ch) + WORD_ROUND(ntohs(ch->length));
 
 	/* 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
 		 * 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_end = ((__u8 *) ch) + WORD_ROUND(ntohs(ch->length));
-	}
+	} while (ch_end < skb->tail);
 
 	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,
 	 * free it as well.
 	 */
-	if (queue->in_progress)
+	if (queue->in_progress) {
 		sctp_chunk_free(queue->in_progress);
+		queue->in_progress = NULL;
+	}
 
 	if (queue->malloced) {
 		/* 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)
 {
-	if (*pos > sctp_ep_hashsize)
+	if (*pos >= sctp_ep_hashsize)
 		return NULL;
 
 	if (*pos < 0)
@@ -185,8 +185,6 @@ static void * sctp_eps_seq_start(struct seq_file *seq, loff_t *pos)
 	if (*pos == 0)
 		seq_printf(seq, " ENDPT     SOCK   STY SST HBKT LPORT   UID INODE LADDRS\n");
 
-	++*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)
 {
-	if (*pos > sctp_ep_hashsize)
+	if (++*pos >= sctp_ep_hashsize)
 		return NULL;
 
-	++*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_endpoint *ep;
 	struct sock *sk;
-	int    hash = *(int *)v;
+	int    hash = *(loff_t *)v;
 
-	if (hash > sctp_ep_hashsize)
+	if (hash >= sctp_ep_hashsize)
 		return -ENOMEM;
 
-	head = &sctp_ep_hashtable[hash-1];
+	head = &sctp_ep_hashtable[hash];
 	sctp_local_bh_disable();
 	read_lock(&head->lock);
 	for (epb = head->chain; epb; epb = epb->next) {
 		ep = sctp_ep(epb);
 		sk = epb->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,
 			   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)
 {
-	if (*pos > sctp_assoc_hashsize)
+	if (*pos >= sctp_assoc_hashsize)
 		return NULL;
 
 	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 "
 				"RPORT LADDRS <-> RADDRS\n");
 
-	++*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)
 {
-	if (*pos > sctp_assoc_hashsize)
+	if (++*pos >= sctp_assoc_hashsize)
 		return NULL;
 
-	++*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_association *assoc;
 	struct sock *sk;
-	int    hash = *(int *)v;
+	int    hash = *(loff_t *)v;
 
-	if (hash > sctp_assoc_hashsize)
+	if (hash >= sctp_assoc_hashsize)
 		return -ENOMEM;
 
-	head = &sctp_assoc_hashtable[hash-1];
+	head = &sctp_assoc_hashtable[hash];
 	sctp_local_bh_disable();
 	read_lock(&head->lock);
 	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,
 			   "%8p %8p %-3d %-3d %-2d %-4d %4d %8d %8d %7d %5lu %-5d %5d ",
 			   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),
 			   assoc->sndbuf_used,
 			   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;
 	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)
 		+ 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_cookie *bear_cookie;
 	int headersize, bodysize, fixed_size;
-	__u8 digest[SCTP_SIGNATURE_SIZE];
+	__u8 *digest = ep->digest;
 	struct scatterlist sg;
 	unsigned int keylen, len;
 	char *key;
@@ -1362,7 +1367,12 @@ struct sctp_association *sctp_unpack_cookie(
 	struct sk_buff *skb = chunk->skb;
 	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;
 	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"
 					" init_err_counter: %d"
 					" cycle: %d"
-					" timeout: %d\n",
+					" timeout: %ld\n",
 					asoc->init_err_counter,
 					asoc->init_cycle,
 					asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]);
@@ -1328,7 +1328,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
 			SCTP_DEBUG_PRINTK(
 				"T1 COOKIE Timeout adjustment"
 				" init_err_counter: %d"
-				" timeout: %d\n",
+				" timeout: %ld\n",
 				asoc->init_err_counter,
 				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;
 
 		ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));
+		if (ch_end > skb->tail)
+			break;
 
 		if (SCTP_CID_SHUTDOWN_ACK == ch->type)
 			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->pathmaxrxt  = sctp_max_retrans_path;
 	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 |
 	                  SPP_PMTUD_ENABLE |
 	                  SPP_SACKDELAY_ENABLE;
@@ -5602,8 +5602,12 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
 	 */
 	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. */
 	sctp_assoc_migrate(assoc, newsk);
+	spin_unlock_bh(&oldsk->sk_lock.slock);
 
 	/* If the association on the newsk is already closed before accept()
 	 * 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,
 		.procname	= "cookie_preserve_enable",
 		.data		= &sctp_cookie_preserve_enable,
-		.maxlen		= sizeof(long),
+		.maxlen		= sizeof(int),
 		.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,

+ 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;
 
 	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);
 }