Merge master.kernel.org:/home/rmk/linux-2.6-arm
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Fri, 21 Sep 2007 21:05:45 +0000 (14:05 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Fri, 21 Sep 2007 21:05:45 +0000 (14:05 -0700)
* master.kernel.org:/home/rmk/linux-2.6-arm:
  [ARM] 4569/1: ep93xx_gpio_irq_type(): fix spurious enumeration offset for FGPIO handling
  [ARM] 4568/1: fix l2x0 cache invalidate handling of unaligned addresses

98 files changed:
Documentation/input/iforce-protocol.txt
Documentation/kernel-parameters.txt
MAINTAINERS
Makefile
arch/i386/boot/header.S
arch/i386/boot/video.c
arch/i386/kernel/acpi/wakeup.S
arch/i386/xen/enlighten.c
arch/mips/dec/setup.c
arch/mips/kernel/cpu-bugs64.c
arch/mips/sibyte/bcm1480/setup.c
arch/powerpc/kernel/time.c
arch/powerpc/kernel/vdso.c
arch/powerpc/platforms/cell/spufs/sched.c
arch/um/include/kern_util.h
arch/um/kernel/irq.c
arch/um/os-Linux/file.c
arch/um/os-Linux/signal.c
arch/x86_64/Kconfig
arch/x86_64/ia32/ia32entry.S
arch/x86_64/kernel/acpi/wakeup.S
arch/x86_64/kernel/process.c
arch/x86_64/kernel/ptrace.c
arch/x86_64/kernel/smp.c
arch/x86_64/mm/fault.c
drivers/ata/ahci.c
drivers/ata/libata-core.c
drivers/ata/libata-sff.c
drivers/base/core.c
drivers/block/DAC960.c
drivers/char/agp/agp.h
drivers/char/agp/intel-agp.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/mspec.c
drivers/ide/ide-disk.c
drivers/ide/ppc/pmac.c
drivers/ieee1394/ieee1394_core.c
drivers/ieee1394/ohci1394.c
drivers/media/video/usbvision/usbvision-cards.c
drivers/mtd/nand/cafe_nand.c
drivers/net/bnx2.c
drivers/net/myri10ge/myri10ge.c
drivers/net/phy/phy.c
drivers/net/pppoe.c
drivers/net/pppol2tp.c
drivers/net/sky2.c
drivers/net/sky2.h
drivers/rtc/rtc-ds1553.c
drivers/rtc/rtc-ds1742.c
drivers/serial/sunsab.c
drivers/video/intelfb/intelfbhw.c
fs/exec.c
fs/ext3/namei.c
fs/ext4/namei.c
fs/nfs/super.c
fs/ocfs2/aops.c
fs/ocfs2/file.c
fs/ocfs2/localalloc.c
fs/ocfs2/localalloc.h
fs/ocfs2/suballoc.c
fs/ocfs2/suballoc.h
fs/ocfs2/vote.c
fs/signalfd.c
fs/xfs/linux-2.6/xfs_aops.c
fs/xfs/linux-2.6/xfs_super.c
fs/xfs/xfs_buf_item.h
fs/xfs/xfs_filestream.c
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_mru_cache.c
fs/xfs/xfs_mru_cache.h
fs/xfs/xfs_trans_buf.c
fs/xfs/xfs_vnodeops.c
include/asm-mips/compiler.h
include/asm-powerpc/time.h
include/asm-x86_64/pgalloc.h
include/asm-x86_64/pgtable.h
include/linux/init_task.h
include/linux/mempolicy.h
include/linux/sched.h
include/linux/signalfd.h
include/linux/user_namespace.h
init/Kconfig
init/do_mounts_initrd.c
kernel/exit.c
kernel/fork.c
kernel/sched.c
kernel/sched_fair.c
kernel/signal.c
kernel/sysctl.c
kernel/user.c
kernel/user_namespace.c
kernel/utsname.c
mm/hugetlb.c
mm/mempolicy.c
net/netfilter/nfnetlink_log.c
net/sched/sch_sfq.c
net/sunrpc/svcsock.c
security/selinux/hooks.c

index 95df4ca70e717865cb23e7520a1ab8e8f978fb21..8777d2d321e38437424896c9f45e26ddff81ebbc 100644 (file)
-** Introduction\r
-This document describes what I managed to discover about the protocol used to\r
-specify force effects to I-Force 2.0 devices.  None of this information comes\r
-from Immerse. That's why you should not trust what is written in this\r
-document. This document is intended to help understanding the protocol.\r
-This is not a reference. Comments and corrections are welcome.  To contact me,\r
-send an email to: deneux@ifrance.com\r
-\r
-** WARNING **\r
-I may not be held responsible for any dammage or harm caused if you try to\r
-send data to your I-Force device based on what you read in this document.\r
-\r
-** Preliminary Notes:\r
-All values are hexadecimal with big-endian encoding (msb on the left). Beware,\r
-values inside packets are encoded using little-endian.  Bytes whose roles are\r
-unknown are marked ???  Information that needs deeper inspection is marked (?)\r
-\r
-** General form of a packet **\r
-This is how packets look when the device uses the rs232 to communicate.\r
-2B OP LEN DATA CS\r
-CS is the checksum. It is equal to the exclusive or of all bytes.\r
-\r
-When using USB:\r
-OP DATA\r
-The 2B, LEN and CS fields have disappeared, probably because USB handles frames and\r
-data corruption is handled or unsignificant.\r
-\r
-First, I describe effects that are sent by the device to the computer\r
-\r
-** Device input state\r
-This packet is used to indicate the state of each button and the value of each\r
-axis\r
-OP= 01 for a joystick, 03 for a wheel\r
-LEN= Varies from device to device\r
-00 X-Axis lsb\r
-01 X-Axis msb\r
-02 Y-Axis lsb, or gas pedal for a wheel\r
-03 Y-Axis msb, or brake pedal for a wheel\r
-04 Throttle\r
-05 Buttons\r
-06 Lower 4 bits: Buttons\r
-   Upper 4 bits: Hat\r
-07 Rudder\r
-\r
-** Device effects states\r
-OP= 02\r
-LEN= Varies\r
-00 ? Bit 1 (Value 2) is the value of the deadman switch\r
-01 Bit 8 is set if the effect is playing. Bits 0 to 7 are the effect id.\r
-02 ??\r
-03 Address of parameter block changed (lsb)\r
-04 Address of parameter block changed (msb)\r
-05 Address of second parameter block changed (lsb)\r
-... depending on the number of parameter blocks updated\r
-\r
-** Force effect **\r
-OP=  01\r
-LEN= 0e\r
-00 Channel (when playing several effects at the same time, each must be assigned a channel)\r
-01 Wave form\r
-       Val 00 Constant\r
-       Val 20 Square\r
-       Val 21 Triangle\r
-       Val 22 Sine\r
-       Val 23 Sawtooth up\r
-       Val 24 Sawtooth down\r
-       Val 40 Spring (Force = f(pos))\r
-       Val 41 Friction (Force = f(velocity)) and Inertia (Force = f(acceleration))\r
-\r
-       \r
-02 Axes affected and trigger\r
-       Bits 4-7: Val 2 = effect along one axis. Byte 05 indicates direction\r
-                 Val 4 = X axis only. Byte 05 must contain 5a\r
-                 Val 8 = Y axis only. Byte 05 must contain b4\r
-                 Val c = X and Y axes. Bytes 05 must contain 60\r
-       Bits 0-3: Val 0 = No trigger\r
-                 Val x+1 = Button x triggers the effect\r
-       When the whole byte is 0, cancel the previously set trigger\r
-\r
-03-04 Duration of effect (little endian encoding, in ms)\r
-\r
-05 Direction of effect, if applicable. Else, see 02 for value to assign.\r
-\r
-06-07 Minimum time between triggering.\r
-\r
-08-09 Address of periodicity or magnitude parameters\r
-0a-0b Address of attack and fade parameters, or ffff if none.\r
-*or*\r
-08-09 Address of interactive parameters for X-axis, or ffff if not applicable\r
-0a-0b Address of interactive parameters for Y-axis, or ffff if not applicable\r
-\r
-0c-0d Delay before execution of effect (little endian encoding, in ms)\r
-\r
-\r
-** Time based parameters **\r
-\r
-*** Attack and fade ***\r
-OP=  02\r
-LEN= 08\r
-00-01 Address where to store the parameteres\r
-02-03 Duration of attack (little endian encoding, in ms)\r
-04 Level at end of attack. Signed byte.\r
-05-06 Duration of fade.\r
-07 Level at end of fade.\r
-\r
-*** Magnitude ***\r
-OP=  03\r
-LEN= 03\r
-00-01 Address\r
-02 Level. Signed byte.\r
-\r
-*** Periodicity ***\r
-OP=  04\r
-LEN= 07\r
-00-01 Address\r
-02 Magnitude. Signed byte.\r
-03 Offset. Signed byte.\r
-04 Phase. Val 00 = 0 deg, Val 40 = 90 degs.\r
-05-06 Period (little endian encoding, in ms)\r
-\r
-** Interactive parameters **\r
-OP=  05\r
-LEN= 0a\r
-00-01 Address\r
-02 Positive Coeff\r
-03 Negative Coeff\r
-04+05 Offset (center)\r
-06+07 Dead band (Val 01F4 = 5000 (decimal))\r
-08 Positive saturation (Val 0a = 1000 (decimal) Val 64 = 10000 (decimal))\r
-09 Negative saturation\r
-\r
-The encoding is a bit funny here: For coeffs, these are signed values. The\r
-maximum value is 64 (100 decimal), the min is 9c.\r
-For the offset, the minimum value is FE0C, the maximum value is 01F4.\r
-For the deadband, the minimum value is 0, the max is 03E8.\r
-\r
-** Controls **\r
-OP=  41\r
-LEN= 03\r
-00 Channel\r
-01 Start/Stop\r
-       Val 00: Stop\r
-       Val 01: Start and play once.\r
-       Val 41: Start and play n times (See byte 02 below)\r
-02 Number of iterations n.\r
-\r
-** Init **\r
-\r
-*** Querying features ***\r
-OP=  ff\r
-Query command. Length varies according to the query type.\r
-The general format of this packet is:\r
-ff 01 QUERY [INDEX] CHECKSUM\r
-reponses are of the same form:\r
-FF LEN QUERY VALUE_QUERIED CHECKSUM2\r
-where LEN = 1 + length(VALUE_QUERIED)\r
-\r
-**** Query ram size ****\r
-QUERY = 42 ('B'uffer size)\r
-The device should reply with the same packet plus two additionnal bytes\r
-containing the size of the memory:\r
-ff 03 42 03 e8 CS would mean that the device has 1000 bytes of ram available.\r
-\r
-**** Query number of effects ****\r
-QUERY = 4e ('N'umber of effects)\r
-The device should respond by sending the number of effects that can be played\r
-at the same time (one byte)\r
-ff 02 4e 14 CS would stand for 20 effects.\r
-\r
-**** Vendor's id ****\r
-QUERY = 4d ('M'anufacturer)\r
-Query the vendors'id (2 bytes)\r
-\r
-**** Product id *****\r
-QUERY = 50 ('P'roduct)\r
-Query the product id (2 bytes)\r
-\r
-**** Open device ****\r
-QUERY = 4f ('O'pen) \r
-No data returned.\r
-\r
-**** Close device *****\r
-QUERY = 43 ('C')lose\r
-No data returned.\r
-\r
-**** Query effect ****\r
-QUERY = 45 ('E') \r
-Send effect type.\r
-Returns nonzero if supported (2 bytes)\r
-\r
-**** Firmware Version ****\r
-QUERY = 56 ('V'ersion)\r
-Sends back 3 bytes - major, minor, subminor\r
-\r
-*** Initialisation of the device ***\r
-\r
-**** Set Control ****\r
-!!! Device dependent, can be different on different models !!!\r
-OP=  40 <idx> <val> [<val>]\r
-LEN= 2 or 3\r
-00 Idx\r
-   Idx 00 Set dead zone (0..2048) \r
-   Idx 01 Ignore Deadman sensor (0..1)     \r
-   Idx 02 Enable comm watchdog (0..1)     \r
-   Idx 03 Set the strength of the spring (0..100)   \r
-   Idx 04 Enable or disable the spring (0/1)\r
-   Idx 05 Set axis saturation threshold (0..2048) \r
-\r
-**** Set Effect State ****\r
-OP=  42 <val>\r
-LEN= 1\r
-00 State\r
-   Bit 3 Pause force feedback\r
-   Bit 2 Enable force feedback\r
-   Bit 0 Stop all effects\r
-\r
-**** Set overall gain ****\r
-OP=  43 <val>\r
-LEN= 1\r
-00 Gain\r
-   Val 00 = 0%\r
-   Val 40 = 50%\r
-   Val 80 = 100%\r
-\r
-** Parameter memory **\r
-\r
-Each device has a certain amount of memory to store parameters of effects.\r
-The amount of RAM may vary, I encountered values from 200 to 1000 bytes. Below\r
-is the amount of memory apparently needed for every set of parameters:\r
- - period : 0c\r
- - magnitude : 02\r
- - attack and fade : 0e\r
- - interactive : 08\r
-\r
-** Appendix: How to study the protocol ? **\r
-\r
-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)\r
-2. Start a soft spying RS232 or USB (depending on where you connected your joystick/wheel). I used ComPortSpy from fCoder (alpha version!)\r
-3. Play the effect, and watch what happens on the spy screen.\r
-\r
-A few words about ComPortSpy:\r
-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.\r
-Remember it's free (as in free beer) and alpha!\r
-\r
-** URLS **\r
-Check www.immerse.com for Immersion Studio, and www.fcoder.com for ComPortSpy.\r
-\r
-** Author of this document **\r
-Johann Deneux <deneux@ifrance.com>\r
-Home page at http://www.esil.univ-mrs.fr/~jdeneux/projects/ff/\r
-\r
-Additions by Vojtech Pavlik.\r
-\r
-I-Force is trademark of Immersion Corp.\r
+** 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 <idx> <val> [<val>]
+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 <val>
+LEN= 1
+00 State
+   Bit 3 Pause force feedback
+   Bit 2 Enable force feedback
+   Bit 0 Stop all effects
+
+**** Set overall gain ****
+OP=  43 <val>
+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 <deneux@ifrance.com>
+Home page at http://www.esil.univ-mrs.fr/~jdeneux/projects/ff/
+
+Additions by Vojtech Pavlik.
+
+I-Force is trademark of Immersion Corp.
index 586b6f85d4e035e55db1aef41ca010b346c846f9..4d175c7512464671e14731239d5bf943b72c5614 100644 (file)
@@ -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: <reboot_mode>[,<reboot_mode2>[,...]]
-                       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"
 
index 9c54a5ef0ba7560232ee24fff40c3728fb277ecb..9a91d9e3f1f25c2e0aaded950fae19e4d6fa7e08 100644 (file)
@@ -2622,8 +2622,8 @@ P:        Harald Welte
 P:     Jozsef Kadlecsik
 P:     Patrick McHardy
 M:     kaber@trash.net
-L:     netfilter-devel@lists.netfilter.org
-L:     netfilter@lists.netfilter.org (subscribers-only)
+L:     netfilter-devel@vger.kernel.org
+L:     netfilter@vger.kernel.org
 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@coreworks.de
+M:     kaber@trash.net
 L:     netdev@vger.kernel.org
 T:     git kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6.git
 S:     Maintained
index e0fdf499ef2075675ed39dd9058833343840772e..c265e41ec55a48b9966a5d65845b930b3185dcd0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 23
-EXTRAVERSION =-rc6
-NAME = Pink Farting Weasel
+EXTRAVERSION =-rc7
+NAME = Arr Matey! A Hairy Bilge Rat!
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
index 7f4a2c53bd762b91746216ac44cbe957d938fa33..f3140e596d407d892eb75aa0c486bd7411e1dcb2 100644 (file)
@@ -275,7 +275,7 @@ die:
        hlt
        jmp     die
 
-       .size   die, .-due
+       .size   die, .-die
 
        .section ".initdata", "a"
 setup_corrupt:
index 693f20d3102e9322759adca6834f2de4e159d0a1..e4ba897bf9a3748c89e442141887ea9e0dbba721 100644 (file)
@@ -147,7 +147,7 @@ int mode_defined(u16 mode)
 }
 
 /* Set mode (without recalc) */
-static int raw_set_mode(u16 mode)
+static int raw_set_mode(u16 mode, u16 *real_mode)
 {
        int nmode, i;
        struct card_info *card;
@@ -165,8 +165,10 @@ static int raw_set_mode(u16 mode)
 
                        if ((mode == nmode && visible) ||
                            mode == mi->mode ||
-                           mode == (mi->y << 8)+mi->x)
+                           mode == (mi->y << 8)+mi->x) {
+                               *real_mode = mi->mode;
                                return card->set_mode(mi);
+                       }
 
                        if (visible)
                                nmode++;
@@ -178,7 +180,7 @@ static int raw_set_mode(u16 mode)
                if (mode >= card->xmode_first &&
                    mode < card->xmode_first+card->xmode_n) {
                        struct mode_info mix;
-                       mix.mode = mode;
+                       *real_mode = mix.mode = mode;
                        mix.x = mix.y = 0;
                        return card->set_mode(&mix);
                }
@@ -223,6 +225,7 @@ 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)
@@ -232,13 +235,16 @@ static int set_mode(u16 mode)
        else if (mode == EXTENDED_VGA)
                mode = VIDEO_8POINT;
 
-       rv = raw_set_mode(mode);
+       rv = raw_set_mode(mode, &real_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;
 }
 
index ed0a0f2c1597a8b739f28081850c3f8b5b8c6248..f22ba8534d26ee19488753eacd2e1057ab841a33 100644 (file)
@@ -151,51 +151,30 @@ 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
-#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
-
-       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
+       subb    $VIDEO_FIRST_VESA>>8, %bh
+       cmpb    $2, %bh
+       jb      check_vesa
 
-setbad:        clc
+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
 
index f0c37511d8da82d6e30650a6d7f0cc6cbd6dd368..f01bfcd4bdee4c63059ff2a2fd9f8ec4b1b0d1e1 100644 (file)
@@ -623,8 +623,8 @@ static unsigned long xen_read_cr2_direct(void)
 
 static void xen_write_cr4(unsigned long cr4)
 {
-       /* never allow TSC to be disabled */
-       native_write_cr4(cr4 & ~X86_CR4_TSD);
+       /* Just ignore cr4 changes; Xen doesn't allow us to do
+          anything anyway. */
 }
 
 static unsigned long xen_read_cr3(void)
index b8a5e75ba0ab4b6bce2bc979a8c7527f050c571d..3e634f2f5443585c98a6f360ac595b7f3774d6d2 100644 (file)
@@ -55,7 +55,7 @@ EXPORT_SYMBOL(dec_kn_slot_size);
 
 int dec_tc_bus;
 
-spinlock_t ioasic_ssr_lock;
+DEFINE_SPINLOCK(ioasic_ssr_lock);
 
 volatile u32 *ioasic_base;
 
index ac04f0adc408b45548cc9bd720797d29dec94878..6648fde20b965d839a7e9978ff830662dc5c0d92 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003, 2004  Maciej W. Rozycki
+ * Copyright (C) 2003, 2004, 2007  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"
                :
-               : "rn" (align), "rn" (mod));
+               : GCC_IMM_ASM (align), GCC_IMM_ASM (mod));
 }
 
 static inline void mult_sh_align_mod(long *v1, long *v2, long *w,
index bb28f28e8042254da6c19bbd6ece9da20bba8de8..7e1aa348b8e078d41302a86979789f654eaf33f3 100644 (file)
@@ -15,6 +15,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/reboot.h>
@@ -35,6 +36,7 @@ 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;
 
index 727a6699f2f41c36ffaac9a205a1aaf3405ec554..c627cf86d1e3d1c7ae4501cdb1057f8d81522f25 100644 (file)
@@ -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 = mftb();
+       p->tb = get_tb_or_rtc();
        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();
+       __get_cpu_var(last_jiffy) = get_tb_or_rtc();
        snapshot_purr();
 }
 
@@ -684,6 +684,8 @@ 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);
@@ -977,7 +979,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();
+       boot_tb = get_tb_or_rtc();
 
        tm = get_boot_time();
 
index cef01e4e898916483f289238e7d4bc3ac79c59bb..213fa31ac53785155b4293536b198437e6457182 100644 (file)
@@ -98,6 +98,18 @@ 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
+       },
 };
 
 /*
index c784edd40ea748c74518d0d4bf9d7e4ac1ce4636..5bebe7fbe056de17a39a8b78d419f67580735f74 100644 (file)
@@ -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->prio > ctx->prio &&
+                       if (tmp && 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);
index 8d7f7c1cb9c64e40dd96cd17f8e65fe3b9a323da..6c2be26f1d7db94647ba856f8217b03b86e9e63b 100644 (file)
@@ -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);
 
-unsigned long to_irq_stack(int sig, unsigned long *mask_out);
+extern unsigned long to_irq_stack(unsigned long *mask_out);
 unsigned long from_irq_stack(int nested);
 
 #endif
index 9870febdbead3897b2ed9257ba0548d7e0389159..cf0dd9cf8c430e5cb7578d1166277d74970859ae 100644 (file)
@@ -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(int sig, unsigned long *mask_out)
+unsigned long to_irq_stack(unsigned long *mask_out)
 {
        struct thread_info *ti;
        unsigned long mask, old;
        int nested;
 
-       mask = xchg(&pending_mask, 1 << sig);
+       mask = xchg(&pending_mask, *mask_out);
        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(int sig, unsigned long *mask_out)
                 * and pending_mask contains a bit for each interrupt
                 * that came in.
                 */
-               old = 1 << sig;
+               old = *mask_out;
                do {
                        old |= mask;
                        mask = xchg(&pending_mask, old);
@@ -550,6 +550,7 @@ unsigned long to_irq_stack(int sig, unsigned long *mask_out)
 
                task = cpu_tasks[ti->cpu].task;
                tti = task_thread_info(task);
+
                *ti = *tti;
                ti->real_thread = tti;
                task->stack = ti;
index 6f92f732d25346aef20f43eda05efe8d7f9d8c12..c3ecc2a84e0cb29b3b1a95908cca588fdfc11201 100644 (file)
@@ -320,7 +320,8 @@ int os_file_size(char *file, unsigned long long *size_out)
        }
 
        if(S_ISBLK(buf.ust_mode)){
-               int fd, blocks;
+               int fd;
+               long blocks;
 
                fd = os_open_file(file, of_read(OPENFLAGS()), 0);
                if(fd < 0){
index 18e5c8b67eb8cebbe84db25bed7e64e623522dc9..b98f7ea2d2f6562ce894e4a4fe6f57b003af7768 100644 (file)
@@ -119,7 +119,7 @@ void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
 
 void handle_signal(int sig, struct sigcontext *sc)
 {
-       unsigned long pending = 0;
+       unsigned long pending = 1UL << sig;
 
        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(sig, &pending);
+               bail = to_irq_stack(&pending);
                if(bail)
                        return;
 
index ffa036406289cee0e9734f558d6e57ffa9bb0b7e..b4d9089a6a06736cf5c8b9fc2ac1955a8ad19360 100644 (file)
@@ -60,14 +60,6 @@ config ZONE_DMA
        bool
        default y
 
-config QUICKLIST
-       bool
-       default y
-
-config NR_QUICK
-       int
-       default 2
-
 config ISA
        bool
 
index 938278697e206bdb10027918f5aff8a587383be0..18b23181090808b953f91568d6183345b8028fd1 100644 (file)
        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
@@ -152,7 +164,7 @@ sysenter_tracesys:
        movq    $-ENOSYS,RAX(%rsp)      /* really needed? */
        movq    %rsp,%rdi        /* &pt_regs -> arg1 */
        call    syscall_trace_enter
-       LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
+       LOAD_ARGS32 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
@@ -255,7 +267,7 @@ cstar_tracesys:
        movq $-ENOSYS,RAX(%rsp) /* really needed? */
        movq %rsp,%rdi        /* &pt_regs -> arg1 */
        call syscall_trace_enter
-       LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
+       LOAD_ARGS32 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
@@ -334,7 +346,7 @@ ia32_tracesys:
        movq $-ENOSYS,RAX(%rsp) /* really needed? */
        movq %rsp,%rdi        /* &pt_regs -> arg1 */
        call syscall_trace_enter
-       LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
+       LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
        RESTORE_REST
        jmp ia32_do_syscall
 END(ia32_syscall)
index 13f1480cbec93bbfb8fd2d8f9a7aa8f9a3ba6f48..a06f2bcabef9d5f3cfe0928c31d0b753894d6aca 100644 (file)
@@ -81,7 +81,7 @@ wakeup_code:
        testl   $2, realmode_flags - wakeup_code
        jz      1f
        mov     video_mode - wakeup_code, %ax
-       call    mode_seta
+       call    mode_set
 1:
 
        movw    $0xb800, %ax
@@ -291,52 +291,31 @@ 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_seta:
+mode_set:
        movw    %ax, %bx
-#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
-
-       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
+       subb    $VIDEO_FIRST_VESA>>8, %bh
+       cmpb    $2, %bh
+       jb      check_vesa
 
-setbada:       clc
+setbad:
+       clc
        ret
 
-check_vesaa:
-       subb    $VIDEO_FIRST_VESA>>8, %bh
+check_vesa:
        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     _setbada                                # AH=0 if OK
+       jnz     setbad                          # AH=0 if OK
 
        stc
        ret
 
-_setbada: jmp setbada
-
 wakeup_stack_begin:    # Stack grows down
 
 .org   0xff0
index 2842f50cbe3fde220dfc33a61b720720aa7a7e7f..98956555450beff2c49d22eed79a63aecff87175 100644 (file)
@@ -208,7 +208,6 @@ 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)
index e83cc67155ac253cbbec207b8ef246bc55f0a408..eea3702427b409d28c83c7e02a88c093a5c26232 100644 (file)
@@ -232,10 +232,6 @@ 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)
index 673a300b59442df7dcc193f6fb78e7aaa30eceda..df4a82812adbbad89fe7d491c3ac7347553cb281 100644 (file)
@@ -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);
index 327c9f2fa6269f3020f94f856cd8e0b8b36ab494..54816adb8e933c8c09e41afcf3008331afb5adc6 100644 (file)
@@ -374,6 +374,13 @@ 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
index 06f212ff2b4f2093e6d954c169c8c2454136dbb7..c16820325d7bf127fc1989e3dede84665cc3fed6 100644 (file)
@@ -418,10 +418,12 @@ 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 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 */
+       { 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 */
 
        /* VIA */
        { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */
index c43de9a710db95266f8d49f1e2f12cbb7cb93bdc..772be09b468966277c7d1a41960d52b758cd7480 100644 (file)
@@ -3778,6 +3778,9 @@ 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 */
@@ -3794,6 +3797,7 @@ 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 */
index 1cce2198baaf1203deb7e1e7e6df305e215501df..8023167bbbeb68623fd9939887010fb74362cb70 100644 (file)
@@ -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 a readb() here, to
+       /* Strictly, one may wish to issue an ioread8() 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,6 +307,9 @@ 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
         */
 }
 
index e6738bcbe5a9b2da343e5d20a67b51a6b28545ee..6de33d7a29ba989194cd6fa4f0148cc702acebed 100644 (file)
@@ -679,14 +679,26 @@ 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
                {
-                       char * class_name = make_class_name(dev->class->name,
-                                                               &dev->kobj);
+                       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);
                        if (class_name)
                                error = sysfs_create_link(&dev->parent->kobj,
                                                        &dev->kobj, class_name);
@@ -694,6 +706,11 @@ 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;
index 504a95d888b2ce1863c61c901885c4bd8c033212..84d6aa500e26b24a3e73ada55c87d4c44efb6be9 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/genhd.h>
 #include <linux/hdreg.h>
 #include <linux/blkpg.h>
+#include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
index 35ab1a9f8e8b42269ea1e7a7e9d13f9c86f16d0b..8955e7ff759a7c9b9269fee1e2398a81622cccdd 100644 (file)
@@ -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             0xF0
+#define I830_GMCH_GMS_MASK             0x70
 #define I830_GMCH_GMS_DISABLED         0x00
 #define I830_GMCH_GMS_LOCAL            0x10
 #define I830_GMCH_GMS_STOLEN_512       0x20
@@ -190,6 +190,7 @@ 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)
index 7c69bf259caa7ca3258dfd5d0441dc71d1f6bf21..a5d0e95a227acc618697acc25e5d82282f4900d0 100644 (file)
@@ -511,7 +511,7 @@ static void intel_i830_init_gtt_entries(void)
                 */
                if (IS_G33)
                        size = 0;
