Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
diff --git a/arch/sparc64/solaris/socket.c b/arch/sparc64/solaris/socket.c
index 0674058..d3a66ea 100644
--- a/arch/sparc64/solaris/socket.c
+++ b/arch/sparc64/solaris/socket.c
@@ -16,6 +16,7 @@
 #include <linux/net.h>
 #include <linux/compat.h>
 #include <net/compat.h>
+#include <net/sock.h>
 
 #include <asm/uaccess.h>
 #include <asm/string.h>
@@ -297,121 +298,165 @@
 {
 	struct socket *sock;
 	char address[MAX_SOCK_ADDR];
-	struct iovec iov[UIO_FASTIOV];
+	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
 	unsigned char ctl[sizeof(struct cmsghdr) + 20];
 	unsigned char *ctl_buf = ctl;
-	struct msghdr kern_msg;
-	int err, total_len;
+	struct msghdr msg_sys;
+	int err, ctl_len, iov_size, total_len;
 
-	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
-		return -EFAULT;
-	if(kern_msg.msg_iovlen > UIO_MAXIOV)
-		return -EINVAL;
-	err = verify_compat_iovec(&kern_msg, iov, address, VERIFY_READ);
-	if (err < 0)
+	err = -EFAULT;
+	if (msghdr_from_user32_to_kern(&msg_sys, user_msg))
 		goto out;
+
+	sock = sockfd_lookup(fd, &err);
+	if (!sock)
+		goto out;
+
+	/* do not move before msg_sys is valid */
+	err = -EMSGSIZE;
+	if (msg_sys.msg_iovlen > UIO_MAXIOV)
+		goto out_put;
+
+	/* Check whether to allocate the iovec area*/
+	err = -ENOMEM;
+	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
+	if (msg_sys.msg_iovlen > UIO_FASTIOV) {
+		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
+		if (!iov)
+			goto out_put;
+	}
+
+	err = verify_compat_iovec(&msg_sys, iov, address, VERIFY_READ);
+	if (err < 0)
+		goto out_freeiov;
 	total_len = err;
 
-	if(kern_msg.msg_controllen) {
-		struct sol_cmsghdr __user *ucmsg = kern_msg.msg_control;
+	err = -ENOBUFS;
+	if (msg_sys.msg_controllen > INT_MAX)
+		goto out_freeiov;
+
+	ctl_len = msg_sys.msg_controllen;
+	if (ctl_len) {
+		struct sol_cmsghdr __user *ucmsg = msg_sys.msg_control;
 		unsigned long *kcmsg;
 		compat_size_t cmlen;
 
-		if (kern_msg.msg_controllen <= sizeof(compat_size_t))
-			return -EINVAL;
+		err = -EINVAL;
+		if (ctl_len <= sizeof(compat_size_t))
+			goto out_freeiov;
 
-		if(kern_msg.msg_controllen > sizeof(ctl)) {
+		if (ctl_len > sizeof(ctl)) {
 			err = -ENOBUFS;
-			ctl_buf = kmalloc(kern_msg.msg_controllen, GFP_KERNEL);
-			if(!ctl_buf)
+			ctl_buf = kmalloc(ctl_len, GFP_KERNEL);
+			if (!ctl_buf)
 				goto out_freeiov;
 		}
 		__get_user(cmlen, &ucmsg->cmsg_len);
 		kcmsg = (unsigned long *) ctl_buf;
 		*kcmsg++ = (unsigned long)cmlen;
 		err = -EFAULT;
-		if(copy_from_user(kcmsg, &ucmsg->cmsg_level,
-				  kern_msg.msg_controllen - sizeof(compat_size_t)))
+		if (copy_from_user(kcmsg, &ucmsg->cmsg_level,
+				   ctl_len - sizeof(compat_size_t)))
 			goto out_freectl;
-		kern_msg.msg_control = ctl_buf;
+		msg_sys.msg_control = ctl_buf;
 	}
-	kern_msg.msg_flags = solaris_to_linux_msgflags(user_flags);
+	msg_sys.msg_flags = solaris_to_linux_msgflags(user_flags);
 
-	lock_kernel();
-	sock = sockfd_lookup(fd, &err);
-	if (sock != NULL) {
-		if (sock->file->f_flags & O_NONBLOCK)
-			kern_msg.msg_flags |= MSG_DONTWAIT;
-		err = sock_sendmsg(sock, &kern_msg, total_len);
-		sockfd_put(sock);
-	}
-	unlock_kernel();
+	if (sock->file->f_flags & O_NONBLOCK)
+		msg_sys.msg_flags |= MSG_DONTWAIT;
+	err = sock_sendmsg(sock, &msg_sys, total_len);
 
 out_freectl:
-	/* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
-	if(ctl_buf != ctl)
-		kfree(ctl_buf);
+	if (ctl_buf != ctl)    
+		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
 out_freeiov:
-	if(kern_msg.msg_iov != iov)
-		kfree(kern_msg.msg_iov);
-out:
+	if (iov != iovstack)
+		sock_kfree_s(sock->sk, iov, iov_size);
+out_put:
+	sockfd_put(sock);
+out:       
 	return err;
 }
 
 asmlinkage int solaris_recvmsg(int fd, struct sol_nmsghdr __user *user_msg, unsigned int user_flags)
 {
-	struct iovec iovstack[UIO_FASTIOV];
-	struct msghdr kern_msg;
-	char addr[MAX_SOCK_ADDR];
 	struct socket *sock;
+	struct iovec iovstack[UIO_FASTIOV];
 	struct iovec *iov = iovstack;
+	struct msghdr msg_sys;
+	unsigned long cmsg_ptr;
+	int err, iov_size, total_len, len;
+
+	/* kernel mode address */
+	char addr[MAX_SOCK_ADDR];
+
+	/* user mode address pointers */
 	struct sockaddr __user *uaddr;
 	int __user *uaddr_len;
-	unsigned long cmsg_ptr;
-	int err, total_len, len = 0;
 
-	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
+	if (msghdr_from_user32_to_kern(&msg_sys, user_msg))
 		return -EFAULT;
-	if(kern_msg.msg_iovlen > UIO_MAXIOV)
-		return -EINVAL;
 
-	uaddr = kern_msg.msg_name;
-	uaddr_len = &user_msg->msg_namelen;
-	err = verify_compat_iovec(&kern_msg, iov, addr, VERIFY_WRITE);
-	if (err < 0)
+	sock = sockfd_lookup(fd, &err);
+	if (!sock)
 		goto out;
+
+	err = -EMSGSIZE;
+	if (msg_sys.msg_iovlen > UIO_MAXIOV)
+		goto out_put;
+
+	/* Check whether to allocate the iovec area*/
+	err = -ENOMEM;
+	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
+	if (msg_sys.msg_iovlen > UIO_FASTIOV) {
+		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
+		if (!iov)
+			goto out_put;
+	}
+
+	/*
+	 *	Save the user-mode address (verify_iovec will change the
+	 *	kernel msghdr to use the kernel address space)
+	 */
+	 
+	uaddr = (void __user *) msg_sys.msg_name;
+	uaddr_len = &user_msg->msg_namelen;
+	err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
+	if (err < 0)
+		goto out_freeiov;
 	total_len = err;
 
-	cmsg_ptr = (unsigned long) kern_msg.msg_control;
-	kern_msg.msg_flags = 0;
+	cmsg_ptr = (unsigned long) msg_sys.msg_control;
+	msg_sys.msg_flags = MSG_CMSG_COMPAT;
 
-	lock_kernel();
-	sock = sockfd_lookup(fd, &err);
-	if (sock != NULL) {
-		if (sock->file->f_flags & O_NONBLOCK)
-			user_flags |= MSG_DONTWAIT;
-		err = sock_recvmsg(sock, &kern_msg, total_len, user_flags);
-		if(err >= 0)
-			len = err;
-		sockfd_put(sock);
-	}
-	unlock_kernel();
+	if (sock->file->f_flags & O_NONBLOCK)
+		user_flags |= MSG_DONTWAIT;
 
-	if(uaddr != NULL && err >= 0)
-		err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
-	if(err >= 0) {
-		err = __put_user(linux_to_solaris_msgflags(kern_msg.msg_flags), &user_msg->msg_flags);
-		if(!err) {
-			/* XXX Convert cmsg back into userspace 32-bit format... */
-			err = __put_user((unsigned long)kern_msg.msg_control - cmsg_ptr,
-					 &user_msg->msg_controllen);
-		}
-	}
-
-	if(kern_msg.msg_iov != iov)
-		kfree(kern_msg.msg_iov);
-out:
+	err = sock_recvmsg(sock, &msg_sys, total_len, user_flags);
 	if(err < 0)
-		return err;
-	return len;
+		goto out_freeiov;
+
+	len = err;
+
+	if (uaddr != NULL) {
+		err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len);
+		if (err < 0)
+			goto out_freeiov;
+	}
+	err = __put_user(linux_to_solaris_msgflags(msg_sys.msg_flags), &user_msg->msg_flags);
+	if (err)
+		goto out_freeiov;
+	err = __put_user((unsigned long)msg_sys.msg_control - cmsg_ptr,
+			 &user_msg->msg_controllen);
+	if (err)
+		goto out_freeiov;
+	err = len;
+
+out_freeiov:
+	if (iov != iovstack)
+		sock_kfree_s(sock->sk, iov, iov_size);
+out_put:
+	sockfd_put(sock);
+out:
+	return err;
 }
diff --git a/drivers/char/watchdog/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c
index f975dab..a13395e 100644
--- a/drivers/char/watchdog/i8xx_tco.c
+++ b/drivers/char/watchdog/i8xx_tco.c
@@ -1,5 +1,5 @@
 /*
- *	i8xx_tco 0.07:	TCO timer driver for i8xx chipsets
+ *	i8xx_tco:	TCO timer driver for i8xx chipsets
  *
  *	(c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
  *				http://www.kernelconcepts.de
@@ -63,6 +63,9 @@
  *  20050128 Wim Van Sebroeck <wim@iguana.be>
  *	0.07 Added support for the ICH4-M, ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW
  *	     chipsets. Also added support for the "undocumented" ICH7 chipset.
+ *  20050807 Wim Van Sebroeck <wim@iguana.be>
+ *	0.08 Make sure that the watchdog is only "armed" when started.
+ *	     (Kernel Bug 4251)
  */
 
 /*
@@ -87,7 +90,7 @@
 #include "i8xx_tco.h"
 
 /* Module and version information */
-#define TCO_VERSION "0.07"
+#define TCO_VERSION "0.08"
 #define TCO_MODULE_NAME "i8xx TCO timer"
 #define TCO_DRIVER_NAME   TCO_MODULE_NAME ", v" TCO_VERSION
 #define PFX TCO_MODULE_NAME ": "
@@ -125,10 +128,18 @@
 	unsigned char val;
 
 	spin_lock(&tco_lock);
+
+	/* disable chipset's NO_REBOOT bit */
+	pci_read_config_byte (i8xx_tco_pci, 0xd4, &val);
+	val &= 0xfd;
+	pci_write_config_byte (i8xx_tco_pci, 0xd4, val);
+
+	/* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled to count */
 	val = inb (TCO1_CNT + 1);
 	val &= 0xf7;
 	outb (val, TCO1_CNT + 1);
 	val = inb (TCO1_CNT + 1);
+
 	spin_unlock(&tco_lock);
 
 	if (val & 0x08)
@@ -138,13 +149,20 @@
 
 static int tco_timer_stop (void)
 {
-	unsigned char val;
+	unsigned char val, val1;
 
 	spin_lock(&tco_lock);
+	/* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */
 	val = inb (TCO1_CNT + 1);
 	val |= 0x08;
 	outb (val, TCO1_CNT + 1);
 	val = inb (TCO1_CNT + 1);
+
+	/* Set the NO_REBOOT bit to prevent later reboots, just for sure */
+	pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1);
+	val1 |= 0x02;
+	pci_write_config_byte (i8xx_tco_pci, 0xd4, val1);
+
 	spin_unlock(&tco_lock);
 
 	if ((val & 0x08) == 0)
@@ -155,6 +173,7 @@
 static int tco_timer_keepalive (void)
 {
 	spin_lock(&tco_lock);
+	/* Reload the timer by writing to the TCO Timer Reload register */
 	outb (0x01, TCO1_RLD);
 	spin_unlock(&tco_lock);
 	return 0;
@@ -417,9 +436,8 @@
 			printk (KERN_ERR PFX "failed to get TCOBASE address\n");
 			return 0;
 		}
-		/*
-		 * Check chipset's NO_REBOOT bit
-		 */
+
+		/* Check chipset's NO_REBOOT bit */
 		pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1);
 		if (val1 & 0x02) {
 			val1 &= 0xfd;
@@ -430,6 +448,10 @@
 				return 0;	/* Cannot reset NO_REBOOT bit */
 			}
 		}
+		/* Disable reboots untill the watchdog starts */
+		val1 |= 0x02;
+		pci_write_config_byte (i8xx_tco_pci, 0xd4, val1);
+
 		/* Set the TCO_EN bit in SMI_EN register */
 		if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) {
 			printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
@@ -505,17 +527,10 @@
 
 static void __exit watchdog_cleanup (void)
 {
-	u8 val;
-
 	/* Stop the timer before we leave */
 	if (!nowayout)
 		tco_timer_stop ();
 
-	/* Set the NO_REBOOT bit to prevent later reboots, just for sure */
-	pci_read_config_byte (i8xx_tco_pci, 0xd4, &val);
-	val |= 0x02;
-	pci_write_config_byte (i8xx_tco_pci, 0xd4, val);
-
 	/* Deregister */
 	misc_deregister (&i8xx_tco_miscdev);
 	unregister_reboot_notifier(&i8xx_tco_notifier);
diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c
index 1c99536..fa503ed 100644
--- a/drivers/i2c/busses/i2c-sibyte.c
+++ b/drivers/i2c/busses/i2c-sibyte.c
@@ -23,8 +23,8 @@
 #include <asm/sibyte/sb1250_smbus.h>
 
 static struct i2c_algo_sibyte_data sibyte_board_data[2] = {
-	{ NULL, 0, (void *) (KSEG1+A_SMB_BASE(0)) },
-	{ NULL, 1, (void *) (KSEG1+A_SMB_BASE(1)) }
+	{ NULL, 0, (void *) (CKSEG1+A_SMB_BASE(0)) },
+	{ NULL, 1, (void *) (CKSEG1+A_SMB_BASE(1)) }
 };
 
 static struct i2c_adapter sibyte_board_adapter[2] = {
diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig
index 06e8eb1..43a942a 100644
--- a/drivers/message/i2o/Kconfig
+++ b/drivers/message/i2o/Kconfig
@@ -53,6 +53,9 @@
 	  To compile this support as a module, choose M here: the
 	  module will be called i2o_config.
 
+	  Note: If you want to use the new API you have to download the
+	  i2o_config patch from http://i2o.shadowconnect.com/
+
 config I2O_CONFIG_OLD_IOCTL
 	bool "Enable ioctls (OBSOLETE)"
 	depends on I2O_CONFIG
diff --git a/drivers/message/i2o/config-osm.c b/drivers/message/i2o/config-osm.c
index fe2e7af..af32ab4 100644
--- a/drivers/message/i2o/config-osm.c
+++ b/drivers/message/i2o/config-osm.c
@@ -30,503 +30,9 @@
 
 static struct i2o_driver i2o_config_driver;
 
-/* Special file operations for sysfs */
-struct fops_attribute {
-	struct bin_attribute bin;
-	struct file_operations fops;
-};
-
-/**
- *	sysfs_read_dummy
- */
-static ssize_t sysfs_read_dummy(struct kobject *kobj, char *buf, loff_t offset,
-				size_t count)
-{
-	return 0;
-};
-
-/**
- *	sysfs_write_dummy
- */
-static ssize_t sysfs_write_dummy(struct kobject *kobj, char *buf, loff_t offset,
-				 size_t count)
-{
-	return 0;
-};
-
-/**
- *	sysfs_create_fops_file - Creates attribute with special file operations
- *	@kobj: kobject which should contains the attribute
- *	@attr: attributes which should be used to create file
- *
- *	First creates attribute @attr in kobject @kobj. If it is the first time
- *	this function is called, merge old fops from sysfs with new one and
- *	write it back. Afterwords the new fops will be set for the created
- *	attribute.
- *
- *	Returns 0 on success or negative error code on failure.
- */
-static int sysfs_create_fops_file(struct kobject *kobj,
-				  struct fops_attribute *attr)
-{
-	struct file_operations tmp, *fops;
-	struct dentry *d;
-	struct qstr qstr;
-	int rc;
-
-	fops = &attr->fops;
-
-	if (fops->read)
-		attr->bin.read = sysfs_read_dummy;
-
-	if (fops->write)
-		attr->bin.write = sysfs_write_dummy;
-
-	if ((rc = sysfs_create_bin_file(kobj, &attr->bin)))
-		return rc;
-
-	qstr.name = attr->bin.attr.name;
-	qstr.len = strlen(qstr.name);
-	qstr.hash = full_name_hash(qstr.name, qstr.len);
-
-	if ((d = lookup_hash(&qstr, kobj->dentry))) {
-		if (!fops->owner) {
-			memcpy(&tmp, d->d_inode->i_fop, sizeof(tmp));
-			if (fops->read)
-				tmp.read = fops->read;
-			if (fops->write)
-				tmp.write = fops->write;
-			memcpy(fops, &tmp, sizeof(tmp));
-		}
-
-		d->d_inode->i_fop = fops;
-	} else
-		sysfs_remove_bin_file(kobj, &attr->bin);
-
-	return -ENOENT;
-};
-
-/**
- *	sysfs_remove_fops_file - Remove attribute with special file operations
- *	@kobj: kobject which contains the attribute
- *	@attr: attributes which are used to create file
- *
- *	Only wrapper arround sysfs_remove_bin_file()
- *
- *	Returns 0 on success or negative error code on failure.
- */
-static inline int sysfs_remove_fops_file(struct kobject *kobj,
-					 struct fops_attribute *attr)
-{
-	return sysfs_remove_bin_file(kobj, &attr->bin);
-};
-
-/**
- *	i2o_config_read_hrt - Returns the HRT of the controller
- *	@kob: kernel object handle
- *	@buf: buffer into which the HRT should be copied
- *	@off: file offset
- *	@count: number of bytes to read
- *
- *	Put @count bytes starting at @off into @buf from the HRT of the I2O
- *	controller corresponding to @kobj.
- *
- *	Returns number of bytes copied into buffer.
- */
-static ssize_t i2o_config_read_hrt(struct kobject *kobj, char *buf,
-				   loff_t offset, size_t count)
-{
-	struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
-	i2o_hrt *hrt = c->hrt.virt;
-
-	u32 size = (hrt->num_entries * hrt->entry_len + 2) * 4;
-
-	if (offset > size)
-		return 0;
-
-	if (offset + count > size)
-		count = size - offset;
-
-	memcpy(buf, (u8 *) hrt + offset, count);
-
-	return count;
-};
-
-/**
- *	i2o_config_read_lct - Returns the LCT of the controller
- *	@kob: kernel object handle
- *	@buf: buffer into which the LCT should be copied
- *	@off: file offset
- *	@count: number of bytes to read
- *
- *	Put @count bytes starting at @off into @buf from the LCT of the I2O
- *	controller corresponding to @kobj.
- *
- *	Returns number of bytes copied into buffer.
- */
-static ssize_t i2o_config_read_lct(struct kobject *kobj, char *buf,
-				   loff_t offset, size_t count)
-{
-	struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
-	u32 size = c->lct->table_size * 4;
-
-	if (offset > size)
-		return 0;
-
-	if (offset + count > size)
-		count = size - offset;
-
-	memcpy(buf, (u8 *) c->lct + offset, count);
-
-	return count;
-};
-
-#define I2O_CONFIG_SW_ATTR(_name,_mode,_type,_swid) \
-static ssize_t i2o_config_##_name##_read(struct file *file, char __user *buf, size_t count, loff_t * offset) { \
-	return i2o_config_sw_read(file, buf, count, offset, _type, _swid); \
-};\
-\
-static ssize_t i2o_config_##_name##_write(struct file *file, const char __user *buf, size_t count, loff_t * offset) { \
-	return i2o_config_sw_write(file, buf, count, offset, _type, _swid); \
-}; \
-\
-static struct fops_attribute i2o_config_attr_##_name = { \
-	.bin = { .attr = { .name = __stringify(_name), .mode = _mode, \
-			   .owner = THIS_MODULE }, \
-		 .size = 0, }, \
-	.fops = { .write = i2o_config_##_name##_write, \
-		  .read = i2o_config_##_name##_read} \
-};
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
-
-/**
- *	i2o_config_dpt_reagion - Converts type and id to flash region
- *	@swtype: type of software module reading
- *	@swid: id of software which should be read
- *
- *	Converts type and id from I2O spec to the matching region for DPT /
- *	Adaptec controllers.
- *
- *	Returns region which match type and id or -1 on error.
- */
-static u32 i2o_config_dpt_region(u8 swtype, u8 swid)
-{
-	switch (swtype) {
-	case I2O_SOFTWARE_MODULE_IRTOS:
-		/*
-		 * content: operation firmware
-		 * region size:
-		 *      0xbc000 for 2554, 3754, 2564, 3757
-		 *      0x170000 for 2865
-		 *      0x17c000 for 3966
-		 */
-		if (!swid)
-			return 0;
-
-		break;
-
-	case I2O_SOFTWARE_MODULE_IOP_PRIVATE:
-		/*
-		 * content: BIOS and SMOR
-		 * BIOS size: first 0x8000 bytes
-		 * region size:
-		 *      0x40000 for 2554, 3754, 2564, 3757
-		 *      0x80000 for 2865, 3966
-		 */
-		if (!swid)
-			return 1;
-
-		break;
-
-	case I2O_SOFTWARE_MODULE_IOP_CONFIG:
-		switch (swid) {
-		case 0:
-			/*
-			 * content: NVRAM defaults
-			 * region size: 0x2000 bytes
-			 */
-			return 2;
-		case 1:
-			/*
-			 * content: serial number
-			 * region size: 0x2000 bytes
-			 */
-			return 3;
-		}
-		break;
-	}
-
-	return -1;
-};
-
-#endif
-
-/**
- *	i2o_config_sw_read - Read a software module from controller
- *	@file: file pointer
- *	@buf: buffer into which the data should be copied
- *	@count: number of bytes to read
- *	@off: file offset
- *	@swtype: type of software module reading
- *	@swid: id of software which should be read
- *
- *	Transfers @count bytes at offset @offset from IOP into buffer using
- *	type @swtype and id @swid as described in I2O spec.
- *
- *	Returns number of bytes copied into buffer or error code on failure.
- */
-static ssize_t i2o_config_sw_read(struct file *file, char __user * buf,
-				  size_t count, loff_t * offset, u8 swtype,
-				  u32 swid)
-{
-	struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata;
-	struct kobject *kobj = sd->s_element;
-	struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
-	u32 m, function = I2O_CMD_SW_UPLOAD;
-	struct i2o_dma buffer;
-	struct i2o_message __iomem *msg;
-	u32 __iomem *mptr;
-	int rc, status;
-
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return -EBUSY;
-
-	mptr = &msg->body[3];
-
-	if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL))) {
-		i2o_msg_nop(c, m);
-		return rc;
-	}
-#ifdef CONFIG_I2O_EXT_ADAPTEC
-	if (c->adaptec) {
-		mptr = &msg->body[4];
-		function = I2O_CMD_PRIVATE;
-
-		writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]);
-
-		writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_READ,
-		       &msg->body[0]);
-		writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]);
-		writel(*offset, &msg->body[2]);
-		writel(count, &msg->body[3]);
-	} else
-#endif
-		writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
-
-	writel(0xD0000000 | count, mptr++);
-	writel(buffer.phys, mptr);
-
-	writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]);
-	writel(i2o_config_driver.context, &msg->u.head[2]);
-	writel(0, &msg->u.head[3]);
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
-	if (!c->adaptec)
-#endif
-	{
-		writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]);
-		writel(0, &msg->body[1]);
-		writel(swid, &msg->body[2]);
-	}
-
-	status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
-
-	if (status == I2O_POST_WAIT_OK) {
-		if (!(rc = copy_to_user(buf, buffer.virt, count))) {
-			rc = count;
-			*offset += count;
-		}
-	} else
-		rc = -EIO;
-
-	if (status != -ETIMEDOUT)
-		i2o_dma_free(&c->pdev->dev, &buffer);
-
-	return rc;
-};
-
-/**
- *	i2o_config_sw_write - Write a software module to controller
- *	@file: file pointer
- *	@buf: buffer into which the data should be copied
- *	@count: number of bytes to read
- *	@off: file offset
- *	@swtype: type of software module writing
- *	@swid: id of software which should be written
- *
- *	Transfers @count bytes at offset @offset from buffer to IOP using
- *	type @swtype and id @swid as described in I2O spec.
- *
- *	Returns number of bytes copied from buffer or error code on failure.
- */
-static ssize_t i2o_config_sw_write(struct file *file, const char __user * buf,
-				   size_t count, loff_t * offset, u8 swtype,
-				   u32 swid)
-{
-	struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata;
-	struct kobject *kobj = sd->s_element;
-	struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
-	u32 m, function = I2O_CMD_SW_DOWNLOAD;
-	struct i2o_dma buffer;
-	struct i2o_message __iomem *msg;
-	u32 __iomem *mptr;
-	int rc, status;
-
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return -EBUSY;
-
-	mptr = &msg->body[3];
-
-	if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL)))
-		goto nop_msg;
-
-	if ((rc = copy_from_user(buffer.virt, buf, count)))
-		goto free_buffer;
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
-	if (c->adaptec) {
-		mptr = &msg->body[4];
-		function = I2O_CMD_PRIVATE;
-
-		writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]);
-
-		writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_WRITE,
-		       &msg->body[0]);
-		writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]);
-		writel(*offset, &msg->body[2]);
-		writel(count, &msg->body[3]);
-	} else
-#endif
-		writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
-
-	writel(0xD4000000 | count, mptr++);
-	writel(buffer.phys, mptr);
-
-	writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]);
-	writel(i2o_config_driver.context, &msg->u.head[2]);
-	writel(0, &msg->u.head[3]);
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
-	if (!c->adaptec)
-#endif
-	{
-		writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]);
-		writel(0, &msg->body[1]);
-		writel(swid, &msg->body[2]);
-	}
-
-	status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
-
-	if (status != -ETIMEDOUT)
-		i2o_dma_free(&c->pdev->dev, &buffer);
-
-	if (status != I2O_POST_WAIT_OK)
-		return -EIO;
-
-	*offset += count;
-
-	return count;
-
-      free_buffer:
-	i2o_dma_free(&c->pdev->dev, &buffer);
-
-      nop_msg:
-	i2o_msg_nop(c, m);
-
-	return rc;
-};
-
-/* attribute for HRT in sysfs */
-static struct bin_attribute i2o_config_hrt_attr = {
-	.attr = {
-		 .name = "hrt",
-		 .mode = S_IRUGO,
-		 .owner = THIS_MODULE},
-	.size = 0,
-	.read = i2o_config_read_hrt
-};
-
-/* attribute for LCT in sysfs */
-static struct bin_attribute i2o_config_lct_attr = {
-	.attr = {
-		 .name = "lct",
-		 .mode = S_IRUGO,
-		 .owner = THIS_MODULE},
-	.size = 0,
-	.read = i2o_config_read_lct
-};
-
-/* IRTOS firmware access */
-I2O_CONFIG_SW_ATTR(irtos, S_IWRSR, I2O_SOFTWARE_MODULE_IRTOS, 0);
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
-
-/*
- * attribute for BIOS / SMOR, nvram and serial number access on DPT / Adaptec
- * controllers
- */
-I2O_CONFIG_SW_ATTR(bios, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_PRIVATE, 0);
-I2O_CONFIG_SW_ATTR(nvram, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 0);
-I2O_CONFIG_SW_ATTR(serial, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 1);
-
-#endif
-
-/**
- *	i2o_config_notify_controller_add - Notify of added controller
- *	@c: the controller which was added
- *
- *	If a I2O controller is added, we catch the notification to add sysfs
- *	entries.
- */
-static void i2o_config_notify_controller_add(struct i2o_controller *c)
-{
-	struct kobject *kobj = &c->exec->device.kobj;
-
-	sysfs_create_bin_file(kobj, &i2o_config_hrt_attr);
-	sysfs_create_bin_file(kobj, &i2o_config_lct_attr);
-
-	sysfs_create_fops_file(kobj, &i2o_config_attr_irtos);
-#ifdef CONFIG_I2O_EXT_ADAPTEC
-	if (c->adaptec) {
-		sysfs_create_fops_file(kobj, &i2o_config_attr_bios);
-		sysfs_create_fops_file(kobj, &i2o_config_attr_nvram);
-		sysfs_create_fops_file(kobj, &i2o_config_attr_serial);
-	}
-#endif
-};
-
-/**
- *	i2o_config_notify_controller_remove - Notify of removed controller
- *	@c: the controller which was removed
- *
- *	If a I2O controller is removed, we catch the notification to remove the
- *	sysfs entries.
- */
-static void i2o_config_notify_controller_remove(struct i2o_controller *c)
-{
-	struct kobject *kobj = &c->exec->device.kobj;
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
-	if (c->adaptec) {
-		sysfs_remove_fops_file(kobj, &i2o_config_attr_serial);
-		sysfs_remove_fops_file(kobj, &i2o_config_attr_nvram);
-		sysfs_remove_fops_file(kobj, &i2o_config_attr_bios);
-	}
-#endif
-	sysfs_remove_fops_file(kobj, &i2o_config_attr_irtos);
-
-	sysfs_remove_bin_file(kobj, &i2o_config_lct_attr);
-	sysfs_remove_bin_file(kobj, &i2o_config_hrt_attr);
-};
-
 /* Config OSM driver struct */
 static struct i2o_driver i2o_config_driver = {
 	.name = OSM_NAME,
-	.notify_controller_add = i2o_config_notify_controller_add,
-	.notify_controller_remove = i2o_config_notify_controller_remove
 };
 
 #ifdef CONFIG_I2O_CONFIG_OLD_IOCTL
diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h
index 5f6187b..73c8a08 100644
--- a/drivers/serial/cpm_uart/cpm_uart.h
+++ b/drivers/serial/cpm_uart/cpm_uart.h
@@ -40,13 +40,15 @@
 #define TX_NUM_FIFO	4
 #define TX_BUF_SIZE	32
 
+#define SCC_WAIT_CLOSING 100
+
 struct uart_cpm_port {
 	struct uart_port	port;
-	u16			rx_nrfifos;	
+	u16			rx_nrfifos;
 	u16			rx_fifosize;
-	u16			tx_nrfifos;	
+	u16			tx_nrfifos;
 	u16			tx_fifosize;
-	smc_t			*smcp;	
+	smc_t			*smcp;
 	smc_uart_t		*smcup;
 	scc_t			*sccp;
 	scc_uart_t		*sccup;
@@ -67,6 +69,8 @@
 	int			 bits;
 	/* Keep track of 'odd' SMC2 wirings */
 	int			is_portb;
+	/* wait on close if needed */
+	int 			wait_closing;
 };
 
 extern int cpm_uart_port_map[UART_NR];
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index 29db677..d639ac9 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -9,9 +9,10 @@
  *
  *  Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2)
  *              Pantelis Antoniou (panto@intracom.gr) (CPM1)
