From 70e0fed57ce53438dd83fbff9992fdb3c4723133 Mon Sep 17 00:00:00 2001 From: Rui Sousa Date: Sat, 15 Sep 2007 00:56:19 +0100 Subject: [PATCH] --- yaml --- r: 65102 b: refs/heads/master c: 4f6627ac3ba6948a4aebec80edfd6565aec3a40c h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/Documentation/input/iforce-protocol.txt | 508 +++++++++--------- trunk/Documentation/kernel-parameters.txt | 20 +- trunk/MAINTAINERS | 6 +- trunk/Makefile | 4 +- trunk/arch/arm/mm/cache-l2x0.c | 12 +- trunk/arch/i386/boot/header.S | 2 +- trunk/arch/i386/boot/video.c | 14 +- trunk/arch/i386/kernel/acpi/wakeup.S | 41 +- trunk/arch/i386/xen/enlighten.c | 4 +- trunk/arch/mips/dec/setup.c | 2 +- trunk/arch/mips/kernel/cpu-bugs64.c | 4 +- trunk/arch/mips/sibyte/bcm1480/setup.c | 2 - trunk/arch/powerpc/kernel/time.c | 8 +- trunk/arch/powerpc/kernel/vdso.c | 12 - .../arch/powerpc/platforms/cell/spufs/sched.c | 4 +- trunk/arch/um/include/kern_util.h | 2 +- trunk/arch/um/kernel/irq.c | 7 +- trunk/arch/um/os-Linux/file.c | 3 +- trunk/arch/um/os-Linux/signal.c | 4 +- trunk/arch/x86_64/Kconfig | 8 + trunk/arch/x86_64/ia32/ia32entry.S | 18 +- trunk/arch/x86_64/kernel/acpi/wakeup.S | 47 +- trunk/arch/x86_64/kernel/process.c | 1 + trunk/arch/x86_64/kernel/ptrace.c | 4 + trunk/arch/x86_64/kernel/smp.c | 2 +- trunk/arch/x86_64/mm/fault.c | 7 - trunk/drivers/ata/ahci.c | 10 +- trunk/drivers/ata/libata-core.c | 4 - trunk/drivers/ata/libata-sff.c | 5 +- trunk/drivers/base/core.c | 29 +- trunk/drivers/block/DAC960.c | 1 - trunk/drivers/char/agp/agp.h | 3 +- trunk/drivers/char/agp/intel-agp.c | 2 +- trunk/drivers/char/ipmi/ipmi_si_intf.c | 3 +- trunk/drivers/char/mspec.c | 69 +-- trunk/drivers/ide/ide-disk.c | 1 - trunk/drivers/ide/ppc/pmac.c | 2 + trunk/drivers/ieee1394/ieee1394_core.c | 2 +- trunk/drivers/ieee1394/ohci1394.c | 4 +- .../media/video/usbvision/usbvision-cards.c | 1 - trunk/drivers/mtd/nand/cafe_nand.c | 3 +- trunk/drivers/net/bnx2.c | 7 +- trunk/drivers/net/myri10ge/myri10ge.c | 3 - trunk/drivers/net/phy/phy.c | 1 - trunk/drivers/net/pppoe.c | 3 +- trunk/drivers/net/pppol2tp.c | 118 ++-- trunk/drivers/net/sky2.c | 368 ++++--------- trunk/drivers/net/sky2.h | 41 +- trunk/drivers/rtc/rtc-ds1553.c | 2 +- trunk/drivers/rtc/rtc-ds1742.c | 2 +- trunk/drivers/serial/sunsab.c | 107 ++-- trunk/drivers/video/intelfb/intelfbhw.c | 2 +- trunk/fs/exec.c | 3 + trunk/fs/ext3/namei.c | 73 +-- trunk/fs/ext4/namei.c | 73 +-- trunk/fs/nfs/super.c | 2 +- trunk/fs/ocfs2/aops.c | 33 +- trunk/fs/ocfs2/file.c | 4 +- trunk/fs/ocfs2/localalloc.c | 4 +- trunk/fs/ocfs2/localalloc.h | 2 +- trunk/fs/ocfs2/suballoc.c | 29 +- trunk/fs/ocfs2/suballoc.h | 11 - trunk/fs/ocfs2/vote.c | 4 +- trunk/fs/signalfd.c | 190 ++++++- trunk/fs/xfs/linux-2.6/xfs_aops.c | 1 - trunk/fs/xfs/linux-2.6/xfs_super.c | 4 +- trunk/fs/xfs/xfs_buf_item.h | 5 - trunk/fs/xfs/xfs_filestream.c | 3 +- trunk/fs/xfs/xfs_log_recover.c | 51 +- trunk/fs/xfs/xfs_mru_cache.c | 72 ++- trunk/fs/xfs/xfs_mru_cache.h | 6 +- trunk/fs/xfs/xfs_trans_buf.c | 1 - trunk/fs/xfs/xfs_vnodeops.c | 20 +- trunk/include/asm-mips/compiler.h | 4 +- trunk/include/asm-powerpc/time.h | 5 - trunk/include/asm-x86_64/pgalloc.h | 73 ++- trunk/include/asm-x86_64/pgtable.h | 1 - trunk/include/linux/init_task.h | 2 +- trunk/include/linux/mempolicy.h | 4 +- trunk/include/linux/sched.h | 6 +- trunk/include/linux/signalfd.h | 40 +- trunk/include/linux/user_namespace.h | 2 +- trunk/init/Kconfig | 1 - trunk/init/do_mounts_initrd.c | 4 +- trunk/kernel/exit.c | 9 + trunk/kernel/fork.c | 2 +- trunk/kernel/sched.c | 10 +- trunk/kernel/sched_fair.c | 63 +-- trunk/kernel/signal.c | 8 +- trunk/kernel/sysctl.c | 8 - trunk/kernel/user.c | 45 +- trunk/kernel/user_namespace.c | 4 +- trunk/kernel/utsname.c | 2 - trunk/mm/hugetlb.c | 4 +- trunk/mm/mempolicy.c | 79 +-- trunk/net/netfilter/nfnetlink_log.c | 13 +- trunk/net/sched/sch_sfq.c | 10 +- trunk/net/sunrpc/svcsock.c | 3 +- trunk/security/selinux/hooks.c | 2 - 100 files changed, 1113 insertions(+), 1423 deletions(-) diff --git a/[refs] b/[refs] index 4a94dc4a95f0..1ea40c85819a 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: da8f153e51290e7438ba7da66234a864e5d3e1c1 +refs/heads/master: 4f6627ac3ba6948a4aebec80edfd6565aec3a40c diff --git a/trunk/Documentation/input/iforce-protocol.txt b/trunk/Documentation/input/iforce-protocol.txt index 8777d2d321e3..95df4ca70e71 100644 --- a/trunk/Documentation/input/iforce-protocol.txt +++ b/trunk/Documentation/input/iforce-protocol.txt @@ -1,254 +1,254 @@ -** Introduction -This document describes what I managed to discover about the protocol used to -specify force effects to I-Force 2.0 devices. None of this information comes -from Immerse. That's why you should not trust what is written in this -document. This document is intended to help understanding the protocol. -This is not a reference. Comments and corrections are welcome. To contact me, -send an email to: deneux@ifrance.com - -** WARNING ** -I may not be held responsible for any dammage or harm caused if you try to -send data to your I-Force device based on what you read in this document. - -** Preliminary Notes: -All values are hexadecimal with big-endian encoding (msb on the left). Beware, -values inside packets are encoded using little-endian. Bytes whose roles are -unknown are marked ??? Information that needs deeper inspection is marked (?) - -** General form of a packet ** -This is how packets look when the device uses the rs232 to communicate. -2B OP LEN DATA CS -CS is the checksum. It is equal to the exclusive or of all bytes. - -When using USB: -OP DATA -The 2B, LEN and CS fields have disappeared, probably because USB handles frames and -data corruption is handled or unsignificant. - -First, I describe effects that are sent by the device to the computer - -** Device input state -This packet is used to indicate the state of each button and the value of each -axis -OP= 01 for a joystick, 03 for a wheel -LEN= Varies from device to device -00 X-Axis lsb -01 X-Axis msb -02 Y-Axis lsb, or gas pedal for a wheel -03 Y-Axis msb, or brake pedal for a wheel -04 Throttle -05 Buttons -06 Lower 4 bits: Buttons - Upper 4 bits: Hat -07 Rudder - -** Device effects states -OP= 02 -LEN= Varies -00 ? Bit 1 (Value 2) is the value of the deadman switch -01 Bit 8 is set if the effect is playing. Bits 0 to 7 are the effect id. -02 ?? -03 Address of parameter block changed (lsb) -04 Address of parameter block changed (msb) -05 Address of second parameter block changed (lsb) -... depending on the number of parameter blocks updated - -** Force effect ** -OP= 01 -LEN= 0e -00 Channel (when playing several effects at the same time, each must be assigned a channel) -01 Wave form - Val 00 Constant - Val 20 Square - Val 21 Triangle - Val 22 Sine - Val 23 Sawtooth up - Val 24 Sawtooth down - Val 40 Spring (Force = f(pos)) - Val 41 Friction (Force = f(velocity)) and Inertia (Force = f(acceleration)) - - -02 Axes affected and trigger - Bits 4-7: Val 2 = effect along one axis. Byte 05 indicates direction - Val 4 = X axis only. Byte 05 must contain 5a - Val 8 = Y axis only. Byte 05 must contain b4 - Val c = X and Y axes. Bytes 05 must contain 60 - Bits 0-3: Val 0 = No trigger - Val x+1 = Button x triggers the effect - When the whole byte is 0, cancel the previously set trigger - -03-04 Duration of effect (little endian encoding, in ms) - -05 Direction of effect, if applicable. Else, see 02 for value to assign. - -06-07 Minimum time between triggering. - -08-09 Address of periodicity or magnitude parameters -0a-0b Address of attack and fade parameters, or ffff if none. -*or* -08-09 Address of interactive parameters for X-axis, or ffff if not applicable -0a-0b Address of interactive parameters for Y-axis, or ffff if not applicable - -0c-0d Delay before execution of effect (little endian encoding, in ms) - - -** Time based parameters ** - -*** Attack and fade *** -OP= 02 -LEN= 08 -00-01 Address where to store the parameteres -02-03 Duration of attack (little endian encoding, in ms) -04 Level at end of attack. Signed byte. -05-06 Duration of fade. -07 Level at end of fade. - -*** Magnitude *** -OP= 03 -LEN= 03 -00-01 Address -02 Level. Signed byte. - -*** Periodicity *** -OP= 04 -LEN= 07 -00-01 Address -02 Magnitude. Signed byte. -03 Offset. Signed byte. -04 Phase. Val 00 = 0 deg, Val 40 = 90 degs. -05-06 Period (little endian encoding, in ms) - -** Interactive parameters ** -OP= 05 -LEN= 0a -00-01 Address -02 Positive Coeff -03 Negative Coeff -04+05 Offset (center) -06+07 Dead band (Val 01F4 = 5000 (decimal)) -08 Positive saturation (Val 0a = 1000 (decimal) Val 64 = 10000 (decimal)) -09 Negative saturation - -The encoding is a bit funny here: For coeffs, these are signed values. The -maximum value is 64 (100 decimal), the min is 9c. -For the offset, the minimum value is FE0C, the maximum value is 01F4. -For the deadband, the minimum value is 0, the max is 03E8. - -** Controls ** -OP= 41 -LEN= 03 -00 Channel -01 Start/Stop - Val 00: Stop - Val 01: Start and play once. - Val 41: Start and play n times (See byte 02 below) -02 Number of iterations n. - -** Init ** - -*** Querying features *** -OP= ff -Query command. Length varies according to the query type. -The general format of this packet is: -ff 01 QUERY [INDEX] CHECKSUM -reponses are of the same form: -FF LEN QUERY VALUE_QUERIED CHECKSUM2 -where LEN = 1 + length(VALUE_QUERIED) - -**** Query ram size **** -QUERY = 42 ('B'uffer size) -The device should reply with the same packet plus two additionnal bytes -containing the size of the memory: -ff 03 42 03 e8 CS would mean that the device has 1000 bytes of ram available. - -**** Query number of effects **** -QUERY = 4e ('N'umber of effects) -The device should respond by sending the number of effects that can be played -at the same time (one byte) -ff 02 4e 14 CS would stand for 20 effects. - -**** Vendor's id **** -QUERY = 4d ('M'anufacturer) -Query the vendors'id (2 bytes) - -**** Product id ***** -QUERY = 50 ('P'roduct) -Query the product id (2 bytes) - -**** Open device **** -QUERY = 4f ('O'pen) -No data returned. - -**** Close device ***** -QUERY = 43 ('C')lose -No data returned. - -**** Query effect **** -QUERY = 45 ('E') -Send effect type. -Returns nonzero if supported (2 bytes) - -**** Firmware Version **** -QUERY = 56 ('V'ersion) -Sends back 3 bytes - major, minor, subminor - -*** Initialisation of the device *** - -**** Set Control **** -!!! Device dependent, can be different on different models !!! -OP= 40 [] -LEN= 2 or 3 -00 Idx - Idx 00 Set dead zone (0..2048) - Idx 01 Ignore Deadman sensor (0..1) - Idx 02 Enable comm watchdog (0..1) - Idx 03 Set the strength of the spring (0..100) - Idx 04 Enable or disable the spring (0/1) - Idx 05 Set axis saturation threshold (0..2048) - -**** Set Effect State **** -OP= 42 -LEN= 1 -00 State - Bit 3 Pause force feedback - Bit 2 Enable force feedback - Bit 0 Stop all effects - -**** Set overall gain **** -OP= 43 -LEN= 1 -00 Gain - Val 00 = 0% - Val 40 = 50% - Val 80 = 100% - -** Parameter memory ** - -Each device has a certain amount of memory to store parameters of effects. -The amount of RAM may vary, I encountered values from 200 to 1000 bytes. Below -is the amount of memory apparently needed for every set of parameters: - - period : 0c - - magnitude : 02 - - attack and fade : 0e - - interactive : 08 - -** Appendix: How to study the protocol ? ** - -1. Generate effects using the force editor provided with the DirectX SDK, or use Immersion Studio (freely available at their web site in the developer section: www.immersion.com) -2. Start a soft spying RS232 or USB (depending on where you connected your joystick/wheel). I used ComPortSpy from fCoder (alpha version!) -3. Play the effect, and watch what happens on the spy screen. - -A few words about ComPortSpy: -At first glance, this soft seems, hum, well... buggy. In fact, data appear with a few seconds latency. Personnaly, I restart it every time I play an effect. -Remember it's free (as in free beer) and alpha! - -** URLS ** -Check www.immerse.com for Immersion Studio, and www.fcoder.com for ComPortSpy. - -** Author of this document ** -Johann Deneux -Home page at http://www.esil.univ-mrs.fr/~jdeneux/projects/ff/ - -Additions by Vojtech Pavlik. - -I-Force is trademark of Immersion Corp. +** Introduction +This document describes what I managed to discover about the protocol used to +specify force effects to I-Force 2.0 devices. None of this information comes +from Immerse. That's why you should not trust what is written in this +document. This document is intended to help understanding the protocol. +This is not a reference. Comments and corrections are welcome. To contact me, +send an email to: deneux@ifrance.com + +** WARNING ** +I may not be held responsible for any dammage or harm caused if you try to +send data to your I-Force device based on what you read in this document. + +** Preliminary Notes: +All values are hexadecimal with big-endian encoding (msb on the left). Beware, +values inside packets are encoded using little-endian. Bytes whose roles are +unknown are marked ??? Information that needs deeper inspection is marked (?) + +** General form of a packet ** +This is how packets look when the device uses the rs232 to communicate. +2B OP LEN DATA CS +CS is the checksum. It is equal to the exclusive or of all bytes. + +When using USB: +OP DATA +The 2B, LEN and CS fields have disappeared, probably because USB handles frames and +data corruption is handled or unsignificant. + +First, I describe effects that are sent by the device to the computer + +** Device input state +This packet is used to indicate the state of each button and the value of each +axis +OP= 01 for a joystick, 03 for a wheel +LEN= Varies from device to device +00 X-Axis lsb +01 X-Axis msb +02 Y-Axis lsb, or gas pedal for a wheel +03 Y-Axis msb, or brake pedal for a wheel +04 Throttle +05 Buttons +06 Lower 4 bits: Buttons + Upper 4 bits: Hat +07 Rudder + +** Device effects states +OP= 02 +LEN= Varies +00 ? Bit 1 (Value 2) is the value of the deadman switch +01 Bit 8 is set if the effect is playing. Bits 0 to 7 are the effect id. +02 ?? +03 Address of parameter block changed (lsb) +04 Address of parameter block changed (msb) +05 Address of second parameter block changed (lsb) +... depending on the number of parameter blocks updated + +** Force effect ** +OP= 01 +LEN= 0e +00 Channel (when playing several effects at the same time, each must be assigned a channel) +01 Wave form + Val 00 Constant + Val 20 Square + Val 21 Triangle + Val 22 Sine + Val 23 Sawtooth up + Val 24 Sawtooth down + Val 40 Spring (Force = f(pos)) + Val 41 Friction (Force = f(velocity)) and Inertia (Force = f(acceleration)) + + +02 Axes affected and trigger + Bits 4-7: Val 2 = effect along one axis. Byte 05 indicates direction + Val 4 = X axis only. Byte 05 must contain 5a + Val 8 = Y axis only. Byte 05 must contain b4 + Val c = X and Y axes. Bytes 05 must contain 60 + Bits 0-3: Val 0 = No trigger + Val x+1 = Button x triggers the effect + When the whole byte is 0, cancel the previously set trigger + +03-04 Duration of effect (little endian encoding, in ms) + +05 Direction of effect, if applicable. Else, see 02 for value to assign. + +06-07 Minimum time between triggering. + +08-09 Address of periodicity or magnitude parameters +0a-0b Address of attack and fade parameters, or ffff if none. +*or* +08-09 Address of interactive parameters for X-axis, or ffff if not applicable +0a-0b Address of interactive parameters for Y-axis, or ffff if not applicable + +0c-0d Delay before execution of effect (little endian encoding, in ms) + + +** Time based parameters ** + +*** Attack and fade *** +OP= 02 +LEN= 08 +00-01 Address where to store the parameteres +02-03 Duration of attack (little endian encoding, in ms) +04 Level at end of attack. Signed byte. +05-06 Duration of fade. +07 Level at end of fade. + +*** Magnitude *** +OP= 03 +LEN= 03 +00-01 Address +02 Level. Signed byte. + +*** Periodicity *** +OP= 04 +LEN= 07 +00-01 Address +02 Magnitude. Signed byte. +03 Offset. Signed byte. +04 Phase. Val 00 = 0 deg, Val 40 = 90 degs. +05-06 Period (little endian encoding, in ms) + +** Interactive parameters ** +OP= 05 +LEN= 0a +00-01 Address +02 Positive Coeff +03 Negative Coeff +04+05 Offset (center) +06+07 Dead band (Val 01F4 = 5000 (decimal)) +08 Positive saturation (Val 0a = 1000 (decimal) Val 64 = 10000 (decimal)) +09 Negative saturation + +The encoding is a bit funny here: For coeffs, these are signed values. The +maximum value is 64 (100 decimal), the min is 9c. +For the offset, the minimum value is FE0C, the maximum value is 01F4. +For the deadband, the minimum value is 0, the max is 03E8. + +** Controls ** +OP= 41 +LEN= 03 +00 Channel +01 Start/Stop + Val 00: Stop + Val 01: Start and play once. + Val 41: Start and play n times (See byte 02 below) +02 Number of iterations n. + +** Init ** + +*** Querying features *** +OP= ff +Query command. Length varies according to the query type. +The general format of this packet is: +ff 01 QUERY [INDEX] CHECKSUM +reponses are of the same form: +FF LEN QUERY VALUE_QUERIED CHECKSUM2 +where LEN = 1 + length(VALUE_QUERIED) + +**** Query ram size **** +QUERY = 42 ('B'uffer size) +The device should reply with the same packet plus two additionnal bytes +containing the size of the memory: +ff 03 42 03 e8 CS would mean that the device has 1000 bytes of ram available. + +**** Query number of effects **** +QUERY = 4e ('N'umber of effects) +The device should respond by sending the number of effects that can be played +at the same time (one byte) +ff 02 4e 14 CS would stand for 20 effects. + +**** Vendor's id **** +QUERY = 4d ('M'anufacturer) +Query the vendors'id (2 bytes) + +**** Product id ***** +QUERY = 50 ('P'roduct) +Query the product id (2 bytes) + +**** Open device **** +QUERY = 4f ('O'pen) +No data returned. + +**** Close device ***** +QUERY = 43 ('C')lose +No data returned. + +**** Query effect **** +QUERY = 45 ('E') +Send effect type. +Returns nonzero if supported (2 bytes) + +**** Firmware Version **** +QUERY = 56 ('V'ersion) +Sends back 3 bytes - major, minor, subminor + +*** Initialisation of the device *** + +**** Set Control **** +!!! Device dependent, can be different on different models !!! +OP= 40 [] +LEN= 2 or 3 +00 Idx + Idx 00 Set dead zone (0..2048) + Idx 01 Ignore Deadman sensor (0..1) + Idx 02 Enable comm watchdog (0..1) + Idx 03 Set the strength of the spring (0..100) + Idx 04 Enable or disable the spring (0/1) + Idx 05 Set axis saturation threshold (0..2048) + +**** Set Effect State **** +OP= 42 +LEN= 1 +00 State + Bit 3 Pause force feedback + Bit 2 Enable force feedback + Bit 0 Stop all effects + +**** Set overall gain **** +OP= 43 +LEN= 1 +00 Gain + Val 00 = 0% + Val 40 = 50% + Val 80 = 100% + +** Parameter memory ** + +Each device has a certain amount of memory to store parameters of effects. +The amount of RAM may vary, I encountered values from 200 to 1000 bytes. Below +is the amount of memory apparently needed for every set of parameters: + - period : 0c + - magnitude : 02 + - attack and fade : 0e + - interactive : 08 + +** Appendix: How to study the protocol ? ** + +1. Generate effects using the force editor provided with the DirectX SDK, or use Immersion Studio (freely available at their web site in the developer section: www.immersion.com) +2. Start a soft spying RS232 or USB (depending on where you connected your joystick/wheel). I used ComPortSpy from fCoder (alpha version!) +3. Play the effect, and watch what happens on the spy screen. + +A few words about ComPortSpy: +At first glance, this soft seems, hum, well... buggy. In fact, data appear with a few seconds latency. Personnaly, I restart it every time I play an effect. +Remember it's free (as in free beer) and alpha! + +** URLS ** +Check www.immerse.com for Immersion Studio, and www.fcoder.com for ComPortSpy. + +** Author of this document ** +Johann Deneux +Home page at http://www.esil.univ-mrs.fr/~jdeneux/projects/ff/ + +Additions by Vojtech Pavlik. + +I-Force is trademark of Immersion Corp. diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index 4d175c751246..586b6f85d4e0 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -1,5 +1,5 @@ - Kernel Parameters - ~~~~~~~~~~~~~~~~~ + Kernel Parameters + ~~~~~~~~~~~~~~~~~ The following is a consolidated list of the kernel parameters as implemented (mostly) by the __setup() macro and sorted into English Dictionary order @@ -1462,7 +1462,7 @@ and is between 256 and 4096 characters. It is defined in the file reboot= [BUGS=X86-32,BUGS=ARM,BUGS=IA-64] Rebooting mode Format: [,[,...]] - See arch/*/kernel/reboot.c or arch/*/kernel/process.c + See arch/*/kernel/reboot.c or arch/*/kernel/process.c reserve= [KNL,BUGS] Force the kernel to ignore some iomem area @@ -1550,12 +1550,12 @@ and is between 256 and 4096 characters. It is defined in the file selinux_compat_net = [SELINUX] Set initial selinux_compat_net flag value. - Format: { "0" | "1" } - 0 -- use new secmark-based packet controls - 1 -- use legacy packet controls - Default value is 0 (preferred). - Value can be changed at runtime via - /selinux/compat_net. + Format: { "0" | "1" } + 0 -- use new secmark-based packet controls + 1 -- use legacy packet controls + Default value is 0 (preferred). + Value can be changed at runtime via + /selinux/compat_net. serialnumber [BUGS=X86-32] @@ -1954,7 +1954,7 @@ and is between 256 and 4096 characters. It is defined in the file norandmaps Don't use address space randomization Equivalent to echo 0 > /proc/sys/kernel/randomize_va_space - unwind_debug=N N > 0 will enable dwarf2 unwinder debugging + unwind_debug=N N > 0 will enable dwarf2 unwinder debugging This is useful to get more information why you got a "dwarf2 unwinder stuck" diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 9a91d9e3f1f2..9c54a5ef0ba7 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -2622,8 +2622,8 @@ P: Harald Welte P: Jozsef Kadlecsik P: Patrick McHardy M: kaber@trash.net -L: netfilter-devel@vger.kernel.org -L: netfilter@vger.kernel.org +L: netfilter-devel@lists.netfilter.org +L: netfilter@lists.netfilter.org (subscribers-only) L: coreteam@netfilter.org W: http://www.netfilter.org/ W: http://www.iptables.org/ @@ -2676,7 +2676,7 @@ M: jmorris@namei.org P: Hideaki YOSHIFUJI M: yoshfuji@linux-ipv6.org P: Patrick McHardy -M: kaber@trash.net +M: kaber@coreworks.de L: netdev@vger.kernel.org T: git kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6.git S: Maintained diff --git a/trunk/Makefile b/trunk/Makefile index c265e41ec55a..e0fdf499ef20 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -1,8 +1,8 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 23 -EXTRAVERSION =-rc7 -NAME = Arr Matey! A Hairy Bilge Rat! +EXTRAVERSION =-rc6 +NAME = Pink Farting Weasel # *DOCUMENTATION* # To see a list of typical targets execute "make help" diff --git a/trunk/arch/arm/mm/cache-l2x0.c b/trunk/arch/arm/mm/cache-l2x0.c index b4e9b734e0bd..76b800a95191 100644 --- a/trunk/arch/arm/mm/cache-l2x0.c +++ b/trunk/arch/arm/mm/cache-l2x0.c @@ -57,7 +57,17 @@ static void l2x0_inv_range(unsigned long start, unsigned long end) { unsigned long addr; - start &= ~(CACHE_LINE_SIZE - 1); + if (start & (CACHE_LINE_SIZE - 1)) { + start &= ~(CACHE_LINE_SIZE - 1); + sync_writel(start, L2X0_CLEAN_INV_LINE_PA, 1); + start += CACHE_LINE_SIZE; + } + + if (end & (CACHE_LINE_SIZE - 1)) { + end &= ~(CACHE_LINE_SIZE - 1); + sync_writel(end, L2X0_CLEAN_INV_LINE_PA, 1); + } + for (addr = start; addr < end; addr += CACHE_LINE_SIZE) sync_writel(addr, L2X0_INV_LINE_PA, 1); cache_sync(); diff --git a/trunk/arch/i386/boot/header.S b/trunk/arch/i386/boot/header.S index f3140e596d40..7f4a2c53bd76 100644 --- a/trunk/arch/i386/boot/header.S +++ b/trunk/arch/i386/boot/header.S @@ -275,7 +275,7 @@ die: hlt jmp die - .size die, .-die + .size die, .-due .section ".initdata", "a" setup_corrupt: diff --git a/trunk/arch/i386/boot/video.c b/trunk/arch/i386/boot/video.c index e4ba897bf9a3..693f20d3102e 100644 --- a/trunk/arch/i386/boot/video.c +++ b/trunk/arch/i386/boot/video.c @@ -147,7 +147,7 @@ int mode_defined(u16 mode) } /* Set mode (without recalc) */ -static int raw_set_mode(u16 mode, u16 *real_mode) +static int raw_set_mode(u16 mode) { int nmode, i; struct card_info *card; @@ -165,10 +165,8 @@ static int raw_set_mode(u16 mode, u16 *real_mode) if ((mode == nmode && visible) || mode == mi->mode || - mode == (mi->y << 8)+mi->x) { - *real_mode = mi->mode; + mode == (mi->y << 8)+mi->x) return card->set_mode(mi); - } if (visible) nmode++; @@ -180,7 +178,7 @@ static int raw_set_mode(u16 mode, u16 *real_mode) if (mode >= card->xmode_first && mode < card->xmode_first+card->xmode_n) { struct mode_info mix; - *real_mode = mix.mode = mode; + mix.mode = mode; mix.x = mix.y = 0; return card->set_mode(&mix); } @@ -225,7 +223,6 @@ static void vga_recalc_vertical(void) static int set_mode(u16 mode) { int rv; - u16 real_mode; /* Very special mode numbers... */ if (mode == VIDEO_CURRENT_MODE) @@ -235,16 +232,13 @@ static int set_mode(u16 mode) else if (mode == EXTENDED_VGA) mode = VIDEO_8POINT; - rv = raw_set_mode(mode, &real_mode); + rv = raw_set_mode(mode); if (rv) return rv; if (mode & VIDEO_RECALC) vga_recalc_vertical(); - /* Save the canonical mode number for the kernel, not - an alias, size specification or menu position */ - boot_params.hdr.vid_mode = real_mode; return 0; } diff --git a/trunk/arch/i386/kernel/acpi/wakeup.S b/trunk/arch/i386/kernel/acpi/wakeup.S index f22ba8534d26..ed0a0f2c1597 100644 --- a/trunk/arch/i386/kernel/acpi/wakeup.S +++ b/trunk/arch/i386/kernel/acpi/wakeup.S @@ -151,30 +151,51 @@ bogus_real_magic: #define VIDEO_FIRST_V7 0x0900 # Setting of user mode (AX=mode ID) => CF=success - -# For now, we only handle VESA modes (0x0200..0x03ff). To handle other -# modes, we should probably compile in the video code from the boot -# directory. mode_set: movw %ax, %bx - subb $VIDEO_FIRST_VESA>>8, %bh - cmpb $2, %bh - jb check_vesa +#if 0 + cmpb $0xff, %ah + jz setalias + + testb $VIDEO_RECALC>>8, %ah + jnz _setrec + + cmpb $VIDEO_FIRST_RESOLUTION>>8, %ah + jnc setres + + cmpb $VIDEO_FIRST_SPECIAL>>8, %ah + jz setspc -setbad: - clc + cmpb $VIDEO_FIRST_V7>>8, %ah + jz setv7 +#endif + + cmpb $VIDEO_FIRST_VESA>>8, %ah + jnc check_vesa +#if 0 + orb %ah, %ah + jz setmenu +#endif + + decb %ah +# jz setbios Add bios modes later + +setbad: clc ret check_vesa: + subb $VIDEO_FIRST_VESA>>8, %bh orw $0x4000, %bx # Use linear frame buffer movw $0x4f02, %ax # VESA BIOS mode set call int $0x10 cmpw $0x004f, %ax # AL=4f if implemented - jnz setbad # AH=0 if OK + jnz _setbad # AH=0 if OK stc ret +_setbad: jmp setbad + .code32 ALIGN diff --git a/trunk/arch/i386/xen/enlighten.c b/trunk/arch/i386/xen/enlighten.c index f01bfcd4bdee..f0c37511d8da 100644 --- a/trunk/arch/i386/xen/enlighten.c +++ b/trunk/arch/i386/xen/enlighten.c @@ -623,8 +623,8 @@ static unsigned long xen_read_cr2_direct(void) static void xen_write_cr4(unsigned long cr4) { - /* Just ignore cr4 changes; Xen doesn't allow us to do - anything anyway. */ + /* never allow TSC to be disabled */ + native_write_cr4(cr4 & ~X86_CR4_TSD); } static unsigned long xen_read_cr3(void) diff --git a/trunk/arch/mips/dec/setup.c b/trunk/arch/mips/dec/setup.c index 3e634f2f5443..b8a5e75ba0ab 100644 --- a/trunk/arch/mips/dec/setup.c +++ b/trunk/arch/mips/dec/setup.c @@ -55,7 +55,7 @@ EXPORT_SYMBOL(dec_kn_slot_size); int dec_tc_bus; -DEFINE_SPINLOCK(ioasic_ssr_lock); +spinlock_t ioasic_ssr_lock; volatile u32 *ioasic_base; diff --git a/trunk/arch/mips/kernel/cpu-bugs64.c b/trunk/arch/mips/kernel/cpu-bugs64.c index 6648fde20b96..ac04f0adc408 100644 --- a/trunk/arch/mips/kernel/cpu-bugs64.c +++ b/trunk/arch/mips/kernel/cpu-bugs64.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2004, 2007 Maciej W. Rozycki + * Copyright (C) 2003, 2004 Maciej W. Rozycki * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -29,7 +29,7 @@ static inline void align_mod(const int align, const int mod) ".endr\n\t" ".set pop" : - : GCC_IMM_ASM (align), GCC_IMM_ASM (mod)); + : "rn" (align), "rn" (mod)); } static inline void mult_sh_align_mod(long *v1, long *v2, long *w, diff --git a/trunk/arch/mips/sibyte/bcm1480/setup.c b/trunk/arch/mips/sibyte/bcm1480/setup.c index 7e1aa348b8e0..bb28f28e8042 100644 --- a/trunk/arch/mips/sibyte/bcm1480/setup.c +++ b/trunk/arch/mips/sibyte/bcm1480/setup.c @@ -15,7 +15,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include #include #include #include @@ -36,7 +35,6 @@ unsigned int soc_type; EXPORT_SYMBOL(soc_type); unsigned int periph_rev; unsigned int zbbus_mhz; -EXPORT_SYMBOL(zbbus_mhz); static unsigned int part_type; diff --git a/trunk/arch/powerpc/kernel/time.c b/trunk/arch/powerpc/kernel/time.c index c627cf86d1e3..727a6699f2f4 100644 --- a/trunk/arch/powerpc/kernel/time.c +++ b/trunk/arch/powerpc/kernel/time.c @@ -239,7 +239,7 @@ static void snapshot_tb_and_purr(void *data) struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data); local_irq_save(flags); - p->tb = get_tb_or_rtc(); + p->tb = mftb(); p->purr = mfspr(SPRN_PURR); wmb(); p->initialized = 1; @@ -317,7 +317,7 @@ static void snapshot_purr(void) */ void snapshot_timebase(void) { - __get_cpu_var(last_jiffy) = get_tb_or_rtc(); + __get_cpu_var(last_jiffy) = get_tb(); snapshot_purr(); } @@ -684,8 +684,6 @@ void timer_interrupt(struct pt_regs * regs) write_seqlock(&xtime_lock); tb_next_jiffy = tb_last_jiffy + tb_ticks_per_jiffy; - if (__USE_RTC() && tb_next_jiffy >= 1000000000) - tb_next_jiffy -= 1000000000; if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) { tb_last_jiffy = tb_next_jiffy; do_timer(1); @@ -979,7 +977,7 @@ void __init time_init(void) tb_to_ns_scale = scale; tb_to_ns_shift = shift; /* Save the current timebase to pretty up CONFIG_PRINTK_TIME */ - boot_tb = get_tb_or_rtc(); + boot_tb = get_tb(); tm = get_boot_time(); diff --git a/trunk/arch/powerpc/kernel/vdso.c b/trunk/arch/powerpc/kernel/vdso.c index 213fa31ac537..cef01e4e8989 100644 --- a/trunk/arch/powerpc/kernel/vdso.c +++ b/trunk/arch/powerpc/kernel/vdso.c @@ -98,18 +98,6 @@ static struct vdso_patch_def vdso_patches[] = { CPU_FTR_USE_TB, 0, "__kernel_gettimeofday", NULL }, - { - CPU_FTR_USE_TB, 0, - "__kernel_clock_gettime", NULL - }, - { - CPU_FTR_USE_TB, 0, - "__kernel_clock_getres", NULL - }, - { - CPU_FTR_USE_TB, 0, - "__kernel_get_tbfreq", NULL - }, }; /* diff --git a/trunk/arch/powerpc/platforms/cell/spufs/sched.c b/trunk/arch/powerpc/platforms/cell/spufs/sched.c index 5bebe7fbe056..c784edd40ea7 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/sched.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/sched.c @@ -579,7 +579,7 @@ static struct spu *find_victim(struct spu_context *ctx) list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list) { struct spu_context *tmp = spu->ctx; - if (tmp && tmp->prio > ctx->prio && + if (tmp->prio > ctx->prio && (!victim || tmp->prio > victim->prio)) victim = spu->ctx; } @@ -611,9 +611,9 @@ static struct spu *find_victim(struct spu_context *ctx) mutex_lock(&cbe_spu_info[node].list_mutex); cbe_spu_info[node].nr_active--; - spu_unbind_context(spu, victim); mutex_unlock(&cbe_spu_info[node].list_mutex); + spu_unbind_context(spu, victim); victim->stats.invol_ctx_switch++; spu->stats.invol_ctx_switch++; mutex_unlock(&victim->state_mutex); diff --git a/trunk/arch/um/include/kern_util.h b/trunk/arch/um/include/kern_util.h index 6c2be26f1d7d..8d7f7c1cb9c6 100644 --- a/trunk/arch/um/include/kern_util.h +++ b/trunk/arch/um/include/kern_util.h @@ -117,7 +117,7 @@ extern void sigio_handler(int sig, union uml_pt_regs *regs); extern void copy_sc(union uml_pt_regs *regs, void *from); -extern unsigned long to_irq_stack(unsigned long *mask_out); +unsigned long to_irq_stack(int sig, unsigned long *mask_out); unsigned long from_irq_stack(int nested); #endif diff --git a/trunk/arch/um/kernel/irq.c b/trunk/arch/um/kernel/irq.c index cf0dd9cf8c43..9870febdbead 100644 --- a/trunk/arch/um/kernel/irq.c +++ b/trunk/arch/um/kernel/irq.c @@ -518,13 +518,13 @@ int init_aio_irq(int irq, char *name, irq_handler_t handler) static unsigned long pending_mask; -unsigned long to_irq_stack(unsigned long *mask_out) +unsigned long to_irq_stack(int sig, unsigned long *mask_out) { struct thread_info *ti; unsigned long mask, old; int nested; - mask = xchg(&pending_mask, *mask_out); + mask = xchg(&pending_mask, 1 << sig); if(mask != 0){ /* If any interrupts come in at this point, we want to * make sure that their bits aren't lost by our @@ -534,7 +534,7 @@ unsigned long to_irq_stack(unsigned long *mask_out) * and pending_mask contains a bit for each interrupt * that came in. */ - old = *mask_out; + old = 1 << sig; do { old |= mask; mask = xchg(&pending_mask, old); @@ -550,7 +550,6 @@ unsigned long to_irq_stack(unsigned long *mask_out) task = cpu_tasks[ti->cpu].task; tti = task_thread_info(task); - *ti = *tti; ti->real_thread = tti; task->stack = ti; diff --git a/trunk/arch/um/os-Linux/file.c b/trunk/arch/um/os-Linux/file.c index c3ecc2a84e0c..6f92f732d253 100644 --- a/trunk/arch/um/os-Linux/file.c +++ b/trunk/arch/um/os-Linux/file.c @@ -320,8 +320,7 @@ int os_file_size(char *file, unsigned long long *size_out) } if(S_ISBLK(buf.ust_mode)){ - int fd; - long blocks; + int fd, blocks; fd = os_open_file(file, of_read(OPENFLAGS()), 0); if(fd < 0){ diff --git a/trunk/arch/um/os-Linux/signal.c b/trunk/arch/um/os-Linux/signal.c index b98f7ea2d2f6..18e5c8b67eb8 100644 --- a/trunk/arch/um/os-Linux/signal.c +++ b/trunk/arch/um/os-Linux/signal.c @@ -119,7 +119,7 @@ void (*handlers[_NSIG])(int sig, struct sigcontext *sc); void handle_signal(int sig, struct sigcontext *sc) { - unsigned long pending = 1UL << sig; + unsigned long pending = 0; do { int nested, bail; @@ -134,7 +134,7 @@ void handle_signal(int sig, struct sigcontext *sc) * have to return, and the upper handler will deal * with this interrupt. */ - bail = to_irq_stack(&pending); + bail = to_irq_stack(sig, &pending); if(bail) return; diff --git a/trunk/arch/x86_64/Kconfig b/trunk/arch/x86_64/Kconfig index b4d9089a6a06..ffa036406289 100644 --- a/trunk/arch/x86_64/Kconfig +++ b/trunk/arch/x86_64/Kconfig @@ -60,6 +60,14 @@ config ZONE_DMA bool default y +config QUICKLIST + bool + default y + +config NR_QUICK + int + default 2 + config ISA bool diff --git a/trunk/arch/x86_64/ia32/ia32entry.S b/trunk/arch/x86_64/ia32/ia32entry.S index 18b231810908..938278697e20 100644 --- a/trunk/arch/x86_64/ia32/ia32entry.S +++ b/trunk/arch/x86_64/ia32/ia32entry.S @@ -38,18 +38,6 @@ movq %rax,R8(%rsp) .endm - .macro LOAD_ARGS32 offset - movl \offset(%rsp),%r11d - movl \offset+8(%rsp),%r10d - movl \offset+16(%rsp),%r9d - movl \offset+24(%rsp),%r8d - movl \offset+40(%rsp),%ecx - movl \offset+48(%rsp),%edx - movl \offset+56(%rsp),%esi - movl \offset+64(%rsp),%edi - movl \offset+72(%rsp),%eax - .endm - .macro CFI_STARTPROC32 simple CFI_STARTPROC \simple CFI_UNDEFINED r8 @@ -164,7 +152,7 @@ sysenter_tracesys: movq $-ENOSYS,RAX(%rsp) /* really needed? */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter - LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ + LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */ RESTORE_REST movl %ebp, %ebp /* no need to do an access_ok check here because rbp has been @@ -267,7 +255,7 @@ cstar_tracesys: movq $-ENOSYS,RAX(%rsp) /* really needed? */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter - LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ + LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */ RESTORE_REST movl RSP-ARGOFFSET(%rsp), %r8d /* no need to do an access_ok check here because r8 has been @@ -346,7 +334,7 @@ ia32_tracesys: movq $-ENOSYS,RAX(%rsp) /* really needed? */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter - LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ + LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */ RESTORE_REST jmp ia32_do_syscall END(ia32_syscall) diff --git a/trunk/arch/x86_64/kernel/acpi/wakeup.S b/trunk/arch/x86_64/kernel/acpi/wakeup.S index a06f2bcabef9..13f1480cbec9 100644 --- a/trunk/arch/x86_64/kernel/acpi/wakeup.S +++ b/trunk/arch/x86_64/kernel/acpi/wakeup.S @@ -81,7 +81,7 @@ wakeup_code: testl $2, realmode_flags - wakeup_code jz 1f mov video_mode - wakeup_code, %ax - call mode_set + call mode_seta 1: movw $0xb800, %ax @@ -291,31 +291,52 @@ no_longmode: #define VIDEO_FIRST_V7 0x0900 # Setting of user mode (AX=mode ID) => CF=success - -# For now, we only handle VESA modes (0x0200..0x03ff). To handle other -# modes, we should probably compile in the video code from the boot -# directory. .code16 -mode_set: +mode_seta: movw %ax, %bx - subb $VIDEO_FIRST_VESA>>8, %bh - cmpb $2, %bh - jb check_vesa +#if 0 + cmpb $0xff, %ah + jz setalias + + testb $VIDEO_RECALC>>8, %ah + jnz _setrec + + cmpb $VIDEO_FIRST_RESOLUTION>>8, %ah + jnc setres + + cmpb $VIDEO_FIRST_SPECIAL>>8, %ah + jz setspc -setbad: - clc + cmpb $VIDEO_FIRST_V7>>8, %ah + jz setv7 +#endif + + cmpb $VIDEO_FIRST_VESA>>8, %ah + jnc check_vesaa +#if 0 + orb %ah, %ah + jz setmenu +#endif + + decb %ah +# jz setbios Add bios modes later + +setbada: clc ret -check_vesa: +check_vesaa: + subb $VIDEO_FIRST_VESA>>8, %bh orw $0x4000, %bx # Use linear frame buffer movw $0x4f02, %ax # VESA BIOS mode set call int $0x10 cmpw $0x004f, %ax # AL=4f if implemented - jnz setbad # AH=0 if OK + jnz _setbada # AH=0 if OK stc ret +_setbada: jmp setbada + wakeup_stack_begin: # Stack grows down .org 0xff0 diff --git a/trunk/arch/x86_64/kernel/process.c b/trunk/arch/x86_64/kernel/process.c index 98956555450b..2842f50cbe3f 100644 --- a/trunk/arch/x86_64/kernel/process.c +++ b/trunk/arch/x86_64/kernel/process.c @@ -208,6 +208,7 @@ void cpu_idle (void) if (__get_cpu_var(cpu_idle_state)) __get_cpu_var(cpu_idle_state) = 0; + check_pgt_cache(); rmb(); idle = pm_idle; if (!idle) diff --git a/trunk/arch/x86_64/kernel/ptrace.c b/trunk/arch/x86_64/kernel/ptrace.c index eea3702427b4..e83cc67155ac 100644 --- a/trunk/arch/x86_64/kernel/ptrace.c +++ b/trunk/arch/x86_64/kernel/ptrace.c @@ -232,6 +232,10 @@ static int putreg(struct task_struct *child, { unsigned long tmp; + /* Some code in the 64bit emulation may not be 64bit clean. + Don't take any chances. */ + if (test_tsk_thread_flag(child, TIF_IA32)) + value &= 0xffffffff; switch (regno) { case offsetof(struct user_regs_struct,fs): if (value && (value & 3) != 3) diff --git a/trunk/arch/x86_64/kernel/smp.c b/trunk/arch/x86_64/kernel/smp.c index df4a82812adb..673a300b5944 100644 --- a/trunk/arch/x86_64/kernel/smp.c +++ b/trunk/arch/x86_64/kernel/smp.c @@ -241,7 +241,7 @@ void flush_tlb_mm (struct mm_struct * mm) } if (!cpus_empty(cpu_mask)) flush_tlb_others(cpu_mask, mm, FLUSH_ALL); - + check_pgt_cache(); preempt_enable(); } EXPORT_SYMBOL(flush_tlb_mm); diff --git a/trunk/arch/x86_64/mm/fault.c b/trunk/arch/x86_64/mm/fault.c index 54816adb8e93..327c9f2fa626 100644 --- a/trunk/arch/x86_64/mm/fault.c +++ b/trunk/arch/x86_64/mm/fault.c @@ -374,13 +374,6 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, if (unlikely(in_atomic() || !mm)) goto bad_area_nosemaphore; - /* - * User-mode registers count as a user access even for any - * potential system fault or CPU buglet. - */ - if (user_mode_vm(regs)) - error_code |= PF_USER; - again: /* When running in the kernel we expect faults to occur only to * addresses in user space. All other faults represent errors in the diff --git a/trunk/drivers/ata/ahci.c b/trunk/drivers/ata/ahci.c index c16820325d7b..06f212ff2b4f 100644 --- a/trunk/drivers/ata/ahci.c +++ b/trunk/drivers/ata/ahci.c @@ -418,12 +418,10 @@ static const struct pci_device_id ahci_pci_tbl[] = { /* ATI */ { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */ - { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb600 }, /* ATI SB700/800 */ - { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb600 }, /* ATI SB700/800 */ - { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb600 }, /* ATI SB700/800 */ - { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb600 }, /* ATI SB700/800 */ - { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb600 }, /* ATI SB700/800 */ - { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb600 }, /* ATI SB700/800 */ + { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb600 }, /* ATI SB700 IDE */ + { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb600 }, /* ATI SB700 AHCI */ + { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb600 }, /* ATI SB700 nraid5 */ + { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb600 }, /* ATI SB700 raid5 */ /* VIA */ { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */ diff --git a/trunk/drivers/ata/libata-core.c b/trunk/drivers/ata/libata-core.c index 772be09b4689..c43de9a710db 100644 --- a/trunk/drivers/ata/libata-core.c +++ b/trunk/drivers/ata/libata-core.c @@ -3778,9 +3778,6 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "Maxtor 6L250S0", "BANC1G10", ATA_HORKAGE_NONCQ }, { "Maxtor 6B200M0", "BANC1BM0", ATA_HORKAGE_NONCQ }, { "Maxtor 6B200M0", "BANC1B10", ATA_HORKAGE_NONCQ }, - { "Maxtor 7B250S0", "BANC1B70", ATA_HORKAGE_NONCQ, }, - { "Maxtor 7B300S0", "BANC1B70", ATA_HORKAGE_NONCQ }, - { "Maxtor 7V300F0", "VA111630", ATA_HORKAGE_NONCQ }, { "HITACHI HDS7250SASUN500G 0621KTAWSD", "K2AOAJ0AHITACHI", ATA_HORKAGE_NONCQ }, /* NCQ hard hangs device under heavier load, needs hard power cycle */ @@ -3797,7 +3794,6 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "WDC WD740ADFD-00NLR1", NULL, ATA_HORKAGE_NONCQ, }, { "FUJITSU MHV2080BH", "00840028", ATA_HORKAGE_NONCQ, }, { "ST9160821AS", "3.CLF", ATA_HORKAGE_NONCQ, }, - { "ST3160812AS", "3.AD", ATA_HORKAGE_NONCQ, }, { "SAMSUNG HD401LJ", "ZZ100-15", ATA_HORKAGE_NONCQ, }, /* devices which puke on READ_NATIVE_MAX */ diff --git a/trunk/drivers/ata/libata-sff.c b/trunk/drivers/ata/libata-sff.c index 8023167bbbeb..1cce2198baaf 100644 --- a/trunk/drivers/ata/libata-sff.c +++ b/trunk/drivers/ata/libata-sff.c @@ -297,7 +297,7 @@ void ata_bmdma_start (struct ata_queued_cmd *qc) dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD); iowrite8(dmactl | ATA_DMA_START, ap->ioaddr.bmdma_addr + ATA_DMA_CMD); - /* Strictly, one may wish to issue an ioread8() here, to + /* Strictly, one may wish to issue a readb() here, to * flush the mmio write. However, control also passes * to the hardware at this point, and it will interrupt * us when we are to resume control. So, in effect, @@ -307,9 +307,6 @@ void ata_bmdma_start (struct ata_queued_cmd *qc) * is expected, so I think it is best to not add a readb() * without first all the MMIO ATA cards/mobos. * Or maybe I'm just being paranoid. - * - * FIXME: The posting of this write means I/O starts are - * unneccessarily delayed for MMIO */ } diff --git a/trunk/drivers/base/core.c b/trunk/drivers/base/core.c index 6de33d7a29ba..e6738bcbe5a9 100644 --- a/trunk/drivers/base/core.c +++ b/trunk/drivers/base/core.c @@ -679,26 +679,14 @@ static int device_add_class_symlinks(struct device *dev) goto out_subsys; } if (dev->parent) { + error = sysfs_create_link(&dev->kobj, &dev->parent->kobj, + "device"); + if (error) + goto out_busid; #ifdef CONFIG_SYSFS_DEPRECATED { - struct device *parent = dev->parent; - char *class_name; - - /* - * In old sysfs stacked class devices had 'device' - * link pointing to real device instead of parent - */ - while (parent->class && !parent->bus && parent->parent) - parent = parent->parent; - - error = sysfs_create_link(&dev->kobj, - &parent->kobj, - "device"); - if (error) - goto out_busid; - - class_name = make_class_name(dev->class->name, - &dev->kobj); + char * class_name = make_class_name(dev->class->name, + &dev->kobj); if (class_name) error = sysfs_create_link(&dev->parent->kobj, &dev->kobj, class_name); @@ -706,11 +694,6 @@ static int device_add_class_symlinks(struct device *dev) if (error) goto out_device; } -#else - error = sysfs_create_link(&dev->kobj, &dev->parent->kobj, - "device"); - if (error) - goto out_busid; #endif } return 0; diff --git a/trunk/drivers/block/DAC960.c b/trunk/drivers/block/DAC960.c index 84d6aa500e26..504a95d888b2 100644 --- a/trunk/drivers/block/DAC960.c +++ b/trunk/drivers/block/DAC960.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/trunk/drivers/char/agp/agp.h b/trunk/drivers/char/agp/agp.h index 8955e7ff759a..35ab1a9f8e8b 100644 --- a/trunk/drivers/char/agp/agp.h +++ b/trunk/drivers/char/agp/agp.h @@ -176,7 +176,7 @@ struct agp_bridge_data { #define I830_GMCH_MEM_MASK 0x1 #define I830_GMCH_MEM_64M 0x1 #define I830_GMCH_MEM_128M 0 -#define I830_GMCH_GMS_MASK 0x70 +#define I830_GMCH_GMS_MASK 0xF0 #define I830_GMCH_GMS_DISABLED 0x00 #define I830_GMCH_GMS_LOCAL 0x10 #define I830_GMCH_GMS_STOLEN_512 0x20 @@ -190,7 +190,6 @@ struct agp_bridge_data { #define INTEL_I830_ERRSTS 0x92 /* Intel 855GM/852GM registers */ -#define I855_GMCH_GMS_MASK 0xF0 #define I855_GMCH_GMS_STOLEN_0M 0x0 #define I855_GMCH_GMS_STOLEN_1M (0x1 << 4) #define I855_GMCH_GMS_STOLEN_4M (0x2 << 4) diff --git a/trunk/drivers/char/agp/intel-agp.c b/trunk/drivers/char/agp/intel-agp.c index a5d0e95a227a..7c69bf259caa 100644 --- a/trunk/drivers/char/agp/intel-agp.c +++ b/trunk/drivers/char/agp/intel-agp.c @@ -511,7 +511,7 @@ static void intel_i830_init_gtt_entries(void) */ if (IS_G33) size = 0; - switch (gmch_ctrl & I855_GMCH_GMS_MASK) { + switch (gmch_ctrl & I830_GMCH_GMS_MASK) { case I855_GMCH_GMS_STOLEN_1M: gtt_entries = MB(1) - KB(size); break; diff --git a/trunk/drivers/char/ipmi/ipmi_si_intf.c b/trunk/drivers/char/ipmi/ipmi_si_intf.c index dd441ff4af56..9b07f7851061 100644 --- a/trunk/drivers/char/ipmi/ipmi_si_intf.c +++ b/trunk/drivers/char/ipmi/ipmi_si_intf.c @@ -2215,8 +2215,7 @@ static int ipmi_pci_resume(struct pci_dev *pdev) static struct pci_device_id ipmi_pci_devices[] = { { PCI_DEVICE(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID) }, - { PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) }, - { 0, } + { PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) } }; MODULE_DEVICE_TABLE(pci, ipmi_pci_devices); diff --git a/trunk/drivers/char/mspec.c b/trunk/drivers/char/mspec.c index 049a46cc9f87..c08a4152ee8f 100644 --- a/trunk/drivers/char/mspec.c +++ b/trunk/drivers/char/mspec.c @@ -67,7 +67,7 @@ /* * Page types allocated by the device. */ -enum mspec_page_type { +enum { MSPEC_FETCHOP = 1, MSPEC_CACHED, MSPEC_UNCACHED @@ -83,25 +83,15 @@ static int is_sn2; * One of these structures is allocated when an mspec region is mmaped. The * structure is pointed to by the vma->vm_private_data field in the vma struct. * This structure is used to record the addresses of the mspec pages. - * This structure is shared by all vma's that are split off from the - * original vma when split_vma()'s are done. - * - * The refcnt is incremented atomically because mm->mmap_sem does not - * protect in fork case where multiple tasks share the vma_data. */ struct vma_data { atomic_t refcnt; /* Number of vmas sharing the data. */ - spinlock_t lock; /* Serialize access to this structure. */ + spinlock_t lock; /* Serialize access to the vma. */ int count; /* Number of pages allocated. */ - enum mspec_page_type type; /* Type of pages allocated. */ - int flags; /* See VMD_xxx below. */ - unsigned long vm_start; /* Original (unsplit) base. */ - unsigned long vm_end; /* Original (unsplit) end. */ + int type; /* Type of pages allocated. */ unsigned long maddr[0]; /* Array of MSPEC addresses. */ }; -#define VMD_VMALLOCED 0x1 /* vmalloc'd rather than kmalloc'd */ - /* used on shub2 to clear FOP cache in the HUB */ static unsigned long scratch_page[MAX_NUMNODES]; #define SH2_AMO_CACHE_ENTRIES 4 @@ -139,8 +129,8 @@ mspec_zero_block(unsigned long addr, int len) * mspec_open * * Called when a device mapping is created by a means other than mmap - * (via fork, munmap, etc.). Increments the reference count on the - * underlying mspec data so it is not freed prematurely. + * (via fork, etc.). Increments the reference count on the underlying + * mspec data so it is not freed prematurely. */ static void mspec_open(struct vm_area_struct *vma) @@ -161,44 +151,34 @@ static void mspec_close(struct vm_area_struct *vma) { struct vma_data *vdata; - int index, last_index, result; - unsigned long my_page; + int i, pages, result, vdata_size; vdata = vma->vm_private_data; + if (!atomic_dec_and_test(&vdata->refcnt)) + return; - BUG_ON(vma->vm_start < vdata->vm_start || vma->vm_end > vdata->vm_end); - - spin_lock(&vdata->lock); - index = (vma->vm_start - vdata->vm_start) >> PAGE_SHIFT; - last_index = (vma->vm_end - vdata->vm_start) >> PAGE_SHIFT; - for (; index < last_index; index++) { - if (vdata->maddr[index] == 0) + pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; + vdata_size = sizeof(struct vma_data) + pages * sizeof(long); + for (i = 0; i < pages; i++) { + if (vdata->maddr[i] == 0) continue; /* * Clear the page before sticking it back * into the pool. */ - my_page = vdata->maddr[index]; - vdata->maddr[index] = 0; - spin_unlock(&vdata->lock); - result = mspec_zero_block(my_page, PAGE_SIZE); + result = mspec_zero_block(vdata->maddr[i], PAGE_SIZE); if (!result) - uncached_free_page(my_page); + uncached_free_page(vdata->maddr[i]); else printk(KERN_WARNING "mspec_close(): " "failed to zero page %i\n", result); - spin_lock(&vdata->lock); } - spin_unlock(&vdata->lock); - if (!atomic_dec_and_test(&vdata->refcnt)) - return; - - if (vdata->flags & VMD_VMALLOCED) - vfree(vdata); - else + if (vdata_size <= PAGE_SIZE) kfree(vdata); + else + vfree(vdata); } @@ -215,8 +195,7 @@ mspec_nopfn(struct vm_area_struct *vma, unsigned long address) int index; struct vma_data *vdata = vma->vm_private_data; - BUG_ON(address < vdata->vm_start || address >= vdata->vm_end); - index = (address - vdata->vm_start) >> PAGE_SHIFT; + index = (address - vma->vm_start) >> PAGE_SHIFT; maddr = (volatile unsigned long) vdata->maddr[index]; if (maddr == 0) { maddr = uncached_alloc_page(numa_node_id()); @@ -258,11 +237,10 @@ static struct vm_operations_struct mspec_vm_ops = { * underlying pages. */ static int -mspec_mmap(struct file *file, struct vm_area_struct *vma, - enum mspec_page_type type) +mspec_mmap(struct file *file, struct vm_area_struct *vma, int type) { struct vma_data *vdata; - int pages, vdata_size, flags = 0; + int pages, vdata_size; if (vma->vm_pgoff != 0) return -EINVAL; @@ -277,17 +255,12 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma, vdata_size = sizeof(struct vma_data) + pages * sizeof(long); if (vdata_size <= PAGE_SIZE) vdata = kmalloc(vdata_size, GFP_KERNEL); - else { + else vdata = vmalloc(vdata_size); - flags = VMD_VMALLOCED; - } if (!vdata) return -ENOMEM; memset(vdata, 0, vdata_size); - vdata->vm_start = vma->vm_start; - vdata->vm_end = vma->vm_end; - vdata->flags = flags; vdata->type = type; spin_lock_init(&vdata->lock); vdata->refcnt = ATOMIC_INIT(1); diff --git a/trunk/drivers/ide/ide-disk.c b/trunk/drivers/ide/ide-disk.c index 4754769eda97..eba1adbc1b6a 100644 --- a/trunk/drivers/ide/ide-disk.c +++ b/trunk/drivers/ide/ide-disk.c @@ -487,7 +487,6 @@ static inline int idedisk_supports_lba48(const struct hd_driveid *id) */ static const struct drive_list_entry hpa_list[] = { { "ST340823A", NULL }, - { "ST320413A", NULL }, { NULL, NULL } }; diff --git a/trunk/drivers/ide/ppc/pmac.c b/trunk/drivers/ide/ppc/pmac.c index f19eb6daeefd..4b13cd9a027d 100644 --- a/trunk/drivers/ide/ppc/pmac.c +++ b/trunk/drivers/ide/ppc/pmac.c @@ -1802,7 +1802,9 @@ pmac_ide_dma_check(ide_drive_t *drive) { struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); + pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data; int enable = 1; + int map; drive->using_dma = 0; if (drive->media == ide_floppy) diff --git a/trunk/drivers/ieee1394/ieee1394_core.c b/trunk/drivers/ieee1394/ieee1394_core.c index 98fd985a32ff..ee45259573c8 100644 --- a/trunk/drivers/ieee1394/ieee1394_core.c +++ b/trunk/drivers/ieee1394/ieee1394_core.c @@ -1273,7 +1273,7 @@ static void __exit ieee1394_cleanup(void) unregister_chrdev_region(IEEE1394_CORE_DEV, 256); } -module_init(ieee1394_init); +fs_initcall(ieee1394_init); /* same as ohci1394 */ module_exit(ieee1394_cleanup); /* Exported symbols */ diff --git a/trunk/drivers/ieee1394/ohci1394.c b/trunk/drivers/ieee1394/ohci1394.c index 372c5c16eb31..5667c8102efc 100644 --- a/trunk/drivers/ieee1394/ohci1394.c +++ b/trunk/drivers/ieee1394/ohci1394.c @@ -3537,5 +3537,7 @@ static int __init ohci1394_init(void) return pci_register_driver(&ohci1394_pci_driver); } -module_init(ohci1394_init); +/* Register before most other device drivers. + * Useful for remote debugging via physical DMA, e.g. using firescope. */ +fs_initcall(ohci1394_init); module_exit(ohci1394_cleanup); diff --git a/trunk/drivers/media/video/usbvision/usbvision-cards.c b/trunk/drivers/media/video/usbvision/usbvision-cards.c index f09eb102731b..380564cd3317 100644 --- a/trunk/drivers/media/video/usbvision/usbvision-cards.c +++ b/trunk/drivers/media/video/usbvision/usbvision-cards.c @@ -1081,7 +1081,6 @@ struct usb_device_id usbvision_table [] = { { USB_DEVICE(0x2304, 0x0301), .driver_info=PINNA_LINX_VD_IN_CAB_PAL }, { USB_DEVICE(0x2304, 0x0419), .driver_info=PINNA_PCTV_BUNGEE_PAL_FM }, { USB_DEVICE(0x2400, 0x4200), .driver_info=HPG_WINTV }, - { }, /* terminate list */ }; MODULE_DEVICE_TABLE (usb, usbvision_table); diff --git a/trunk/drivers/mtd/nand/cafe_nand.c b/trunk/drivers/mtd/nand/cafe_nand.c index 6f32a35eb106..cff969d05d4a 100644 --- a/trunk/drivers/mtd/nand/cafe_nand.c +++ b/trunk/drivers/mtd/nand/cafe_nand.c @@ -816,8 +816,7 @@ static void __devexit cafe_nand_remove(struct pci_dev *pdev) } static struct pci_device_id cafe_nand_tbl[] = { - { 0x11ab, 0x4100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MEMORY_FLASH << 8, 0xFFFF0 }, - { 0, } + { 0x11ab, 0x4100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MEMORY_FLASH << 8, 0xFFFF0 } }; MODULE_DEVICE_TABLE(pci, cafe_nand_tbl); diff --git a/trunk/drivers/net/bnx2.c b/trunk/drivers/net/bnx2.c index 66eed22cbd21..854d80c330ec 100644 --- a/trunk/drivers/net/bnx2.c +++ b/trunk/drivers/net/bnx2.c @@ -54,8 +54,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.6.5" -#define DRV_MODULE_RELDATE "September 20, 2007" +#define DRV_MODULE_VERSION "1.6.4" +#define DRV_MODULE_RELDATE "August 3, 2007" #define RUN_AT(x) (jiffies + (x)) @@ -6727,8 +6727,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) } else if (CHIP_NUM(bp) == CHIP_NUM_5706 || CHIP_NUM(bp) == CHIP_NUM_5708) bp->phy_flags |= PHY_CRC_FIX_FLAG; - else if (CHIP_ID(bp) == CHIP_ID_5709_A0 || - CHIP_ID(bp) == CHIP_ID_5709_A1) + else if (CHIP_ID(bp) == CHIP_ID_5709_A0) bp->phy_flags |= PHY_DIS_EARLY_DAC_FLAG; if ((CHIP_ID(bp) == CHIP_ID_5708_A0) || diff --git a/trunk/drivers/net/myri10ge/myri10ge.c b/trunk/drivers/net/myri10ge/myri10ge.c index 556962f9612d..1c42266bf889 100644 --- a/trunk/drivers/net/myri10ge/myri10ge.c +++ b/trunk/drivers/net/myri10ge/myri10ge.c @@ -3094,12 +3094,9 @@ static void myri10ge_remove(struct pci_dev *pdev) } #define PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E 0x0008 -#define PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E_9 0x0009 static struct pci_device_id myri10ge_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_MYRICOM, PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E)}, - {PCI_DEVICE - (PCI_VENDOR_ID_MYRICOM, PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E_9)}, {0}, }; diff --git a/trunk/drivers/net/phy/phy.c b/trunk/drivers/net/phy/phy.c index cb230f44d6fc..0cc4369cacba 100644 --- a/trunk/drivers/net/phy/phy.c +++ b/trunk/drivers/net/phy/phy.c @@ -409,7 +409,6 @@ int phy_mii_ioctl(struct phy_device *phydev, return 0; } -EXPORT_SYMBOL(phy_mii_ioctl); /** * phy_start_aneg - start auto-negotiation for this PHY device diff --git a/trunk/drivers/net/pppoe.c b/trunk/drivers/net/pppoe.c index 9b30cd600a64..0d7f570b9a54 100644 --- a/trunk/drivers/net/pppoe.c +++ b/trunk/drivers/net/pppoe.c @@ -879,7 +879,8 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb) dev->hard_header(skb, dev, ETH_P_PPP_SES, po->pppoe_pa.remote, NULL, data_len); - dev_queue_xmit(skb); + if (dev_queue_xmit(skb) < 0) + goto abort; return 1; diff --git a/trunk/drivers/net/pppol2tp.c b/trunk/drivers/net/pppol2tp.c index abe91cb595f4..266e8b38fe10 100644 --- a/trunk/drivers/net/pppol2tp.c +++ b/trunk/drivers/net/pppol2tp.c @@ -491,46 +491,44 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb) u16 hdrflags; u16 tunnel_id, session_id; int length; - int offset; + struct udphdr *uh; tunnel = pppol2tp_sock_to_tunnel(sock); if (tunnel == NULL) goto error; - /* UDP always verifies the packet length. */ - __skb_pull(skb, sizeof(struct udphdr)); - /* Short packet? */ - if (!pskb_may_pull(skb, 12)) { + if (skb->len < sizeof(struct udphdr)) { PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_INFO, "%s: recv short packet (len=%d)\n", tunnel->name, skb->len); goto error; } /* Point to L2TP header */ - ptr = skb->data; + ptr = skb->data + sizeof(struct udphdr); /* Get L2TP header flags */ hdrflags = ntohs(*(__be16*)ptr); /* Trace packet contents, if enabled */ if (tunnel->debug & PPPOL2TP_MSG_DATA) { - length = min(16u, skb->len); - if (!pskb_may_pull(skb, length)) - goto error; - printk(KERN_DEBUG "%s: recv: ", tunnel->name); - offset = 0; - do { - printk(" %02X", ptr[offset]); - } while (++offset < length); - + for (length = 0; length < 16; length++) + printk(" %02X", ptr[length]); printk("\n"); } /* Get length of L2TP packet */ - length = skb->len; + uh = (struct udphdr *) skb_transport_header(skb); + length = ntohs(uh->len) - sizeof(struct udphdr); + + /* Too short? */ + if (length < 12) { + PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_INFO, + "%s: recv short L2TP packet (len=%d)\n", tunnel->name, length); + goto error; + } /* If type is control packet, it is handled by userspace. */ if (hdrflags & L2TP_HDRFLAG_T) { @@ -608,6 +606,7 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb) "%s: recv data has no seq numbers when required. " "Discarding\n", session->name); session->stats.rx_seq_discards++; + session->stats.rx_errors++; goto discard; } @@ -626,6 +625,7 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb) "%s: recv data has no seq numbers when required. " "Discarding\n", session->name); session->stats.rx_seq_discards++; + session->stats.rx_errors++; goto discard; } @@ -634,14 +634,10 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb) } /* If offset bit set, skip it. */ - if (hdrflags & L2TP_HDRFLAG_O) { - offset = ntohs(*(__be16 *)ptr); - skb->transport_header += 2 + offset; - if (!pskb_may_pull(skb, skb_transport_offset(skb) + 2)) - goto discard; - } + if (hdrflags & L2TP_HDRFLAG_O) + ptr += 2 + ntohs(*(__be16 *) ptr); - __skb_pull(skb, skb_transport_offset(skb)); + skb_pull(skb, ptr - skb->data); /* Skip PPP header, if present. In testing, Microsoft L2TP clients * don't send the PPP header (PPP header compression enabled), but @@ -677,6 +673,7 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb) */ if (PPPOL2TP_SKB_CB(skb)->ns != session->nr) { session->stats.rx_seq_discards++; + session->stats.rx_errors++; PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG, "%s: oos pkt %hu len %d discarded, " "waiting for %hu, reorder_q_len=%d\n", @@ -701,7 +698,6 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb) return 0; discard: - session->stats.rx_errors++; kfree_skb(skb); sock_put(session->sock); @@ -962,6 +958,7 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) int data_len = skb->len; struct inet_sock *inet; __wsum csum = 0; + struct sk_buff *skb2 = NULL; struct udphdr *uh; unsigned int len; @@ -992,30 +989,41 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) */ headroom = NET_SKB_PAD + sizeof(struct iphdr) + sizeof(struct udphdr) + hdr_len + sizeof(ppph); - if (skb_cow_head(skb, headroom)) - goto abort; + if (skb_headroom(skb) < headroom) { + skb2 = skb_realloc_headroom(skb, headroom); + if (skb2 == NULL) + goto abort; + } else + skb2 = skb; + + /* Check that the socket has room */ + if (atomic_read(&sk_tun->sk_wmem_alloc) < sk_tun->sk_sndbuf) + skb_set_owner_w(skb2, sk_tun); + else + goto discard; /* Setup PPP header */ - __skb_push(skb, sizeof(ppph)); - skb->data[0] = ppph[0]; - skb->data[1] = ppph[1]; + skb_push(skb2, sizeof(ppph)); + skb2->data[0] = ppph[0]; + skb2->data[1] = ppph[1]; /* Setup L2TP header */ - pppol2tp_build_l2tp_header(session, __skb_push(skb, hdr_len)); + skb_push(skb2, hdr_len); + pppol2tp_build_l2tp_header(session, skb2->data); /* Setup UDP header */ inet = inet_sk(sk_tun); - __skb_push(skb, sizeof(*uh)); - skb_reset_transport_header(skb); - uh = udp_hdr(skb); + skb_push(skb2, sizeof(struct udphdr)); + skb_reset_transport_header(skb2); + uh = (struct udphdr *) skb2->data; uh->source = inet->sport; uh->dest = inet->dport; uh->len = htons(sizeof(struct udphdr) + hdr_len + sizeof(ppph) + data_len); uh->check = 0; - /* *BROKEN* Calculate UDP checksum if configured to do so */ + /* Calculate UDP checksum if configured to do so */ if (sk_tun->sk_no_check != UDP_CSUM_NOXMIT) - csum = udp_csum_outgoing(sk_tun, skb); + csum = udp_csum_outgoing(sk_tun, skb2); /* Debug */ if (session->send_seq) @@ -1028,7 +1036,7 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) if (session->debug & PPPOL2TP_MSG_DATA) { int i; - unsigned char *datap = skb->data; + unsigned char *datap = skb2->data; printk(KERN_DEBUG "%s: xmit:", session->name); for (i = 0; i < data_len; i++) { @@ -1041,18 +1049,18 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) printk("\n"); } - memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); - IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | - IPSKB_REROUTED); - nf_reset(skb); + memset(&(IPCB(skb2)->opt), 0, sizeof(IPCB(skb2)->opt)); + IPCB(skb2)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | + IPSKB_REROUTED); + nf_reset(skb2); /* Get routing info from the tunnel socket */ - dst_release(skb->dst); - skb->dst = sk_dst_get(sk_tun); + dst_release(skb2->dst); + skb2->dst = sk_dst_get(sk_tun); /* Queue the packet to IP for output */ - len = skb->len; - rc = ip_queue_xmit(skb, 1); + len = skb2->len; + rc = ip_queue_xmit(skb2, 1); /* Update stats */ if (rc >= 0) { @@ -1065,12 +1073,17 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) session->stats.tx_errors++; } - return 1; - -abort: /* Free the original skb */ kfree_skb(skb); + return 1; + +discard: + /* Free the new skb. Caller will free original skb. */ + if (skb2 != skb) + kfree_skb(skb2); +abort: + return 0; } /***************************************************************************** @@ -1313,14 +1326,12 @@ static struct sock *pppol2tp_prepare_tunnel_socket(int fd, u16 tunnel_id, goto err; } - sk = sock->sk; - /* Quick sanity checks */ - err = -EPROTONOSUPPORT; - if (sk->sk_protocol != IPPROTO_UDP) { + err = -ESOCKTNOSUPPORT; + if (sock->type != SOCK_DGRAM) { PRINTK(-1, PPPOL2TP_MSG_CONTROL, KERN_ERR, - "tunl %hu: fd %d wrong protocol, got %d, expected %d\n", - tunnel_id, fd, sk->sk_protocol, IPPROTO_UDP); + "tunl %hu: fd %d wrong type, got %d, expected %d\n", + tunnel_id, fd, sock->type, SOCK_DGRAM); goto err; } err = -EAFNOSUPPORT; @@ -1332,6 +1343,7 @@ static struct sock *pppol2tp_prepare_tunnel_socket(int fd, u16 tunnel_id, } err = -ENOTCONN; + sk = sock->sk; /* Check if this socket has already been prepped */ tunnel = (struct pppol2tp_tunnel *)sk->sk_user_data; diff --git a/trunk/drivers/net/sky2.c b/trunk/drivers/net/sky2.c index eaffe551d1d8..5d812de65d90 100644 --- a/trunk/drivers/net/sky2.c +++ b/trunk/drivers/net/sky2.c @@ -51,7 +51,7 @@ #include "sky2.h" #define DRV_NAME "sky2" -#define DRV_VERSION "1.18" +#define DRV_VERSION "1.17" #define PFX DRV_NAME " " /* @@ -118,15 +118,12 @@ static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4351) }, /* 88E8036 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4352) }, /* 88E8038 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) }, /* 88E8039 */ - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4354) }, /* 88E8040 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4356) }, /* 88EC033 */ - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x435A) }, /* 88E8048 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) }, /* 88E8052 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) }, /* 88E8053 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) }, /* 88E8055 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) }, /* 88E8056 */ - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4365) }, /* 88E8070 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, /* 88EC036 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, /* 88EC032 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */ @@ -150,7 +147,6 @@ static const char *yukon2_name[] = { "Extreme", /* 0xb5 */ "EC", /* 0xb6 */ "FE", /* 0xb7 */ - "FE+", /* 0xb8 */ }; static void sky2_set_multicast(struct net_device *dev); @@ -221,7 +217,8 @@ static void sky2_power_on(struct sky2_hw *hw) else sky2_write8(hw, B2_Y2_CLK_GATE, 0); - if (hw->flags & SKY2_HW_ADV_POWER_CTL) { + if (hw->chip_id == CHIP_ID_YUKON_EC_U || + hw->chip_id == CHIP_ID_YUKON_EX) { u32 reg; sky2_pci_write32(hw, PCI_DEV_REG3, 0); @@ -314,8 +311,10 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) struct sky2_port *sky2 = netdev_priv(hw->dev[port]); u16 ctrl, ct1000, adv, pg, ledctrl, ledover, reg; - if (sky2->autoneg == AUTONEG_ENABLE && - !(hw->flags & SKY2_HW_NEWER_PHY)) { + if (sky2->autoneg == AUTONEG_ENABLE + && !(hw->chip_id == CHIP_ID_YUKON_XL + || hw->chip_id == CHIP_ID_YUKON_EC_U + || hw->chip_id == CHIP_ID_YUKON_EX)) { u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | @@ -335,7 +334,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); if (sky2_is_copper(hw)) { - if (!(hw->flags & SKY2_HW_GIGABIT)) { + if (hw->chip_id == CHIP_ID_YUKON_FE) { /* enable automatic crossover */ ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1; } else { @@ -347,7 +346,9 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) /* downshift on PHY 88E1112 and 88E1149 is changed */ if (sky2->autoneg == AUTONEG_ENABLE - && (hw->flags & SKY2_HW_NEWER_PHY)) { + && (hw->chip_id == CHIP_ID_YUKON_XL + || hw->chip_id == CHIP_ID_YUKON_EC_U + || hw->chip_id == CHIP_ID_YUKON_EX)) { /* set downshift counter to 3x and enable downshift */ ctrl &= ~PHY_M_PC_DSC_MSK; ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA; @@ -363,7 +364,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); /* special setup for PHY 88E1112 Fiber */ - if (hw->chip_id == CHIP_ID_YUKON_XL && (hw->flags & SKY2_HW_FIBRE_PHY)) { + if (hw->chip_id == CHIP_ID_YUKON_XL && !sky2_is_copper(hw)) { pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); /* Fiber: select 1000BASE-X only mode MAC Specific Ctrl Reg. */ @@ -454,7 +455,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) gma_write16(hw, port, GM_GP_CTRL, reg); - if (hw->flags & SKY2_HW_GIGABIT) + if (hw->chip_id != CHIP_ID_YUKON_FE) gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000); gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv); @@ -478,23 +479,6 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl); break; - case CHIP_ID_YUKON_FE_P: - /* Enable Link Partner Next Page */ - ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); - ctrl |= PHY_M_PC_ENA_LIP_NP; - - /* disable Energy Detect and enable scrambler */ - ctrl &= ~(PHY_M_PC_ENA_ENE_DT | PHY_M_PC_DIS_SCRAMB); - gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); - - /* set LED2 -> ACT, LED1 -> LINK, LED0 -> SPEED */ - ctrl = PHY_M_FELP_LED2_CTRL(LED_PAR_CTRL_ACT_BL) | - PHY_M_FELP_LED1_CTRL(LED_PAR_CTRL_LINK) | - PHY_M_FELP_LED0_CTRL(LED_PAR_CTRL_SPEED); - - gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl); - break; - case CHIP_ID_YUKON_XL: pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); @@ -564,13 +548,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) /* set page register to 0 */ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0); - } else if (hw->chip_id == CHIP_ID_YUKON_FE_P && - hw->chip_rev == CHIP_REV_YU_FE2_A0) { - /* apply workaround for integrated resistors calibration */ - gm_phy_write(hw, port, PHY_MARV_PAGE_ADDR, 17); - gm_phy_write(hw, port, PHY_MARV_PAGE_DATA, 0x3f60); } else if (hw->chip_id != CHIP_ID_YUKON_EX) { - /* no effect on Yukon-XL */ gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) { @@ -691,25 +669,25 @@ static void sky2_wol_init(struct sky2_port *sky2) static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port) { - struct net_device *dev = hw->dev[port]; - - if (dev->mtu <= ETH_DATA_LEN) + if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev != CHIP_REV_YU_EX_A0) { sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), - TX_JUMBO_DIS | TX_STFW_ENA); - - else if (hw->chip_id != CHIP_ID_YUKON_EC_U) - sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), - TX_STFW_ENA | TX_JUMBO_ENA); - else { - /* set Tx GMAC FIFO Almost Empty Threshold */ - sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR), - (ECU_JUMBO_WM << 16) | ECU_AE_THR); + TX_STFW_ENA | + (hw->dev[port]->mtu > ETH_DATA_LEN) ? TX_JUMBO_ENA : TX_JUMBO_DIS); + } else { + if (hw->dev[port]->mtu > ETH_DATA_LEN) { + /* set Tx GMAC FIFO Almost Empty Threshold */ + sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR), + (ECU_JUMBO_WM << 16) | ECU_AE_THR); - sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), - TX_JUMBO_ENA | TX_STFW_DIS); + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), + TX_JUMBO_ENA | TX_STFW_DIS); - /* Can't do offload because of lack of store/forward */ - dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | NETIF_F_ALL_CSUM); + /* Can't do offload because of lack of store/forward */ + hw->dev[port]->features &= ~(NETIF_F_TSO | NETIF_F_SG + | NETIF_F_ALL_CSUM); + } else + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), + TX_JUMBO_DIS | TX_STFW_ENA); } } @@ -795,8 +773,7 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) /* Configure Rx MAC FIFO */ sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR); rx_reg = GMF_OPER_ON | GMF_RX_F_FL_ON; - if (hw->chip_id == CHIP_ID_YUKON_EX || - hw->chip_id == CHIP_ID_YUKON_FE_P) + if (hw->chip_id == CHIP_ID_YUKON_EX) rx_reg |= GMF_RX_OVER_ON; sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), rx_reg); @@ -805,18 +782,13 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR); /* Set threshold to 0xa (64 bytes) + 1 to workaround pause bug */ - reg = RX_GMF_FL_THR_DEF + 1; - /* Another magic mystery workaround from sk98lin */ - if (hw->chip_id == CHIP_ID_YUKON_FE_P && - hw->chip_rev == CHIP_REV_YU_FE2_A0) - reg = 0x178; - sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), reg); + sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF+1); /* Configure Tx MAC FIFO */ sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR); sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); - if (!(hw->flags & SKY2_HW_RAMBUFFER)) { + if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) { sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8); sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8); @@ -995,15 +967,19 @@ static void sky2_rx_unmap_skb(struct pci_dev *pdev, struct rx_ring_info *re) */ static void rx_set_checksum(struct sky2_port *sky2) { - struct sky2_rx_le *le = sky2_next_rx(sky2); + struct sky2_rx_le *le; - le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN); - le->ctrl = 0; - le->opcode = OP_TCPSTART | HW_OWNER; + if (sky2->hw->chip_id != CHIP_ID_YUKON_EX) { + le = sky2_next_rx(sky2); + le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN); + le->ctrl = 0; + le->opcode = OP_TCPSTART | HW_OWNER; + + sky2_write32(sky2->hw, + Q_ADDR(rxqaddr[sky2->port], Q_CSR), + sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); + } - sky2_write32(sky2->hw, - Q_ADDR(rxqaddr[sky2->port], Q_CSR), - sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); } /* @@ -1199,8 +1175,7 @@ static int sky2_rx_start(struct sky2_port *sky2) sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1); - if (!(hw->flags & SKY2_HW_NEW_LE)) - rx_set_checksum(sky2); + rx_set_checksum(sky2); /* Space needed for frame data + headers rounded up */ size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8); @@ -1271,7 +1246,7 @@ static int sky2_up(struct net_device *dev) struct sky2_port *sky2 = netdev_priv(dev); struct sky2_hw *hw = sky2->hw; unsigned port = sky2->port; - u32 imask; + u32 ramsize, imask; int cap, err = -ENOMEM; struct net_device *otherdev = hw->dev[sky2->port^1]; @@ -1326,12 +1301,12 @@ static int sky2_up(struct net_device *dev) sky2_mac_init(hw, port); - if (hw->flags & SKY2_HW_RAMBUFFER) { - /* Register is number of 4K blocks on internal RAM buffer. */ - u32 ramsize = sky2_read8(hw, B2_E_0) * 4; - u32 rxspace; + /* Register is number of 4K blocks on internal RAM buffer. */ + ramsize = sky2_read8(hw, B2_E_0) * 4; + printk(KERN_INFO PFX "%s: ram buffer %dK\n", dev->name, ramsize); - printk(KERN_DEBUG PFX "%s: ram buffer %dK\n", dev->name, ramsize); + if (ramsize > 0) { + u32 rxspace; if (ramsize < 16) rxspace = ramsize / 2; @@ -1461,15 +1436,13 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) /* Check for TCP Segmentation Offload */ mss = skb_shinfo(skb)->gso_size; if (mss != 0) { - - if (!(hw->flags & SKY2_HW_NEW_LE)) + if (hw->chip_id != CHIP_ID_YUKON_EX) mss += ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb); if (mss != sky2->tx_last_mss) { le = get_tx_le(sky2); le->addr = cpu_to_le32(mss); - - if (hw->flags & SKY2_HW_NEW_LE) + if (hw->chip_id == CHIP_ID_YUKON_EX) le->opcode = OP_MSS | HW_OWNER; else le->opcode = OP_LRGLEN | HW_OWNER; @@ -1495,7 +1468,8 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) /* Handle TCP checksum offload */ if (skb->ip_summed == CHECKSUM_PARTIAL) { /* On Yukon EX (some versions) encoding change. */ - if (hw->flags & SKY2_HW_AUTO_TX_SUM) + if (hw->chip_id == CHIP_ID_YUKON_EX + && hw->chip_rev != CHIP_REV_YU_EX_B0) ctrl |= CALSUM; /* auto checksum */ else { const unsigned offset = skb_transport_offset(skb); @@ -1648,6 +1622,9 @@ static int sky2_down(struct net_device *dev) if (netif_msg_ifdown(sky2)) printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); + if (netif_carrier_ok(dev) && --hw->active == 0) + del_timer(&hw->watchdog_timer); + /* Stop more packets from being queued */ netif_stop_queue(dev); @@ -1731,15 +1708,11 @@ static int sky2_down(struct net_device *dev) static u16 sky2_phy_speed(const struct sky2_hw *hw, u16 aux) { - if (hw->flags & SKY2_HW_FIBRE_PHY) + if (!sky2_is_copper(hw)) return SPEED_1000; - if (!(hw->flags & SKY2_HW_GIGABIT)) { - if (aux & PHY_M_PS_SPEED_100) - return SPEED_100; - else - return SPEED_10; - } + if (hw->chip_id == CHIP_ID_YUKON_FE) + return (aux & PHY_M_PS_SPEED_100) ? SPEED_100 : SPEED_10; switch (aux & PHY_M_PS_SPEED_MSK) { case PHY_M_PS_SPEED_1000: @@ -1772,13 +1745,17 @@ static void sky2_link_up(struct sky2_port *sky2) netif_carrier_on(sky2->netdev); - mod_timer(&hw->watchdog_timer, jiffies + 1); + if (hw->active++ == 0) + mod_timer(&hw->watchdog_timer, jiffies + 1); + /* Turn on link LED */ sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF); - if (hw->flags & SKY2_HW_NEWER_PHY) { + if (hw->chip_id == CHIP_ID_YUKON_XL + || hw->chip_id == CHIP_ID_YUKON_EC_U + || hw->chip_id == CHIP_ID_YUKON_EX) { u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); u16 led = PHY_M_LEDC_LOS_CTRL(1); /* link active */ @@ -1823,6 +1800,11 @@ static void sky2_link_down(struct sky2_port *sky2) netif_carrier_off(sky2->netdev); + /* Stop watchdog if both ports are not active */ + if (--hw->active == 0) + del_timer(&hw->watchdog_timer); + + /* Turn on link LED */ sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); @@ -1865,7 +1847,7 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux) /* Since the pause result bits seem to in different positions on * different chips. look at registers. */ - if (hw->flags & SKY2_HW_FIBRE_PHY) { + if (!sky2_is_copper(hw)) { /* Shift for bits in fiber PHY */ advert &= ~(ADVERTISE_PAUSE_CAP|ADVERTISE_PAUSE_ASYM); lpa &= ~(LPA_PAUSE_CAP|LPA_PAUSE_ASYM); @@ -1976,9 +1958,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) return -EINVAL; - if (new_mtu > ETH_DATA_LEN && - (hw->chip_id == CHIP_ID_YUKON_FE || - hw->chip_id == CHIP_ID_YUKON_FE_P)) + if (new_mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_FE) return -EINVAL; if (!netif_running(dev)) { @@ -1995,7 +1975,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) synchronize_irq(hw->pdev->irq); - if (!(hw->flags & SKY2_HW_RAMBUFFER)) + if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) sky2_set_tx_stfwd(hw, port); ctl = gma_read16(hw, port, GM_GP_CTRL); @@ -2123,13 +2103,6 @@ static struct sk_buff *sky2_receive(struct net_device *dev, struct sky2_port *sky2 = netdev_priv(dev); struct rx_ring_info *re = sky2->rx_ring + sky2->rx_next; struct sk_buff *skb = NULL; - u16 count = (status & GMR_FS_LEN) >> 16; - -#ifdef SKY2_VLAN_TAG_USED - /* Account for vlan tag */ - if (sky2->vlgrp && (status & GMR_FS_VLAN)) - count -= VLAN_HLEN; -#endif if (unlikely(netif_msg_rx_status(sky2))) printk(KERN_DEBUG PFX "%s: rx slot %u status 0x%x len %d\n", @@ -2144,8 +2117,7 @@ static struct sk_buff *sky2_receive(struct net_device *dev, if (!(status & GMR_FS_RX_OK)) goto resubmit; - /* if length reported by DMA does not match PHY, packet was truncated */ - if (length != count) + if (status >> 16 != length) goto len_mismatch; if (length < copybreak) @@ -2161,10 +2133,6 @@ static struct sk_buff *sky2_receive(struct net_device *dev, /* Truncation of overlength packets causes PHY length to not match MAC length */ ++sky2->net_stats.rx_length_errors; - if (netif_msg_rx_err(sky2) && net_ratelimit()) - pr_info(PFX "%s: rx length mismatch: length %d status %#x\n", - dev->name, length, status); - goto resubmit; error: ++sky2->net_stats.rx_errors; @@ -2234,7 +2202,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) } /* This chip reports checksum status differently */ - if (hw->flags & SKY2_HW_NEW_LE) { + if (hw->chip_id == CHIP_ID_YUKON_EX) { if (sky2->rx_csum && (le->css & (CSS_ISIPV4 | CSS_ISIPV6)) && (le->css & CSS_TCPUDPCSOK)) @@ -2275,14 +2243,8 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) if (!sky2->rx_csum) break; - /* If this happens then driver assuming wrong format */ - if (unlikely(hw->flags & SKY2_HW_NEW_LE)) { - if (net_ratelimit()) - printk(KERN_NOTICE "%s: unexpected" - " checksum status\n", - dev->name); + if (hw->chip_id == CHIP_ID_YUKON_EX) break; - } /* Both checksum counters are programmed to start at * the same offset, so unless there is a problem they @@ -2474,72 +2436,20 @@ static void sky2_le_error(struct sky2_hw *hw, unsigned port, sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_CLR_IRQ_CHK); } -static int sky2_rx_hung(struct net_device *dev) -{ - struct sky2_port *sky2 = netdev_priv(dev); - struct sky2_hw *hw = sky2->hw; - unsigned port = sky2->port; - unsigned rxq = rxqaddr[port]; - u32 mac_rp = sky2_read32(hw, SK_REG(port, RX_GMF_RP)); - u8 mac_lev = sky2_read8(hw, SK_REG(port, RX_GMF_RLEV)); - u8 fifo_rp = sky2_read8(hw, Q_ADDR(rxq, Q_RP)); - u8 fifo_lev = sky2_read8(hw, Q_ADDR(rxq, Q_RL)); - - /* If idle and MAC or PCI is stuck */ - if (sky2->check.last == dev->last_rx && - ((mac_rp == sky2->check.mac_rp && - mac_lev != 0 && mac_lev >= sky2->check.mac_lev) || - /* Check if the PCI RX hang */ - (fifo_rp == sky2->check.fifo_rp && - fifo_lev != 0 && fifo_lev >= sky2->check.fifo_lev))) { - printk(KERN_DEBUG PFX "%s: hung mac %d:%d fifo %d (%d:%d)\n", - dev->name, mac_lev, mac_rp, fifo_lev, fifo_rp, - sky2_read8(hw, Q_ADDR(rxq, Q_WP))); - return 1; - } else { - sky2->check.last = dev->last_rx; - sky2->check.mac_rp = mac_rp; - sky2->check.mac_lev = mac_lev; - sky2->check.fifo_rp = fifo_rp; - sky2->check.fifo_lev = fifo_lev; - return 0; - } -} - +/* Check for lost IRQ once a second */ static void sky2_watchdog(unsigned long arg) { struct sky2_hw *hw = (struct sky2_hw *) arg; - struct net_device *dev; - /* Check for lost IRQ once a second */ if (sky2_read32(hw, B0_ISRC)) { - dev = hw->dev[0]; + struct net_device *dev = hw->dev[0]; + if (__netif_rx_schedule_prep(dev)) __netif_rx_schedule(dev); - } else { - int i, active = 0; - - for (i = 0; i < hw->ports; i++) { - dev = hw->dev[i]; - if (!netif_running(dev)) - continue; - ++active; - - /* For chips with Rx FIFO, check if stuck */ - if ((hw->flags & SKY2_HW_RAMBUFFER) && - sky2_rx_hung(dev)) { - pr_info(PFX "%s: receiver hang detected\n", - dev->name); - schedule_work(&hw->restart_work); - return; - } - } - - if (active == 0) - return; } - mod_timer(&hw->watchdog_timer, round_jiffies(jiffies + HZ)); + if (hw->active > 0) + mod_timer(&hw->watchdog_timer, round_jiffies(jiffies + HZ)); } /* Hardware/software error handling */ @@ -2636,25 +2546,17 @@ static void sky2_netpoll(struct net_device *dev) #endif /* Chip internal frequency for clock calculations */ -static u32 sky2_mhz(const struct sky2_hw *hw) +static inline u32 sky2_mhz(const struct sky2_hw *hw) { switch (hw->chip_id) { case CHIP_ID_YUKON_EC: case CHIP_ID_YUKON_EC_U: case CHIP_ID_YUKON_EX: - return 125; - + return 125; /* 125 Mhz */ case CHIP_ID_YUKON_FE: - return 100; - - case CHIP_ID_YUKON_FE_P: - return 50; - - case CHIP_ID_YUKON_XL: - return 156; - - default: - BUG(); + return 100; /* 100 Mhz */ + default: /* YUKON_XL */ + return 156; /* 156 Mhz */ } } @@ -2679,62 +2581,23 @@ static int __devinit sky2_init(struct sky2_hw *hw) sky2_write8(hw, B0_CTST, CS_RST_CLR); hw->chip_id = sky2_read8(hw, B2_CHIP_ID); - hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4; - - switch(hw->chip_id) { - case CHIP_ID_YUKON_XL: - hw->flags = SKY2_HW_GIGABIT - | SKY2_HW_NEWER_PHY - | SKY2_HW_RAMBUFFER; - break; - - case CHIP_ID_YUKON_EC_U: - hw->flags = SKY2_HW_GIGABIT - | SKY2_HW_NEWER_PHY - | SKY2_HW_ADV_POWER_CTL; - break; - - case CHIP_ID_YUKON_EX: - hw->flags = SKY2_HW_GIGABIT - | SKY2_HW_NEWER_PHY - | SKY2_HW_NEW_LE - | SKY2_HW_ADV_POWER_CTL; - - /* New transmit checksum */ - if (hw->chip_rev != CHIP_REV_YU_EX_B0) - hw->flags |= SKY2_HW_AUTO_TX_SUM; - break; - - case CHIP_ID_YUKON_EC: - /* This rev is really old, and requires untested workarounds */ - if (hw->chip_rev == CHIP_REV_YU_EC_A1) { - dev_err(&hw->pdev->dev, "unsupported revision Yukon-EC rev A1\n"); - return -EOPNOTSUPP; - } - hw->flags = SKY2_HW_GIGABIT | SKY2_HW_RAMBUFFER; - break; - - case CHIP_ID_YUKON_FE: - hw->flags = SKY2_HW_RAMBUFFER; - break; - - case CHIP_ID_YUKON_FE_P: - hw->flags = SKY2_HW_NEWER_PHY - | SKY2_HW_NEW_LE - | SKY2_HW_AUTO_TX_SUM - | SKY2_HW_ADV_POWER_CTL; - break; - default: + if (hw->chip_id < CHIP_ID_YUKON_XL || hw->chip_id > CHIP_ID_YUKON_FE) { dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n", hw->chip_id); return -EOPNOTSUPP; } - hw->pmd_type = sky2_read8(hw, B2_PMD_TYP); - if (hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P') - hw->flags |= SKY2_HW_FIBRE_PHY; + hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4; + /* This rev is really old, and requires untested workarounds */ + if (hw->chip_id == CHIP_ID_YUKON_EC && hw->chip_rev == CHIP_REV_YU_EC_A1) { + dev_err(&hw->pdev->dev, "unsupported revision Yukon-%s (0x%x) rev %d\n", + yukon2_name[hw->chip_id - CHIP_ID_YUKON_XL], + hw->chip_id, hw->chip_rev); + return -EOPNOTSUPP; + } + hw->pmd_type = sky2_read8(hw, B2_PMD_TYP); hw->ports = 1; t8 = sky2_read8(hw, B2_Y2_HW_RES); if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) { @@ -2928,9 +2791,7 @@ static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) sky2->wol = wol->wolopts; - if (hw->chip_id == CHIP_ID_YUKON_EC_U || - hw->chip_id == CHIP_ID_YUKON_EX || - hw->chip_id == CHIP_ID_YUKON_FE_P) + if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) sky2_write32(hw, B0_CTST, sky2->wol ? Y2_HW_WOL_ON : Y2_HW_WOL_OFF); @@ -2948,7 +2809,7 @@ static u32 sky2_supported_modes(const struct sky2_hw *hw) | SUPPORTED_100baseT_Full | SUPPORTED_Autoneg | SUPPORTED_TP; - if (hw->flags & SKY2_HW_GIGABIT) + if (hw->chip_id != CHIP_ID_YUKON_FE) modes |= SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full; return modes; @@ -2968,6 +2829,13 @@ static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->supported = sky2_supported_modes(hw); ecmd->phy_address = PHY_ADDR_MARV; if (sky2_is_copper(hw)) { + ecmd->supported = SUPPORTED_10baseT_Half + | SUPPORTED_10baseT_Full + | SUPPORTED_100baseT_Half + | SUPPORTED_100baseT_Full + | SUPPORTED_1000baseT_Half + | SUPPORTED_1000baseT_Full + | SUPPORTED_Autoneg | SUPPORTED_TP; ecmd->port = PORT_TP; ecmd->speed = sky2->speed; } else { @@ -3923,13 +3791,6 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, sky2->hw = hw; sky2->msg_enable = netif_msg_init(debug, default_msg); - /* This chip has hardware problems that generates - * bogus PHY receive status so by default shut up the message. - */ - if (hw->chip_id == CHIP_ID_YUKON_FE_P && - hw->chip_rev == CHIP_REV_YU_FE2_A0) - sky2->msg_enable &= ~NETIF_MSG_RX_ERR; - /* Auto speed and flow control */ sky2->autoneg = AUTONEG_ENABLE; sky2->flow_mode = FC_BOTH; @@ -3985,7 +3846,7 @@ static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id) return IRQ_NONE; if (status & Y2_IS_IRQ_SW) { - hw->flags |= SKY2_HW_USE_MSI; + hw->msi = 1; wake_up(&hw->msi_wait); sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); } @@ -4013,9 +3874,9 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw) sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ); sky2_read8(hw, B0_CTST); - wait_event_timeout(hw->msi_wait, (hw->flags & SKY2_HW_USE_MSI), HZ/10); + wait_event_timeout(hw->msi_wait, hw->msi, HZ/10); - if (!(hw->flags & SKY2_HW_USE_MSI)) { + if (!hw->msi) { /* MSI test failed, go back to INTx mode */ dev_info(&pdev->dev, "No interrupt generated using MSI, " "switching to INTx mode.\n"); @@ -4148,8 +4009,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev, goto err_out_free_netdev; } - err = request_irq(pdev->irq, sky2_intr, - (hw->flags & SKY2_HW_USE_MSI) ? 0 : IRQF_SHARED, + err = request_irq(pdev->irq, sky2_intr, hw->msi ? 0 : IRQF_SHARED, dev->name, hw); if (err) { dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq); @@ -4182,7 +4042,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev, return 0; err_out_unregister: - if (hw->flags & SKY2_HW_USE_MSI) + if (hw->msi) pci_disable_msi(pdev); unregister_netdev(dev); err_out_free_netdev: @@ -4231,7 +4091,7 @@ static void __devexit sky2_remove(struct pci_dev *pdev) sky2_read8(hw, B0_CTST); free_irq(pdev->irq, hw); - if (hw->flags & SKY2_HW_USE_MSI) + if (hw->msi) pci_disable_msi(pdev); pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma); pci_release_regions(pdev); @@ -4299,9 +4159,7 @@ static int sky2_resume(struct pci_dev *pdev) pci_enable_wake(pdev, PCI_D0, 0); /* Re-enable all clocks */ - if (hw->chip_id == CHIP_ID_YUKON_EX || - hw->chip_id == CHIP_ID_YUKON_EC_U || - hw->chip_id == CHIP_ID_YUKON_FE_P) + if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U) sky2_pci_write32(hw, PCI_DEV_REG3, 0); sky2_reset(hw); diff --git a/trunk/drivers/net/sky2.h b/trunk/drivers/net/sky2.h index 69cd98400fe6..72e12b7cfa40 100644 --- a/trunk/drivers/net/sky2.h +++ b/trunk/drivers/net/sky2.h @@ -470,24 +470,18 @@ enum { CHIP_ID_YUKON_EX = 0xb5, /* Chip ID for YUKON-2 Extreme */ CHIP_ID_YUKON_EC = 0xb6, /* Chip ID for YUKON-2 EC */ CHIP_ID_YUKON_FE = 0xb7, /* Chip ID for YUKON-2 FE */ - CHIP_ID_YUKON_FE_P = 0xb8, /* Chip ID for YUKON-2 FE+ */ -}; -enum yukon_ec_rev { + CHIP_REV_YU_EC_A1 = 0, /* Chip Rev. for Yukon-EC A1/A0 */ CHIP_REV_YU_EC_A2 = 1, /* Chip Rev. for Yukon-EC A2 */ CHIP_REV_YU_EC_A3 = 2, /* Chip Rev. for Yukon-EC A3 */ -}; -enum yukon_ec_u_rev { + CHIP_REV_YU_EC_U_A0 = 1, CHIP_REV_YU_EC_U_A1 = 2, CHIP_REV_YU_EC_U_B0 = 3, -}; -enum yukon_fe_rev { + CHIP_REV_YU_FE_A1 = 1, CHIP_REV_YU_FE_A2 = 2, -}; -enum yukon_fe_p_rev { - CHIP_REV_YU_FE2_A0 = 0, + }; enum yukon_ex_rev { CHIP_REV_YU_EX_A0 = 1, @@ -1674,7 +1668,7 @@ enum { /* Receive Frame Status Encoding */ enum { - GMR_FS_LEN = 0x7fff<<16, /* Bit 30..16: Rx Frame Length */ + GMR_FS_LEN = 0xffff<<16, /* Bit 31..16: Rx Frame Length */ GMR_FS_VLAN = 1<<13, /* VLAN Packet */ GMR_FS_JABBER = 1<<12, /* Jabber Packet */ GMR_FS_UN_SIZE = 1<<11, /* Undersize Packet */ @@ -1735,10 +1729,6 @@ enum { GMF_RX_CTRL_DEF = GMF_OPER_ON | GMF_RX_F_FL_ON, }; -/* TX_GMF_EA 32 bit Tx GMAC FIFO End Address */ -enum { - TX_DYN_WM_ENA = 3, /* Yukon-FE+ specific */ -}; /* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */ enum { @@ -2027,14 +2017,6 @@ struct sky2_port { u16 rx_tag; struct vlan_group *vlgrp; #endif - struct { - unsigned long last; - u32 mac_rp; - u8 mac_lev; - u8 fifo_rp; - u8 fifo_lev; - } check; - dma_addr_t rx_le_map; dma_addr_t tx_le_map; @@ -2058,20 +2040,12 @@ struct sky2_hw { void __iomem *regs; struct pci_dev *pdev; struct net_device *dev[2]; - unsigned long flags; -#define SKY2_HW_USE_MSI 0x00000001 -#define SKY2_HW_FIBRE_PHY 0x00000002 -#define SKY2_HW_GIGABIT 0x00000004 -#define SKY2_HW_NEWER_PHY 0x00000008 -#define SKY2_HW_RAMBUFFER 0x00000010 /* chip has RAM FIFO */ -#define SKY2_HW_NEW_LE 0x00000020 /* new LSOv2 format */ -#define SKY2_HW_AUTO_TX_SUM 0x00000040 /* new IP decode for Tx */ -#define SKY2_HW_ADV_POWER_CTL 0x00000080 /* additional PHY power regs */ u8 chip_id; u8 chip_rev; u8 pmd_type; u8 ports; + u8 active; struct sky2_status_le *st_le; u32 st_idx; @@ -2079,12 +2053,13 @@ struct sky2_hw { struct timer_list watchdog_timer; struct work_struct restart_work; + int msi; wait_queue_head_t msi_wait; }; static inline int sky2_is_copper(const struct sky2_hw *hw) { - return !(hw->flags & SKY2_HW_FIBRE_PHY); + return !(hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P'); } /* Register accessor for memory mapped device */ diff --git a/trunk/drivers/rtc/rtc-ds1553.c b/trunk/drivers/rtc/rtc-ds1553.c index 5ab3492817d1..46da5714932c 100644 --- a/trunk/drivers/rtc/rtc-ds1553.c +++ b/trunk/drivers/rtc/rtc-ds1553.c @@ -61,7 +61,7 @@ struct rtc_plat_data { struct rtc_device *rtc; void __iomem *ioaddr; - resource_size_t baseaddr; + unsigned long baseaddr; unsigned long last_jiffies; int irq; unsigned int irqen; diff --git a/trunk/drivers/rtc/rtc-ds1742.c b/trunk/drivers/rtc/rtc-ds1742.c index 67291b0f8283..b2e5481ba3b6 100644 --- a/trunk/drivers/rtc/rtc-ds1742.c +++ b/trunk/drivers/rtc/rtc-ds1742.c @@ -55,7 +55,7 @@ struct rtc_plat_data { void __iomem *ioaddr_rtc; size_t size_nvram; size_t size; - resource_size_t baseaddr; + unsigned long baseaddr; unsigned long last_jiffies; }; diff --git a/trunk/drivers/serial/sunsab.c b/trunk/drivers/serial/sunsab.c index e348ba684050..bca57bb94939 100644 --- a/trunk/drivers/serial/sunsab.c +++ b/trunk/drivers/serial/sunsab.c @@ -58,7 +58,6 @@ struct uart_sunsab_port { unsigned char interrupt_mask1;/* ISR1 masking */ unsigned char pvr_dtr_bit; /* Which PVR bit is DTR */ unsigned char pvr_dsr_bit; /* Which PVR bit is DSR */ - unsigned int gis_shift; int type; /* SAB82532 version */ /* Setting configuration bits while the transmitter is active @@ -306,15 +305,13 @@ static irqreturn_t sunsab_interrupt(int irq, void *dev_id) struct tty_struct *tty; union sab82532_irq_status status; unsigned long flags; - unsigned char gis; spin_lock_irqsave(&up->port.lock, flags); status.stat = 0; - gis = readb(&up->regs->r.gis) >> up->gis_shift; - if (gis & 1) + if (readb(&up->regs->r.gis) & SAB82532_GIS_ISA0) status.sreg.isr0 = readb(&up->regs->r.isr0); - if (gis & 2) + if (readb(&up->regs->r.gis) & SAB82532_GIS_ISA1) status.sreg.isr1 = readb(&up->regs->r.isr1); tty = NULL; @@ -330,6 +327,35 @@ static irqreturn_t sunsab_interrupt(int irq, void *dev_id) transmit_chars(up, &status); } + spin_unlock(&up->port.lock); + + if (tty) + tty_flip_buffer_push(tty); + + up++; + + spin_lock(&up->port.lock); + + status.stat = 0; + if (readb(&up->regs->r.gis) & SAB82532_GIS_ISB0) + status.sreg.isr0 = readb(&up->regs->r.isr0); + if (readb(&up->regs->r.gis) & SAB82532_GIS_ISB1) + status.sreg.isr1 = readb(&up->regs->r.isr1); + + tty = NULL; + if (status.stat) { + if ((status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME | + SAB82532_ISR0_RFO | SAB82532_ISR0_RPF)) || + (status.sreg.isr1 & SAB82532_ISR1_BRK)) + + tty = receive_chars(up, &status); + if ((status.sreg.isr0 & SAB82532_ISR0_CDSC) || + (status.sreg.isr1 & (SAB82532_ISR1_BRK | SAB82532_ISR1_CSC))) + check_status(up, &status); + if (status.sreg.isr1 & (SAB82532_ISR1_ALLS | SAB82532_ISR1_XPR)) + transmit_chars(up, &status); + } + spin_unlock_irqrestore(&up->port.lock, flags); if (tty) @@ -513,10 +539,6 @@ static int sunsab_startup(struct uart_port *port) struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; unsigned long flags; unsigned char tmp; - int err = request_irq(up->port.irq, sunsab_interrupt, - IRQF_SHARED, "sab", up); - if (err) - return err; spin_lock_irqsave(&up->port.lock, flags); @@ -619,7 +641,6 @@ static void sunsab_shutdown(struct uart_port *port) #endif spin_unlock_irqrestore(&up->port.lock, flags); - free_irq(up->port.irq, up); } /* @@ -987,11 +1008,9 @@ static int __devinit sunsab_init_one(struct uart_sunsab_port *up, if ((up->port.line & 0x1) == 0) { up->pvr_dsr_bit = (1 << 0); up->pvr_dtr_bit = (1 << 1); - up->gis_shift = 2; } else { up->pvr_dsr_bit = (1 << 3); up->pvr_dtr_bit = (1 << 2); - up->gis_shift = 0; } up->cached_pvr = (1 << 1) | (1 << 2) | (1 << 4); writeb(up->cached_pvr, &up->regs->w.pvr); @@ -1004,6 +1023,19 @@ static int __devinit sunsab_init_one(struct uart_sunsab_port *up, up->tec_timeout = SAB82532_MAX_TEC_TIMEOUT; up->cec_timeout = SAB82532_MAX_CEC_TIMEOUT; + if (!(up->port.line & 0x01)) { + int err; + + err = request_irq(up->port.irq, sunsab_interrupt, + IRQF_SHARED, "sab", up); + if (err) { + of_iounmap(&op->resource[0], + up->port.membase, + sizeof(union sab82532_async_regs)); + return err; + } + } + return 0; } @@ -1019,60 +1051,52 @@ static int __devinit sab_probe(struct of_device *op, const struct of_device_id * 0, (inst * 2) + 0); if (err) - goto out; + return err; err = sunsab_init_one(&up[1], op, sizeof(union sab82532_async_regs), (inst * 2) + 1); - if (err) - goto out1; + if (err) { + of_iounmap(&op->resource[0], + up[0].port.membase, + sizeof(union sab82532_async_regs)); + free_irq(up[0].port.irq, &up[0]); + return err; + } sunserial_console_match(SUNSAB_CONSOLE(), op->node, &sunsab_reg, up[0].port.line); + uart_add_one_port(&sunsab_reg, &up[0].port); sunserial_console_match(SUNSAB_CONSOLE(), op->node, &sunsab_reg, up[1].port.line); - - err = uart_add_one_port(&sunsab_reg, &up[0].port); - if (err) - goto out2; - - err = uart_add_one_port(&sunsab_reg, &up[1].port); - if (err) - goto out3; + uart_add_one_port(&sunsab_reg, &up[1].port); dev_set_drvdata(&op->dev, &up[0]); inst++; return 0; +} -out3: - uart_remove_one_port(&sunsab_reg, &up[0].port); -out2: - of_iounmap(&op->resource[0], - up[1].port.membase, - sizeof(union sab82532_async_regs)); -out1: +static void __devexit sab_remove_one(struct uart_sunsab_port *up) +{ + struct of_device *op = to_of_device(up->port.dev); + + uart_remove_one_port(&sunsab_reg, &up->port); + if (!(up->port.line & 1)) + free_irq(up->port.irq, up); of_iounmap(&op->resource[0], - up[0].port.membase, + up->port.membase, sizeof(union sab82532_async_regs)); -out: - return err; } static int __devexit sab_remove(struct of_device *op) { struct uart_sunsab_port *up = dev_get_drvdata(&op->dev); - uart_remove_one_port(&sunsab_reg, &up[1].port); - uart_remove_one_port(&sunsab_reg, &up[0].port); - of_iounmap(&op->resource[0], - up[1].port.membase, - sizeof(union sab82532_async_regs)); - of_iounmap(&op->resource[0], - up[0].port.membase, - sizeof(union sab82532_async_regs)); + sab_remove_one(&up[0]); + sab_remove_one(&up[1]); dev_set_drvdata(&op->dev, NULL); @@ -1119,7 +1143,6 @@ static int __init sunsab_init(void) sunsab_reg.minor = sunserial_current_minor; sunsab_reg.nr = num_channels; - sunsab_reg.cons = SUNSAB_CONSOLE(); err = uart_register_driver(&sunsab_reg); if (err) { diff --git a/trunk/drivers/video/intelfb/intelfbhw.c b/trunk/drivers/video/intelfb/intelfbhw.c index 6a47682d8614..b21d0dec9283 100644 --- a/trunk/drivers/video/intelfb/intelfbhw.c +++ b/trunk/drivers/video/intelfb/intelfbhw.c @@ -1352,7 +1352,7 @@ intelfbhw_program_mode(struct intelfb_info *dinfo, /* turn off PLL */ tmp = INREG(dpll_reg); - tmp &= ~DPLL_VCO_ENABLE; + dpll_reg &= ~DPLL_VCO_ENABLE; OUTREG(dpll_reg, tmp); /* Set PLL parameters */ diff --git a/trunk/fs/exec.c b/trunk/fs/exec.c index 073b0b8c6d05..c21a8cc06277 100644 --- a/trunk/fs/exec.c +++ b/trunk/fs/exec.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -783,6 +784,7 @@ static int de_thread(struct task_struct *tsk) * and we can just re-use it all. */ if (atomic_read(&oldsighand->count) <= 1) { + signalfd_detach(tsk); exit_itimers(sig); return 0; } @@ -921,6 +923,7 @@ static int de_thread(struct task_struct *tsk) sig->flags = 0; no_thread_group: + signalfd_detach(tsk); exit_itimers(sig); if (leader) release_task(leader); diff --git a/trunk/fs/ext3/namei.c b/trunk/fs/ext3/namei.c index c1fa1908dba0..1586807b8177 100644 --- a/trunk/fs/ext3/namei.c +++ b/trunk/fs/ext3/namei.c @@ -140,8 +140,7 @@ struct dx_frame struct dx_map_entry { u32 hash; - u16 offs; - u16 size; + u32 offs; }; #ifdef CONFIG_EXT3_INDEX @@ -380,28 +379,13 @@ dx_probe(struct dentry *dentry, struct inode *dir, entries = (struct dx_entry *) (((char *)&root->info) + root->info.info_length); - - if (dx_get_limit(entries) != dx_root_limit(dir, - root->info.info_length)) { - ext3_warning(dir->i_sb, __FUNCTION__, - "dx entry: limit != root limit"); - brelse(bh); - *err = ERR_BAD_DX_DIR; - goto fail; - } - + assert(dx_get_limit(entries) == dx_root_limit(dir, + root->info.info_length)); dxtrace (printk("Look up %x", hash)); while (1) { count = dx_get_count(entries); - if (!count || count > dx_get_limit(entries)) { - ext3_warning(dir->i_sb, __FUNCTION__, - "dx entry: no count or count > limit"); - brelse(bh); - *err = ERR_BAD_DX_DIR; - goto fail2; - } - + assert (count && count <= dx_get_limit(entries)); p = entries + 1; q = entries + count - 1; while (p <= q) @@ -439,15 +423,8 @@ dx_probe(struct dentry *dentry, struct inode *dir, if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err))) goto fail2; at = entries = ((struct dx_node *) bh->b_data)->entries; - if (dx_get_limit(entries) != dx_node_limit (dir)) { - ext3_warning(dir->i_sb, __FUNCTION__, - "dx entry: limit != node limit"); - brelse(bh); - *err = ERR_BAD_DX_DIR; - goto fail2; - } + assert (dx_get_limit(entries) == dx_node_limit (dir)); frame++; - frame->bh = NULL; } fail2: while (frame >= frame_in) { @@ -455,10 +432,6 @@ dx_probe(struct dentry *dentry, struct inode *dir, frame--; } fail: - if (*err == ERR_BAD_DX_DIR) - ext3_warning(dir->i_sb, __FUNCTION__, - "Corrupt dir inode %ld, running e2fsck is " - "recommended.", dir->i_ino); return NULL; } @@ -698,10 +671,6 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, * Directory block splitting, compacting */ -/* - * Create map of hash values, offsets, and sizes, stored at end of block. - * Returns number of entries mapped. - */ static int dx_make_map (struct ext3_dir_entry_2 *de, int size, struct dx_hash_info *hinfo, struct dx_map_entry *map_tail) { @@ -715,8 +684,7 @@ static int dx_make_map (struct ext3_dir_entry_2 *de, int size, ext3fs_dirhash(de->name, de->name_len, &h); map_tail--; map_tail->hash = h.hash; - map_tail->offs = (u16) ((char *) de - base); - map_tail->size = le16_to_cpu(de->rec_len); + map_tail->offs = (u32) ((char *) de - base); count++; cond_resched(); } @@ -726,7 +694,6 @@ static int dx_make_map (struct ext3_dir_entry_2 *de, int size, return count; } -/* Sort map by hash value */ static void dx_sort_map (struct dx_map_entry *map, unsigned count) { struct dx_map_entry *p, *q, *top = map + count - 1; @@ -1124,10 +1091,6 @@ static inline void ext3_set_de_type(struct super_block *sb, } #ifdef CONFIG_EXT3_INDEX -/* - * Move count entries from end of map between two memory locations. - * Returns pointer to last entry moved. - */ static struct ext3_dir_entry_2 * dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count) { @@ -1146,10 +1109,6 @@ dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count) return (struct ext3_dir_entry_2 *) (to - rec_len); } -/* - * Compact each dir entry in the range to the minimal rec_len. - * Returns pointer to last entry in range. - */ static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size) { struct ext3_dir_entry_2 *next, *to, *prev, *de = (struct ext3_dir_entry_2 *) base; @@ -1172,11 +1131,6 @@ static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size) return prev; } -/* - * Split a full leaf block to make room for a new dir entry. - * Allocate a new block, and move entries so that they are approx. equally full. - * Returns pointer to de in block into which the new entry will be inserted. - */ static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, struct buffer_head **bh,struct dx_frame *frame, struct dx_hash_info *hinfo, int *error) @@ -1188,7 +1142,7 @@ static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, u32 hash2; struct dx_map_entry *map; char *data1 = (*bh)->b_data, *data2; - unsigned split, move, size, i; + unsigned split; struct ext3_dir_entry_2 *de = NULL, *de2; int err = 0; @@ -1216,19 +1170,8 @@ static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, count = dx_make_map ((struct ext3_dir_entry_2 *) data1, blocksize, hinfo, map); map -= count; + split = count/2; // need to adjust to actual middle dx_sort_map (map, count); - /* Split the existing block in the middle, size-wise */ - size = 0; - move = 0; - for (i = count-1; i >= 0; i--) { - /* is more than half of this entry in 2nd half of the block? */ - if (size + map[i].size/2 > blocksize/2) - break; - size += map[i].size; - move++; - } - /* map index at which we will split */ - split = count - move; hash2 = map[split].hash; continued = hash2 == map[split - 1].hash; dxtrace(printk("Split block %i at %x, %i/%i\n", diff --git a/trunk/fs/ext4/namei.c b/trunk/fs/ext4/namei.c index 5fdb862e71c4..da224974af78 100644 --- a/trunk/fs/ext4/namei.c +++ b/trunk/fs/ext4/namei.c @@ -140,8 +140,7 @@ struct dx_frame struct dx_map_entry { u32 hash; - u16 offs; - u16 size; + u32 offs; }; #ifdef CONFIG_EXT4_INDEX @@ -380,28 +379,13 @@ dx_probe(struct dentry *dentry, struct inode *dir, entries = (struct dx_entry *) (((char *)&root->info) + root->info.info_length); - - if (dx_get_limit(entries) != dx_root_limit(dir, - root->info.info_length)) { - ext4_warning(dir->i_sb, __FUNCTION__, - "dx entry: limit != root limit"); - brelse(bh); - *err = ERR_BAD_DX_DIR; - goto fail; - } - + assert(dx_get_limit(entries) == dx_root_limit(dir, + root->info.info_length)); dxtrace (printk("Look up %x", hash)); while (1) { count = dx_get_count(entries); - if (!count || count > dx_get_limit(entries)) { - ext4_warning(dir->i_sb, __FUNCTION__, - "dx entry: no count or count > limit"); - brelse(bh); - *err = ERR_BAD_DX_DIR; - goto fail2; - } - + assert (count && count <= dx_get_limit(entries)); p = entries + 1; q = entries + count - 1; while (p <= q) @@ -439,15 +423,8 @@ dx_probe(struct dentry *dentry, struct inode *dir, if (!(bh = ext4_bread (NULL,dir, dx_get_block(at), 0, err))) goto fail2; at = entries = ((struct dx_node *) bh->b_data)->entries; - if (dx_get_limit(entries) != dx_node_limit (dir)) { - ext4_warning(dir->i_sb, __FUNCTION__, - "dx entry: limit != node limit"); - brelse(bh); - *err = ERR_BAD_DX_DIR; - goto fail2; - } + assert (dx_get_limit(entries) == dx_node_limit (dir)); frame++; - frame->bh = NULL; } fail2: while (frame >= frame_in) { @@ -455,10 +432,6 @@ dx_probe(struct dentry *dentry, struct inode *dir, frame--; } fail: - if (*err == ERR_BAD_DX_DIR) - ext4_warning(dir->i_sb, __FUNCTION__, - "Corrupt dir inode %ld, running e2fsck is " - "recommended.", dir->i_ino); return NULL; } @@ -698,10 +671,6 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash, * Directory block splitting, compacting */ -/* - * Create map of hash values, offsets, and sizes, stored at end of block. - * Returns number of entries mapped. - */ static int dx_make_map (struct ext4_dir_entry_2 *de, int size, struct dx_hash_info *hinfo, struct dx_map_entry *map_tail) { @@ -715,8 +684,7 @@ static int dx_make_map (struct ext4_dir_entry_2 *de, int size, ext4fs_dirhash(de->name, de->name_len, &h); map_tail--; map_tail->hash = h.hash; - map_tail->offs = (u16) ((char *) de - base); - map_tail->size = le16_to_cpu(de->rec_len); + map_tail->offs = (u32) ((char *) de - base); count++; cond_resched(); } @@ -726,7 +694,6 @@ static int dx_make_map (struct ext4_dir_entry_2 *de, int size, return count; } -/* Sort map by hash value */ static void dx_sort_map (struct dx_map_entry *map, unsigned count) { struct dx_map_entry *p, *q, *top = map + count - 1; @@ -1122,10 +1089,6 @@ static inline void ext4_set_de_type(struct super_block *sb, } #ifdef CONFIG_EXT4_INDEX -/* - * Move count entries from end of map between two memory locations. - * Returns pointer to last entry moved. - */ static struct ext4_dir_entry_2 * dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count) { @@ -1144,10 +1107,6 @@ dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count) return (struct ext4_dir_entry_2 *) (to - rec_len); } -/* - * Compact each dir entry in the range to the minimal rec_len. - * Returns pointer to last entry in range. - */ static struct ext4_dir_entry_2* dx_pack_dirents(char *base, int size) { struct ext4_dir_entry_2 *next, *to, *prev, *de = (struct ext4_dir_entry_2 *) base; @@ -1170,11 +1129,6 @@ static struct ext4_dir_entry_2* dx_pack_dirents(char *base, int size) return prev; } -/* - * Split a full leaf block to make room for a new dir entry. - * Allocate a new block, and move entries so that they are approx. equally full. - * Returns pointer to de in block into which the new entry will be inserted. - */ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, struct buffer_head **bh,struct dx_frame *frame, struct dx_hash_info *hinfo, int *error) @@ -1186,7 +1140,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, u32 hash2; struct dx_map_entry *map; char *data1 = (*bh)->b_data, *data2; - unsigned split, move, size, i; + unsigned split; struct ext4_dir_entry_2 *de = NULL, *de2; int err = 0; @@ -1214,19 +1168,8 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, count = dx_make_map ((struct ext4_dir_entry_2 *) data1, blocksize, hinfo, map); map -= count; + split = count/2; // need to adjust to actual middle dx_sort_map (map, count); - /* Split the existing block in the middle, size-wise */ - size = 0; - move = 0; - for (i = count-1; i >= 0; i--) { - /* is more than half of this entry in 2nd half of the block? */ - if (size + map[i].size/2 > blocksize/2) - break; - size += map[i].size; - move++; - } - /* map index at which we will split */ - split = count - move; hash2 = map[split].hash; continued = hash2 == map[split - 1].hash; dxtrace(printk("Split block %i at %x, %i/%i\n", diff --git a/trunk/fs/nfs/super.c b/trunk/fs/nfs/super.c index b878528b64c1..8ed593766f16 100644 --- a/trunk/fs/nfs/super.c +++ b/trunk/fs/nfs/super.c @@ -345,8 +345,8 @@ void __exit unregister_nfs_fs(void) unregister_shrinker(&acl_shrinker); #ifdef CONFIG_NFS_V4 unregister_filesystem(&nfs4_fs_type); -#endif nfs_unregister_sysctl(); +#endif unregister_filesystem(&nfs_fs_type); } diff --git a/trunk/fs/ocfs2/aops.c b/trunk/fs/ocfs2/aops.c index f37f25c931f5..50cd8a209012 100644 --- a/trunk/fs/ocfs2/aops.c +++ b/trunk/fs/ocfs2/aops.c @@ -930,11 +930,18 @@ static void ocfs2_write_failure(struct inode *inode, loff_t user_pos, unsigned user_len) { int i; - unsigned from = user_pos & (PAGE_CACHE_SIZE - 1), - to = user_pos + user_len; + unsigned from, to; struct page *tmppage; - ocfs2_zero_new_buffers(wc->w_target_page, from, to); + ocfs2_zero_new_buffers(wc->w_target_page, user_pos, user_len); + + if (wc->w_large_pages) { + from = wc->w_target_from; + to = wc->w_target_to; + } else { + from = 0; + to = PAGE_CACHE_SIZE; + } for(i = 0; i < wc->w_num_pages; i++) { tmppage = wc->w_pages[i]; @@ -984,6 +991,9 @@ static int ocfs2_prepare_page_for_write(struct inode *inode, u64 *p_blkno, map_from = cluster_start; map_to = cluster_end; } + + wc->w_target_from = map_from; + wc->w_target_to = map_to; } else { /* * If we haven't allocated the new page yet, we @@ -1201,33 +1211,18 @@ static int ocfs2_write_cluster_by_desc(struct address_space *mapping, loff_t pos, unsigned len) { int ret, i; - loff_t cluster_off; - unsigned int local_len = len; struct ocfs2_write_cluster_desc *desc; - struct ocfs2_super *osb = OCFS2_SB(mapping->host->i_sb); for (i = 0; i < wc->w_clen; i++) { desc = &wc->w_desc[i]; - /* - * We have to make sure that the total write passed in - * doesn't extend past a single cluster. - */ - local_len = len; - cluster_off = pos & (osb->s_clustersize - 1); - if ((cluster_off + local_len) > osb->s_clustersize) - local_len = osb->s_clustersize - cluster_off; - ret = ocfs2_write_cluster(mapping, desc->c_phys, desc->c_unwritten, data_ac, meta_ac, - wc, desc->c_cpos, pos, local_len); + wc, desc->c_cpos, pos, len); if (ret) { mlog_errno(ret); goto out; } - - len -= local_len; - pos += local_len; } ret = 0; diff --git a/trunk/fs/ocfs2/file.c b/trunk/fs/ocfs2/file.c index f3bc3658e7a5..7e34e66159c6 100644 --- a/trunk/fs/ocfs2/file.c +++ b/trunk/fs/ocfs2/file.c @@ -491,8 +491,8 @@ int ocfs2_do_extend_allocation(struct ocfs2_super *osb, goto leave; } - status = __ocfs2_claim_clusters(osb, handle, data_ac, 1, - clusters_to_add, &bit_off, &num_bits); + status = ocfs2_claim_clusters(osb, handle, data_ac, 1, + &bit_off, &num_bits); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); diff --git a/trunk/fs/ocfs2/localalloc.c b/trunk/fs/ocfs2/localalloc.c index de984d272576..545f7892cdf3 100644 --- a/trunk/fs/ocfs2/localalloc.c +++ b/trunk/fs/ocfs2/localalloc.c @@ -524,12 +524,13 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb, handle_t *handle, struct ocfs2_alloc_context *ac, - u32 bits_wanted, + u32 min_bits, u32 *bit_off, u32 *num_bits) { int status, start; struct inode *local_alloc_inode; + u32 bits_wanted; void *bitmap; struct ocfs2_dinode *alloc; struct ocfs2_local_alloc *la; @@ -537,6 +538,7 @@ int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb, mlog_entry_void(); BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL); + bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given; local_alloc_inode = ac->ac_inode; alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; la = OCFS2_LOCAL_ALLOC(alloc); diff --git a/trunk/fs/ocfs2/localalloc.h b/trunk/fs/ocfs2/localalloc.h index 3f76631e110c..385a10152f9c 100644 --- a/trunk/fs/ocfs2/localalloc.h +++ b/trunk/fs/ocfs2/localalloc.h @@ -48,7 +48,7 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb, handle_t *handle, struct ocfs2_alloc_context *ac, - u32 bits_wanted, + u32 min_bits, u32 *bit_off, u32 *num_bits); diff --git a/trunk/fs/ocfs2/suballoc.c b/trunk/fs/ocfs2/suballoc.c index 8f09f5235e3a..d9c5c9fcb30f 100644 --- a/trunk/fs/ocfs2/suballoc.c +++ b/trunk/fs/ocfs2/suballoc.c @@ -1486,21 +1486,21 @@ static inline void ocfs2_block_to_cluster_group(struct inode *inode, * contig. allocation, set to '1' to indicate we can deal with extents * of any size. */ -int __ocfs2_claim_clusters(struct ocfs2_super *osb, - handle_t *handle, - struct ocfs2_alloc_context *ac, - u32 min_clusters, - u32 max_clusters, - u32 *cluster_start, - u32 *num_clusters) +int ocfs2_claim_clusters(struct ocfs2_super *osb, + handle_t *handle, + struct ocfs2_alloc_context *ac, + u32 min_clusters, + u32 *cluster_start, + u32 *num_clusters) { int status; - unsigned int bits_wanted = max_clusters; + unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given; u64 bg_blkno = 0; u16 bg_bit_off; mlog_entry_void(); + BUG_ON(!ac); BUG_ON(ac->ac_bits_given >= ac->ac_bits_wanted); BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL @@ -1557,19 +1557,6 @@ int __ocfs2_claim_clusters(struct ocfs2_super *osb, return status; } -int ocfs2_claim_clusters(struct ocfs2_super *osb, - handle_t *handle, - struct ocfs2_alloc_context *ac, - u32 min_clusters, - u32 *cluster_start, - u32 *num_clusters) -{ - unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given; - - return __ocfs2_claim_clusters(osb, handle, ac, min_clusters, - bits_wanted, cluster_start, num_clusters); -} - static inline int ocfs2_block_group_clear_bits(handle_t *handle, struct inode *alloc_inode, struct ocfs2_group_desc *bg, diff --git a/trunk/fs/ocfs2/suballoc.h b/trunk/fs/ocfs2/suballoc.h index cafe93703095..f212dc01a84b 100644 --- a/trunk/fs/ocfs2/suballoc.h +++ b/trunk/fs/ocfs2/suballoc.h @@ -85,17 +85,6 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb, u32 min_clusters, u32 *cluster_start, u32 *num_clusters); -/* - * Use this variant of ocfs2_claim_clusters to specify a maxiumum - * number of clusters smaller than the allocation reserved. - */ -int __ocfs2_claim_clusters(struct ocfs2_super *osb, - handle_t *handle, - struct ocfs2_alloc_context *ac, - u32 min_clusters, - u32 max_clusters, - u32 *cluster_start, - u32 *num_clusters); int ocfs2_free_suballoc_bits(handle_t *handle, struct inode *alloc_inode, diff --git a/trunk/fs/ocfs2/vote.c b/trunk/fs/ocfs2/vote.c index c05358538f2b..66a13ee63d4c 100644 --- a/trunk/fs/ocfs2/vote.c +++ b/trunk/fs/ocfs2/vote.c @@ -66,7 +66,7 @@ struct ocfs2_vote_msg { struct ocfs2_msg_hdr v_hdr; __be32 v_reserved1; -} __attribute__ ((packed)); +}; /* Responses are given these values to maintain backwards * compatibility with older ocfs2 versions */ @@ -78,7 +78,7 @@ struct ocfs2_response_msg { struct ocfs2_msg_hdr r_hdr; __be32 r_response; -} __attribute__ ((packed)); +}; struct ocfs2_vote_work { struct list_head w_list; diff --git a/trunk/fs/signalfd.c b/trunk/fs/signalfd.c index aefb0be07942..a8e293d30034 100644 --- a/trunk/fs/signalfd.c +++ b/trunk/fs/signalfd.c @@ -11,10 +11,8 @@ * Now using anonymous inode source. * Thanks to Oleg Nesterov for useful code review and suggestions. * More comments and suggestions from Arnd Bergmann. - * Sat May 19, 2007: Davi E. M. Arnaut + * Sat May 19, 2007: Davi E. M. Arnaut * Retrieve multiple signals with one read() call - * Sun Jul 15, 2007: Davide Libenzi - * Attach to the sighand only during read() and poll(). */ #include @@ -29,12 +27,102 @@ #include struct signalfd_ctx { + struct list_head lnk; + wait_queue_head_t wqh; sigset_t sigmask; + struct task_struct *tsk; }; +struct signalfd_lockctx { + struct task_struct *tsk; + unsigned long flags; +}; + +/* + * Tries to acquire the sighand lock. We do not increment the sighand + * use count, and we do not even pin the task struct, so we need to + * do it inside an RCU read lock, and we must be prepared for the + * ctx->tsk going to NULL (in signalfd_deliver()), and for the sighand + * being detached. We return 0 if the sighand has been detached, or + * 1 if we were able to pin the sighand lock. + */ +static int signalfd_lock(struct signalfd_ctx *ctx, struct signalfd_lockctx *lk) +{ + struct sighand_struct *sighand = NULL; + + rcu_read_lock(); + lk->tsk = rcu_dereference(ctx->tsk); + if (likely(lk->tsk != NULL)) + sighand = lock_task_sighand(lk->tsk, &lk->flags); + rcu_read_unlock(); + + if (!sighand) + return 0; + + if (!ctx->tsk) { + unlock_task_sighand(lk->tsk, &lk->flags); + return 0; + } + + if (lk->tsk->tgid == current->tgid) + lk->tsk = current; + + return 1; +} + +static void signalfd_unlock(struct signalfd_lockctx *lk) +{ + unlock_task_sighand(lk->tsk, &lk->flags); +} + +/* + * This must be called with the sighand lock held. + */ +void signalfd_deliver(struct task_struct *tsk, int sig) +{ + struct sighand_struct *sighand = tsk->sighand; + struct signalfd_ctx *ctx, *tmp; + + BUG_ON(!sig); + list_for_each_entry_safe(ctx, tmp, &sighand->signalfd_list, lnk) { + /* + * We use a negative signal value as a way to broadcast that the + * sighand has been orphaned, so that we can notify all the + * listeners about this. Remember the ctx->sigmask is inverted, + * so if the user is interested in a signal, that corresponding + * bit will be zero. + */ + if (sig < 0) { + if (ctx->tsk == tsk) { + ctx->tsk = NULL; + list_del_init(&ctx->lnk); + wake_up(&ctx->wqh); + } + } else { + if (!sigismember(&ctx->sigmask, sig)) + wake_up(&ctx->wqh); + } + } +} + +static void signalfd_cleanup(struct signalfd_ctx *ctx) +{ + struct signalfd_lockctx lk; + + /* + * This is tricky. If the sighand is gone, we do not need to remove + * context from the list, the list itself won't be there anymore. + */ + if (signalfd_lock(ctx, &lk)) { + list_del(&ctx->lnk); + signalfd_unlock(&lk); + } + kfree(ctx); +} + static int signalfd_release(struct inode *inode, struct file *file) { - kfree(file->private_data); + signalfd_cleanup(file->private_data); return 0; } @@ -42,15 +130,23 @@ static unsigned int signalfd_poll(struct file *file, poll_table *wait) { struct signalfd_ctx *ctx = file->private_data; unsigned int events = 0; + struct signalfd_lockctx lk; - poll_wait(file, ¤t->sighand->signalfd_wqh, wait); + poll_wait(file, &ctx->wqh, wait); - spin_lock_irq(¤t->sighand->siglock); - if (next_signal(¤t->pending, &ctx->sigmask) || - next_signal(¤t->signal->shared_pending, - &ctx->sigmask)) + /* + * Let the caller get a POLLIN in this case, ala socket recv() when + * the peer disconnects. + */ + if (signalfd_lock(ctx, &lk)) { + if ((lk.tsk == current && + next_signal(&lk.tsk->pending, &ctx->sigmask) > 0) || + next_signal(&lk.tsk->signal->shared_pending, + &ctx->sigmask) > 0) + events |= POLLIN; + signalfd_unlock(&lk); + } else events |= POLLIN; - spin_unlock_irq(¤t->sighand->siglock); return events; } @@ -123,46 +219,59 @@ static ssize_t signalfd_dequeue(struct signalfd_ctx *ctx, siginfo_t *info, int nonblock) { ssize_t ret; + struct signalfd_lockctx lk; DECLARE_WAITQUEUE(wait, current); - spin_lock_irq(¤t->sighand->siglock); - ret = dequeue_signal(current, &ctx->sigmask, info); + if (!signalfd_lock(ctx, &lk)) + return 0; + + ret = dequeue_signal(lk.tsk, &ctx->sigmask, info); switch (ret) { case 0: if (!nonblock) break; ret = -EAGAIN; default: - spin_unlock_irq(¤t->sighand->siglock); + signalfd_unlock(&lk); return ret; } - add_wait_queue(¤t->sighand->signalfd_wqh, &wait); + add_wait_queue(&ctx->wqh, &wait); for (;;) { set_current_state(TASK_INTERRUPTIBLE); - ret = dequeue_signal(current, &ctx->sigmask, info); + ret = dequeue_signal(lk.tsk, &ctx->sigmask, info); + signalfd_unlock(&lk); if (ret != 0) break; if (signal_pending(current)) { ret = -ERESTARTSYS; break; } - spin_unlock_irq(¤t->sighand->siglock); schedule(); - spin_lock_irq(¤t->sighand->siglock); + ret = signalfd_lock(ctx, &lk); + if (unlikely(!ret)) { + /* + * Let the caller read zero byte, ala socket + * recv() when the peer disconnect. This test + * must be done before doing a dequeue_signal(), + * because if the sighand has been orphaned, + * the dequeue_signal() call is going to crash + * because ->sighand will be long gone. + */ + break; + } } - spin_unlock_irq(¤t->sighand->siglock); - remove_wait_queue(¤t->sighand->signalfd_wqh, &wait); + remove_wait_queue(&ctx->wqh, &wait); __set_current_state(TASK_RUNNING); return ret; } /* - * Returns a multiple of the size of a "struct signalfd_siginfo", or a negative - * error code. The "count" parameter must be at least the size of a - * "struct signalfd_siginfo". + * Returns either the size of a "struct signalfd_siginfo", or zero if the + * sighand we are attached to, has been orphaned. The "count" parameter + * must be at least the size of a "struct signalfd_siginfo". */ static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) @@ -178,6 +287,7 @@ static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count, return -EINVAL; siginfo = (struct signalfd_siginfo __user *) buf; + do { ret = signalfd_dequeue(ctx, &info, nonblock); if (unlikely(ret <= 0)) @@ -190,7 +300,7 @@ static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count, nonblock = 1; } while (--count); - return total ? total: ret; + return total ? total : ret; } static const struct file_operations signalfd_fops = { @@ -199,13 +309,20 @@ static const struct file_operations signalfd_fops = { .read = signalfd_read, }; +/* + * Create a file descriptor that is associated with our signal + * state. We can pass it around to others if we want to, but + * it will always be _our_ signal state. + */ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask) { int error; sigset_t sigmask; struct signalfd_ctx *ctx; + struct sighand_struct *sighand; struct file *file; struct inode *inode; + struct signalfd_lockctx lk; if (sizemask != sizeof(sigset_t) || copy_from_user(&sigmask, user_mask, sizeof(sigmask))) @@ -218,7 +335,17 @@ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemas if (!ctx) return -ENOMEM; + init_waitqueue_head(&ctx->wqh); ctx->sigmask = sigmask; + ctx->tsk = current->group_leader; + + sighand = current->sighand; + /* + * Add this fd to the list of signal listeners. + */ + spin_lock_irq(&sighand->siglock); + list_add_tail(&ctx->lnk, &sighand->signalfd_list); + spin_unlock_irq(&sighand->siglock); /* * When we call this, the initialization must be complete, since @@ -237,18 +364,23 @@ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemas fput(file); return -EINVAL; } - spin_lock_irq(¤t->sighand->siglock); - ctx->sigmask = sigmask; - spin_unlock_irq(¤t->sighand->siglock); - - wake_up(¤t->sighand->signalfd_wqh); + /* + * We need to be prepared of the fact that the sighand this fd + * is attached to, has been detched. In that case signalfd_lock() + * will return 0, and we'll just skip setting the new mask. + */ + if (signalfd_lock(ctx, &lk)) { + ctx->sigmask = sigmask; + signalfd_unlock(&lk); + } + wake_up(&ctx->wqh); fput(file); } return ufd; err_fdalloc: - kfree(ctx); + signalfd_cleanup(ctx); return error; } diff --git a/trunk/fs/xfs/linux-2.6/xfs_aops.c b/trunk/fs/xfs/linux-2.6/xfs_aops.c index 5f152f60d74d..d9c40fe64195 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_aops.c +++ b/trunk/fs/xfs/linux-2.6/xfs_aops.c @@ -181,7 +181,6 @@ xfs_setfilesize( ip->i_d.di_size = isize; ip->i_update_core = 1; ip->i_update_size = 1; - mark_inode_dirty_sync(vn_to_inode(ioend->io_vnode)); } xfs_iunlock(ip, XFS_ILOCK_EXCL); diff --git a/trunk/fs/xfs/linux-2.6/xfs_super.c b/trunk/fs/xfs/linux-2.6/xfs_super.c index 491d1f4f202d..4528f9a3f304 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_super.c +++ b/trunk/fs/xfs/linux-2.6/xfs_super.c @@ -415,10 +415,8 @@ xfs_fs_write_inode( if (vp) { vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); - if (sync) { - filemap_fdatawait(inode->i_mapping); + if (sync) flags |= FLUSH_SYNC; - } error = bhv_vop_iflush(vp, flags); if (error == EAGAIN) error = sync? bhv_vop_iflush(vp, flags | FLUSH_LOG) : 0; diff --git a/trunk/fs/xfs/xfs_buf_item.h b/trunk/fs/xfs/xfs_buf_item.h index fa25b7dcc6c3..d7e136143066 100644 --- a/trunk/fs/xfs/xfs_buf_item.h +++ b/trunk/fs/xfs/xfs_buf_item.h @@ -52,11 +52,6 @@ typedef struct xfs_buf_log_format_t { #define XFS_BLI_UDQUOT_BUF 0x4 #define XFS_BLI_PDQUOT_BUF 0x8 #define XFS_BLI_GDQUOT_BUF 0x10 -/* - * This flag indicates that the buffer contains newly allocated - * inodes. - */ -#define XFS_BLI_INODE_NEW_BUF 0x20 #define XFS_BLI_CHUNK 128 #define XFS_BLI_SHIFT 7 diff --git a/trunk/fs/xfs/xfs_filestream.c b/trunk/fs/xfs/xfs_filestream.c index 16f8e175167d..ce2278611bb7 100644 --- a/trunk/fs/xfs/xfs_filestream.c +++ b/trunk/fs/xfs/xfs_filestream.c @@ -467,7 +467,8 @@ void xfs_filestream_flush( xfs_mount_t *mp) { - xfs_mru_cache_flush(mp->m_filestream); + /* point in time flush, so keep the reaper running */ + xfs_mru_cache_flush(mp->m_filestream, 1); } /* diff --git a/trunk/fs/xfs/xfs_log_recover.c b/trunk/fs/xfs/xfs_log_recover.c index dacb19739cc2..8ae6e8e5f3db 100644 --- a/trunk/fs/xfs/xfs_log_recover.c +++ b/trunk/fs/xfs/xfs_log_recover.c @@ -1874,7 +1874,6 @@ xlog_recover_do_inode_buffer( /*ARGSUSED*/ STATIC void xlog_recover_do_reg_buffer( - xfs_mount_t *mp, xlog_recover_item_t *item, xfs_buf_t *bp, xfs_buf_log_format_t *buf_f) @@ -1885,50 +1884,6 @@ xlog_recover_do_reg_buffer( unsigned int *data_map = NULL; unsigned int map_size = 0; int error; - int stale_buf = 1; - - /* - * Scan through the on-disk inode buffer and attempt to - * determine if it has been written to since it was logged. - * - * - If any of the magic numbers are incorrect then the buffer is stale - * - If any of the modes are non-zero then the buffer is not stale - * - If all of the modes are zero and at least one of the generation - * counts is non-zero then the buffer is stale - * - * If the end result is a stale buffer then the log buffer is replayed - * otherwise it is skipped. - * - * This heuristic is not perfect. It can be improved by scanning the - * entire inode chunk for evidence that any of the inode clusters have - * been updated. To fix this problem completely we will need a major - * architectural change to the logging system. - */ - if (buf_f->blf_flags & XFS_BLI_INODE_NEW_BUF) { - xfs_dinode_t *dip; - int inodes_per_buf; - int mode_count = 0; - int gen_count = 0; - - stale_buf = 0; - inodes_per_buf = XFS_BUF_COUNT(bp) >> mp->m_sb.sb_inodelog; - for (i = 0; i < inodes_per_buf; i++) { - dip = (xfs_dinode_t *)xfs_buf_offset(bp, - i * mp->m_sb.sb_inodesize); - if (be16_to_cpu(dip->di_core.di_magic) != - XFS_DINODE_MAGIC) { - stale_buf = 1; - break; - } - if (be16_to_cpu(dip->di_core.di_mode)) - mode_count++; - if (be16_to_cpu(dip->di_core.di_gen)) - gen_count++; - } - - if (!mode_count && gen_count) - stale_buf = 1; - } switch (buf_f->blf_type) { case XFS_LI_BUF: @@ -1962,7 +1917,7 @@ xlog_recover_do_reg_buffer( -1, 0, XFS_QMOPT_DOWARN, "dquot_buf_recover"); } - if (!error && stale_buf) + if (!error) memcpy(xfs_buf_offset(bp, (uint)bit << XFS_BLI_SHIFT), /* dest */ item->ri_buf[i].i_addr, /* source */ @@ -2134,7 +2089,7 @@ xlog_recover_do_dquot_buffer( if (log->l_quotaoffs_flag & type) return; - xlog_recover_do_reg_buffer(mp, item, bp, buf_f); + xlog_recover_do_reg_buffer(item, bp, buf_f); } /* @@ -2235,7 +2190,7 @@ xlog_recover_do_buffer_trans( (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) { xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f); } else { - xlog_recover_do_reg_buffer(mp, item, bp, buf_f); + xlog_recover_do_reg_buffer(item, bp, buf_f); } if (error) return XFS_ERROR(error); diff --git a/trunk/fs/xfs/xfs_mru_cache.c b/trunk/fs/xfs/xfs_mru_cache.c index e0b358c1c533..7deb9e3cbbd3 100644 --- a/trunk/fs/xfs/xfs_mru_cache.c +++ b/trunk/fs/xfs/xfs_mru_cache.c @@ -206,11 +206,8 @@ _xfs_mru_cache_list_insert( */ if (!_xfs_mru_cache_migrate(mru, now)) { mru->time_zero = now; - if (!mru->queued) { - mru->queued = 1; - queue_delayed_work(xfs_mru_reap_wq, &mru->work, - mru->grp_count * mru->grp_time); - } + if (!mru->next_reap) + mru->next_reap = mru->grp_count * mru->grp_time; } else { grp = (now - mru->time_zero) / mru->grp_time; grp = (mru->lru_grp + grp) % mru->grp_count; @@ -274,26 +271,29 @@ _xfs_mru_cache_reap( struct work_struct *work) { xfs_mru_cache_t *mru = container_of(work, xfs_mru_cache_t, work.work); - unsigned long now, next; + unsigned long now; ASSERT(mru && mru->lists); if (!mru || !mru->lists) return; mutex_spinlock(&mru->lock); - next = _xfs_mru_cache_migrate(mru, jiffies); - _xfs_mru_cache_clear_reap_list(mru); - - mru->queued = next; - if ((mru->queued > 0)) { - now = jiffies; - if (next <= now) - next = 0; - else - next -= now; - queue_delayed_work(xfs_mru_reap_wq, &mru->work, next); + now = jiffies; + if (mru->reap_all || + (mru->next_reap && time_after(now, mru->next_reap))) { + if (mru->reap_all) + now += mru->grp_count * mru->grp_time * 2; + mru->next_reap = _xfs_mru_cache_migrate(mru, now); + _xfs_mru_cache_clear_reap_list(mru); } + /* + * the process that triggered the reap_all is responsible + * for restating the periodic reap if it is required. + */ + if (!mru->reap_all) + queue_delayed_work(xfs_mru_reap_wq, &mru->work, mru->grp_time); + mru->reap_all = 0; mutex_spinunlock(&mru->lock, 0); } @@ -352,7 +352,7 @@ xfs_mru_cache_create( /* An extra list is needed to avoid reaping up to a grp_time early. */ mru->grp_count = grp_count + 1; - mru->lists = kmem_zalloc(mru->grp_count * sizeof(*mru->lists), KM_SLEEP); + mru->lists = kmem_alloc(mru->grp_count * sizeof(*mru->lists), KM_SLEEP); if (!mru->lists) { err = ENOMEM; @@ -374,6 +374,11 @@ xfs_mru_cache_create( mru->grp_time = grp_time; mru->free_func = free_func; + /* start up the reaper event */ + mru->next_reap = 0; + mru->reap_all = 0; + queue_delayed_work(xfs_mru_reap_wq, &mru->work, mru->grp_time); + *mrup = mru; exit: @@ -389,25 +394,35 @@ xfs_mru_cache_create( * Call xfs_mru_cache_flush() to flush out all cached entries, calling their * free functions as they're deleted. When this function returns, the caller is * guaranteed that all the free functions for all the elements have finished - * executing and the reaper is not running. + * executing. + * + * While we are flushing, we stop the periodic reaper event from triggering. + * Normally, we want to restart this periodic event, but if we are shutting + * down the cache we do not want it restarted. hence the restart parameter + * where 0 = do not restart reaper and 1 = restart reaper. */ void xfs_mru_cache_flush( - xfs_mru_cache_t *mru) + xfs_mru_cache_t *mru, + int restart) { if (!mru || !mru->lists) return; + cancel_rearming_delayed_workqueue(xfs_mru_reap_wq, &mru->work); + mutex_spinlock(&mru->lock); - if (mru->queued) { - mutex_spinunlock(&mru->lock, 0); - cancel_rearming_delayed_workqueue(xfs_mru_reap_wq, &mru->work); - mutex_spinlock(&mru->lock); - } + mru->reap_all = 1; + mutex_spinunlock(&mru->lock, 0); - _xfs_mru_cache_migrate(mru, jiffies + mru->grp_count * mru->grp_time); - _xfs_mru_cache_clear_reap_list(mru); + queue_work(xfs_mru_reap_wq, &mru->work.work); + flush_workqueue(xfs_mru_reap_wq); + mutex_spinlock(&mru->lock); + WARN_ON_ONCE(mru->reap_all != 0); + mru->reap_all = 0; + if (restart) + queue_delayed_work(xfs_mru_reap_wq, &mru->work, mru->grp_time); mutex_spinunlock(&mru->lock, 0); } @@ -418,7 +433,8 @@ xfs_mru_cache_destroy( if (!mru || !mru->lists) return; - xfs_mru_cache_flush(mru); + /* we don't want the reaper to restart here */ + xfs_mru_cache_flush(mru, 0); kmem_free(mru->lists, mru->grp_count * sizeof(*mru->lists)); kmem_free(mru, sizeof(*mru)); diff --git a/trunk/fs/xfs/xfs_mru_cache.h b/trunk/fs/xfs/xfs_mru_cache.h index dd58ea1bbebe..624fd10ee8e5 100644 --- a/trunk/fs/xfs/xfs_mru_cache.h +++ b/trunk/fs/xfs/xfs_mru_cache.h @@ -32,9 +32,11 @@ typedef struct xfs_mru_cache unsigned int grp_time; /* Time period spanned by grps. */ unsigned int lru_grp; /* Group containing time zero. */ unsigned long time_zero; /* Time first element was added. */ + unsigned long next_reap; /* Time that the reaper should + next do something. */ + unsigned int reap_all; /* if set, reap all lists */ xfs_mru_cache_free_func_t free_func; /* Function pointer for freeing. */ struct delayed_work work; /* Workqueue data for reaping. */ - unsigned int queued; /* work has been queued */ } xfs_mru_cache_t; int xfs_mru_cache_init(void); @@ -42,7 +44,7 @@ void xfs_mru_cache_uninit(void); int xfs_mru_cache_create(struct xfs_mru_cache **mrup, unsigned int lifetime_ms, unsigned int grp_count, xfs_mru_cache_free_func_t free_func); -void xfs_mru_cache_flush(xfs_mru_cache_t *mru); +void xfs_mru_cache_flush(xfs_mru_cache_t *mru, int restart); void xfs_mru_cache_destroy(struct xfs_mru_cache *mru); int xfs_mru_cache_insert(struct xfs_mru_cache *mru, unsigned long key, void *value); diff --git a/trunk/fs/xfs/xfs_trans_buf.c b/trunk/fs/xfs/xfs_trans_buf.c index 95fff6872a2f..60b6b898022b 100644 --- a/trunk/fs/xfs/xfs_trans_buf.c +++ b/trunk/fs/xfs/xfs_trans_buf.c @@ -966,7 +966,6 @@ xfs_trans_inode_alloc_buf( ASSERT(atomic_read(&bip->bli_refcount) > 0); bip->bli_flags |= XFS_BLI_INODE_ALLOC_BUF; - bip->bli_format.blf_flags |= XFS_BLI_INODE_NEW_BUF; } diff --git a/trunk/fs/xfs/xfs_vnodeops.c b/trunk/fs/xfs/xfs_vnodeops.c index 603459229904..1a5ad8cd97b0 100644 --- a/trunk/fs/xfs/xfs_vnodeops.c +++ b/trunk/fs/xfs/xfs_vnodeops.c @@ -1082,9 +1082,6 @@ xfs_fsync( if (XFS_FORCED_SHUTDOWN(ip->i_mount)) return XFS_ERROR(EIO); - if (flag & FSYNC_DATA) - filemap_fdatawait(vn_to_inode(XFS_ITOV(ip))->i_mapping); - /* * We always need to make sure that the required inode state * is safe on disk. The vnode might be clean but because @@ -3772,16 +3769,12 @@ xfs_inode_flush( sync_lsn = log->l_last_sync_lsn; GRANT_UNLOCK(log, s); - if ((XFS_LSN_CMP(iip->ili_last_lsn, sync_lsn) > 0)) { - if (flags & FLUSH_SYNC) - log_flags |= XFS_LOG_SYNC; - error = xfs_log_force(mp, iip->ili_last_lsn, log_flags); - if (error) - return error; - } - - if (ip->i_update_core == 0) + if ((XFS_LSN_CMP(iip->ili_last_lsn, sync_lsn) <= 0)) return 0; + + if (flags & FLUSH_SYNC) + log_flags |= XFS_LOG_SYNC; + return xfs_log_force(mp, iip->ili_last_lsn, log_flags); } } @@ -3795,6 +3788,9 @@ xfs_inode_flush( if (flags & FLUSH_INODE) { int flush_flags; + if (xfs_ipincount(ip)) + return EAGAIN; + if (flags & FLUSH_SYNC) { xfs_ilock(ip, XFS_ILOCK_SHARED); xfs_iflock(ip); diff --git a/trunk/include/asm-mips/compiler.h b/trunk/include/asm-mips/compiler.h index aa6b876bbd78..169ae26105e9 100644 --- a/trunk/include/asm-mips/compiler.h +++ b/trunk/include/asm-mips/compiler.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007 Maciej W. Rozycki + * Copyright (C) 2004 Maciej W. Rozycki * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -9,10 +9,8 @@ #define _ASM_COMPILER_H #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) -#define GCC_IMM_ASM "n" #define GCC_REG_ACCUM "$0" #else -#define GCC_IMM_ASM "rn" #define GCC_REG_ACCUM "accum" #endif diff --git a/trunk/include/asm-powerpc/time.h b/trunk/include/asm-powerpc/time.h index c104c15c6625..d7f5ddfbaac7 100644 --- a/trunk/include/asm-powerpc/time.h +++ b/trunk/include/asm-powerpc/time.h @@ -149,11 +149,6 @@ static inline u64 get_tb(void) } #endif /* !CONFIG_PPC64 */ -static inline u64 get_tb_or_rtc(void) -{ - return __USE_RTC() ? get_rtc() : get_tb(); -} - static inline void set_tb(unsigned int upper, unsigned int lower) { mtspr(SPRN_TBWL, 0); diff --git a/trunk/include/asm-x86_64/pgalloc.h b/trunk/include/asm-x86_64/pgalloc.h index 8bb564687860..b467be6d367f 100644 --- a/trunk/include/asm-x86_64/pgalloc.h +++ b/trunk/include/asm-x86_64/pgalloc.h @@ -4,6 +4,10 @@ #include #include #include +#include + +#define QUICK_PGD 0 /* We preserve special mappings over free */ +#define QUICK_PT 1 /* Other page table pages that are zero on free */ #define pmd_populate_kernel(mm, pmd, pte) \ set_pmd(pmd, __pmd(_PAGE_TABLE | __pa(pte))) @@ -20,23 +24,23 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *p static inline void pmd_free(pmd_t *pmd) { BUG_ON((unsigned long)pmd & (PAGE_SIZE-1)); - free_page((unsigned long)pmd); + quicklist_free(QUICK_PT, NULL, pmd); } static inline pmd_t *pmd_alloc_one (struct mm_struct *mm, unsigned long addr) { - return (pmd_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT); + return (pmd_t *)quicklist_alloc(QUICK_PT, GFP_KERNEL|__GFP_REPEAT, NULL); } static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) { - return (pud_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT); + return (pud_t *)quicklist_alloc(QUICK_PT, GFP_KERNEL|__GFP_REPEAT, NULL); } static inline void pud_free (pud_t *pud) { BUG_ON((unsigned long)pud & (PAGE_SIZE-1)); - free_page((unsigned long)pud); + quicklist_free(QUICK_PT, NULL, pud); } static inline void pgd_list_add(pgd_t *pgd) @@ -57,41 +61,57 @@ static inline void pgd_list_del(pgd_t *pgd) spin_unlock(&pgd_lock); } -static inline pgd_t *pgd_alloc(struct mm_struct *mm) +static inline void pgd_ctor(void *x) { unsigned boundary; - pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT); - if (!pgd) - return NULL; - pgd_list_add(pgd); + pgd_t *pgd = x; + struct page *page = virt_to_page(pgd); + /* * Copy kernel pointers in from init. - * Could keep a freelist or slab cache of those because the kernel - * part never changes. */ boundary = pgd_index(__PAGE_OFFSET); - memset(pgd, 0, boundary * sizeof(pgd_t)); memcpy(pgd + boundary, - init_level4_pgt + boundary, - (PTRS_PER_PGD - boundary) * sizeof(pgd_t)); + init_level4_pgt + boundary, + (PTRS_PER_PGD - boundary) * sizeof(pgd_t)); + + spin_lock(&pgd_lock); + list_add(&page->lru, &pgd_list); + spin_unlock(&pgd_lock); +} + +static inline void pgd_dtor(void *x) +{ + pgd_t *pgd = x; + struct page *page = virt_to_page(pgd); + + spin_lock(&pgd_lock); + list_del(&page->lru); + spin_unlock(&pgd_lock); +} + +static inline pgd_t *pgd_alloc(struct mm_struct *mm) +{ + pgd_t *pgd = (pgd_t *)quicklist_alloc(QUICK_PGD, + GFP_KERNEL|__GFP_REPEAT, pgd_ctor); return pgd; } static inline void pgd_free(pgd_t *pgd) { BUG_ON((unsigned long)pgd & (PAGE_SIZE-1)); - pgd_list_del(pgd); - free_page((unsigned long)pgd); + quicklist_free(QUICK_PGD, pgd_dtor, pgd); } static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) { - return (pte_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT); + return (pte_t *)quicklist_alloc(QUICK_PT, GFP_KERNEL|__GFP_REPEAT, NULL); } static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) { - void *p = (void *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT); + void *p = (void *)quicklist_alloc(QUICK_PT, GFP_KERNEL|__GFP_REPEAT, NULL); + if (!p) return NULL; return virt_to_page(p); @@ -103,17 +123,22 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long add static inline void pte_free_kernel(pte_t *pte) { BUG_ON((unsigned long)pte & (PAGE_SIZE-1)); - free_page((unsigned long)pte); + quicklist_free(QUICK_PT, NULL, pte); } static inline void pte_free(struct page *pte) { - __free_page(pte); -} + quicklist_free_page(QUICK_PT, NULL, pte); +} -#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte)) +#define __pte_free_tlb(tlb,pte) quicklist_free_page(QUICK_PT, NULL,(pte)) -#define __pmd_free_tlb(tlb,x) tlb_remove_page((tlb),virt_to_page(x)) -#define __pud_free_tlb(tlb,x) tlb_remove_page((tlb),virt_to_page(x)) +#define __pmd_free_tlb(tlb,x) quicklist_free(QUICK_PT, NULL, (x)) +#define __pud_free_tlb(tlb,x) quicklist_free(QUICK_PT, NULL, (x)) +static inline void check_pgt_cache(void) +{ + quicklist_trim(QUICK_PGD, pgd_dtor, 25, 16); + quicklist_trim(QUICK_PT, NULL, 25, 16); +} #endif /* _X86_64_PGALLOC_H */ diff --git a/trunk/include/asm-x86_64/pgtable.h b/trunk/include/asm-x86_64/pgtable.h index 57dd6b3107ea..c9d8764c89d1 100644 --- a/trunk/include/asm-x86_64/pgtable.h +++ b/trunk/include/asm-x86_64/pgtable.h @@ -411,7 +411,6 @@ pte_t *lookup_address(unsigned long addr); #define HAVE_ARCH_UNMAPPED_AREA #define pgtable_cache_init() do { } while (0) -#define check_pgt_cache() do { } while (0) #define PAGE_AGP PAGE_KERNEL_NOCACHE #define HAVE_PAGE_AGP 1 diff --git a/trunk/include/linux/init_task.h b/trunk/include/linux/init_task.h index f8abfa349ef9..cab741c2d603 100644 --- a/trunk/include/linux/init_task.h +++ b/trunk/include/linux/init_task.h @@ -86,7 +86,7 @@ extern struct nsproxy init_nsproxy; .count = ATOMIC_INIT(1), \ .action = { { { .sa_handler = NULL, } }, }, \ .siglock = __SPIN_LOCK_UNLOCKED(sighand.siglock), \ - .signalfd_wqh = __WAIT_QUEUE_HEAD_INITIALIZER(sighand.signalfd_wqh), \ + .signalfd_list = LIST_HEAD_INIT(sighand.signalfd_list), \ } extern struct group_info init_groups; diff --git a/trunk/include/linux/mempolicy.h b/trunk/include/linux/mempolicy.h index a020eb2d4e2a..5bdd656e88cf 100644 --- a/trunk/include/linux/mempolicy.h +++ b/trunk/include/linux/mempolicy.h @@ -159,7 +159,7 @@ extern void mpol_fix_fork_child_flag(struct task_struct *p); extern struct mempolicy default_policy; extern struct zonelist *huge_zonelist(struct vm_area_struct *vma, - unsigned long addr, gfp_t gfp_flags, struct mempolicy **mpol); + unsigned long addr, gfp_t gfp_flags); extern unsigned slab_node(struct mempolicy *policy); extern enum zone_type policy_zone; @@ -256,7 +256,7 @@ static inline void mpol_fix_fork_child_flag(struct task_struct *p) #define set_cpuset_being_rebound(x) do {} while (0) static inline struct zonelist *huge_zonelist(struct vm_area_struct *vma, - unsigned long addr, gfp_t gfp_flags, struct mempolicy **mpol) + unsigned long addr, gfp_t gfp_flags) { return NODE_DATA(0)->node_zonelists + gfp_zone(gfp_flags); } diff --git a/trunk/include/linux/sched.h b/trunk/include/linux/sched.h index a01ac6dd5f5e..f4e324ed2e44 100644 --- a/trunk/include/linux/sched.h +++ b/trunk/include/linux/sched.h @@ -438,7 +438,7 @@ struct sighand_struct { atomic_t count; struct k_sigaction action[_NSIG]; spinlock_t siglock; - wait_queue_head_t signalfd_wqh; + struct list_head signalfd_list; }; struct pacct_struct { @@ -593,7 +593,7 @@ struct user_struct { #endif /* Hash table maintenance information */ - struct hlist_node uidhash_node; + struct list_head uidhash_list; uid_t uid; }; @@ -1406,7 +1406,6 @@ extern unsigned int sysctl_sched_wakeup_granularity; extern unsigned int sysctl_sched_batch_wakeup_granularity; extern unsigned int sysctl_sched_stat_granularity; extern unsigned int sysctl_sched_runtime_limit; -extern unsigned int sysctl_sched_compat_yield; extern unsigned int sysctl_sched_child_runs_first; extern unsigned int sysctl_sched_features; @@ -1473,7 +1472,6 @@ static inline struct user_struct *get_uid(struct user_struct *u) } extern void free_uid(struct user_struct *); extern void switch_uid(struct user_struct *); -extern void release_uids(struct user_namespace *ns); #include diff --git a/trunk/include/linux/signalfd.h b/trunk/include/linux/signalfd.h index 4c9ff0910ae0..510429495690 100644 --- a/trunk/include/linux/signalfd.h +++ b/trunk/include/linux/signalfd.h @@ -45,17 +45,49 @@ struct signalfd_siginfo { #ifdef CONFIG_SIGNALFD /* - * Deliver the signal to listening signalfd. + * Deliver the signal to listening signalfd. This must be called + * with the sighand lock held. Same are the following that end up + * calling signalfd_deliver(). + */ +void signalfd_deliver(struct task_struct *tsk, int sig); + +/* + * No need to fall inside signalfd_deliver() if no signal listeners + * are available. */ static inline void signalfd_notify(struct task_struct *tsk, int sig) { - if (unlikely(waitqueue_active(&tsk->sighand->signalfd_wqh))) - wake_up(&tsk->sighand->signalfd_wqh); + if (unlikely(!list_empty(&tsk->sighand->signalfd_list))) + signalfd_deliver(tsk, sig); +} + +/* + * The signal -1 is used to notify the signalfd that the sighand + * is on its way to be detached. + */ +static inline void signalfd_detach_locked(struct task_struct *tsk) +{ + if (unlikely(!list_empty(&tsk->sighand->signalfd_list))) + signalfd_deliver(tsk, -1); +} + +static inline void signalfd_detach(struct task_struct *tsk) +{ + struct sighand_struct *sighand = tsk->sighand; + + if (unlikely(!list_empty(&sighand->signalfd_list))) { + spin_lock_irq(&sighand->siglock); + signalfd_deliver(tsk, -1); + spin_unlock_irq(&sighand->siglock); + } } #else /* CONFIG_SIGNALFD */ -static inline void signalfd_notify(struct task_struct *tsk, int sig) { } +#define signalfd_deliver(t, s) do { } while (0) +#define signalfd_notify(t, s) do { } while (0) +#define signalfd_detach_locked(t) do { } while (0) +#define signalfd_detach(t) do { } while (0) #endif /* CONFIG_SIGNALFD */ diff --git a/trunk/include/linux/user_namespace.h b/trunk/include/linux/user_namespace.h index b5f41d4c2eec..1101b0ce878f 100644 --- a/trunk/include/linux/user_namespace.h +++ b/trunk/include/linux/user_namespace.h @@ -11,7 +11,7 @@ struct user_namespace { struct kref kref; - struct hlist_head uidhash_table[UIDHASH_SZ]; + struct list_head uidhash_table[UIDHASH_SZ]; struct user_struct *root_user; }; diff --git a/trunk/init/Kconfig b/trunk/init/Kconfig index d54d0cadcc06..96b54595f1dc 100644 --- a/trunk/init/Kconfig +++ b/trunk/init/Kconfig @@ -488,7 +488,6 @@ config SIGNALFD config TIMERFD bool "Enable timerfd() system call" if EMBEDDED select ANON_INODES - depends on BROKEN default y help Enable the timerfd() system call that allows to receive timer diff --git a/trunk/init/do_mounts_initrd.c b/trunk/init/do_mounts_initrd.c index fd4fc12d2624..a6b4c0c08e13 100644 --- a/trunk/init/do_mounts_initrd.c +++ b/trunk/init/do_mounts_initrd.c @@ -57,10 +57,8 @@ static void __init handle_initrd(void) pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD); if (pid > 0) - while (pid != sys_wait4(-1, NULL, 0, NULL)) { - try_to_freeze(); + while (pid != sys_wait4(-1, NULL, 0, NULL)) yield(); - } /* move initrd to rootfs' /old */ sys_fchdir(old_fd); diff --git a/trunk/kernel/exit.c b/trunk/kernel/exit.c index 993369ee94d1..06b24b3aa370 100644 --- a/trunk/kernel/exit.c +++ b/trunk/kernel/exit.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -85,6 +86,14 @@ static void __exit_signal(struct task_struct *tsk) sighand = rcu_dereference(tsk->sighand); spin_lock(&sighand->siglock); + /* + * Notify that this sighand has been detached. This must + * be called with the tsk->sighand lock held. Also, this + * access tsk->sighand internally, so it must be called + * before tsk->sighand is reset. + */ + signalfd_detach_locked(tsk); + posix_cpu_timers_exit(tsk); if (atomic_dec_and_test(&sig->count)) posix_cpu_timers_exit_group(tsk); diff --git a/trunk/kernel/fork.c b/trunk/kernel/fork.c index 33f12f48684a..7332e236d367 100644 --- a/trunk/kernel/fork.c +++ b/trunk/kernel/fork.c @@ -1438,7 +1438,7 @@ static void sighand_ctor(void *data, struct kmem_cache *cachep, struct sighand_struct *sighand = data; spin_lock_init(&sighand->siglock); - init_waitqueue_head(&sighand->signalfd_wqh); + INIT_LIST_HEAD(&sighand->signalfd_list); } void __init proc_caches_init(void) diff --git a/trunk/kernel/sched.c b/trunk/kernel/sched.c index 6107a0cd6325..deeb1f8e0c30 100644 --- a/trunk/kernel/sched.c +++ b/trunk/kernel/sched.c @@ -1682,11 +1682,6 @@ void fastcall wake_up_new_task(struct task_struct *p, unsigned long clone_flags) p->prio = effective_prio(p); - if (rt_prio(p->prio)) - p->sched_class = &rt_sched_class; - else - p->sched_class = &fair_sched_class; - if (!p->sched_class->task_new || !sysctl_sched_child_runs_first || (clone_flags & CLONE_VM) || task_cpu(p) != this_cpu || !current->se.on_rq) { @@ -4555,7 +4550,10 @@ asmlinkage long sys_sched_yield(void) struct rq *rq = this_rq_lock(); schedstat_inc(rq, yld_cnt); - current->sched_class->yield_task(rq, current); + if (unlikely(rq->nr_running == 1)) + schedstat_inc(rq, yld_act_empty); + else + current->sched_class->yield_task(rq, current); /* * Since we are going to call schedule() anyway, there's diff --git a/trunk/kernel/sched_fair.c b/trunk/kernel/sched_fair.c index c9fbe8e73a45..892616bf2c77 100644 --- a/trunk/kernel/sched_fair.c +++ b/trunk/kernel/sched_fair.c @@ -42,14 +42,6 @@ unsigned int sysctl_sched_latency __read_mostly = 20000000ULL; */ unsigned int sysctl_sched_min_granularity __read_mostly = 2000000ULL; -/* - * sys_sched_yield() compat mode - * - * This option switches the agressive yield implementation of the - * old scheduler back on. - */ -unsigned int __read_mostly sysctl_sched_compat_yield; - /* * SCHED_BATCH wake-up granularity. * (default: 25 msec, units: nanoseconds) @@ -905,62 +897,19 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int sleep) } /* - * sched_yield() support is very simple - we dequeue and enqueue. - * - * If compat_yield is turned on then we requeue to the end of the tree. + * sched_yield() support is very simple - we dequeue and enqueue */ static void yield_task_fair(struct rq *rq, struct task_struct *p) { struct cfs_rq *cfs_rq = task_cfs_rq(p); - struct rb_node **link = &cfs_rq->tasks_timeline.rb_node; - struct sched_entity *rightmost, *se = &p->se; - struct rb_node *parent; - - /* - * Are we the only task in the tree? - */ - if (unlikely(cfs_rq->nr_running == 1)) - return; - - if (likely(!sysctl_sched_compat_yield)) { - __update_rq_clock(rq); - /* - * Dequeue and enqueue the task to update its - * position within the tree: - */ - dequeue_entity(cfs_rq, &p->se, 0); - enqueue_entity(cfs_rq, &p->se, 0); - - return; - } - /* - * Find the rightmost entry in the rbtree: - */ - do { - parent = *link; - link = &parent->rb_right; - } while (*link); - rightmost = rb_entry(parent, struct sched_entity, run_node); + __update_rq_clock(rq); /* - * Already in the rightmost position? - */ - if (unlikely(rightmost == se)) - return; - - /* - * Minimally necessary key value to be last in the tree: - */ - se->fair_key = rightmost->fair_key + 1; - - if (cfs_rq->rb_leftmost == &se->run_node) - cfs_rq->rb_leftmost = rb_next(&se->run_node); - /* - * Relink the task to the rightmost position: + * Dequeue and enqueue the task to update its + * position within the tree: */ - rb_erase(&se->run_node, &cfs_rq->tasks_timeline); - rb_link_node(&se->run_node, parent, link); - rb_insert_color(&se->run_node, &cfs_rq->tasks_timeline); + dequeue_entity(cfs_rq, &p->se, 0); + enqueue_entity(cfs_rq, &p->se, 0); } /* diff --git a/trunk/kernel/signal.c b/trunk/kernel/signal.c index 9fb91a32edda..3169bed0b4d0 100644 --- a/trunk/kernel/signal.c +++ b/trunk/kernel/signal.c @@ -378,7 +378,8 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) /* We only dequeue private signals from ourselves, we don't let * signalfd steal them */ - signr = __dequeue_signal(&tsk->pending, mask, info); + if (likely(tsk == current)) + signr = __dequeue_signal(&tsk->pending, mask, info); if (!signr) { signr = __dequeue_signal(&tsk->signal->shared_pending, mask, info); @@ -406,7 +407,8 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) } } } - recalc_sigpending(); + if (likely(tsk == current)) + recalc_sigpending(); if (signr && unlikely(sig_kernel_stop(signr))) { /* * Set a marker that we have dequeued a stop signal. Our @@ -423,7 +425,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT)) tsk->signal->flags |= SIGNAL_STOP_DEQUEUED; } - if (signr && + if (signr && likely(tsk == current) && ((info->si_code & __SI_MASK) == __SI_TIMER) && info->si_sys_private){ /* diff --git a/trunk/kernel/sysctl.c b/trunk/kernel/sysctl.c index 53a456ebf6d5..6ace893c17c9 100644 --- a/trunk/kernel/sysctl.c +++ b/trunk/kernel/sysctl.c @@ -303,14 +303,6 @@ static ctl_table kern_table[] = { .proc_handler = &proc_dointvec, }, #endif - { - .ctl_name = CTL_UNNUMBERED, - .procname = "sched_compat_yield", - .data = &sysctl_sched_compat_yield, - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = &proc_dointvec, - }, #ifdef CONFIG_PROVE_LOCKING { .ctl_name = CTL_UNNUMBERED, diff --git a/trunk/kernel/user.c b/trunk/kernel/user.c index 9ca2848fc356..e7d11cef6998 100644 --- a/trunk/kernel/user.c +++ b/trunk/kernel/user.c @@ -55,22 +55,25 @@ struct user_struct root_user = { /* * These routines must be called with the uidhash spinlock held! */ -static inline void uid_hash_insert(struct user_struct *up, struct hlist_head *hashent) +static inline void uid_hash_insert(struct user_struct *up, struct list_head *hashent) { - hlist_add_head(&up->uidhash_node, hashent); + list_add(&up->uidhash_list, hashent); } static inline void uid_hash_remove(struct user_struct *up) { - hlist_del_init(&up->uidhash_node); + list_del(&up->uidhash_list); } -static inline struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent) +static inline struct user_struct *uid_hash_find(uid_t uid, struct list_head *hashent) { - struct user_struct *user; - struct hlist_node *h; + struct list_head *up; + + list_for_each(up, hashent) { + struct user_struct *user; + + user = list_entry(up, struct user_struct, uidhash_list); - hlist_for_each_entry(user, h, hashent, uidhash_node) { if(user->uid == uid) { atomic_inc(&user->__count); return user; @@ -119,7 +122,7 @@ void free_uid(struct user_struct *up) struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid) { - struct hlist_head *hashent = uidhashentry(ns, uid); + struct list_head *hashent = uidhashentry(ns, uid); struct user_struct *up; spin_lock_irq(&uidhash_lock); @@ -199,30 +202,6 @@ void switch_uid(struct user_struct *new_user) suid_keys(current); } -void release_uids(struct user_namespace *ns) -{ - int i; - unsigned long flags; - struct hlist_head *head; - struct hlist_node *nd; - - spin_lock_irqsave(&uidhash_lock, flags); - /* - * collapse the chains so that the user_struct-s will - * be still alive, but not in hashes. subsequent free_uid() - * will free them. - */ - for (i = 0; i < UIDHASH_SZ; i++) { - head = ns->uidhash_table + i; - while (!hlist_empty(head)) { - nd = head->first; - hlist_del_init(nd); - } - } - spin_unlock_irqrestore(&uidhash_lock, flags); - - free_uid(ns->root_user); -} static int __init uid_cache_init(void) { @@ -232,7 +211,7 @@ static int __init uid_cache_init(void) 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); for(n = 0; n < UIDHASH_SZ; ++n) - INIT_HLIST_HEAD(init_user_ns.uidhash_table + n); + INIT_LIST_HEAD(init_user_ns.uidhash_table + n); /* Insert the root user immediately (init already runs as root) */ spin_lock_irq(&uidhash_lock); diff --git a/trunk/kernel/user_namespace.c b/trunk/kernel/user_namespace.c index 7af90fc4f0fd..85af9422ea6e 100644 --- a/trunk/kernel/user_namespace.c +++ b/trunk/kernel/user_namespace.c @@ -39,7 +39,7 @@ static struct user_namespace *clone_user_ns(struct user_namespace *old_ns) kref_init(&ns->kref); for (n = 0; n < UIDHASH_SZ; ++n) - INIT_HLIST_HEAD(ns->uidhash_table + n); + INIT_LIST_HEAD(ns->uidhash_table + n); /* Insert new root user. */ ns->root_user = alloc_uid(ns, 0); @@ -81,7 +81,7 @@ void free_user_ns(struct kref *kref) struct user_namespace *ns; ns = container_of(kref, struct user_namespace, kref); - release_uids(ns); + free_uid(ns->root_user); kfree(ns); } diff --git a/trunk/kernel/utsname.c b/trunk/kernel/utsname.c index 816d7b24fa03..9d8180a0f0d8 100644 --- a/trunk/kernel/utsname.c +++ b/trunk/kernel/utsname.c @@ -28,9 +28,7 @@ static struct uts_namespace *clone_uts_ns(struct uts_namespace *old_ns) if (!ns) return ERR_PTR(-ENOMEM); - down_read(&uts_sem); memcpy(&ns->name, &old_ns->name, sizeof(ns->name)); - up_read(&uts_sem); kref_init(&ns->kref); return ns; } diff --git a/trunk/mm/hugetlb.c b/trunk/mm/hugetlb.c index 84c795ee2d65..de4cf458d6e1 100644 --- a/trunk/mm/hugetlb.c +++ b/trunk/mm/hugetlb.c @@ -71,9 +71,8 @@ static struct page *dequeue_huge_page(struct vm_area_struct *vma, { int nid; struct page *page = NULL; - struct mempolicy *mpol; struct zonelist *zonelist = huge_zonelist(vma, address, - htlb_alloc_mask, &mpol); + htlb_alloc_mask); struct zone **z; for (z = zonelist->zones; *z; z++) { @@ -88,7 +87,6 @@ static struct page *dequeue_huge_page(struct vm_area_struct *vma, break; } } - mpol_free(mpol); /* unref if mpol !NULL */ return page; } diff --git a/trunk/mm/mempolicy.c b/trunk/mm/mempolicy.c index 3d6ac9505d07..bb54b88c3d5a 100644 --- a/trunk/mm/mempolicy.c +++ b/trunk/mm/mempolicy.c @@ -1077,37 +1077,21 @@ asmlinkage long compat_sys_mbind(compat_ulong_t start, compat_ulong_t len, #endif -/* - * get_vma_policy(@task, @vma, @addr) - * @task - task for fallback if vma policy == default - * @vma - virtual memory area whose policy is sought - * @addr - address in @vma for shared policy lookup - * - * Returns effective policy for a VMA at specified address. - * Falls back to @task or system default policy, as necessary. - * Returned policy has extra reference count if shared, vma, - * or some other task's policy [show_numa_maps() can pass - * @task != current]. It is the caller's responsibility to - * free the reference in these cases. - */ +/* Return effective policy for a VMA */ static struct mempolicy * get_vma_policy(struct task_struct *task, struct vm_area_struct *vma, unsigned long addr) { struct mempolicy *pol = task->mempolicy; - int shared_pol = 0; if (vma) { - if (vma->vm_ops && vma->vm_ops->get_policy) { + if (vma->vm_ops && vma->vm_ops->get_policy) pol = vma->vm_ops->get_policy(vma, addr); - shared_pol = 1; /* if pol non-NULL, add ref below */ - } else if (vma->vm_policy && + else if (vma->vm_policy && vma->vm_policy->policy != MPOL_DEFAULT) pol = vma->vm_policy; } if (!pol) pol = &default_policy; - else if (!shared_pol && pol != current->mempolicy) - mpol_get(pol); /* vma or other task's policy */ return pol; } @@ -1223,45 +1207,19 @@ static inline unsigned interleave_nid(struct mempolicy *pol, } #ifdef CONFIG_HUGETLBFS -/* - * huge_zonelist(@vma, @addr, @gfp_flags, @mpol) - * @vma = virtual memory area whose policy is sought - * @addr = address in @vma for shared policy lookup and interleave policy - * @gfp_flags = for requested zone - * @mpol = pointer to mempolicy pointer for reference counted 'BIND policy - * - * Returns a zonelist suitable for a huge page allocation. - * If the effective policy is 'BIND, returns pointer to policy's zonelist. - * If it is also a policy for which get_vma_policy() returns an extra - * reference, we must hold that reference until after allocation. - * In that case, return policy via @mpol so hugetlb allocation can drop - * the reference. For non-'BIND referenced policies, we can/do drop the - * reference here, so the caller doesn't need to know about the special case - * for default and current task policy. - */ +/* Return a zonelist suitable for a huge page allocation. */ struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr, - gfp_t gfp_flags, struct mempolicy **mpol) + gfp_t gfp_flags) { struct mempolicy *pol = get_vma_policy(current, vma, addr); - struct zonelist *zl; - *mpol = NULL; /* probably no unref needed */ if (pol->policy == MPOL_INTERLEAVE) { unsigned nid; nid = interleave_nid(pol, vma, addr, HPAGE_SHIFT); - __mpol_free(pol); /* finished with pol */ return NODE_DATA(nid)->node_zonelists + gfp_zone(gfp_flags); } - - zl = zonelist_policy(GFP_HIGHUSER, pol); - if (unlikely(pol != &default_policy && pol != current->mempolicy)) { - if (pol->policy != MPOL_BIND) - __mpol_free(pol); /* finished with pol */ - else - *mpol = pol; /* unref needed after allocation */ - } - return zl; + return zonelist_policy(GFP_HIGHUSER, pol); } #endif @@ -1306,7 +1264,6 @@ struct page * alloc_page_vma(gfp_t gfp, struct vm_area_struct *vma, unsigned long addr) { struct mempolicy *pol = get_vma_policy(current, vma, addr); - struct zonelist *zl; cpuset_update_task_memory_state(); @@ -1316,19 +1273,7 @@ alloc_page_vma(gfp_t gfp, struct vm_area_struct *vma, unsigned long addr) nid = interleave_nid(pol, vma, addr, PAGE_SHIFT); return alloc_page_interleave(gfp, 0, nid); } - zl = zonelist_policy(gfp, pol); - if (pol != &default_policy && pol != current->mempolicy) { - /* - * slow path: ref counted policy -- shared or vma - */ - struct page *page = __alloc_pages(gfp, 0, zl); - __mpol_free(pol); - return page; - } - /* - * fast path: default or task policy - */ - return __alloc_pages(gfp, 0, zl); + return __alloc_pages(gfp, 0, zonelist_policy(gfp, pol)); } /** @@ -1927,7 +1872,6 @@ int show_numa_map(struct seq_file *m, void *v) struct numa_maps *md; struct file *file = vma->vm_file; struct mm_struct *mm = vma->vm_mm; - struct mempolicy *pol; int n; char buffer[50]; @@ -1938,13 +1882,8 @@ int show_numa_map(struct seq_file *m, void *v) if (!md) return 0; - pol = get_vma_policy(priv->task, vma, vma->vm_start); - mpol_to_str(buffer, sizeof(buffer), pol); - /* - * unref shared or other task's mempolicy - */ - if (pol != &default_policy && pol != current->mempolicy) - __mpol_free(pol); + mpol_to_str(buffer, sizeof(buffer), + get_vma_policy(priv->task, vma, vma->vm_start)); seq_printf(m, "%08lx %s", vma->vm_start, buffer); diff --git a/trunk/net/netfilter/nfnetlink_log.c b/trunk/net/netfilter/nfnetlink_log.c index 2351533a8507..e185a5b55913 100644 --- a/trunk/net/netfilter/nfnetlink_log.c +++ b/trunk/net/netfilter/nfnetlink_log.c @@ -58,6 +58,7 @@ struct nfulnl_instance { unsigned int qlen; /* number of nlmsgs in skb */ struct sk_buff *skb; /* pre-allocatd skb */ + struct nlmsghdr *lastnlh; /* netlink header of last msg in skb */ struct timer_list timer; int peer_pid; /* PID of the peer process */ @@ -344,12 +345,10 @@ static struct sk_buff *nfulnl_alloc_skb(unsigned int inst_size, static int __nfulnl_send(struct nfulnl_instance *inst) { - int status = -1; + int status; if (inst->qlen > 1) - NLMSG_PUT(inst->skb, 0, 0, - NLMSG_DONE, - sizeof(struct nfgenmsg)); + inst->lastnlh->nlmsg_type = NLMSG_DONE; status = nfnetlink_unicast(inst->skb, inst->peer_pid, MSG_DONTWAIT); if (status < 0) { @@ -359,8 +358,8 @@ __nfulnl_send(struct nfulnl_instance *inst) inst->qlen = 0; inst->skb = NULL; + inst->lastnlh = NULL; -nlmsg_failure: return status; } @@ -539,6 +538,7 @@ __build_packet_message(struct nfulnl_instance *inst, } nlh->nlmsg_len = inst->skb->tail - old_tail; + inst->lastnlh = nlh; return 0; nlmsg_failure: @@ -644,8 +644,7 @@ nfulnl_log_packet(unsigned int pf, } if (inst->qlen >= qthreshold || - (inst->skb && size > - skb_tailroom(inst->skb) - sizeof(struct nfgenmsg))) { + (inst->skb && size > skb_tailroom(inst->skb))) { /* either the queue len is too high or we don't have * enough room in the skb left. flush to userspace. */ UDEBUG("flushing old skb\n"); diff --git a/trunk/net/sched/sch_sfq.c b/trunk/net/sched/sch_sfq.c index 3a23e30bc79e..957957309859 100644 --- a/trunk/net/sched/sch_sfq.c +++ b/trunk/net/sched/sch_sfq.c @@ -270,7 +270,7 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc* sch) q->tail = x; } } - if (++sch->q.qlen <= q->limit) { + if (++sch->q.qlen < q->limit-1) { sch->bstats.bytes += skb->len; sch->bstats.packets++; return 0; @@ -306,7 +306,7 @@ sfq_requeue(struct sk_buff *skb, struct Qdisc* sch) q->tail = x; } } - if (++sch->q.qlen <= q->limit) { + if (++sch->q.qlen < q->limit - 1) { sch->qstats.requeues++; return 0; } @@ -391,10 +391,10 @@ static int sfq_change(struct Qdisc *sch, struct rtattr *opt) q->quantum = ctl->quantum ? : psched_mtu(sch->dev); q->perturb_period = ctl->perturb_period*HZ; if (ctl->limit) - q->limit = min_t(u32, ctl->limit, SFQ_DEPTH - 2); + q->limit = min_t(u32, ctl->limit, SFQ_DEPTH); qlen = sch->q.qlen; - while (sch->q.qlen > q->limit) + while (sch->q.qlen >= q->limit-1) sfq_drop(sch); qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen); @@ -423,7 +423,7 @@ static int sfq_init(struct Qdisc *sch, struct rtattr *opt) q->dep[i+SFQ_DEPTH].next = i+SFQ_DEPTH; q->dep[i+SFQ_DEPTH].prev = i+SFQ_DEPTH; } - q->limit = SFQ_DEPTH - 2; + q->limit = SFQ_DEPTH; q->max_depth = 0; q->tail = SFQ_DEPTH; if (opt == NULL) { diff --git a/trunk/net/sunrpc/svcsock.c b/trunk/net/sunrpc/svcsock.c index 036ab520df21..1a899924023f 100644 --- a/trunk/net/sunrpc/svcsock.c +++ b/trunk/net/sunrpc/svcsock.c @@ -1110,8 +1110,7 @@ svc_tcp_accept(struct svc_sock *svsk) serv->sv_name); printk(KERN_NOTICE "%s: last TCP connect from %s\n", - serv->sv_name, __svc_print_addr(sin, - buf, sizeof(buf))); + serv->sv_name, buf); } /* * Always select the oldest socket. It's not fair, diff --git a/trunk/security/selinux/hooks.c b/trunk/security/selinux/hooks.c index 0753b20e23fe..36946629b6ca 100644 --- a/trunk/security/selinux/hooks.c +++ b/trunk/security/selinux/hooks.c @@ -316,7 +316,6 @@ static inline int inode_doinit(struct inode *inode) } enum { - Opt_error = -1, Opt_context = 1, Opt_fscontext = 2, Opt_defcontext = 4, @@ -328,7 +327,6 @@ static match_table_t tokens = { {Opt_fscontext, "fscontext=%s"}, {Opt_defcontext, "defcontext=%s"}, {Opt_rootcontext, "rootcontext=%s"}, - {Opt_error, NULL}, }; #define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"