-               switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
+               switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
                case I855_GMCH_GMS_STOLEN_1M:
                        gtt_entries = MB(1) - KB(size);
                        break;
index 9b07f78510611197c86fac1d76febf997d1200f1..dd441ff4af56662da423fbd5fc88f1ae8819ac42 100644 (file)
@@ -2215,7 +2215,8 @@ 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) }
+       { PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) },
+       { 0, }
 };
 MODULE_DEVICE_TABLE(pci, ipmi_pci_devices);
 
index c08a4152ee8fc2f5df6032221d519beafb4837f0..049a46cc9f87612b157d2abbe0aedd568d3e3372 100644 (file)
@@ -67,7 +67,7 @@
 /*
  * Page types allocated by the device.
  */
-enum {
+enum mspec_page_type {
        MSPEC_FETCHOP = 1,
        MSPEC_CACHED,
        MSPEC_UNCACHED
@@ -83,15 +83,25 @@ 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 the vma. */
+       spinlock_t lock;        /* Serialize access to this structure. */
        int count;              /* Number of pages allocated. */
-       int type;               /* Type 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. */
        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
@@ -129,8 +139,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, etc.).  Increments the reference count on the underlying
- * mspec data so it is not freed prematurely.
+ * (via fork, munmap, 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)
@@ -151,34 +161,44 @@ static void
 mspec_close(struct vm_area_struct *vma)
 {
        struct vma_data *vdata;
-       int i, pages, result, vdata_size;
+       int index, last_index, result;
+       unsigned long my_page;
 
        vdata = vma->vm_private_data;
-       if (!atomic_dec_and_test(&vdata->refcnt))
-               return;
 
-       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)
+       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)
                        continue;
                /*
                 * Clear the page before sticking it back
                 * into the pool.
                 */
-               result = mspec_zero_block(vdata->maddr[i], PAGE_SIZE);
+               my_page = vdata->maddr[index];
+               vdata->maddr[index] = 0;
+               spin_unlock(&vdata->lock);
+               result = mspec_zero_block(my_page, PAGE_SIZE);
                if (!result)
-                       uncached_free_page(vdata->maddr[i]);
+                       uncached_free_page(my_page);
                else
                        printk(KERN_WARNING "mspec_close(): "
                               "failed to zero page %i\n",
                               result);
+               spin_lock(&vdata->lock);
        }
+       spin_unlock(&vdata->lock);
 
-       if (vdata_size <= PAGE_SIZE)
-               kfree(vdata);
-       else
+       if (!atomic_dec_and_test(&vdata->refcnt))
+               return;
+
+       if (vdata->flags & VMD_VMALLOCED)
                vfree(vdata);
+       else
+               kfree(vdata);
 }
 
 
@@ -195,7 +215,8 @@ mspec_nopfn(struct vm_area_struct *vma, unsigned long address)
        int index;
        struct vma_data *vdata = vma->vm_private_data;
 
-       index = (address - vma->vm_start) >> PAGE_SHIFT;
+       BUG_ON(address < vdata->vm_start || address >= vdata->vm_end);
+       index = (address - vdata->vm_start) >> PAGE_SHIFT;
        maddr = (volatile unsigned long) vdata->maddr[index];
        if (maddr == 0) {
                maddr = uncached_alloc_page(numa_node_id());
@@ -237,10 +258,11 @@ static struct vm_operations_struct mspec_vm_ops = {
  * underlying pages.
  */
 static int
-mspec_mmap(struct file *file, struct vm_area_struct *vma, int type)
+mspec_mmap(struct file *file, struct vm_area_struct *vma,
+                                       enum mspec_page_type type)
 {
        struct vma_data *vdata;
-       int pages, vdata_size;
+       int pages, vdata_size, flags = 0;
 
        if (vma->vm_pgoff != 0)
                return -EINVAL;
@@ -255,12 +277,17 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma, int type)
        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);
index eba1adbc1b6a0733137085f67a6933ccb4ebba13..4754769eda9781ee2531b46f8bcbf42167e41685 100644 (file)
@@ -487,6 +487,7 @@ 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 }
 };
 
index 4b13cd9a027d5f9dc1d2ffc22dec940d7387c2ce..f19eb6daeefd19e805376d1c7f86cde815b75d14 100644 (file)
@@ -1802,9 +1802,7 @@ 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)
index ee45259573c8b3c9450637e07047bb5f58ab9d2b..98fd985a32ffb003affce760342a42a0d54709e6 100644 (file)
@@ -1273,7 +1273,7 @@ static void __exit ieee1394_cleanup(void)
        unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
 }
 
-fs_initcall(ieee1394_init); /* same as ohci1394 */
+module_init(ieee1394_init);
 module_exit(ieee1394_cleanup);
 
 /* Exported symbols */
index 5667c8102efc0dcc56d14a786e602a7437ab4596..372c5c16eb3180df3940d13d8f602acf4c1d97aa 100644 (file)
@@ -3537,7 +3537,5 @@ static int __init ohci1394_init(void)
        return pci_register_driver(&ohci1394_pci_driver);
 }
 
-/* Register before most other device drivers.
- * Useful for remote debugging via physical DMA, e.g. using firescope. */
-fs_initcall(ohci1394_init);
+module_init(ohci1394_init);
 module_exit(ohci1394_cleanup);
index 380564cd3317d222ea2908c7e6e6d8ef1a12e43b..f09eb102731b25693e818eb83700120ad16f68ff 100644 (file)
@@ -1081,6 +1081,7 @@ 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);
index cff969d05d4a1824cb18fda1808f89a9f9700000..6f32a35eb1069142ade478b2860d2c0297568827 100644 (file)
@@ -816,7 +816,8 @@ 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 }
+       { 0x11ab, 0x4100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MEMORY_FLASH << 8, 0xFFFF0 },
+       { 0, }
 };
 
 MODULE_DEVICE_TABLE(pci, cafe_nand_tbl);
index 854d80c330ec8ab4449bddb23a1af1bf43927f0c..66eed22cbd21963e70b7edddc9929ef192dae186 100644 (file)
@@ -54,8 +54,8 @@
 
 #define DRV_MODULE_NAME                "bnx2"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "1.6.4"
-#define DRV_MODULE_RELDATE     "August 3, 2007"
+#define DRV_MODULE_VERSION     "1.6.5"
+#define DRV_MODULE_RELDATE     "September 20, 2007"
 
 #define RUN_AT(x) (jiffies + (x))
 
@@ -6727,7 +6727,8 @@ 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)
+       else if (CHIP_ID(bp) == CHIP_ID_5709_A0 ||
+                CHIP_ID(bp) == CHIP_ID_5709_A1)
                bp->phy_flags |= PHY_DIS_EARLY_DAC_FLAG;
 
        if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
index 1c42266bf88965139244818f49fcca958d1611ad..556962f9612d45ea3f6cfbf90868d0f069fe4e5f 100644 (file)
@@ -3094,9 +3094,12 @@ 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},
 };
 
index 0cc4369cacba77778a9e4a7a92a1338041f94cfb..cb230f44d6fc3418cd899c42a76552a0091e9ee4 100644 (file)
@@ -409,6 +409,7 @@ 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
index 0d7f570b9a545eca66557ff3e903617a9f5b54f2..9b30cd600a643af5ba54f6c47c9be9e15f6c8dbe 100644 (file)
@@ -879,8 +879,7 @@ 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);
 
-       if (dev_queue_xmit(skb) < 0)
-               goto abort;
+       dev_queue_xmit(skb);
 
        return 1;
 
index 266e8b38fe10004366e78f3bce482add5037b407..abe91cb595f4fe723a561282f90ed4a1090ec495 100644 (file)
@@ -491,44 +491,46 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
        u16 hdrflags;
        u16 tunnel_id, session_id;
        int length;
-       struct udphdr *uh;
+       int offset;
 
        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 (skb->len < sizeof(struct udphdr)) {
+       if (!pskb_may_pull(skb, 12)) {
                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 + sizeof(struct udphdr);
+       ptr = skb->data;
 
        /* 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);
 
-               for (length = 0; length < 16; length++)
-                       printk(" %02X", ptr[length]);
+               offset = 0;
+               do {
+                       printk(" %02X", ptr[offset]);
+               } while (++offset < length);
+
                printk("\n");
        }
 
        /* Get length of L2TP packet */
-       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;
-       }
+       length = skb->len;
 
        /* If type is control packet, it is handled by userspace. */
        if (hdrflags & L2TP_HDRFLAG_T) {
@@ -606,7 +608,6 @@ 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;
                }
 
@@ -625,7 +626,6 @@ 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,10 +634,14 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
        }
 
        /* If offset bit set, skip it. */
-       if (hdrflags & L2TP_HDRFLAG_O)
-               ptr += 2 + ntohs(*(__be16 *) ptr);
+       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;
+       }
 
-       skb_pull(skb, ptr - skb->data);
+       __skb_pull(skb, skb_transport_offset(skb));
 
        /* Skip PPP header, if present.  In testing, Microsoft L2TP clients
         * don't send the PPP header (PPP header compression enabled), but
@@ -673,7 +677,6 @@ 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",
@@ -698,6 +701,7 @@ 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);
 
@@ -958,7 +962,6 @@ 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;
 
@@ -989,41 +992,30 @@ 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_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;
+       if (skb_cow_head(skb, headroom))
+               goto abort;
 
        /* Setup PPP header */
-       skb_push(skb2, sizeof(ppph));
-       skb2->data[0] = ppph[0];
-       skb2->data[1] = ppph[1];
+       __skb_push(skb, sizeof(ppph));
+       skb->data[0] = ppph[0];
+       skb->data[1] = ppph[1];
 
        /* Setup L2TP header */
-       skb_push(skb2, hdr_len);
-       pppol2tp_build_l2tp_header(session, skb2->data);
+       pppol2tp_build_l2tp_header(session, __skb_push(skb, hdr_len));
 
        /* Setup UDP header */
        inet = inet_sk(sk_tun);
-       skb_push(skb2, sizeof(struct udphdr));
-       skb_reset_transport_header(skb2);
-       uh = (struct udphdr *) skb2->data;
+       __skb_push(skb, sizeof(*uh));
+       skb_reset_transport_header(skb);
+       uh = udp_hdr(skb);
        uh->source = inet->sport;
        uh->dest = inet->dport;
        uh->len = htons(sizeof(struct udphdr) + hdr_len + sizeof(ppph) + data_len);
        uh->check = 0;
 
-       /* Calculate UDP checksum if configured to do so */
+       /* *BROKEN* Calculate UDP checksum if configured to do so */
        if (sk_tun->sk_no_check != UDP_CSUM_NOXMIT)
-               csum = udp_csum_outgoing(sk_tun, skb2);
+               csum = udp_csum_outgoing(sk_tun, skb);
 
        /* Debug */
        if (session->send_seq)
@@ -1036,7 +1028,7 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
 
        if (session->debug & PPPOL2TP_MSG_DATA) {
                int i;
-               unsigned char *datap = skb2->data;
+               unsigned char *datap = skb->data;
 
                printk(KERN_DEBUG "%s: xmit:", session->name);
                for (i = 0; i < data_len; i++) {
@@ -1049,18 +1041,18 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
                printk("\n");
        }
 
-       memset(&(IPCB(skb2)->opt), 0, sizeof(IPCB(skb2)->opt));
-       IPCB(skb2)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED |
-                              IPSKB_REROUTED);
-       nf_reset(skb2);
+       memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+       IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED |
+                             IPSKB_REROUTED);
+       nf_reset(skb);
 
        /* Get routing info from the tunnel socket */
-       dst_release(skb2->dst);
-       skb2->dst = sk_dst_get(sk_tun);
+       dst_release(skb->dst);
+       skb->dst = sk_dst_get(sk_tun);
 
        /* Queue the packet to IP for output */
-       len = skb2->len;
-       rc = ip_queue_xmit(skb2, 1);
+       len = skb->len;
+       rc = ip_queue_xmit(skb, 1);
 
        /* Update stats */
        if (rc >= 0) {
@@ -1073,17 +1065,12 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
                session->stats.tx_errors++;
        }
 
-       /* 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;
+       /* Free the original skb */
+       kfree_skb(skb);
+       return 1;
 }
 
 /*****************************************************************************
@@ -1326,12 +1313,14 @@ static struct sock *pppol2tp_prepare_tunnel_socket(int fd, u16 tunnel_id,
                goto err;
        }
 
+       sk = sock->sk;
+
        /* Quick sanity checks */
-       err = -ESOCKTNOSUPPORT;
-       if (sock->type != SOCK_DGRAM) {
+       err = -EPROTONOSUPPORT;
+       if (sk->sk_protocol != IPPROTO_UDP) {
                PRINTK(-1, PPPOL2TP_MSG_CONTROL, KERN_ERR,
-                      "tunl %hu: fd %d wrong type, got %d, expected %d\n",
-                      tunnel_id, fd, sock->type, SOCK_DGRAM);
+                      "tunl %hu: fd %d wrong protocol, got %d, expected %d\n",
+                      tunnel_id, fd, sk->sk_protocol, IPPROTO_UDP);
                goto err;
        }
        err = -EAFNOSUPPORT;
@@ -1343,7 +1332,6 @@ 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;
index 5d812de65d90a4d4467327ec675daf5d669d824c..eaffe551d1d8108e68e7d8a59a0db3e5f1b85a22 100644 (file)
@@ -51,7 +51,7 @@
 #include "sky2.h"
 
 #define DRV_NAME               "sky2"
-#define DRV_VERSION            "1.17"
+#define DRV_VERSION            "1.18"
 #define PFX                    DRV_NAME " "
 
 /*
@@ -118,12 +118,15 @@ 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 */
@@ -147,6 +150,7 @@ static const char *yukon2_name[] = {
        "Extreme",      /* 0xb5 */
        "EC",           /* 0xb6 */
        "FE",           /* 0xb7 */
+       "FE+",          /* 0xb8 */
 };
 
 static void sky2_set_multicast(struct net_device *dev);
@@ -217,8 +221,7 @@ static void sky2_power_on(struct sky2_hw *hw)
        else
                sky2_write8(hw, B2_Y2_CLK_GATE, 0);
 
-       if (hw->chip_id == CHIP_ID_YUKON_EC_U ||
-           hw->chip_id == CHIP_ID_YUKON_EX) {
+       if (hw->flags & SKY2_HW_ADV_POWER_CTL) {
                u32 reg;
 
                sky2_pci_write32(hw, PCI_DEV_REG3, 0);
@@ -311,10 +314,8 @@ 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->chip_id == CHIP_ID_YUKON_XL
-                || hw->chip_id == CHIP_ID_YUKON_EC_U
-                || hw->chip_id == CHIP_ID_YUKON_EX)) {
+       if (sky2->autoneg == AUTONEG_ENABLE &&
+           !(hw->flags & SKY2_HW_NEWER_PHY)) {
                u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
 
                ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
@@ -334,7 +335,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->chip_id == CHIP_ID_YUKON_FE) {
+               if (!(hw->flags & SKY2_HW_GIGABIT)) {
                        /* enable automatic crossover */
                        ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1;
                } else {
@@ -346,9 +347,7 @@ 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->chip_id == CHIP_ID_YUKON_XL
-                               || hw->chip_id == CHIP_ID_YUKON_EC_U
-                               || hw->chip_id == CHIP_ID_YUKON_EX)) {
+                           && (hw->flags & SKY2_HW_NEWER_PHY)) {
                                /* 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;
@@ -364,7 +363,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 && !sky2_is_copper(hw)) {
+       if (hw->chip_id == CHIP_ID_YUKON_XL && (hw->flags & SKY2_HW_FIBRE_PHY)) {
                pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
 
                /* Fiber: select 1000BASE-X only mode MAC Specific Ctrl Reg. */
@@ -455,7 +454,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
 
        gma_write16(hw, port, GM_GP_CTRL, reg);
 
-       if (hw->chip_id != CHIP_ID_YUKON_FE)
+       if (hw->flags & SKY2_HW_GIGABIT)
                gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000);
 
        gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv);
@@ -479,6 +478,23 @@ 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);
 
@@ -548,7 +564,13 @@ 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) {
@@ -669,25 +691,25 @@ static void sky2_wol_init(struct sky2_port *sky2)
 
 static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port)
 {
-       if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev != CHIP_REV_YU_EX_A0) {
+       struct net_device *dev = hw->dev[port];
+
+       if (dev->mtu <= ETH_DATA_LEN)
                sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
-                            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);
+                            TX_JUMBO_DIS | TX_STFW_ENA);
 
-                       sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
-                                    TX_JUMBO_ENA | TX_STFW_DIS);
+       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);
 
-                       /* 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);
+               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);
        }
 }
 
@@ -773,7 +795,8 @@ 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)
+       if (hw->chip_id == CHIP_ID_YUKON_EX ||
+           hw->chip_id == CHIP_ID_YUKON_FE_P)
                rx_reg |= GMF_RX_OVER_ON;
 
        sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), rx_reg);
@@ -782,13 +805,18 @@ 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  */
-       sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF+1);
+       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);
 
        /* 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->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) {
+       if (!(hw->flags & SKY2_HW_RAMBUFFER)) {
                sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8);
                sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8);
 
@@ -967,19 +995,15 @@ 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;
+       struct sky2_rx_le *le = sky2_next_rx(sky2);
 
-       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);
-       }
+       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);
 }
 
 /*
@@ -1175,7 +1199,8 @@ static int sky2_rx_start(struct sky2_port *sky2)
 
        sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1);
 
-       rx_set_checksum(sky2);
+       if (!(hw->flags & SKY2_HW_NEW_LE))
+               rx_set_checksum(sky2);
 
        /* Space needed for frame data + headers rounded up */
        size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8);
@@ -1246,7 +1271,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 ramsize, imask;
+       u32 imask;
        int cap, err = -ENOMEM;
        struct net_device *otherdev = hw->dev[sky2->port^1];
 
@@ -1301,13 +1326,13 @@ static int sky2_up(struct net_device *dev)
 
        sky2_mac_init(hw, port);
 
-       /* 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);
-
-       if (ramsize > 0) {
+       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;
 
+               printk(KERN_DEBUG PFX "%s: ram buffer %dK\n", dev->name, ramsize);
+
                if (ramsize < 16)
                        rxspace = ramsize / 2;
                else
@@ -1436,13 +1461,15 @@ 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->chip_id != CHIP_ID_YUKON_EX)
+
+               if (!(hw->flags & SKY2_HW_NEW_LE))
                        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->chip_id == CHIP_ID_YUKON_EX)
+
+                       if (hw->flags & SKY2_HW_NEW_LE)
                                le->opcode = OP_MSS | HW_OWNER;
                        else
                                le->opcode = OP_LRGLEN | HW_OWNER;
@@ -1468,8 +1495,7 @@ 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->chip_id == CHIP_ID_YUKON_EX
-                   && hw->chip_rev != CHIP_REV_YU_EX_B0)
+               if (hw->flags & SKY2_HW_AUTO_TX_SUM)
                        ctrl |= CALSUM; /* auto checksum */
                else {
                        const unsigned offset = skb_transport_offset(skb);
@@ -1622,9 +1648,6 @@ 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);
 
@@ -1708,11 +1731,15 @@ static int sky2_down(struct net_device *dev)
 
 static u16 sky2_phy_speed(const struct sky2_hw *hw, u16 aux)
 {
-       if (!sky2_is_copper(hw))
+       if (hw->flags & SKY2_HW_FIBRE_PHY)
                return SPEED_1000;
 
-       if (hw->chip_id == CHIP_ID_YUKON_FE)
-               return (aux & PHY_M_PS_SPEED_100) ? SPEED_100 : SPEED_10;
+       if (!(hw->flags & SKY2_HW_GIGABIT)) {
+               if (aux & PHY_M_PS_SPEED_100)
+                       return SPEED_100;
+               else
+                       return SPEED_10;
+       }
 
        switch (aux & PHY_M_PS_SPEED_MSK) {
        case PHY_M_PS_SPEED_1000:
@@ -1745,17 +1772,13 @@ static void sky2_link_up(struct sky2_port *sky2)
 
        netif_carrier_on(sky2->netdev);
 
-       if (hw->active++ == 0)
-               mod_timer(&hw->watchdog_timer, jiffies + 1);
-
+       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->chip_id == CHIP_ID_YUKON_XL
-           || hw->chip_id == CHIP_ID_YUKON_EC_U
-           || hw->chip_id == CHIP_ID_YUKON_EX) {
+       if (hw->flags & SKY2_HW_NEWER_PHY) {
                u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
                u16 led = PHY_M_LEDC_LOS_CTRL(1);       /* link active */
 
@@ -1800,11 +1823,6 @@ 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);
 
@@ -1847,7 +1865,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 (!sky2_is_copper(hw)) {
+       if (hw->flags & SKY2_HW_FIBRE_PHY) {
                /* Shift for bits in fiber PHY */
                advert &= ~(ADVERTISE_PAUSE_CAP|ADVERTISE_PAUSE_ASYM);
                lpa &= ~(LPA_PAUSE_CAP|LPA_PAUSE_ASYM);
@@ -1958,7 +1976,9 @@ 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)
+       if (new_mtu > ETH_DATA_LEN &&
+           (hw->chip_id == CHIP_ID_YUKON_FE ||
+            hw->chip_id == CHIP_ID_YUKON_FE_P))
                return -EINVAL;
 
        if (!netif_running(dev)) {
@@ -1975,7 +1995,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
 
        synchronize_irq(hw->pdev->irq);
 
-       if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)
+       if (!(hw->flags & SKY2_HW_RAMBUFFER))
                sky2_set_tx_stfwd(hw, port);
 
        ctl = gma_read16(hw, port, GM_GP_CTRL);
@@ -2103,6 +2123,13 @@ 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",
@@ -2117,7 +2144,8 @@ static struct sk_buff *sky2_receive(struct net_device *dev,
        if (!(status & GMR_FS_RX_OK))
                goto resubmit;
 
-       if (status >> 16 != length)
+       /* if length reported by DMA does not match PHY, packet was truncated */
+       if (length != count)
                goto len_mismatch;
 
        if (length < copybreak)
@@ -2133,6 +2161,10 @@ len_mismatch:
        /* 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;
@@ -2202,7 +2234,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
                        }
 
                        /* This chip reports checksum status differently */
-                       if (hw->chip_id == CHIP_ID_YUKON_EX) {
+                       if (hw->flags & SKY2_HW_NEW_LE) {
                                if (sky2->rx_csum &&
                                    (le->css & (CSS_ISIPV4 | CSS_ISIPV6)) &&
                                    (le->css & CSS_TCPUDPCSOK))
@@ -2243,8 +2275,14 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
                        if (!sky2->rx_csum)
                                break;
 
-                       if (hw->chip_id == CHIP_ID_YUKON_EX)
+                       /* 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);
                                break;
+                       }
 
                        /* Both checksum counters are programmed to start at
                         * the same offset, so unless there is a problem they
@@ -2436,20 +2474,72 @@ static void sky2_le_error(struct sky2_hw *hw, unsigned port,
        sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_CLR_IRQ_CHK);
 }
 
-/* Check for lost IRQ once a second */
+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;
+       }
+}
+
 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)) {
-               struct net_device *dev = hw->dev[0];
-
+               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;
        }
 
-       if (hw->active > 0)
-               mod_timer(&hw->watchdog_timer, round_jiffies(jiffies + HZ));
+       mod_timer(&hw->watchdog_timer, round_jiffies(jiffies + HZ));
 }
 
 /* Hardware/software error handling */
@@ -2546,17 +2636,25 @@ static void sky2_netpoll(struct net_device *dev)
 #endif
 
 /* Chip internal frequency for clock calculations */
-static inline u32 sky2_mhz(const struct sky2_hw *hw)
+static 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;     /* 125 Mhz */
+               return 125;
+
        case CHIP_ID_YUKON_FE:
-               return 100;     /* 100 Mhz */
-       default:                /* YUKON_XL */
-               return 156;     /* 156 Mhz */
+               return 100;
+
+       case CHIP_ID_YUKON_FE_P:
+               return 50;
+
+       case CHIP_ID_YUKON_XL:
+               return 156;
+
+       default:
+               BUG();
        }
 }
 