- * 
+ *
  *  Copyright (C) 2004 Freescale Semiconductor, Inc.
  *            (C) 2004 Intracom, S.A.
+ *            (C) 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@ru.mvista.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -70,8 +71,22 @@
 
 /**************************************************************/
 
+static inline unsigned long cpu2cpm_addr(void *addr)
+{
+	if ((unsigned long)addr >= CPM_ADDR)
+		return (unsigned long)addr;
+	return virt_to_bus(addr);
+}
+
+static inline void *cpm2cpu_addr(unsigned long addr)
+{
+	if (addr >= CPM_ADDR)
+		return (void *)addr;
+	return bus_to_virt(addr);
+}
+
 /*
- * Check, if transmit buffers are processed		
+ * Check, if transmit buffers are processed
 */
 static unsigned int cpm_uart_tx_empty(struct uart_port *port)
 {
@@ -143,15 +158,18 @@
 	}
 
 	if (cpm_uart_tx_pump(port) != 0) {
-		if (IS_SMC(pinfo))
+		if (IS_SMC(pinfo)) {
 			smcp->smc_smcm |= SMCM_TX;
-		else
+			smcp->smc_smcmr |= SMCMR_TEN;
+		} else {
 			sccp->scc_sccm |= UART_SCCM_TX;
+			pinfo->sccp->scc_gsmrl |= SCC_GSMRL_ENT;
+		}
 	}
 }
 
 /*
- * Stop receiver 
+ * Stop receiver
  */
 static void cpm_uart_stop_rx(struct uart_port *port)
 {
@@ -176,7 +194,7 @@
 }
 
 /*
- * Generate a break. 
+ * Generate a break.
  */
 static void cpm_uart_break_ctl(struct uart_port *port, int break_state)
 {
@@ -231,7 +249,7 @@
 		/* get number of characters, and check spce in flip-buffer */
 		i = bdp->cbd_datlen;
 
-		/* If we have not enough room in tty flip buffer, then we try 
+		/* If we have not enough room in tty flip buffer, then we try
 		 * later, which will be the next rx-interrupt or a timeout
 		 */
 		if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) {
@@ -243,7 +261,7 @@
 		}
 
 		/* get pointer */
