diff options
| -rw-r--r-- | arch/sparc64/solaris/socket.c | 193 | ||||
| -rw-r--r-- | drivers/char/watchdog/i8xx_tco.c | 41 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-sibyte.c | 4 | ||||
| -rw-r--r-- | drivers/message/i2o/Kconfig | 3 | ||||
| -rw-r--r-- | drivers/message/i2o/config-osm.c | 494 | ||||
| -rw-r--r-- | drivers/serial/cpm_uart/cpm_uart.h | 10 | ||||
| -rw-r--r-- | drivers/serial/cpm_uart/cpm_uart_core.c | 132 | ||||
| -rw-r--r-- | drivers/serial/cpm_uart/cpm_uart_cpm1.c | 53 | ||||
| -rw-r--r-- | kernel/cpuset.c | 68 | ||||
| -rw-r--r-- | net/compat.c | 9 | ||||
| -rw-r--r-- | net/sunrpc/svcsock.c | 2 |
11 files changed, 324 insertions, 685 deletions
diff --git a/arch/sparc64/solaris/socket.c b/arch/sparc64/solaris/socket.c index 06740582717e..d3a66ea74a7f 100644 --- a/arch/sparc64/solaris/socket.c +++ b/arch/sparc64/solaris/socket.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/net.h> | 16 | #include <linux/net.h> |
| 17 | #include <linux/compat.h> | 17 | #include <linux/compat.h> |
| 18 | #include <net/compat.h> | 18 | #include <net/compat.h> |
| 19 | #include <net/sock.h> | ||
| 19 | 20 | ||
| 20 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
| 21 | #include <asm/string.h> | 22 | #include <asm/string.h> |
| @@ -297,121 +298,165 @@ asmlinkage int solaris_sendmsg(int fd, struct sol_nmsghdr __user *user_msg, unsi | |||
| 297 | { | 298 | { |
| 298 | struct socket *sock; | 299 | struct socket *sock; |
| 299 | char address[MAX_SOCK_ADDR]; | 300 | char address[MAX_SOCK_ADDR]; |
| 300 | struct iovec iov[UIO_FASTIOV]; | 301 | struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; |
| 301 | unsigned char ctl[sizeof(struct cmsghdr) + 20]; | 302 | unsigned char ctl[sizeof(struct cmsghdr) + 20]; |
| 302 | unsigned char *ctl_buf = ctl; | 303 | unsigned char *ctl_buf = ctl; |
| 303 | struct msghdr kern_msg; | 304 | struct msghdr msg_sys; |
| 304 | int err, total_len; | 305 | int err, ctl_len, iov_size, total_len; |
| 305 | 306 | ||
| 306 | if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) | 307 | err = -EFAULT; |
| 307 | return -EFAULT; | 308 | if (msghdr_from_user32_to_kern(&msg_sys, user_msg)) |
| 308 | if(kern_msg.msg_iovlen > UIO_MAXIOV) | 309 | goto out; |
| 309 | return -EINVAL; | 310 | |
| 310 | err = verify_compat_iovec(&kern_msg, iov, address, VERIFY_READ); | 311 | sock = sockfd_lookup(fd, &err); |
| 311 | if (err < 0) | 312 | if (!sock) |
| 312 | goto out; | 313 | goto out; |
| 314 | |||
| 315 | /* do not move before msg_sys is valid */ | ||
| 316 | err = -EMSGSIZE; | ||
| 317 | if (msg_sys.msg_iovlen > UIO_MAXIOV) | ||
| 318 | goto out_put; | ||
| 319 | |||
| 320 | /* Check whether to allocate the iovec area*/ | ||
| 321 | err = -ENOMEM; | ||
| 322 | iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); | ||
| 323 | if (msg_sys.msg_iovlen > UIO_FASTIOV) { | ||
| 324 | iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); | ||
| 325 | if (!iov) | ||
| 326 | goto out_put; | ||
| 327 | } | ||
| 328 | |||
| 329 | err = verify_compat_iovec(&msg_sys, iov, address, VERIFY_READ); | ||
| 330 | if (err < 0) | ||
| 331 | goto out_freeiov; | ||
| 313 | total_len = err; | 332 | total_len = err; |
| 314 | 333 | ||
| 315 | if(kern_msg.msg_controllen) { | 334 | err = -ENOBUFS; |
| 316 | struct sol_cmsghdr __user *ucmsg = kern_msg.msg_control; | 335 | if (msg_sys.msg_controllen > INT_MAX) |
| 336 | goto out_freeiov; | ||
| 337 | |||
| 338 | ctl_len = msg_sys.msg_controllen; | ||
| 339 | if (ctl_len) { | ||
| 340 | struct sol_cmsghdr __user *ucmsg = msg_sys.msg_control; | ||
| 317 | unsigned long *kcmsg; | 341 | unsigned long *kcmsg; |
| 318 | compat_size_t cmlen; | 342 | compat_size_t cmlen; |
| 319 | 343 | ||
| 320 | if (kern_msg.msg_controllen <= sizeof(compat_size_t)) | 344 | err = -EINVAL; |
| 321 | return -EINVAL; | 345 | if (ctl_len <= sizeof(compat_size_t)) |
| 346 | goto out_freeiov; | ||
| 322 | 347 | ||
| 323 | if(kern_msg.msg_controllen > sizeof(ctl)) { | 348 | if (ctl_len > sizeof(ctl)) { |
| 324 | err = -ENOBUFS; | 349 | err = -ENOBUFS; |
| 325 | ctl_buf = kmalloc(kern_msg.msg_controllen, GFP_KERNEL); | 350 | ctl_buf = kmalloc(ctl_len, GFP_KERNEL); |
| 326 | if(!ctl_buf) | 351 | if (!ctl_buf) |
| 327 | goto out_freeiov; | 352 | goto out_freeiov; |
| 328 | } | 353 | } |
| 329 | __get_user(cmlen, &ucmsg->cmsg_len); | 354 | __get_user(cmlen, &ucmsg->cmsg_len); |
| 330 | kcmsg = (unsigned long *) ctl_buf; | 355 | kcmsg = (unsigned long *) ctl_buf; |
| 331 | *kcmsg++ = (unsigned long)cmlen; | 356 | *kcmsg++ = (unsigned long)cmlen; |
| 332 | err = -EFAULT; | 357 | err = -EFAULT; |
| 333 | if(copy_from_user(kcmsg, &ucmsg->cmsg_level, | 358 | if (copy_from_user(kcmsg, &ucmsg->cmsg_level, |
| 334 | kern_msg.msg_controllen - sizeof(compat_size_t))) | 359 | ctl_len - sizeof(compat_size_t))) |
| 335 | goto out_freectl; | 360 | goto out_freectl; |
| 336 | kern_msg.msg_control = ctl_buf; | 361 | msg_sys.msg_control = ctl_buf; |
| 337 | } | 362 | } |
| 338 | kern_msg.msg_flags = solaris_to_linux_msgflags(user_flags); | 363 | msg_sys.msg_flags = solaris_to_linux_msgflags(user_flags); |
| 339 | 364 | ||
| 340 | lock_kernel(); | 365 | if (sock->file->f_flags & O_NONBLOCK) |
| 341 | sock = sockfd_lookup(fd, &err); | 366 | msg_sys.msg_flags |= MSG_DONTWAIT; |
| 342 | if (sock != NULL) { | 367 | err = sock_sendmsg(sock, &msg_sys, total_len); |
| 343 | if (sock->file->f_flags & O_NONBLOCK) | ||
| 344 | kern_msg.msg_flags |= MSG_DONTWAIT; | ||
| 345 | err = sock_sendmsg(sock, &kern_msg, total_len); | ||
| 346 | sockfd_put(sock); | ||
| 347 | } | ||
| 348 | unlock_kernel(); | ||
| 349 | 368 | ||
| 350 | out_freectl: | 369 | out_freectl: |
| 351 | /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */ | 370 | if (ctl_buf != ctl) |
| 352 | if(ctl_buf != ctl) | 371 | sock_kfree_s(sock->sk, ctl_buf, ctl_len); |
| 353 | kfree(ctl_buf); | ||
| 354 | out_freeiov: | 372 | out_freeiov: |
| 355 | if(kern_msg.msg_iov != iov) | 373 | if (iov != iovstack) |
| 356 | kfree(kern_msg.msg_iov); | 374 | sock_kfree_s(sock->sk, iov, iov_size); |
| 357 | out: | 375 | out_put: |
| 376 | sockfd_put(sock); | ||
| 377 | out: | ||
| 358 | return err; | 378 | return err; |
| 359 | } | 379 | } |
| 360 | 380 | ||
| 361 | asmlinkage int solaris_recvmsg(int fd, struct sol_nmsghdr __user *user_msg, unsigned int user_flags) | 381 | asmlinkage int solaris_recvmsg(int fd, struct sol_nmsghdr __user *user_msg, unsigned int user_flags) |
| 362 | { | 382 | { |
| 363 | struct iovec iovstack[UIO_FASTIOV]; | ||
| 364 | struct msghdr kern_msg; | ||
| 365 | char addr[MAX_SOCK_ADDR]; | ||
| 366 | struct socket *sock; | 383 | struct socket *sock; |
| 384 | struct iovec iovstack[UIO_FASTIOV]; | ||
| 367 | struct iovec *iov = iovstack; | 385 | struct iovec *iov = iovstack; |
| 386 | struct msghdr msg_sys; | ||
| 387 | unsigned long cmsg_ptr; | ||
| 388 | int err, iov_size, total_len, len; | ||
| 389 | |||
| 390 | /* kernel mode address */ | ||
| 391 | char addr[MAX_SOCK_ADDR]; | ||
| 392 | |||
| 393 | /* user mode address pointers */ | ||
| 368 | struct sockaddr __user *uaddr; | 394 | struct sockaddr __user *uaddr; |
| 369 | int __user *uaddr_len; | 395 | int __user *uaddr_len; |
| 370 | unsigned long cmsg_ptr; | ||
| 371 | int err, total_len, len = 0; | ||
| 372 | 396 | ||
| 373 | if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) | 397 | if (msghdr_from_user32_to_kern(&msg_sys, user_msg)) |
| 374 | return -EFAULT; | 398 | return -EFAULT; |
| 375 | if(kern_msg.msg_iovlen > UIO_MAXIOV) | ||
| 376 | return -EINVAL; | ||
| 377 | 399 | ||
| 378 | uaddr = kern_msg.msg_name; | 400 | sock = sockfd_lookup(fd, &err); |
| 401 | if (!sock) | ||
| 402 | goto out; | ||
| 403 | |||
| 404 | err = -EMSGSIZE; | ||
| 405 | if (msg_sys.msg_iovlen > UIO_MAXIOV) | ||
| 406 | goto out_put; | ||
| 407 | |||
| 408 | /* Check whether to allocate the iovec area*/ | ||
| 409 | err = -ENOMEM; | ||
| 410 | iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); | ||
| 411 | if (msg_sys.msg_iovlen > UIO_FASTIOV) { | ||
| 412 | iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); | ||
| 413 | if (!iov) | ||
| 414 | goto out_put; | ||
| 415 | } | ||
| 416 | |||
| 417 | /* | ||
| 418 | * Save the user-mode address (verify_iovec will change the | ||
| 419 | * kernel msghdr to use the kernel address space) | ||
| 420 | */ | ||
| 421 | |||
| 422 | uaddr = (void __user *) msg_sys.msg_name; | ||
| 379 | uaddr_len = &user_msg->msg_namelen; | 423 | uaddr_len = &user_msg->msg_namelen; |
| 380 | err = verify_compat_iovec(&kern_msg, iov, addr, VERIFY_WRITE); | 424 | err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE); |
| 381 | if (err < 0) | 425 | if (err < 0) |
| 382 | goto out; | 426 | goto out_freeiov; |
| 383 | total_len = err; | 427 | total_len = err; |
| 384 | 428 | ||
| 385 | cmsg_ptr = (unsigned long) kern_msg.msg_control; | 429 | cmsg_ptr = (unsigned long) msg_sys.msg_control; |
| 386 | kern_msg.msg_flags = 0; | 430 | msg_sys.msg_flags = MSG_CMSG_COMPAT; |
| 387 | 431 | ||
| 388 | lock_kernel(); | 432 | if (sock->file->f_flags & O_NONBLOCK) |
| 389 | sock = sockfd_lookup(fd, &err); | 433 | user_flags |= MSG_DONTWAIT; |
| 390 | if (sock != NULL) { | 434 | |
| 391 | if (sock->file->f_flags & O_NONBLOCK) | 435 | err = sock_recvmsg(sock, &msg_sys, total_len, user_flags); |
| 392 | user_flags |= MSG_DONTWAIT; | 436 | if(err < 0) |
| 393 | err = sock_recvmsg(sock, &kern_msg, total_len, user_flags); | 437 | goto out_freeiov; |
| 394 | if(err >= 0) | 438 | |
| 395 | len = err; | 439 | len = err; |
| 396 | sockfd_put(sock); | 440 | |
| 397 | } | 441 | if (uaddr != NULL) { |
| 398 | unlock_kernel(); | 442 | err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len); |
| 399 | 443 | if (err < 0) | |
| 400 | if(uaddr != NULL && err >= 0) | 444 | goto out_freeiov; |
| 401 | err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); | ||
| 402 | if(err >= 0) { | ||
| 403 | err = __put_user(linux_to_solaris_msgflags(kern_msg.msg_flags), &user_msg->msg_flags); | ||
| 404 | if(!err) { | ||
| 405 | /* XXX Convert cmsg back into userspace 32-bit format... */ | ||
| 406 | err = __put_user((unsigned long)kern_msg.msg_control - cmsg_ptr, | ||
| 407 | &user_msg->msg_controllen); | ||
| 408 | } | ||
| 409 | } | 445 | } |
| 446 | err = __put_user(linux_to_solaris_msgflags(msg_sys.msg_flags), &user_msg->msg_flags); | ||
| 447 | if (err) | ||
| 448 | goto out_freeiov; | ||
| 449 | err = __put_user((unsigned long)msg_sys.msg_control - cmsg_ptr, | ||
| 450 | &user_msg->msg_controllen); | ||
| 451 | if (err) | ||
| 452 | goto out_freeiov; | ||
| 453 | err = len; | ||
| 410 | 454 | ||
| 411 | if(kern_msg.msg_iov != iov) | 455 | out_freeiov: |
| 412 | kfree(kern_msg.msg_iov); | 456 | if (iov != iovstack) |
| 457 | sock_kfree_s(sock->sk, iov, iov_size); | ||
| 458 | out_put: | ||
| 459 | sockfd_put(sock); | ||
| 413 | out: | 460 | out: |
| 414 | if(err < 0) | 461 | return err; |
| 415 | return err; | ||
| 416 | return len; | ||
| 417 | } | 462 | } |
diff --git a/drivers/char/watchdog/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c index f975dab1ddf9..a13395e2c372 100644 --- a/drivers/char/watchdog/i8xx_tco.c +++ b/drivers/char/watchdog/i8xx_tco.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * i8xx_tco 0.07: TCO timer driver for i8xx chipsets | 2 | * i8xx_tco: TCO timer driver for i8xx chipsets |
| 3 | * | 3 | * |
| 4 | * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved. | 4 | * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved. |
| 5 | * http://www.kernelconcepts.de | 5 | * http://www.kernelconcepts.de |
| @@ -63,6 +63,9 @@ | |||
| 63 | * 20050128 Wim Van Sebroeck <wim@iguana.be> | 63 | * 20050128 Wim Van Sebroeck <wim@iguana.be> |
| 64 | * 0.07 Added support for the ICH4-M, ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW | 64 | * 0.07 Added support for the ICH4-M, ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW |
| 65 | * chipsets. Also added support for the "undocumented" ICH7 chipset. | 65 | * chipsets. Also added support for the "undocumented" ICH7 chipset. |
| 66 | * 20050807 Wim Van Sebroeck <wim@iguana.be> | ||
| 67 | * 0.08 Make sure that the watchdog is only "armed" when started. | ||
| 68 | * (Kernel Bug 4251) | ||
| 66 | */ | 69 | */ |
| 67 | 70 | ||
| 68 | /* | 71 | /* |
| @@ -87,7 +90,7 @@ | |||
| 87 | #include "i8xx_tco.h" | 90 | #include "i8xx_tco.h" |
| 88 | 91 | ||
| 89 | /* Module and version information */ | 92 | /* Module and version information */ |
| 90 | #define TCO_VERSION "0.07" | 93 | #define TCO_VERSION "0.08" |
| 91 | #define TCO_MODULE_NAME "i8xx TCO timer" | 94 | #define TCO_MODULE_NAME "i8xx TCO timer" |
| 92 | #define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION | 95 | #define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION |
| 93 | #define PFX TCO_MODULE_NAME ": " | 96 | #define PFX TCO_MODULE_NAME ": " |
| @@ -125,10 +128,18 @@ static int tco_timer_start (void) | |||
| 125 | unsigned char val; | 128 | unsigned char val; |
| 126 | 129 | ||
| 127 | spin_lock(&tco_lock); | 130 | spin_lock(&tco_lock); |
| 131 | |||
| 132 | /* disable chipset's NO_REBOOT bit */ | ||
| 133 | pci_read_config_byte (i8xx_tco_pci, 0xd4, &val); | ||
| 134 | val &= 0xfd; | ||
| 135 | pci_write_config_byte (i8xx_tco_pci, 0xd4, val); | ||
| 136 | |||
| 137 | /* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled to count */ | ||
| 128 | val = inb (TCO1_CNT + 1); | 138 | val = inb (TCO1_CNT + 1); |
| 129 | val &= 0xf7; | 139 | val &= 0xf7; |
| 130 | outb (val, TCO1_CNT + 1); | 140 | outb (val, TCO1_CNT + 1); |
| 131 | val = inb (TCO1_CNT + 1); | 141 | val = inb (TCO1_CNT + 1); |
| 142 | |||
| 132 | spin_unlock(&tco_lock); | 143 | spin_unlock(&tco_lock); |
| 133 | 144 | ||
| 134 | if (val & 0x08) | 145 | if (val & 0x08) |
| @@ -138,13 +149,20 @@ static int tco_timer_start (void) | |||
| 138 | 149 | ||
| 139 | static int tco_timer_stop (void) | 150 | static int tco_timer_stop (void) |
| 140 | { | 151 | { |
| 141 | unsigned char val; | 152 | unsigned char val, val1; |
| 142 | 153 | ||
| 143 | spin_lock(&tco_lock); | 154 | spin_lock(&tco_lock); |
| 155 | /* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */ | ||
| 144 | val = inb (TCO1_CNT + 1); | 156 | val = inb (TCO1_CNT + 1); |
| 145 | val |= 0x08; | 157 | val |= 0x08; |
| 146 | outb (val, TCO1_CNT + 1); | 158 | outb (val, TCO1_CNT + 1); |
| 147 | val = inb (TCO1_CNT + 1); | 159 | val = inb (TCO1_CNT + 1); |
| 160 | |||
| 161 | /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ | ||
| 162 | pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); | ||
| 163 | val1 |= 0x02; | ||
| 164 | pci_write_config_byte (i8xx_tco_pci, 0xd4, val1); | ||
| 165 | |||
| 148 | spin_unlock(&tco_lock); | 166 | spin_unlock(&tco_lock); |
| 149 | 167 | ||
| 150 | if ((val & 0x08) == 0) | 168 | if ((val & 0x08) == 0) |
| @@ -155,6 +173,7 @@ static int tco_timer_stop (void) | |||
| 155 | static int tco_timer_keepalive (void) | 173 | static int tco_timer_keepalive (void) |
| 156 | { | 174 | { |
| 157 | spin_lock(&tco_lock); | 175 | spin_lock(&tco_lock); |
| 176 | /* Reload the timer by writing to the TCO Timer Reload register */ | ||
| 158 | outb (0x01, TCO1_RLD); | 177 | outb (0x01, TCO1_RLD); |
| 159 | spin_unlock(&tco_lock); | 178 | spin_unlock(&tco_lock); |
| 160 | return 0; | 179 | return 0; |
| @@ -417,9 +436,8 @@ static unsigned char __init i8xx_tco_getdevice (void) | |||
| 417 | printk (KERN_ERR PFX "failed to get TCOBASE address\n"); | 436 | printk (KERN_ERR PFX "failed to get TCOBASE address\n"); |
| 418 | return 0; | 437 | return 0; |
| 419 | } | 438 | } |
| 420 | /* | 439 | |
| 421 | * Check chipset's NO_REBOOT bit | 440 | /* Check chipset's NO_REBOOT bit */ |
| 422 | */ | ||
| 423 | pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); | 441 | pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); |
| 424 | if (val1 & 0x02) { | 442 | if (val1 & 0x02) { |
| 425 | val1 &= 0xfd; | 443 | val1 &= 0xfd; |
| @@ -430,6 +448,10 @@ static unsigned char __init i8xx_tco_getdevice (void) | |||
| 430 | return 0; /* Cannot reset NO_REBOOT bit */ | 448 | return 0; /* Cannot reset NO_REBOOT bit */ |
| 431 | } | 449 | } |
| 432 | } | 450 | } |
| 451 | /* Disable reboots untill the watchdog starts */ | ||
| 452 | val1 |= 0x02; | ||
| 453 | pci_write_config_byte (i8xx_tco_pci, 0xd4, val1); | ||
| 454 | |||
| 433 | /* Set the TCO_EN bit in SMI_EN register */ | 455 | /* Set the TCO_EN bit in SMI_EN register */ |
| 434 | if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) { | 456 | if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) { |
| 435 | printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", | 457 | printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", |
| @@ -505,17 +527,10 @@ out: | |||
| 505 | 527 | ||
| 506 | static void __exit watchdog_cleanup (void) | 528 | static void __exit watchdog_cleanup (void) |
| 507 | { | 529 | { |
| 508 | u8 val; | ||
| 509 | |||
| 510 | /* Stop the timer before we leave */ | 530 | /* Stop the timer before we leave */ |
| 511 | if (!nowayout) | 531 | if (!nowayout) |
| 512 | tco_timer_stop (); | 532 | tco_timer_stop (); |
| 513 | 533 | ||
| 514 | /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ | ||
| 515 | pci_read_config_byte (i8xx_tco_pci, 0xd4, &val); | ||
| 516 | val |= 0x02; | ||
| 517 | pci_write_config_byte (i8xx_tco_pci, 0xd4, val); | ||
| 518 | |||
| 519 | /* Deregister */ | 534 | /* Deregister */ |
| 520 | misc_deregister (&i8xx_tco_miscdev); | 535 | misc_deregister (&i8xx_tco_miscdev); |
| 521 | unregister_reboot_notifier(&i8xx_tco_notifier); | 536 | unregister_reboot_notifier(&i8xx_tco_notifier); |
diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c index 1c99536b673b..fa503ed9f86d 100644 --- a/drivers/i2c/busses/i2c-sibyte.c +++ b/drivers/i2c/busses/i2c-sibyte.c | |||
| @@ -23,8 +23,8 @@ | |||
| 23 | #include <asm/sibyte/sb1250_smbus.h> | 23 | #include <asm/sibyte/sb1250_smbus.h> |
| 24 | 24 | ||
| 25 | static struct i2c_algo_sibyte_data sibyte_board_data[2] = { | 25 | static struct i2c_algo_sibyte_data sibyte_board_data[2] = { |
| 26 | { NULL, 0, (void *) (KSEG1+A_SMB_BASE(0)) }, | 26 | { NULL, 0, (void *) (CKSEG1+A_SMB_BASE(0)) }, |
| 27 | { NULL, 1, (void *) (KSEG1+A_SMB_BASE(1)) } | 27 | { NULL, 1, (void *) (CKSEG1+A_SMB_BASE(1)) } |
| 28 | }; | 28 | }; |
| 29 | 29 | ||
| 30 | static struct i2c_adapter sibyte_board_adapter[2] = { | 30 | static struct i2c_adapter sibyte_board_adapter[2] = { |
diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig index 06e8eb19a05c..43a942a29c2e 100644 --- a/drivers/message/i2o/Kconfig +++ b/drivers/message/i2o/Kconfig | |||
| @@ -53,6 +53,9 @@ config I2O_CONFIG | |||
| 53 | To compile this support as a module, choose M here: the | 53 | To compile this support as a module, choose M here: the |
| 54 | module will be called i2o_config. | 54 | module will be called i2o_config. |
| 55 | 55 | ||
| 56 | Note: If you want to use the new API you have to download the | ||
| 57 | i2o_config patch from http://i2o.shadowconnect.com/ | ||
| 58 | |||
| 56 | config I2O_CONFIG_OLD_IOCTL | 59 | config I2O_CONFIG_OLD_IOCTL |
| 57 | bool "Enable ioctls (OBSOLETE)" | 60 | bool "Enable ioctls (OBSOLETE)" |
| 58 | depends on I2O_CONFIG | 61 | depends on I2O_CONFIG |
diff --git a/drivers/message/i2o/config-osm.c b/drivers/message/i2o/config-osm.c index fe2e7afc9eae..af32ab4e90cd 100644 --- a/drivers/message/i2o/config-osm.c +++ b/drivers/message/i2o/config-osm.c | |||
| @@ -30,503 +30,9 @@ | |||
| 30 | 30 | ||
| 31 | static struct i2o_driver i2o_config_driver; | 31 | static struct i2o_driver i2o_config_driver; |
| 32 | 32 | ||
| 33 | /* Special file operations for sysfs */ | ||
| 34 | struct fops_attribute { | ||
| 35 | struct bin_attribute bin; | ||
| 36 | struct file_operations fops; | ||
| 37 | }; | ||
| 38 | |||
| 39 | /** | ||
| 40 | * sysfs_read_dummy | ||
| 41 | */ | ||
| 42 | static ssize_t sysfs_read_dummy(struct kobject *kobj, char *buf, loff_t offset, | ||
| 43 | size_t count) | ||
| 44 | { | ||
| 45 | return 0; | ||
| 46 | }; | ||
| 47 | |||
| 48 | /** | ||
| 49 | * sysfs_write_dummy | ||
| 50 | */ | ||
| 51 | static ssize_t sysfs_write_dummy(struct kobject *kobj, char *buf, loff_t offset, | ||
| 52 | size_t count) | ||
| 53 | { | ||
| 54 | return 0; | ||
| 55 | }; | ||
| 56 | |||
| 57 | /** | ||
| 58 | * sysfs_create_fops_file - Creates attribute with special file operations | ||
| 59 | * @kobj: kobject which should contains the attribute | ||
| 60 | * @attr: attributes which should be used to create file | ||
| 61 | * | ||
| 62 | * First creates attribute @attr in kobject @kobj. If it is the first time | ||
| 63 | * this function is called, merge old fops from sysfs with new one and | ||
| 64 | * write it back. Afterwords the new fops will be set for the created | ||
| 65 | * attribute. | ||
| 66 | * | ||
| 67 | * Returns 0 on success or negative error code on failure. | ||
| 68 | */ | ||
| 69 | static int sysfs_create_fops_file(struct kobject *kobj, | ||
| 70 | struct fops_attribute *attr) | ||
| 71 | { | ||
| 72 | struct file_operations tmp, *fops; | ||
| 73 | struct dentry *d; | ||
| 74 | struct qstr qstr; | ||
| 75 | int rc; | ||
| 76 | |||
| 77 | fops = &attr->fops; | ||
| 78 | |||
| 79 | if (fops->read) | ||
| 80 | attr->bin.read = sysfs_read_dummy; | ||
| 81 | |||
| 82 | if (fops->write) | ||
| 83 | attr->bin.write = sysfs_write_dummy; | ||
| 84 | |||
| 85 | if ((rc = sysfs_create_bin_file(kobj, &attr->bin))) | ||
| 86 | return rc; | ||
| 87 | |||
| 88 | qstr.name = attr->bin.attr.name; | ||
| 89 | qstr.len = strlen(qstr.name); | ||
| 90 | qstr.hash = full_name_hash(qstr.name, qstr.len); | ||
| 91 | |||
| 92 | if ((d = lookup_hash(&qstr, kobj->dentry))) { | ||
| 93 | if (!fops->owner) { | ||
| 94 | memcpy(&tmp, d->d_inode->i_fop, sizeof(tmp)); | ||
| 95 | if (fops->read) | ||
| 96 | tmp.read = fops->read; | ||
| 97 | if (fops->write) | ||
| 98 | tmp.write = fops->write; | ||
| 99 | memcpy(fops, &tmp, sizeof(tmp)); | ||
| 100 | } | ||
| 101 | |||
| 102 | d->d_inode->i_fop = fops; | ||
| 103 | } else | ||
| 104 | sysfs_remove_bin_file(kobj, &attr->bin); | ||
| 105 | |||
| 106 | return -ENOENT; | ||
| 107 | }; | ||
| 108 | |||
| 109 | /** | ||
| 110 | * sysfs_remove_fops_file - Remove attribute with special file operations | ||
| 111 | * @kobj: kobject which contains the attribute | ||
| 112 | * @attr: attributes which are used to create file | ||
| 113 | * | ||
| 114 | * Only wrapper arround sysfs_remove_bin_file() | ||
| 115 | * | ||
| 116 | * Returns 0 on success or negative error code on failure. | ||
| 117 | */ | ||
| 118 | static inline int sysfs_remove_fops_file(struct kobject *kobj, | ||
| 119 | struct fops_attribute *attr) | ||
| 120 | { | ||
| 121 | return sysfs_remove_bin_file(kobj, &attr->bin); | ||
| 122 | }; | ||
| 123 | |||
| 124 | /** | ||
| 125 | * i2o_config_read_hrt - Returns the HRT of the controller | ||
| 126 | * @kob: kernel object handle | ||
| 127 | * @buf: buffer into which the HRT should be copied | ||
| 128 | * @off: file offset | ||
| 129 | * @count: number of bytes to read | ||
| 130 | * | ||
| 131 | * Put @count bytes starting at @off into @buf from the HRT of the I2O | ||
| 132 | * controller corresponding to @kobj. | ||
| 133 | * | ||
| 134 | * Returns number of bytes copied into buffer. | ||
| 135 | */ | ||
| 136 | static ssize_t i2o_config_read_hrt(struct kobject *kobj, char *buf, | ||
| 137 | loff_t offset, size_t count) | ||
| 138 | { | ||
| 139 | struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; | ||
| 140 | i2o_hrt *hrt = c->hrt.virt; | ||
| 141 | |||
| 142 | u32 size = (hrt->num_entries * hrt->entry_len + 2) * 4; | ||
| 143 | |||
| 144 | if (offset > size) | ||
| 145 | return 0; | ||
| 146 | |||
| 147 | if (offset + count > size) | ||
| 148 | count = size - offset; | ||
| 149 | |||
| 150 | memcpy(buf, (u8 *) hrt + offset, count); | ||
| 151 | |||
| 152 | return count; | ||
| 153 | }; | ||
| 154 | |||
| 155 | /** | ||
| 156 | * i2o_config_read_lct - Returns the LCT of the controller | ||
| 157 | * @kob: kernel object handle | ||
| 158 | * @buf: buffer into which the LCT should be copied | ||
| 159 | * @off: file offset | ||
| 160 | * @count: number of bytes to read | ||
| 161 | * | ||
| 162 | * Put @count bytes starting at @off into @buf from the LCT of the I2O | ||
| 163 | * controller corresponding to @kobj. | ||
| 164 | * | ||
| 165 | * Returns number of bytes copied into buffer. | ||
| 166 | */ | ||
| 167 | static ssize_t i2o_config_read_lct(struct kobject *kobj, char *buf, | ||
| 168 | loff_t offset, size_t count) | ||
| 169 | { | ||
| 170 | struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; | ||
| 171 | u32 size = c->lct->table_size * 4; | ||
| 172 | |||
| 173 | if (offset > size) | ||
| 174 | return 0; | ||
| 175 | |||
| 176 | if (offset + count > size) | ||
| 177 | count = size - offset; | ||
| 178 | |||
| 179 | memcpy(buf, (u8 *) c->lct + offset, count); | ||
| 180 | |||
| 181 | return count; | ||
| 182 | }; | ||
| 183 | |||
| 184 | #define I2O_CONFIG_SW_ATTR(_name,_mode,_type,_swid) \ | ||
| 185 | static ssize_t i2o_config_##_name##_read(struct file *file, char __user *buf, size_t count, loff_t * offset) { \ | ||
| 186 | return i2o_config_sw_read(file, buf, count, offset, _type, _swid); \ | ||
| 187 | };\ | ||
| 188 | \ | ||
| 189 | static ssize_t i2o_config_##_name##_write(struct file *file, const char __user *buf, size_t count, loff_t * offset) { \ | ||
| 190 | return i2o_config_sw_write(file, buf, count, offset, _type, _swid); \ | ||
| 191 | }; \ | ||
| 192 | \ | ||
| 193 | static struct fops_attribute i2o_config_attr_##_name = { \ | ||
| 194 | .bin = { .attr = { .name = __stringify(_name), .mode = _mode, \ | ||
| 195 | .owner = THIS_MODULE }, \ | ||
| 196 | .size = 0, }, \ | ||
| 197 | .fops = { .write = i2o_config_##_name##_write, \ | ||
| 198 | .read = i2o_config_##_name##_read} \ | ||
| 199 | }; | ||
| 200 | |||
| 201 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
| 202 | |||
| 203 | /** | ||
| 204 | * i2o_config_dpt_reagion - Converts type and id to flash region | ||
| 205 | * @swtype: type of software module reading | ||
| 206 | * @swid: id of software which should be read | ||
| 207 | * | ||
| 208 | * Converts type and id from I2O spec to the matching region for DPT / | ||
| 209 | * Adaptec controllers. | ||
| 210 | * | ||
| 211 | * Returns region which match type and id or -1 on error. | ||
| 212 | */ | ||
| 213 | static u32 i2o_config_dpt_region(u8 swtype, u8 swid) | ||
| 214 | { | ||
| 215 | switch (swtype) { | ||
| 216 | case I2O_SOFTWARE_MODULE_IRTOS: | ||
| 217 | /* | ||
| 218 | * content: operation firmware | ||
| 219 | * region size: | ||
| 220 | * 0xbc000 for 2554, 3754, 2564, 3757 | ||
| 221 | * 0x170000 for 2865 | ||
| 222 | * 0x17c000 for 3966 | ||
| 223 | */ | ||
| 224 | if (!swid) | ||
| 225 | return 0; | ||
| 226 | |||
| 227 | break; | ||
| 228 | |||
| 229 | case I2O_SOFTWARE_MODULE_IOP_PRIVATE: | ||
| 230 | /* | ||
| 231 | * content: BIOS and SMOR | ||
| 232 | * BIOS size: first 0x8000 bytes | ||
| 233 | * region size: | ||
| 234 | * 0x40000 for 2554, 3754, 2564, 3757 | ||
| 235 | * 0x80000 for 2865, 3966 | ||
| 236 | */ | ||
| 237 | if (!swid) | ||
| 238 | return 1; | ||
| 239 | |||
| 240 | break; | ||
| 241 | |||
| 242 | case I2O_SOFTWARE_MODULE_IOP_CONFIG: | ||
| 243 | switch (swid) { | ||
| 244 | case 0: | ||
| 245 | /* | ||
| 246 | * content: NVRAM defaults | ||
| 247 | * region size: 0x2000 bytes | ||
| 248 | */ | ||
| 249 | return 2; | ||
| 250 | case 1: | ||
| 251 | /* | ||
| 252 | * content: serial number | ||
| 253 | * region size: 0x2000 bytes | ||
| 254 | */ | ||
| 255 | return 3; | ||
| 256 | } | ||
| 257 | break; | ||
| 258 | } | ||
| 259 | |||
| 260 | return -1; | ||
| 261 | }; | ||
| 262 | |||
| 263 | #endif | ||
| 264 | |||
| 265 | /** | ||
| 266 | * i2o_config_sw_read - Read a software module from controller | ||
| 267 | * @file: file pointer | ||
| 268 | * @buf: buffer into which the data should be copied | ||
| 269 | * @count: number of bytes to read | ||
| 270 | * @off: file offset | ||
| 271 | * @swtype: type of software module reading | ||
| 272 | * @swid: id of software which should be read | ||
| 273 | * | ||
| 274 | * Transfers @count bytes at offset @offset from IOP into buffer using | ||
| 275 | * type @swtype and id @swid as described in I2O spec. | ||
| 276 | * | ||
| 277 | * Returns number of bytes copied into buffer or error code on failure. | ||
| 278 | */ | ||
| 279 | static ssize_t i2o_config_sw_read(struct file *file, char __user * buf, | ||
| 280 | size_t count, loff_t * offset, u8 swtype, | ||
| 281 | u32 swid) | ||
| 282 | { | ||
| 283 | struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata; | ||
| 284 | struct kobject *kobj = sd->s_element; | ||
| 285 | struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; | ||
| 286 | u32 m, function = I2O_CMD_SW_UPLOAD; | ||
| 287 | struct i2o_dma buffer; | ||
| 288 | struct i2o_message __iomem *msg; | ||
| 289 | u32 __iomem *mptr; | ||
| 290 | int rc, status; | ||
| 291 | |||
| 292 | m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); | ||
| 293 | if (m == I2O_QUEUE_EMPTY) | ||
| 294 | return -EBUSY; | ||
| 295 | |||
| 296 | mptr = &msg->body[3]; | ||
| 297 | |||
| 298 | if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL))) { | ||
| 299 | i2o_msg_nop(c, m); | ||
| 300 | return rc; | ||
| 301 | } | ||
| 302 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
| 303 | if (c->adaptec) { | ||
| 304 | mptr = &msg->body[4]; | ||
| 305 | function = I2O_CMD_PRIVATE; | ||
| 306 | |||
| 307 | writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]); | ||
| 308 | |||
| 309 | writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_READ, | ||
| 310 | &msg->body[0]); | ||
| 311 | writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]); | ||
| 312 | writel(*offset, &msg->body[2]); | ||
| 313 | writel(count, &msg->body[3]); | ||
| 314 | } else | ||
| 315 | #endif | ||
| 316 | writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]); | ||
| 317 | |||
| 318 | writel(0xD0000000 | count, mptr++); | ||
| 319 | writel(buffer.phys, mptr); | ||
| 320 | |||
| 321 | writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]); | ||
| 322 | writel(i2o_config_driver.context, &msg->u.head[2]); | ||
| 323 | writel(0, &msg->u.head[3]); | ||
| 324 | |||
| 325 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
| 326 | if (!c->adaptec) | ||
| 327 | #endif | ||
| 328 | { | ||
| 329 | writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]); | ||
| 330 | writel(0, &msg->body[1]); | ||
| 331 | writel(swid, &msg->body[2]); | ||
| 332 | } | ||
| 333 | |||
| 334 | status = i2o_msg_post_wait_mem(c, m, 60, &buffer); | ||
| 335 | |||
| 336 | if (status == I2O_POST_WAIT_OK) { | ||
| 337 | if (!(rc = copy_to_user(buf, buffer.virt, count))) { | ||
| 338 | rc = count; | ||
| 339 | *offset += count; | ||
| 340 | } | ||
| 341 | } else | ||
| 342 | rc = -EIO; | ||
| 343 | |||
| 344 | if (status != -ETIMEDOUT) | ||
| 345 | i2o_dma_free(&c->pdev->dev, &buffer); | ||
| 346 | |||
| 347 | return rc; | ||
| 348 | }; | ||
| 349 | |||
| 350 | /** | ||
| 351 | * i2o_config_sw_write - Write a software module to controller | ||
| 352 | * @file: file pointer | ||
| 353 | * @buf: buffer into which the data should be copied | ||
| 354 | * @count: number of bytes to read | ||
| 355 | * @off: file offset | ||
| 356 | * @swtype: type of software module writing | ||
| 357 | * @swid: id of software which should be written | ||
| 358 | * | ||
| 359 | * Transfers @count bytes at offset @offset from buffer to IOP using | ||
| 360 | * type @swtype and id @swid as described in I2O spec. | ||
| 361 | * | ||
| 362 | * Returns number of bytes copied from buffer or error code on failure. | ||
| 363 | */ | ||
| 364 | static ssize_t i2o_config_sw_write(struct file *file, const char __user * buf, | ||
| 365 | size_t count, loff_t * offset, u8 swtype, | ||
| 366 | u32 swid) | ||
| 367 | { | ||
| 368 | struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata; | ||
| 369 | struct kobject *kobj = sd->s_element; | ||
| 370 | struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; | ||
| 371 | u32 m, function = I2O_CMD_SW_DOWNLOAD; | ||
| 372 | struct i2o_dma buffer; | ||
| 373 | struct i2o_message __iomem *msg; | ||
| 374 | u32 __iomem *mptr; | ||
| 375 | int rc, status; | ||
| 376 | |||
| 377 | m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); | ||
| 378 | if (m == I2O_QUEUE_EMPTY) | ||
| 379 | return -EBUSY; | ||
| 380 | |||
| 381 | mptr = &msg->body[3]; | ||
| 382 | |||
| 383 | if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL))) | ||
| 384 | goto nop_msg; | ||
| 385 | |||
| 386 | if ((rc = copy_from_user(buffer.virt, buf, count))) | ||
| 387 | goto free_buffer; | ||
| 388 | |||
| 389 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
| 390 | if (c->adaptec) { | ||
| 391 | mptr = &msg->body[4]; | ||
| 392 | function = I2O_CMD_PRIVATE; | ||
| 393 | |||
| 394 | writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]); | ||
| 395 | |||
| 396 | writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_WRITE, | ||
| 397 | &msg->body[0]); | ||
| 398 | writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]); | ||
| 399 | writel(*offset, &msg->body[2]); | ||
| 400 | writel(count, &msg->body[3]); | ||
| 401 | } else | ||
| 402 | #endif | ||
| 403 | writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]); | ||
| 404 | |||
| 405 | writel(0xD4000000 | count, mptr++); | ||
| 406 | writel(buffer.phys, mptr); | ||
| 407 | |||
| 408 | writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]); | ||
| 409 | writel(i2o_config_driver.context, &msg->u.head[2]); | ||
| 410 | writel(0, &msg->u.head[3]); | ||
| 411 | |||
| 412 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
| 413 | if (!c->adaptec) | ||
| 414 | #endif | ||
| 415 | { | ||
| 416 | writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]); | ||
| 417 | writel(0, &msg->body[1]); | ||
| 418 | writel(swid, &msg->body[2]); | ||
| 419 | } | ||
| 420 | |||
| 421 | status = i2o_msg_post_wait_mem(c, m, 60, &buffer); | ||
| 422 | |||
| 423 | if (status != -ETIMEDOUT) | ||
| 424 | i2o_dma_free(&c->pdev->dev, &buffer); | ||
| 425 | |||
| 426 | if (status != I2O_POST_WAIT_OK) | ||
| 427 | return -EIO; | ||
| 428 | |||
| 429 | *offset += count; | ||
| 430 | |||
| 431 | return count; | ||
| 432 | |||
| 433 | free_buffer: | ||
| 434 | i2o_dma_free(&c->pdev->dev, &buffer); | ||
| 435 | |||
| 436 | nop_msg: | ||
| 437 | i2o_msg_nop(c, m); | ||
| 438 | |||
| 439 | return rc; | ||
| 440 | }; | ||
| 441 | |||
| 442 | /* attribute for HRT in sysfs */ | ||
| 443 | static struct bin_attribute i2o_config_hrt_attr = { | ||
| 444 | .attr = { | ||
| 445 | .name = "hrt", | ||
| 446 | .mode = S_IRUGO, | ||
| 447 | .owner = THIS_MODULE}, | ||
| 448 | .size = 0, | ||
| 449 | .read = i2o_config_read_hrt | ||
| 450 | }; | ||
| 451 | |||
| 452 | /* attribute for LCT in sysfs */ | ||
| 453 | static struct bin_attribute i2o_config_lct_attr = { | ||
| 454 | .attr = { | ||
| 455 | .name = "lct", | ||
| 456 | .mode = S_IRUGO, | ||
| 457 | .owner = THIS_MODULE}, | ||
| 458 | .size = 0, | ||
| 459 | .read = i2o_config_read_lct | ||
| 460 | }; | ||
| 461 | |||
| 462 | /* IRTOS firmware access */ | ||
| 463 | I2O_CONFIG_SW_ATTR(irtos, S_IWRSR, I2O_SOFTWARE_MODULE_IRTOS, 0); | ||
| 464 | |||
| 465 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
| 466 | |||
| 467 | /* | ||
| 468 | * attribute for BIOS / SMOR, nvram and serial number access on DPT / Adaptec | ||
| 469 | * controllers | ||
| 470 | */ | ||
| 471 | I2O_CONFIG_SW_ATTR(bios, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_PRIVATE, 0); | ||
| 472 | I2O_CONFIG_SW_ATTR(nvram, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 0); | ||
| 473 | I2O_CONFIG_SW_ATTR(serial, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 1); | ||
| 474 | |||
| 475 | #endif | ||
| 476 | |||
| 477 | /** | ||
| 478 | * i2o_config_notify_controller_add - Notify of added controller | ||
| 479 | * @c: the controller which was added | ||
| 480 | * | ||
| 481 | * If a I2O controller is added, we catch the notification to add sysfs | ||
| 482 | * entries. | ||
| 483 | */ | ||
| 484 | static void i2o_config_notify_controller_add(struct i2o_controller *c) | ||
| 485 | { | ||
| 486 | struct kobject *kobj = &c->exec->device.kobj; | ||
| 487 | |||
| 488 | sysfs_create_bin_file(kobj, &i2o_config_hrt_attr); | ||
| 489 | sysfs_create_bin_file(kobj, &i2o_config_lct_attr); | ||
| 490 | |||
| 491 | sysfs_create_fops_file(kobj, &i2o_config_attr_irtos); | ||
| 492 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
| 493 | if (c->adaptec) { | ||
| 494 | sysfs_create_fops_file(kobj, &i2o_config_attr_bios); | ||
| 495 | sysfs_create_fops_file(kobj, &i2o_config_attr_nvram); | ||
| 496 | sysfs_create_fops_file(kobj, &i2o_config_attr_serial); | ||
| 497 | } | ||
| 498 | #endif | ||
| 499 | }; | ||
| 500 | |||
| 501 | /** | ||
| 502 | * i2o_config_notify_controller_remove - Notify of removed controller | ||
| 503 | * @c: the controller which was removed | ||
| 504 | * | ||
| 505 | * If a I2O controller is removed, we catch the notification to remove the | ||
| 506 | * sysfs entries. | ||
| 507 | */ | ||
| 508 | static void i2o_config_notify_controller_remove(struct i2o_controller *c) | ||
| 509 | { | ||
| 510 | struct kobject *kobj = &c->exec->device.kobj; | ||
| 511 | |||
| 512 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
| 513 | if (c->adaptec) { | ||
| 514 | sysfs_remove_fops_file(kobj, &i2o_config_attr_serial); | ||
| 515 | sysfs_remove_fops_file(kobj, &i2o_config_attr_nvram); | ||
| 516 | sysfs_remove_fops_file(kobj, &i2o_config_attr_bios); | ||
| 517 | } | ||
| 518 | #endif | ||
| 519 | sysfs_remove_fops_file(kobj, &i2o_config_attr_irtos); | ||
| 520 | |||
| 521 | sysfs_remove_bin_file(kobj, &i2o_config_lct_attr); | ||
| 522 | sysfs_remove_bin_file(kobj, &i2o_config_hrt_attr); | ||
| 523 | }; | ||
| 524 | |||
| 525 | /* Config OSM driver struct */ | 33 | /* Config OSM driver struct */ |
| 526 | static struct i2o_driver i2o_config_driver = { | 34 | static struct i2o_driver i2o_config_driver = { |
| 527 | .name = OSM_NAME, | 35 | .name = OSM_NAME, |
| 528 | .notify_controller_add = i2o_config_notify_controller_add, | ||
| 529 | .notify_controller_remove = i2o_config_notify_controller_remove | ||
| 530 | }; | 36 | }; |
| 531 | 37 | ||
| 532 | #ifdef CONFIG_I2O_CONFIG_OLD_IOCTL | 38 | #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 5f6187baad86..73c8a088c160 100644 --- a/drivers/serial/cpm_uart/cpm_uart.h +++ b/drivers/serial/cpm_uart/cpm_uart.h | |||
| @@ -40,13 +40,15 @@ | |||
| 40 | #define TX_NUM_FIFO 4 | 40 | #define TX_NUM_FIFO 4 |
| 41 | #define TX_BUF_SIZE 32 | 41 | #define TX_BUF_SIZE 32 |
| 42 | 42 | ||
| 43 | #define SCC_WAIT_CLOSING 100 | ||
| 44 | |||
| 43 | struct uart_cpm_port { | 45 | struct uart_cpm_port { |
| 44 | struct uart_port port; | 46 | struct uart_port port; |
| 45 | u16 rx_nrfifos; | 47 | u16 rx_nrfifos; |
| 46 | u16 rx_fifosize; | 48 | u16 rx_fifosize; |
| 47 | u16 tx_nrfifos; | 49 | u16 tx_nrfifos; |
| 48 | u16 tx_fifosize; | 50 | u16 tx_fifosize; |
| 49 | smc_t *smcp; | 51 | smc_t *smcp; |
| 50 | smc_uart_t *smcup; | 52 | smc_uart_t *smcup; |
| 51 | scc_t *sccp; | 53 | scc_t *sccp; |
| 52 | scc_uart_t *sccup; | 54 | scc_uart_t *sccup; |
| @@ -67,6 +69,8 @@ struct uart_cpm_port { | |||
| 67 | int bits; | 69 | int bits; |
| 68 | /* Keep track of 'odd' SMC2 wirings */ | 70 | /* Keep track of 'odd' SMC2 wirings */ |
| 69 | int is_portb; | 71 | int is_portb; |
| 72 | /* wait on close if needed */ | ||
| 73 | int wait_closing; | ||
| 70 | }; | 74 | }; |
| 71 | 75 | ||
| 72 | extern int cpm_uart_port_map[UART_NR]; | 76 | 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 29db677d4284..d639ac92a117 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c | |||
| @@ -9,9 +9,10 @@ | |||
| 9 | * | 9 | * |
| 10 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2) | 10 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2) |
| 11 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) | 11 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) |
| 12 | * | 12 | * |
| 13 | * Copyright (C) 2004 Freescale Semiconductor, Inc. | 13 | * Copyright (C) 2004 Freescale Semiconductor, Inc. |
| 14 | * (C) 2004 Intracom, S.A. | 14 | * (C) 2004 Intracom, S.A. |
| 15 | * (C) 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@ru.mvista.com> | ||
| 15 | * | 16 | * |
| 16 | * This program is free software; you can redistribute it and/or modify | 17 | * This program is free software; you can redistribute it and/or modify |
| 17 | * it under the terms of the GNU General Public License as published by | 18 | * it under the terms of the GNU General Public License as published by |
| @@ -70,8 +71,22 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo); | |||
| 70 | 71 | ||
| 71 | /**************************************************************/ | 72 | /**************************************************************/ |
| 72 | 73 | ||
| 74 | static inline unsigned long cpu2cpm_addr(void *addr) | ||
| 75 | { | ||
| 76 | if ((unsigned long)addr >= CPM_ADDR) | ||
| 77 | return (unsigned long)addr; | ||
| 78 | return virt_to_bus(addr); | ||
| 79 | } | ||
| 80 | |||
| 81 | static inline void *cpm2cpu_addr(unsigned long addr) | ||
| 82 | { | ||
| 83 | if (addr >= CPM_ADDR) | ||
| 84 | return (void *)addr; | ||
| 85 | return bus_to_virt(addr); | ||
| 86 | } | ||
| 87 | |||
| 73 | /* | 88 | /* |
| 74 | * Check, if transmit buffers are processed | 89 | * Check, if transmit buffers are processed |
| 75 | */ | 90 | */ |
| 76 | static unsigned int cpm_uart_tx_empty(struct uart_port *port) | 91 | static unsigned int cpm_uart_tx_empty(struct uart_port *port) |
| 77 | { | 92 | { |
| @@ -143,15 +158,18 @@ static void cpm_uart_start_tx(struct uart_port *port, unsigned int tty_start) | |||
| 143 | } | 158 | } |
| 144 | 159 | ||
| 145 | if (cpm_uart_tx_pump(port) != 0) { | 160 | if (cpm_uart_tx_pump(port) != 0) { |
| 146 | if (IS_SMC(pinfo)) | 161 | if (IS_SMC(pinfo)) { |
| 147 | smcp->smc_smcm |= SMCM_TX; | 162 | smcp->smc_smcm |= SMCM_TX; |
| 148 | else | 163 | smcp->smc_smcmr |= SMCMR_TEN; |
| 164 | } else { | ||
| 149 | sccp->scc_sccm |= UART_SCCM_TX; | 165 | sccp->scc_sccm |= UART_SCCM_TX; |
| 166 | pinfo->sccp->scc_gsmrl |= SCC_GSMRL_ENT; | ||
| 167 | } | ||
| 150 | } | 168 | } |
| 151 | } | 169 | } |
| 152 | 170 | ||
| 153 | /* | 171 | /* |
| 154 | * Stop receiver | 172 | * Stop receiver |
| 155 | */ | 173 | */ |
| 156 | static void cpm_uart_stop_rx(struct uart_port *port) | 174 | static void cpm_uart_stop_rx(struct uart_port *port) |
| 157 | { | 175 | { |
| @@ -176,7 +194,7 @@ static void cpm_uart_enable_ms(struct uart_port *port) | |||
| 176 | } | 194 | } |
| 177 | 195 | ||
| 178 | /* | 196 | /* |
| 179 | * Generate a break. | 197 | * Generate a break. |
| 180 | */ | 198 | */ |
| 181 | static void cpm_uart_break_ctl(struct uart_port *port, int break_state) | 199 | static void cpm_uart_break_ctl(struct uart_port *port, int break_state) |
| 182 | { | 200 | { |
| @@ -231,7 +249,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) | |||
| 231 | /* get number of characters, and check spce in flip-buffer */ | 249 | /* get number of characters, and check spce in flip-buffer */ |
| 232 | i = bdp->cbd_datlen; | 250 | i = bdp->cbd_datlen; |
| 233 | 251 | ||
| 234 | /* If we have not enough room in tty flip buffer, then we try | 252 | /* If we have not enough room in tty flip buffer, then we try |
| 235 | * later, which will be the next rx-interrupt or a timeout | 253 | * later, which will be the next rx-interrupt or a timeout |
| 236 | */ | 254 | */ |
| 237 | if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) { | 255 | if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) { |
| @@ -243,7 +261,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) | |||
| 243 | } | 261 | } |
| 244 | 262 | ||
| 245 | /* get pointer */ | 263 | /* get pointer */ |
| 246 | cp = (unsigned char *)bus_to_virt(bdp->cbd_bufaddr); | 264 | cp = cpm2cpu_addr(bdp->cbd_bufaddr); |
| 247 | 265 | ||
| 248 | /* loop through the buffer */ | 266 | /* loop through the buffer */ |
| 249 | while (i-- > 0) { | 267 | while (i-- > 0) { |
| @@ -265,13 +283,14 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) | |||
| 265 | } /* End while (i--) */ | 283 | } /* End while (i--) */ |
| 266 | 284 | ||
| 267 | /* This BD is ready to be used again. Clear status. get next */ | 285 | /* This BD is ready to be used again. Clear status. get next */ |
| 268 | bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV); | 286 | bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID); |
| 269 | bdp->cbd_sc |= BD_SC_EMPTY; | 287 | bdp->cbd_sc |= BD_SC_EMPTY; |
| 270 | 288 | ||
| 271 | if (bdp->cbd_sc & BD_SC_WRAP) | 289 | if (bdp->cbd_sc & BD_SC_WRAP) |
| 272 | bdp = pinfo->rx_bd_base; | 290 | bdp = pinfo->rx_bd_base; |
| 273 | else | 291 | else |
| 274 | bdp++; | 292 | bdp++; |
| 293 | |||
| 275 | } /* End for (;;) */ | 294 | } /* End for (;;) */ |
| 276 | 295 | ||
| 277 | /* Write back buffer pointer */ | 296 | /* Write back buffer pointer */ |
| @@ -336,22 +355,22 @@ static irqreturn_t cpm_uart_int(int irq, void *data, struct pt_regs *regs) | |||
| 336 | 355 | ||
| 337 | if (IS_SMC(pinfo)) { | 356 | if (IS_SMC(pinfo)) { |
| 338 | events = smcp->smc_smce; | 357 | events = smcp->smc_smce; |
| 358 | smcp->smc_smce = events; | ||
| 339 | if (events & SMCM_BRKE) | 359 | if (events & SMCM_BRKE) |
| 340 | uart_handle_break(port); | 360 | uart_handle_break(port); |
| 341 | if (events & SMCM_RX) | 361 | if (events & SMCM_RX) |
| 342 | cpm_uart_int_rx(port, regs); | 362 | cpm_uart_int_rx(port, regs); |
| 343 | if (events & SMCM_TX) | 363 | if (events & SMCM_TX) |
| 344 | cpm_uart_int_tx(port, regs); | 364 | cpm_uart_int_tx(port, regs); |
| 345 | smcp->smc_smce = events; | ||
| 346 | } else { | 365 | } else { |
| 347 | events = sccp->scc_scce; | 366 | events = sccp->scc_scce; |
| 367 | sccp->scc_scce = events; | ||
| 348 | if (events & UART_SCCM_BRKE) | 368 | if (events & UART_SCCM_BRKE) |
| 349 | uart_handle_break(port); | 369 | uart_handle_break(port); |
| 350 | if (events & UART_SCCM_RX) | 370 | if (events & UART_SCCM_RX) |
| 351 | cpm_uart_int_rx(port, regs); | 371 | cpm_uart_int_rx(port, regs); |
| 352 | if (events & UART_SCCM_TX) | 372 | if (events & UART_SCCM_TX) |
| 353 | cpm_uart_int_tx(port, regs); | 373 | cpm_uart_int_tx(port, regs); |
| 354 | sccp->scc_scce = events; | ||
| 355 | } | 374 | } |
| 356 | return (events) ? IRQ_HANDLED : IRQ_NONE; | 375 | return (events) ? IRQ_HANDLED : IRQ_NONE; |
| 357 | } | 376 | } |
| @@ -360,6 +379,7 @@ static int cpm_uart_startup(struct uart_port *port) | |||
| 360 | { | 379 | { |
| 361 | int retval; | 380 | int retval; |
| 362 | struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; | 381 | struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; |
| 382 | int line = pinfo - cpm_uart_ports; | ||
| 363 | 383 | ||
| 364 | pr_debug("CPM uart[%d]:startup\n", port->line); | 384 | pr_debug("CPM uart[%d]:startup\n", port->line); |
| 365 | 385 | ||
| @@ -376,9 +396,19 @@ static int cpm_uart_startup(struct uart_port *port) | |||
| 376 | pinfo->sccp->scc_sccm |= UART_SCCM_RX; | 396 | pinfo->sccp->scc_sccm |= UART_SCCM_RX; |
| 377 | } | 397 | } |
| 378 | 398 | ||
| 399 | if (!(pinfo->flags & FLAG_CONSOLE)) | ||
| 400 | cpm_line_cr_cmd(line,CPM_CR_INIT_TRX); | ||
| 379 | return 0; | 401 | return 0; |
| 380 | } | 402 | } |
| 381 | 403 | ||
| 404 | inline void cpm_uart_wait_until_send(struct uart_cpm_port *pinfo) | ||
| 405 | { | ||
| 406 | unsigned long target_jiffies = jiffies + pinfo->wait_closing; | ||
| 407 | |||
| 408 | while (!time_after(jiffies, target_jiffies)) | ||
| 409 | schedule(); | ||
| 410 | } | ||
| 411 | |||
| 382 | /* | 412 | /* |
| 383 | * Shutdown the uart | 413 | * Shutdown the uart |
| 384 | */ | 414 | */ |
| @@ -394,6 +424,12 @@ static void cpm_uart_shutdown(struct uart_port *port) | |||
| 394 | 424 | ||
| 395 | /* If the port is not the console, disable Rx and Tx. */ | 425 | /* If the port is not the console, disable Rx and Tx. */ |
| 396 | if (!(pinfo->flags & FLAG_CONSOLE)) { | 426 | if (!(pinfo->flags & FLAG_CONSOLE)) { |
| 427 | /* Wait for all the BDs marked sent */ | ||
| 428 | while(!cpm_uart_tx_empty(port)) | ||
| 429 | schedule_timeout(2); | ||
| 430 | if(pinfo->wait_closing) | ||
| 431 | cpm_uart_wait_until_send(pinfo); | ||
| 432 | |||
| 397 | /* Stop uarts */ | 433 | /* Stop uarts */ |
| 398 | if (IS_SMC(pinfo)) { | 434 | if (IS_SMC(pinfo)) { |
| 399 | volatile smc_t *smcp = pinfo->smcp; | 435 | volatile smc_t *smcp = pinfo->smcp; |
| @@ -502,7 +538,7 @@ static void cpm_uart_set_termios(struct uart_port *port, | |||
| 502 | */ | 538 | */ |
| 503 | if ((termios->c_cflag & CREAD) == 0) | 539 | if ((termios->c_cflag & CREAD) == 0) |
| 504 | port->read_status_mask &= ~BD_SC_EMPTY; | 540 | port->read_status_mask &= ~BD_SC_EMPTY; |
| 505 | 541 | ||
| 506 | spin_lock_irqsave(&port->lock, flags); | 542 | spin_lock_irqsave(&port->lock, flags); |
| 507 | 543 | ||
| 508 | /* Start bit has not been added (so don't, because we would just | 544 | /* Start bit has not been added (so don't, because we would just |
| @@ -569,7 +605,8 @@ static int cpm_uart_tx_pump(struct uart_port *port) | |||
| 569 | /* Pick next descriptor and fill from buffer */ | 605 | /* Pick next descriptor and fill from buffer */ |
| 570 | bdp = pinfo->tx_cur; | 606 | bdp = pinfo->tx_cur; |
| 571 | 607 | ||
| 572 | p = bus_to_virt(bdp->cbd_bufaddr); | 608 | p = cpm2cpu_addr(bdp->cbd_bufaddr); |
| 609 | |||
| 573 | *p++ = xmit->buf[xmit->tail]; | 610 | *p++ = xmit->buf[xmit->tail]; |
| 574 | bdp->cbd_datlen = 1; | 611 | bdp->cbd_datlen = 1; |
| 575 | bdp->cbd_sc |= BD_SC_READY; | 612 | bdp->cbd_sc |= BD_SC_READY; |
| @@ -595,7 +632,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) | |||
| 595 | 632 | ||
| 596 | while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) { | 633 | while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) { |
| 597 | count = 0; | 634 | count = 0; |
| 598 | p = bus_to_virt(bdp->cbd_bufaddr); | 635 | p = cpm2cpu_addr(bdp->cbd_bufaddr); |
| 599 | while (count < pinfo->tx_fifosize) { | 636 | while (count < pinfo->tx_fifosize) { |
| 600 | *p++ = xmit->buf[xmit->tail]; | 637 | *p++ = xmit->buf[xmit->tail]; |
| 601 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | 638 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
| @@ -606,6 +643,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) | |||
| 606 | } | 643 | } |
| 607 | bdp->cbd_datlen = count; | 644 | bdp->cbd_datlen = count; |
| 608 | bdp->cbd_sc |= BD_SC_READY; | 645 | bdp->cbd_sc |= BD_SC_READY; |
| 646 | __asm__("eieio"); | ||
| 609 | /* Get next BD. */ | 647 | /* Get next BD. */ |
| 610 | if (bdp->cbd_sc & BD_SC_WRAP) | 648 | if (bdp->cbd_sc & BD_SC_WRAP) |
| 611 | bdp = pinfo->tx_bd_base; | 649 | bdp = pinfo->tx_bd_base; |
| @@ -643,12 +681,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo) | |||
| 643 | mem_addr = pinfo->mem_addr; | 681 | mem_addr = pinfo->mem_addr; |
| 644 | bdp = pinfo->rx_cur = pinfo->rx_bd_base; | 682 | bdp = pinfo->rx_cur = pinfo->rx_bd_base; |
| 645 | for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) { | 683 | for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) { |
| 646 | bdp->cbd_bufaddr = virt_to_bus(mem_addr); | 684 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); |
| 647 | bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT; | 685 | bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT; |
| 648 | mem_addr += pinfo->rx_fifosize; | 686 | mem_addr += pinfo->rx_fifosize; |
| 649 | } | 687 | } |
| 650 | 688 | ||
| 651 | bdp->cbd_bufaddr = virt_to_bus(mem_addr); | 689 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); |
| 652 | bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; | 690 | bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; |
| 653 | 691 | ||
| 654 | /* Set the physical address of the host memory | 692 | /* Set the physical address of the host memory |
| @@ -658,12 +696,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo) | |||
| 658 | mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize); | 696 | mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize); |
| 659 | bdp = pinfo->tx_cur = pinfo->tx_bd_base; | 697 | bdp = pinfo->tx_cur = pinfo->tx_bd_base; |
| 660 | for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) { | 698 | for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) { |
| 661 | bdp->cbd_bufaddr = virt_to_bus(mem_addr); | 699 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); |
| 662 | bdp->cbd_sc = BD_SC_INTRPT; | 700 | bdp->cbd_sc = BD_SC_INTRPT; |
| 663 | mem_addr += pinfo->tx_fifosize; | 701 | mem_addr += pinfo->tx_fifosize; |
| 664 | } | 702 | } |
| 665 | 703 | ||
| 666 | bdp->cbd_bufaddr = virt_to_bus(mem_addr); | 704 | bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); |
| 667 | bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT; | 705 | bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT; |
| 668 | } | 706 | } |
| 669 | 707 | ||
| @@ -763,6 +801,8 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo) | |||
| 763 | /* Using idle charater time requires some additional tuning. */ | 801 | /* Using idle charater time requires some additional tuning. */ |
| 764 | up->smc_mrblr = pinfo->rx_fifosize; | 802 | up->smc_mrblr = pinfo->rx_fifosize; |
| 765 | up->smc_maxidl = pinfo->rx_fifosize; | 803 | up->smc_maxidl = pinfo->rx_fifosize; |
| 804 | up->smc_brklen = 0; | ||
| 805 | up->smc_brkec = 0; | ||
| 766 | up->smc_brkcr = 1; | 806 | up->smc_brkcr = 1; |
| 767 | 807 | ||
| 768 | cpm_line_cr_cmd(line, CPM_CR_INIT_TRX); | 808 | cpm_line_cr_cmd(line, CPM_CR_INIT_TRX); |
| @@ -796,7 +836,7 @@ static int cpm_uart_request_port(struct uart_port *port) | |||
| 796 | /* | 836 | /* |
| 797 | * Setup any port IO, connect any baud rate generators, | 837 | * Setup any port IO, connect any baud rate generators, |
| 798 | * etc. This is expected to be handled by board | 838 | * etc. This is expected to be handled by board |
| 799 | * dependant code | 839 | * dependant code |
| 800 | */ | 840 | */ |
| 801 | if (pinfo->set_lineif) | 841 | if (pinfo->set_lineif) |
| 802 | pinfo->set_lineif(pinfo); | 842 | pinfo->set_lineif(pinfo); |
| @@ -815,6 +855,10 @@ static int cpm_uart_request_port(struct uart_port *port) | |||
| 815 | return ret; | 855 | return ret; |
| 816 | 856 | ||
| 817 | cpm_uart_initbd(pinfo); | 857 | cpm_uart_initbd(pinfo); |
| 858 | if (IS_SMC(pinfo)) | ||
| 859 | cpm_uart_init_smc(pinfo); | ||
| 860 | else | ||
| 861 | cpm_uart_init_scc(pinfo); | ||
| 818 | 862 | ||
| 819 | return 0; | 863 | return 0; |
| 820 | } | 864 | } |
| @@ -869,7 +913,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { | |||
| 869 | .flags = FLAG_SMC, | 913 | .flags = FLAG_SMC, |
| 870 | .tx_nrfifos = TX_NUM_FIFO, | 914 | .tx_nrfifos = TX_NUM_FIFO, |
| 871 | .tx_fifosize = TX_BUF_SIZE, | 915 | .tx_fifosize = TX_BUF_SIZE, |
| 872 | .rx_nrfifos = RX_NUM_FIFO, | 916 | .rx_nrfifos = RX_NUM_FIFO, |
| 873 | .rx_fifosize = RX_BUF_SIZE, | 917 | .rx_fifosize = RX_BUF_SIZE, |
| 874 | .set_lineif = smc1_lineif, | 918 | .set_lineif = smc1_lineif, |
| 875 | }, | 919 | }, |
| @@ -883,7 +927,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { | |||
| 883 | .flags = FLAG_SMC, | 927 | .flags = FLAG_SMC, |
| 884 | .tx_nrfifos = TX_NUM_FIFO, | 928 | .tx_nrfifos = TX_NUM_FIFO, |
| 885 | .tx_fifosize = TX_BUF_SIZE, | 929 | .tx_fifosize = TX_BUF_SIZE, |
| 886 | .rx_nrfifos = RX_NUM_FIFO, | 930 | .rx_nrfifos = RX_NUM_FIFO, |
| 887 | .rx_fifosize = RX_BUF_SIZE, | 931 | .rx_fifosize = RX_BUF_SIZE, |
| 888 | .set_lineif = smc2_lineif, | 932 | .set_lineif = smc2_lineif, |
| 889 | #ifdef CONFIG_SERIAL_CPM_ALT_SMC2 | 933 | #ifdef CONFIG_SERIAL_CPM_ALT_SMC2 |
| @@ -899,9 +943,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { | |||
| 899 | }, | 943 | }, |
| 900 | .tx_nrfifos = TX_NUM_FIFO, | 944 | .tx_nrfifos = TX_NUM_FIFO, |
| 901 | .tx_fifosize = TX_BUF_SIZE, | 945 | .tx_fifosize = TX_BUF_SIZE, |
| 902 | .rx_nrfifos = RX_NUM_FIFO, | 946 | .rx_nrfifos = RX_NUM_FIFO, |
| 903 | .rx_fifosize = RX_BUF_SIZE, | 947 | .rx_fifosize = RX_BUF_SIZE, |
| 904 | .set_lineif = scc1_lineif, | 948 | .set_lineif = scc1_lineif, |
| 949 | .wait_closing = SCC_WAIT_CLOSING, | ||
| 905 | }, | 950 | }, |
| 906 | [UART_SCC2] = { | 951 | [UART_SCC2] = { |
| 907 | .port = { | 952 | .port = { |
| @@ -912,9 +957,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { | |||
| 912 | }, | 957 | }, |
| 913 | .tx_nrfifos = TX_NUM_FIFO, | 958 | .tx_nrfifos = TX_NUM_FIFO, |
| 914 | .tx_fifosize = TX_BUF_SIZE, | 959 | .tx_fifosize = TX_BUF_SIZE, |
| 915 | .rx_nrfifos = RX_NUM_FIFO, | 960 | .rx_nrfifos = RX_NUM_FIFO, |
| 916 | .rx_fifosize = RX_BUF_SIZE, | 961 | .rx_fifosize = RX_BUF_SIZE, |
| 917 | .set_lineif = scc2_lineif, | 962 | .set_lineif = scc2_lineif, |
| 963 | .wait_closing = SCC_WAIT_CLOSING, | ||
| 918 | }, | 964 | }, |
| 919 | [UART_SCC3] = { | 965 | [UART_SCC3] = { |
| 920 | .port = { | 966 | .port = { |
| @@ -925,9 +971,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { | |||
| 925 | }, | 971 | }, |
| 926 | .tx_nrfifos = TX_NUM_FIFO, | 972 | .tx_nrfifos = TX_NUM_FIFO, |
| 927 | .tx_fifosize = TX_BUF_SIZE, | 973 | .tx_fifosize = TX_BUF_SIZE, |
| 928 | .rx_nrfifos = RX_NUM_FIFO, | 974 | .rx_nrfifos = RX_NUM_FIFO, |
| 929 | .rx_fifosize = RX_BUF_SIZE, | 975 | .rx_fifosize = RX_BUF_SIZE, |
| 930 | .set_lineif = scc3_lineif, | 976 | .set_lineif = scc3_lineif, |
| 977 | .wait_closing = SCC_WAIT_CLOSING, | ||
| 931 | }, | 978 | }, |
| 932 | [UART_SCC4] = { | 979 | [UART_SCC4] = { |
| 933 | .port = { | 980 | .port = { |
| @@ -938,9 +985,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { | |||
| 938 | }, | 985 | }, |
| 939 | .tx_nrfifos = TX_NUM_FIFO, | 986 | .tx_nrfifos = TX_NUM_FIFO, |
| 940 | .tx_fifosize = TX_BUF_SIZE, | 987 | .tx_fifosize = TX_BUF_SIZE, |
| 941 | .rx_nrfifos = RX_NUM_FIFO, | 988 | .rx_nrfifos = RX_NUM_FIFO, |
| 942 | .rx_fifosize = RX_BUF_SIZE, | 989 | .rx_fifosize = RX_BUF_SIZE, |
| 943 | .set_lineif = scc4_lineif, | 990 | .set_lineif = scc4_lineif, |
| 991 | .wait_closing = SCC_WAIT_CLOSING, | ||
| 944 | }, | 992 | }, |
| 945 | }; | 993 | }; |
| 946 | 994 | ||
| @@ -983,11 +1031,8 @@ static void cpm_uart_console_write(struct console *co, const char *s, | |||
| 983 | * If the buffer address is in the CPM DPRAM, don't | 1031 | * If the buffer address is in the CPM DPRAM, don't |
| 984 | * convert it. | 1032 | * convert it. |
| 985 | */ | 1033 | */ |
| 986 | if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR) | 1034 | cp = cpm2cpu_addr(bdp->cbd_bufaddr); |
| 987 | cp = (unsigned char *) (bdp->cbd_bufaddr); | 1035 | |
| 988 | else | ||
| 989 | cp = bus_to_virt(bdp->cbd_bufaddr); | ||
| 990 | |||
| 991 | *cp = *s; | 1036 | *cp = *s; |
| 992 | 1037 | ||
| 993 | bdp->cbd_datlen = 1; | 1038 | bdp->cbd_datlen = 1; |
| @@ -1003,10 +1048,7 @@ static void cpm_uart_console_write(struct console *co, const char *s, | |||
| 1003 | while ((bdp->cbd_sc & BD_SC_READY) != 0) | 1048 | while ((bdp->cbd_sc & BD_SC_READY) != 0) |
| 1004 | ; | 1049 | ; |
| 1005 | 1050 | ||
| 1006 | if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR) | 1051 | cp = cpm2cpu_addr(bdp->cbd_bufaddr); |
| 1007 | cp = (unsigned char *) (bdp->cbd_bufaddr); | ||
| 1008 | else | ||
| 1009 | cp = bus_to_virt(bdp->cbd_bufaddr); | ||
| 1010 | 1052 | ||
| 1011 | *cp = 13; | 1053 | *cp = 13; |
| 1012 | bdp->cbd_datlen = 1; | 1054 | bdp->cbd_datlen = 1; |
| @@ -1045,7 +1087,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) | |||
| 1045 | port = | 1087 | port = |
| 1046 | (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]]; | 1088 | (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]]; |
| 1047 | pinfo = (struct uart_cpm_port *)port; | 1089 | pinfo = (struct uart_cpm_port *)port; |
| 1048 | 1090 | ||
| 1049 | pinfo->flags |= FLAG_CONSOLE; | 1091 | pinfo->flags |= FLAG_CONSOLE; |
| 1050 | 1092 | ||
| 1051 | if (options) { | 1093 | if (options) { |
| @@ -1062,7 +1104,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) | |||
| 1062 | /* | 1104 | /* |
| 1063 | * Setup any port IO, connect any baud rate generators, | 1105 | * Setup any port IO, connect any baud rate generators, |
| 1064 | * etc. This is expected to be handled by board | 1106 | * etc. This is expected to be handled by board |
| 1065 | * dependant code | 1107 | * dependant code |
| 1066 | */ | 1108 | */ |
| 1067 | if (pinfo->set_lineif) | 1109 | if (pinfo->set_lineif) |
| 1068 | pinfo->set_lineif(pinfo); | 1110 | pinfo->set_lineif(pinfo); |
| @@ -1092,14 +1134,14 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) | |||
| 1092 | return 0; | 1134 | return 0; |
| 1093 | } | 1135 | } |
| 1094 | 1136 | ||
| 1095 | extern struct uart_driver cpm_reg; | 1137 | static struct uart_driver cpm_reg; |
| 1096 | static struct console cpm_scc_uart_console = { | 1138 | static struct console cpm_scc_uart_console = { |
| 1097 | .name "ttyCPM", | 1139 | .name = "ttyCPM", |
| 1098 | .write cpm_uart_console_write, | 1140 | .write = cpm_uart_console_write, |
| 1099 | .device uart_console_device, | 1141 | .device = uart_console_device, |
| 1100 | .setup cpm_uart_console_setup, | 1142 | .setup = cpm_uart_console_setup, |
| 1101 | .flags CON_PRINTBUFFER, | 1143 | .flags = CON_PRINTBUFFER, |
| 1102 | .index -1, | 1144 | .index = -1, |
| 1103 | .data = &cpm_reg, | 1145 | .data = &cpm_reg, |
| 1104 | }; | 1146 | }; |
| 1105 | 1147 | ||
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c index 8efbd6d1d6a4..4b0786e7eb7f 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2) | 6 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2) |
| 7 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) | 7 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) |
| 8 | * | 8 | * |
| 9 | * Copyright (C) 2004 Freescale Semiconductor, Inc. | 9 | * Copyright (C) 2004 Freescale Semiconductor, Inc. |
| 10 | * (C) 2004 Intracom, S.A. | 10 | * (C) 2004 Intracom, S.A. |
| 11 | * | 11 | * |
| @@ -82,6 +82,17 @@ void cpm_line_cr_cmd(int line, int cmd) | |||
| 82 | void smc1_lineif(struct uart_cpm_port *pinfo) | 82 | void smc1_lineif(struct uart_cpm_port *pinfo) |
| 83 | { | 83 | { |
| 84 | volatile cpm8xx_t *cp = cpmp; | 84 | volatile cpm8xx_t *cp = cpmp; |
| 85 | |||
| 86 | (void)cp; /* fix warning */ | ||
| 87 | #if defined (CONFIG_MPC885ADS) | ||
| 88 | /* Enable SMC1 transceivers */ | ||
| 89 | { | ||
| 90 | cp->cp_pepar |= 0x000000c0; | ||
| 91 | cp->cp_pedir &= ~0x000000c0; | ||
| 92 | cp->cp_peso &= ~0x00000040; | ||
| 93 | cp->cp_peso |= 0x00000080; | ||
| 94 | } | ||
| 95 | #elif defined (CONFIG_MPC86XADS) | ||
| 85 | unsigned int iobits = 0x000000c0; | 96 | unsigned int iobits = 0x000000c0; |
| 86 | 97 | ||
| 87 | if (!pinfo->is_portb) { | 98 | if (!pinfo->is_portb) { |
| @@ -93,41 +104,33 @@ void smc1_lineif(struct uart_cpm_port *pinfo) | |||
| 93 | ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits; | 104 | ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits; |
| 94 | ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits; | 105 | ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits; |
| 95 | } | 106 | } |
| 96 | |||
| 97 | #ifdef CONFIG_MPC885ADS | ||
| 98 | /* Enable SMC1 transceivers */ | ||
| 99 | { | ||
| 100 | volatile uint __iomem *bcsr1 = ioremap(BCSR1, 4); | ||
| 101 | uint tmp; | ||
| 102 | |||
| 103 | tmp = in_be32(bcsr1); | ||
| 104 | tmp &= ~BCSR1_RS232EN_1; | ||
| 105 | out_be32(bcsr1, tmp); | ||
| 106 | iounmap(bcsr1); | ||
| 107 | } | ||
| 108 | #endif | 107 | #endif |
| 109 | |||
| 110 | pinfo->brg = 1; | 108 | pinfo->brg = 1; |
| 111 | } | 109 | } |
| 112 | 110 | ||
| 113 | void smc2_lineif(struct uart_cpm_port *pinfo) | 111 | void smc2_lineif(struct uart_cpm_port *pinfo) |
| 114 | { | 112 | { |
| 115 | #ifdef CONFIG_MPC885ADS | ||
| 116 | volatile cpm8xx_t *cp = cpmp; | 113 | volatile cpm8xx_t *cp = cpmp; |
| 117 | volatile uint __iomem *bcsr1; | ||
| 118 | uint tmp; | ||
| 119 | 114 | ||
| 115 | (void)cp; /* fix warning */ | ||
| 116 | #if defined (CONFIG_MPC885ADS) | ||
| 120 | cp->cp_pepar |= 0x00000c00; | 117 | cp->cp_pepar |= 0x00000c00; |
| 121 | cp->cp_pedir &= ~0x00000c00; | 118 | cp->cp_pedir &= ~0x00000c00; |
| 122 | cp->cp_peso &= ~0x00000400; | 119 | cp->cp_peso &= ~0x00000400; |
| 123 | cp->cp_peso |= 0x00000800; | 120 | cp->cp_peso |= 0x00000800; |
| 121 | #elif defined (CONFIG_MPC86XADS) | ||
| 122 | unsigned int iobits = 0x00000c00; | ||
| 123 | |||
| 124 | if (!pinfo->is_portb) { | ||
| 125 | cp->cp_pbpar |= iobits; | ||
| 126 | cp->cp_pbdir &= ~iobits; | ||
| 127 | cp->cp_pbodr &= ~iobits; | ||
| 128 | } else { | ||
| 129 | ((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits; | ||
| 130 | ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits; | ||
| 131 | ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits; | ||
| 132 | } | ||
| 124 | 133 | ||
| 125 | /* Enable SMC2 transceivers */ | ||
| 126 | bcsr1 = ioremap(BCSR1, 4); | ||
| 127 | tmp = in_be32(bcsr1); | ||
| 128 | tmp &= ~BCSR1_RS232EN_2; | ||
| 129 | out_be32(bcsr1, tmp); | ||
| 130 | iounmap(bcsr1); | ||
| 131 | #endif | 134 | #endif |
| 132 | 135 | ||
| 133 | pinfo->brg = 2; | 136 | pinfo->brg = 2; |
| @@ -158,7 +161,7 @@ void scc4_lineif(struct uart_cpm_port *pinfo) | |||
| 158 | } | 161 | } |
| 159 | 162 | ||
| 160 | /* | 163 | /* |
| 161 | * Allocate DP-Ram and memory buffers. We need to allocate a transmit and | 164 | * Allocate DP-Ram and memory buffers. We need to allocate a transmit and |
| 162 | * receive buffer descriptors from dual port ram, and a character | 165 | * receive buffer descriptors from dual port ram, and a character |
| 163 | * buffer area from host mem. If we are allocating for the console we need | 166 | * buffer area from host mem. If we are allocating for the console we need |
| 164 | * to do it from bootmem | 167 | * to do it from bootmem |
| @@ -185,6 +188,8 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) | |||
| 185 | memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) + | 188 | memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) + |
| 186 | L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize); | 189 | L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize); |
| 187 | if (is_con) { | 190 | if (is_con) { |
| 191 | /* was hostalloc but changed cause it blows away the */ | ||
| 192 | /* large tlb mapping when pinning the kernel area */ | ||
| 188 | mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8)); | 193 | mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8)); |
| 189 | dma_addr = 0; | 194 | dma_addr = 0; |
| 190 | } else | 195 | } else |
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 805fb9097318..21a4e3b2cbda 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
| @@ -398,21 +398,31 @@ static int cpuset_path(const struct cpuset *cs, char *buf, int buflen) | |||
| 398 | * to continue to serve a useful existence. Next time it's released, | 398 | * to continue to serve a useful existence. Next time it's released, |
| 399 | * we will get notified again, if it still has 'notify_on_release' set. | 399 | * we will get notified again, if it still has 'notify_on_release' set. |
| 400 | * | 400 | * |
| 401 | * Note final arg to call_usermodehelper() is 0 - that means | 401 | * The final arg to call_usermodehelper() is 0, which means don't |
| 402 | * don't wait. Since we are holding the global cpuset_sem here, | 402 | * wait. The separate /sbin/cpuset_release_agent task is forked by |
| 403 | * and we are asking another thread (started from keventd) to rmdir a | 403 | * call_usermodehelper(), then control in this thread returns here, |
| 404 | * cpuset, we can't wait - or we'd deadlock with the removing thread | 404 | * without waiting for the release agent task. We don't bother to |
| 405 | * on cpuset_sem. | 405 | * wait because the caller of this routine has no use for the exit |
| 406 | * status of the /sbin/cpuset_release_agent task, so no sense holding | ||
| 407 | * our caller up for that. | ||
| 408 | * | ||
| 409 | * The simple act of forking that task might require more memory, | ||
| 410 | * which might need cpuset_sem. So this routine must be called while | ||
| 411 | * cpuset_sem is not held, to avoid a possible deadlock. See also | ||
| 412 | * comments for check_for_release(), below. | ||
| 406 | */ | 413 | */ |
| 407 | 414 | ||
| 408 | static int cpuset_release_agent(char *cpuset_str) | 415 | static void cpuset_release_agent(const char *pathbuf) |
| 409 | { | 416 | { |
| 410 | char *argv[3], *envp[3]; | 417 | char *argv[3], *envp[3]; |
| 411 | int i; | 418 | int i; |
| 412 | 419 | ||
| 420 | if (!pathbuf) | ||
| 421 | return; | ||
| 422 | |||
| 413 | i = 0; | 423 | i = 0; |
| 414 | argv[i++] = "/sbin/cpuset_release_agent"; | 424 | argv[i++] = "/sbin/cpuset_release_agent"; |
| 415 | argv[i++] = cpuset_str; | 425 | argv[i++] = (char *)pathbuf; |
| 416 | argv[i] = NULL; | 426 | argv[i] = NULL; |
| 417 | 427 | ||
| 418 | i = 0; | 428 | i = 0; |
| @@ -421,17 +431,29 @@ static int cpuset_release_agent(char *cpuset_str) | |||
| 421 | envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; | 431 | envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; |
| 422 | envp[i] = NULL; | 432 | envp[i] = NULL; |
| 423 | 433 | ||
| 424 | return call_usermodehelper(argv[0], argv, envp, 0); | 434 | call_usermodehelper(argv[0], argv, envp, 0); |
| 435 | kfree(pathbuf); | ||
| 425 | } | 436 | } |
| 426 | 437 | ||
| 427 | /* | 438 | /* |
| 428 | * Either cs->count of using tasks transitioned to zero, or the | 439 | * Either cs->count of using tasks transitioned to zero, or the |
| 429 | * cs->children list of child cpusets just became empty. If this | 440 | * cs->children list of child cpusets just became empty. If this |
| 430 | * cs is notify_on_release() and now both the user count is zero and | 441 | * cs is notify_on_release() and now both the user count is zero and |
| 431 | * the list of children is empty, send notice to user land. | 442 | * the list of children is empty, prepare cpuset path in a kmalloc'd |
| 443 | * buffer, to be returned via ppathbuf, so that the caller can invoke | ||
| 444 | * cpuset_release_agent() with it later on, once cpuset_sem is dropped. | ||
| 445 | * Call here with cpuset_sem held. | ||
| 446 | * | ||
| 447 | * This check_for_release() routine is responsible for kmalloc'ing | ||
| 448 | * pathbuf. The above cpuset_release_agent() is responsible for | ||
| 449 | * kfree'ing pathbuf. The caller of these routines is responsible | ||
| 450 | * for providing a pathbuf pointer, initialized to NULL, then | ||
| 451 | * calling check_for_release() with cpuset_sem held and the address | ||
| 452 | * of the pathbuf pointer, then dropping cpuset_sem, then calling | ||
| 453 | * cpuset_release_agent() with pathbuf, as set by check_for_release(). | ||
| 432 | */ | 454 | */ |
| 433 | 455 | ||
| 434 | static void check_for_release(struct cpuset *cs) | 456 | static void check_for_release(struct cpuset *cs, char **ppathbuf) |
| 435 | { | 457 | { |
| 436 | if (notify_on_release(cs) && atomic_read(&cs->count) == 0 && | 458 | if (notify_on_release(cs) && atomic_read(&cs->count) == 0 && |
| 437 | list_empty(&cs->children)) { | 459 | list_empty(&cs->children)) { |
| @@ -441,10 +463,9 @@ static void check_for_release(struct cpuset *cs) | |||
| 441 | if (!buf) | 463 | if (!buf) |
| 442 | return; | 464 | return; |
| 443 | if (cpuset_path(cs, buf, PAGE_SIZE) < 0) | 465 | if (cpuset_path(cs, buf, PAGE_SIZE) < 0) |
| 444 | goto out; | 466 | kfree(buf); |
| 445 | cpuset_release_agent(buf); | 467 | else |
| 446 | out: | 468 | *ppathbuf = buf; |
| 447 | kfree(buf); | ||
| 448 | } | 469 | } |
| 449 | } | 470 | } |
| 450 | 471 | ||
| @@ -727,14 +748,14 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf) | |||
| 727 | return 0; | 748 | return 0; |
| 728 | } | 749 | } |
| 729 | 750 | ||
| 730 | static int attach_task(struct cpuset *cs, char *buf) | 751 | static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf) |
| 731 | { | 752 | { |
| 732 | pid_t pid; | 753 | pid_t pid; |
| 733 | struct task_struct *tsk; | 754 | struct task_struct *tsk; |
| 734 | struct cpuset *oldcs; | 755 | struct cpuset *oldcs; |
| 735 | cpumask_t cpus; | 756 | cpumask_t cpus; |
| 736 | 757 | ||
| 737 | if (sscanf(buf, "%d", &pid) != 1) | 758 | if (sscanf(pidbuf, "%d", &pid) != 1) |
| 738 | return -EIO; | 759 | return -EIO; |
| 739 | if (cpus_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed)) | 760 | if (cpus_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed)) |
| 740 | return -ENOSPC; | 761 | return -ENOSPC; |
| @@ -777,7 +798,7 @@ static int attach_task(struct cpuset *cs, char *buf) | |||
| 777 | 798 | ||
| 778 | put_task_struct(tsk); | 799 | put_task_struct(tsk); |
| 779 | if (atomic_dec_and_test(&oldcs->count)) | 800 | if (atomic_dec_and_test(&oldcs->count)) |
| 780 | check_for_release(oldcs); | 801 | check_for_release(oldcs, ppathbuf); |
| 781 | return 0; | 802 | return 0; |
| 782 | } | 803 | } |
| 783 | 804 | ||
| @@ -801,6 +822,7 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us | |||
| 801 | struct cftype *cft = __d_cft(file->f_dentry); | 822 | struct cftype *cft = __d_cft(file->f_dentry); |
| 802 | cpuset_filetype_t type = cft->private; | 823 | cpuset_filetype_t type = cft->private; |
| 803 | char *buffer; | 824 | char *buffer; |
| 825 | char *pathbuf = NULL; | ||
| 804 | int retval = 0; | 826 | int retval = 0; |
| 805 | 827 | ||
| 806 | /* Crude upper limit on largest legitimate cpulist user might write. */ | 828 | /* Crude upper limit on largest legitimate cpulist user might write. */ |
| @@ -841,7 +863,7 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us | |||
| 841 | retval = update_flag(CS_NOTIFY_ON_RELEASE, cs, buffer); | 863 | retval = update_flag(CS_NOTIFY_ON_RELEASE, cs, buffer); |
| 842 | break; | 864 | break; |
| 843 | case FILE_TASKLIST: | 865 | case FILE_TASKLIST: |
| 844 | retval = attach_task(cs, buffer); | 866 | retval = attach_task(cs, buffer, &pathbuf); |
| 845 | break; | 867 | break; |
| 846 | default: | 868 | default: |
| 847 | retval = -EINVAL; | 869 | retval = -EINVAL; |
| @@ -852,6 +874,7 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us | |||
| 852 | retval = nbytes; | 874 | retval = nbytes; |
| 853 | out2: | 875 | out2: |
| 854 | up(&cpuset_sem); | 876 | up(&cpuset_sem); |
| 877 | cpuset_release_agent(pathbuf); | ||
| 855 | out1: | 878 | out1: |
| 856 | kfree(buffer); | 879 | kfree(buffer); |
| 857 | return retval; | 880 | return retval; |
| @@ -1357,6 +1380,7 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry) | |||
| 1357 | struct cpuset *cs = dentry->d_fsdata; | 1380 | struct cpuset *cs = dentry->d_fsdata; |
| 1358 | struct dentry *d; | 1381 | struct dentry *d; |
| 1359 | struct cpuset *parent; | 1382 | struct cpuset *parent; |
| 1383 | char *pathbuf = NULL; | ||
| 1360 | 1384 | ||
| 1361 | /* the vfs holds both inode->i_sem already */ | 1385 | /* the vfs holds both inode->i_sem already */ |
| 1362 | 1386 | ||
| @@ -1376,7 +1400,7 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry) | |||
| 1376 | update_cpu_domains(cs); | 1400 | update_cpu_domains(cs); |
| 1377 | list_del(&cs->sibling); /* delete my sibling from parent->children */ | 1401 | list_del(&cs->sibling); /* delete my sibling from parent->children */ |
| 1378 | if (list_empty(&parent->children)) | 1402 | if (list_empty(&parent->children)) |
| 1379 | check_for_release(parent); | 1403 | check_for_release(parent, &pathbuf); |
| 1380 | spin_lock(&cs->dentry->d_lock); | 1404 | spin_lock(&cs->dentry->d_lock); |
| 1381 | d = dget(cs->dentry); | 1405 | d = dget(cs->dentry); |
| 1382 | cs->dentry = NULL; | 1406 | cs->dentry = NULL; |
| @@ -1384,6 +1408,7 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry) | |||
| 1384 | cpuset_d_remove_dir(d); | 1408 | cpuset_d_remove_dir(d); |
| 1385 | dput(d); | 1409 | dput(d); |
| 1386 | up(&cpuset_sem); | 1410 | up(&cpuset_sem); |
| 1411 | cpuset_release_agent(pathbuf); | ||
| 1387 | return 0; | 1412 | return 0; |
| 1388 | } | 1413 | } |
| 1389 | 1414 | ||
| @@ -1483,10 +1508,13 @@ void cpuset_exit(struct task_struct *tsk) | |||
| 1483 | task_unlock(tsk); | 1508 | task_unlock(tsk); |
| 1484 | 1509 | ||
| 1485 | if (notify_on_release(cs)) { | 1510 | if (notify_on_release(cs)) { |
| 1511 | char *pathbuf = NULL; | ||
| 1512 | |||
| 1486 | down(&cpuset_sem); | 1513 | down(&cpuset_sem); |
| 1487 | if (atomic_dec_and_test(&cs->count)) | 1514 | if (atomic_dec_and_test(&cs->count)) |
| 1488 | check_for_release(cs); | 1515 | check_for_release(cs, &pathbuf); |
| 1489 | up(&cpuset_sem); | 1516 | up(&cpuset_sem); |
| 1517 | cpuset_release_agent(pathbuf); | ||
| 1490 | } else { | 1518 | } else { |
| 1491 | atomic_dec(&cs->count); | 1519 | atomic_dec(&cs->count); |
| 1492 | } | 1520 | } |
diff --git a/net/compat.c b/net/compat.c index be5d936dc423..d99ab9695893 100644 --- a/net/compat.c +++ b/net/compat.c | |||
| @@ -91,20 +91,11 @@ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov, | |||
| 91 | } else | 91 | } else |
| 92 | kern_msg->msg_name = NULL; | 92 | kern_msg->msg_name = NULL; |
| 93 | 93 | ||
| 94 | if(kern_msg->msg_iovlen > UIO_FASTIOV) { | ||
| 95 | kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), | ||
| 96 | GFP_KERNEL); | ||
| 97 | if(!kern_iov) | ||
| 98 | return -ENOMEM; | ||
| 99 | } | ||
| 100 | |||
| 101 | tot_len = iov_from_user_compat_to_kern(kern_iov, | 94 | tot_len = iov_from_user_compat_to_kern(kern_iov, |
| 102 | (struct compat_iovec __user *)kern_msg->msg_iov, | 95 | (struct compat_iovec __user *)kern_msg->msg_iov, |
| 103 | kern_msg->msg_iovlen); | 96 | kern_msg->msg_iovlen); |
| 104 | if(tot_len >= 0) | 97 | if(tot_len >= 0) |
| 105 | kern_msg->msg_iov = kern_iov; | 98 | kern_msg->msg_iov = kern_iov; |
| 106 | else if(kern_msg->msg_iovlen > UIO_FASTIOV) | ||
| 107 | kfree(kern_iov); | ||
| 108 | 99 | ||
| 109 | return tot_len; | 100 | return tot_len; |
| 110 | } | 101 | } |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 56db8f13e6cb..d0c3120d0233 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
| @@ -586,7 +586,7 @@ svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
| 586 | } | 586 | } |
| 587 | if (skb->stamp.tv_sec == 0) { | 587 | if (skb->stamp.tv_sec == 0) { |
| 588 | skb->stamp.tv_sec = xtime.tv_sec; | 588 | skb->stamp.tv_sec = xtime.tv_sec; |
| 589 | skb->stamp.tv_usec = xtime.tv_nsec * 1000; | 589 | skb->stamp.tv_usec = xtime.tv_nsec / NSEC_PER_USEC; |
| 590 | /* Don't enable netstamp, sunrpc doesn't | 590 | /* Don't enable netstamp, sunrpc doesn't |
| 591 | need that much accuracy */ | 591 | need that much accuracy */ |
| 592 | } | 592 | } |