@@ -2581,23 +2679,62 @@ 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);
-       if (hw->chip_id < CHIP_ID_YUKON_XL || hw->chip_id > CHIP_ID_YUKON_FE) {
+       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:
                dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n",
                        hw->chip_id);
                return -EOPNOTSUPP;
        }
 
-       hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4;
+       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;
 
-       /* 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) {
@@ -2791,7 +2928,9 @@ 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)
+       if (hw->chip_id == CHIP_ID_YUKON_EC_U ||
+           hw->chip_id == CHIP_ID_YUKON_EX ||
+           hw->chip_id == CHIP_ID_YUKON_FE_P)
                sky2_write32(hw, B0_CTST, sky2->wol
                             ? Y2_HW_WOL_ON : Y2_HW_WOL_OFF);
 
@@ -2809,7 +2948,7 @@ static u32 sky2_supported_modes(const struct sky2_hw *hw)
                        | SUPPORTED_100baseT_Full
                        | SUPPORTED_Autoneg | SUPPORTED_TP;
 
-               if (hw->chip_id != CHIP_ID_YUKON_FE)
+               if (hw->flags & SKY2_HW_GIGABIT)
                        modes |= SUPPORTED_1000baseT_Half
                                | SUPPORTED_1000baseT_Full;
                return modes;
@@ -2829,13 +2968,6 @@ 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 {
@@ -3791,6 +3923,13 @@ 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;
@@ -3846,7 +3985,7 @@ static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id)
                return IRQ_NONE;
 
        if (status & Y2_IS_IRQ_SW) {
-               hw->msi = 1;
+               hw->flags |= SKY2_HW_USE_MSI;
                wake_up(&hw->msi_wait);
                sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ);
        }
@@ -3874,9 +4013,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->msi, HZ/10);
+       wait_event_timeout(hw->msi_wait, (hw->flags & SKY2_HW_USE_MSI), HZ/10);
 
-       if (!hw->msi) {
+       if (!(hw->flags & SKY2_HW_USE_MSI)) {
                /* MSI test failed, go back to INTx mode */
                dev_info(&pdev->dev, "No interrupt generated using MSI, "
                         "switching to INTx mode.\n");
@@ -4009,7 +4148,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
                goto err_out_free_netdev;
        }
 
-       err = request_irq(pdev->irq,  sky2_intr, hw->msi ? 0 : IRQF_SHARED,
+       err = request_irq(pdev->irq, sky2_intr,
+                         (hw->flags & SKY2_HW_USE_MSI) ? 0 : IRQF_SHARED,
                          dev->name, hw);
        if (err) {
                dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq);
@@ -4042,7 +4182,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
        return 0;
 
 err_out_unregister:
-       if (hw->msi)
+       if (hw->flags & SKY2_HW_USE_MSI)
                pci_disable_msi(pdev);
        unregister_netdev(dev);
 err_out_free_netdev:
@@ -4091,7 +4231,7 @@ static void __devexit sky2_remove(struct pci_dev *pdev)
        sky2_read8(hw, B0_CTST);
 
        free_irq(pdev->irq, hw);
-       if (hw->msi)
+       if (hw->flags & SKY2_HW_USE_MSI)
                pci_disable_msi(pdev);
        pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma);
        pci_release_regions(pdev);
@@ -4159,7 +4299,9 @@ 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)
+       if (hw->chip_id == CHIP_ID_YUKON_EX ||
+           hw->chip_id == CHIP_ID_YUKON_EC_U ||
+           hw->chip_id == CHIP_ID_YUKON_FE_P)
                sky2_pci_write32(hw, PCI_DEV_REG3, 0);
 
        sky2_reset(hw);
index 72e12b7cfa40e27dd5af5e25e9294b416feef325..69cd98400fe669639b596ea99185d66e9b49e265 100644 (file)
@@ -470,18 +470,24 @@ 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,
@@ -1668,7 +1674,7 @@ enum {
 
 /* Receive Frame Status Encoding */
 enum {
-       GMR_FS_LEN      = 0xffff<<16, /* Bit 31..16:    Rx Frame Length */
+       GMR_FS_LEN      = 0x7fff<<16, /* Bit 30..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 */
@@ -1729,6 +1735,10 @@ 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 {
@@ -2017,6 +2027,14 @@ 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;
@@ -2040,12 +2058,20 @@ 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;
@@ -2053,13 +2079,12 @@ 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->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P');
+       return !(hw->flags & SKY2_HW_FIBRE_PHY);
 }
 
 /* Register accessor for memory mapped device */
index 46da5714932c3e15f9607058a4855aeba02f6e3d..5ab3492817d16b0574202380b9ddb2a394042ba5 100644 (file)
@@ -61,7 +61,7 @@
 struct rtc_plat_data {
        struct rtc_device *rtc;
        void __iomem *ioaddr;
-       unsigned long baseaddr;
+       resource_size_t baseaddr;
        unsigned long last_jiffies;
        int irq;
        unsigned int irqen;
index b2e5481ba3b610766eee9936170c6e3455d03d21..67291b0f82838a6e7214827b0706fdbf07096ae3 100644 (file)
@@ -55,7 +55,7 @@ struct rtc_plat_data {
        void __iomem *ioaddr_rtc;
        size_t size_nvram;
        size_t size;
-       unsigned long baseaddr;
+       resource_size_t baseaddr;
        unsigned long last_jiffies;
 };
 
index bca57bb949393275c902f5f31e35e1abe9527d1a..e348ba684050eca227fa0e8a5ed8f148a0521ccc 100644 (file)
@@ -58,6 +58,7 @@ 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
@@ -305,13 +306,15 @@ 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;
-       if (readb(&up->regs->r.gis) & SAB82532_GIS_ISA0)
+       gis = readb(&up->regs->r.gis) >> up->gis_shift;
+       if (gis & 1)
                status.sreg.isr0 = readb(&up->regs->r.isr0);
-       if (readb(&up->regs->r.gis) & SAB82532_GIS_ISA1)
+       if (gis & 2)
                status.sreg.isr1 = readb(&up->regs->r.isr1);
 
        tty = NULL;
@@ -327,35 +330,6 @@ 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)
@@ -539,6 +513,10 @@ 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);
 
@@ -641,6 +619,7 @@ static void sunsab_shutdown(struct uart_port *port)
 #endif
 
        spin_unlock_irqrestore(&up->port.lock, flags);
+       free_irq(up->port.irq, up);
 }
 
 /*
@@ -1008,9 +987,11 @@ 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);
@@ -1023,19 +1004,6 @@ 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;
 }
 
@@ -1051,52 +1019,60 @@ static int __devinit sab_probe(struct of_device *op, const struct of_device_id *
                              0,
                              (inst * 2) + 0);
        if (err)
-               return err;
+               goto out;
 
        err = sunsab_init_one(&up[1], op,
                              sizeof(union sab82532_async_regs),
                              (inst * 2) + 1);
-       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;
-       }
+       if (err)
+               goto out1;
 
        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);
-       uart_add_one_port(&sunsab_reg, &up[1].port);
+
+       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;
 
        dev_set_drvdata(&op->dev, &up[0]);
 
        inst++;
 
        return 0;
-}
-
-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);
+out3:
+       uart_remove_one_port(&sunsab_reg, &up[0].port);
+out2:
        of_iounmap(&op->resource[0],
-                  up->port.membase,
+                  up[1].port.membase,
                   sizeof(union sab82532_async_regs));
+out1:
+       of_iounmap(&op->resource[0],
+                  up[0].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);
 
-       sab_remove_one(&up[0]);
-       sab_remove_one(&up[1]);
+       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));
 
        dev_set_drvdata(&op->dev, NULL);
 
@@ -1143,6 +1119,7 @@ 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) {
index b21d0dec92836d1481b7a33e4325e91f2a355a1b..6a47682d861446639c5c81bd0db1cc26af3b6036 100644 (file)
@@ -1352,7 +1352,7 @@ intelfbhw_program_mode(struct intelfb_info *dinfo,
 
        /* turn off PLL */
        tmp = INREG(dpll_reg);
-       dpll_reg &= ~DPLL_VCO_ENABLE;
+       tmp &= ~DPLL_VCO_ENABLE;
        OUTREG(dpll_reg, tmp);
 
        /* Set PLL parameters */
index c21a8cc0627709db512597ff2af82ab7c094e67d..073b0b8c6d055a3fd947f16fbdbe5552a6bc34c8 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -50,7 +50,6 @@
 #include <linux/tsacct_kern.h>
 #include <linux/cn_proc.h>
 #include <linux/audit.h>
-#include <linux/signalfd.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -784,7 +783,6 @@ 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;
        }
@@ -923,7 +921,6 @@ 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);
index 1586807b81779ef9c02008e6828c9df50d4f000c..c1fa1908dba05137158d0e9f40b991a983a4c9d8 100644 (file)
@@ -140,7 +140,8 @@ struct dx_frame
 struct dx_map_entry
 {
        u32 hash;
-       u32 offs;
+       u16 offs;
+       u16 size;
 };
 
 #ifdef CONFIG_EXT3_INDEX
@@ -379,13 +380,28 @@ dx_probe(struct dentry *dentry, struct inode *dir,
 
        entries = (struct dx_entry *) (((char *)&root->info) +
                                       root->info.info_length);
-       assert(dx_get_limit(entries) == dx_root_limit(dir,
-                                                     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;
+       }
+
        dxtrace (printk("Look up %x", hash));
        while (1)
        {
                count = dx_get_count(entries);
-               assert (count && count <= dx_get_limit(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;
+               }
+
                p = entries + 1;
                q = entries + count - 1;
                while (p <= q)
@@ -423,8 +439,15 @@ 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;
-               assert (dx_get_limit(entries) == dx_node_limit (dir));
+               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;
+               }
                frame++;
+               frame->bh = NULL;
        }
 fail2:
        while (frame >= frame_in) {
@@ -432,6 +455,10 @@ fail2:
                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;
 }
 
@@ -671,6 +698,10 @@ errout:
  * 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)
 {
@@ -684,7 +715,8 @@ 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 = (u32) ((char *) de - base);
+                       map_tail->offs = (u16) ((char *) de - base);
+                       map_tail->size = le16_to_cpu(de->rec_len);
                        count++;
                        cond_resched();
                }
@@ -694,6 +726,7 @@ 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;
@@ -1091,6 +1124,10 @@ 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)
 {
@@ -1109,6 +1146,10 @@ 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;
@@ -1131,6 +1172,11 @@ 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)
@@ -1142,7 +1188,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;
+       unsigned split, move, size, i;
        struct ext3_dir_entry_2 *de = NULL, *de2;
        int     err = 0;
 
@@ -1170,8 +1216,19 @@ 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",
index da224974af7861efeab66cdd0de475e0679f9432..5fdb862e71c47fb8df885e87e93090141227154a 100644 (file)
@@ -140,7 +140,8 @@ struct dx_frame
 struct dx_map_entry
 {
        u32 hash;
-       u32 offs;
+       u16 offs;
+       u16 size;
 };
 
 #ifdef CONFIG_EXT4_INDEX
@@ -379,13 +380,28 @@ dx_probe(struct dentry *dentry, struct inode *dir,
 
        entries = (struct dx_entry *) (((char *)&root->info) +
                                       root->info.info_length);
-       assert(dx_get_limit(entries) == dx_root_limit(dir,
-                                                     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;
+       }
+
        dxtrace (printk("Look up %x", hash));
        while (1)
        {
                count = dx_get_count(entries);
-               assert (count && count <= dx_get_limit(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;
+               }
+
                p = entries + 1;
                q = entries + count - 1;
                while (p <= q)
@@ -423,8 +439,15 @@ 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;
-               assert (dx_get_limit(entries) == dx_node_limit (dir));
+               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;
+               }
                frame++;
+               frame->bh = NULL;
        }
 fail2:
        while (frame >= frame_in) {
@@ -432,6 +455,10 @@ fail2:
                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;
 }
 
@@ -671,6 +698,10 @@ errout:
  * 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)
 {
@@ -684,7 +715,8 @@ 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 = (u32) ((char *) de - base);
+                       map_tail->offs = (u16) ((char *) de - base);
+                       map_tail->size = le16_to_cpu(de->rec_len);
                        count++;
                        cond_resched();
                }
@@ -694,6 +726,7 @@ 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;
@@ -1089,6 +1122,10 @@ 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)
 {
@@ -1107,6 +1144,10 @@ 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;
@@ -1129,6 +1170,11 @@ 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)
@@ -1140,7 +1186,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;
+       unsigned split, move, size, i;
        struct ext4_dir_entry_2 *de = NULL, *de2;
        int     err = 0;
 
@@ -1168,8 +1214,19 @@ 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",
index 8ed593766f160260c972df87d93fc1ecb8634305..b878528b64c1a9d0aed22fd19b20339bc1644b22 100644 (file)
@@ -345,8 +345,8 @@ void __exit unregister_nfs_fs(void)
        unregister_shrinker(&acl_shrinker);
 #ifdef CONFIG_NFS_V4
        unregister_filesystem(&nfs4_fs_type);
-       nfs_unregister_sysctl();
 #endif
+       nfs_unregister_sysctl();
        unregister_filesystem(&nfs_fs_type);
 }
 
index 50cd8a209012ed0cd216c651483416c71baa0d28..f37f25c931f59f7e8b6b5c27ab502529f8621834 100644 (file)
@@ -930,18 +930,11 @@ static void ocfs2_write_failure(struct inode *inode,
                                loff_t user_pos, unsigned user_len)
 {
        int i;
-       unsigned from, to;
+       unsigned from = user_pos & (PAGE_CACHE_SIZE - 1),
+               to = user_pos + user_len;
        struct page *tmppage;
 
-       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;
-       }
+       ocfs2_zero_new_buffers(wc->w_target_page, from, to);
 
        for(i = 0; i < wc->w_num_pages; i++) {
                tmppage = wc->w_pages[i];
@@ -991,9 +984,6 @@ 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
@@ -1211,18 +1201,33 @@ 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, len);
+                                         wc, desc->c_cpos, pos, local_len);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
                }
+
+               len -= local_len;
+               pos += local_len;
        }
 
        ret = 0;
index 7e34e66159c690cb13beb43abaebe58b8f285333..f3bc3658e7a5ef69ee677c2822b541c557da84b7 100644 (file)
@@ -491,8 +491,8 @@ int ocfs2_do_extend_allocation(struct ocfs2_super *osb,
                goto leave;
        }
 
-       status = ocfs2_claim_clusters(osb, handle, data_ac, 1,
-                                     &bit_off, &num_bits);
+       status = __ocfs2_claim_clusters(osb, handle, data_ac, 1,
+                                       clusters_to_add, &bit_off, &num_bits);
        if (status < 0) {
                if (status != -ENOSPC)
                        mlog_errno(status);
index 545f7892cdf39b645888e12fa8614598dbb86bfb..de984d2725760ee1d523b8fe588831c09891ec2f 100644 (file)
@@ -524,13 +524,12 @@ bail:
 int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
                                 handle_t *handle,
                                 struct ocfs2_alloc_context *ac,
-                                u32 min_bits,
+                                u32 bits_wanted,
                                 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;
@@ -538,7 +537,6 @@ 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);
index 385a10152f9c8a7fd72cad76ec2a0bc6a90eff09..3f76631e110c5a6284963cfe186b2c9a0917dabd 100644 (file)
@@ -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 min_bits,
+                                u32 bits_wanted,
                                 u32 *bit_off,
                                 u32 *num_bits);
 
index d9c5c9fcb30fc300bb9132f54f0526156f5847b8..8f09f5235e3a68651ca279ab34598f2f22270cc8 100644 (file)
@@ -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 *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 max_clusters,
+                          u32 *cluster_start,
+                          u32 *num_clusters)
 {
        int status;
-       unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
+       unsigned int bits_wanted = max_clusters;
        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,6 +1557,19 @@ bail:
        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,
index f212dc01a84bd83088f5f7a70460a44efddc1b4a..cafe93703095f187a5fadf825a6415c9d1837bad 100644 (file)
@@ -85,6 +85,17 @@ 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,
index 66a13ee63d4c7cd2ee496214cd7ea6a2c6b31b65..c05358538f2bfa96ddab90b7ddd1c01d1faa3efb 100644 (file)
@@ -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;
index a8e293d3003432ff493eff7069f32305fa35006a..aefb0be07942d735de747ad8697834368f8a907a 100644 (file)
  *      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 <davi@haxent.com.br>
+ *  Sat May 19, 2007: Davi E. M. Arnaut <davi@haxent.com.br>
  *      Retrieve multiple signals with one read() call
+ *  Sun Jul 15, 2007: Davide Libenzi <davidel@xmailserver.org>
+ *      Attach to the sighand only during read() and poll().
  */
 
 #include <linux/file.h>
 #include <linux/signalfd.h>
 
 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)
 {
-       signalfd_cleanup(file->private_data);
+       kfree(file->private_data);
        return 0;
 }
 
@@ -130,23 +42,15 @@ 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, &ctx->wqh, wait);
+       poll_wait(file, &current->sighand->signalfd_wqh, wait);
 
-       /*
-        * 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
+       spin_lock_irq(&current->sighand->siglock);
+       if (next_signal(&current->pending, &ctx->sigmask) ||
+           next_signal(&current->signal->shared_pending,
+                       &ctx->sigmask))
                events |= POLLIN;
+       spin_unlock_irq(&current->sighand->siglock);
 
        return events;
 }
@@ -219,59 +123,46 @@ 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);
 
-       if (!signalfd_lock(ctx, &lk))
-               return 0;
-
-       ret = dequeue_signal(lk.tsk, &ctx->sigmask, info);
+       spin_lock_irq(&current->sighand->siglock);
+       ret = dequeue_signal(current, &ctx->sigmask, info);
        switch (ret) {
        case 0:
                if (!nonblock)
                        break;
                ret = -EAGAIN;
        default:
-               signalfd_unlock(&lk);
+               spin_unlock_irq(&current->sighand->siglock);
                return ret;
        }
 
-       add_wait_queue(&ctx->wqh, &wait);
+       add_wait_queue(&current->sighand->signalfd_wqh, &wait);
        for (;;) {
                set_current_state(TASK_INTERRUPTIBLE);
-               ret = dequeue_signal(lk.tsk, &ctx->sigmask, info);
-               signalfd_unlock(&lk);
+               ret = dequeue_signal(current, &ctx->sigmask, info);
                if (ret != 0)
                        break;
                if (signal_pending(current)) {
                        ret = -ERESTARTSYS;
                        break;
                }
+               spin_unlock_irq(&current->sighand->siglock);
                schedule();
-               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_lock_irq(&current->sighand->siglock);
        }
+       spin_unlock_irq(&current->sighand->siglock);
 
-       remove_wait_queue(&ctx->wqh, &wait);
+       remove_wait_queue(&current->sighand->signalfd_wqh, &wait);
        __set_current_state(TASK_RUNNING);
 
        return ret;
 }
 
 /*
- * 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".
+ * 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".
  */
 static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count,
                             loff_t *ppos)
@@ -287,7 +178,6 @@ 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))
@@ -300,7 +190,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 = {
@@ -309,20 +199,13 @@ 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)))
@@ -335,17 +218,7 @@ 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
@@ -364,23 +237,18 @@ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemas
                        fput(file);
                        return -EINVAL;
                }
-               /*
-                * 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);
+               spin_lock_irq(&current->sighand->siglock);
+               ctx->sigmask = sigmask;
+               spin_unlock_irq(&current->sighand->siglock);
+
+               wake_up(&current->sighand->signalfd_wqh);
                fput(file);
        }
 
        return ufd;
 
 err_fdalloc:
-       signalfd_cleanup(ctx);
+       kfree(ctx);
        return error;
 }
 
index d9c40fe641953a20b9b5fc8059f65b481382f9b7..5f152f60d74d83ce8878fcba2ee16780ee767513 100644 (file)
@@ -181,6 +181,7 @@ 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);
index 4528f9a3f304d5e923fa09458bd6aacfd04161c2..491d1f4f202d8d5919ade355c0a212825e8c8a54 100644 (file)
@@ -415,8 +415,10 @@ xfs_fs_write_inode(
 
        if (vp) {
                vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
-               if (sync)
+               if (sync) {
+                       filemap_fdatawait(inode->i_mapping);
                        flags |= FLUSH_SYNC;
+               }
                error = bhv_vop_iflush(vp, flags);
                if (error == EAGAIN)
                        error = sync? bhv_vop_iflush(vp, flags | FLUSH_LOG) : 0;
index d7e13614306635bfae1f31bfbd1728e0ff3c1e36..fa25b7dcc6c3515b3e4c7c5f217b91cbca77e4ae 100644 (file)
@@ -52,6 +52,11 @@ 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
index ce2278611bb74232269f2adad55a7e619141988f..16f8e175167d1d8ed95738a4a082b4c192d26fca 100644 (file)
@@ -467,8 +467,7 @@ void
 xfs_filestream_flush(
        xfs_mount_t     *mp)
 {
-       /* point in time flush, so keep the reaper running */
-       xfs_mru_cache_flush(mp->m_filestream, 1);
+       xfs_mru_cache_flush(mp->m_filestream);
 }
 
 /*
index 8ae6e8e5f3db70e1a5c0ee276361f0907fe3f793..dacb19739cc2830ae561a811321362e0fbf2bd6d 100644 (file)
@@ -1874,6 +1874,7 @@ 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)
@@ -1884,6 +1885,50 @@ xlog_recover_do_reg_buffer(
        unsigned int            *data_map = NULL;
        unsigned int            map_size = 0;
        int                     error;
+       int                     stale_buf = 1;
+
+       /*
+        * Scan through the on-disk inode buffer and attempt to
+        * determine if it has been written to since it was logged.
+        *
+        * - If any of the magic numbers are incorrect then the buffer is stale
+        * - If any of the modes are non-zero then the buffer is not stale
+        * - If all of the modes are zero and at least one of the generation
+        *   counts is non-zero then the buffer is stale
+        *
+        * If the end result is a stale buffer then the log buffer is replayed
+        * otherwise it is skipped.
+        *
+        * This heuristic is not perfect.  It can be improved by scanning the
+        * entire inode chunk for evidence that any of the inode clusters have
+        * been updated.  To fix this problem completely we will need a major
+        * architectural change to the logging system.
+        */
+       if (buf_f->blf_flags & XFS_BLI_INODE_NEW_BUF) {
+               xfs_dinode_t    *dip;
+               int             inodes_per_buf;
+               int             mode_count = 0;
+               int             gen_count = 0;
+
+               stale_buf = 0;
+               inodes_per_buf = XFS_BUF_COUNT(bp) >> mp->m_sb.sb_inodelog;
+               for (i = 0; i < inodes_per_buf; i++) {
+                       dip = (xfs_dinode_t *)xfs_buf_offset(bp,
+                               i * mp->m_sb.sb_inodesize);
+                       if (be16_to_cpu(dip->di_core.di_magic) !=
+                                       XFS_DINODE_MAGIC) {
+                               stale_buf = 1;
+                               break;
+                       }
+                       if (be16_to_cpu(dip->di_core.di_mode))
+                               mode_count++;
+                       if (be16_to_cpu(dip->di_core.di_gen))
+                               gen_count++;
+               }
+
+               if (!mode_count && gen_count)
+                       stale_buf = 1;
+       }
 
        switch (buf_f->blf_type) {
        case XFS_LI_BUF:
@@ -1917,7 +1962,7 @@ xlog_recover_do_reg_buffer(
                                               -1, 0, XFS_QMOPT_DOWARN,
                                               "dquot_buf_recover");
                }
-               if (!error)
+               if (!error && stale_buf)
                        memcpy(xfs_buf_offset(bp,
                                (uint)bit << XFS_BLI_SHIFT),    /* dest */
                                item->ri_buf[i].i_addr,         /* source */
@@ -2089,7 +2134,7 @@ xlog_recover_do_dquot_buffer(
        if (log->l_quotaoffs_flag & type)
                return;
 
-       xlog_recover_do_reg_buffer(item, bp, buf_f);
+       xlog_recover_do_reg_buffer(mp, item, bp, buf_f);
 }
 
 /*
@@ -2190,7 +2235,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(item, bp, buf_f);
+               xlog_recover_do_reg_buffer(mp, item, bp, buf_f);
        }
        if (error)
                return XFS_ERROR(error);
index 7deb9e3cbbd3dcb2669186605f8cb9fc91d084e3..e0b358c1c533cc66220d47140dbd5df4b0341a96 100644 (file)
@@ -206,8 +206,11 @@ _xfs_mru_cache_list_insert(
         */
        if (!_xfs_mru_cache_migrate(mru, now)) {
                mru->time_zero = now;
-               if (!mru->next_reap)
-                       mru->next_reap = mru->grp_count * mru->grp_time;
+               if (!mru->queued) {
+                       mru->queued = 1;
+                       queue_delayed_work(xfs_mru_reap_wq, &mru->work,
+                                          mru->grp_count * mru->grp_time);
+               }
        } else {
                grp = (now - mru->time_zero) / mru->grp_time;
                grp = (mru->lru_grp + grp) % mru->grp_count;
@@ -271,29 +274,26 @@ _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;
+       unsigned long           now, next;
 
        ASSERT(mru && mru->lists);
        if (!mru || !mru->lists)
                return;
 
        mutex_spinlock(&mru->lock);
-       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);
+       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);
        }
 
-       /*
-        * 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_alloc(mru->grp_count * sizeof(*mru->lists), KM_SLEEP);
+       mru->lists = kmem_zalloc(mru->grp_count * sizeof(*mru->lists), KM_SLEEP);
 
        if (!mru->lists) {
                err = ENOMEM;
@@ -374,11 +374,6 @@ 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:
@@ -394,35 +389,25 @@ exit:
  * 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.
- *
- * 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.
+ * executing and the reaper is not running.
  */
 void
 xfs_mru_cache_flush(
-       xfs_mru_cache_t         *mru,
-       int                     restart)
+       xfs_mru_cache_t         *mru)
 {
        if (!mru || !mru->lists)
                return;
 
-       cancel_rearming_delayed_workqueue(xfs_mru_reap_wq, &mru->work);
-
        mutex_spinlock(&mru->lock);
-       mru->reap_all = 1;
-       mutex_spinunlock(&mru->lock, 0);
+       if (mru->queued) {
+               mutex_spinunlock(&mru->lock, 0);
+               cancel_rearming_delayed_workqueue(xfs_mru_reap_wq, &mru->work);
+               mutex_spinlock(&mru->lock);
+       }
 
-       queue_work(xfs_mru_reap_wq, &mru->work.work);
-       flush_workqueue(xfs_mru_reap_wq);
+       _xfs_mru_cache_migrate(mru, jiffies + mru->grp_count * mru->grp_time);
+       _xfs_mru_cache_clear_reap_list(mru);
 
-       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);
 }
 
@@ -433,8 +418,7 @@ xfs_mru_cache_destroy(
        if (!mru || !mru->lists)
                return;
 
-       /* we don't want the reaper to restart here */
-       xfs_mru_cache_flush(mru, 0);
+       xfs_mru_cache_flush(mru);
 
        kmem_free(mru->lists, mru->grp_count * sizeof(*mru->lists));
        kmem_free(mru, sizeof(*mru));
index 624fd10ee8e5ed21be6be354bb999e147989b915..dd58ea1bbebefeb0a49116c1f52be41e4dc60e44 100644 (file)
@@ -32,11 +32,9 @@ 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);
@@ -44,7 +42,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, int restart);
+void xfs_mru_cache_flush(xfs_mru_cache_t *mru);
 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);
index 60b6b898022bcb1be98f96f2a21615e1bff5e131..95fff6872a2fcd32c17cdff342bebe062ded95e7 100644 (file)
@@ -966,6 +966,7 @@ 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;
 }
 
 
index 1a5ad8cd97b00d3d8cd24c04961ea075cb5e1635..603459229904e0b6701b4a883b262041967e9a0a 100644 (file)
@@ -1082,6 +1082,9 @@ 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
@@ -3769,12 +3772,16 @@ 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))
-                               return 0;
+                       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 (flags & FLUSH_SYNC)
-                               log_flags |= XFS_LOG_SYNC;
-                       return xfs_log_force(mp, iip->ili_last_lsn, log_flags);
+                       if (ip->i_update_core == 0)
+                               return 0;
                }
        }
 
@@ -3788,9 +3795,6 @@ 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);
index 169ae26105e9d8d5f71b41606f5399d9243db170..aa6b876bbd78d153042af014979eea2af04b768a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004  Maciej W. Rozycki
+ * Copyright (C) 2004, 2007  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,8 +9,10 @@
 #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
 
index d7f5ddfbaac77f5f69c32643a6ef1691bb6e7820..c104c15c6625b5d35a06ae22f0a4a96cc20a2131 100644 (file)
@@ -149,6 +149,11 @@ 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);
index b467be6d367f8b3725c1b7449e9d052ea1c3e768..8bb5646878602f3731e345b46a80486f593e1640 100644 (file)
@@ -4,10 +4,6 @@
 #include <asm/pda.h>
 #include <linux/threads.h>
 #include <linux/mm.h>
-#include <linux/quicklist.h>
-
-#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)))
@@ -24,23 +20,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));
-       quicklist_free(QUICK_PT, NULL, pmd);
+       free_page((unsigned long)pmd);
 }
 
 static inline pmd_t *pmd_alloc_one (struct mm_struct *mm, unsigned long addr)
 {
-       return (pmd_t *)quicklist_alloc(QUICK_PT, GFP_KERNEL|__GFP_REPEAT, NULL);
+       return (pmd_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
 }
 
 static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
-       return (pud_t *)quicklist_alloc(QUICK_PT, GFP_KERNEL|__GFP_REPEAT, NULL);
+       return (pud_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
 }
 
 static inline void pud_free (pud_t *pud)
 {
        BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
-       quicklist_free(QUICK_PT, NULL, pud);
+       free_page((unsigned long)pud);
 }
 
 static inline void pgd_list_add(pgd_t *pgd)
@@ -61,57 +57,41 @@ static inline void pgd_list_del(pgd_t *pgd)
        spin_unlock(&pgd_lock);
 }
 
-static inline void pgd_ctor(void *x)
+static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 {
        unsigned boundary;
-       pgd_t *pgd = x;
-       struct page *page = virt_to_page(pgd);
-
+       pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
+       if (!pgd)
+               return NULL;
+       pgd_list_add(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));
-
-       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);
+              init_level4_pgt + boundary,
+              (PTRS_PER_PGD - boundary) * sizeof(pgd_t));
        return pgd;
 }
 
 static inline void pgd_free(pgd_t *pgd)
 {
        BUG_ON((unsigned long)pgd & (PAGE_SIZE-1));
-       quicklist_free(QUICK_PGD, pgd_dtor, pgd);
+       pgd_list_del(pgd);
+       free_page((unsigned long)pgd);
 }
 
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
 {
-       return (pte_t *)quicklist_alloc(QUICK_PT, GFP_KERNEL|__GFP_REPEAT, NULL);
+       return (pte_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
 }
 
 static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
 {
-       void *p = (void *)quicklist_alloc(QUICK_PT, GFP_KERNEL|__GFP_REPEAT, NULL);
-
+       void *p = (void *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
        if (!p)
                return NULL;
        return virt_to_page(p);
@@ -123,22 +103,17 @@ 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));
-       quicklist_free(QUICK_PT, NULL, pte);
+       free_page((unsigned long)pte); 
 }
 
 static inline void pte_free(struct page *pte)
 {
-       quicklist_free_page(QUICK_PT, NULL, pte);
-}
+       __free_page(pte);
+} 
 
-#define __pte_free_tlb(tlb,pte) quicklist_free_page(QUICK_PT, NULL,(pte))
+#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte))
 
-#define __pmd_free_tlb(tlb,x)   quicklist_free(QUICK_PT, NULL, (x))
-#define __pud_free_tlb(tlb,x)   quicklist_free(QUICK_PT, NULL, (x))
+#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))
 
-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 */
index c9d8764c89d182920dc1b50b4938f63521292c70..57dd6b3107ead9395f546ccd2ed5e7e1123ad1e8 100644 (file)
@@ -411,6 +411,7 @@ 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
index cab741c2d6033ad937b761852def3fbbf60b763b..f8abfa349ef924344a11b1fd9739e68bd4d72b24 100644 (file)
@@ -86,7 +86,7 @@ extern struct nsproxy init_nsproxy;
        .count          = ATOMIC_INIT(1),                               \
        .action         = { { { .sa_handler = NULL, } }, },             \
        .siglock        = __SPIN_LOCK_UNLOCKED(sighand.siglock),        \
-       .signalfd_list  = LIST_HEAD_INIT(sighand.signalfd_list),        \
+       .signalfd_wqh   = __WAIT_QUEUE_HEAD_INITIALIZER(sighand.signalfd_wqh),  \
 }
 
 extern struct group_info init_groups;
index 5bdd656e88cf598a9e41758dc54bf35a644a2e69..a020eb2d4e2a3984fe8807cb833947c42367a232 100644 (file)
@@ -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);
+               unsigned long addr, gfp_t gfp_flags, struct mempolicy **mpol);
 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)
+               unsigned long addr, gfp_t gfp_flags, struct mempolicy **mpol)
 {
        return NODE_DATA(0)->node_zonelists + gfp_zone(gfp_flags);
 }
index f4e324ed2e4478e5282ba3b4c0f33339fc581dd8..a01ac6dd5f5e1c07d9a54a8f879512db2eac3905 100644 (file)
@@ -438,7 +438,7 @@ struct sighand_struct {
        atomic_t                count;
        struct k_sigaction      action[_NSIG];
        spinlock_t              siglock;
-       struct list_head        signalfd_list;
+       wait_queue_head_t       signalfd_wqh;
 };
 
 struct pacct_struct {
@@ -593,7 +593,7 @@ struct user_struct {
 #endif
 
        /* Hash table maintenance information */
-       struct list_head uidhash_list;
+       struct hlist_node uidhash_node;
        uid_t uid;
 };
 
@@ -1406,6 +1406,7 @@ 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;
 
@@ -1472,6 +1473,7 @@ 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 <asm/current.h>
 
index 5104294956906c038e4359ab4e37c35632e2e478..4c9ff0910ae01d39f691a23c9acf5d1db48b06d2 100644 (file)
@@ -45,49 +45,17 @@ struct signalfd_siginfo {
 #ifdef CONFIG_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.
+ * Deliver the signal to listening signalfd.
  */
 static inline void signalfd_notify(struct task_struct *tsk, int sig)
 {
-       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);
-       }
+       if (unlikely(waitqueue_active(&tsk->sighand->signalfd_wqh)))
+               wake_up(&tsk->sighand->signalfd_wqh);
 }
 
 #else /* CONFIG_SIGNALFD */
 
-#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)
+static inline void signalfd_notify(struct task_struct *tsk, int sig) { }
 
 #endif /* CONFIG_SIGNALFD */
 
index 1101b0ce878f67973d5037f7b651cabf1fb8d28e..b5f41d4c2eec71a3d3c786128f0f980f0b41317d 100644 (file)
@@ -11,7 +11,7 @@
 
 struct user_namespace {
        struct kref             kref;
-       struct list_head        uidhash_table[UIDHASH_SZ];
+       struct hlist_head       uidhash_table[UIDHASH_SZ];
        struct user_struct      *root_user;
 };
 