-		cp = (unsigned char *)bus_to_virt(bdp->cbd_bufaddr);
+		cp = cpm2cpu_addr(bdp->cbd_bufaddr);
 
 		/* loop through the buffer */
 		while (i-- > 0) {
@@ -265,13 +283,14 @@
 		}		/* End while (i--) */
 
 		/* This BD is ready to be used again. Clear status. get next */
-		bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
+		bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID);
 		bdp->cbd_sc |= BD_SC_EMPTY;
 
 		if (bdp->cbd_sc & BD_SC_WRAP)
 			bdp = pinfo->rx_bd_base;
 		else
 			bdp++;
+
 	} /* End for (;;) */
 
 	/* Write back buffer pointer */
@@ -336,22 +355,22 @@
 
 	if (IS_SMC(pinfo)) {
 		events = smcp->smc_smce;
+		smcp->smc_smce = events;
 		if (events & SMCM_BRKE)
 			uart_handle_break(port);
 		if (events & SMCM_RX)
 			cpm_uart_int_rx(port, regs);
 		if (events & SMCM_TX)
 			cpm_uart_int_tx(port, regs);
-		smcp->smc_smce = events;
 	} else {
 		events = sccp->scc_scce;
+		sccp->scc_scce = events;
 		if (events & UART_SCCM_BRKE)
 			uart_handle_break(port);
 		if (events & UART_SCCM_RX)
 			cpm_uart_int_rx(port, regs);
 		if (events & UART_SCCM_TX)
 			cpm_uart_int_tx(port, regs);
-		sccp->scc_scce = events;
 	}
 	return (events) ? IRQ_HANDLED : IRQ_NONE;
 }
@@ -360,6 +379,7 @@
 {
 	int retval;
 	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+	int line = pinfo - cpm_uart_ports;
 
 	pr_debug("CPM uart[%d]:startup\n", port->line);
 
@@ -376,9 +396,19 @@
 		pinfo->sccp->scc_sccm |= UART_SCCM_RX;
 	}
 
+	if (!(pinfo->flags & FLAG_CONSOLE))
+		cpm_line_cr_cmd(line,CPM_CR_INIT_TRX);
 	return 0;
 }
 
+inline void cpm_uart_wait_until_send(struct uart_cpm_port *pinfo)
+{
+	unsigned long target_jiffies = jiffies + pinfo->wait_closing;
+
+	while (!time_after(jiffies, target_jiffies))
+   		schedule();
+}
+
 /*
  * Shutdown the uart
  */
@@ -394,6 +424,12 @@
 
 	/* If the port is not the console, disable Rx and Tx. */
 	if (!(pinfo->flags & FLAG_CONSOLE)) {
+		/* Wait for all the BDs marked sent */
+		while(!cpm_uart_tx_empty(port))
+			schedule_timeout(2);
+		if(pinfo->wait_closing)
+			cpm_uart_wait_until_send(pinfo);
+
 		/* Stop uarts */
 		if (IS_SMC(pinfo)) {
 			volatile smc_t *smcp = pinfo->smcp;
@@ -502,7 +538,7 @@
 	 */
 	if ((termios->c_cflag & CREAD) == 0)
 		port->read_status_mask &= ~BD_SC_EMPTY;
-	
+
 	spin_lock_irqsave(&port->lock, flags);
 
 	/* Start bit has not been added (so don't, because we would just
@@ -569,7 +605,8 @@
 		/* Pick next descriptor and fill from buffer */
 		bdp = pinfo->tx_cur;
 
-		p = bus_to_virt(bdp->cbd_bufaddr);
+		p = cpm2cpu_addr(bdp->cbd_bufaddr);
+
 		*p++ = xmit->buf[xmit->tail];
 		bdp->cbd_datlen = 1;
 		bdp->cbd_sc |= BD_SC_READY;
@@ -595,7 +632,7 @@
 
 	while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) {
 		count = 0;
-		p = bus_to_virt(bdp->cbd_bufaddr);
+		p = cpm2cpu_addr(bdp->cbd_bufaddr);
 		while (count < pinfo->tx_fifosize) {
 			*p++ = xmit->buf[xmit->tail];
 			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
@@ -606,6 +643,7 @@
 		}
 		bdp->cbd_datlen = count;
 		bdp->cbd_sc |= BD_SC_READY;
+		__asm__("eieio");
 		/* Get next BD. */
 		if (bdp->cbd_sc & BD_SC_WRAP)
 			bdp = pinfo->tx_bd_base;
@@ -643,12 +681,12 @@
 	mem_addr = pinfo->mem_addr;
 	bdp = pinfo->rx_cur = pinfo->rx_bd_base;
 	for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) {
-		bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+		bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
 		bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
 		mem_addr += pinfo->rx_fifosize;
 	}
-	
-	bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+
+	bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
 	bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
 
 	/* Set the physical address of the host memory
@@ -658,12 +696,12 @@
 	mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize);
 	bdp = pinfo->tx_cur = pinfo->tx_bd_base;
 	for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) {
-		bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+		bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
 		bdp->cbd_sc = BD_SC_INTRPT;
 		mem_addr += pinfo->tx_fifosize;
 	}
-	
-	bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+
+	bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
 	bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT;
 }
 
@@ -763,6 +801,8 @@
 	/* Using idle charater time requires some additional tuning.  */
 	up->smc_mrblr = pinfo->rx_fifosize;
 	up->smc_maxidl = pinfo->rx_fifosize;
+	up->smc_brklen = 0;
+	up->smc_brkec = 0;
 	up->smc_brkcr = 1;
 
 	cpm_line_cr_cmd(line, CPM_CR_INIT_TRX);
@@ -796,7 +836,7 @@
 	/*
 	 * Setup any port IO, connect any baud rate generators,
 	 * etc.  This is expected to be handled by board
-	 * dependant code 
+	 * dependant code
 	 */
 	if (pinfo->set_lineif)
 		pinfo->set_lineif(pinfo);
@@ -815,6 +855,10 @@
 		return ret;
 
 	cpm_uart_initbd(pinfo);
+	if (IS_SMC(pinfo))
+		cpm_uart_init_smc(pinfo);
+	else
+		cpm_uart_init_scc(pinfo);
 
 	return 0;
 }
@@ -869,7 +913,7 @@
 		.flags = FLAG_SMC,
 		.tx_nrfifos = TX_NUM_FIFO,
 		.tx_fifosize = TX_BUF_SIZE,
-		.rx_nrfifos = RX_NUM_FIFO, 
+		.rx_nrfifos = RX_NUM_FIFO,
 		.rx_fifosize = RX_BUF_SIZE,
 		.set_lineif = smc1_lineif,
 	},
@@ -883,7 +927,7 @@
 		.flags = FLAG_SMC,
 		.tx_nrfifos = TX_NUM_FIFO,
 		.tx_fifosize = TX_BUF_SIZE,
-		.rx_nrfifos = RX_NUM_FIFO, 
+		.rx_nrfifos = RX_NUM_FIFO,
 		.rx_fifosize = RX_BUF_SIZE,
 		.set_lineif = smc2_lineif,
 #ifdef CONFIG_SERIAL_CPM_ALT_SMC2
@@ -899,9 +943,10 @@
 		},
 		.tx_nrfifos = TX_NUM_FIFO,
 		.tx_fifosize = TX_BUF_SIZE,
-		.rx_nrfifos = RX_NUM_FIFO, 
+		.rx_nrfifos = RX_NUM_FIFO,
 		.rx_fifosize = RX_BUF_SIZE,
 		.set_lineif = scc1_lineif,
