From 7626e07b6a55de7d9fc59eb05f8f00b47a873cc0 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 9 Aug 2005 12:30:07 -0700 Subject: [PATCH] --- yaml --- r: 5739 b: refs/heads/master c: 218b29e0c3995ee15782de55ad1dd74cce1a728d h: refs/heads/master i: 5737: d4b7dd0fa2ad2365505e913d715bf7bf4694bb09 5735: fed97958ac6ea2e0ddd687e3c4fbae8ff3d3f306 v: v3 --- [refs] | 2 +- trunk/arch/sparc64/solaris/socket.c | 193 +++---- trunk/drivers/char/watchdog/i8xx_tco.c | 41 +- trunk/drivers/i2c/busses/i2c-sibyte.c | 4 +- trunk/drivers/message/i2o/Kconfig | 3 - trunk/drivers/message/i2o/config-osm.c | 494 ++++++++++++++++++ trunk/drivers/sbus/char/envctrl.c | 41 +- trunk/drivers/serial/cpm_uart/cpm_uart.h | 10 +- trunk/drivers/serial/cpm_uart/cpm_uart_core.c | 132 ++--- trunk/drivers/serial/cpm_uart/cpm_uart_cpm1.c | 53 +- trunk/kernel/cpuset.c | 68 +-- trunk/net/compat.c | 9 + trunk/net/sunrpc/svcsock.c | 2 +- 13 files changed, 696 insertions(+), 356 deletions(-) diff --git a/[refs] b/[refs] index dc3ca36d7376..c325c84fbd88 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 25f13053651569bd0c87927ff49d07d9225feadb +refs/heads/master: 218b29e0c3995ee15782de55ad1dd74cce1a728d diff --git a/trunk/arch/sparc64/solaris/socket.c b/trunk/arch/sparc64/solaris/socket.c index d3a66ea74a7f..06740582717e 100644 --- a/trunk/arch/sparc64/solaris/socket.c +++ b/trunk/arch/sparc64/solaris/socket.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -298,165 +297,121 @@ asmlinkage int solaris_sendmsg(int fd, struct sol_nmsghdr __user *user_msg, unsi { struct socket *sock; char address[MAX_SOCK_ADDR]; - struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; + struct iovec iov[UIO_FASTIOV]; unsigned char ctl[sizeof(struct cmsghdr) + 20]; unsigned char *ctl_buf = ctl; - struct msghdr msg_sys; - int err, ctl_len, iov_size, total_len; + struct msghdr kern_msg; + int err, total_len; - 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(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) - goto out_freeiov; + goto out; total_len = err; - 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; + if(kern_msg.msg_controllen) { + struct sol_cmsghdr __user *ucmsg = kern_msg.msg_control; unsigned long *kcmsg; compat_size_t cmlen; - err = -EINVAL; - if (ctl_len <= sizeof(compat_size_t)) - goto out_freeiov; + if (kern_msg.msg_controllen <= sizeof(compat_size_t)) + return -EINVAL; - if (ctl_len > sizeof(ctl)) { + if(kern_msg.msg_controllen > sizeof(ctl)) { err = -ENOBUFS; - ctl_buf = kmalloc(ctl_len, GFP_KERNEL); - if (!ctl_buf) + ctl_buf = kmalloc(kern_msg.msg_controllen, 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, - ctl_len - sizeof(compat_size_t))) + if(copy_from_user(kcmsg, &ucmsg->cmsg_level, + kern_msg.msg_controllen - sizeof(compat_size_t))) goto out_freectl; - msg_sys.msg_control = ctl_buf; + kern_msg.msg_control = ctl_buf; } - msg_sys.msg_flags = solaris_to_linux_msgflags(user_flags); + kern_msg.msg_flags = solaris_to_linux_msgflags(user_flags); - if (sock->file->f_flags & O_NONBLOCK) - msg_sys.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &msg_sys, total_len); + 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(); out_freectl: - if (ctl_buf != ctl) - sock_kfree_s(sock->sk, ctl_buf, ctl_len); + /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */ + if(ctl_buf != ctl) + kfree(ctl_buf); out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); -out: + if(kern_msg.msg_iov != iov) + kfree(kern_msg.msg_iov); +out: return err; } asmlinkage int solaris_recvmsg(int fd, struct sol_nmsghdr __user *user_msg, unsigned int user_flags) { - 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 */ + struct msghdr kern_msg; char addr[MAX_SOCK_ADDR]; - - /* user mode address pointers */ + struct socket *sock; + struct iovec *iov = iovstack; struct sockaddr __user *uaddr; int __user *uaddr_len; + unsigned long cmsg_ptr; + int err, total_len, len = 0; - if (msghdr_from_user32_to_kern(&msg_sys, user_msg)) + if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) return -EFAULT; + if(kern_msg.msg_iovlen > UIO_MAXIOV) + return -EINVAL; - 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 = kern_msg.msg_name; uaddr_len = &user_msg->msg_namelen; - err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE); + err = verify_compat_iovec(&kern_msg, iov, addr, VERIFY_WRITE); if (err < 0) - goto out_freeiov; + goto out; total_len = err; - cmsg_ptr = (unsigned long) msg_sys.msg_control; - msg_sys.msg_flags = MSG_CMSG_COMPAT; - - if (sock->file->f_flags & O_NONBLOCK) - user_flags |= MSG_DONTWAIT; - - err = sock_recvmsg(sock, &msg_sys, total_len, user_flags); - if(err < 0) - goto out_freeiov; - - len = err; + cmsg_ptr = (unsigned long) kern_msg.msg_control; + kern_msg.msg_flags = 0; - if (uaddr != NULL) { - err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len); - if (err < 0) - goto out_freeiov; + 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(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); + } } - 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); + if(kern_msg.msg_iov != iov) + kfree(kern_msg.msg_iov); out: - return err; + if(err < 0) + return err; + return len; } diff --git a/trunk/drivers/char/watchdog/i8xx_tco.c b/trunk/drivers/char/watchdog/i8xx_tco.c index a13395e2c372..f975dab1ddf9 100644 --- a/trunk/drivers/char/watchdog/i8xx_tco.c +++ b/trunk/drivers/char/watchdog/i8xx_tco.c @@ -1,5 +1,5 @@ /* - * i8xx_tco: TCO timer driver for i8xx chipsets + * i8xx_tco 0.07: TCO timer driver for i8xx chipsets * * (c) Copyright 2000 kernel concepts , All Rights Reserved. * http://www.kernelconcepts.de @@ -63,9 +63,6 @@ * 20050128 Wim Van Sebroeck * 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 - * 0.08 Make sure that the watchdog is only "armed" when started. - * (Kernel Bug 4251) */ /* @@ -90,7 +87,7 @@ #include "i8xx_tco.h" /* Module and version information */ -#define TCO_VERSION "0.08" +#define TCO_VERSION "0.07" #define TCO_MODULE_NAME "i8xx TCO timer" #define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION #define PFX TCO_MODULE_NAME ": " @@ -128,18 +125,10 @@ static int tco_timer_start (void) 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) @@ -149,20 +138,13 @@ static int tco_timer_start (void) static int tco_timer_stop (void) { - unsigned char val, val1; + unsigned char val; 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) @@ -173,7 +155,6 @@ static int tco_timer_stop (void) 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; @@ -436,8 +417,9 @@ static unsigned char __init i8xx_tco_getdevice (void) 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; @@ -448,10 +430,6 @@ static unsigned char __init i8xx_tco_getdevice (void) 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", @@ -527,10 +505,17 @@ static int __init watchdog_init (void) 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/trunk/drivers/i2c/busses/i2c-sibyte.c b/trunk/drivers/i2c/busses/i2c-sibyte.c index fa503ed9f86d..1c99536b673b 100644 --- a/trunk/drivers/i2c/busses/i2c-sibyte.c +++ b/trunk/drivers/i2c/busses/i2c-sibyte.c @@ -23,8 +23,8 @@ #include static struct i2c_algo_sibyte_data sibyte_board_data[2] = { - { NULL, 0, (void *) (CKSEG1+A_SMB_BASE(0)) }, - { NULL, 1, (void *) (CKSEG1+A_SMB_BASE(1)) } + { NULL, 0, (void *) (KSEG1+A_SMB_BASE(0)) }, + { NULL, 1, (void *) (KSEG1+A_SMB_BASE(1)) } }; static struct i2c_adapter sibyte_board_adapter[2] = { diff --git a/trunk/drivers/message/i2o/Kconfig b/trunk/drivers/message/i2o/Kconfig index 43a942a29c2e..06e8eb19a05c 100644 --- a/trunk/drivers/message/i2o/Kconfig +++ b/trunk/drivers/message/i2o/Kconfig @@ -53,9 +53,6 @@ config I2O_CONFIG 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/trunk/drivers/message/i2o/config-osm.c b/trunk/drivers/message/i2o/config-osm.c index af32ab4e90cd..fe2e7afc9eae 100644 --- a/trunk/drivers/message/i2o/config-osm.c +++ b/trunk/drivers/message/i2o/config-osm.c @@ -30,9 +30,503 @@ 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/trunk/drivers/sbus/char/envctrl.c b/trunk/drivers/sbus/char/envctrl.c index 9a8c572554f5..e103b12f9efe 100644 --- a/trunk/drivers/sbus/char/envctrl.c +++ b/trunk/drivers/sbus/char/envctrl.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -1010,16 +1011,13 @@ static int kenvctrld(void *__unused) poll_interval = 5000; /* TODO env_mon_interval */ - daemonize("kenvctrld"); - allow_signal(SIGKILL); - - kenvctrld_task = current; - printk(KERN_INFO "envctrl: %s starting...\n", current->comm); for (;;) { - if(msleep_interruptible(poll_interval)) - break; + msleep_interruptible(poll_interval); + if (kthread_should_stop()) + break; + for (whichcpu = 0; whichcpu < ENVCTRL_MAX_CPU; ++whichcpu) { if (0 < envctrl_read_cpu_info(whichcpu, cputemp, ENVCTRL_CPUTEMP_MON, @@ -1118,9 +1116,11 @@ static int __init envctrl_init(void) i2c_childlist[i].addr, (0 == i) ? ("\n") : (" ")); } - err = kernel_thread(kenvctrld, NULL, CLONE_FS | CLONE_FILES); - if (err < 0) + kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld"); + if (IS_ERR(kenvctrld_task)) { + err = ERR_PTR(kenvctrld_task); goto out_deregister; + } return 0; @@ -1142,28 +1142,7 @@ static void __exit envctrl_cleanup(void) { int i; - if (NULL != kenvctrld_task) { - force_sig(SIGKILL, kenvctrld_task); - for (;;) { - struct task_struct *p; - int found = 0; - - read_lock(&tasklist_lock); - for_each_process(p) { - if (p == kenvctrld_task) { - found = 1; - break; - } - } - read_unlock(&tasklist_lock); - - if (!found) - break; - - msleep(1000); - } - kenvctrld_task = NULL; - } + kthread_stop(kenvctrld_task); iounmap(i2c); misc_deregister(&envctrl_dev); diff --git a/trunk/drivers/serial/cpm_uart/cpm_uart.h b/trunk/drivers/serial/cpm_uart/cpm_uart.h index 73c8a088c160..5f6187baad86 100644 --- a/trunk/drivers/serial/cpm_uart/cpm_uart.h +++ b/trunk/drivers/serial/cpm_uart/cpm_uart.h @@ -40,15 +40,13 @@ #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; @@ -69,8 +67,6 @@ struct uart_cpm_port { 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/trunk/drivers/serial/cpm_uart/cpm_uart_core.c b/trunk/drivers/serial/cpm_uart/cpm_uart_core.c index d639ac92a117..29db677d4284 100644 --- a/trunk/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/trunk/drivers/serial/cpm_uart/cpm_uart_core.c @@ -9,10 +9,9 @@ * * 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 * * 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 @@ -71,22 +70,8 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo); /**************************************************************/ -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) { @@ -158,18 +143,15 @@ static void cpm_uart_start_tx(struct uart_port *port, unsigned int tty_start) } if (cpm_uart_tx_pump(port) != 0) { - if (IS_SMC(pinfo)) { + if (IS_SMC(pinfo)) smcp->smc_smcm |= SMCM_TX; - smcp->smc_smcmr |= SMCMR_TEN; - } else { + 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) { @@ -194,7 +176,7 @@ static void cpm_uart_enable_ms(struct uart_port *port) } /* - * Generate a break. + * Generate a break. */ static void cpm_uart_break_ctl(struct uart_port *port, int break_state) { @@ -249,7 +231,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) /* 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) { @@ -261,7 +243,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) } /* get pointer */ - cp = cpm2cpu_addr(bdp->cbd_bufaddr); + cp = (unsigned char *)bus_to_virt(bdp->cbd_bufaddr); /* loop through the buffer */ while (i-- > 0) { @@ -283,14 +265,13 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) } /* 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 | BD_SC_ID); + bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV); 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 */ @@ -355,22 +336,22 @@ static irqreturn_t cpm_uart_int(int irq, void *data, struct pt_regs *regs) 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; } @@ -379,7 +360,6 @@ static int cpm_uart_startup(struct uart_port *port) { 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); @@ -396,19 +376,9 @@ static int cpm_uart_startup(struct uart_port *port) 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 */ @@ -424,12 +394,6 @@ static void cpm_uart_shutdown(struct uart_port *port) /* 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; @@ -538,7 +502,7 @@ static void cpm_uart_set_termios(struct uart_port *port, */ 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 @@ -605,8 +569,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) /* Pick next descriptor and fill from buffer */ bdp = pinfo->tx_cur; - p = cpm2cpu_addr(bdp->cbd_bufaddr); - + p = bus_to_virt(bdp->cbd_bufaddr); *p++ = xmit->buf[xmit->tail]; bdp->cbd_datlen = 1; bdp->cbd_sc |= BD_SC_READY; @@ -632,7 +595,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) { count = 0; - p = cpm2cpu_addr(bdp->cbd_bufaddr); + p = bus_to_virt(bdp->cbd_bufaddr); while (count < pinfo->tx_fifosize) { *p++ = xmit->buf[xmit->tail]; xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); @@ -643,7 +606,6 @@ static int cpm_uart_tx_pump(struct uart_port *port) } 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; @@ -681,12 +643,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo) 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 = cpu2cpm_addr(mem_addr); + bdp->cbd_bufaddr = virt_to_bus(mem_addr); bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT; mem_addr += pinfo->rx_fifosize; } - - bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); + + bdp->cbd_bufaddr = virt_to_bus(mem_addr); bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; /* Set the physical address of the host memory @@ -696,12 +658,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo) 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 = cpu2cpm_addr(mem_addr); + bdp->cbd_bufaddr = virt_to_bus(mem_addr); bdp->cbd_sc = BD_SC_INTRPT; mem_addr += pinfo->tx_fifosize; } - - bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); + + bdp->cbd_bufaddr = virt_to_bus(mem_addr); bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT; } @@ -801,8 +763,6 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo) /* 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); @@ -836,7 +796,7 @@ static int cpm_uart_request_port(struct uart_port *port) /* * 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); @@ -855,10 +815,6 @@ static int cpm_uart_request_port(struct uart_port *port) return ret; cpm_uart_initbd(pinfo); - if (IS_SMC(pinfo)) - cpm_uart_init_smc(pinfo); - else - cpm_uart_init_scc(pinfo); return 0; } @@ -913,7 +869,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { .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, }, @@ -927,7 +883,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { .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 @@ -943,10 +899,9 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { }, .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 = { @@ -957,10 +912,9 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { }, .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 = { @@ -971,10 +925,9 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { }, .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 = { @@ -985,10 +938,9 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { }, .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, }, }; @@ -1031,8 +983,11 @@ static void cpm_uart_console_write(struct console *co, const char *s, * If the buffer address is in the CPM DPRAM, don't * convert it. */ - cp = cpm2cpu_addr(bdp->cbd_bufaddr); - + if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR) + cp = (unsigned char *) (bdp->cbd_bufaddr); + else + cp = bus_to_virt(bdp->cbd_bufaddr); + *cp = *s; bdp->cbd_datlen = 1; @@ -1048,7 +1003,10 @@ static void cpm_uart_console_write(struct console *co, const char *s, while ((bdp->cbd_sc & BD_SC_READY) != 0) ; - cp = cpm2cpu_addr(bdp->cbd_bufaddr); + if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR) + cp = (unsigned char *) (bdp->cbd_bufaddr); + else + cp = bus_to_virt(bdp->cbd_bufaddr); *cp = 13; bdp->cbd_datlen = 1; @@ -1087,7 +1045,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) 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) { @@ -1104,7 +1062,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) /* * 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); @@ -1134,14 +1092,14 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) return 0; } -static struct uart_driver cpm_reg; +extern 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/trunk/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/trunk/drivers/serial/cpm_uart/cpm_uart_cpm1.c index 4b0786e7eb7f..8efbd6d1d6a4 100644 --- a/trunk/drivers/serial/cpm_uart/cpm_uart_cpm1.c +++ b/trunk/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,17 +82,6 @@ void cpm_line_cr_cmd(int line, int cmd) 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) { @@ -104,33 +93,41 @@ void smc1_lineif(struct uart_cpm_port *pinfo) ((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; - - 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; - } + /* Enable SMC2 transceivers */ + bcsr1 = ioremap(BCSR1, 4); + tmp = in_be32(bcsr1); + tmp &= ~BCSR1_RS232EN_2; + out_be32(bcsr1, tmp); + iounmap(bcsr1); #endif pinfo->brg = 2; @@ -161,7 +158,7 @@ void scc4_lineif(struct uart_cpm_port *pinfo) } /* - * 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 @@ -188,8 +185,6 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) 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/trunk/kernel/cpuset.c b/trunk/kernel/cpuset.c index 21a4e3b2cbda..805fb9097318 100644 --- a/trunk/kernel/cpuset.c +++ b/trunk/kernel/cpuset.c @@ -398,31 +398,21 @@ static int cpuset_path(const struct cpuset *cs, char *buf, int buflen) * 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. * - * 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. + * 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. */ -static void cpuset_release_agent(const char *pathbuf) +static int cpuset_release_agent(char *cpuset_str) { char *argv[3], *envp[3]; int i; - if (!pathbuf) - return; - i = 0; argv[i++] = "/sbin/cpuset_release_agent"; - argv[i++] = (char *)pathbuf; + argv[i++] = cpuset_str; argv[i] = NULL; i = 0; @@ -431,29 +421,17 @@ static void cpuset_release_agent(const char *pathbuf) envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; envp[i] = NULL; - call_usermodehelper(argv[0], argv, envp, 0); - kfree(pathbuf); + return call_usermodehelper(argv[0], argv, envp, 0); } /* * 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, 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(). + * the list of children is empty, send notice to user land. */ -static void check_for_release(struct cpuset *cs, char **ppathbuf) +static void check_for_release(struct cpuset *cs) { if (notify_on_release(cs) && atomic_read(&cs->count) == 0 && list_empty(&cs->children)) { @@ -463,9 +441,10 @@ static void check_for_release(struct cpuset *cs, char **ppathbuf) if (!buf) return; if (cpuset_path(cs, buf, PAGE_SIZE) < 0) - kfree(buf); - else - *ppathbuf = buf; + goto out; + cpuset_release_agent(buf); +out: + kfree(buf); } } @@ -748,14 +727,14 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf) return 0; } -static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf) +static int attach_task(struct cpuset *cs, char *buf) { pid_t pid; struct task_struct *tsk; struct cpuset *oldcs; cpumask_t cpus; - if (sscanf(pidbuf, "%d", &pid) != 1) + if (sscanf(buf, "%d", &pid) != 1) return -EIO; if (cpus_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed)) return -ENOSPC; @@ -798,7 +777,7 @@ static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf) put_task_struct(tsk); if (atomic_dec_and_test(&oldcs->count)) - check_for_release(oldcs, ppathbuf); + check_for_release(oldcs); return 0; } @@ -822,7 +801,6 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us 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. */ @@ -863,7 +841,7 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us retval = update_flag(CS_NOTIFY_ON_RELEASE, cs, buffer); break; case FILE_TASKLIST: - retval = attach_task(cs, buffer, &pathbuf); + retval = attach_task(cs, buffer); break; default: retval = -EINVAL; @@ -874,7 +852,6 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us retval = nbytes; out2: up(&cpuset_sem); - cpuset_release_agent(pathbuf); out1: kfree(buffer); return retval; @@ -1380,7 +1357,6 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry) struct cpuset *cs = dentry->d_fsdata; struct dentry *d; struct cpuset *parent; - char *pathbuf = NULL; /* the vfs holds both inode->i_sem already */ @@ -1400,7 +1376,7 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry) update_cpu_domains(cs); list_del(&cs->sibling); /* delete my sibling from parent->children */ if (list_empty(&parent->children)) - check_for_release(parent, &pathbuf); + check_for_release(parent); spin_lock(&cs->dentry->d_lock); d = dget(cs->dentry); cs->dentry = NULL; @@ -1408,7 +1384,6 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry) cpuset_d_remove_dir(d); dput(d); up(&cpuset_sem); - cpuset_release_agent(pathbuf); return 0; } @@ -1508,13 +1483,10 @@ void cpuset_exit(struct task_struct *tsk) 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, &pathbuf); + check_for_release(cs); up(&cpuset_sem); - cpuset_release_agent(pathbuf); } else { atomic_dec(&cs->count); } diff --git a/trunk/net/compat.c b/trunk/net/compat.c index d99ab9695893..be5d936dc423 100644 --- a/trunk/net/compat.c +++ b/trunk/net/compat.c @@ -91,11 +91,20 @@ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov, } 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/trunk/net/sunrpc/svcsock.c b/trunk/net/sunrpc/svcsock.c index d0c3120d0233..56db8f13e6cb 100644 --- a/trunk/net/sunrpc/svcsock.c +++ b/trunk/net/sunrpc/svcsock.c @@ -586,7 +586,7 @@ svc_udp_recvfrom(struct svc_rqst *rqstp) } if (skb->stamp.tv_sec == 0) { skb->stamp.tv_sec = xtime.tv_sec; - skb->stamp.tv_usec = xtime.tv_nsec / NSEC_PER_USEC; + skb->stamp.tv_usec = xtime.tv_nsec * 1000; /* Don't enable netstamp, sunrpc doesn't need that much accuracy */ }