diff --git a/[refs] b/[refs] index a6cc815e1848..05a54a7945ff 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 6110e02b97377a2903853faf3ecaff0e742fbe93 +refs/heads/master: a21101c46ca5b4320e31408853cdcbf7cb1ce4ed 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/mach-ep93xx/core.c b/trunk/arch/arm/mach-ep93xx/core.c index 70b2c7801110..851cc7158ca3 100644 --- a/trunk/arch/arm/mach-ep93xx/core.c +++ b/trunk/arch/arm/mach-ep93xx/core.c @@ -336,7 +336,7 @@ static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type) if (line >= 0 && line < 16) { gpio_line_config(line, GPIO_IN); } else { - gpio_line_config(EP93XX_GPIO_LINE_F(line-16), GPIO_IN); + gpio_line_config(EP93XX_GPIO_LINE_F(line), GPIO_IN); } port = line >> 3; diff --git a/trunk/arch/arm/mm/cache-l2x0.c b/trunk/arch/arm/mm/cache-l2x0.c index 76b800a95191..b4e9b734e0bd 100644 --- a/trunk/arch/arm/mm/cache-l2x0.c +++ b/trunk/arch/arm/mm/cache-l2x0.c @@ -57,17 +57,7 @@ static void l2x0_inv_range(unsigned long start, unsigned long end) { unsigned long addr; - 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); - } - + start &= ~(CACHE_LINE_SIZE - 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/acpi/video.c b/trunk/drivers/acpi/video.c index 3c9bb85a6a93..6cb3e7b12145 100644 --- a/trunk/drivers/acpi/video.c +++ b/trunk/drivers/acpi/video.c @@ -1754,7 +1754,7 @@ static int acpi_video_bus_put_devices(struct acpi_video_bus *video) static int acpi_video_bus_start_devices(struct acpi_video_bus *video) { - return acpi_video_bus_DOS(video, 1, 0); + return acpi_video_bus_DOS(video, 0, 0); } static int acpi_video_bus_stop_devices(struct acpi_video_bus *video) 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/kvm/Kconfig b/trunk/drivers/kvm/Kconfig index 0a419a0de603..7b64fd4aa2f3 100644 --- a/trunk/drivers/kvm/Kconfig +++ b/trunk/drivers/kvm/Kconfig @@ -6,8 +6,7 @@ menuconfig VIRTUALIZATION depends on X86 default y ---help--- - Say Y here to get to see options for using your Linux host to run other - operating systems inside virtual machines (guests). + Say Y here to get to see options for virtualization guest drivers. This option alone does not add any kernel code. If you say N, all options in this submenu will be skipped and disabled. 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 36d8f6aa11af..ce2278611bb7 100644 --- a/trunk/fs/xfs/xfs_filestream.c +++ b/trunk/fs/xfs/xfs_filestream.c @@ -350,10 +350,9 @@ _xfs_filestream_update_ag( /* xfs_fstrm_free_func(): callback for freeing cached stream items. */ void xfs_fstrm_free_func( - unsigned long ino, - void *data) + xfs_ino_t ino, + fstrm_item_t *item) { - fstrm_item_t *item = (fstrm_item_t *)data; xfs_inode_t *ip = item->ip; int ref; @@ -439,7 +438,7 @@ xfs_filestream_mount( grp_count = 10; err = xfs_mru_cache_create(&mp->m_filestream, lifetime, grp_count, - xfs_fstrm_free_func); + (xfs_mru_cache_free_func_t)xfs_fstrm_free_func); return err; } @@ -468,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 7174991f4bef..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 (dip->di_core.di_mode) - mode_count++; - if (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"