index 96b54595f1dc16e1809852ca0462184b948b54b4..d54d0cadcc064c284c10cce88beaf9c55ccf0cdd 100644 (file)
@@ -488,6 +488,7 @@ 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
index a6b4c0c08e13ea4bc1db5ade1cf8eb73d18c7d72..fd4fc12d262464b0b763e2e0fb5dd1781f2a3b70 100644 (file)
@@ -57,8 +57,10 @@ static void __init handle_initrd(void)
 
        pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
        if (pid > 0)
-               while (pid != sys_wait4(-1, NULL, 0, NULL))
+               while (pid != sys_wait4(-1, NULL, 0, NULL)) {
+                       try_to_freeze();
                        yield();
+               }
 
        /* move initrd to rootfs' /old */
        sys_fchdir(old_fd);
index 06b24b3aa370c69577012023b12573d4c7624d19..993369ee94d1ebb8d4c7675a821e90abf8a1737e 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/pid_namespace.h>
 #include <linux/ptrace.h>
 #include <linux/profile.h>
-#include <linux/signalfd.h>
 #include <linux/mount.h>
 #include <linux/proc_fs.h>
 #include <linux/kthread.h>
@@ -86,14 +85,6 @@ 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);
index 7332e236d3676153dc9f40c1a78848e6e2810632..33f12f48684a0053a82d72506c1d7ec1e7ca6a15 100644 (file)
@@ -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_LIST_HEAD(&sighand->signalfd_list);
+       init_waitqueue_head(&sighand->signalfd_wqh);
 }
 
 void __init proc_caches_init(void)
index deeb1f8e0c309b4214d9854f2d67699d54f17caa..6107a0cd6325f9afe219007e1e1e446fda899b78 100644 (file)
@@ -1682,6 +1682,11 @@ 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) {
@@ -4550,10 +4555,7 @@ asmlinkage long sys_sched_yield(void)
        struct rq *rq = this_rq_lock();
 
        schedstat_inc(rq, yld_cnt);
-       if (unlikely(rq->nr_running == 1))
-               schedstat_inc(rq, yld_act_empty);
-       else
-               current->sched_class->yield_task(rq, current);
+       current->sched_class->yield_task(rq, current);
 
        /*
         * Since we are going to call schedule() anyway, there's
index 892616bf2c77ab212d28823c6fe1bc76b1cb7825..c9fbe8e73a45c66f36bb2ddf8bf5eaf24d93c141 100644 (file)
@@ -42,6 +42,14 @@ 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)
@@ -897,19 +905,62 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int sleep)
 }
 
 /*
- * sched_yield() support is very simple - we dequeue and enqueue
+ * 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.
  */
 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;
 
-       __update_rq_clock(rq);
        /*
-        * Dequeue and enqueue the task to update its
-        * position within the tree:
+        * 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:
         */
-       dequeue_entity(cfs_rq, &p->se, 0);
-       enqueue_entity(cfs_rq, &p->se, 0);
+       do {
+               parent = *link;
+               link = &parent->rb_right;
+       } while (*link);
+
+       rightmost = rb_entry(parent, struct sched_entity, run_node);
+       /*
+        * 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:
+        */
+       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);
 }
 
 /*
index 3169bed0b4d0e44166b37c48ed663d516a9ccba5..9fb91a32eddaddfd47d09cb0aa66586a5635a39e 100644 (file)
@@ -378,8 +378,7 @@ 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
         */
-       if (likely(tsk == current))
-               signr = __dequeue_signal(&tsk->pending, mask, info);
+       signr = __dequeue_signal(&tsk->pending, mask, info);
        if (!signr) {
                signr = __dequeue_signal(&tsk->signal->shared_pending,
                                         mask, info);
@@ -407,8 +406,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
                        }
                }
        }
-       if (likely(tsk == current))
-               recalc_sigpending();
+       recalc_sigpending();
        if (signr && unlikely(sig_kernel_stop(signr))) {
                /*
                 * Set a marker that we have dequeued a stop signal.  Our
@@ -425,7 +423,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 && likely(tsk == current) &&
+       if (signr &&
             ((info->si_code & __SI_MASK) == __SI_TIMER) &&
             info->si_sys_private){
                /*
index 6ace893c17c94dc737bda11fb63ee2811d34de79..53a456ebf6d50dd3e4705ccc84e5b0a1c44f6c90 100644 (file)
@@ -303,6 +303,14 @@ 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,
index e7d11cef6998fdb378506d72232c4041738dce2f..9ca2848fc35676fa8ebac52f20c33f7f056d09ff 100644 (file)
@@ -55,25 +55,22 @@ 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 list_head *hashent)
+static inline void uid_hash_insert(struct user_struct *up, struct hlist_head *hashent)
 {
-       list_add(&up->uidhash_list, hashent);
+       hlist_add_head(&up->uidhash_node, hashent);
 }
 
 static inline void uid_hash_remove(struct user_struct *up)
 {
-       list_del(&up->uidhash_list);
+       hlist_del_init(&up->uidhash_node);
 }
 
-static inline struct user_struct *uid_hash_find(uid_t uid, struct list_head *hashent)
+static inline struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent)
 {
-       struct list_head *up;
-
-       list_for_each(up, hashent) {
-               struct user_struct *user;
-
-               user = list_entry(up, struct user_struct, uidhash_list);
+       struct user_struct *user;
+       struct hlist_node *h;
 
+       hlist_for_each_entry(user, h, hashent, uidhash_node) {
                if(user->uid == uid) {
                        atomic_inc(&user->__count);
                        return user;
@@ -122,7 +119,7 @@ void free_uid(struct user_struct *up)
 
 struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid)
 {
-       struct list_head *hashent = uidhashentry(ns, uid);
+       struct hlist_head *hashent = uidhashentry(ns, uid);
        struct user_struct *up;
 
        spin_lock_irq(&uidhash_lock);
@@ -202,6 +199,30 @@ 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)
 {
@@ -211,7 +232,7 @@ static int __init uid_cache_init(void)
                        0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
 
        for(n = 0; n < UIDHASH_SZ; ++n)
-               INIT_LIST_HEAD(init_user_ns.uidhash_table + n);
+               INIT_HLIST_HEAD(init_user_ns.uidhash_table + n);
 
        /* Insert the root user immediately (init already runs as root) */
        spin_lock_irq(&uidhash_lock);
index 85af9422ea6e0163afd849f59237752825a62406..7af90fc4f0fd3d870c1f5dbb3b0771fc16bbc5a4 100644 (file)
@@ -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_LIST_HEAD(ns->uidhash_table + n);
+               INIT_HLIST_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);
-       free_uid(ns->root_user);
+       release_uids(ns);
        kfree(ns);
 }
 
index 9d8180a0f0d815dbe051dbb6a710385d22f0b342..816d7b24fa031af51b08d9108366d21626e3d38e 100644 (file)
@@ -28,7 +28,9 @@ 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;
 }
index de4cf458d6e1979432aad46613d0816146347fc1..84c795ee2d650f807223c3f17a072c3f2eb52c72 100644 (file)
@@ -71,8 +71,9 @@ 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);
+                                       htlb_alloc_mask, &mpol);
        struct zone **z;
 
        for (z = zonelist->zones; *z; z++) {
@@ -87,6 +88,7 @@ static struct page *dequeue_huge_page(struct vm_area_struct *vma,
                        break;
                }
        }
+       mpol_free(mpol);        /* unref if mpol !NULL */
        return page;
 }
 
index bb54b88c3d5aaab2752569f046129bea8082f4ec..3d6ac9505d0716e83c1eeee3a58ede5c5baa0a1b 100644 (file)
@@ -1077,21 +1077,37 @@ asmlinkage long compat_sys_mbind(compat_ulong_t start, compat_ulong_t len,
 
 #endif
 
-/* Return effective policy for a VMA */
+/*
+ * 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.
+ */
 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);
-               else if (vma->vm_policy &&
+                       shared_pol = 1; /* if pol non-NULL, add ref below */
+               } 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;
 }
 
@@ -1207,19 +1223,45 @@ static inline unsigned interleave_nid(struct mempolicy *pol,
 }
 
 #ifdef CONFIG_HUGETLBFS
-/* Return a zonelist suitable for a huge page allocation. */
+/*
+ * 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.
+ */
 struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr,
-                                                       gfp_t gfp_flags)
+                               gfp_t gfp_flags, struct mempolicy **mpol)
 {
        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);
        }
-       return zonelist_policy(GFP_HIGHUSER, pol);
+
+       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;
 }
 #endif
 
@@ -1264,6 +1306,7 @@ 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();
 
@@ -1273,7 +1316,19 @@ 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);
        }
-       return __alloc_pages(gfp, 0, zonelist_policy(gfp, pol));
+       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);
 }
 
 /**
@@ -1872,6 +1927,7 @@ 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];
 
@@ -1882,8 +1938,13 @@ int show_numa_map(struct seq_file *m, void *v)
        if (!md)
                return 0;
 
-       mpol_to_str(buffer, sizeof(buffer),
-                           get_vma_policy(priv->task, vma, vma->vm_start));
+       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);
 
        seq_printf(m, "%08lx %s", vma->vm_start, buffer);
 
index e185a5b55913ce8b37af7de85b5e9a9f8b46f2e1..2351533a850755bebd1c9ca6b26c9462fd296cf8 100644 (file)
@@ -58,7 +58,6 @@ 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 */
 
@@ -345,10 +344,12 @@ static struct sk_buff *nfulnl_alloc_skb(unsigned int inst_size,
 static int
 __nfulnl_send(struct nfulnl_instance *inst)
 {
-       int status;
+       int status = -1;
 
        if (inst->qlen > 1)
-               inst->lastnlh->nlmsg_type = NLMSG_DONE;
+               NLMSG_PUT(inst->skb, 0, 0,
+                         NLMSG_DONE,
+                         sizeof(struct nfgenmsg));
 
        status = nfnetlink_unicast(inst->skb, inst->peer_pid, MSG_DONTWAIT);
        if (status < 0) {
@@ -358,8 +359,8 @@ __nfulnl_send(struct nfulnl_instance *inst)
 
        inst->qlen = 0;
        inst->skb = NULL;
-       inst->lastnlh = NULL;
 
+nlmsg_failure:
        return status;
 }
 
@@ -538,7 +539,6 @@ __build_packet_message(struct nfulnl_instance *inst,
        }
 
        nlh->nlmsg_len = inst->skb->tail - old_tail;
-       inst->lastnlh = nlh;
        return 0;
 
 nlmsg_failure:
@@ -644,7 +644,8 @@ nfulnl_log_packet(unsigned int pf,
        }
 
        if (inst->qlen >= qthreshold ||
-           (inst->skb && size > skb_tailroom(inst->skb))) {
+           (inst->skb && size >
+            skb_tailroom(inst->skb) - sizeof(struct nfgenmsg))) {
                /* 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");
index 9579573098598df19066e0910e181e68a94ef080..3a23e30bc79e3689dc1f16fc9c16d0d76f820865 100644 (file)
@@ -270,7 +270,7 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc* sch)
                        q->tail = x;
                }
        }
-       if (++sch->q.qlen < q->limit-1) {
+       if (++sch->q.qlen <= q->limit) {
                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 - 1) {
+       if (++sch->q.qlen <= q->limit) {
                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);
+               q->limit = min_t(u32, ctl->limit, SFQ_DEPTH - 2);
 
        qlen = sch->q.qlen;
-       while (sch->q.qlen >= q->limit-1)
+       while (sch->q.qlen > q->limit)
                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;
+       q->limit = SFQ_DEPTH - 2;
        q->max_depth = 0;
        q->tail = SFQ_DEPTH;
        if (opt == NULL) {
index 1a899924023faefc4e6a65b2ab80f4918306e05a..036ab520df21ec5ecea04342e979fc58762aa059 100644 (file)
@@ -1110,7 +1110,8 @@ svc_tcp_accept(struct svc_sock *svsk)
                                                   serv->sv_name);
                                printk(KERN_NOTICE
                                       "%s: last TCP connect from %s\n",
-                                      serv->sv_name, buf);
+                                      serv->sv_name, __svc_print_addr(sin,
+                                                       buf, sizeof(buf)));
                        }
                        /*
                         * Always select the oldest socket. It's not fair,
index 36946629b6cafa391baa7168e55a8aab2bef3b78..0753b20e23fed48c80f4864b67fbe476de8daced 100644 (file)
@@ -316,6 +316,7 @@ static inline int inode_doinit(struct inode *inode)
 }
 
 enum {
+       Opt_error = -1,
        Opt_context = 1,
        Opt_fscontext = 2,
        Opt_defcontext = 4,
@@ -327,6 +328,7 @@ 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"