diff options
author | Anton Altaparmakov <aia21@cantab.net> | 2005-09-19 09:47:49 +0100 |
---|---|---|
committer | Anton Altaparmakov <aia21@cantab.net> | 2005-09-19 09:47:49 +0100 |
commit | 044a500e46742d39d22f1781cfb64ba93b463e39 (patch) | |
tree | b0313211ea7ba26b90c1083ade0e4c9f486b87db | |
parent | f6098cf449b81c14a51e48dd22ae47d03126a1de (diff) | |
parent | 6c0741fbdee5bd0f8ed13ac287c4ab18e8ba7d83 (diff) |
Merge branch 'master' of /home/src/linux-2.6/
163 files changed, 3679 insertions, 2861 deletions
@@ -2211,6 +2211,15 @@ D: OV511 driver S: (address available on request) S: USA +N: Ian McDonald +E: iam4@cs.waikato.ac.nz +E: imcdnzl@gmail.com +W: http://wand.net.nz/~iam4 +W: http://imcdnzl.blogspot.com +D: DCCP, CCID3 +S: Hamilton +S: New Zealand + N: Patrick McHardy E: kaber@trash.net P: 1024D/12155E80 B128 7DE6 FF0A C2B2 48BE AB4C C9D4 964E 1215 5E80 @@ -2246,19 +2255,12 @@ S: D-90453 Nuernberg S: Germany N: Arnaldo Carvalho de Melo -E: acme@conectiva.com.br -E: acme@kernel.org -E: acme@gnu.org -W: http://bazar2.conectiva.com.br/~acme -W: http://advogato.org/person/acme +E: acme@mandriva.com +E: acme@ghostprotocols.net +W: http://oops.ghostprotocols.net:81/blog/ P: 1024D/9224DF01 D5DF E3BB E3C8 BCBB F8AD 841A B6AB 4681 9224 DF01 -D: wanrouter hacking -D: misc Makefile, Config.in, drivers and network stacks fixes -D: IPX & LLC network stacks maintainer -D: Cyclom 2X synchronous card driver -D: wl3501 PCMCIA wireless card driver -D: i18n for minicom, net-tools, util-linux, fetchmail, etc -S: Conectiva S.A. +D: IPX, LLC, DCCP, cyc2x, wl3501_cs, net/ hacks +S: Mandriva S: R. Tocantins, 89 - Cristo Rei S: 80050-430 - Curitiba - Paraná S: Brazil diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle index 22e5f9036f3c..eb7db3c19227 100644 --- a/Documentation/CodingStyle +++ b/Documentation/CodingStyle @@ -410,7 +410,26 @@ Kernel messages do not have to be terminated with a period. Printing numbers in parentheses (%d) adds no value and should be avoided. - Chapter 13: References + Chapter 13: Allocating memory + +The kernel provides the following general purpose memory allocators: +kmalloc(), kzalloc(), kcalloc(), and vmalloc(). Please refer to the API +documentation for further information about them. + +The preferred form for passing a size of a struct is the following: + + p = kmalloc(sizeof(*p), ...); + +The alternative form where struct name is spelled out hurts readability and +introduces an opportunity for a bug when the pointer variable type is changed +but the corresponding sizeof that is passed to a memory allocator is not. + +Casting the return value which is a void pointer is redundant. The conversion +from void pointer to any other pointer type is guaranteed by the C programming +language. + + + Chapter 14: References The C Programming Language, Second Edition by Brian W. Kernighan and Dennis M. Ritchie. diff --git a/Documentation/dell_rbu.txt b/Documentation/dell_rbu.txt index bcfa5c35036b..95d7f62e4dbc 100644 --- a/Documentation/dell_rbu.txt +++ b/Documentation/dell_rbu.txt @@ -13,6 +13,8 @@ the BIOS on Dell servers (starting from servers sold since 1999), desktops and notebooks (starting from those sold in 2005). Please go to http://support.dell.com register and you can find info on OpenManage and Dell Update packages (DUP). +Libsmbios can also be used to update BIOS on Dell systems go to +http://linux.dell.com/libsmbios/ for details. Dell_RBU driver supports BIOS update using the monilothic image and packetized image methods. In case of moniolithic the driver allocates a contiguous chunk @@ -22,8 +24,8 @@ would place each packet in contiguous physical memory. The driver also maintains a link list of packets for reading them back. If the dell_rbu driver is unloaded all the allocated memory is freed. -The rbu driver needs to have an application which will inform the BIOS to -enable the update in the next system reboot. +The rbu driver needs to have an application (as mentioned above)which will +inform the BIOS to enable the update in the next system reboot. The user should not unload the rbu driver after downloading the BIOS image or updating. @@ -42,9 +44,11 @@ In case of packet mechanism the single memory can be broken in smaller chuks of contiguous memory and the BIOS image is scattered in these packets. By default the driver uses monolithic memory for the update type. This can be -changed to contiguous during the driver load time by specifying the load +changed to packets during the driver load time by specifying the load parameter image_type=packet. This can also be changed later as below echo packet > /sys/devices/platform/dell_rbu/image_type +Also echoing either mono ,packet or init in to image_type will free up the +memory allocated by the driver. Do the steps below to download the BIOS image. 1) echo 1 > /sys/class/firmware/dell_rbu/loading @@ -53,9 +57,13 @@ Do the steps below to download the BIOS image. The /sys/class/firmware/dell_rbu/ entries will remain till the following is done. -echo -1 > /sys/class/firmware/dell_rbu/loading - +echo -1 > /sys/class/firmware/dell_rbu/loading. Until this step is completed the drivr cannot be unloaded. +If an user by accident executes steps 1 and 3 above without executing step 2; +it will make the /sys/class/firmware/dell_rbu/ entries to disappear. +The entries can be recreated by doing the following +echo init > /sys/devices/platform/dell_rbu/image_type +NOTE: echoing init in image_type does not change it original value. Also the driver provides /sys/devices/platform/dell_rbu/data readonly file to read back the image downloaded. This is useful in case of packet update diff --git a/Documentation/filesystems/relayfs.txt b/Documentation/filesystems/relayfs.txt index d24e1b0d4f39..d803abed29f0 100644 --- a/Documentation/filesystems/relayfs.txt +++ b/Documentation/filesystems/relayfs.txt @@ -15,7 +15,7 @@ retrieve the data as it becomes available. The format of the data logged into the channel buffers is completely up to the relayfs client; relayfs does however provide hooks which -allow clients to impose some stucture on the buffer data. Nor does +allow clients to impose some structure on the buffer data. Nor does relayfs implement any form of data filtering - this also is left to the client. The purpose is to keep relayfs as simple as possible. diff --git a/Documentation/ia64/mca.txt b/Documentation/ia64/mca.txt new file mode 100644 index 000000000000..a71cc6a67ef7 --- /dev/null +++ b/Documentation/ia64/mca.txt @@ -0,0 +1,194 @@ +An ad-hoc collection of notes on IA64 MCA and INIT processing. Feel +free to update it with notes about any area that is not clear. + +--- + +MCA/INIT are completely asynchronous. They can occur at any time, when +the OS is in any state. Including when one of the cpus is already +holding a spinlock. Trying to get any lock from MCA/INIT state is +asking for deadlock. Also the state of structures that are protected +by locks is indeterminate, including linked lists. + +--- + +The complicated ia64 MCA process. All of this is mandated by Intel's +specification for ia64 SAL, error recovery and and unwind, it is not as +if we have a choice here. + +* MCA occurs on one cpu, usually due to a double bit memory error. + This is the monarch cpu. + +* SAL sends an MCA rendezvous interrupt (which is a normal interrupt) + to all the other cpus, the slaves. + +* Slave cpus that receive the MCA interrupt call down into SAL, they + end up spinning disabled while the MCA is being serviced. + +* If any slave cpu was already spinning disabled when the MCA occurred + then it cannot service the MCA interrupt. SAL waits ~20 seconds then + sends an unmaskable INIT event to the slave cpus that have not + already rendezvoused. + +* Because MCA/INIT can be delivered at any time, including when the cpu + is down in PAL in physical mode, the registers at the time of the + event are _completely_ undefined. In particular the MCA/INIT + handlers cannot rely on the thread pointer, PAL physical mode can + (and does) modify TP. It is allowed to do that as long as it resets + TP on return. However MCA/INIT events expose us to these PAL + internal TP changes. Hence curr_task(). + +* If an MCA/INIT event occurs while the kernel was running (not user + space) and the kernel has called PAL then the MCA/INIT handler cannot + assume that the kernel stack is in a fit state to be used. Mainly + because PAL may or may not maintain the stack pointer internally. + Because the MCA/INIT handlers cannot trust the kernel stack, they + have to use their own, per-cpu stacks. The MCA/INIT stacks are + preformatted with just enough task state to let the relevant handlers + do their job. + +* Unlike most other architectures, the ia64 struct task is embedded in + the kernel stack[1]. So switching to a new kernel stack means that + we switch to a new task as well. Because various bits of the kernel + assume that current points into the struct task, switching to a new + stack also means a new value for current. + +* Once all slaves have rendezvoused and are spinning disabled, the + monarch is entered. The monarch now tries to diagnose the problem + and decide if it can recover or not. + +* Part of the monarch's job is to look at the state of all the other + tasks. The only way to do that on ia64 is to call the unwinder, + as mandated by Intel. + +* The starting point for the unwind depends on whether a task is + running or not. That is, whether it is on a cpu or is blocked. The + monarch has to determine whether or not a task is on a cpu before it + knows how to start unwinding it. The tasks that received an MCA or + INIT event are no longer running, they have been converted to blocked + tasks. But (and its a big but), the cpus that received the MCA + rendezvous interrupt are still running on their normal kernel stacks! + +* To distinguish between these two cases, the monarch must know which + tasks are on a cpu and which are not. Hence each slave cpu that + switches to an MCA/INIT stack, registers its new stack using + set_curr_task(), so the monarch can tell that the _original_ task is + no longer running on that cpu. That gives us a decent chance of + getting a valid backtrace of the _original_ task. + +* MCA/INIT can be nested, to a depth of 2 on any cpu. In the case of a + nested error, we want diagnostics on the MCA/INIT handler that + failed, not on the task that was originally running. Again this + requires set_curr_task() so the MCA/INIT handlers can register their + own stack as running on that cpu. Then a recursive error gets a + trace of the failing handler's "task". + +[1] My (Keith Owens) original design called for ia64 to separate its + struct task and the kernel stacks. Then the MCA/INIT data would be + chained stacks like i386 interrupt stacks. But that required + radical surgery on the rest of ia64, plus extra hard wired TLB + entries with its associated performance degradation. David + Mosberger vetoed that approach. Which meant that separate kernel + stacks meant separate "tasks" for the MCA/INIT handlers. + +--- + +INIT is less complicated than MCA. Pressing the nmi button or using +the equivalent command on the management console sends INIT to all +cpus. SAL picks one one of the cpus as the monarch and the rest are +slaves. All the OS INIT handlers are entered at approximately the same +time. The OS monarch prints the state of all tasks and returns, after +which the slaves return and the system resumes. + +At least that is what is supposed to happen. Alas there are broken +versions of SAL out there. Some drive all the cpus as monarchs. Some +drive them all as slaves. Some drive one cpu as monarch, wait for that +cpu to return from the OS then drive the rest as slaves. Some versions +of SAL cannot even cope with returning from the OS, they spin inside +SAL on resume. The OS INIT code has workarounds for some of these +broken SAL symptoms, but some simply cannot be fixed from the OS side. + +--- + +The scheduler hooks used by ia64 (curr_task, set_curr_task) are layer +violations. Unfortunately MCA/INIT start off as massive layer +violations (can occur at _any_ time) and they build from there. + +At least ia64 makes an attempt at recovering from hardware errors, but +it is a difficult problem because of the asynchronous nature of these +errors. When processing an unmaskable interrupt we sometimes need +special code to cope with our inability to take any locks. + +--- + +How is ia64 MCA/INIT different from x86 NMI? + +* x86 NMI typically gets delivered to one cpu. MCA/INIT gets sent to + all cpus. + +* x86 NMI cannot be nested. MCA/INIT can be nested, to a depth of 2 + per cpu. + +* x86 has a separate struct task which points to one of multiple kernel + stacks. ia64 has the struct task embedded in the single kernel + stack, so switching stack means switching task. + +* x86 does not call the BIOS so the NMI handler does not have to worry + about any registers having changed. MCA/INIT can occur while the cpu + is in PAL in physical mode, with undefined registers and an undefined + kernel stack. + +* i386 backtrace is not very sensitive to whether a process is running + or not. ia64 unwind is very, very sensitive to whether a process is + running or not. + +--- + +What happens when MCA/INIT is delivered what a cpu is running user +space code? + +The user mode registers are stored in the RSE area of the MCA/INIT on +entry to the OS and are restored from there on return to SAL, so user +mode registers are preserved across a recoverable MCA/INIT. Since the +OS has no idea what unwind data is available for the user space stack, +MCA/INIT never tries to backtrace user space. Which means that the OS +does not bother making the user space process look like a blocked task, +i.e. the OS does not copy pt_regs and switch_stack to the user space +stack. Also the OS has no idea how big the user space RSE and memory +stacks are, which makes it too risky to copy the saved state to a user +mode stack. + +--- + +How do we get a backtrace on the tasks that were running when MCA/INIT +was delivered? + +mca.c:::ia64_mca_modify_original_stack(). That identifies and +verifies the original kernel stack, copies the dirty registers from +the MCA/INIT stack's RSE to the original stack's RSE, copies the +skeleton struct pt_regs and switch_stack to the original stack, fills +in the skeleton structures from the PAL minstate area and updates the +original stack's thread.ksp. That makes the original stack look +exactly like any other blocked task, i.e. it now appears to be +sleeping. To get a backtrace, just start with thread.ksp for the +original task and unwind like any other sleeping task. + +--- + +How do we identify the tasks that were running when MCA/INIT was +delivered? + +If the previous task has been verified and converted to a blocked +state, then sos->prev_task on the MCA/INIT stack is updated to point to +the previous task. You can look at that field in dumps or debuggers. +To help distinguish between the handler and the original tasks, +handlers have _TIF_MCA_INIT set in thread_info.flags. + +The sos data is always in the MCA/INIT handler stack, at offset +MCA_SOS_OFFSET. You can get that value from mca_asm.h or calculate it +as KERNEL_STACK_SIZE - sizeof(struct pt_regs) - sizeof(struct +ia64_sal_os_state), with 16 byte alignment for all structures. + +Also the comm field of the MCA/INIT task is modified to include the pid +of the original task, for humans to use. For example, a comm field of +'MCA 12159' means that pid 12159 was running when the MCA was +delivered. diff --git a/MAINTAINERS b/MAINTAINERS index d1e0eb46d201..dc8f3babcabd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -686,6 +686,13 @@ P: Guennadi Liakhovetski M: g.liakhovetski@gmx.de S: Maintained +DCCP PROTOCOL +P: Arnaldo Carvalho de Melo +M: acme@mandriva.com +L: dccp@vger.kernel.org +W: http://www.wlug.org.nz/DCCP +S: Maintained + DECnet NETWORK LAYER P: Patrick Caulfield M: patrick@tykepenguin.com @@ -2271,12 +2278,6 @@ M: R.E.Wolff@BitWizard.nl L: linux-kernel@vger.kernel.org ? S: Supported -SPX NETWORK LAYER -P: Jay Schulist -M: jschlst@samba.org -L: netdev@vger.kernel.org -S: Supported - SRM (Alpha) environment access P: Jan-Benedict Glaw M: jbglaw@lug-owl.de diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 0636116210d2..01fe990d3e54 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -37,6 +37,7 @@ #include <linux/namei.h> #include <linux/uio.h> #include <linux/vfs.h> +#include <linux/rcupdate.h> #include <asm/fpu.h> #include <asm/io.h> @@ -975,6 +976,7 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, long timeout; int ret = -EINVAL; struct fdtable *fdt; + int max_fdset; timeout = MAX_SCHEDULE_TIMEOUT; if (tvp) { @@ -996,8 +998,11 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, } } + rcu_read_lock(); fdt = files_fdtable(current->files); - if (n < 0 || n > fdt->max_fdset) + max_fdset = fdt->max_fdset; + rcu_read_unlock(); + if (n < 0 || n > max_fdset) goto out_nofds; /* diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index 2786f7c34b3f..a7bd85700152 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c @@ -551,7 +551,7 @@ struct locomo_save_data { u16 LCM_SPIMD; }; -static int locomo_suspend(struct device *dev, u32 pm_message_t, u32 level) +static int locomo_suspend(struct device *dev, pm_message_t state, u32 level) { struct locomo *lchip = dev_get_drvdata(dev); struct locomo_save_data *save; diff --git a/arch/arm/configs/enp2611_defconfig b/arch/arm/configs/enp2611_defconfig index f67ca01b4982..30e6444f9aaa 100644 --- a/arch/arm/configs/enp2611_defconfig +++ b/arch/arm/configs/enp2611_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc2 -# Thu Jul 7 16:41:21 2005 +# Linux kernel version: 2.6.13 +# Wed Sep 14 10:51:52 2005 # CONFIG_ARM=y CONFIG_MMU=y @@ -135,7 +135,6 @@ CONFIG_PCI_NAMES=y # # Kernel Features # -# CONFIG_SMP is not set # CONFIG_PREEMPT is not set # CONFIG_NO_IDLE_HZ is not set # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set @@ -179,6 +178,68 @@ CONFIG_BINFMT_ELF=y # CONFIG_PM is not set # +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_IP_TCPDIAG is not set +# CONFIG_IP_TCPDIAG_IPV6 is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set + +# # Device Drivers # @@ -248,6 +309,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y CONFIG_MTD_IXP2000=y # CONFIG_MTD_EDB7312 is not set # CONFIG_MTD_PCI is not set +# CONFIG_MTD_PLATRAM is not set # # Self-contained MTD device drivers @@ -334,72 +396,8 @@ CONFIG_IOSCHED_CFQ=y # CONFIG_I2O is not set # -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -CONFIG_SYN_COOKIES=y -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -# CONFIG_IP_TCPDIAG is not set -# CONFIG_IP_TCPDIAG_IPV6 is not set -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y -# CONFIG_IPV6 is not set -# CONFIG_NETFILTER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing +# Network device support # -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set CONFIG_NETDEVICES=y CONFIG_DUMMY=y # CONFIG_BONDING is not set @@ -509,6 +507,8 @@ CONFIG_DLCI_MAX=8 # CONFIG_SLIP is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set # # ISDN subsystem @@ -635,7 +635,7 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_ISA is not set -# CONFIG_I2C_IXP2000 is not set +CONFIG_I2C_IXP2000=y # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set @@ -649,11 +649,28 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set # CONFIG_I2C_PCA_ISA is not set +CONFIG_I2C_SENSOR=y # -# Hardware Sensors Chip support +# Miscellaneous I2C Chip support # -CONFIG_I2C_SENSOR=y +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +CONFIG_SENSORS_EEPROM=y +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set @@ -679,30 +696,15 @@ CONFIG_I2C_SENSOR=y # CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627EHF is not set - -# -# Other I2C Chip support -# -# CONFIG_SENSORS_DS1337 is not set -# CONFIG_SENSORS_DS1374 is not set -CONFIG_SENSORS_EEPROM=y -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCA9539 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set -# CONFIG_SENSORS_MAX6875 is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_HWMON_DEBUG_CHIP is not set # # Misc devices @@ -770,6 +772,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set @@ -812,8 +815,7 @@ CONFIG_RAMFS=y # CONFIG_JFFS_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -# CONFIG_JFFS2_FS_NOR_ECC is not set +CONFIG_JFFS2_FS_WRITEBUFFER=y # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set CONFIG_JFFS2_ZLIB=y CONFIG_JFFS2_RTIME=y diff --git a/arch/arm/configs/ixdp2400_defconfig b/arch/arm/configs/ixdp2400_defconfig index 5c6c928215d0..678720fa2e2e 100644 --- a/arch/arm/configs/ixdp2400_defconfig +++ b/arch/arm/configs/ixdp2400_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc2 -# Thu Jul 7 16:49:01 2005 +# Linux kernel version: 2.6.13 +# Wed Sep 14 10:52:01 2005 # CONFIG_ARM=y CONFIG_MMU=y @@ -136,7 +136,6 @@ CONFIG_PCI_NAMES=y # # Kernel Features # -# CONFIG_SMP is not set # CONFIG_PREEMPT is not set # CONFIG_NO_IDLE_HZ is not set # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set @@ -180,6 +179,68 @@ CONFIG_BINFMT_ELF=y # CONFIG_PM is not set # +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_IP_TCPDIAG is not set +# CONFIG_IP_TCPDIAG_IPV6 is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set + +# # Device Drivers # @@ -249,6 +310,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y CONFIG_MTD_IXP2000=y # CONFIG_MTD_EDB7312 is not set # CONFIG_MTD_PCI is not set +# CONFIG_MTD_PLATRAM is not set # # Self-contained MTD device drivers @@ -335,72 +397,8 @@ CONFIG_IOSCHED_CFQ=y # CONFIG_I2O is not set # -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -CONFIG_SYN_COOKIES=y -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -# CONFIG_IP_TCPDIAG is not set -# CONFIG_IP_TCPDIAG_IPV6 is not set -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y -# CONFIG_IPV6 is not set -# CONFIG_NETFILTER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing +# Network device support # -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set CONFIG_NETDEVICES=y CONFIG_DUMMY=y # CONFIG_BONDING is not set @@ -510,6 +508,8 @@ CONFIG_DLCI_MAX=8 # CONFIG_SLIP is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set # # ISDN subsystem @@ -636,7 +636,7 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_ISA is not set -# CONFIG_I2C_IXP2000 is not set +CONFIG_I2C_IXP2000=y # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set @@ -650,11 +650,28 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set # CONFIG_I2C_PCA_ISA is not set +CONFIG_I2C_SENSOR=y # -# Hardware Sensors Chip support +# Miscellaneous I2C Chip support # -CONFIG_I2C_SENSOR=y +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +CONFIG_SENSORS_EEPROM=y +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set @@ -680,30 +697,15 @@ CONFIG_I2C_SENSOR=y # CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627EHF is not set - -# -# Other I2C Chip support -# -# CONFIG_SENSORS_DS1337 is not set -# CONFIG_SENSORS_DS1374 is not set -CONFIG_SENSORS_EEPROM=y -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCA9539 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set -# CONFIG_SENSORS_MAX6875 is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_HWMON_DEBUG_CHIP is not set # # Misc devices @@ -771,6 +773,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set @@ -813,8 +816,7 @@ CONFIG_RAMFS=y # CONFIG_JFFS_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -# CONFIG_JFFS2_FS_NOR_ECC is not set +CONFIG_JFFS2_FS_WRITEBUFFER=y # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set CONFIG_JFFS2_ZLIB=y CONFIG_JFFS2_RTIME=y diff --git a/arch/arm/configs/ixdp2401_defconfig b/arch/arm/configs/ixdp2401_defconfig index 6dc40f6be0ef..38c9a721d5c9 100644 --- a/arch/arm/configs/ixdp2401_defconfig +++ b/arch/arm/configs/ixdp2401_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc2 -# Thu Jul 7 16:49:08 2005 +# Linux kernel version: 2.6.13 +# Wed Sep 14 10:52:10 2005 # CONFIG_ARM=y CONFIG_MMU=y @@ -136,7 +136,6 @@ CONFIG_PCI_NAMES=y # # Kernel Features # -# CONFIG_SMP is not set # CONFIG_PREEMPT is not set # CONFIG_NO_IDLE_HZ is not set # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set @@ -180,6 +179,68 @@ CONFIG_BINFMT_ELF=y # CONFIG_PM is not set # +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set + +# # Device Drivers # @@ -249,6 +310,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y CONFIG_MTD_IXP2000=y # CONFIG_MTD_EDB7312 is not set # CONFIG_MTD_PCI is not set +# CONFIG_MTD_PLATRAM is not set # # Self-contained MTD device drivers @@ -335,72 +397,8 @@ CONFIG_IOSCHED_CFQ=y # CONFIG_I2O is not set # -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -CONFIG_SYN_COOKIES=y -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -CONFIG_IP_TCPDIAG=y -# CONFIG_IP_TCPDIAG_IPV6 is not set -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y -# CONFIG_IPV6 is not set -# CONFIG_NETFILTER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing +# Network device support # -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set CONFIG_NETDEVICES=y CONFIG_DUMMY=y # CONFIG_BONDING is not set @@ -511,6 +509,8 @@ CONFIG_DLCI_MAX=8 # CONFIG_SLIP is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set # # ISDN subsystem @@ -637,7 +637,7 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_ISA is not set -# CONFIG_I2C_IXP2000 is not set +CONFIG_I2C_IXP2000=y # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set @@ -651,11 +651,28 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set # CONFIG_I2C_PCA_ISA is not set +CONFIG_I2C_SENSOR=y # -# Hardware Sensors Chip support +# Miscellaneous I2C Chip support # -CONFIG_I2C_SENSOR=y +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +CONFIG_SENSORS_EEPROM=y +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set @@ -681,30 +698,15 @@ CONFIG_I2C_SENSOR=y # CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627EHF is not set - -# -# Other I2C Chip support -# -# CONFIG_SENSORS_DS1337 is not set -# CONFIG_SENSORS_DS1374 is not set -CONFIG_SENSORS_EEPROM=y -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCA9539 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set -# CONFIG_SENSORS_MAX6875 is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_HWMON_DEBUG_CHIP is not set # # Misc devices @@ -772,6 +774,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set @@ -814,8 +817,7 @@ CONFIG_RAMFS=y # CONFIG_JFFS_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -# CONFIG_JFFS2_FS_NOR_ECC is not set +CONFIG_JFFS2_FS_WRITEBUFFER=y # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set CONFIG_JFFS2_ZLIB=y CONFIG_JFFS2_RTIME=y diff --git a/arch/arm/configs/ixdp2800_defconfig b/arch/arm/configs/ixdp2800_defconfig index d2bb0b7153fe..261e2343903b 100644 --- a/arch/arm/configs/ixdp2800_defconfig +++ b/arch/arm/configs/ixdp2800_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc2 -# Thu Jul 7 16:49:20 2005 +# Linux kernel version: 2.6.13 +# Wed Sep 14 10:52:23 2005 # CONFIG_ARM=y CONFIG_MMU=y @@ -136,7 +136,6 @@ CONFIG_PCI_NAMES=y # # Kernel Features # -# CONFIG_SMP is not set # CONFIG_PREEMPT is not set # CONFIG_NO_IDLE_HZ is not set # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set @@ -180,6 +179,68 @@ CONFIG_BINFMT_ELF=y # CONFIG_PM is not set # +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_IP_TCPDIAG is not set +# CONFIG_IP_TCPDIAG_IPV6 is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set + +# # Device Drivers # @@ -249,6 +310,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y CONFIG_MTD_IXP2000=y # CONFIG_MTD_EDB7312 is not set # CONFIG_MTD_PCI is not set +# CONFIG_MTD_PLATRAM is not set # # Self-contained MTD device drivers @@ -335,72 +397,8 @@ CONFIG_IOSCHED_CFQ=y # CONFIG_I2O is not set # -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -CONFIG_SYN_COOKIES=y -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -# CONFIG_IP_TCPDIAG is not set -# CONFIG_IP_TCPDIAG_IPV6 is not set -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y -# CONFIG_IPV6 is not set -# CONFIG_NETFILTER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing +# Network device support # -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set CONFIG_NETDEVICES=y CONFIG_DUMMY=y # CONFIG_BONDING is not set @@ -510,6 +508,8 @@ CONFIG_DLCI_MAX=8 # CONFIG_SLIP is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set # # ISDN subsystem @@ -636,7 +636,7 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_ISA is not set -# CONFIG_I2C_IXP2000 is not set +CONFIG_I2C_IXP2000=y # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set @@ -650,11 +650,28 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set # CONFIG_I2C_PCA_ISA is not set +CONFIG_I2C_SENSOR=y # -# Hardware Sensors Chip support +# Miscellaneous I2C Chip support # -CONFIG_I2C_SENSOR=y +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +CONFIG_SENSORS_EEPROM=y +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set @@ -680,30 +697,15 @@ CONFIG_I2C_SENSOR=y # CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627EHF is not set - -# -# Other I2C Chip support -# -# CONFIG_SENSORS_DS1337 is not set -# CONFIG_SENSORS_DS1374 is not set -CONFIG_SENSORS_EEPROM=y -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCA9539 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set -# CONFIG_SENSORS_MAX6875 is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_HWMON_DEBUG_CHIP is not set # # Misc devices @@ -771,6 +773,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set @@ -813,8 +816,7 @@ CONFIG_RAMFS=y # CONFIG_JFFS_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -# CONFIG_JFFS2_FS_NOR_ECC is not set +CONFIG_JFFS2_FS_WRITEBUFFER=y # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set CONFIG_JFFS2_ZLIB=y CONFIG_JFFS2_RTIME=y diff --git a/arch/arm/configs/ixdp2801_defconfig b/arch/arm/configs/ixdp2801_defconfig index 2d6f960e3395..12ef23d1c016 100644 --- a/arch/arm/configs/ixdp2801_defconfig +++ b/arch/arm/configs/ixdp2801_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc2 -# Thu Jul 7 16:49:13 2005 +# Linux kernel version: 2.6.13 +# Wed Sep 14 10:52:16 2005 # CONFIG_ARM=y CONFIG_MMU=y @@ -136,7 +136,6 @@ CONFIG_PCI_NAMES=y # # Kernel Features # -# CONFIG_SMP is not set # CONFIG_PREEMPT is not set # CONFIG_NO_IDLE_HZ is not set # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set @@ -180,6 +179,68 @@ CONFIG_BINFMT_ELF=y # CONFIG_PM is not set # +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_IP_TCPDIAG is not set +# CONFIG_IP_TCPDIAG_IPV6 is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set + +# # Device Drivers # @@ -249,6 +310,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y CONFIG_MTD_IXP2000=y # CONFIG_MTD_EDB7312 is not set # CONFIG_MTD_PCI is not set +# CONFIG_MTD_PLATRAM is not set # # Self-contained MTD device drivers @@ -335,72 +397,8 @@ CONFIG_IOSCHED_CFQ=y # CONFIG_I2O is not set # -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -CONFIG_SYN_COOKIES=y -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -# CONFIG_IP_TCPDIAG is not set -# CONFIG_IP_TCPDIAG_IPV6 is not set -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y -# CONFIG_IPV6 is not set -# CONFIG_NETFILTER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing +# Network device support # -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set CONFIG_NETDEVICES=y CONFIG_DUMMY=y # CONFIG_BONDING is not set @@ -511,6 +509,8 @@ CONFIG_DLCI_MAX=8 # CONFIG_SLIP is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set # # ISDN subsystem @@ -637,7 +637,7 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_ISA is not set -# CONFIG_I2C_IXP2000 is not set +CONFIG_I2C_IXP2000=y # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set @@ -651,11 +651,28 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set # CONFIG_I2C_PCA_ISA is not set +CONFIG_I2C_SENSOR=y # -# Hardware Sensors Chip support +# Miscellaneous I2C Chip support # -CONFIG_I2C_SENSOR=y +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +CONFIG_SENSORS_EEPROM=y +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set @@ -681,30 +698,15 @@ CONFIG_I2C_SENSOR=y # CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627EHF is not set - -# -# Other I2C Chip support -# -# CONFIG_SENSORS_DS1337 is not set -# CONFIG_SENSORS_DS1374 is not set -CONFIG_SENSORS_EEPROM=y -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCA9539 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set -# CONFIG_SENSORS_MAX6875 is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_HWMON_DEBUG_CHIP is not set # # Misc devices @@ -772,6 +774,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set @@ -814,8 +817,7 @@ CONFIG_RAMFS=y # CONFIG_JFFS_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -# CONFIG_JFFS2_FS_NOR_ECC is not set +CONFIG_JFFS2_FS_WRITEBUFFER=y # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set CONFIG_JFFS2_ZLIB=y CONFIG_JFFS2_RTIME=y diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c index ac423e3e224b..4c31f2923055 100644 --- a/arch/arm/kernel/semaphore.c +++ b/arch/arm/kernel/semaphore.c @@ -178,7 +178,7 @@ int __down_trylock(struct semaphore * sem) * registers (r0 to r3 and lr), but not ip, as we use it as a return * value in some cases.. */ -asm(" .section .sched.text,\"ax\" \n\ +asm(" .section .sched.text,\"ax\",%progbits \n\ .align 5 \n\ .globl __down_failed \n\ __down_failed: \n\ diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c index ae1fa099d5fa..39b06ed80646 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -123,6 +123,7 @@ static void __init ixdp425_init(void) platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices)); } +#ifdef CONFIG_ARCH_IXDP465 MACHINE_START(IXDP425, "Intel IXDP425 Development Platform") /* Maintainer: MontaVista Software, Inc. */ .phys_ram = PHYS_OFFSET, @@ -134,7 +135,9 @@ MACHINE_START(IXDP425, "Intel IXDP425 Development Platform") .boot_params = 0x0100, .init_machine = ixdp425_init, MACHINE_END +#endif +#ifdef CONFIG_MACH_IXDP465 MACHINE_START(IXDP465, "Intel IXDP465 Development Platform") /* Maintainer: MontaVista Software, Inc. */ .phys_ram = PHYS_OFFSET, @@ -146,7 +149,9 @@ MACHINE_START(IXDP465, "Intel IXDP465 Development Platform") .boot_params = 0x0100, .init_machine = ixdp425_init, MACHINE_END +#endif +#ifdef CONFIG_ARCH_PRPMC1100 MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform") /* Maintainer: MontaVista Software, Inc. */ .phys_ram = PHYS_OFFSET, @@ -158,6 +163,7 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform") .boot_params = 0x0100, .init_machine = ixdp425_init, MACHINE_END +#endif /* * Avila is functionally equivalent to IXDP425 except that it adds diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 426c2bc517eb..be37586cb1b0 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -198,13 +198,10 @@ static void corgi_mci_setpower(struct device *dev, unsigned int vdd) { struct pxamci_platform_data* p_d = dev->platform_data; - if (( 1 << vdd) & p_d->ocr_mask) { - printk(KERN_DEBUG "%s: on\n", __FUNCTION__); + if (( 1 << vdd) & p_d->ocr_mask) GPSR1 = GPIO_bit(CORGI_GPIO_SD_PWR); - } else { - printk(KERN_DEBUG "%s: off\n", __FUNCTION__); + else GPCR1 = GPIO_bit(CORGI_GPIO_SD_PWR); - } } static int corgi_mci_get_ro(struct device *dev) @@ -259,6 +256,16 @@ static struct platform_device *devices[] __initdata = { static void __init corgi_init(void) { + /* setup sleep mode values */ + PWER = 0x00000002; + PFER = 0x00000000; + PRER = 0x00000002; + PGSR0 = 0x0158C000; + PGSR1 = 0x00FF0080; + PGSR2 = 0x0001C004; + /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */ + PCFR |= PCFR_OPDE; + corgi_ssp_set_machinfo(&corgi_ssp_machinfo); pxa_gpio_mode(CORGI_GPIO_USB_PULLUP | GPIO_OUT); @@ -285,42 +292,14 @@ static void __init fixup_corgi(struct machine_desc *desc, mi->bank[0].size = (64*1024*1024); } -static void __init corgi_init_irq(void) -{ - pxa_init_irq(); -} - -static struct map_desc corgi_io_desc[] __initdata = { -/* virtual physical length */ -/* { 0xf1000000, 0x08000000, 0x01000000, MT_DEVICE },*/ /* LCDC (readable for Qt driver) */ -/* { 0xef700000, 0x10800000, 0x00001000, MT_DEVICE },*/ /* SCOOP */ - { 0xef800000, 0x00000000, 0x00800000, MT_DEVICE }, /* Boot Flash */ -}; - -static void __init corgi_map_io(void) -{ - pxa_map_io(); - iotable_init(corgi_io_desc,ARRAY_SIZE(corgi_io_desc)); - - /* setup sleep mode values */ - PWER = 0x00000002; - PFER = 0x00000000; - PRER = 0x00000002; - PGSR0 = 0x0158C000; - PGSR1 = 0x00FF0080; - PGSR2 = 0x0001C004; - /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */ - PCFR |= PCFR_OPDE; -} - #ifdef CONFIG_MACH_CORGI MACHINE_START(CORGI, "SHARP Corgi") .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_corgi, - .map_io = corgi_map_io, - .init_irq = corgi_init_irq, + .map_io = pxa_map_io, + .init_irq = pxa_init_irq, .init_machine = corgi_init, .timer = &pxa_timer, MACHINE_END @@ -332,8 +311,8 @@ MACHINE_START(SHEPHERD, "SHARP Shepherd") .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_corgi, - .map_io = corgi_map_io, - .init_irq = corgi_init_irq, + .map_io = pxa_map_io, + .init_irq = pxa_init_irq, .init_machine = corgi_init, .timer = &pxa_timer, MACHINE_END @@ -345,8 +324,8 @@ MACHINE_START(HUSKY, "SHARP Husky") .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_corgi, - .map_io = corgi_map_io, - .init_irq = corgi_init_irq, + .map_io = pxa_map_io, + .init_irq = pxa_init_irq, .init_machine = corgi_init, .timer = &pxa_timer, MACHINE_END diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index 47cfb8bb8318..f25638810017 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -30,6 +30,8 @@ #include <asm/arch/pxa-regs.h> #include <asm/arch/irq.h> +#include <asm/arch/mmc.h> +#include <asm/arch/udc.h> #include <asm/arch/poodle.h> #include <asm/arch/pxafb.h> @@ -93,6 +95,83 @@ static struct platform_device locomo_device = { .resource = locomo_resources, }; + +/* + * MMC/SD Device + * + * The card detect interrupt isn't debounced so we delay it by 250ms + * to give the card a chance to fully insert/eject. + */ +static struct pxamci_platform_data poodle_mci_platform_data; + +static int poodle_mci_init(struct device *dev, irqreturn_t (*poodle_detect_int)(int, void *, struct pt_regs *), void *data) +{ + int err; + + /* setup GPIO for PXA25x MMC controller */ + pxa_gpio_mode(GPIO6_MMCCLK_MD); + pxa_gpio_mode(GPIO8_MMCCS0_MD); + pxa_gpio_mode(POODLE_GPIO_nSD_DETECT | GPIO_IN); + pxa_gpio_mode(POODLE_GPIO_SD_PWR | GPIO_OUT); + + poodle_mci_platform_data.detect_delay = msecs_to_jiffies(250); + + err = request_irq(POODLE_IRQ_GPIO_nSD_DETECT, poodle_detect_int, SA_INTERRUPT, + "MMC card detect", data); + if (err) { + printk(KERN_ERR "poodle_mci_init: MMC/SD: can't request MMC card detect IRQ\n"); + return -1; + } + + set_irq_type(POODLE_IRQ_GPIO_nSD_DETECT, IRQT_BOTHEDGE); + + return 0; +} + +static void poodle_mci_setpower(struct device *dev, unsigned int vdd) +{ + struct pxamci_platform_data* p_d = dev->platform_data; + + if (( 1 << vdd) & p_d->ocr_mask) + GPSR1 = GPIO_bit(POODLE_GPIO_SD_PWR); + else + GPCR1 = GPIO_bit(POODLE_GPIO_SD_PWR); +} + +static void poodle_mci_exit(struct device *dev, void *data) +{ + free_irq(POODLE_IRQ_GPIO_nSD_DETECT, data); +} + +static struct pxamci_platform_data poodle_mci_platform_data = { + .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, + .init = poodle_mci_init, + .setpower = poodle_mci_setpower, + .exit = poodle_mci_exit, +}; + + +/* + * USB Device Controller + */ +static void poodle_udc_command(int cmd) +{ + switch(cmd) { + case PXA2XX_UDC_CMD_CONNECT: + GPSR(POODLE_GPIO_USB_PULLUP) = GPIO_bit(POODLE_GPIO_USB_PULLUP); + break; + case PXA2XX_UDC_CMD_DISCONNECT: + GPCR(POODLE_GPIO_USB_PULLUP) = GPIO_bit(POODLE_GPIO_USB_PULLUP); + break; + } +} + +static struct pxa2xx_udc_mach_info udc_info __initdata = { + /* no connect GPIO; poodle can't tell connection status */ + .udc_command = poodle_udc_command, +}; + + /* PXAFB device */ static struct pxafb_mach_info poodle_fb_info __initdata = { .pixclock = 144700, @@ -126,6 +205,15 @@ static void __init poodle_init(void) { int ret = 0; + /* setup sleep mode values */ + PWER = 0x00000002; + PFER = 0x00000000; + PRER = 0x00000002; + PGSR0 = 0x00008000; + PGSR1 = 0x003F0202; + PGSR2 = 0x0001C000; + PCFR |= PCFR_OPDE; + /* cpu initialize */ /* Pgsr Register */ PGSR0 = 0x0146dd80; @@ -155,6 +243,9 @@ static void __init poodle_init(void) GPSR2 = 0x00000000; set_pxa_fb_info(&poodle_fb_info); + pxa_gpio_mode(POODLE_GPIO_USB_PULLUP | GPIO_OUT); + pxa_set_udc_info(&udc_info); + pxa_set_mci_info(&poodle_mci_platform_data); scoop_num = 1; scoop_devs = &poodle_pcmcia_scoop[0]; @@ -171,32 +262,12 @@ static void __init fixup_poodle(struct machine_desc *desc, sharpsl_save_param(); } -static struct map_desc poodle_io_desc[] __initdata = { - /* virtual physical length */ - { 0xef800000, 0x00000000, 0x00800000, MT_DEVICE }, /* Boot Flash */ -}; - -static void __init poodle_map_io(void) -{ - pxa_map_io(); - iotable_init(poodle_io_desc, ARRAY_SIZE(poodle_io_desc)); - - /* setup sleep mode values */ - PWER = 0x00000002; - PFER = 0x00000000; - PRER = 0x00000002; - PGSR0 = 0x00008000; - PGSR1 = 0x003F0202; - PGSR2 = 0x0001C000; - PCFR |= PCFR_OPDE; -} - MACHINE_START(POODLE, "SHARP Poodle") .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_poodle, - .map_io = poodle_map_io, + .map_io = pxa_map_io, .init_irq = pxa_init_irq, .timer = &pxa_timer, .init_machine = poodle_init, diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index 8cb69113a57c..25d6a4e27533 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c @@ -111,12 +111,11 @@ static struct mtd_partition collie_partitions[] = { static void collie_set_vpp(int vpp) { - write_scoop_reg(SCOOP_GPCR, read_scoop_reg(SCOOP_GPCR) | COLLIE_SCP_VPEN); - if (vpp) { - write_scoop_reg(SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) | COLLIE_SCP_VPEN); - } else { - write_scoop_reg(SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) & ~COLLIE_SCP_VPEN); - } + write_scoop_reg(&colliescoop_device.dev, SCOOP_GPCR, read_scoop_reg(SCOOP_GPCR) | COLLIE_SCP_VPEN); + if (vpp) + write_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) | COLLIE_SCP_VPEN); + else + write_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) & ~COLLIE_SCP_VPEN); } static struct flash_platform_data collie_flash_data = { diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h index 279e3afa3c39..f085d68e568e 100644 --- a/arch/arm/mach-sa1100/generic.h +++ b/arch/arm/mach-sa1100/generic.h @@ -39,3 +39,6 @@ extern void sa11x0_set_ssp_data(struct sa11x0_ssp_plat_ops *ops); struct irda_platform_data; void sa11x0_set_irda_data(struct irda_platform_data *irda); + +struct mcp_plat_data; +void sa11x0_set_mcp_data(struct mcp_plat_data *data); diff --git a/arch/arm26/boot/compressed/hw-bse.c b/arch/arm26/boot/compressed/hw-bse.c deleted file mode 100644 index 3e8f07f8e08a..000000000000 --- a/arch/arm26/boot/compressed/hw-bse.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Bright Star Engineering Inc. - * - * code for readng parameters from the - * parameter blocks of the boot block - * flash memory - * - */ - -static int strcmp(const char *s1, const char *s2) -{ - while (*s1 != '\0' && *s1 == *s2) - { - s1++; - s2++; - } - - return (*(unsigned char *) s1) - (*(unsigned char *) s2); -} - -struct pblk_t { - char type; - unsigned short size; -}; - -static char *bse_getflashparam(char *name) { - unsigned int esize; - char *q,*r; - unsigned char *p,*e; - struct pblk_t *thepb = (struct pblk_t *) 0x00004000; - struct pblk_t *altpb = (struct pblk_t *) 0x00006000; - if (thepb->type&1) { - if (altpb->type&1) { - /* no valid param block */ - return (char*)0; - } else { - /* altpb is valid */ - struct pblk_t *tmp; - tmp = thepb; - thepb = altpb; - altpb = tmp; - } - } - p = (char*)thepb + sizeof(struct pblk_t); - e = p + thepb->size; - while (p < e) { - q = p; - esize = *p; - if (esize == 0xFF) break; - if (esize == 0) break; - if (esize > 127) { - esize = (esize&0x7F)<<8 | p[1]; - q++; - } - q++; - r=q; - if (*r && ((name == 0) || (!strcmp(name,r)))) { - while (*q++) ; - return q; - } - p+=esize; - } - return (char*)0; -} - -void bse_setup(void) { - /* extract the linux cmdline from flash */ - char *name=bse_getflashparam("linuxboot"); - char *x = (char *)0xc0000100; - if (name) { - while (*name) *x++=*name++; - } - *x=0; -} diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 28a4529fdd60..7e926471e4ec 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -899,7 +899,7 @@ int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base) if ((err = iosapic_init(phys_addr, gsi_base))) return err; -#if CONFIG_ACPI_NUMA +#ifdef CONFIG_ACPI_NUMA acpi_map_iosapic(handle, 0, NULL, NULL); #endif /* CONFIG_ACPI_NUMA */ diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index ba0b6a1f429f..0741b066b98f 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -491,7 +491,7 @@ GLOBAL_ENTRY(prefetch_stack) ;; lfetch.fault [r16], 128 br.ret.sptk.many rp -END(prefetch_switch_stack) +END(prefetch_stack) GLOBAL_ENTRY(execve) mov r15=__NR_execve // put syscall number in place diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c index 6e683745af49..80f83d6cdbfc 100644 --- a/arch/ia64/kernel/mca_drv.c +++ b/arch/ia64/kernel/mca_drv.c @@ -84,23 +84,23 @@ mca_page_isolate(unsigned long paddr) struct page *p; /* whether physical address is valid or not */ - if ( !ia64_phys_addr_valid(paddr) ) + if (!ia64_phys_addr_valid(paddr)) return ISOLATE_NG; /* convert physical address to physical page number */ p = pfn_to_page(paddr>>PAGE_SHIFT); /* check whether a page number have been already registered or not */ - for( i = 0; i < num_page_isolate; i++ ) - if( page_isolate[i] == p ) + for (i = 0; i < num_page_isolate; i++) + if (page_isolate[i] == p) return ISOLATE_OK; /* already listed */ /* limitation check */ - if( num_page_isolate == MAX_PAGE_ISOLATE ) + if (num_page_isolate == MAX_PAGE_ISOLATE) return ISOLATE_NG; /* kick pages having attribute 'SLAB' or 'Reserved' */ - if( PageSlab(p) || PageReserved(p) ) + if (PageSlab(p) || PageReserved(p)) return ISOLATE_NG; /* add attribute 'Reserved' and register the page */ @@ -139,10 +139,10 @@ mca_handler_bh(unsigned long paddr) * @peidx: pointer to index of processor error section */ -static void +static void mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx) { - /* + /* * calculate the start address of * "struct cpuid_info" and "sal_processor_static_info_t". */ @@ -164,7 +164,7 @@ mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx) } /** - * mca_make_slidx - Make index of SAL error record + * mca_make_slidx - Make index of SAL error record * @buffer: pointer to SAL error record * @slidx: pointer to index of SAL error record * @@ -172,12 +172,12 @@ mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx) * 1 if record has platform error / 0 if not */ #define LOG_INDEX_ADD_SECT_PTR(sect, ptr) \ - { slidx_list_t *hl = &slidx_pool.buffer[slidx_pool.cur_idx]; \ - hl->hdr = ptr; \ - list_add(&hl->list, &(sect)); \ - slidx_pool.cur_idx = (slidx_pool.cur_idx + 1)%slidx_pool.max_idx; } + {slidx_list_t *hl = &slidx_pool.buffer[slidx_pool.cur_idx]; \ + hl->hdr = ptr; \ + list_add(&hl->list, &(sect)); \ + slidx_pool.cur_idx = (slidx_pool.cur_idx + 1)%slidx_pool.max_idx; } -static int +static int mca_make_slidx(void *buffer, slidx_table_t *slidx) { int platform_err = 0; @@ -214,28 +214,36 @@ mca_make_slidx(void *buffer, slidx_table_t *slidx) sp = (sal_log_section_hdr_t *)((char*)buffer + ercd_pos); if (!efi_guidcmp(sp->guid, SAL_PROC_DEV_ERR_SECT_GUID)) { LOG_INDEX_ADD_SECT_PTR(slidx->proc_err, sp); - } else if (!efi_guidcmp(sp->guid, SAL_PLAT_MEM_DEV_ERR_SECT_GUID)) { + } else if (!efi_guidcmp(sp->guid, + SAL_PLAT_MEM_DEV_ERR_SECT_GUID)) { platform_err = 1; LOG_INDEX_ADD_SECT_PTR(slidx->mem_dev_err, sp); - } else if (!efi_guidcmp(sp->guid, SAL_PLAT_SEL_DEV_ERR_SECT_GUID)) { + } else if (!efi_guidcmp(sp->guid, + SAL_PLAT_SEL_DEV_ERR_SECT_GUID)) { platform_err = 1; LOG_INDEX_ADD_SECT_PTR(slidx->sel_dev_err, sp); - } else if (!efi_guidcmp(sp->guid, SAL_PLAT_PCI_BUS_ERR_SECT_GUID)) { + } else if (!efi_guidcmp(sp->guid, + SAL_PLAT_PCI_BUS_ERR_SECT_GUID)) { platform_err = 1; LOG_INDEX_ADD_SECT_PTR(slidx->pci_bus_err, sp); - } else if (!efi_guidcmp(sp->guid, SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID)) { + } else if (!efi_guidcmp(sp->guid, + SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID)) { platform_err = 1; LOG_INDEX_ADD_SECT_PTR(slidx->smbios_dev_err, sp); - } else if (!efi_guidcmp(sp->guid, SAL_PLAT_PCI_COMP_ERR_SECT_GUID)) { + } else if (!efi_guidcmp(sp->guid, + SAL_PLAT_PCI_COMP_ERR_SECT_GUID)) { platform_err = 1; LOG_INDEX_ADD_SECT_PTR(slidx->pci_comp_err, sp); - } else if (!efi_guidcmp(sp->guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID)) { + } else if (!efi_guidcmp(sp->guid, + SAL_PLAT_SPECIFIC_ERR_SECT_GUID)) { platform_err = 1; LOG_INDEX_ADD_SECT_PTR(slidx->plat_specific_err, sp); - } else if (!efi_guidcmp(sp->guid, SAL_PLAT_HOST_CTLR_ERR_SECT_GUID)) { + } else if (!efi_guidcmp(sp->guid, + SAL_PLAT_HOST_CTLR_ERR_SECT_GUID)) { platform_err = 1; LOG_INDEX_ADD_SECT_PTR(slidx->host_ctlr_err, sp); - } else if (!efi_guidcmp(sp->guid, SAL_PLAT_BUS_ERR_SECT_GUID)) { + } else if (!efi_guidcmp(sp->guid, + SAL_PLAT_BUS_ERR_SECT_GUID)) { platform_err = 1; LOG_INDEX_ADD_SECT_PTR(slidx->plat_bus_err, sp); } else { @@ -253,15 +261,16 @@ mca_make_slidx(void *buffer, slidx_table_t *slidx) * Return value: * 0 on Success / -ENOMEM on Failure */ -static int +static int init_record_index_pools(void) { int i; int rec_max_size; /* Maximum size of SAL error records */ int sect_min_size; /* Minimum size of SAL error sections */ /* minimum size table of each section */ - static int sal_log_sect_min_sizes[] = { - sizeof(sal_log_processor_info_t) + sizeof(sal_processor_static_info_t), + static int sal_log_sect_min_sizes[] = { + sizeof(sal_log_processor_info_t) + + sizeof(sal_processor_static_info_t), sizeof(sal_log_mem_dev_err_info_t), sizeof(sal_log_sel_dev_err_info_t), sizeof(sal_log_pci_bus_err_info_t), @@ -294,7 +303,8 @@ init_record_index_pools(void) /* - 3 - */ slidx_pool.max_idx = (rec_max_size/sect_min_size) * 2 + 1; - slidx_pool.buffer = (slidx_list_t *) kmalloc(slidx_pool.max_idx * sizeof(slidx_list_t), GFP_KERNEL); + slidx_pool.buffer = (slidx_list_t *) + kmalloc(slidx_pool.max_idx * sizeof(slidx_list_t), GFP_KERNEL); return slidx_pool.buffer ? 0 : -ENOMEM; } @@ -308,6 +318,7 @@ init_record_index_pools(void) * is_mca_global - Check whether this MCA is global or not * @peidx: pointer of index of processor error section * @pbci: pointer to pal_bus_check_info_t + * @sos: pointer to hand off struct between SAL and OS * * Return value: * MCA_IS_LOCAL / MCA_IS_GLOBAL @@ -317,11 +328,12 @@ static mca_type_t is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci, struct ia64_sal_os_state *sos) { - pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx); + pal_processor_state_info_t *psp = + (pal_processor_state_info_t*)peidx_psp(peidx); - /* + /* * PAL can request a rendezvous, if the MCA has a global scope. - * If "rz_always" flag is set, SAL requests MCA rendezvous + * If "rz_always" flag is set, SAL requests MCA rendezvous * in spite of global MCA. * Therefore it is local MCA when rendezvous has not been requested. * Failed to rendezvous, the system must be down. @@ -381,13 +393,15 @@ is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci, * @slidx: pointer of index of SAL error record * @peidx: pointer of index of processor error section * @pbci: pointer of pal_bus_check_info + * @sos: pointer to hand off struct between SAL and OS * * Return value: * 1 on Success / 0 on Failure */ static int -recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci, +recover_from_read_error(slidx_table_t *slidx, + peidx_table_t *peidx, pal_bus_check_info_t *pbci, struct ia64_sal_os_state *sos) { sal_log_mod_error_info_t *smei; @@ -453,24 +467,28 @@ recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_chec * @slidx: pointer of index of SAL error record * @peidx: pointer of index of processor error section * @pbci: pointer of pal_bus_check_info + * @sos: pointer to hand off struct between SAL and OS * * Return value: * 1 on Success / 0 on Failure */ static int -recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci, +recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, + pal_bus_check_info_t *pbci, struct ia64_sal_os_state *sos) { int status = 0; - pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx); + pal_processor_state_info_t *psp = + (pal_processor_state_info_t*)peidx_psp(peidx); if (psp->bc && pbci->eb && pbci->bsi == 0) { switch(pbci->type) { case 1: /* partial read */ case 3: /* full line(cpu) read */ case 9: /* I/O space read */ - status = recover_from_read_error(slidx, peidx, pbci, sos); + status = recover_from_read_error(slidx, peidx, pbci, + sos); break; case 0: /* unknown */ case 2: /* partial write */ @@ -481,7 +499,8 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_ case 8: /* write coalescing transactions */ case 10: /* I/O space write */ case 11: /* inter-processor interrupt message(IPI) */ - case 12: /* interrupt acknowledge or external task priority cycle */ + case 12: /* interrupt acknowledge or + external task priority cycle */ default: break; } @@ -496,6 +515,7 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_ * @slidx: pointer of index of SAL error record * @peidx: pointer of index of processor error section * @pbci: pointer of pal_bus_check_info + * @sos: pointer to hand off struct between SAL and OS * * Return value: * 1 on Success / 0 on Failure @@ -509,15 +529,17 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_ */ static int -recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci, +recover_from_processor_error(int platform, slidx_table_t *slidx, + peidx_table_t *peidx, pal_bus_check_info_t *pbci, struct ia64_sal_os_state *sos) { - pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx); + pal_processor_state_info_t *psp = + (pal_processor_state_info_t*)peidx_psp(peidx); - /* + /* * We cannot recover errors with other than bus_check. */ - if (psp->cc || psp->rc || psp->uc) + if (psp->cc || psp->rc || psp->uc) return 0; /* @@ -546,10 +568,10 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t * * (e.g. a load from poisoned memory) * This means "there are some platform errors". */ - if (platform) + if (platform) return recover_from_platform_error(slidx, peidx, pbci, sos); - /* - * On account of strange SAL error record, we cannot recover. + /* + * On account of strange SAL error record, we cannot recover. */ return 0; } @@ -557,14 +579,14 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t * /** * mca_try_to_recover - Try to recover from MCA * @rec: pointer to a SAL error record + * @sos: pointer to hand off struct between SAL and OS * * Return value: * 1 on Success / 0 on Failure */ static int -mca_try_to_recover(void *rec, - struct ia64_sal_os_state *sos) +mca_try_to_recover(void *rec, struct ia64_sal_os_state *sos) { int platform_err; int n_proc_err; @@ -588,7 +610,8 @@ mca_try_to_recover(void *rec, } /* Make index of processor error section */ - mca_make_peidx((sal_log_processor_info_t*)slidx_first_entry(&slidx.proc_err)->hdr, &peidx); + mca_make_peidx((sal_log_processor_info_t*) + slidx_first_entry(&slidx.proc_err)->hdr, &peidx); /* Extract Processor BUS_CHECK[0] */ *((u64*)&pbci) = peidx_check_info(&peidx, bus_check, 0); @@ -598,7 +621,8 @@ mca_try_to_recover(void *rec, return 0; /* Try to recover a processor error */ - return recover_from_processor_error(platform_err, &slidx, &peidx, &pbci, sos); + return recover_from_processor_error(platform_err, &slidx, &peidx, + &pbci, sos); } /* @@ -611,7 +635,7 @@ int __init mca_external_handler_init(void) return -ENOMEM; /* register external mca handlers */ - if (ia64_reg_MCA_extension(mca_try_to_recover)){ + if (ia64_reg_MCA_extension(mca_try_to_recover)) { printk(KERN_ERR "ia64_reg_MCA_extension failed.\n"); kfree(slidx_pool.buffer); return -EFAULT; diff --git a/arch/ia64/kernel/mca_drv.h b/arch/ia64/kernel/mca_drv.h index 0227b761f2c4..e2f6fa1e0ef6 100644 --- a/arch/ia64/kernel/mca_drv.h +++ b/arch/ia64/kernel/mca_drv.h @@ -6,7 +6,7 @@ * Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com) */ /* - * Processor error section: + * Processor error section: * * +-sal_log_processor_info_t *info-------------+ * | sal_log_section_hdr_t header; | diff --git a/arch/ia64/kernel/mca_drv_asm.S b/arch/ia64/kernel/mca_drv_asm.S index 2d7e0217638d..3f298ee4d00c 100644 --- a/arch/ia64/kernel/mca_drv_asm.S +++ b/arch/ia64/kernel/mca_drv_asm.S @@ -13,45 +13,45 @@ #include <asm/ptrace.h> GLOBAL_ENTRY(mca_handler_bhhook) - invala // clear RSE ? - ;; // - cover // - ;; // - clrrrb // + invala // clear RSE ? + ;; + cover + ;; + clrrrb ;; - alloc r16=ar.pfs,0,2,1,0 // make a new frame + alloc r16=ar.pfs,0,2,1,0 // make a new frame ;; - mov ar.rsc=0 + mov ar.rsc=0 ;; - mov r13=IA64_KR(CURRENT) // current task pointer + mov r13=IA64_KR(CURRENT) // current task pointer ;; - mov r2=r13 + mov r2=r13 ;; - addl r22=IA64_RBS_OFFSET,r2 + addl r22=IA64_RBS_OFFSET,r2 ;; - mov ar.bspstore=r22 + mov ar.bspstore=r22 ;; - addl sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r2 + addl sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r2 ;; - adds r2=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13 + adds r2=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13 ;; - st1 [r2]=r0 // clear current->thread.on_ustack flag - mov loc0=r16 - movl loc1=mca_handler_bh // recovery C function + st1 [r2]=r0 // clear current->thread.on_ustack flag + mov loc0=r16 + movl loc1=mca_handler_bh // recovery C function ;; - mov out0=r8 // poisoned address - mov b6=loc1 + mov out0=r8 // poisoned address + mov b6=loc1 ;; - mov loc1=rp + mov loc1=rp ;; - ssm psr.i + ssm psr.i ;; - br.call.sptk.many rp=b6 // does not return ... + br.call.sptk.many rp=b6 // does not return ... ;; - mov ar.pfs=loc0 - mov rp=loc1 + mov ar.pfs=loc0 + mov rp=loc1 ;; - mov r8=r0 + mov r8=r0 br.ret.sptk.many rp ;; END(mca_handler_bhhook) diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 1650353e3f77..d71731ee5b61 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -574,7 +574,7 @@ pfm_protect_ctx_ctxsw(pfm_context_t *x) return 0UL; } -static inline unsigned long +static inline void pfm_unprotect_ctx_ctxsw(pfm_context_t *x, unsigned long f) { spin_unlock(&(x)->ctx_lock); @@ -2218,12 +2218,13 @@ static void pfm_free_fd(int fd, struct file *file) { struct files_struct *files = current->files; - struct fdtable *fdt = files_fdtable(files); + struct fdtable *fdt; /* * there ie no fd_uninstall(), so we do it here */ spin_lock(&files->file_lock); + fdt = files_fdtable(files); rcu_assign_pointer(fdt->fd[fd], NULL); spin_unlock(&files->file_lock); diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index 8b9b226005d1..b8d08f33f7ee 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile @@ -34,7 +34,8 @@ ifeq ($(CONFIG_40x),y) obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o ppc405_pci.o endif endif -obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) +obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) \ + ppc_sys.o mpc8xx_devices.o mpc8xx_sys.o ifeq ($(CONFIG_8xx),y) obj-$(CONFIG_PCI) += qspan_pci.o i8259.o endif diff --git a/arch/ppc/syslib/mpc8xx_devices.c b/arch/ppc/syslib/mpc8xx_devices.c new file mode 100644 index 000000000000..2b5f0e701687 --- /dev/null +++ b/arch/ppc/syslib/mpc8xx_devices.c @@ -0,0 +1,224 @@ +/* + * arch/ppc/syslib/mpc8xx_devices.c + * + * MPC8xx Device descriptions + * + * Maintainer: Kumar Gala <kumar.gala@freescale.com> + * + * Copyright 2005 MontaVista Software, Inc. by Vitaly Bordug<vbordug@ru.mvista.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/device.h> +#include <linux/serial_8250.h> +#include <linux/mii.h> +#include <asm/commproc.h> +#include <asm/mpc8xx.h> +#include <asm/irq.h> +#include <asm/ppc_sys.h> + +/* We use offsets for IORESOURCE_MEM to do not set dependences at compile time. + * They will get fixed up by mach_mpc8xx_fixup + */ + +struct platform_device ppc_sys_platform_devices[] = { + [MPC8xx_CPM_FEC1] = { + .name = "fsl-cpm-fec", + .id = 1, + .num_resources = 2, + .resource = (struct resource[]) { + { + .name = "regs", + .start = 0xe00, + .end = 0xe88, + .flags = IORESOURCE_MEM, + }, + { + .name = "interrupt", + .start = MPC8xx_INT_FEC1, + .end = MPC8xx_INT_FEC1, + .flags = IORESOURCE_IRQ, + }, + }, + }, + [MPC8xx_CPM_FEC2] = { + .name = "fsl-cpm-fec", + .id = 2, + .num_resources = 2, + .resource = (struct resource[]) { + { + .name = "regs", + .start = 0x1e00, + .end = 0x1e88, + .flags = IORESOURCE_MEM, + }, + { + .name = "interrupt", + .start = MPC8xx_INT_FEC2, + .end = MPC8xx_INT_FEC2, + .flags = IORESOURCE_IRQ, + }, + }, + }, + [MPC8xx_CPM_SCC1] = { + .name = "fsl-cpm-scc", + .id = 1, + .num_resources = 3, + .resource = (struct resource[]) { + { + .name = "regs", + .start = 0xa00, + .end = 0xa18, + .flags = IORESOURCE_MEM, + }, + { + .name = "pram", + .start = 0x3c00, + .end = 0x3c80, + .flags = IORESOURCE_MEM, + }, + { + .name = "interrupt", + .start = MPC8xx_INT_SCC1, + .end = MPC8xx_INT_SCC1, + .flags = IORESOURCE_IRQ, + }, + }, + }, + [MPC8xx_CPM_SCC2] = { + .name = "fsl-cpm-scc", + .id = 2, + .num_resources = 3, + .resource = (struct resource[]) { + { + .name = "regs", + .start = 0xa20, + .end = 0xa38, + .flags = IORESOURCE_MEM, + }, + { + .name = "pram", + .start = 0x3d00, + .end = 0x3d80, + .flags = IORESOURCE_MEM, + }, + + { + .name = "interrupt", + .start = MPC8xx_INT_SCC2, + .end = MPC8xx_INT_SCC2, + .flags = IORESOURCE_IRQ, + }, + }, + }, + [MPC8xx_CPM_SCC3] = { + .name = "fsl-cpm-scc", + .id = 3, + .num_resources = 3, + .resource = (struct resource[]) { + { + .name = "regs", + .start = 0xa40, + .end = 0xa58, + .flags = IORESOURCE_MEM, + }, + { + .name = "pram", + .start = 0x3e00, + .end = 0x3e80, + .flags = IORESOURCE_MEM, + }, + + { + .name = "interrupt", + .start = MPC8xx_INT_SCC3, + .end = MPC8xx_INT_SCC3, + .flags = IORESOURCE_IRQ, + }, + }, + }, + [MPC8xx_CPM_SCC4] = { + .name = "fsl-cpm-scc", + .id = 4, + .num_resources = 3, + .resource = (struct resource[]) { + { + .name = "regs", + .start = 0xa60, + .end = 0xa78, + .flags = IORESOURCE_MEM, + }, + { + .name = "pram", + .start = 0x3f00, + .end = 0x3f80, + .flags = IORESOURCE_MEM, + }, + + { + .name = "interrupt", + .start = MPC8xx_INT_SCC4, + .end = MPC8xx_INT_SCC4, + .flags = IORESOURCE_IRQ, + }, + }, + }, + [MPC8xx_CPM_SMC1] = { + .name = "fsl-cpm-smc", + .id = 1, + .num_resources = 2, + .resource = (struct resource[]) { + { + .name = "regs", + .start = 0xa82, + .end = 0xa91, + .flags = IORESOURCE_MEM, + }, + { + .name = "interrupt", + .start = MPC8xx_INT_SMC1, + .end = MPC8xx_INT_SMC1, + .flags = IORESOURCE_IRQ, + }, + }, + }, + [MPC8xx_CPM_SMC2] = { + .name = "fsl-cpm-smc", + .id = 2, + .num_resources = 2, + .resource = (struct resource[]) { + { + .name = "regs", + .start = 0xa92, + .end = 0xaa1, + .flags = IORESOURCE_MEM, + }, + { + .name = "interrupt", + .start = MPC8xx_INT_SMC2, + .end = MPC8xx_INT_SMC2, + .flags = IORESOURCE_IRQ, + }, + }, + }, +}; + +static int __init mach_mpc8xx_fixup(struct platform_device *pdev) +{ + ppc_sys_fixup_mem_resource (pdev, IMAP_ADDR); + return 0; +} + +static int __init mach_mpc8xx_init(void) +{ + ppc_sys_device_fixup = mach_mpc8xx_fixup; + return 0; +} + +postcore_initcall(mach_mpc8xx_init); diff --git a/arch/ppc/syslib/mpc8xx_sys.c b/arch/ppc/syslib/mpc8xx_sys.c new file mode 100644 index 000000000000..a532ccc861c0 --- /dev/null +++ b/arch/ppc/syslib/mpc8xx_sys.c @@ -0,0 +1,61 @@ +/* + * arch/ppc/platforms/mpc8xx_sys.c + * + * MPC8xx System descriptions + * + * Maintainer: Kumar Gala <kumar.gala@freescale.com> + * + * Copyright 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@ru.mvista.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/device.h> +#include <asm/ppc_sys.h> + +struct ppc_sys_spec *cur_ppc_sys_spec; +struct ppc_sys_spec ppc_sys_specs[] = { + { + .ppc_sys_name = "MPC86X", + .mask = 0xFFFFFFFF, + .value = 0x00000000, + .num_devices = 2, + .device_list = (enum ppc_sys_devices[]) + { + MPC8xx_CPM_FEC1, + MPC8xx_CPM_SCC1, + MPC8xx_CPM_SCC2, + MPC8xx_CPM_SCC3, + MPC8xx_CPM_SCC4, + MPC8xx_CPM_SMC1, + MPC8xx_CPM_SMC2, + }, + }, + { + .ppc_sys_name = "MPC885", + .mask = 0xFFFFFFFF, + .value = 0x00000000, + .num_devices = 3, + .device_list = (enum ppc_sys_devices[]) + { + MPC8xx_CPM_FEC1, + MPC8xx_CPM_FEC2, + MPC8xx_CPM_SCC1, + MPC8xx_CPM_SCC2, + MPC8xx_CPM_SCC3, + MPC8xx_CPM_SCC4, + MPC8xx_CPM_SMC1, + MPC8xx_CPM_SMC2, + }, + }, + { /* default match */ + .ppc_sys_name = "", + .mask = 0x00000000, + .value = 0x00000000, + }, +}; diff --git a/arch/ppc/syslib/open_pic2.c b/arch/ppc/syslib/open_pic2.c index 2e0ea92144f6..9a7e8748e2b2 100644 --- a/arch/ppc/syslib/open_pic2.c +++ b/arch/ppc/syslib/open_pic2.c @@ -575,7 +575,7 @@ static void openpic2_cached_disable_irq(u_int irq) * we need something better to deal with that... Maybe switch to S1 for * cpufreq changes */ -int openpic2_suspend(struct sys_device *sysdev, u32 state) +int openpic2_suspend(struct sys_device *sysdev, pm_message_t state) { int i; unsigned long flags; diff --git a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c index 7fbc68bbb739..be3f25cf3e9f 100644 --- a/arch/ppc64/mm/fault.c +++ b/arch/ppc64/mm/fault.c @@ -38,6 +38,7 @@ #include <asm/system.h> #include <asm/uaccess.h> #include <asm/kdebug.h> +#include <asm/siginfo.h> /* * Check whether the instruction at regs->nip is a store using diff --git a/arch/s390/defconfig b/arch/s390/defconfig index 0865251a3f44..45d44c6bb39d 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc4 -# Fri Jul 29 14:49:30 2005 +# Linux kernel version: 2.6.14-rc1 +# Wed Sep 14 16:46:19 2005 # CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y @@ -21,6 +21,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32 # General setup # CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y @@ -33,6 +34,7 @@ CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_CPUSETS is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set @@ -94,6 +96,7 @@ CONFIG_FLATMEM_MANUAL=y # CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set # # I/O subsystem configuration @@ -151,8 +154,8 @@ CONFIG_IP_FIB_HASH=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_INET_TUNNEL is not set -CONFIG_IP_TCPDIAG=y -CONFIG_IP_TCPDIAG_IPV6=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_BIC=y CONFIG_IPV6=y @@ -165,6 +168,11 @@ CONFIG_IPV6=y # CONFIG_NETFILTER is not set # +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# # SCTP Configuration (EXPERIMENTAL) # # CONFIG_IP_SCTP is not set @@ -217,9 +225,11 @@ CONFIG_NET_CLS_POLICE=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETFILTER_NETLINK is not set # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set +# CONFIG_IEEE80211 is not set # CONFIG_PCMCIA is not set # @@ -233,6 +243,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # # SCSI device support # +# CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_PROC_FS=y @@ -260,6 +271,7 @@ CONFIG_SCSI_LOGGING=y # CONFIG_SCSI_SPI_ATTRS is not set CONFIG_SCSI_FC_ATTRS=y # CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set # # SCSI low-level drivers @@ -280,7 +292,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set # CONFIG_CDROM_PKTCDVD is not set @@ -384,6 +395,10 @@ CONFIG_EQUALIZER=m CONFIG_TUN=m # +# PHY device support +# + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -453,10 +468,6 @@ CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set - -# -# XFS support -# # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set @@ -465,6 +476,7 @@ CONFIG_INOTIFY=y CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set # # CD-ROM/DVD Filesystems @@ -485,11 +497,10 @@ CONFIG_DNOTIFY=y CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_SYSFS=y -# CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y -# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set # # Miscellaneous filesystems @@ -533,6 +544,7 @@ CONFIG_SUNRPC=y # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set # # Partition Types @@ -572,6 +584,7 @@ CONFIG_MSDOS_PARTITION=y CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set CONFIG_DEBUG_PREEMPT=y @@ -626,5 +639,6 @@ CONFIG_CRYPTO=y # Library routines # # CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set CONFIG_CRC32=m # CONFIG_LIBCRC32C is not set diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index ab1e49d2e518..8584dd823218 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -6,7 +6,7 @@ EXTRA_AFLAGS := -traditional obj-y := bitmap.o traps.o time.o process.o \ setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ - semaphore.o s390_ext.o debug.o profile.o irq.o + semaphore.o s390_ext.o debug.o profile.o irq.o reipl_diag.o extra-$(CONFIG_ARCH_S390_31) += head.o extra-$(CONFIG_ARCH_S390X) += head64.o diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 58fc7fbcb40e..9b30f4cf32c4 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -108,7 +108,7 @@ STACK_SIZE = 1 << STACK_SHIFT bl BASED(0f) l %r14,BASED(.Lcleanup_critical) basr %r14,%r14 - tm 0(%r12),0x01 # retest problem state after cleanup + tm 1(%r12),0x01 # retest problem state after cleanup bnz BASED(1f) 0: l %r14,__LC_ASYNC_STACK # are we already on the async stack ? slr %r14,%r15 diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index d0c9ffaa25db..7b9b4a2ba1d7 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -101,7 +101,7 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING) clc \psworg+8(8),BASED(.Lcritical_start) jl 0f brasl %r14,cleanup_critical - tm 0(%r12),0x01 # retest problem state after cleanup + tm 1(%r12),0x01 # retest problem state after cleanup jnz 1f 0: lg %r14,__LC_ASYNC_STACK # are we already on the async. stack ? slgr %r14,%r15 diff --git a/arch/s390/kernel/reipl_diag.c b/arch/s390/kernel/reipl_diag.c new file mode 100644 index 000000000000..83cb42bc0b76 --- /dev/null +++ b/arch/s390/kernel/reipl_diag.c @@ -0,0 +1,39 @@ +/* + * This file contains the implementation of the + * Linux re-IPL support + * + * (C) Copyright IBM Corp. 2005 + * + * Author(s): Volker Sameske (sameske@de.ibm.com) + * + */ + +#include <linux/kernel.h> + +static unsigned int reipl_diag_rc1; +static unsigned int reipl_diag_rc2; + +/* + * re-IPL the system using the last used IPL parameters + */ +void reipl_diag(void) +{ + asm volatile ( + " la %%r4,0\n" + " la %%r5,0\n" + " diag %%r4,%2,0x308\n" + "0:\n" + " st %%r4,%0\n" + " st %%r5,%1\n" + ".section __ex_table,\"a\"\n" +#ifdef __s390x__ + " .align 8\n" + " .quad 0b, 0b\n" +#else + " .align 4\n" + " .long 0b, 0b\n" +#endif + ".previous\n" + : "=m" (reipl_diag_rc1), "=m" (reipl_diag_rc2) + : "d" (3) : "cc", "4", "5" ); +} diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 5ba5a5485da9..5204778b8e5e 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -261,8 +261,11 @@ void (*_machine_power_off)(void) = machine_power_off_smp; * Reboot, halt and power_off routines for non SMP. */ extern void reipl(unsigned long devno); +extern void reipl_diag(void); static void do_machine_restart_nonsmp(char * __unused) { + reipl_diag(); + if (MACHINE_IS_VM) cpcmd ("IPL", NULL, 0); else @@ -634,6 +637,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) struct cpuinfo_S390 *cpuinfo; unsigned long n = (unsigned long) v - 1; + preempt_disable(); if (!n) { seq_printf(m, "vendor_id : IBM/S390\n" "# processors : %i\n" @@ -658,6 +662,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) cpuinfo->cpu_id.ident, cpuinfo->cpu_id.machine); } + preempt_enable(); return 0; } diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 85222fee4361..e13c87b446b2 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -65,6 +65,7 @@ extern char vmhalt_cmd[]; extern char vmpoff_cmd[]; extern void reipl(unsigned long devno); +extern void reipl_diag(void); static void smp_ext_bitcall(int, ec_bit_sig); static void smp_ext_bitcall_others(ec_bit_sig); @@ -283,6 +284,8 @@ static void do_machine_restart(void * __unused) * interrupted by an external interrupt and s390irq * locks are always held disabled). */ + reipl_diag(); + if (MACHINE_IS_VM) cpcmd ("IPL", NULL, 0, NULL); else diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386 index 8ad156a00499..5d92cacd56c6 100644 --- a/arch/um/Kconfig.i386 +++ b/arch/um/Kconfig.i386 @@ -42,3 +42,7 @@ config ARCH_HAS_SC_SIGNALS config ARCH_REUSE_HOST_VSYSCALL_AREA bool default y + +config X86_CMPXCHG + bool + default y diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c index 7a0d115b29d0..5db136e2651c 100644 --- a/arch/um/drivers/mcast_user.c +++ b/arch/um/drivers/mcast_user.c @@ -13,7 +13,6 @@ #include <errno.h> #include <unistd.h> -#include <linux/inet.h> #include <sys/socket.h> #include <sys/un.h> #include <sys/time.h> @@ -55,7 +54,7 @@ static int mcast_open(void *data) struct mcast_data *pri = data; struct sockaddr_in *sin = pri->mcast_addr; struct ip_mreq mreq; - int fd = -EINVAL, yes = 1, err = -EINVAL;; + int fd, yes = 1, err = 0; if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) @@ -66,13 +65,14 @@ static int mcast_open(void *data) if (fd < 0){ printk("mcast_open : data socket failed, errno = %d\n", errno); - fd = -errno; + err = -errno; goto out; } if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", errno); + err = -errno; goto out_close; } @@ -81,6 +81,7 @@ static int mcast_open(void *data) sizeof(pri->ttl)) < 0) { printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", errno); + err = -errno; goto out_close; } @@ -88,12 +89,14 @@ static int mcast_open(void *data) if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", errno); + err = -errno; goto out_close; } /* bind socket to mcast address */ if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { printk("mcast_open : data bind failed, errno = %d\n", errno); + err = -errno; goto out_close; } @@ -108,14 +111,15 @@ static int mcast_open(void *data) "interface on the host.\n"); printk("eth0 should be configured in order to use the " "multicast transport.\n"); + err = -errno; goto out_close; } - out: return fd; out_close: os_close_file(fd); + out: return err; } diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index c190c2414197..12c95368124a 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -32,6 +32,7 @@ #include "os.h" #include "umid.h" #include "irq_kern.h" +#include "choose-mode.h" static int do_unlink_socket(struct notifier_block *notifier, unsigned long what, void *data) @@ -276,6 +277,7 @@ void mconsole_proc(struct mc_request *req) go - continue the UML after a 'stop' \n\ log <string> - make UML enter <string> into the kernel log\n\ proc <file> - returns the contents of the UML's /proc/<file>\n\ + stack <pid> - returns the stack of the specified pid\n\ " void mconsole_help(struct mc_request *req) @@ -479,6 +481,56 @@ void mconsole_sysrq(struct mc_request *req) } #endif +/* Mconsole stack trace + * Added by Allan Graves, Jeff Dike + * Dumps a stacks registers to the linux console. + * Usage stack <pid>. + */ +void do_stack(struct mc_request *req) +{ + char *ptr = req->request.data; + int pid_requested= -1; + struct task_struct *from = NULL; + struct task_struct *to = NULL; + + /* Would be nice: + * 1) Send showregs output to mconsole. + * 2) Add a way to stack dump all pids. + */ + + ptr += strlen("stack"); + while(isspace(*ptr)) ptr++; + + /* Should really check for multiple pids or reject bad args here */ + /* What do the arguments in mconsole_reply mean? */ + if(sscanf(ptr, "%d", &pid_requested) == 0){ + mconsole_reply(req, "Please specify a pid", 1, 0); + return; + } + + from = current; + to = find_task_by_pid(pid_requested); + + if((to == NULL) || (pid_requested == 0)) { + mconsole_reply(req, "Couldn't find that pid", 1, 0); + return; + } + to->thread.saved_task = current; + + switch_to(from, to, from); + mconsole_reply(req, "Stack Dumped to console and message log", 0, 0); +} + +void mconsole_stack(struct mc_request *req) +{ + /* This command doesn't work in TT mode, so let's check and then + * get out of here + */ + CHOOSE_MODE(mconsole_reply(req, "Sorry, this doesn't work in TT mode", + 1, 0), + do_stack(req)); +} + /* Changed by mconsole_setup, which is __setup, and called before SMP is * active. */ diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index fe5afb13252c..310c1f823f26 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c @@ -30,6 +30,7 @@ static struct mconsole_command commands[] = { { "go", mconsole_go, MCONSOLE_INTR }, { "log", mconsole_log, MCONSOLE_INTR }, { "proc", mconsole_proc, MCONSOLE_PROC }, + { "stack", mconsole_stack, MCONSOLE_INTR }, }; /* Initialized in mconsole_init, which is an initcall */ @@ -172,9 +173,9 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len) if(notify_sock < 0){ notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0); if(notify_sock < 0){ - printk("mconsole_notify - socket failed, errno = %d\n", - errno); err = -errno; + printk("mconsole_notify - socket failed, errno = %d\n", + err); } } unlock_notify(); @@ -197,8 +198,8 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len) n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target, sizeof(target)); if(n < 0){ - printk("mconsole_notify - sendto failed, errno = %d\n", errno); err = -errno; + printk("mconsole_notify - sendto failed, errno = %d\n", errno); } return(err); } diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c index ed84d01df6cc..0306a1b215b7 100644 --- a/arch/um/drivers/pty.c +++ b/arch/um/drivers/pty.c @@ -43,8 +43,9 @@ static int pts_open(int input, int output, int primary, void *d, fd = get_pty(); if(fd < 0){ + err = -errno; printk("open_pts : Failed to open pts\n"); - return(-errno); + return err; } if(data->raw){ CATCH_EINTR(err = tcgetattr(fd, &data->tt)); diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c deleted file mode 100644 index b94d2bc4fe06..000000000000 --- a/arch/um/drivers/ubd_user.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) - * Copyright (C) 2001 Ridgerun,Inc (glonnon@ridgerun.com) - * Licensed under the GPL - */ - -#include <stddef.h> -#include <unistd.h> -#include <errno.h> -#include <sched.h> -#include <signal.h> -#include <string.h> -#include <netinet/in.h> -#include <sys/time.h> -#include <sys/socket.h> -#include <sys/mman.h> -#include <sys/param.h> -#include "asm/types.h" -#include "user_util.h" -#include "kern_util.h" -#include "user.h" -#include "ubd_user.h" -#include "os.h" -#include "cow.h" - -#include <endian.h> -#include <byteswap.h> - -void ignore_sigwinch_sig(void) -{ - signal(SIGWINCH, SIG_IGN); -} - -int start_io_thread(unsigned long sp, int *fd_out) -{ - int pid, fds[2], err; - - err = os_pipe(fds, 1, 1); - if(err < 0){ - printk("start_io_thread - os_pipe failed, err = %d\n", -err); - goto out; - } - - kernel_fd = fds[0]; - *fd_out = fds[1]; - - pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD, - NULL); - if(pid < 0){ - printk("start_io_thread - clone failed : errno = %d\n", errno); - err = -errno; - goto out_close; - } - - return(pid); - - out_close: - os_close_file(fds[0]); - os_close_file(fds[1]); - kernel_fd = -1; - *fd_out = -1; - out: - return(err); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index 93dc1911363f..90e0e5ff451e 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c @@ -110,13 +110,15 @@ int xterm_open(int input, int output, int primary, void *d, fd = mkstemp(file); if(fd < 0){ + err = -errno; printk("xterm_open : mkstemp failed, errno = %d\n", errno); - return(-errno); + return err; } if(unlink(file)){ + err = -errno; printk("xterm_open : unlink failed, errno = %d\n", errno); - return(-errno); + return err; } os_close_file(fd); diff --git a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h index cfa368e045a5..b1b512f47035 100644 --- a/arch/um/include/mconsole.h +++ b/arch/um/include/mconsole.h @@ -81,6 +81,7 @@ extern void mconsole_stop(struct mc_request *req); extern void mconsole_go(struct mc_request *req); extern void mconsole_log(struct mc_request *req); extern void mconsole_proc(struct mc_request *req); +extern void mconsole_stack(struct mc_request *req); extern int mconsole_get_request(int fd, struct mc_request *req); extern int mconsole_notify(char *sock_name, int type, const void *data, diff --git a/arch/um/include/mem_user.h b/arch/um/include/mem_user.h index d6404bb64662..9fef4123a65a 100644 --- a/arch/um/include/mem_user.h +++ b/arch/um/include/mem_user.h @@ -51,7 +51,6 @@ extern unsigned long task_size; extern void check_devanon(void); extern int init_mem_user(void); -extern int create_mem_file(unsigned long len); extern void setup_memory(void *entry); extern unsigned long find_iomem(char *driver, unsigned long *len_out); extern int init_maps(unsigned long physmem, unsigned long iomem, @@ -64,20 +63,6 @@ extern unsigned long phys_offset(unsigned long phys); extern void unmap_physmem(void); extern void map_memory(unsigned long virt, unsigned long phys, unsigned long len, int r, int w, int x); -extern int protect_memory(unsigned long addr, unsigned long len, - int r, int w, int x, int must_succeed); extern unsigned long get_kmem_end(void); -extern void check_tmpexec(void); #endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 4c362458052c..583329d0a539 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -157,6 +157,9 @@ extern int os_lock_file(int fd, int excl); extern void os_early_checks(void); extern int can_do_skas(void); +/* mem.c */ +extern int create_mem_file(unsigned long len); + /* process.c */ extern unsigned long os_process_pc(int pid); extern int os_process_parent(int pid); @@ -181,6 +184,8 @@ extern unsigned long long os_usecs(void); /* tt.c * for tt mode only (will be deleted in future...) */ +extern int protect_memory(unsigned long addr, unsigned long len, + int r, int w, int x, int must_succeed); extern void forward_pending_sigio(int target); extern int start_fork_tramp(void *arg, unsigned long temp_stack, int clone_flags, int (*tramp)(void *)); diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index 614b8ebeb0ed..1a0001b3850c 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -1,4 +1,4 @@ -# +# # Copyright (C) 2002 Jeff Dike (jdike@karaya.com) # Licensed under the GPL # @@ -7,11 +7,11 @@ extra-y := vmlinux.lds clean-files := obj-y = config.o exec_kern.o exitcode.o \ - helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o mem_user.o \ - physmem.o process_kern.o ptrace.o reboot.o resource.o sigio_user.o \ - sigio_kern.o signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o \ - tempfile.o time.o time_kern.o tlb.o trap_kern.o trap_user.o \ - uaccess_user.o um_arch.o umid.o user_util.o + helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o physmem.o \ + process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \ + signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \ + time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o \ + umid.o user_util.o obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o obj-$(CONFIG_GPROF) += gprof_syms.o @@ -24,8 +24,8 @@ obj-$(CONFIG_MODE_SKAS) += skas/ user-objs-$(CONFIG_TTY_LOG) += tty_log.o -USER_OBJS := $(user-objs-y) config.o helper.o main.o tempfile.o time.o \ - tty_log.o umid.o user_util.o +USER_OBJS := $(user-objs-y) config.o helper.o main.o time.o tty_log.o umid.o \ + user_util.o include arch/um/scripts/Makefile.rules diff --git a/arch/um/kernel/helper.c b/arch/um/kernel/helper.c index f83e1e8e2392..33fb0bd3b11a 100644 --- a/arch/um/kernel/helper.c +++ b/arch/um/kernel/helper.c @@ -85,8 +85,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, data.fd = fds[1]; pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data); if(pid < 0){ - printk("run_helper : clone failed, errno = %d\n", errno); ret = -errno; + printk("run_helper : clone failed, errno = %d\n", errno); goto out_close; } @@ -122,7 +122,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, unsigned long *stack_out, int stack_order) { unsigned long stack, sp; - int pid, status; + int pid, status, err; stack = alloc_stack(stack_order, um_in_interrupt()); if(stack == 0) return(-ENOMEM); @@ -130,16 +130,18 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, sp = stack + (page_size() << stack_order) - sizeof(void *); pid = clone(proc, (void *) sp, flags | SIGCHLD, arg); if(pid < 0){ + err = -errno; printk("run_helper_thread : clone failed, errno = %d\n", errno); - return(-errno); + return err; } if(stack_out == NULL){ CATCH_EINTR(pid = waitpid(pid, &status, 0)); if(pid < 0){ + err = -errno; printk("run_helper_thread - wait failed, errno = %d\n", errno); - pid = -errno; + pid = err; } if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) printk("run_helper_thread - thread returned status " @@ -156,8 +158,8 @@ int helper_wait(int pid) CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG)); if(ret < 0){ + ret = -errno; printk("helper_wait : waitpid failed, errno = %d\n", errno); - return(-errno); } return(ret); } diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c index cd7c85be0a1b..49ed5ddf0704 100644 --- a/arch/um/kernel/init_task.c +++ b/arch/um/kernel/init_task.c @@ -13,6 +13,7 @@ #include "asm/pgtable.h" #include "user_util.h" #include "mem_user.h" +#include "os.h" static struct fs_struct init_fs = INIT_FS; struct mm_struct init_mm = INIT_MM(init_mm); @@ -45,8 +46,8 @@ __attribute__((__section__(".data.init_task"))) = void unprotect_stack(unsigned long stack) { - protect_memory(stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE, - 1, 1, 0, 1); + os_protect_memory((void *) stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE, + 1, 1, 0); } /* diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 64fa062cc119..ea008b031a8f 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -19,6 +19,10 @@ #include "mem_user.h" #include "uml_uaccess.h" #include "os.h" +#include "linux/types.h" +#include "linux/string.h" +#include "init.h" +#include "kern_constants.h" extern char __binary_start; @@ -368,6 +372,16 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) return pte; } +struct iomem_region *iomem_regions = NULL; +int iomem_size = 0; + +extern int parse_iomem(char *str, int *add) __init; + +__uml_setup("iomem=", parse_iomem, +"iomem=<name>,<file>\n" +" Configure <file> as an IO memory region named <name>.\n\n" +); + /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff --git a/arch/um/kernel/mem_user.c b/arch/um/kernel/mem_user.c deleted file mode 100644 index 4a663fd434bb..000000000000 --- a/arch/um/kernel/mem_user.c +++ /dev/null @@ -1,273 +0,0 @@ -/* - * arch/um/kernel/mem_user.c - * - * BRIEF MODULE DESCRIPTION - * user side memory routines for supporting IO memory inside user mode linux - * - * Copyright (C) 2001 RidgeRun, Inc. - * Author: RidgeRun, Inc. - * Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <stdarg.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/mman.h> -#include "kern_util.h" -#include "user.h" -#include "user_util.h" -#include "mem_user.h" -#include "init.h" -#include "os.h" -#include "tempfile.h" -#include "kern_constants.h" - -#define TEMPNAME_TEMPLATE "vm_file-XXXXXX" - -static int create_tmp_file(unsigned long len) -{ - int fd, err; - char zero; - - fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1); - if(fd < 0) { - os_print_error(fd, "make_tempfile"); - exit(1); - } - - err = os_mode_fd(fd, 0777); - if(err < 0){ - os_print_error(err, "os_mode_fd"); - exit(1); - } - err = os_seek_file(fd, len); - if(err < 0){ - os_print_error(err, "os_seek_file"); - exit(1); - } - zero = 0; - err = os_write_file(fd, &zero, 1); - if(err != 1){ - os_print_error(err, "os_write_file"); - exit(1); - } - - return(fd); -} - -void check_tmpexec(void) -{ - void *addr; - int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE); - - addr = mmap(NULL, UM_KERN_PAGE_SIZE, - PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0); - printf("Checking PROT_EXEC mmap in /tmp..."); - fflush(stdout); - if(addr == MAP_FAILED){ - err = errno; - perror("failed"); - if(err == EPERM) - printf("/tmp must be not mounted noexec\n"); - exit(1); - } - printf("OK\n"); - munmap(addr, UM_KERN_PAGE_SIZE); - - os_close_file(fd); -} - -static int have_devanon = 0; - -void check_devanon(void) -{ - int fd; - - printk("Checking for /dev/anon on the host..."); - fd = open("/dev/anon", O_RDWR); - if(fd < 0){ - printk("Not available (open failed with errno %d)\n", errno); - return; - } - - printk("OK\n"); - have_devanon = 1; -} - -static int create_anon_file(unsigned long len) -{ - void *addr; - int fd; - - fd = open("/dev/anon", O_RDWR); - if(fd < 0) { - os_print_error(fd, "opening /dev/anon"); - exit(1); - } - - addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - if(addr == MAP_FAILED){ - perror("mapping physmem file"); - exit(1); - } - munmap(addr, len); - - return(fd); -} - -int create_mem_file(unsigned long len) -{ - int err, fd; - - if(have_devanon) - fd = create_anon_file(len); - else fd = create_tmp_file(len); - - err = os_set_exec_close(fd, 1); - if(err < 0) - os_print_error(err, "exec_close"); - return(fd); -} - -struct iomem_region *iomem_regions = NULL; -int iomem_size = 0; - -static int __init parse_iomem(char *str, int *add) -{ - struct iomem_region *new; - struct uml_stat buf; - char *file, *driver; - int fd, err, size; - - driver = str; - file = strchr(str,','); - if(file == NULL){ - printf("parse_iomem : failed to parse iomem\n"); - goto out; - } - *file = '\0'; - file++; - fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0); - if(fd < 0){ - os_print_error(fd, "parse_iomem - Couldn't open io file"); - goto out; - } - - err = os_stat_fd(fd, &buf); - if(err < 0){ - os_print_error(err, "parse_iomem - cannot stat_fd file"); - goto out_close; - } - - new = malloc(sizeof(*new)); - if(new == NULL){ - perror("Couldn't allocate iomem_region struct"); - goto out_close; - } - - size = (buf.ust_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1); - - *new = ((struct iomem_region) { .next = iomem_regions, - .driver = driver, - .fd = fd, - .size = size, - .phys = 0, - .virt = 0 }); - iomem_regions = new; - iomem_size += new->size + UM_KERN_PAGE_SIZE; - - return(0); - out_close: - os_close_file(fd); - out: - return(1); -} - -__uml_setup("iomem=", parse_iomem, -"iomem=<name>,<file>\n" -" Configure <file> as an IO memory region named <name>.\n\n" -); - -int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, - int must_succeed) -{ - int err; - - err = os_protect_memory((void *) addr, len, r, w, x); - if(err < 0){ - if(must_succeed) - panic("protect failed, err = %d", -err); - else return(err); - } - return(0); -} - -#if 0 -/* Debugging facility for dumping stuff out to the host, avoiding the timing - * problems that come with printf and breakpoints. - * Enable in case of emergency. - */ - -int logging = 1; -int logging_fd = -1; - -int logging_line = 0; -char logging_buf[512]; - -void log(char *fmt, ...) -{ - va_list ap; - struct timeval tv; - struct openflags flags; - - if(logging == 0) return; - if(logging_fd < 0){ - flags = of_create(of_trunc(of_rdwr(OPENFLAGS()))); - logging_fd = os_open_file("log", flags, 0644); - } - gettimeofday(&tv, NULL); - sprintf(logging_buf, "%d\t %u.%u ", logging_line++, tv.tv_sec, - tv.tv_usec); - va_start(ap, fmt); - vsprintf(&logging_buf[strlen(logging_buf)], fmt, ap); - va_end(ap); - write(logging_fd, logging_buf, strlen(logging_buf)); -} -#endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index c23d8a08d0ff..39cf568ccfaf 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c @@ -113,8 +113,23 @@ void set_current(void *t) void *_switch_to(void *prev, void *next, void *last) { - return(CHOOSE_MODE(switch_to_tt(prev, next), - switch_to_skas(prev, next))); + struct task_struct *from = prev; + struct task_struct *to= next; + + to->thread.prev_sched = from; + set_current(to); + + do { + current->thread.saved_task = NULL ; + CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next); + if(current->thread.saved_task) + show_regs(&(current->thread.regs)); + next= current->thread.saved_task; + prev= current; + } while(current->thread.saved_task); + + return(current->thread.prev_sched); + } void interrupt_end(void) diff --git a/arch/um/kernel/skas/include/mode_kern-skas.h b/arch/um/kernel/skas/include/mode_kern-skas.h index e48490028111..c97a80dfe370 100644 --- a/arch/um/kernel/skas/include/mode_kern-skas.h +++ b/arch/um/kernel/skas/include/mode_kern-skas.h @@ -11,7 +11,7 @@ #include "asm/ptrace.h" extern void flush_thread_skas(void); -extern void *switch_to_skas(void *prev, void *next); +extern void switch_to_skas(void *prev, void *next); extern void start_thread_skas(struct pt_regs *regs, unsigned long eip, unsigned long esp); extern int copy_thread_skas(int nr, unsigned long clone_flags, diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c index 3d1b227226e6..efe92e8aa2a9 100644 --- a/arch/um/kernel/skas/process_kern.c +++ b/arch/um/kernel/skas/process_kern.c @@ -24,7 +24,7 @@ #include "proc_mm.h" #include "registers.h" -void *switch_to_skas(void *prev, void *next) +void switch_to_skas(void *prev, void *next) { struct task_struct *from, *to; @@ -35,16 +35,11 @@ void *switch_to_skas(void *prev, void *next) if(current->pid == 0) switch_timers(0); - to->thread.prev_sched = from; - set_current(to); - switch_threads(&from->thread.mode.skas.switch_buf, to->thread.mode.skas.switch_buf); if(current->pid == 0) switch_timers(1); - - return(current->thread.prev_sched); } extern void schedule_tail(struct task_struct *prev); diff --git a/arch/um/kernel/tempfile.c b/arch/um/kernel/tempfile.c deleted file mode 100644 index b1674bc1395d..000000000000 --- a/arch/um/kernel/tempfile.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> -#include <sys/param.h> -#include "init.h" - -/* Modified from create_mem_file and start_debugger */ -static char *tempdir = NULL; - -static void __init find_tempdir(void) -{ - char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL }; - int i; - char *dir = NULL; - - if(tempdir != NULL) return; /* We've already been called */ - for(i = 0; dirs[i]; i++){ - dir = getenv(dirs[i]); - if((dir != NULL) && (*dir != '\0')) - break; - } - if((dir == NULL) || (*dir == '\0')) - dir = "/tmp"; - - tempdir = malloc(strlen(dir) + 2); - if(tempdir == NULL){ - fprintf(stderr, "Failed to malloc tempdir, " - "errno = %d\n", errno); - return; - } - strcpy(tempdir, dir); - strcat(tempdir, "/"); -} - -int make_tempfile(const char *template, char **out_tempname, int do_unlink) -{ - char tempname[MAXPATHLEN]; - int fd; - - find_tempdir(); - if (*template != '/') - strcpy(tempname, tempdir); - else - *tempname = 0; - strcat(tempname, template); - fd = mkstemp(tempname); - if(fd < 0){ - fprintf(stderr, "open - cannot create %s: %s\n", tempname, - strerror(errno)); - return -1; - } - if(do_unlink && (unlink(tempname) < 0)){ - perror("unlink"); - return -1; - } - if(out_tempname){ - *out_tempname = strdup(tempname); - if(*out_tempname == NULL){ - perror("strdup"); - return -1; - } - } - return(fd); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c index 80ed6188e8a2..0a562c3c0fd8 100644 --- a/arch/um/kernel/tlb.c +++ b/arch/um/kernel/tlb.c @@ -307,7 +307,7 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) } else if(pte_newprot(*pte)){ updated = 1; - protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1); + os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1); } addr += PAGE_SIZE; } diff --git a/arch/um/kernel/tt/include/mode_kern-tt.h b/arch/um/kernel/tt/include/mode_kern-tt.h index e0ca0e0b2516..2a35b15c5fef 100644 --- a/arch/um/kernel/tt/include/mode_kern-tt.h +++ b/arch/um/kernel/tt/include/mode_kern-tt.h @@ -11,7 +11,7 @@ #include "asm/ptrace.h" #include "asm/uaccess.h" -extern void *switch_to_tt(void *prev, void *next); +extern void switch_to_tt(void *prev, void *next); extern void flush_thread_tt(void); extern void start_thread_tt(struct pt_regs *regs, unsigned long eip, unsigned long esp); diff --git a/arch/um/kernel/tt/mem_user.c b/arch/um/kernel/tt/mem_user.c index 3085267459b1..03e589895388 100644 --- a/arch/um/kernel/tt/mem_user.c +++ b/arch/um/kernel/tt/mem_user.c @@ -12,6 +12,7 @@ #include "tt.h" #include "mem_user.h" #include "user_util.h" +#include "os.h" void remap_data(void *segment_start, void *segment_end, int w) { diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c index a189a2b92935..0de05a268b22 100644 --- a/arch/um/kernel/tt/process_kern.c +++ b/arch/um/kernel/tt/process_kern.c @@ -26,7 +26,7 @@ #include "init.h" #include "tt.h" -void *switch_to_tt(void *prev, void *next, void *last) +int switch_to_tt(void *prev, void *next, void *last) { struct task_struct *from, *to, *prev_sched; unsigned long flags; @@ -36,8 +36,6 @@ void *switch_to_tt(void *prev, void *next, void *last) from = prev; to = next; - to->thread.prev_sched = from; - cpu = from->thread_info->cpu; if(cpu == 0) forward_interrupts(to->thread.mode.tt.extern_pid); @@ -53,7 +51,6 @@ void *switch_to_tt(void *prev, void *next, void *last) forward_pending_sigio(to->thread.mode.tt.extern_pid); c = 0; - set_current(to); err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c)); if(err != sizeof(c)) @@ -85,8 +82,6 @@ void *switch_to_tt(void *prev, void *next, void *last) flush_tlb_all(); local_irq_restore(flags); - - return(current->thread.prev_sched); } void release_thread_tt(struct task_struct *task) diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 09f6f7ce4695..f0a275947d34 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -361,11 +361,6 @@ int linux_main(int argc, char **argv) uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0, &host_task_size, &task_size); - /* Need to check this early because mmapping happens before the - * kernel is running. - */ - check_tmpexec(); - brk_start = (unsigned long) sbrk(0); CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start); /* Increase physical memory size for exec-shield users diff --git a/arch/um/kernel/user_util.c b/arch/um/kernel/user_util.c index 954ff67cc8b3..a25f3ea11fd7 100644 --- a/arch/um/kernel/user_util.c +++ b/arch/um/kernel/user_util.c @@ -109,18 +109,14 @@ int raw(int fd) int err; CATCH_EINTR(err = tcgetattr(fd, &tt)); - if (err < 0) { - printk("tcgetattr failed, errno = %d\n", errno); - return(-errno); - } + if(err < 0) + return -errno; cfmakeraw(&tt); CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt)); - if (err < 0) { - printk("tcsetattr failed, errno = %d\n", errno); - return(-errno); - } + if(err < 0) + return -errno; /* XXX tcsetattr could have applied only some changes * (and cfmakeraw() is a set of changes) */ diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index 7a1662419c0c..d15ec2af6a22 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile @@ -3,11 +3,11 @@ # Licensed under the GPL # -obj-y = aio.o elf_aux.o file.o process.o signal.o start_up.o time.o tt.o \ - tty.o user_syms.o drivers/ sys-$(SUBARCH)/ +obj-y = aio.o elf_aux.o file.o mem.o process.o signal.o start_up.o time.o \ + tt.o tty.o user_syms.o drivers/ sys-$(SUBARCH)/ -USER_OBJS := aio.o elf_aux.o file.o process.o signal.o start_up.o time.o tt.o \ - tty.o +USER_OBJS := aio.o elf_aux.o file.o mem.o process.o signal.o start_up.o \ + time.o tt.o tty.o elf_aux.o: $(ARCH_DIR)/kernel-offsets.h CFLAGS_elf_aux.o += -I$(objtree)/arch/um diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c index b04897cd995d..298d5632128b 100644 --- a/arch/um/os-Linux/aio.c +++ b/arch/um/os-Linux/aio.c @@ -117,6 +117,8 @@ static int do_aio(aio_context_t ctx, struct aio_context *aio) err = io_submit(ctx, 1, &iocbp); if(err > 0) err = 0; + else + err = -errno; out: return err; @@ -142,7 +144,7 @@ static int aio_thread(void *arg) "errno = %d\n", errno); } else { - aio = (struct aio_context *) event.data; + aio = (struct aio_context *) (long) event.data; if(update_aio(aio, event.res)){ do_aio(ctx, aio); continue; @@ -313,15 +315,16 @@ static int init_aio_26(void) int err; if(io_setup(256, &ctx)){ + err = -errno; printk("aio_thread failed to initialize context, err = %d\n", errno); - return -errno; + return err; } err = run_helper_thread(aio_thread, NULL, CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); if(err < 0) - return -errno; + return err; aio_pid = err; diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c index 4b83c6c3f48d..4ba9b17adf13 100644 --- a/arch/um/os-Linux/drivers/tuntap_user.c +++ b/arch/um/os-Linux/drivers/tuntap_user.c @@ -75,7 +75,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, struct msghdr msg; struct cmsghdr *cmsg; struct iovec iov; - int pid, n; + int pid, n, err; sprintf(version_buf, "%d", UML_NET_VERSION); @@ -105,9 +105,10 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, n = recvmsg(me, &msg, 0); *used_out = n; if(n < 0){ + err = -errno; printk("tuntap_open_tramp : recvmsg failed - errno = %d\n", errno); - return(-errno); + return err; } CATCH_EINTR(waitpid(pid, NULL, 0)); @@ -147,9 +148,10 @@ static int tuntap_open(void *data) ifr.ifr_flags = IFF_TAP | IFF_NO_PI; strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name)); if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){ + err = -errno; printk("TUNSETIFF failed, errno = %d\n", errno); os_close_file(pri->fd); - return(-errno); + return err; } } else { diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c index 1399520a8588..e770cb029578 100644 --- a/arch/um/os-Linux/elf_aux.c +++ b/arch/um/os-Linux/elf_aux.c @@ -54,7 +54,8 @@ __init void scan_elf_aux( char **envp) * a_un, so we have to use a_val, which is * all that's left. */ - elf_aux_platform = (char *) auxv->a_un.a_val; + elf_aux_platform = + (char *) (long) auxv->a_un.a_val; break; case AT_PAGESZ: page_size = auxv->a_un.a_val; diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c index fd45bb260907..f55773c819e6 100644 --- a/arch/um/os-Linux/file.c +++ b/arch/um/os-Linux/file.c @@ -119,15 +119,11 @@ int os_window_size(int fd, int *rows, int *cols) int os_new_tty_pgrp(int fd, int pid) { - if(ioctl(fd, TIOCSCTTY, 0) < 0){ - printk("TIOCSCTTY failed, errno = %d\n", errno); - return(-errno); - } + if(ioctl(fd, TIOCSCTTY, 0) < 0) + return -errno; - if(tcsetpgrp(fd, pid) < 0){ - printk("tcsetpgrp failed, errno = %d\n", errno); - return(-errno); - } + if(tcsetpgrp(fd, pid) < 0) + return -errno; return(0); } @@ -146,18 +142,12 @@ int os_set_slip(int fd) int disc, sencap; disc = N_SLIP; - if(ioctl(fd, TIOCSETD, &disc) < 0){ - printk("Failed to set slip line discipline - " - "errno = %d\n", errno); - return(-errno); - } + if(ioctl(fd, TIOCSETD, &disc) < 0) + return -errno; sencap = 0; - if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0){ - printk("Failed to set slip encapsulation - " - "errno = %d\n", errno); - return(-errno); - } + if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0) + return -errno; return(0); } @@ -180,22 +170,15 @@ int os_sigio_async(int master, int slave) int flags; flags = fcntl(master, F_GETFL); - if(flags < 0) { - printk("fcntl F_GETFL failed, errno = %d\n", errno); - return(-errno); - } + if(flags < 0) + return errno; if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) || - (fcntl(master, F_SETOWN, os_getpid()) < 0)){ - printk("fcntl F_SETFL or F_SETOWN failed, errno = %d\n", - errno); - return(-errno); - } + (fcntl(master, F_SETOWN, os_getpid()) < 0)) + return -errno; - if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)){ - printk("fcntl F_SETFL failed, errno = %d\n", errno); - return(-errno); - } + if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)) + return -errno; return(0); } @@ -255,7 +238,7 @@ int os_file_mode(char *file, struct openflags *mode_out) int os_open_file(char *file, struct openflags flags, int mode) { - int fd, f = 0; + int fd, err, f = 0; if(flags.r && flags.w) f = O_RDWR; else if(flags.r) f = O_RDONLY; @@ -272,8 +255,9 @@ int os_open_file(char *file, struct openflags flags, int mode) return(-errno); if(flags.cl && fcntl(fd, F_SETFD, 1)){ + err = -errno; os_close_file(fd); - return(-errno); + return err; } return(fd); @@ -383,9 +367,9 @@ int os_file_size(char *file, unsigned long long *size_out) return(fd); } if(ioctl(fd, BLKGETSIZE, &blocks) < 0){ + err = -errno; printk("Couldn't get the block size of \"%s\", " "errno = %d\n", file, errno); - err = -errno; os_close_file(fd); return(err); } @@ -473,11 +457,14 @@ int os_pipe(int *fds, int stream, int close_on_exec) int os_set_fd_async(int fd, int owner) { + int err; + /* XXX This should do F_GETFL first */ if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){ + err = -errno; printk("os_set_fd_async : failed to set O_ASYNC and " "O_NONBLOCK on fd # %d, errno = %d\n", fd, errno); - return(-errno); + return err; } #ifdef notdef if(fcntl(fd, F_SETFD, 1) < 0){ @@ -488,10 +475,11 @@ int os_set_fd_async(int fd, int owner) if((fcntl(fd, F_SETSIG, SIGIO) < 0) || (fcntl(fd, F_SETOWN, owner) < 0)){ + err = -errno; printk("os_set_fd_async : Failed to fcntl F_SETOWN " "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd, owner, errno); - return(-errno); + return err; } return(0); @@ -516,11 +504,9 @@ int os_set_fd_block(int fd, int blocking) if(blocking) flags &= ~O_NONBLOCK; else flags |= O_NONBLOCK; - if(fcntl(fd, F_SETFL, flags) < 0){ - printk("Failed to change blocking on fd # %d, errno = %d\n", - fd, errno); - return(-errno); - } + if(fcntl(fd, F_SETFL, flags) < 0) + return -errno; + return(0); } @@ -609,11 +595,8 @@ int os_create_unix_socket(char *file, int len, int close_on_exec) int sock, err; sock = socket(PF_UNIX, SOCK_DGRAM, 0); - if (sock < 0){ - printk("create_unix_socket - socket failed, errno = %d\n", - errno); - return(-errno); - } + if(sock < 0) + return -errno; if(close_on_exec) { err = os_set_exec_close(sock, 1); @@ -628,11 +611,8 @@ int os_create_unix_socket(char *file, int len, int close_on_exec) snprintf(addr.sun_path, len, "%s", file); err = bind(sock, (struct sockaddr *) &addr, sizeof(addr)); - if (err < 0){ - printk("create_listening_socket at '%s' - bind failed, " - "errno = %d\n", file, errno); - return(-errno); - } + if(err < 0) + return -errno; return(sock); } diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c new file mode 100644 index 000000000000..8e71edaaf80b --- /dev/null +++ b/arch/um/os-Linux/mem.c @@ -0,0 +1,161 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <stdarg.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/mman.h> +#include "kern_util.h" +#include "user.h" +#include "user_util.h" +#include "mem_user.h" +#include "init.h" +#include "os.h" +#include "tempfile.h" +#include "kern_constants.h" + +#include <sys/param.h> + +static char *tempdir = NULL; + +static void __init find_tempdir(void) +{ + char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL }; + int i; + char *dir = NULL; + + if(tempdir != NULL) return; /* We've already been called */ + for(i = 0; dirs[i]; i++){ + dir = getenv(dirs[i]); + if((dir != NULL) && (*dir != '\0')) + break; + } + if((dir == NULL) || (*dir == '\0')) + dir = "/tmp"; + + tempdir = malloc(strlen(dir) + 2); + if(tempdir == NULL){ + fprintf(stderr, "Failed to malloc tempdir, " + "errno = %d\n", errno); + return; + } + strcpy(tempdir, dir); + strcat(tempdir, "/"); +} + +/* + * This proc still used in tt-mode + * (file: kernel/tt/ptproxy/proxy.c, proc: start_debugger). + * So it isn't 'static' yet. + */ +int make_tempfile(const char *template, char **out_tempname, int do_unlink) +{ + char tempname[MAXPATHLEN]; + int fd; + + find_tempdir(); + if (*template != '/') + strcpy(tempname, tempdir); + else + *tempname = 0; + strcat(tempname, template); + fd = mkstemp(tempname); + if(fd < 0){ + fprintf(stderr, "open - cannot create %s: %s\n", tempname, + strerror(errno)); + return -1; + } + if(do_unlink && (unlink(tempname) < 0)){ + perror("unlink"); + return -1; + } + if(out_tempname){ + *out_tempname = strdup(tempname); + if(*out_tempname == NULL){ + perror("strdup"); + return -1; + } + } + return(fd); +} + +#define TEMPNAME_TEMPLATE "vm_file-XXXXXX" + +/* + * This proc is used in start_up.c + * So it isn't 'static'. + */ +int create_tmp_file(unsigned long len) +{ + int fd, err; + char zero; + + fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1); + if(fd < 0) { + exit(1); + } + + err = fchmod(fd, 0777); + if(err < 0){ + perror("os_mode_fd"); + exit(1); + } + + if (lseek64(fd, len, SEEK_SET) < 0) { + perror("os_seek_file"); + exit(1); + } + + zero = 0; + + err = os_write_file(fd, &zero, 1); + if(err != 1){ + errno = -err; + perror("os_write_file"); + exit(1); + } + + return(fd); +} + +static int create_anon_file(unsigned long len) +{ + void *addr; + int fd; + + fd = open("/dev/anon", O_RDWR); + if(fd < 0) { + perror("opening /dev/anon"); + exit(1); + } + + addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + if(addr == MAP_FAILED){ + perror("mapping physmem file"); + exit(1); + } + munmap(addr, len); + + return(fd); +} + +extern int have_devanon; + +int create_mem_file(unsigned long len) +{ + int err, fd; + + if(have_devanon) + fd = create_anon_file(len); + else fd = create_tmp_file(len); + + err = os_set_exec_close(fd, 1); + if(err < 0){ + errno = -err; + perror("exec_close"); + } + return(fd); +} diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 040cc1472bc7..6af83171ca4e 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -4,18 +4,22 @@ */ #include <stdio.h> +#include <stddef.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> #include <unistd.h> #include <signal.h> #include <sched.h> +#include <fcntl.h> #include <errno.h> -#include <stdarg.h> -#include <stdlib.h> #include <setjmp.h> #include <sys/time.h> #include <sys/wait.h> #include <sys/mman.h> #include <asm/unistd.h> #include <asm/page.h> +#include <sys/types.h> #include "user_util.h" #include "kern_util.h" #include "user.h" @@ -25,6 +29,7 @@ #include "sysdep/sigcontext.h" #include "irq_user.h" #include "ptrace_user.h" +#include "mem_user.h" #include "time_user.h" #include "init.h" #include "os.h" @@ -32,6 +37,8 @@ #include "choose-mode.h" #include "mode.h" #include "tempfile.h" +#include "kern_constants.h" + #ifdef UML_CONFIG_MODE_SKAS #include "skas.h" #include "skas_ptrace.h" @@ -276,9 +283,38 @@ static void __init check_ptrace(void) check_sysemu(); } +extern int create_tmp_file(unsigned long len); + +static void check_tmpexec(void) +{ + void *addr; + int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE); + + addr = mmap(NULL, UM_KERN_PAGE_SIZE, + PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0); + printf("Checking PROT_EXEC mmap in /tmp..."); + fflush(stdout); + if(addr == MAP_FAILED){ + err = errno; + perror("failed"); + if(err == EPERM) + printf("/tmp must be not mounted noexec\n"); + exit(1); + } + printf("OK\n"); + munmap(addr, UM_KERN_PAGE_SIZE); + + close(fd); +} + void os_early_checks(void) { check_ptrace(); + + /* Need to check this early because mmapping happens before the + * kernel is running. + */ + check_tmpexec(); } static int __init noprocmm_cmd_param(char *str, int* add) @@ -357,3 +393,72 @@ int can_do_skas(void) return(0); } #endif + +int have_devanon = 0; + +void check_devanon(void) +{ + int fd; + + printk("Checking for /dev/anon on the host..."); + fd = open("/dev/anon", O_RDWR); + if(fd < 0){ + printk("Not available (open failed with errno %d)\n", errno); + return; + } + + printk("OK\n"); + have_devanon = 1; +} + +int __init parse_iomem(char *str, int *add) +{ + struct iomem_region *new; + struct uml_stat buf; + char *file, *driver; + int fd, err, size; + + driver = str; + file = strchr(str,','); + if(file == NULL){ + printf("parse_iomem : failed to parse iomem\n"); + goto out; + } + *file = '\0'; + file++; + fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0); + if(fd < 0){ + os_print_error(fd, "parse_iomem - Couldn't open io file"); + goto out; + } + + err = os_stat_fd(fd, &buf); + if(err < 0){ + os_print_error(err, "parse_iomem - cannot stat_fd file"); + goto out_close; + } + + new = malloc(sizeof(*new)); + if(new == NULL){ + perror("Couldn't allocate iomem_region struct"); + goto out_close; + } + + size = (buf.ust_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1); + + *new = ((struct iomem_region) { .next = iomem_regions, + .driver = driver, + .fd = fd, + .size = size, + .phys = 0, + .virt = 0 }); + iomem_regions = new; + iomem_size += new->size + UM_KERN_PAGE_SIZE; + + return(0); + out_close: + os_close_file(fd); + out: + return(1); +} + diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c index 5b047ab8416a..a6db8877931a 100644 --- a/arch/um/os-Linux/tt.c +++ b/arch/um/os-Linux/tt.c @@ -36,6 +36,20 @@ #include "mode.h" #include "tempfile.h" +int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, + int must_succeed) +{ + int err; + + err = os_protect_memory((void *) addr, len, r, w, x); + if(err < 0){ + if(must_succeed) + panic("protect failed, err = %d", -err); + else return(err); + } + return(0); +} + /* *------------------------- * only for tt mode (will be deleted in future...) diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c index 4e34b0f9d613..ab3f87aaff70 100644 --- a/arch/x86_64/kernel/e820.c +++ b/arch/x86_64/kernel/e820.c @@ -17,6 +17,8 @@ #include <linux/ioport.h> #include <linux/string.h> #include <linux/kexec.h> +#include <linux/module.h> + #include <asm/page.h> #include <asm/e820.h> #include <asm/proto.h> diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 351d8d64c2fb..238f73e1a834 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -831,11 +831,26 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c) #endif } +#define HWCR 0xc0010015 + static int __init init_amd(struct cpuinfo_x86 *c) { int r; int level; +#ifdef CONFIG_SMP + unsigned long value; + + // Disable TLB flush filter by setting HWCR.FFDIS: + // bit 6 of msr C001_0015 + // + // Errata 63 for SH-B3 steppings + // Errata 122 for all(?) steppings + rdmsrl(HWCR, value); + value |= 1 << 6; + wrmsrl(HWCR, value); +#endif + /* Bit 31 in normal CPUID used for nonstandard 3DNow ID; 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */ clear_bit(0*32+31, &c->x86_capability); diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c index 711d2f314ac3..94af920465b5 100644 --- a/drivers/block/paride/pf.c +++ b/drivers/block/paride/pf.c @@ -750,6 +750,14 @@ static int pf_ready(void) static struct request_queue *pf_queue; +static void pf_end_request(int uptodate) +{ + if (pf_req) { + end_request(pf_req, uptodate); + pf_req = NULL; + } +} + static void do_pf_request(request_queue_t * q) { if (pf_busy) @@ -765,7 +773,7 @@ repeat: pf_count = pf_req->current_nr_sectors; if (pf_block + pf_count > get_capacity(pf_req->rq_disk)) { - end_request(pf_req, 0); + pf_end_request(0); goto repeat; } @@ -780,7 +788,7 @@ repeat: pi_do_claimed(pf_current->pi, do_pf_write); else { pf_busy = 0; - end_request(pf_req, 0); + pf_end_request(0); goto repeat; } } @@ -798,9 +806,11 @@ static int pf_next_buf(void) if (!pf_count) return 1; spin_lock_irqsave(&pf_spin_lock, saved_flags); - end_request(pf_req, 1); - pf_count = pf_req->current_nr_sectors; - pf_buf = pf_req->buffer; + pf_end_request(1); + if (pf_req) { + pf_count = pf_req->current_nr_sectors; + pf_buf = pf_req->buffer; + } spin_unlock_irqrestore(&pf_spin_lock, saved_flags); return 1; } @@ -810,7 +820,7 @@ static inline void next_request(int success) unsigned long saved_flags; spin_lock_irqsave(&pf_spin_lock, saved_flags); - end_request(pf_req, success); + pf_end_request(success); pf_busy = 0; do_pf_request(pf_queue); spin_unlock_irqrestore(&pf_spin_lock, saved_flags); diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c index 856c2278e9d0..079ec344eb47 100644 --- a/drivers/block/scsi_ioctl.c +++ b/drivers/block/scsi_ioctl.c @@ -168,6 +168,7 @@ static int verify_command(struct file *file, unsigned char *cmd) safe_for_write(WRITE_VERIFY_12), safe_for_write(WRITE_16), safe_for_write(WRITE_LONG), + safe_for_write(WRITE_LONG_2), safe_for_write(ERASE), safe_for_write(GPCMD_MODE_SELECT_10), safe_for_write(MODE_SELECT), diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c index 99762b6c19ae..de5d6d212674 100644 --- a/drivers/char/agp/hp-agp.c +++ b/drivers/char/agp/hp-agp.c @@ -252,7 +252,7 @@ hp_zx1_configure (void) readl(hp->ioc_regs+HP_ZX1_PDIR_BASE); writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG); readl(hp->ioc_regs+HP_ZX1_TCNFG); - writel(~(HP_ZX1_IOVA_SIZE-1), hp->ioc_regs+HP_ZX1_IMASK); + writel((unsigned int)(~(HP_ZX1_IOVA_SIZE-1)), hp->ioc_regs+HP_ZX1_IMASK); readl(hp->ioc_regs+HP_ZX1_IMASK); writel(hp->iova_base|1, hp->ioc_regs+HP_ZX1_IBASE); readl(hp->ioc_regs+HP_ZX1_IBASE); diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 58d3738a2b7f..407708a001e4 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c @@ -534,7 +534,7 @@ static void shutdown(struct channel *ch) unsigned long flags; struct tty_struct *tty; - struct board_chan *bc; + struct board_chan __iomem *bc; if (!(ch->asyncflags & ASYNC_INITIALIZED)) return; @@ -618,7 +618,7 @@ static int pc_write(struct tty_struct * tty, struct channel *ch; unsigned long flags; int remain; - struct board_chan *bc; + struct board_chan __iomem *bc; /* ---------------------------------------------------------------- pc_write is primarily called directly by the kernel routine @@ -685,7 +685,7 @@ static int pc_write(struct tty_struct * tty, ------------------------------------------------------------------- */ dataLen = min(bytesAvailable, dataLen); - memcpy(ch->txptr + head, buf, dataLen); + memcpy_toio(ch->txptr + head, buf, dataLen); buf += dataLen; head += dataLen; amountCopied += dataLen; @@ -726,7 +726,7 @@ static int pc_write_room(struct tty_struct *tty) struct channel *ch; unsigned long flags; unsigned int head, tail; - struct board_chan *bc; + struct board_chan __iomem *bc; remain = 0; @@ -773,7 +773,7 @@ static int pc_chars_in_buffer(struct tty_struct *tty) int remain; unsigned long flags; struct channel *ch; - struct board_chan *bc; + struct board_chan __iomem *bc; /* --------------------------------------------------------- verifyChannel returns the channel from the tty struct @@ -830,7 +830,7 @@ static void pc_flush_buffer(struct tty_struct *tty) unsigned int tail; unsigned long flags; struct channel *ch; - struct board_chan *bc; + struct board_chan __iomem *bc; /* --------------------------------------------------------- verifyChannel returns the channel from the tty struct if it is valid. This serves as a sanity check. @@ -976,7 +976,7 @@ static int pc_open(struct tty_struct *tty, struct file * filp) struct channel *ch; unsigned long flags; int line, retval, boardnum; - struct board_chan *bc; + struct board_chan __iomem *bc; unsigned int head; line = tty->index; @@ -1041,7 +1041,7 @@ static int pc_open(struct tty_struct *tty, struct file * filp) ch->statusflags = 0; /* Save boards current modem status */ - ch->imodem = bc->mstat; + ch->imodem = readb(&bc->mstat); /* ---------------------------------------------------------------- Set receive head and tail ptrs to each other. This indicates @@ -1399,10 +1399,10 @@ static void post_fep_init(unsigned int crd) { /* Begin post_fep_init */ int i; - unsigned char *memaddr; - struct global_data *gd; + void __iomem *memaddr; + struct global_data __iomem *gd; struct board_info *bd; - struct board_chan *bc; + struct board_chan __iomem *bc; struct channel *ch; int shrinkmem = 0, lowwater ; @@ -1461,7 +1461,7 @@ static void post_fep_init(unsigned int crd) 8 and 64 of these structures. -------------------------------------------------------------------- */ - bc = (struct board_chan *)(memaddr + CHANSTRUCT); + bc = memaddr + CHANSTRUCT; /* ------------------------------------------------------------------- The below assignment will set gd to point at the BEGINING of @@ -1470,7 +1470,7 @@ static void post_fep_init(unsigned int crd) pointer begins at 0xd10. ---------------------------------------------------------------------- */ - gd = (struct global_data *)(memaddr + GLOBAL); + gd = memaddr + GLOBAL; /* -------------------------------------------------------------------- XEPORTS (address 0xc22) points at the number of channels the @@ -1493,6 +1493,7 @@ static void post_fep_init(unsigned int crd) for (i = 0; i < bd->numports; i++, ch++, bc++) { /* Begin for each port */ unsigned long flags; + u16 tseg, rseg; ch->brdchan = bc; ch->mailbox = gd; @@ -1553,50 +1554,53 @@ static void post_fep_init(unsigned int crd) shrinkmem = 0; } + tseg = readw(&bc->tseg); + rseg = readw(&bc->rseg); + switch (bd->type) { case PCIXEM: case PCIXRJ: case PCIXR: /* Cover all the 2MEG cards */ - ch->txptr = memaddr + (((bc->tseg) << 4) & 0x1fffff); - ch->rxptr = memaddr + (((bc->rseg) << 4) & 0x1fffff); - ch->txwin = FEPWIN | ((bc->tseg) >> 11); - ch->rxwin = FEPWIN | ((bc->rseg) >> 11); + ch->txptr = memaddr + ((tseg << 4) & 0x1fffff); + ch->rxptr = memaddr + ((rseg << 4) & 0x1fffff); + ch->txwin = FEPWIN | (tseg >> 11); + ch->rxwin = FEPWIN | (rseg >> 11); break; case PCXEM: case EISAXEM: /* Cover all the 32K windowed cards */ /* Mask equal to window size - 1 */ - ch->txptr = memaddr + (((bc->tseg) << 4) & 0x7fff); - ch->rxptr = memaddr + (((bc->rseg) << 4) & 0x7fff); - ch->txwin = FEPWIN | ((bc->tseg) >> 11); - ch->rxwin = FEPWIN | ((bc->rseg) >> 11); + ch->txptr = memaddr + ((tseg << 4) & 0x7fff); + ch->rxptr = memaddr + ((rseg << 4) & 0x7fff); + ch->txwin = FEPWIN | (tseg >> 11); + ch->rxwin = FEPWIN | (rseg >> 11); break; case PCXEVE: case PCXE: - ch->txptr = memaddr + (((bc->tseg - bd->memory_seg) << 4) & 0x1fff); - ch->txwin = FEPWIN | ((bc->tseg - bd->memory_seg) >> 9); - ch->rxptr = memaddr + (((bc->rseg - bd->memory_seg) << 4) & 0x1fff); - ch->rxwin = FEPWIN | ((bc->rseg - bd->memory_seg) >>9 ); + ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4) & 0x1fff); + ch->txwin = FEPWIN | ((tseg - bd->memory_seg) >> 9); + ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4) & 0x1fff); + ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >>9 ); break; case PCXI: case PC64XE: - ch->txptr = memaddr + ((bc->tseg - bd->memory_seg) << 4); - ch->rxptr = memaddr + ((bc->rseg - bd->memory_seg) << 4); + ch->txptr = memaddr + ((tseg - bd->memory_seg) << 4); + ch->rxptr = memaddr + ((rseg - bd->memory_seg) << 4); ch->txwin = ch->rxwin = 0; break; } /* End switch bd->type */ ch->txbufhead = 0; - ch->txbufsize = bc->tmax + 1; + ch->txbufsize = readw(&bc->tmax) + 1; ch->rxbufhead = 0; - ch->rxbufsize = bc->rmax + 1; + ch->rxbufsize = readw(&bc->rmax) + 1; lowwater = ch->txbufsize >= 2000 ? 1024 : (ch->txbufsize / 2); @@ -1718,11 +1722,11 @@ static void epcapoll(unsigned long ignored) static void doevent(int crd) { /* Begin doevent */ - void *eventbuf; + void __iomem *eventbuf; struct channel *ch, *chan0; static struct tty_struct *tty; struct board_info *bd; - struct board_chan *bc; + struct board_chan __iomem *bc; unsigned int tail, head; int event, channel; int mstat, lstat; @@ -1817,7 +1821,7 @@ static void doevent(int crd) static void fepcmd(struct channel *ch, int cmd, int word_or_byte, int byte2, int ncmds, int bytecmd) { /* Begin fepcmd */ - unchar *memaddr; + unchar __iomem *memaddr; unsigned int head, cmdTail, cmdStart, cmdMax; long count; int n; @@ -2000,7 +2004,7 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch) unsigned int cmdHead; struct termios *ts; - struct board_chan *bc; + struct board_chan __iomem *bc; unsigned mval, hflow, cflag, iflag; bc = ch->brdchan; @@ -2010,7 +2014,7 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch) ts = tty->termios; if ((ts->c_cflag & CBAUD) == 0) { /* Begin CBAUD detected */ cmdHead = readw(&bc->rin); - bc->rout = cmdHead; + writew(cmdHead, &bc->rout); cmdHead = readw(&bc->tin); /* Changing baud in mid-stream transmission can be wonderful */ /* --------------------------------------------------------------- @@ -2116,7 +2120,7 @@ static void receive_data(struct channel *ch) unchar *rptr; struct termios *ts = NULL; struct tty_struct *tty; - struct board_chan *bc; + struct board_chan __iomem *bc; int dataToRead, wrapgap, bytesAvailable; unsigned int tail, head; unsigned int wrapmask; @@ -2154,7 +2158,7 @@ static void receive_data(struct channel *ch) --------------------------------------------------------------------- */ if (!tty || !ts || !(ts->c_cflag & CREAD)) { - bc->rout = head; + writew(head, &bc->rout); return; } @@ -2270,7 +2274,7 @@ static int info_ioctl(struct tty_struct *tty, struct file * file, static int pc_tiocmget(struct tty_struct *tty, struct file *file) { struct channel *ch = (struct channel *) tty->driver_data; - struct board_chan *bc; + struct board_chan __iomem *bc; unsigned int mstat, mflag = 0; unsigned long flags; @@ -2351,7 +2355,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, unsigned long flags; unsigned int mflag, mstat; unsigned char startc, stopc; - struct board_chan *bc; + struct board_chan __iomem *bc; struct channel *ch = (struct channel *) tty->driver_data; void __user *argp = (void __user *)arg; @@ -2633,7 +2637,7 @@ static void pc_start(struct tty_struct *tty) spin_lock_irqsave(&epca_lock, flags); /* Just in case output was resumed because of a change in Digi-flow */ if (ch->statusflags & TXSTOPPED) { /* Begin transmit resume requested */ - struct board_chan *bc; + struct board_chan __iomem *bc; globalwinon(ch); bc = ch->brdchan; if (ch->statusflags & LOWWAIT) @@ -2727,7 +2731,7 @@ void digi_send_break(struct channel *ch, int msec) static void setup_empty_event(struct tty_struct *tty, struct channel *ch) { /* Begin setup_empty_event */ - struct board_chan *bc = ch->brdchan; + struct board_chan __iomem *bc = ch->brdchan; globalwinon(ch); ch->statusflags |= EMPTYWAIT; diff --git a/drivers/char/epca.h b/drivers/char/epca.h index 20eeb5a70e1a..456d6c8f94a8 100644 --- a/drivers/char/epca.h +++ b/drivers/char/epca.h @@ -128,17 +128,17 @@ struct channel unsigned long c_cflag; unsigned long c_lflag; unsigned long c_oflag; - unsigned char *txptr; - unsigned char *rxptr; + unsigned char __iomem *txptr; + unsigned char __iomem *rxptr; unsigned char *tmp_buf; struct board_info *board; - struct board_chan *brdchan; + struct board_chan __iomem *brdchan; struct digi_struct digiext; struct tty_struct *tty; wait_queue_head_t open_wait; wait_queue_head_t close_wait; struct work_struct tqueue; - struct global_data *mailbox; + struct global_data __iomem *mailbox; }; struct board_info @@ -149,8 +149,8 @@ struct board_info unsigned short numports; unsigned long port; unsigned long membase; - unsigned char __iomem *re_map_port; - unsigned char *re_map_membase; + void __iomem *re_map_port; + void __iomem *re_map_membase; unsigned long memory_seg; void ( * memwinon ) (struct board_info *, unsigned int) ; void ( * memwinoff ) (struct board_info *, unsigned int) ; diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index 3b865f34a095..b66782398258 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c @@ -50,7 +50,7 @@ MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>"); MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); MODULE_LICENSE("GPL"); -MODULE_VERSION("1.0"); +MODULE_VERSION("2.0"); #define BIOS_SCAN_LIMIT 0xffffffff #define MAX_IMAGE_LENGTH 16 @@ -65,10 +65,11 @@ static struct _rbu_data { unsigned long packet_write_count; unsigned long num_packets; unsigned long packetsize; + int entry_created; } rbu_data; -static char image_type[MAX_IMAGE_LENGTH] = "mono"; -module_param_string(image_type, image_type, sizeof(image_type), 0); +static char image_type[MAX_IMAGE_LENGTH + 1] = "mono"; +module_param_string(image_type, image_type, sizeof (image_type), 0); MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet"); struct packet_data { @@ -114,7 +115,7 @@ static int fill_last_packet(void *data, size_t length) if ((rbu_data.packet_write_count + length) > rbu_data.packetsize) { pr_debug("dell_rbu:%s: packet size data " - "overrun\n", __FUNCTION__); + "overrun\n", __FUNCTION__); return -EINVAL; } @@ -146,12 +147,14 @@ static int create_packet(size_t length) pr_debug("create_packet: packetsize not specified\n"); return -EINVAL; } + spin_unlock(&rbu_data.lock); + newpacket = kmalloc(sizeof (struct packet_data), GFP_KERNEL); + spin_lock(&rbu_data.lock); - newpacket = kmalloc(sizeof(struct packet_data), GFP_KERNEL); if (!newpacket) { printk(KERN_WARNING - "dell_rbu:%s: failed to allocate new " - "packet\n", __FUNCTION__); + "dell_rbu:%s: failed to allocate new " + "packet\n", __FUNCTION__); return -ENOMEM; } @@ -160,15 +163,17 @@ static int create_packet(size_t length) * there is no upper limit on memory * address for packetized mechanism */ - newpacket->data = (unsigned char *)__get_free_pages(GFP_KERNEL, - ordernum); + spin_unlock(&rbu_data.lock); + newpacket->data = (unsigned char *) __get_free_pages(GFP_KERNEL, + ordernum); + spin_lock(&rbu_data.lock); pr_debug("create_packet: newpacket %p\n", newpacket->data); if (!newpacket->data) { printk(KERN_WARNING - "dell_rbu:%s: failed to allocate new " - "packet\n", __FUNCTION__); + "dell_rbu:%s: failed to allocate new " + "packet\n", __FUNCTION__); kfree(newpacket); return -ENOMEM; } @@ -204,9 +209,8 @@ static int packetize_data(void *data, size_t length) return rc; } -static int -do_packet_read(char *data, struct list_head *ptemp_list, - int length, int bytes_read, int *list_read_count) +static int do_packet_read(char *data, struct list_head *ptemp_list, + int length, int bytes_read, int *list_read_count) { void *ptemp_buf; struct packet_data *newpacket = NULL; @@ -239,7 +243,7 @@ do_packet_read(char *data, struct list_head *ptemp_list, return bytes_copied; } -static int packet_read_list(char *data, size_t * pread_length) +static int packet_read_list(char *data, size_t *pread_length) { struct list_head *ptemp_list; int temp_count = 0; @@ -258,8 +262,7 @@ static int packet_read_list(char *data, size_t * pread_length) ptemp_list = (&packet_data_head.list)->next; while (!list_empty(ptemp_list)) { bytes_copied = do_packet_read(pdest, ptemp_list, - remaining_bytes, bytes_read, - &temp_count); + remaining_bytes, bytes_read, &temp_count); remaining_bytes -= bytes_copied; bytes_read += bytes_copied; pdest += bytes_copied; @@ -287,7 +290,7 @@ static void packet_empty_list(void) ptemp_list = (&packet_data_head.list)->next; while (!list_empty(ptemp_list)) { newpacket = - list_entry(ptemp_list, struct packet_data, list); + list_entry(ptemp_list, struct packet_data, list); pnext_list = ptemp_list->next; list_del(ptemp_list); ptemp_list = pnext_list; @@ -296,8 +299,8 @@ static void packet_empty_list(void) * to make sure there are no stale RBU packets left in memory */ memset(newpacket->data, 0, rbu_data.packetsize); - free_pages((unsigned long)newpacket->data, - newpacket->ordernum); + free_pages((unsigned long) newpacket->data, + newpacket->ordernum); kfree(newpacket); } rbu_data.packet_write_count = 0; @@ -319,14 +322,13 @@ static void img_update_free(void) * BIOS image copied in memory. */ memset(rbu_data.image_update_buffer, 0, - rbu_data.image_update_buffer_size); + rbu_data.image_update_buffer_size); if (rbu_data.dma_alloc == 1) dma_free_coherent(NULL, rbu_data.bios_image_size, - rbu_data.image_update_buffer, - dell_rbu_dmaaddr); + rbu_data.image_update_buffer, dell_rbu_dmaaddr); else - free_pages((unsigned long)rbu_data.image_update_buffer, - rbu_data.image_update_ordernum); + free_pages((unsigned long) rbu_data.image_update_buffer, + rbu_data.image_update_ordernum); /* * Re-initialize the rbu_data variables after a free @@ -366,7 +368,7 @@ static int img_update_realloc(unsigned long size) */ if ((size != 0) && (rbu_data.image_update_buffer == NULL)) { printk(KERN_ERR "dell_rbu:%s: corruption " - "check failed\n", __FUNCTION__); + "check failed\n", __FUNCTION__); return -EINVAL; } /* @@ -385,17 +387,16 @@ static int img_update_realloc(unsigned long size) ordernum = get_order(size); image_update_buffer = - (unsigned char *)__get_free_pages(GFP_KERNEL, ordernum); + (unsigned char *) __get_free_pages(GFP_KERNEL, ordernum); img_buf_phys_addr = - (unsigned long)virt_to_phys(image_update_buffer); + (unsigned long) virt_to_phys(image_update_buffer); if (img_buf_phys_addr > BIOS_SCAN_LIMIT) { - free_pages((unsigned long)image_update_buffer, ordernum); + free_pages((unsigned long) image_update_buffer, ordernum); ordernum = -1; image_update_buffer = dma_alloc_coherent(NULL, size, - &dell_rbu_dmaaddr, - GFP_KERNEL); + &dell_rbu_dmaaddr, GFP_KERNEL); dma_alloc = 1; } @@ -405,13 +406,13 @@ static int img_update_realloc(unsigned long size) rbu_data.image_update_buffer = image_update_buffer; rbu_data.image_update_buffer_size = size; rbu_data.bios_image_size = - rbu_data.image_update_buffer_size; + rbu_data.image_update_buffer_size; rbu_data.image_update_ordernum = ordernum; rbu_data.dma_alloc = dma_alloc; rc = 0; } else { pr_debug("Not enough memory for image update:" - "size = %ld\n", size); + "size = %ld\n", size); rc = -ENOMEM; } @@ -438,7 +439,7 @@ static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count) if (pos > imagesize) { retval = 0; printk(KERN_WARNING "dell_rbu:read_packet_data: " - "data underrun\n"); + "data underrun\n"); goto read_rbu_data_exit; } @@ -468,11 +469,11 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) /* check to see if we have something to return */ if ((rbu_data.image_update_buffer == NULL) || - (rbu_data.bios_image_size == 0)) { + (rbu_data.bios_image_size == 0)) { pr_debug("read_rbu_data_mono: image_update_buffer %p ," - "bios_image_size %lu\n", - rbu_data.image_update_buffer, - rbu_data.bios_image_size); + "bios_image_size %lu\n", + rbu_data.image_update_buffer, + rbu_data.bios_image_size); ret_count = -ENOMEM; goto read_rbu_data_exit; } @@ -497,8 +498,8 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) return ret_count; } -static ssize_t -read_rbu_data(struct kobject *kobj, char *buffer, loff_t pos, size_t count) +static ssize_t read_rbu_data(struct kobject *kobj, char *buffer, + loff_t pos, size_t count) { ssize_t ret_count = 0; @@ -515,62 +516,20 @@ read_rbu_data(struct kobject *kobj, char *buffer, loff_t pos, size_t count) return ret_count; } -static ssize_t -read_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos, - size_t count) -{ - int size = 0; - if (!pos) - size = sprintf(buffer, "%s\n", image_type); - return size; -} - -static ssize_t -write_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos, - size_t count) -{ - int rc = count; - spin_lock(&rbu_data.lock); - - if (strlen(buffer) < MAX_IMAGE_LENGTH) - sscanf(buffer, "%s", image_type); - else - printk(KERN_WARNING "dell_rbu: image_type is invalid" - "max chars = %d, \n incoming str--%s-- \n", - MAX_IMAGE_LENGTH, buffer); - - /* we must free all previous allocations */ - packet_empty_list(); - img_update_free(); - - spin_unlock(&rbu_data.lock); - return rc; - -} - -static struct bin_attribute rbu_data_attr = { - .attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444}, - .read = read_rbu_data, -}; - -static struct bin_attribute rbu_image_type_attr = { - .attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644}, - .read = read_rbu_image_type, - .write = write_rbu_image_type, -}; - static void callbackfn_rbu(const struct firmware *fw, void *context) { int rc = 0; - if (!fw || !fw->size) + if (!fw || !fw->size) { + rbu_data.entry_created = 0; return; + } spin_lock(&rbu_data.lock); if (!strcmp(image_type, "mono")) { if (!img_update_realloc(fw->size)) memcpy(rbu_data.image_update_buffer, - fw->data, fw->size); + fw->data, fw->size); } else if (!strcmp(image_type, "packet")) { if (!rbu_data.packetsize) rbu_data.packetsize = fw->size; @@ -584,14 +543,103 @@ static void callbackfn_rbu(const struct firmware *fw, void *context) spin_unlock(&rbu_data.lock); rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, - "dell_rbu", &rbu_device->dev, - &context, callbackfn_rbu); + "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu); if (rc) printk(KERN_ERR - "dell_rbu:%s request_firmware_nowait failed" - " %d\n", __FUNCTION__, rc); + "dell_rbu:%s request_firmware_nowait failed" + " %d\n", __FUNCTION__, rc); + else + rbu_data.entry_created = 1; +} + +static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer, + loff_t pos, size_t count) +{ + int size = 0; + if (!pos) + size = sprintf(buffer, "%s\n", image_type); + return size; +} + +static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer, + loff_t pos, size_t count) +{ + int rc = count; + int req_firm_rc = 0; + int i; + spin_lock(&rbu_data.lock); + /* + * Find the first newline or space + */ + for (i = 0; i < count; ++i) + if (buffer[i] == '\n' || buffer[i] == ' ') { + buffer[i] = '\0'; + break; + } + if (i == count) + buffer[count] = '\0'; + + if (strstr(buffer, "mono")) + strcpy(image_type, "mono"); + else if (strstr(buffer, "packet")) + strcpy(image_type, "packet"); + else if (strstr(buffer, "init")) { + /* + * If due to the user error the driver gets in a bad + * state where even though it is loaded , the + * /sys/class/firmware/dell_rbu entries are missing. + * to cover this situation the user can recreate entries + * by writing init to image_type. + */ + if (!rbu_data.entry_created) { + spin_unlock(&rbu_data.lock); + req_firm_rc = request_firmware_nowait(THIS_MODULE, + FW_ACTION_NOHOTPLUG, "dell_rbu", + &rbu_device->dev, &context, + callbackfn_rbu); + if (req_firm_rc) { + printk(KERN_ERR + "dell_rbu:%s request_firmware_nowait" + " failed %d\n", __FUNCTION__, rc); + rc = -EIO; + } else + rbu_data.entry_created = 1; + + spin_lock(&rbu_data.lock); + } + } else { + printk(KERN_WARNING "dell_rbu: image_type is invalid\n"); + spin_unlock(&rbu_data.lock); + return -EINVAL; + } + + /* we must free all previous allocations */ + packet_empty_list(); + img_update_free(); + spin_unlock(&rbu_data.lock); + + return rc; } +static struct bin_attribute rbu_data_attr = { + .attr = { + .name = "data", + .owner = THIS_MODULE, + .mode = 0444, + }, + .read = read_rbu_data, +}; + +static struct bin_attribute rbu_image_type_attr = { + .attr = { + .name = "image_type", + .owner = THIS_MODULE, + .mode = 0644, + }, + .read = read_rbu_image_type, + .write = write_rbu_image_type, +}; + static int __init dcdrbu_init(void) { int rc = 0; @@ -599,11 +647,11 @@ static int __init dcdrbu_init(void) init_packet_head(); rbu_device = - platform_device_register_simple("dell_rbu", -1, NULL, 0); + platform_device_register_simple("dell_rbu", -1, NULL, 0); if (!rbu_device) { printk(KERN_ERR - "dell_rbu:%s:platform_device_register_simple " - "failed\n", __FUNCTION__); + "dell_rbu:%s:platform_device_register_simple " + "failed\n", __FUNCTION__); return -EIO; } @@ -611,11 +659,12 @@ static int __init dcdrbu_init(void) sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr); rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, - "dell_rbu", &rbu_device->dev, - &context, callbackfn_rbu); + "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu); if (rc) printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait" - " failed %d\n", __FUNCTION__, rc); + " failed %d\n", __FUNCTION__, rc); + else + rbu_data.entry_created = 1; return rc; diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c index eaebfc14c933..4c56411f3993 100644 --- a/drivers/hwmon/hdaps.c +++ b/drivers/hwmon/hdaps.c @@ -5,10 +5,10 @@ * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com> * * The HardDisk Active Protection System (hdaps) is present in the IBM ThinkPad - * T41, T42, T43, R51, and X40, at least. It provides a basic two-axis - * accelerometer and other data, such as the device's temperature. + * T41, T42, T43, R50, R50p, R51, and X40, at least. It provides a basic + * two-axis accelerometer and other data, such as the device's temperature. * - * Based on the document by Mark A. Smith available at + * This driver is based on the document by Mark A. Smith available at * http://www.almaden.ibm.com/cs/people/marksmith/tpaps.html and a lot of trial * and error. * @@ -36,12 +36,7 @@ #include <asm/io.h> #define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */ -#define HDAPS_NR_PORTS 0x30 /* 0x1600 - 0x162f */ - -#define STATE_FRESH 0x50 /* accelerometer data is fresh */ - -#define REFRESH_ASYNC 0x00 /* do asynchronous refresh */ -#define REFRESH_SYNC 0x01 /* do synchronous refresh */ +#define HDAPS_NR_PORTS 0x30 /* number of ports: 0x1600 - 0x162f */ #define HDAPS_PORT_STATE 0x1611 /* device state */ #define HDAPS_PORT_YPOS 0x1612 /* y-axis position */ @@ -53,7 +48,7 @@ #define HDAPS_PORT_UNKNOWN 0x161c /* what is this? */ #define HDAPS_PORT_KMACT 0x161d /* keyboard or mouse activity */ -#define HDAPS_READ_MASK 0xff /* some reads have the low 8 bits set */ +#define STATE_FRESH 0x50 /* accelerometer data is fresh */ #define KEYBD_MASK 0x20 /* set if keyboard activity */ #define MOUSE_MASK 0x40 /* set if mouse activity */ @@ -63,12 +58,11 @@ #define INIT_TIMEOUT_MSECS 4000 /* wait up to 4s for device init ... */ #define INIT_WAIT_MSECS 200 /* ... in 200ms increments */ -static struct platform_device *pdev; -static struct input_dev hdaps_idev; +#define HDAPS_POLL_PERIOD (HZ/20) /* poll for input every 1/20s */ +#define HDAPS_INPUT_FUZZ 4 /* input event threshold */ + static struct timer_list hdaps_timer; -static unsigned int hdaps_mousedev_threshold = 4; -static unsigned long hdaps_poll_ms = 50; -static unsigned int hdaps_mousedev; +static struct platform_device *pdev; static unsigned int hdaps_invert; static u8 km_activity; static int rest_x; @@ -81,14 +75,14 @@ static DECLARE_MUTEX(hdaps_sem); */ static inline u8 __get_latch(u16 port) { - return inb(port) & HDAPS_READ_MASK; + return inb(port) & 0xff; } /* - * __check_latch - Check a port latch for a given value. Callers must hold - * hdaps_sem. Returns zero if the port contains the given value. + * __check_latch - Check a port latch for a given value. Returns zero if the + * port contains the given value. Callers must hold hdaps_sem. */ -static inline unsigned int __check_latch(u16 port, u8 val) +static inline int __check_latch(u16 port, u8 val) { if (__get_latch(port) == val) return 0; @@ -99,7 +93,7 @@ static inline unsigned int __check_latch(u16 port, u8 val) * __wait_latch - Wait up to 100us for a port latch to get a certain value, * returning zero if the value is obtained. Callers must hold hdaps_sem. */ -static unsigned int __wait_latch(u16 port, u8 val) +static int __wait_latch(u16 port, u8 val) { unsigned int i; @@ -109,59 +103,42 @@ static unsigned int __wait_latch(u16 port, u8 val) udelay(5); } - return -EINVAL; + return -EIO; } /* - * __device_refresh - Request a refresh from the accelerometer. - * - * If sync is REFRESH_SYNC, we perform a synchronous refresh and will wait. - * Returns zero if successful and nonzero on error. - * - * If sync is REFRESH_ASYNC, we merely kick off a new refresh if the device is - * not up-to-date. Always returns zero. - * - * Callers must hold hdaps_sem. + * __device_refresh - request a refresh from the accelerometer. Does not wait + * for refresh to complete. Callers must hold hdaps_sem. */ -static int __device_refresh(unsigned int sync) +static void __device_refresh(void) { - u8 state; - - udelay(100); - - state = inb(0x1604); - if (state == STATE_FRESH) - return 0; - - outb(0x11, 0x1610); - outb(0x01, 0x161f); - if (sync == REFRESH_ASYNC) - return 0; + udelay(200); + if (inb(0x1604) != STATE_FRESH) { + outb(0x11, 0x1610); + outb(0x01, 0x161f); + } +} +/* + * __device_refresh_sync - request a synchronous refresh from the + * accelerometer. We wait for the refresh to complete. Returns zero if + * successful and nonzero on error. Callers must hold hdaps_sem. + */ +static int __device_refresh_sync(void) +{ + __device_refresh(); return __wait_latch(0x1604, STATE_FRESH); } /* - * __device_complete - Indicate to the accelerometer that we are done reading + * __device_complete - indicate to the accelerometer that we are done reading * data, and then initiate an async refresh. Callers must hold hdaps_sem. */ static inline void __device_complete(void) { inb(0x161f); inb(0x1604); - __device_refresh(REFRESH_ASYNC); -} - -static int __hdaps_readb_one(unsigned int port, u8 *val) -{ - /* do a sync refresh -- we need to be sure that we read fresh data */ - if (__device_refresh(REFRESH_SYNC)) - return -EIO; - - *val = inb(port); - __device_complete(); - - return 0; + __device_refresh(); } /* @@ -174,17 +151,26 @@ static int hdaps_readb_one(unsigned int port, u8 *val) int ret; down(&hdaps_sem); - ret = __hdaps_readb_one(port, val); - up(&hdaps_sem); + /* do a sync refresh -- we need to be sure that we read fresh data */ + ret = __device_refresh_sync(); + if (ret) + goto out; + + *val = inb(port); + __device_complete(); + +out: + up(&hdaps_sem); return ret; } +/* __hdaps_read_pair - internal lockless helper for hdaps_read_pair(). */ static int __hdaps_read_pair(unsigned int port1, unsigned int port2, int *x, int *y) { /* do a sync refresh -- we need to be sure that we read fresh data */ - if (__device_refresh(REFRESH_SYNC)) + if (__device_refresh_sync()) return -EIO; *y = inw(port2); @@ -217,11 +203,13 @@ static int hdaps_read_pair(unsigned int port1, unsigned int port2, return ret; } -/* initialize the accelerometer */ +/* + * hdaps_device_init - initialize the accelerometer. Returns zero on success + * and negative error code on failure. Can sleep. + */ static int hdaps_device_init(void) { - unsigned int total_msecs = INIT_TIMEOUT_MSECS; - int ret = -ENXIO; + int total, ret = -ENXIO; down(&hdaps_sem); @@ -231,8 +219,10 @@ static int hdaps_device_init(void) goto out; /* - * The 0x03 value appears to only work on some thinkpads, such as the - * T42p. Others return 0x01. + * Most ThinkPads return 0x01. + * + * Others--namely the R50p, T41p, and T42p--return 0x03. These laptops + * have "inverted" axises. * * The 0x02 value occurs when the chip has been previously initialized. */ @@ -267,24 +257,23 @@ static int hdaps_device_init(void) outb(0x01, 0x161f); if (__wait_latch(0x161f, 0x00)) goto out; - if (__device_refresh(REFRESH_SYNC)) + if (__device_refresh_sync()) goto out; if (__wait_latch(0x1611, 0x00)) goto out; /* we have done our dance, now let's wait for the applause */ - while (total_msecs > 0) { - u8 ignored; + for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) { + int x, y; /* a read of the device helps push it into action */ - __hdaps_readb_one(HDAPS_PORT_UNKNOWN, &ignored); + __hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y); if (!__wait_latch(0x1611, 0x02)) { ret = 0; break; } msleep(INIT_WAIT_MSECS); - total_msecs -= INIT_WAIT_MSECS; } out: @@ -293,96 +282,6 @@ out: } -/* Input class stuff */ - -/* - * hdaps_calibrate - Zero out our "resting" values. Callers must hold hdaps_sem. - */ -static void hdaps_calibrate(void) -{ - int x, y; - - if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y)) - return; - - rest_x = x; - rest_y = y; -} - -static void hdaps_mousedev_poll(unsigned long unused) -{ - int x, y; - - /* Cannot sleep. Try nonblockingly. If we fail, try again later. */ - if (down_trylock(&hdaps_sem)) { - mod_timer(&hdaps_timer,jiffies+msecs_to_jiffies(hdaps_poll_ms)); - return; - } - - if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y)) - goto out; - - x -= rest_x; - y -= rest_y; - if (abs(x) > hdaps_mousedev_threshold) - input_report_rel(&hdaps_idev, REL_X, x); - if (abs(y) > hdaps_mousedev_threshold) - input_report_rel(&hdaps_idev, REL_Y, y); - input_sync(&hdaps_idev); - - mod_timer(&hdaps_timer, jiffies + msecs_to_jiffies(hdaps_poll_ms)); - -out: - up(&hdaps_sem); -} - -/* - * hdaps_mousedev_enable - enable the input class device. Can sleep. - */ -static void hdaps_mousedev_enable(void) -{ - down(&hdaps_sem); - - /* calibrate the device before enabling */ - hdaps_calibrate(); - - /* initialize the input class */ - init_input_dev(&hdaps_idev); - hdaps_idev.dev = &pdev->dev; - hdaps_idev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); - hdaps_idev.relbit[0] = BIT(REL_X) | BIT(REL_Y); - hdaps_idev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT); - input_register_device(&hdaps_idev); - - /* start up our timer */ - init_timer(&hdaps_timer); - hdaps_timer.function = hdaps_mousedev_poll; - hdaps_timer.expires = jiffies + msecs_to_jiffies(hdaps_poll_ms); - add_timer(&hdaps_timer); - - hdaps_mousedev = 1; - - up(&hdaps_sem); - - printk(KERN_INFO "hdaps: input device enabled.\n"); -} - -/* - * hdaps_mousedev_disable - disable the input class device. Caller must hold - * hdaps_sem. - */ -static void hdaps_mousedev_disable(void) -{ - down(&hdaps_sem); - if (hdaps_mousedev) { - hdaps_mousedev = 0; - del_timer_sync(&hdaps_timer); - input_unregister_device(&hdaps_idev); - } - up(&hdaps_sem); -} - - /* Device model stuff */ static int hdaps_probe(struct device *dev) @@ -412,6 +311,49 @@ static struct device_driver hdaps_driver = { .resume = hdaps_resume }; +/* Input class stuff */ + +static struct input_dev hdaps_idev = { + .name = "hdaps", + .evbit = { BIT(EV_ABS) }, + .absbit = { BIT(ABS_X) | BIT(ABS_Y) }, + .absmin = { [ABS_X] = -256, [ABS_Y] = -256 }, + .absmax = { [ABS_X] = 256, [ABS_Y] = 256 }, + .absfuzz = { [ABS_X] = HDAPS_INPUT_FUZZ, [ABS_Y] = HDAPS_INPUT_FUZZ }, + .absflat = { [ABS_X] = HDAPS_INPUT_FUZZ, [ABS_Y] = HDAPS_INPUT_FUZZ }, +}; + +/* + * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_sem. + */ +static void hdaps_calibrate(void) +{ + __hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &rest_x, &rest_y); +} + +static void hdaps_mousedev_poll(unsigned long unused) +{ + int x, y; + + /* Cannot sleep. Try nonblockingly. If we fail, try again later. */ + if (down_trylock(&hdaps_sem)) { + mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD); + return; + } + + if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y)) + goto out; + + input_report_abs(&hdaps_idev, ABS_X, x - rest_x); + input_report_abs(&hdaps_idev, ABS_Y, y - rest_y); + input_sync(&hdaps_idev); + + mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD); + +out: + up(&hdaps_sem); +} + /* Sysfs Files */ @@ -517,69 +459,6 @@ static ssize_t hdaps_invert_store(struct device *dev, return count; } -static ssize_t hdaps_mousedev_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", hdaps_mousedev); -} - -static ssize_t hdaps_mousedev_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int enable; - - if (sscanf(buf, "%d", &enable) != 1) - return -EINVAL; - - if (enable == 1) - hdaps_mousedev_enable(); - else if (enable == 0) - hdaps_mousedev_disable(); - else - return -EINVAL; - - return count; -} - -static ssize_t hdaps_poll_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%lu\n", hdaps_poll_ms); -} - -static ssize_t hdaps_poll_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned int poll; - - if (sscanf(buf, "%u", &poll) != 1 || poll == 0) - return -EINVAL; - hdaps_poll_ms = poll; - - return count; -} - -static ssize_t hdaps_threshold_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%u\n", hdaps_mousedev_threshold); -} - -static ssize_t hdaps_threshold_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned int threshold; - - if (sscanf(buf, "%u", &threshold) != 1 || threshold == 0) - return -EINVAL; - hdaps_mousedev_threshold = threshold; - - return count; -} - static DEVICE_ATTR(position, 0444, hdaps_position_show, NULL); static DEVICE_ATTR(variance, 0444, hdaps_variance_show, NULL); static DEVICE_ATTR(temp1, 0444, hdaps_temp1_show, NULL); @@ -588,10 +467,6 @@ static DEVICE_ATTR(keyboard_activity, 0444, hdaps_keyboard_activity_show, NULL); static DEVICE_ATTR(mouse_activity, 0444, hdaps_mouse_activity_show, NULL); static DEVICE_ATTR(calibrate, 0644, hdaps_calibrate_show,hdaps_calibrate_store); static DEVICE_ATTR(invert, 0644, hdaps_invert_show, hdaps_invert_store); -static DEVICE_ATTR(mousedev, 0644, hdaps_mousedev_show, hdaps_mousedev_store); -static DEVICE_ATTR(mousedev_poll_ms, 0644, hdaps_poll_show, hdaps_poll_store); -static DEVICE_ATTR(mousedev_threshold, 0644, hdaps_threshold_show, - hdaps_threshold_store); static struct attribute *hdaps_attributes[] = { &dev_attr_position.attr, @@ -601,9 +476,6 @@ static struct attribute *hdaps_attributes[] = { &dev_attr_keyboard_activity.attr, &dev_attr_mouse_activity.attr, &dev_attr_calibrate.attr, - &dev_attr_mousedev.attr, - &dev_attr_mousedev_threshold.attr, - &dev_attr_mousedev_poll_ms.attr, &dev_attr_invert.attr, NULL, }; @@ -619,7 +491,7 @@ static struct attribute_group hdaps_attribute_group = { * XXX: We should be able to return nonzero and halt the detection process. * But there is a bug in dmi_check_system() where a nonzero return from the * first match will result in a return of failure from dmi_check_system(). - * I fixed this; the patch is in 2.6-mm. Once in Linus's tree we can make + * I fixed this; the patch is 2.6-git. Once in a released tree, we can make * hdaps_dmi_match_invert() return hdaps_dmi_match(), which in turn returns 1. */ static int hdaps_dmi_match(struct dmi_system_id *id) @@ -668,6 +540,7 @@ static int __init hdaps_init(void) HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"), HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"), HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"), + HDAPS_DMI_MATCH_NORMAL("ThinkPad X41 Tablet"), { .ident = NULL } }; @@ -696,8 +569,18 @@ static int __init hdaps_init(void) if (ret) goto out_device; - if (hdaps_mousedev) - hdaps_mousedev_enable(); + /* initial calibrate for the input device */ + hdaps_calibrate(); + + /* initialize the input class */ + hdaps_idev.dev = &pdev->dev; + input_register_device(&hdaps_idev); + + /* start up our timer for the input device */ + init_timer(&hdaps_timer); + hdaps_timer.function = hdaps_mousedev_poll; + hdaps_timer.expires = jiffies + HDAPS_POLL_PERIOD; + add_timer(&hdaps_timer); printk(KERN_INFO "hdaps: driver successfully loaded.\n"); return 0; @@ -715,8 +598,8 @@ out: static void __exit hdaps_exit(void) { - hdaps_mousedev_disable(); - + del_timer_sync(&hdaps_timer); + input_unregister_device(&hdaps_idev); sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group); platform_device_unregister(pdev); driver_unregister(&hdaps_driver); @@ -728,9 +611,6 @@ static void __exit hdaps_exit(void) module_init(hdaps_init); module_exit(hdaps_exit); -module_param_named(mousedev, hdaps_mousedev, bool, 0); -MODULE_PARM_DESC(mousedev, "enable the input class device"); - module_param_named(invert, hdaps_invert, bool, 0); MODULE_PARM_DESC(invert, "invert data along each axis"); diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index d04f62ab5de1..ace8edad6e96 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -500,6 +500,7 @@ static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long } rq.special = args; + args->rq = &rq; return ide_do_drive_cmd(drive, &rq, ide_wait); } diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c index 8337b0f26cc4..4866fc32d8d9 100644 --- a/drivers/isdn/hisax/hfc_pci.c +++ b/drivers/isdn/hisax/hfc_pci.c @@ -61,6 +61,7 @@ static const PCI_ENTRY id_list[] = {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_E,"Digi International", "Digi DataFire Micro V (Europe)"}, {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_A,"Digi International", "Digi DataFire Micro V IOM2 (North America)"}, {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_A,"Digi International", "Digi DataFire Micro V (North America)"}, + {PCI_VENDOR_ID_SITECOM, PCI_DEVICE_ID_SITECOM_DC105V2, "Sitecom Europe", "DC-105 ISDN PCI"}, {0, 0, NULL, NULL}, }; diff --git a/drivers/isdn/hisax/st5481.h b/drivers/isdn/hisax/st5481.h index 0fda5c89429b..9ffaae7c657a 100644 --- a/drivers/isdn/hisax/st5481.h +++ b/drivers/isdn/hisax/st5481.h @@ -466,10 +466,10 @@ void st5481_stop(struct st5481_adapter *adapter); #define __debug_variable st5481_debug #include "hisax_debug.h" -#ifdef CONFIG_HISAX_DEBUG - extern int st5481_debug; +#ifdef CONFIG_HISAX_DEBUG + #define DBG_ISO_PACKET(level,urb) \ if (level & __debug_variable) dump_iso_packet(__FUNCTION__,urb) diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c index 2fcd093921d8..0a2536d62402 100644 --- a/drivers/isdn/hisax/st5481_b.c +++ b/drivers/isdn/hisax/st5481_b.c @@ -172,14 +172,18 @@ static void usb_b_out_complete(struct urb *urb, struct pt_regs *regs) test_and_clear_bit(buf_nr, &b_out->busy); if (unlikely(urb->status < 0)) { - if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) { - WARN("urb status %d",urb->status); - if (b_out->busy == 0) { - st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL); - } - } else { - DBG(1,"urb killed"); - return; // Give up + switch (urb->status) { + case -ENOENT: + case -ESHUTDOWN: + case -ECONNRESET: + DBG(4,"urb killed status %d", urb->status); + return; // Give up + default: + WARN("urb status %d",urb->status); + if (b_out->busy == 0) { + st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL); + } + break; } } @@ -205,7 +209,9 @@ static void st5481B_mode(struct st5481_bcs *bcs, int mode) bcs->mode = mode; // Cancel all USB transfers on this B channel + b_out->urb[0]->transfer_flags |= URB_ASYNC_UNLINK; usb_unlink_urb(b_out->urb[0]); + b_out->urb[1]->transfer_flags |= URB_ASYNC_UNLINK; usb_unlink_urb(b_out->urb[1]); b_out->busy = 0; diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c index 071b1d31999f..941f7022ada1 100644 --- a/drivers/isdn/hisax/st5481_d.c +++ b/drivers/isdn/hisax/st5481_d.c @@ -382,16 +382,20 @@ static void usb_d_out_complete(struct urb *urb, struct pt_regs *regs) test_and_clear_bit(buf_nr, &d_out->busy); if (unlikely(urb->status < 0)) { - if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) { - WARN("urb status %d",urb->status); - if (d_out->busy == 0) { - st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter); - } - return; - } else { - DBG(1,"urb killed"); - return; // Give up + switch (urb->status) { + case -ENOENT: + case -ESHUTDOWN: + case -ECONNRESET: + DBG(1,"urb killed status %d", urb->status); + break; + default: + WARN("urb status %d",urb->status); + if (d_out->busy == 0) { + st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter); + } + break; } + return; // Give up } FsmEvent(&adapter->d_out.fsm, EV_DOUT_COMPLETE, (void *) buf_nr); @@ -709,14 +713,14 @@ int st5481_setup_d(struct st5481_adapter *adapter) adapter->l1m.fsm = &l1fsm; adapter->l1m.state = ST_L1_F3; - adapter->l1m.debug = 1; + adapter->l1m.debug = st5481_debug & 0x100; adapter->l1m.userdata = adapter; adapter->l1m.printdebug = l1m_debug; FsmInitTimer(&adapter->l1m, &adapter->timer); adapter->d_out.fsm.fsm = &dout_fsm; adapter->d_out.fsm.state = ST_DOUT_NONE; - adapter->d_out.fsm.debug = 1; + adapter->d_out.fsm.debug = st5481_debug & 0x100; adapter->d_out.fsm.userdata = adapter; adapter->d_out.fsm.printdebug = dout_debug; diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c index 7aa810d5d333..2cf5d1a6df6c 100644 --- a/drivers/isdn/hisax/st5481_init.c +++ b/drivers/isdn/hisax/st5481_init.c @@ -43,10 +43,10 @@ static int number_of_leds = 2; /* 2 LEDs on the adpater default */ module_param(number_of_leds, int, 0); #ifdef CONFIG_HISAX_DEBUG -static int debug = 0x1; +static int debug = 0; module_param(debug, int, 0); -int st5481_debug; #endif +int st5481_debug; static LIST_HEAD(adapter_list); diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c index ab62223297a5..ffd5b2d45552 100644 --- a/drivers/isdn/hisax/st5481_usb.c +++ b/drivers/isdn/hisax/st5481_usb.c @@ -132,11 +132,15 @@ static void usb_ctrl_complete(struct urb *urb, struct pt_regs *regs) struct ctrl_msg *ctrl_msg; if (unlikely(urb->status < 0)) { - if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) { - WARN("urb status %d",urb->status); - } else { - DBG(1,"urb killed"); - return; // Give up + switch (urb->status) { + case -ENOENT: + case -ESHUTDOWN: + case -ECONNRESET: + DBG(1,"urb killed status %d", urb->status); + return; // Give up + default: + WARN("urb status %d",urb->status); + break; } } @@ -184,22 +188,22 @@ static void usb_int_complete(struct urb *urb, struct pt_regs *regs) int status; switch (urb->status) { - case 0: - /* success */ - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - DBG(1, "urb shutting down with status: %d", urb->status); - return; - default: - WARN("nonzero urb status received: %d", urb->status); - goto exit; + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + DBG(2, "urb shutting down with status: %d", urb->status); + return; + default: + WARN("nonzero urb status received: %d", urb->status); + goto exit; } - DBG_PACKET(1, data, INT_PKT_SIZE); + DBG_PACKET(2, data, INT_PKT_SIZE); if (urb->actual_length == 0) { goto exit; @@ -250,7 +254,7 @@ int st5481_setup_usb(struct st5481_adapter *adapter) struct urb *urb; u8 *buf; - DBG(1,""); + DBG(2,""); if ((status = usb_reset_configuration (dev)) < 0) { WARN("reset_configuration failed,status=%d",status); @@ -330,15 +334,17 @@ void st5481_release_usb(struct st5481_adapter *adapter) DBG(1,""); // Stop and free Control and Interrupt URBs - usb_unlink_urb(ctrl->urb); + usb_kill_urb(ctrl->urb); if (ctrl->urb->transfer_buffer) kfree(ctrl->urb->transfer_buffer); usb_free_urb(ctrl->urb); + ctrl->urb = NULL; - usb_unlink_urb(intr->urb); + usb_kill_urb(intr->urb); if (intr->urb->transfer_buffer) kfree(intr->urb->transfer_buffer); usb_free_urb(intr->urb); + ctrl->urb = NULL; } /* @@ -406,6 +412,7 @@ fill_isoc_urb(struct urb *urb, struct usb_device *dev, spin_lock_init(&urb->lock); urb->dev=dev; urb->pipe=pipe; + urb->interval = 1; urb->transfer_buffer=buf; urb->number_of_packets = num_packets; urb->transfer_buffer_length=num_packets*packet_size; @@ -452,7 +459,9 @@ st5481_setup_isocpipes(struct urb* urb[2], struct usb_device *dev, if (urb[j]) { if (urb[j]->transfer_buffer) kfree(urb[j]->transfer_buffer); + urb[j]->transfer_buffer = NULL; usb_free_urb(urb[j]); + urb[j] = NULL; } } return retval; @@ -463,10 +472,11 @@ void st5481_release_isocpipes(struct urb* urb[2]) int j; for (j = 0; j < 2; j++) { - usb_unlink_urb(urb[j]); + usb_kill_urb(urb[j]); if (urb[j]->transfer_buffer) kfree(urb[j]->transfer_buffer); usb_free_urb(urb[j]); + urb[j] = NULL; } } @@ -485,11 +495,15 @@ static void usb_in_complete(struct urb *urb, struct pt_regs *regs) int len, count, status; if (unlikely(urb->status < 0)) { - if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) { - WARN("urb status %d",urb->status); - } else { - DBG(1,"urb killed"); - return; // Give up + switch (urb->status) { + case -ENOENT: + case -ESHUTDOWN: + case -ECONNRESET: + DBG(1,"urb killed status %d", urb->status); + return; // Give up + default: + WARN("urb status %d",urb->status); + break; } } @@ -631,7 +645,9 @@ void st5481_in_mode(struct st5481_in *in, int mode) in->mode = mode; + in->urb[0]->transfer_flags |= URB_ASYNC_UNLINK; usb_unlink_urb(in->urb[0]); + in->urb[1]->transfer_flags |= URB_ASYNC_UNLINK; usb_unlink_urb(in->urb[1]); if (in->mode != L1_MODE_NULL) { diff --git a/drivers/md/raid6.h b/drivers/md/raid6.h index f80ee6350edf..31cbee71365f 100644 --- a/drivers/md/raid6.h +++ b/drivers/md/raid6.h @@ -69,9 +69,13 @@ extern const char raid6_empty_zero_page[PAGE_SIZE]; #define __init #define __exit #define __attribute_const__ __attribute__((const)) +#define noinline __attribute__((noinline)) #define preempt_enable() #define preempt_disable() +#define cpu_has_feature(x) 1 +#define enable_kernel_altivec() +#define disable_kernel_altivec() #endif /* __KERNEL__ */ diff --git a/drivers/md/raid6algos.c b/drivers/md/raid6algos.c index acf386fc4b4f..51c63c0cf1c9 100644 --- a/drivers/md/raid6algos.c +++ b/drivers/md/raid6algos.c @@ -19,6 +19,7 @@ #include "raid6.h" #ifndef __KERNEL__ #include <sys/mman.h> +#include <stdio.h> #endif struct raid6_calls raid6_call; diff --git a/drivers/md/raid6altivec.uc b/drivers/md/raid6altivec.uc index 1de8f030eee0..b9afd35b8812 100644 --- a/drivers/md/raid6altivec.uc +++ b/drivers/md/raid6altivec.uc @@ -27,16 +27,20 @@ #ifdef CONFIG_ALTIVEC #include <altivec.h> -#include <asm/system.h> -#include <asm/cputable.h> +#ifdef __KERNEL__ +# include <asm/system.h> +# include <asm/cputable.h> +#endif /* - * This is the C data type to use + * This is the C data type to use. We use a vector of + * signed char so vec_cmpgt() will generate the right + * instruction. */ -typedef vector unsigned char unative_t; +typedef vector signed char unative_t; -#define NBYTES(x) ((vector unsigned char) {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}) +#define NBYTES(x) ((vector signed char) {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}) #define NSIZE sizeof(unative_t) /* @@ -108,7 +112,11 @@ int raid6_have_altivec(void); int raid6_have_altivec(void) { /* This assumes either all CPUs have Altivec or none does */ +# ifdef __KERNEL__ return cpu_has_feature(CPU_FTR_ALTIVEC); +# else + return 1; +# endif } #endif diff --git a/drivers/md/raid6test/Makefile b/drivers/md/raid6test/Makefile index 557806728609..78e0396adf2a 100644 --- a/drivers/md/raid6test/Makefile +++ b/drivers/md/raid6test/Makefile @@ -8,6 +8,8 @@ OPTFLAGS = -O2 # Adjust as desired CFLAGS = -I.. -g $(OPTFLAGS) LD = ld PERL = perl +AR = ar +RANLIB = ranlib .c.o: $(CC) $(CFLAGS) -c -o $@ $< @@ -18,18 +20,33 @@ PERL = perl %.uc: ../%.uc cp -f $< $@ -all: raid6.o raid6test +all: raid6.a raid6test -raid6.o: raid6int1.o raid6int2.o raid6int4.o raid6int8.o raid6int16.o \ +raid6.a: raid6int1.o raid6int2.o raid6int4.o raid6int8.o raid6int16.o \ raid6int32.o \ raid6mmx.o raid6sse1.o raid6sse2.o \ + raid6altivec1.o raid6altivec2.o raid6altivec4.o raid6altivec8.o \ raid6recov.o raid6algos.o \ raid6tables.o - $(LD) -r -o $@ $^ + rm -f $@ + $(AR) cq $@ $^ + $(RANLIB) $@ -raid6test: raid6.o test.c +raid6test: test.c raid6.a $(CC) $(CFLAGS) -o raid6test $^ +raid6altivec1.c: raid6altivec.uc ../unroll.pl + $(PERL) ../unroll.pl 1 < raid6altivec.uc > $@ + +raid6altivec2.c: raid6altivec.uc ../unroll.pl + $(PERL) ../unroll.pl 2 < raid6altivec.uc > $@ + +raid6altivec4.c: raid6altivec.uc ../unroll.pl + $(PERL) ../unroll.pl 4 < raid6altivec.uc > $@ + +raid6altivec8.c: raid6altivec.uc ../unroll.pl + $(PERL) ../unroll.pl 8 < raid6altivec.uc > $@ + raid6int1.c: raid6int.uc ../unroll.pl $(PERL) ../unroll.pl 1 < raid6int.uc > $@ @@ -52,7 +69,7 @@ raid6tables.c: mktables ./mktables > raid6tables.c clean: - rm -f *.o mktables mktables.c raid6int.uc raid6*.c raid6test + rm -f *.o *.a mktables mktables.c raid6int.uc raid6*.c raid6test spotless: clean rm -f *~ diff --git a/drivers/mtd/maps/sharpsl-flash.c b/drivers/mtd/maps/sharpsl-flash.c index d15da6fd84c1..b7f093fbf9b0 100644 --- a/drivers/mtd/maps/sharpsl-flash.c +++ b/drivers/mtd/maps/sharpsl-flash.c @@ -82,7 +82,7 @@ int __init init_sharpsl(void) } else if (machine_is_tosa()) { sharpsl_partitions[0].size=0x006a0000; sharpsl_partitions[0].offset=0x00160000; - } else if (machine_is_spitz()) { + } else if (machine_is_spitz() || machine_is_akita() || machine_is_borzoi()) { sharpsl_partitions[0].size=0x006b0000; sharpsl_partitions[0].offset=0x00140000; } else { diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index 9853b87bb756..88b5b5b40b43 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c @@ -221,10 +221,16 @@ sharpsl_nand_init(void) sharpsl_partition_info[1].size=25 * 1024 * 1024; } else if (machine_is_husky()) { sharpsl_partition_info[1].size=53 * 1024 * 1024; - } + } else if (machine_is_spitz()) { + sharpsl_partition_info[1].size=5 * 1024 * 1024; + } else if (machine_is_akita()) { + sharpsl_partition_info[1].size=58 * 1024 * 1024; + } else if (machine_is_borzoi()) { + sharpsl_partition_info[1].size=32 * 1024 * 1024; + } } - if (machine_is_husky()) { + if (machine_is_husky() || machine_is_borzoi()) { /* Need to use small eraseblock size for backward compatibility */ sharpsl_mtd->flags |= MTD_NO_VIRTBLOCKS; } diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 34b80de34fae..bc537440ca02 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -353,8 +353,6 @@ struct cp_private { struct net_device_stats net_stats; struct cp_extra_stats cp_stats; - struct cp_dma_stats *nic_stats; - dma_addr_t nic_stats_dma; unsigned rx_tail ____cacheline_aligned; struct cp_desc *rx_ring; @@ -1143,10 +1141,6 @@ static int cp_alloc_rings (struct cp_private *cp) cp->rx_ring = mem; cp->tx_ring = &cp->rx_ring[CP_RX_RING_SIZE]; - mem += (CP_RING_BYTES - CP_STATS_SIZE); - cp->nic_stats = mem; - cp->nic_stats_dma = cp->ring_dma + (CP_RING_BYTES - CP_STATS_SIZE); - return cp_init_rings(cp); } @@ -1187,7 +1181,6 @@ static void cp_free_rings (struct cp_private *cp) pci_free_consistent(cp->pdev, CP_RING_BYTES, cp->rx_ring, cp->ring_dma); cp->rx_ring = NULL; cp->tx_ring = NULL; - cp->nic_stats = NULL; } static int cp_open (struct net_device *dev) @@ -1516,13 +1509,17 @@ static void cp_get_ethtool_stats (struct net_device *dev, struct ethtool_stats *estats, u64 *tmp_stats) { struct cp_private *cp = netdev_priv(dev); + struct cp_dma_stats *nic_stats; + dma_addr_t dma; int i; - memset(cp->nic_stats, 0, sizeof(struct cp_dma_stats)); + nic_stats = pci_alloc_consistent(cp->pdev, sizeof(*nic_stats), &dma); + if (!nic_stats) + return; /* begin NIC statistics dump */ - cpw32(StatsAddr + 4, (cp->nic_stats_dma >> 16) >> 16); - cpw32(StatsAddr, (cp->nic_stats_dma & 0xffffffff) | DumpStats); + cpw32(StatsAddr + 4, (u64)dma >> 32); + cpw32(StatsAddr, ((u64)dma & DMA_32BIT_MASK) | DumpStats); cpr32(StatsAddr); for (i = 0; i < 1000; i++) { @@ -1532,24 +1529,27 @@ static void cp_get_ethtool_stats (struct net_device *dev, } cpw32(StatsAddr, 0); cpw32(StatsAddr + 4, 0); + cpr32(StatsAddr); i = 0; - tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_ok); - tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok); - tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_err); - tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_err); - tmp_stats[i++] = le16_to_cpu(cp->nic_stats->rx_fifo); - tmp_stats[i++] = le16_to_cpu(cp->nic_stats->frame_align); - tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_1col); - tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_mcol); - tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_phys); - tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_bcast); - tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_ok_mcast); - tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_abort); - tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_underrun); + tmp_stats[i++] = le64_to_cpu(nic_stats->tx_ok); + tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok); + tmp_stats[i++] = le64_to_cpu(nic_stats->tx_err); + tmp_stats[i++] = le32_to_cpu(nic_stats->rx_err); + tmp_stats[i++] = le16_to_cpu(nic_stats->rx_fifo); + tmp_stats[i++] = le16_to_cpu(nic_stats->frame_align); + tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_1col); + tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_mcol); + tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_phys); + tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_bcast); + tmp_stats[i++] = le32_to_cpu(nic_stats->rx_ok_mcast); + tmp_stats[i++] = le16_to_cpu(nic_stats->tx_abort); + tmp_stats[i++] = le16_to_cpu(nic_stats->tx_underrun); tmp_stats[i++] = cp->cp_stats.rx_frags; if (i != CP_NUM_STATS) BUG(); + + pci_free_consistent(cp->pdev, sizeof(*nic_stats), nic_stats, dma); } static struct ethtool_ops cp_ethtool_ops = { diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 94c9f68dd16b..90449a0f2a6c 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2879,6 +2879,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) * This target is not on a VLAN */ if (rt->u.dst.dev == bond->dev) { + ip_rt_put(rt); dprintk("basa: rtdev == bond->dev: arp_send\n"); bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], bond->master_ip, 0); @@ -2898,6 +2899,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) } if (vlan_id) { + ip_rt_put(rt); bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], vlan->vlan_ip, vlan_id); continue; @@ -2909,6 +2911,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) bond->dev->name, NIPQUAD(fl.fl4_dst), rt->u.dst.dev ? rt->u.dst.dev->name : "NULL"); } + ip_rt_put(rt); } } @@ -5036,6 +5039,14 @@ static int __init bonding_init(void) return 0; out_err: + /* + * rtnl_unlock() will run netdev_run_todo(), putting the + * thus-far-registered bonding devices into a state which + * unregigister_netdevice() will accept + */ + rtnl_unlock(); + rtnl_lock(); + /* free and unregister all bonds that were successfully added */ bond_free_all(); diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 4e19220473d0..c796f41b4a52 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -1817,6 +1817,10 @@ spider_net_setup_phy(struct spider_net_card *card) /* LEDs active in both modes, autosense prio = fiber */ spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0x945f); + /* switch off fibre autoneg */ + spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0xfc01); + spider_net_write_phy(card->netdev, 1, 0x0b, 0x0004); + phy->def->ops->read_link(phy); pr_info("Found %s with %i Mbps, %s-duplex.\n", phy->def->name, phy->speed, phy->duplex==1 ? "Full" : "Half"); diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 7599f52e15b3..81f4aedf534c 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -67,8 +67,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.39" -#define DRV_MODULE_RELDATE "September 5, 2005" +#define DRV_MODULE_VERSION "3.40" +#define DRV_MODULE_RELDATE "September 15, 2005" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -3442,31 +3442,47 @@ static void tg3_tx_timeout(struct net_device *dev) schedule_work(&tp->reset_task); } +/* Test for DMA buffers crossing any 4GB boundaries: 4G, 8G, etc */ +static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len) +{ + u32 base = (u32) mapping & 0xffffffff; + + return ((base > 0xffffdcc0) && + (base + len + 8 < base)); +} + static void tg3_set_txd(struct tg3 *, int, dma_addr_t, int, u32, u32); static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb, - u32 guilty_entry, int guilty_len, - u32 last_plus_one, u32 *start, u32 mss) + u32 last_plus_one, u32 *start, + u32 base_flags, u32 mss) { struct sk_buff *new_skb = skb_copy(skb, GFP_ATOMIC); - dma_addr_t new_addr; + dma_addr_t new_addr = 0; u32 entry = *start; - int i; + int i, ret = 0; if (!new_skb) { - dev_kfree_skb(skb); - return -1; + ret = -1; + } else { + /* New SKB is guaranteed to be linear. */ + entry = *start; + new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len, + PCI_DMA_TODEVICE); + /* Make sure new skb does not cross any 4G boundaries. + * Drop the packet if it does. + */ + if (tg3_4g_overflow_test(new_addr, new_skb->len)) { + ret = -1; + dev_kfree_skb(new_skb); + new_skb = NULL; + } else { + tg3_set_txd(tp, entry, new_addr, new_skb->len, + base_flags, 1 | (mss << 1)); + *start = NEXT_TX(entry); + } } - /* New SKB is guaranteed to be linear. */ - entry = *start; - new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len, - PCI_DMA_TODEVICE); - tg3_set_txd(tp, entry, new_addr, new_skb->len, - (skb->ip_summed == CHECKSUM_HW) ? - TXD_FLAG_TCPUDP_CSUM : 0, 1 | (mss << 1)); - *start = NEXT_TX(entry); - /* Now clean up the sw ring entries. */ i = 0; while (entry != last_plus_one) { @@ -3491,7 +3507,7 @@ static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb, dev_kfree_skb(skb); - return 0; + return ret; } static void tg3_set_txd(struct tg3 *tp, int entry, @@ -3517,19 +3533,10 @@ static void tg3_set_txd(struct tg3 *tp, int entry, txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT; } -static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len) -{ - u32 base = (u32) mapping & 0xffffffff; - - return ((base > 0xffffdcc0) && - (base + len + 8 < base)); -} - static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); dma_addr_t mapping; - unsigned int i; u32 len, entry, base_flags, mss; int would_hit_hwbug; @@ -3624,7 +3631,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) would_hit_hwbug = 0; if (tg3_4g_overflow_test(mapping, len)) - would_hit_hwbug = entry + 1; + would_hit_hwbug = 1; tg3_set_txd(tp, entry, mapping, len, base_flags, (skb_shinfo(skb)->nr_frags == 0) | (mss << 1)); @@ -3648,12 +3655,8 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) tp->tx_buffers[entry].skb = NULL; pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping); - if (tg3_4g_overflow_test(mapping, len)) { - /* Only one should match. */ - if (would_hit_hwbug) - BUG(); - would_hit_hwbug = entry + 1; - } + if (tg3_4g_overflow_test(mapping, len)) + would_hit_hwbug = 1; if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) tg3_set_txd(tp, entry, mapping, len, @@ -3669,34 +3672,15 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) if (would_hit_hwbug) { u32 last_plus_one = entry; u32 start; - unsigned int len = 0; - - would_hit_hwbug -= 1; - entry = entry - 1 - skb_shinfo(skb)->nr_frags; - entry &= (TG3_TX_RING_SIZE - 1); - start = entry; - i = 0; - while (entry != last_plus_one) { - if (i == 0) - len = skb_headlen(skb); - else - len = skb_shinfo(skb)->frags[i-1].size; - if (entry == would_hit_hwbug) - break; - - i++; - entry = NEXT_TX(entry); - - } + start = entry - 1 - skb_shinfo(skb)->nr_frags; + start &= (TG3_TX_RING_SIZE - 1); /* If the workaround fails due to memory/mapping * failure, silently drop this packet. */ - if (tigon3_4gb_hwbug_workaround(tp, skb, - entry, len, - last_plus_one, - &start, mss)) + if (tigon3_4gb_hwbug_workaround(tp, skb, last_plus_one, + &start, base_flags, mss)) goto out_unlock; entry = start; @@ -9271,6 +9255,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) static struct pci_device_id write_reorder_chipsets[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_K8_NB) }, { }, }; u32 misc_ctrl_reg; @@ -9285,7 +9271,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_SUN_570X; #endif - /* If we have an AMD 762 chipset, write + /* If we have an AMD 762 or K8 chipset, write * reordering to the mailbox registers done by the host * controller can cause major troubles. We read back from * every mailbox register write to force the writes to be @@ -9532,7 +9518,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->write32_rx_mbox = tg3_write_indirect_mbox; iounmap(tp->regs); - tp->regs = 0; + tp->regs = NULL; pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd); pci_cmd &= ~PCI_COMMAND_MEMORY; @@ -10680,7 +10666,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, err_out_iounmap: if (tp->regs) { iounmap(tp->regs); - tp->regs = 0; + tp->regs = NULL; } err_out_free_dev: @@ -10705,7 +10691,7 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev) unregister_netdev(dev); if (tp->regs) { iounmap(tp->regs); - tp->regs = 0; + tp->regs = NULL; } free_netdev(dev); pci_release_regions(pdev); diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c index 8122fe734aa7..b1ba429e0a2d 100644 --- a/drivers/pci/hotplug/ibmphp_pci.c +++ b/drivers/pci/hotplug/ibmphp_pci.c @@ -558,7 +558,7 @@ static int configure_device (struct pci_func *func) pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_CACHE_LINE_SIZE, CACHE); pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_LATENCY_TIMER, LATENCY); - pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_ROM_ADDRESS, 0x00L); + pci_bus_write_config_dword (ibmphp_pci_bus, devfn, PCI_ROM_ADDRESS, 0x00L); pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_COMMAND, DEVICEENABLE); return 0; diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 0e0947601526..898f6da6f0de 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -2526,7 +2526,6 @@ configure_new_function(struct controller *ctrl, struct pci_func *func, int cloop; u8 temp_byte; u8 class_code; - u16 temp_word; u32 rc; u32 temp_register; u32 base; @@ -2682,8 +2681,7 @@ configure_new_function(struct controller *ctrl, struct pci_func *func, } /* End of base register loop */ /* disable ROM base Address */ - temp_word = 0x00L; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_word); + rc = pci_bus_write_config_dword (pci_bus, devfn, PCI_ROM_ADDRESS, 0x00); /* Set HP parameters (Cache Line Size, Latency Timer) */ rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL); diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 783b5abb0717..91c9903e621f 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -2824,8 +2824,7 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f } #endif /* Disable ROM base Address */ - temp_word = 0x00L; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_word); + rc = pci_bus_write_config_dword (pci_bus, devfn, PCI_ROM_ADDRESS, 0x00); /* Set HP parameters (Cache Line Size, Latency Timer) */ rc = shpchprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL); diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index aac83ce6469c..a1c52a682191 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/blacklist.c * S/390 common I/O routines -- blacklisting of specific devices - * $Revision: 1.34 $ + * $Revision: 1.35 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -35,7 +35,7 @@ */ /* 65536 bits to indicate if a devno is blacklisted or not */ -#define __BL_DEV_WORDS (__MAX_SUBCHANNELS + (8*sizeof(long) - 1) / \ +#define __BL_DEV_WORDS ((__MAX_SUBCHANNELS + (8*sizeof(long) - 1)) / \ (8*sizeof(long))) static unsigned long bl_dev[__BL_DEV_WORDS]; typedef enum {add, free} range_action; diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c index 6aeef3bacc33..0cb47eca91f3 100644 --- a/drivers/s390/crypto/z90main.c +++ b/drivers/s390/crypto/z90main.c @@ -682,9 +682,6 @@ z90crypt_cleanup_module(void) del_timer(&config_timer); del_timer(&cleanup_timer); - if (z90_device_work) - destroy_workqueue(z90_device_work); - destroy_z90crypt(); PRINTKN("Unloaded.\n"); diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index 3a0285669adf..2ad4797ce024 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h @@ -24,7 +24,7 @@ #include "qeth_mpc.h" -#define VERSION_QETH_H "$Revision: 1.139 $" +#define VERSION_QETH_H "$Revision: 1.142 $" #ifdef CONFIG_QETH_IPV6 #define QETH_VERSION_IPV6 ":IPv6" @@ -1172,7 +1172,7 @@ extern int qeth_realloc_buffer_pool(struct qeth_card *, int); extern int -qeth_set_large_send(struct qeth_card *); +qeth_set_large_send(struct qeth_card *, enum qeth_large_send_types); extern void qeth_fill_header(struct qeth_card *, struct qeth_hdr *, diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 79c74f3a11f5..86582cf1e19e 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_main.c ($Revision: 1.214 $) + * linux/drivers/s390/net/qeth_main.c ($Revision: 1.224 $) * * Linux on zSeries OSA Express and HiperSockets support * @@ -12,7 +12,7 @@ * Frank Pavlic (pavlic@de.ibm.com) and * Thomas Spatzier <tspat@de.ibm.com> * - * $Revision: 1.214 $ $Date: 2005/05/04 20:19:18 $ + * $Revision: 1.224 $ $Date: 2005/05/04 20:19:18 $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,14 +29,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/*** - * eye catcher; just for debugging purposes - */ -void volatile -qeth_eyecatcher(void) -{ - return; -} #include <linux/config.h> #include <linux/module.h> @@ -80,7 +72,7 @@ qeth_eyecatcher(void) #include "qeth_eddp.h" #include "qeth_tso.h" -#define VERSION_QETH_C "$Revision: 1.214 $" +#define VERSION_QETH_C "$Revision: 1.224 $" static const char *version = "qeth S/390 OSA-Express driver"; /** @@ -2759,11 +2751,9 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, queue->card->perf_stats.outbound_do_qdio_start_time; #endif if (rc){ - QETH_DBF_SPRINTF(trace, 0, "qeth_flush_buffers: do_QDIO " - "returned error (%i) on device %s.", - rc, CARD_DDEV_ID(queue->card)); QETH_DBF_TEXT(trace, 2, "flushbuf"); QETH_DBF_TEXT_(trace, 2, " err%d", rc); + QETH_DBF_TEXT_(trace, 2, "%s", CARD_DDEV_ID(queue->card)); queue->card->stats.tx_errors += count; /* this must not happen under normal circumstances. if it * happens something is really wrong -> recover */ @@ -2909,11 +2899,8 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status, QETH_DBF_TEXT(trace, 6, "qdouhdl"); if (status & QDIO_STATUS_LOOK_FOR_ERROR) { if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){ - QETH_DBF_SPRINTF(trace, 2, "On device %s: " - "received active check " - "condition (0x%08x).", - CARD_BUS_ID(card), status); - QETH_DBF_TEXT(trace, 2, "chkcond"); + QETH_DBF_TEXT(trace, 2, "achkcond"); + QETH_DBF_TEXT_(trace, 2, "%s", CARD_BUS_ID(card)); QETH_DBF_TEXT_(trace, 2, "%08x", status); netif_stop_queue(card->dev); qeth_schedule_recovery(card); @@ -3356,26 +3343,32 @@ qeth_halt_channel(struct qeth_channel *channel) static int qeth_halt_channels(struct qeth_card *card) { - int rc = 0; + int rc1 = 0, rc2=0, rc3 = 0; QETH_DBF_TEXT(trace,3,"haltchs"); - if ((rc = qeth_halt_channel(&card->read))) - return rc; - if ((rc = qeth_halt_channel(&card->write))) - return rc; - return qeth_halt_channel(&card->data); + rc1 = qeth_halt_channel(&card->read); + rc2 = qeth_halt_channel(&card->write); + rc3 = qeth_halt_channel(&card->data); + if (rc1) + return rc1; + if (rc2) + return rc2; + return rc3; } static int qeth_clear_channels(struct qeth_card *card) { - int rc = 0; + int rc1 = 0, rc2=0, rc3 = 0; QETH_DBF_TEXT(trace,3,"clearchs"); - if ((rc = qeth_clear_channel(&card->read))) - return rc; - if ((rc = qeth_clear_channel(&card->write))) - return rc; - return qeth_clear_channel(&card->data); + rc1 = qeth_clear_channel(&card->read); + rc2 = qeth_clear_channel(&card->write); + rc3 = qeth_clear_channel(&card->data); + if (rc1) + return rc1; + if (rc2) + return rc2; + return rc3; } static int @@ -3445,23 +3438,23 @@ qeth_mpc_initialize(struct qeth_card *card) } if ((rc = qeth_cm_enable(card))){ QETH_DBF_TEXT_(setup, 2, "2err%d", rc); - return rc; + goto out_qdio; } if ((rc = qeth_cm_setup(card))){ QETH_DBF_TEXT_(setup, 2, "3err%d", rc); - return rc; + goto out_qdio; } if ((rc = qeth_ulp_enable(card))){ QETH_DBF_TEXT_(setup, 2, "4err%d", rc); - return rc; + goto out_qdio; } if ((rc = qeth_ulp_setup(card))){ QETH_DBF_TEXT_(setup, 2, "5err%d", rc); - return rc; + goto out_qdio; } if ((rc = qeth_alloc_qdio_buffers(card))){ QETH_DBF_TEXT_(setup, 2, "5err%d", rc); - return rc; + goto out_qdio; } if ((rc = qeth_qdio_establish(card))){ QETH_DBF_TEXT_(setup, 2, "6err%d", rc); @@ -3795,12 +3788,16 @@ static inline int qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb, struct qeth_hdr **hdr, int ipv) { + int rc; #ifdef CONFIG_QETH_VLAN u16 *tag; #endif QETH_DBF_TEXT(trace, 6, "prepskb"); + rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr)); + if (rc) + return rc; #ifdef CONFIG_QETH_VLAN if (card->vlangrp && vlan_tx_tag_present(*skb) && ((ipv == 6) || card->options.layer2) ) { @@ -4251,7 +4248,8 @@ out: } static inline int -qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb) +qeth_get_elements_no(struct qeth_card *card, void *hdr, + struct sk_buff *skb, int elems) { int elements_needed = 0; @@ -4261,9 +4259,10 @@ qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb) if (elements_needed == 0 ) elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) + skb->len) >> PAGE_SHIFT); - if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){ + if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)){ PRINT_ERR("qeth_do_send_packet: invalid size of " - "IP packet. Discarded."); + "IP packet (Number=%d / Length=%d). Discarded.\n", + (elements_needed+elems), skb->len); return 0; } return elements_needed; @@ -4275,7 +4274,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) int ipv = 0; int cast_type; struct qeth_qdio_out_q *queue; - struct qeth_hdr *hdr; + struct qeth_hdr *hdr = NULL; int elements_needed = 0; enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; struct qeth_eddp_context *ctx = NULL; @@ -4337,9 +4336,11 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) return -EINVAL; } } else { - elements_needed += qeth_get_elements_no(card,(void*) hdr, skb); - if (!elements_needed) + int elems = qeth_get_elements_no(card,(void*) hdr, skb, + elements_needed); + if (!elems) return -EINVAL; + elements_needed += elems; } if (card->info.type != QETH_CARD_TYPE_IQD) @@ -4504,7 +4505,11 @@ qeth_arp_set_no_entries(struct qeth_card *card, int no_entries) QETH_DBF_TEXT(trace,3,"arpstnoe"); - /* TODO: really not supported by GuestLAN? */ + /* + * currently GuestLAN only supports the ARP assist function + * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_SET_NO_ENTRIES; + * thus we say EOPNOTSUPP for this ARP function + */ if (card->info.guestlan) return -EOPNOTSUPP; if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) { @@ -4681,14 +4686,6 @@ qeth_arp_query(struct qeth_card *card, char *udata) QETH_DBF_TEXT(trace,3,"arpquery"); - /* - * currently GuestLAN does only deliver all zeros on query arp, - * even though arp processing is supported (according to IPA supp. - * funcs flags); since all zeros is no valueable information, - * we say EOPNOTSUPP for all ARP functions - */ - /*if (card->info.guestlan) - return -EOPNOTSUPP; */ if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/ IPA_ARP_PROCESSING)) { PRINT_WARN("ARP processing not supported " @@ -4894,10 +4891,9 @@ qeth_arp_add_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry) QETH_DBF_TEXT(trace,3,"arpadent"); /* - * currently GuestLAN does only deliver all zeros on query arp, - * even though arp processing is supported (according to IPA supp. - * funcs flags); since all zeros is no valueable information, - * we say EOPNOTSUPP for all ARP functions + * currently GuestLAN only supports the ARP assist function + * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_ADD_ENTRY; + * thus we say EOPNOTSUPP for this ARP function */ if (card->info.guestlan) return -EOPNOTSUPP; @@ -4937,10 +4933,9 @@ qeth_arp_remove_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry QETH_DBF_TEXT(trace,3,"arprment"); /* - * currently GuestLAN does only deliver all zeros on query arp, - * even though arp processing is supported (according to IPA supp. - * funcs flags); since all zeros is no valueable information, - * we say EOPNOTSUPP for all ARP functions + * currently GuestLAN only supports the ARP assist function + * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_REMOVE_ENTRY; + * thus we say EOPNOTSUPP for this ARP function */ if (card->info.guestlan) return -EOPNOTSUPP; @@ -4978,11 +4973,10 @@ qeth_arp_flush_cache(struct qeth_card *card) QETH_DBF_TEXT(trace,3,"arpflush"); /* - * currently GuestLAN does only deliver all zeros on query arp, - * even though arp processing is supported (according to IPA supp. - * funcs flags); since all zeros is no valueable information, - * we say EOPNOTSUPP for all ARP functions - */ + * currently GuestLAN only supports the ARP assist function + * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_FLUSH_CACHE; + * thus we say EOPNOTSUPP for this ARP function + */ if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD)) return -EOPNOTSUPP; if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) { @@ -7038,14 +7032,16 @@ qeth_setrouting_v6(struct qeth_card *card) } int -qeth_set_large_send(struct qeth_card *card) +qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type) { int rc = 0; - if (card->dev == NULL) + if (card->dev == NULL) { + card->options.large_send = type; return 0; - + } netif_stop_queue(card->dev); + card->options.large_send = type; switch (card->options.large_send) { case QETH_LARGE_SEND_EDDP: card->dev->features |= NETIF_F_TSO | NETIF_F_SG; @@ -7066,7 +7062,6 @@ qeth_set_large_send(struct qeth_card *card) card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG); break; } - netif_wake_queue(card->dev); return rc; } @@ -8257,7 +8252,6 @@ qeth_init(void) { int rc=0; - qeth_eyecatcher(); PRINT_INFO("loading %s (%s/%s/%s/%s/%s/%s/%s %s %s)\n", version, VERSION_QETH_C, VERSION_QETH_H, VERSION_QETH_MPC_H, VERSION_QETH_MPC_C, @@ -8338,7 +8332,6 @@ again: printk("qeth: removed\n"); } -EXPORT_SYMBOL(qeth_eyecatcher); module_init(qeth_init); module_exit(qeth_exit); MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>"); diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c index 98bedb0cb387..dda105b73063 100644 --- a/drivers/s390/net/qeth_sys.c +++ b/drivers/s390/net/qeth_sys.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.51 $) + * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.54 $) * * Linux on zSeries OSA Express and HiperSockets support * This file contains code related to sysfs. @@ -20,7 +20,7 @@ #include "qeth_mpc.h" #include "qeth_fs.h" -const char *VERSION_QETH_SYS_C = "$Revision: 1.51 $"; +const char *VERSION_QETH_SYS_C = "$Revision: 1.54 $"; /*****************************************************************************/ /* */ @@ -722,10 +722,13 @@ qeth_dev_layer2_store(struct device *dev, struct device_attribute *attr, const c if (!card) return -EINVAL; + if (card->info.type == QETH_CARD_TYPE_IQD) { + PRINT_WARN("Layer2 on Hipersockets is not supported! \n"); + return -EPERM; + } if (((card->state != CARD_STATE_DOWN) && - (card->state != CARD_STATE_RECOVER)) || - (card->info.type != QETH_CARD_TYPE_OSAE)) + (card->state != CARD_STATE_RECOVER))) return -EPERM; i = simple_strtoul(buf, &tmp, 16); @@ -771,9 +774,7 @@ qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, con if (!card) return -EINVAL; - tmp = strsep((char **) &buf, "\n"); - if (!strcmp(tmp, "no")){ type = QETH_LARGE_SEND_NO; } else if (!strcmp(tmp, "EDDP")) { @@ -786,10 +787,8 @@ qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, con } if (card->options.large_send == type) return count; - card->options.large_send = type; - if ((rc = qeth_set_large_send(card))) + if ((rc = qeth_set_large_send(card, type))) return rc; - return count; } diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 5cc53cd9323e..d92273cbe0de 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2465,9 +2465,12 @@ static unsigned long ata_pio_poll(struct ata_port *ap) * * LOCKING: * None. (executing in kernel thread context) + * + * RETURNS: + * Non-zero if qc completed, zero otherwise. */ -static void ata_pio_complete (struct ata_port *ap) +static int ata_pio_complete (struct ata_port *ap) { struct ata_queued_cmd *qc; u8 drv_stat; @@ -2486,14 +2489,14 @@ static void ata_pio_complete (struct ata_port *ap) if (drv_stat & (ATA_BUSY | ATA_DRQ)) { ap->pio_task_state = PIO_ST_LAST_POLL; ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO; - return; + return 0; } } drv_stat = ata_wait_idle(ap); if (!ata_ok(drv_stat)) { ap->pio_task_state = PIO_ST_ERR; - return; + return 0; } qc = ata_qc_from_tag(ap, ap->active_tag); @@ -2502,6 +2505,10 @@ static void ata_pio_complete (struct ata_port *ap) ap->pio_task_state = PIO_ST_IDLE; ata_poll_qc_complete(qc, drv_stat); + + /* another command may start at this point */ + + return 1; } @@ -2709,7 +2716,7 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes) next_sg: if (unlikely(qc->cursg >= qc->n_elem)) { - /* + /* * The end of qc->sg is reached and the device expects * more data to transfer. In order not to overrun qc->sg * and fulfill length specified in the byte count register, @@ -2721,7 +2728,7 @@ next_sg: unsigned int i; if (words) /* warning if bytes > 1 */ - printk(KERN_WARNING "ata%u: %u bytes trailing data\n", + printk(KERN_WARNING "ata%u: %u bytes trailing data\n", ap->id, bytes); for (i = 0; i < words; i++) @@ -2849,9 +2856,7 @@ static void ata_pio_block(struct ata_port *ap) if (is_atapi_taskfile(&qc->tf)) { /* no more data to transfer or unsupported ATAPI command */ if ((status & ATA_DRQ) == 0) { - ap->pio_task_state = PIO_ST_IDLE; - - ata_poll_qc_complete(qc, status); + ap->pio_task_state = PIO_ST_LAST; return; } @@ -2887,7 +2892,12 @@ static void ata_pio_error(struct ata_port *ap) static void ata_pio_task(void *_data) { struct ata_port *ap = _data; - unsigned long timeout = 0; + unsigned long timeout; + int qc_completed; + +fsm_start: + timeout = 0; + qc_completed = 0; switch (ap->pio_task_state) { case PIO_ST_IDLE: @@ -2898,7 +2908,7 @@ static void ata_pio_task(void *_data) break; case PIO_ST_LAST: - ata_pio_complete(ap); + qc_completed = ata_pio_complete(ap); break; case PIO_ST_POLL: @@ -2913,10 +2923,9 @@ static void ata_pio_task(void *_data) } if (timeout) - queue_delayed_work(ata_wq, &ap->pio_task, - timeout); - else - queue_work(ata_wq, &ap->pio_task); + queue_delayed_work(ata_wq, &ap->pio_task, timeout); + else if (!qc_completed) + goto fsm_start; } static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev, diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 3e9b64137873..23d095d3817b 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -201,6 +201,7 @@ int qla2100_pci_config(scsi_qla_host_t *ha) { uint16_t w, mwi; + uint32_t d; unsigned long flags; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; @@ -215,9 +216,9 @@ qla2100_pci_config(scsi_qla_host_t *ha) pci_write_config_word(ha->pdev, PCI_COMMAND, w); /* Reset expansion ROM address decode enable */ - pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w); - w &= ~PCI_ROM_ADDRESS_ENABLE; - pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w); + pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); + d &= ~PCI_ROM_ADDRESS_ENABLE; + pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); /* Get PCI bus information. */ spin_lock_irqsave(&ha->hardware_lock, flags); @@ -237,6 +238,7 @@ int qla2300_pci_config(scsi_qla_host_t *ha) { uint16_t w, mwi; + uint32_t d; unsigned long flags = 0; uint32_t cnt; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; @@ -302,9 +304,9 @@ qla2300_pci_config(scsi_qla_host_t *ha) pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80); /* Reset expansion ROM address decode enable */ - pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w); - w &= ~PCI_ROM_ADDRESS_ENABLE; - pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w); + pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); + d &= ~PCI_ROM_ADDRESS_ENABLE; + pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); /* Get PCI bus information. */ spin_lock_irqsave(&ha->hardware_lock, flags); @@ -324,6 +326,7 @@ int qla24xx_pci_config(scsi_qla_host_t *ha) { uint16_t w, mwi; + uint32_t d; unsigned long flags = 0; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; int pcix_cmd_reg, pcie_dctl_reg; @@ -366,9 +369,9 @@ qla24xx_pci_config(scsi_qla_host_t *ha) } /* Reset expansion ROM address decode enable */ - pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w); - w &= ~PCI_ROM_ADDRESS_ENABLE; - pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w); + pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); + d &= ~PCI_ROM_ADDRESS_ENABLE; + pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); /* Get PCI bus information. */ spin_lock_irqsave(&ha->hardware_lock, flags); diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index a3cd0ee8486d..0585ab27ffde 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -781,7 +781,7 @@ mpc52xx_uart_remove(struct device *dev) #ifdef CONFIG_PM static int -mpc52xx_uart_suspend(struct device *dev, u32 state, u32 level) +mpc52xx_uart_suspend(struct device *dev, pm_message_t state, u32 level) { struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev); diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c index a32817678552..630f2dfa9699 100644 --- a/drivers/video/backlight/corgi_bl.c +++ b/drivers/video/backlight/corgi_bl.c @@ -19,17 +19,18 @@ #include <linux/fb.h> #include <linux/backlight.h> -#include <asm/arch-pxa/corgi.h> -#include <asm/hardware/scoop.h> +#include <asm/mach-types.h> +#include <asm/arch/sharpsl.h> -#define CORGI_MAX_INTENSITY 0x3e #define CORGI_DEFAULT_INTENSITY 0x1f -#define CORGI_LIMIT_MASK 0x0b +#define CORGI_LIMIT_MASK 0x0b static int corgibl_powermode = FB_BLANK_UNBLANK; static int current_intensity = 0; static int corgibl_limit = 0; +static void (*corgibl_mach_set_intensity)(int intensity); static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED; +static struct backlight_properties corgibl_data; static void corgibl_send_intensity(int intensity) { diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index cabd53cec991..6c2244cf0e74 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -425,7 +425,7 @@ static void imxfb_setup_gpio(struct imxfb_info *fbi) * Power management hooks. Note that we won't be called from IRQ context, * unlike the blank functions above, so we may sleep. */ -static int imxfb_suspend(struct device *dev, u32 state, u32 level) +static int imxfb_suspend(struct device *dev, pm_message_t state, u32 level) { struct imxfb_info *fbi = dev_get_drvdata(dev); pr_debug("%s\n",__FUNCTION__); @@ -562,6 +562,7 @@ static inline void lock_kiocb(struct kiocb *iocb) static inline void unlock_kiocb(struct kiocb *iocb) { kiocbClearLocked(iocb); + smp_mb__after_clear_bit(); wake_up_bit(&iocb->ki_flags, KIF_LOCKED); } diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 6ab1dd0ca904..403b90a1213d 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -231,8 +231,9 @@ struct ep_pqueue { static void ep_poll_safewake_init(struct poll_safewake *psw); static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq); -static int ep_getfd(int *efd, struct inode **einode, struct file **efile); -static int ep_file_init(struct file *file); +static int ep_getfd(int *efd, struct inode **einode, struct file **efile, + struct eventpoll *ep); +static int ep_alloc(struct eventpoll **pep); static void ep_free(struct eventpoll *ep); static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd); static void ep_use_epitem(struct epitem *epi); @@ -501,38 +502,37 @@ void eventpoll_release_file(struct file *file) asmlinkage long sys_epoll_create(int size) { int error, fd; + struct eventpoll *ep; struct inode *inode; struct file *file; DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d)\n", current, size)); - /* Sanity check on the size parameter */ + /* + * Sanity check on the size parameter, and create the internal data + * structure ( "struct eventpoll" ). + */ error = -EINVAL; - if (size <= 0) + if (size <= 0 || (error = ep_alloc(&ep)) != 0) goto eexit_1; /* * Creates all the items needed to setup an eventpoll file. That is, * a file structure, and inode and a free file descriptor. */ - error = ep_getfd(&fd, &inode, &file); - if (error) - goto eexit_1; - - /* Setup the file internal data structure ( "struct eventpoll" ) */ - error = ep_file_init(file); + error = ep_getfd(&fd, &inode, &file, ep); if (error) goto eexit_2; - DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n", current, size, fd)); return fd; eexit_2: - sys_close(fd); + ep_free(ep); + kfree(ep); eexit_1: DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n", current, size, error)); @@ -706,7 +706,8 @@ eexit_1: /* * Creates the file descriptor to be used by the epoll interface. */ -static int ep_getfd(int *efd, struct inode **einode, struct file **efile) +static int ep_getfd(int *efd, struct inode **einode, struct file **efile, + struct eventpoll *ep) { struct qstr this; char name[32]; @@ -756,7 +757,7 @@ static int ep_getfd(int *efd, struct inode **einode, struct file **efile) file->f_op = &eventpoll_fops; file->f_mode = FMODE_READ; file->f_version = 0; - file->private_data = NULL; + file->private_data = ep; /* Install the new setup file into the allocated fd. */ fd_install(fd, file); @@ -777,14 +778,13 @@ eexit_1: } -static int ep_file_init(struct file *file) +static int ep_alloc(struct eventpoll **pep) { - struct eventpoll *ep; + struct eventpoll *ep = kzalloc(sizeof(*ep), GFP_KERNEL); - if (!(ep = kmalloc(sizeof(struct eventpoll), GFP_KERNEL))) + if (!ep) return -ENOMEM; - memset(ep, 0, sizeof(*ep)); rwlock_init(&ep->lock); init_rwsem(&ep->sem); init_waitqueue_head(&ep->wq); @@ -792,9 +792,9 @@ static int ep_file_init(struct file *file) INIT_LIST_HEAD(&ep->rdllist); ep->rbr = RB_ROOT; - file->private_data = ep; + *pep = ep; - DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_file_init() ep=%p\n", + DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_alloc() ep=%p\n", current, ep)); return 0; } diff --git a/fs/fat/file.c b/fs/fat/file.c index 62ffa9139400..7134403d5be2 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -12,39 +12,6 @@ #include <linux/smp_lock.h> #include <linux/buffer_head.h> -static ssize_t fat_file_aio_write(struct kiocb *iocb, const char __user *buf, - size_t count, loff_t pos) -{ - struct inode *inode = iocb->ki_filp->f_dentry->d_inode; - int retval; - - retval = generic_file_aio_write(iocb, buf, count, pos); - if (retval > 0) { - inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; - MSDOS_I(inode)->i_attrs |= ATTR_ARCH; - mark_inode_dirty(inode); -// check the locking rules -// if (IS_SYNC(inode)) -// fat_sync_inode(inode); - } - return retval; -} - -static ssize_t fat_file_writev(struct file *filp, const struct iovec *iov, - unsigned long nr_segs, loff_t *ppos) -{ - struct inode *inode = filp->f_dentry->d_inode; - int retval; - - retval = generic_file_writev(filp, iov, nr_segs, ppos); - if (retval > 0) { - inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; - MSDOS_I(inode)->i_attrs |= ATTR_ARCH; - mark_inode_dirty(inode); - } - return retval; -} - int fat_generic_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { @@ -148,9 +115,9 @@ struct file_operations fat_file_operations = { .read = do_sync_read, .write = do_sync_write, .readv = generic_file_readv, - .writev = fat_file_writev, + .writev = generic_file_writev, .aio_read = generic_file_aio_read, - .aio_write = fat_file_aio_write, + .aio_write = generic_file_aio_write, .mmap = generic_file_mmap, .ioctl = fat_generic_ioctl, .fsync = file_fsync, diff --git a/fs/fat/inode.c b/fs/fat/inode.c index a7cbe68e2259..51b1d15d9d5c 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -102,6 +102,19 @@ static int fat_prepare_write(struct file *file, struct page *page, &MSDOS_I(page->mapping->host)->mmu_private); } +static int fat_commit_write(struct file *file, struct page *page, + unsigned from, unsigned to) +{ + struct inode *inode = page->mapping->host; + int err = generic_commit_write(file, page, from, to); + if (!err && !(MSDOS_I(inode)->i_attrs & ATTR_ARCH)) { + inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; + MSDOS_I(inode)->i_attrs |= ATTR_ARCH; + mark_inode_dirty(inode); + } + return err; +} + static sector_t _fat_bmap(struct address_space *mapping, sector_t block) { return generic_block_bmap(mapping, block, fat_get_block); @@ -112,7 +125,7 @@ static struct address_space_operations fat_aops = { .writepage = fat_writepage, .sync_page = block_sync_page, .prepare_write = fat_prepare_write, - .commit_write = generic_commit_write, + .commit_write = fat_commit_write, .bmap = _fat_bmap }; diff --git a/fs/locks.c b/fs/locks.c index c2c09b4798d6..f7daa5f48949 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -124,6 +124,7 @@ #include <linux/smp_lock.h> #include <linux/syscalls.h> #include <linux/time.h> +#include <linux/rcupdate.h> #include <asm/semaphore.h> #include <asm/uaccess.h> @@ -2205,6 +2206,7 @@ void steal_locks(fl_owner_t from) lock_kernel(); j = 0; + rcu_read_lock(); fdt = files_fdtable(files); for (;;) { unsigned long set; @@ -2222,6 +2224,7 @@ void steal_locks(fl_owner_t from) set >>= 1; } } + rcu_read_unlock(); unlock_kernel(); } EXPORT_SYMBOL(steal_locks); diff --git a/fs/proc/array.c b/fs/proc/array.c index d88d518d30f6..d84eecacbeaf 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -74,6 +74,7 @@ #include <linux/file.h> #include <linux/times.h> #include <linux/cpuset.h> +#include <linux/rcupdate.h> #include <asm/uaccess.h> #include <asm/pgtable.h> @@ -180,12 +181,14 @@ static inline char * task_state(struct task_struct *p, char *buffer) p->gid, p->egid, p->sgid, p->fsgid); read_unlock(&tasklist_lock); task_lock(p); + rcu_read_lock(); if (p->files) fdt = files_fdtable(p->files); buffer += sprintf(buffer, "FDSize:\t%d\n" "Groups:\t", fdt ? fdt->max_fds : 0); + rcu_read_unlock(); group_info = p->group_info; get_group_info(group_info); diff --git a/include/asm-arm/arch-aaec2000/memory.h b/include/asm-arm/arch-aaec2000/memory.h index 681b6a6171a1..79c90813bc3e 100644 --- a/include/asm-arm/arch-aaec2000/memory.h +++ b/include/asm-arm/arch-aaec2000/memory.h @@ -64,10 +64,6 @@ #define NODE_MAX_MEM_SHIFT 26 #define NODE_MAX_MEM_SIZE (1 << NODE_MAX_MEM_SHIFT) -#else - -#define PFN_TO_NID(addr) (0) - #endif /* CONFIG_DISCONTIGMEM */ #endif /* __ASM_ARCH_MEMORY_H */ diff --git a/include/asm-arm/arch-iop3xx/memory.h b/include/asm-arm/arch-iop3xx/memory.h index dc4735cb0c10..45351f5cd904 100644 --- a/include/asm-arm/arch-iop3xx/memory.h +++ b/include/asm-arm/arch-iop3xx/memory.h @@ -36,6 +36,4 @@ #endif -#define PFN_TO_NID(addr) (0) - #endif diff --git a/include/asm-arm/arch-ixp2000/ixp2000-regs.h b/include/asm-arm/arch-ixp2000/ixp2000-regs.h index 75623f81ef75..32aece069869 100644 --- a/include/asm-arm/arch-ixp2000/ixp2000-regs.h +++ b/include/asm-arm/arch-ixp2000/ixp2000-regs.h @@ -370,8 +370,6 @@ #define GLOBAL_REG_BASE (IXP2000_GLOBAL_REG_VIRT_BASE + 0x0a00) #define GLOBAL_REG(x) (volatile unsigned long*)(GLOBAL_REG_BASE | (x)) -#define IXP2000_PROD_ID GLOBAL_REG(0x00) - #define IXP2000_MAJ_PROD_TYPE_MASK 0x001F0000 #define IXP2000_MAJ_PROD_TYPE_IXP2000 0x00000000 #define IXP2000_MIN_PROD_TYPE_MASK 0x0000FF00 diff --git a/include/asm-arm/arch-ixp2000/platform.h b/include/asm-arm/arch-ixp2000/platform.h index c0caf3e3e6fd..abdcf51bd283 100644 --- a/include/asm-arm/arch-ixp2000/platform.h +++ b/include/asm-arm/arch-ixp2000/platform.h @@ -31,20 +31,24 @@ #include <asm/system.h> /* Pickup local_irq_ functions */ -static inline void ixp2000_reg_write(volatile unsigned long *reg, unsigned long val) +static inline void ixp2000_reg_write(volatile void *reg, unsigned long val) { - volatile unsigned long dummy; + unsigned long dummy; unsigned long flags; local_irq_save(flags); - *reg = val; + *((volatile unsigned long *)reg) = val; barrier(); - dummy = *reg; + dummy = *((volatile unsigned long *)reg); local_irq_restore(flags); } #else -#define ixp2000_reg_write(reg, val) (*reg = val) +static inline void ixp2000_reg_write(volatile void *reg, unsigned long val) +{ + *((volatile unsigned long *)reg) = val; +} #endif /* IXDP2400 || IXDP2401 */ +#define ixp2000_reg_read(reg) (*((volatile unsigned long *)reg)) /* * Boards may multiplex different devices on the 2nd channel of @@ -84,7 +88,7 @@ void ixp2000_release_slowport(struct slowport_cfg *); */ static inline unsigned ixp2000_has_broken_slowport(void) { - unsigned long id = *IXP2000_PROD_ID; + unsigned long id = *IXP2000_PRODUCT_ID; unsigned long id_prod = id & (IXP2000_MAJ_PROD_TYPE_MASK | IXP2000_MIN_PROD_TYPE_MASK); return (((id_prod == diff --git a/include/asm-arm/arch-lh7a40x/memory.h b/include/asm-arm/arch-lh7a40x/memory.h index 7e2fea372663..c650e6feb9d5 100644 --- a/include/asm-arm/arch-lh7a40x/memory.h +++ b/include/asm-arm/arch-lh7a40x/memory.h @@ -85,10 +85,6 @@ (((unsigned long)(addr) & 0x01ffffff) >> PAGE_SHIFT) # endif -#else - -# define PFN_TO_NID(addr) (0) - #endif #endif diff --git a/include/asm-arm/arch-omap/memory.h b/include/asm-arm/arch-omap/memory.h index 84f81e315a25..ef32d61eec7a 100644 --- a/include/asm-arm/arch-omap/memory.h +++ b/include/asm-arm/arch-omap/memory.h @@ -86,6 +86,5 @@ #endif /* CONFIG_ARCH_OMAP1510 */ -#define PHYS_TO_NID(addr) (0) #endif diff --git a/include/asm-arm/arch-pxa/memory.h b/include/asm-arm/arch-pxa/memory.h index 217a80b820ff..58bad9748b5c 100644 --- a/include/asm-arm/arch-pxa/memory.h +++ b/include/asm-arm/arch-pxa/memory.h @@ -67,10 +67,6 @@ #define LOCAL_MAP_NR(addr) \ (((unsigned long)(addr) & 0x03ffffff) >> PAGE_SHIFT) -#else - -#define PFN_TO_NID(addr) (0) - #endif #endif diff --git a/include/asm-arm/arch-pxa/poodle.h b/include/asm-arm/arch-pxa/poodle.h index 58bda9d571a5..6b5ac5144e70 100644 --- a/include/asm-arm/arch-pxa/poodle.h +++ b/include/asm-arm/arch-pxa/poodle.h @@ -37,24 +37,25 @@ #define POODLE_GPIO_nSD_DETECT (9) #define POODLE_GPIO_MAIN_BAT_LOW (13) #define POODLE_GPIO_BAT_COVER (13) +#define POODLE_GPIO_USB_PULLUP (20) #define POODLE_GPIO_ADC_TEMP_ON (21) #define POODLE_GPIO_BYPASS_ON (36) #define POODLE_GPIO_CHRG_ON (38) #define POODLE_GPIO_CHRG_FULL (16) /* PXA GPIOs */ -#define POODLE_IRQ_GPIO_ON_KEY IRQ_GPIO0 -#define POODLE_IRQ_GPIO_AC_IN IRQ_GPIO1 -#define POODLE_IRQ_GPIO_HP_IN IRQ_GPIO4 -#define POODLE_IRQ_GPIO_CO IRQ_GPIO16 -#define POODLE_IRQ_GPIO_TP_INT IRQ_GPIO5 -#define POODLE_IRQ_GPIO_WAKEUP IRQ_GPIO11 -#define POODLE_IRQ_GPIO_GA_INT IRQ_GPIO10 -#define POODLE_IRQ_GPIO_CF_IRQ IRQ_GPIO17 -#define POODLE_IRQ_GPIO_CF_CD IRQ_GPIO14 -#define POODLE_IRQ_GPIO_nSD_INT IRQ_GPIO8 -#define POODLE_IRQ_GPIO_nSD_DETECT IRQ_GPIO9 -#define POODLE_IRQ_GPIO_MAIN_BAT_LOW IRQ_GPIO13 +#define POODLE_IRQ_GPIO_ON_KEY IRQ_GPIO(0) +#define POODLE_IRQ_GPIO_AC_IN IRQ_GPIO(1) +#define POODLE_IRQ_GPIO_HP_IN IRQ_GPIO(4) +#define POODLE_IRQ_GPIO_CO IRQ_GPIO(16) +#define POODLE_IRQ_GPIO_TP_INT IRQ_GPIO(5) +#define POODLE_IRQ_GPIO_WAKEUP IRQ_GPIO(11) +#define POODLE_IRQ_GPIO_GA_INT IRQ_GPIO(10) +#define POODLE_IRQ_GPIO_CF_IRQ IRQ_GPIO(17) +#define POODLE_IRQ_GPIO_CF_CD IRQ_GPIO(14) +#define POODLE_IRQ_GPIO_nSD_INT IRQ_GPIO(8) +#define POODLE_IRQ_GPIO_nSD_DETECT IRQ_GPIO(9) +#define POODLE_IRQ_GPIO_MAIN_BAT_LOW IRQ_GPIO(13) /* SCOOP GPIOs */ #define POODLE_SCOOP_CHARGE_ON SCOOP_GPCR_PA11 diff --git a/include/asm-arm/arch-sa1100/memory.h b/include/asm-arm/arch-sa1100/memory.h index 32d3d5bde34d..8743ff5c1b23 100644 --- a/include/asm-arm/arch-sa1100/memory.h +++ b/include/asm-arm/arch-sa1100/memory.h @@ -99,10 +99,6 @@ __arch_adjust_zones(int node, unsigned long *size, unsigned long *holes) #define LOCAL_MAP_NR(addr) \ (((unsigned long)(addr) & 0x07ffffff) >> PAGE_SHIFT) -#else - -#define PFN_TO_NID(addr) (0) - #endif #endif diff --git a/include/asm-arm/futex.h b/include/asm-arm/futex.h index 2cac5ecd9d00..9feff4ce1424 100644 --- a/include/asm-arm/futex.h +++ b/include/asm-arm/futex.h @@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) int cmp = (encoded_op >> 24) & 15; int oparg = (encoded_op << 8) >> 20; int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret, tem; + int oldval = 0, ret; if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) oparg = 1 << oparg; diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h index e47bea7d1723..a8a933a775db 100644 --- a/include/asm-arm/memory.h +++ b/include/asm-arm/memory.h @@ -160,12 +160,25 @@ static inline __deprecated void *bus_to_virt(unsigned long x) #define page_to_pfn(page) \ (( (page) - page_zone(page)->zone_mem_map) \ + page_zone(page)->zone_start_pfn) + #define pfn_to_page(pfn) \ (PFN_TO_MAPBASE(pfn) + LOCAL_MAP_NR((pfn) << PAGE_SHIFT)) -#define pfn_valid(pfn) (PFN_TO_NID(pfn) < MAX_NUMNODES) + +#define pfn_valid(pfn) \ + ({ \ + unsigned int nid = PFN_TO_NID(pfn); \ + int valid = nid < MAX_NUMNODES; \ + if (valid) { \ + pg_data_t *node = NODE_DATA(nid); \ + valid = (pfn - node->node_start_pfn) < \ + node->node_spanned_pages; \ + } \ + valid; \ + }) #define virt_to_page(kaddr) \ (ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr)) + #define virt_addr_valid(kaddr) (KVADDR_TO_NID(kaddr) < MAX_NUMNODES) /* diff --git a/include/asm-ppc/irq.h b/include/asm-ppc/irq.h index 55752474d0d9..bd9674807f05 100644 --- a/include/asm-ppc/irq.h +++ b/include/asm-ppc/irq.h @@ -138,6 +138,16 @@ irq_canonicalize(int irq) #define SIU_IRQ7 (14) #define SIU_LEVEL7 (15) +#define MPC8xx_INT_FEC1 SIU_LEVEL1 +#define MPC8xx_INT_FEC2 SIU_LEVEL3 + +#define MPC8xx_INT_SCC1 (CPM_IRQ_OFFSET + CPMVEC_SCC1) +#define MPC8xx_INT_SCC2 (CPM_IRQ_OFFSET + CPMVEC_SCC2) +#define MPC8xx_INT_SCC3 (CPM_IRQ_OFFSET + CPMVEC_SCC3) +#define MPC8xx_INT_SCC4 (CPM_IRQ_OFFSET + CPMVEC_SCC4) +#define MPC8xx_INT_SMC1 (CPM_IRQ_OFFSET + CPMVEC_SMC1) +#define MPC8xx_INT_SMC2 (CPM_IRQ_OFFSET + CPMVEC_SMC2) + /* The internal interrupts we can configure as we see fit. * My personal preference is CPM at level 2, which puts it above the * MBX PCI/ISA/IDE interrupts. diff --git a/include/asm-ppc/mpc8xx.h b/include/asm-ppc/mpc8xx.h index dc8e59896050..208a2e11daee 100644 --- a/include/asm-ppc/mpc8xx.h +++ b/include/asm-ppc/mpc8xx.h @@ -97,6 +97,22 @@ extern unsigned char __res[]; struct pt_regs; +enum ppc_sys_devices { + MPC8xx_CPM_FEC1, + MPC8xx_CPM_FEC2, + MPC8xx_CPM_I2C, + MPC8xx_CPM_SCC1, + MPC8xx_CPM_SCC2, + MPC8xx_CPM_SCC3, + MPC8xx_CPM_SCC4, + MPC8xx_CPM_SPI, + MPC8xx_CPM_MCC1, + MPC8xx_CPM_MCC2, + MPC8xx_CPM_SMC1, + MPC8xx_CPM_SMC2, + MPC8xx_CPM_USB, +}; + #endif /* !__ASSEMBLY__ */ #endif /* CONFIG_8xx */ #endif /* __CONFIG_8xx_DEFS */ diff --git a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h index 048f7c8596ee..549f44843c5e 100644 --- a/include/asm-ppc/ppc_sys.h +++ b/include/asm-ppc/ppc_sys.h @@ -27,6 +27,8 @@ #include <asm/mpc83xx.h> #elif defined(CONFIG_85xx) #include <asm/mpc85xx.h> +#elif defined(CONFIG_8xx) +#include <asm/mpc8xx.h> #elif defined(CONFIG_PPC_MPC52xx) #include <asm/mpc52xx.h> #elif defined(CONFIG_MPC10X_BRIDGE) diff --git a/include/asm-um/processor-generic.h b/include/asm-um/processor-generic.h index b2fc94fbc2d9..2d242360c3d6 100644 --- a/include/asm-um/processor-generic.h +++ b/include/asm-um/processor-generic.h @@ -21,6 +21,7 @@ struct thread_struct { * copy_thread) to mark that we are begin called from userspace (fork / * vfork / clone), and reset to 0 after. It is left to 0 when called * from kernelspace (i.e. kernel_thread() or fork_idle(), as of 2.6.11). */ + struct task_struct *saved_task; int forking; int nsyscalls; struct pt_regs regs; diff --git a/include/asm-um/system-i386.h b/include/asm-um/system-i386.h index ea8381de3cc9..c436263e67ba 100644 --- a/include/asm-um/system-i386.h +++ b/include/asm-um/system-i386.h @@ -3,6 +3,4 @@ #include "asm/system-generic.h" -#define __HAVE_ARCH_CMPXCHG 1 - #endif diff --git a/include/asm-x86_64/desc.h b/include/asm-x86_64/desc.h index 594e610f4a1e..68ac3c62fe3d 100644 --- a/include/asm-x86_64/desc.h +++ b/include/asm-x86_64/desc.h @@ -8,6 +8,8 @@ #ifndef __ASSEMBLY__ #include <linux/string.h> +#include <linux/smp.h> + #include <asm/segment.h> #include <asm/mmu.h> diff --git a/include/linux/dccp.h b/include/linux/dccp.h index 8bf4bacb5051..71fab4311e92 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -4,16 +4,6 @@ #include <linux/types.h> #include <asm/byteorder.h> -/* Structure describing an Internet (DCCP) socket address. */ -struct sockaddr_dccp { - __u16 sdccp_family; /* Address family */ - __u16 sdccp_port; /* Port number */ - __u32 sdccp_addr; /* Internet address */ - __u32 sdccp_service; /* Service */ - /* Pad to size of `struct sockaddr': 16 bytes . */ - __u32 sdccp_pad; -}; - /** * struct dccp_hdr - generic part of DCCP packet header * @@ -188,6 +178,11 @@ enum { /* DCCP socket options */ #define DCCP_SOCKOPT_PACKET_SIZE 1 +#define DCCP_SOCKOPT_SERVICE 2 +#define DCCP_SOCKOPT_CCID_RX_INFO 128 +#define DCCP_SOCKOPT_CCID_TX_INFO 192 + +#define DCCP_SERVICE_LIST_MAX_LEN 32 #ifdef __KERNEL__ @@ -337,7 +332,8 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb) */ struct dccp_options { __u64 dccpo_sequence_window; - __u8 dccpo_ccid; + __u8 dccpo_rx_ccid; + __u8 dccpo_tx_ccid; __u8 dccpo_send_ack_vector; __u8 dccpo_send_ndp_count; }; @@ -360,14 +356,8 @@ static inline struct dccp_request_sock *dccp_rsk(const struct request_sock *req) extern struct inet_timewait_death_row dccp_death_row; -/* Read about the ECN nonce to see why it is 253 */ -#define DCCP_MAX_ACK_VECTOR_LEN 253 - struct dccp_options_received { - u32 dccpor_ndp:24, - dccpor_ack_vector_len:8; - u32 dccpor_ack_vector_idx:10; - /* 22 bits hole, try to pack */ + u32 dccpor_ndp; /* only 24 bits */ u32 dccpor_timestamp; u32 dccpor_timestamp_echo; u32 dccpor_elapsed_time; @@ -382,6 +372,27 @@ enum dccp_role { DCCP_ROLE_SERVER, }; +struct dccp_service_list { + __u32 dccpsl_nr; + __u32 dccpsl_list[0]; +}; + +#define DCCP_SERVICE_INVALID_VALUE htonl((__u32)-1) + +static inline int dccp_list_has_service(const struct dccp_service_list *sl, + const u32 service) +{ + if (likely(sl != NULL)) { + u32 i = sl->dccpsl_nr; + while (i--) + if (sl->dccpsl_list[i] == service) + return 1; + } + return 0; +} + +struct dccp_ackvec; + /** * struct dccp_sock - DCCP socket state * @@ -402,7 +413,7 @@ enum dccp_role { * @dccps_packet_size - Set thru setsockopt * @dccps_role - Role of this sock, one of %dccp_role * @dccps_ndp_count - number of Non Data Packets since last data packet - * @dccps_hc_rx_ackpkts - receiver half connection acked packets + * @dccps_hc_rx_ackvec - rx half connection ack vector */ struct dccp_sock { /* inet_connection_sock has to be the first member of dccp_sock */ @@ -417,7 +428,8 @@ struct dccp_sock { __u64 dccps_gss; __u64 dccps_gsr; __u64 dccps_gar; - unsigned long dccps_service; + __u32 dccps_service; + struct dccp_service_list *dccps_service_list; struct timeval dccps_timestamp_time; __u32 dccps_timestamp_echo; __u32 dccps_packet_size; @@ -426,7 +438,7 @@ struct dccp_sock { __u32 dccps_pmtu_cookie; __u32 dccps_mss_cache; struct dccp_options dccps_options; - struct dccp_ackpkts *dccps_hc_rx_ackpkts; + struct dccp_ackvec *dccps_hc_rx_ackvec; void *dccps_hc_rx_ccid_private; void *dccps_hc_tx_ccid_private; struct ccid *dccps_hc_rx_ccid; @@ -443,6 +455,11 @@ static inline struct dccp_sock *dccp_sk(const struct sock *sk) return (struct dccp_sock *)sk; } +static inline int dccp_service_not_initialized(const struct sock *sk) +{ + return dccp_sk(sk)->dccps_service == DCCP_SERVICE_INVALID_VALUE; +} + static inline const char *dccp_role(const struct sock *sk) { switch (dccp_sk(sk)->dccps_role) { diff --git a/include/linux/i2c.h b/include/linux/i2c.h index be35332b67e6..3d49a305bf88 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -230,11 +230,6 @@ struct i2c_adapter { struct device dev; /* the adapter device */ struct class_device class_dev; /* the class device */ -#ifdef CONFIG_PROC_FS - /* No need to set this when you initialize the adapter */ - int inode; -#endif /* def CONFIG_PROC_FS */ - int nr; struct list_head clients; struct list_head list; diff --git a/include/linux/joystick.h b/include/linux/joystick.h index 06b9af77eb7f..5fd20ddd7ae3 100644 --- a/include/linux/joystick.h +++ b/include/linux/joystick.h @@ -111,29 +111,30 @@ struct js_corr { #define JS_SET_ALL 8 struct JS_DATA_TYPE { - __s32 buttons; - __s32 x; - __s32 y; + int32_t buttons; + int32_t x; + int32_t y; }; struct JS_DATA_SAVE_TYPE_32 { - __s32 JS_TIMEOUT; - __s32 BUSY; - __s32 JS_EXPIRETIME; - __s32 JS_TIMELIMIT; + int32_t JS_TIMEOUT; + int32_t BUSY; + int32_t JS_EXPIRETIME; + int32_t JS_TIMELIMIT; struct JS_DATA_TYPE JS_SAVE; struct JS_DATA_TYPE JS_CORR; }; struct JS_DATA_SAVE_TYPE_64 { - __s32 JS_TIMEOUT; - __s32 BUSY; - __s64 JS_EXPIRETIME; - __s64 JS_TIMELIMIT; + int32_t JS_TIMEOUT; + int32_t BUSY; + int64_t JS_EXPIRETIME; + int64_t JS_TIMELIMIT; struct JS_DATA_TYPE JS_SAVE; struct JS_DATA_TYPE JS_CORR; }; +#ifdef __KERNEL__ #if BITS_PER_LONG == 64 #define JS_DATA_SAVE_TYPE JS_DATA_SAVE_TYPE_64 #elif BITS_PER_LONG == 32 @@ -141,5 +142,6 @@ struct JS_DATA_SAVE_TYPE_64 { #else #error Unexpected BITS_PER_LONG #endif +#endif #endif /* _LINUX_JOYSTICK_H */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 72fe3385743c..c49d28eca561 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -491,6 +491,7 @@ #define PCI_DEVICE_ID_AMI_MEGARAID2 0x9060 #define PCI_VENDOR_ID_AMD 0x1022 +#define PCI_DEVICE_ID_AMD_K8_NB 0x1100 #define PCI_DEVICE_ID_AMD_LANCE 0x2000 #define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001 #define PCI_DEVICE_ID_AMD_SCSI 0x2020 @@ -2252,6 +2253,9 @@ #define PCI_VENDOR_ID_INFINICON 0x1820 +#define PCI_VENDOR_ID_SITECOM 0x182d +#define PCI_DEVICE_ID_SITECOM_DC105V2 0x3069 + #define PCI_VENDOR_ID_TOPSPIN 0x1867 #define PCI_VENDOR_ID_TDI 0x192E diff --git a/include/linux/tfrc.h b/include/linux/tfrc.h new file mode 100644 index 000000000000..7dab7831c3cb --- /dev/null +++ b/include/linux/tfrc.h @@ -0,0 +1,35 @@ +#ifndef _LINUX_TFRC_H_ +#define _LINUX_TFRC_H_ +/* + * include/linux/tfrc.h + * + * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. + * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz> + * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> + * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <linux/types.h> + +struct tfrc_rx_info { + __u32 tfrcrx_x_recv; + __u32 tfrcrx_rtt; + __u32 tfrcrx_p; +}; + +struct tfrc_tx_info { + __u32 tfrctx_x; + __u32 tfrctx_x_recv; + __u32 tfrctx_x_calc; + __u32 tfrctx_rtt; + __u32 tfrctx_p; + __u32 tfrctx_rto; + __u32 tfrctx_ipi; +}; + +#endif /* _LINUX_TFRC_H_ */ diff --git a/kernel/exit.c b/kernel/exit.c index 6d2089a1bce7..ee6d8b8abef5 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -371,6 +371,12 @@ static inline void close_files(struct files_struct * files) struct fdtable *fdt; j = 0; + + /* + * It is safe to dereference the fd table without RCU or + * ->file_lock because this is the last reference to the + * files structure. + */ fdt = files_fdtable(files); for (;;) { unsigned long set; diff --git a/kernel/fork.c b/kernel/fork.c index 8149f3602881..533ce27f4b2c 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1062,7 +1062,8 @@ static task_t *copy_process(unsigned long clone_flags, * parent's CPU). This avoids alot of nasty races. */ p->cpus_allowed = current->cpus_allowed; - if (unlikely(!cpu_isset(task_cpu(p), p->cpus_allowed))) + if (unlikely(!cpu_isset(task_cpu(p), p->cpus_allowed) || + !cpu_online(task_cpu(p)))) set_task_cpu(p, smp_processor_id()); /* diff --git a/kernel/sys.c b/kernel/sys.c index c80412be2302..f723522e6986 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1728,8 +1728,7 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, error = put_user(current->pdeath_signal, (int __user *)arg2); break; case PR_GET_DUMPABLE: - if (current->mm->dumpable) - error = 1; + error = current->mm->dumpable; break; case PR_SET_DUMPABLE: if (arg2 < 0 || arg2 > 2) { diff --git a/mm/Kconfig b/mm/Kconfig index 4e9937ac3529..391ffc54d136 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -29,7 +29,7 @@ config FLATMEM_MANUAL If unsure, choose this option (Flat Memory) over any other. config DISCONTIGMEM_MANUAL - bool "Discontigious Memory" + bool "Discontiguous Memory" depends on ARCH_DISCONTIGMEM_ENABLE help This option provides enhanced support for discontiguous @@ -52,7 +52,7 @@ config SPARSEMEM_MANUAL memory hotplug systems. This is normal. For many other systems, this will be an alternative to - "Discontigious Memory". This option provides some potential + "Discontiguous Memory". This option provides some potential performance benefits, along with decreased code complexity, but it is newer, and more experimental. diff --git a/net/Kconfig b/net/Kconfig index 2bdd5623fdd5..60f6f321bd76 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -140,6 +140,7 @@ config BRIDGE_NETFILTER If unsure, say N. +source "net/netfilter/Kconfig" source "net/ipv4/netfilter/Kconfig" source "net/ipv6/netfilter/Kconfig" source "net/decnet/netfilter/Kconfig" @@ -206,8 +207,6 @@ config NET_PKTGEN To compile this code as a module, choose M here: the module will be called pktgen. -source "net/netfilter/Kconfig" - endmenu endmenu diff --git a/net/dccp/Makefile b/net/dccp/Makefile index fb97bb042455..344a8da153fc 100644 --- a/net/dccp/Makefile +++ b/net/dccp/Makefile @@ -3,6 +3,8 @@ obj-$(CONFIG_IP_DCCP) += dccp.o dccp-y := ccid.o input.o ipv4.o minisocks.o options.o output.o proto.o \ timer.o +dccp-$(CONFIG_IP_DCCP_ACKVEC) += ackvec.o + obj-$(CONFIG_INET_DCCP_DIAG) += dccp_diag.o dccp_diag-y := diag.o diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c new file mode 100644 index 000000000000..6530283eafca --- /dev/null +++ b/net/dccp/ackvec.c @@ -0,0 +1,419 @@ +/* + * net/dccp/ackvec.c + * + * An implementation of the DCCP protocol + * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@ghostprotocols.net> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; version 2 of the License; + */ + +#include "ackvec.h" +#include "dccp.h" + +#include <linux/dccp.h> +#include <linux/skbuff.h> + +#include <net/sock.h> + +int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) +{ + struct dccp_sock *dp = dccp_sk(sk); + struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec; + int len = av->dccpav_vec_len + 2; + struct timeval now; + u32 elapsed_time; + unsigned char *to, *from; + + dccp_timestamp(sk, &now); + elapsed_time = timeval_delta(&now, &av->dccpav_time) / 10; + + if (elapsed_time != 0) + dccp_insert_option_elapsed_time(sk, skb, elapsed_time); + + if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) + return -1; + + /* + * XXX: now we have just one ack vector sent record, so + * we have to wait for it to be cleared. + * + * Of course this is not acceptable, but this is just for + * basic testing now. + */ + if (av->dccpav_ack_seqno != DCCP_MAX_SEQNO + 1) + return -1; + + DCCP_SKB_CB(skb)->dccpd_opt_len += len; + + to = skb_push(skb, len); + *to++ = DCCPO_ACK_VECTOR_0; + *to++ = len; + + len = av->dccpav_vec_len; + from = av->dccpav_buf + av->dccpav_buf_head; + + /* Check if buf_head wraps */ + if (av->dccpav_buf_head + len > av->dccpav_vec_len) { + const u32 tailsize = (av->dccpav_vec_len - av->dccpav_buf_head); + + memcpy(to, from, tailsize); + to += tailsize; + len -= tailsize; + from = av->dccpav_buf; + } + + memcpy(to, from, len); + /* + * From draft-ietf-dccp-spec-11.txt: + * + * For each acknowledgement it sends, the HC-Receiver will add an + * acknowledgement record. ack_seqno will equal the HC-Receiver + * sequence number it used for the ack packet; ack_ptr will equal + * buf_head; ack_ackno will equal buf_ackno; and ack_nonce will + * equal buf_nonce. + * + * This implemention uses just one ack record for now. + */ + av->dccpav_ack_seqno = DCCP_SKB_CB(skb)->dccpd_seq; + av->dccpav_ack_ptr = av->dccpav_buf_head; + av->dccpav_ack_ackno = av->dccpav_buf_ackno; + av->dccpav_ack_nonce = av->dccpav_buf_nonce; + av->dccpav_sent_len = av->dccpav_vec_len; + + dccp_pr_debug("%sACK Vector 0, len=%d, ack_seqno=%llu, " + "ack_ackno=%llu\n", + debug_prefix, av->dccpav_sent_len, + (unsigned long long)av->dccpav_ack_seqno, + (unsigned long long)av->dccpav_ack_ackno); + return -1; +} + +struct dccp_ackvec *dccp_ackvec_alloc(const unsigned int len, + const unsigned int __nocast priority) +{ + struct dccp_ackvec *av = kmalloc(sizeof(*av) + len, priority); + + if (av != NULL) { + av->dccpav_buf_len = len; + av->dccpav_buf_head = + av->dccpav_buf_tail = av->dccpav_buf_len - 1; + av->dccpav_buf_ackno = + av->dccpav_ack_ackno = av->dccpav_ack_seqno = ~0LLU; + av->dccpav_buf_nonce = av->dccpav_buf_nonce = 0; + av->dccpav_ack_ptr = 0; + av->dccpav_time.tv_sec = 0; + av->dccpav_time.tv_usec = 0; + av->dccpav_sent_len = av->dccpav_vec_len = 0; + } + + return av; +} + +void dccp_ackvec_free(struct dccp_ackvec *av) +{ + kfree(av); +} + +static inline u8 dccp_ackvec_state(const struct dccp_ackvec *av, + const unsigned int index) +{ + return av->dccpav_buf[index] & DCCP_ACKVEC_STATE_MASK; +} + +static inline u8 dccp_ackvec_len(const struct dccp_ackvec *av, + const unsigned int index) +{ + return av->dccpav_buf[index] & DCCP_ACKVEC_LEN_MASK; +} + +/* + * If several packets are missing, the HC-Receiver may prefer to enter multiple + * bytes with run length 0, rather than a single byte with a larger run length; + * this simplifies table updates if one of the missing packets arrives. + */ +static inline int dccp_ackvec_set_buf_head_state(struct dccp_ackvec *av, + const unsigned int packets, + const unsigned char state) +{ + unsigned int gap; + signed long new_head; + + if (av->dccpav_vec_len + packets > av->dccpav_buf_len) + return -ENOBUFS; + + gap = packets - 1; + new_head = av->dccpav_buf_head - packets; + + if (new_head < 0) { + if (gap > 0) { + memset(av->dccpav_buf, DCCP_ACKVEC_STATE_NOT_RECEIVED, + gap + new_head + 1); + gap = -new_head; + } + new_head += av->dccpav_buf_len; + } + + av->dccpav_buf_head = new_head; + + if (gap > 0) + memset(av->dccpav_buf + av->dccpav_buf_head + 1, + DCCP_ACKVEC_STATE_NOT_RECEIVED, gap); + + av->dccpav_buf[av->dccpav_buf_head] = state; + av->dccpav_vec_len += packets; + return 0; +} + +/* + * Implements the draft-ietf-dccp-spec-11.txt Appendix A + */ +int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, + const u64 ackno, const u8 state) +{ + /* + * Check at the right places if the buffer is full, if it is, tell the + * caller to start dropping packets till the HC-Sender acks our ACK + * vectors, when we will free up space in dccpav_buf. + * + * We may well decide to do buffer compression, etc, but for now lets + * just drop. + * + * From Appendix A: + * + * Of course, the circular buffer may overflow, either when the + * HC-Sender is sending data at a very high rate, when the + * HC-Receiver's acknowledgements are not reaching the HC-Sender, + * or when the HC-Sender is forgetting to acknowledge those acks + * (so the HC-Receiver is unable to clean up old state). In this + * case, the HC-Receiver should either compress the buffer (by + * increasing run lengths when possible), transfer its state to + * a larger buffer, or, as a last resort, drop all received + * packets, without processing them whatsoever, until its buffer + * shrinks again. + */ + + /* See if this is the first ackno being inserted */ + if (av->dccpav_vec_len == 0) { + av->dccpav_buf[av->dccpav_buf_head] = state; + av->dccpav_vec_len = 1; + } else if (after48(ackno, av->dccpav_buf_ackno)) { + const u64 delta = dccp_delta_seqno(av->dccpav_buf_ackno, + ackno); + + /* + * Look if the state of this packet is the same as the + * previous ackno and if so if we can bump the head len. + */ + if (delta == 1 && + dccp_ackvec_state(av, av->dccpav_buf_head) == state && + (dccp_ackvec_len(av, av->dccpav_buf_head) < + DCCP_ACKVEC_LEN_MASK)) + av->dccpav_buf[av->dccpav_buf_head]++; + else if (dccp_ackvec_set_buf_head_state(av, delta, state)) + return -ENOBUFS; + } else { + /* + * A.1.2. Old Packets + * + * When a packet with Sequence Number S arrives, and + * S <= buf_ackno, the HC-Receiver will scan the table + * for the byte corresponding to S. (Indexing structures + * could reduce the complexity of this scan.) + */ + u64 delta = dccp_delta_seqno(ackno, av->dccpav_buf_ackno); + unsigned int index = av->dccpav_buf_head; + + while (1) { + const u8 len = dccp_ackvec_len(av, index); + const u8 state = dccp_ackvec_state(av, index); + /* + * valid packets not yet in dccpav_buf have a reserved + * entry, with a len equal to 0. + */ + if (state == DCCP_ACKVEC_STATE_NOT_RECEIVED && + len == 0 && delta == 0) { /* Found our + reserved seat! */ + dccp_pr_debug("Found %llu reserved seat!\n", + (unsigned long long)ackno); + av->dccpav_buf[index] = state; + goto out; + } + /* len == 0 means one packet */ + if (delta < len + 1) + goto out_duplicate; + + delta -= len + 1; + if (++index == av->dccpav_buf_len) + index = 0; + } + } + + av->dccpav_buf_ackno = ackno; + dccp_timestamp(sk, &av->dccpav_time); +out: + dccp_pr_debug(""); + return 0; + +out_duplicate: + /* Duplicate packet */ + dccp_pr_debug("Received a dup or already considered lost " + "packet: %llu\n", (unsigned long long)ackno); + return -EILSEQ; +} + +#ifdef CONFIG_IP_DCCP_DEBUG +void dccp_ackvector_print(const u64 ackno, const unsigned char *vector, int len) +{ + if (!dccp_debug) + return; + + printk("ACK vector len=%d, ackno=%llu |", len, + (unsigned long long)ackno); + + while (len--) { + const u8 state = (*vector & DCCP_ACKVEC_STATE_MASK) >> 6; + const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK; + + printk("%d,%d|", state, rl); + ++vector; + } + + printk("\n"); +} + +void dccp_ackvec_print(const struct dccp_ackvec *av) +{ + dccp_ackvector_print(av->dccpav_buf_ackno, + av->dccpav_buf + av->dccpav_buf_head, + av->dccpav_vec_len); +} +#endif + +static void dccp_ackvec_trow_away_ack_record(struct dccp_ackvec *av) +{ + /* + * As we're keeping track of the ack vector size (dccpav_vec_len) and + * the sent ack vector size (dccpav_sent_len) we don't need + * dccpav_buf_tail at all, but keep this code here as in the future + * we'll implement a vector of ack records, as suggested in + * draft-ietf-dccp-spec-11.txt Appendix A. -acme + */ +#if 0 + av->dccpav_buf_tail = av->dccpav_ack_ptr + 1; + if (av->dccpav_buf_tail >= av->dccpav_vec_len) + av->dccpav_buf_tail -= av->dccpav_vec_len; +#endif + av->dccpav_vec_len -= av->dccpav_sent_len; +} + +void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, struct sock *sk, + const u64 ackno) +{ + /* Check if we actually sent an ACK vector */ + if (av->dccpav_ack_seqno == DCCP_MAX_SEQNO + 1) + return; + + if (ackno == av->dccpav_ack_seqno) { +#ifdef CONFIG_IP_DCCP_DEBUG + struct dccp_sock *dp = dccp_sk(sk); + const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? + "CLIENT rx ack: " : "server rx ack: "; +#endif + dccp_pr_debug("%sACK packet 0, len=%d, ack_seqno=%llu, " + "ack_ackno=%llu, ACKED!\n", + debug_prefix, 1, + (unsigned long long)av->dccpav_ack_seqno, + (unsigned long long)av->dccpav_ack_ackno); + dccp_ackvec_trow_away_ack_record(av); + av->dccpav_ack_seqno = DCCP_MAX_SEQNO + 1; + } +} + +static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av, + struct sock *sk, u64 ackno, + const unsigned char len, + const unsigned char *vector) +{ + unsigned char i; + + /* Check if we actually sent an ACK vector */ + if (av->dccpav_ack_seqno == DCCP_MAX_SEQNO + 1) + return; + /* + * We're in the receiver half connection, so if the received an ACK + * vector ackno (e.g. 50) before dccpav_ack_seqno (e.g. 52), we're + * not interested. + * + * Extra explanation with example: + * + * if we received an ACK vector with ackno 50, it can only be acking + * 50, 49, 48, etc, not 52 (the seqno for the ACK vector we sent). + */ + /* dccp_pr_debug("is %llu < %llu? ", ackno, av->dccpav_ack_seqno); */ + if (before48(ackno, av->dccpav_ack_seqno)) { + /* dccp_pr_debug_cat("yes\n"); */ + return; + } + /* dccp_pr_debug_cat("no\n"); */ + + i = len; + while (i--) { + const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK; + u64 ackno_end_rl; + + dccp_set_seqno(&ackno_end_rl, ackno - rl); + + /* + * dccp_pr_debug("is %llu <= %llu <= %llu? ", ackno_end_rl, + * av->dccpav_ack_seqno, ackno); + */ + if (between48(av->dccpav_ack_seqno, ackno_end_rl, ackno)) { + const u8 state = (*vector & + DCCP_ACKVEC_STATE_MASK) >> 6; + /* dccp_pr_debug_cat("yes\n"); */ + + if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) { +#ifdef CONFIG_IP_DCCP_DEBUG + struct dccp_sock *dp = dccp_sk(sk); + const char *debug_prefix = + dp->dccps_role == DCCP_ROLE_CLIENT ? + "CLIENT rx ack: " : "server rx ack: "; +#endif + dccp_pr_debug("%sACK vector 0, len=%d, " + "ack_seqno=%llu, ack_ackno=%llu, " + "ACKED!\n", + debug_prefix, len, + (unsigned long long) + av->dccpav_ack_seqno, + (unsigned long long) + av->dccpav_ack_ackno); + dccp_ackvec_trow_away_ack_record(av); + } + /* + * If dccpav_ack_seqno was not received, no problem + * we'll send another ACK vector. + */ + av->dccpav_ack_seqno = DCCP_MAX_SEQNO + 1; + break; + } + /* dccp_pr_debug_cat("no\n"); */ + + dccp_set_seqno(&ackno, ackno_end_rl - 1); + ++vector; + } +} + +int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, + const u8 opt, const u8 *value, const u8 len) +{ + if (len > DCCP_MAX_ACKVEC_LEN) + return -1; + + /* dccp_ackvector_print(DCCP_SKB_CB(skb)->dccpd_ack_seq, value, len); */ + dccp_ackvec_check_rcv_ackvector(dccp_sk(sk)->dccps_hc_rx_ackvec, sk, + DCCP_SKB_CB(skb)->dccpd_ack_seq, + len, value); + return 0; +} diff --git a/net/dccp/ackvec.h b/net/dccp/ackvec.h new file mode 100644 index 000000000000..8ca51c9191f7 --- /dev/null +++ b/net/dccp/ackvec.h @@ -0,0 +1,133 @@ +#ifndef _ACKVEC_H +#define _ACKVEC_H +/* + * net/dccp/ackvec.h + * + * An implementation of the DCCP protocol + * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@mandriva.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/config.h> +#include <linux/compiler.h> +#include <linux/time.h> +#include <linux/types.h> + +/* Read about the ECN nonce to see why it is 253 */ +#define DCCP_MAX_ACKVEC_LEN 253 + +#define DCCP_ACKVEC_STATE_RECEIVED 0 +#define DCCP_ACKVEC_STATE_ECN_MARKED (1 << 6) +#define DCCP_ACKVEC_STATE_NOT_RECEIVED (3 << 6) + +#define DCCP_ACKVEC_STATE_MASK 0xC0 /* 11000000 */ +#define DCCP_ACKVEC_LEN_MASK 0x3F /* 00111111 */ + +/** struct dccp_ackvec - ack vector + * + * This data structure is the one defined in the DCCP draft + * Appendix A. + * + * @dccpav_buf_head - circular buffer head + * @dccpav_buf_tail - circular buffer tail + * @dccpav_buf_ackno - ack # of the most recent packet acknowledgeable in the + * buffer (i.e. %dccpav_buf_head) + * @dccpav_buf_nonce - the one-bit sum of the ECN Nonces on all packets acked + * by the buffer with State 0 + * + * Additionally, the HC-Receiver must keep some information about the + * Ack Vectors it has recently sent. For each packet sent carrying an + * Ack Vector, it remembers four variables: + * + * @dccpav_ack_seqno - the Sequence Number used for the packet + * (HC-Receiver seqno) + * @dccpav_ack_ptr - the value of buf_head at the time of acknowledgement. + * @dccpav_ack_ackno - the Acknowledgement Number used for the packet + * (HC-Sender seqno) + * @dccpav_ack_nonce - the one-bit sum of the ECN Nonces for all State 0. + * + * @dccpav_buf_len - circular buffer length + * @dccpav_time - the time in usecs + * @dccpav_buf - circular buffer of acknowledgeable packets + */ +struct dccp_ackvec { + unsigned int dccpav_buf_head; + unsigned int dccpav_buf_tail; + u64 dccpav_buf_ackno; + u64 dccpav_ack_seqno; + u64 dccpav_ack_ackno; + unsigned int dccpav_ack_ptr; + unsigned int dccpav_sent_len; + unsigned int dccpav_vec_len; + unsigned int dccpav_buf_len; + struct timeval dccpav_time; + u8 dccpav_buf_nonce; + u8 dccpav_ack_nonce; + u8 dccpav_buf[0]; +}; + +struct sock; +struct sk_buff; + +#ifdef CONFIG_IP_DCCP_ACKVEC +extern struct dccp_ackvec *dccp_ackvec_alloc(unsigned int len, + const unsigned int __nocast priority); +extern void dccp_ackvec_free(struct dccp_ackvec *av); + +extern int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, + const u64 ackno, const u8 state); + +extern void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, + struct sock *sk, const u64 ackno); +extern int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, + const u8 opt, const u8 *value, const u8 len); + +extern int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb); + +static inline int dccp_ackvec_pending(const struct dccp_ackvec *av) +{ + return av->dccpav_sent_len != av->dccpav_vec_len; +} +#else /* CONFIG_IP_DCCP_ACKVEC */ +static inline struct dccp_ackvec *dccp_ackvec_alloc(unsigned int len, + const unsigned int __nocast priority) +{ + return NULL; +} + +static inline void dccp_ackvec_free(struct dccp_ackvec *av) +{ +} + +static inline int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, + const u64 ackno, const u8 state) +{ + return -1; +} + +static inline void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, + struct sock *sk, const u64 ackno) +{ +} + +static inline int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, + const u8 opt, const u8 *value, const u8 len) +{ + return -1; +} + +static inline int dccp_insert_option_ackvec(const struct sock *sk, + const struct sk_buff *skb) +{ + return -1; +} + +static inline int dccp_ackvec_pending(const struct dccp_ackvec *av) +{ + return 0; +} +#endif /* CONFIG_IP_DCCP_ACKVEC */ +#endif /* _ACKVEC_H */ diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h index 962f1e9e2f7e..21e55142dcd3 100644 --- a/net/dccp/ccid.h +++ b/net/dccp/ccid.h @@ -14,6 +14,7 @@ */ #include <net/sock.h> +#include <linux/compiler.h> #include <linux/dccp.h> #include <linux/list.h> #include <linux/module.h> @@ -54,6 +55,14 @@ struct ccid { struct tcp_info *info); void (*ccid_hc_tx_get_info)(struct sock *sk, struct tcp_info *info); + int (*ccid_hc_rx_getsockopt)(struct sock *sk, + const int optname, int len, + u32 __user *optval, + int __user *optlen); + int (*ccid_hc_tx_getsockopt)(struct sock *sk, + const int optname, int len, + u32 __user *optval, + int __user *optlen); }; extern int ccid_register(struct ccid *ccid); @@ -177,4 +186,26 @@ static inline void ccid_hc_tx_get_info(struct ccid *ccid, struct sock *sk, if (ccid->ccid_hc_tx_get_info != NULL) ccid->ccid_hc_tx_get_info(sk, info); } + +static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk, + const int optname, int len, + u32 __user *optval, int __user *optlen) +{ + int rc = -ENOPROTOOPT; + if (ccid->ccid_hc_rx_getsockopt != NULL) + rc = ccid->ccid_hc_rx_getsockopt(sk, optname, len, + optval, optlen); + return rc; +} + +static inline int ccid_hc_tx_getsockopt(struct ccid *ccid, struct sock *sk, + const int optname, int len, + u32 __user *optval, int __user *optlen) +{ + int rc = -ENOPROTOOPT; + if (ccid->ccid_hc_tx_getsockopt != NULL) + rc = ccid->ccid_hc_tx_getsockopt(sk, optname, len, + optval, optlen); + return rc; +} #endif /* _CCID_H */ diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 38aa84986118..aa68e0ab274d 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -1120,6 +1120,60 @@ static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info) info->tcpi_rtt = hctx->ccid3hctx_rtt; } +static int ccid3_hc_rx_getsockopt(struct sock *sk, const int optname, int len, + u32 __user *optval, int __user *optlen) +{ + const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); + const void *val; + + /* Listen socks doesn't have a private CCID block */ + if (sk->sk_state == DCCP_LISTEN) + return -EINVAL; + + switch (optname) { + case DCCP_SOCKOPT_CCID_RX_INFO: + if (len < sizeof(hcrx->ccid3hcrx_tfrc)) + return -EINVAL; + len = sizeof(hcrx->ccid3hcrx_tfrc); + val = &hcrx->ccid3hcrx_tfrc; + break; + default: + return -ENOPROTOOPT; + } + + if (put_user(len, optlen) || copy_to_user(optval, val, len)) + return -EFAULT; + + return 0; +} + +static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len, + u32 __user *optval, int __user *optlen) +{ + const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); + const void *val; + + /* Listen socks doesn't have a private CCID block */ + if (sk->sk_state == DCCP_LISTEN) + return -EINVAL; + + switch (optname) { + case DCCP_SOCKOPT_CCID_TX_INFO: + if (len < sizeof(hctx->ccid3hctx_tfrc)) + return -EINVAL; + len = sizeof(hctx->ccid3hctx_tfrc); + val = &hctx->ccid3hctx_tfrc; + break; + default: + return -ENOPROTOOPT; + } + + if (put_user(len, optlen) || copy_to_user(optval, val, len)) + return -EFAULT; + + return 0; +} + static struct ccid ccid3 = { .ccid_id = 3, .ccid_name = "ccid3", @@ -1139,6 +1193,8 @@ static struct ccid ccid3 = { .ccid_hc_rx_packet_recv = ccid3_hc_rx_packet_recv, .ccid_hc_rx_get_info = ccid3_hc_rx_get_info, .ccid_hc_tx_get_info = ccid3_hc_tx_get_info, + .ccid_hc_rx_getsockopt = ccid3_hc_rx_getsockopt, + .ccid_hc_tx_getsockopt = ccid3_hc_tx_getsockopt, }; module_param(ccid3_debug, int, 0444); diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index eb248778eea3..0bde4583d091 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h @@ -40,6 +40,7 @@ #include <linux/list.h> #include <linux/time.h> #include <linux/types.h> +#include <linux/tfrc.h> #define TFRC_MIN_PACKET_SIZE 16 #define TFRC_STD_PACKET_SIZE 256 @@ -93,12 +94,15 @@ struct ccid3_options_received { * @ccid3hctx_hist - Packet history */ struct ccid3_hc_tx_sock { - u32 ccid3hctx_x; - u32 ccid3hctx_x_recv; - u32 ccid3hctx_x_calc; + struct tfrc_tx_info ccid3hctx_tfrc; +#define ccid3hctx_x ccid3hctx_tfrc.tfrctx_x +#define ccid3hctx_x_recv ccid3hctx_tfrc.tfrctx_x_recv +#define ccid3hctx_x_calc ccid3hctx_tfrc.tfrctx_x_calc +#define ccid3hctx_rtt ccid3hctx_tfrc.tfrctx_rtt +#define ccid3hctx_p ccid3hctx_tfrc.tfrctx_p +#define ccid3hctx_t_rto ccid3hctx_tfrc.tfrctx_rto +#define ccid3hctx_t_ipi ccid3hctx_tfrc.tfrctx_ipi u16 ccid3hctx_s; - u32 ccid3hctx_rtt; - u32 ccid3hctx_p; u8 ccid3hctx_state; u8 ccid3hctx_last_win_count; u8 ccid3hctx_idle; @@ -106,19 +110,19 @@ struct ccid3_hc_tx_sock { struct timer_list ccid3hctx_no_feedback_timer; struct timeval ccid3hctx_t_ld; struct timeval ccid3hctx_t_nom; - u32 ccid3hctx_t_rto; - u32 ccid3hctx_t_ipi; u32 ccid3hctx_delta; struct list_head ccid3hctx_hist; struct ccid3_options_received ccid3hctx_options_received; }; struct ccid3_hc_rx_sock { + struct tfrc_rx_info ccid3hcrx_tfrc; +#define ccid3hcrx_x_recv ccid3hcrx_tfrc.tfrcrx_x_recv +#define ccid3hcrx_rtt ccid3hcrx_tfrc.tfrcrx_rtt +#define ccid3hcrx_p ccid3hcrx_tfrc.tfrcrx_p u64 ccid3hcrx_seqno_last_counter:48, ccid3hcrx_state:8, ccid3hcrx_last_counter:4; - u32 ccid3hcrx_rtt; - u32 ccid3hcrx_p; u32 ccid3hcrx_bytes_recv; struct timeval ccid3hcrx_tstamp_last_feedback; struct timeval ccid3hcrx_tstamp_last_ack; @@ -127,7 +131,6 @@ struct ccid3_hc_rx_sock { u16 ccid3hcrx_s; u32 ccid3hcrx_pinv; u32 ccid3hcrx_elapsed_time; - u32 ccid3hcrx_x_recv; }; static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk) diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 95c4630b3b18..5871c027f9dc 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -17,6 +17,7 @@ #include <net/snmp.h> #include <net/sock.h> #include <net/tcp.h> +#include "ackvec.h" #ifdef CONFIG_IP_DCCP_DEBUG extern int dccp_debug; @@ -258,13 +259,12 @@ extern int dccp_v4_send_reset(struct sock *sk, extern void dccp_send_close(struct sock *sk, const int active); struct dccp_skb_cb { - __u8 dccpd_type; - __u8 dccpd_reset_code; - __u8 dccpd_service; - __u8 dccpd_ccval; + __u8 dccpd_type:4; + __u8 dccpd_ccval:4; + __u8 dccpd_reset_code; + __u16 dccpd_opt_len; __u64 dccpd_seq; __u64 dccpd_ack_seq; - int dccpd_opt_len; }; #define DCCP_SKB_CB(__skb) ((struct dccp_skb_cb *)&((__skb)->cb[0])) @@ -359,6 +359,17 @@ static inline void dccp_update_gss(struct sock *sk, u64 seq) (dp->dccps_gss - dp->dccps_options.dccpo_sequence_window + 1)); } + +static inline int dccp_ack_pending(const struct sock *sk) +{ + const struct dccp_sock *dp = dccp_sk(sk); + return dp->dccps_timestamp_echo != 0 || +#ifdef CONFIG_IP_DCCP_ACKVEC + (dp->dccps_options.dccpo_send_ack_vector && + dccp_ackvec_pending(dp->dccps_hc_rx_ackvec)) || +#endif + inet_csk_ack_scheduled(sk); +} extern void dccp_insert_options(struct sock *sk, struct sk_buff *skb); extern void dccp_insert_option_elapsed_time(struct sock *sk, @@ -372,65 +383,6 @@ extern void dccp_insert_option(struct sock *sk, struct sk_buff *skb, extern struct socket *dccp_ctl_socket; -#define DCCP_ACKPKTS_STATE_RECEIVED 0 -#define DCCP_ACKPKTS_STATE_ECN_MARKED (1 << 6) -#define DCCP_ACKPKTS_STATE_NOT_RECEIVED (3 << 6) - -#define DCCP_ACKPKTS_STATE_MASK 0xC0 /* 11000000 */ -#define DCCP_ACKPKTS_LEN_MASK 0x3F /* 00111111 */ - -/** struct dccp_ackpkts - acknowledgeable packets - * - * This data structure is the one defined in the DCCP draft - * Appendix A. - * - * @dccpap_buf_head - circular buffer head - * @dccpap_buf_tail - circular buffer tail - * @dccpap_buf_ackno - ack # of the most recent packet acknowledgeable in the - * buffer (i.e. %dccpap_buf_head) - * @dccpap_buf_nonce - the one-bit sum of the ECN Nonces on all packets acked - * by the buffer with State 0 - * - * Additionally, the HC-Receiver must keep some information about the - * Ack Vectors it has recently sent. For each packet sent carrying an - * Ack Vector, it remembers four variables: - * - * @dccpap_ack_seqno - the Sequence Number used for the packet - * (HC-Receiver seqno) - * @dccpap_ack_ptr - the value of buf_head at the time of acknowledgement. - * @dccpap_ack_ackno - the Acknowledgement Number used for the packet - * (HC-Sender seqno) - * @dccpap_ack_nonce - the one-bit sum of the ECN Nonces for all State 0. - * - * @dccpap_buf_len - circular buffer length - * @dccpap_time - the time in usecs - * @dccpap_buf - circular buffer of acknowledgeable packets - */ -struct dccp_ackpkts { - unsigned int dccpap_buf_head; - unsigned int dccpap_buf_tail; - u64 dccpap_buf_ackno; - u64 dccpap_ack_seqno; - u64 dccpap_ack_ackno; - unsigned int dccpap_ack_ptr; - unsigned int dccpap_buf_vector_len; - unsigned int dccpap_ack_vector_len; - unsigned int dccpap_buf_len; - struct timeval dccpap_time; - u8 dccpap_buf_nonce; - u8 dccpap_ack_nonce; - u8 dccpap_buf[0]; -}; - -extern struct dccp_ackpkts * - dccp_ackpkts_alloc(unsigned int len, - const unsigned int __nocast priority); -extern void dccp_ackpkts_free(struct dccp_ackpkts *ap); -extern int dccp_ackpkts_add(struct dccp_ackpkts *ap, const struct sock *sk, - u64 ackno, u8 state); -extern void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap, - struct sock *sk, u64 ackno); - extern void dccp_timestamp(const struct sock *sk, struct timeval *tv); static inline suseconds_t timeval_usecs(const struct timeval *tv) @@ -471,15 +423,4 @@ static inline void timeval_sub_usecs(struct timeval *tv, } } -#ifdef CONFIG_IP_DCCP_DEBUG -extern void dccp_ackvector_print(const u64 ackno, - const unsigned char *vector, int len); -extern void dccp_ackpkts_print(const struct dccp_ackpkts *ap); -#else -static inline void dccp_ackvector_print(const u64 ackno, - const unsigned char *vector, - int len) { } -static inline void dccp_ackpkts_print(const struct dccp_ackpkts *ap) { } -#endif - #endif /* _DCCP_H */ diff --git a/net/dccp/input.c b/net/dccp/input.c index c74034cf7ede..1b6b2cb12376 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -16,6 +16,7 @@ #include <net/sock.h> +#include "ackvec.h" #include "ccid.h" #include "dccp.h" @@ -60,8 +61,8 @@ static inline void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb) struct dccp_sock *dp = dccp_sk(sk); if (dp->dccps_options.dccpo_send_ack_vector) - dccp_ackpkts_check_rcv_ackno(dp->dccps_hc_rx_ackpkts, sk, - DCCP_SKB_CB(skb)->dccpd_ack_seq); + dccp_ackvec_check_rcv_ackno(dp->dccps_hc_rx_ackvec, sk, + DCCP_SKB_CB(skb)->dccpd_ack_seq); } static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb) @@ -164,37 +165,11 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb, if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) dccp_event_ack_recv(sk, skb); - /* - * FIXME: check ECN to see if we should use - * DCCP_ACKPKTS_STATE_ECN_MARKED - */ - if (dp->dccps_options.dccpo_send_ack_vector) { - struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; - - if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, sk, - DCCP_SKB_CB(skb)->dccpd_seq, - DCCP_ACKPKTS_STATE_RECEIVED)) { - LIMIT_NETDEBUG(KERN_WARNING "DCCP: acknowledgeable " - "packets buffer full!\n"); - ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1; - inet_csk_schedule_ack(sk); - inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, - TCP_DELACK_MIN, - DCCP_RTO_MAX); - goto discard; - } - - /* - * FIXME: this activation is probably wrong, have to study more - * TCP delack machinery and how it fits into DCCP draft, but - * for now it kinda "works" 8) - */ - if (!inet_csk_ack_scheduled(sk)) { - inet_csk_schedule_ack(sk); - inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, 5 * HZ, - DCCP_RTO_MAX); - } - } + if (dp->dccps_options.dccpo_send_ack_vector && + dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, + DCCP_SKB_CB(skb)->dccpd_seq, + DCCP_ACKVEC_STATE_RECEIVED)) + goto discard; ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); @@ -384,9 +359,9 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, } out_invalid_packet: - return 1; /* dccp_v4_do_rcv will send a reset, but... - FIXME: the reset code should be - DCCP_RESET_CODE_PACKET_ERROR */ + /* dccp_v4_do_rcv will send a reset */ + DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR; + return 1; } static int dccp_rcv_respond_partopen_state_process(struct sock *sk, @@ -433,6 +408,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, struct dccp_hdr *dh, unsigned len) { struct dccp_sock *dp = dccp_sk(sk); + struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); const int old_state = sk->sk_state; int queued = 0; @@ -473,7 +449,8 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, if (dh->dccph_type == DCCP_PKT_RESET) goto discard; - /* Caller (dccp_v4_do_rcv) will send Reset(No Connection)*/ + /* Caller (dccp_v4_do_rcv) will send Reset */ + dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; return 1; } @@ -487,36 +464,17 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, if (dccp_parse_options(sk, skb)) goto discard; - if (DCCP_SKB_CB(skb)->dccpd_ack_seq != - DCCP_PKT_WITHOUT_ACK_SEQ) + if (dcb->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) dccp_event_ack_recv(sk, skb); ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); - /* - * FIXME: check ECN to see if we should use - * DCCP_ACKPKTS_STATE_ECN_MARKED - */ - if (dp->dccps_options.dccpo_send_ack_vector) { - if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, sk, - DCCP_SKB_CB(skb)->dccpd_seq, - DCCP_ACKPKTS_STATE_RECEIVED)) - goto discard; - /* - * FIXME: this activation is probably wrong, have to - * study more TCP delack machinery and how it fits into - * DCCP draft, but for now it kinda "works" 8) - */ - if ((dp->dccps_hc_rx_ackpkts->dccpap_ack_seqno == - DCCP_MAX_SEQNO + 1) && - !inet_csk_ack_scheduled(sk)) { - inet_csk_schedule_ack(sk); - inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, - TCP_DELACK_MIN, - DCCP_RTO_MAX); - } - } + if (dp->dccps_options.dccpo_send_ack_vector && + dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, + DCCP_SKB_CB(skb)->dccpd_seq, + DCCP_ACKVEC_STATE_RECEIVED)) + goto discard; } /* @@ -551,8 +509,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, dh->dccph_type == DCCP_PKT_REQUEST) || (sk->sk_state == DCCP_RESPOND && dh->dccph_type == DCCP_PKT_DATA)) { - dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, - DCCP_PKT_SYNC); + dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNC); goto discard; } else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) { dccp_rcv_closereq(sk, skb); @@ -563,13 +520,13 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, } if (unlikely(dh->dccph_type == DCCP_PKT_SYNC)) { - dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, - DCCP_PKT_SYNCACK); + dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNCACK); goto discard; } switch (sk->sk_state) { case DCCP_CLOSED: + dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; return 1; case DCCP_REQUESTING: diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 2afaa464e7f0..40fe6afacde6 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -23,6 +23,7 @@ #include <net/tcp_states.h> #include <net/xfrm.h> +#include "ackvec.h" #include "ccid.h" #include "dccp.h" @@ -246,6 +247,9 @@ static int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, dp->dccps_role = DCCP_ROLE_CLIENT; + if (dccp_service_not_initialized(sk)) + return -EPROTO; + if (addr_len < sizeof(struct sockaddr_in)) return -EINVAL; @@ -661,6 +665,16 @@ static inline u64 dccp_v4_init_sequence(const struct sock *sk, dccp_hdr(skb)->dccph_sport); } +static inline int dccp_bad_service_code(const struct sock *sk, + const __u32 service) +{ + const struct dccp_sock *dp = dccp_sk(sk); + + if (dp->dccps_service == service) + return 0; + return !dccp_list_has_service(dp->dccps_service_list, service); +} + int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) { struct inet_request_sock *ireq; @@ -669,13 +683,22 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) struct dccp_request_sock *dreq; const __u32 saddr = skb->nh.iph->saddr; const __u32 daddr = skb->nh.iph->daddr; + const __u32 service = dccp_hdr_request(skb)->dccph_req_service; + struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); + __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY; struct dst_entry *dst = NULL; /* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */ if (((struct rtable *)skb->dst)->rt_flags & - (RTCF_BROADCAST | RTCF_MULTICAST)) + (RTCF_BROADCAST | RTCF_MULTICAST)) { + reset_code = DCCP_RESET_CODE_NO_CONNECTION; goto drop; + } + if (dccp_bad_service_code(sk, service)) { + reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE; + goto drop; + } /* * TW buckets are converted to open requests without * limitations, they conserve resources and peer is @@ -718,9 +741,9 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) * dccp_create_openreq_child. */ dreq = dccp_rsk(req); - dreq->dreq_isr = DCCP_SKB_CB(skb)->dccpd_seq; - dreq->dreq_iss = dccp_v4_init_sequence(sk, skb); - dreq->dreq_service = dccp_hdr_request(skb)->dccph_req_service; + dreq->dreq_isr = dcb->dccpd_seq; + dreq->dreq_iss = dccp_v4_init_sequence(sk, skb); + dreq->dreq_service = service; if (dccp_v4_send_response(sk, req, dst)) goto drop_and_free; @@ -735,6 +758,7 @@ drop_and_free: __reqsk_free(req); drop: DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS); + dcb->dccpd_reset_code = reset_code; return -1; } @@ -1005,7 +1029,6 @@ int dccp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) return 0; reset: - DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; dccp_v4_ctl_send_reset(skb); discard: kfree_skb(skb); @@ -1090,45 +1113,7 @@ int dccp_v4_rcv(struct sk_buff *skb) goto discard_it; dh = dccp_hdr(skb); -#if 0 - /* - * Use something like this to simulate some DATA/DATAACK loss to test - * dccp_ackpkts_add, you'll get something like this on a session that - * sends 10 DATA/DATAACK packets: - * - * ackpkts_print: 281473596467422 |0,0|3,0|0,0|3,0|0,0|3,0|0,0|3,0|0,1| - * - * 0, 0 means: DCCP_ACKPKTS_STATE_RECEIVED, RLE == just this packet - * 0, 1 means: DCCP_ACKPKTS_STATE_RECEIVED, RLE == two adjacent packets - * with the same state - * 3, 0 means: DCCP_ACKPKTS_STATE_NOT_RECEIVED, RLE == just this packet - * - * So... - * - * 281473596467422 was received - * 281473596467421 was not received - * 281473596467420 was received - * 281473596467419 was not received - * 281473596467418 was received - * 281473596467417 was not received - * 281473596467416 was received - * 281473596467415 was not received - * 281473596467414 was received - * 281473596467413 was received (this one was the 3way handshake - * RESPONSE) - * - */ - if (dh->dccph_type == DCCP_PKT_DATA || - dh->dccph_type == DCCP_PKT_DATAACK) { - static int discard = 0; - if (discard) { - discard = 0; - goto discard_it; - } - discard = 1; - } -#endif DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb); DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type; @@ -1242,11 +1227,9 @@ static int dccp_v4_init_sock(struct sock *sk) do_gettimeofday(&dp->dccps_epoch); if (dp->dccps_options.dccpo_send_ack_vector) { - dp->dccps_hc_rx_ackpkts = - dccp_ackpkts_alloc(DCCP_MAX_ACK_VECTOR_LEN, - GFP_KERNEL); - - if (dp->dccps_hc_rx_ackpkts == NULL) + dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(DCCP_MAX_ACKVEC_LEN, + GFP_KERNEL); + if (dp->dccps_hc_rx_ackvec == NULL) return -ENOMEM; } @@ -1258,16 +1241,18 @@ static int dccp_v4_init_sock(struct sock *sk) * setsockopt(CCIDs-I-want/accept). -acme */ if (likely(!dccp_ctl_socket_init)) { - dp->dccps_hc_rx_ccid = ccid_init(dp->dccps_options.dccpo_ccid, + dp->dccps_hc_rx_ccid = ccid_init(dp->dccps_options.dccpo_rx_ccid, sk); - dp->dccps_hc_tx_ccid = ccid_init(dp->dccps_options.dccpo_ccid, + dp->dccps_hc_tx_ccid = ccid_init(dp->dccps_options.dccpo_tx_ccid, sk); if (dp->dccps_hc_rx_ccid == NULL || dp->dccps_hc_tx_ccid == NULL) { ccid_exit(dp->dccps_hc_rx_ccid, sk); ccid_exit(dp->dccps_hc_tx_ccid, sk); - dccp_ackpkts_free(dp->dccps_hc_rx_ackpkts); - dp->dccps_hc_rx_ackpkts = NULL; + if (dp->dccps_options.dccpo_send_ack_vector) { + dccp_ackvec_free(dp->dccps_hc_rx_ackvec); + dp->dccps_hc_rx_ackvec = NULL; + } dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; return -ENOMEM; } @@ -1280,6 +1265,7 @@ static int dccp_v4_init_sock(struct sock *sk) sk->sk_write_space = dccp_write_space; dp->dccps_mss_cache = 536; dp->dccps_role = DCCP_ROLE_UNDEFINED; + dp->dccps_service = DCCP_SERVICE_INVALID_VALUE; return 0; } @@ -1301,10 +1287,17 @@ static int dccp_v4_destroy_sock(struct sock *sk) if (inet_csk(sk)->icsk_bind_hash != NULL) inet_put_port(&dccp_hashinfo, sk); + if (dp->dccps_service_list != NULL) { + kfree(dp->dccps_service_list); + dp->dccps_service_list = NULL; + } + ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk); ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk); - dccp_ackpkts_free(dp->dccps_hc_rx_ackpkts); - dp->dccps_hc_rx_ackpkts = NULL; + if (dp->dccps_options.dccpo_send_ack_vector) { + dccp_ackvec_free(dp->dccps_hc_rx_ackvec); + dp->dccps_hc_rx_ackvec = NULL; + } ccid_exit(dp->dccps_hc_rx_ccid, sk); ccid_exit(dp->dccps_hc_tx_ccid, sk); dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 18461bc04cbe..1393461898bb 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -19,6 +19,7 @@ #include <net/xfrm.h> #include <net/inet_timewait_sock.h> +#include "ackvec.h" #include "ccid.h" #include "dccp.h" @@ -93,22 +94,24 @@ struct sock *dccp_create_openreq_child(struct sock *sk, struct inet_connection_sock *newicsk = inet_csk(sk); struct dccp_sock *newdp = dccp_sk(newsk); - newdp->dccps_hc_rx_ackpkts = NULL; - newdp->dccps_role = DCCP_ROLE_SERVER; - newicsk->icsk_rto = DCCP_TIMEOUT_INIT; + newdp->dccps_role = DCCP_ROLE_SERVER; + newdp->dccps_hc_rx_ackvec = NULL; + newdp->dccps_service_list = NULL; + newdp->dccps_service = dreq->dreq_service; + newicsk->icsk_rto = DCCP_TIMEOUT_INIT; do_gettimeofday(&newdp->dccps_epoch); if (newdp->dccps_options.dccpo_send_ack_vector) { - newdp->dccps_hc_rx_ackpkts = - dccp_ackpkts_alloc(DCCP_MAX_ACK_VECTOR_LEN, - GFP_ATOMIC); + newdp->dccps_hc_rx_ackvec = + dccp_ackvec_alloc(DCCP_MAX_ACKVEC_LEN, + GFP_ATOMIC); /* * XXX: We're using the same CCIDs set on the parent, * i.e. sk_clone copied the master sock and left the * CCID pointers for this child, that is why we do the * __ccid_get calls. */ - if (unlikely(newdp->dccps_hc_rx_ackpkts == NULL)) + if (unlikely(newdp->dccps_hc_rx_ackvec == NULL)) goto out_free; } @@ -116,7 +119,7 @@ struct sock *dccp_create_openreq_child(struct sock *sk, newsk) != 0 || ccid_hc_tx_init(newdp->dccps_hc_tx_ccid, newsk) != 0)) { - dccp_ackpkts_free(newdp->dccps_hc_rx_ackpkts); + dccp_ackvec_free(newdp->dccps_hc_rx_ackvec); ccid_hc_rx_exit(newdp->dccps_hc_rx_ccid, newsk); ccid_hc_tx_exit(newdp->dccps_hc_tx_ccid, newsk); out_free: diff --git a/net/dccp/options.c b/net/dccp/options.c index d4c4242d8dd7..0a76426c9aea 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -18,19 +18,15 @@ #include <linux/kernel.h> #include <linux/skbuff.h> +#include "ackvec.h" #include "ccid.h" #include "dccp.h" -static void dccp_ackpkts_check_rcv_ackvector(struct dccp_ackpkts *ap, - struct sock *sk, - const u64 ackno, - const unsigned char len, - const unsigned char *vector); - /* stores the default values for new connection. may be changed with sysctl */ static const struct dccp_options dccpo_default_values = { .dccpo_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW, - .dccpo_ccid = DCCPF_INITIAL_CCID, + .dccpo_rx_ccid = DCCPF_INITIAL_CCID, + .dccpo_tx_ccid = DCCPF_INITIAL_CCID, .dccpo_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR, .dccpo_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT, }; @@ -113,25 +109,13 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) opt_recv->dccpor_ndp); break; case DCCPO_ACK_VECTOR_0: - if (len > DCCP_MAX_ACK_VECTOR_LEN) - goto out_invalid_option; - + case DCCPO_ACK_VECTOR_1: if (pkt_type == DCCP_PKT_DATA) continue; - opt_recv->dccpor_ack_vector_len = len; - opt_recv->dccpor_ack_vector_idx = value - options; - - dccp_pr_debug("%sACK vector 0, len=%d, ack_ackno=%llu\n", - debug_prefix, len, - (unsigned long long) - DCCP_SKB_CB(skb)->dccpd_ack_seq); - dccp_ackvector_print(DCCP_SKB_CB(skb)->dccpd_ack_seq, - value, len); - dccp_ackpkts_check_rcv_ackvector(dp->dccps_hc_rx_ackpkts, - sk, - DCCP_SKB_CB(skb)->dccpd_ack_seq, - len, value); + if (dp->dccps_options.dccpo_send_ack_vector && + dccp_ackvec_parse(sk, skb, opt, value, len)) + goto out_invalid_option; break; case DCCPO_TIMESTAMP: if (len != 4) @@ -352,86 +336,6 @@ void dccp_insert_option_elapsed_time(struct sock *sk, EXPORT_SYMBOL_GPL(dccp_insert_option_elapsed_time); -static void dccp_insert_option_ack_vector(struct sock *sk, struct sk_buff *skb) -{ - struct dccp_sock *dp = dccp_sk(sk); -#ifdef CONFIG_IP_DCCP_DEBUG - const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? - "CLIENT TX opt: " : "server TX opt: "; -#endif - struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; - int len = ap->dccpap_buf_vector_len + 2; - struct timeval now; - u32 elapsed_time; - unsigned char *to, *from; - - dccp_timestamp(sk, &now); - elapsed_time = timeval_delta(&now, &ap->dccpap_time) / 10; - - if (elapsed_time != 0) - dccp_insert_option_elapsed_time(sk, skb, elapsed_time); - - if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) { - LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to " - "insert ACK Vector!\n"); - return; - } - - /* - * XXX: now we have just one ack vector sent record, so - * we have to wait for it to be cleared. - * - * Of course this is not acceptable, but this is just for - * basic testing now. - */ - if (ap->dccpap_ack_seqno != DCCP_MAX_SEQNO + 1) - return; - - DCCP_SKB_CB(skb)->dccpd_opt_len += len; - - to = skb_push(skb, len); - *to++ = DCCPO_ACK_VECTOR_0; - *to++ = len; - - len = ap->dccpap_buf_vector_len; - from = ap->dccpap_buf + ap->dccpap_buf_head; - - /* Check if buf_head wraps */ - if (ap->dccpap_buf_head + len > ap->dccpap_buf_len) { - const unsigned int tailsize = (ap->dccpap_buf_len - - ap->dccpap_buf_head); - - memcpy(to, from, tailsize); - to += tailsize; - len -= tailsize; - from = ap->dccpap_buf; - } - - memcpy(to, from, len); - /* - * From draft-ietf-dccp-spec-11.txt: - * - * For each acknowledgement it sends, the HC-Receiver will add an - * acknowledgement record. ack_seqno will equal the HC-Receiver - * sequence number it used for the ack packet; ack_ptr will equal - * buf_head; ack_ackno will equal buf_ackno; and ack_nonce will - * equal buf_nonce. - * - * This implemention uses just one ack record for now. - */ - ap->dccpap_ack_seqno = DCCP_SKB_CB(skb)->dccpd_seq; - ap->dccpap_ack_ptr = ap->dccpap_buf_head; - ap->dccpap_ack_ackno = ap->dccpap_buf_ackno; - ap->dccpap_ack_nonce = ap->dccpap_buf_nonce; - ap->dccpap_ack_vector_len = ap->dccpap_buf_vector_len; - - dccp_pr_debug("%sACK Vector 0, len=%d, ack_seqno=%llu, " - "ack_ackno=%llu\n", - debug_prefix, ap->dccpap_ack_vector_len, - (unsigned long long) ap->dccpap_ack_seqno, - (unsigned long long) ap->dccpap_ack_ackno); -} - void dccp_timestamp(const struct sock *sk, struct timeval *tv) { const struct dccp_sock *dp = dccp_sk(sk); @@ -528,9 +432,8 @@ void dccp_insert_options(struct sock *sk, struct sk_buff *skb) if (!dccp_packet_without_ack(skb)) { if (dp->dccps_options.dccpo_send_ack_vector && - (dp->dccps_hc_rx_ackpkts->dccpap_buf_ackno != - DCCP_MAX_SEQNO + 1)) - dccp_insert_option_ack_vector(sk, skb); + dccp_ackvec_pending(dp->dccps_hc_rx_ackvec)) + dccp_insert_option_ackvec(sk, skb); if (dp->dccps_timestamp_echo != 0) dccp_insert_option_timestamp_echo(sk, skb); } @@ -557,331 +460,3 @@ void dccp_insert_options(struct sock *sk, struct sk_buff *skb) } } } - -struct dccp_ackpkts *dccp_ackpkts_alloc(const unsigned int len, - const unsigned int __nocast priority) -{ - struct dccp_ackpkts *ap = kmalloc(sizeof(*ap) + len, priority); - - if (ap != NULL) { -#ifdef CONFIG_IP_DCCP_DEBUG - memset(ap->dccpap_buf, 0xFF, len); -#endif - ap->dccpap_buf_len = len; - ap->dccpap_buf_head = - ap->dccpap_buf_tail = - ap->dccpap_buf_len - 1; - ap->dccpap_buf_ackno = - ap->dccpap_ack_ackno = - ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1; - ap->dccpap_buf_nonce = ap->dccpap_buf_nonce = 0; - ap->dccpap_ack_ptr = 0; - ap->dccpap_time.tv_sec = 0; - ap->dccpap_time.tv_usec = 0; - ap->dccpap_buf_vector_len = ap->dccpap_ack_vector_len = 0; - } - - return ap; -} - -void dccp_ackpkts_free(struct dccp_ackpkts *ap) -{ - if (ap != NULL) { -#ifdef CONFIG_IP_DCCP_DEBUG - memset(ap, 0xFF, sizeof(*ap) + ap->dccpap_buf_len); -#endif - kfree(ap); - } -} - -static inline u8 dccp_ackpkts_state(const struct dccp_ackpkts *ap, - const unsigned int index) -{ - return ap->dccpap_buf[index] & DCCP_ACKPKTS_STATE_MASK; -} - -static inline u8 dccp_ackpkts_len(const struct dccp_ackpkts *ap, - const unsigned int index) -{ - return ap->dccpap_buf[index] & DCCP_ACKPKTS_LEN_MASK; -} - -/* - * If several packets are missing, the HC-Receiver may prefer to enter multiple - * bytes with run length 0, rather than a single byte with a larger run length; - * this simplifies table updates if one of the missing packets arrives. - */ -static inline int dccp_ackpkts_set_buf_head_state(struct dccp_ackpkts *ap, - const unsigned int packets, - const unsigned char state) -{ - unsigned int gap; - signed long new_head; - - if (ap->dccpap_buf_vector_len + packets > ap->dccpap_buf_len) - return -ENOBUFS; - - gap = packets - 1; - new_head = ap->dccpap_buf_head - packets; - - if (new_head < 0) { - if (gap > 0) { - memset(ap->dccpap_buf, DCCP_ACKPKTS_STATE_NOT_RECEIVED, - gap + new_head + 1); - gap = -new_head; - } - new_head += ap->dccpap_buf_len; - } - - ap->dccpap_buf_head = new_head; - - if (gap > 0) - memset(ap->dccpap_buf + ap->dccpap_buf_head + 1, - DCCP_ACKPKTS_STATE_NOT_RECEIVED, gap); - - ap->dccpap_buf[ap->dccpap_buf_head] = state; - ap->dccpap_buf_vector_len += packets; - return 0; -} - -/* - * Implements the draft-ietf-dccp-spec-11.txt Appendix A - */ -int dccp_ackpkts_add(struct dccp_ackpkts *ap, const struct sock *sk, - u64 ackno, u8 state) -{ - /* - * Check at the right places if the buffer is full, if it is, tell the - * caller to start dropping packets till the HC-Sender acks our ACK - * vectors, when we will free up space in dccpap_buf. - * - * We may well decide to do buffer compression, etc, but for now lets - * just drop. - * - * From Appendix A: - * - * Of course, the circular buffer may overflow, either when the - * HC-Sender is sending data at a very high rate, when the - * HC-Receiver's acknowledgements are not reaching the HC-Sender, - * or when the HC-Sender is forgetting to acknowledge those acks - * (so the HC-Receiver is unable to clean up old state). In this - * case, the HC-Receiver should either compress the buffer (by - * increasing run lengths when possible), transfer its state to - * a larger buffer, or, as a last resort, drop all received - * packets, without processing them whatsoever, until its buffer - * shrinks again. - */ - - /* See if this is the first ackno being inserted */ - if (ap->dccpap_buf_vector_len == 0) { - ap->dccpap_buf[ap->dccpap_buf_head] = state; - ap->dccpap_buf_vector_len = 1; - } else if (after48(ackno, ap->dccpap_buf_ackno)) { - const u64 delta = dccp_delta_seqno(ap->dccpap_buf_ackno, - ackno); - - /* - * Look if the state of this packet is the same as the - * previous ackno and if so if we can bump the head len. - */ - if (delta == 1 && - dccp_ackpkts_state(ap, ap->dccpap_buf_head) == state && - (dccp_ackpkts_len(ap, ap->dccpap_buf_head) < - DCCP_ACKPKTS_LEN_MASK)) - ap->dccpap_buf[ap->dccpap_buf_head]++; - else if (dccp_ackpkts_set_buf_head_state(ap, delta, state)) - return -ENOBUFS; - } else { - /* - * A.1.2. Old Packets - * - * When a packet with Sequence Number S arrives, and - * S <= buf_ackno, the HC-Receiver will scan the table - * for the byte corresponding to S. (Indexing structures - * could reduce the complexity of this scan.) - */ - u64 delta = dccp_delta_seqno(ackno, ap->dccpap_buf_ackno); - unsigned int index = ap->dccpap_buf_head; - - while (1) { - const u8 len = dccp_ackpkts_len(ap, index); - const u8 state = dccp_ackpkts_state(ap, index); - /* - * valid packets not yet in dccpap_buf have a reserved - * entry, with a len equal to 0. - */ - if (state == DCCP_ACKPKTS_STATE_NOT_RECEIVED && - len == 0 && delta == 0) { /* Found our - reserved seat! */ - dccp_pr_debug("Found %llu reserved seat!\n", - (unsigned long long) ackno); - ap->dccpap_buf[index] = state; - goto out; - } - /* len == 0 means one packet */ - if (delta < len + 1) - goto out_duplicate; - - delta -= len + 1; - if (++index == ap->dccpap_buf_len) - index = 0; - } - } - - ap->dccpap_buf_ackno = ackno; - dccp_timestamp(sk, &ap->dccpap_time); -out: - dccp_pr_debug(""); - dccp_ackpkts_print(ap); - return 0; - -out_duplicate: - /* Duplicate packet */ - dccp_pr_debug("Received a dup or already considered lost " - "packet: %llu\n", (unsigned long long) ackno); - return -EILSEQ; -} - -#ifdef CONFIG_IP_DCCP_DEBUG -void dccp_ackvector_print(const u64 ackno, const unsigned char *vector, - int len) -{ - if (!dccp_debug) - return; - - printk("ACK vector len=%d, ackno=%llu |", len, - (unsigned long long) ackno); - - while (len--) { - const u8 state = (*vector & DCCP_ACKPKTS_STATE_MASK) >> 6; - const u8 rl = (*vector & DCCP_ACKPKTS_LEN_MASK); - - printk("%d,%d|", state, rl); - ++vector; - } - - printk("\n"); -} - -void dccp_ackpkts_print(const struct dccp_ackpkts *ap) -{ - dccp_ackvector_print(ap->dccpap_buf_ackno, - ap->dccpap_buf + ap->dccpap_buf_head, - ap->dccpap_buf_vector_len); -} -#endif - -static void dccp_ackpkts_trow_away_ack_record(struct dccp_ackpkts *ap) -{ - /* - * As we're keeping track of the ack vector size - * (dccpap_buf_vector_len) and the sent ack vector size - * (dccpap_ack_vector_len) we don't need dccpap_buf_tail at all, but - * keep this code here as in the future we'll implement a vector of - * ack records, as suggested in draft-ietf-dccp-spec-11.txt - * Appendix A. -acme - */ -#if 0 - ap->dccpap_buf_tail = ap->dccpap_ack_ptr + 1; - if (ap->dccpap_buf_tail >= ap->dccpap_buf_len) - ap->dccpap_buf_tail -= ap->dccpap_buf_len; -#endif - ap->dccpap_buf_vector_len -= ap->dccpap_ack_vector_len; -} - -void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap, struct sock *sk, - u64 ackno) -{ - /* Check if we actually sent an ACK vector */ - if (ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1) - return; - - if (ackno == ap->dccpap_ack_seqno) { -#ifdef CONFIG_IP_DCCP_DEBUG - struct dccp_sock *dp = dccp_sk(sk); - const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? - "CLIENT rx ack: " : "server rx ack: "; -#endif - dccp_pr_debug("%sACK packet 0, len=%d, ack_seqno=%llu, " - "ack_ackno=%llu, ACKED!\n", - debug_prefix, 1, - (unsigned long long) ap->dccpap_ack_seqno, - (unsigned long long) ap->dccpap_ack_ackno); - dccp_ackpkts_trow_away_ack_record(ap); - ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1; - } -} - -static void dccp_ackpkts_check_rcv_ackvector(struct dccp_ackpkts *ap, - struct sock *sk, u64 ackno, - const unsigned char len, - const unsigned char *vector) -{ - unsigned char i; - - /* Check if we actually sent an ACK vector */ - if (ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1) - return; - /* - * We're in the receiver half connection, so if the received an ACK - * vector ackno (e.g. 50) before dccpap_ack_seqno (e.g. 52), we're - * not interested. - * - * Extra explanation with example: - * - * if we received an ACK vector with ackno 50, it can only be acking - * 50, 49, 48, etc, not 52 (the seqno for the ACK vector we sent). - */ - /* dccp_pr_debug("is %llu < %llu? ", ackno, ap->dccpap_ack_seqno); */ - if (before48(ackno, ap->dccpap_ack_seqno)) { - /* dccp_pr_debug_cat("yes\n"); */ - return; - } - /* dccp_pr_debug_cat("no\n"); */ - - i = len; - while (i--) { - const u8 rl = (*vector & DCCP_ACKPKTS_LEN_MASK); - u64 ackno_end_rl; - - dccp_set_seqno(&ackno_end_rl, ackno - rl); - - /* - * dccp_pr_debug("is %llu <= %llu <= %llu? ", ackno_end_rl, - * ap->dccpap_ack_seqno, ackno); - */ - if (between48(ap->dccpap_ack_seqno, ackno_end_rl, ackno)) { - const u8 state = (*vector & - DCCP_ACKPKTS_STATE_MASK) >> 6; - /* dccp_pr_debug_cat("yes\n"); */ - - if (state != DCCP_ACKPKTS_STATE_NOT_RECEIVED) { -#ifdef CONFIG_IP_DCCP_DEBUG - struct dccp_sock *dp = dccp_sk(sk); - const char *debug_prefix = - dp->dccps_role == DCCP_ROLE_CLIENT ? - "CLIENT rx ack: " : "server rx ack: "; -#endif - dccp_pr_debug("%sACK vector 0, len=%d, " - "ack_seqno=%llu, ack_ackno=%llu, " - "ACKED!\n", - debug_prefix, len, - (unsigned long long) - ap->dccpap_ack_seqno, - (unsigned long long) - ap->dccpap_ack_ackno); - dccp_ackpkts_trow_away_ack_record(ap); - } - /* - * If dccpap_ack_seqno was not received, no problem - * we'll send another ACK vector. - */ - ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1; - break; - } - /* dccp_pr_debug_cat("no\n"); */ - - dccp_set_seqno(&ackno, ackno_end_rl - 1); - ++vector; - } -} diff --git a/net/dccp/output.c b/net/dccp/output.c index ea6d0e91e511..4786bdcddcc9 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -16,6 +16,7 @@ #include <net/sock.h> +#include "ackvec.h" #include "ccid.h" #include "dccp.h" @@ -85,7 +86,7 @@ int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) switch (dcb->dccpd_type) { case DCCP_PKT_REQUEST: dccp_hdr_request(skb)->dccph_req_service = - dcb->dccpd_service; + dp->dccps_service; break; case DCCP_PKT_RESET: dccp_hdr_reset(skb)->dccph_reset_code = @@ -225,7 +226,6 @@ int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, long *timeo) err = dccp_wait_for_ccid(sk, skb, timeo); if (err == 0) { - const struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); const int len = skb->len; @@ -236,15 +236,7 @@ int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, long *timeo) inet_csk(sk)->icsk_rto, DCCP_RTO_MAX); dcb->dccpd_type = DCCP_PKT_DATAACK; - /* - * FIXME: we really should have a - * dccps_ack_pending or use icsk. - */ - } else if (inet_csk_ack_scheduled(sk) || - dp->dccps_timestamp_echo != 0 || - (dp->dccps_options.dccpo_send_ack_vector && - ap->dccpap_buf_ackno != DCCP_MAX_SEQNO + 1 && - ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1)) + } else if (dccp_ack_pending(sk)) dcb->dccpd_type = DCCP_PKT_DATAACK; else dcb->dccpd_type = DCCP_PKT_DATA; @@ -270,6 +262,7 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, struct request_sock *req) { struct dccp_hdr *dh; + struct dccp_request_sock *dreq; const int dccp_header_size = sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_response); @@ -285,8 +278,9 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, skb->dst = dst_clone(dst); skb->csum = 0; + dreq = dccp_rsk(req); DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE; - DCCP_SKB_CB(skb)->dccpd_seq = dccp_rsk(req)->dreq_iss; + DCCP_SKB_CB(skb)->dccpd_seq = dreq->dreq_iss; dccp_insert_options(sk, skb); skb->h.raw = skb_push(skb, dccp_header_size); @@ -300,8 +294,9 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, DCCP_SKB_CB(skb)->dccpd_opt_len) / 4; dh->dccph_type = DCCP_PKT_RESPONSE; dh->dccph_x = 1; - dccp_hdr_set_seq(dh, dccp_rsk(req)->dreq_iss); - dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dccp_rsk(req)->dreq_isr); + dccp_hdr_set_seq(dh, dreq->dreq_iss); + dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dreq->dreq_isr); + dccp_hdr_response(skb)->dccph_resp_service = dreq->dreq_service; dh->dccph_checksum = dccp_v4_checksum(skb, inet_rsk(req)->loc_addr, inet_rsk(req)->rmt_addr); @@ -397,9 +392,6 @@ int dccp_connect(struct sock *sk) skb_reserve(skb, MAX_DCCP_HEADER); DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST; - /* FIXME: set service to something meaningful, coming - * from userspace*/ - DCCP_SKB_CB(skb)->dccpd_service = 0; skb->csum = 0; skb_set_owner_w(skb, sk); diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 18a0e69c9dc7..a1cfd0e9e3bc 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -94,7 +94,15 @@ EXPORT_SYMBOL_GPL(dccp_state_name); static inline int dccp_listen_start(struct sock *sk) { - dccp_sk(sk)->dccps_role = DCCP_ROLE_LISTEN; + struct dccp_sock *dp = dccp_sk(sk); + + dp->dccps_role = DCCP_ROLE_LISTEN; + /* + * Apps need to use setsockopt(DCCP_SOCKOPT_SERVICE) + * before calling listen() + */ + if (dccp_service_not_initialized(sk)) + return -EPROTO; return inet_csk_listen_start(sk, TCP_SYNQ_HSIZE); } @@ -202,6 +210,42 @@ int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg) return -ENOIOCTLCMD; } +static int dccp_setsockopt_service(struct sock *sk, const u32 service, + char __user *optval, int optlen) +{ + struct dccp_sock *dp = dccp_sk(sk); + struct dccp_service_list *sl = NULL; + + if (service == DCCP_SERVICE_INVALID_VALUE || + optlen > DCCP_SERVICE_LIST_MAX_LEN * sizeof(u32)) + return -EINVAL; + + if (optlen > sizeof(service)) { + sl = kmalloc(optlen, GFP_KERNEL); + if (sl == NULL) + return -ENOMEM; + + sl->dccpsl_nr = optlen / sizeof(u32) - 1; + if (copy_from_user(sl->dccpsl_list, + optval + sizeof(service), + optlen - sizeof(service)) || + dccp_list_has_service(sl, DCCP_SERVICE_INVALID_VALUE)) { + kfree(sl); + return -EFAULT; + } + } + + lock_sock(sk); + dp->dccps_service = service; + + if (dp->dccps_service_list != NULL) + kfree(dp->dccps_service_list); + + dp->dccps_service_list = sl; + release_sock(sk); + return 0; +} + int dccp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen) { @@ -218,8 +262,10 @@ int dccp_setsockopt(struct sock *sk, int level, int optname, if (get_user(val, (int __user *)optval)) return -EFAULT; - lock_sock(sk); + if (optname == DCCP_SOCKOPT_SERVICE) + return dccp_setsockopt_service(sk, val, optval, optlen); + lock_sock(sk); dp = dccp_sk(sk); err = 0; @@ -236,6 +282,37 @@ int dccp_setsockopt(struct sock *sk, int level, int optname, return err; } +static int dccp_getsockopt_service(struct sock *sk, int len, + u32 __user *optval, + int __user *optlen) +{ + const struct dccp_sock *dp = dccp_sk(sk); + const struct dccp_service_list *sl; + int err = -ENOENT, slen = 0, total_len = sizeof(u32); + + lock_sock(sk); + if (dccp_service_not_initialized(sk)) + goto out; + + if ((sl = dp->dccps_service_list) != NULL) { + slen = sl->dccpsl_nr * sizeof(u32); + total_len += slen; + } + + err = -EINVAL; + if (total_len > len) + goto out; + + err = 0; + if (put_user(total_len, optlen) || + put_user(dp->dccps_service, optval) || + (sl != NULL && copy_to_user(optval + 1, sl->dccpsl_list, slen))) + err = -EFAULT; +out: + release_sock(sk); + return err; +} + int dccp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) { @@ -248,8 +325,7 @@ int dccp_getsockopt(struct sock *sk, int level, int optname, if (get_user(len, optlen)) return -EFAULT; - len = min_t(unsigned int, len, sizeof(int)); - if (len < 0) + if (len < sizeof(int)) return -EINVAL; dp = dccp_sk(sk); @@ -257,7 +333,17 @@ int dccp_getsockopt(struct sock *sk, int level, int optname, switch (optname) { case DCCP_SOCKOPT_PACKET_SIZE: val = dp->dccps_packet_size; + len = sizeof(dp->dccps_packet_size); break; + case DCCP_SOCKOPT_SERVICE: + return dccp_getsockopt_service(sk, len, + (u32 __user *)optval, optlen); + case 128 ... 191: + return ccid_hc_rx_getsockopt(dp->dccps_hc_rx_ccid, sk, optname, + len, (u32 __user *)optval, optlen); + case 192 ... 255: + return ccid_hc_tx_getsockopt(dp->dccps_hc_tx_ccid, sk, optname, + len, (u32 __user *)optval, optlen); default: return -ENOPROTOOPT; } diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 30aa8e2ee214..e2162d270073 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -51,6 +51,14 @@ config IP_NF_CONNTRACK_EVENTS IF unsure, say `N'. +config IP_NF_CONNTRACK_NETLINK + tristate 'Connection tracking netlink interface' + depends on IP_NF_CONNTRACK && NETFILTER_NETLINK + depends on IP_NF_CONNTRACK!=y || NETFILTER_NETLINK!=m + help + This option enables support for a netlink-based userspace interface + + config IP_NF_CT_PROTO_SCTP tristate 'SCTP protocol connection tracking support (EXPERIMENTAL)' depends on IP_NF_CONNTRACK && EXPERIMENTAL @@ -774,11 +782,5 @@ config IP_NF_ARP_MANGLE Allows altering the ARP packet payload: source and destination hardware and network addresses. -config IP_NF_CONNTRACK_NETLINK - tristate 'Connection tracking netlink interface' - depends on IP_NF_CONNTRACK && NETFILTER_NETLINK - help - This option enables support for a netlink-based userspace interface - endmenu diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 19cba16e6e1e..f8cd8e42961e 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -1143,7 +1143,10 @@ void ip_ct_refresh_acct(struct ip_conntrack *ct, if (del_timer(&ct->timeout)) { ct->timeout.expires = jiffies + extra_jiffies; add_timer(&ct->timeout); - ip_conntrack_event_cache(IPCT_REFRESH, skb); + /* FIXME: We loose some REFRESH events if this function + * is called without an skb. I'll fix this later -HW */ + if (skb) + ip_conntrack_event_cache(IPCT_REFRESH, skb); } ct_add_counters(ct, ctinfo, skb); write_unlock_bh(&ip_conntrack_lock); diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 7d38913754b1..9bcb398fbc1f 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -13,6 +13,7 @@ #include <linux/config.h> #include <linux/proc_fs.h> #include <linux/jhash.h> +#include <linux/bitops.h> #include <linux/skbuff.h> #include <linux/ip.h> #include <linux/tcp.h> @@ -30,7 +31,7 @@ #include <linux/netfilter_ipv4/ipt_CLUSTERIP.h> #include <linux/netfilter_ipv4/ip_conntrack.h> -#define CLUSTERIP_VERSION "0.7" +#define CLUSTERIP_VERSION "0.8" #define DEBUG_CLUSTERIP @@ -49,13 +50,14 @@ MODULE_DESCRIPTION("iptables target for CLUSTERIP"); struct clusterip_config { struct list_head list; /* list of all configs */ atomic_t refcount; /* reference count */ + atomic_t entries; /* number of entries/rules + * referencing us */ u_int32_t clusterip; /* the IP address */ u_int8_t clustermac[ETH_ALEN]; /* the MAC address */ struct net_device *dev; /* device */ u_int16_t num_total_nodes; /* total number of nodes */ - u_int16_t num_local_nodes; /* number of local nodes */ - u_int16_t local_nodes[CLUSTERIP_MAX_NODES]; /* node number array */ + unsigned long local_nodes; /* node number array */ #ifdef CONFIG_PROC_FS struct proc_dir_entry *pde; /* proc dir entry */ @@ -66,8 +68,7 @@ struct clusterip_config { static LIST_HEAD(clusterip_configs); -/* clusterip_lock protects the clusterip_configs list _AND_ the configurable - * data within all structurses (num_local_nodes, local_nodes[]) */ +/* clusterip_lock protects the clusterip_configs list */ static DEFINE_RWLOCK(clusterip_lock); #ifdef CONFIG_PROC_FS @@ -76,23 +77,48 @@ static struct proc_dir_entry *clusterip_procdir; #endif static inline void -clusterip_config_get(struct clusterip_config *c) { +clusterip_config_get(struct clusterip_config *c) +{ atomic_inc(&c->refcount); } static inline void -clusterip_config_put(struct clusterip_config *c) { - if (atomic_dec_and_test(&c->refcount)) { +clusterip_config_put(struct clusterip_config *c) +{ + if (atomic_dec_and_test(&c->refcount)) + kfree(c); +} + +/* increase the count of entries(rules) using/referencing this config */ +static inline void +clusterip_config_entry_get(struct clusterip_config *c) +{ + atomic_inc(&c->entries); +} + +/* decrease the count of entries using/referencing this config. If last + * entry(rule) is removed, remove the config from lists, but don't free it + * yet, since proc-files could still be holding references */ +static inline void +clusterip_config_entry_put(struct clusterip_config *c) +{ + if (atomic_dec_and_test(&c->entries)) { write_lock_bh(&clusterip_lock); list_del(&c->list); write_unlock_bh(&clusterip_lock); + dev_mc_delete(c->dev, c->clustermac, ETH_ALEN, 0); dev_put(c->dev); - kfree(c); + + /* In case anyone still accesses the file, the open/close + * functions are also incrementing the refcount on their own, + * so it's safe to remove the entry even if it's in use. */ +#ifdef CONFIG_PROC_FS + remove_proc_entry(c->pde->name, c->pde->parent); +#endif } } - static struct clusterip_config * __clusterip_config_find(u_int32_t clusterip) { @@ -111,7 +137,7 @@ __clusterip_config_find(u_int32_t clusterip) } static inline struct clusterip_config * -clusterip_config_find_get(u_int32_t clusterip) +clusterip_config_find_get(u_int32_t clusterip, int entry) { struct clusterip_config *c; @@ -122,11 +148,24 @@ clusterip_config_find_get(u_int32_t clusterip) return NULL; } atomic_inc(&c->refcount); + if (entry) + atomic_inc(&c->entries); read_unlock_bh(&clusterip_lock); return c; } +static void +clusterip_config_init_nodelist(struct clusterip_config *c, + const struct ipt_clusterip_tgt_info *i) +{ + int n; + + for (n = 0; n < i->num_local_nodes; n++) { + set_bit(i->local_nodes[n] - 1, &c->local_nodes); + } +} + static struct clusterip_config * clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip, struct net_device *dev) @@ -143,11 +182,11 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip, c->clusterip = ip; memcpy(&c->clustermac, &i->clustermac, ETH_ALEN); c->num_total_nodes = i->num_total_nodes; - c->num_local_nodes = i->num_local_nodes; - memcpy(&c->local_nodes, &i->local_nodes, sizeof(c->local_nodes)); + clusterip_config_init_nodelist(c, i); c->hash_mode = i->hash_mode; c->hash_initval = i->hash_initval; atomic_set(&c->refcount, 1); + atomic_set(&c->entries, 1); #ifdef CONFIG_PROC_FS /* create proc dir entry */ @@ -171,53 +210,28 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip, static int clusterip_add_node(struct clusterip_config *c, u_int16_t nodenum) { - int i; - - write_lock_bh(&clusterip_lock); - if (c->num_local_nodes >= CLUSTERIP_MAX_NODES - || nodenum > CLUSTERIP_MAX_NODES) { - write_unlock_bh(&clusterip_lock); + if (nodenum == 0 || + nodenum > c->num_total_nodes) return 1; - } - - /* check if we alrady have this number in our array */ - for (i = 0; i < c->num_local_nodes; i++) { - if (c->local_nodes[i] == nodenum) { - write_unlock_bh(&clusterip_lock); - return 1; - } - } - c->local_nodes[c->num_local_nodes++] = nodenum; + /* check if we already have this number in our bitfield */ + if (test_and_set_bit(nodenum - 1, &c->local_nodes)) + return 1; - write_unlock_bh(&clusterip_lock); return 0; } static int clusterip_del_node(struct clusterip_config *c, u_int16_t nodenum) { - int i; - - write_lock_bh(&clusterip_lock); - - if (c->num_local_nodes <= 1 || nodenum > CLUSTERIP_MAX_NODES) { - write_unlock_bh(&clusterip_lock); + if (nodenum == 0 || + nodenum > c->num_total_nodes) return 1; - } - for (i = 0; i < c->num_local_nodes; i++) { - if (c->local_nodes[i] == nodenum) { - int size = sizeof(u_int16_t)*(c->num_local_nodes-(i+1)); - memmove(&c->local_nodes[i], &c->local_nodes[i+1], size); - c->num_local_nodes--; - write_unlock_bh(&clusterip_lock); - return 0; - } - } + if (test_and_clear_bit(nodenum - 1, &c->local_nodes)) + return 0; - write_unlock_bh(&clusterip_lock); return 1; } @@ -285,25 +299,7 @@ clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config) static inline int clusterip_responsible(struct clusterip_config *config, u_int32_t hash) { - int i; - - read_lock_bh(&clusterip_lock); - - if (config->num_local_nodes == 0) { - read_unlock_bh(&clusterip_lock); - return 0; - } - - for (i = 0; i < config->num_local_nodes; i++) { - if (config->local_nodes[i] == hash) { - read_unlock_bh(&clusterip_lock); - return 1; - } - } - - read_unlock_bh(&clusterip_lock); - - return 0; + return test_bit(hash - 1, &config->local_nodes); } /*********************************************************************** @@ -415,8 +411,26 @@ checkentry(const char *tablename, /* FIXME: further sanity checks */ - config = clusterip_config_find_get(e->ip.dst.s_addr); - if (!config) { + config = clusterip_config_find_get(e->ip.dst.s_addr, 1); + if (config) { + if (cipinfo->config != NULL) { + /* Case A: This is an entry that gets reloaded, since + * it still has a cipinfo->config pointer. Simply + * increase the entry refcount and return */ + if (cipinfo->config != config) { + printk(KERN_ERR "CLUSTERIP: Reloaded entry " + "has invalid config pointer!\n"); + return 0; + } + clusterip_config_entry_get(cipinfo->config); + } else { + /* Case B: This is a new rule referring to an existing + * clusterip config. */ + cipinfo->config = config; + clusterip_config_entry_get(cipinfo->config); + } + } else { + /* Case C: This is a completely new clusterip config */ if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) { printk(KERN_WARNING "CLUSTERIP: no config found for %u.%u.%u.%u, need 'new'\n", NIPQUAD(e->ip.dst.s_addr)); return 0; @@ -443,10 +457,9 @@ checkentry(const char *tablename, } dev_mc_add(config->dev,config->clustermac, ETH_ALEN, 0); } + cipinfo->config = config; } - cipinfo->config = config; - return 1; } @@ -455,13 +468,10 @@ static void destroy(void *matchinfo, unsigned int matchinfosize) { struct ipt_clusterip_tgt_info *cipinfo = matchinfo; - /* we first remove the proc entry and then drop the reference - * count. In case anyone still accesses the file, the open/close - * functions are also incrementing the refcount on their own */ -#ifdef CONFIG_PROC_FS - remove_proc_entry(cipinfo->config->pde->name, - cipinfo->config->pde->parent); -#endif + /* if no more entries are referencing the config, remove it + * from the list and destroy the proc entry */ + clusterip_config_entry_put(cipinfo->config); + clusterip_config_put(cipinfo->config); } @@ -533,7 +543,7 @@ arp_mangle(unsigned int hook, /* if there is no clusterip configuration for the arp reply's * source ip, we don't want to mangle it */ - c = clusterip_config_find_get(payload->src_ip); + c = clusterip_config_find_get(payload->src_ip, 0); if (!c) return NF_ACCEPT; @@ -574,56 +584,69 @@ static struct nf_hook_ops cip_arp_ops = { #ifdef CONFIG_PROC_FS +struct clusterip_seq_position { + unsigned int pos; /* position */ + unsigned int weight; /* number of bits set == size */ + unsigned int bit; /* current bit */ + unsigned long val; /* current value */ +}; + static void *clusterip_seq_start(struct seq_file *s, loff_t *pos) { struct proc_dir_entry *pde = s->private; struct clusterip_config *c = pde->data; - unsigned int *nodeidx; - - read_lock_bh(&clusterip_lock); - if (*pos >= c->num_local_nodes) + unsigned int weight; + u_int32_t local_nodes; + struct clusterip_seq_position *idx; + + /* FIXME: possible race */ + local_nodes = c->local_nodes; + weight = hweight32(local_nodes); + if (*pos >= weight) return NULL; - nodeidx = kmalloc(sizeof(unsigned int), GFP_KERNEL); - if (!nodeidx) + idx = kmalloc(sizeof(struct clusterip_seq_position), GFP_KERNEL); + if (!idx) return ERR_PTR(-ENOMEM); - *nodeidx = *pos; - return nodeidx; + idx->pos = *pos; + idx->weight = weight; + idx->bit = ffs(local_nodes); + idx->val = local_nodes; + clear_bit(idx->bit - 1, &idx->val); + + return idx; } static void *clusterip_seq_next(struct seq_file *s, void *v, loff_t *pos) { - struct proc_dir_entry *pde = s->private; - struct clusterip_config *c = pde->data; - unsigned int *nodeidx = (unsigned int *)v; + struct clusterip_seq_position *idx = (struct clusterip_seq_position *)v; - *pos = ++(*nodeidx); - if (*pos >= c->num_local_nodes) { + *pos = ++idx->pos; + if (*pos >= idx->weight) { kfree(v); return NULL; } - return nodeidx; + idx->bit = ffs(idx->val); + clear_bit(idx->bit - 1, &idx->val); + return idx; } static void clusterip_seq_stop(struct seq_file *s, void *v) { kfree(v); - - read_unlock_bh(&clusterip_lock); } static int clusterip_seq_show(struct seq_file *s, void *v) { - struct proc_dir_entry *pde = s->private; - struct clusterip_config *c = pde->data; - unsigned int *nodeidx = (unsigned int *)v; + struct clusterip_seq_position *idx = (struct clusterip_seq_position *)v; - if (*nodeidx != 0) + if (idx->pos != 0) seq_putc(s, ','); - seq_printf(s, "%u", c->local_nodes[*nodeidx]); - if (*nodeidx == c->num_local_nodes-1) + seq_printf(s, "%u", idx->bit); + + if (idx->pos == idx->weight - 1) seq_putc(s, '\n'); return 0; diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 2b9bf9bd177f..6001948600f3 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -639,6 +639,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, int tclass = -1; int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; int err; + int connected = 0; /* destination address check */ if (sin6) { @@ -748,6 +749,7 @@ do_udp_sendmsg: fl->fl_ip_dport = inet->dport; daddr = &np->daddr; fl->fl6_flowlabel = np->flow_label; + connected = 1; } if (!fl->oif) @@ -770,6 +772,7 @@ do_udp_sendmsg: } if (!(opt->opt_nflen|opt->opt_flen)) opt = NULL; + connected = 0; } if (opt == NULL) opt = np->opt; @@ -787,10 +790,13 @@ do_udp_sendmsg: ipv6_addr_copy(&final, &fl->fl6_dst); ipv6_addr_copy(&fl->fl6_dst, rt0->addr); final_p = &final; + connected = 0; } - if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst)) + if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst)) { fl->oif = np->mcast_oif; + connected = 0; + } err = ip6_dst_lookup(sk, &dst, fl); if (err) @@ -846,7 +852,7 @@ do_append_data: else if (!corkreq) err = udp_v6_push_pending_frames(sk, up); - if (dst) + if (dst && connected) ip6_dst_store(sk, dst, ipv6_addr_equal(&fl->fl6_dst, &np->daddr) ? &np->daddr : NULL); diff --git a/net/socket.c b/net/socket.c index c699e93c33d7..f9264472377f 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1862,7 +1862,8 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flag if (err < 0) goto out_freeiov; } - err = __put_user(msg_sys.msg_flags, COMPAT_FLAGS(msg)); + err = __put_user((msg_sys.msg_flags & ~MSG_CMSG_COMPAT), + COMPAT_FLAGS(msg)); if (err) goto out_freeiov; if (MSG_CMSG_COMPAT & flags) diff --git a/security/seclvl.c b/security/seclvl.c index dc4e17b6eaf6..1caac0164643 100644 --- a/security/seclvl.c +++ b/security/seclvl.c @@ -252,10 +252,9 @@ passwd_write_file(struct file * file, const char __user * buf, } if (count < 0 || count >= PAGE_SIZE) - return -ENOMEM; - if (*ppos != 0) { return -EINVAL; - } + if (*ppos != 0) + return -EINVAL; page = (char *)get_zeroed_page(GFP_KERNEL); if (!page) return -ENOMEM; @@ -265,9 +264,8 @@ passwd_write_file(struct file * file, const char __user * buf, len = strlen(page); /* ``echo "secret" > seclvl/passwd'' includes a newline */ - if (page[len - 1] == '\n') { + if (page[len - 1] == '\n') len--; - } /* Hash the password, then compare the hashed values */ if ((rc = plaintext_to_sha1(tmp, page, len))) { seclvl_printk(0, KERN_ERR, "Error hashing password: rc = " @@ -275,9 +273,8 @@ passwd_write_file(struct file * file, const char __user * buf, return rc; } for (i = 0; i < SHA1_DIGEST_SIZE; i++) { - if (hashedPassword[i] != tmp[i]) { + if (hashedPassword[i] != tmp[i]) return -EPERM; - } } seclvl_printk(0, KERN_INFO, "Password accepted; seclvl reduced to 0.\n"); @@ -482,9 +479,8 @@ static void seclvl_file_free_security(struct file *filp) */ static int seclvl_umount(struct vfsmount *mnt, int flags) { - if (current->pid == 1) { + if (current->pid == 1) return 0; - } if (seclvl == 2) { seclvl_printk(1, KERN_WARNING, "Attempt to unmount in secure " "level %d\n", seclvl); @@ -638,9 +634,8 @@ static int __init seclvl_init(void) static void __exit seclvl_exit(void) { securityfs_remove(seclvl_ino); - if (*passwd || *sha1_passwd) { + if (*passwd || *sha1_passwd) securityfs_remove(passwd_ino); - } securityfs_remove(dir_ino); if (secondary == 1) { mod_unreg_security(MY_NAME, &seclvl_ops); diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index 34195b748608..b2d5db20ec8c 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c @@ -650,7 +650,7 @@ static int aaci_do_resume(snd_card_t *card, unsigned int state) return 0; } -static int aaci_suspend(struct amba_device *dev, u32 state) +static int aaci_suspend(struct amba_device *dev, pm_message_t state) { snd_card_t *card = amba_get_drvdata(dev); return card ? aaci_do_suspend(card) : 0; |