+		.wait_closing = SCC_WAIT_CLOSING,
 	},
 	[UART_SCC2] = {
 		.port = {
@@ -912,9 +957,10 @@
 		},
 		.tx_nrfifos = TX_NUM_FIFO,
 		.tx_fifosize = TX_BUF_SIZE,
-		.rx_nrfifos = RX_NUM_FIFO, 
+		.rx_nrfifos = RX_NUM_FIFO,
 		.rx_fifosize = RX_BUF_SIZE,
 		.set_lineif = scc2_lineif,
+		.wait_closing = SCC_WAIT_CLOSING,
 	},
 	[UART_SCC3] = {
 		.port = {
@@ -925,9 +971,10 @@
 		},
 		.tx_nrfifos = TX_NUM_FIFO,
 		.tx_fifosize = TX_BUF_SIZE,
-		.rx_nrfifos = RX_NUM_FIFO, 
+		.rx_nrfifos = RX_NUM_FIFO,
 		.rx_fifosize = RX_BUF_SIZE,
 		.set_lineif = scc3_lineif,
+		.wait_closing = SCC_WAIT_CLOSING,
 	},
 	[UART_SCC4] = {
 		.port = {
@@ -938,9 +985,10 @@
 		},
 		.tx_nrfifos = TX_NUM_FIFO,
 		.tx_fifosize = TX_BUF_SIZE,
-		.rx_nrfifos = RX_NUM_FIFO, 
+		.rx_nrfifos = RX_NUM_FIFO,
 		.rx_fifosize = RX_BUF_SIZE,
 		.set_lineif = scc4_lineif,
+		.wait_closing = SCC_WAIT_CLOSING,
 	},
 };
 
@@ -983,11 +1031,8 @@
 		 * If the buffer address is in the CPM DPRAM, don't
 		 * convert it.
 		 */
-		if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR)
-			cp = (unsigned char *) (bdp->cbd_bufaddr);
-		else
-			cp = bus_to_virt(bdp->cbd_bufaddr);
-		
+		cp = cpm2cpu_addr(bdp->cbd_bufaddr);
+
 		*cp = *s;
 
 		bdp->cbd_datlen = 1;
@@ -1003,10 +1048,7 @@
 			while ((bdp->cbd_sc & BD_SC_READY) != 0)
 				;
 
-			if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR)
-				cp = (unsigned char *) (bdp->cbd_bufaddr);
-			else
-				cp = bus_to_virt(bdp->cbd_bufaddr);
+			cp = cpm2cpu_addr(bdp->cbd_bufaddr);
 
 			*cp = 13;
 			bdp->cbd_datlen = 1;
@@ -1045,7 +1087,7 @@
 	port =
 	    (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]];
 	pinfo = (struct uart_cpm_port *)port;
-	
+
 	pinfo->flags |= FLAG_CONSOLE;
 
 	if (options) {
@@ -1062,7 +1104,7 @@
 	/*
 	 * Setup any port IO, connect any baud rate generators,
 	 * etc.  This is expected to be handled by board
-	 * dependant code 
+	 * dependant code
 	 */
 	if (pinfo->set_lineif)
 		pinfo->set_lineif(pinfo);
@@ -1092,14 +1134,14 @@
 	return 0;
 }
 
-extern struct uart_driver cpm_reg;
+static struct uart_driver cpm_reg;
 static struct console cpm_scc_uart_console = {
-	.name		"ttyCPM",
-	.write		cpm_uart_console_write,
-	.device		uart_console_device,
-	.setup		cpm_uart_console_setup,
-	.flags		CON_PRINTBUFFER,
-	.index		-1,
+	.name		= "ttyCPM",
+	.write		= cpm_uart_console_write,
+	.device		= uart_console_device,
+	.setup		= cpm_uart_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
 	.data		= &cpm_reg,
 };
 
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
index 8efbd6d..4b0786e 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
@@ -5,7 +5,7 @@
  *
  *  Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2)
  *              Pantelis Antoniou (panto@intracom.gr) (CPM1)
- * 
+ *
  *  Copyright (C) 2004 Freescale Semiconductor, Inc.
  *            (C) 2004 Intracom, S.A.
  *
@@ -82,6 +82,17 @@
 void smc1_lineif(struct uart_cpm_port *pinfo)
 {
 	volatile cpm8xx_t *cp = cpmp;
+
+	(void)cp;	/* fix warning */
+#if defined (CONFIG_MPC885ADS)
+	/* Enable SMC1 transceivers */
+	{
+		cp->cp_pepar |= 0x000000c0;
+		cp->cp_pedir &= ~0x000000c0;
+		cp->cp_peso &= ~0x00000040;
+		cp->cp_peso |= 0x00000080;
+	}
+#elif defined (CONFIG_MPC86XADS)
 	unsigned int iobits = 0x000000c0;
 
 	if (!pinfo->is_portb) {
@@ -93,41 +104,33 @@
 		((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits;
 		((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits;
 	}
-
-#ifdef CONFIG_MPC885ADS
-	/* Enable SMC1 transceivers */
-	{
-		volatile uint __iomem *bcsr1 = ioremap(BCSR1, 4);
-		uint tmp;
-
-		tmp = in_be32(bcsr1);
-		tmp &= ~BCSR1_RS232EN_1;
-		out_be32(bcsr1, tmp);
-		iounmap(bcsr1);
-	}
 #endif
-
 	pinfo->brg = 1;
 }
 
 void smc2_lineif(struct uart_cpm_port *pinfo)
 {
-#ifdef CONFIG_MPC885ADS
 	volatile cpm8xx_t *cp = cpmp;
-	volatile uint __iomem *bcsr1;
-	uint tmp;
 
+	(void)cp;	/* fix warning */
+#if defined (CONFIG_MPC885ADS)
 	cp->cp_pepar |= 0x00000c00;
 	cp->cp_pedir &= ~0x00000c00;
 	cp->cp_peso &= ~0x00000400;
 	cp->cp_peso |= 0x00000800;
+#elif defined (CONFIG_MPC86XADS)
+	unsigned int iobits = 0x00000c00;
 
-	/* Enable SMC2 transceivers */
-	bcsr1 = ioremap(BCSR1, 4);
-	tmp = in_be32(bcsr1);
-	tmp &= ~BCSR1_RS232EN_2;
-	out_be32(bcsr1, tmp);
-	iounmap(bcsr1);
+	if (!pinfo->is_portb) {
+		cp->cp_pbpar |= iobits;
+		cp->cp_pbdir &= ~iobits;
+		cp->cp_pbodr &= ~iobits;
+	} else {
+		((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits;
+		((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits;
+		((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits;
+	}
+
 #endif
 
 	pinfo->brg = 2;
@@ -158,7 +161,7 @@
 }
 
 /*
- * Allocate DP-Ram and memory buffers. We need to allocate a transmit and 
+ * Allocate DP-Ram and memory buffers. We need to allocate a transmit and
  * receive buffer descriptors from dual port ram, and a character
  * buffer area from host mem. If we are allocating for the console we need
  * to do it from bootmem
@@ -185,6 +188,8 @@
 	memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
 	    L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
 	if (is_con) {
+		/* was hostalloc but changed cause it blows away the */
+		/* large tlb mapping when pinning the kernel area    */
 		mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8));
 		dma_addr = 0;
 	} else
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 805fb90..21a4e3b 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -398,21 +398,31 @@
  * to continue to serve a useful existence.  Next time it's released,
  * we will get notified again, if it still has 'notify_on_release' set.
  *
- * Note final arg to call_usermodehelper() is 0 - that means
- * don't wait.  Since we are holding the global cpuset_sem here,
- * and we are asking another thread (started from keventd) to rmdir a
- * cpuset, we can't wait - or we'd deadlock with the removing thread
- * on cpuset_sem.
+ * The final arg to call_usermodehelper() is 0, which means don't
+ * wait.  The separate /sbin/cpuset_release_agent task is forked by
+ * call_usermodehelper(), then control in this thread returns here,
+ * without waiting for the release agent task.  We don't bother to
+ * wait because the caller of this routine has no use for the exit
+ * status of the /sbin/cpuset_release_agent task, so no sense holding
+ * our caller up for that.
+ *
+ * The simple act of forking that task might require more memory,
+ * which might need cpuset_sem.  So this routine must be called while
+ * cpuset_sem is not held, to avoid a possible deadlock.  See also
+ * comments for check_for_release(), below.
  */
 
-static int cpuset_release_agent(char *cpuset_str)
+static void cpuset_release_agent(const char *pathbuf)
 {
 	char *argv[3], *envp[3];
 	int i;
 
+	if (!pathbuf)
+		return;
+
 	i = 0;
 	argv[i++] = "/sbin/cpuset_release_agent";
-	argv[i++] = cpuset_str;
+	argv[i++] = (char *)pathbuf;
 	argv[i] = NULL;
 
 	i = 0;
@@ -421,17 +431,29 @@
 	envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
 	envp[i] = NULL;
 
-	return call_usermodehelper(argv[0], argv, envp, 0);
+	call_usermodehelper(argv[0], argv, envp, 0);
+	kfree(pathbuf);
 }
 
 /*
  * Either cs->count of using tasks transitioned to zero, or the
  * cs->children list of child cpusets just became empty.  If this
  * cs is notify_on_release() and now both the user count is zero and
- * the list of children is empty, send notice to user land.
+ * the list of children is empty, prepare cpuset path in a kmalloc'd
+ * buffer, to be returned via ppathbuf, so that the caller can invoke
+ * cpuset_release_agent() with it later on, once cpuset_sem is dropped.
+ * Call here with cpuset_sem held.
+ *
+ * This check_for_release() routine is responsible for kmalloc'ing
+ * pathbuf.  The above cpuset_release_agent() is responsible for
+ * kfree'ing pathbuf.  The caller of these routines is responsible
+ * for providing a pathbuf pointer, initialized to NULL, then
+ * calling check_for_release() with cpuset_sem held and the address
+ * of the pathbuf pointer, then dropping cpuset_sem, then calling
+ * cpuset_release_agent() with pathbuf, as set by check_for_release().
  */
 
-static void check_for_release(struct cpuset *cs)
+static void check_for_release(struct cpuset *cs, char **ppathbuf)
 {
 	if (notify_on_release(cs) && atomic_read(&cs->count) == 0 &&
 	    list_empty(&cs->children)) {
@@ -441,10 +463,9 @@
 		if (!buf)
 			return;
 		if (cpuset_path(cs, buf, PAGE_SIZE) < 0)
-			goto out;
-		cpuset_release_agent(buf);
-out:
-		kfree(buf);
+			kfree(buf);
+		else
+			*ppathbuf = buf;
 	}
 }
 
@@ -727,14 +748,14 @@
 	return 0;
 }
 
-static int attach_task(struct cpuset *cs, char *buf)
+static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf)
 {
 	pid_t pid;
 	struct task_struct *tsk;
 	struct cpuset *oldcs;
 	cpumask_t cpus;
 
-	if (sscanf(buf, "%d", &pid) != 1)
+	if (sscanf(pidbuf, "%d", &pid) != 1)
 		return -EIO;
 	if (cpus_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed))
 		return -ENOSPC;
@@ -777,7 +798,7 @@
 
 	put_task_struct(tsk);
 	if (atomic_dec_and_test(&oldcs->count))
-		check_for_release(oldcs);
+		check_for_release(oldcs, ppathbuf);
 	return 0;
 }
 
@@ -801,6 +822,7 @@
 	struct cftype *cft = __d_cft(file->f_dentry);
 	cpuset_filetype_t type = cft->private;
 	char *buffer;
+	char *pathbuf = NULL;
 	int retval = 0;
 
 	/* Crude upper limit on largest legitimate cpulist user might write. */
@@ -841,7 +863,7 @@
 		retval = update_flag(CS_NOTIFY_ON_RELEASE, cs, buffer);
 		break;
 	case FILE_TASKLIST:
-		retval = attach_task(cs, buffer);
+		retval = attach_task(cs, buffer, &pathbuf);
 		break;
 	default:
 		retval = -EINVAL;
@@ -852,6 +874,7 @@
 		retval = nbytes;
 out2:
 	up(&cpuset_sem);
+	cpuset_release_agent(pathbuf);
 out1:
 	kfree(buffer);
 	return retval;
@@ -1357,6 +1380,7 @@
 	struct cpuset *cs = dentry->d_fsdata;
 	struct dentry *d;
 	struct cpuset *parent;
+	char *pathbuf = NULL;
 
 	/* the vfs holds both inode->i_sem already */
 
@@ -1376,7 +1400,7 @@
 		update_cpu_domains(cs);
 	list_del(&cs->sibling);	/* delete my sibling from parent->children */
 	if (list_empty(&parent->children))
-		check_for_release(parent);
+		check_for_release(parent, &pathbuf);
 	spin_lock(&cs->dentry->d_lock);
 	d = dget(cs->dentry);
 	cs->dentry = NULL;
@@ -1384,6 +1408,7 @@
 	cpuset_d_remove_dir(d);
 	dput(d);
 	up(&cpuset_sem);
+	cpuset_release_agent(pathbuf);
 	return 0;
 }
 
@@ -1483,10 +1508,13 @@
 	task_unlock(tsk);
 
 	if (notify_on_release(cs)) {
+		char *pathbuf = NULL;
+
 		down(&cpuset_sem);
 		if (atomic_dec_and_test(&cs->count))
-			check_for_release(cs);
+			check_for_release(cs, &pathbuf);
 		up(&cpuset_sem);
+		cpuset_release_agent(pathbuf);
 	} else {
 		atomic_dec(&cs->count);
 	}
diff --git a/net/compat.c b/net/compat.c
index be5d936..d99ab96 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -91,20 +91,11 @@
 	} else
 		kern_msg->msg_name = NULL;
 
-	if(kern_msg->msg_iovlen > UIO_FASTIOV) {
-		kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
-				   GFP_KERNEL);
-		if(!kern_iov)
-			return -ENOMEM;
-	}
-
 	tot_len = iov_from_user_compat_to_kern(kern_iov,
 					  (struct compat_iovec __user *)kern_msg->msg_iov,
 					  kern_msg->msg_iovlen);
 	if(tot_len >= 0)
 		kern_msg->msg_iov = kern_iov;
-	else if(kern_msg->msg_iovlen > UIO_FASTIOV)
-		kfree(kern_iov);
 
 	return tot_len;
 }
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 56db8f1..d0c3120 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -586,7 +586,7 @@
 	}
 	if (skb->stamp.tv_sec == 0) {
 		skb->stamp.tv_sec = xtime.tv_sec; 
-		skb->stamp.tv_usec = xtime.tv_nsec * 1000; 
+		skb->stamp.tv_usec = xtime.tv_nsec / NSEC_PER_USEC; 
 		/* Don't enable netstamp, sunrpc doesn't 
 		   need that much accuracy */
 	}