Commit 77f0154f authored by Tony Lindgren's avatar Tony Lindgren

Merge with ../linux-2.6

parents b8cf664c b5da623a
S3C24XX USB Host support
========================
Introduction
------------
This document details the S3C2410/S3C2440 in-built OHCI USB host support.
Configuration
-------------
Enable at least the following kernel options:
menuconfig:
Device Drivers --->
USB support --->
<*> Support for Host-side USB
<*> OHCI HCD support
.config:
CONFIG_USB
CONFIG_USB_OHCI_HCD
Once these options are configured, the standard set of USB device
drivers can be configured and used.
Board Support
-------------
The driver attaches to a platform device, which will need to be
added by the board specific support file in linux/arch/arm/mach-s3c2410,
such as mach-bast.c or mach-smdk2410.c
The platform device's platform_data field is only needed if the
board implements extra power control or over-current monitoring.
The OHCI driver does not ensure the state of the S3C2410's MISCCTRL
register, so if both ports are to be used for the host, then it is
the board support file's responsibility to ensure that the second
port is configured to be connected to the OHCI core.
Platform Data
-------------
See linux/include/asm-arm/arch-s3c2410/usb-control.h for the
descriptions of the platform device data. An implementation
can be found in linux/arch/arm/mach-s3c2410/usb-simtec.c .
The `struct s3c2410_hcd_info` contains a pair of functions
that get called to enable over-current detection, and to
control the port power status.
The ports are numbered 0 and 1.
power_control:
Called to enable or disable the power on the port.
enable_oc:
Called to enable or disable the over-current monitoring.
This should claim or release the resources being used to
check the power condition on the port, such as an IRQ.
report_oc:
The OHCI driver fills this field in for the over-current code
to call when there is a change to the over-current state on
an port. The ports argument is a bitmask of 1 bit per port,
with bit X being 1 for an over-current on port X.
The function s3c2410_usb_report_oc() has been provided to
ensure this is called correctly.
port[x]:
This is struct describes each port, 0 or 1. The platform driver
should set the flags field of each port to S3C_HCDFLG_USED if
the port is enabled.
Document Author
---------------
Ben Dooks, (c) 2005 Simtec Electronics
...@@ -533,6 +533,13 @@ ENTRY(__switch_to) ...@@ -533,6 +533,13 @@ ENTRY(__switch_to)
ldr r3, [r2, #TI_TP_VALUE] ldr r3, [r2, #TI_TP_VALUE]
stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack
ldr r6, [r2, #TI_CPU_DOMAIN]! ldr r6, [r2, #TI_CPU_DOMAIN]!
#if __LINUX_ARM_ARCH__ >= 6
#ifdef CONFIG_CPU_MPCORE
clrex
#else
strex r3, r4, [ip] @ Clear exclusive monitor
#endif
#endif
#if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT) #if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT)
mra r4, r5, acc0 mra r4, r5, acc0
stmia ip, {r4, r5} stmia ip, {r4, r5}
......
#if __LINUX_ARM_ARCH__ >= 6 #include <linux/config.h>
#if __LINUX_ARM_ARCH__ >= 6 && defined(CONFIG_CPU_MPCORE)
.macro bitop, instr .macro bitop, instr
mov r2, #1 mov r2, #1
and r3, r0, #7 @ Get bit offset and r3, r0, #7 @ Get bit offset
......
/* linux/arch/arm/mach-s3c2410/usb-simtec.c /* linux/arch/arm/mach-s3c2410/usb-simtec.c
* *
* Copyright (c) 2004 Simtec Electronics * Copyright (c) 2004,2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk> * Ben Dooks <ben@simtec.co.uk>
* *
* http://www.simtec.co.uk/products/EB2410ITX/ * http://www.simtec.co.uk/products/EB2410ITX/
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
* Modifications: * Modifications:
* 14-Sep-2004 BJD Created * 14-Sep-2004 BJD Created
* 18-Oct-2004 BJD Cleanups, and added code to report OC cleared * 18-Oct-2004 BJD Cleanups, and added code to report OC cleared
* 09-Aug-2005 BJD Renamed s3c2410_report_oc to s3c2410_usb_report_oc
* 09-Aug-2005 BJD Ports powered only if both are enabled
*/ */
#define DEBUG #define DEBUG
...@@ -47,13 +49,19 @@ ...@@ -47,13 +49,19 @@
* designed boards. * designed boards.
*/ */
static unsigned int power_state[2];
static void static void
usb_simtec_powercontrol(int port, int to) usb_simtec_powercontrol(int port, int to)
{ {
pr_debug("usb_simtec_powercontrol(%d,%d)\n", port, to); pr_debug("usb_simtec_powercontrol(%d,%d)\n", port, to);
if (port == 1) power_state[port] = to;
s3c2410_gpio_setpin(S3C2410_GPB4, to ? 0:1);
if (power_state[0] && power_state[1])
s3c2410_gpio_setpin(S3C2410_GPB4, 0);
else
s3c2410_gpio_setpin(S3C2410_GPB4, 1);
} }
static irqreturn_t static irqreturn_t
...@@ -63,10 +71,10 @@ usb_simtec_ocirq(int irq, void *pw, struct pt_regs *regs) ...@@ -63,10 +71,10 @@ usb_simtec_ocirq(int irq, void *pw, struct pt_regs *regs)
if (s3c2410_gpio_getpin(S3C2410_GPG10) == 0) { if (s3c2410_gpio_getpin(S3C2410_GPG10) == 0) {
pr_debug("usb_simtec: over-current irq (oc detected)\n"); pr_debug("usb_simtec: over-current irq (oc detected)\n");
s3c2410_report_oc(info, 3); s3c2410_usb_report_oc(info, 3);
} else { } else {
pr_debug("usb_simtec: over-current irq (oc cleared)\n"); pr_debug("usb_simtec: over-current irq (oc cleared)\n");
s3c2410_report_oc(info, 0); s3c2410_usb_report_oc(info, 0);
} }
return IRQ_HANDLED; return IRQ_HANDLED;
......
...@@ -383,6 +383,7 @@ static void __init build_mem_type_table(void) ...@@ -383,6 +383,7 @@ static void __init build_mem_type_table(void)
{ {
struct cachepolicy *cp; struct cachepolicy *cp;
unsigned int cr = get_cr(); unsigned int cr = get_cr();
unsigned int user_pgprot;
int cpu_arch = cpu_architecture(); int cpu_arch = cpu_architecture();
int i; int i;
...@@ -408,6 +409,9 @@ static void __init build_mem_type_table(void) ...@@ -408,6 +409,9 @@ static void __init build_mem_type_table(void)
} }
} }
cp = &cache_policies[cachepolicy];
user_pgprot = cp->pte;
/* /*
* ARMv6 and above have extended page tables. * ARMv6 and above have extended page tables.
*/ */
...@@ -426,11 +430,18 @@ static void __init build_mem_type_table(void) ...@@ -426,11 +430,18 @@ static void __init build_mem_type_table(void)
mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
/*
* Mark the device area as "shared device"
*/
mem_types[MT_DEVICE].prot_pte |= L_PTE_BUFFERABLE; mem_types[MT_DEVICE].prot_pte |= L_PTE_BUFFERABLE;
mem_types[MT_DEVICE].prot_sect |= PMD_SECT_BUFFERED; mem_types[MT_DEVICE].prot_sect |= PMD_SECT_BUFFERED;
}
cp = &cache_policies[cachepolicy]; /*
* User pages need to be mapped with the ASID
* (iow, non-global)
*/
user_pgprot |= L_PTE_ASID;
}
if (cpu_arch >= CPU_ARCH_ARMv5) { if (cpu_arch >= CPU_ARCH_ARMv5) {
mem_types[MT_LOW_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE; mem_types[MT_LOW_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE;
...@@ -448,7 +459,7 @@ static void __init build_mem_type_table(void) ...@@ -448,7 +459,7 @@ static void __init build_mem_type_table(void)
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
unsigned long v = pgprot_val(protection_map[i]); unsigned long v = pgprot_val(protection_map[i]);
v &= (~(PTE_BUFFERABLE|PTE_CACHEABLE)) | cp->pte; v &= (~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot;
protection_map[i] = __pgprot(v); protection_map[i] = __pgprot(v);
} }
......
...@@ -111,12 +111,6 @@ ENTRY(cpu_v6_switch_mm) ...@@ -111,12 +111,6 @@ ENTRY(cpu_v6_switch_mm)
mcr p15, 0, r1, c13, c0, 1 @ set context ID mcr p15, 0, r1, c13, c0, 1 @ set context ID
mov pc, lr mov pc, lr
#define nG (1 << 11)
#define APX (1 << 9)
#define AP1 (1 << 5)
#define AP0 (1 << 4)
#define XN (1 << 0)
/* /*
* cpu_v6_set_pte(ptep, pte) * cpu_v6_set_pte(ptep, pte)
* *
...@@ -139,24 +133,24 @@ ENTRY(cpu_v6_switch_mm) ...@@ -139,24 +133,24 @@ ENTRY(cpu_v6_switch_mm)
ENTRY(cpu_v6_set_pte) ENTRY(cpu_v6_set_pte)
str r1, [r0], #-2048 @ linux version str r1, [r0], #-2048 @ linux version
bic r2, r1, #0x00000ff0 bic r2, r1, #0x000007f0
bic r2, r2, #0x00000003 bic r2, r2, #0x00000003
orr r2, r2, #AP0 | 2 orr r2, r2, #PTE_EXT_AP0 | 2
tst r1, #L_PTE_WRITE tst r1, #L_PTE_WRITE
tstne r1, #L_PTE_DIRTY tstne r1, #L_PTE_DIRTY
orreq r2, r2, #APX orreq r2, r2, #PTE_EXT_APX
tst r1, #L_PTE_USER tst r1, #L_PTE_USER
orrne r2, r2, #AP1 | nG orrne r2, r2, #PTE_EXT_AP1
tstne r2, #APX tstne r2, #PTE_EXT_APX
bicne r2, r2, #APX | AP0 bicne r2, r2, #PTE_EXT_APX | PTE_EXT_AP0
tst r1, #L_PTE_YOUNG tst r1, #L_PTE_YOUNG
biceq r2, r2, #APX | AP1 | AP0 biceq r2, r2, #PTE_EXT_APX | PTE_EXT_AP_MASK
@ tst r1, #L_PTE_EXEC @ tst r1, #L_PTE_EXEC
@ orreq r2, r2, #XN @ orreq r2, r2, #PTE_EXT_XN
tst r1, #L_PTE_PRESENT tst r1, #L_PTE_PRESENT
moveq r2, #0 moveq r2, #0
......
...@@ -179,7 +179,7 @@ static int can_do_pal_halt = 1; ...@@ -179,7 +179,7 @@ static int can_do_pal_halt = 1;
static int __init nohalt_setup(char * str) static int __init nohalt_setup(char * str)
{ {
pal_halt = 0; pal_halt = can_do_pal_halt = 0;
return 1; return 1;
} }
__setup("nohalt", nohalt_setup); __setup("nohalt", nohalt_setup);
......
...@@ -1803,7 +1803,7 @@ static void __init fixup_device_tree(void) ...@@ -1803,7 +1803,7 @@ static void __init fixup_device_tree(void)
if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))
== PROM_ERROR) == PROM_ERROR)
return; return;
if (u3_rev != 0x35) if (u3_rev != 0x35 && u3_rev != 0x37)
return; return;
/* does it need fixup ? */ /* does it need fixup ? */
if (prom_getproplen(i2c, "interrupts") > 0) if (prom_getproplen(i2c, "interrupts") > 0)
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/net.h> #include <linux/net.h>
#include <linux/compat.h> #include <linux/compat.h>
#include <net/compat.h> #include <net/compat.h>
#include <net/sock.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/string.h> #include <asm/string.h>
...@@ -297,121 +298,165 @@ asmlinkage int solaris_sendmsg(int fd, struct sol_nmsghdr __user *user_msg, unsi ...@@ -297,121 +298,165 @@ asmlinkage int solaris_sendmsg(int fd, struct sol_nmsghdr __user *user_msg, unsi
{ {
struct socket *sock; struct socket *sock;
char address[MAX_SOCK_ADDR]; char address[MAX_SOCK_ADDR];
struct iovec iov[UIO_FASTIOV]; struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
unsigned char ctl[sizeof(struct cmsghdr) + 20]; unsigned char ctl[sizeof(struct cmsghdr) + 20];
unsigned char *ctl_buf = ctl; unsigned char *ctl_buf = ctl;
struct msghdr kern_msg; struct msghdr msg_sys;
int err, total_len; int err, ctl_len, iov_size, total_len;
if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) err = -EFAULT;
return -EFAULT; if (msghdr_from_user32_to_kern(&msg_sys, user_msg))
if(kern_msg.msg_iovlen > UIO_MAXIOV) goto out;
return -EINVAL;
err = verify_compat_iovec(&kern_msg, iov, address, VERIFY_READ); sock = sockfd_lookup(fd, &err);
if (err < 0) if (!sock)
goto out; goto out;
/* do not move before msg_sys is valid */
err = -EMSGSIZE;
if (msg_sys.msg_iovlen > UIO_MAXIOV)
goto out_put;
/* Check whether to allocate the iovec area*/
err = -ENOMEM;
iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
if (msg_sys.msg_iovlen > UIO_FASTIOV) {
iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
if (!iov)
goto out_put;
}
err = verify_compat_iovec(&msg_sys, iov, address, VERIFY_READ);
if (err < 0)
goto out_freeiov;
total_len = err; total_len = err;
if(kern_msg.msg_controllen) { err = -ENOBUFS;
struct sol_cmsghdr __user *ucmsg = kern_msg.msg_control; if (msg_sys.msg_controllen > INT_MAX)
goto out_freeiov;
ctl_len = msg_sys.msg_controllen;
if (ctl_len) {
struct sol_cmsghdr __user *ucmsg = msg_sys.msg_control;
unsigned long *kcmsg; unsigned long *kcmsg;
compat_size_t cmlen; compat_size_t cmlen;
if (kern_msg.msg_controllen <= sizeof(compat_size_t)) err = -EINVAL;
return -EINVAL; if (ctl_len <= sizeof(compat_size_t))
goto out_freeiov;
if(kern_msg.msg_controllen > sizeof(ctl)) { if (ctl_len > sizeof(ctl)) {
err = -ENOBUFS; err = -ENOBUFS;
ctl_buf = kmalloc(kern_msg.msg_controllen, GFP_KERNEL); ctl_buf = kmalloc(ctl_len, GFP_KERNEL);
if(!ctl_buf) if (!ctl_buf)
goto out_freeiov; goto out_freeiov;
} }
__get_user(cmlen, &ucmsg->cmsg_len); __get_user(cmlen, &ucmsg->cmsg_len);
kcmsg = (unsigned long *) ctl_buf; kcmsg = (unsigned long *) ctl_buf;
*kcmsg++ = (unsigned long)cmlen; *kcmsg++ = (unsigned long)cmlen;
err = -EFAULT; err = -EFAULT;
if(copy_from_user(kcmsg, &ucmsg->cmsg_level, if (copy_from_user(kcmsg, &ucmsg->cmsg_level,
kern_msg.msg_controllen - sizeof(compat_size_t))) ctl_len - sizeof(compat_size_t)))
goto out_freectl; goto out_freectl;
kern_msg.msg_control = ctl_buf; msg_sys.msg_control = ctl_buf;
} }
kern_msg.msg_flags = solaris_to_linux_msgflags(user_flags); msg_sys.msg_flags = solaris_to_linux_msgflags(user_flags);
lock_kernel(); if (sock->file->f_flags & O_NONBLOCK)
sock = sockfd_lookup(fd, &err); msg_sys.msg_flags |= MSG_DONTWAIT;
if (sock != NULL) { err = sock_sendmsg(sock, &msg_sys, total_len);
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: out_freectl:
/* N.B. Use kfree here, as kern_msg.msg_controllen might change? */ if (ctl_buf != ctl)
if(ctl_buf != ctl) sock_kfree_s(sock->sk, ctl_buf, ctl_len);
kfree(ctl_buf);
out_freeiov: out_freeiov:
if(kern_msg.msg_iov != iov) if (iov != iovstack)
kfree(kern_msg.msg_iov); sock_kfree_s(sock->sk, iov, iov_size);
out: out_put:
sockfd_put(sock);
out:
return err; return err;
} }
asmlinkage int solaris_recvmsg(int fd, struct sol_nmsghdr __user *user_msg, unsigned int user_flags) asmlinkage int solaris_recvmsg(int fd, struct sol_nmsghdr __user *user_msg, unsigned int user_flags)
{ {
struct iovec iovstack[UIO_FASTIOV];
struct msghdr kern_msg;
char addr[MAX_SOCK_ADDR];
struct socket *sock; struct socket *sock;
struct iovec iovstack[UIO_FASTIOV];
struct iovec *iov = iovstack; struct iovec *iov = iovstack;
struct msghdr msg_sys;
unsigned long cmsg_ptr;
int err, iov_size, total_len, len;
/* kernel mode address */
char addr[MAX_SOCK_ADDR];
/* user mode address pointers */
struct sockaddr __user *uaddr; struct sockaddr __user *uaddr;
int __user *uaddr_len; int __user *uaddr_len;
unsigned long cmsg_ptr;
int err, total_len, len = 0;
if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) if (msghdr_from_user32_to_kern(&msg_sys, user_msg))
return -EFAULT; return -EFAULT;
if(kern_msg.msg_iovlen > UIO_MAXIOV)
return -EINVAL;
uaddr = kern_msg.msg_name; sock = sockfd_lookup(fd, &err);
if (!sock)
goto out;
err = -EMSGSIZE;
if (msg_sys.msg_iovlen > UIO_MAXIOV)
goto out_put;
/* Check whether to allocate the iovec area*/
err = -ENOMEM;
iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
if (msg_sys.msg_iovlen > UIO_FASTIOV) {
iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
if (!iov)
goto out_put;
}
/*
* Save the user-mode address (verify_iovec will change the
* kernel msghdr to use the kernel address space)
*/
uaddr = (void __user *) msg_sys.msg_name;
uaddr_len = &user_msg->msg_namelen; uaddr_len = &user_msg->msg_namelen;
err = verify_compat_iovec(&kern_msg, iov, addr, VERIFY_WRITE); err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
if (err < 0) if (err < 0)
goto out; goto out_freeiov;
total_len = err; total_len = err;
cmsg_ptr = (unsigned long) kern_msg.msg_control; cmsg_ptr = (unsigned long) msg_sys.msg_control;
kern_msg.msg_flags = 0; msg_sys.msg_flags = MSG_CMSG_COMPAT;
lock_kernel(); if (sock->file->f_flags & O_NONBLOCK)
sock = sockfd_lookup(fd, &err); user_flags |= MSG_DONTWAIT;
if (sock != NULL) {
if (sock->file->f_flags & O_NONBLOCK) err = sock_recvmsg(sock, &msg_sys, total_len, user_flags);
user_flags |= MSG_DONTWAIT; if(err < 0)
err = sock_recvmsg(sock, &kern_msg, total_len, user_flags); goto out_freeiov;
if(err >= 0)
len = err; len = err;
sockfd_put(sock);
} if (uaddr != NULL) {
unlock_kernel(); err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len);
if (err < 0)
if(uaddr != NULL && err >= 0) goto out_freeiov;
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;
if(kern_msg.msg_iov != iov) out_freeiov:
kfree(kern_msg.msg_iov); if (iov != iovstack)
sock_kfree_s(sock->sk, iov, iov_size);
out_put:
sockfd_put(sock);
out: out:
if(err < 0) return err;
return err;
return len;
} }
/* /*
* i8xx_tco 0.07: TCO timer driver for i8xx chipsets * i8xx_tco: TCO timer driver for i8xx chipsets
* *
* (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved. * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
* http://www.kernelconcepts.de * http://www.kernelconcepts.de
...@@ -63,6 +63,9 @@ ...@@ -63,6 +63,9 @@
* 20050128 Wim Van Sebroeck <wim@iguana.be> * 20050128 Wim Van Sebroeck <wim@iguana.be>
* 0.07 Added support for the ICH4-M, ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW * 0.07 Added support for the ICH4-M, ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW
* chipsets. Also added support for the "undocumented" ICH7 chipset. * chipsets. Also added support for the "undocumented" ICH7 chipset.
* 20050807 Wim Van Sebroeck <wim@iguana.be>
* 0.08 Make sure that the watchdog is only "armed" when started.
* (Kernel Bug 4251)
*/ */
/* /*
...@@ -87,7 +90,7 @@ ...@@ -87,7 +90,7 @@
#include "i8xx_tco.h" #include "i8xx_tco.h"
/* Module and version information */ /* Module and version information */
#define TCO_VERSION "0.07" #define TCO_VERSION "0.08"
#define TCO_MODULE_NAME "i8xx TCO timer" #define TCO_MODULE_NAME "i8xx TCO timer"
#define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION #define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION
#define PFX TCO_MODULE_NAME ": " #define PFX TCO_MODULE_NAME ": "
...@@ -125,10 +128,18 @@ static int tco_timer_start (void) ...@@ -125,10 +128,18 @@ static int tco_timer_start (void)
unsigned char val; unsigned char val;
spin_lock(&tco_lock); 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 = inb (TCO1_CNT + 1);
val &= 0xf7; val &= 0xf7;
outb (val, TCO1_CNT + 1); outb (val, TCO1_CNT + 1);
val = inb (TCO1_CNT + 1); val = inb (TCO1_CNT + 1);
spin_unlock(&tco_lock); spin_unlock(&tco_lock);
if (val & 0x08) if (val & 0x08)
...@@ -138,13 +149,20 @@ static int tco_timer_start (void) ...@@ -138,13 +149,20 @@ static int tco_timer_start (void)
static int tco_timer_stop (void) static int tco_timer_stop (void)
{ {
unsigned char val; unsigned char val, val1;
spin_lock(&tco_lock); spin_lock(&tco_lock);
/* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */
val = inb (TCO1_CNT + 1); val = inb (TCO1_CNT + 1);
val |= 0x08; val |= 0x08;
outb (val, TCO1_CNT + 1); outb (val, TCO1_CNT + 1);
val = inb (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); spin_unlock(&tco_lock);
if ((val & 0x08) == 0) if ((val & 0x08) == 0)
...@@ -155,6 +173,7 @@ static int tco_timer_stop (void) ...@@ -155,6 +173,7 @@ static int tco_timer_stop (void)
static int tco_timer_keepalive (void) static int tco_timer_keepalive (void)
{ {
spin_lock(&tco_lock); spin_lock(&tco_lock);
/* Reload the timer by writing to the TCO Timer Reload register */
outb (0x01, TCO1_RLD); outb (0x01, TCO1_RLD);
spin_unlock(&tco_lock); spin_unlock(&tco_lock);
return 0; return 0;
...@@ -417,9 +436,8 @@ static unsigned char __init i8xx_tco_getdevice (void) ...@@ -417,9 +436,8 @@ static unsigned char __init i8xx_tco_getdevice (void)
printk (KERN_ERR PFX "failed to get TCOBASE address\n"); printk (KERN_ERR PFX "failed to get TCOBASE address\n");
return 0; return 0;
} }
/*
* Check chipset's NO_REBOOT bit /* Check chipset's NO_REBOOT bit */
*/
pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1);
if (val1 & 0x02) { if (val1 & 0x02) {
val1 &= 0xfd; val1 &= 0xfd;
...@@ -430,6 +448,10 @@ static unsigned char __init i8xx_tco_getdevice (void) ...@@ -430,6 +448,10 @@ static unsigned char __init i8xx_tco_getdevice (void)
return 0; /* Cannot reset NO_REBOOT bit */ 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 */ /* Set the TCO_EN bit in SMI_EN register */
if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) { if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) {
printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
...@@ -505,17 +527,10 @@ out: ...@@ -505,17 +527,10 @@ out:
static void __exit watchdog_cleanup (void) static void __exit watchdog_cleanup (void)
{ {
u8 val;
/* Stop the timer before we leave */ /* Stop the timer before we leave */
if (!nowayout) if (!nowayout)
tco_timer_stop (); 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 */ /* Deregister */
misc_deregister (&i8xx_tco_miscdev); misc_deregister (&i8xx_tco_miscdev);
unregister_reboot_notifier(&i8xx_tco_notifier); unregister_reboot_notifier(&i8xx_tco_notifier);
......
...@@ -23,8 +23,8 @@ ...@@ -23,8 +23,8 @@
#include <asm/sibyte/sb1250_smbus.h> #include <asm/sibyte/sb1250_smbus.h>
static struct i2c_algo_sibyte_data sibyte_board_data[2] = { static struct i2c_algo_sibyte_data sibyte_board_data[2] = {
{ NULL, 0, (void *) (KSEG1+A_SMB_BASE(0)) }, { NULL, 0, (void *) (CKSEG1+A_SMB_BASE(0)) },
{ NULL, 1, (void *) (KSEG1+A_SMB_BASE(1)) } { NULL, 1, (void *) (CKSEG1+A_SMB_BASE(1)) }
}; };
static struct i2c_adapter sibyte_board_adapter[2] = { static struct i2c_adapter sibyte_board_adapter[2] = {
......
...@@ -1220,7 +1220,7 @@ static int ide_disk_probe(struct device *dev) ...@@ -1220,7 +1220,7 @@ static int ide_disk_probe(struct device *dev)
goto failed; goto failed;
g = alloc_disk_node(1 << PARTN_BITS, g = alloc_disk_node(1 << PARTN_BITS,
pcibus_to_node(drive->hwif->pci_dev->bus)); hwif_to_node(drive->hwif));
if (!g) if (!g)
goto out_free_idkp; goto out_free_idkp;
......
...@@ -960,15 +960,6 @@ static void save_match(ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match) ...@@ -960,15 +960,6 @@ static void save_match(ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match)
} }
#endif /* MAX_HWIFS > 1 */ #endif /* MAX_HWIFS > 1 */
static inline int hwif_to_node(ide_hwif_t *hwif)
{
if (hwif->pci_dev)
return pcibus_to_node(hwif->pci_dev->bus);
else
/* Add ways to determine the node of other busses here */
return -1;
}
/* /*
* init request queue * init request queue
*/ */
......
...@@ -275,9 +275,9 @@ static int __init ns558_init(void) ...@@ -275,9 +275,9 @@ static int __init ns558_init(void)
static void __exit ns558_exit(void) static void __exit ns558_exit(void)
{ {
struct ns558 *ns558; struct ns558 *ns558, *safe;
list_for_each_entry(ns558, &ns558_list, node) { list_for_each_entry_safe(ns558, safe, &ns558_list, node) {
gameport_unregister_port(ns558->gameport); gameport_unregister_port(ns558->gameport);
release_region(ns558->io & ~(ns558->size - 1), ns558->size); release_region(ns558->io & ~(ns558->size - 1), ns558->size);
kfree(ns558); kfree(ns558);
......
...@@ -188,7 +188,7 @@ config DVB_BCM3510 ...@@ -188,7 +188,7 @@ config DVB_BCM3510
support this frontend. support this frontend.
config DVB_LGDT330X config DVB_LGDT330X
tristate "LGDT3302 or LGDT3303 based (DViCO FusionHDTV Gold)" tristate "LG Electronics LGDT3302/LGDT3303 based"
depends on DVB_CORE depends on DVB_CORE
help help
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
......
...@@ -172,38 +172,6 @@ static int lgdt330x_SwReset(struct lgdt330x_state* state) ...@@ -172,38 +172,6 @@ static int lgdt330x_SwReset(struct lgdt330x_state* state)
} }
} }
#ifdef MUTE_TDA9887
static int i2c_write_ntsc_demod (struct lgdt330x_state* state, u8 buf[2])
{
struct i2c_msg msg =
{ .addr = 0x43,
.flags = 0,
.buf = buf,
.len = 2 };
int err;
if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, msg.buf[0], msg.buf[1], err);
if (err < 0)
return err;
else
return -EREMOTEIO;
}
return 0;
}
static void fiddle_with_ntsc_if_demod(struct lgdt330x_state* state)
{
// Experimental code
u8 buf0[] = {0x00, 0x20};
u8 buf1[] = {0x01, 0x00};
u8 buf2[] = {0x02, 0x00};
i2c_write_ntsc_demod(state, buf0);
i2c_write_ntsc_demod(state, buf1);
i2c_write_ntsc_demod(state, buf2);
}
#endif
static int lgdt330x_init(struct dvb_frontend* fe) static int lgdt330x_init(struct dvb_frontend* fe)
{ {
...@@ -267,9 +235,6 @@ static int lgdt330x_init(struct dvb_frontend* fe) ...@@ -267,9 +235,6 @@ static int lgdt330x_init(struct dvb_frontend* fe)
chip_name = "LGDT3303"; chip_name = "LGDT3303";
err = i2c_write_demod_bytes(state, lgdt3303_init_data, err = i2c_write_demod_bytes(state, lgdt3303_init_data,
sizeof(lgdt3303_init_data)); sizeof(lgdt3303_init_data));
#ifdef MUTE_TDA9887
fiddle_with_ntsc_if_demod(state);
#endif
break; break;
default: default:
chip_name = "undefined"; chip_name = "undefined";
...@@ -772,7 +737,7 @@ error: ...@@ -772,7 +737,7 @@ error:
static struct dvb_frontend_ops lgdt3302_ops = { static struct dvb_frontend_ops lgdt3302_ops = {
.info = { .info = {
.name= "LG Electronics LGDT3302/LGDT3303 VSB/QAM Frontend", .name= "LG Electronics LGDT3302 VSB/QAM Frontend",
.type = FE_ATSC, .type = FE_ATSC,
.frequency_min= 54000000, .frequency_min= 54000000,
.frequency_max= 858000000, .frequency_max= 858000000,
......
...@@ -53,6 +53,9 @@ config I2O_CONFIG ...@@ -53,6 +53,9 @@ config I2O_CONFIG
To compile this support as a module, choose M here: the To compile this support as a module, choose M here: the
module will be called i2o_config. 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 config I2O_CONFIG_OLD_IOCTL
bool "Enable ioctls (OBSOLETE)" bool "Enable ioctls (OBSOLETE)"
depends on I2O_CONFIG depends on I2O_CONFIG
......
This diff is collapsed.
...@@ -32,6 +32,8 @@ ...@@ -32,6 +32,8 @@
#include <linux/i2o.h> #include <linux/i2o.h>
#include "core.h" #include "core.h"
#define OSM_DESCRIPTION "I2O-subsystem"
/* PCI device id table for all I2O controllers */ /* PCI device id table for all I2O controllers */
static struct pci_device_id __devinitdata i2o_pci_ids[] = { static struct pci_device_id __devinitdata i2o_pci_ids[] = {
{PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)}, {PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)},
...@@ -66,6 +68,8 @@ static void i2o_pci_free(struct i2o_controller *c) ...@@ -66,6 +68,8 @@ static void i2o_pci_free(struct i2o_controller *c)
if (c->base.virt) if (c->base.virt)
iounmap(c->base.virt); iounmap(c->base.virt);
pci_release_regions(c->pdev);
} }
/** /**
...@@ -84,6 +88,11 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) ...@@ -84,6 +88,11 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
int i; int i;
if (pci_request_regions(pdev, OSM_DESCRIPTION)) {
printk(KERN_ERR "%s: device already claimed\n", c->name);
return -ENODEV;
}
for (i = 0; i < 6; i++) { for (i = 0; i < 6; i++) {
/* Skip I/O spaces */ /* Skip I/O spaces */
if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) { if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
...@@ -138,6 +147,7 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) ...@@ -138,6 +147,7 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
c->base.virt = ioremap_nocache(c->base.phys, c->base.len); c->base.virt = ioremap_nocache(c->base.phys, c->base.len);
if (!c->base.virt) { if (!c->base.virt) {
printk(KERN_ERR "%s: Unable to map controller.\n", c->name); printk(KERN_ERR "%s: Unable to map controller.\n", c->name);
i2o_pci_free(c);
return -ENOMEM; return -ENOMEM;
} }
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
#include "wbsd.h" #include "wbsd.h"
#define DRIVER_NAME "wbsd" #define DRIVER_NAME "wbsd"
#define DRIVER_VERSION "1.2" #define DRIVER_VERSION "1.3"
#ifdef CONFIG_MMC_DEBUG #ifdef CONFIG_MMC_DEBUG
#define DBG(x...) \ #define DBG(x...) \
......
...@@ -130,12 +130,11 @@ struct sixpack { ...@@ -130,12 +130,11 @@ struct sixpack {
#define AX25_6PACK_HEADER_LEN 0 #define AX25_6PACK_HEADER_LEN 0
static void sp_start_tx_timer(struct sixpack *);
static void sixpack_decode(struct sixpack *, unsigned char[], int); static void sixpack_decode(struct sixpack *, unsigned char[], int);
static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char); static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char);
/* /*
* perform the persistence/slottime algorithm for CSMA access. If the * Perform the persistence/slottime algorithm for CSMA access. If the
* persistence check was successful, write the data to the serial driver. * persistence check was successful, write the data to the serial driver.
* Note that in case of DAMA operation, the data is not sent here. * Note that in case of DAMA operation, the data is not sent here.
*/ */
...@@ -143,7 +142,7 @@ static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char); ...@@ -143,7 +142,7 @@ static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char);
static void sp_xmit_on_air(unsigned long channel) static void sp_xmit_on_air(unsigned long channel)
{ {
struct sixpack *sp = (struct sixpack *) channel; struct sixpack *sp = (struct sixpack *) channel;
int actual; int actual, when = sp->slottime;
static unsigned char random; static unsigned char random;
random = random * 17 + 41; random = random * 17 + 41;
...@@ -159,20 +158,10 @@ static void sp_xmit_on_air(unsigned long channel) ...@@ -159,20 +158,10 @@ static void sp_xmit_on_air(unsigned long channel)
sp->tty->driver->write(sp->tty, &sp->led_state, 1); sp->tty->driver->write(sp->tty, &sp->led_state, 1);
sp->status2 = 0; sp->status2 = 0;
} else } else
sp_start_tx_timer(sp); mod_timer(&sp->tx_t, jiffies + ((when + 1) * HZ) / 100);
} }
/* ----> 6pack timer interrupt handler and friends. <---- */ /* ----> 6pack timer interrupt handler and friends. <---- */
static void sp_start_tx_timer(struct sixpack *sp)
{
int when = sp->slottime;
del_timer(&sp->tx_t);
sp->tx_t.data = (unsigned long) sp;
sp->tx_t.function = sp_xmit_on_air;
sp->tx_t.expires = jiffies + ((when + 1) * HZ) / 100;
add_timer(&sp->tx_t);
}
/* Encapsulate one AX.25 frame and stuff into a TTY queue. */ /* Encapsulate one AX.25 frame and stuff into a TTY queue. */
static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len) static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
...@@ -243,8 +232,7 @@ static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len) ...@@ -243,8 +232,7 @@ static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
sp->xleft = count; sp->xleft = count;
sp->xhead = sp->xbuff; sp->xhead = sp->xbuff;
sp->status2 = count; sp->status2 = count;
if (sp->duplex == 0) sp_xmit_on_air((unsigned long)sp);
sp_start_tx_timer(sp);
} }
return; return;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#define __KERNEL_SYSCALLS__ #define __KERNEL_SYSCALLS__
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -459,10 +460,6 @@ static struct task_struct *kenvctrld_task; ...@@ -459,10 +460,6 @@ static struct task_struct *kenvctrld_task;
static int kenvctrld(void *__unused) static int kenvctrld(void *__unused)
{ {
daemonize("kenvctrld");
allow_signal(SIGKILL);
kenvctrld_task = current;
printk(KERN_INFO "bbc_envctrl: kenvctrld starting...\n"); printk(KERN_INFO "bbc_envctrl: kenvctrld starting...\n");
last_warning_jiffies = jiffies - WARN_INTERVAL; last_warning_jiffies = jiffies - WARN_INTERVAL;
for (;;) { for (;;) {
...@@ -470,7 +467,7 @@ static int kenvctrld(void *__unused) ...@@ -470,7 +467,7 @@ static int kenvctrld(void *__unused)
struct bbc_fan_control *fp; struct bbc_fan_control *fp;
msleep_interruptible(POLL_INTERVAL); msleep_interruptible(POLL_INTERVAL);
if (signal_pending(current)) if (kthread_should_stop())
break; break;
for (tp = all_bbc_temps; tp; tp = tp->next) { for (tp = all_bbc_temps; tp; tp = tp->next) {
...@@ -577,7 +574,6 @@ int bbc_envctrl_init(void) ...@@ -577,7 +574,6 @@ int bbc_envctrl_init(void)
int temp_index = 0; int temp_index = 0;
int fan_index = 0; int fan_index = 0;
int devidx = 0; int devidx = 0;
int err = 0;
while ((echild = bbc_i2c_getdev(devidx++)) != NULL) { while ((echild = bbc_i2c_getdev(devidx++)) != NULL) {
if (!strcmp(echild->prom_name, "temperature")) if (!strcmp(echild->prom_name, "temperature"))
...@@ -585,9 +581,13 @@ int bbc_envctrl_init(void) ...@@ -585,9 +581,13 @@ int bbc_envctrl_init(void)
if (!strcmp(echild->prom_name, "fan-control")) if (!strcmp(echild->prom_name, "fan-control"))
attach_one_fan(echild, fan_index++); attach_one_fan(echild, fan_index++);
} }
if (temp_index != 0 && fan_index != 0) if (temp_index != 0 && fan_index != 0) {
err = kernel_thread(kenvctrld, NULL, CLONE_FS | CLONE_FILES); kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld");
return err; if (IS_ERR(kenvctrld_task))
return PTR_ERR(kenvctrld_task);
}
return 0;
} }
static void destroy_one_temp(struct bbc_cpu_temperature *tp) static void destroy_one_temp(struct bbc_cpu_temperature *tp)
...@@ -607,26 +607,7 @@ void bbc_envctrl_cleanup(void) ...@@ -607,26 +607,7 @@ void bbc_envctrl_cleanup(void)
struct bbc_cpu_temperature *tp; struct bbc_cpu_temperature *tp;
struct bbc_fan_control *fp; struct bbc_fan_control *fp;
if (kenvctrld_task != NULL) { kthread_stop(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;
}
tp = all_bbc_temps; tp = all_bbc_temps;
while (tp != NULL) { while (tp != NULL) {
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/ioport.h> #include <linux/ioport.h>
...@@ -1010,16 +1011,13 @@ static int kenvctrld(void *__unused) ...@@ -1010,16 +1011,13 @@ static int kenvctrld(void *__unused)
poll_interval = 5000; /* TODO env_mon_interval */ poll_interval = 5000; /* TODO env_mon_interval */
daemonize("kenvctrld");
allow_signal(SIGKILL);
kenvctrld_task = current;
printk(KERN_INFO "envctrl: %s starting...\n", current->comm); printk(KERN_INFO "envctrl: %s starting...\n", current->comm);
for (;;) { for (;;) {
if(msleep_interruptible(poll_interval)) msleep_interruptible(poll_interval);
break;
if (kthread_should_stop())
break;
for (whichcpu = 0; whichcpu < ENVCTRL_MAX_CPU; ++whichcpu) { for (whichcpu = 0; whichcpu < ENVCTRL_MAX_CPU; ++whichcpu) {
if (0 < envctrl_read_cpu_info(whichcpu, cputemp, if (0 < envctrl_read_cpu_info(whichcpu, cputemp,
ENVCTRL_CPUTEMP_MON, ENVCTRL_CPUTEMP_MON,
...@@ -1041,7 +1039,6 @@ static int kenvctrld(void *__unused) ...@@ -1041,7 +1039,6 @@ static int kenvctrld(void *__unused)
static int __init envctrl_init(void) static int __init envctrl_init(void)
{ {
#ifdef CONFIG_PCI
struct linux_ebus *ebus = NULL; struct linux_ebus *ebus = NULL;
struct linux_ebus_device *edev = NULL; struct linux_ebus_device *edev = NULL;
struct linux_ebus_child *edev_child = NULL; struct linux_ebus_child *edev_child = NULL;
...@@ -1118,9 +1115,11 @@ done: ...@@ -1118,9 +1115,11 @@ done:
i2c_childlist[i].addr, (0 == i) ? ("\n") : (" ")); i2c_childlist[i].addr, (0 == i) ? ("\n") : (" "));
} }
err = kernel_thread(kenvctrld, NULL, CLONE_FS | CLONE_FILES); kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld");
if (err < 0) if (IS_ERR(kenvctrld_task)) {
err = PTR_ERR(kenvctrld_task);
goto out_deregister; goto out_deregister;
}
return 0; return 0;
...@@ -1133,37 +1132,13 @@ out_iounmap: ...@@ -1133,37 +1132,13 @@ out_iounmap:
kfree(i2c_childlist[i].tables); kfree(i2c_childlist[i].tables);
} }
return err; return err;
#else
return -ENODEV;
#endif
} }
static void __exit envctrl_cleanup(void) static void __exit envctrl_cleanup(void)
{ {
int i; int i;
if (NULL != kenvctrld_task) { kthread_stop(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;
}
iounmap(i2c); iounmap(i2c);
misc_deregister(&envctrl_dev); misc_deregister(&envctrl_dev);
......
...@@ -907,9 +907,13 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev ...@@ -907,9 +907,13 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
raptorFlag = TRUE; raptorFlag = TRUE;
} }
if (pci_request_regions(pDev, "dpt_i2o")) {
PERROR("dpti: adpt_config_hba: pci request region failed\n");
return -EINVAL;
}
base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size); base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size);
if (!base_addr_virt) { if (!base_addr_virt) {
pci_release_regions(pDev);
PERROR("dpti: adpt_config_hba: io remap failed\n"); PERROR("dpti: adpt_config_hba: io remap failed\n");
return -EINVAL; return -EINVAL;
} }
...@@ -919,6 +923,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev ...@@ -919,6 +923,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
if (!msg_addr_virt) { if (!msg_addr_virt) {
PERROR("dpti: adpt_config_hba: io remap failed on BAR1\n"); PERROR("dpti: adpt_config_hba: io remap failed on BAR1\n");
iounmap(base_addr_virt); iounmap(base_addr_virt);
pci_release_regions(pDev);
return -EINVAL; return -EINVAL;
} }
} else { } else {
...@@ -932,6 +937,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev ...@@ -932,6 +937,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
iounmap(msg_addr_virt); iounmap(msg_addr_virt);
} }
iounmap(base_addr_virt); iounmap(base_addr_virt);
pci_release_regions(pDev);
return -ENOMEM; return -ENOMEM;
} }
memset(pHba, 0, sizeof(adpt_hba)); memset(pHba, 0, sizeof(adpt_hba));
...@@ -1027,6 +1033,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba) ...@@ -1027,6 +1033,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba)
up(&adpt_configuration_lock); up(&adpt_configuration_lock);
iounmap(pHba->base_addr_virt); iounmap(pHba->base_addr_virt);
pci_release_regions(pHba->pDev);
if(pHba->msg_addr_virt != pHba->base_addr_virt){ if(pHba->msg_addr_virt != pHba->base_addr_virt){
iounmap(pHba->msg_addr_virt); iounmap(pHba->msg_addr_virt);
} }
......
...@@ -385,6 +385,7 @@ int ata_scsi_error(struct Scsi_Host *host) ...@@ -385,6 +385,7 @@ int ata_scsi_error(struct Scsi_Host *host)
* appropriate place * appropriate place
*/ */
host->host_failed--; host->host_failed--;
INIT_LIST_HEAD(&host->eh_cmd_q);
DPRINTK("EXIT\n"); DPRINTK("EXIT\n");
return 0; return 0;
......
...@@ -468,7 +468,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc) ...@@ -468,7 +468,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
for (i = 0; i < last; i++) { for (i = 0; i < last; i++) {
buf[idx++] = cpu_to_le32(sg_dma_address(&sg[i])); buf[idx++] = cpu_to_le32(sg_dma_address(&sg[i]));
buf[idx++] = cpu_to_le32(sg_dma_len(&sg[i])); buf[idx++] = cpu_to_le32(sg_dma_len(&sg[i]));
total_len += sg[i].length; total_len += sg_dma_len(&sg[i]);
} }
buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT); buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT);
sgt_len = idx * 4; sgt_len = idx * 4;
......
...@@ -336,9 +336,23 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, ...@@ -336,9 +336,23 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
unsigned long flags; unsigned long flags;
const int size = sizeof(struct scsi_target) const int size = sizeof(struct scsi_target)
+ shost->transportt->target_size; + shost->transportt->target_size;
struct scsi_target *starget = kmalloc(size, GFP_ATOMIC); struct scsi_target *starget;
struct scsi_target *found_target; struct scsi_target *found_target;
/*
* Obtain the real parent from the transport. The transport
* is allowed to fail (no error) if there is nothing at that
* target id.
*/
if (shost->transportt->target_parent) {
spin_lock_irqsave(shost->host_lock, flags);
parent = shost->transportt->target_parent(shost, channel, id);
spin_unlock_irqrestore(shost->host_lock, flags);
if (!parent)
return NULL;
}
starget = kmalloc(size, GFP_KERNEL);
if (!starget) { if (!starget) {
printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
return NULL; return NULL;
......
...@@ -1022,6 +1022,23 @@ static int fc_rport_match(struct attribute_container *cont, ...@@ -1022,6 +1022,23 @@ static int fc_rport_match(struct attribute_container *cont,
return &i->rport_attr_cont.ac == cont; return &i->rport_attr_cont.ac == cont;
} }
/*
* Must be called with shost->host_lock held
*/
static struct device *fc_target_parent(struct Scsi_Host *shost,
int channel, uint id)
{
struct fc_rport *rport;
list_for_each_entry(rport, &fc_host_rports(shost), peers)
if ((rport->channel == channel) &&
(rport->scsi_target_id == id))
return &rport->dev;
return NULL;
}
struct scsi_transport_template * struct scsi_transport_template *
fc_attach_transport(struct fc_function_template *ft) fc_attach_transport(struct fc_function_template *ft)
{ {
...@@ -1057,6 +1074,8 @@ fc_attach_transport(struct fc_function_template *ft) ...@@ -1057,6 +1074,8 @@ fc_attach_transport(struct fc_function_template *ft)
/* Transport uses the shost workq for scsi scanning */ /* Transport uses the shost workq for scsi scanning */
i->t.create_work_queue = 1; i->t.create_work_queue = 1;
i->t.target_parent = fc_target_parent;
/* /*
* Setup SCSI Target Attributes. * Setup SCSI Target Attributes.
......
...@@ -40,13 +40,15 @@ ...@@ -40,13 +40,15 @@
#define TX_NUM_FIFO 4 #define TX_NUM_FIFO 4
#define TX_BUF_SIZE 32 #define TX_BUF_SIZE 32
#define SCC_WAIT_CLOSING 100
struct uart_cpm_port { struct uart_cpm_port {
struct uart_port port; struct uart_port port;
u16 rx_nrfifos; u16 rx_nrfifos;
u16 rx_fifosize; u16 rx_fifosize;
u16 tx_nrfifos; u16 tx_nrfifos;
u16 tx_fifosize; u16 tx_fifosize;
smc_t *smcp; smc_t *smcp;
smc_uart_t *smcup; smc_uart_t *smcup;
scc_t *sccp; scc_t *sccp;
scc_uart_t *sccup; scc_uart_t *sccup;
...@@ -67,6 +69,8 @@ struct uart_cpm_port { ...@@ -67,6 +69,8 @@ struct uart_cpm_port {
int bits; int bits;
/* Keep track of 'odd' SMC2 wirings */ /* Keep track of 'odd' SMC2 wirings */
int is_portb; int is_portb;
/* wait on close if needed */
int wait_closing;
}; };
extern int cpm_uart_port_map[UART_NR]; extern int cpm_uart_port_map[UART_NR];
......
This diff is collapsed.
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2) * Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2)
* Pantelis Antoniou (panto@intracom.gr) (CPM1) * Pantelis Antoniou (panto@intracom.gr) (CPM1)
* *
* Copyright (C) 2004 Freescale Semiconductor, Inc. * Copyright (C) 2004 Freescale Semiconductor, Inc.
* (C) 2004 Intracom, S.A. * (C) 2004 Intracom, S.A.
* *
...@@ -82,6 +82,17 @@ void cpm_line_cr_cmd(int line, int cmd) ...@@ -82,6 +82,17 @@ void cpm_line_cr_cmd(int line, int cmd)
void smc1_lineif(struct uart_cpm_port *pinfo) void smc1_lineif(struct uart_cpm_port *pinfo)
{ {
volatile cpm8xx_t *cp = cpmp; 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; unsigned int iobits = 0x000000c0;
if (!pinfo->is_portb) { if (!pinfo->is_portb) {
...@@ -93,41 +104,33 @@ void smc1_lineif(struct uart_cpm_port *pinfo) ...@@ -93,41 +104,33 @@ void smc1_lineif(struct uart_cpm_port *pinfo)
((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits; ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits;
((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~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 #endif
pinfo->brg = 1; pinfo->brg = 1;
} }
void smc2_lineif(struct uart_cpm_port *pinfo) void smc2_lineif(struct uart_cpm_port *pinfo)
{ {
#ifdef CONFIG_MPC885ADS
volatile cpm8xx_t *cp = cpmp; 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_pepar |= 0x00000c00;
cp->cp_pedir &= ~0x00000c00; cp->cp_pedir &= ~0x00000c00;
cp->cp_peso &= ~0x00000400; cp->cp_peso &= ~0x00000400;
cp->cp_peso |= 0x00000800; 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 #endif
pinfo->brg = 2; pinfo->brg = 2;
...@@ -158,7 +161,7 @@ void scc4_lineif(struct uart_cpm_port *pinfo) ...@@ -158,7 +161,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 * receive buffer descriptors from dual port ram, and a character
* buffer area from host mem. If we are allocating for the console we need * buffer area from host mem. If we are allocating for the console we need
* to do it from bootmem * to do it from bootmem
...@@ -185,6 +188,8 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) ...@@ -185,6 +188,8 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) + memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize); L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
if (is_con) { 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)); mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8));
dma_addr = 0; dma_addr = 0;
} else } else
......
...@@ -717,6 +717,9 @@ static void pxafb_enable_controller(struct pxafb_info *fbi) ...@@ -717,6 +717,9 @@ static void pxafb_enable_controller(struct pxafb_info *fbi)
DPRINTK("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2); DPRINTK("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2);
DPRINTK("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3); DPRINTK("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3);
/* enable LCD controller clock */
pxa_set_cken(CKEN16_LCD, 1);
/* Sequence from 11.7.10 */ /* Sequence from 11.7.10 */
LCCR3 = fbi->reg_lccr3; LCCR3 = fbi->reg_lccr3;
LCCR2 = fbi->reg_lccr2; LCCR2 = fbi->reg_lccr2;
...@@ -750,6 +753,9 @@ static void pxafb_disable_controller(struct pxafb_info *fbi) ...@@ -750,6 +753,9 @@ static void pxafb_disable_controller(struct pxafb_info *fbi)
schedule_timeout(20 * HZ / 1000); schedule_timeout(20 * HZ / 1000);
remove_wait_queue(&fbi->ctrlr_wait, &wait); remove_wait_queue(&fbi->ctrlr_wait, &wait);
/* disable LCD controller clock */
pxa_set_cken(CKEN16_LCD, 0);
} }
/* /*
...@@ -1299,8 +1305,6 @@ int __init pxafb_probe(struct device *dev) ...@@ -1299,8 +1305,6 @@ int __init pxafb_probe(struct device *dev)
ret = -ENOMEM; ret = -ENOMEM;
goto failed; goto failed;
} }
/* enable LCD controller clock */
pxa_set_cken(CKEN16_LCD, 1);
ret = request_irq(IRQ_LCD, pxafb_handle_irq, SA_INTERRUPT, "LCD", fbi); ret = request_irq(IRQ_LCD, pxafb_handle_irq, SA_INTERRUPT, "LCD", fbi);
if (ret) { if (ret) {
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
* Changelog: * Changelog:
* 11-Sep-2004 BJD Created file * 11-Sep-2004 BJD Created file
* 21-Sep-2004 BJD Updated port info * 21-Sep-2004 BJD Updated port info
* 09-Aug-2005 BJD Renamed s3c2410_report_oc s3c2410_usb_report_oc
*/ */
#ifndef __ASM_ARCH_USBCONTROL_H #ifndef __ASM_ARCH_USBCONTROL_H
...@@ -35,7 +36,7 @@ struct s3c2410_hcd_info { ...@@ -35,7 +36,7 @@ struct s3c2410_hcd_info {
void (*report_oc)(struct s3c2410_hcd_info *, int ports); void (*report_oc)(struct s3c2410_hcd_info *, int ports);
}; };
static void inline s3c2410_report_oc(struct s3c2410_hcd_info *info, int ports) static void inline s3c2410_usb_report_oc(struct s3c2410_hcd_info *info, int ports)
{ {
if (info->report_oc != NULL) { if (info->report_oc != NULL) {
(info->report_oc)(info, ports); (info->report_oc)(info, ports);
......
...@@ -188,12 +188,18 @@ extern void __pgd_error(const char *file, int line, unsigned long val); ...@@ -188,12 +188,18 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
/* /*
* - extended small page/tiny page * - extended small page/tiny page
*/ */
#define PTE_EXT_XN (1 << 0) /* v6 */
#define PTE_EXT_AP_MASK (3 << 4) #define PTE_EXT_AP_MASK (3 << 4)
#define PTE_EXT_AP0 (1 << 4)
#define PTE_EXT_AP1 (2 << 4)
#define PTE_EXT_AP_UNO_SRO (0 << 4) #define PTE_EXT_AP_UNO_SRO (0 << 4)
#define PTE_EXT_AP_UNO_SRW (1 << 4) #define PTE_EXT_AP_UNO_SRW (PTE_EXT_AP0)
#define PTE_EXT_AP_URO_SRW (2 << 4) #define PTE_EXT_AP_URO_SRW (PTE_EXT_AP1)
#define PTE_EXT_AP_URW_SRW (3 << 4) #define PTE_EXT_AP_URW_SRW (PTE_EXT_AP1|PTE_EXT_AP0)
#define PTE_EXT_TEX(x) ((x) << 6) /* v5 */ #define PTE_EXT_TEX(x) ((x) << 6) /* v5 */
#define PTE_EXT_APX (1 << 9) /* v6 */
#define PTE_EXT_SHARED (1 << 10) /* v6 */
#define PTE_EXT_NG (1 << 11) /* v6 */
/* /*
* - small page * - small page
...@@ -224,6 +230,8 @@ extern void __pgd_error(const char *file, int line, unsigned long val); ...@@ -224,6 +230,8 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
#define L_PTE_WRITE (1 << 5) #define L_PTE_WRITE (1 << 5)
#define L_PTE_EXEC (1 << 6) #define L_PTE_EXEC (1 << 6)
#define L_PTE_DIRTY (1 << 7) #define L_PTE_DIRTY (1 << 7)
#define L_PTE_SHARED (1 << 10) /* shared between CPUs (v6) */
#define L_PTE_ASID (1 << 11) /* non-global (use ASID, v6) */
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
......
...@@ -1501,4 +1501,10 @@ extern struct bus_type ide_bus_type; ...@@ -1501,4 +1501,10 @@ extern struct bus_type ide_bus_type;
#define ide_id_has_flush_cache_ext(id) \ #define ide_id_has_flush_cache_ext(id) \
(((id)->cfs_enable_2 & 0x2400) == 0x2400) (((id)->cfs_enable_2 & 0x2400) == 0x2400)
static inline int hwif_to_node(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
return dev ? pcibus_to_node(dev->bus) : -1;
}
#endif /* _IDE_H */ #endif /* _IDE_H */
...@@ -29,6 +29,14 @@ struct scsi_transport_template { ...@@ -29,6 +29,14 @@ struct scsi_transport_template {
struct transport_container target_attrs; struct transport_container target_attrs;
struct transport_container device_attrs; struct transport_container device_attrs;
/*
* If set, call target_parent prior to allocating a scsi_target,
* so we get the appropriate parent for the target. This function
* is required for transports like FC and iSCSI that do not put the
* scsi_target under scsi_host.
*/
struct device *(*target_parent)(struct Scsi_Host *, int, uint);
/* The size of the specific transport attribute structure (a /* The size of the specific transport attribute structure (a
* space of this size will be left at the end of the * space of this size will be left at the end of the
* scsi_* structure */ * scsi_* structure */
......
...@@ -398,21 +398,31 @@ static int cpuset_path(const struct cpuset *cs, char *buf, int buflen) ...@@ -398,21 +398,31 @@ static int cpuset_path(const struct cpuset *cs, char *buf, int buflen)
* to continue to serve a useful existence. Next time it's released, * 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. * we will get notified again, if it still has 'notify_on_release' set.
* *
* Note final arg to call_usermodehelper() is 0 - that means * The final arg to call_usermodehelper() is 0, which means don't
* don't wait. Since we are holding the global cpuset_sem here, * wait. The separate /sbin/cpuset_release_agent task is forked by
* and we are asking another thread (started from keventd) to rmdir a * call_usermodehelper(), then control in this thread returns here,
* cpuset, we can't wait - or we'd deadlock with the removing thread * without waiting for the release agent task. We don't bother to
* on cpuset_sem. * wait because the caller of this routine has no use for the exit
* status of the /sbin/cpuset_release_agent task, so no sense holding
* our caller up for that.
*
* The simple act of forking that task might require more memory,
* which might need cpuset_sem. So this routine must be called while
* cpuset_sem is not held, to avoid a possible deadlock. See also
* comments for check_for_release(), below.
*/ */
static int cpuset_release_agent(char *cpuset_str) static void cpuset_release_agent(const char *pathbuf)
{ {
char *argv[3], *envp[3]; char *argv[3], *envp[3];
int i; int i;
if (!pathbuf)
return;
i = 0; i = 0;
argv[i++] = "/sbin/cpuset_release_agent"; argv[i++] = "/sbin/cpuset_release_agent";
argv[i++] = cpuset_str; argv[i++] = (char *)pathbuf;
argv[i] = NULL; argv[i] = NULL;
i = 0; i = 0;
...@@ -421,17 +431,29 @@ static int cpuset_release_agent(char *cpuset_str) ...@@ -421,17 +431,29 @@ static int cpuset_release_agent(char *cpuset_str)
envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
envp[i] = NULL; envp[i] = NULL;
return call_usermodehelper(argv[0], argv, envp, 0); call_usermodehelper(argv[0], argv, envp, 0);
kfree(pathbuf);
} }
/* /*
* Either cs->count of using tasks transitioned to zero, or the * Either cs->count of using tasks transitioned to zero, or the
* cs->children list of child cpusets just became empty. If this * 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 * cs is notify_on_release() and now both the user count is zero and
* the list of children is empty, send notice to user land. * the list of children is empty, prepare cpuset path in a kmalloc'd
* buffer, to be returned via ppathbuf, so that the caller can invoke
* cpuset_release_agent() with it later on, once cpuset_sem is dropped.
* Call here with cpuset_sem held.
*
* This check_for_release() routine is responsible for kmalloc'ing
* pathbuf. The above cpuset_release_agent() is responsible for
* kfree'ing pathbuf. The caller of these routines is responsible
* for providing a pathbuf pointer, initialized to NULL, then
* calling check_for_release() with cpuset_sem held and the address
* of the pathbuf pointer, then dropping cpuset_sem, then calling
* cpuset_release_agent() with pathbuf, as set by check_for_release().
*/ */
static void check_for_release(struct cpuset *cs) static void check_for_release(struct cpuset *cs, char **ppathbuf)
{ {
if (notify_on_release(cs) && atomic_read(&cs->count) == 0 && if (notify_on_release(cs) && atomic_read(&cs->count) == 0 &&
list_empty(&cs->children)) { list_empty(&cs->children)) {
...@@ -441,10 +463,9 @@ static void check_for_release(struct cpuset *cs) ...@@ -441,10 +463,9 @@ static void check_for_release(struct cpuset *cs)
if (!buf) if (!buf)
return; return;
if (cpuset_path(cs, buf, PAGE_SIZE) < 0) if (cpuset_path(cs, buf, PAGE_SIZE) < 0)
goto out; kfree(buf);
cpuset_release_agent(buf); else
out: *ppathbuf = buf;
kfree(buf);
} }
} }
...@@ -727,14 +748,14 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf) ...@@ -727,14 +748,14 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf)
return 0; return 0;
} }
static int attach_task(struct cpuset *cs, char *buf) static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf)
{ {
pid_t pid; pid_t pid;
struct task_struct *tsk; struct task_struct *tsk;
struct cpuset *oldcs; struct cpuset *oldcs;
cpumask_t cpus; cpumask_t cpus;
if (sscanf(buf, "%d", &pid) != 1) if (sscanf(pidbuf, "%d", &pid) != 1)
return -EIO; return -EIO;
if (cpus_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed)) if (cpus_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed))
return -ENOSPC; return -ENOSPC;
...@@ -777,7 +798,7 @@ static int attach_task(struct cpuset *cs, char *buf) ...@@ -777,7 +798,7 @@ static int attach_task(struct cpuset *cs, char *buf)
put_task_struct(tsk); put_task_struct(tsk);
if (atomic_dec_and_test(&oldcs->count)) if (atomic_dec_and_test(&oldcs->count))
check_for_release(oldcs); check_for_release(oldcs, ppathbuf);
return 0; return 0;
} }
...@@ -801,6 +822,7 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us ...@@ -801,6 +822,7 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us
struct cftype *cft = __d_cft(file->f_dentry); struct cftype *cft = __d_cft(file->f_dentry);
cpuset_filetype_t type = cft->private; cpuset_filetype_t type = cft->private;
char *buffer; char *buffer;
char *pathbuf = NULL;
int retval = 0; int retval = 0;
/* Crude upper limit on largest legitimate cpulist user might write. */ /* 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,7 +863,7 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us
retval = update_flag(CS_NOTIFY_ON_RELEASE, cs, buffer); retval = update_flag(CS_NOTIFY_ON_RELEASE, cs, buffer);
break; break;
case FILE_TASKLIST: case FILE_TASKLIST:
retval = attach_task(cs, buffer); retval = attach_task(cs, buffer, &pathbuf);
break; break;
default: default:
retval = -EINVAL; retval = -EINVAL;
...@@ -852,6 +874,7 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us ...@@ -852,6 +874,7 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us
retval = nbytes; retval = nbytes;
out2: out2:
up(&cpuset_sem); up(&cpuset_sem);
cpuset_release_agent(pathbuf);
out1: out1:
kfree(buffer); kfree(buffer);
return retval; return retval;
...@@ -1357,6 +1380,7 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry) ...@@ -1357,6 +1380,7 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
struct cpuset *cs = dentry->d_fsdata; struct cpuset *cs = dentry->d_fsdata;
struct dentry *d; struct dentry *d;
struct cpuset *parent; struct cpuset *parent;
char *pathbuf = NULL;
/* the vfs holds both inode->i_sem already */ /* the vfs holds both inode->i_sem already */
...@@ -1376,7 +1400,7 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry) ...@@ -1376,7 +1400,7 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
update_cpu_domains(cs); update_cpu_domains(cs);
list_del(&cs->sibling); /* delete my sibling from parent->children */ list_del(&cs->sibling); /* delete my sibling from parent->children */
if (list_empty(&parent->children)) if (list_empty(&parent->children))
check_for_release(parent); check_for_release(parent, &pathbuf);
spin_lock(&cs->dentry->d_lock); spin_lock(&cs->dentry->d_lock);
d = dget(cs->dentry); d = dget(cs->dentry);
cs->dentry = NULL; cs->dentry = NULL;
...@@ -1384,6 +1408,7 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry) ...@@ -1384,6 +1408,7 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
cpuset_d_remove_dir(d); cpuset_d_remove_dir(d);
dput(d); dput(d);
up(&cpuset_sem); up(&cpuset_sem);
cpuset_release_agent(pathbuf);
return 0; return 0;
} }
...@@ -1483,10 +1508,13 @@ void cpuset_exit(struct task_struct *tsk) ...@@ -1483,10 +1508,13 @@ void cpuset_exit(struct task_struct *tsk)
task_unlock(tsk); task_unlock(tsk);
if (notify_on_release(cs)) { if (notify_on_release(cs)) {
char *pathbuf = NULL;
down(&cpuset_sem); down(&cpuset_sem);
if (atomic_dec_and_test(&cs->count)) if (atomic_dec_and_test(&cs->count))
check_for_release(cs); check_for_release(cs, &pathbuf);
up(&cpuset_sem); up(&cpuset_sem);
cpuset_release_agent(pathbuf);
} else { } else {
atomic_dec(&cs->count); atomic_dec(&cs->count);
} }
......
...@@ -308,8 +308,6 @@ struct workqueue_struct *__create_workqueue(const char *name, ...@@ -308,8 +308,6 @@ struct workqueue_struct *__create_workqueue(const char *name,
struct workqueue_struct *wq; struct workqueue_struct *wq;
struct task_struct *p; struct task_struct *p;
BUG_ON(strlen(name) > 10);
wq = kmalloc(sizeof(*wq), GFP_KERNEL); wq = kmalloc(sizeof(*wq), GFP_KERNEL);
if (!wq) if (!wq)
return NULL; return NULL;
......
...@@ -91,20 +91,11 @@ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov, ...@@ -91,20 +91,11 @@ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov,
} else } else
kern_msg->msg_name = NULL; 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, tot_len = iov_from_user_compat_to_kern(kern_iov,
(struct compat_iovec __user *)kern_msg->msg_iov, (struct compat_iovec __user *)kern_msg->msg_iov,
kern_msg->msg_iovlen); kern_msg->msg_iovlen);
if(tot_len >= 0) if(tot_len >= 0)
kern_msg->msg_iov = kern_iov; kern_msg->msg_iov = kern_iov;
else if(kern_msg->msg_iovlen > UIO_FASTIOV)
kfree(kern_iov);
return tot_len; return tot_len;
} }
......
...@@ -1876,15 +1876,6 @@ static inline unsigned int dn_current_mss(struct sock *sk, int flags) ...@@ -1876,15 +1876,6 @@ static inline unsigned int dn_current_mss(struct sock *sk, int flags)
return mss_now; return mss_now;
} }
static int dn_error(struct sock *sk, int flags, int err)
{
if (err == -EPIPE)
err = sock_error(sk) ? : -EPIPE;
if (err == -EPIPE && !(flags & MSG_NOSIGNAL))
send_sig(SIGPIPE, current, 0);
return err;
}
static int dn_sendmsg(struct kiocb *iocb, struct socket *sock, static int dn_sendmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t size) struct msghdr *msg, size_t size)
{ {
...@@ -2045,7 +2036,7 @@ out: ...@@ -2045,7 +2036,7 @@ out:
return sent ? sent : err; return sent ? sent : err;
out_err: out_err:
err = dn_error(sk, flags, err); err = sk_stream_error(sk, flags, err);
release_sock(sk); release_sock(sk);
return err; return err;
} }
......
...@@ -1370,15 +1370,21 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) ...@@ -1370,15 +1370,21 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
if (skb->len > cur_mss) { if (skb->len > cur_mss) {
int old_factor = tcp_skb_pcount(skb); int old_factor = tcp_skb_pcount(skb);
int new_factor; int diff;
if (tcp_fragment(sk, skb, cur_mss, cur_mss)) if (tcp_fragment(sk, skb, cur_mss, cur_mss))
return -ENOMEM; /* We'll try again later. */ return -ENOMEM; /* We'll try again later. */
/* New SKB created, account for it. */ /* New SKB created, account for it. */
new_factor = tcp_skb_pcount(skb); diff = old_factor - tcp_skb_pcount(skb) -
tp->packets_out -= old_factor - new_factor; tcp_skb_pcount(skb->next);
tp->packets_out += tcp_skb_pcount(skb->next); tp->packets_out -= diff;
if (diff > 0) {
tp->fackets_out -= diff;
if ((int)tp->fackets_out < 0)
tp->fackets_out = 0;
}
} }
/* Collapse two adjacent packets if worthwhile and we can. */ /* Collapse two adjacent packets if worthwhile and we can. */
......
...@@ -586,7 +586,7 @@ svc_udp_recvfrom(struct svc_rqst *rqstp) ...@@ -586,7 +586,7 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
} }
if (skb->stamp.tv_sec == 0) { if (skb->stamp.tv_sec == 0) {
skb->stamp.tv_sec = xtime.tv_sec; skb->stamp.tv_sec = xtime.tv_sec;
skb->stamp.tv_usec = xtime.tv_nsec * 1000; skb->stamp.tv_usec = xtime.tv_nsec / NSEC_PER_USEC;
/* Don't enable netstamp, sunrpc doesn't /* Don't enable netstamp, sunrpc doesn't
need that much accuracy */ need that much accuracy */
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment