Merge branch 'release' of master.kernel.org:/home/ftp/pub/scm/linux/kernel/git/aegl/linux-2.6

* 'release' of master.kernel.org:/home/ftp/pub/scm/linux/kernel/git/aegl/linux-2.6:
  [IA64] Move sg_dma_{len,address} from pci.h to scatterlist.h
diff --git a/Documentation/cachetlb.txt b/Documentation/cachetlb.txt
index 53245c4..73e794f 100644
--- a/Documentation/cachetlb.txt
+++ b/Documentation/cachetlb.txt
@@ -179,10 +179,21 @@
 	lines associated with 'mm'.
 
 	This interface is used to handle whole address space
-	page table operations such as what happens during
-	fork, exit, and exec.
+	page table operations such as what happens during exit and exec.
 
-2) void flush_cache_range(struct vm_area_struct *vma,
+2) void flush_cache_dup_mm(struct mm_struct *mm)
+
+	This interface flushes an entire user address space from
+	the caches.  That is, after running, there will be no cache
+	lines associated with 'mm'.
+
+	This interface is used to handle whole address space
+	page table operations such as what happens during fork.
+
+	This option is separate from flush_cache_mm to allow some
+	optimizations for VIPT caches.
+
+3) void flush_cache_range(struct vm_area_struct *vma,
 			  unsigned long start, unsigned long end)
 
 	Here we are flushing a specific range of (user) virtual
@@ -199,7 +210,7 @@
 	call flush_cache_page (see below) for each entry which may be
 	modified.
 
-3) void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
+4) void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
 
 	This time we need to remove a PAGE_SIZE sized range
 	from the cache.  The 'vma' is the backing structure used by
@@ -220,7 +231,7 @@
 
 	This is used primarily during fault processing.
 
-4) void flush_cache_kmaps(void)
+5) void flush_cache_kmaps(void)
 
 	This routine need only be implemented if the platform utilizes
 	highmem.  It will be called right before all of the kmaps
@@ -232,7 +243,7 @@
 
 	This routing should be implemented in asm/highmem.h
 
-5) void flush_cache_vmap(unsigned long start, unsigned long end)
+6) void flush_cache_vmap(unsigned long start, unsigned long end)
    void flush_cache_vunmap(unsigned long start, unsigned long end)
 
 	Here in these two interfaces we are flushing a specific range
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 64ce44d..040f437 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -151,15 +151,6 @@
 
 ---------------------------
 
-What:	I2C interface of the it87 driver
-When:	January 2007
-Why:	The ISA interface is faster and should be always available. The I2C
-	probing is also known to cause trouble in at least one case (see
-	bug #5889.)
-Who:	Jean Delvare <khali@linux-fr.org>
-
----------------------------
-
 What:	Unused EXPORT_SYMBOL/EXPORT_SYMBOL_GPL exports
 	(temporary transition config option provided until then)
 	The transition config option will also be removed at the same time.
diff --git a/Documentation/filesystems/bfs.txt b/Documentation/filesystems/bfs.txt
index d2841e0..ea825e1 100644
--- a/Documentation/filesystems/bfs.txt
+++ b/Documentation/filesystems/bfs.txt
@@ -54,4 +54,4 @@
 If you have any patches, questions or suggestions regarding this BFS
 implementation please contact the author:
 
-Tigran A. Aivazian <tigran@veritas.com>
+Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
diff --git a/Documentation/hwmon/f71805f b/Documentation/hwmon/f71805f
index 2ca69df..bfd0f15 100644
--- a/Documentation/hwmon/f71805f
+++ b/Documentation/hwmon/f71805f
@@ -6,6 +6,10 @@
     Prefix: 'f71805f'
     Addresses scanned: none, address read from Super I/O config space
     Datasheet: Provided by Fintek on request
+  * Fintek F71872F/FG
+    Prefix: 'f71872f'
+    Addresses scanned: none, address read from Super I/O config space
+    Datasheet: Provided by Fintek on request
 
 Author: Jean Delvare <khali@linux-fr.org>
 
@@ -13,8 +17,8 @@
 test system (custom Jetway K8M8MS motherboard, with CPU and RAM) and
 for providing initial documentation.
 
-Thanks to Kris Chen from Fintek for answering technical questions and
-providing additional documentation.
+Thanks to Kris Chen and Aaron Huang from Fintek for answering technical
+questions and providing additional documentation.
 
 Thanks to Chris Lin from Jetway for providing wiring schematics and
 answering technical questions.
@@ -28,8 +32,11 @@
 source), 3 fans and 3 temperature sensors.
 
 This chip also has fan controlling features, using either DC or PWM, in
-three different modes (one manual, two automatic). The driver doesn't
-support these features yet.
+three different modes (one manual, two automatic).
+
+The Fintek F71872F/FG Super I/O chip is almost the same, with two
+additional internal voltages monitored (VSB and battery). It also features
+6 VID inputs. The VID inputs are not yet supported by this driver.
 
 The driver assumes that no more than one chip is present, which seems
 reasonable.
@@ -42,7 +49,8 @@
 range is thus from 0 to 2.040 V. Voltage values outside of this range
 need external resistors. An exception is in0, which is used to monitor
 the chip's own power source (+3.3V), and is divided internally by a
-factor 2.
+factor 2. For the F71872F/FG, in9 (VSB) and in10 (battery) are also
+divided internally by a factor 2.
 
 The two LSB of the voltage limit registers are not used (always 0), so
 you can only set the limits in steps of 32 mV (before scaling).
@@ -61,9 +69,12 @@
 in6     VIN6    VCC1.5V      10K       -        1.00    1.50 V
 in7     VIN7    VCORE        10K       -        1.00   ~1.40 V (1)
 in8     VIN8    VSB5V       200K     47K        1.00    0.95 V
+in10    VSB     VSB3.3V     int.    int.        2.00    1.65 V (3)
+in9     VBAT    VBATTERY    int.    int.        2.00    1.50 V (3)
 
 (1) Depends on your hardware setup.
 (2) Obviously not correct, swapping R1 and R2 would make more sense.
+(3) F71872F/FG only.
 
 These values can be used as hints at best, as motherboard manufacturers
 are free to use a completely different setup. As a matter of fact, the
@@ -103,3 +114,38 @@
 or a thermistor. The driver reports the currently selected mode, but
 doesn't allow changing it. In theory, the BIOS should have configured
 everything properly.
+
+
+Fan Control
+-----------
+
+Both PWM (pulse-width modulation) and DC fan speed control methods are
+supported. The right one to use depends on external circuitry on the
+motherboard, so the driver assumes that the BIOS set the method
+properly. The driver will report the method, but won't let you change
+it.
+
+When the PWM method is used, you can select the operating frequency,
+from 187.5 kHz (default) to 31 Hz. The best frequency depends on the
+fan model. As a rule of thumb, lower frequencies seem to give better
+control, but may generate annoying high-pitch noise. Fintek recommends
+not going below 1 kHz, as the fan tachometers get confused by lower
+frequencies as well.
+
+When the DC method is used, Fintek recommends not going below 5 V, which
+corresponds to a pwm value of 106 for the driver. The driver doesn't
+enforce this limit though.
+
+Three different fan control modes are supported:
+
+* Manual mode
+  You ask for a specific PWM duty cycle or DC voltage.
+
+* Fan speed mode
+  You ask for a specific fan speed. This mode assumes that pwm1
+  corresponds to fan1, pwm2 to fan2 and pwm3 to fan3.
+
+* Temperature mode
+  You define 3 temperature/fan speed trip points, and the fan speed is
+  adjusted depending on the measured temperature, using interpolation.
+  This mode is not yet supported by the driver.
diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87
index e783fd6..74a8099 100644
--- a/Documentation/hwmon/it87
+++ b/Documentation/hwmon/it87
@@ -9,8 +9,7 @@
                http://www.ite.com.tw/
   * IT8712F
     Prefix: 'it8712'
-    Addresses scanned: I2C 0x2d
-                       from Super I/O config space (8 I/O ports)
+    Addresses scanned: from Super I/O config space (8 I/O ports)
     Datasheet: Publicly available at the ITE website
                http://www.ite.com.tw/
   * IT8716F
@@ -53,6 +52,18 @@
   misconfigured by BIOS - PWM values would be inverted. This option tries
   to fix this. Please contact your BIOS manufacturer and ask him for fix.
 
+
+Hardware Interfaces
+-------------------
+
+All the chips suported by this driver are LPC Super-I/O chips, accessed
+through the LPC bus (ISA-like I/O ports). The IT8712F additionally has an
+SMBus interface to the hardware monitoring functions. This driver no
+longer supports this interface though, as it is slower and less reliable
+than the ISA access, and was only available on a small number of
+motherboard models.
+
+
 Description
 -----------
 
diff --git a/Documentation/hwmon/k8temp b/Documentation/hwmon/k8temp
index 30d123b..0005c71 100644
--- a/Documentation/hwmon/k8temp
+++ b/Documentation/hwmon/k8temp
@@ -8,7 +8,7 @@
     Datasheet: http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/32559.pdf
 
 Author: Rudolf Marek
-Contact: Rudolf Marek <r.marek@sh.cvut.cz>
+Contact: Rudolf Marek <r.marek@assembler.cz>
 
 Description
 -----------
diff --git a/Documentation/hwmon/pc87427 b/Documentation/hwmon/pc87427
new file mode 100644
index 0000000..9a0708f
--- /dev/null
+++ b/Documentation/hwmon/pc87427
@@ -0,0 +1,38 @@
+Kernel driver pc87427
+=====================
+
+Supported chips:
+  * National Semiconductor PC87427
+    Prefix: 'pc87427'
+    Addresses scanned: none, address read from Super I/O config space
+    Datasheet: http://www.winbond.com.tw/E-WINBONDHTM/partner/apc_007.html
+
+Author: Jean Delvare <khali@linux-fr.org>
+
+Thanks to Amir Habibi at Candelis for setting up a test system, and to
+Michael Kress for testing several iterations of this driver.
+
+
+Description
+-----------
+
+The National Semiconductor Super I/O chip includes complete hardware
+monitoring capabilities. It can monitor up to 18 voltages, 8 fans and
+6 temperature sensors. Only the fans are supported at the moment.
+
+This chip also has fan controlling features, which are not yet supported
+by this driver either.
+
+The driver assumes that no more than one chip is present, which seems
+reasonable.
+
+
+Fan Monitoring
+--------------
+
+Fan rotation speeds are reported as 14-bit values from a gated clock
+signal. Speeds down to 83 RPM can be measured.
+
+An alarm is triggered if the rotation speed drops below a programmable
+limit. Another alarm is triggered if the speed is too low to to be measured
+(including stalled or missing fan).
diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface
index d1d390a..efef3b9 100644
--- a/Documentation/hwmon/sysfs-interface
+++ b/Documentation/hwmon/sysfs-interface
@@ -208,12 +208,14 @@
 ****************
 
 temp[1-*]_type	Sensor type selection.
-		Integers 1 to 4 or thermistor Beta value (typically 3435)
+		Integers 1 to 6 or thermistor Beta value (typically 3435)
 		RW
 		1: PII/Celeron Diode
 		2: 3904 transistor
 		3: thermal diode
 		4: thermistor (default/unknown Beta)
+		5: AMD AMDSI
+		6: Intel PECI
 		Not all types are supported by all chips
 
 temp[1-*]_max	Temperature max value.
diff --git a/Documentation/hwmon/w83627ehf b/Documentation/hwmon/w83627ehf
index caa610a..8a15a74 100644
--- a/Documentation/hwmon/w83627ehf
+++ b/Documentation/hwmon/w83627ehf
@@ -10,7 +10,7 @@
 Authors:
         Jean Delvare <khali@linux-fr.org>
         Yuan Mu (Winbond)
-        Rudolf Marek <r.marek@sh.cvut.cz>
+        Rudolf Marek <r.marek@assembler.cz>
 
 Description
 -----------
diff --git a/Documentation/hwmon/w83791d b/Documentation/hwmon/w83791d
index 19b2ed7..db9881d 100644
--- a/Documentation/hwmon/w83791d
+++ b/Documentation/hwmon/w83791d
@@ -18,7 +18,7 @@
     and Mark Studebaker <mdsxyz123@yahoo.com>
   w83792d.c:
     Chunhao Huang <DZShen@Winbond.com.tw>,
-    Rudolf Marek <r.marek@sh.cvut.cz>
+    Rudolf Marek <r.marek@assembler.cz>
 
 Additional contributors:
     Sven Anders <anders@anduras.de>
diff --git a/Documentation/hwmon/w83793 b/Documentation/hwmon/w83793
new file mode 100644
index 0000000..45e5408
--- /dev/null
+++ b/Documentation/hwmon/w83793
@@ -0,0 +1,110 @@
+Kernel driver w83793
+====================
+
+Supported chips:
+  * Winbond W83793G/W83793R
+    Prefix: 'w83793'
+    Addresses scanned: I2C 0x2c - 0x2f
+    Datasheet: Still not published
+
+Authors:
+    Yuan Mu (Winbond Electronics)
+    Rudolf Marek <r.marek@assembler.cz>
+
+
+Module parameters
+-----------------
+
+* reset int
+  (default 0)
+  This parameter is not recommended, it will lose motherboard specific
+  settings. Use 'reset=1' to reset the chip when loading this module.
+
+* force_subclients=bus,caddr,saddr1,saddr2
+  This is used to force the i2c addresses for subclients of
+  a certain chip. Typical usage is `force_subclients=0,0x2f,0x4a,0x4b'
+  to force the subclients of chip 0x2f on bus 0 to i2c addresses
+  0x4a and 0x4b.
+
+
+Description
+-----------
+
+This driver implements support for Winbond W83793G/W83793R chips.
+
+* Exported features
+  This driver exports 10 voltage sensors, up to 12 fan tachometer inputs,
+  6 remote temperatures, up to 8 sets of PWM fan controls, SmartFan
+  (automatic fan speed control) on all temperature/PWM combinations, 2
+  sets of 6-pin CPU VID input.
+
+* Sensor resolutions
+  If your motherboard maker used the reference design, the resolution of
+  voltage0-2 is 2mV, resolution of voltage3/4/5 is 16mV, 8mV for voltage6,
+  24mV for voltage7/8. Temp1-4 have a 0.25 degree Celsius resolution,
+  temp5-6 have a 1 degree Celsiis resolution.
+
+* Temperature sensor types
+  Temp1-4 have 3 possible types. It can be read from (and written to)
+  temp[1-4]_type.
+  - If the value of 0, the related temperature channel stops
+    monitoring.
+  - If the value is 3, it starts monitoring using a remote termal diode
+    (default).
+  - If the value is 5, it starts monitoring using the temperature sensor
+    in AMD CPU and get result by AMDSI.
+  - If the value is 6, it starts monitoring using the temperature sensor
+    in Intel CPU and get result by PECI.
+  Temp5-6 can be connected to external thermistors (value of
+  temp[5-6]_type is 4). They can also be disabled (value is 0).
+
+* Alarm mechanism
+  For voltage sensors, an alarm triggers if the measured value is below
+  the low voltage limit or over the high voltage limit.
+  For temperature sensors, an alarm triggers if the measured value goes
+  above the high temperature limit, and wears off only after the measured
+  value drops below the hysteresis value.
+  For fan sensors, an alarm triggers if the measured value is below the
+  low speed limit.
+
+* SmartFan/PWM control
+  If you want to set a pwm fan to manual mode, you just need to make sure it
+  is not controlled by any temp channel, for example, you want to set fan1
+  to manual mode, you need to check the value of temp[1-6]_fan_map, make
+  sure bit 0 is cleared in the 6 values. And then set the pwm1 value to
+  control the fan.
+
+  Each temperature channel can control all the 8 PWM outputs (by setting the
+  corresponding bit in tempX_fan_map), you can set the temperature channel
+  mode using temp[1-6]_pwm_enable, 2 is Thermal Cruise mode and 3
+  is the SmartFanII mode. Temperature channels will try to speed up or
+  slow down all controlled fans, this means one fan can receive different
+  PWM value requests from different temperature channels, but the chip
+  will always pick the safest (max) PWM value for each fan.
+
+  In Thermal Cruise mode, the chip attempts to keep the temperature at a
+  predefined value, within a tolerance margin. So if tempX_input >
+  thermal_cruiseX + toleranceX, the chip will increase the PWM value,
+  if tempX_input < thermal_cruiseX - toleranceX, the chip will decrease
+  the PWM value. If the temperature is within the tolerance range, the PWM
+  value is left unchanged.
+
+  SmartFanII works differently, you have to define up to 7 PWM, temperature
+  trip points, defining a PWM/temperature curve which the chip will follow.
+  While not fundamentally different from the Thermal Cruise mode, the
+  implementation is quite different, giving you a finer-grained control.
+
+* Chassis
+  If the case open alarm triggers, it will stay in this state unless cleared
+  by any write to the sysfs file "chassis".
+
+* VID and VRM
+  The VRM version is detected automatically, don't modify the it unless you
+  *do* know the cpu VRM version and it's not properly detected.
+
+
+Notes
+-----
+
+  Only Fan1-5 and PWM1-3 are guaranteed to always exist, other fan inputs and
+  PWM outputs may or may not exist depending on the chip pin configuration.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index d8323b8..ef69c75 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1656,6 +1656,12 @@
 	sym53c416=	[HW,SCSI]
 			See header of drivers/scsi/sym53c416.c.
 
+	sysrq_always_enabled
+			[KNL]
+			Ignore sysrq setting - this boot parameter will
+			neutralize any effect of /proc/sys/kernel/sysrq.
+			Useful for debugging.
+
 	t128=		[HW,SCSI]
 			See header of drivers/scsi/t128.c.
 
diff --git a/MAINTAINERS b/MAINTAINERS
index 8a0bfec..dea5b2a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -277,7 +277,7 @@
 
 ALI1563 I2C DRIVER
 P:	Rudolf Marek
-M:	r.marek@sh.cvut.cz
+M:	r.marek@assembler.cz
 L:	i2c@lm-sensors.org
 S:	Maintained
 
@@ -296,6 +296,13 @@
 W:	http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html
 S:	Supported
 
+AMS (Apple Motion Sensor) DRIVER
+P:	Stelian Pop
+M:	stelian@popies.net
+P:	Michael Hanselmann
+M:	linux-kernel@hansmi.ch
+S:	Supported
+
 AMSO1100 RNIC DRIVER
 P:	Tom Tucker
 M:	tom@opengridcomputing.com
@@ -1747,6 +1754,13 @@
 W:	http://www.cse.unsw.edu.au/~neilb/patches/linux-devel/
 S:	Maintained
 
+KERNEL VIRTUAL MACHINE (KVM)
+P:	Avi Kivity
+M:	avi@qumranet.com
+L:	kvm-devel@lists.sourceforge.net
+W:	kvm.sourceforge.net
+S:	Supported
+
 KEXEC
 P:	Eric Biederman
 M:	ebiederm@xmission.com
@@ -3429,6 +3443,12 @@
 L:	lm-sensors@lm-sensors.org
 S:	Maintained
 
+W83793 HARDWARE MONITORING DRIVER
+P:	Rudolf Marek
+M:	r.marek@assembler.cz
+L:	lm-sensors@lm-sensors.org
+S:	Maintained
+
 W83L51xD SD/MMC CARD INTERFACE DRIVER
 P:	Pierre Ossman
 M:	drzeus-wbsd@drzeus.cx
diff --git a/Makefile b/Makefile
index 4eabaa8..f732e75 100644
--- a/Makefile
+++ b/Makefile
@@ -1390,12 +1390,18 @@
 
 PHONY += checkstack kernelrelease kernelversion
 
-# Use $(SUBARCH) here instead of $(ARCH) so that this works for UML.
-# In the UML case, $(SUBARCH) is the name of the underlying
-# architecture, while for all other arches, it is the same as $(ARCH).
+# UML needs a little special treatment here.  It wants to use the host
+# toolchain, so needs $(SUBARCH) passed to checkstack.pl.  Everyone
+# else wants $(ARCH), including people doing cross-builds, which means
+# that $(SUBARCH) doesn't work here.
+ifeq ($(ARCH), um)
+CHECKSTACK_ARCH := $(SUBARCH)
+else
+CHECKSTACK_ARCH := $(ARCH)
+endif
 checkstack:
 	$(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \
-	$(PERL) $(src)/scripts/checkstack.pl $(SUBARCH)
+	$(PERL) $(src)/scripts/checkstack.pl $(CHECKSTACK_ARCH)
 
 kernelrelease:
 	$(if $(wildcard include/config/kernel.release), $(Q)echo $(KERNELRELEASE), \
diff --git a/arch/arm/kernel/apm.c b/arch/arm/kernel/apm.c
index a11fb9a..2c37b70 100644
--- a/arch/arm/kernel/apm.c
+++ b/arch/arm/kernel/apm.c
@@ -423,7 +423,7 @@
 {
 	struct apm_user *as;
 
-	as = (struct apm_user *)kzalloc(sizeof(*as), GFP_KERNEL);
+	as = kzalloc(sizeof(*as), GFP_KERNEL);
 	if (as) {
 		/*
 		 * XXX - this is a tiny bit broken, when we consider BSD
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index a786f76..71257e3 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -353,7 +353,7 @@
 		}
 		if (c_id(&excd) == 0x80) { /* loader */
 			if (!ec->loader) {
-				ec->loader = (loader_t)kmalloc(c_len(&excd),
+				ec->loader = kmalloc(c_len(&excd),
 							       GFP_KERNEL);
 				if (ec->loader)
 					ecard_readbytes(ec->loader, ec,
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig
index d135568..8781aae 100644
--- a/arch/arm/mach-omap1/Kconfig
+++ b/arch/arm/mach-omap1/Kconfig
@@ -43,6 +43,7 @@
 config MACH_OMAP_OSK
 	bool "TI OSK Support"
 	depends on ARCH_OMAP1 && ARCH_OMAP16XX
+	select TPS65010
     	help
 	  TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here
           if you have such a board.
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index 3a62280..7d0cf7a 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -30,6 +30,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/irq.h>
+#include <linux/interrupt.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
diff --git a/arch/arm26/kernel/ecard.c b/arch/arm26/kernel/ecard.c
index 43dd41b..9dbc1724 100644
--- a/arch/arm26/kernel/ecard.c
+++ b/arch/arm26/kernel/ecard.c
@@ -215,7 +215,7 @@
 		}
 		if (c_id(&excd) == 0x80) { /* loader */
 			if (!ec->loader) {
-				ec->loader = (loader_t)kmalloc(c_len(&excd),
+				ec->loader = kmalloc(c_len(&excd),
 							       GFP_KERNEL);
 				if (ec->loader)
 					ecard_readbytes(ec->loader, ec,
diff --git a/arch/arm26/kernel/irq.c b/arch/arm26/kernel/irq.c
index d87d68b..d53382c 100644
--- a/arch/arm26/kernel/irq.c
+++ b/arch/arm26/kernel/irq.c
@@ -545,7 +545,7 @@
 	    (irq_flags & IRQF_SHARED && !dev_id))
 		return -EINVAL;
 
-	action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+	action = kmalloc(sizeof(struct irqaction), GFP_KERNEL);
 	if (!action)
 		return -ENOMEM;
 
diff --git a/arch/cris/arch-v10/drivers/axisflashmap.c b/arch/cris/arch-v10/drivers/axisflashmap.c
index 4fa81ab..ffade19 100644
--- a/arch/cris/arch-v10/drivers/axisflashmap.c
+++ b/arch/cris/arch-v10/drivers/axisflashmap.c
@@ -516,7 +516,7 @@
 #else
 		struct mtd_info *mtd_ram;
 
-		mtd_ram = (struct mtd_info *)kmalloc(sizeof(struct mtd_info),
+		mtd_ram = kmalloc(sizeof(struct mtd_info),
 						     GFP_KERNEL);
 		if (!mtd_ram) {
 			panic("axisflashmap couldn't allocate memory for "
diff --git a/arch/cris/arch-v10/drivers/gpio.c b/arch/cris/arch-v10/drivers/gpio.c
index fcba663..9aba18b 100644
--- a/arch/cris/arch-v10/drivers/gpio.c
+++ b/arch/cris/arch-v10/drivers/gpio.c
@@ -440,7 +440,7 @@
 	if (p > GPIO_MINOR_LAST)
 		return -EINVAL;
 
-	priv = (struct gpio_private *)kmalloc(sizeof(struct gpio_private), 
+	priv = kmalloc(sizeof(struct gpio_private),
 					      GFP_KERNEL);
 
 	if (!priv)
diff --git a/arch/cris/arch-v32/drivers/axisflashmap.c b/arch/cris/arch-v32/drivers/axisflashmap.c
index 4195232..5180d45 100644
--- a/arch/cris/arch-v32/drivers/axisflashmap.c
+++ b/arch/cris/arch-v32/drivers/axisflashmap.c
@@ -427,7 +427,7 @@
 #else
 		struct mtd_info *mtd_ram;
 
-		mtd_ram = (struct mtd_info *)kmalloc(sizeof(struct mtd_info),
+		mtd_ram = kmalloc(sizeof(struct mtd_info),
 						     GFP_KERNEL);
 		if (!mtd_ram) {
 			panic("axisflashmap couldn't allocate memory for "
diff --git a/arch/cris/arch-v32/drivers/gpio.c b/arch/cris/arch-v32/drivers/gpio.c
index c3f876b..08d36f0 100644
--- a/arch/cris/arch-v32/drivers/gpio.c
+++ b/arch/cris/arch-v32/drivers/gpio.c
@@ -423,7 +423,7 @@
 	if (p > GPIO_MINOR_LAST)
 		return -EINVAL;
 
-	priv = (struct gpio_private *)kmalloc(sizeof(struct gpio_private),
+	priv = kmalloc(sizeof(struct gpio_private),
 					      GFP_KERNEL);
 
 	if (!priv)
diff --git a/arch/cris/arch-v32/kernel/signal.c b/arch/cris/arch-v32/kernel/signal.c
index 99e59b3..7cd6ac8 100644
--- a/arch/cris/arch-v32/kernel/signal.c
+++ b/arch/cris/arch-v32/kernel/signal.c
@@ -686,7 +686,7 @@
 int __init
 cris_init_signal(void)
 {
-	u16* data = (u16*)kmalloc(PAGE_SIZE, GFP_KERNEL);
+	u16* data = kmalloc(PAGE_SIZE, GFP_KERNEL);
 
 	/* This is movu.w __NR_sigreturn, r9; break 13; */
 	data[0] = 0x9c5f;
diff --git a/arch/cris/kernel/profile.c b/arch/cris/kernel/profile.c
index 69c5218..f60ab78 100644
--- a/arch/cris/kernel/profile.c
+++ b/arch/cris/kernel/profile.c
@@ -59,7 +59,7 @@
 __init init_cris_profile(void)
 {
   struct proc_dir_entry *entry;
-  sample_buffer = (char*)kmalloc(SAMPLE_BUFFER_SIZE, GFP_KERNEL);
+  sample_buffer = kmalloc(SAMPLE_BUFFER_SIZE, GFP_KERNEL);
   sample_buffer_pos = sample_buffer;
   entry = create_proc_entry("system_profile", S_IWUSR | S_IRUGO, NULL);
   if (entry) {
diff --git a/arch/h8300/kernel/ints.c b/arch/h8300/kernel/ints.c
index 1bfc77e..587ef7f 100644
--- a/arch/h8300/kernel/ints.c
+++ b/arch/h8300/kernel/ints.c
@@ -141,7 +141,7 @@
 		return -EBUSY;
 
 	if (use_kmalloc)
-		irq_handle = (irq_handler_t *)kmalloc(sizeof(irq_handler_t), GFP_ATOMIC);
+		irq_handle = kmalloc(sizeof(irq_handler_t), GFP_ATOMIC);
 	else {
 		/* use bootmem allocater */
 		irq_handle = (irq_handler_t *)alloc_bootmem(sizeof(irq_handler_t));
diff --git a/arch/h8300/platform/h8s/ints.c b/arch/h8300/platform/h8s/ints.c
index 270440d..567f681 100644
--- a/arch/h8300/platform/h8s/ints.c
+++ b/arch/h8300/platform/h8s/ints.c
@@ -176,7 +176,7 @@
 	}		
 
 	if (use_kmalloc)
-		irq_handle = (irq_handler_t *)kmalloc(sizeof(irq_handler_t), GFP_ATOMIC);
+		irq_handle = kmalloc(sizeof(irq_handler_t), GFP_ATOMIC);
 	else {
 		/* use bootmem allocater */
 		irq_handle = (irq_handler_t *)alloc_bootmem(sizeof(irq_handler_t));
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index a97847d..b75cff2 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -1604,7 +1604,7 @@
 {
 	struct apm_user *	as;
 
-	as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL);
+	as = kmalloc(sizeof(*as), GFP_KERNEL);
 	if (as == NULL) {
 		printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n",
 		       sizeof(*as));
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index 9723466..47ffec5 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -1,7 +1,7 @@
 /*
  *	Intel CPU Microcode Update Driver for Linux
  *
- *	Copyright (C) 2000-2004 Tigran Aivazian
+ *	Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
  *		      2006	Shaohua Li <shaohua.li@intel.com>
  *
  *	This driver allows to upgrade microcode on Intel processors
@@ -92,7 +92,7 @@
 #include <asm/processor.h>
 
 MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver");
-MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
+MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
 MODULE_LICENSE("GPL");
 
 #define MICROCODE_VERSION 	"1.14a"
@@ -752,7 +752,7 @@
 	register_hotcpu_notifier(&mc_cpu_notifier);
 
 	printk(KERN_INFO 
-		"IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@veritas.com>\n");
+		"IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@aivazian.fsnet.co.uk>\n");
 	return 0;
 }
 
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index b0f84e5..aef39be 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -69,9 +69,7 @@
 
 /* Number of siblings per CPU package */
 int smp_num_siblings = 1;
-#ifdef CONFIG_SMP
 EXPORT_SYMBOL(smp_num_siblings);
-#endif
 
 /* Last level cache ID of each logical CPU */
 int cpu_llc_id[NR_CPUS] __cpuinitdata = {[0 ... NR_CPUS-1] = BAD_APICID};
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 462ea17..3336799 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -189,7 +189,7 @@
 	int e;
 
 	for (sz = PAGE_SIZE; sz < 16 * PAGE_SIZE; sz += PAGE_SIZE) {
-		if (!(p = (char *)kmalloc(sz, GFP_KERNEL)))
+		if (!(p = kmalloc(sz, GFP_KERNEL)))
 			break;
 		e = ia64_sn_ioif_get_pci_topology(__pa(p), sz);
 		if (e == SALRET_OK)
diff --git a/arch/m68k/mm/kmap.c b/arch/m68k/mm/kmap.c
index b54ef17..46b7d60 100644
--- a/arch/m68k/mm/kmap.c
+++ b/arch/m68k/mm/kmap.c
@@ -59,7 +59,7 @@
 	unsigned long addr;
 	struct vm_struct **p, *tmp, *area;
 
-	area = (struct vm_struct *)kmalloc(sizeof(*area), GFP_KERNEL);
+	area = kmalloc(sizeof(*area), GFP_KERNEL);
 	if (!area)
 		return NULL;
 	addr = KMAP_START;
diff --git a/arch/mips/kernel/apm.c b/arch/mips/kernel/apm.c
index 528e731..ba16d07 100644
--- a/arch/mips/kernel/apm.c
+++ b/arch/mips/kernel/apm.c
@@ -356,7 +356,7 @@
 {
 	struct apm_user *as;
 
-	as = (struct apm_user *)kzalloc(sizeof(*as), GFP_KERNEL);
+	as = kzalloc(sizeof(*as), GFP_KERNEL);
 	if (as) {
 		/*
 		 * XXX - this is a tiny bit broken, when we consider BSD
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index ea2d153..30245c0 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -203,6 +203,31 @@
 	preempt_check_resched();
 }
 
+void copy_user_highpage(struct page *to, struct page *from,
+	unsigned long vaddr, struct vm_area_struct *vma)
+{
+	void *vfrom, *vto;
+
+	vto = kmap_atomic(to, KM_USER1);
+	if (cpu_has_dc_aliases) {
+		vfrom = kmap_coherent(from, vaddr);
+		copy_page(vto, vfrom);
+		kunmap_coherent(from);
+	} else {
+		vfrom = kmap_atomic(from, KM_USER0);
+		copy_page(vto, vfrom);
+		kunmap_atomic(vfrom, KM_USER0);
+	}
+	if (((vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc) ||
+	    pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK))
+		flush_data_cache_page((unsigned long)vto);
+	kunmap_atomic(vto, KM_USER1);
+	/* Make sure this page is cleared on other CPU's too before using it */
+	smp_wmb();
+}
+
+EXPORT_SYMBOL(copy_user_highpage);
+
 void copy_to_user_page(struct vm_area_struct *vma,
 	struct page *page, unsigned long vaddr, void *dst, const void *src,
 	unsigned long len)
diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c
index d883092..04c2ff4 100644
--- a/arch/parisc/hpux/sys_hpux.c
+++ b/arch/parisc/hpux/sys_hpux.c
@@ -475,7 +475,7 @@
 		printk(KERN_DEBUG "len of arg1 = %d\n", len);
 		if (len == 0)
 			return 0;
-		fsname = (char *) kmalloc(len, GFP_KERNEL);
+		fsname = kmalloc(len, GFP_KERNEL);
 		if ( !fsname ) {
 			printk(KERN_DEBUG "failed to kmalloc fsname\n");
 			return 0;
diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c
index 920bdbf..c10ab47 100644
--- a/arch/parisc/kernel/unwind.c
+++ b/arch/parisc/kernel/unwind.c
@@ -343,7 +343,7 @@
 	struct pt_regs *r = &t->thread.regs;
 	struct pt_regs *r2;
 
-	r2 = (struct pt_regs *)kmalloc(sizeof(struct pt_regs), GFP_KERNEL);
+	r2 = kmalloc(sizeof(struct pt_regs), GFP_KERNEL);
 	if (!r2)
 		return;
 	*r2 = *r;
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index 6960f09..869cebb 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -505,7 +505,7 @@
 		return -ENODEV;
 	total_size = ppc_md.nvram_size();
 	
-	header = (char *) kmalloc(NVRAM_HEADER_LEN, GFP_KERNEL);
+	header = kmalloc(NVRAM_HEADER_LEN, GFP_KERNEL);
 	if (!header) {
 		printk(KERN_ERR "nvram_scan_partitions: Failed kmalloc\n");
 		return -ENOMEM;
@@ -574,7 +574,7 @@
 	}
   	
   	/* initialize our anchor for the nvram partition list */
-  	nvram_part = (struct nvram_partition *) kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);
+  	nvram_part = kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);
   	if (!nvram_part) {
   		printk(KERN_ERR "nvram_init: Failed kmalloc\n");
   		return -ENOMEM;
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index 8336dea..2847cd5 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -670,7 +670,7 @@
 	struct pci_controller* hose;
 	struct property *map_prop;
 
-	pci_to_OF_bus_map = (u8*)kmalloc(pci_bus_count, GFP_KERNEL);
+	pci_to_OF_bus_map = kmalloc(pci_bus_count, GFP_KERNEL);
 	if (!pci_to_OF_bus_map) {
 		printk(KERN_ERR "Can't allocate OF bus map !\n");
 		return;
diff --git a/arch/powerpc/mm/imalloc.c b/arch/powerpc/mm/imalloc.c
index add8c1a..c831815 100644
--- a/arch/powerpc/mm/imalloc.c
+++ b/arch/powerpc/mm/imalloc.c
@@ -138,7 +138,7 @@
 	struct vm_struct *vm2 = NULL;
 	struct vm_struct *new_vm = NULL;
 	
-	vm1 = (struct vm_struct *) kmalloc(sizeof(*vm1), GFP_KERNEL);
+	vm1 = kmalloc(sizeof(*vm1), GFP_KERNEL);
 	if (vm1	== NULL) {
 		printk(KERN_ERR "%s() out of memory\n", __FUNCTION__);
 		return NULL;
@@ -172,7 +172,7 @@
 		 * uppermost remainder, and use existing parent one for the
 		 * lower remainder of parent range
 		 */
-		vm2 = (struct vm_struct *) kmalloc(sizeof(*vm2), GFP_KERNEL);
+		vm2 = kmalloc(sizeof(*vm2), GFP_KERNEL);
 		if (vm2 == NULL) {
 			printk(KERN_ERR "%s() out of memory\n", __FUNCTION__);
 			kfree(vm1);
@@ -206,7 +206,7 @@
 			break;
 	}
 	
-	area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);
+	area = kmalloc(sizeof(*area), GFP_KERNEL);
 	if (!area)
 		return NULL;
 	area->flags = 0;
diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c
index b6b462d..f2bae04 100644
--- a/arch/powerpc/platforms/pseries/eeh_cache.c
+++ b/arch/powerpc/platforms/pseries/eeh_cache.c
@@ -153,7 +153,7 @@
 			return piar;
 		}
 	}
-	piar = (struct pci_io_addr_range *)kmalloc(sizeof(struct pci_io_addr_range), GFP_ATOMIC);
+	piar = kmalloc(sizeof(struct pci_io_addr_range), GFP_ATOMIC);
 	if (!piar)
 		return NULL;
 
diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c
index 709952c..06b84c3 100644
--- a/arch/ppc/8260_io/fcc_enet.c
+++ b/arch/ppc/8260_io/fcc_enet.c
@@ -1892,10 +1892,10 @@
 	/* Allocate space for the buffer descriptors from regular memory.
 	 * Initialize base addresses for the buffer descriptors.
 	 */
-	cep->rx_bd_base = (cbd_t *)kmalloc(sizeof(cbd_t) * RX_RING_SIZE,
+	cep->rx_bd_base = kmalloc(sizeof(cbd_t) * RX_RING_SIZE,
 			GFP_KERNEL | GFP_DMA);
 	ep->fen_genfcc.fcc_rbase = __pa(cep->rx_bd_base);
-	cep->tx_bd_base = (cbd_t *)kmalloc(sizeof(cbd_t) * TX_RING_SIZE,
+	cep->tx_bd_base = kmalloc(sizeof(cbd_t) * TX_RING_SIZE,
 			GFP_KERNEL | GFP_DMA);
 	ep->fen_genfcc.fcc_tbase = __pa(cep->tx_bd_base);
 
diff --git a/arch/ppc/8xx_io/cs4218_tdm.c b/arch/ppc/8xx_io/cs4218_tdm.c
index c71ef3c..b7bb5f0 100644
--- a/arch/ppc/8xx_io/cs4218_tdm.c
+++ b/arch/ppc/8xx_io/cs4218_tdm.c
@@ -2601,7 +2601,7 @@
 	/* Initialize beep stuff */
 	orig_mksound = kd_mksound;
 	kd_mksound = cs_mksound;
-	beep_buf = (short *) kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL);
+	beep_buf = kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL);
 	if (beep_buf == NULL)
 		printk(KERN_WARNING "dmasound: no memory for "
 		       "beep buffer\n");
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index ff69056..1227236 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -407,7 +407,7 @@
 
 config APPLDATA_MEM
 	tristate "Monitor memory management statistics"
-	depends on APPLDATA_BASE
+	depends on APPLDATA_BASE && VM_EVENT_COUNTERS
 	help
 	  This provides memory management related data to the Linux - VM Monitor
 	  Stream, like paging/swapping rate, memory utilisation, etc.
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index ef5266f..bb57bc0 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -191,13 +191,13 @@
 	debug_entry_t*** areas;
 	int i,j;
 
-	areas = (debug_entry_t ***) kmalloc(nr_areas *
+	areas = kmalloc(nr_areas *
 					sizeof(debug_entry_t**),
 					GFP_KERNEL);
 	if (!areas)
 		goto fail_malloc_areas;
 	for (i = 0; i < nr_areas; i++) {
-		areas[i] = (debug_entry_t**) kmalloc(pages_per_area *
+		areas[i] = kmalloc(pages_per_area *
 				sizeof(debug_entry_t*),GFP_KERNEL);
 		if (!areas[i]) {
 			goto fail_malloc_areas2;
@@ -242,7 +242,7 @@
 
 	/* alloc everything */
 
-	rc = (debug_info_t*) kmalloc(sizeof(debug_info_t), GFP_KERNEL);
+	rc = kmalloc(sizeof(debug_info_t), GFP_KERNEL);
 	if(!rc)
 		goto fail_malloc_rc;
 	rc->active_entries = kcalloc(nr_areas, sizeof(int), GFP_KERNEL);
@@ -634,7 +634,7 @@
 		rc = -ENOMEM;
 		goto out;
 	}
-	p_info = (file_private_info_t *) kmalloc(sizeof(file_private_info_t),
+	p_info = kmalloc(sizeof(file_private_info_t),
 						GFP_KERNEL);
 	if(!p_info){
 		if(debug_info_snapshot)
diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c
index 4faf96f..bc5beaa 100644
--- a/arch/s390/kernel/s390_ext.c
+++ b/arch/s390/kernel/s390_ext.c
@@ -37,7 +37,7 @@
         ext_int_info_t *p;
         int index;
 
-	p = (ext_int_info_t *) kmalloc(sizeof(ext_int_info_t), GFP_ATOMIC);
+	p = kmalloc(sizeof(ext_int_info_t), GFP_ATOMIC);
         if (p == NULL)
                 return -ENOMEM;
         p->code = code;
diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c
index c8cb211..5b4841d 100644
--- a/arch/sparc/kernel/irq.c
+++ b/arch/sparc/kernel/irq.c
@@ -425,7 +425,7 @@
 	}
 	
 	if (action == NULL)
-	    action = (struct irqaction *)kmalloc(sizeof(struct irqaction),
+	    action = kmalloc(sizeof(struct irqaction),
 						 GFP_ATOMIC);
 	
 	if (!action) { 
@@ -528,7 +528,7 @@
 	}
 	
 	if (action == NULL)
-		action = (struct irqaction *)kmalloc(sizeof(struct irqaction),
+		action = kmalloc(sizeof(struct irqaction),
 						     GFP_ATOMIC);
 	
 	if (!action) { 
diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c
index cf1b8ba..0e27e22 100644
--- a/arch/sparc/kernel/sun4d_irq.c
+++ b/arch/sparc/kernel/sun4d_irq.c
@@ -327,7 +327,7 @@
 	}
 	
 	if (action == NULL)
-		action = (struct irqaction *)kmalloc(sizeof(struct irqaction),
+		action = kmalloc(sizeof(struct irqaction),
 						     GFP_ATOMIC);
 	
 	if (!action) { 
diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
index 4446f66..2ebc2c0 100644
--- a/arch/sparc64/kernel/sys_sunos32.c
+++ b/arch/sparc64/kernel/sys_sunos32.c
@@ -1055,7 +1055,7 @@
 		break;
 	case 2:
 		rval = -EFAULT;
-		kmbuf = (struct msgbuf *)kmalloc(sizeof(struct msgbuf) + arg3,
+		kmbuf = kmalloc(sizeof(struct msgbuf) + arg3,
 						 GFP_KERNEL);
 		if (!kmbuf)
 			break;
@@ -1078,7 +1078,7 @@
 		break;
 	case 3:
 		rval = -EFAULT;
-		kmbuf = (struct msgbuf *)kmalloc(sizeof(struct msgbuf) + arg3,
+		kmbuf = kmalloc(sizeof(struct msgbuf) + arg3,
 						 GFP_KERNEL);
 		if (!kmbuf || sunos_msgbuf_get((struct msgbuf32 __user *)(unsigned long)arg2,
 					       kmbuf, arg3))
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index b2e9762..afe3d42 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -72,9 +72,11 @@
 	return pkt_len;
 }
 
-static void uml_dev_close(void* dev)
+static void uml_dev_close(struct work_struct *work)
 {
-	dev_close( (struct net_device *) dev);
+	struct uml_net_private *lp =
+		container_of(work, struct uml_net_private, work);
+	dev_close(lp->dev);
 }
 
 irqreturn_t uml_net_interrupt(int irq, void *dev_id)
@@ -89,7 +91,6 @@
 	spin_lock(&lp->lock);
 	while((err = uml_net_rx(dev)) > 0) ;
 	if(err < 0) {
-		DECLARE_WORK(close_work, uml_dev_close, dev);
 		printk(KERN_ERR 
 		       "Device '%s' read returned %d, shutting it down\n", 
 		       dev->name, err);
@@ -97,9 +98,10 @@
 		 * again lp->lock.
 		 * And dev_close() can be safely called multiple times on the
 		 * same device, since it tests for (dev->flags & IFF_UP). So
-		 * there's no harm in delaying the device shutdown. */
-		schedule_work(&close_work);
-#error this is not permitted - close_work will go out of scope
+		 * there's no harm in delaying the device shutdown.
+		 * Furthermore, the workqueue will not re-enqueue an already
+		 * enqueued work item. */
+		schedule_work(&lp->work);
 		goto out;
 	}
 	reactivate_fd(lp->fd, UM_ETH_IRQ);
@@ -365,6 +367,7 @@
 	/* This points to the transport private data. It's still clear, but we
 	 * must memset it to 0 *now*. Let's help the drivers. */
 	memset(lp, 0, size);
+	INIT_WORK(&lp->work, uml_dev_close);
 
 	/* sysfs register */
 	if (!driver_registered) {
diff --git a/arch/um/include/net_kern.h b/arch/um/include/net_kern.h
index 280459f..218f8b4 100644
--- a/arch/um/include/net_kern.h
+++ b/arch/um/include/net_kern.h
@@ -11,6 +11,7 @@
 #include <linux/skbuff.h>
 #include <linux/socket.h>
 #include <linux/list.h>
+#include <linux/workqueue.h>
 
 struct uml_net {
 	struct list_head list;
@@ -26,6 +27,7 @@
 	struct net_device *dev;
 	struct timer_list tl;
 	struct net_device_stats stats;
+	struct work_struct work;
 	int fd;
 	unsigned char mac[ETH_ALEN];
 	unsigned short (*protocol)(struct sk_buff *);
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index 49057d8..5db7737 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -166,7 +166,7 @@
 	struct ptrace_ldt ptrace_ldt = (struct ptrace_ldt) {
 			.func = 0,
 			.bytecount = bytecount,
-			.ptr = (void *)kmalloc(bytecount, GFP_KERNEL)};
+			.ptr = kmalloc(bytecount, GFP_KERNEL)};
 	u32 cpu;
 
 	if(ptrace_ldt.ptr == NULL)
@@ -426,7 +426,7 @@
 		host_ldt_entries = dummy_list;
 	else {
 		size = (size + 1) * sizeof(dummy_list[0]);
-		host_ldt_entries = (short *)kmalloc(size, GFP_KERNEL);
+		host_ldt_entries = kmalloc(size, GFP_KERNEL);
 		if(host_ldt_entries == NULL) {
 			printk("ldt_get_host_info: couldn't allocate host ldt list\n");
 			goto out_free;
diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index d573017..71f733c 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -6,7 +6,7 @@
 
 
 obj-y := align.o entry.o irq.o coprocessor.o process.o ptrace.o semaphore.o  \
-	 setup.o signal.o syscalls.o time.o traps.o vectors.o platform.o  \
+	 setup.o signal.o syscall.o time.o traps.o vectors.o platform.o  \
 	 pci-dma.o
 
 ## windowspill.o
diff --git a/arch/xtensa/kernel/syscall.c b/arch/xtensa/kernel/syscall.c
index 418268f..fe3834b 100644
--- a/arch/xtensa/kernel/syscall.c
+++ b/arch/xtensa/kernel/syscall.c
@@ -16,7 +16,7 @@
  *
  */
 #include <asm/uaccess.h>
-#include <asm/syscalls.h>
+#include <asm/syscall.h>
 #include <asm/unistd.h>
 #include <linux/linkage.h>
 #include <linux/stringify.h>
diff --git a/block/as-iosched.c b/block/as-iosched.c
index 5934c4b..ef12627 100644
--- a/block/as-iosched.c
+++ b/block/as-iosched.c
@@ -1462,20 +1462,7 @@
 
 static int __init as_init(void)
 {
-	int ret;
-
-	ret = elv_register(&iosched_as);
-	if (!ret) {
-		/*
-		 * don't allow AS to get unregistered, since we would have
-		 * to browse all tasks in the system and release their
-		 * as_io_context first
-		 */
-		__module_get(THIS_MODULE);
-		return 0;
-	}
-
-	return ret;
+	return elv_register(&iosched_as);
 }
 
 static void __exit as_exit(void)
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 78c6b31..533a293 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -219,9 +219,12 @@
 	return !cfqd->busy_queues;
 }
 
-static inline pid_t cfq_queue_pid(struct task_struct *task, int rw)
+static inline pid_t cfq_queue_pid(struct task_struct *task, int rw, int is_sync)
 {
-	if (rw == READ || rw == WRITE_SYNC)
+	/*
+	 * Use the per-process queue, for read requests and syncronous writes
+	 */
+	if (!(rw & REQ_RW) || is_sync)
 		return task->pid;
 
 	return CFQ_KEY_ASYNC;
@@ -473,7 +476,7 @@
 cfq_find_rq_fmerge(struct cfq_data *cfqd, struct bio *bio)
 {
 	struct task_struct *tsk = current;
-	pid_t key = cfq_queue_pid(tsk, bio_data_dir(bio));
+	pid_t key = cfq_queue_pid(tsk, bio_data_dir(bio), bio_sync(bio));
 	struct cfq_queue *cfqq;
 
 	cfqq = cfq_find_cfq_hash(cfqd, key, tsk->ioprio);
@@ -1748,6 +1751,9 @@
 	struct cfq_data *cfqd = q->elevator->elevator_data;
 	struct task_struct *tsk = current;
 	struct cfq_queue *cfqq;
+	unsigned int key;
+
+	key = cfq_queue_pid(tsk, rw, rw & REQ_RW_SYNC);
 
 	/*
 	 * don't force setup of a queue from here, as a call to may_queue
@@ -1755,7 +1761,7 @@
 	 * so just lookup a possibly existing queue, or return 'may queue'
 	 * if that fails
 	 */
-	cfqq = cfq_find_cfq_hash(cfqd, cfq_queue_pid(tsk, rw), tsk->ioprio);
+	cfqq = cfq_find_cfq_hash(cfqd, key, tsk->ioprio);
 	if (cfqq) {
 		cfq_init_prio_data(cfqq);
 		cfq_prio_boost(cfqq);
@@ -1798,10 +1804,10 @@
 	struct task_struct *tsk = current;
 	struct cfq_io_context *cic;
 	const int rw = rq_data_dir(rq);
-	pid_t key = cfq_queue_pid(tsk, rw);
+	const int is_sync = rq_is_sync(rq);
+	pid_t key = cfq_queue_pid(tsk, rw, is_sync);
 	struct cfq_queue *cfqq;
 	unsigned long flags;
-	int is_sync = key != CFQ_KEY_ASYNC;
 
 	might_sleep_if(gfp_mask & __GFP_WAIT);
 
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index a541b42..79807db 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -2058,15 +2058,16 @@
  * Returns NULL on failure, with queue_lock held.
  * Returns !NULL on success, with queue_lock *not held*.
  */
-static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
-				   gfp_t gfp_mask)
+static struct request *get_request(request_queue_t *q, int rw_flags,
+				   struct bio *bio, gfp_t gfp_mask)
 {
 	struct request *rq = NULL;
 	struct request_list *rl = &q->rq;
 	struct io_context *ioc = NULL;
+	const int rw = rw_flags & 0x01;
 	int may_queue, priv;
 
-	may_queue = elv_may_queue(q, rw);
+	may_queue = elv_may_queue(q, rw_flags);
 	if (may_queue == ELV_MQUEUE_NO)
 		goto rq_starved;
 
@@ -2114,7 +2115,7 @@
 
 	spin_unlock_irq(q->queue_lock);
 
-	rq = blk_alloc_request(q, rw, priv, gfp_mask);
+	rq = blk_alloc_request(q, rw_flags, priv, gfp_mask);
 	if (unlikely(!rq)) {
 		/*
 		 * Allocation failed presumably due to memory. Undo anything
@@ -2162,12 +2163,13 @@
  *
  * Called with q->queue_lock held, and returns with it unlocked.
  */
-static struct request *get_request_wait(request_queue_t *q, int rw,
+static struct request *get_request_wait(request_queue_t *q, int rw_flags,
 					struct bio *bio)
 {
+	const int rw = rw_flags & 0x01;
 	struct request *rq;
 
-	rq = get_request(q, rw, bio, GFP_NOIO);
+	rq = get_request(q, rw_flags, bio, GFP_NOIO);
 	while (!rq) {
 		DEFINE_WAIT(wait);
 		struct request_list *rl = &q->rq;
@@ -2175,7 +2177,7 @@
 		prepare_to_wait_exclusive(&rl->wait[rw], &wait,
 				TASK_UNINTERRUPTIBLE);
 
-		rq = get_request(q, rw, bio, GFP_NOIO);
+		rq = get_request(q, rw_flags, bio, GFP_NOIO);
 
 		if (!rq) {
 			struct io_context *ioc;
@@ -2910,6 +2912,7 @@
 	int el_ret, nr_sectors, barrier, err;
 	const unsigned short prio = bio_prio(bio);
 	const int sync = bio_sync(bio);
+	int rw_flags;
 
 	nr_sectors = bio_sectors(bio);
 
@@ -2984,10 +2987,19 @@
 
 get_rq:
 	/*
+	 * This sync check and mask will be re-done in init_request_from_bio(),
+	 * but we need to set it earlier to expose the sync flag to the
+	 * rq allocator and io schedulers.
+	 */
+	rw_flags = bio_data_dir(bio);
+	if (sync)
+		rw_flags |= REQ_RW_SYNC;
+
+	/*
 	 * Grab a free request. This is might sleep but can not fail.
 	 * Returns with the queue unlocked.
 	 */
-	req = get_request_wait(q, bio_data_dir(bio), bio);
+	req = get_request_wait(q, rw_flags, bio);
 
 	/*
 	 * After dropping the lock and possibly sleeping here, our request
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index 034c939b..6e93004f 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -17,7 +17,6 @@
 #include <linux/crypto.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/io.h>
 #include <linux/module.h>
 #include <linux/scatterlist.h>
 #include <linux/seq_file.h>
diff --git a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c
index 0485423..674bf81 100644
--- a/drivers/acorn/block/fd1772.c
+++ b/drivers/acorn/block/fd1772.c
@@ -1549,12 +1549,12 @@
 #ifdef TRACKBUFFER
 	BufferDrive = BufferSide = BufferTrack = -1;
 	/* Atari uses 512 - I want to eventually cope with 1K sectors */
-	DMABuffer = (char *)kmalloc((FD1772_MAX_SECTORS+1)*512,GFP_KERNEL);
+	DMABuffer = kmalloc((FD1772_MAX_SECTORS+1)*512,GFP_KERNEL);
 	TrackBuffer = DMABuffer + 512;
 #else
 	/* Allocate memory for the DMAbuffer - on the Atari this takes it
 	   out of some special memory... */
-	DMABuffer = (char *) kmalloc(2048);	/* Copes with pretty large sectors */
+	DMABuffer = kmalloc(2048);	/* Copes with pretty large sectors */
 #endif
 	err = -ENOMEM;
 	if (!DMAbuffer)
diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
index 9021e34..90786d7 100644
--- a/drivers/ata/pdc_adma.c
+++ b/drivers/ata/pdc_adma.c
@@ -551,7 +551,7 @@
 		return rc;
 	adma_enter_reg_mode(ap);
 	rc = -ENOMEM;
-	pp = kcalloc(1, sizeof(*pp), GFP_KERNEL);
+	pp = kzalloc(sizeof(*pp), GFP_KERNEL);
 	if (!pp)
 		goto err_out;
 	pp->pkt = dma_alloc_coherent(dev, ADMA_PKT_BYTES, &pp->pkt_dma,
@@ -672,7 +672,7 @@
 	if (rc)
 		goto err_out_iounmap;
 
-	probe_ent = kcalloc(1, sizeof(*probe_ent), GFP_KERNEL);
+	probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
 	if (probe_ent == NULL) {
 		rc = -ENOMEM;
 		goto err_out_iounmap;
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index bc1b13c..5aab7bd 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -1832,7 +1832,7 @@
 	/* initialize memory management */
 	buffer_mem = eni_dev->mem - (buf - eni_dev->ram);
 	eni_dev->free_list_size = buffer_mem/MID_MIN_BUF_SIZE/2;
-	eni_dev->free_list = (struct eni_free *) kmalloc(
+	eni_dev->free_list = kmalloc(
 	    sizeof(struct eni_free)*(eni_dev->free_list_size+1),GFP_KERNEL);
 	if (!eni_dev->free_list) {
 		printk(KERN_ERR DEV_LABEL "(itf %d): couldn't get free page\n",
@@ -2232,7 +2232,7 @@
 		goto out0;
 	}
 
-	eni_dev = (struct eni_dev *) kmalloc(sizeof(struct eni_dev),GFP_KERNEL);
+	eni_dev = kmalloc(sizeof(struct eni_dev),GFP_KERNEL);
 	if (!eni_dev) goto out0;
 	if (!cpu_zeroes) {
 		cpu_zeroes = pci_alloc_consistent(pci_dev,ENI_ZEROES_SIZE,
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index 7d9b4e5..db33f6f 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -2351,7 +2351,7 @@
 
 	cid = he_mkcid(he_dev, vpi, vci);
 
-	he_vcc = (struct he_vcc *) kmalloc(sizeof(struct he_vcc), GFP_ATOMIC);
+	he_vcc = kmalloc(sizeof(struct he_vcc), GFP_ATOMIC);
 	if (he_vcc == NULL) {
 		hprintk("unable to allocate he_vcc during open\n");
 		return -ENOMEM;
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c
index 2678255..09f477d 100644
--- a/drivers/atm/lanai.c
+++ b/drivers/atm/lanai.c
@@ -2602,7 +2602,7 @@
 	struct atm_dev *atmdev;
 	int result;
 
-	lanai = (struct lanai_dev *) kmalloc(sizeof(*lanai), GFP_KERNEL);
+	lanai = kmalloc(sizeof(*lanai), GFP_KERNEL);
 	if (lanai == NULL) {
 		printk(KERN_ERR DEV_LABEL
 		       ": couldn't allocate dev_data structure!\n");
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c
index bd09045..aab9b37 100644
--- a/drivers/atm/nicstar.c
+++ b/drivers/atm/nicstar.c
@@ -997,7 +997,7 @@
    if (size != VBR_SCQSIZE && size != CBR_SCQSIZE)
       return NULL;
 
-   scq = (scq_info *) kmalloc(sizeof(scq_info), GFP_KERNEL);
+   scq = kmalloc(sizeof(scq_info), GFP_KERNEL);
    if (scq == NULL)
       return NULL;
    scq->org = kmalloc(2 * size, GFP_KERNEL);
@@ -1006,7 +1006,7 @@
       kfree(scq);
       return NULL;
    }
-   scq->skb = (struct sk_buff **) kmalloc(sizeof(struct sk_buff *) *
+   scq->skb = kmalloc(sizeof(struct sk_buff *) *
                                           (size / NS_SCQE_SIZE), GFP_KERNEL);
    if (scq->skb == NULL)
    {
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c
index 7df0f37..756d4f7 100644
--- a/drivers/atm/zatm.c
+++ b/drivers/atm/zatm.c
@@ -996,7 +996,7 @@
 
 	DPRINTK("start_tx\n");
 	zatm_dev = ZATM_DEV(dev);
-	zatm_dev->tx_map = (struct atm_vcc **) kmalloc(sizeof(struct atm_vcc *)*
+	zatm_dev->tx_map = kmalloc(sizeof(struct atm_vcc *)*
 	    zatm_dev->chans,GFP_KERNEL);
 	if (!zatm_dev->tx_map) return -ENOMEM;
 	zatm_dev->tx_bw = ATM_OC3_PCR;
@@ -1591,7 +1591,7 @@
 	struct zatm_dev *zatm_dev;
 	int ret = -ENOMEM;
 
-	zatm_dev = (struct zatm_dev *) kmalloc(sizeof(*zatm_dev), GFP_KERNEL);
+	zatm_dev = kmalloc(sizeof(*zatm_dev), GFP_KERNEL);
 	if (!zatm_dev) {
 		printk(KERN_EMERG "%s: memory shortage\n", DEV_LABEL);
 		goto out;
diff --git a/drivers/base/class.c b/drivers/base/class.c
index f098881..8bf2ca2 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -163,6 +163,8 @@
 void class_unregister(struct class * cls)
 {
 	pr_debug("device class '%s': unregistering\n", cls->name);
+	if (cls->virtual_dir)
+		kobject_unregister(cls->virtual_dir);
 	remove_class_attrs(cls);
 	subsystem_unregister(&cls->subsys);
 }
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c
index dbe0735..f95d502 100644
--- a/drivers/base/dmapool.c
+++ b/drivers/base/dmapool.c
@@ -173,7 +173,7 @@
 	mapsize = (mapsize + BITS_PER_LONG - 1) / BITS_PER_LONG;
 	mapsize *= sizeof (long);
 
-	page = (struct dma_page *) kmalloc (mapsize + sizeof *page, mem_flags);
+	page = kmalloc(mapsize + sizeof *page, mem_flags);
 	if (!page)
 		return NULL;
 	page->vaddr = dma_alloc_coherent (pool->dev,
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index d1df4a0..f9c903b 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -212,7 +212,7 @@
  *	pointer.  The memory associated with the platform data will be freed
  *	when the platform device is released.
  */
-int platform_device_add_data(struct platform_device *pdev, void *data, size_t size)
+int platform_device_add_data(struct platform_device *pdev, const void *data, size_t size)
 {
 	void *d;
 
@@ -473,7 +473,7 @@
  * Returns zero if the driver registered and bound to a device, else returns
  * a negative error code and with the driver not registered.
  */
-int platform_driver_probe(struct platform_driver *drv,
+int __init_or_module platform_driver_probe(struct platform_driver *drv,
 		int (*probe)(struct platform_device *))
 {
 	int retval, code;
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index ce9cfcb..58c1deb 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -28,13 +28,6 @@
 	tristate "Atari floppy support"
 	depends on ATARI
 
-config BLK_DEV_SWIM_IOP
-	bool "Macintosh IIfx/Quadra 900/Quadra 950 floppy support (EXPERIMENTAL)"
-	depends on MAC && EXPERIMENTAL && BROKEN
-	help
-	  Say Y here to support the SWIM (Super Woz Integrated Machine) IOP
-	  floppy controller on the Macintosh IIfx and Quadra 900/950.
-
 config MAC_FLOPPY
 	tristate "Support for PowerMac floppy"
 	depends on PPC_PMAC && !PPC_PMAC64
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 410f259..dd88e33 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -9,7 +9,6 @@
 obj-$(CONFIG_BLK_DEV_FD)	+= floppy.o
 obj-$(CONFIG_AMIGA_FLOPPY)	+= amiflop.o
 obj-$(CONFIG_ATARI_FLOPPY)	+= ataflop.o
-obj-$(CONFIG_BLK_DEV_SWIM_IOP)	+= swim_iop.o
 obj-$(CONFIG_ATARI_ACSI)	+= acsi.o
 obj-$(CONFIG_ATARI_SLM)		+= acsi_slm.o
 obj-$(CONFIG_AMIGA_Z2RAM)	+= z2ram.o
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index ee159ed..d719a5d 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1039,7 +1039,7 @@
 				status = -ENOMEM;
 				goto cleanup1;
 			}
-			buff_size = (int *)kmalloc(MAXSGENTRIES * sizeof(int),
+			buff_size = kmalloc(MAXSGENTRIES * sizeof(int),
 						   GFP_KERNEL);
 			if (!buff_size) {
 				status = -ENOMEM;
@@ -2837,7 +2837,7 @@
 	if (err) {
 		printk(KERN_ERR "cciss: Cannot obtain PCI resources, "
 		       "aborting\n");
-		goto err_out_disable_pdev;
+		return err;
 	}
 
 	subsystem_vendor_id = pdev->subsystem_vendor;
@@ -2865,7 +2865,7 @@
 #ifdef CCISS_DEBUG
 	printk("address 0 = %x\n", c->paddr);
 #endif				/* CCISS_DEBUG */
-	c->vaddr = remap_pci_mem(c->paddr, 200);
+	c->vaddr = remap_pci_mem(c->paddr, 0x250);
 
 	/* Wait for the board to become ready.  (PCI hotplug needs this.)
 	 * We poll for up to 120 secs, once per 100ms. */
@@ -3004,11 +3004,12 @@
 	}
 	return 0;
 
-      err_out_free_res:
+err_out_free_res:
+	/*
+	 * Deliberately omit pci_disable_device(): it does something nasty to
+	 * Smart Array controllers that pci_enable_device does not undo
+	 */
 	pci_release_regions(pdev);
-
-      err_out_disable_pdev:
-	pci_disable_device(pdev);
 	return err;
 }
 
@@ -3382,8 +3383,11 @@
 		if (drv->queue)
 			blk_cleanup_queue(drv->queue);
 	}
+	/*
+	 * Deliberately omit pci_disable_device(): it does something nasty to
+	 * Smart Array controllers that pci_enable_device does not undo
+	 */
 	pci_release_regions(pdev);
-	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
 	free_hba(i);
 	return -1;
@@ -3452,8 +3456,11 @@
 #ifdef CONFIG_CISS_SCSI_TAPE
 	kfree(hba[i]->scsi_rejects.complete);
 #endif
+	/*
+	 * Deliberately omit pci_disable_device(): it does something nasty to
+	 * Smart Array controllers that pci_enable_device does not undo
+	 */
 	pci_release_regions(pdev);
-	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
 	free_hba(i);
 }
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index d5f519e..b94cd1c 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -1625,7 +1625,7 @@
 		" processing\n");
 	/* Command does not return anything, but idasend command needs a 
 		buffer */
-	id_ctlr_buf = (id_ctlr_t *)kmalloc(sizeof(id_ctlr_t), GFP_KERNEL);
+	id_ctlr_buf = kmalloc(sizeof(id_ctlr_t), GFP_KERNEL);
 	if(id_ctlr_buf==NULL)
 	{
 		printk(KERN_WARNING "cpqarray: Out of memory. "
@@ -1660,14 +1660,14 @@
 
 	info_p->log_drv_map = 0;	
 	
-	id_ldrive = (id_log_drv_t *)kmalloc(sizeof(id_log_drv_t), GFP_KERNEL);
+	id_ldrive = kmalloc(sizeof(id_log_drv_t), GFP_KERNEL);
 	if(id_ldrive == NULL)
 	{
 		printk( KERN_ERR "cpqarray:  out of memory.\n");
 		return;
 	}
 
-	id_ctlr_buf = (id_ctlr_t *)kmalloc(sizeof(id_ctlr_t), GFP_KERNEL);
+	id_ctlr_buf = kmalloc(sizeof(id_ctlr_t), GFP_KERNEL);
 	if(id_ctlr_buf == NULL)
 	{
 		kfree(id_ldrive);
@@ -1675,7 +1675,7 @@
 		return;
 	}
 
-	id_lstatus_buf = (sense_log_drv_stat_t *)kmalloc(sizeof(sense_log_drv_stat_t), GFP_KERNEL);
+	id_lstatus_buf = kmalloc(sizeof(sense_log_drv_stat_t), GFP_KERNEL);
 	if(id_lstatus_buf == NULL)
 	{
 		kfree(id_ctlr_buf);
@@ -1684,7 +1684,7 @@
 		return;
 	}
 
-	sense_config_buf = (config_t *)kmalloc(sizeof(config_t), GFP_KERNEL);
+	sense_config_buf = kmalloc(sizeof(config_t), GFP_KERNEL);
 	if(sense_config_buf == NULL)
 	{
 		kfree(id_lstatus_buf);
diff --git a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c
deleted file mode 100644
index ed7b06c..0000000
--- a/drivers/block/swim_iop.c
+++ /dev/null
@@ -1,578 +0,0 @@
-/*
- * Driver for the SWIM (Super Woz Integrated Machine) IOP
- * floppy controller on the Macintosh IIfx and Quadra 900/950
- *
- * Written by Joshua M. Thompson (funaho@jurai.org)
- * based on the SWIM3 driver (c) 1996 by Paul Mackerras.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * 1999-06-12 (jmt) - Initial implementation.
- */
-
-/*
- * -------------------
- * Theory of Operation
- * -------------------
- *
- * Since the SWIM IOP is message-driven we implement a simple request queue
- * system.  One outstanding request may be queued at any given time (this is
- * an IOP limitation); only when that request has completed can a new request
- * be sent.
- */
-
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/fd.h>
-#include <linux/ioctl.h>
-#include <linux/blkdev.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/mac_iop.h>
-#include <asm/swim_iop.h>
-
-#define DRIVER_VERSION "Version 0.1 (1999-06-12)"
-
-#define MAX_FLOPPIES	4
-
-enum swim_state {
-	idle,
-	available,
-	revalidating,
-	transferring,
-	ejecting
-};
-
-struct floppy_state {
-	enum swim_state state;
-	int	drive_num;	/* device number */
-	int	secpercyl;	/* disk geometry information */
-	int	secpertrack;
-	int	total_secs;
-	int	write_prot;	/* 1 if write-protected, 0 if not, -1 dunno */
-	int	ref_count;
-	struct timer_list timeout;
-	int	ejected;
-	struct wait_queue *wait;
-	int	wanted;
-	int	timeout_pending;
-};
-
-struct swim_iop_req {
-	int	sent;
-	int	complete;
-	__u8	command[32];
-	struct floppy_state *fs;
-	void	(*done)(struct swim_iop_req *);
-};
-
-static struct swim_iop_req *current_req;
-static int floppy_count;
-
-static struct floppy_state floppy_states[MAX_FLOPPIES];
-static DEFINE_SPINLOCK(swim_iop_lock);
-
-#define CURRENT elv_next_request(swim_queue)
-
-static char *drive_names[7] = {
-	"not installed",	/* DRV_NONE    */
-	"unknown (1)",		/* DRV_UNKNOWN */
-	"a 400K drive",		/* DRV_400K    */
-	"an 800K drive"		/* DRV_800K    */
-	"unknown (4)",		/* ????        */
-	"an FDHD",		/* DRV_FDHD    */
-	"unknown (6)",		/* ????        */
-	"an Apple HD20"		/* DRV_HD20    */
-};
-
-int swimiop_init(void);
-static void swimiop_init_request(struct swim_iop_req *);
-static int swimiop_send_request(struct swim_iop_req *);
-static void swimiop_receive(struct iop_msg *);
-static void swimiop_status_update(int, struct swim_drvstatus *);
-static int swimiop_eject(struct floppy_state *fs);
-
-static int floppy_ioctl(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long param);
-static int floppy_open(struct inode *inode, struct file *filp);
-static int floppy_release(struct inode *inode, struct file *filp);
-static int floppy_check_change(struct gendisk *disk);
-static int floppy_revalidate(struct gendisk *disk);
-static int grab_drive(struct floppy_state *fs, enum swim_state state,
-		      int interruptible);
-static void release_drive(struct floppy_state *fs);
-static void set_timeout(struct floppy_state *fs, int nticks,
-			void (*proc)(unsigned long));
-static void fd_request_timeout(unsigned long);
-static void do_fd_request(request_queue_t * q);
-static void start_request(struct floppy_state *fs);
-
-static struct block_device_operations floppy_fops = {
-	.open		= floppy_open,
-	.release	= floppy_release,
-	.ioctl		= floppy_ioctl,
-	.media_changed	= floppy_check_change,
-	.revalidate_disk= floppy_revalidate,
-};
-
-static struct request_queue *swim_queue;
-/*
- * SWIM IOP initialization
- */
-
-int swimiop_init(void)
-{
-	volatile struct swim_iop_req req;
-	struct swimcmd_status *cmd = (struct swimcmd_status *) &req.command[0];
-	struct swim_drvstatus *ds = &cmd->status;
-	struct floppy_state *fs;
-	int i;
-
-	current_req = NULL;
-	floppy_count = 0;
-
-	if (!iop_ism_present)
-		return -ENODEV;
-
-	if (register_blkdev(FLOPPY_MAJOR, "fd"))
-		return -EBUSY;
-
-	swim_queue = blk_init_queue(do_fd_request, &swim_iop_lock);
-	if (!swim_queue) {
-		unregister_blkdev(FLOPPY_MAJOR, "fd");
-		return -ENOMEM;
-	}
-
-	printk("SWIM-IOP: %s by Joshua M. Thompson (funaho@jurai.org)\n",
-		DRIVER_VERSION);
-
-	if (iop_listen(SWIM_IOP, SWIM_CHAN, swimiop_receive, "SWIM") != 0) {
-		printk(KERN_ERR "SWIM-IOP: IOP channel already in use; can't initialize.\n");
-		unregister_blkdev(FLOPPY_MAJOR, "fd");
-		blk_cleanup_queue(swim_queue);
-		return -EBUSY;
-	}
-
-	printk(KERN_ERR "SWIM_IOP: probing for installed drives.\n");
-
-	for (i = 0 ; i < MAX_FLOPPIES ; i++) {
-		memset(&floppy_states[i], 0, sizeof(struct floppy_state));
-		fs = &floppy_states[floppy_count];
-
-		swimiop_init_request(&req);
-		cmd->code = CMD_STATUS;
-		cmd->drive_num = i + 1;
-		if (swimiop_send_request(&req) != 0) continue;
-		while (!req.complete);
-		if (cmd->error != 0) {
-			printk(KERN_ERR "SWIM-IOP: probe on drive %d returned error %d\n", i, (uint) cmd->error);
-			continue;
-		}
-		if (ds->installed != 0x01) continue;
-		printk("SWIM-IOP: drive %d is %s (%s, %s, %s, %s)\n", i,
-			drive_names[ds->info.type],
-			ds->info.external? "ext" : "int",
-			ds->info.scsi? "scsi" : "floppy",
-			ds->info.fixed? "fixed" : "removable",
-			ds->info.secondary? "secondary" : "primary");
-		swimiop_status_update(floppy_count, ds);
-		fs->state = idle;
-
-		init_timer(&fs->timeout);
-		floppy_count++;
-	}
-	printk("SWIM-IOP: detected %d installed drives.\n", floppy_count);
-
-	for (i = 0; i < floppy_count; i++) {
-		struct gendisk *disk = alloc_disk(1);
-		if (!disk)
-			continue;
-		disk->major = FLOPPY_MAJOR;
-		disk->first_minor = i;
-		disk->fops = &floppy_fops;
-		sprintf(disk->disk_name, "fd%d", i);
-		disk->private_data = &floppy_states[i];
-		disk->queue = swim_queue;
-		set_capacity(disk, 2880 * 2);
-		add_disk(disk);
-	}
-
-	return 0;
-}
-
-static void swimiop_init_request(struct swim_iop_req *req)
-{
-	req->sent = 0;
-	req->complete = 0;
-	req->done = NULL;
-}
-
-static int swimiop_send_request(struct swim_iop_req *req)
-{
-	unsigned long flags;
-	int err;
-
-	/* It's doubtful an interrupt routine would try to send */
-	/* a SWIM request, but I'd rather play it safe here.    */
-
-	local_irq_save(flags);
-
-	if (current_req != NULL) {
-		local_irq_restore(flags);
-		return -ENOMEM;
-	}
-
-	current_req = req;
-
-	/* Interrupts should be back on for iop_send_message() */
-
-	local_irq_restore(flags);
-
-	err = iop_send_message(SWIM_IOP, SWIM_CHAN, (void *) req,
-				sizeof(req->command), (__u8 *) &req->command[0],
-				swimiop_receive);
-
-	/* No race condition here; we own current_req at this point */
-
-	if (err) {
-		current_req = NULL;
-	} else {
-		req->sent = 1;
-	}
-	return err;
-}
-
-/*
- * Receive a SWIM message from the IOP.
- *
- * This will be called in two cases:
- *
- * 1. A message has been successfully sent to the IOP.
- * 2. An unsolicited message was received from the IOP.
- */
-
-void swimiop_receive(struct iop_msg *msg)
-{
-	struct swim_iop_req *req;
-	struct swimmsg_status *sm;
-	struct swim_drvstatus *ds;
-
-	req = current_req;
-
-	switch(msg->status) {
-		case IOP_MSGSTATUS_COMPLETE:
-			memcpy(&req->command[0], &msg->reply[0], sizeof(req->command));
-			req->complete = 1;
-			if (req->done) (*req->done)(req);
-			current_req = NULL;
-			break;
-		case IOP_MSGSTATUS_UNSOL:
-			sm = (struct swimmsg_status *) &msg->message[0];
-			ds = &sm->status;
-			swimiop_status_update(sm->drive_num, ds);
-			iop_complete_message(msg);
-			break;
-	}
-}
-
-static void swimiop_status_update(int drive_num, struct swim_drvstatus *ds)
-{
-	struct floppy_state *fs = &floppy_states[drive_num];
-
-	fs->write_prot = (ds->write_prot == 0x80);
-	if ((ds->disk_in_drive != 0x01) && (ds->disk_in_drive != 0x02)) {
-		fs->ejected = 1;
-	} else {
-		fs->ejected = 0;
-	}
-	switch(ds->info.type) {
-		case DRV_400K:
-			fs->secpercyl = 10;
-			fs->secpertrack = 10;
-			fs->total_secs = 800;
-			break;
-		case DRV_800K:
-			fs->secpercyl = 20;
-			fs->secpertrack = 10;
-			fs->total_secs = 1600;
-			break;
-		case DRV_FDHD:
-			fs->secpercyl = 36;
-			fs->secpertrack = 18;
-			fs->total_secs = 2880;
-			break;
-		default:
-			fs->secpercyl = 0;
-			fs->secpertrack = 0;
-			fs->total_secs = 0;
-			break;
-	}
-}
-
-static int swimiop_eject(struct floppy_state *fs)
-{
-	int err, n;
-	struct swim_iop_req req;
-	struct swimcmd_eject *cmd = (struct swimcmd_eject *) &req.command[0];
-
-	err = grab_drive(fs, ejecting, 1);
-	if (err) return err;
-
-	swimiop_init_request(&req);
-	cmd->code = CMD_EJECT;
-	cmd->drive_num = fs->drive_num;
-	err = swimiop_send_request(&req);
-	if (err) {
-		release_drive(fs);
-		return err;
-	}
-	for (n = 2*HZ; n > 0; --n) {
-		if (req.complete) break;
-		if (signal_pending(current)) {
-			err = -EINTR;
-			break;
-		}
-		schedule_timeout_interruptible(1);
-	}
-	release_drive(fs);
-	return cmd->error;
-}
-
-static struct floppy_struct floppy_type =
-	{ 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL };	/*  7 1.44MB 3.5"   */
-
-static int floppy_ioctl(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long param)
-{
-	struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
-	int err;
-
-	if ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
-	switch (cmd) {
-	case FDEJECT:
-		if (fs->ref_count != 1)
-			return -EBUSY;
-		err = swimiop_eject(fs);
-		return err;
-	case FDGETPRM:
-	        if (copy_to_user((void *) param, (void *) &floppy_type,
-				 sizeof(struct floppy_struct)))
-			return -EFAULT;
-		return 0;
-	}
-	return -ENOTTY;
-}
-
-static int floppy_open(struct inode *inode, struct file *filp)
-{
-	struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
-
-	if (fs->ref_count == -1 || filp->f_flags & O_EXCL)
-		return -EBUSY;
-
-	if ((filp->f_flags & O_NDELAY) == 0 && (filp->f_mode & 3)) {
-		check_disk_change(inode->i_bdev);
-		if (fs->ejected)
-			return -ENXIO;
-	}
-
-	if ((filp->f_mode & 2) && fs->write_prot)
-		return -EROFS;
-
-	if (filp->f_flags & O_EXCL)
-		fs->ref_count = -1;
-	else
-		++fs->ref_count;
-
-	return 0;
-}
-
-static int floppy_release(struct inode *inode, struct file *filp)
-{
-	struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
-	if (fs->ref_count > 0)
-		fs->ref_count--;
-	return 0;
-}
-
-static int floppy_check_change(struct gendisk *disk)
-{
-	struct floppy_state *fs = disk->private_data;
-	return fs->ejected;
-}
-
-static int floppy_revalidate(struct gendisk *disk)
-{
-	struct floppy_state *fs = disk->private_data;
-	grab_drive(fs, revalidating, 0);
-	/* yadda, yadda */
-	release_drive(fs);
-	return 0;
-}
-
-static void floppy_off(unsigned int nr)
-{
-}
-
-static int grab_drive(struct floppy_state *fs, enum swim_state state,
-		      int interruptible)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	if (fs->state != idle) {
-		++fs->wanted;
-		while (fs->state != available) {
-			if (interruptible && signal_pending(current)) {
-				--fs->wanted;
-				local_irq_restore(flags);
-				return -EINTR;
-			}
-			interruptible_sleep_on(&fs->wait);
-		}
-		--fs->wanted;
-	}
-	fs->state = state;
-	local_irq_restore(flags);
-	return 0;
-}
-
-static void release_drive(struct floppy_state *fs)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	fs->state = idle;
-	start_request(fs);
-	local_irq_restore(flags);
-}
-
-static void set_timeout(struct floppy_state *fs, int nticks,
-			void (*proc)(unsigned long))
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	if (fs->timeout_pending)
-		del_timer(&fs->timeout);
-	init_timer(&fs->timeout);
-	fs->timeout.expires = jiffies + nticks;
-	fs->timeout.function = proc;
-	fs->timeout.data = (unsigned long) fs;
-	add_timer(&fs->timeout);
-	fs->timeout_pending = 1;
-	local_irq_restore(flags);
-}
-
-static void do_fd_request(request_queue_t * q)
-{
-	int i;
-
-	for (i = 0 ; i < floppy_count ; i++) {
-		start_request(&floppy_states[i]);
-	}
-}
-
-static void fd_request_complete(struct swim_iop_req *req)
-{
-	struct floppy_state *fs = req->fs;
-	struct swimcmd_rw *cmd = (struct swimcmd_rw *) &req->command[0];
-
-	del_timer(&fs->timeout);
-	fs->timeout_pending = 0;
-	fs->state = idle;
-	if (cmd->error) {
-		printk(KERN_ERR "SWIM-IOP: error %d on read/write request.\n", cmd->error);
-		end_request(CURRENT, 0);
-	} else {
-		CURRENT->sector += cmd->num_blocks;
-		CURRENT->current_nr_sectors -= cmd->num_blocks;
-		if (CURRENT->current_nr_sectors <= 0) {
-			end_request(CURRENT, 1);
-			return;
-		}
-	}
-	start_request(fs);
-}
-
-static void fd_request_timeout(unsigned long data)
-{
-	struct floppy_state *fs = (struct floppy_state *) data;
-
-	fs->timeout_pending = 0;
-	end_request(CURRENT, 0);
-	fs->state = idle;
-}
-
-static void start_request(struct floppy_state *fs)
-{
-	volatile struct swim_iop_req req;
-	struct swimcmd_rw *cmd = (struct swimcmd_rw *) &req.command[0];
-
-	if (fs->state == idle && fs->wanted) {
-		fs->state = available;
-		wake_up(&fs->wait);
-		return;
-	}
-	while (CURRENT && fs->state == idle) {
-		if (CURRENT->bh && !buffer_locked(CURRENT->bh))
-			panic("floppy: block not locked");
-#if 0
-		printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n",
-		       CURRENT->rq_disk->disk_name, CURRENT->cmd,
-		       CURRENT->sector, CURRENT->nr_sectors, CURRENT->buffer);
-		printk("           errors=%d current_nr_sectors=%ld\n",
-		      CURRENT->errors, CURRENT->current_nr_sectors);
-#endif
-
-		if (CURRENT->sector < 0 || CURRENT->sector >= fs->total_secs) {
-			end_request(CURRENT, 0);
-			continue;
-		}
-		if (CURRENT->current_nr_sectors == 0) {
-			end_request(CURRENT, 1);
-			continue;
-		}
-		if (fs->ejected) {
-			end_request(CURRENT, 0);
-			continue;
-		}
-
-		swimiop_init_request(&req);
-		req.fs = fs;
-		req.done = fd_request_complete;
-
-		if (CURRENT->cmd == WRITE) {
-			if (fs->write_prot) {
-				end_request(CURRENT, 0);
-				continue;
-			}
-			cmd->code = CMD_WRITE;
-		} else {
-			cmd->code = CMD_READ;
-
-		}
-		cmd->drive_num = fs->drive_num;
-		cmd->buffer = CURRENT->buffer;
-		cmd->first_block = CURRENT->sector;
-		cmd->num_blocks = CURRENT->current_nr_sectors;
-
-		if (swimiop_send_request(&req)) {
-			end_request(CURRENT, 0);
-			continue;
-		}
-
-		set_timeout(fs, HZ*CURRENT->current_nr_sectors,
-				fd_request_timeout);
-
-		fs->state = transferring;
-	}
-}
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 2df5cf4..e4a2f8f 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -1810,7 +1810,7 @@
 
 	size = sizeof(s->disckey.value) + 4;
 
-	if ((buf = (u_char *) kmalloc(size, GFP_KERNEL)) == NULL)
+	if ((buf = kmalloc(size, GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 
 	init_cdrom_command(&cgc, buf, size, CGC_DATA_READ);
@@ -1861,7 +1861,7 @@
 
 	size = sizeof(s->manufact.value) + 4;
 
-	if ((buf = (u_char *) kmalloc(size, GFP_KERNEL)) == NULL)
+	if ((buf = kmalloc(size, GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 
 	init_cdrom_command(&cgc, buf, size, CGC_DATA_READ);
@@ -2849,7 +2849,7 @@
 		/* FIXME: we need upper bound checking, too!! */
 		if (lba < 0)
 			return -EINVAL;
-		cgc.buffer = (char *) kmalloc(blocksize, GFP_KERNEL);
+		cgc.buffer = kmalloc(blocksize, GFP_KERNEL);
 		if (cgc.buffer == NULL)
 			return -ENOMEM;
 		memset(&sense, 0, sizeof(sense));
@@ -3031,7 +3031,7 @@
 		int size = sizeof(dvd_struct);
 		if (!CDROM_CAN(CDC_DVD))
 			return -ENOSYS;
-		if ((s = (dvd_struct *) kmalloc(size, GFP_KERNEL)) == NULL)
+		if ((s = kmalloc(size, GFP_KERNEL)) == NULL)
 			return -ENOMEM;
 		cdinfo(CD_DO_IOCTL, "entering DVD_READ_STRUCT\n"); 
 		if (copy_from_user(s, (dvd_struct __user *)arg, size)) {
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
index e6d8e9e..b6c61bb 100644
--- a/drivers/cdrom/cm206.c
+++ b/drivers/cdrom/cm206.c
@@ -1420,7 +1420,7 @@
 		return -EIO;
 	}
 	printk(" adapter at 0x%x", cm206_base);
-	cd = (struct cm206_struct *) kmalloc(size, GFP_KERNEL);
+	cd = kmalloc(size, GFP_KERNEL);
 	if (!cd)
                goto out_base;
 	/* Now we have found the adaptor card, try to reset it. As we have
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 0a3aee2..9e43e39 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -97,7 +97,7 @@
 
 config COMPUTONE
 	tristate "Computone IntelliPort Plus serial support"
-	depends on SERIAL_NONSTANDARD
+	depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
 	---help---
 	  This driver supports the entire family of Intelliport II/Plus
 	  controllers with the exception of the MicroChannel controllers and
@@ -203,7 +203,7 @@
 
 config MOXA_SMARTIO_NEW
 	tristate "Moxa SmartIO support v. 2.0 (EXPERIMENTAL)"
-	depends on SERIAL_NONSTANDARD
+	depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA)
 	help
 	  Say Y here if you have a Moxa SmartIO multiport serial card and/or
 	  want to help develop a new version of this driver.
@@ -218,7 +218,7 @@
 
 config ISI
 	tristate "Multi-Tech multiport card support (EXPERIMENTAL)"
-	depends on SERIAL_NONSTANDARD
+	depends on SERIAL_NONSTANDARD && PCI
 	select FW_LOADER
 	help
 	  This is a driver for the Multi-Tech cards which provide several
@@ -312,7 +312,7 @@
 
 config SX
 	tristate "Specialix SX (and SI) card support"
-	depends on SERIAL_NONSTANDARD
+	depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA)
 	help
 	  This is a driver for the SX and SI multiport serial cards.
 	  Please read the file <file:Documentation/sx.txt> for details.
diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c
index 04a1202..b99b756 100644
--- a/drivers/char/consolemap.c
+++ b/drivers/char/consolemap.c
@@ -443,7 +443,7 @@
 	p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
 	if (p && p->readonly) return -EIO;
 	if (!p || --p->refcount) {
-		q = (struct uni_pagedir *)kmalloc(sizeof(*p), GFP_KERNEL);
+		q = kmalloc(sizeof(*p), GFP_KERNEL);
 		if (!q) {
 			if (p) p->refcount++;
 			return -ENOMEM;
diff --git a/drivers/char/lcd.c b/drivers/char/lcd.c
index da601fd..d649abb 100644
--- a/drivers/char/lcd.c
+++ b/drivers/char/lcd.c
@@ -459,7 +459,7 @@
 			    (&display, (struct lcd_display *) arg,
 			     sizeof(struct lcd_display)))
 				return -EFAULT;
-			rom = (unsigned char *) kmalloc((128), GFP_ATOMIC);
+			rom = kmalloc((128), GFP_ATOMIC);
 			if (rom == NULL) {
 				printk(KERN_ERR LCD "kmalloc() failed in %s\n",
 						__FUNCTION__);
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index b70b538..b51d08b 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -525,7 +525,7 @@
 			return -EIO;
 		}
 	}
-	lp_table[minor].lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL);
+	lp_table[minor].lp_buffer = kmalloc(LP_BUFFER_SIZE, GFP_KERNEL);
 	if (!lp_table[minor].lp_buffer) {
 		LP_F(minor) &= ~LP_BUSY;
 		return -ENOMEM;
diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c
index efa8076..cd989dc 100644
--- a/drivers/char/mxser_new.c
+++ b/drivers/char/mxser_new.c
@@ -315,6 +315,7 @@
 static int mxser_set_baud_method[MXSER_PORTS + 1];
 static spinlock_t gm_lock;
 
+#ifdef CONFIG_PCI
 static int CheckIsMoxaMust(int io)
 {
 	u8 oldmcr, hwid;
@@ -337,6 +338,7 @@
 	}
 	return MOXA_OTHER_UART;
 }
+#endif
 
 static void process_txrx_fifo(struct mxser_port *info)
 {
@@ -2380,9 +2382,11 @@
 	if (irq)
 		free_irq(brd->irq, brd);
 	if (pdev != NULL) {	/* PCI */
+#ifdef CONFIG_PCI
 		pci_release_region(pdev, 2);
 		pci_release_region(pdev, 3);
 		pci_dev_put(pdev);
+#endif
 	} else {
 		release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
 		release_region(brd->vector, 1);
@@ -2546,6 +2550,7 @@
 static int __devinit mxser_probe(struct pci_dev *pdev,
 		const struct pci_device_id *ent)
 {
+#ifdef CONFIG_PCI
 	struct mxser_board *brd;
 	unsigned int i, j;
 	unsigned long ioaddress;
@@ -2644,6 +2649,9 @@
 	brd->info = NULL;
 err:
 	return retval;
+#else
+	return -ENODEV;
+#endif
 }
 
 static void __devexit mxser_remove(struct pci_dev *pdev)
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index 103d338..dc6d418 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -125,8 +125,8 @@
 static void receive_char(struct r3964_info *pInfo, const unsigned char c);
 static void receive_error(struct r3964_info *pInfo, const char flag);
 static void on_timeout(unsigned long priv);
-static int enable_signals(struct r3964_info *pInfo, pid_t pid, int arg);
-static int read_telegram(struct r3964_info *pInfo, pid_t pid, unsigned char __user *buf);
+static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg);
+static int read_telegram(struct r3964_info *pInfo, struct pid *pid, unsigned char __user *buf);
 static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg,
              int error_code, struct r3964_block_header *pBlock);
 static struct r3964_message* remove_msg(struct r3964_info *pInfo, 
@@ -829,7 +829,7 @@
 }
 
 static struct r3964_client_info *findClient(
-  struct r3964_info *pInfo, pid_t pid)
+  struct r3964_info *pInfo, struct pid *pid)
 {
    struct r3964_client_info *pClient;
    
@@ -843,7 +843,7 @@
    return NULL;
 }
 
-static int enable_signals(struct r3964_info *pInfo, pid_t pid, int arg)
+static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg)
 {
    struct r3964_client_info *pClient;
    struct r3964_client_info **ppClient;
@@ -858,7 +858,7 @@
          
          if(pClient->pid == pid)
          {
-            TRACE_PS("removing client %d from client list", pid);
+            TRACE_PS("removing client %d from client list", pid_nr(pid));
             *ppClient = pClient->next;
             while(pClient->msg_count)
             {
@@ -869,6 +869,7 @@
                   TRACE_M("enable_signals - msg kfree %p",pMsg);
                }
             }
+	    put_pid(pClient->pid);
             kfree(pClient);
             TRACE_M("enable_signals - kfree %p",pClient);
             return 0;
@@ -892,10 +893,10 @@
          if(pClient==NULL)
             return -ENOMEM;
 
-         TRACE_PS("add client %d to client list", pid);
+         TRACE_PS("add client %d to client list", pid_nr(pid));
 	 spin_lock_init(&pClient->lock);
          pClient->sig_flags=arg;
-         pClient->pid = pid;
+         pClient->pid = get_pid(pid);
          pClient->next=pInfo->firstClient;
          pClient->first_msg = NULL;
          pClient->last_msg = NULL;
@@ -908,7 +909,7 @@
    return 0;
 }
 
-static int read_telegram(struct r3964_info *pInfo, pid_t pid, unsigned char __user *buf)
+static int read_telegram(struct r3964_info *pInfo, struct pid *pid, unsigned char __user *buf)
 {
     struct r3964_client_info *pClient;
     struct r3964_block_header *block;
@@ -1005,7 +1006,7 @@
    /* Send SIGIO signal to client process: */
    if(pClient->sig_flags & R3964_USE_SIGIO)
    {
-      kill_proc(pClient->pid, SIGIO, 1);
+      kill_pid(pClient->pid, SIGIO, 1);
    }
 }
 
@@ -1042,7 +1043,7 @@
 {
     struct r3964_block_header *block;
 
-    TRACE_PS("remove_client_block PID %d", pClient->pid);
+    TRACE_PS("remove_client_block PID %d", pid_nr(pClient->pid));
 
     block=pClient->next_block_to_read;
     if(block)
@@ -1157,6 +1158,7 @@
              TRACE_M("r3964_close - msg kfree %p",pMsg);
           }
        }
+       put_pid(pClient->pid);
        kfree(pClient);
        TRACE_M("r3964_close - client kfree %p",pClient);
        pClient=pNext;
@@ -1193,12 +1195,11 @@
    struct r3964_client_message theMsg;
    DECLARE_WAITQUEUE (wait, current);
    
-   int pid = current->pid;
    int count;
    
    TRACE_L("read()");
  
-   pClient=findClient(pInfo, pid);
+   pClient=findClient(pInfo, task_pid(current));
    if(pClient)
    {
       pMsg = remove_msg(pInfo, pClient);
@@ -1252,7 +1253,6 @@
    struct r3964_block_header *pHeader;
    struct r3964_client_info *pClient;
    unsigned char *new_data;
-   int pid;
    
    TRACE_L("write request, %d characters", count);
 /* 
@@ -1295,9 +1295,7 @@
    pHeader->locks = 0;
    pHeader->owner = NULL;
    
-   pid=current->pid;
-   
-   pClient=findClient(pInfo, pid);
+   pClient=findClient(pInfo, task_pid(current));
    if(pClient)
    {
       pHeader->owner = pClient;
@@ -1328,7 +1326,7 @@
    switch(cmd)
    {
       case R3964_ENABLE_SIGNALS:
-         return enable_signals(pInfo, current->pid, arg);
+         return enable_signals(pInfo, task_pid(current), arg);
       case R3964_SETPRIORITY:
          if(arg<R3964_MASTER || arg>R3964_SLAVE)
             return -EINVAL;
@@ -1341,7 +1339,7 @@
             pInfo->flags &= ~R3964_BCC;
          return 0;
       case R3964_READ_TELEGRAM:
-         return read_telegram(pInfo, current->pid, (unsigned char __user *)arg);
+         return read_telegram(pInfo, task_pid(current), (unsigned char __user *)arg);
       default:
          return -ENOIOCTLCMD;
    }
@@ -1357,7 +1355,6 @@
 		      struct poll_table_struct *wait)
 {
    struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data;
-   int pid=current->pid;
    struct r3964_client_info *pClient;
    struct r3964_message *pMsg=NULL;
    unsigned long flags;
@@ -1365,7 +1362,7 @@
 
    TRACE_L("POLL");
 
-   pClient=findClient(pInfo,pid);
+   pClient=findClient(pInfo, task_pid(current));
    if(pClient)
      {
        poll_wait(file, &pInfo->read_wait, wait);
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index e96a00f..2bdb014 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -1151,7 +1151,6 @@
 	n = min(*nr, n);
 	spin_unlock_irqrestore(&tty->read_lock, flags);
 	if (n) {
-		mb();
 		retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
 		n -= retval;
 		spin_lock_irqsave(&tty->read_lock, flags);
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 5152ced..f108c13 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -541,7 +541,7 @@
     if (debug_level >= DEBUG_LEVEL_INFO)
 	    printk("mgslpc_attach\n");
 
-    info = (MGSLPC_INFO *)kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL);
+    info = kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL);
     if (!info) {
 	    printk("Error can't allocate device instance data\n");
 	    return -ENOMEM;
diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c
index 167ebc8..245f031 100644
--- a/drivers/char/rio/riocmd.c
+++ b/drivers/char/rio/riocmd.c
@@ -556,7 +556,7 @@
 {
 	struct CmdBlk *CmdBlkP;
 
-	CmdBlkP = (struct CmdBlk *)kmalloc(sizeof(struct CmdBlk), GFP_ATOMIC);
+	CmdBlkP = kmalloc(sizeof(struct CmdBlk), GFP_ATOMIC);
 	if (CmdBlkP)
 		memset(CmdBlkP, 0, sizeof(struct CmdBlk));
 	return CmdBlkP;
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index 66a7385..e1d70e8 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -113,7 +113,7 @@
 #define hpet_set_rtc_irq_bit(arg) 		0
 #define hpet_rtc_timer_init() 			do { } while (0)
 #define hpet_rtc_dropped_irq() 			0
-static inline irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) {return 0;}
+static irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) {return 0;}
 #else
 extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id);
 #endif
@@ -165,7 +165,9 @@
 }
 #endif
 
+#ifdef CONFIG_PROC_FS
 static int rtc_proc_open(struct inode *inode, struct file *file);
+#endif
 
 /*
  *	Bits in rtc_status. (6 bits of room for future expansion)
@@ -906,6 +908,7 @@
 	.fops		= &rtc_fops,
 };
 
+#ifdef CONFIG_PROC_FS
 static const struct file_operations rtc_proc_fops = {
 	.owner = THIS_MODULE,
 	.open = rtc_proc_open,
@@ -913,14 +916,13 @@
 	.llseek = seq_lseek,
 	.release = single_release,
 };
-
-#if defined(RTC_IRQ) && !defined(__sparc__)
-static irq_handler_t rtc_int_handler_ptr;
 #endif
 
 static int __init rtc_init(void)
 {
+#ifdef CONFIG_PROC_FS
 	struct proc_dir_entry *ent;
+#endif
 #if defined(__alpha__) || defined(__mips__)
 	unsigned int year, ctrl;
 	char *guess = NULL;
@@ -932,9 +934,11 @@
 	struct sparc_isa_bridge *isa_br;
 	struct sparc_isa_device *isa_dev;
 #endif
-#endif
-#ifndef __sparc__
+#else
 	void *r;
+#ifdef RTC_IRQ
+	irq_handler_t rtc_int_handler_ptr;
+#endif
 #endif
 
 #ifdef __sparc__
@@ -958,6 +962,7 @@
 		}
 	}
 #endif
+	rtc_has_irq = 0;
 	printk(KERN_ERR "rtc_init: no PC rtc found\n");
 	return -EIO;
 
@@ -972,6 +977,7 @@
 	 * PCI Slot 2 INTA# (and some INTx# in Slot 1).
 	 */
 	if (request_irq(rtc_irq, rtc_interrupt, IRQF_SHARED, "rtc", (void *)&rtc_port)) {
+		rtc_has_irq = 0;
 		printk(KERN_ERR "rtc: cannot register IRQ %d\n", rtc_irq);
 		return -EIO;
 	}
@@ -982,6 +988,9 @@
 	else
 		r = request_mem_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc");
 	if (!r) {
+#ifdef RTC_IRQ
+		rtc_has_irq = 0;
+#endif
 		printk(KERN_ERR "rtc: I/O resource %lx is not free.\n",
 		       (long)(RTC_PORT(0)));
 		return -EIO;
@@ -996,6 +1005,7 @@
 
 	if(request_irq(RTC_IRQ, rtc_int_handler_ptr, IRQF_DISABLED, "rtc", NULL)) {
 		/* Yeah right, seeing as irq 8 doesn't even hit the bus. */
+		rtc_has_irq = 0;
 		printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ);
 		if (RTC_IOMAPPED)
 			release_region(RTC_PORT(0), RTC_IO_EXTENT);
@@ -1012,21 +1022,19 @@
 	if (misc_register(&rtc_dev)) {
 #ifdef RTC_IRQ
 		free_irq(RTC_IRQ, NULL);
+		rtc_has_irq = 0;
 #endif
 		release_region(RTC_PORT(0), RTC_IO_EXTENT);
 		return -ENODEV;
 	}
 
+#ifdef CONFIG_PROC_FS
 	ent = create_proc_entry("driver/rtc", 0, NULL);
-	if (!ent) {
-#ifdef RTC_IRQ
-		free_irq(RTC_IRQ, NULL);
+	if (ent)
+		ent->proc_fops = &rtc_proc_fops;
+	else
+		printk(KERN_WARNING "rtc: Failed to register with procfs.\n");
 #endif
-		release_region(RTC_PORT(0), RTC_IO_EXTENT);
-		misc_deregister(&rtc_dev);
-		return -ENOMEM;
-	}
-	ent->proc_fops = &rtc_proc_fops;
 
 #if defined(__alpha__) || defined(__mips__)
 	rtc_freq = HZ;
@@ -1159,6 +1167,7 @@
 }
 #endif
 
+#ifdef CONFIG_PROC_FS
 /*
  *	Info exported via "/proc/driver/rtc".
  */
@@ -1243,6 +1252,7 @@
 {
 	return single_open(file, rtc_proc_show, NULL);
 }
+#endif
 
 void rtc_get_rtc_time(struct rtc_time *rtc_tm)
 {
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index a3008ce..1da92a6 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -2498,8 +2498,10 @@
 		/* It is safe/allowed to del_timer a non-active timer */
 		del_timer(&board->timer);
 		if (pdev) {
+#ifdef CONFIG_PCI
 			pci_iounmap(pdev, board->base);
 			pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2);
+#endif
 		} else {
 			iounmap(board->base);
 			release_region(board->hw_base, board->hw_len);
@@ -2601,6 +2603,7 @@
 
 #endif
 
+#ifdef CONFIG_PCI
  /******************************************************** 
  * Setting bit 17 in the CNTRL register of the PLX 9050  * 
  * chip forces a retry on writes while a read is pending.*
@@ -2632,10 +2635,12 @@
 	}
 	iounmap(rebase);
 }
+#endif
 
 static int __devinit sx_pci_probe(struct pci_dev *pdev,
 				  const struct pci_device_id *ent)
 {
+#ifdef CONFIG_PCI
 	struct sx_board *board;
 	unsigned int i, reg;
 	int retval = -EIO;
@@ -2700,6 +2705,9 @@
 	board->flags &= ~SX_BOARD_PRESENT;
 err:
 	return retval;
+#else
+	return -ENODEV;
+#endif
 }
 
 static void __devexit sx_pci_remove(struct pci_dev *pdev)
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index acc6fab..3fa625d 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -4332,7 +4332,7 @@
 {
 	struct mgsl_struct *info;
 	
-	info = (struct mgsl_struct *)kmalloc(sizeof(struct mgsl_struct),
+	info = kmalloc(sizeof(struct mgsl_struct),
 		 GFP_KERNEL);
 		 
 	if (!info) {
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index 53e8ccf..8f4d67a 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -2730,7 +2730,7 @@
 		return 0;
 
 	if (!info->tx_buf) {
-		info->tx_buf = (unsigned char *)kmalloc(info->max_frame_size, GFP_KERNEL);
+		info->tx_buf = kmalloc(info->max_frame_size, GFP_KERNEL);
 		if (!info->tx_buf) {
 			printk(KERN_ERR"%s(%d):%s can't allocate transmit buffer\n",
 				__FILE__,__LINE__,info->device_name);
@@ -3798,7 +3798,7 @@
 {
 	SLMP_INFO *info;
 
-	info = (SLMP_INFO *)kmalloc(sizeof(SLMP_INFO),
+	info = kmalloc(sizeof(SLMP_INFO),
 		 GFP_KERNEL);
 
 	if (!info) {
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 05810c8..1393523 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -41,7 +41,34 @@
 #include <asm/irq_regs.h>
 
 /* Whether we react on sysrq keys or just ignore them */
-int sysrq_enabled = 1;
+int __read_mostly __sysrq_enabled = 1;
+
+static int __read_mostly sysrq_always_enabled;
+
+int sysrq_on(void)
+{
+	return __sysrq_enabled || sysrq_always_enabled;
+}
+
+/*
+ * A value of 1 means 'all', other nonzero values are an op mask:
+ */
+static inline int sysrq_on_mask(int mask)
+{
+	return sysrq_always_enabled || __sysrq_enabled == 1 ||
+						(__sysrq_enabled & mask);
+}
+
+static int __init sysrq_always_enabled_setup(char *str)
+{
+	sysrq_always_enabled = 1;
+	printk(KERN_INFO "debug: sysrq always enabled.\n");
+
+	return 1;
+}
+
+__setup("sysrq_always_enabled", sysrq_always_enabled_setup);
+
 
 static void sysrq_handle_loglevel(int key, struct tty_struct *tty)
 {
@@ -379,8 +406,7 @@
 		 * Should we check for enabled operations (/proc/sysrq-trigger
 		 * should not) and is the invoked operation enabled?
 		 */
-		if (!check_mask || sysrq_enabled == 1 ||
-		    (sysrq_enabled & op_p->enable_mask)) {
+		if (!check_mask || sysrq_on_mask(op_p->enable_mask)) {
 			printk("%s\n", op_p->action_msg);
 			console_loglevel = orig_log_level;
 			op_p->handler(key, tty);
@@ -414,9 +440,8 @@
  */
 void handle_sysrq(int key, struct tty_struct *tty)
 {
-	if (!sysrq_enabled)
-		return;
-	__handle_sysrq(key, tty, 1);
+	if (sysrq_on())
+		__handle_sysrq(key, tty, 1);
 }
 EXPORT_SYMBOL(handle_sysrq);
 
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 4044c86..47a6eac 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -3335,18 +3335,13 @@
 	int session;
 	int		i;
 	struct file	*filp;
-	struct tty_ldisc *disc;
 	struct fdtable *fdt;
 	
 	if (!tty)
 		return;
 	session = tty->session;
 	
-	/* We don't want an ldisc switch during this */
-	disc = tty_ldisc_ref(tty);
-	if (disc && disc->flush_buffer)
-		disc->flush_buffer(tty);
-	tty_ldisc_deref(disc);
+	tty_ldisc_flush(tty);
 
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
@@ -3821,6 +3816,7 @@
 	barrier();
 	return tty;
 }
+EXPORT_SYMBOL_GPL(get_current_tty);
 
 /*
  * Initialize the console device. This is called *early*, so
diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c
index 6d2e314..0e0da44 100644
--- a/drivers/char/viocons.c
+++ b/drivers/char/viocons.c
@@ -61,10 +61,7 @@
 static DEFINE_SPINLOCK(consolelock);
 static DEFINE_SPINLOCK(consoleloglock);
 
-#ifdef CONFIG_MAGIC_SYSRQ
 static int vio_sysrq_pressed;
-extern int sysrq_enabled;
-#endif
 
 #define VIOCHAR_NUM_BUF		16
 
@@ -936,8 +933,10 @@
 	 */
 	num_pushed = 0;
 	for (index = 0; index < cevent->len; index++) {
-#ifdef CONFIG_MAGIC_SYSRQ
-		if (sysrq_enabled) {
+		/*
+		 * Will be optimized away if !CONFIG_MAGIC_SYSRQ:
+		 */
+		if (sysrq_on()) {
 			/* 0x0f is the ascii character for ^O */
 			if (cevent->data[index] == '\x0f') {
 				vio_sysrq_pressed = 1;
@@ -956,7 +955,6 @@
 				continue;
 			}
 		}
-#endif
 		/*
 		 * The sysrq sequence isn't included in this check if
 		 * sysrq is enabled and compiled into the kernel because
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index a8239da..06c32a3 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -784,7 +784,7 @@
 	if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
 		return 0;
 
-	newscreen = (unsigned short *) kmalloc(new_screen_size, GFP_USER);
+	newscreen = kmalloc(new_screen_size, GFP_USER);
 	if (!newscreen)
 		return -ENOMEM;
 
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index ac5d60e..dc8368e 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -129,7 +129,7 @@
 			    !capable(CAP_SYS_RESOURCE))
 				return -EPERM;
 
-			key_map = (ushort *) kmalloc(sizeof(plain_map),
+			key_map = kmalloc(sizeof(plain_map),
 						     GFP_KERNEL);
 			if (!key_map)
 				return -ENOMEM;
@@ -259,7 +259,7 @@
 		    sz = 256;
 		    while (sz < funcbufsize - funcbufleft + delta)
 		      sz <<= 1;
-		    fnw = (char *) kmalloc(sz, GFP_KERNEL);
+		    fnw = kmalloc(sz, GFP_KERNEL);
 		    if(!fnw) {
 		      ret = -ENOMEM;
 		      goto reterr;
@@ -1087,7 +1087,7 @@
 	switch_screen(vc);
 
 	/*
-	 * This can't appear below a successful kill_proc().  If it did,
+	 * This can't appear below a successful kill_pid().  If it did,
 	 * then the *blank_screen operation could occur while X, having
 	 * received acqsig, is waking up on another processor.  This
 	 * condition can lead to overlapping accesses to the VGA range
@@ -1110,7 +1110,7 @@
 	 */
 	if (vc->vt_mode.mode == VT_PROCESS) {
 		/*
-		 * Send the signal as privileged - kill_proc() will
+		 * Send the signal as privileged - kill_pid() will
 		 * tell us if the process has gone or something else
 		 * is awry
 		 */
@@ -1170,7 +1170,7 @@
 	vc = vc_cons[fg_console].d;
 	if (vc->vt_mode.mode == VT_PROCESS) {
 		/*
-		 * Send the signal as privileged - kill_proc() will
+		 * Send the signal as privileged - kill_pid() will
 		 * tell us if the process has gone or something else
 		 * is awry
 		 */
diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c
index ca4e67a..22b62b3 100644
--- a/drivers/fc4/fc.c
+++ b/drivers/fc4/fc.c
@@ -266,7 +266,7 @@
 			printk ("FC: Bad magic from REPORT_AL_MAP on %s - %08x\n", fc->name, p->magic);
 			fc->state = FC_STATE_OFFLINE;
 		} else {
-			fc->posmap = (fcp_posmap *)kzalloc(sizeof(fcp_posmap)+p->len, GFP_KERNEL);
+			fc->posmap = kzalloc(sizeof(fcp_posmap)+p->len, GFP_KERNEL);
 			if (!fc->posmap) {
 				printk("FC: Not enough memory, offlining channel\n");
 				fc->state = FC_STATE_OFFLINE;
@@ -355,7 +355,7 @@
 			for (i = fc->can_queue; i < fc->scsi_bitmap_end; i++)
 				set_bit (i, fc->scsi_bitmap);
 			fc->scsi_free = fc->can_queue;
-			fc->cmd_slots = (fcp_cmnd **)kzalloc(slots * sizeof(fcp_cmnd*), GFP_KERNEL);
+			fc->cmd_slots = kzalloc(slots * sizeof(fcp_cmnd*), GFP_KERNEL);
 			fc->abort_count = 0;
 		} else {
 			fc->scsi_name[0] = 0;
@@ -933,7 +933,7 @@
         DECLARE_MUTEX_LOCKED(sem);
 
 	if (!fc->rst_pkt) {
-		fc->rst_pkt = (struct scsi_cmnd *) kmalloc(sizeof(SCpnt), GFP_KERNEL);
+		fc->rst_pkt = kmalloc(sizeof(SCpnt), GFP_KERNEL);
 		if (!fc->rst_pkt) return FAILED;
 		
 		fcmd = FCP_CMND(fc->rst_pkt);
@@ -1107,7 +1107,7 @@
 	logi *l;
 	int status;
 
-	l = (logi *)kzalloc(2 * sizeof(logi), GFP_KERNEL);
+	l = kzalloc(2 * sizeof(logi), GFP_KERNEL);
 	if (!l) return -ENOMEM;
 	l->code = LS_PLOGI;
 	memcpy (&l->nport_wwn, &fc->wwn_nport, sizeof(fc_wwn));
@@ -1141,7 +1141,7 @@
 	prli *p;
 	int status;
 
-	p = (prli *)kzalloc(2 * sizeof(prli), GFP_KERNEL);
+	p = kzalloc(2 * sizeof(prli), GFP_KERNEL);
 	if (!p) return -ENOMEM;
 	p->code = LS_PRLI;
 	p->params[0] = 0x08002000;
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index e76d919..891ef6d 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -106,6 +106,31 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called k8temp.
 
+config SENSORS_AMS
+	tristate "Apple Motion Sensor driver"
+	depends on HWMON && PPC_PMAC && !PPC64 && INPUT && ((ADB_PMU && I2C = y) || (ADB_PMU && !I2C) || I2C) && EXPERIMENTAL
+	help
+	  Support for the motion sensor included in PowerBooks. Includes
+	  implementations for PMU and I2C.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called ams.
+
+config SENSORS_AMS_PMU
+	bool "PMU variant"
+	depends on SENSORS_AMS && ADB_PMU
+	default y
+	help
+	  PMU variant of motion sensor, found in late 2005 PowerBooks.
+
+config SENSORS_AMS_I2C
+	bool "I2C variant"
+	depends on SENSORS_AMS && I2C
+	default y
+	help
+	  I2C variant of motion sensor, found in early 2005 PowerBooks and
+	  iBooks.
+
 config SENSORS_ASB100
 	tristate "Asus ASB100 Bach"
 	depends on HWMON && I2C && EXPERIMENTAL
@@ -142,11 +167,12 @@
 	  will be called ds1621.
 
 config SENSORS_F71805F
-	tristate "Fintek F71805F/FG"
+	tristate "Fintek F71805F/FG and F71872F/FG"
 	depends on HWMON && EXPERIMENTAL
 	help
 	  If you say yes here you get support for hardware monitoring
-	  features of the Fintek F71805F/FG chips.
+	  features of the Fintek F71805F/FG and F71872F/FG Super-I/O
+	  chips.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called f71805f.
@@ -353,6 +379,19 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called pc87360.
 
+config SENSORS_PC87427
+	tristate "National Semiconductor PC87427"
+	depends on HWMON && EXPERIMENTAL
+	help
+	  If you say yes here you get access to the hardware monitoring
+	  functions of the National Semiconductor PC87427 Super-I/O chip.
+	  The chip has two distinct logical devices, one for fan speed
+	  monitoring and control, and one for voltage and temperature
+	  monitoring. Only fan speed monitoring is supported right now.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called pc87427.
+
 config SENSORS_SIS5595
 	tristate "Silicon Integrated Systems Corp. SiS5595"
 	depends on HWMON && I2C && PCI && EXPERIMENTAL
@@ -474,6 +513,16 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called w83792d.
 
+config SENSORS_W83793
+	tristate "Winbond W83793"
+	depends on HWMON && I2C && EXPERIMENTAL
+	help
+	  If you say yes here you get support for the Winbond W83793
+	  hardware monitoring chip.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called w83793.
+
 config SENSORS_W83L785TS
 	tristate "Winbond W83L785TS-S"
 	depends on HWMON && I2C && EXPERIMENTAL
@@ -527,6 +576,9 @@
 	  This driver also provides an absolute input class device, allowing
 	  the laptop to act as a pinball machine-esque joystick.
 
+	  If your ThinkPad is not recognized by the driver, please update to latest
+	  BIOS. This is especially the case for some R52 ThinkPads.
+
 	  Say Y here if you have an applicable laptop and want to experience
 	  the awesome power of hdaps.
 
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index af01cc6..3166112 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -9,6 +9,7 @@
 obj-$(CONFIG_SENSORS_ASB100)	+= asb100.o
 obj-$(CONFIG_SENSORS_W83627HF)	+= w83627hf.o
 obj-$(CONFIG_SENSORS_W83792D)	+= w83792d.o
+obj-$(CONFIG_SENSORS_W83793)	+= w83793.o
 obj-$(CONFIG_SENSORS_W83781D)	+= w83781d.o
 obj-$(CONFIG_SENSORS_W83791D)	+= w83791d.o
 
@@ -18,6 +19,7 @@
 obj-$(CONFIG_SENSORS_ADM1026)	+= adm1026.o
 obj-$(CONFIG_SENSORS_ADM1031)	+= adm1031.o
 obj-$(CONFIG_SENSORS_ADM9240)	+= adm9240.o
+obj-$(CONFIG_SENSORS_AMS)	+= ams/
 obj-$(CONFIG_SENSORS_ATXP1)	+= atxp1.o
 obj-$(CONFIG_SENSORS_DS1621)	+= ds1621.o
 obj-$(CONFIG_SENSORS_F71805F)	+= f71805f.o
@@ -41,6 +43,7 @@
 obj-$(CONFIG_SENSORS_LM92)	+= lm92.o
 obj-$(CONFIG_SENSORS_MAX1619)	+= max1619.o
 obj-$(CONFIG_SENSORS_PC87360)	+= pc87360.o
+obj-$(CONFIG_SENSORS_PC87427)	+= pc87427.o
 obj-$(CONFIG_SENSORS_SIS5595)	+= sis5595.o
 obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
 obj-$(CONFIG_SENSORS_SMSC47M1)	+= smsc47m1.o
diff --git a/drivers/hwmon/ams/Makefile b/drivers/hwmon/ams/Makefile
new file mode 100644
index 0000000..41c95b2
--- /dev/null
+++ b/drivers/hwmon/ams/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for Apple Motion Sensor driver
+#
+
+ams-y					:= ams-core.o ams-input.o
+ams-$(CONFIG_SENSORS_AMS_PMU)		+= ams-pmu.o
+ams-$(CONFIG_SENSORS_AMS_I2C)		+= ams-i2c.o
+obj-$(CONFIG_SENSORS_AMS)		+= ams.o
diff --git a/drivers/hwmon/ams/ams-core.c b/drivers/hwmon/ams/ams-core.c
new file mode 100644
index 0000000..f1f0f5d
--- /dev/null
+++ b/drivers/hwmon/ams/ams-core.c
@@ -0,0 +1,265 @@
+/*
+ * Apple Motion Sensor driver
+ *
+ * Copyright (C) 2005 Stelian Pop (stelian@popies.net)
+ * Copyright (C) 2006 Michael Hanselmann (linux-kernel@hansmi.ch)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <asm/pmac_pfunc.h>
+#include <asm/of_platform.h>
+
+#include "ams.h"
+
+/* There is only one motion sensor per machine */
+struct ams ams_info;
+
+static unsigned int verbose;
+module_param(verbose, bool, 0644);
+MODULE_PARM_DESC(verbose, "Show free falls and shocks in kernel output");
+
+/* Call with ams_info.lock held! */
+void ams_sensors(s8 *x, s8 *y, s8 *z)
+{
+	u32 orient = ams_info.vflag? ams_info.orient1 : ams_info.orient2;
+
+	if (orient & 0x80)
+		/* X and Y swapped */
+		ams_info.get_xyz(y, x, z);
+	else
+		ams_info.get_xyz(x, y, z);
+
+	if (orient & 0x04)
+		*z = ~(*z);
+	if (orient & 0x02)
+		*y = ~(*y);
+	if (orient & 0x01)
+		*x = ~(*x);
+}
+
+static ssize_t ams_show_current(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	s8 x, y, z;
+
+	mutex_lock(&ams_info.lock);
+	ams_sensors(&x, &y, &z);
+	mutex_unlock(&ams_info.lock);
+
+	return snprintf(buf, PAGE_SIZE, "%d %d %d\n", x, y, z);
+}
+
+static DEVICE_ATTR(current, S_IRUGO, ams_show_current, NULL);
+
+static void ams_handle_irq(void *data)
+{
+	enum ams_irq irq = *((enum ams_irq *)data);
+
+	spin_lock(&ams_info.irq_lock);
+
+	ams_info.worker_irqs |= irq;
+	schedule_work(&ams_info.worker);
+
+	spin_unlock(&ams_info.irq_lock);
+}
+
+static enum ams_irq ams_freefall_irq_data = AMS_IRQ_FREEFALL;
+static struct pmf_irq_client ams_freefall_client = {
+	.owner = THIS_MODULE,
+	.handler = ams_handle_irq,
+	.data = &ams_freefall_irq_data,
+};
+
+static enum ams_irq ams_shock_irq_data = AMS_IRQ_SHOCK;
+static struct pmf_irq_client ams_shock_client = {
+	.owner = THIS_MODULE,
+	.handler = ams_handle_irq,
+	.data = &ams_shock_irq_data,
+};
+
+/* Once hard disk parking is implemented in the kernel, this function can
+ * trigger it.
+ */
+static void ams_worker(struct work_struct *work)
+{
+	mutex_lock(&ams_info.lock);
+
+	if (ams_info.has_device) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&ams_info.irq_lock, flags);
+
+		if (ams_info.worker_irqs & AMS_IRQ_FREEFALL) {
+			if (verbose)
+				printk(KERN_INFO "ams: freefall detected!\n");
+
+			ams_info.worker_irqs &= ~AMS_IRQ_FREEFALL;
+
+			/* we must call this with interrupts enabled */
+			spin_unlock_irqrestore(&ams_info.irq_lock, flags);
+			ams_info.clear_irq(AMS_IRQ_FREEFALL);
+			spin_lock_irqsave(&ams_info.irq_lock, flags);
+		}
+
+		if (ams_info.worker_irqs & AMS_IRQ_SHOCK) {
+			if (verbose)
+				printk(KERN_INFO "ams: shock detected!\n");
+
+			ams_info.worker_irqs &= ~AMS_IRQ_SHOCK;
+
+			/* we must call this with interrupts enabled */
+			spin_unlock_irqrestore(&ams_info.irq_lock, flags);
+			ams_info.clear_irq(AMS_IRQ_SHOCK);
+			spin_lock_irqsave(&ams_info.irq_lock, flags);
+		}
+
+		spin_unlock_irqrestore(&ams_info.irq_lock, flags);
+	}
+
+	mutex_unlock(&ams_info.lock);
+}
+
+/* Call with ams_info.lock held! */
+int ams_sensor_attach(void)
+{
+	int result;
+	u32 *prop;
+
+	/* Get orientation */
+	prop = (u32*)get_property(ams_info.of_node, "orientation", NULL);
+	if (!prop)
+		return -ENODEV;
+	ams_info.orient1 = *prop;
+	ams_info.orient2 = *(prop + 1);
+
+	/* Register freefall interrupt handler */
+	result = pmf_register_irq_client(ams_info.of_node,
+			"accel-int-1",
+			&ams_freefall_client);
+	if (result < 0)
+		return -ENODEV;
+
+	/* Reset saved irqs */
+	ams_info.worker_irqs = 0;
+
+	/* Register shock interrupt handler */
+	result = pmf_register_irq_client(ams_info.of_node,
+			"accel-int-2",
+			&ams_shock_client);
+	if (result < 0)
+		goto release_freefall;
+
+	/* Create device */
+	ams_info.of_dev = of_platform_device_create(ams_info.of_node, "ams", NULL);
+	if (!ams_info.of_dev) {
+		result = -ENODEV;
+		goto release_shock;
+	}
+
+	/* Create attributes */
+	result = device_create_file(&ams_info.of_dev->dev, &dev_attr_current);
+	if (result)
+		goto release_of;
+
+	ams_info.vflag = !!(ams_info.get_vendor() & 0x10);
+
+	/* Init input device */
+	result = ams_input_init();
+	if (result)
+		goto release_device_file;
+
+	return result;
+release_device_file:
+	device_remove_file(&ams_info.of_dev->dev, &dev_attr_current);
+release_of:
+	of_device_unregister(ams_info.of_dev);
+release_shock:
+	pmf_unregister_irq_client(&ams_shock_client);
+release_freefall:
+	pmf_unregister_irq_client(&ams_freefall_client);
+	return result;
+}
+
+int __init ams_init(void)
+{
+	struct device_node *np;
+
+	spin_lock_init(&ams_info.irq_lock);
+	mutex_init(&ams_info.lock);
+	INIT_WORK(&ams_info.worker, ams_worker);
+
+#ifdef CONFIG_SENSORS_AMS_I2C
+	np = of_find_node_by_name(NULL, "accelerometer");
+	if (np && device_is_compatible(np, "AAPL,accelerometer_1"))
+		/* Found I2C motion sensor */
+		return ams_i2c_init(np);
+#endif
+
+#ifdef CONFIG_SENSORS_AMS_PMU
+	np = of_find_node_by_name(NULL, "sms");
+	if (np && device_is_compatible(np, "sms"))
+		/* Found PMU motion sensor */
+		return ams_pmu_init(np);
+#endif
+
+	printk(KERN_ERR "ams: No motion sensor found.\n");
+
+	return -ENODEV;
+}
+
+void ams_exit(void)
+{
+	mutex_lock(&ams_info.lock);
+
+	if (ams_info.has_device) {
+		/* Remove input device */
+		ams_input_exit();
+
+		/* Shut down implementation */
+		ams_info.exit();
+
+		/* Flush interrupt worker
+		 *
+		 * We do this after ams_info.exit(), because an interrupt might
+		 * have arrived before disabling them.
+		 */
+		flush_scheduled_work();
+
+		/* Remove attributes */
+		device_remove_file(&ams_info.of_dev->dev, &dev_attr_current);
+
+		/* Remove device */
+		of_device_unregister(ams_info.of_dev);
+
+		/* Remove handler */
+		pmf_unregister_irq_client(&ams_shock_client);
+		pmf_unregister_irq_client(&ams_freefall_client);
+	}
+
+	mutex_unlock(&ams_info.lock);
+}
+
+MODULE_AUTHOR("Stelian Pop, Michael Hanselmann");
+MODULE_DESCRIPTION("Apple Motion Sensor driver");
+MODULE_LICENSE("GPL");
+
+module_init(ams_init);
+module_exit(ams_exit);
diff --git a/drivers/hwmon/ams/ams-i2c.c b/drivers/hwmon/ams/ams-i2c.c
new file mode 100644
index 0000000..0d24bdf
--- /dev/null
+++ b/drivers/hwmon/ams/ams-i2c.c
@@ -0,0 +1,299 @@
+/*
+ * Apple Motion Sensor driver (I2C variant)
+ *
+ * Copyright (C) 2005 Stelian Pop (stelian@popies.net)
+ * Copyright (C) 2006 Michael Hanselmann (linux-kernel@hansmi.ch)
+ *
+ * Clean room implementation based on the reverse engineered Mac OS X driver by
+ * Johannes Berg <johannes@sipsolutions.net>, documentation available at
+ * http://johannes.sipsolutions.net/PowerBook/Apple_Motion_Sensor_Specification
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include "ams.h"
+
+/* AMS registers */
+#define AMS_COMMAND	0x00	/* command register */
+#define AMS_STATUS	0x01	/* status register */
+#define AMS_CTRL1	0x02	/* read control 1 (number of values) */
+#define AMS_CTRL2	0x03	/* read control 2 (offset?) */
+#define AMS_CTRL3	0x04	/* read control 3 (size of each value?) */
+#define AMS_DATA1	0x05	/* read data 1 */
+#define AMS_DATA2	0x06	/* read data 2 */
+#define AMS_DATA3	0x07	/* read data 3 */
+#define AMS_DATA4	0x08	/* read data 4 */
+#define AMS_DATAX	0x20	/* data X */
+#define AMS_DATAY	0x21	/* data Y */
+#define AMS_DATAZ	0x22	/* data Z */
+#define AMS_FREEFALL	0x24	/* freefall int control */
+#define AMS_SHOCK	0x25	/* shock int control */
+#define AMS_SENSLOW	0x26	/* sensitivity low limit */
+#define AMS_SENSHIGH	0x27	/* sensitivity high limit */
+#define AMS_CTRLX	0x28	/* control X */
+#define AMS_CTRLY	0x29	/* control Y */
+#define AMS_CTRLZ	0x2A	/* control Z */
+#define AMS_UNKNOWN1	0x2B	/* unknown 1 */
+#define AMS_UNKNOWN2	0x2C	/* unknown 2 */
+#define AMS_UNKNOWN3	0x2D	/* unknown 3 */
+#define AMS_VENDOR	0x2E	/* vendor */
+
+/* AMS commands - use with the AMS_COMMAND register */
+enum ams_i2c_cmd {
+	AMS_CMD_NOOP = 0,
+	AMS_CMD_VERSION,
+	AMS_CMD_READMEM,
+	AMS_CMD_WRITEMEM,
+	AMS_CMD_ERASEMEM,
+	AMS_CMD_READEE,
+	AMS_CMD_WRITEEE,
+	AMS_CMD_RESET,
+	AMS_CMD_START,
+};
+
+static int ams_i2c_attach(struct i2c_adapter *adapter);
+static int ams_i2c_detach(struct i2c_adapter *adapter);
+
+static struct i2c_driver ams_i2c_driver = {
+	.driver = {
+		.name   = "ams",
+		.owner  = THIS_MODULE,
+	},
+	.attach_adapter = ams_i2c_attach,
+	.detach_adapter = ams_i2c_detach,
+};
+
+static s32 ams_i2c_read(u8 reg)
+{
+	return i2c_smbus_read_byte_data(&ams_info.i2c_client, reg);
+}
+
+static int ams_i2c_write(u8 reg, u8 value)
+{
+	return i2c_smbus_write_byte_data(&ams_info.i2c_client, reg, value);
+}
+
+static int ams_i2c_cmd(enum ams_i2c_cmd cmd)
+{
+	s32 result;
+	int remaining = HZ / 20;
+
+	ams_i2c_write(AMS_COMMAND, cmd);
+	mdelay(5);
+
+	while (remaining) {
+		result = ams_i2c_read(AMS_COMMAND);
+		if (result == 0 || result & 0x80)
+			return 0;
+
+		remaining = schedule_timeout(remaining);
+	}
+
+	return -1;
+}
+
+static void ams_i2c_set_irq(enum ams_irq reg, char enable)
+{
+	if (reg & AMS_IRQ_FREEFALL) {
+		u8 val = ams_i2c_read(AMS_CTRLX);
+		if (enable)
+			val |= 0x80;
+		else
+			val &= ~0x80;
+		ams_i2c_write(AMS_CTRLX, val);
+	}
+
+	if (reg & AMS_IRQ_SHOCK) {
+		u8 val = ams_i2c_read(AMS_CTRLY);
+		if (enable)
+			val |= 0x80;
+		else
+			val &= ~0x80;
+		ams_i2c_write(AMS_CTRLY, val);
+	}
+
+	if (reg & AMS_IRQ_GLOBAL) {
+		u8 val = ams_i2c_read(AMS_CTRLZ);
+		if (enable)
+			val |= 0x80;
+		else
+			val &= ~0x80;
+		ams_i2c_write(AMS_CTRLZ, val);
+	}
+}
+
+static void ams_i2c_clear_irq(enum ams_irq reg)
+{
+	if (reg & AMS_IRQ_FREEFALL)
+		ams_i2c_write(AMS_FREEFALL, 0);
+
+	if (reg & AMS_IRQ_SHOCK)
+		ams_i2c_write(AMS_SHOCK, 0);
+}
+
+static u8 ams_i2c_get_vendor(void)
+{
+	return ams_i2c_read(AMS_VENDOR);
+}
+
+static void ams_i2c_get_xyz(s8 *x, s8 *y, s8 *z)
+{
+	*x = ams_i2c_read(AMS_DATAX);
+	*y = ams_i2c_read(AMS_DATAY);
+	*z = ams_i2c_read(AMS_DATAZ);
+}
+
+static int ams_i2c_attach(struct i2c_adapter *adapter)
+{
+	unsigned long bus;
+	int vmaj, vmin;
+	int result;
+
+	/* There can be only one */
+	if (unlikely(ams_info.has_device))
+		return -ENODEV;
+
+	if (strncmp(adapter->name, "uni-n", 5))
+		return -ENODEV;
+
+	bus = simple_strtoul(adapter->name + 6, NULL, 10);
+	if (bus != ams_info.i2c_bus)
+		return -ENODEV;
+
+	ams_info.i2c_client.addr = ams_info.i2c_address;
+	ams_info.i2c_client.adapter = adapter;
+	ams_info.i2c_client.driver = &ams_i2c_driver;
+	strcpy(ams_info.i2c_client.name, "Apple Motion Sensor");
+
+	if (ams_i2c_cmd(AMS_CMD_RESET)) {
+		printk(KERN_INFO "ams: Failed to reset the device\n");
+		return -ENODEV;
+	}
+
+	if (ams_i2c_cmd(AMS_CMD_START)) {
+		printk(KERN_INFO "ams: Failed to start the device\n");
+		return -ENODEV;
+	}
+
+	/* get version/vendor information */
+	ams_i2c_write(AMS_CTRL1, 0x02);
+	ams_i2c_write(AMS_CTRL2, 0x85);
+	ams_i2c_write(AMS_CTRL3, 0x01);
+
+	ams_i2c_cmd(AMS_CMD_READMEM);
+
+	vmaj = ams_i2c_read(AMS_DATA1);
+	vmin = ams_i2c_read(AMS_DATA2);
+	if (vmaj != 1 || vmin != 52) {
+		printk(KERN_INFO "ams: Incorrect device version (%d.%d)\n",
+			vmaj, vmin);
+		return -ENODEV;
+	}
+
+	ams_i2c_cmd(AMS_CMD_VERSION);
+
+	vmaj = ams_i2c_read(AMS_DATA1);
+	vmin = ams_i2c_read(AMS_DATA2);
+	if (vmaj != 0 || vmin != 1) {
+		printk(KERN_INFO "ams: Incorrect firmware version (%d.%d)\n",
+			vmaj, vmin);
+		return -ENODEV;
+	}
+
+	/* Disable interrupts */
+	ams_i2c_set_irq(AMS_IRQ_ALL, 0);
+
+	result = ams_sensor_attach();
+	if (result < 0)
+		return result;
+
+	/* Set default values */
+	ams_i2c_write(AMS_SENSLOW, 0x15);
+	ams_i2c_write(AMS_SENSHIGH, 0x60);
+	ams_i2c_write(AMS_CTRLX, 0x08);
+	ams_i2c_write(AMS_CTRLY, 0x0F);
+	ams_i2c_write(AMS_CTRLZ, 0x4F);
+	ams_i2c_write(AMS_UNKNOWN1, 0x14);
+
+	/* Clear interrupts */
+	ams_i2c_clear_irq(AMS_IRQ_ALL);
+
+	ams_info.has_device = 1;
+
+	/* Enable interrupts */
+	ams_i2c_set_irq(AMS_IRQ_ALL, 1);
+
+	printk(KERN_INFO "ams: Found I2C based motion sensor\n");
+
+	return 0;
+}
+
+static int ams_i2c_detach(struct i2c_adapter *adapter)
+{
+	if (ams_info.has_device) {
+		/* Disable interrupts */
+		ams_i2c_set_irq(AMS_IRQ_ALL, 0);
+
+		/* Clear interrupts */
+		ams_i2c_clear_irq(AMS_IRQ_ALL);
+
+		printk(KERN_INFO "ams: Unloading\n");
+
+		ams_info.has_device = 0;
+	}
+
+	return 0;
+}
+
+static void ams_i2c_exit(void)
+{
+	i2c_del_driver(&ams_i2c_driver);
+}
+
+int __init ams_i2c_init(struct device_node *np)
+{
+	char *tmp_bus;
+	int result;
+	u32 *prop;
+
+	mutex_lock(&ams_info.lock);
+
+	/* Set implementation stuff */
+	ams_info.of_node = np;
+	ams_info.exit = ams_i2c_exit;
+	ams_info.get_vendor = ams_i2c_get_vendor;
+	ams_info.get_xyz = ams_i2c_get_xyz;
+	ams_info.clear_irq = ams_i2c_clear_irq;
+	ams_info.bustype = BUS_I2C;
+
+	/* look for bus either using "reg" or by path */
+	prop = (u32*)get_property(ams_info.of_node, "reg", NULL);
+	if (!prop) {
+		result = -ENODEV;
+
+		goto exit;
+	}
+
+	tmp_bus = strstr(ams_info.of_node->full_name, "/i2c-bus@");
+	if (tmp_bus)
+		ams_info.i2c_bus = *(tmp_bus + 9) - '0';
+	else
+		ams_info.i2c_bus = ((*prop) >> 8) & 0x0f;
+	ams_info.i2c_address = ((*prop) & 0xff) >> 1;
+
+	result = i2c_add_driver(&ams_i2c_driver);
+
+exit:
+	mutex_unlock(&ams_info.lock);
+
+	return result;
+}
diff --git a/drivers/hwmon/ams/ams-input.c b/drivers/hwmon/ams/ams-input.c
new file mode 100644
index 0000000..f126aa4
--- /dev/null
+++ b/drivers/hwmon/ams/ams-input.c
@@ -0,0 +1,160 @@
+/*
+ * Apple Motion Sensor driver (joystick emulation)
+ *
+ * Copyright (C) 2005 Stelian Pop (stelian@popies.net)
+ * Copyright (C) 2006 Michael Hanselmann (linux-kernel@hansmi.ch)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include "ams.h"
+
+static unsigned int joystick;
+module_param(joystick, bool, 0644);
+MODULE_PARM_DESC(joystick, "Enable the input class device on module load");
+
+static unsigned int invert;
+module_param(invert, bool, 0644);
+MODULE_PARM_DESC(invert, "Invert input data on X and Y axis");
+
+static int ams_input_kthread(void *data)
+{
+	s8 x, y, z;
+
+	while (!kthread_should_stop()) {
+		mutex_lock(&ams_info.lock);
+
+		ams_sensors(&x, &y, &z);
+
+		x -= ams_info.xcalib;
+		y -= ams_info.ycalib;
+		z -= ams_info.zcalib;
+
+		input_report_abs(ams_info.idev, ABS_X, invert ? -x : x);
+		input_report_abs(ams_info.idev, ABS_Y, invert ? -y : y);
+		input_report_abs(ams_info.idev, ABS_Z, z);
+
+		input_sync(ams_info.idev);
+
+		mutex_unlock(&ams_info.lock);
+
+		msleep(25);
+	}
+
+	return 0;
+}
+
+static int ams_input_open(struct input_dev *dev)
+{
+	ams_info.kthread = kthread_run(ams_input_kthread, NULL, "kams");
+	return IS_ERR(ams_info.kthread) ? PTR_ERR(ams_info.kthread) : 0;
+}
+
+static void ams_input_close(struct input_dev *dev)
+{
+	kthread_stop(ams_info.kthread);
+}
+
+/* Call with ams_info.lock held! */
+static void ams_input_enable(void)
+{
+	s8 x, y, z;
+
+	if (ams_info.idev)
+		return;
+
+	ams_sensors(&x, &y, &z);
+	ams_info.xcalib = x;
+	ams_info.ycalib = y;
+	ams_info.zcalib = z;
+
+	ams_info.idev = input_allocate_device();
+	if (!ams_info.idev)
+		return;
+
+	ams_info.idev->name = "Apple Motion Sensor";
+	ams_info.idev->id.bustype = ams_info.bustype;
+	ams_info.idev->id.vendor = 0;
+	ams_info.idev->open = ams_input_open;
+	ams_info.idev->close = ams_input_close;
+	ams_info.idev->cdev.dev = &ams_info.of_dev->dev;
+
+	input_set_abs_params(ams_info.idev, ABS_X, -50, 50, 3, 0);
+	input_set_abs_params(ams_info.idev, ABS_Y, -50, 50, 3, 0);
+	input_set_abs_params(ams_info.idev, ABS_Z, -50, 50, 3, 0);
+
+	set_bit(EV_ABS, ams_info.idev->evbit);
+	set_bit(EV_KEY, ams_info.idev->evbit);
+	set_bit(BTN_TOUCH, ams_info.idev->keybit);
+
+	if (input_register_device(ams_info.idev)) {
+		input_free_device(ams_info.idev);
+		ams_info.idev = NULL;
+		return;
+	}
+}
+
+/* Call with ams_info.lock held! */
+static void ams_input_disable(void)
+{
+	if (ams_info.idev) {
+		input_unregister_device(ams_info.idev);
+		ams_info.idev = NULL;
+	}
+}
+
+static ssize_t ams_input_show_joystick(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n", joystick);
+}
+
+static ssize_t ams_input_store_joystick(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	if (sscanf(buf, "%d\n", &joystick) != 1)
+		return -EINVAL;
+
+	mutex_lock(&ams_info.lock);
+
+	if (joystick)
+		ams_input_enable();
+	else
+		ams_input_disable();
+
+	mutex_unlock(&ams_info.lock);
+
+	return count;
+}
+
+static DEVICE_ATTR(joystick, S_IRUGO | S_IWUSR,
+	ams_input_show_joystick, ams_input_store_joystick);
+
+/* Call with ams_info.lock held! */
+int ams_input_init(void)
+{
+	int result;
+
+	result = device_create_file(&ams_info.of_dev->dev, &dev_attr_joystick);
+
+	if (!result && joystick)
+		ams_input_enable();
+	return result;
+}
+
+/* Call with ams_info.lock held! */
+void ams_input_exit()
+{
+	ams_input_disable();
+	device_remove_file(&ams_info.of_dev->dev, &dev_attr_joystick);
+}
diff --git a/drivers/hwmon/ams/ams-pmu.c b/drivers/hwmon/ams/ams-pmu.c
new file mode 100644
index 0000000..4636ae0
--- /dev/null
+++ b/drivers/hwmon/ams/ams-pmu.c
@@ -0,0 +1,207 @@
+/*
+ * Apple Motion Sensor driver (PMU variant)
+ *
+ * Copyright (C) 2006 Michael Hanselmann (linux-kernel@hansmi.ch)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+
+#include "ams.h"
+
+/* Attitude */
+#define AMS_X			0x00
+#define AMS_Y			0x01
+#define AMS_Z			0x02
+
+/* Not exactly known, maybe chip vendor */
+#define AMS_VENDOR		0x03
+
+/* Freefall registers */
+#define AMS_FF_CLEAR		0x04
+#define AMS_FF_ENABLE		0x05
+#define AMS_FF_LOW_LIMIT	0x06
+#define AMS_FF_DEBOUNCE		0x07
+
+/* Shock registers */
+#define AMS_SHOCK_CLEAR		0x08
+#define AMS_SHOCK_ENABLE	0x09
+#define AMS_SHOCK_HIGH_LIMIT	0x0a
+#define AMS_SHOCK_DEBOUNCE	0x0b
+
+/* Global interrupt and power control register */
+#define AMS_CONTROL		0x0c
+
+static u8 ams_pmu_cmd;
+
+static void ams_pmu_req_complete(struct adb_request *req)
+{
+	complete((struct completion *)req->arg);
+}
+
+/* Only call this function from task context */
+static void ams_pmu_set_register(u8 reg, u8 value)
+{
+	static struct adb_request req;
+	DECLARE_COMPLETION(req_complete);
+
+	req.arg = &req_complete;
+	if (pmu_request(&req, ams_pmu_req_complete, 4, ams_pmu_cmd, 0x00, reg, value))
+		return;
+
+	wait_for_completion(&req_complete);
+}
+
+/* Only call this function from task context */
+static u8 ams_pmu_get_register(u8 reg)
+{
+	static struct adb_request req;
+	DECLARE_COMPLETION(req_complete);
+
+	req.arg = &req_complete;
+	if (pmu_request(&req, ams_pmu_req_complete, 3, ams_pmu_cmd, 0x01, reg))
+		return 0;
+
+	wait_for_completion(&req_complete);
+
+	if (req.reply_len > 0)
+		return req.reply[0];
+	else
+		return 0;
+}
+
+/* Enables or disables the specified interrupts */
+static void ams_pmu_set_irq(enum ams_irq reg, char enable)
+{
+	if (reg & AMS_IRQ_FREEFALL) {
+		u8 val = ams_pmu_get_register(AMS_FF_ENABLE);
+		if (enable)
+			val |= 0x80;
+		else
+			val &= ~0x80;
+		ams_pmu_set_register(AMS_FF_ENABLE, val);
+	}
+
+	if (reg & AMS_IRQ_SHOCK) {
+		u8 val = ams_pmu_get_register(AMS_SHOCK_ENABLE);
+		if (enable)
+			val |= 0x80;
+		else
+			val &= ~0x80;
+		ams_pmu_set_register(AMS_SHOCK_ENABLE, val);
+	}
+
+	if (reg & AMS_IRQ_GLOBAL) {
+		u8 val = ams_pmu_get_register(AMS_CONTROL);
+		if (enable)
+			val |= 0x80;
+		else
+			val &= ~0x80;
+		ams_pmu_set_register(AMS_CONTROL, val);
+	}
+}
+
+static void ams_pmu_clear_irq(enum ams_irq reg)
+{
+	if (reg & AMS_IRQ_FREEFALL)
+		ams_pmu_set_register(AMS_FF_CLEAR, 0x00);
+
+	if (reg & AMS_IRQ_SHOCK)
+		ams_pmu_set_register(AMS_SHOCK_CLEAR, 0x00);
+}
+
+static u8 ams_pmu_get_vendor(void)
+{
+	return ams_pmu_get_register(AMS_VENDOR);
+}
+
+static void ams_pmu_get_xyz(s8 *x, s8 *y, s8 *z)
+{
+	*x = ams_pmu_get_register(AMS_X);
+	*y = ams_pmu_get_register(AMS_Y);
+	*z = ams_pmu_get_register(AMS_Z);
+}
+
+static void ams_pmu_exit(void)
+{
+	/* Disable interrupts */
+	ams_pmu_set_irq(AMS_IRQ_ALL, 0);
+
+	/* Clear interrupts */
+	ams_pmu_clear_irq(AMS_IRQ_ALL);
+
+	ams_info.has_device = 0;
+
+	printk(KERN_INFO "ams: Unloading\n");
+}
+
+int __init ams_pmu_init(struct device_node *np)
+{
+	u32 *prop;
+	int result;
+
+	mutex_lock(&ams_info.lock);
+
+	/* Set implementation stuff */
+	ams_info.of_node = np;
+	ams_info.exit = ams_pmu_exit;
+	ams_info.get_vendor = ams_pmu_get_vendor;
+	ams_info.get_xyz = ams_pmu_get_xyz;
+	ams_info.clear_irq = ams_pmu_clear_irq;
+	ams_info.bustype = BUS_HOST;
+
+	/* Get PMU command, should be 0x4e, but we can never know */
+	prop = (u32*)get_property(ams_info.of_node, "reg", NULL);
+	if (!prop) {
+		result = -ENODEV;
+		goto exit;
+	}
+	ams_pmu_cmd = ((*prop) >> 8) & 0xff;
+
+	/* Disable interrupts */
+	ams_pmu_set_irq(AMS_IRQ_ALL, 0);
+
+	/* Clear interrupts */
+	ams_pmu_clear_irq(AMS_IRQ_ALL);
+
+	result = ams_sensor_attach();
+	if (result < 0)
+		goto exit;
+
+	/* Set default values */
+	ams_pmu_set_register(AMS_FF_LOW_LIMIT, 0x15);
+	ams_pmu_set_register(AMS_FF_ENABLE, 0x08);
+	ams_pmu_set_register(AMS_FF_DEBOUNCE, 0x14);
+
+	ams_pmu_set_register(AMS_SHOCK_HIGH_LIMIT, 0x60);
+	ams_pmu_set_register(AMS_SHOCK_ENABLE, 0x0f);
+	ams_pmu_set_register(AMS_SHOCK_DEBOUNCE, 0x14);
+
+	ams_pmu_set_register(AMS_CONTROL, 0x4f);
+
+	/* Clear interrupts */
+	ams_pmu_clear_irq(AMS_IRQ_ALL);
+
+	ams_info.has_device = 1;
+
+	/* Enable interrupts */
+	ams_pmu_set_irq(AMS_IRQ_ALL, 1);
+
+	printk(KERN_INFO "ams: Found PMU based motion sensor\n");
+
+	result = 0;
+
+exit:
+	mutex_unlock(&ams_info.lock);
+
+	return result;
+}
diff --git a/drivers/hwmon/ams/ams.h b/drivers/hwmon/ams/ams.h
new file mode 100644
index 0000000..240730e
--- /dev/null
+++ b/drivers/hwmon/ams/ams.h
@@ -0,0 +1,72 @@
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/kthread.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <asm/of_device.h>
+
+enum ams_irq {
+	AMS_IRQ_FREEFALL = 0x01,
+	AMS_IRQ_SHOCK = 0x02,
+	AMS_IRQ_GLOBAL = 0x04,
+	AMS_IRQ_ALL =
+		AMS_IRQ_FREEFALL |
+		AMS_IRQ_SHOCK |
+		AMS_IRQ_GLOBAL,
+};
+
+struct ams {
+	/* Locks */
+	spinlock_t irq_lock;
+	struct mutex lock;
+
+	/* General properties */
+	struct device_node *of_node;
+	struct of_device *of_dev;
+	char has_device;
+	char vflag;
+	u32 orient1;
+	u32 orient2;
+
+	/* Interrupt worker */
+	struct work_struct worker;
+	u8 worker_irqs;
+
+	/* Implementation
+	 *
+	 * Only call these functions with the main lock held.
+	 */
+	void (*exit)(void);
+
+	void (*get_xyz)(s8 *x, s8 *y, s8 *z);
+	u8 (*get_vendor)(void);
+
+	void (*clear_irq)(enum ams_irq reg);
+
+#ifdef CONFIG_SENSORS_AMS_I2C
+	/* I2C properties */
+	int i2c_bus;
+	int i2c_address;
+	struct i2c_client i2c_client;
+#endif
+
+	/* Joystick emulation */
+	struct task_struct *kthread;
+	struct input_dev *idev;
+	__u16 bustype;
+
+	/* calibrated null values */
+	int xcalib, ycalib, zcalib;
+};
+
+extern struct ams ams_info;
+
+extern void ams_sensors(s8 *x, s8 *y, s8 *z);
+extern int ams_sensor_attach(void);
+
+extern int ams_pmu_init(struct device_node *np);
+extern int ams_i2c_init(struct device_node *np);
+
+extern int ams_input_init(void);
+extern void ams_input_exit(void);
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
index de17a72..a272cae 100644
--- a/drivers/hwmon/f71805f.c
+++ b/drivers/hwmon/f71805f.c
@@ -1,12 +1,15 @@
 /*
- * f71805f.c - driver for the Fintek F71805F/FG Super-I/O chip integrated
- *             hardware monitoring features
+ * f71805f.c - driver for the Fintek F71805F/FG and F71872F/FG Super-I/O
+ *             chips integrated hardware monitoring features
  * Copyright (C) 2005-2006  Jean Delvare <khali@linux-fr.org>
  *
  * The F71805F/FG is a LPC Super-I/O chip made by Fintek. It integrates
  * complete hardware monitoring features: voltage, fan and temperature
  * sensors, and manual and automatic fan speed control.
  *
+ * The F71872F/FG is almost the same, with two more voltages monitored,
+ * and 6 VID inputs.
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -37,6 +40,7 @@
 static struct platform_device *pdev;
 
 #define DRVNAME "f71805f"
+enum kinds { f71805f, f71872f };
 
 /*
  * Super-I/O constants and functions
@@ -48,11 +52,13 @@
 #define SIO_REG_DEVID		0x20	/* Device ID (2 bytes) */
 #define SIO_REG_DEVREV		0x22	/* Device revision */
 #define SIO_REG_MANID		0x23	/* Fintek ID (2 bytes) */
+#define SIO_REG_FNSEL1		0x29	/* Multi Function Select 1 (F71872F) */
 #define SIO_REG_ENABLE		0x30	/* Logical device enable */
 #define SIO_REG_ADDR		0x60	/* Logical device address (2 bytes) */
 
 #define SIO_FINTEK_ID		0x1934
 #define SIO_F71805F_ID		0x0406
+#define SIO_F71872F_ID		0x0341
 
 static inline int
 superio_inb(int base, int reg)
@@ -96,22 +102,25 @@
  * ISA constants
  */
 
-#define REGION_LENGTH		2
-#define ADDR_REG_OFFSET		0
-#define DATA_REG_OFFSET		1
+#define REGION_LENGTH		8
+#define ADDR_REG_OFFSET		5
+#define DATA_REG_OFFSET		6
 
 /*
  * Registers
  */
 
-/* in nr from 0 to 8 (8-bit values) */
+/* in nr from 0 to 10 (8-bit values) */
 #define F71805F_REG_IN(nr)		(0x10 + (nr))
-#define F71805F_REG_IN_HIGH(nr)		(0x40 + 2 * (nr))
-#define F71805F_REG_IN_LOW(nr)		(0x41 + 2 * (nr))
+#define F71805F_REG_IN_HIGH(nr)		((nr) < 10 ? 0x40 + 2 * (nr) : 0x2E)
+#define F71805F_REG_IN_LOW(nr)		((nr) < 10 ? 0x41 + 2 * (nr) : 0x2F)
 /* fan nr from 0 to 2 (12-bit values, two registers) */
 #define F71805F_REG_FAN(nr)		(0x20 + 2 * (nr))
 #define F71805F_REG_FAN_LOW(nr)		(0x28 + 2 * (nr))
+#define F71805F_REG_FAN_TARGET(nr)	(0x69 + 16 * (nr))
 #define F71805F_REG_FAN_CTRL(nr)	(0x60 + 16 * (nr))
+#define F71805F_REG_PWM_FREQ(nr)	(0x63 + 16 * (nr))
+#define F71805F_REG_PWM_DUTY(nr)	(0x6B + 16 * (nr))
 /* temp nr from 0 to 2 (8-bit values) */
 #define F71805F_REG_TEMP(nr)		(0x1B + (nr))
 #define F71805F_REG_TEMP_HIGH(nr)	(0x54 + 2 * (nr))
@@ -122,6 +131,14 @@
 /* status nr from 0 to 2 */
 #define F71805F_REG_STATUS(nr)		(0x36 + (nr))
 
+/* individual register bits */
+#define FAN_CTRL_DC_MODE		0x10
+#define FAN_CTRL_LATCH_FULL		0x08
+#define FAN_CTRL_MODE_MASK		0x03
+#define FAN_CTRL_MODE_SPEED		0x00
+#define FAN_CTRL_MODE_TEMPERATURE	0x01
+#define FAN_CTRL_MODE_MANUAL		0x02
+
 /*
  * Data structures and manipulation thereof
  */
@@ -138,12 +155,16 @@
 	unsigned long last_limits;	/* In jiffies */
 
 	/* Register values */
-	u8 in[9];
-	u8 in_high[9];
-	u8 in_low[9];
+	u8 in[11];
+	u8 in_high[11];
+	u8 in_low[11];
+	u16 has_in;
 	u16 fan[3];
 	u16 fan_low[3];
-	u8 fan_enabled;		/* Read once at init time */
+	u16 fan_target[3];
+	u8 fan_ctrl[3];
+	u8 pwm[3];
+	u8 pwm_freq[3];
 	u8 temp[3];
 	u8 temp_high[3];
 	u8 temp_hyst[3];
@@ -151,6 +172,11 @@
 	unsigned long alarms;
 };
 
+struct f71805f_sio_data {
+	enum kinds kind;
+	u8 fnsel1;
+};
+
 static inline long in_from_reg(u8 reg)
 {
 	return (reg * 8);
@@ -200,6 +226,33 @@
 	return (1500000 / rpm);
 }
 
+static inline unsigned long pwm_freq_from_reg(u8 reg)
+{
+	unsigned long clock = (reg & 0x80) ? 48000000UL : 1000000UL;
+
+	reg &= 0x7f;
+	if (reg == 0)
+		reg++;
+	return clock / (reg << 8);
+}
+
+static inline u8 pwm_freq_to_reg(unsigned long val)
+{
+	if (val >= 187500)	/* The highest we can do */
+		return 0x80;
+	if (val >= 1475)	/* Use 48 MHz clock */
+		return 0x80 | (48000000UL / (val << 8));
+	if (val < 31)		/* The lowest we can do */
+		return 0x7f;
+	else			/* Use 1 MHz clock */
+		return 1000000UL / (val << 8);
+}
+
+static inline int pwm_mode_from_reg(u8 reg)
+{
+	return !(reg & FAN_CTRL_DC_MODE);
+}
+
 static inline long temp_from_reg(u8 reg)
 {
 	return (reg * 1000);
@@ -274,16 +327,21 @@
 	/* Limit registers cache is refreshed after 60 seconds */
 	if (time_after(jiffies, data->last_updated + 60 * HZ)
 	 || !data->valid) {
-		for (nr = 0; nr < 9; nr++) {
+		for (nr = 0; nr < 11; nr++) {
+			if (!(data->has_in & (1 << nr)))
+				continue;
 			data->in_high[nr] = f71805f_read8(data,
 					    F71805F_REG_IN_HIGH(nr));
 			data->in_low[nr] = f71805f_read8(data,
 					   F71805F_REG_IN_LOW(nr));
 		}
 		for (nr = 0; nr < 3; nr++) {
-			if (data->fan_enabled & (1 << nr))
-				data->fan_low[nr] = f71805f_read16(data,
-						    F71805F_REG_FAN_LOW(nr));
+			data->fan_low[nr] = f71805f_read16(data,
+					    F71805F_REG_FAN_LOW(nr));
+			data->fan_target[nr] = f71805f_read16(data,
+					       F71805F_REG_FAN_TARGET(nr));
+			data->pwm_freq[nr] = f71805f_read8(data,
+					     F71805F_REG_PWM_FREQ(nr));
 		}
 		for (nr = 0; nr < 3; nr++) {
 			data->temp_high[nr] = f71805f_read8(data,
@@ -299,14 +357,19 @@
 	/* Measurement registers cache is refreshed after 1 second */
 	if (time_after(jiffies, data->last_updated + HZ)
 	 || !data->valid) {
-		for (nr = 0; nr < 9; nr++) {
+		for (nr = 0; nr < 11; nr++) {
+			if (!(data->has_in & (1 << nr)))
+				continue;
 			data->in[nr] = f71805f_read8(data,
 				       F71805F_REG_IN(nr));
 		}
 		for (nr = 0; nr < 3; nr++) {
-			if (data->fan_enabled & (1 << nr))
-				data->fan[nr] = f71805f_read16(data,
-						F71805F_REG_FAN(nr));
+			data->fan[nr] = f71805f_read16(data,
+					F71805F_REG_FAN(nr));
+			data->fan_ctrl[nr] = f71805f_read8(data,
+					     F71805F_REG_FAN_CTRL(nr));
+			data->pwm[nr] = f71805f_read8(data,
+					F71805F_REG_PWM_DUTY(nr));
 		}
 		for (nr = 0; nr < 3; nr++) {
 			data->temp[nr] = f71805f_read8(data,
@@ -333,35 +396,43 @@
 			char *buf)
 {
 	struct f71805f_data *data = f71805f_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
 
-	return sprintf(buf, "%ld\n", in0_from_reg(data->in[0]));
+	return sprintf(buf, "%ld\n", in0_from_reg(data->in[nr]));
 }
 
 static ssize_t show_in0_max(struct device *dev, struct device_attribute
 			    *devattr, char *buf)
 {
 	struct f71805f_data *data = f71805f_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
 
-	return sprintf(buf, "%ld\n", in0_from_reg(data->in_high[0]));
+	return sprintf(buf, "%ld\n", in0_from_reg(data->in_high[nr]));
 }
 
 static ssize_t show_in0_min(struct device *dev, struct device_attribute
 			    *devattr, char *buf)
 {
 	struct f71805f_data *data = f71805f_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
 
-	return sprintf(buf, "%ld\n", in0_from_reg(data->in_low[0]));
+	return sprintf(buf, "%ld\n", in0_from_reg(data->in_low[nr]));
 }
 
 static ssize_t set_in0_max(struct device *dev, struct device_attribute
 			   *devattr, const char *buf, size_t count)
 {
 	struct f71805f_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
 	long val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
-	data->in_high[0] = in0_to_reg(val);
-	f71805f_write8(data, F71805F_REG_IN_HIGH(0), data->in_high[0]);
+	data->in_high[nr] = in0_to_reg(val);
+	f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]);
 	mutex_unlock(&data->update_lock);
 
 	return count;
@@ -371,11 +442,13 @@
 			   *devattr, const char *buf, size_t count)
 {
 	struct f71805f_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
 	long val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
-	data->in_low[0] = in0_to_reg(val);
-	f71805f_write8(data, F71805F_REG_IN_LOW(0), data->in_low[0]);
+	data->in_low[nr] = in0_to_reg(val);
+	f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]);
 	mutex_unlock(&data->update_lock);
 
 	return count;
@@ -463,6 +536,16 @@
 	return sprintf(buf, "%ld\n", fan_from_reg(data->fan_low[nr]));
 }
 
+static ssize_t show_fan_target(struct device *dev, struct device_attribute
+			       *devattr, char *buf)
+{
+	struct f71805f_data *data = f71805f_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+
+	return sprintf(buf, "%ld\n", fan_from_reg(data->fan_target[nr]));
+}
+
 static ssize_t set_fan_min(struct device *dev, struct device_attribute
 			   *devattr, const char *buf, size_t count)
 {
@@ -479,6 +562,157 @@
 	return count;
 }
 
+static ssize_t set_fan_target(struct device *dev, struct device_attribute
+			      *devattr, const char *buf, size_t count)
+{
+	struct f71805f_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+	long val = simple_strtol(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	data->fan_target[nr] = fan_to_reg(val);
+	f71805f_write16(data, F71805F_REG_FAN_TARGET(nr),
+			data->fan_target[nr]);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
+			char *buf)
+{
+	struct f71805f_data *data = f71805f_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+
+	return sprintf(buf, "%d\n", (int)data->pwm[nr]);
+}
+
+static ssize_t show_pwm_enable(struct device *dev, struct device_attribute
+			       *devattr, char *buf)
+{
+	struct f71805f_data *data = f71805f_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+	int mode;
+
+	switch (data->fan_ctrl[nr] & FAN_CTRL_MODE_MASK) {
+	case FAN_CTRL_MODE_SPEED:
+		mode = 3;
+		break;
+	case FAN_CTRL_MODE_TEMPERATURE:
+		mode = 2;
+		break;
+	default: /* MANUAL */
+		mode = 1;
+	}
+
+	return sprintf(buf, "%d\n", mode);
+}
+
+static ssize_t show_pwm_freq(struct device *dev, struct device_attribute
+			     *devattr, char *buf)
+{
+	struct f71805f_data *data = f71805f_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+
+	return sprintf(buf, "%lu\n", pwm_freq_from_reg(data->pwm_freq[nr]));
+}
+
+static ssize_t show_pwm_mode(struct device *dev, struct device_attribute
+			     *devattr, char *buf)
+{
+	struct f71805f_data *data = f71805f_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+
+	return sprintf(buf, "%d\n", pwm_mode_from_reg(data->fan_ctrl[nr]));
+}
+
+static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
+		       const char *buf, size_t count)
+{
+	struct f71805f_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+
+	if (val > 255)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	data->pwm[nr] = val;
+	f71805f_write8(data, F71805F_REG_PWM_DUTY(nr), data->pwm[nr]);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static struct attribute *f71805f_attr_pwm[];
+
+static ssize_t set_pwm_enable(struct device *dev, struct device_attribute
+			      *devattr, const char *buf, size_t count)
+{
+	struct f71805f_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+	u8 reg;
+
+	if (val < 1 || val > 3)
+		return -EINVAL;
+
+	if (val > 1) { /* Automatic mode, user can't set PWM value */
+		if (sysfs_chmod_file(&dev->kobj, f71805f_attr_pwm[nr],
+				     S_IRUGO))
+			dev_dbg(dev, "chmod -w pwm%d failed\n", nr + 1);
+	}
+
+	mutex_lock(&data->update_lock);
+	reg = f71805f_read8(data, F71805F_REG_FAN_CTRL(nr))
+	    & ~FAN_CTRL_MODE_MASK;
+	switch (val) {
+	case 1:
+		reg |= FAN_CTRL_MODE_MANUAL;
+		break;
+	case 2:
+		reg |= FAN_CTRL_MODE_TEMPERATURE;
+		break;
+	case 3:
+		reg |= FAN_CTRL_MODE_SPEED;
+		break;
+	}
+	data->fan_ctrl[nr] = reg;
+	f71805f_write8(data, F71805F_REG_FAN_CTRL(nr), reg);
+	mutex_unlock(&data->update_lock);
+
+	if (val == 1) { /* Manual mode, user can set PWM value */
+		if (sysfs_chmod_file(&dev->kobj, f71805f_attr_pwm[nr],
+				     S_IRUGO | S_IWUSR))
+			dev_dbg(dev, "chmod +w pwm%d failed\n", nr + 1);
+	}
+
+	return count;
+}
+
+static ssize_t set_pwm_freq(struct device *dev, struct device_attribute
+			    *devattr, const char *buf, size_t count)
+{
+	struct f71805f_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	data->pwm_freq[nr] = pwm_freq_to_reg(val);
+	f71805f_write8(data, F71805F_REG_PWM_FREQ(nr), data->pwm_freq[nr]);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
 static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
 			 char *buf)
 {
@@ -557,7 +791,7 @@
 {
 	struct f71805f_data *data = f71805f_update_device(dev);
 
-	return sprintf(buf, "%lu\n", data->alarms & 0x1ff);
+	return sprintf(buf, "%lu\n", data->alarms & 0x7ff);
 }
 
 static ssize_t show_alarms_fan(struct device *dev, struct device_attribute
@@ -594,9 +828,11 @@
 	return sprintf(buf, "%s\n", data->name);
 }
 
-static DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL);
-static DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max);
-static DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min);
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL, 0);
+static SENSOR_DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR,
+			  show_in0_max, set_in0_max, 0);
+static SENSOR_DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR,
+			  show_in0_min, set_in0_min, 0);
 static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1);
 static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR,
 			  show_in_max, set_in_max, 1);
@@ -637,16 +873,32 @@
 			  show_in_max, set_in_max, 8);
 static SENSOR_DEVICE_ATTR(in8_min, S_IRUGO | S_IWUSR,
 			  show_in_min, set_in_min, 8);
+static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_in0, NULL, 9);
+static SENSOR_DEVICE_ATTR(in9_max, S_IRUGO | S_IWUSR,
+			  show_in0_max, set_in0_max, 9);
+static SENSOR_DEVICE_ATTR(in9_min, S_IRUGO | S_IWUSR,
+			  show_in0_min, set_in0_min, 9);
+static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_in0, NULL, 10);
+static SENSOR_DEVICE_ATTR(in10_max, S_IRUGO | S_IWUSR,
+			  show_in0_max, set_in0_max, 10);
+static SENSOR_DEVICE_ATTR(in10_min, S_IRUGO | S_IWUSR,
+			  show_in0_min, set_in0_min, 10);
 
 static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
 static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR,
 			  show_fan_min, set_fan_min, 0);
+static SENSOR_DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR,
+			  show_fan_target, set_fan_target, 0);
 static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
 static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR,
 			  show_fan_min, set_fan_min, 1);
+static SENSOR_DEVICE_ATTR(fan2_target, S_IRUGO | S_IWUSR,
+			  show_fan_target, set_fan_target, 1);
 static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
 static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO | S_IWUSR,
 			  show_fan_min, set_fan_min, 2);
+static SENSOR_DEVICE_ATTR(fan3_target, S_IRUGO | S_IWUSR,
+			  show_fan_target, set_fan_target, 2);
 
 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR,
@@ -667,6 +919,27 @@
 		    show_temp_hyst, set_temp_hyst, 2);
 static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2);
 
+/* pwm (value) files are created read-only, write permission is
+   then added or removed dynamically as needed */
+static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO, show_pwm, set_pwm, 0);
+static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
+			  show_pwm_enable, set_pwm_enable, 0);
+static SENSOR_DEVICE_ATTR(pwm1_freq, S_IRUGO | S_IWUSR,
+			  show_pwm_freq, set_pwm_freq, 0);
+static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO, show_pwm_mode, NULL, 0);
+static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO, show_pwm, set_pwm, 1);
+static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR,
+			  show_pwm_enable, set_pwm_enable, 1);
+static SENSOR_DEVICE_ATTR(pwm2_freq, S_IRUGO | S_IWUSR,
+			  show_pwm_freq, set_pwm_freq, 1);
+static SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO, show_pwm_mode, NULL, 1);
+static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO, show_pwm, set_pwm, 2);
+static SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR,
+			  show_pwm_enable, set_pwm_enable, 2);
+static SENSOR_DEVICE_ATTR(pwm3_freq, S_IRUGO | S_IWUSR,
+			  show_pwm_freq, set_pwm_freq, 2);
+static SENSOR_DEVICE_ATTR(pwm3_mode, S_IRUGO, show_pwm_mode, NULL, 2);
+
 static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
 static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
 static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
@@ -676,6 +949,8 @@
 static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6);
 static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 7);
 static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 8);
+static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 9);
+static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, 10);
 static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 11);
 static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 12);
 static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13);
@@ -689,9 +964,9 @@
 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
 static struct attribute *f71805f_attributes[] = {
-	&dev_attr_in0_input.attr,
-	&dev_attr_in0_max.attr,
-	&dev_attr_in0_min.attr,
+	&sensor_dev_attr_in0_input.dev_attr.attr,
+	&sensor_dev_attr_in0_max.dev_attr.attr,
+	&sensor_dev_attr_in0_min.dev_attr.attr,
 	&sensor_dev_attr_in1_input.dev_attr.attr,
 	&sensor_dev_attr_in1_max.dev_attr.attr,
 	&sensor_dev_attr_in1_min.dev_attr.attr,
@@ -701,9 +976,6 @@
 	&sensor_dev_attr_in3_input.dev_attr.attr,
 	&sensor_dev_attr_in3_max.dev_attr.attr,
 	&sensor_dev_attr_in3_min.dev_attr.attr,
-	&sensor_dev_attr_in4_input.dev_attr.attr,
-	&sensor_dev_attr_in4_max.dev_attr.attr,
-	&sensor_dev_attr_in4_min.dev_attr.attr,
 	&sensor_dev_attr_in5_input.dev_attr.attr,
 	&sensor_dev_attr_in5_max.dev_attr.attr,
 	&sensor_dev_attr_in5_min.dev_attr.attr,
@@ -713,9 +985,29 @@
 	&sensor_dev_attr_in7_input.dev_attr.attr,
 	&sensor_dev_attr_in7_max.dev_attr.attr,
 	&sensor_dev_attr_in7_min.dev_attr.attr,
-	&sensor_dev_attr_in8_input.dev_attr.attr,
-	&sensor_dev_attr_in8_max.dev_attr.attr,
-	&sensor_dev_attr_in8_min.dev_attr.attr,
+
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan1_min.dev_attr.attr,
+	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan1_target.dev_attr.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_min.dev_attr.attr,
+	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan2_target.dev_attr.attr,
+	&sensor_dev_attr_fan3_input.dev_attr.attr,
+	&sensor_dev_attr_fan3_min.dev_attr.attr,
+	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan3_target.dev_attr.attr,
+
+	&sensor_dev_attr_pwm1.dev_attr.attr,
+	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
+	&sensor_dev_attr_pwm1_mode.dev_attr.attr,
+	&sensor_dev_attr_pwm2.dev_attr.attr,
+	&sensor_dev_attr_pwm2_enable.dev_attr.attr,
+	&sensor_dev_attr_pwm2_mode.dev_attr.attr,
+	&sensor_dev_attr_pwm3.dev_attr.attr,
+	&sensor_dev_attr_pwm3_enable.dev_attr.attr,
+	&sensor_dev_attr_pwm3_mode.dev_attr.attr,
 
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	&sensor_dev_attr_temp1_max.dev_attr.attr,
@@ -734,11 +1026,9 @@
 	&sensor_dev_attr_in1_alarm.dev_attr.attr,
 	&sensor_dev_attr_in2_alarm.dev_attr.attr,
 	&sensor_dev_attr_in3_alarm.dev_attr.attr,
-	&sensor_dev_attr_in4_alarm.dev_attr.attr,
 	&sensor_dev_attr_in5_alarm.dev_attr.attr,
 	&sensor_dev_attr_in6_alarm.dev_attr.attr,
 	&sensor_dev_attr_in7_alarm.dev_attr.attr,
-	&sensor_dev_attr_in8_alarm.dev_attr.attr,
 	&dev_attr_alarms_in.attr,
 	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
 	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
@@ -754,29 +1044,59 @@
 	.attrs = f71805f_attributes,
 };
 
-static struct attribute *f71805f_attributes_fan[3][4] = {
+static struct attribute *f71805f_attributes_optin[4][5] = {
 	{
-		&sensor_dev_attr_fan1_input.dev_attr.attr,
-		&sensor_dev_attr_fan1_min.dev_attr.attr,
-		&sensor_dev_attr_fan1_alarm.dev_attr.attr,
+		&sensor_dev_attr_in4_input.dev_attr.attr,
+		&sensor_dev_attr_in4_max.dev_attr.attr,
+		&sensor_dev_attr_in4_min.dev_attr.attr,
+		&sensor_dev_attr_in4_alarm.dev_attr.attr,
 		NULL
 	}, {
-		&sensor_dev_attr_fan2_input.dev_attr.attr,
-		&sensor_dev_attr_fan2_min.dev_attr.attr,
-		&sensor_dev_attr_fan2_alarm.dev_attr.attr,
+		&sensor_dev_attr_in8_input.dev_attr.attr,
+		&sensor_dev_attr_in8_max.dev_attr.attr,
+		&sensor_dev_attr_in8_min.dev_attr.attr,
+		&sensor_dev_attr_in8_alarm.dev_attr.attr,
 		NULL
 	}, {
-		&sensor_dev_attr_fan3_input.dev_attr.attr,
-		&sensor_dev_attr_fan3_min.dev_attr.attr,
-		&sensor_dev_attr_fan3_alarm.dev_attr.attr,
+		&sensor_dev_attr_in9_input.dev_attr.attr,
+		&sensor_dev_attr_in9_max.dev_attr.attr,
+		&sensor_dev_attr_in9_min.dev_attr.attr,
+		&sensor_dev_attr_in9_alarm.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_in10_input.dev_attr.attr,
+		&sensor_dev_attr_in10_max.dev_attr.attr,
+		&sensor_dev_attr_in10_min.dev_attr.attr,
+		&sensor_dev_attr_in10_alarm.dev_attr.attr,
 		NULL
 	}
 };
 
-static const struct attribute_group f71805f_group_fan[3] = {
-	{ .attrs = f71805f_attributes_fan[0] },
-	{ .attrs = f71805f_attributes_fan[1] },
-	{ .attrs = f71805f_attributes_fan[2] },
+static const struct attribute_group f71805f_group_optin[4] = {
+	{ .attrs = f71805f_attributes_optin[0] },
+	{ .attrs = f71805f_attributes_optin[1] },
+	{ .attrs = f71805f_attributes_optin[2] },
+	{ .attrs = f71805f_attributes_optin[3] },
+};
+
+/* We don't include pwm_freq files in the arrays above, because they must be
+   created conditionally (only if pwm_mode is 1 == PWM) */
+static struct attribute *f71805f_attributes_pwm_freq[] = {
+	&sensor_dev_attr_pwm1_freq.dev_attr.attr,
+	&sensor_dev_attr_pwm2_freq.dev_attr.attr,
+	&sensor_dev_attr_pwm3_freq.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group f71805f_group_pwm_freq = {
+	.attrs = f71805f_attributes_pwm_freq,
+};
+
+/* We also need an indexed access to pwmN files to toggle writability */
+static struct attribute *f71805f_attr_pwm[] = {
+	&sensor_dev_attr_pwm1.dev_attr.attr,
+	&sensor_dev_attr_pwm2.dev_attr.attr,
+	&sensor_dev_attr_pwm3.dev_attr.attr,
 };
 
 /*
@@ -798,18 +1118,30 @@
 	/* Fan monitoring can be disabled. If it is, we won't be polling
 	   the register values, and won't create the related sysfs files. */
 	for (i = 0; i < 3; i++) {
-		reg = f71805f_read8(data, F71805F_REG_FAN_CTRL(i));
-		if (!(reg & 0x80))
-			data->fan_enabled |= (1 << i);
+		data->fan_ctrl[i] = f71805f_read8(data,
+						  F71805F_REG_FAN_CTRL(i));
+		/* Clear latch full bit, else "speed mode" fan speed control
+		   doesn't work */
+		if (data->fan_ctrl[i] & FAN_CTRL_LATCH_FULL) {
+			data->fan_ctrl[i] &= ~FAN_CTRL_LATCH_FULL;
+			f71805f_write8(data, F71805F_REG_FAN_CTRL(i),
+				       data->fan_ctrl[i]);
+		}
 	}
 }
 
 static int __devinit f71805f_probe(struct platform_device *pdev)
 {
+	struct f71805f_sio_data *sio_data = pdev->dev.platform_data;
 	struct f71805f_data *data;
 	struct resource *res;
 	int i, err;
 
+	static const char *names[] = {
+		"f71805f",
+		"f71872f",
+	};
+
 	if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		printk(KERN_ERR DRVNAME ": Out of memory\n");
@@ -819,24 +1151,69 @@
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 	data->addr = res->start;
 	mutex_init(&data->lock);
-	data->name = "f71805f";
+	data->name = names[sio_data->kind];
 	mutex_init(&data->update_lock);
 
 	platform_set_drvdata(pdev, data);
 
+	/* Some voltage inputs depend on chip model and configuration */
+	switch (sio_data->kind) {
+	case f71805f:
+		data->has_in = 0x1ff;
+		break;
+	case f71872f:
+		data->has_in = 0x6ef;
+		if (sio_data->fnsel1 & 0x01)
+			data->has_in |= (1 << 4); /* in4 */
+		if (sio_data->fnsel1 & 0x02)
+			data->has_in |= (1 << 8); /* in8 */
+		break;
+	}
+
 	/* Initialize the F71805F chip */
 	f71805f_init_device(data);
 
 	/* Register sysfs interface files */
 	if ((err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group)))
 		goto exit_free;
-	for (i = 0; i < 3; i++) {
-		if (!(data->fan_enabled & (1 << i)))
-			continue;
+	if (data->has_in & (1 << 4)) { /* in4 */
 		if ((err = sysfs_create_group(&pdev->dev.kobj,
-					      &f71805f_group_fan[i])))
+					      &f71805f_group_optin[0])))
 			goto exit_remove_files;
 	}
+	if (data->has_in & (1 << 8)) { /* in8 */
+		if ((err = sysfs_create_group(&pdev->dev.kobj,
+					      &f71805f_group_optin[1])))
+			goto exit_remove_files;
+	}
+	if (data->has_in & (1 << 9)) { /* in9 (F71872F/FG only) */
+		if ((err = sysfs_create_group(&pdev->dev.kobj,
+					      &f71805f_group_optin[2])))
+			goto exit_remove_files;
+	}
+	if (data->has_in & (1 << 10)) { /* in9 (F71872F/FG only) */
+		if ((err = sysfs_create_group(&pdev->dev.kobj,
+					      &f71805f_group_optin[3])))
+			goto exit_remove_files;
+	}
+	for (i = 0; i < 3; i++) {
+		/* If control mode is PWM, create pwm_freq file */
+		if (!(data->fan_ctrl[i] & FAN_CTRL_DC_MODE)) {
+			if ((err = sysfs_create_file(&pdev->dev.kobj,
+					f71805f_attributes_pwm_freq[i])))
+				goto exit_remove_files;
+		}
+		/* If PWM is in manual mode, add write permission */
+		if (data->fan_ctrl[i] & FAN_CTRL_MODE_MANUAL) {
+			if ((err = sysfs_chmod_file(&pdev->dev.kobj,
+						    f71805f_attr_pwm[i],
+						    S_IRUGO | S_IWUSR))) {
+				dev_err(&pdev->dev, "chmod +w pwm%d failed\n",
+					i + 1);
+				goto exit_remove_files;
+			}
+		}
+	}
 
 	data->class_dev = hwmon_device_register(&pdev->dev);
 	if (IS_ERR(data->class_dev)) {
@@ -849,8 +1226,9 @@
 
 exit_remove_files:
 	sysfs_remove_group(&pdev->dev.kobj, &f71805f_group);
-	for (i = 0; i < 3; i++)
-		sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_fan[i]);
+	for (i = 0; i < 4; i++)
+		sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]);
+	sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq);
 exit_free:
 	platform_set_drvdata(pdev, NULL);
 	kfree(data);
@@ -866,8 +1244,9 @@
 	platform_set_drvdata(pdev, NULL);
 	hwmon_device_unregister(data->class_dev);
 	sysfs_remove_group(&pdev->dev.kobj, &f71805f_group);
-	for (i = 0; i < 3; i++)
-		sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_fan[i]);
+	for (i = 0; i < 4; i++)
+		sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]);
+	sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq);
 	kfree(data);
 
 	return 0;
@@ -882,7 +1261,8 @@
 	.remove		= __devexit_p(f71805f_remove),
 };
 
-static int __init f71805f_device_add(unsigned short address)
+static int __init f71805f_device_add(unsigned short address,
+				     const struct f71805f_sio_data *sio_data)
 {
 	struct resource res = {
 		.start	= address,
@@ -906,26 +1286,45 @@
 		goto exit_device_put;
 	}
 
+	pdev->dev.platform_data = kmalloc(sizeof(struct f71805f_sio_data),
+					  GFP_KERNEL);
+	if (!pdev->dev.platform_data) {
+		err = -ENOMEM;
+		printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
+		goto exit_device_put;
+	}
+	memcpy(pdev->dev.platform_data, sio_data,
+	       sizeof(struct f71805f_sio_data));
+
 	err = platform_device_add(pdev);
 	if (err) {
 		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
 		       err);
-		goto exit_device_put;
+		goto exit_kfree_data;
 	}
 
 	return 0;
 
+exit_kfree_data:
+	kfree(pdev->dev.platform_data);
+	pdev->dev.platform_data = NULL;
 exit_device_put:
 	platform_device_put(pdev);
 exit:
 	return err;
 }
 
-static int __init f71805f_find(int sioaddr, unsigned short *address)
+static int __init f71805f_find(int sioaddr, unsigned short *address,
+			       struct f71805f_sio_data *sio_data)
 {
 	int err = -ENODEV;
 	u16 devid;
 
+	static const char *names[] = {
+		"F71805F/FG",
+		"F71872F/FG",
+	};
+
 	superio_enter(sioaddr);
 
 	devid = superio_inw(sioaddr, SIO_REG_MANID);
@@ -933,7 +1332,15 @@
 		goto exit;
 
 	devid = superio_inw(sioaddr, SIO_REG_DEVID);
-	if (devid != SIO_F71805F_ID) {
+	switch (devid) {
+	case SIO_F71805F_ID:
+		sio_data->kind = f71805f;
+		break;
+	case SIO_F71872F_ID:
+		sio_data->kind = f71872f;
+		sio_data->fnsel1 = superio_inb(sioaddr, SIO_REG_FNSEL1);
+		break;
+	default:
 		printk(KERN_INFO DRVNAME ": Unsupported Fintek device, "
 		       "skipping\n");
 		goto exit;
@@ -952,10 +1359,12 @@
 		       "skipping\n");
 		goto exit;
 	}
+	*address &= ~(REGION_LENGTH - 1);	/* Ignore 3 LSB */
 
 	err = 0;
-	printk(KERN_INFO DRVNAME ": Found F71805F chip at %#x, revision %u\n",
-	       *address, superio_inb(sioaddr, SIO_REG_DEVREV));
+	printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %u\n",
+	       names[sio_data->kind], *address,
+	       superio_inb(sioaddr, SIO_REG_DEVREV));
 
 exit:
 	superio_exit(sioaddr);
@@ -966,9 +1375,10 @@
 {
 	int err;
 	unsigned short address;
+	struct f71805f_sio_data sio_data;
 
-	if (f71805f_find(0x2e, &address)
-	 && f71805f_find(0x4e, &address))
+	if (f71805f_find(0x2e, &address, &sio_data)
+	 && f71805f_find(0x4e, &address, &sio_data))
 		return -ENODEV;
 
 	err = platform_driver_register(&f71805f_driver);
@@ -976,7 +1386,7 @@
 		goto exit;
 
 	/* Sets global pdev as a side effect */
-	err = f71805f_device_add(address);
+	err = f71805f_device_add(address, &sio_data);
 	if (err)
 		goto exit_driver;
 
@@ -990,13 +1400,16 @@
 
 static void __exit f71805f_exit(void)
 {
+	kfree(pdev->dev.platform_data);
+	pdev->dev.platform_data = NULL;
 	platform_device_unregister(pdev);
+
 	platform_driver_unregister(&f71805f_driver);
 }
 
 MODULE_AUTHOR("Jean Delvare <khali@linux-fr>");
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("F71805F hardware monitoring driver");
+MODULE_DESCRIPTION("F71805F/F71872F hardware monitoring driver");
 
 module_init(f71805f_init);
 module_exit(f71805f_exit);
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
index e8ef62b..bf759ea 100644
--- a/drivers/hwmon/hdaps.c
+++ b/drivers/hwmon/hdaps.c
@@ -478,74 +478,64 @@
 /* Module stuff */
 
 /* hdaps_dmi_match - found a match.  return one, short-circuiting the hunt. */
-static int hdaps_dmi_match(struct dmi_system_id *id)
+static int __init hdaps_dmi_match(struct dmi_system_id *id)
 {
 	printk(KERN_INFO "hdaps: %s detected.\n", id->ident);
 	return 1;
 }
 
 /* hdaps_dmi_match_invert - found an inverted match. */
-static int hdaps_dmi_match_invert(struct dmi_system_id *id)
+static int __init hdaps_dmi_match_invert(struct dmi_system_id *id)
 {
 	hdaps_invert = 1;
 	printk(KERN_INFO "hdaps: inverting axis readings.\n");
 	return hdaps_dmi_match(id);
 }
 
-#define HDAPS_DMI_MATCH_NORMAL(model)	{		\
-	.ident = "IBM " model,				\
+#define HDAPS_DMI_MATCH_NORMAL(vendor, model) {		\
+	.ident = vendor " " model,			\
 	.callback = hdaps_dmi_match,			\
 	.matches = {					\
-		DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),	\
+		DMI_MATCH(DMI_BOARD_VENDOR, vendor),	\
 		DMI_MATCH(DMI_PRODUCT_VERSION, model)	\
 	}						\
 }
 
-#define HDAPS_DMI_MATCH_INVERT(model)	{		\
-	.ident = "IBM " model,				\
+#define HDAPS_DMI_MATCH_INVERT(vendor, model) {		\
+	.ident = vendor " " model,			\
 	.callback = hdaps_dmi_match_invert,		\
 	.matches = {					\
-		DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),	\
+		DMI_MATCH(DMI_BOARD_VENDOR, vendor),	\
 		DMI_MATCH(DMI_PRODUCT_VERSION, model)	\
 	}						\
 }
 
-#define HDAPS_DMI_MATCH_LENOVO(model)   {               \
-        .ident = "Lenovo " model,                       \
-        .callback = hdaps_dmi_match_invert,             \
-        .matches = {                                    \
-                DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),  \
-                DMI_MATCH(DMI_PRODUCT_VERSION, model)   \
-        }                                               \
-}
+/* Note that HDAPS_DMI_MATCH_NORMAL("ThinkPad T42") would match
+   "ThinkPad T42p", so the order of the entries matters.
+   If your ThinkPad is not recognized, please update to latest
+   BIOS. This is especially the case for some R52 ThinkPads. */
+static struct dmi_system_id __initdata hdaps_whitelist[] = {
+	HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad R50p"),
+	HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R50"),
+	HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R51"),
+	HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R52"),
+	HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T41p"),
+	HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T41"),
+	HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T42p"),
+	HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T42"),
+	HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T43"),
+	HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T60"),
+	HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X40"),
+	HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X41"),
+	HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X60"),
+	HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad Z60m"),
+	{ .ident = NULL }
+};
 
 static int __init hdaps_init(void)
 {
 	int ret;
 
-	/* Note that HDAPS_DMI_MATCH_NORMAL("ThinkPad T42") would match
-	  "ThinkPad T42p", so the order of the entries matters */
-	struct dmi_system_id hdaps_whitelist[] = {
-		HDAPS_DMI_MATCH_NORMAL("ThinkPad H"),
-		HDAPS_DMI_MATCH_INVERT("ThinkPad R50p"),
-		HDAPS_DMI_MATCH_NORMAL("ThinkPad R50"),
-		HDAPS_DMI_MATCH_NORMAL("ThinkPad R51"),
-		HDAPS_DMI_MATCH_NORMAL("ThinkPad R52"),
-		HDAPS_DMI_MATCH_NORMAL("ThinkPad H"),	 /* R52 (1846AQG) */
-		HDAPS_DMI_MATCH_INVERT("ThinkPad T41p"),
-		HDAPS_DMI_MATCH_NORMAL("ThinkPad T41"),
-		HDAPS_DMI_MATCH_INVERT("ThinkPad T42p"),
-		HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"),
-		HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"),
-		HDAPS_DMI_MATCH_LENOVO("ThinkPad T60p"),
-		HDAPS_DMI_MATCH_LENOVO("ThinkPad T60"),
-		HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"),
-		HDAPS_DMI_MATCH_NORMAL("ThinkPad X41"),
-		HDAPS_DMI_MATCH_LENOVO("ThinkPad X60"),
-		HDAPS_DMI_MATCH_NORMAL("ThinkPad Z60m"),
-		{ .ident = NULL }
-	};
-
 	if (!dmi_check_system(hdaps_whitelist)) {
 		printk(KERN_WARNING "hdaps: supported laptop not found!\n");
 		ret = -ENODEV;
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c
index 9d67320..31c4200 100644
--- a/drivers/hwmon/hwmon-vid.c
+++ b/drivers/hwmon/hwmon-vid.c
@@ -1,7 +1,7 @@
 /*
     hwmon-vid.c - VID/VRM/VRD voltage conversions
 
-    Copyright (c) 2004 Rudolf Marek <r.marek@sh.cvut.cz>
+    Copyright (c) 2004 Rudolf Marek <r.marek@assembler.cz>
 
     Partly imported from i2c-vid.h of the lm_sensors project
     Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
@@ -232,7 +232,7 @@
 EXPORT_SYMBOL(vid_from_reg);
 EXPORT_SYMBOL(vid_which_vrm);
 
-MODULE_AUTHOR("Rudolf Marek <r.marek@sh.cvut.cz>");
+MODULE_AUTHOR("Rudolf Marek <r.marek@assembler.cz>");
 
 MODULE_DESCRIPTION("hwmon-vid driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 323ef06..1ed8b7e 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -3,7 +3,7 @@
              monitoring.
 
     Supports: IT8705F  Super I/O chip w/LPC interface
-              IT8712F  Super I/O chip w/LPC interface & SMBus
+              IT8712F  Super I/O chip w/LPC interface
               IT8716F  Super I/O chip w/LPC interface
               IT8718F  Super I/O chip w/LPC interface
               Sis950   A clone of the IT8705F
@@ -41,12 +41,8 @@
 #include <asm/io.h>
 
 
-/* Addresses to scan */
-static unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END };
 static unsigned short isa_address;
-
-/* Insmod parameters */
-I2C_CLIENT_INSMOD_4(it87, it8712, it8716, it8718);
+enum chips { it87, it8712, it8716, it8718 };
 
 #define	REG	0x2e	/* The register to read/write */
 #define	DEV	0x07	/* Register: Logical device select */
@@ -162,8 +158,6 @@
 #define IT87_REG_TEMP_HIGH(nr) (0x40 + (nr) * 2)
 #define IT87_REG_TEMP_LOW(nr)  (0x41 + (nr) * 2)
 
-#define IT87_REG_I2C_ADDR      0x48
-
 #define IT87_REG_VIN_ENABLE    0x50
 #define IT87_REG_TEMP_ENABLE   0x51
 
@@ -242,33 +236,22 @@
 };
 
 
-static int it87_attach_adapter(struct i2c_adapter *adapter);
-static int it87_isa_attach_adapter(struct i2c_adapter *adapter);
-static int it87_detect(struct i2c_adapter *adapter, int address, int kind);
+static int it87_detect(struct i2c_adapter *adapter);
 static int it87_detach_client(struct i2c_client *client);
 
 static int it87_read_value(struct i2c_client *client, u8 reg);
-static int it87_write_value(struct i2c_client *client, u8 reg, u8 value);
+static void it87_write_value(struct i2c_client *client, u8 reg, u8 value);
 static struct it87_data *it87_update_device(struct device *dev);
 static int it87_check_pwm(struct i2c_client *client);
 static void it87_init_client(struct i2c_client *client, struct it87_data *data);
 
 
-static struct i2c_driver it87_driver = {
-	.driver = {
-		.name	= "it87",
-	},
-	.id		= I2C_DRIVERID_IT87,
-	.attach_adapter	= it87_attach_adapter,
-	.detach_client	= it87_detach_client,
-};
-
 static struct i2c_driver it87_isa_driver = {
 	.driver = {
 		.owner	= THIS_MODULE,
 		.name	= "it87-isa",
 	},
-	.attach_adapter	= it87_isa_attach_adapter,
+	.attach_adapter	= it87_detect,
 	.detach_client	= it87_detach_client,
 };
 
@@ -850,22 +833,6 @@
 	.attrs = it87_attributes_opt,
 };
 
-/* This function is called when:
-     * it87_driver is inserted (when this module is loaded), for each
-       available adapter
-     * when a new adapter is inserted (and it87_driver is still present) */
-static int it87_attach_adapter(struct i2c_adapter *adapter)
-{
-	if (!(adapter->class & I2C_CLASS_HWMON))
-		return 0;
-	return i2c_probe(adapter, &addr_data, it87_detect);
-}
-
-static int it87_isa_attach_adapter(struct i2c_adapter *adapter)
-{
-	return it87_detect(adapter, isa_address, -1);
-}
-
 /* SuperIO detection - will change isa_address if a chip is found */
 static int __init it87_find(unsigned short *address)
 {
@@ -916,29 +883,20 @@
 }
 
 /* This function is called by i2c_probe */
-static int it87_detect(struct i2c_adapter *adapter, int address, int kind)
+static int it87_detect(struct i2c_adapter *adapter)
 {
-	int i;
 	struct i2c_client *new_client;
 	struct it87_data *data;
 	int err = 0;
-	const char *name = "";
-	int is_isa = i2c_is_isa_adapter(adapter);
+	const char *name;
 	int enable_pwm_interface;
 
-	if (!is_isa && 
-	    !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
-		goto ERROR0;
-
 	/* Reserve the ISA region */
-	if (is_isa)
-		if (!request_region(address, IT87_EXTENT,
-				    it87_isa_driver.driver.name))
-			goto ERROR0;
-
-	/* For now, we presume we have a valid client. We create the
-	   client structure, even though we cannot fill it completely yet.
-	   But it allows us to access it87_{read,write}_value. */
+	if (!request_region(isa_address, IT87_EXTENT,
+			    it87_isa_driver.driver.name)){
+		err = -EBUSY;
+		goto ERROR0;
+	}
 
 	if (!(data = kzalloc(sizeof(struct it87_data), GFP_KERNEL))) {
 		err = -ENOMEM;
@@ -946,80 +904,46 @@
 	}
 
 	new_client = &data->client;
-	if (is_isa)
-		mutex_init(&data->lock);
+	mutex_init(&data->lock);
 	i2c_set_clientdata(new_client, data);
-	new_client->addr = address;
+	new_client->addr = isa_address;
 	new_client->adapter = adapter;
-	new_client->driver = is_isa ? &it87_isa_driver : &it87_driver;
-	new_client->flags = 0;
+	new_client->driver = &it87_isa_driver;
 
 	/* Now, we do the remaining detection. */
-
-	if (kind < 0) {
-		if ((it87_read_value(new_client, IT87_REG_CONFIG) & 0x80)
-		  || (!is_isa
-		   && it87_read_value(new_client, IT87_REG_I2C_ADDR) != address)) {
-		   	err = -ENODEV;
-			goto ERROR2;
-		}
+	if ((it87_read_value(new_client, IT87_REG_CONFIG) & 0x80)
+	 || it87_read_value(new_client, IT87_REG_CHIPID) != 0x90) {
+		err = -ENODEV;
+		goto ERROR2;
 	}
 
 	/* Determine the chip type. */
-	if (kind <= 0) {
-		i = it87_read_value(new_client, IT87_REG_CHIPID);
-		if (i == 0x90) {
-			kind = it87;
-			if (is_isa) {
-				switch (chip_type) {
-				case IT8712F_DEVID:
-					kind = it8712;
-					break;
-				case IT8716F_DEVID:
-					kind = it8716;
-					break;
-				case IT8718F_DEVID:
-					kind = it8718;
-					break;
-				}
-			}
-		}
-		else {
-			if (kind == 0)
-				dev_info(&adapter->dev, 
-					"Ignoring 'force' parameter for unknown chip at "
-					"adapter %d, address 0x%02x\n",
-					i2c_adapter_id(adapter), address);
-			err = -ENODEV;
-			goto ERROR2;
-		}
-	}
-
-	if (kind == it87) {
-		name = "it87";
-	} else if (kind == it8712) {
+	switch (chip_type) {
+	case IT8712F_DEVID:
+		data->type = it8712;
 		name = "it8712";
-	} else if (kind == it8716) {
+		break;
+	case IT8716F_DEVID:
+		data->type = it8716;
 		name = "it8716";
-	} else if (kind == it8718) {
+		break;
+	case IT8718F_DEVID:
+		data->type = it8718;
 		name = "it8718";
+		break;
+	default:
+		data->type = it87;
+		name = "it87";
 	}
 
 	/* Fill in the remaining client fields and put it into the global list */
 	strlcpy(new_client->name, name, I2C_NAME_SIZE);
-	data->type = kind;
-	data->valid = 0;
 	mutex_init(&data->update_lock);
 
 	/* Tell the I2C layer a new client has arrived */
 	if ((err = i2c_attach_client(new_client)))
 		goto ERROR2;
 
-	if (!is_isa)
-		dev_info(&new_client->dev, "The I2C interface to IT87xxF "
-			 "hardware monitoring chips is deprecated. Please "
-			 "report if you still rely on it.\n");
-
 	/* Check PWM configuration */
 	enable_pwm_interface = it87_check_pwm(new_client);
 
@@ -1129,8 +1053,7 @@
 ERROR2:
 	kfree(data);
 ERROR1:
-	if (is_isa)
-		release_region(address, IT87_EXTENT);
+	release_region(isa_address, IT87_EXTENT);
 ERROR0:
 	return err;
 }
@@ -1147,50 +1070,39 @@
 	if ((err = i2c_detach_client(client)))
 		return err;
 
-	if(i2c_is_isa_client(client))
-		release_region(client->addr, IT87_EXTENT);
+	release_region(client->addr, IT87_EXTENT);
 	kfree(data);
 
 	return 0;
 }
 
-/* The SMBus locks itself, but ISA access must be locked explicitly! 
-   We don't want to lock the whole ISA bus, so we lock each client
-   separately.
+/* ISA access must be locked explicitly!
    We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
    would slow down the IT87 access and should not be necessary. */
 static int it87_read_value(struct i2c_client *client, u8 reg)
 {
 	struct it87_data *data = i2c_get_clientdata(client);
-
 	int res;
-	if (i2c_is_isa_client(client)) {
-		mutex_lock(&data->lock);
-		outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET);
-		res = inb_p(client->addr + IT87_DATA_REG_OFFSET);
-		mutex_unlock(&data->lock);
-		return res;
-	} else
-		return i2c_smbus_read_byte_data(client, reg);
+
+	mutex_lock(&data->lock);
+	outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET);
+	res = inb_p(client->addr + IT87_DATA_REG_OFFSET);
+	mutex_unlock(&data->lock);
+
+	return res;
 }
 
-/* The SMBus locks itself, but ISA access muse be locked explicitly! 
-   We don't want to lock the whole ISA bus, so we lock each client
-   separately.
+/* ISA access must be locked explicitly!
    We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
    would slow down the IT87 access and should not be necessary. */
-static int it87_write_value(struct i2c_client *client, u8 reg, u8 value)
+static void it87_write_value(struct i2c_client *client, u8 reg, u8 value)
 {
 	struct it87_data *data = i2c_get_clientdata(client);
 
-	if (i2c_is_isa_client(client)) {
-		mutex_lock(&data->lock);
-		outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET);
-		outb_p(value, client->addr + IT87_DATA_REG_OFFSET);
-		mutex_unlock(&data->lock);
-		return 0;
-	} else
-		return i2c_smbus_write_byte_data(client, reg, value);
+	mutex_lock(&data->lock);
+	outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET);
+	outb_p(value, client->addr + IT87_DATA_REG_OFFSET);
+	mutex_unlock(&data->lock);
 }
 
 /* Return 1 if and only if the PWM interface is safe to use */
@@ -1426,26 +1338,14 @@
 {
 	int res;
 
-	res = i2c_add_driver(&it87_driver);
-	if (res)
+	if ((res = it87_find(&isa_address)))
 		return res;
-
-	if (!it87_find(&isa_address)) {
-		res = i2c_isa_add_driver(&it87_isa_driver);
-		if (res) {
-			i2c_del_driver(&it87_driver);
-			return res;
-		}
-	}
-
-	return 0;
+	return i2c_isa_add_driver(&it87_isa_driver);
 }
 
 static void __exit sm_it87_exit(void)
 {
-	if (isa_address)
-		i2c_isa_del_driver(&it87_isa_driver);
-	i2c_del_driver(&it87_driver);
+	i2c_isa_del_driver(&it87_isa_driver);
 }
 
 
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c
index f58b64e..5d8d0ca 100644
--- a/drivers/hwmon/k8temp.c
+++ b/drivers/hwmon/k8temp.c
@@ -1,7 +1,7 @@
 /*
  * k8temp.c - Linux kernel module for hardware monitoring
  *
- * Copyright (C) 2006 Rudolf Marek <r.marek@sh.cvut.cz>
+ * Copyright (C) 2006 Rudolf Marek <r.marek@assembler.cz>
  *
  * Inspired from the w83785 and amd756 drivers.
  *
@@ -286,7 +286,7 @@
 	pci_unregister_driver(&k8temp_driver);
 }
 
-MODULE_AUTHOR("Rudolf Marek <r.marek@sh.cvut.cz>");
+MODULE_AUTHOR("Rudolf Marek <r.marek@assembler.cz>");
 MODULE_DESCRIPTION("AMD K8 core temperature monitor");
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index 3b8b819..c8a21be 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -1000,7 +1000,7 @@
 			(i&0x02) ? "external" : "internal");
 
 		data->vid_conf = confreg[3];
-		data->vrm = 90;
+		data->vrm = vid_which_vrm();
 	}
 
 	/* Fan clock dividers may be needed before any data is read */
diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c
new file mode 100644
index 0000000..affa21a
--- /dev/null
+++ b/drivers/hwmon/pc87427.c
@@ -0,0 +1,627 @@
+/*
+ *  pc87427.c - hardware monitoring driver for the
+ *              National Semiconductor PC87427 Super-I/O chip
+ *  Copyright (C) 2006 Jean Delvare <khali@linux-fr.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  Supports the following chips:
+ *
+ *  Chip        #vin    #fan    #pwm    #temp   devid
+ *  PC87427     -       8       -       -       0xF2
+ *
+ *  This driver assumes that no more than one chip is present.
+ *  Only fan inputs are supported so far, although the chip can do much more.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
+#include <asm/io.h>
+
+static struct platform_device *pdev;
+
+#define DRVNAME "pc87427"
+
+/* The lock mutex protects both the I/O accesses (needed because the
+   device is using banked registers) and the register cache (needed to keep
+   the data in the registers and the cache in sync at any time). */
+struct pc87427_data {
+	struct class_device *class_dev;
+	struct mutex lock;
+	int address[2];
+	const char *name;
+
+	unsigned long last_updated;	/* in jiffies */
+	u8 fan_enabled;			/* bit vector */
+	u16 fan[8];			/* register values */
+	u16 fan_min[8];			/* register values */
+	u8 fan_status[8];		/* register values */
+};
+
+/*
+ * Super-I/O registers and operations
+ */
+
+#define SIOREG_LDSEL	0x07	/* Logical device select */
+#define SIOREG_DEVID	0x20	/* Device ID */
+#define SIOREG_ACT	0x30	/* Device activation */
+#define SIOREG_MAP	0x50	/* I/O or memory mapping */
+#define SIOREG_IOBASE	0x60	/* I/O base address */
+
+static const u8 logdev[2] = { 0x09, 0x14 };
+static const char *logdev_str[2] = { DRVNAME " FMC", DRVNAME " HMC" };
+#define LD_FAN		0
+#define LD_IN		1
+#define LD_TEMP		1
+
+static inline void superio_outb(int sioaddr, int reg, int val)
+{
+	outb(reg, sioaddr);
+	outb(val, sioaddr + 1);
+}
+
+static inline int superio_inb(int sioaddr, int reg)
+{
+	outb(reg, sioaddr);
+	return inb(sioaddr + 1);
+}
+
+static inline void superio_exit(int sioaddr)
+{
+	outb(0x02, sioaddr);
+	outb(0x02, sioaddr + 1);
+}
+
+/*
+ * Logical devices
+ */
+
+#define REGION_LENGTH		32
+#define PC87427_REG_BANK	0x0f
+#define BANK_FM(nr)		(nr)
+#define BANK_FT(nr)		(0x08 + (nr))
+#define BANK_FC(nr)		(0x10 + (nr) * 2)
+
+/*
+ * I/O access functions
+ */
+
+/* ldi is the logical device index */
+static inline int pc87427_read8(struct pc87427_data *data, u8 ldi, u8 reg)
+{
+	return inb(data->address[ldi] + reg);
+}
+
+/* Must be called with data->lock held, except during init */
+static inline int pc87427_read8_bank(struct pc87427_data *data, u8 ldi,
+				     u8 bank, u8 reg)
+{
+	outb(bank, data->address[ldi] + PC87427_REG_BANK);
+	return inb(data->address[ldi] + reg);
+}
+
+/* Must be called with data->lock held, except during init */
+static inline void pc87427_write8_bank(struct pc87427_data *data, u8 ldi,
+				       u8 bank, u8 reg, u8 value)
+{
+	outb(bank, data->address[ldi] + PC87427_REG_BANK);
+	outb(value, data->address[ldi] + reg);
+}
+
+/*
+ * Fan registers and conversions
+ */
+
+/* fan data registers are 16-bit wide */
+#define PC87427_REG_FAN			0x12
+#define PC87427_REG_FAN_MIN		0x14
+#define PC87427_REG_FAN_STATUS		0x10
+
+#define FAN_STATUS_STALL		(1 << 3)
+#define FAN_STATUS_LOSPD		(1 << 1)
+#define FAN_STATUS_MONEN		(1 << 0)
+
+/* Dedicated function to read all registers related to a given fan input.
+   This saves us quite a few locks and bank selections.
+   Must be called with data->lock held.
+   nr is from 0 to 7 */
+static void pc87427_readall_fan(struct pc87427_data *data, u8 nr)
+{
+	int iobase = data->address[LD_FAN];
+
+	outb(BANK_FM(nr), iobase + PC87427_REG_BANK);
+	data->fan[nr] = inw(iobase + PC87427_REG_FAN);
+	data->fan_min[nr] = inw(iobase + PC87427_REG_FAN_MIN);
+	data->fan_status[nr] = inb(iobase + PC87427_REG_FAN_STATUS);
+	/* Clear fan alarm bits */
+	outb(data->fan_status[nr], iobase + PC87427_REG_FAN_STATUS);
+}
+
+/* The 2 LSB of fan speed registers are used for something different.
+   The actual 2 LSB of the measurements are not available. */
+static inline unsigned long fan_from_reg(u16 reg)
+{
+	reg &= 0xfffc;
+	if (reg == 0x0000 || reg == 0xfffc)
+		return 0;
+	return 5400000UL / reg;
+}
+
+/* The 2 LSB of the fan speed limit registers are not significant. */
+static inline u16 fan_to_reg(unsigned long val)
+{
+	if (val < 83UL)
+		return 0xffff;
+	if (val >= 1350000UL)
+		return 0x0004;
+	return ((1350000UL + val / 2) / val) << 2;
+}
+
+/*
+ * Data interface
+ */
+
+static struct pc87427_data *pc87427_update_device(struct device *dev)
+{
+	struct pc87427_data *data = dev_get_drvdata(dev);
+	int i;
+
+	mutex_lock(&data->lock);
+	if (!time_after(jiffies, data->last_updated + HZ)
+	 && data->last_updated)
+		goto done;
+
+	/* Fans */
+	for (i = 0; i < 8; i++) {
+		if (!(data->fan_enabled & (1 << i)))
+			continue;
+		pc87427_readall_fan(data, i);
+	}
+	data->last_updated = jiffies;
+
+done:
+	mutex_unlock(&data->lock);
+	return data;
+}
+
+static ssize_t show_fan_input(struct device *dev, struct device_attribute
+			      *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pc87427_data *data = pc87427_update_device(dev);
+	int nr = attr->index;
+
+	return sprintf(buf, "%lu\n", fan_from_reg(data->fan[nr]));
+}
+
+static ssize_t show_fan_min(struct device *dev, struct device_attribute
+			    *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pc87427_data *data = pc87427_update_device(dev);
+	int nr = attr->index;
+
+	return sprintf(buf, "%lu\n", fan_from_reg(data->fan_min[nr]));
+}
+
+static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
+			      *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pc87427_data *data = pc87427_update_device(dev);
+	int nr = attr->index;
+
+	return sprintf(buf, "%d\n", !!(data->fan_status[nr]
+				       & FAN_STATUS_LOSPD));
+}
+
+static ssize_t show_fan_fault(struct device *dev, struct device_attribute
+			      *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pc87427_data *data = pc87427_update_device(dev);
+	int nr = attr->index;
+
+	return sprintf(buf, "%d\n", !!(data->fan_status[nr]
+				       & FAN_STATUS_STALL));
+}
+
+static ssize_t set_fan_min(struct device *dev, struct device_attribute
+			   *devattr, const char *buf, size_t count)
+{
+	struct pc87427_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+	int iobase = data->address[LD_FAN];
+
+	mutex_lock(&data->lock);
+	outb(BANK_FM(nr), iobase + PC87427_REG_BANK);
+	/* The low speed limit registers are read-only while monitoring
+	   is enabled, so we have to disable monitoring, then change the
+	   limit, and finally enable monitoring again. */
+	outb(0, iobase + PC87427_REG_FAN_STATUS);
+	data->fan_min[nr] = fan_to_reg(val);
+	outw(data->fan_min[nr], iobase + PC87427_REG_FAN_MIN);
+	outb(FAN_STATUS_MONEN, iobase + PC87427_REG_FAN_STATUS);
+	mutex_unlock(&data->lock);
+
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan_input, NULL, 3);
+static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan_input, NULL, 4);
+static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan_input, NULL, 5);
+static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan_input, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan_input, NULL, 7);
+
+static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO,
+			  show_fan_min, set_fan_min, 0);
+static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO,
+			  show_fan_min, set_fan_min, 1);
+static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO,
+			  show_fan_min, set_fan_min, 2);
+static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO,
+			  show_fan_min, set_fan_min, 3);
+static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO,
+			  show_fan_min, set_fan_min, 4);
+static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO,
+			  show_fan_min, set_fan_min, 5);
+static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO,
+			  show_fan_min, set_fan_min, 6);
+static SENSOR_DEVICE_ATTR(fan8_min, S_IWUSR | S_IRUGO,
+			  show_fan_min, set_fan_min, 7);
+
+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_fan_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_fan_alarm, NULL, 5);
+static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_fan_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_fan_alarm, NULL, 7);
+
+static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_fan_fault, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, show_fan_fault, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, show_fan_fault, NULL, 3);
+static SENSOR_DEVICE_ATTR(fan5_fault, S_IRUGO, show_fan_fault, NULL, 4);
+static SENSOR_DEVICE_ATTR(fan6_fault, S_IRUGO, show_fan_fault, NULL, 5);
+static SENSOR_DEVICE_ATTR(fan7_fault, S_IRUGO, show_fan_fault, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan8_fault, S_IRUGO, show_fan_fault, NULL, 7);
+
+static struct attribute *pc87427_attributes_fan[8][5] = {
+	{
+		&sensor_dev_attr_fan1_input.dev_attr.attr,
+		&sensor_dev_attr_fan1_min.dev_attr.attr,
+		&sensor_dev_attr_fan1_alarm.dev_attr.attr,
+		&sensor_dev_attr_fan1_fault.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_fan2_input.dev_attr.attr,
+		&sensor_dev_attr_fan2_min.dev_attr.attr,
+		&sensor_dev_attr_fan2_alarm.dev_attr.attr,
+		&sensor_dev_attr_fan2_fault.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_fan3_input.dev_attr.attr,
+		&sensor_dev_attr_fan3_min.dev_attr.attr,
+		&sensor_dev_attr_fan3_alarm.dev_attr.attr,
+		&sensor_dev_attr_fan3_fault.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_fan4_input.dev_attr.attr,
+		&sensor_dev_attr_fan4_min.dev_attr.attr,
+		&sensor_dev_attr_fan4_alarm.dev_attr.attr,
+		&sensor_dev_attr_fan4_fault.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_fan5_input.dev_attr.attr,
+		&sensor_dev_attr_fan5_min.dev_attr.attr,
+		&sensor_dev_attr_fan5_alarm.dev_attr.attr,
+		&sensor_dev_attr_fan5_fault.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_fan6_input.dev_attr.attr,
+		&sensor_dev_attr_fan6_min.dev_attr.attr,
+		&sensor_dev_attr_fan6_alarm.dev_attr.attr,
+		&sensor_dev_attr_fan6_fault.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_fan7_input.dev_attr.attr,
+		&sensor_dev_attr_fan7_min.dev_attr.attr,
+		&sensor_dev_attr_fan7_alarm.dev_attr.attr,
+		&sensor_dev_attr_fan7_fault.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_fan8_input.dev_attr.attr,
+		&sensor_dev_attr_fan8_min.dev_attr.attr,
+		&sensor_dev_attr_fan8_alarm.dev_attr.attr,
+		&sensor_dev_attr_fan8_fault.dev_attr.attr,
+		NULL
+	}
+};
+
+static const struct attribute_group pc87427_group_fan[8] = {
+	{ .attrs = pc87427_attributes_fan[0] },
+	{ .attrs = pc87427_attributes_fan[1] },
+	{ .attrs = pc87427_attributes_fan[2] },
+	{ .attrs = pc87427_attributes_fan[3] },
+	{ .attrs = pc87427_attributes_fan[4] },
+	{ .attrs = pc87427_attributes_fan[5] },
+	{ .attrs = pc87427_attributes_fan[6] },
+	{ .attrs = pc87427_attributes_fan[7] },
+};
+
+static ssize_t show_name(struct device *dev, struct device_attribute
+			 *devattr, char *buf)
+{
+	struct pc87427_data *data = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%s\n", data->name);
+}
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+
+/*
+ * Device detection, attach and detach
+ */
+
+static void __devinit pc87427_init_device(struct device *dev)
+{
+	struct pc87427_data *data = dev_get_drvdata(dev);
+	int i;
+	u8 reg;
+
+	/* The FMC module should be ready */
+	reg = pc87427_read8(data, LD_FAN, PC87427_REG_BANK);
+	if (!(reg & 0x80))
+		dev_warn(dev, "FMC module not ready!\n");
+
+	/* Check which fans are enabled */
+	for (i = 0; i < 8; i++) {
+		reg = pc87427_read8_bank(data, LD_FAN, BANK_FM(i),
+					 PC87427_REG_FAN_STATUS);
+		if (reg & FAN_STATUS_MONEN)
+			data->fan_enabled |= (1 << i);
+	}
+
+	if (!data->fan_enabled) {
+		dev_dbg(dev, "Enabling all fan inputs\n");
+		for (i = 0; i < 8; i++)
+			pc87427_write8_bank(data, LD_FAN, BANK_FM(i),
+					    PC87427_REG_FAN_STATUS,
+					    FAN_STATUS_MONEN);
+		data->fan_enabled = 0xff;
+	}
+}
+
+static int __devinit pc87427_probe(struct platform_device *pdev)
+{
+	struct pc87427_data *data;
+	struct resource *res;
+	int i, err;
+
+	if (!(data = kzalloc(sizeof(struct pc87427_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		printk(KERN_ERR DRVNAME ": Out of memory\n");
+		goto exit;
+	}
+
+	/* This will need to be revisited when we add support for
+	   temperature and voltage monitoring. */
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	data->address[0] = res->start;
+
+	mutex_init(&data->lock);
+	data->name = "pc87427";
+	platform_set_drvdata(pdev, data);
+	pc87427_init_device(&pdev->dev);
+
+	/* Register sysfs hooks */
+	if ((err = device_create_file(&pdev->dev, &dev_attr_name)))
+		goto exit_kfree;
+	for (i = 0; i < 8; i++) {
+		if (!(data->fan_enabled & (1 << i)))
+			continue;
+		if ((err = sysfs_create_group(&pdev->dev.kobj,
+					      &pc87427_group_fan[i])))
+			goto exit_remove_files;
+	}
+
+	data->class_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
+		goto exit_remove_files;
+	}
+
+	return 0;
+
+exit_remove_files:
+	for (i = 0; i < 8; i++) {
+		if (!(data->fan_enabled & (1 << i)))
+			continue;
+		sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
+	}
+exit_kfree:
+	platform_set_drvdata(pdev, NULL);
+	kfree(data);
+exit:
+	return err;
+}
+
+static int __devexit pc87427_remove(struct platform_device *pdev)
+{
+	struct pc87427_data *data = platform_get_drvdata(pdev);
+	int i;
+
+	platform_set_drvdata(pdev, NULL);
+	hwmon_device_unregister(data->class_dev);
+	device_remove_file(&pdev->dev, &dev_attr_name);
+	for (i = 0; i < 8; i++) {
+		if (!(data->fan_enabled & (1 << i)))
+			continue;
+		sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
+	}
+	kfree(data);
+
+	return 0;
+}
+
+
+static struct platform_driver pc87427_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= DRVNAME,
+	},
+	.probe		= pc87427_probe,
+	.remove		= __devexit_p(pc87427_remove),
+};
+
+static int __init pc87427_device_add(unsigned short address)
+{
+	struct resource res = {
+		.start	= address,
+		.end	= address + REGION_LENGTH - 1,
+		.name	= logdev_str[0],
+		.flags	= IORESOURCE_IO,
+	};
+	int err;
+
+	pdev = platform_device_alloc(DRVNAME, address);
+	if (!pdev) {
+		err = -ENOMEM;
+		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+		goto exit;
+	}
+
+	err = platform_device_add_resources(pdev, &res, 1);
+	if (err) {
+		printk(KERN_ERR DRVNAME ": Device resource addition failed "
+		       "(%d)\n", err);
+		goto exit_device_put;
+	}
+
+	err = platform_device_add(pdev);
+	if (err) {
+		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
+		       err);
+		goto exit_device_put;
+	}
+
+	return 0;
+
+exit_device_put:
+	platform_device_put(pdev);
+exit:
+	return err;
+}
+
+static int __init pc87427_find(int sioaddr, unsigned short *address)
+{
+	u16 val;
+	int i, err = 0;
+
+	/* Identify device */
+	val = superio_inb(sioaddr, SIOREG_DEVID);
+	if (val != 0xf2) {	/* PC87427 */
+		err = -ENODEV;
+		goto exit;
+	}
+
+	for (i = 0; i < 2; i++) {
+		address[i] = 0;
+		/* Select logical device */
+		superio_outb(sioaddr, SIOREG_LDSEL, logdev[i]);
+
+		val = superio_inb(sioaddr, SIOREG_ACT);
+		if (!(val & 0x01)) {
+			printk(KERN_INFO DRVNAME ": Logical device 0x%02x "
+			       "not activated\n", logdev[i]);
+			continue;
+		}
+
+		val = superio_inb(sioaddr, SIOREG_MAP);
+		if (val & 0x01) {
+			printk(KERN_WARNING DRVNAME ": Logical device 0x%02x "
+			       "is memory-mapped, can't use\n", logdev[i]);
+			continue;
+		}
+
+		val = (superio_inb(sioaddr, SIOREG_IOBASE) << 8)
+		    | superio_inb(sioaddr, SIOREG_IOBASE + 1);
+		if (!val) {
+			printk(KERN_INFO DRVNAME ": I/O base address not set "
+			       "for logical device 0x%02x\n", logdev[i]);
+			continue;
+		}
+		address[i] = val;
+	}
+
+exit:
+	superio_exit(sioaddr);
+	return err;
+}
+
+static int __init pc87427_init(void)
+{
+	int err;
+	unsigned short address[2];
+
+	if (pc87427_find(0x2e, address)
+	 && pc87427_find(0x4e, address))
+		return -ENODEV;
+
+	/* For now the driver only handles fans so we only care about the
+	   first address. */
+	if (!address[0])
+		return -ENODEV;
+
+	err = platform_driver_register(&pc87427_driver);
+	if (err)
+		goto exit;
+
+	/* Sets global pdev as a side effect */
+	err = pc87427_device_add(address[0]);
+	if (err)
+		goto exit_driver;
+
+	return 0;
+
+exit_driver:
+	platform_driver_unregister(&pc87427_driver);
+exit:
+	return err;
+}
+
+static void __exit pc87427_exit(void)
+{
+	platform_device_unregister(pdev);
+	platform_driver_unregister(&pc87427_driver);
+}
+
+MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
+MODULE_DESCRIPTION("PC87427 hardware monitoring driver");
+MODULE_LICENSE("GPL");
+
+module_init(pc87427_init);
+module_exit(pc87427_exit);
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 2257806..212a155 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -3,7 +3,7 @@
                 the Winbond W83627EHF Super-I/O chip
     Copyright (C) 2005  Jean Delvare <khali@linux-fr.org>
     Copyright (C) 2006  Yuan Mu (Winbond),
-                        Rudolf Marek <r.marek@sh.cvut.cz>
+                        Rudolf Marek <r.marek@assembler.cz>
                         David Hubbard <david.c.hubbard@gmail.com>
 
     Shamelessly ripped from the w83627hf driver
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index 4e10826..b0fa296 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -3,7 +3,7 @@
                 monitoring
     Copyright (C) 2004, 2005 Winbond Electronics Corp.
                         Chunhao Huang <DZShen@Winbond.com.tw>,
-                        Rudolf Marek <r.marek@sh.cvut.cz>
+                        Rudolf Marek <r.marek@assembler.cz>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c
new file mode 100644
index 0000000..c12ac5a
--- /dev/null
+++ b/drivers/hwmon/w83793.c
@@ -0,0 +1,1609 @@
+/*
+    w83793.c - Linux kernel driver for hardware monitoring
+    Copyright (C) 2006 Winbond Electronics Corp.
+                  Yuan Mu
+                  Rudolf Marek <r.marek@assembler.cz>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation - version 2.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301 USA.
+*/
+
+/*
+    Supports following chips:
+
+    Chip	#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA
+    w83793	10	12	8	6	0x7b	0x5ca3	yes	no
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_1(w83793);
+I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
+		       "{bus, clientaddr, subclientaddr1, subclientaddr2}");
+
+static int reset;
+module_param(reset, bool, 0);
+MODULE_PARM_DESC(reset, "Set to 1 to reset chip, not recommended");
+
+/*
+   Address 0x00, 0x0d, 0x0e, 0x0f in all three banks are reserved
+   as ID, Bank Select registers
+*/
+#define W83793_REG_BANKSEL		0x00
+#define W83793_REG_VENDORID		0x0d
+#define W83793_REG_CHIPID		0x0e
+#define W83793_REG_DEVICEID		0x0f
+
+#define W83793_REG_CONFIG		0x40
+#define W83793_REG_MFC			0x58
+#define W83793_REG_FANIN_CTRL		0x5c
+#define W83793_REG_FANIN_SEL		0x5d
+#define W83793_REG_I2C_ADDR		0x0b
+#define W83793_REG_I2C_SUBADDR		0x0c
+#define W83793_REG_VID_INA		0x05
+#define W83793_REG_VID_INB		0x06
+#define W83793_REG_VID_LATCHA		0x07
+#define W83793_REG_VID_LATCHB		0x08
+#define W83793_REG_VID_CTRL		0x59
+
+static u16 W83793_REG_TEMP_MODE[2] = { 0x5e, 0x5f };
+
+#define TEMP_READ	0
+#define TEMP_CRIT	1
+#define TEMP_CRIT_HYST	2
+#define TEMP_WARN	3
+#define TEMP_WARN_HYST	4
+/* only crit and crit_hyst affect real-time alarm status
+   current crit crit_hyst warn warn_hyst */
+static u16 W83793_REG_TEMP[][5] = {
+	{0x1c, 0x78, 0x79, 0x7a, 0x7b},
+	{0x1d, 0x7c, 0x7d, 0x7e, 0x7f},
+	{0x1e, 0x80, 0x81, 0x82, 0x83},
+	{0x1f, 0x84, 0x85, 0x86, 0x87},
+	{0x20, 0x88, 0x89, 0x8a, 0x8b},
+	{0x21, 0x8c, 0x8d, 0x8e, 0x8f},
+};
+
+#define W83793_REG_TEMP_LOW_BITS	0x22
+
+#define W83793_REG_BEEP(index)		(0x53 + (index))
+#define W83793_REG_ALARM(index)		(0x4b + (index))
+
+#define W83793_REG_CLR_CHASSIS		0x4a	/* SMI MASK4 */
+#define W83793_REG_IRQ_CTRL		0x50
+#define W83793_REG_OVT_CTRL		0x51
+#define W83793_REG_OVT_BEEP		0x52
+
+#define IN_READ				0
+#define IN_MAX				1
+#define IN_LOW				2
+static const u16 W83793_REG_IN[][3] = {
+	/* Current, High, Low */
+	{0x10, 0x60, 0x61},	/* Vcore A	*/
+	{0x11, 0x62, 0x63},	/* Vcore B	*/
+	{0x12, 0x64, 0x65},	/* Vtt		*/
+	{0x14, 0x6a, 0x6b},	/* VSEN1	*/
+	{0x15, 0x6c, 0x6d},	/* VSEN2	*/
+	{0x16, 0x6e, 0x6f},	/* +3VSEN	*/
+	{0x17, 0x70, 0x71},	/* +12VSEN	*/
+	{0x18, 0x72, 0x73},	/* 5VDD		*/
+	{0x19, 0x74, 0x75},	/* 5VSB		*/
+	{0x1a, 0x76, 0x77},	/* VBAT		*/
+};
+
+/* Low Bits of Vcore A/B Vtt Read/High/Low */
+static const u16 W83793_REG_IN_LOW_BITS[] = { 0x1b, 0x68, 0x69 };
+static u8 scale_in[] = { 2, 2, 2, 16, 16, 16, 8, 24, 24, 16 };
+
+#define W83793_REG_FAN(index)		(0x23 + 2 * (index))	/* High byte */
+#define W83793_REG_FAN_MIN(index)	(0x90 + 2 * (index))	/* High byte */
+
+#define W83793_REG_PWM_DEFAULT		0xb2
+#define W83793_REG_PWM_ENABLE		0x207
+#define W83793_REG_PWM_UPTIME		0xc3	/* Unit in 0.1 second */
+#define W83793_REG_PWM_DOWNTIME		0xc4	/* Unit in 0.1 second */
+#define W83793_REG_TEMP_CRITICAL	0xc5
+
+#define PWM_DUTY			0
+#define PWM_START			1
+#define PWM_NONSTOP			2
+#define W83793_REG_PWM(index, nr)	(((nr) == 0 ? 0xb3 : \
+					 (nr) == 1 ? 0x220 : 0x218) + (index))
+
+/* bit field, fan1 is bit0, fan2 is bit1 ... */
+#define W83793_REG_TEMP_FAN_MAP(index)	(0x201 + (index))
+#define W83793_REG_TEMP_TOL(index)	(0x208 + (index))
+#define W83793_REG_TEMP_CRUISE(index)	(0x210 + (index))
+#define W83793_REG_PWM_STOP_TIME(index)	(0x228 + (index))
+#define W83793_REG_SF2_TEMP(index, nr)	(0x230 + ((index) << 4) + (nr))
+#define W83793_REG_SF2_PWM(index, nr)	(0x238 + ((index) << 4) + (nr))
+
+static inline unsigned long FAN_FROM_REG(u16 val)
+{
+	if ((val >= 0xfff) || (val == 0))
+		return	0;
+	return (1350000UL / val);
+}
+
+static inline u16 FAN_TO_REG(long rpm)
+{
+	if (rpm <= 0)
+		return 0x0fff;
+	return SENSORS_LIMIT((1350000 + (rpm >> 1)) / rpm, 1, 0xffe);
+}
+
+static inline unsigned long TIME_FROM_REG(u8 reg)
+{
+	return (reg * 100);
+}
+
+static inline u8 TIME_TO_REG(unsigned long val)
+{
+	return SENSORS_LIMIT((val + 50) / 100, 0, 0xff);
+}
+
+static inline long TEMP_FROM_REG(s8 reg)
+{
+	return (reg * 1000);
+}
+
+static inline s8 TEMP_TO_REG(long val, s8 min, s8 max)
+{
+	return SENSORS_LIMIT((val + (val < 0 ? -500 : 500)) / 1000, min, max);
+}
+
+struct w83793_data {
+	struct i2c_client client;
+	struct i2c_client *lm75[2];
+	struct class_device *class_dev;
+	struct mutex update_lock;
+	char valid;			/* !=0 if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+	unsigned long last_nonvolatile;	/* In jiffies, last time we update the
+					   nonvolatile registers */
+
+	u8 bank;
+	u8 vrm;
+	u8 vid[2];
+	u8 in[10][3];		/* Register value, read/high/low */
+	u8 in_low_bits[3];	/* Additional resolution for VCore A/B Vtt */
+
+	u16 has_fan;		/* Only fan1- fan5 has own pins */
+	u16 fan[12];		/* Register value combine */
+	u16 fan_min[12];	/* Register value combine */
+
+	s8 temp[6][5];		/* current, crit, crit_hyst,warn, warn_hyst */
+	u8 temp_low_bits;	/* Additional resolution TD1-TD4 */
+	u8 temp_mode[2];	/* byte 0: Temp D1-D4 mode each has 2 bits
+				   byte 1: Temp R1,R2 mode, each has 1 bit */
+	u8 temp_critical;	/* If reached all fan will be at full speed */
+	u8 temp_fan_map[6];	/* Temp controls which pwm fan, bit field */
+
+	u8 has_pwm;
+	u8 pwm_enable;		/* Register value, each Temp has 1 bit */
+	u8 pwm_uptime;		/* Register value */
+	u8 pwm_downtime;	/* Register value */
+	u8 pwm_default;		/* All fan default pwm, next poweron valid */
+	u8 pwm[8][3];		/* Register value */
+	u8 pwm_stop_time[8];
+	u8 temp_cruise[6];
+
+	u8 alarms[5];		/* realtime status registers */
+	u8 beeps[5];
+	u8 beep_enable;
+	u8 tolerance[3];	/* Temp tolerance(Smart Fan I/II) */
+	u8 sf2_pwm[6][7];	/* Smart FanII: Fan duty cycle */
+	u8 sf2_temp[6][7];	/* Smart FanII: Temp level point */
+};
+
+static u8 w83793_read_value(struct i2c_client *client, u16 reg);
+static int w83793_write_value(struct i2c_client *client, u16 reg, u8 value);
+static int w83793_attach_adapter(struct i2c_adapter *adapter);
+static int w83793_detect(struct i2c_adapter *adapter, int address, int kind);
+static int w83793_detach_client(struct i2c_client *client);
+static void w83793_init_client(struct i2c_client *client);
+static void w83793_update_nonvolatile(struct device *dev);
+static struct w83793_data *w83793_update_device(struct device *dev);
+
+static struct i2c_driver w83793_driver = {
+	.driver = {
+		   .name = "w83793",
+	},
+	.attach_adapter = w83793_attach_adapter,
+	.detach_client = w83793_detach_client,
+};
+
+static ssize_t
+show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83793_data *data = i2c_get_clientdata(client);
+
+	return sprintf(buf, "%d\n", data->vrm);
+}
+
+static ssize_t
+show_vid(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct w83793_data *data = w83793_update_device(dev);
+	struct sensor_device_attribute_2 *sensor_attr =
+	    to_sensor_dev_attr_2(attr);
+	int index = sensor_attr->index;
+
+	return sprintf(buf, "%d\n", vid_from_reg(data->vid[index], data->vrm));
+}
+
+static ssize_t
+store_vrm(struct device *dev, struct device_attribute *attr,
+	  const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83793_data *data = i2c_get_clientdata(client);
+
+	data->vrm = simple_strtoul(buf, NULL, 10);
+	return count;
+}
+
+#define ALARM_STATUS			0
+#define BEEP_ENABLE			1
+static ssize_t
+show_alarm_beep(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct w83793_data *data = w83793_update_device(dev);
+	struct sensor_device_attribute_2 *sensor_attr =
+	    to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int index = sensor_attr->index >> 3;
+	int bit = sensor_attr->index & 0x07;
+	u8 val;
+
+	if (ALARM_STATUS == nr) {
+		val = (data->alarms[index] >> (bit)) & 1;
+	} else {		/* BEEP_ENABLE */
+		val = (data->beeps[index] >> (bit)) & 1;
+	}
+
+	return sprintf(buf, "%u\n", val);
+}
+
+static ssize_t
+store_beep(struct device *dev, struct device_attribute *attr,
+	   const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83793_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute_2 *sensor_attr =
+	    to_sensor_dev_attr_2(attr);
+	int index = sensor_attr->index >> 3;
+	int shift = sensor_attr->index & 0x07;
+	u8 beep_bit = 1 << shift;
+	u8 val;
+
+	val = simple_strtoul(buf, NULL, 10);
+	if (val != 0 && val != 1)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	data->beeps[index] = w83793_read_value(client, W83793_REG_BEEP(index));
+	data->beeps[index] &= ~beep_bit;
+	data->beeps[index] |= val << shift;
+	w83793_write_value(client, W83793_REG_BEEP(index), data->beeps[index]);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t
+show_beep_enable(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct w83793_data *data = w83793_update_device(dev);
+	return sprintf(buf, "%u\n", (data->beep_enable >> 1) & 0x01);
+}
+
+static ssize_t
+store_beep_enable(struct device *dev, struct device_attribute *attr,
+		  const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83793_data *data = i2c_get_clientdata(client);
+	u8 val = simple_strtoul(buf, NULL, 10);
+
+	if (val != 0 && val != 1)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	data->beep_enable = w83793_read_value(client, W83793_REG_OVT_BEEP)
+			    & 0xfd;
+	data->beep_enable |= val << 1;
+	w83793_write_value(client, W83793_REG_OVT_BEEP, data->beep_enable);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+/* Write any value to clear chassis alarm */
+static ssize_t
+store_chassis_clear(struct device *dev,
+		    struct device_attribute *attr, const char *buf,
+		    size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83793_data *data = i2c_get_clientdata(client);
+	u8 val;
+
+	mutex_lock(&data->update_lock);
+	val = w83793_read_value(client, W83793_REG_CLR_CHASSIS);
+	val |= 0x80;
+	w83793_write_value(client, W83793_REG_CLR_CHASSIS, val);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+#define FAN_INPUT			0
+#define FAN_MIN				1
+static ssize_t
+show_fan(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct sensor_device_attribute_2 *sensor_attr =
+	    to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int index = sensor_attr->index;
+	struct w83793_data *data = w83793_update_device(dev);
+	u16 val;
+
+	if (FAN_INPUT == nr) {
+		val = data->fan[index] & 0x0fff;
+	} else {
+		val = data->fan_min[index] & 0x0fff;
+	}
+
+	return sprintf(buf, "%lu\n", FAN_FROM_REG(val));
+}
+
+static ssize_t
+store_fan_min(struct device *dev, struct device_attribute *attr,
+	      const char *buf, size_t count)
+{
+	struct sensor_device_attribute_2 *sensor_attr =
+	    to_sensor_dev_attr_2(attr);
+	int index = sensor_attr->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83793_data *data = i2c_get_clientdata(client);
+	u16 val = FAN_TO_REG(simple_strtoul(buf, NULL, 10));
+
+	mutex_lock(&data->update_lock);
+	data->fan_min[index] = val;
+	w83793_write_value(client, W83793_REG_FAN_MIN(index),
+			   (val >> 8) & 0xff);
+	w83793_write_value(client, W83793_REG_FAN_MIN(index) + 1, val & 0xff);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+#define PWM_DUTY			0
+#define PWM_START			1
+#define PWM_NONSTOP			2
+#define PWM_STOP_TIME			3
+static ssize_t
+show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct sensor_device_attribute_2 *sensor_attr =
+	    to_sensor_dev_attr_2(attr);
+	struct w83793_data *data = w83793_update_device(dev);
+	u16 val;
+	int nr = sensor_attr->nr;
+	int index = sensor_attr->index;
+
+	if (PWM_STOP_TIME == nr)
+		val = TIME_FROM_REG(data->pwm_stop_time[index]);
+	else
+		val = (data->pwm[index][nr] & 0x3f) << 2;
+
+	return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t
+store_pwm(struct device *dev, struct device_attribute *attr,
+	  const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83793_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute_2 *sensor_attr =
+	    to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int index = sensor_attr->index;
+	u8 val;
+
+	mutex_lock(&data->update_lock);
+	if (PWM_STOP_TIME == nr) {
+		val = TIME_TO_REG(simple_strtoul(buf, NULL, 10));
+		data->pwm_stop_time[index] = val;
+		w83793_write_value(client, W83793_REG_PWM_STOP_TIME(index),
+				   val);
+	} else {
+		val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 0xff)
+		      >> 2;
+		data->pwm[index][nr] =
+		    w83793_read_value(client, W83793_REG_PWM(index, nr)) & 0xc0;
+		data->pwm[index][nr] |= val;
+		w83793_write_value(client, W83793_REG_PWM(index, nr),
+							data->pwm[index][nr]);
+	}
+
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+show_temp(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct sensor_device_attribute_2 *sensor_attr =
+	    to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int index = sensor_attr->index;
+	struct w83793_data *data = w83793_update_device(dev);
+	long temp = TEMP_FROM_REG(data->temp[index][nr]);
+
+	if (TEMP_READ == nr && index < 4) {	/* Only TD1-TD4 have low bits */
+		int low = ((data->temp_low_bits >> (index * 2)) & 0x03) * 250;
+		temp += temp > 0 ? low : -low;
+	}
+	return sprintf(buf, "%ld\n", temp);
+}
+
+static ssize_t
+store_temp(struct device *dev, struct device_attribute *attr,
+	   const char *buf, size_t count)
+{
+	struct sensor_device_attribute_2 *sensor_attr =
+	    to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int index = sensor_attr->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83793_data *data = i2c_get_clientdata(client);
+	long tmp = simple_strtol(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	data->temp[index][nr] = TEMP_TO_REG(tmp, -128, 127);
+	w83793_write_value(client, W83793_REG_TEMP[index][nr],
+			   data->temp[index][nr]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+/*
+	TD1-TD4
+	each has 4 mode:(2 bits)
+	0:	Stop monitor
+	1:	Use internal temp sensor(default)
+	2:	Use sensor in AMD CPU and get result by AMDSI
+	3:	Use sensor in Intel CPU and get result by PECI
+
+	TR1-TR2
+	each has 2 mode:(1 bit)
+	0:	Disable temp sensor monitor
+	1:	To enable temp sensors monitor
+*/
+
+/* 0 disable, 5 AMDSI, 6 PECI */
+static u8 TO_TEMP_MODE[] = { 0, 0, 5, 6 };
+
+static ssize_t
+show_temp_mode(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct w83793_data *data = w83793_update_device(dev);
+	struct sensor_device_attribute_2 *sensor_attr =
+	    to_sensor_dev_attr_2(attr);
+	int index = sensor_attr->index;
+	u8 mask = (index < 4) ? 0x03 : 0x01;
+	u8 shift = (index < 4) ? (2 * index) : (index - 4);
+	u8 tmp;
+	index = (index < 4) ? 0 : 1;
+
+	tmp = (data->temp_mode[index] >> shift) & mask;
+
+	/* for the internal sensor, found out if diode or thermistor */
+	if (tmp == 1) {
+		tmp = index == 0 ? 3 : 4;
+	} else {
+		tmp = TO_TEMP_MODE[tmp];
+	}
+
+	return sprintf(buf, "%d\n", tmp);
+}
+
+static ssize_t
+store_temp_mode(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83793_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute_2 *sensor_attr =
+	    to_sensor_dev_attr_2(attr);
+	int index = sensor_attr->index;
+	u8 mask = (index < 4) ? 0x03 : 0x01;
+	u8 shift = (index < 4) ? (2 * index) : (index - 4);
+	u8 val = simple_strtoul(buf, NULL, 10);
+
+	/* transform the sysfs interface values into table above */
+	if ((val == 5 || val == 6) && (index < 4)) {
+		val -= 3;
+	} else if ((val == 3 && index < 4)
+		|| (val == 4 && index >= 4)
+		|| val == 0) {
+		/* transform diode or thermistor into internal enable */
+		val = !!val;
+	} else {
+		return -EINVAL;
+	}
+
+	index = (index < 4) ? 0 : 1;
+	mutex_lock(&data->update_lock);
+	data->temp_mode[index] =
+	    w83793_read_value(client, W83793_REG_TEMP_MODE[index]);
+	data->temp_mode[index] &= ~(mask << shift);
+	data->temp_mode[index] |= val << shift;
+	w83793_write_value(client, W83793_REG_TEMP_MODE[index],
+							data->temp_mode[index]);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+#define SETUP_PWM_DEFAULT		0
+#define SETUP_PWM_UPTIME		1	/* Unit in 0.1s */
+#define SETUP_PWM_DOWNTIME		2	/* Unit in 0.1s */
+#define SETUP_TEMP_CRITICAL		3
+static ssize_t
+show_sf_setup(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct sensor_device_attribute_2 *sensor_attr =
+	    to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	struct w83793_data *data = w83793_update_device(dev);
+	u32 val = 0;
+
+	if (SETUP_PWM_DEFAULT == nr) {
+		val = (data->pwm_default & 0x3f) << 2;
+	} else if (SETUP_PWM_UPTIME == nr) {
+		val = TIME_FROM_REG(data->pwm_uptime);
+	} else if (SETUP_PWM_DOWNTIME == nr) {
+		val = TIME_FROM_REG(data->pwm_downtime);
+	} else if (SETUP_TEMP_CRITICAL == nr) {
+		val = TEMP_FROM_REG(data->temp_critical & 0x7f);
+	}
+
+	return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t
+store_sf_setup(struct device *dev, struct device_attribute *attr,
+	       const char *buf, size_t count)
+{
+	struct sensor_device_attribute_2 *sensor_attr =
+	    to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83793_data *data = i2c_get_clientdata(client);
+
+	mutex_lock(&data->update_lock);
+	if (SETUP_PWM_DEFAULT == nr) {
+		data->pwm_default =
+		    w83793_read_value(client, W83793_REG_PWM_DEFAULT) & 0xc0;
+		data->pwm_default |= SENSORS_LIMIT(simple_strtoul(buf, NULL,
+								  10),
+						   0, 0xff) >> 2;
+		w83793_write_value(client, W83793_REG_PWM_DEFAULT,
+							data->pwm_default);
+	} else if (SETUP_PWM_UPTIME == nr) {
+		data->pwm_uptime = TIME_TO_REG(simple_strtoul(buf, NULL, 10));
+		data->pwm_uptime += data->pwm_uptime == 0 ? 1 : 0;
+		w83793_write_value(client, W83793_REG_PWM_UPTIME,
+							data->pwm_uptime);
+	} else if (SETUP_PWM_DOWNTIME == nr) {
+		data->pwm_downtime = TIME_TO_REG(simple_strtoul(buf, NULL, 10));
+		data->pwm_downtime += data->pwm_downtime == 0 ? 1 : 0;
+		w83793_write_value(client, W83793_REG_PWM_DOWNTIME,
+							data->pwm_downtime);
+	} else {		/* SETUP_TEMP_CRITICAL */
+		data->temp_critical =
+		    w83793_read_value(client, W83793_REG_TEMP_CRITICAL) & 0x80;
+		data->temp_critical |= TEMP_TO_REG(simple_strtol(buf, NULL, 10),
+						   0, 0x7f);
+		w83793_write_value(client, W83793_REG_TEMP_CRITICAL,
+							data->temp_critical);
+	}
+
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+/*
+	Temp SmartFan control
+	TEMP_FAN_MAP
+	Temp channel control which pwm fan, bitfield, bit 0 indicate pwm1...
+	It's possible two or more temp channels control the same fan, w83793
+	always prefers to pick the most critical request and applies it to
+	the related Fan.
+	It's possible one fan is not in any mapping of 6 temp channels, this
+	means the fan is manual mode
+
+	TEMP_PWM_ENABLE
+	Each temp channel has its own SmartFan mode, and temp channel
+	control	fans that are set by TEMP_FAN_MAP
+	0:	SmartFanII mode
+	1:	Thermal Cruise Mode
+
+	TEMP_CRUISE
+	Target temperature in thermal cruise mode, w83793 will try to turn
+	fan speed to keep the temperature of target device around this
+	temperature.
+
+	TEMP_TOLERANCE
+	If Temp higher or lower than target with this tolerance, w83793
+	will take actions to speed up or slow down the fan to keep the
+	temperature within the tolerance range.
+*/
+
+#define TEMP_FAN_MAP			0
+#define TEMP_PWM_ENABLE			1
+#define TEMP_CRUISE			2
+#define TEMP_TOLERANCE			3
+static ssize_t
+show_sf_ctrl(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct sensor_device_attribute_2 *sensor_attr =
+	    to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int index = sensor_attr->index;
+	struct w83793_data *data = w83793_update_device(dev);
+	u32 val;
+
+	if (TEMP_FAN_MAP == nr) {
+		val = data->temp_fan_map[index];
+	} else if (TEMP_PWM_ENABLE == nr) {
+		/* +2 to transfrom into 2 and 3 to conform with sysfs intf */
+		val = ((data->pwm_enable >> index) & 0x01) + 2;
+	} else if (TEMP_CRUISE == nr) {
+		val = TEMP_FROM_REG(data->temp_cruise[index] & 0x7f);
+	} else {		/* TEMP_TOLERANCE */
+		val = data->tolerance[index >> 1] >> ((index & 0x01) ? 4 : 0);
+		val = TEMP_FROM_REG(val & 0x0f);
+	}
+	return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t
+store_sf_ctrl(struct device *dev, struct device_attribute *attr,
+	      const char *buf, size_t count)
+{
+	struct sensor_device_attribute_2 *sensor_attr =
+	    to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int index = sensor_attr->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83793_data *data = i2c_get_clientdata(client);
+	u32 val;
+
+	mutex_lock(&data->update_lock);
+	if (TEMP_FAN_MAP == nr) {
+		val = simple_strtoul(buf, NULL, 10) & 0xff;
+		w83793_write_value(client, W83793_REG_TEMP_FAN_MAP(index), val);
+		data->temp_fan_map[index] = val;
+	} else if (TEMP_PWM_ENABLE == nr) {
+		val = simple_strtoul(buf, NULL, 10);
+		if (2 == val || 3 == val) {
+			data->pwm_enable =
+			    w83793_read_value(client, W83793_REG_PWM_ENABLE);
+			if (val - 2)
+				data->pwm_enable |= 1 << index;
+			else
+				data->pwm_enable &= ~(1 << index);
+			w83793_write_value(client, W83793_REG_PWM_ENABLE,
+							data->pwm_enable);
+		} else {
+			mutex_unlock(&data->update_lock);
+			return -EINVAL;
+		}
+	} else if (TEMP_CRUISE == nr) {
+		data->temp_cruise[index] =
+		    w83793_read_value(client, W83793_REG_TEMP_CRUISE(index));
+		val = TEMP_TO_REG(simple_strtol(buf, NULL, 10), 0, 0x7f);
+		data->temp_cruise[index] &= 0x80;
+		data->temp_cruise[index] |= val;
+
+		w83793_write_value(client, W83793_REG_TEMP_CRUISE(index),
+						data->temp_cruise[index]);
+	} else {		/* TEMP_TOLERANCE */
+		int i = index >> 1;
+		u8 shift = (index & 0x01) ? 4 : 0;
+		data->tolerance[i] =
+		    w83793_read_value(client, W83793_REG_TEMP_TOL(i));
+
+		val = TEMP_TO_REG(simple_strtol(buf, NULL, 10), 0, 0x0f);
+		data->tolerance[i] &= ~(0x0f << shift);
+		data->tolerance[i] |= val << shift;
+		w83793_write_value(client, W83793_REG_TEMP_TOL(i),
+							data->tolerance[i]);
+	}
+
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+show_sf2_pwm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct sensor_device_attribute_2 *sensor_attr =
+	    to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int index = sensor_attr->index;
+	struct w83793_data *data = w83793_update_device(dev);
+
+	return sprintf(buf, "%d\n", (data->sf2_pwm[index][nr] & 0x3f) << 2);
+}
+
+static ssize_t
+store_sf2_pwm(struct device *dev, struct device_attribute *attr,
+	      const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83793_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute_2 *sensor_attr =
+	    to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int index = sensor_attr->index;
+	u8 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 0xff) >> 2;
+
+	mutex_lock(&data->update_lock);
+	data->sf2_pwm[index][nr] =
+	    w83793_read_value(client, W83793_REG_SF2_PWM(index, nr)) & 0xc0;
+	data->sf2_pwm[index][nr] |= val;
+	w83793_write_value(client, W83793_REG_SF2_PWM(index, nr),
+						data->sf2_pwm[index][nr]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+show_sf2_temp(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct sensor_device_attribute_2 *sensor_attr =
+	    to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int index = sensor_attr->index;
+	struct w83793_data *data = w83793_update_device(dev);
+
+	return sprintf(buf, "%ld\n",
+		       TEMP_FROM_REG(data->sf2_temp[index][nr] & 0x7f));
+}
+
+static ssize_t
+store_sf2_temp(struct device *dev, struct device_attribute *attr,
+	       const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83793_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute_2 *sensor_attr =
+	    to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int index = sensor_attr->index;
+	u8 val = TEMP_TO_REG(simple_strtol(buf, NULL, 10), 0, 0x7f);
+
+	mutex_lock(&data->update_lock);
+	data->sf2_temp[index][nr] =
+	    w83793_read_value(client, W83793_REG_SF2_TEMP(index, nr)) & 0x80;
+	data->sf2_temp[index][nr] |= val;
+	w83793_write_value(client, W83793_REG_SF2_TEMP(index, nr),
+					     data->sf2_temp[index][nr]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+/* only Vcore A/B and Vtt have additional 2 bits precision */
+static ssize_t
+show_in(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct sensor_device_attribute_2 *sensor_attr =
+	    to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int index = sensor_attr->index;
+	struct w83793_data *data = w83793_update_device(dev);
+	u16 val = data->in[index][nr];
+
+	if (index < 3) {
+		val <<= 2;
+		val += (data->in_low_bits[nr] >> (index * 2)) & 0x3;
+	}
+	return sprintf(buf, "%d\n", val * scale_in[index]);
+}
+
+static ssize_t
+store_in(struct device *dev, struct device_attribute *attr,
+	 const char *buf, size_t count)
+{
+	struct sensor_device_attribute_2 *sensor_attr =
+	    to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int index = sensor_attr->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83793_data *data = i2c_get_clientdata(client);
+	u32 val;
+
+	val =
+	    (simple_strtoul(buf, NULL, 10) +
+	     scale_in[index] / 2) / scale_in[index];
+	mutex_lock(&data->update_lock);
+	if (index > 2) {
+		val = SENSORS_LIMIT(val, 0, 255);
+	} else {
+		val = SENSORS_LIMIT(val, 0, 0x3FF);
+		data->in_low_bits[nr] =
+		    w83793_read_value(client, W83793_REG_IN_LOW_BITS[nr]);
+		data->in_low_bits[nr] &= ~(0x03 << (2 * index));
+		data->in_low_bits[nr] |= (val & 0x03) << (2 * index);
+		w83793_write_value(client, W83793_REG_IN_LOW_BITS[nr],
+						     data->in_low_bits[nr]);
+		val >>= 2;
+	}
+	data->in[index][nr] = val;
+	w83793_write_value(client, W83793_REG_IN[index][nr],
+							data->in[index][nr]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+#define NOT_USED			-1
+
+#define SENSOR_ATTR_IN(index)						\
+	SENSOR_ATTR_2(in##index##_input, S_IRUGO, show_in, NULL,	\
+		IN_READ, index),					\
+	SENSOR_ATTR_2(in##index##_max, S_IRUGO | S_IWUSR, show_in,	\
+		store_in, IN_MAX, index),				\
+	SENSOR_ATTR_2(in##index##_min, S_IRUGO | S_IWUSR, show_in,	\
+		store_in, IN_LOW, index),				\
+	SENSOR_ATTR_2(in##index##_alarm, S_IRUGO, show_alarm_beep,	\
+		NULL, ALARM_STATUS, index + ((index > 2) ? 1 : 0)),	\
+	SENSOR_ATTR_2(in##index##_beep, S_IWUSR | S_IRUGO,		\
+		show_alarm_beep, store_beep, BEEP_ENABLE,		\
+		index + ((index > 2) ? 1 : 0))
+
+#define SENSOR_ATTR_FAN(index)						\
+	SENSOR_ATTR_2(fan##index##_alarm, S_IRUGO, show_alarm_beep,	\
+		NULL, ALARM_STATUS, index + 17),			\
+	SENSOR_ATTR_2(fan##index##_beep, S_IWUSR | S_IRUGO,		\
+		show_alarm_beep, store_beep, BEEP_ENABLE, index + 17),	\
+	SENSOR_ATTR_2(fan##index##_input, S_IRUGO, show_fan,		\
+		NULL, FAN_INPUT, index - 1),				\
+	SENSOR_ATTR_2(fan##index##_min, S_IWUSR | S_IRUGO,		\
+		show_fan, store_fan_min, FAN_MIN, index - 1)
+
+#define SENSOR_ATTR_PWM(index)						\
+	SENSOR_ATTR_2(pwm##index, S_IWUSR | S_IRUGO, show_pwm,		\
+		store_pwm, PWM_DUTY, index - 1),			\
+	SENSOR_ATTR_2(pwm##index##_nonstop, S_IWUSR | S_IRUGO,		\
+		show_pwm, store_pwm, PWM_NONSTOP, index - 1),		\
+	SENSOR_ATTR_2(pwm##index##_start, S_IWUSR | S_IRUGO,		\
+		show_pwm, store_pwm, PWM_START, index - 1),		\
+	SENSOR_ATTR_2(pwm##index##_stop_time, S_IWUSR | S_IRUGO,	\
+		show_pwm, store_pwm, PWM_STOP_TIME, index - 1)
+
+#define SENSOR_ATTR_TEMP(index)						\
+	SENSOR_ATTR_2(temp##index##_type, S_IRUGO | S_IWUSR,		\
+		show_temp_mode, store_temp_mode, NOT_USED, index - 1),	\
+	SENSOR_ATTR_2(temp##index##_input, S_IRUGO, show_temp,		\
+		NULL, TEMP_READ, index - 1),				\
+	SENSOR_ATTR_2(temp##index##_max, S_IRUGO | S_IWUSR, show_temp,	\
+		store_temp, TEMP_CRIT, index - 1),			\
+	SENSOR_ATTR_2(temp##index##_max_hyst, S_IRUGO | S_IWUSR,	\
+		show_temp, store_temp, TEMP_CRIT_HYST, index - 1),	\
+	SENSOR_ATTR_2(temp##index##_warn, S_IRUGO | S_IWUSR, show_temp,	\
+		store_temp, TEMP_WARN, index - 1),			\
+	SENSOR_ATTR_2(temp##index##_warn_hyst, S_IRUGO | S_IWUSR,	\
+		show_temp, store_temp, TEMP_WARN_HYST, index - 1),	\
+	SENSOR_ATTR_2(temp##index##_alarm, S_IRUGO,			\
+		show_alarm_beep, NULL, ALARM_STATUS, index + 11),	\
+	SENSOR_ATTR_2(temp##index##_beep, S_IWUSR | S_IRUGO,		\
+		show_alarm_beep, store_beep, BEEP_ENABLE, index + 11),	\
+	SENSOR_ATTR_2(temp##index##_auto_channels_pwm,			\
+		S_IRUGO | S_IWUSR, show_sf_ctrl, store_sf_ctrl,		\
+		TEMP_FAN_MAP, index - 1),				\
+	SENSOR_ATTR_2(temp##index##_pwm_enable, S_IWUSR | S_IRUGO,	\
+		show_sf_ctrl, store_sf_ctrl, TEMP_PWM_ENABLE,		\
+		index - 1),						\
+	SENSOR_ATTR_2(thermal_cruise##index, S_IRUGO | S_IWUSR,		\
+		show_sf_ctrl, store_sf_ctrl, TEMP_CRUISE, index - 1),	\
+	SENSOR_ATTR_2(tolerance##index, S_IRUGO | S_IWUSR, show_sf_ctrl,\
+		store_sf_ctrl, TEMP_TOLERANCE, index - 1),		\
+	SENSOR_ATTR_2(temp##index##_auto_point1_pwm, S_IRUGO | S_IWUSR, \
+		show_sf2_pwm, store_sf2_pwm, 0, index - 1),		\
+	SENSOR_ATTR_2(temp##index##_auto_point2_pwm, S_IRUGO | S_IWUSR, \
+		show_sf2_pwm, store_sf2_pwm, 1, index - 1),		\
+	SENSOR_ATTR_2(temp##index##_auto_point3_pwm, S_IRUGO | S_IWUSR, \
+		show_sf2_pwm, store_sf2_pwm, 2, index - 1),		\
+	SENSOR_ATTR_2(temp##index##_auto_point4_pwm, S_IRUGO | S_IWUSR, \
+		show_sf2_pwm, store_sf2_pwm, 3, index - 1),		\
+	SENSOR_ATTR_2(temp##index##_auto_point5_pwm, S_IRUGO | S_IWUSR, \
+		show_sf2_pwm, store_sf2_pwm, 4, index - 1),		\
+	SENSOR_ATTR_2(temp##index##_auto_point6_pwm, S_IRUGO | S_IWUSR, \
+		show_sf2_pwm, store_sf2_pwm, 5, index - 1),		\
+	SENSOR_ATTR_2(temp##index##_auto_point7_pwm, S_IRUGO | S_IWUSR, \
+		show_sf2_pwm, store_sf2_pwm, 6, index - 1),		\
+	SENSOR_ATTR_2(temp##index##_auto_point1_temp, S_IRUGO | S_IWUSR,\
+		show_sf2_temp, store_sf2_temp, 0, index - 1),		\
+	SENSOR_ATTR_2(temp##index##_auto_point2_temp, S_IRUGO | S_IWUSR,\
+		show_sf2_temp, store_sf2_temp, 1, index - 1),		\
+	SENSOR_ATTR_2(temp##index##_auto_point3_temp, S_IRUGO | S_IWUSR,\
+		show_sf2_temp, store_sf2_temp, 2, index - 1),		\
+	SENSOR_ATTR_2(temp##index##_auto_point4_temp, S_IRUGO | S_IWUSR,\
+		show_sf2_temp, store_sf2_temp, 3, index - 1),		\
+	SENSOR_ATTR_2(temp##index##_auto_point5_temp, S_IRUGO | S_IWUSR,\
+		show_sf2_temp, store_sf2_temp, 4, index - 1),		\
+	SENSOR_ATTR_2(temp##index##_auto_point6_temp, S_IRUGO | S_IWUSR,\
+		show_sf2_temp, store_sf2_temp, 5, index - 1),		\
+	SENSOR_ATTR_2(temp##index##_auto_point7_temp, S_IRUGO | S_IWUSR,\
+		show_sf2_temp, store_sf2_temp, 6, index - 1)
+
+static struct sensor_device_attribute_2 w83793_sensor_attr_2[] = {
+	SENSOR_ATTR_IN(0),
+	SENSOR_ATTR_IN(1),
+	SENSOR_ATTR_IN(2),
+	SENSOR_ATTR_IN(3),
+	SENSOR_ATTR_IN(4),
+	SENSOR_ATTR_IN(5),
+	SENSOR_ATTR_IN(6),
+	SENSOR_ATTR_IN(7),
+	SENSOR_ATTR_IN(8),
+	SENSOR_ATTR_IN(9),
+	SENSOR_ATTR_TEMP(1),
+	SENSOR_ATTR_TEMP(2),
+	SENSOR_ATTR_TEMP(3),
+	SENSOR_ATTR_TEMP(4),
+	SENSOR_ATTR_TEMP(5),
+	SENSOR_ATTR_TEMP(6),
+	SENSOR_ATTR_FAN(1),
+	SENSOR_ATTR_FAN(2),
+	SENSOR_ATTR_FAN(3),
+	SENSOR_ATTR_FAN(4),
+	SENSOR_ATTR_FAN(5),
+	SENSOR_ATTR_PWM(1),
+	SENSOR_ATTR_PWM(2),
+	SENSOR_ATTR_PWM(3),
+};
+
+/* Fan6-Fan12 */
+static struct sensor_device_attribute_2 w83793_left_fan[] = {
+	SENSOR_ATTR_FAN(6),
+	SENSOR_ATTR_FAN(7),
+	SENSOR_ATTR_FAN(8),
+	SENSOR_ATTR_FAN(9),
+	SENSOR_ATTR_FAN(10),
+	SENSOR_ATTR_FAN(11),
+	SENSOR_ATTR_FAN(12),
+};
+
+/* Pwm4-Pwm8 */
+static struct sensor_device_attribute_2 w83793_left_pwm[] = {
+	SENSOR_ATTR_PWM(4),
+	SENSOR_ATTR_PWM(5),
+	SENSOR_ATTR_PWM(6),
+	SENSOR_ATTR_PWM(7),
+	SENSOR_ATTR_PWM(8),
+};
+
+static struct sensor_device_attribute_2 sda_single_files[] = {
+	SENSOR_ATTR_2(cpu0_vid, S_IRUGO, show_vid, NULL, NOT_USED, 0),
+	SENSOR_ATTR_2(cpu1_vid, S_IRUGO, show_vid, NULL, NOT_USED, 1),
+	SENSOR_ATTR_2(vrm, S_IWUSR | S_IRUGO, show_vrm, store_vrm,
+		      NOT_USED, NOT_USED),
+	SENSOR_ATTR_2(chassis, S_IWUSR | S_IRUGO, show_alarm_beep,
+		      store_chassis_clear, ALARM_STATUS, 30),
+	SENSOR_ATTR_2(beep_enable, S_IWUSR | S_IRUGO, show_beep_enable,
+		      store_beep_enable, NOT_USED, NOT_USED),
+	SENSOR_ATTR_2(pwm_default, S_IWUSR | S_IRUGO, show_sf_setup,
+		      store_sf_setup, SETUP_PWM_DEFAULT, NOT_USED),
+	SENSOR_ATTR_2(pwm_uptime, S_IWUSR | S_IRUGO, show_sf_setup,
+		      store_sf_setup, SETUP_PWM_UPTIME, NOT_USED),
+	SENSOR_ATTR_2(pwm_downtime, S_IWUSR | S_IRUGO, show_sf_setup,
+		      store_sf_setup, SETUP_PWM_DOWNTIME, NOT_USED),
+	SENSOR_ATTR_2(temp_critical, S_IWUSR | S_IRUGO, show_sf_setup,
+		      store_sf_setup, SETUP_TEMP_CRITICAL, NOT_USED),
+};
+
+static void w83793_init_client(struct i2c_client *client)
+{
+	if (reset) {
+		w83793_write_value(client, W83793_REG_CONFIG, 0x80);
+	}
+
+	/* Start monitoring */
+	w83793_write_value(client, W83793_REG_CONFIG,
+			   w83793_read_value(client, W83793_REG_CONFIG) | 0x01);
+
+}
+
+static int w83793_attach_adapter(struct i2c_adapter *adapter)
+{
+	if (!(adapter->class & I2C_CLASS_HWMON))
+		return 0;
+	return i2c_probe(adapter, &addr_data, w83793_detect);
+}
+
+static int w83793_detach_client(struct i2c_client *client)
+{
+	struct w83793_data *data = i2c_get_clientdata(client);
+	struct device *dev = &client->dev;
+	int err, i;
+
+	/* main client */
+	if (data) {
+		hwmon_device_unregister(data->class_dev);
+
+		for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++)
+			device_remove_file(dev,
+					   &w83793_sensor_attr_2[i].dev_attr);
+
+		for (i = 0; i < ARRAY_SIZE(sda_single_files); i++)
+			device_remove_file(dev, &sda_single_files[i].dev_attr);
+
+		for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++)
+			device_remove_file(dev, &w83793_left_fan[i].dev_attr);
+
+		for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++)
+			device_remove_file(dev, &w83793_left_pwm[i].dev_attr);
+	}
+
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	/* main client */
+	if (data)
+		kfree(data);
+	/* subclient */
+	else
+		kfree(client);
+
+	return 0;
+}
+
+static int
+w83793_create_subclient(struct i2c_adapter *adapter,
+			struct i2c_client *client, int addr,
+			struct i2c_client **sub_cli)
+{
+	int err = 0;
+	struct i2c_client *sub_client;
+
+	(*sub_cli) = sub_client =
+	    kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+	if (!(sub_client)) {
+		return -ENOMEM;
+	}
+	sub_client->addr = 0x48 + addr;
+	i2c_set_clientdata(sub_client, NULL);
+	sub_client->adapter = adapter;
+	sub_client->driver = &w83793_driver;
+	strlcpy(sub_client->name, "w83793 subclient", I2C_NAME_SIZE);
+	if ((err = i2c_attach_client(sub_client))) {
+		dev_err(&client->dev, "subclient registration "
+			"at address 0x%x failed\n", sub_client->addr);
+		kfree(sub_client);
+	}
+	return err;
+}
+
+static int
+w83793_detect_subclients(struct i2c_adapter *adapter, int address,
+			 int kind, struct i2c_client *client)
+{
+	int i, id, err;
+	u8 tmp;
+	struct w83793_data *data = i2c_get_clientdata(client);
+
+	id = i2c_adapter_id(adapter);
+	if (force_subclients[0] == id && force_subclients[1] == address) {
+		for (i = 2; i <= 3; i++) {
+			if (force_subclients[i] < 0x48
+			    || force_subclients[i] > 0x4f) {
+				dev_err(&client->dev,
+					"invalid subclient "
+					"address %d; must be 0x48-0x4f\n",
+					force_subclients[i]);
+				err = -EINVAL;
+				goto ERROR_SC_0;
+			}
+		}
+		w83793_write_value(client, W83793_REG_I2C_SUBADDR,
+				   (force_subclients[2] & 0x07) |
+				   ((force_subclients[3] & 0x07) << 4));
+	}
+
+	tmp = w83793_read_value(client, W83793_REG_I2C_SUBADDR);
+	if (!(tmp & 0x08)) {
+		err =
+		    w83793_create_subclient(adapter, client, tmp & 0x7,
+					    &data->lm75[0]);
+		if (err < 0)
+			goto ERROR_SC_0;
+	}
+	if (!(tmp & 0x80)) {
+		if ((data->lm75[0] != NULL)
+		    && ((tmp & 0x7) == ((tmp >> 4) & 0x7))) {
+			dev_err(&client->dev,
+				"duplicate addresses 0x%x, "
+				"use force_subclients\n", data->lm75[0]->addr);
+			err = -ENODEV;
+			goto ERROR_SC_1;
+		}
+		err = w83793_create_subclient(adapter, client,
+					      (tmp >> 4) & 0x7, &data->lm75[1]);
+		if (err < 0)
+			goto ERROR_SC_1;
+	}
+
+	return 0;
+
+	/* Undo inits in case of errors */
+
+ERROR_SC_1:
+	if (data->lm75[0] != NULL) {
+		i2c_detach_client(data->lm75[0]);
+		kfree(data->lm75[0]);
+	}
+ERROR_SC_0:
+	return err;
+}
+
+static int w83793_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	int i;
+	u8 tmp, val;
+	struct i2c_client *client;
+	struct device *dev;
+	struct w83793_data *data;
+	int files_fan = ARRAY_SIZE(w83793_left_fan) / 7;
+	int files_pwm = ARRAY_SIZE(w83793_left_pwm) / 5;
+	int err = 0;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+		goto exit;
+	}
+
+	/* OK. For now, we presume we have a valid client. We now create the
+	   client structure, even though we cannot fill it completely yet.
+	   But it allows us to access w83793_{read,write}_value. */
+
+	if (!(data = kzalloc(sizeof(struct w83793_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	client = &data->client;
+	dev = &client->dev;
+	i2c_set_clientdata(client, data);
+	client->addr = address;
+	client->adapter = adapter;
+	client->driver = &w83793_driver;
+
+	data->bank = i2c_smbus_read_byte_data(client, W83793_REG_BANKSEL);
+
+	/* Now, we do the remaining detection. */
+	if (kind < 0) {
+		tmp = data->bank & 0x80 ? 0x5c : 0xa3;
+		/* Check Winbond vendor ID */
+		if (tmp != i2c_smbus_read_byte_data(client,
+							W83793_REG_VENDORID)) {
+			pr_debug("w83793: Detection failed at check "
+				 "vendor id\n");
+			err = -ENODEV;
+			goto free_mem;
+		}
+
+		/* If Winbond chip, address of chip and W83793_REG_I2C_ADDR
+		   should match */
+		if ((data->bank & 0x07) == 0
+		 && i2c_smbus_read_byte_data(client, W83793_REG_I2C_ADDR) !=
+		    (address << 1)) {
+			pr_debug("w83793: Detection failed at check "
+				 "i2c addr\n");
+			err = -ENODEV;
+			goto free_mem;
+		}
+
+	}
+
+	/* We have either had a force parameter, or we have already detected the
+	   Winbond. Determine the chip type now */
+
+	if (kind <= 0) {
+		if (0x7b == w83793_read_value(client, W83793_REG_CHIPID)) {
+			kind = w83793;
+		} else {
+			if (kind == 0)
+				dev_warn(&adapter->dev, "w83793: Ignoring "
+					 "'force' parameter for unknown chip "
+					 "at address 0x%02x\n", address);
+			err = -ENODEV;
+			goto free_mem;
+		}
+	}
+
+	/* Fill in the remaining client fields and put into the global list */
+	strlcpy(client->name, "w83793", I2C_NAME_SIZE);
+
+	mutex_init(&data->update_lock);
+
+	/* Tell the I2C layer a new client has arrived */
+	if ((err = i2c_attach_client(client)))
+		goto free_mem;
+
+	if ((err = w83793_detect_subclients(adapter, address, kind, client)))
+		goto detach_client;
+
+	/* Initialize the chip */
+	w83793_init_client(client);
+
+	data->vrm = vid_which_vrm();
+	/*
+	   Only fan 1-5 has their own input pins,
+	   Pwm 1-3 has their own pins
+	 */
+	data->has_fan = 0x1f;
+	data->has_pwm = 0x07;
+	tmp = w83793_read_value(client, W83793_REG_MFC);
+	val = w83793_read_value(client, W83793_REG_FANIN_CTRL);
+
+	/* check the function of pins 49-56 */
+	if (!(tmp & 0x80)) {
+		data->has_pwm |= 0x18;	/* pwm 4,5 */
+		if (val & 0x01) {	/* fan 6 */
+			data->has_fan |= 0x20;
+			data->has_pwm |= 0x20;
+		}
+		if (val & 0x02) {	/* fan 7 */
+			data->has_fan |= 0x40;
+			data->has_pwm |= 0x40;
+		}
+		if (!(tmp & 0x40) && (val & 0x04)) {	/* fan 8 */
+			data->has_fan |= 0x80;
+			data->has_pwm |= 0x80;
+		}
+	}
+
+	if (0x08 == (tmp & 0x0c)) {
+		if (val & 0x08)	/* fan 9 */
+			data->has_fan |= 0x100;
+		if (val & 0x10)	/* fan 10 */
+			data->has_fan |= 0x200;
+	}
+
+	if (0x20 == (tmp & 0x30)) {
+		if (val & 0x20)	/* fan 11 */
+			data->has_fan |= 0x400;
+		if (val & 0x40)	/* fan 12 */
+			data->has_fan |= 0x800;
+	}
+
+	if ((tmp & 0x01) && (val & 0x04)) {	/* fan 8, second location */
+		data->has_fan |= 0x80;
+		data->has_pwm |= 0x80;
+	}
+
+	/* Register sysfs hooks */
+	for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) {
+		err = device_create_file(dev,
+					 &w83793_sensor_attr_2[i].dev_attr);
+		if (err)
+			goto exit_remove;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) {
+		err = device_create_file(dev, &sda_single_files[i].dev_attr);
+		if (err)
+			goto exit_remove;
+
+	}
+
+	for (i = 5; i < 12; i++) {
+		int j;
+		if (!(data->has_fan & (1 << i)))
+			continue;
+		for (j = 0; j < files_fan; j++) {
+			err = device_create_file(dev,
+					   &w83793_left_fan[(i - 5) * files_fan
+								+ j].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+	}
+
+	for (i = 3; i < 8; i++) {
+		int j;
+		if (!(data->has_pwm & (1 << i)))
+			continue;
+		for (j = 0; j < files_pwm; j++) {
+			err = device_create_file(dev,
+					   &w83793_left_pwm[(i - 3) * files_pwm
+								+ j].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+	}
+
+	data->class_dev = hwmon_device_register(dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_remove;
+	}
+
+	return 0;
+
+	/* Unregister sysfs hooks */
+
+exit_remove:
+	for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++)
+		device_remove_file(dev, &w83793_sensor_attr_2[i].dev_attr);
+
+	for (i = 0; i < ARRAY_SIZE(sda_single_files); i++)
+		device_remove_file(dev, &sda_single_files[i].dev_attr);
+
+	for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++)
+		device_remove_file(dev, &w83793_left_fan[i].dev_attr);
+
+	for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++)
+		device_remove_file(dev, &w83793_left_pwm[i].dev_attr);
+
+	if (data->lm75[0] != NULL) {
+		i2c_detach_client(data->lm75[0]);
+		kfree(data->lm75[0]);
+	}
+	if (data->lm75[1] != NULL) {
+		i2c_detach_client(data->lm75[1]);
+		kfree(data->lm75[1]);
+	}
+detach_client:
+	i2c_detach_client(client);
+free_mem:
+	kfree(data);
+exit:
+	return err;
+}
+
+static void w83793_update_nonvolatile(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83793_data *data = i2c_get_clientdata(client);
+	int i, j;
+	/*
+	   They are somewhat "stable" registers, and to update them everytime
+	   takes so much time, it's just not worthy. Update them in a long
+	   interval to avoid exception.
+	 */
+	if (!(time_after(jiffies, data->last_nonvolatile + HZ * 300)
+	      || !data->valid))
+		return;
+	/* update voltage limits */
+	for (i = 1; i < 3; i++) {
+		for (j = 0; j < ARRAY_SIZE(data->in); j++) {
+			data->in[j][i] =
+			    w83793_read_value(client, W83793_REG_IN[j][i]);
+		}
+		data->in_low_bits[i] =
+		    w83793_read_value(client, W83793_REG_IN_LOW_BITS[i]);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
+		/* Update the Fan measured value and limits */
+		if (!(data->has_fan & (1 << i))) {
+			continue;
+		}
+		data->fan_min[i] =
+		    w83793_read_value(client, W83793_REG_FAN_MIN(i)) << 8;
+		data->fan_min[i] |=
+		    w83793_read_value(client, W83793_REG_FAN_MIN(i) + 1);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(data->temp_fan_map); i++) {
+		data->temp_fan_map[i] =
+		    w83793_read_value(client, W83793_REG_TEMP_FAN_MAP(i));
+		for (j = 1; j < 5; j++) {
+			data->temp[i][j] =
+			    w83793_read_value(client, W83793_REG_TEMP[i][j]);
+		}
+		data->temp_cruise[i] =
+		    w83793_read_value(client, W83793_REG_TEMP_CRUISE(i));
+		for (j = 0; j < 7; j++) {
+			data->sf2_pwm[i][j] =
+			    w83793_read_value(client, W83793_REG_SF2_PWM(i, j));
+			data->sf2_temp[i][j] =
+			    w83793_read_value(client,
+					      W83793_REG_SF2_TEMP(i, j));
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(data->temp_mode); i++)
+		data->temp_mode[i] =
+		    w83793_read_value(client, W83793_REG_TEMP_MODE[i]);
+
+	for (i = 0; i < ARRAY_SIZE(data->tolerance); i++) {
+		data->tolerance[i] =
+		    w83793_read_value(client, W83793_REG_TEMP_TOL(i));
+	}
+
+	for (i = 0; i < ARRAY_SIZE(data->pwm); i++) {
+		if (!(data->has_pwm & (1 << i)))
+			continue;
+		data->pwm[i][PWM_NONSTOP] =
+		    w83793_read_value(client, W83793_REG_PWM(i, PWM_NONSTOP));
+		data->pwm[i][PWM_START] =
+		    w83793_read_value(client, W83793_REG_PWM(i, PWM_START));
+		data->pwm_stop_time[i] =
+		    w83793_read_value(client, W83793_REG_PWM_STOP_TIME(i));
+	}
+
+	data->pwm_default = w83793_read_value(client, W83793_REG_PWM_DEFAULT);
+	data->pwm_enable = w83793_read_value(client, W83793_REG_PWM_ENABLE);
+	data->pwm_uptime = w83793_read_value(client, W83793_REG_PWM_UPTIME);
+	data->pwm_downtime = w83793_read_value(client, W83793_REG_PWM_DOWNTIME);
+	data->temp_critical =
+	    w83793_read_value(client, W83793_REG_TEMP_CRITICAL);
+	data->beep_enable = w83793_read_value(client, W83793_REG_OVT_BEEP);
+
+	for (i = 0; i < ARRAY_SIZE(data->beeps); i++) {
+		data->beeps[i] = w83793_read_value(client, W83793_REG_BEEP(i));
+	}
+
+	data->last_nonvolatile = jiffies;
+}
+
+static struct w83793_data *w83793_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83793_data *data = i2c_get_clientdata(client);
+	int i;
+
+	mutex_lock(&data->update_lock);
+
+	if (!(time_after(jiffies, data->last_updated + HZ * 2)
+	      || !data->valid))
+		goto END;
+
+	/* Update the voltages measured value and limits */
+	for (i = 0; i < ARRAY_SIZE(data->in); i++)
+		data->in[i][IN_READ] =
+		    w83793_read_value(client, W83793_REG_IN[i][IN_READ]);
+
+	data->in_low_bits[IN_READ] =
+	    w83793_read_value(client, W83793_REG_IN_LOW_BITS[IN_READ]);
+
+	for (i = 0; i < ARRAY_SIZE(data->fan); i++) {
+		if (!(data->has_fan & (1 << i))) {
+			continue;
+		}
+		data->fan[i] =
+		    w83793_read_value(client, W83793_REG_FAN(i)) << 8;
+		data->fan[i] |=
+		    w83793_read_value(client, W83793_REG_FAN(i) + 1);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(data->temp); i++)
+		data->temp[i][TEMP_READ] =
+		    w83793_read_value(client, W83793_REG_TEMP[i][TEMP_READ]);
+
+	data->temp_low_bits =
+	    w83793_read_value(client, W83793_REG_TEMP_LOW_BITS);
+
+	for (i = 0; i < ARRAY_SIZE(data->pwm); i++) {
+		if (data->has_pwm & (1 << i))
+			data->pwm[i][PWM_DUTY] =
+			    w83793_read_value(client,
+					      W83793_REG_PWM(i, PWM_DUTY));
+	}
+
+	for (i = 0; i < ARRAY_SIZE(data->alarms); i++)
+		data->alarms[i] =
+		    w83793_read_value(client, W83793_REG_ALARM(i));
+	data->vid[0] = w83793_read_value(client, W83793_REG_VID_INA);
+	data->vid[1] = w83793_read_value(client, W83793_REG_VID_INB);
+	w83793_update_nonvolatile(dev);
+	data->last_updated = jiffies;
+	data->valid = 1;
+
+END:
+	mutex_unlock(&data->update_lock);
+	return data;
+}
+
+/* Ignore the possibility that somebody change bank outside the driver
+   Must be called with data->update_lock held, except during initialization */
+static u8 w83793_read_value(struct i2c_client *client, u16 reg)
+{
+	struct w83793_data *data = i2c_get_clientdata(client);
+	u8 res = 0xff;
+	u8 new_bank = reg >> 8;
+
+	new_bank |= data->bank & 0xfc;
+	if (data->bank != new_bank) {
+		if (i2c_smbus_write_byte_data
+		    (client, W83793_REG_BANKSEL, new_bank) >= 0)
+			data->bank = new_bank;
+		else {
+			dev_err(&client->dev,
+				"set bank to %d failed, fall back "
+				"to bank %d, read reg 0x%x error\n",
+				new_bank, data->bank, reg);
+			res = 0x0;	/* read 0x0 from the chip */
+			goto END;
+		}
+	}
+	res = i2c_smbus_read_byte_data(client, reg & 0xff);
+END:
+	return res;
+}
+
+/* Must be called with data->update_lock held, except during initialization */
+static int w83793_write_value(struct i2c_client *client, u16 reg, u8 value)
+{
+	struct w83793_data *data = i2c_get_clientdata(client);
+	int res;
+	u8 new_bank = reg >> 8;
+
+	new_bank |= data->bank & 0xfc;
+	if (data->bank != new_bank) {
+		if ((res = i2c_smbus_write_byte_data
+		    (client, W83793_REG_BANKSEL, new_bank)) >= 0)
+			data->bank = new_bank;
+		else {
+			dev_err(&client->dev,
+				"set bank to %d failed, fall back "
+				"to bank %d, write reg 0x%x error\n",
+				new_bank, data->bank, reg);
+			goto END;
+		}
+	}
+
+	res = i2c_smbus_write_byte_data(client, reg & 0xff, value);
+END:
+	return res;
+}
+
+static int __init sensors_w83793_init(void)
+{
+	return i2c_add_driver(&w83793_driver);
+}
+
+static void __exit sensors_w83793_exit(void)
+{
+	i2c_del_driver(&w83793_driver);
+}
+
+MODULE_AUTHOR("Yuan Mu");
+MODULE_DESCRIPTION("w83793 driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_w83793_init);
+module_exit(sensors_w83793_exit);
diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
index 33fbb47..8e1e3f8 100644
--- a/drivers/i2c/busses/i2c-ali1563.c
+++ b/drivers/i2c/busses/i2c-ali1563.c
@@ -2,7 +2,7 @@
  *	i2c-ali1563.c - i2c driver for the ALi 1563 Southbridge
  *
  *	Copyright (C) 2004 Patrick Mochel
- *		      2005 Rudolf Marek <r.marek@sh.cvut.cz>
+ *		      2005 Rudolf Marek <r.marek@assembler.cz>
  *
  *	The 1563 southbridge is deceptively similar to the 1533, with a
  *	few notable exceptions. One of those happens to be the fact they
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
index 60bef94..4ee56de 100644
--- a/drivers/i2c/chips/tps65010.c
+++ b/drivers/i2c/chips/tps65010.c
@@ -82,7 +82,7 @@
 	struct i2c_client	client;
 	struct mutex		lock;
 	int			irq;
-	struct work_struct	work;
+	struct delayed_work	work;
 	struct dentry		*file;
 	unsigned		charging:1;
 	unsigned		por:1;
@@ -328,7 +328,7 @@
 {
 	u8 tmp = 0, mask, poll;
 
-	/* IRQs won't trigger irqs for certain events, but we can get
+	/* IRQs won't trigger for certain events, but we can get
 	 * others by polling (normally, with external power applied).
 	 */
 	poll = 0;
@@ -411,10 +411,11 @@
 }
 
 /* handle IRQs and polling using keventd for now */
-static void tps65010_work(void *_tps)
+static void tps65010_work(struct work_struct *work)
 {
-	struct tps65010		*tps = _tps;
+	struct tps65010		*tps;
 
+	tps = container_of(work, struct tps65010, work.work);
 	mutex_lock(&tps->lock);
 
 	tps65010_interrupt(tps);
@@ -452,7 +453,7 @@
 
 	disable_irq_nosync(irq);
 	set_bit(FLAG_IRQ_ENABLE, &tps->flags);
-	(void) schedule_work(&tps->work);
+	(void) schedule_work(&tps->work.work);
 	return IRQ_HANDLED;
 }
 
@@ -465,13 +466,15 @@
 	struct tps65010		*tps;
 
 	tps = container_of(client, struct tps65010, client);
+	free_irq(tps->irq, tps);
 #ifdef	CONFIG_ARM
 	if (machine_is_omap_h2())
 		omap_free_gpio(58);
 	if (machine_is_omap_osk())
 		omap_free_gpio(OMAP_MPUIO(1));
 #endif
-	free_irq(tps->irq, tps);
+	cancel_delayed_work(&tps->work);
+	flush_scheduled_work();
 	debugfs_remove(tps->file);
 	if (i2c_detach_client(client) == 0)
 		kfree(tps);
@@ -505,7 +508,7 @@
 		return 0;
 
 	mutex_init(&tps->lock);
-	INIT_WORK(&tps->work, tps65010_work, tps);
+	INIT_DELAYED_WORK(&tps->work, tps65010_work);
 	tps->irq = -1;
 	tps->client.addr = address;
 	tps->client.adapter = bus;
@@ -620,7 +623,7 @@
 	(void) i2c_smbus_write_byte_data(&tps->client, TPS_MASK3, 0x0f
 		| i2c_smbus_read_byte_data(&tps->client, TPS_MASK3));
 
-	tps65010_work(tps);
+	tps65010_work(&tps->work.work);
 
 	tps->file = debugfs_create_file(DRIVER_NAME, S_IRUGO, NULL,
 				tps, DEBUG_FOPS);
@@ -672,7 +675,7 @@
 			&& test_and_set_bit(
 				FLAG_VBUS_CHANGED, &the_tps->flags)) {
 		/* gadget drivers call this in_irq() */
-		(void) schedule_work(&the_tps->work);
+		(void) schedule_work(&the_tps->work.work);
 	}
 	local_irq_restore(flags);
 
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index e3a2676..d33717c 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -2147,7 +2147,7 @@
 		printk("ide-floppy: passing drive %s to ide-scsi emulation.\n", drive->name);
 		goto failed;
 	}
-	if ((floppy = (idefloppy_floppy_t *) kzalloc (sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) {
+	if ((floppy = kzalloc(sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) {
 		printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name);
 		goto failed;
 	}
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index e2f4bb5..b3bcd1d 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -2573,11 +2573,11 @@
 	int pages = tape->pages_per_stage;
 	char *b_data = NULL;
 
-	if ((stage = (idetape_stage_t *) kmalloc (sizeof (idetape_stage_t),GFP_KERNEL)) == NULL)
+	if ((stage = kmalloc(sizeof (idetape_stage_t),GFP_KERNEL)) == NULL)
 		return NULL;
 	stage->next = NULL;
 
-	bh = stage->bh = (struct idetape_bh *)kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
+	bh = stage->bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
 	if (bh == NULL)
 		goto abort;
 	bh->b_reqnext = NULL;
@@ -2607,7 +2607,7 @@
 			continue;
 		}
 		prev_bh = bh;
-		if ((bh = (struct idetape_bh *)kmalloc(sizeof(struct idetape_bh), GFP_KERNEL)) == NULL) {
+		if ((bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL)) == NULL) {
 			free_page((unsigned long) b_data);
 			goto abort;
 		}
@@ -4860,7 +4860,7 @@
 		printk(KERN_WARNING "ide-tape: Use drive %s with ide-scsi emulation and osst.\n", drive->name);
 		printk(KERN_WARNING "ide-tape: OnStream support will be removed soon from ide-tape!\n");
 	}
-	tape = (idetape_tape_t *) kzalloc (sizeof (idetape_tape_t), GFP_KERNEL);
+	tape = kzalloc(sizeof (idetape_tape_t), GFP_KERNEL);
 	if (tape == NULL) {
 		printk(KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name);
 		goto failed;
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index e993a51..08119da 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -4,6 +4,7 @@
  * Copyright (C) 1999-2003		Andre Hedrick <andre@linux-ide.org>
  * Portions Copyright (C) 2001	        Sun Microsystems, Inc.
  * Portions Copyright (C) 2003		Red Hat Inc
+ * Portions Copyright (C) 2005-2006	MontaVista Software, Inc.
  *
  * Thanks to HighPoint Technologies for their assistance, and hardware.
  * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his
@@ -11,9 +12,11 @@
  * development and support.
  *
  *
- * Highpoint have their own driver (source except for the raid part)
- * available from http://www.highpoint-tech.com/hpt3xx-opensource-v131.tgz
- * This may be useful to anyone wanting to work on the mainstream hpt IDE.
+ * HighPoint has its own drivers (open source except for the RAID part)
+ * available from http://www.highpoint-tech.com/BIOS%20+%20Driver/.
+ * This may be useful to anyone wanting to work on this driver, however  do not
+ * trust  them too much since the code tends to become less and less meaningful
+ * as the time passes... :-/
  *
  * Note that final HPT370 support was done by force extraction of GPL.
  *
@@ -52,6 +55,29 @@
  * keeping me sane. 
  *		Alan Cox <alan@redhat.com>
  *
+ * - fix the clock turnaround code: it was writing to the wrong ports when
+ *   called for the secondary channel, caching the current clock mode per-
+ *   channel caused the cached register value to get out of sync with the
+ *   actual one, the channels weren't serialized, the turnaround shouldn't
+ *   be done on 66 MHz PCI bus
+ * - avoid calibrating PLL twice as the second time results in a wrong PCI
+ *   frequency and thus in the wrong timings for the secondary channel
+ * - disable UltraATA/133 for HPT372 by default (50 MHz DPLL clock do not
+ *   allow for this speed anyway)
+ * - add support for HPT302N and HPT371N clocking (the same as for HPT372N)
+ * - HPT371/N are single channel chips, so avoid touching the primary channel
+ *   which exists only virtually (there's no pins for it)
+ * - fix/remove bad/unused timing tables and use one set of tables for the whole
+ *   HPT37x chip family; save space by introducing the separate transfer mode
+ *   table in which the mode lookup is done
+ * - use f_CNT value saved by  the HighPoint BIOS as reading it directly gives
+ *   the wrong PCI frequency since DPLL has already been calibrated by BIOS
+ * - fix the hotswap code:  it caused RESET- to glitch when tristating the bus,
+ *   and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead
+ * - pass to init_chipset() handlers a copy of the IDE PCI device structure as
+ *   they tamper with its fields
+ *		<source@mvista.com>
+ *
  */
 
 
@@ -76,8 +102,8 @@
 
 /* various tuning parameters */
 #define HPT_RESET_STATE_ENGINE
-#undef HPT_DELAY_INTERRUPT
-#undef HPT_SERIALIZE_IO
+#undef	HPT_DELAY_INTERRUPT
+#define HPT_SERIALIZE_IO	0
 
 static const char *quirk_drives[] = {
 	"QUANTUM FIREBALLlct08 08",
@@ -141,305 +167,175 @@
 	NULL
 };
 
-struct chipset_bus_clock_list_entry {
-	u8		xfer_speed;
-	unsigned int	chipset_settings;
+static u8 xfer_speeds[] = {
+	XFER_UDMA_6,
+	XFER_UDMA_5,
+	XFER_UDMA_4,
+	XFER_UDMA_3,
+	XFER_UDMA_2,
+	XFER_UDMA_1,
+	XFER_UDMA_0,
+
+	XFER_MW_DMA_2,
+	XFER_MW_DMA_1,
+	XFER_MW_DMA_0,
+
+	XFER_PIO_4,
+	XFER_PIO_3,
+	XFER_PIO_2,
+	XFER_PIO_1,
+	XFER_PIO_0
 };
 
-/* key for bus clock timings
- * bit
- * 0:3    data_high_time. inactive time of DIOW_/DIOR_ for PIO and MW
- *        DMA. cycles = value + 1
- * 4:8    data_low_time. active time of DIOW_/DIOR_ for PIO and MW
- *        DMA. cycles = value + 1
- * 9:12   cmd_high_time. inactive time of DIOW_/DIOR_ during task file
- *        register access.
- * 13:17  cmd_low_time. active time of DIOW_/DIOR_ during task file
- *        register access.
- * 18:21  udma_cycle_time. clock freq and clock cycles for UDMA xfer.
- *        during task file register access.
- * 22:24  pre_high_time. time to initialize 1st cycle for PIO and MW DMA
- *        xfer.
- * 25:27  cmd_pre_high_time. time to initialize 1st PIO cycle for task
- *        register access.
- * 28     UDMA enable
- * 29     DMA enable
- * 30     PIO_MST enable. if set, the chip is in bus master mode during
- *        PIO.
- * 31     FIFO enable.
+/* Key for bus clock timings
+ * 36x   37x
+ * bits  bits
+ * 0:3	 0:3	data_high_time. Inactive time of DIOW_/DIOR_ for PIO and MW DMA.
+ *		cycles = value + 1
+ * 4:7	 4:8	data_low_time. Active time of DIOW_/DIOR_ for PIO and MW DMA.
+ *		cycles = value + 1
+ * 8:11  9:12	cmd_high_time. Inactive time of DIOW_/DIOR_ during task file
+ *		register access.
+ * 12:15 13:17	cmd_low_time. Active time of DIOW_/DIOR_ during task file
+ *		register access.
+ * 16:18 18:20	udma_cycle_time. Clock cycles for UDMA xfer.
+ * -	 21	CLK frequency: 0=ATA clock, 1=dual ATA clock.
+ * 19:21 22:24	pre_high_time. Time to initialize the 1st cycle for PIO and
+ *		MW DMA xfer.
+ * 22:24 25:27	cmd_pre_high_time. Time to initialize the 1st PIO cycle for
+ *		task file register access.
+ * 28	 28	UDMA enable.
+ * 29	 29	DMA  enable.
+ * 30	 30	PIO MST enable. If set, the chip is in bus master mode during
+ *		PIO xfer.
+ * 31	 31	FIFO enable.
  */
-static struct chipset_bus_clock_list_entry forty_base_hpt366[] = {
-	{	XFER_UDMA_4,	0x900fd943	},
-	{	XFER_UDMA_3,	0x900ad943	},
-	{	XFER_UDMA_2,	0x900bd943	},
-	{	XFER_UDMA_1,	0x9008d943	},
-	{	XFER_UDMA_0,	0x9008d943	},
 
-	{	XFER_MW_DMA_2,	0xa008d943	},
-	{	XFER_MW_DMA_1,	0xa010d955	},
-	{	XFER_MW_DMA_0,	0xa010d9fc	},
+static u32 forty_base_hpt36x[] = {
+	/* XFER_UDMA_6 */	0x900fd943,
+	/* XFER_UDMA_5 */	0x900fd943,
+	/* XFER_UDMA_4 */	0x900fd943,
+	/* XFER_UDMA_3 */	0x900ad943,
+	/* XFER_UDMA_2 */	0x900bd943,
+	/* XFER_UDMA_1 */	0x9008d943,
+	/* XFER_UDMA_0 */	0x9008d943,
 
-	{	XFER_PIO_4,	0xc008d963	},
-	{	XFER_PIO_3,	0xc010d974	},
-	{	XFER_PIO_2,	0xc010d997	},
-	{	XFER_PIO_1,	0xc010d9c7	},
-	{	XFER_PIO_0,	0xc018d9d9	},
-	{	0,		0x0120d9d9	}
+	/* XFER_MW_DMA_2 */	0xa008d943,
+	/* XFER_MW_DMA_1 */	0xa010d955,
+	/* XFER_MW_DMA_0 */	0xa010d9fc,
+
+	/* XFER_PIO_4 */	0xc008d963,
+	/* XFER_PIO_3 */	0xc010d974,
+	/* XFER_PIO_2 */	0xc010d997,
+	/* XFER_PIO_1 */	0xc010d9c7,
+	/* XFER_PIO_0 */	0xc018d9d9
 };
 
-static struct chipset_bus_clock_list_entry thirty_three_base_hpt366[] = {
-	{	XFER_UDMA_4,	0x90c9a731	},
-	{	XFER_UDMA_3,	0x90cfa731	},
-	{	XFER_UDMA_2,	0x90caa731	},
-	{	XFER_UDMA_1,	0x90cba731	},
-	{	XFER_UDMA_0,	0x90c8a731	},
+static u32 thirty_three_base_hpt36x[] = {
+	/* XFER_UDMA_6 */	0x90c9a731,
+	/* XFER_UDMA_5 */	0x90c9a731,
+	/* XFER_UDMA_4 */	0x90c9a731,
+	/* XFER_UDMA_3 */	0x90cfa731,
+	/* XFER_UDMA_2 */	0x90caa731,
+	/* XFER_UDMA_1 */	0x90cba731,
+	/* XFER_UDMA_0 */	0x90c8a731,
 
-	{	XFER_MW_DMA_2,	0xa0c8a731	},
-	{	XFER_MW_DMA_1,	0xa0c8a732	},	/* 0xa0c8a733 */
-	{	XFER_MW_DMA_0,	0xa0c8a797	},
+	/* XFER_MW_DMA_2 */	0xa0c8a731,
+	/* XFER_MW_DMA_1 */	0xa0c8a732,	/* 0xa0c8a733 */
+	/* XFER_MW_DMA_0 */	0xa0c8a797,
 
-	{	XFER_PIO_4,	0xc0c8a731	},
-	{	XFER_PIO_3,	0xc0c8a742	},
-	{	XFER_PIO_2,	0xc0d0a753	},
-	{	XFER_PIO_1,	0xc0d0a7a3	},	/* 0xc0d0a793 */
-	{	XFER_PIO_0,	0xc0d0a7aa	},	/* 0xc0d0a7a7 */
-	{	0,		0x0120a7a7	}
+	/* XFER_PIO_4 */	0xc0c8a731,
+	/* XFER_PIO_3 */	0xc0c8a742,
+	/* XFER_PIO_2 */	0xc0d0a753,
+	/* XFER_PIO_1 */	0xc0d0a7a3,	/* 0xc0d0a793 */
+	/* XFER_PIO_0 */	0xc0d0a7aa	/* 0xc0d0a7a7 */
 };
 
-static struct chipset_bus_clock_list_entry twenty_five_base_hpt366[] = {
-	{	XFER_UDMA_4,	0x90c98521	},
-	{	XFER_UDMA_3,	0x90cf8521	},
-	{	XFER_UDMA_2,	0x90cf8521	},
-	{	XFER_UDMA_1,	0x90cb8521	},
-	{	XFER_UDMA_0,	0x90cb8521	},
+static u32 twenty_five_base_hpt36x[] = {
+	/* XFER_UDMA_6 */	0x90c98521,
+	/* XFER_UDMA_5 */	0x90c98521,
+	/* XFER_UDMA_4 */	0x90c98521,
+	/* XFER_UDMA_3 */	0x90cf8521,
+	/* XFER_UDMA_2 */	0x90cf8521,
+	/* XFER_UDMA_1 */	0x90cb8521,
+	/* XFER_UDMA_0 */	0x90cb8521,
 
-	{	XFER_MW_DMA_2,	0xa0ca8521	},
-	{	XFER_MW_DMA_1,	0xa0ca8532	},
-	{	XFER_MW_DMA_0,	0xa0ca8575	},
+	/* XFER_MW_DMA_2 */	0xa0ca8521,
+	/* XFER_MW_DMA_1 */	0xa0ca8532,
+	/* XFER_MW_DMA_0 */	0xa0ca8575,
 
-	{	XFER_PIO_4,	0xc0ca8521	},
-	{	XFER_PIO_3,	0xc0ca8532	},
-	{	XFER_PIO_2,	0xc0ca8542	},
-	{	XFER_PIO_1,	0xc0d08572	},
-	{	XFER_PIO_0,	0xc0d08585	},
-	{	0,		0x01208585	}
+	/* XFER_PIO_4 */	0xc0ca8521,
+	/* XFER_PIO_3 */	0xc0ca8532,
+	/* XFER_PIO_2 */	0xc0ca8542,
+	/* XFER_PIO_1 */	0xc0d08572,
+	/* XFER_PIO_0 */	0xc0d08585
 };
 
-/* from highpoint documentation. these are old values */
-static struct chipset_bus_clock_list_entry thirty_three_base_hpt370[] = {
-/*	{	XFER_UDMA_5,	0x1A85F442,	0x16454e31	}, */
-	{	XFER_UDMA_5,	0x16454e31	},
-	{	XFER_UDMA_4,	0x16454e31	},
-	{	XFER_UDMA_3,	0x166d4e31	},
-	{	XFER_UDMA_2,	0x16494e31	},
-	{	XFER_UDMA_1,	0x164d4e31	},
-	{	XFER_UDMA_0,	0x16514e31	},
+static u32 thirty_three_base_hpt37x[] = {
+	/* XFER_UDMA_6 */	0x12446231,	/* 0x12646231 ?? */
+	/* XFER_UDMA_5 */	0x12446231,
+	/* XFER_UDMA_4 */	0x12446231,
+	/* XFER_UDMA_3 */	0x126c6231,
+	/* XFER_UDMA_2 */	0x12486231,
+	/* XFER_UDMA_1 */	0x124c6233,
+	/* XFER_UDMA_0 */	0x12506297,
 
-	{	XFER_MW_DMA_2,	0x26514e21	},
-	{	XFER_MW_DMA_1,	0x26514e33	},
-	{	XFER_MW_DMA_0,	0x26514e97	},
+	/* XFER_MW_DMA_2 */	0x22406c31,
+	/* XFER_MW_DMA_1 */	0x22406c33,
+	/* XFER_MW_DMA_0 */	0x22406c97,
 
-	{	XFER_PIO_4,	0x06514e21	},
-	{	XFER_PIO_3,	0x06514e22	},
-	{	XFER_PIO_2,	0x06514e33	},
-	{	XFER_PIO_1,	0x06914e43	},
-	{	XFER_PIO_0,	0x06914e57	},
-	{	0,		0x06514e57	}
+	/* XFER_PIO_4 */	0x06414e31,
+	/* XFER_PIO_3 */	0x06414e42,
+	/* XFER_PIO_2 */	0x06414e53,
+	/* XFER_PIO_1 */	0x06814e93,
+	/* XFER_PIO_0 */	0x06814ea7
 };
 
-static struct chipset_bus_clock_list_entry sixty_six_base_hpt370[] = {
-	{	XFER_UDMA_5,	0x14846231	},
-	{	XFER_UDMA_4,	0x14886231	},
-	{	XFER_UDMA_3,	0x148c6231	},
-	{	XFER_UDMA_2,	0x148c6231	},
-	{	XFER_UDMA_1,	0x14906231	},
-	{	XFER_UDMA_0,	0x14986231	},
+static u32 fifty_base_hpt37x[] = {
+	/* XFER_UDMA_6 */	0x12848242,
+	/* XFER_UDMA_5 */	0x12848242,
+	/* XFER_UDMA_4 */	0x12ac8242,
+	/* XFER_UDMA_3 */	0x128c8242,
+	/* XFER_UDMA_2 */	0x120c8242,
+	/* XFER_UDMA_1 */	0x12148254,
+	/* XFER_UDMA_0 */	0x121882ea,
 
-	{	XFER_MW_DMA_2,	0x26514e21	},
-	{	XFER_MW_DMA_1,	0x26514e33	},
-	{	XFER_MW_DMA_0,	0x26514e97	},
+	/* XFER_MW_DMA_2 */	0x22808242,
+	/* XFER_MW_DMA_1 */	0x22808254,
+	/* XFER_MW_DMA_0 */	0x228082ea,
 
-	{	XFER_PIO_4,	0x06514e21	},
-	{	XFER_PIO_3,	0x06514e22	},
-	{	XFER_PIO_2,	0x06514e33	},
-	{	XFER_PIO_1,	0x06914e43	},
-	{	XFER_PIO_0,	0x06914e57	},
-	{	0,		0x06514e57	}
+	/* XFER_PIO_4 */	0x0a81f442,
+	/* XFER_PIO_3 */	0x0a81f443,
+	/* XFER_PIO_2 */	0x0a81f454,
+	/* XFER_PIO_1 */	0x0ac1f465,
+	/* XFER_PIO_0 */	0x0ac1f48a
 };
 
-/* these are the current (4 sep 2001) timings from highpoint */
-static struct chipset_bus_clock_list_entry thirty_three_base_hpt370a[] = {
-	{	XFER_UDMA_5,	0x12446231	},
-	{	XFER_UDMA_4,	0x12446231	},
-	{	XFER_UDMA_3,	0x126c6231	},
-	{	XFER_UDMA_2,	0x12486231	},
-	{	XFER_UDMA_1,	0x124c6233	},
-	{	XFER_UDMA_0,	0x12506297	},
+static u32 sixty_six_base_hpt37x[] = {
+	/* XFER_UDMA_6 */	0x1c869c62,
+	/* XFER_UDMA_5 */	0x1cae9c62,	/* 0x1c8a9c62 */
+	/* XFER_UDMA_4 */	0x1c8a9c62,
+	/* XFER_UDMA_3 */	0x1c8e9c62,
+	/* XFER_UDMA_2 */	0x1c929c62,
+	/* XFER_UDMA_1 */	0x1c9a9c62,
+	/* XFER_UDMA_0 */	0x1c829c62,
 
-	{	XFER_MW_DMA_2,	0x22406c31	},
-	{	XFER_MW_DMA_1,	0x22406c33	},
-	{	XFER_MW_DMA_0,	0x22406c97	},
+	/* XFER_MW_DMA_2 */	0x2c829c62,
+	/* XFER_MW_DMA_1 */	0x2c829c66,
+	/* XFER_MW_DMA_0 */	0x2c829d2e,
 
-	{	XFER_PIO_4,	0x06414e31	},
-	{	XFER_PIO_3,	0x06414e42	},
-	{	XFER_PIO_2,	0x06414e53	},
-	{	XFER_PIO_1,	0x06814e93	},
-	{	XFER_PIO_0,	0x06814ea7	},
-	{	0,		0x06814ea7	}
+	/* XFER_PIO_4 */	0x0c829c62,
+	/* XFER_PIO_3 */	0x0c829c84,
+	/* XFER_PIO_2 */	0x0c829ca6,
+	/* XFER_PIO_1 */	0x0d029d26,
+	/* XFER_PIO_0 */	0x0d029d5e
 };
 
-/* 2x 33MHz timings */
-static struct chipset_bus_clock_list_entry sixty_six_base_hpt370a[] = {
-	{	XFER_UDMA_5,	0x1488e673	},
-	{	XFER_UDMA_4,	0x1488e673	},
-	{	XFER_UDMA_3,	0x1498e673	},
-	{	XFER_UDMA_2,	0x1490e673	},
-	{	XFER_UDMA_1,	0x1498e677	},
-	{	XFER_UDMA_0,	0x14a0e73f	},
-
-	{	XFER_MW_DMA_2,	0x2480fa73	},
-	{	XFER_MW_DMA_1,	0x2480fa77	}, 
-	{	XFER_MW_DMA_0,	0x2480fb3f	},
-
-	{	XFER_PIO_4,	0x0c82be73	},
-	{	XFER_PIO_3,	0x0c82be95	},
-	{	XFER_PIO_2,	0x0c82beb7	},
-	{	XFER_PIO_1,	0x0d02bf37	},
-	{	XFER_PIO_0,	0x0d02bf5f	},
-	{	0,		0x0d02bf5f	}
-};
-
-static struct chipset_bus_clock_list_entry fifty_base_hpt370a[] = {
-	{	XFER_UDMA_5,	0x12848242	},
-	{	XFER_UDMA_4,	0x12ac8242	},
-	{	XFER_UDMA_3,	0x128c8242	},
-	{	XFER_UDMA_2,	0x120c8242	},
-	{	XFER_UDMA_1,	0x12148254	},
-	{	XFER_UDMA_0,	0x121882ea	},
-
-	{	XFER_MW_DMA_2,	0x22808242	},
-	{	XFER_MW_DMA_1,	0x22808254	},
-	{	XFER_MW_DMA_0,	0x228082ea	},
-
-	{	XFER_PIO_4,	0x0a81f442	},
-	{	XFER_PIO_3,	0x0a81f443	},
-	{	XFER_PIO_2,	0x0a81f454	},
-	{	XFER_PIO_1,	0x0ac1f465	},
-	{	XFER_PIO_0,	0x0ac1f48a	},
-	{	0,		0x0ac1f48a	}
-};
-
-static struct chipset_bus_clock_list_entry thirty_three_base_hpt372[] = {
-	{	XFER_UDMA_6,	0x1c81dc62	},
-	{	XFER_UDMA_5,	0x1c6ddc62	},
-	{	XFER_UDMA_4,	0x1c8ddc62	},
-	{	XFER_UDMA_3,	0x1c8edc62	},	/* checkme */
-	{	XFER_UDMA_2,	0x1c91dc62	},
-	{	XFER_UDMA_1,	0x1c9adc62	},	/* checkme */
-	{	XFER_UDMA_0,	0x1c82dc62	},	/* checkme */
-
-	{	XFER_MW_DMA_2,	0x2c829262	},
-	{	XFER_MW_DMA_1,	0x2c829266	},	/* checkme */
-	{	XFER_MW_DMA_0,	0x2c82922e	},	/* checkme */
-
-	{	XFER_PIO_4,	0x0c829c62	},
-	{	XFER_PIO_3,	0x0c829c84	},
-	{	XFER_PIO_2,	0x0c829ca6	},
-	{	XFER_PIO_1,	0x0d029d26	},
-	{	XFER_PIO_0,	0x0d029d5e	},
-	{	0,		0x0d029d5e	}
-};
-
-static struct chipset_bus_clock_list_entry fifty_base_hpt372[] = {
-	{	XFER_UDMA_5,	0x12848242	},
-	{	XFER_UDMA_4,	0x12ac8242	},
-	{	XFER_UDMA_3,	0x128c8242	},
-	{	XFER_UDMA_2,	0x120c8242	},
-	{	XFER_UDMA_1,	0x12148254	},
-	{	XFER_UDMA_0,	0x121882ea	},
-
-	{	XFER_MW_DMA_2,	0x22808242	},
-	{	XFER_MW_DMA_1,	0x22808254	},
-	{	XFER_MW_DMA_0,	0x228082ea	},
-
-	{	XFER_PIO_4,	0x0a81f442	},
-	{	XFER_PIO_3,	0x0a81f443	},
-	{	XFER_PIO_2,	0x0a81f454	},
-	{	XFER_PIO_1,	0x0ac1f465	},
-	{	XFER_PIO_0,	0x0ac1f48a	},
-	{	0,		0x0a81f443	}
-};
-
-static struct chipset_bus_clock_list_entry sixty_six_base_hpt372[] = {
-	{	XFER_UDMA_6,	0x1c869c62	},
-	{	XFER_UDMA_5,	0x1cae9c62	},
-	{	XFER_UDMA_4,	0x1c8a9c62	},
-	{	XFER_UDMA_3,	0x1c8e9c62	},
-	{	XFER_UDMA_2,	0x1c929c62	},
-	{	XFER_UDMA_1,	0x1c9a9c62	},
-	{	XFER_UDMA_0,	0x1c829c62	},
-
-	{	XFER_MW_DMA_2,	0x2c829c62	},
-	{	XFER_MW_DMA_1,	0x2c829c66	},
-	{	XFER_MW_DMA_0,	0x2c829d2e	},
-
-	{	XFER_PIO_4,	0x0c829c62	},
-	{	XFER_PIO_3,	0x0c829c84	},
-	{	XFER_PIO_2,	0x0c829ca6	},
-	{	XFER_PIO_1,	0x0d029d26	},
-	{	XFER_PIO_0,	0x0d029d5e	},
-	{	0,		0x0d029d26	}
-};
-
-static struct chipset_bus_clock_list_entry thirty_three_base_hpt374[] = {
-	{	XFER_UDMA_6,	0x12808242	},
-	{	XFER_UDMA_5,	0x12848242	},
-	{	XFER_UDMA_4,	0x12ac8242	},
-	{	XFER_UDMA_3,	0x128c8242	},
-	{	XFER_UDMA_2,	0x120c8242	},
-	{	XFER_UDMA_1,	0x12148254	},
-	{	XFER_UDMA_0,	0x121882ea	},
-
-	{	XFER_MW_DMA_2,	0x22808242	},
-	{	XFER_MW_DMA_1,	0x22808254	},
-	{	XFER_MW_DMA_0,	0x228082ea	},
-
-	{	XFER_PIO_4,	0x0a81f442	},
-	{	XFER_PIO_3,	0x0a81f443	},
-	{	XFER_PIO_2,	0x0a81f454	},
-	{	XFER_PIO_1,	0x0ac1f465	},
-	{	XFER_PIO_0,	0x0ac1f48a	},
-	{	0,		0x06814e93	}
-};
-
-/* FIXME: 50MHz timings for HPT374 */
-
-#if 0
-static struct chipset_bus_clock_list_entry sixty_six_base_hpt374[] = {
-	{	XFER_UDMA_6,	0x12406231	},	/* checkme */
-	{	XFER_UDMA_5,	0x12446231	},	/* 0x14846231 */
-	{	XFER_UDMA_4,	0x16814ea7	},	/* 0x14886231 */
-	{	XFER_UDMA_3,	0x16814ea7	},	/* 0x148c6231 */
-	{	XFER_UDMA_2,	0x16814ea7	},	/* 0x148c6231 */
-	{	XFER_UDMA_1,	0x16814ea7	},	/* 0x14906231 */
-	{	XFER_UDMA_0,	0x16814ea7	},	/* 0x14986231 */
-	{	XFER_MW_DMA_2,	0x16814ea7	},	/* 0x26514e21 */
-	{	XFER_MW_DMA_1,	0x16814ea7	},	/* 0x26514e97 */
-	{	XFER_MW_DMA_0,	0x16814ea7	},	/* 0x26514e97 */
-	{	XFER_PIO_4,	0x06814ea7	},	/* 0x06514e21 */
-	{	XFER_PIO_3,	0x06814ea7	},	/* 0x06514e22 */
-	{	XFER_PIO_2,	0x06814ea7	},	/* 0x06514e33 */
-	{	XFER_PIO_1,	0x06814ea7	},	/* 0x06914e43 */
-	{	XFER_PIO_0,	0x06814ea7	},	/* 0x06914e57 */
-	{	0,		0x06814ea7	}
-};
-#endif
-
 #define HPT366_DEBUG_DRIVE_INFO		0
 #define HPT374_ALLOW_ATA133_6		0
 #define HPT371_ALLOW_ATA133_6		0
 #define HPT302_ALLOW_ATA133_6		0
-#define HPT372_ALLOW_ATA133_6		1
+#define HPT372_ALLOW_ATA133_6		0
 #define HPT370_ALLOW_ATA100_5		1
 #define HPT366_ALLOW_ATA66_4		1
 #define HPT366_ALLOW_ATA66_3		1
@@ -461,9 +357,10 @@
 	int revision;		/* Chipset revision */
 	int flags;		/* Chipset properties */
 #define PLL_MODE	1
-#define IS_372N		2
+#define IS_3xxN 	2
+#define PCI_66MHZ	4
 				/* Speed table */
-	struct chipset_bus_clock_list_entry *speed;
+	u32 *speed;
 };
 
 /*
@@ -600,12 +497,20 @@
 	return 0;
 }
 
-static unsigned int pci_bus_clock_list (u8 speed, struct chipset_bus_clock_list_entry * chipset_table)
+static u32 pci_bus_clock_list(u8 speed, u32 *chipset_table)
 {
-	for ( ; chipset_table->xfer_speed ; chipset_table++)
-		if (chipset_table->xfer_speed == speed)
-			return chipset_table->chipset_settings;
-	return chipset_table->chipset_settings;
+	int i;
+
+	/*
+	 * Lookup the transfer mode table to get the index into
+	 * the timing table.
+	 *
+	 * NOTE: For XFER_PIO_SLOW, PIO mode 0 timings will be used.
+	 */
+	for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++)
+		if (xfer_speeds[i] == speed)
+			break;
+	return chipset_table[i];
 }
 
 static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed)
@@ -956,156 +861,127 @@
 }
 
 /**
- *	hpt372n_set_clock	-	perform clock switching dance
- *	@drive: Drive to switch
- *	@mode: Switching mode (0x21 for write, 0x23 otherwise)
+ *	hpt3xxn_set_clock	-	perform clock switching dance
+ *	@hwif: hwif to switch
+ *	@mode: clocking mode (0x21 for write, 0x23 otherwise)
  *
- *	Switch the DPLL clock on the HPT372N devices. This is a
- *	right mess.
+ *	Switch the DPLL clock on the HPT3xxN devices. This is a	right mess.
+ *	NOTE: avoid touching the disabled primary channel on HPT371N -- it
+ *	doesn't physically exist anyway...
  */
- 
-static void hpt372n_set_clock(ide_drive_t *drive, int mode)
+
+static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-	
-	/* FIXME: should we check for DMA active and BUG() */
+	u8 mcr1, scr2 = hwif->INB(hwif->dma_master + 0x7b);
+
+	if ((scr2 & 0x7f) == mode)
+		return;
+
+	/* MISC. control register 1 has the channel enable bit... */
+	mcr1 = hwif->INB(hwif->dma_master + 0x70);
+
 	/* Tristate the bus */
-	outb(0x80, hwif->dma_base+0x73);
-	outb(0x80, hwif->dma_base+0x77);
-	
+	if (mcr1 & 0x04)
+		hwif->OUTB(0x80, hwif->dma_master + 0x73);
+	hwif->OUTB(0x80, hwif->dma_master + 0x77);
+
 	/* Switch clock and reset channels */
-	outb(mode, hwif->dma_base+0x7B);
-	outb(0xC0, hwif->dma_base+0x79);
-	
+	hwif->OUTB(mode, hwif->dma_master + 0x7b);
+	hwif->OUTB(0xc0, hwif->dma_master + 0x79);
+
 	/* Reset state machines */
-	outb(0x37, hwif->dma_base+0x70);
-	outb(0x37, hwif->dma_base+0x74);
-	
+	if (mcr1 & 0x04)
+		hwif->OUTB(0x37, hwif->dma_master + 0x70);
+	hwif->OUTB(0x37, hwif->dma_master + 0x74);
+
 	/* Complete reset */
-	outb(0x00, hwif->dma_base+0x79);
-	
+	hwif->OUTB(0x00, hwif->dma_master + 0x79);
+
 	/* Reconnect channels to bus */
-	outb(0x00, hwif->dma_base+0x73);
-	outb(0x00, hwif->dma_base+0x77);
+	if (mcr1 & 0x04)
+		hwif->OUTB(0x00, hwif->dma_master + 0x73);
+	hwif->OUTB(0x00, hwif->dma_master + 0x77);
 }
 
 /**
- *	hpt372n_rw_disk		-	prepare for I/O
+ *	hpt3xxn_rw_disk		-	prepare for I/O
  *	@drive: drive for command
  *	@rq: block request structure
  *
- *	This is called when a disk I/O is issued to the 372N.
+ *	This is called when a disk I/O is issued to HPT3xxN.
  *	We need it because of the clock switching.
  */
 
-static void hpt372n_rw_disk(ide_drive_t *drive, struct request *rq)
-{
-	ide_hwif_t *hwif = drive->hwif;
-	int wantclock;
-
-	wantclock = rq_data_dir(rq) ? 0x23 : 0x21;
-
-	if (hwif->config_data != wantclock) {
-		hpt372n_set_clock(drive, wantclock);
-		hwif->config_data = wantclock;
-	}
-}
-
-/*
- * Since SUN Cobalt is attempting to do this operation, I should disclose
- * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date
- * HOTSWAP ATA Infrastructure.
- */
-
-static void hpt3xx_reset (ide_drive_t *drive)
-{
-}
-
-static int hpt3xx_tristate (ide_drive_t * drive, int state)
+static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
-	u8 reg59h = 0, reset	= (hwif->channel) ? 0x80 : 0x40;
-	u8 regXXh = 0, state_reg= (hwif->channel) ? 0x57 : 0x53;
+	u8 wantclock		= rq_data_dir(rq) ? 0x23 : 0x21;
 
-	pci_read_config_byte(dev, 0x59, &reg59h);
-	pci_read_config_byte(dev, state_reg, &regXXh);
-
-	if (state) {
-		(void) ide_do_reset(drive);
-		pci_write_config_byte(dev, state_reg, regXXh|0x80);
-		pci_write_config_byte(dev, 0x59, reg59h|reset);
-	} else {
-		pci_write_config_byte(dev, 0x59, reg59h & ~(reset));
-		pci_write_config_byte(dev, state_reg, regXXh & ~(0x80));
-		(void) ide_do_reset(drive);
-	}
-	return 0;
+	hpt3xxn_set_clock(hwif, wantclock);
 }
 
 /* 
- * set/get power state for a drive.
- * turning the power off does the following things:
- *   1) soft-reset the drive
- *   2) tri-states the ide bus
+ * Set/get power state for a drive.
  *
- * when we turn things back on, we need to re-initialize things.
+ * When we turn the power back on, we need to re-initialize things.
  */
 #define TRISTATE_BIT  0x8000
-static int hpt370_busproc(ide_drive_t * drive, int state)
+
+static int hpt3xx_busproc(ide_drive_t *drive, int state)
 {
 	ide_hwif_t *hwif	= drive->hwif;
 	struct pci_dev *dev	= hwif->pci_dev;
-	u8 tristate = 0, resetmask = 0, bus_reg = 0;
-	u16 tri_reg;
+	u8  tristate, resetmask, bus_reg = 0;
+	u16 tri_reg = 0;
 
 	hwif->bus_state = state;
 
 	if (hwif->channel) { 
 		/* secondary channel */
-		tristate = 0x56;
-		resetmask = 0x80; 
+		tristate  = 0x56;
+		resetmask = 0x80;
 	} else { 
 		/* primary channel */
-		tristate = 0x52;
+		tristate  = 0x52;
 		resetmask = 0x40;
 	}
 
-	/* grab status */
+	/* Grab the status. */
 	pci_read_config_word(dev, tristate, &tri_reg);
 	pci_read_config_byte(dev, 0x59, &bus_reg);
 
-	/* set the state. we don't set it if we don't need to do so.
-	 * make sure that the drive knows that it has failed if it's off */
+	/*
+	 * Set the state. We don't set it if we don't need to do so.
+	 * Make sure that the drive knows that it has failed if it's off.
+	 */
 	switch (state) {
 	case BUSSTATE_ON:
-		hwif->drives[0].failures = 0;
-		hwif->drives[1].failures = 0;
-		if ((bus_reg & resetmask) == 0)
+		if (!(bus_reg & resetmask))
 			return 0;
-		tri_reg &= ~TRISTATE_BIT;
-		bus_reg &= ~resetmask;
-		break;
+		hwif->drives[0].failures = hwif->drives[1].failures = 0;
+
+		pci_write_config_byte(dev, 0x59, bus_reg & ~resetmask);
+		pci_write_config_word(dev, tristate, tri_reg & ~TRISTATE_BIT);
+		return 0;
 	case BUSSTATE_OFF:
-		hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
-		hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
-		if ((tri_reg & TRISTATE_BIT) == 0 && (bus_reg & resetmask))
+		if ((bus_reg & resetmask) && !(tri_reg & TRISTATE_BIT))
 			return 0;
 		tri_reg &= ~TRISTATE_BIT;
-		bus_reg |= resetmask;
 		break;
 	case BUSSTATE_TRISTATE:
-		hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
-		hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
-		if ((tri_reg & TRISTATE_BIT) && (bus_reg & resetmask))
+		if ((bus_reg & resetmask) &&  (tri_reg & TRISTATE_BIT))
 			return 0;
 		tri_reg |= TRISTATE_BIT;
-		bus_reg |= resetmask;
 		break;
+	default:
+		return -EINVAL;
 	}
-	pci_write_config_byte(dev, 0x59, bus_reg);
-	pci_write_config_word(dev, tristate, tri_reg);
 
+	hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
+	hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
+
+	pci_write_config_word(dev, tristate, tri_reg);
+	pci_write_config_byte(dev, 0x59, bus_reg | resetmask);
 	return 0;
 }
 
@@ -1119,14 +995,14 @@
 	/* detect bus speed by looking at control reg timing: */
 	switch((reg1 >> 8) & 7) {
 		case 5:
-			info->speed = forty_base_hpt366;
+			info->speed = forty_base_hpt36x;
 			break;
 		case 9:
-			info->speed = twenty_five_base_hpt366;
+			info->speed = twenty_five_base_hpt36x;
 			break;
 		case 7:
 		default:
-			info->speed = thirty_three_base_hpt366;
+			info->speed = thirty_three_base_hpt36x;
 			break;
 	}
 }
@@ -1136,9 +1012,9 @@
 	struct hpt_info *info = ide_get_hwifdata(hwif);
 	struct pci_dev *dev = hwif->pci_dev;
 	int adjust, i;
-	u16 freq;
-	u32 pll;
-	u8 reg5bh;
+	u16 freq = 0;
+	u32 pll, temp = 0;
+	u8 reg5bh = 0, mcr1 = 0;
 	
 	/*
 	 * default to pci clock. make sure MA15/16 are set to output
@@ -1151,27 +1027,40 @@
 	pci_write_config_byte(dev, 0x5b, 0x23);
 
 	/*
-	 * set up the PLL. we need to adjust it so that it's stable. 
-	 * freq = Tpll * 192 / Tpci
+	 * We'll have to read f_CNT value in order to determine
+	 * the PCI clock frequency according to the following ratio:
 	 *
-	 * Todo. For non x86 should probably check the dword is
-	 * set to 0xABCDExxx indicating the BIOS saved f_CNT
+	 * f_CNT = Fpci * 192 / Fdpll
+	 *
+	 * First try reading the register in which the HighPoint BIOS
+	 * saves f_CNT value before  reprogramming the DPLL from its
+	 * default setting (which differs for the various chips).
+	 * NOTE: This register is only accessible via I/O space.
+	 *
+	 * In case the signature check fails, we'll have to resort to
+	 * reading the f_CNT register itself in hopes that nobody has
+	 * touched the DPLL yet...
 	 */
-	pci_read_config_word(dev, 0x78, &freq);
-	freq &= 0x1FF;
-	
+	temp = inl(pci_resource_start(dev, 4) + 0x90);
+	if ((temp & 0xFFFFF000) != 0xABCDE000) {
+		printk(KERN_WARNING "HPT37X: no clock data saved by BIOS\n");
+
+		/* Calculate the average value of f_CNT */
+		for (temp = i = 0; i < 128; i++) {
+			pci_read_config_word(dev, 0x78, &freq);
+			temp += freq & 0x1ff;
+			mdelay(1);
+		}
+		freq = temp / 128;
+	} else
+		freq = temp & 0x1ff;
+
 	/*
-	 * The 372N uses different PCI clock information and has
-	 * some other complications
-	 *	On PCI33 timing we must clock switch
-	 *	On PCI66 timing we must NOT use the PCI clock
-	 *
-	 * Currently we always set up the PLL for the 372N
+	 * HPT3xxN chips use different PCI clock information.
+	 * Currently we always set up the PLL for them.
 	 */
-	 
-	if(info->flags & IS_372N)
-	{
-		printk(KERN_INFO "hpt: HPT372N detected, using 372N timing.\n");
+
+	if (info->flags & IS_3xxN) {
 		if(freq < 0x55)
 			pll = F_LOW_PCI_33;
 		else if(freq < 0x70)
@@ -1180,10 +1069,8 @@
 			pll = F_LOW_PCI_50;
 		else
 			pll = F_LOW_PCI_66;
-			
-		printk(KERN_INFO "FREQ: %d PLL: %d\n", freq, pll);
-			
-		/* We always use the pll not the PCI clock on 372N */
+
+		printk(KERN_INFO "HPT3xxN detected, FREQ: %d, PLL: %d\n", freq, pll);
 	}
 	else
 	{
@@ -1197,41 +1084,22 @@
 			pll = F_LOW_PCI_66;
 	
 		if (pll == F_LOW_PCI_33) {
-			if (info->revision >= 8)
-				info->speed = thirty_three_base_hpt374;
-			else if (info->revision >= 5)
-				info->speed = thirty_three_base_hpt372;
-			else if (info->revision >= 4)
-				info->speed = thirty_three_base_hpt370a;
-			else
-				info->speed = thirty_three_base_hpt370;
+			info->speed = thirty_three_base_hpt37x;
 			printk(KERN_DEBUG "HPT37X: using 33MHz PCI clock\n");
 		} else if (pll == F_LOW_PCI_40) {
 			/* Unsupported */
 		} else if (pll == F_LOW_PCI_50) {
-			if (info->revision >= 8)
-				info->speed = fifty_base_hpt370a;
-			else if (info->revision >= 5)
-				info->speed = fifty_base_hpt372;
-			else if (info->revision >= 4)
-				info->speed = fifty_base_hpt370a;
-			else
-				info->speed = fifty_base_hpt370a;
+			info->speed = fifty_base_hpt37x;
 			printk(KERN_DEBUG "HPT37X: using 50MHz PCI clock\n");
 		} else {
-			if (info->revision >= 8) {
-				printk(KERN_ERR "HPT37x: 66MHz timings are not supported.\n");
-			}
-			else if (info->revision >= 5)
-				info->speed = sixty_six_base_hpt372;
-			else if (info->revision >= 4)
-				info->speed = sixty_six_base_hpt370a;
-			else
-				info->speed = sixty_six_base_hpt370;
+			info->speed = sixty_six_base_hpt37x;
 			printk(KERN_DEBUG "HPT37X: using 66MHz PCI clock\n");
 		}
 	}
-	
+
+	if (pll == F_LOW_PCI_66)
+		info->flags |= PCI_66MHZ;
+
 	/*
 	 * only try the pll if we don't have a table for the clock
 	 * speed that we're running at. NOTE: the internal PLL will
@@ -1248,11 +1116,8 @@
 	info->flags |= PLL_MODE;
 	
 	/*
-	 * FIXME: make this work correctly, esp with 372N as per
-	 * reference driver code.
-	 *
-	 * adjust PLL based upon PCI clock, enable it, and wait for
-	 * stabilization.
+	 * Adjust the PLL based upon the PCI clock, enable it, and
+	 * wait for stabilization...
 	 */
 	adjust = 0;
 	freq = (pll < F_LOW_PCI_50) ? 2 : 4;
@@ -1275,22 +1140,12 @@
 				pci_write_config_dword(dev, 0x5c, 
 						       pll & ~0x100);
 				pci_write_config_byte(dev, 0x5b, 0x21);
-				if (info->revision >= 8)
-					info->speed = fifty_base_hpt370a;
-				else if (info->revision >= 5)
-					info->speed = fifty_base_hpt372;
-				else if (info->revision >= 4)
-					info->speed = fifty_base_hpt370a;
-				else
-					info->speed = fifty_base_hpt370a;
+
+				info->speed = fifty_base_hpt37x;
 				printk("HPT37X: using 50MHz internal PLL\n");
 				goto init_hpt37X_done;
 			}
 		}
-		if (!pci_get_drvdata(dev)) {
-			printk("No Clock Stabilization!!!\n");
-			return;
-		}
 pll_recal:
 		if (adjust & 1)
 			pll -= (adjust >> 1);
@@ -1300,11 +1155,16 @@
 
 init_hpt37X_done:
 	if (!info->speed)
-		printk(KERN_ERR "HPT37X%s: unknown bus timing [%d %d].\n",
-			(info->flags & IS_372N)?"N":"", pll, freq);
-	/* reset state engine */
-	pci_write_config_byte(dev, 0x50, 0x37); 
-	pci_write_config_byte(dev, 0x54, 0x37); 
+		printk(KERN_ERR "HPT37x%s: unknown bus timing [%d %d].\n",
+		       (info->flags & IS_3xxN) ? "N" : "", pll, freq);
+	/*
+	 * Reset the state engines.
+	 * NOTE: avoid accidentally enabling the primary channel on HPT371N.
+	 */
+	pci_read_config_byte(dev, 0x50, &mcr1);
+	if (mcr1 & 0x04)
+		pci_write_config_byte(dev, 0x50, 0x37);
+	pci_write_config_byte(dev, 0x54, 0x37);
 	udelay(100);
 }
 
@@ -1367,6 +1227,7 @@
 	struct pci_dev *dev		= hwif->pci_dev;
 	struct hpt_info *info		= ide_get_hwifdata(hwif);
 	u8 ata66 = 0, regmask		= (hwif->channel) ? 0x01 : 0x02;
+	int serialize			= HPT_SERIALIZE_IO;
 	
 	hwif->tuneproc			= &hpt3xx_tune_drive;
 	hwif->speedproc			= &hpt3xx_tune_chipset;
@@ -1374,8 +1235,20 @@
 	hwif->intrproc			= &hpt3xx_intrproc;
 	hwif->maskproc			= &hpt3xx_maskproc;
 	
-	if(info->flags & IS_372N)
-		hwif->rw_disk = &hpt372n_rw_disk;
+	/*
+	 * HPT3xxN chips have some complications:
+	 *
+	 * - on 33 MHz PCI we must clock switch
+	 * - on 66 MHz PCI we must NOT use the PCI clock
+	 */
+	if ((info->flags & (IS_3xxN | PCI_66MHZ)) == IS_3xxN) {
+		/*
+		 * Clock is shared between the channels,
+		 * so we'll have to serialize them... :-(
+		 */
+		serialize = 1;
+		hwif->rw_disk = &hpt3xxn_rw_disk;
+	}
 
 	/*
 	 * The HPT37x uses the CBLID pins as outputs for MA15/MA16
@@ -1418,29 +1291,15 @@
 		PCI_FUNC(hwif->pci_dev->devfn));
 #endif /* DEBUG */
 
-#ifdef HPT_SERIALIZE_IO
-	/* serialize access to this device */
-	if (hwif->mate)
+	/* Serialize access to this device */
+	if (serialize && hwif->mate)
 		hwif->serialized = hwif->mate->serialized = 1;
-#endif
 
-	if (info->revision >= 3) {
-		u8 reg5ah = 0;
-			pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10);
-		/*
-		 * set up ioctl for power status.
-		 * note: power affects both
-		 * drives on each channel
-		 */
-		hwif->resetproc	= &hpt3xx_reset;
-		hwif->busproc	= &hpt370_busproc;
-	} else if (info->revision >= 2) {
-		hwif->resetproc	= &hpt3xx_reset;
-		hwif->busproc	= &hpt3xx_tristate;
-	} else {
-		hwif->resetproc = &hpt3xx_reset;
-		hwif->busproc   = &hpt3xx_tristate;
-	}
+	/*
+	 * Set up ioctl for power status.
+	 * NOTE:  power affects both drives on each channel.
+	 */
+	hwif->busproc = &hpt3xx_busproc;
 
 	if (!hwif->dma_base) {
 		hwif->drives[0].autotune = 1;
@@ -1490,7 +1349,7 @@
 		return;
 		
 	if(info->speed == NULL) {
-		printk(KERN_WARNING "hpt: no known IDE timings, disabling DMA.\n");
+		printk(KERN_WARNING "hpt366: no known IDE timings, disabling DMA.\n");
 		return;
 	}
 
@@ -1519,9 +1378,10 @@
 
 static void __devinit init_iops_hpt366(ide_hwif_t *hwif)
 {
-	struct hpt_info *info = kzalloc(sizeof(struct hpt_info), GFP_KERNEL);
-	unsigned long dmabase = pci_resource_start(hwif->pci_dev, 4);
-	u8 did, rid;
+	struct hpt_info *info	= kzalloc(sizeof(struct hpt_info), GFP_KERNEL);
+	struct pci_dev  *dev	= hwif->pci_dev;
+	u16 did			= dev->device;
+	u8  rid			= 0;
 
 	if(info == NULL) {
 		printk(KERN_WARNING "hpt366: out of memory.\n");
@@ -1529,15 +1389,22 @@
 	}
 	ide_set_hwifdata(hwif, info);
 
-	if(dmabase) {
-		did = inb(dmabase + 0x22);
-		rid = inb(dmabase + 0x28);
-
-		if((did == 4 && rid == 6) || (did == 5 && rid > 1))
-			info->flags |= IS_372N;
+	/* Avoid doing the same thing twice. */
+	if (hwif->channel && hwif->mate) {
+		memcpy(info, ide_get_hwifdata(hwif->mate), sizeof(struct hpt_info));
+		return;
 	}
 
-	info->revision = hpt_revision(hwif->pci_dev);
+	pci_read_config_byte(dev, PCI_CLASS_REVISION, &rid);
+
+	if (( did == PCI_DEVICE_ID_TTI_HPT366  && rid == 6) ||
+	    ((did == PCI_DEVICE_ID_TTI_HPT372  ||
+	      did == PCI_DEVICE_ID_TTI_HPT302  ||
+	      did == PCI_DEVICE_ID_TTI_HPT371) && rid > 1) ||
+	      did == PCI_DEVICE_ID_TTI_HPT372N)
+		info->flags |= IS_3xxN;
+
+	info->revision = hpt_revision(dev);
 
 	if (info->revision >= 3)
 		hpt37x_clocking(hwif);
@@ -1574,6 +1441,23 @@
 	return ide_setup_pci_device(dev, d);
 }
 
+static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d)
+{
+	u8 mcr1 = 0;
+
+	/*
+	 * HPT371 chips physically have only one channel, the secondary one,
+	 * but the primary channel registers do exist!  Go figure...
+	 * So,  we manually disable the non-existing channel here
+	 * (if the BIOS hasn't done this already).
+	 */
+	pci_read_config_byte(dev, 0x50, &mcr1);
+	if (mcr1 & 0x04)
+		pci_write_config_byte(dev, 0x50, (mcr1 & ~0x04));
+
+	return ide_setup_pci_device(dev, d);
+}
+
 static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d)
 {
 	struct pci_dev *findev = NULL;
@@ -1661,13 +1545,14 @@
 		.bootable	= OFF_BOARD,
 	},{	/* 3 */
 		.name		= "HPT371",
-		.init_setup	= init_setup_hpt37x,
+		.init_setup	= init_setup_hpt371,
 		.init_chipset	= init_chipset_hpt366,
 		.init_iops	= init_iops_hpt366,
 		.init_hwif	= init_hwif_hpt366,
 		.init_dma	= init_dma_hpt366,
 		.channels	= 2,
 		.autodma	= AUTODMA,
+		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
 		.bootable	= OFF_BOARD,
 	},{	/* 4 */
 		.name		= "HPT374",
@@ -1699,13 +1584,16 @@
  *
  *	Called when the PCI registration layer (or the IDE initialization)
  *	finds a device matching our IDE device tables.
+ *
+ *	NOTE: since we'll have to modify some fields of the ide_pci_device_t
+ *	structure depending on the chip's revision, we'd better pass a local
+ *	copy down the call chain...
  */
- 
 static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-	ide_pci_device_t *d = &hpt366_chipsets[id->driver_data];
+	ide_pci_device_t d = hpt366_chipsets[id->driver_data];
 
-	return d->init_setup(dev, d);
+	return d.init_setup(dev, &d);
 }
 
 static struct pci_device_id hpt366_pci_tbl[] = {
diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c
index 54bc569..35461ea 100644
--- a/drivers/input/keyboard/hilkbd.c
+++ b/drivers/input/keyboard/hilkbd.c
@@ -23,7 +23,12 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/hil.h>
+#include <linux/io.h>
 #include <linux/spinlock.h>
+#include <asm/irq.h>
+#ifdef CONFIG_HP300
+#include <asm/hwtest.h>
+#endif
 
 
 MODULE_AUTHOR("Philip Blundell, Matthew Wilcox, Helge Deller");
diff --git a/drivers/isdn/act2000/act2000_isa.c b/drivers/isdn/act2000/act2000_isa.c
index 3cac237..09ea50d 100644
--- a/drivers/isdn/act2000/act2000_isa.c
+++ b/drivers/isdn/act2000/act2000_isa.c
@@ -408,7 +408,7 @@
         p = cblock.buffer;
         if (!access_ok(VERIFY_READ, p, length))
                 return -EFAULT;
-        buf = (u_char *) kmalloc(1024, GFP_KERNEL);
+        buf = kmalloc(1024, GFP_KERNEL);
         if (!buf)
                 return -ENOMEM;
         timeout = 0;
diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c
index 097bfa7..c4d438c 100644
--- a/drivers/isdn/capi/capidrv.c
+++ b/drivers/isdn/capi/capidrv.c
@@ -2013,7 +2013,7 @@
 	strcpy(card->name, id);
 	card->contrnr = contr;
 	card->nbchan = profp->nbchannel;
-	card->bchans = (capidrv_bchan *) kmalloc(sizeof(capidrv_bchan) * card->nbchan, GFP_ATOMIC);
+	card->bchans = kmalloc(sizeof(capidrv_bchan) * card->nbchan, GFP_ATOMIC);
 	if (!card->bchans) {
 		printk(KERN_WARNING
 		"capidrv: (%s) Could not allocate bchan-structs.\n", id);
diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c
index 399b316..06967da 100644
--- a/drivers/isdn/divert/divert_procfs.c
+++ b/drivers/isdn/divert/divert_procfs.c
@@ -45,7 +45,7 @@
 		return;
 	if (!*cp)
 		return;
-	if (!(ib = (struct divert_info *) kmalloc(sizeof(struct divert_info) + strlen(cp), GFP_ATOMIC)))
+	if (!(ib = kmalloc(sizeof(struct divert_info) + strlen(cp), GFP_ATOMIC)))
 		 return;	/* no memory */
 	strcpy(ib->info_start, cp);	/* set output string */
 	ib->next = NULL;
diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c
index 03319ea..7d97d54 100644
--- a/drivers/isdn/divert/isdn_divert.c
+++ b/drivers/isdn/divert/isdn_divert.c
@@ -153,7 +153,7 @@
   *ielenp = p - ielenp - 1; /* set total IE length */ 
 
   /* allocate mem for information struct */  
-  if (!(cs = (struct call_struc *) kmalloc(sizeof(struct call_struc), GFP_ATOMIC))) 
+  if (!(cs = kmalloc(sizeof(struct call_struc), GFP_ATOMIC)))
              return(-ENOMEM); /* no memory */
   init_timer(&cs->timer);
   cs->info[0] = '\0';
@@ -276,7 +276,7 @@
 { struct deflect_struc *ds,*ds1=NULL;
   unsigned long flags;
 
-  if (!(ds = (struct deflect_struc *) kmalloc(sizeof(struct deflect_struc), 
+  if (!(ds = kmalloc(sizeof(struct deflect_struc),
                                               GFP_KERNEL))) 
     return(-ENOMEM); /* no memory */
 
@@ -451,7 +451,7 @@
            if (dv->rule.action == DEFLECT_PROCEED)
 	    if ((!if_used) || ((!extern_wait_max) && (!dv->rule.waittime))) 
               return(0); /* no external deflection needed */  
-           if (!(cs = (struct call_struc *) kmalloc(sizeof(struct call_struc), GFP_ATOMIC))) 
+           if (!(cs = kmalloc(sizeof(struct call_struc), GFP_ATOMIC)))
              return(0); /* no memory */
            init_timer(&cs->timer);
            cs->info[0] = '\0';
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index 63b629b..b5e7f9c 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -1853,20 +1853,24 @@
 {
 	struct cmdbuf_t *cb;
 	unsigned long flags;
-	int status;
+	int rc;
 
 	gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ?
 			     DEBUG_TRANSCMD : DEBUG_LOCKCMD,
 			   "CMD Transmit", len, buf);
 
-	if (len <= 0)
-		return 0;			/* nothing to do */
+	if (len <= 0) {
+		/* nothing to do */
+		rc = 0;
+		goto notqueued;
+	}
 
 	if (len > IF_WRITEBUF)
 		len = IF_WRITEBUF;
 	if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) {
 		dev_err(cs->dev, "%s: out of memory\n", __func__);
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto notqueued;
 	}
 
 	memcpy(cb->buf, buf, len);
@@ -1891,11 +1895,21 @@
 	if (unlikely(!cs->connected)) {
 		spin_unlock_irqrestore(&cs->lock, flags);
 		gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__);
+		/* flush command queue */
+		spin_lock_irqsave(&cs->cmdlock, flags);
+		while (cs->cmdbuf != NULL)
+			complete_cb(cs);
+		spin_unlock_irqrestore(&cs->cmdlock, flags);
 		return -ENODEV;
 	}
-	status = start_cbsend(cs);
+	rc = start_cbsend(cs);
 	spin_unlock_irqrestore(&cs->lock, flags);
-	return status < 0 ? status : len;
+	return rc < 0 ? rc : len;
+
+notqueued:			/* request handled without queuing */
+	if (wake_tasklet)
+		tasklet_schedule(wake_tasklet);
+	return rc;
 }
 
 /* gigaset_write_room
@@ -1964,20 +1978,15 @@
 
 	/* kill URBs and tasklets before freeing - better safe than sorry */
 	atomic_set(&ubc->running, 0);
-	for (i = 0; i < BAS_OUTURBS; ++i)
-		if (ubc->isoouturbs[i].urb) {
-			gig_dbg(DEBUG_INIT, "%s: killing iso out URB %d",
-				__func__, i);
-			usb_kill_urb(ubc->isoouturbs[i].urb);
-			usb_free_urb(ubc->isoouturbs[i].urb);
-		}
-	for (i = 0; i < BAS_INURBS; ++i)
-		if (ubc->isoinurbs[i]) {
-			gig_dbg(DEBUG_INIT, "%s: killing iso in URB %d",
-				__func__, i);
-			usb_kill_urb(ubc->isoinurbs[i]);
-			usb_free_urb(ubc->isoinurbs[i]);
-		}
+	gig_dbg(DEBUG_INIT, "%s: killing iso URBs", __func__);
+	for (i = 0; i < BAS_OUTURBS; ++i) {
+		usb_kill_urb(ubc->isoouturbs[i].urb);
+		usb_free_urb(ubc->isoouturbs[i].urb);
+	}
+	for (i = 0; i < BAS_INURBS; ++i) {
+		usb_kill_urb(ubc->isoinurbs[i]);
+		usb_free_urb(ubc->isoinurbs[i]);
+	}
 	tasklet_kill(&ubc->sent_tasklet);
 	tasklet_kill(&ubc->rcvd_tasklet);
 	kfree(ubc->isooutbuf);
@@ -2099,55 +2108,32 @@
 	struct bas_bc_state *ubc;
 	int i, j;
 
+	gig_dbg(DEBUG_INIT, "%s: killing URBs", __func__);
 	for (j = 0; j < 2; ++j) {
 		ubc = cs->bcs[j].hw.bas;
-		for (i = 0; i < BAS_OUTURBS; ++i)
-			if (ubc->isoouturbs[i].urb) {
-				usb_kill_urb(ubc->isoouturbs[i].urb);
-				gig_dbg(DEBUG_INIT,
-					"%s: isoc output URB %d/%d unlinked",
-					__func__, j, i);
-				usb_free_urb(ubc->isoouturbs[i].urb);
-				ubc->isoouturbs[i].urb = NULL;
-			}
-		for (i = 0; i < BAS_INURBS; ++i)
-			if (ubc->isoinurbs[i]) {
-				usb_kill_urb(ubc->isoinurbs[i]);
-				gig_dbg(DEBUG_INIT,
-					"%s: isoc input URB %d/%d unlinked",
-					__func__, j, i);
-				usb_free_urb(ubc->isoinurbs[i]);
-				ubc->isoinurbs[i] = NULL;
-			}
+		for (i = 0; i < BAS_OUTURBS; ++i) {
+			usb_kill_urb(ubc->isoouturbs[i].urb);
+			usb_free_urb(ubc->isoouturbs[i].urb);
+			ubc->isoouturbs[i].urb = NULL;
+		}
+		for (i = 0; i < BAS_INURBS; ++i) {
+			usb_kill_urb(ubc->isoinurbs[i]);
+			usb_free_urb(ubc->isoinurbs[i]);
+			ubc->isoinurbs[i] = NULL;
+		}
 	}
-	if (ucs->urb_int_in) {
-		usb_kill_urb(ucs->urb_int_in);
-		gig_dbg(DEBUG_INIT, "%s: interrupt input URB unlinked",
-			__func__);
-		usb_free_urb(ucs->urb_int_in);
-		ucs->urb_int_in = NULL;
-	}
-	if (ucs->urb_cmd_out) {
-		usb_kill_urb(ucs->urb_cmd_out);
-		gig_dbg(DEBUG_INIT, "%s: command output URB unlinked",
-			__func__);
-		usb_free_urb(ucs->urb_cmd_out);
-		ucs->urb_cmd_out = NULL;
-	}
-	if (ucs->urb_cmd_in) {
-		usb_kill_urb(ucs->urb_cmd_in);
-		gig_dbg(DEBUG_INIT, "%s: command input URB unlinked",
-			__func__);
-		usb_free_urb(ucs->urb_cmd_in);
-		ucs->urb_cmd_in = NULL;
-	}
-	if (ucs->urb_ctrl) {
-		usb_kill_urb(ucs->urb_ctrl);
-		gig_dbg(DEBUG_INIT, "%s: control output URB unlinked",
-			__func__);
-		usb_free_urb(ucs->urb_ctrl);
-		ucs->urb_ctrl = NULL;
-	}
+	usb_kill_urb(ucs->urb_int_in);
+	usb_free_urb(ucs->urb_int_in);
+	ucs->urb_int_in = NULL;
+	usb_kill_urb(ucs->urb_cmd_out);
+	usb_free_urb(ucs->urb_cmd_out);
+	ucs->urb_cmd_out = NULL;
+	usb_kill_urb(ucs->urb_cmd_in);
+	usb_free_urb(ucs->urb_cmd_in);
+	ucs->urb_cmd_in = NULL;
+	usb_kill_urb(ucs->urb_ctrl);
+	usb_free_urb(ucs->urb_ctrl);
+	ucs->urb_ctrl = NULL;
 }
 
 /* gigaset_probe
diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c
index 8e2b038..94a93508 100644
--- a/drivers/isdn/hysdn/hysdn_procconf.c
+++ b/drivers/isdn/hysdn/hysdn_procconf.c
@@ -275,7 +275,7 @@
 	} else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
 		/* read access -> output card info data */
 
-		if (!(tmp = (char *) kmalloc(INFO_OUT_LEN * 2 + 2, GFP_KERNEL))) {
+		if (!(tmp = kmalloc(INFO_OUT_LEN * 2 + 2, GFP_KERNEL))) {
 			unlock_kernel();
 			return (-EFAULT);	/* out of memory */
 		}
diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c
index f241f5e..375d956 100644
--- a/drivers/isdn/hysdn/hysdn_proclog.c
+++ b/drivers/isdn/hysdn/hysdn_proclog.c
@@ -111,7 +111,7 @@
 	if (pd->if_used <= 0)
 		return;		/* no open file for read */
 
-	if (!(ib = (struct log_data *) kmalloc(sizeof(struct log_data) + strlen(cp), GFP_ATOMIC)))
+	if (!(ib = kmalloc(sizeof(struct log_data) + strlen(cp), GFP_ATOMIC)))
 		 return;	/* no memory */
 	strcpy(ib->log_start, cp);	/* set output string */
 	ib->next = NULL;
diff --git a/drivers/isdn/i4l/isdn_audio.c b/drivers/isdn/i4l/isdn_audio.c
index 2cc56d6..fb350c5 100644
--- a/drivers/isdn/i4l/isdn_audio.c
+++ b/drivers/isdn/i4l/isdn_audio.c
@@ -328,7 +328,7 @@
 isdn_audio_adpcm_init(adpcm_state * s, int nbits)
 {
 	if (!s)
-		s = (adpcm_state *) kmalloc(sizeof(adpcm_state), GFP_ATOMIC);
+		s = kmalloc(sizeof(adpcm_state), GFP_ATOMIC);
 	if (s) {
 		s->a = 0;
 		s->d = 5;
@@ -343,7 +343,7 @@
 isdn_audio_dtmf_init(dtmf_state * s)
 {
 	if (!s)
-		s = (dtmf_state *) kmalloc(sizeof(dtmf_state), GFP_ATOMIC);
+		s = kmalloc(sizeof(dtmf_state), GFP_ATOMIC);
 	if (s) {
 		s->idx = 0;
 		s->last = ' ';
@@ -621,7 +621,7 @@
 isdn_audio_silence_init(silence_state * s)
 {
 	if (!s)
-		s = (silence_state *) kmalloc(sizeof(silence_state), GFP_ATOMIC);
+		s = kmalloc(sizeof(silence_state), GFP_ATOMIC);
 	if (s) {
 		s->idx = 0;
 		s->state = 0;
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index c36c817..838b373 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -2948,7 +2948,7 @@
 	isdn_net_phone *n;
 
 	if (p) {
-		if (!(n = (isdn_net_phone *) kmalloc(sizeof(isdn_net_phone), GFP_KERNEL)))
+		if (!(n = kmalloc(sizeof(isdn_net_phone), GFP_KERNEL)))
 			return -ENOMEM;
 		strcpy(n->num, phone->phone);
 		n->next = p->local->phone[phone->outgoing & 1];
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index 4381179..1726131b 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -717,7 +717,7 @@
 		printk(KERN_DEBUG "ippp: device not activated.\n");
 		return 0;
 	}
-	nbuf = (unsigned char *) kmalloc(len + 4, GFP_ATOMIC);
+	nbuf = kmalloc(len + 4, GFP_ATOMIC);
 	if (!nbuf) {
 		printk(KERN_WARNING "ippp: Can't alloc buf\n");
 		return 0;
diff --git a/drivers/isdn/pcbit/layer2.c b/drivers/isdn/pcbit/layer2.c
index 6ff8557..eafcce5 100644
--- a/drivers/isdn/pcbit/layer2.c
+++ b/drivers/isdn/pcbit/layer2.c
@@ -100,7 +100,7 @@
 		dev_kfree_skb(skb);
 		return -1;
 	}
-	if ((frame = (struct frame_buf *) kmalloc(sizeof(struct frame_buf),
+	if ((frame = kmalloc(sizeof(struct frame_buf),
 						  GFP_ATOMIC)) == NULL) {
 		printk(KERN_WARNING "pcbit_2_write: kmalloc failed\n");
 		dev_kfree_skb(skb);
diff --git a/drivers/kvm/Kconfig b/drivers/kvm/Kconfig
index 36412e9..703cc88 100644
--- a/drivers/kvm/Kconfig
+++ b/drivers/kvm/Kconfig
@@ -1,6 +1,8 @@
 #
 # KVM configuration
 #
+menu "Virtualization"
+
 config KVM
 	tristate "Kernel-based Virtual Machine (KVM) support"
 	depends on X86 && EXPERIMENTAL
@@ -31,3 +33,5 @@
 	---help---
 	  Provides support for KVM on AMD processors equipped with the AMD-V
 	  (SVM) extensions.
+
+endmenu
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index 5785d08..930e04c 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -140,7 +140,7 @@
 	VCPU_REGS_RBP = 5,
 	VCPU_REGS_RSI = 6,
 	VCPU_REGS_RDI = 7,
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 	VCPU_REGS_R8 = 8,
 	VCPU_REGS_R9 = 9,
 	VCPU_REGS_R10 = 10,
@@ -375,7 +375,7 @@
 void set_cr8(struct kvm_vcpu *vcpu, unsigned long cr0);
 void lmsw(struct kvm_vcpu *vcpu, unsigned long msw);
 
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 void set_efer(struct kvm_vcpu *vcpu, u64 efer);
 #endif
 
@@ -485,7 +485,7 @@
 	return segment_base(tr);
 }
 
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 static inline unsigned long read_msr(unsigned long msr)
 {
 	u64 value;
@@ -533,7 +533,7 @@
 #define TSS_REDIRECTION_SIZE (256 / 8)
 #define RMODE_TSS_SIZE (TSS_BASE_SIZE + TSS_REDIRECTION_SIZE + TSS_IOPB_SIZE + 1)
 
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 
 /*
  * When emulating 32-bit mode, cr3 is only 32 bits even on x86_64.  Therefore
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index b6b8a41..fd1bb87 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -72,18 +72,7 @@
 #define CR8_RESEVED_BITS (~0x0fULL)
 #define EFER_RESERVED_BITS 0xfffffffffffff2fe
 
-struct vmx_msr_entry *find_msr_entry(struct kvm_vcpu *vcpu, u32 msr)
-{
-	int i;
-
-	for (i = 0; i < vcpu->nmsrs; ++i)
-		if (vcpu->guest_msrs[i].index == msr)
-			return &vcpu->guest_msrs[i];
-	return 0;
-}
-EXPORT_SYMBOL_GPL(find_msr_entry);
-
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 // LDT or TSS descriptor in the GDT. 16 bytes.
 struct segment_descriptor_64 {
 	struct segment_descriptor s;
@@ -115,7 +104,7 @@
 	}
 	d = (struct segment_descriptor *)(table_base + (selector & ~7));
 	v = d->base_low | ((ul)d->base_mid << 16) | ((ul)d->base_high << 24);
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 	if (d->system == 0
 	    && (d->type == 2 || d->type == 9 || d->type == 11))
 		v |= ((ul)((struct segment_descriptor_64 *)d)->base_higher) << 32;
@@ -216,7 +205,6 @@
 static void vcpu_put(struct kvm_vcpu *vcpu)
 {
 	kvm_arch_ops->vcpu_put(vcpu);
-	put_cpu();
 	mutex_unlock(&vcpu->mutex);
 }
 
@@ -351,7 +339,7 @@
 	}
 
 	if (!is_paging(vcpu) && (cr0 & CR0_PG_MASK)) {
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 		if ((vcpu->shadow_efer & EFER_LME)) {
 			int cs_db, cs_l;
 
@@ -1120,12 +1108,10 @@
 	return kvm_arch_ops->get_msr(vcpu, msr_index, pdata);
 }
 
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 
 void set_efer(struct kvm_vcpu *vcpu, u64 efer)
 {
-	struct vmx_msr_entry *msr;
-
 	if (efer & EFER_RESERVED_BITS) {
 		printk(KERN_DEBUG "set_efer: 0x%llx #GP, reserved bits\n",
 		       efer);
@@ -1140,16 +1126,12 @@
 		return;
 	}
 
+	kvm_arch_ops->set_efer(vcpu, efer);
+
 	efer &= ~EFER_LMA;
 	efer |= vcpu->shadow_efer & EFER_LMA;
 
 	vcpu->shadow_efer = efer;
-
-	msr = find_msr_entry(vcpu, MSR_EFER);
-
-	if (!(efer & EFER_LMA))
-	    efer &= ~EFER_LME;
-	msr->data = efer;
 }
 EXPORT_SYMBOL_GPL(set_efer);
 
@@ -1243,7 +1225,7 @@
 	regs->rdi = vcpu->regs[VCPU_REGS_RDI];
 	regs->rsp = vcpu->regs[VCPU_REGS_RSP];
 	regs->rbp = vcpu->regs[VCPU_REGS_RBP];
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 	regs->r8 = vcpu->regs[VCPU_REGS_R8];
 	regs->r9 = vcpu->regs[VCPU_REGS_R9];
 	regs->r10 = vcpu->regs[VCPU_REGS_R10];
@@ -1287,7 +1269,7 @@
 	vcpu->regs[VCPU_REGS_RDI] = regs->rdi;
 	vcpu->regs[VCPU_REGS_RSP] = regs->rsp;
 	vcpu->regs[VCPU_REGS_RBP] = regs->rbp;
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 	vcpu->regs[VCPU_REGS_R8] = regs->r8;
 	vcpu->regs[VCPU_REGS_R9] = regs->r9;
 	vcpu->regs[VCPU_REGS_R10] = regs->r10;
@@ -1401,7 +1383,7 @@
 	vcpu->cr8 = sregs->cr8;
 
 	mmu_reset_needed |= vcpu->shadow_efer != sregs->efer;
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 	kvm_arch_ops->set_efer(vcpu, sregs->efer);
 #endif
 	vcpu->apic_base = sregs->apic_base;
@@ -1434,7 +1416,7 @@
 static u32 msrs_to_save[] = {
 	MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP,
 	MSR_K6_STAR,
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 	MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR,
 #endif
 	MSR_IA32_TIME_STAMP_COUNTER,
diff --git a/drivers/kvm/kvm_svm.h b/drivers/kvm/kvm_svm.h
index 7d7f2aa..74cc862 100644
--- a/drivers/kvm/kvm_svm.h
+++ b/drivers/kvm/kvm_svm.h
@@ -9,7 +9,7 @@
 #include "kvm.h"
 
 static const u32 host_save_msrs[] = {
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 	MSR_STAR, MSR_LSTAR, MSR_CSTAR, MSR_SYSCALL_MASK, MSR_KERNEL_GS_BASE,
 	MSR_FS_BASE, MSR_GS_BASE,
 #endif
diff --git a/drivers/kvm/kvm_vmx.h b/drivers/kvm/kvm_vmx.h
index 87e12d2..d139f73 100644
--- a/drivers/kvm/kvm_vmx.h
+++ b/drivers/kvm/kvm_vmx.h
@@ -1,7 +1,7 @@
 #ifndef __KVM_VMX_H
 #define __KVM_VMX_H
 
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 /*
  * avoid save/load MSR_SYSCALL_MASK and MSR_LSTAR by std vt
  * mechanism (cpu bug AA24)
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index 4e29d9b..3d367cb 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -61,22 +61,9 @@
 
 
 #define PT32_PTE_COPY_MASK \
-	(PT_PRESENT_MASK | PT_PWT_MASK | PT_PCD_MASK | \
-	PT_ACCESSED_MASK | PT_DIRTY_MASK | PT_PAT_MASK | \
-	PT_GLOBAL_MASK )
+	(PT_PRESENT_MASK | PT_ACCESSED_MASK | PT_DIRTY_MASK | PT_GLOBAL_MASK)
 
-#define PT32_NON_PTE_COPY_MASK \
-	(PT_PRESENT_MASK | PT_PWT_MASK | PT_PCD_MASK | \
-	PT_ACCESSED_MASK | PT_DIRTY_MASK)
-
-
-#define PT64_PTE_COPY_MASK \
-	(PT64_NX_MASK | PT32_PTE_COPY_MASK)
-
-#define PT64_NON_PTE_COPY_MASK \
-	(PT64_NX_MASK | PT32_NON_PTE_COPY_MASK)
-
-
+#define PT64_PTE_COPY_MASK (PT64_NX_MASK | PT32_PTE_COPY_MASK)
 
 #define PT_FIRST_AVAIL_BITS_SHIFT 9
 #define PT64_SECOND_AVAIL_BITS_SHIFT 52
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h
index 765c2e1..a9771b4 100644
--- a/drivers/kvm/paging_tmpl.h
+++ b/drivers/kvm/paging_tmpl.h
@@ -32,7 +32,6 @@
 	#define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level)
 	#define PT_LEVEL_MASK(level) PT64_LEVEL_MASK(level)
 	#define PT_PTE_COPY_MASK PT64_PTE_COPY_MASK
-	#define PT_NON_PTE_COPY_MASK PT64_NON_PTE_COPY_MASK
 #elif PTTYPE == 32
 	#define pt_element_t u32
 	#define guest_walker guest_walker32
@@ -43,7 +42,6 @@
 	#define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level)
 	#define PT_LEVEL_MASK(level) PT32_LEVEL_MASK(level)
 	#define PT_PTE_COPY_MASK PT32_PTE_COPY_MASK
-	#define PT_NON_PTE_COPY_MASK PT32_NON_PTE_COPY_MASK
 #else
 	#error Invalid PTTYPE value
 #endif
@@ -105,9 +103,7 @@
 	if (PTTYPE == 32 && is_cpuid_PSE36())
 		gaddr |= (guest_pde & PT32_DIR_PSE36_MASK) <<
 			(32 - PT32_DIR_PSE36_SHIFT);
-	*shadow_pte = (guest_pde & (PT_NON_PTE_COPY_MASK | PT_GLOBAL_MASK)) |
-		          ((guest_pde & PT_DIR_PAT_MASK) >>
-			            (PT_DIR_PAT_SHIFT - PT_PAT_SHIFT));
+	*shadow_pte = guest_pde & PT_PTE_COPY_MASK;
 	set_pte_common(vcpu, shadow_pte, gaddr,
 		       guest_pde & PT_DIRTY_MASK, access_bits);
 }
@@ -162,6 +158,7 @@
 		u32 index = SHADOW_PT_INDEX(addr, level);
 		u64 *shadow_ent = ((u64 *)__va(shadow_addr)) + index;
 		pt_element_t *guest_ent;
+		u64 shadow_pte;
 
 		if (is_present_pte(*shadow_ent) || is_io_pte(*shadow_ent)) {
 			if (level == PT_PAGE_TABLE_LEVEL)
@@ -204,14 +201,11 @@
 		shadow_addr = kvm_mmu_alloc_page(vcpu, shadow_ent);
 		if (!VALID_PAGE(shadow_addr))
 			return ERR_PTR(-ENOMEM);
-		if (!kvm_arch_ops->is_long_mode(vcpu) && level == 3)
-			*shadow_ent = shadow_addr |
-				(*guest_ent & (PT_PRESENT_MASK | PT_PWT_MASK | PT_PCD_MASK));
-		else {
-			*shadow_ent = shadow_addr |
-				(*guest_ent & PT_NON_PTE_COPY_MASK);
-			*shadow_ent |= (PT_WRITABLE_MASK | PT_USER_MASK);
-		}
+		shadow_pte = shadow_addr | PT_PRESENT_MASK;
+		if (vcpu->mmu.root_level > 3 || level != 3)
+			shadow_pte |= PT_ACCESSED_MASK
+				| PT_WRITABLE_MASK | PT_USER_MASK;
+		*shadow_ent = shadow_pte;
 		prev_shadow_ent = shadow_ent;
 	}
 }
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index a33a89c..0e6bc8c 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -287,7 +287,7 @@
 
 	struct svm_cpu_data *svm_data;
 	uint64_t efer;
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 	struct desc_ptr gdt_descr;
 #else
 	struct Xgt_desc_struct gdt_descr;
@@ -377,6 +377,7 @@
 	void *msrpm_va;
 	int r;
 
+	kvm_emulator_want_group7_invlpg();
 
 	iopm_pages = alloc_pages(GFP_KERNEL, IOPM_ALLOC_ORDER);
 
@@ -397,7 +398,7 @@
 	memset(msrpm_va, 0xff, PAGE_SIZE * (1 << MSRPM_ALLOC_ORDER));
 	msrpm_base = page_to_pfn(msrpm_pages) << PAGE_SHIFT;
 
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 	set_msr_interception(msrpm_va, MSR_GS_BASE, 1, 1);
 	set_msr_interception(msrpm_va, MSR_FS_BASE, 1, 1);
 	set_msr_interception(msrpm_va, MSR_KERNEL_GS_BASE, 1, 1);
@@ -704,7 +705,7 @@
 
 static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 {
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 	if (vcpu->shadow_efer & KVM_EFER_LME) {
 		if (!is_paging(vcpu) && (cr0 & CR0_PG_MASK)) {
 			vcpu->shadow_efer |= KVM_EFER_LMA;
@@ -1097,7 +1098,7 @@
 	case MSR_IA32_APICBASE:
 		*data = vcpu->apic_base;
 		break;
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 	case MSR_STAR:
 		*data = vcpu->svm->vmcb->save.star;
 		break;
@@ -1149,7 +1150,7 @@
 static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data)
 {
 	switch (ecx) {
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 	case MSR_EFER:
 		set_efer(vcpu, data);
 		break;
@@ -1172,7 +1173,7 @@
 	case MSR_IA32_APICBASE:
 		vcpu->apic_base = data;
 		break;
-#ifdef __x86_64___
+#ifdef CONFIG_X86_64_
 	case MSR_STAR:
 		vcpu->svm->vmcb->save.star = data;
 		break;
@@ -1345,53 +1346,18 @@
 
 static void save_db_regs(unsigned long *db_regs)
 {
-#ifdef __x86_64__
-	asm ("mov %%dr0, %%rax \n\t"
-	     "mov %%rax, %[dr0] \n\t"
-	     "mov %%dr1, %%rax \n\t"
-	     "mov %%rax, %[dr1] \n\t"
-	     "mov %%dr2, %%rax \n\t"
-	     "mov %%rax, %[dr2] \n\t"
-	     "mov %%dr3, %%rax \n\t"
-	     "mov %%rax, %[dr3] \n\t"
-	     : [dr0] "=m"(db_regs[0]),
-	       [dr1] "=m"(db_regs[1]),
-	       [dr2] "=m"(db_regs[2]),
-	       [dr3] "=m"(db_regs[3])
-	     : : "rax");
-#else
-	asm ("mov %%dr0, %%eax \n\t"
-	     "mov %%eax, %[dr0] \n\t"
-	     "mov %%dr1, %%eax \n\t"
-	     "mov %%eax, %[dr1] \n\t"
-	     "mov %%dr2, %%eax \n\t"
-	     "mov %%eax, %[dr2] \n\t"
-	     "mov %%dr3, %%eax \n\t"
-	     "mov %%eax, %[dr3] \n\t"
-	     : [dr0] "=m"(db_regs[0]),
-	       [dr1] "=m"(db_regs[1]),
-	       [dr2] "=m"(db_regs[2]),
-	       [dr3] "=m"(db_regs[3])
-	     : : "eax");
-#endif
+	asm volatile ("mov %%dr0, %0" : "=r"(db_regs[0]));
+	asm volatile ("mov %%dr1, %0" : "=r"(db_regs[1]));
+	asm volatile ("mov %%dr2, %0" : "=r"(db_regs[2]));
+	asm volatile ("mov %%dr3, %0" : "=r"(db_regs[3]));
 }
 
 static void load_db_regs(unsigned long *db_regs)
 {
-	asm volatile ("mov %[dr0], %%dr0 \n\t"
-	     "mov %[dr1], %%dr1 \n\t"
-	     "mov %[dr2], %%dr2 \n\t"
-	     "mov %[dr3], %%dr3 \n\t"
-	     :
-	     : [dr0] "r"(db_regs[0]),
-	       [dr1] "r"(db_regs[1]),
-	       [dr2] "r"(db_regs[2]),
-	       [dr3] "r"(db_regs[3])
-#ifdef __x86_64__
-	     : "rax");
-#else
-	     : "eax");
-#endif
+	asm volatile ("mov %0, %%dr0" : : "r"(db_regs[0]));
+	asm volatile ("mov %0, %%dr1" : : "r"(db_regs[1]));
+	asm volatile ("mov %0, %%dr2" : : "r"(db_regs[2]));
+	asm volatile ("mov %0, %%dr3" : : "r"(db_regs[3]));
 }
 
 static int svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
@@ -1422,7 +1388,7 @@
 		load_db_regs(vcpu->svm->db_regs);
 	}
 	asm volatile (
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 		"push %%rbx; push %%rcx; push %%rdx;"
 		"push %%rsi; push %%rdi; push %%rbp;"
 		"push %%r8;  push %%r9;  push %%r10; push %%r11;"
@@ -1432,7 +1398,7 @@
 		"push %%esi; push %%edi; push %%ebp;"
 #endif
 
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 		"mov %c[rbx](%[vcpu]), %%rbx \n\t"
 		"mov %c[rcx](%[vcpu]), %%rcx \n\t"
 		"mov %c[rdx](%[vcpu]), %%rdx \n\t"
@@ -1456,7 +1422,7 @@
 		"mov %c[rbp](%[vcpu]), %%ebp \n\t"
 #endif
 
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 		/* Enter guest mode */
 		"push %%rax \n\t"
 		"mov %c[svm](%[vcpu]), %%rax \n\t"
@@ -1477,7 +1443,7 @@
 #endif
 
 		/* Save guest registers, load host registers */
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 		"mov %%rbx, %c[rbx](%[vcpu]) \n\t"
 		"mov %%rcx, %c[rcx](%[vcpu]) \n\t"
 		"mov %%rdx, %c[rdx](%[vcpu]) \n\t"
@@ -1518,7 +1484,7 @@
 		  [rsi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RSI])),
 		  [rdi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RDI])),
 		  [rbp]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RBP]))
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 		  ,[r8 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R8 ])),
 		  [r9 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R9 ])),
 		  [r10]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R10])),
@@ -1663,9 +1629,7 @@
 
 static int __init svm_init(void)
 {
-	kvm_emulator_want_group7_invlpg();
-	kvm_init_arch(&svm_arch_ops, THIS_MODULE);
-	return 0;
+	return kvm_init_arch(&svm_arch_ops, THIS_MODULE);
 }
 
 static void __exit svm_exit(void)
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index bda7a7a..f0f0b1a 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -22,6 +22,7 @@
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <asm/io.h>
+#include <asm/desc.h>
 
 #include "segment_descriptor.h"
 
@@ -33,7 +34,7 @@
 static DEFINE_PER_CPU(struct vmcs *, vmxarea);
 static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
 
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 #define HOST_IS_64 1
 #else
 #define HOST_IS_64 0
@@ -70,15 +71,13 @@
 };
 
 static const u32 vmx_msr_index[] = {
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 	MSR_SYSCALL_MASK, MSR_LSTAR, MSR_CSTAR, MSR_KERNEL_GS_BASE,
 #endif
 	MSR_EFER, MSR_K6_STAR,
 };
 #define NR_VMX_MSR (sizeof(vmx_msr_index) / sizeof(*vmx_msr_index))
 
-struct vmx_msr_entry *find_msr_entry(struct kvm_vcpu *vcpu, u32 msr);
-
 static inline int is_page_fault(u32 intr_info)
 {
 	return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
@@ -92,6 +91,16 @@
 		== (INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK);
 }
 
+static struct vmx_msr_entry *find_msr_entry(struct kvm_vcpu *vcpu, u32 msr)
+{
+	int i;
+
+	for (i = 0; i < vcpu->nmsrs; ++i)
+		if (vcpu->guest_msrs[i].index == msr)
+			return &vcpu->guest_msrs[i];
+	return 0;
+}
+
 static void vmcs_clear(struct vmcs *vmcs)
 {
 	u64 phys_addr = __pa(vmcs);
@@ -137,7 +146,7 @@
 
 static u64 vmcs_read64(unsigned long field)
 {
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 	return vmcs_readl(field);
 #else
 	return vmcs_readl(field) | ((u64)vmcs_readl(field+1) << 32);
@@ -167,7 +176,7 @@
 
 static void vmcs_write64(unsigned long field, u64 value)
 {
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 	vmcs_writel(field, value);
 #else
 	vmcs_writel(field, value);
@@ -296,7 +305,7 @@
 
 static void reload_tss(void)
 {
-#ifndef __x86_64__
+#ifndef CONFIG_X86_64
 
 	/*
 	 * VT restores TR but not its size.  Useless.
@@ -327,7 +336,7 @@
 	}
 
 	switch (msr_index) {
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 	case MSR_FS_BASE:
 		data = vmcs_readl(GUEST_FS_BASE);
 		break;
@@ -390,7 +399,7 @@
 {
 	struct vmx_msr_entry *msr;
 	switch (msr_index) {
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 	case MSR_FS_BASE:
 		vmcs_writel(GUEST_FS_BASE, data);
 		break;
@@ -525,7 +534,7 @@
 	u64 old;
 
 	rdmsrl(MSR_IA32_FEATURE_CONTROL, old);
-	if ((old & 5) == 0)
+	if ((old & 5) != 5)
 		/* enable and lock */
 		wrmsrl(MSR_IA32_FEATURE_CONTROL, old | 5);
 	write_cr4(read_cr4() | CR4_VMXE); /* FIXME: not cpu hotplug safe */
@@ -725,7 +734,7 @@
 	fix_rmode_seg(VCPU_SREG_FS, &vcpu->rmode.fs);
 }
 
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 
 static void enter_lmode(struct kvm_vcpu *vcpu)
 {
@@ -767,7 +776,7 @@
 	if (!vcpu->rmode.active && !(cr0 & CR0_PE_MASK))
 		enter_rmode(vcpu);
 
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 	if (vcpu->shadow_efer & EFER_LME) {
 		if (!is_paging(vcpu) && (cr0 & CR0_PG_MASK))
 			enter_lmode(vcpu);
@@ -808,7 +817,7 @@
 	vcpu->cr4 = cr4;
 }
 
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 
 static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer)
 {
@@ -883,6 +892,8 @@
 		ar |= (var->db & 1) << 14;
 		ar |= (var->g & 1) << 15;
 	}
+	if (ar == 0) /* a 0 value means unusable */
+		ar = AR_UNUSABLE_MASK;
 	vmcs_write32(sf->ar_bytes, ar);
 }
 
@@ -1095,7 +1106,7 @@
 	vmcs_write16(HOST_FS_SELECTOR, read_fs());    /* 22.2.4 */
 	vmcs_write16(HOST_GS_SELECTOR, read_gs());    /* 22.2.4 */
 	vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS);  /* 22.2.4 */
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 	rdmsrl(MSR_FS_BASE, a);
 	vmcs_writel(HOST_FS_BASE, a); /* 22.2.4 */
 	rdmsrl(MSR_GS_BASE, a);
@@ -1164,8 +1175,10 @@
                                VM_ENTRY_CONTROLS, 0);
 	vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0);  /* 22.2.1 */
 
+#ifdef CONFIG_X86_64
 	vmcs_writel(VIRTUAL_APIC_PAGE_ADDR, 0);
 	vmcs_writel(TPR_THRESHOLD, 0);
+#endif
 
 	vmcs_writel(CR0_GUEST_HOST_MASK, KVM_GUEST_CR0_MASK);
 	vmcs_writel(CR4_GUEST_HOST_MASK, KVM_GUEST_CR4_MASK);
@@ -1173,7 +1186,7 @@
 	vcpu->cr0 = 0x60000010;
 	vmx_set_cr0(vcpu, vcpu->cr0); // enter rmode
 	vmx_set_cr4(vcpu, 0);
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 	vmx_set_efer(vcpu, 0);
 #endif
 
@@ -1689,7 +1702,7 @@
 		vmcs_write16(HOST_GS_SELECTOR, 0);
 	}
 
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 	vmcs_writel(HOST_FS_BASE, read_msr(MSR_FS_BASE));
 	vmcs_writel(HOST_GS_BASE, read_msr(MSR_GS_BASE));
 #else
@@ -1713,7 +1726,7 @@
 	asm (
 		/* Store host registers */
 		"pushf \n\t"
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 		"push %%rax; push %%rbx; push %%rdx;"
 		"push %%rsi; push %%rdi; push %%rbp;"
 		"push %%r8;  push %%r9;  push %%r10; push %%r11;"
@@ -1727,7 +1740,7 @@
 		/* Check if vmlaunch of vmresume is needed */
 		"cmp $0, %1 \n\t"
 		/* Load guest registers.  Don't clobber flags. */
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 		"mov %c[cr2](%3), %%rax \n\t"
 		"mov %%rax, %%cr2 \n\t"
 		"mov %c[rax](%3), %%rax \n\t"
@@ -1764,7 +1777,7 @@
 		".globl kvm_vmx_return \n\t"
 		"kvm_vmx_return: "
 		/* Save guest registers, load host registers, keep flags */
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 		"xchg %3,     0(%%rsp) \n\t"
 		"mov %%rax, %c[rax](%3) \n\t"
 		"mov %%rbx, %c[rbx](%3) \n\t"
@@ -1816,7 +1829,7 @@
 		[rsi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RSI])),
 		[rdi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RDI])),
 		[rbp]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RBP])),
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 		[r8 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R8 ])),
 		[r9 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R9 ])),
 		[r10]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R10])),
@@ -1837,7 +1850,7 @@
 	fx_save(vcpu->guest_fx_image);
 	fx_restore(vcpu->host_fx_image);
 
-#ifndef __x86_64__
+#ifndef CONFIG_X86_64
 	asm ("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
 #endif
 
@@ -1855,7 +1868,7 @@
 			 */
 			local_irq_disable();
 			load_gs(gs_sel);
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 			wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE));
 #endif
 			local_irq_enable();
@@ -1965,7 +1978,7 @@
 	.set_cr0_no_modeswitch = vmx_set_cr0_no_modeswitch,
 	.set_cr3 = vmx_set_cr3,
 	.set_cr4 = vmx_set_cr4,
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 	.set_efer = vmx_set_efer,
 #endif
 	.get_idt = vmx_get_idt,
@@ -1989,8 +2002,7 @@
 
 static int __init vmx_init(void)
 {
-	kvm_init_arch(&vmx_arch_ops, THIS_MODULE);
-	return 0;
+	return kvm_init_arch(&vmx_arch_ops, THIS_MODULE);
 }
 
 static void __exit vmx_exit(void)
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index 7e838bf..1bff3e9 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -238,7 +238,7 @@
  * any modified flags.
  */
 
-#if defined(__x86_64__)
+#if defined(CONFIG_X86_64)
 #define _LO32 "k"		/* force 32-bit operand */
 #define _STK  "%%rsp"		/* stack pointer */
 #elif defined(__i386__)
@@ -385,7 +385,7 @@
 	} while (0)
 
 /* Emulate an instruction with quadword operands (x86/64 only). */
-#if defined(__x86_64__)
+#if defined(CONFIG_X86_64)
 #define __emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy)           \
 	do {								  \
 		__asm__ __volatile__ (					  \
@@ -495,7 +495,7 @@
 	case X86EMUL_MODE_PROT32:
 		op_bytes = ad_bytes = 4;
 		break;
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
 	case X86EMUL_MODE_PROT64:
 		op_bytes = 4;
 		ad_bytes = 8;
@@ -1341,7 +1341,7 @@
 			}
 			break;
 		}
-#elif defined(__x86_64__)
+#elif defined(CONFIG_X86_64)
 		{
 			unsigned long old, new;
 			if ((rc = ops->read_emulated(cr2, &old, 8, ctxt)) != 0)
diff --git a/drivers/kvm/x86_emulate.h b/drivers/kvm/x86_emulate.h
index 658b58d..5d41bd5 100644
--- a/drivers/kvm/x86_emulate.h
+++ b/drivers/kvm/x86_emulate.h
@@ -162,7 +162,7 @@
 /* Host execution mode. */
 #if defined(__i386__)
 #define X86EMUL_MODE_HOST X86EMUL_MODE_PROT32
-#elif defined(__x86_64__)
+#elif defined(CONFIG_X86_64)
 #define X86EMUL_MODE_HOST X86EMUL_MODE_PROT64
 #endif
 
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index d43ea81..7cec6de 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -828,7 +828,7 @@
 	if (!access_ok(VERIFY_READ, buf, count))
 		return -EFAULT;
 
-	req = (struct adb_request *) kmalloc(sizeof(struct adb_request),
+	req = kmalloc(sizeof(struct adb_request),
 					     GFP_KERNEL);
 	if (req == NULL)
 		return -ENOMEM;
diff --git a/drivers/macintosh/apm_emu.c b/drivers/macintosh/apm_emu.c
index 8862a83..4300c62 100644
--- a/drivers/macintosh/apm_emu.c
+++ b/drivers/macintosh/apm_emu.c
@@ -321,7 +321,7 @@
 {
 	struct apm_user *	as;
 
-	as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL);
+	as = kmalloc(sizeof(*as), GFP_KERNEL);
 	if (as == NULL) {
 		printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n",
 		       sizeof(*as));
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index 6dde27a..6f30459 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -945,7 +945,7 @@
 	 */
 	tlen = sizeof(struct property) + len + 18;
 
-	prop = kcalloc(tlen, 1, GFP_KERNEL);
+	prop = kzalloc(tlen, GFP_KERNEL);
 	if (prop == NULL)
 		return NULL;
 	hdr = (struct smu_sdbp_header *)(prop + 1);
diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c
index d9986f3..93e6ef92 100644
--- a/drivers/macintosh/via-pmu68k.c
+++ b/drivers/macintosh/via-pmu68k.c
@@ -847,7 +847,7 @@
 	n_pbook_pci_saves = npci;
 	if (npci == 0)
 		return;
-	ps = (struct pci_save *) kmalloc(npci * sizeof(*ps), GFP_KERNEL);
+	ps = kmalloc(npci * sizeof(*ps), GFP_KERNEL);
 	pbook_pci_saves = ps;
 	if (ps == NULL)
 		return;
diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c
index a7a5ab5..4ebd0f2 100644
--- a/drivers/md/faulty.c
+++ b/drivers/md/faulty.c
@@ -173,7 +173,7 @@
 	conf_t *conf = (conf_t*)mddev->private;
 	int failit = 0;
 
-	if (bio->bi_rw & 1) {
+	if (bio_data_dir(bio) == WRITE) {
 		/* write request */
 		if (atomic_read(&conf->counters[WriteAll])) {
 			/* special case - don't decrement, don't generic_make_request,
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index b3c5e12..b30f74b 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1736,7 +1736,7 @@
 		/* take from bio_init */
 		bio->bi_next = NULL;
 		bio->bi_flags |= 1 << BIO_UPTODATE;
-		bio->bi_rw = 0;
+		bio->bi_rw = READ;
 		bio->bi_vcnt = 0;
 		bio->bi_idx = 0;
 		bio->bi_phys_segments = 0;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 7492d60..f014191 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1785,7 +1785,7 @@
 						biolist = bio;
 						bio->bi_private = r10_bio;
 						bio->bi_end_io = end_sync_read;
-						bio->bi_rw = 0;
+						bio->bi_rw = READ;
 						bio->bi_sector = r10_bio->devs[j].addr +
 							conf->mirrors[d].rdev->data_offset;
 						bio->bi_bdev = conf->mirrors[d].rdev->bdev;
@@ -1801,7 +1801,7 @@
 						biolist = bio;
 						bio->bi_private = r10_bio;
 						bio->bi_end_io = end_sync_write;
-						bio->bi_rw = 1;
+						bio->bi_rw = WRITE;
 						bio->bi_sector = r10_bio->devs[k].addr +
 							conf->mirrors[i].rdev->data_offset;
 						bio->bi_bdev = conf->mirrors[i].rdev->bdev;
@@ -1870,7 +1870,7 @@
 			biolist = bio;
 			bio->bi_private = r10_bio;
 			bio->bi_end_io = end_sync_read;
-			bio->bi_rw = 0;
+			bio->bi_rw = READ;
 			bio->bi_sector = r10_bio->devs[i].addr +
 				conf->mirrors[d].rdev->data_offset;
 			bio->bi_bdev = conf->mirrors[d].rdev->bdev;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 377f8bc..be008f0 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -1827,16 +1827,16 @@
 		struct bio *bi;
 		mdk_rdev_t *rdev;
 		if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))
-			rw = 1;
+			rw = WRITE;
 		else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
-			rw = 0;
+			rw = READ;
 		else
 			continue;
  
 		bi = &sh->dev[i].req;
  
 		bi->bi_rw = rw;
-		if (rw)
+		if (rw == WRITE)
 			bi->bi_end_io = raid5_end_write_request;
 		else
 			bi->bi_end_io = raid5_end_read_request;
@@ -1872,7 +1872,7 @@
 				atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
 			generic_make_request(bi);
 		} else {
-			if (rw == 1)
+			if (rw == WRITE)
 				set_bit(STRIPE_DEGRADED, &sh->state);
 			PRINTK("skip op %ld on disc %d for sector %llu\n",
 				bi->bi_rw, i, (unsigned long long)sh->sector);
@@ -2370,16 +2370,16 @@
 		struct bio *bi;
 		mdk_rdev_t *rdev;
 		if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))
-			rw = 1;
+			rw = WRITE;
 		else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
-			rw = 0;
+			rw = READ;
 		else
 			continue;
 
 		bi = &sh->dev[i].req;
 
 		bi->bi_rw = rw;
-		if (rw)
+		if (rw == WRITE)
 			bi->bi_end_io = raid5_end_write_request;
 		else
 			bi->bi_end_io = raid5_end_read_request;
@@ -2415,7 +2415,7 @@
 				atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
 			generic_make_request(bi);
 		} else {
-			if (rw == 1)
+			if (rw == WRITE)
 				set_bit(STRIPE_DEGRADED, &sh->state);
 			PRINTK("skip op %ld on disc %d for sector %llu\n",
 				bi->bi_rw, i, (unsigned long long)sh->sector);
@@ -2567,7 +2567,7 @@
 	unsigned int chunk_sectors = mddev->chunk_size >> 9;
 	unsigned int bio_sectors = bio->bi_size >> 9;
 
-	if (bio_data_dir(bio))
+	if (bio_data_dir(bio) == WRITE)
 		return biovec->bv_len; /* always allow writes to be mergeable */
 
 	max =  (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9;
@@ -2751,7 +2751,7 @@
 	disk_stat_inc(mddev->gendisk, ios[rw]);
 	disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bi));
 
-	if (bio_data_dir(bi) == READ &&
+	if (rw == READ &&
 	     mddev->reshape_position == MaxSector &&
 	     chunk_aligned_read(q,bi))
             	return 0;
diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c
index 240ad08..50bc32a 100644
--- a/drivers/media/dvb/bt8xx/dst_ca.c
+++ b/drivers/media/dvb/bt8xx/dst_ca.c
@@ -480,7 +480,7 @@
 	struct ca_msg *hw_buffer;
 	int result = 0;
 
-	if ((hw_buffer = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
+	if ((hw_buffer = kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
 		dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
 		return -ENOMEM;
 	}
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index 80a85cb..3e35931 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -657,7 +657,7 @@
 
 	case BTTV_BOARD_TWINHAN_DST:
 		/*	DST is not a frontend driver !!!		*/
-		state = (struct dst_state *) kmalloc(sizeof (struct dst_state), GFP_KERNEL);
+		state = kmalloc(sizeof (struct dst_state), GFP_KERNEL);
 		if (!state) {
 			printk("dvb_bt8xx: No memory\n");
 			break;
diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
index 42f39a8..a6fb1d6 100644
--- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
+++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
@@ -195,7 +195,7 @@
 	struct ttusbdecfe_state* state = NULL;
 
 	/* allocate memory for the internal state */
-	state = (struct ttusbdecfe_state*) kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
+	state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
 	if (state == NULL)
 		return NULL;
 
@@ -215,7 +215,7 @@
 	struct ttusbdecfe_state* state = NULL;
 
 	/* allocate memory for the internal state */
-	state = (struct ttusbdecfe_state*) kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
+	state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
 	if (state == NULL)
 		return NULL;
 
diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c
index b1012e9..917021f 100644
--- a/drivers/media/video/dabusb.c
+++ b/drivers/media/video/dabusb.c
@@ -218,7 +218,7 @@
 		 pipesize, packets, transfer_buffer_length);
 
 	while (buffers < (s->total_buffer_size << 10)) {
-		b = (pbuff_t) kzalloc (sizeof (buff_t), GFP_KERNEL);
+		b = kzalloc(sizeof (buff_t), GFP_KERNEL);
 		if (!b) {
 			err("kzalloc(sizeof(buff_t))==NULL");
 			goto err;
@@ -659,7 +659,7 @@
 	switch (cmd) {
 
 	case IOCTL_DAB_BULK:
-		pbulk = (pbulk_transfer_t) kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL);
+		pbulk = kmalloc(sizeof (bulk_transfer_t), GFP_KERNEL);
 
 		if (!pbulk) {
 			ret = -ENOMEM;
diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c
index 368d6e2..86d2884 100644
--- a/drivers/media/video/planb.c
+++ b/drivers/media/video/planb.c
@@ -138,7 +138,7 @@
 		+ MAX_LNUM
 #endif /* PLANB_GSCANLINE */
 		);
-	if ((pb->rawbuf = (unsigned char**) kmalloc (npage
+	if ((pb->rawbuf = kmalloc(npage
 				* sizeof(unsigned long), GFP_KERNEL)) == 0)
 		return -ENOMEM;
 	for (i = 0; i < npage; i++) {
diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c
index d8b8802..b560c9d 100644
--- a/drivers/media/video/usbvideo/usbvideo.c
+++ b/drivers/media/video/usbvideo/usbvideo.c
@@ -690,7 +690,7 @@
 	}
 
 	base_size = num_cams * sizeof(struct uvd) + sizeof(struct usbvideo);
-	cams = (struct usbvideo *) kzalloc(base_size, GFP_KERNEL);
+	cams = kzalloc(base_size, GFP_KERNEL);
 	if (cams == NULL) {
 		err("Failed to allocate %d. bytes for usbvideo struct", base_size);
 		return -ENOMEM;
diff --git a/drivers/media/video/videocodec.c b/drivers/media/video/videocodec.c
index 2ae3fb2..290e641 100644
--- a/drivers/media/video/videocodec.c
+++ b/drivers/media/video/videocodec.c
@@ -346,7 +346,7 @@
 		size);
 
 	kfree(videocodec_buf);
-	videocodec_buf = (char *) kmalloc(size, GFP_KERNEL);
+	videocodec_buf = kmalloc(size, GFP_KERNEL);
 
 	i = 0;
 	i += scnprintf(videocodec_buf + i, size - 1,
diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h
index dc388a3..cbe384f 100644
--- a/drivers/message/i2o/core.h
+++ b/drivers/message/i2o/core.h
@@ -18,7 +18,7 @@
 extern int i2o_exec_lct_get(struct i2o_controller *);
 
 extern int __init i2o_exec_init(void);
-extern void __exit i2o_exec_exit(void);
+extern void i2o_exec_exit(void);
 
 /* driver */
 extern struct bus_type i2o_bus_type;
@@ -26,7 +26,7 @@
 extern int i2o_driver_dispatch(struct i2o_controller *, u32);
 
 extern int __init i2o_driver_init(void);
-extern void __exit i2o_driver_exit(void);
+extern void i2o_driver_exit(void);
 
 /* PCI */
 extern int __init i2o_pci_init(void);
diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c
index 9104b65..d3235f2 100644
--- a/drivers/message/i2o/driver.c
+++ b/drivers/message/i2o/driver.c
@@ -362,7 +362,7 @@
  *
  *	Unregisters the I2O bus and frees driver array.
  */
-void __exit i2o_driver_exit(void)
+void i2o_driver_exit(void)
 {
 	bus_unregister(&i2o_bus_type);
 	kfree(i2o_drivers);
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
index 902753b..a539d3b 100644
--- a/drivers/message/i2o/exec-osm.c
+++ b/drivers/message/i2o/exec-osm.c
@@ -595,7 +595,7 @@
  *
  *	Unregisters the Exec OSM from the I2O core.
  */
-void __exit i2o_exec_exit(void)
+void i2o_exec_exit(void)
 {
 	i2o_driver_unregister(&i2o_exec_driver);
 };
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index 1de30d7..e33d446 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -186,7 +186,7 @@
 	if (!dev)
 		return -ENXIO;
 
-	ops = (u8 *) kmalloc(kcmd.oplen, GFP_KERNEL);
+	ops = kmalloc(kcmd.oplen, GFP_KERNEL);
 	if (!ops)
 		return -ENOMEM;
 
@@ -199,7 +199,7 @@
 	 * It's possible to have a _very_ large table
 	 * and that the user asks for all of it at once...
 	 */
-	res = (u8 *) kmalloc(65536, GFP_KERNEL);
+	res = kmalloc(65536, GFP_KERNEL);
 	if (!res) {
 		kfree(ops);
 		return -ENOMEM;
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index 5db7160..0a7e868 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -459,7 +459,7 @@
 	struct mtd_info			*device;
 	struct flash_platform_data	*pdata = spi->dev.platform_data;
 
-	priv = (struct dataflash *) kzalloc(sizeof *priv, GFP_KERNEL);
+	priv = kzalloc(sizeof *priv, GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c
index fa4362f..0f3baa5 100644
--- a/drivers/mtd/rfd_ftl.c
+++ b/drivers/mtd/rfd_ftl.c
@@ -768,7 +768,7 @@
 	if (mtd->type != MTD_NORFLASH)
 		return;
 
-	part = kcalloc(1, sizeof(struct partition), GFP_KERNEL);
+	part = kzalloc(sizeof(struct partition), GFP_KERNEL);
 	if (!part)
 		return;
 
diff --git a/drivers/net/appletalk/ipddp.c b/drivers/net/appletalk/ipddp.c
index b98592a..f22e46d 100644
--- a/drivers/net/appletalk/ipddp.c
+++ b/drivers/net/appletalk/ipddp.c
@@ -186,7 +186,7 @@
  */
 static int ipddp_create(struct ipddp_route *new_rt)
 {
-        struct ipddp_route *rt =(struct ipddp_route*) kmalloc(sizeof(*rt), GFP_KERNEL);
+        struct ipddp_route *rt = kmalloc(sizeof(*rt), GFP_KERNEL);
 
         if (rt == NULL)
                 return -ENOMEM;
diff --git a/drivers/net/bsd_comp.c b/drivers/net/bsd_comp.c
index bae1de1..7845eaf 100644
--- a/drivers/net/bsd_comp.c
+++ b/drivers/net/bsd_comp.c
@@ -395,7 +395,7 @@
  * Allocate the main control structure for this instance.
  */
     maxmaxcode = MAXCODE(bits);
-    db         = (struct bsd_db *) kmalloc (sizeof (struct bsd_db),
+    db         = kmalloc(sizeof (struct bsd_db),
 					    GFP_KERNEL);
     if (!db)
       {
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
index 16620bd..11af0ae 100644
--- a/drivers/net/irda/donauboe.c
+++ b/drivers/net/irda/donauboe.c
@@ -1603,7 +1603,7 @@
   irda_qos_bits_to_value (&self->qos);
 
   /* Allocate twice the size to guarantee alignment */
-  self->ringbuf = (void *) kmalloc (OBOE_RING_LEN << 1, GFP_KERNEL);
+  self->ringbuf = kmalloc(OBOE_RING_LEN << 1, GFP_KERNEL);
   if (!self->ringbuf)
     {
       printk (KERN_ERR DRIVER_NAME ": can't allocate DMA buffers\n");
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 6e95645..3ca1082 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -1747,7 +1747,7 @@
 	/* Don't change this buffer size and allocation without doing
 	 * some heavy and complete testing. Don't ask why :-(
 	 * Jean II */
-	self->speed_buff = (char *) kmalloc(IRDA_USB_SPEED_MTU, GFP_KERNEL);
+	self->speed_buff = kmalloc(IRDA_USB_SPEED_MTU, GFP_KERNEL);
 	if (self->speed_buff == NULL) 
 		goto err_out_3;
 
diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c
index 654a68b..3098960 100644
--- a/drivers/net/irda/irport.c
+++ b/drivers/net/irda/irport.c
@@ -164,7 +164,7 @@
 	
 	/* Allocate memory if needed */
 	if (self->tx_buff.truesize > 0) {
-		self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
+		self->tx_buff.head = kmalloc(self->tx_buff.truesize,
 						      GFP_KERNEL);
 		if (self->tx_buff.head == NULL) {
 			IRDA_ERROR("%s(), can't allocate memory for "
diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c
index b833016..177c502 100644
--- a/drivers/net/lp486e.c
+++ b/drivers/net/lp486e.c
@@ -884,7 +884,7 @@
 
 	dev->trans_start = jiffies;
 
-	tx_cmd = (struct tx_cmd *) kmalloc ((sizeof (struct tx_cmd) + sizeof (struct i596_tbd)), GFP_ATOMIC);
+	tx_cmd = kmalloc((sizeof (struct tx_cmd) + sizeof (struct i596_tbd)), GFP_ATOMIC);
 	if (tx_cmd == NULL) {
 		printk(KERN_WARNING "%s: i596_xmit Memory squeeze, dropping packet.\n", dev->name);
 		lp->stats.tx_dropped++;
@@ -1266,7 +1266,7 @@
 	if (dev->mc_count > 0) {
 		struct dev_mc_list *dmi;
 		char *cp;
-		cmd = (struct i596_cmd *)kmalloc(sizeof(struct i596_cmd)+2+dev->mc_count*6, GFP_ATOMIC);
+		cmd = kmalloc(sizeof(struct i596_cmd)+2+dev->mc_count*6, GFP_ATOMIC);
 		if (cmd == NULL) {
 			printk (KERN_ERR "%s: set_multicast Memory squeeze.\n", dev->name);
 			return;
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index b01fc70..a4d7529 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -50,7 +50,7 @@
 	struct phy_device *dev;
 	/* We allocate the device, and initialize the
 	 * default values */
-	dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 
 	if (NULL == dev)
 		return (struct phy_device*) PTR_ERR((void*)-ENOMEM);
diff --git a/drivers/net/ppp_deflate.c b/drivers/net/ppp_deflate.c
index f54c552..72c8d66 100644
--- a/drivers/net/ppp_deflate.c
+++ b/drivers/net/ppp_deflate.c
@@ -121,7 +121,7 @@
 	if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
 		return NULL;
 
-	state = (struct ppp_deflate_state *) kmalloc(sizeof(*state),
+	state = kmalloc(sizeof(*state),
 						     GFP_KERNEL);
 	if (state == NULL)
 		return NULL;
@@ -341,7 +341,7 @@
 	if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
 		return NULL;
 
-	state = (struct ppp_deflate_state *) kmalloc(sizeof(*state), GFP_KERNEL);
+	state = kmalloc(sizeof(*state), GFP_KERNEL);
 	if (state == NULL)
 		return NULL;
 
diff --git a/drivers/net/ppp_mppe.c b/drivers/net/ppp_mppe.c
index f3655fd..d5bdd25 100644
--- a/drivers/net/ppp_mppe.c
+++ b/drivers/net/ppp_mppe.c
@@ -200,7 +200,7 @@
 	    || options[0] != CI_MPPE || options[1] != CILEN_MPPE)
 		goto out;
 
-	state = (struct ppp_mppe_state *) kmalloc(sizeof(*state), GFP_KERNEL);
+	state = kmalloc(sizeof(*state), GFP_KERNEL);
 	if (state == NULL)
 		goto out;
 
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index b60f045..8a39376 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -749,7 +749,7 @@
 	struct skge_element *e;
 	int i;
 
-	ring->start = kcalloc(sizeof(*e), ring->count, GFP_KERNEL);
+	ring->start = kcalloc(ring->count, sizeof(*e), GFP_KERNEL);
 	if (!ring->start)
 		return -ENOMEM;
 
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 39c2152..a0806d2 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -229,10 +229,10 @@
 	if (len < 576 * 2)
 		len = 576 * 2;
 
-	xbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
-	rbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
+	xbuff = kmalloc(len + 4, GFP_ATOMIC);
+	rbuff = kmalloc(len + 4, GFP_ATOMIC);
 #ifdef SL_INCLUDE_CSLIP
-	cbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
+	cbuff = kmalloc(len + 4, GFP_ATOMIC);
 #endif
 
 
diff --git a/drivers/net/wan/hostess_sv11.c b/drivers/net/wan/hostess_sv11.c
index a4f7357..a02c5fb 100644
--- a/drivers/net/wan/hostess_sv11.c
+++ b/drivers/net/wan/hostess_sv11.c
@@ -231,7 +231,7 @@
 		return NULL;
 	}
 	
-	sv=(struct sv11_device *)kmalloc(sizeof(struct sv11_device), GFP_KERNEL);
+	sv = kmalloc(sizeof(struct sv11_device), GFP_KERNEL);
 	if(!sv)
 		goto fail3;
 			
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
index 36d1c3f..62184de 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/net/wan/pc300_drv.c
@@ -3455,7 +3455,7 @@
 	if ((err = pci_enable_device(pdev)) < 0)
 		return err;
 
-	card = (pc300_t *) kmalloc(sizeof(pc300_t), GFP_KERNEL);
+	card = kmalloc(sizeof(pc300_t), GFP_KERNEL);
 	if (card == NULL) {
 		printk("PC300 found at RAM 0x%016llx, "
 		       "but could not allocate card structure.\n",
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
index b2a23ae..5873c34 100644
--- a/drivers/net/wan/pc300_tty.c
+++ b/drivers/net/wan/pc300_tty.c
@@ -784,7 +784,7 @@
 			continue;
 		} 
 		
-		new = (st_cpc_rx_buf *)kmalloc(rx_len + sizeof(st_cpc_rx_buf), GFP_ATOMIC);
+		new = kmalloc(rx_len + sizeof(st_cpc_rx_buf), GFP_ATOMIC);
 		if (new == 0) {
 			cpc_tty_rx_disc_frame(pc300chan);
 			continue;
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index 9c3ccc6..1c9edd9 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -123,8 +123,8 @@
 	unsigned char *xbuff, *rbuff;
 	int len = 2* newmtu;
 
-	xbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
-	rbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
+	xbuff = kmalloc(len + 4, GFP_ATOMIC);
+	rbuff = kmalloc(len + 4, GFP_ATOMIC);
 
 	if (xbuff == NULL || rbuff == NULL)  
 	{
@@ -465,11 +465,11 @@
 
 	len = dev->mtu * 2;
 
-	sl->rbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
+	sl->rbuff = kmalloc(len + 4, GFP_KERNEL);
 	if (sl->rbuff == NULL)   {
 		goto norbuff;
 	}
-	sl->xbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
+	sl->xbuff = kmalloc(len + 4, GFP_KERNEL);
 	if (sl->xbuff == NULL)   {
 		goto noxbuff;
 	}
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index 974a8e5..efb8cf3 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -1253,7 +1253,7 @@
 			return NULL;
 	}
 
-	tmpbuf = (char *) kmalloc(WLAN_AUTH_CHALLENGE_LEN, GFP_ATOMIC);
+	tmpbuf = kmalloc(WLAN_AUTH_CHALLENGE_LEN, GFP_ATOMIC);
 	if (tmpbuf == NULL) {
 		PDEBUG(DEBUG_AP, "AP: kmalloc failed for challenge\n");
 		return NULL;
diff --git a/drivers/net/wireless/hostap/hostap_download.c b/drivers/net/wireless/hostap/hostap_download.c
index 24fc387..c7678e6 100644
--- a/drivers/net/wireless/hostap/hostap_download.c
+++ b/drivers/net/wireless/hostap/hostap_download.c
@@ -201,7 +201,7 @@
 		0x7f0002 /* Intel PRO/Wireless 2011B (PCI) */,
 	};
 
-	buf = (u8 *) kmalloc(PRISM2_PDA_SIZE, GFP_KERNEL);
+	buf = kmalloc(PRISM2_PDA_SIZE, GFP_KERNEL);
 	if (buf == NULL)
 		return NULL;
 
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index a394a23..3079378 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -2252,7 +2252,7 @@
 	if (txdesc->sw_support) {
 		len = le16_to_cpu(txdesc->data_len);
 		if (len < PRISM2_DATA_MAXLEN) {
-			*payload = (char *) kmalloc(len, GFP_ATOMIC);
+			*payload = kmalloc(len, GFP_ATOMIC);
 			if (*payload == NULL ||
 			    hfa384x_from_bap(dev, BAP0, *payload, len)) {
 				PDEBUG(DEBUG_EXTRA, "%s: could not read TX "
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index 3b7b806..cb08bc5 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -3829,7 +3829,7 @@
 	    p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer)
 		return -EINVAL;
 
-	param = (struct prism2_hostapd_param *) kmalloc(p->length, GFP_KERNEL);
+	param = kmalloc(p->length, GFP_KERNEL);
 	if (param == NULL)
 		return -ENOMEM;
 
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 0796be9..04c19ce 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -250,7 +250,7 @@
 	unsigned long flags;
 	struct hostap_tx_callback_info *entry;
 
-	entry = (struct hostap_tx_callback_info *) kmalloc(sizeof(*entry),
+	entry = kmalloc(sizeof(*entry),
 							   GFP_ATOMIC);
 	if (entry == NULL)
 		return 0;
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index dd9ba4a..0e94fbb 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -2246,7 +2246,7 @@
 	if (priv->snapshot[0])
 		return 1;
 	for (i = 0; i < 0x30; i++) {
-		priv->snapshot[i] = (u8 *) kmalloc(0x1000, GFP_ATOMIC);
+		priv->snapshot[i] = kmalloc(0x1000, GFP_ATOMIC);
 		if (!priv->snapshot[i]) {
 			IPW_DEBUG_INFO("%s: Error allocating snapshot "
 				       "buffer %d\n", priv->net_dev->name, i);
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 96606ed..838d510 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -2775,7 +2775,7 @@
            p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer)
                return -EINVAL;
 
-       param = (struct prism2_hostapd_param *) kmalloc(p->length, GFP_KERNEL);
+       param = kmalloc(p->length, GFP_KERNEL);
        if (param == NULL)
                return -ENOMEM;
 
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index 233d906c..5eb8163 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -603,7 +603,7 @@
   if(lp->wavepoint_table.num_wavepoints==MAX_WAVEPOINTS)
     return NULL;
   
-  new_wavepoint=(wavepoint_history *) kmalloc(sizeof(wavepoint_history),GFP_ATOMIC);
+  new_wavepoint = kmalloc(sizeof(wavepoint_history),GFP_ATOMIC);
   if(new_wavepoint==NULL)
     return NULL;
   
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 77e11dd..78ea72f 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -101,7 +101,7 @@
 
 	/* Allocate a single memory block for values and addresses. */
 	count16 = 2*count;
-	a16 = (zd_addr_t *)kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)),
+	a16 = kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)),
 		                   GFP_NOFS);
 	if (!a16) {
 		dev_dbg_f(zd_chip_dev(chip),
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
index 12bab64..6fb3f79 100644
--- a/drivers/parisc/iosapic.c
+++ b/drivers/parisc/iosapic.c
@@ -874,7 +874,7 @@
 		return NULL;
 	}
 
-	isi = (struct iosapic_info *)kzalloc(sizeof(struct iosapic_info), GFP_KERNEL);
+	isi = kzalloc(sizeof(struct iosapic_info), GFP_KERNEL);
 	if (!isi) {
 		BUG();
 		return NULL;
diff --git a/drivers/pci/hotplug/cpqphp_nvram.c b/drivers/pci/hotplug/cpqphp_nvram.c
index 298a6cf..ae5e974 100644
--- a/drivers/pci/hotplug/cpqphp_nvram.c
+++ b/drivers/pci/hotplug/cpqphp_nvram.c
@@ -520,7 +520,7 @@
 			return 2;
 
 		while (nummem--) {
-			mem_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
 
 			if (!mem_node)
 				break;
@@ -548,7 +548,7 @@
 		}
 
 		while (numpmem--) {
-			p_mem_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			p_mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
 
 			if (!p_mem_node)
 				break;
@@ -576,7 +576,7 @@
 		}
 
 		while (numio--) {
-			io_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			io_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
 
 			if (!io_node)
 				break;
@@ -604,7 +604,7 @@
 		}
 
 		while (numbus--) {
-			bus_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+			bus_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
 
 			if (!bus_node)
 				break;
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 6d3f580..25d3aad 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -1320,7 +1320,7 @@
 	DBG_ENTER_ROUTINE
 	
 	spin_lock_init(&list_lock);	
-	php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL);
+	php_ctlr = kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL);
 
 	if (!php_ctlr) {	/* allocate controller state data */
 		err("%s: HPC controller memory allocation error!\n", __FUNCTION__);
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
index 55866b6..6f5fabb 100644
--- a/drivers/pci/pcie/aer/aerdrv.c
+++ b/drivers/pci/pcie/aer/aerdrv.c
@@ -148,7 +148,7 @@
 {
 	struct aer_rpc *rpc;
 
-	if (!(rpc = (struct aer_rpc *)kmalloc(sizeof(struct aer_rpc),
+	if (!(rpc = kmalloc(sizeof(struct aer_rpc),
 		GFP_KERNEL)))
 		return NULL;
 
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
index 52d4a38..3334f22 100644
--- a/drivers/pcmcia/at91_cf.c
+++ b/drivers/pcmcia/at91_cf.c
@@ -230,7 +230,7 @@
 	if (!io)
 		return -ENODEV;
 
-	cf = kcalloc(1, sizeof *cf, GFP_KERNEL);
+	cf = kzalloc(sizeof *cf, GFP_KERNEL);
 	if (!cf)
 		return -ENOMEM;
 
diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
index 06bf7f4..e65a6b8 100644
--- a/drivers/pcmcia/omap_cf.c
+++ b/drivers/pcmcia/omap_cf.c
@@ -220,7 +220,7 @@
 	if (irq < 0)
 		return -EINVAL;
 
-	cf = kcalloc(1, sizeof *cf, GFP_KERNEL);
+	cf = kzalloc(sizeof *cf, GFP_KERNEL);
 	if (!cf)
 		return -ENOMEM;
 	init_timer(&cf->timer);
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index 3ac5b12..a0b1587 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -395,7 +395,7 @@
 	struct pnp_id * id;
 	if (!dev)
 		return;
-	id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
+	id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
 	if (!id)
 		return;
 	sprintf(id->id, "%c%c%c%x%x%x%x",
@@ -419,7 +419,7 @@
 	struct pnp_dev *dev;
 
 	isapnp_peek(tmp, size);
-	dev = kcalloc(1, sizeof(struct pnp_dev), GFP_KERNEL);
+	dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL);
 	if (!dev)
 		return NULL;
 	dev->number = number;
@@ -450,7 +450,7 @@
 	unsigned long bits;
 
 	isapnp_peek(tmp, size);
-	irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
+	irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
 	if (!irq)
 		return;
 	bits = (tmp[1] << 8) | tmp[0];
@@ -474,7 +474,7 @@
 	struct pnp_dma *dma;
 
 	isapnp_peek(tmp, size);
-	dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL);
+	dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
 	if (!dma)
 		return;
 	dma->map = tmp[0];
@@ -494,7 +494,7 @@
 	struct pnp_port *port;
 
 	isapnp_peek(tmp, size);
-	port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
+	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
 	if (!port)
 		return;
 	port->min = (tmp[2] << 8) | tmp[1];
@@ -517,7 +517,7 @@
 	struct pnp_port *port;
 
 	isapnp_peek(tmp, size);
-	port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
+	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
 	if (!port)
 		return;
 	port->min = port->max = (tmp[1] << 8) | tmp[0];
@@ -539,7 +539,7 @@
 	struct pnp_mem *mem;
 
 	isapnp_peek(tmp, size);
-	mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
 	if (!mem)
 		return;
 	mem->min = ((tmp[2] << 8) | tmp[1]) << 8;
@@ -562,7 +562,7 @@
 	struct pnp_mem *mem;
 
 	isapnp_peek(tmp, size);
-	mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
 	if (!mem)
 		return;
 	mem->min = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
@@ -584,7 +584,7 @@
 	struct pnp_mem *mem;
 
 	isapnp_peek(tmp, size);
-	mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
 	if (!mem)
 		return;
 	mem->min = mem->max = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
@@ -829,7 +829,7 @@
 
 static void isapnp_parse_card_id(struct pnp_card * card, unsigned short vendor, unsigned short device)
 {
-	struct pnp_id * id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
+	struct pnp_id * id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
 	if (!id)
 		return;
 	sprintf(id->id, "%c%c%c%x%x%x%x",
@@ -865,7 +865,7 @@
 			header[4], header[5], header[6], header[7], header[8]);
 		printk(KERN_DEBUG "checksum = 0x%x\n", checksum);
 #endif
-		if ((card = kcalloc(1, sizeof(struct pnp_card), GFP_KERNEL)) == NULL)
+		if ((card = kzalloc(sizeof(struct pnp_card), GFP_KERNEL)) == NULL)
 			continue;
 
 		card->number = csn;
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 6cf34a6..62eda5d 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -139,7 +139,7 @@
 		return 0;
 
 	pnp_dbg("ACPI device : hid %s", acpi_device_hid(device));
-	dev =  kcalloc(1, sizeof(struct pnp_dev), GFP_KERNEL);
+	dev =  kzalloc(sizeof(struct pnp_dev), GFP_KERNEL);
 	if (!dev) {
 		pnp_err("Out of memory");
 		return -ENOMEM;
@@ -169,7 +169,7 @@
 	dev->number = num;
 	
 	/* set the initial values for the PnP device */
-	dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
+	dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
 	if (!dev_id)
 		goto err;
 	pnpidacpi_to_pnpid(acpi_device_hid(device), dev_id->id);
@@ -201,7 +201,7 @@
 		for (i = 0; i < cid_list->count; i++) {
 			if (!ispnpidacpi(cid_list->id[i].value))
 				continue;
-			dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
+			dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
 			if (!dev_id)
 				continue;
 
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 379048f..7a53554 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -298,7 +298,7 @@
 
 	if (p->channel_count == 0)
 		return;
-	dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL);
+	dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
 	if (!dma)
 		return;
 
@@ -354,7 +354,7 @@
 
 	if (p->interrupt_count == 0)
 		return;
-	irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
+	irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
 	if (!irq)
 		return;
 
@@ -375,7 +375,7 @@
 
 	if (p->interrupt_count == 0)
 		return;
-	irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
+	irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
 	if (!irq)
 		return;
 
@@ -396,7 +396,7 @@
 
 	if (io->address_length == 0)
 		return;
-	port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
+	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
 	if (!port)
 		return;
 	port->min = io->minimum;
@@ -417,7 +417,7 @@
 
 	if (io->address_length == 0)
 		return;
-	port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
+	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
 	if (!port)
 		return;
 	port->min = port->max = io->address;
@@ -436,7 +436,7 @@
 
 	if (p->address_length == 0)
 		return;
-	mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
 	if (!mem)
 		return;
 	mem->min = p->minimum;
@@ -459,7 +459,7 @@
 
 	if (p->address_length == 0)
 		return;
-	mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
 	if (!mem)
 		return;
 	mem->min = p->minimum;
@@ -482,7 +482,7 @@
 
 	if (p->address_length == 0)
 		return;
-	mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
 	if (!mem)
 		return;
 	mem->min = mem->max = p->address;
@@ -514,7 +514,7 @@
 		return;
 
 	if (p->resource_type == ACPI_MEMORY_RANGE) {
-		mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+		mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
 		if (!mem)
 			return;
 		mem->min = mem->max = p->minimum;
@@ -524,7 +524,7 @@
 		    ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE : 0;
 		pnp_register_mem_resource(option, mem);
 	} else if (p->resource_type == ACPI_IO_RANGE) {
-		port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
+		port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
 		if (!port)
 			return;
 		port->min = port->max = p->minimum;
@@ -721,7 +721,7 @@
 	if (!res_cnt)
 		return -EINVAL;
 	buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1) + 1;
-	buffer->pointer = kcalloc(1, buffer->length - 1, GFP_KERNEL);
+	buffer->pointer = kzalloc(buffer->length - 1, GFP_KERNEL);
 	if (!buffer->pointer)
 		return -ENOMEM;
 	pnp_dbg("Res cnt %d", res_cnt);
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index 33adeba..95738db 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -109,10 +109,10 @@
 	if (!current->fs->root) {
 		return -EAGAIN;
 	}
-	if (!(envp = (char **) kcalloc (20, sizeof (char *), GFP_KERNEL))) {
+	if (!(envp = kcalloc(20, sizeof (char *), GFP_KERNEL))) {
 		return -ENOMEM;
 	}
-	if (!(buf = kcalloc (1, 256, GFP_KERNEL))) {
+	if (!(buf = kzalloc(256, GFP_KERNEL))) {
 		kfree (envp);
 		return -ENOMEM;
 	}
@@ -220,7 +220,7 @@
 	if(!pnpbios_is_dynamic(dev))
 		return -EPERM;
 
-	node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
+	node = kzalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node)
 		return -1;
 	if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) {
@@ -243,7 +243,7 @@
 	if (!pnpbios_is_dynamic(dev))
 		return -EPERM;
 
-	node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
+	node = kzalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node)
 		return -1;
 	if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) {
@@ -294,7 +294,7 @@
 	if(dev->flags & PNPBIOS_NO_DISABLE || !pnpbios_is_dynamic(dev))
 		return -EPERM;
 
-	node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
+	node = kzalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node)
 		return -ENOMEM;
 
@@ -336,7 +336,7 @@
 	}
 
 	/* set the initial values for the PnP device */
-	dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
+	dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
 	if (!dev_id)
 		return -1;
 	pnpid32_to_pnpid(node->eisa_id,id);
@@ -374,7 +374,7 @@
 	struct pnp_bios_node *node;
 	struct pnp_dev *dev;
 
-	node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
+	node = kzalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node)
 		return;
 
@@ -391,7 +391,7 @@
 				break;
 		}
 		nodes_got++;
-		dev =  kcalloc(1, sizeof (struct pnp_dev), GFP_KERNEL);
+		dev =  kzalloc(sizeof (struct pnp_dev), GFP_KERNEL);
 		if (!dev)
 			break;
 		if(insert_device(dev,node)<0)
diff --git a/drivers/pnp/pnpbios/proc.c b/drivers/pnp/pnpbios/proc.c
index 5a3dfc9..8027073 100644
--- a/drivers/pnp/pnpbios/proc.c
+++ b/drivers/pnp/pnpbios/proc.c
@@ -87,7 +87,7 @@
 		return -EFBIG;
 	}
 
-	tmpbuf = kcalloc(1, escd.escd_size, GFP_KERNEL);
+	tmpbuf = kzalloc(escd.escd_size, GFP_KERNEL);
 	if (!tmpbuf) return -ENOMEM;
 
 	if (pnp_bios_read_escd(tmpbuf, escd.nv_storage_base)) {
@@ -133,7 +133,7 @@
 	if (pos >= 0xff)
 		return 0;
 
-	node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
+	node = kzalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node) return -ENOMEM;
 
 	for (nodenum=pos; nodenum<0xff; ) {
@@ -168,7 +168,7 @@
 	u8 nodenum = (long)data;
 	int len;
 
-	node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
+	node = kzalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node) return -ENOMEM;
 	if (pnp_bios_get_dev_node(&nodenum, boot, node)) {
 		kfree(node);
@@ -188,7 +188,7 @@
 	u8 nodenum = (long)data;
 	int ret = count;
 
-	node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
+	node = kzalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node)
 		return -ENOMEM;
 	if (pnp_bios_get_dev_node(&nodenum, boot, node)) {
diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c
index ef508a4..95b7968 100644
--- a/drivers/pnp/pnpbios/rsparser.c
+++ b/drivers/pnp/pnpbios/rsparser.c
@@ -248,7 +248,7 @@
 pnpbios_parse_mem_option(unsigned char *p, int size, struct pnp_option *option)
 {
 	struct pnp_mem * mem;
-	mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
 	if (!mem)
 		return;
 	mem->min = ((p[5] << 8) | p[4]) << 8;
@@ -264,7 +264,7 @@
 pnpbios_parse_mem32_option(unsigned char *p, int size, struct pnp_option *option)
 {
 	struct pnp_mem * mem;
-	mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
 	if (!mem)
 		return;
 	mem->min = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
@@ -280,7 +280,7 @@
 pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, struct pnp_option *option)
 {
 	struct pnp_mem * mem;
-	mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
 	if (!mem)
 		return;
 	mem->min = mem->max = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
@@ -297,7 +297,7 @@
 	struct pnp_irq * irq;
 	unsigned long bits;
 
-	irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
+	irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
 	if (!irq)
 		return;
 	bits = (p[2] << 8) | p[1];
@@ -314,7 +314,7 @@
 pnpbios_parse_dma_option(unsigned char *p, int size, struct pnp_option *option)
 {
 	struct pnp_dma * dma;
-	dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL);
+	dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
 	if (!dma)
 		return;
 	dma->map = p[1];
@@ -327,7 +327,7 @@
 pnpbios_parse_port_option(unsigned char *p, int size, struct pnp_option *option)
 {
 	struct pnp_port * port;
-	port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
+	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
 	if (!port)
 		return;
 	port->min = (p[3] << 8) | p[2];
@@ -343,7 +343,7 @@
 pnpbios_parse_fixed_port_option(unsigned char *p, int size, struct pnp_option *option)
 {
 	struct pnp_port * port;
-	port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
+	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
 	if (!port)
 		return;
 	port->min = port->max = (p[2] << 8) | p[1];
@@ -527,7 +527,7 @@
 		case SMALL_TAG_COMPATDEVID: /* compatible ID */
 			if (len != 4)
 				goto len_err;
-			dev_id =  kcalloc(1, sizeof (struct pnp_id), GFP_KERNEL);
+			dev_id =  kzalloc(sizeof (struct pnp_id), GFP_KERNEL);
 			if (!dev_id)
 				return NULL;
 			memset(dev_id, 0, sizeof(struct pnp_id));
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c
index 5c8addc..4f654c9 100644
--- a/drivers/rtc/rtc-at91rm9200.c
+++ b/drivers/rtc/rtc-at91rm9200.c
@@ -137,6 +137,9 @@
 	tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
 	tm->tm_year = at91_alarm_year - 1900;
 
+	alrm->enabled = (at91_sys_read(AT91_RTC_IMR) & AT91_RTC_ALARM)
+			? 1 : 0;
+
 	pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
 		1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
 		tm->tm_hour, tm->tm_min, tm->tm_sec);
@@ -223,8 +226,6 @@
 {
 	unsigned long imr = at91_sys_read(AT91_RTC_IMR);
 
-	seq_printf(seq, "alarm_IRQ\t: %s\n",
-			(imr & AT91_RTC_ALARM) ? "yes" : "no");
 	seq_printf(seq, "update_IRQ\t: %s\n",
 			(imr & AT91_RTC_ACKUPD) ? "yes" : "no");
 	seq_printf(seq, "periodic_IRQ\t: %s\n",
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index 828b329..94d3df6 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -435,7 +435,7 @@
 		goto err_cdev_del;
 	}
 
-	dev_info(class_dev->dev, "rtc intf: dev (%d:%d)\n",
+	dev_dbg(class_dev->dev, "rtc intf: dev (%d:%d)\n",
 		MAJOR(rtc->rtc_dev->devt),
 		MINOR(rtc->rtc_dev->devt));
 
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index eac5fb1..d59880d 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -279,9 +279,8 @@
 	local_irq_enable();
 
 	bcd2tm(&alm->time);
-	alm->pending = !!(rtc_read(OMAP_RTC_INTERRUPTS_REG)
+	alm->enabled = !!(rtc_read(OMAP_RTC_INTERRUPTS_REG)
 			& OMAP_RTC_INTERRUPTS_IT_ALARM);
-	alm->enabled = alm->pending && device_may_wakeup(dev);
 
 	return 0;
 }
diff --git a/drivers/rtc/rtc-proc.c b/drivers/rtc/rtc-proc.c
index d51d8f2..c272afd 100644
--- a/drivers/rtc/rtc-proc.c
+++ b/drivers/rtc/rtc-proc.c
@@ -65,7 +65,7 @@
 			seq_printf(seq, "%02d\n", alrm.time.tm_mday);
 		else
 			seq_printf(seq, "**\n");
-		seq_printf(seq, "alrm_wakeup\t: %s\n",
+		seq_printf(seq, "alarm_IRQ\t: %s\n",
 				alrm.enabled ? "yes" : "no");
 		seq_printf(seq, "alrm_pending\t: %s\n",
 				alrm.pending ? "yes" : "no");
@@ -120,7 +120,7 @@
 			ent->owner = rtc->owner;
 			ent->data = class_dev;
 
-			dev_info(class_dev->dev, "rtc intf: proc\n");
+			dev_dbg(class_dev->dev, "rtc intf: proc\n");
 		}
 		else
 			rtc_dev = NULL;
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index e301dea..f406a2b 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -191,6 +191,8 @@
 
 	alm_en = readb(base + S3C2410_RTCALM);
 
+	alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0;
+
 	pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n",
 		 alm_en,
 		 alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday,
@@ -331,12 +333,8 @@
 
 static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
 {
-	unsigned int rtcalm = readb(s3c_rtc_base + S3C2410_RTCALM);
 	unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT);
 
-	seq_printf(seq, "alarm_IRQ\t: %s\n",
-		   (rtcalm & S3C2410_RTCALM_ALMEN) ? "yes" : "no" );
-
 	seq_printf(seq, "periodic_IRQ\t: %s\n",
 		     (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" );
 
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index bd4d7d1..9c8ead4 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -289,9 +289,7 @@
 
 static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
 {
-	seq_printf(seq, "trim/divider\t: 0x%08lx\n", RTTR);
-	seq_printf(seq, "alarm_IRQ\t: %s\n",
-			(RTSR & RTSR_ALE) ? "yes" : "no" );
+	seq_printf(seq, "trim/divider\t: 0x%08x\n", (u32) RTTR);
 	seq_printf(seq, "update_IRQ\t: %s\n",
 			(RTSR & RTSR_HZE) ? "yes" : "no");
 	seq_printf(seq, "periodic_IRQ\t: %s\n",
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c
index 625637b..9418a59 100644
--- a/drivers/rtc/rtc-sysfs.c
+++ b/drivers/rtc/rtc-sysfs.c
@@ -83,7 +83,7 @@
 {
 	int err;
 
-	dev_info(class_dev->dev, "rtc intf: sysfs\n");
+	dev_dbg(class_dev->dev, "rtc intf: sysfs\n");
 
 	err = sysfs_create_group(&class_dev->kobj, &rtc_attr_group);
 	if (err)
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index c9321b9..25b5d7a 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -688,7 +688,7 @@
 	raw->cdev = cdev;
 	raw->inbuf = (char *) raw + sizeof(struct raw3215_info);
 	memset(raw, 0, sizeof(struct raw3215_info));
-	raw->buffer = (char *) kmalloc(RAW3215_BUFFER_SIZE,
+	raw->buffer = kmalloc(RAW3215_BUFFER_SIZE,
 				       GFP_KERNEL|GFP_DMA);
 	if (raw->buffer == NULL) {
 		spin_lock(&raw3215_device_lock);
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
index e3491a5..3e86fd1 100644
--- a/drivers/s390/char/keyboard.c
+++ b/drivers/s390/char/keyboard.c
@@ -377,7 +377,7 @@
 		if (!(key_map = kbd->key_maps[tmp.kb_table])) {
 			int j;
 
-			key_map = (ushort *) kmalloc(sizeof(plain_map),
+			key_map = kmalloc(sizeof(plain_map),
 						     GFP_KERNEL);
 			if (!key_map)
 				return -ENOMEM;
diff --git a/drivers/s390/char/sclp_cpi.c b/drivers/s390/char/sclp_cpi.c
index 732dfbd..f7c10d9 100644
--- a/drivers/s390/char/sclp_cpi.c
+++ b/drivers/s390/char/sclp_cpi.c
@@ -127,7 +127,7 @@
 	struct cpi_sccb *sccb;
 	struct cpi_evbuf *evb;
 
-	req = (struct sclp_req *) kmalloc(sizeof(struct sclp_req), GFP_KERNEL);
+	req = kmalloc(sizeof(struct sclp_req), GFP_KERNEL);
 	if (req == NULL)
 		return ERR_PTR(-ENOMEM);
 	sccb = (struct cpi_sccb *) __get_free_page(GFP_KERNEL | GFP_DMA);
diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c
index a62b000..5bb13a9 100644
--- a/drivers/s390/crypto/zcrypt_cex2a.c
+++ b/drivers/s390/crypto/zcrypt_cex2a.c
@@ -295,7 +295,7 @@
 	struct completion work;
 	int rc;
 
-	ap_msg.message = (void *) kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL);
+	ap_msg.message = kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL);
 	if (!ap_msg.message)
 		return -ENOMEM;
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
@@ -337,7 +337,7 @@
 	struct completion work;
 	int rc;
 
-	ap_msg.message = (void *) kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL);
+	ap_msg.message = kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL);
 	if (!ap_msg.message)
 		return -ENOMEM;
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c
index b6a4ecd..32e3701 100644
--- a/drivers/s390/crypto/zcrypt_pcica.c
+++ b/drivers/s390/crypto/zcrypt_pcica.c
@@ -279,7 +279,7 @@
 	struct completion work;
 	int rc;
 
-	ap_msg.message = (void *) kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
+	ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
 	if (!ap_msg.message)
 		return -ENOMEM;
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
@@ -321,7 +321,7 @@
 	struct completion work;
 	int rc;
 
-	ap_msg.message = (void *) kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
+	ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
 	if (!ap_msg.message)
 		return -ENOMEM;
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
index 2da8b93..b7153c1 100644
--- a/drivers/s390/crypto/zcrypt_pcixcc.c
+++ b/drivers/s390/crypto/zcrypt_pcixcc.c
@@ -717,7 +717,7 @@
 	};
 	int rc;
 
-	ap_msg.message = (void *) kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
+	ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
 	if (!ap_msg.message)
 		return -ENOMEM;
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
index 3257c22..03cc263 100644
--- a/drivers/s390/net/ctcmain.c
+++ b/drivers/s390/net/ctcmain.c
@@ -1646,7 +1646,7 @@
 		return -1;
 	}
 	memset(ch, 0, sizeof (struct channel));
-	if ((ch->ccw = (struct ccw1 *) kmalloc(8*sizeof(struct ccw1),
+	if ((ch->ccw = kmalloc(8*sizeof(struct ccw1),
 					       GFP_KERNEL | GFP_DMA)) == NULL) {
 		kfree(ch);
 		ctc_pr_warn("ctc: Out of memory in add_channel\n");
@@ -1693,7 +1693,7 @@
 		return -1;
 	}
 	fsm_newstate(ch->fsm, CH_STATE_IDLE);
-	if ((ch->irb = (struct irb *) kmalloc(sizeof (struct irb),
+	if ((ch->irb = kmalloc(sizeof (struct irb),
 					      GFP_KERNEL)) == NULL) {
 		ctc_pr_warn("ctc: Out of memory in add_channel\n");
 		kfree_fsm(ch->fsm);
@@ -2535,7 +2535,7 @@
 	DBF_TEXT(trace, 4, __FUNCTION__);
 	if (!priv)
 		return;
-	sbuf = (char *)kmalloc(2048, GFP_KERNEL);
+	sbuf = kmalloc(2048, GFP_KERNEL);
 	if (sbuf == NULL)
 		return;
 	p = sbuf;
diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
index 1476ce2..229aeb5 100644
--- a/drivers/s390/net/iucv.c
+++ b/drivers/s390/net/iucv.c
@@ -772,7 +772,7 @@
 	}
 
 	/* Allocate handler entry */
-	new_handler = (handler *)kmalloc(sizeof(handler), GFP_ATOMIC);
+	new_handler = kmalloc(sizeof(handler), GFP_ATOMIC);
 	if (new_handler == NULL) {
 		printk(KERN_WARNING "%s: storage allocation for new handler "
 		       "failed.\n", __FUNCTION__);
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 5d39b2d..85093b7 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -237,7 +237,7 @@
 		return 0;
 
 	len = strlen(devstr) + 1;
-	str = (char *) kmalloc(len, GFP_KERNEL);
+	str = kmalloc(len, GFP_KERNEL);
 	if (!str)
 		goto err_out;
 	memcpy(str, devstr, len);
diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c
index 2722af5..386e7de 100644
--- a/drivers/sbus/char/vfc_dev.c
+++ b/drivers/sbus/char/vfc_dev.c
@@ -659,7 +659,7 @@
 	if (!cards)
 		return -ENODEV;
 
-	vfc_dev_lst = (struct vfc_dev **)kmalloc(sizeof(struct vfc_dev *) *
+	vfc_dev_lst = kmalloc(sizeof(struct vfc_dev *) *
 						 (cards+1),
 						 GFP_KERNEL);
 	if (vfc_dev_lst == NULL)
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index ac108f9..426cd6f 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -288,7 +288,7 @@
 
 	if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS)
 		maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
-	fsa_dev_ptr = (struct fsa_dev_info *) kmalloc(
+	fsa_dev_ptr = kmalloc(
 	  sizeof(*fsa_dev_ptr) * maximum_num_containers, GFP_KERNEL);
 	if (!fsa_dev_ptr) {
 		aac_fib_free(fibptr);
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index d5cf8b9..6d305b2 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -386,7 +386,7 @@
 	 *	Ok now init the communication subsystem
 	 */
 
-	dev->queues = (struct aac_queue_block *) kmalloc(sizeof(struct aac_queue_block), GFP_KERNEL);
+	dev->queues = kmalloc(sizeof(struct aac_queue_block), GFP_KERNEL);
 	if (dev->queues == NULL) {
 		printk(KERN_ERR "Error could not allocate comm region.\n");
 		return NULL;
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index d7a61a6..1d239f6 100644
--- a/drivers/scsi/aha1542.c
+++ b/drivers/scsi/aha1542.c
@@ -699,7 +699,7 @@
 #endif
 		int i;
 		ccb[mbo].op = 2;	/* SCSI Initiator Command  w/scatter-gather */
-		SCpnt->host_scribble = (unsigned char *) kmalloc(512, GFP_KERNEL | GFP_DMA);
+		SCpnt->host_scribble = kmalloc(512, GFP_KERNEL | GFP_DMA);
 		sgpnt = (struct scatterlist *) SCpnt->request_buffer;
 		cptr = (struct chain *) SCpnt->host_scribble;
 		if (cptr == NULL) {
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index 46eed10..7d1fec6 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -2565,7 +2565,7 @@
       }
     }
     scb_count = min( (i-1), p->scb_data->maxscbs - p->scb_data->numscbs);
-    scb_ap = (struct aic7xxx_scb *)kmalloc(sizeof (struct aic7xxx_scb) * scb_count
+    scb_ap = kmalloc(sizeof (struct aic7xxx_scb) * scb_count
 					   + sizeof(struct aic7xxx_scb_dma), GFP_ATOMIC);
     if (scb_ap == NULL)
       return(0);
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index e95b367..a965ed3 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -4319,7 +4319,7 @@
 
 	dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages);
 	while (pages--) {
-		ptr = (struct SGentry *)kmalloc(PAGE_SIZE, GFP_KERNEL);
+		ptr = kmalloc(PAGE_SIZE, GFP_KERNEL);
 		if (!ptr) {
 			adapter_sg_tables_free(acb);
 			return 1;
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 60b1b43..365db53 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -297,7 +297,7 @@
 	s32 rcode;
 
 	memset(msg, 0, sizeof(msg));
-	buf = (u8*)kmalloc(80,GFP_KERNEL|ADDR32);
+	buf = kmalloc(80,GFP_KERNEL|ADDR32);
 	if(!buf){
 		printk(KERN_ERR"%s: Could not allocate buffer\n",pHba->name);
 		return;
@@ -1311,7 +1311,7 @@
 		schedule_timeout_uninterruptible(1);
 	} while (m == EMPTY_QUEUE);
 
-	status = (u8*)kmalloc(4, GFP_KERNEL|ADDR32);
+	status = kmalloc(4, GFP_KERNEL|ADDR32);
 	if(status == NULL) {
 		adpt_send_nop(pHba, m);
 		printk(KERN_ERR"IOP reset failed - no free memory.\n");
@@ -1444,7 +1444,7 @@
 			}
 			continue;
 		}
-		d = (struct i2o_device *)kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
+		d = kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
 		if(d==NULL)
 		{
 			printk(KERN_CRIT"%s: Out of memory for I2O device data.\n",pHba->name);
@@ -2425,7 +2425,7 @@
 				pDev = pDev->next_lun;
 			}
 			if(!pDev ) { // Something new add it
-				d = (struct i2o_device *)kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
+				d = kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
 				if(d==NULL)
 				{
 					printk(KERN_CRIT "Out of memory for I2O device data.\n");
@@ -2728,7 +2728,7 @@
 
 	kfree(pHba->reply_pool);
 
-	pHba->reply_pool = (u32*)kmalloc(pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, GFP_KERNEL|ADDR32);
+	pHba->reply_pool = kmalloc(pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, GFP_KERNEL|ADDR32);
 	if(!pHba->reply_pool){
 		printk(KERN_ERR"%s: Could not allocate reply pool\n",pHba->name);
 		return -1;
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index f160357..d561663 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -2828,7 +2828,7 @@
 
 	for (; tul_num_scb >= MAX_TARGETS + 3; tul_num_scb--) {
 		i = tul_num_ch * tul_num_scb * sizeof(SCB);
-		if ((tul_scb = (SCB *) kmalloc(i, GFP_ATOMIC | GFP_DMA)) != NULL)
+		if ((tul_scb = kmalloc(i, GFP_ATOMIC | GFP_DMA)) != NULL)
 			break;
 	}
 	if (tul_scb == NULL) {
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 824fe08..7d23110 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -5777,7 +5777,7 @@
 	dev_num = i;
 
 	/* allocate a struct osst_tape for this device */
-	tpnt = (struct osst_tape *)kmalloc(sizeof(struct osst_tape), GFP_ATOMIC);
+	tpnt = kmalloc(sizeof(struct osst_tape), GFP_ATOMIC);
 	if (tpnt == NULL) {
 		write_unlock(&os_scsi_tapes_lock);
 		printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c
index aa60a5f..3b2e1a5 100644
--- a/drivers/scsi/pluto.c
+++ b/drivers/scsi/pluto.c
@@ -117,7 +117,7 @@
 #endif
 			return 0;
 	}
-	fcs = (struct ctrl_inquiry *) kmalloc (sizeof (struct ctrl_inquiry) * fcscount, GFP_DMA);
+	fcs = kmalloc(sizeof (struct ctrl_inquiry) * fcscount, GFP_DMA);
 	if (!fcs) {
 		printk ("PLUTO: Not enough memory to probe\n");
 		return 0;
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
index d1268cb..0578ba4 100644
--- a/drivers/scsi/sr_ioctl.c
+++ b/drivers/scsi/sr_ioctl.c
@@ -546,7 +546,7 @@
 	if (!xa_test)
 		return 0;
 
-	raw_sector = (unsigned char *) kmalloc(2048, GFP_KERNEL | SR_GFP_DMA(cd));
+	raw_sector = kmalloc(2048, GFP_KERNEL | SR_GFP_DMA(cd));
 	if (!raw_sector)
 		return -ENOMEM;
 	if (0 == sr_read_sector(cd, cd->ms_offset + 16,
diff --git a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c
index a3e9d0f..4eb3da9 100644
--- a/drivers/scsi/sr_vendor.c
+++ b/drivers/scsi/sr_vendor.c
@@ -117,7 +117,7 @@
 		density = (blocklength > 2048) ? 0x81 : 0x83;
 #endif
 
-	buffer = (unsigned char *) kmalloc(512, GFP_KERNEL | GFP_DMA);
+	buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
 	if (!buffer)
 		return -ENOMEM;
 
@@ -164,7 +164,7 @@
 	if (cd->cdi.mask & CDC_MULTI_SESSION)
 		return 0;
 
-	buffer = (unsigned char *) kmalloc(512, GFP_KERNEL | GFP_DMA);
+	buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
 	if (!buffer)
 		return -ENOMEM;
 
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index 940fa1e..21cd4c7 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -5545,7 +5545,7 @@
 	/*
 	 *  Allocate the array of lists of CCBs hashed by DSA.
 	 */
-	np->ccbh = kcalloc(sizeof(struct sym_ccb **), CCB_HASH_SIZE, GFP_KERNEL);
+	np->ccbh = kcalloc(CCB_HASH_SIZE, sizeof(struct sym_ccb **), GFP_KERNEL);
 	if (!np->ccbh)
 		goto attach_failed;
 
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 4d0ff8f..52e2e64 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -2239,6 +2239,30 @@
 		pbn_b0_bt_1_460800 },
 
 	/*
+	 * Korenix Jetcard F0/F1 cards (JC1204, JC1208, JC1404, JC1408).
+	 * Cards are identified by their subsystem vendor IDs, which
+	 * (in hex) match the model number.
+	 *
+	 * Note that JC140x are RS422/485 cards which require ox950
+	 * ACR = 0x10, and as such are not currently fully supported.
+	 */
+	{	PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
+		0x1204, 0x0004, 0, 0,
+		pbn_b0_4_921600 },
+	{	PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
+		0x1208, 0x0004, 0, 0,
+		pbn_b0_4_921600 },
+/*	{	PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
+		0x1402, 0x0002, 0, 0,
+		pbn_b0_2_921600 }, */
+/*	{	PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
+		0x1404, 0x0004, 0, 0,
+		pbn_b0_4_921600 }, */
+	{	PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF1,
+		0x1208, 0x0004, 0, 0,
+		pbn_b0_4_921600 },
+
+	/*
 	 * Dell Remote Access Card 4 - Tim_T_Murphy@Dell.com
 	 */
 	{	PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_RAC4,
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 72f3db9..3e0abbb 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -598,7 +598,7 @@
 {
 	struct at91_request *req;
 
-	req = kcalloc(1, sizeof (struct at91_request), gfp_flags);
+	req = kzalloc(sizeof (struct at91_request), gfp_flags);
 	if (!req)
 		return NULL;
 
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index 5516c59..2d12bf9 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -2195,7 +2195,7 @@
 	if (size == 0)
 		return NULL;
 
-	gb = (struct gs_buf *)kmalloc(sizeof(struct gs_buf), kmalloc_flags);
+	gb = kmalloc(sizeof(struct gs_buf), kmalloc_flags);
 	if (gb == NULL)
 		return NULL;
 
diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c
index 9325e46..282d82e 100644
--- a/drivers/usb/host/hc_crisv10.c
+++ b/drivers/usb/host/hc_crisv10.c
@@ -365,7 +365,7 @@
 /* Adds an urb_entry last in the list for this epid. */
 static inline void urb_list_add(struct urb *urb, int epid)
 {
-	urb_entry_t *urb_entry = (urb_entry_t *)kmalloc(sizeof(urb_entry_t), KMALLOC_FLAG);
+	urb_entry_t *urb_entry = kmalloc(sizeof(urb_entry_t), KMALLOC_FLAG);
 	assert(urb_entry);
 
 	urb_entry->urb = urb;
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index c703f73..6c7f3ef 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -766,7 +766,7 @@
                 bep->bufp = kmalloc (bufsize, GFP_KERNEL);
                 if (!bep->bufp)
 			goto bl_fail;
-                bep->dr = (struct usb_ctrlrequest *) kmalloc (sizeof (struct usb_ctrlrequest), GFP_KERNEL);
+                bep->dr = kmalloc(sizeof (struct usb_ctrlrequest), GFP_KERNEL);
                 if (!bep->dr)
 			goto bl_fail;
                 bep->urbp = usb_alloc_urb (0, GFP_KERNEL);
@@ -1969,7 +1969,7 @@
 	info("device is a %s", cp->dev_desc);
 
         /* get the maximum allowed control transfer length */
-        pbuf = (__le16 *) kmalloc (2, GFP_KERNEL);    /* use an allocated buffer because of urb target */
+        pbuf = kmalloc(2, GFP_KERNEL);    /* use an allocated buffer because of urb target */
         if (!pbuf) {
 		err( "out of memory");
 		goto pfail;
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index 7e8a0ac..7025025 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -705,7 +705,7 @@
 	/*
 	 * Allocate parport interface 
 	 */
-	if (!(priv = kcalloc(sizeof(struct parport_uss720_private), 1, GFP_KERNEL))) {
+	if (!(priv = kzalloc(sizeof(struct parport_uss720_private), GFP_KERNEL))) {
 		usb_put_dev(usbdev);
 		return -ENOMEM;
 	}
diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c
index 99f26b3..ea5f44d 100644
--- a/drivers/usb/net/rndis_host.c
+++ b/drivers/usb/net/rndis_host.c
@@ -469,7 +469,7 @@
 	struct rndis_halt	*halt;
 
 	/* try to clear any rndis state/activity (no i/o from stack!) */
-	halt = kcalloc(1, sizeof *halt, GFP_KERNEL);
+	halt = kzalloc(sizeof *halt, GFP_KERNEL);
 	if (halt) {
 		halt->msg_type = RNDIS_MSG_HALT;
 		halt->msg_len = ccpu2(sizeof *halt);
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index a1fdb85..45cdf9b 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -1493,7 +1493,7 @@
 	if (size == 0)
 		return NULL;
 
-	cb = (struct cypress_buf *)kmalloc(sizeof(struct cypress_buf), GFP_KERNEL);
+	cb = kmalloc(sizeof(struct cypress_buf), GFP_KERNEL);
 	if (cb == NULL)
 		return NULL;
 
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 9d9ea87..efd9ce3 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -1681,7 +1681,7 @@
 	for( i=0; i<serial->type->num_ports+1; i++ ) {
 
 		/* allocate port private structure */
-		priv = (struct digi_port *)kmalloc( sizeof(struct digi_port),
+		priv = kmalloc( sizeof(struct digi_port),
 			GFP_KERNEL );
 		if( priv == (struct digi_port *)0 ) {
 			while( --i >= 0 )
@@ -1714,7 +1714,7 @@
 	}
 
 	/* allocate serial private structure */
-	serial_priv = (struct digi_serial *)kmalloc( sizeof(struct digi_serial),
+	serial_priv = kmalloc( sizeof(struct digi_serial),
 		GFP_KERNEL );
 	if( serial_priv == (struct digi_serial *)0 ) {
 		for( i=0; i<serial->type->num_ports+1; i++ )
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 2da2684..980285c 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -2811,7 +2811,7 @@
 	if (size == 0)
 		return NULL;
 
-	eb = (struct edge_buf *)kmalloc(sizeof(struct edge_buf), GFP_KERNEL);
+	eb = kmalloc(sizeof(struct edge_buf), GFP_KERNEL);
 	if (eb == NULL)
 		return NULL;
 
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index d72cf8b..42f757a 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -595,7 +595,7 @@
 
 	bytes_in = 0;
 	bytes_out = 0;
-	priv = (struct ipaq_private *)kmalloc(sizeof(struct ipaq_private), GFP_KERNEL);
+	priv = kmalloc(sizeof(struct ipaq_private), GFP_KERNEL);
 	if (priv == NULL) {
 		err("%s - Out of memory", __FUNCTION__);
 		return -ENOMEM;
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index e284d6c..62bea0c 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -269,7 +269,7 @@
 	}
 
 	// allocate memory for write_urb transfer buffer
-	port->write_urb->transfer_buffer = (unsigned char *) kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL);
+	port->write_urb->transfer_buffer = kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL);
 	if (! port->write_urb->transfer_buffer) {
 		kfree(transfer_buffer);
 		usb_free_urb(port->write_urb);
@@ -696,7 +696,7 @@
 		return 0;
 
 	case TCFLSH:   // 0x540B
-		transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL);
+		transfer_buffer = kmalloc(transfer_buffer_length, GFP_KERNEL);
 		if (! transfer_buffer) {
 		 	return -ENOBUFS;
 		}
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index d124d78..5dc2ac9 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -159,7 +159,7 @@
 	if (size == 0)
 		return NULL;
 
-	pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);
+	pb = kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);
 	if (pb == NULL)
 		return NULL;
 
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index f42eb9e..8318900 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -1710,7 +1710,7 @@
 {
 	struct circ_buf *cb;
 
-	cb = (struct circ_buf *)kmalloc(sizeof(struct circ_buf), GFP_KERNEL);
+	cb = kmalloc(sizeof(struct circ_buf), GFP_KERNEL);
 	if (cb == NULL)
 		return NULL;
 
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index dc45e58..5483d85 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -416,7 +416,7 @@
 	for (i = 0; i < serial->num_ports; i++) {
 		port = serial->port[i];
 
-		info = (struct whiteheat_private *)kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
+		info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
 		if (info == NULL) {
 			err("%s: Out of memory for port structures\n", serial->type->description);
 			goto no_private;
@@ -487,7 +487,7 @@
 		usb_set_serial_port_data(port, info);
 	}
 
-	command_info = (struct whiteheat_command_private *)kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL);
+	command_info = kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL);
 	if (command_info == NULL) {
 		err("%s: Out of memory for port structures\n", serial->type->description);
 		goto no_command_private;
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index fb8baca..e3528ec 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -646,7 +646,7 @@
 		return result;
 	}
 
-	buf = (unsigned char *) kmalloc(bulklen, GFP_NOIO);
+	buf = kmalloc(bulklen, GFP_NOIO);
 	if (!buf)
 		return -ENOMEM;
 
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
index 6761b68..6c9dc2e 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -447,7 +447,7 @@
 		goto out;
 	}
 
-	fb = (struct clcd_fb *) kmalloc(sizeof(struct clcd_fb), GFP_KERNEL);
+	fb = kmalloc(sizeof(struct clcd_fb), GFP_KERNEL);
 	if (!fb) {
 		printk(KERN_INFO "CLCD: could not allocate new clcd_fb struct\n");
 		ret = -ENOMEM;
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index 88a4784..1a849b8 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -2906,14 +2906,6 @@
 	par->crsr.spot_x = par->crsr.spot_y = 0;
 	par->crsr.height = par->crsr.width = 0;
 
-#if 0	/* fbmon not done.  uncomment for 2.5.x -brad */
-	if (!fbmon_valid_timings(pixclock[clk_shift], htotal, vtotal,
-				 &fb_info)) {
-		DPRINTK("mode doesn't fit for monitor\n");
-		return -EINVAL;
-	}
-#endif
-
 	return 0;
 }
 
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 176f9b8..09684d7 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -1488,10 +1488,6 @@
 	else
 		info->var.accel_flags = 0;
 
-#if 0 /* fbmon is not done. uncomment for 2.5.x -brad */
-	if (!fbmon_valid_timings(pixclock, htotal, vtotal, info))
-		return -EINVAL;
-#endif
 	aty_crtc_to_var(&crtc, var);
 	var->pixclock = par->pll_ops->pll_to_var(info, &pll);
 	return 0;
diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/matrox/i2c-matroxfb.c
index 797b423..fe28848 100644
--- a/drivers/video/matrox/i2c-matroxfb.c
+++ b/drivers/video/matrox/i2c-matroxfb.c
@@ -146,7 +146,7 @@
 	unsigned long flags;
 	struct matroxfb_dh_maven_info* m2info;
 
-	m2info = (struct matroxfb_dh_maven_info*)kmalloc(sizeof(*m2info), GFP_KERNEL);
+	m2info = kmalloc(sizeof(*m2info), GFP_KERNEL);
 	if (!m2info)
 		return NULL;
 
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index e9b4115..cb2aa40 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -2028,7 +2028,7 @@
 	}
 
 #ifdef CONFIG_FB_MATROX_MULTIHEAD
-	minfo = (struct matrox_fb_info*)kmalloc(sizeof(*minfo), GFP_KERNEL);
+	minfo = kmalloc(sizeof(*minfo), GFP_KERNEL);
 	if (!minfo)
 		return -1;
 #else
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
index 27eb4bb..2c98010 100644
--- a/drivers/video/matrox/matroxfb_crtc2.c
+++ b/drivers/video/matrox/matroxfb_crtc2.c
@@ -694,7 +694,7 @@
 	/* hardware is CRTC2 incapable... */
 	if (!ACCESS_FBINFO(devflags.crtc2))
 		return NULL;
-	m2info = (struct matroxfb_dh_fb_info*)kmalloc(sizeof(*m2info), GFP_KERNEL);
+	m2info = kmalloc(sizeof(*m2info), GFP_KERNEL);
 	if (!m2info) {
 		printk(KERN_ERR "matroxfb_crtc2: Not enough memory for CRTC2 control structs\n");
 		return NULL;
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
index 711cb11..59cd1e7 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/sstfb.c
@@ -21,6 +21,11 @@
  *	Remove never finished and bogus 24/32bit support
  *	Clean up macro abuse
  *	Minor tidying for format.
+ * 12/2006 Helge Deller    <deller@gmx.de>
+ *	add /sys/class/graphics/fbX/vgapass sysfs-interface
+ *	add module option "mode_option" to set initial screen mode
+ *	use fbdev default videomode database
+ *	remove debug functions from ioctl
  */
 
 /*
@@ -65,19 +70,10 @@
  *
  * sstfb specific ioctls:
  *   		toggle vga (0x46db) : toggle vga_pass_through
- *   		fill fb    (0x46dc) : fills fb
- *   		test disp  (0x46de) : draws a test image
  */
 
 #undef SST_DEBUG
 
-/*
-  Default video mode .
-  0 800x600@60  took from glide
-  1 640x480@75  took from glide
-  2 1024x768@76 std fb.mode
-  3 640x480@60  glide default */
-#define DEFAULT_MODE 3 
 
 /*
  * Includes
@@ -92,20 +88,24 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <asm/io.h>
-#include <asm/ioctl.h>
 #include <asm/uaccess.h>
 #include <video/sstfb.h>
 
 
 /* initialized by setup */
 
-static int vgapass;		/* enable Vga passthrough cable */
+static int vgapass;		/* enable VGA passthrough cable */
 static int mem;			/* mem size in MB, 0 = autodetect */
 static int clipping = 1;	/* use clipping (slower, safer) */
 static int gfxclk;		/* force FBI freq in Mhz . Dangerous */
 static int slowpci;		/* slow PCI settings */
 
-static char *mode_option __devinitdata;
+/*
+  Possible default video modes: 800x600@60, 640x480@75, 1024x768@76, 640x480@60
+*/
+#define DEFAULT_VIDEO_MODE "640x480@60"
+
+static char *mode_option __devinitdata = DEFAULT_VIDEO_MODE;
 
 enum {
 	ID_VOODOO1 = 0,
@@ -119,48 +119,11 @@
  { .name = "Voodoo2",	      .default_gfx_clock = 75000, .max_gfxclk = 85 },
 };
 
-static struct fb_var_screeninfo	sstfb_default =
-#if ( DEFAULT_MODE == 0 )
-    { /* 800x600@60, 16 bpp .borowed from glide/sst1/include/sst1init.h */
-    800, 600, 800, 600, 0, 0, 16, 0,
-    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-    0, 0, -1, -1, 0,
-    25000, 86, 41, 23, 1, 127, 4,
-    0, FB_VMODE_NONINTERLACED };
-#elif ( DEFAULT_MODE == 1 )
-    {/* 640x480@75, 16 bpp .borowed from glide/sst1/include/sst1init.h */
-    640, 480, 640, 480, 0, 0, 16, 0,
-    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-    0, 0, -1, -1, 0,
-    31746, 118, 17, 16, 1, 63, 3,
-    0, FB_VMODE_NONINTERLACED };
-#elif ( DEFAULT_MODE == 2 )
-    { /* 1024x768@76 took from my /etc/fb.modes */
-    1024, 768, 1024, 768,0, 0, 16,0,
-    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-    0, 0, -1, -1, 0,
-    11764, 208, 8, 36, 16, 120, 3 ,
-    0, FB_VMODE_NONINTERLACED };
-#elif ( DEFAULT_MODE == 3 )
-    { /* 640x480@60 , 16bpp glide default ?*/
-    640, 480, 640, 480, 0, 0, 16, 0,
-    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-    0, 0, -1, -1, 0,
-    39721 ,  38, 26 ,  25 ,18  , 96 ,2,
-    0, FB_VMODE_NONINTERLACED };
-#elif
-    #error "Invalid DEFAULT_MODE value !"
-#endif
-
 
 /*
  * debug functions
  */
 
-static void sstfb_drawdebugimage(struct fb_info *info);
-static int sstfb_dump_regs(struct fb_info *info);
-
-
 #if (SST_DEBUG_REG > 0)
 static void sst_dbg_print_read_reg(u32 reg, u32 val) {
 	const char *regname;
@@ -726,51 +689,77 @@
 	return 0;
 }
 
-static int sstfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
+static void sstfb_setvgapass( struct fb_info *info, int enable )
 {
 	struct sstfb_par *par = info->par;
 	struct pci_dev *sst_dev = par->dev;
-	u32 fbiinit0, tmp, val;
-	u_long p;
+	u32 fbiinit0, tmp;
+
+	enable = enable ? 1:0;
+	if (par->vgapass == enable)
+		return;
+	par->vgapass = enable;
+
+	pci_read_config_dword(sst_dev, PCI_INIT_ENABLE, &tmp);
+	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
+			       tmp | PCI_EN_INIT_WR );
+	fbiinit0 = sst_read (FBIINIT0);
+	if (par->vgapass) {
+		sst_write(FBIINIT0, fbiinit0 & ~DIS_VGA_PASSTHROUGH);
+		printk(KERN_INFO "fb%d: Enabling VGA pass-through\n", info->node );
+	} else {
+		sst_write(FBIINIT0, fbiinit0 | DIS_VGA_PASSTHROUGH);
+		printk(KERN_INFO "fb%d: Disabling VGA pass-through\n", info->node );
+	}
+	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp);
+}
+
+static ssize_t store_vgapass(struct device *device, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct fb_info *info = dev_get_drvdata(device);
+	char ** last = NULL;
+	int val;
+
+	val = simple_strtoul(buf, last, 0);
+	sstfb_setvgapass(info, val);
+
+	return count;
+}
+
+static ssize_t show_vgapass(struct device *device, struct device_attribute *attr,
+			char *buf)
+{
+	struct fb_info *info = dev_get_drvdata(device);
+	struct sstfb_par *par = info->par;
+	return snprintf(buf, PAGE_SIZE, "%d\n", par->vgapass);
+}
+
+static struct device_attribute device_attrs[] = {
+	__ATTR(vgapass, S_IRUGO|S_IWUSR, show_vgapass, store_vgapass)
+	};
+
+static int sstfb_ioctl(struct fb_info *info, unsigned int cmd,
+			unsigned long arg)
+{
+	struct sstfb_par *par;
+	u32 val;
 
 	switch (cmd) {
-		
-	/* dump current FBIINIT values to system log */
-	case _IO('F', 0xdb):            /* 0x46db */
-		return sstfb_dump_regs(info);
-		
-	/* fills lfb with #arg pixels */
-	case _IOW('F', 0xdc, u32):	/* 0x46dc */
+	/* set/get VGA pass_through mode */
+	case SSTFB_SET_VGAPASS:
 		if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
 			return -EFAULT;
-		if (val > info->fix.smem_len)
-			val = info->fix.smem_len;
-		for (p = 0 ; p < val; p += 2)
-			writew(p >> 6, info->screen_base + p);
+		sstfb_setvgapass(info, val);
 		return 0;
-		
-	/* change VGA pass_through mode */
-	case _IOW('F', 0xdd, u32):	/* 0x46dd */
-		if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
+	case SSTFB_GET_VGAPASS:
+		par = info->par;
+		val = par->vgapass;
+		if (copy_to_user((void __user *)arg, &val, sizeof(val)))
 			return -EFAULT;
-		pci_read_config_dword(sst_dev, PCI_INIT_ENABLE, &tmp);
-		pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
-				       tmp | PCI_EN_INIT_WR );
-		fbiinit0 = sst_read (FBIINIT0);
-		if (val)
-			sst_write(FBIINIT0, fbiinit0 & ~EN_VGA_PASSTHROUGH);
-		else
-			sst_write(FBIINIT0, fbiinit0 | EN_VGA_PASSTHROUGH);
-		pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp);
-		return 0;
-		
-	/* draw test image  */
-	case _IO('F', 0xde):		/* 0x46de */
-		f_dprintk("test color display at %d bpp\n",
-					info->var.bits_per_pixel);
-		sstfb_drawdebugimage(info);
 		return 0;
 	}
+
 	return -EINVAL;
 }
 
@@ -804,6 +793,7 @@
 /*
  * FillRect 2D command (solidfill or invert (via ROP_XOR)) - Voodoo2 only
  */
+#if 0
 static void sstfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 
 {
 	struct sstfb_par *par = info->par;
@@ -825,6 +815,7 @@
 		 | (BLT_16BPP_FMT << 3) /* | BIT(14) */ | BIT(15) | BIT(16) );
 	sst_wait_idle();
 }
+#endif
 
 
 
@@ -1156,6 +1147,7 @@
 	struct pll_timing gfx_timings;
 	struct sst_spec *spec;
 	int Fout;
+	int gfx_clock;
 
 	spec = &voodoo_spec[par->type];
 	f_ddprintk(" fbiinit0   fbiinit1   fbiinit2   fbiinit3   fbiinit4  "
@@ -1196,15 +1188,15 @@
 	}
 
 	/* set graphic clock */
-	par->gfx_clock = spec->default_gfx_clock;
+	gfx_clock = spec->default_gfx_clock;
 	if ((gfxclk >10 ) && (gfxclk < spec->max_gfxclk)) {
 		printk(KERN_INFO "sstfb: Using supplied graphic freq : %dMHz\n", gfxclk);
-		 par->gfx_clock = gfxclk *1000;
+		 gfx_clock = gfxclk *1000;
 	} else if (gfxclk) {
 		printk(KERN_WARNING "sstfb: %dMhz is way out of spec! Using default\n", gfxclk);
 	}
 
-	sst_calc_pll(par->gfx_clock, &Fout, &gfx_timings);
+	sst_calc_pll(gfx_clock, &Fout, &gfx_timings);
 	par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK);
 
 	/* disable fbiinit remap */
@@ -1215,10 +1207,11 @@
 	fbiinit0 = FBIINIT0_DEFAULT;
 	fbiinit1 = FBIINIT1_DEFAULT;
 	fbiinit4 = FBIINIT4_DEFAULT;
-	if (vgapass)
-		fbiinit0 &= ~EN_VGA_PASSTHROUGH;
+	par->vgapass = vgapass;
+	if (par->vgapass)
+		fbiinit0 &= ~DIS_VGA_PASSTHROUGH;
 	else
-		fbiinit0 |= EN_VGA_PASSTHROUGH;
+		fbiinit0 |= DIS_VGA_PASSTHROUGH;
 	if (slowpci) {
 		fbiinit1 |= SLOW_PCI_WRITES;
 		fbiinit4 |= SLOW_PCI_READS;
@@ -1267,7 +1260,7 @@
 	/* TODO maybe shutdown the dac, vrefresh and so on... */
 	pci_write_config_dword(dev, PCI_INIT_ENABLE,
 	                       PCI_EN_INIT_WR);
-	sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET | EN_VGA_PASSTHROUGH);
+	sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET | DIS_VGA_PASSTHROUGH);
 	pci_write_config_dword(dev, PCI_VCLK_DISABLE,0);
 	/* maybe keep fbiinit* and PCI_INIT_enable in the fb_info struct
 	 * from start ? */
@@ -1278,8 +1271,7 @@
 /*
  * Interface to the world
  */
-#ifndef MODULE
-static int  __init sstfb_setup(char *options)
+static int  __devinit sstfb_setup(char *options)
 {
 	char *this_opt;
 
@@ -1312,7 +1304,7 @@
 	}
 	return 0;
 }
-#endif
+
 
 static struct fb_ops sstfb_ops = {
 	.owner		= THIS_MODULE,
@@ -1416,15 +1408,10 @@
 	 */
 	fix->line_length = 2048; /* default value, for 24 or 32bit: 4096 */
 	
-	if ( mode_option &&
-	     fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16)) {
-		printk(KERN_ERR "sstfb: can't set supplied video mode. Using default\n");
-		info->var = sstfb_default;
-	} else
-		info->var = sstfb_default;
+	fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16);
 
 	if (sstfb_check_var(&info->var, info)) {
-		printk(KERN_ERR "sstfb: invalid default video mode.\n");
+		printk(KERN_ERR "sstfb: invalid video mode.\n");
 		goto fail;
 	}
 
@@ -1442,10 +1429,11 @@
 		goto fail;
 	}
 
-	if (1) /* set to 0 to see an initial bitmap instead */
-		sstfb_clear_screen(info);
-	else
-		sstfb_drawdebugimage(info);
+	sstfb_clear_screen(info);
+
+	if (device_create_file(info->dev, &device_attrs[0]))
+		printk(KERN_WARNING "sstfb: can't create sysfs entry.\n");
+
 
 	printk(KERN_INFO "fb%d: %s frame buffer device at 0x%p\n",
 	       info->node, fix->id, info->screen_base);
@@ -1453,6 +1441,7 @@
 	return 0;
 
 fail:
+	fb_dealloc_cmap(&info->cmap);
 	iounmap(info->screen_base);
 fail_fb_remap:
 	iounmap(par->mmio_vbase);
@@ -1473,21 +1462,23 @@
 	info = pci_get_drvdata(pdev);
 	par = info->par;
 	
+	device_remove_file(info->dev, &device_attrs[0]);
 	sst_shutdown(info);
-	unregister_framebuffer(info);
 	iounmap(info->screen_base);
 	iounmap(par->mmio_vbase);
 	release_mem_region(info->fix.smem_start, 0x400000);
 	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
+	fb_dealloc_cmap(&info->cmap);
+	unregister_framebuffer(info);
 	framebuffer_release(info);
 }
 
 
-static struct pci_device_id sstfb_id_tbl[] = {
-	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_VOODOO1 },
-	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_VOODOO2 },
+static const struct pci_device_id sstfb_id_tbl[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO ),
+		.driver_data = ID_VOODOO1, },
+	{ PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO2),
+		.driver_data = ID_VOODOO2, },
 	{ 0 },
 };
 
@@ -1501,142 +1492,23 @@
 
 static int __devinit sstfb_init(void)
 {
-#ifndef MODULE
 	char *option = NULL;
 
 	if (fb_get_options("sstfb", &option))
 		return -ENODEV;
 	sstfb_setup(option);
-#endif
+
 	return pci_register_driver(&sstfb_driver);
 }
 
-#ifdef MODULE
 static void __devexit sstfb_exit(void)
 {
 	pci_unregister_driver(&sstfb_driver);
 }
-#endif
 
 
-/*
- * testing and debugging functions
- */
-
-static int sstfb_dump_regs(struct fb_info *info)
-{
-#ifdef SST_DEBUG
-	static struct { u32 reg ; const char *reg_name;}  pci_regs[] = {
-		{ PCI_INIT_ENABLE, "initenable"},
-		{ PCI_VCLK_ENABLE, "enable vclk"},
-		{ PCI_VCLK_DISABLE, "disable vclk"},
-	};
-
-	static struct { u32 reg ; const char *reg_name;}  sst_regs[] = {
-		{FBIINIT0,"fbiinit0"},
-		{FBIINIT1,"fbiinit1"},
-		{FBIINIT2,"fbiinit2"},
-		{FBIINIT3,"fbiinit3"},
-		{FBIINIT4,"fbiinit4"},
-		{FBIINIT5,"fbiinit5"},
-		{FBIINIT6,"fbiinit6"},
-		{FBIINIT7,"fbiinit7"},
-		{LFBMODE,"lfbmode"},
-		{FBZMODE,"fbzmode"},
-	};
-
-	const int pci_s = ARRAY_SIZE(pci_regs);
-	const int sst_s = ARRAY_SIZE(sst_regs);
-	struct sstfb_par *par = info->par;
-	struct pci_dev *dev = par->dev;
-	u32 pci_res[pci_s];
-	u32 sst_res[sst_s];
-	int i;
-
-	for (i=0; i<pci_s; i++) {
-		pci_read_config_dword(dev, pci_regs[i].reg, &pci_res[i]);
-	}
-	for (i=0; i<sst_s; i++) {
-		sst_res[i] = sst_read(sst_regs[i].reg);
-	}
-
-	dprintk("hardware register dump:\n");
-	for (i=0; i<pci_s; i++) {
-		dprintk("%s %0#10x\n", pci_regs[i].reg_name, pci_res[i]);
-	}
-	for (i=0; i<sst_s; i++) {
-		dprintk("%s %0#10x\n", sst_regs[i].reg_name, sst_res[i]);
-	}
-	return 0;
-#else
-	return -EINVAL;
-#endif
-}
-
-static void sstfb_fillrect_softw( struct fb_info *info, const struct fb_fillrect *rect)
-{
-	u8 __iomem *fbbase_virt = info->screen_base;
-	int x, y, w = info->var.bits_per_pixel == 16 ? 2 : 4;
-	u32 color = rect->color, height = rect->height;
-	u8 __iomem *p;
-	
-	if (w==2) color |= color<<16;
-	for (y=rect->dy; height; y++, height--) {
-		p = fbbase_virt + y*info->fix.line_length + rect->dx*w;
-		x = rect->width;
-		if (w==2) x>>=1;
-		while (x) {
-			writel(color, p);
-			p += 4;
-			x--;
-		}
-	}
-}
-
-static void sstfb_drawrect_XY( struct fb_info *info, int x, int y,
-		int w, int h, int color, int hwfunc)
-{
-	struct fb_fillrect rect;
-	rect.dx = x;
-	rect.dy = y;
-	rect.height = h;
-	rect.width = w;
-	rect.color = color;
-	rect.rop = ROP_COPY;
-	if (hwfunc)
-		sstfb_fillrect(info, &rect);
-	else
-		sstfb_fillrect_softw(info, &rect);
-}
-
-/* print some squares on the fb */
-static void sstfb_drawdebugimage(struct fb_info *info)
-{
-	static int idx;
-
-	/* clear screen */
-	sstfb_clear_screen(info);
-	
-   	idx = (idx+1) & 1;
-
-	/* white rect */
-	sstfb_drawrect_XY(info, 0, 0, 50, 50, 0xffff, idx);
-	
-	/* blue rect */
-	sstfb_drawrect_XY(info, 50, 50, 50, 50, 0x001f, idx);
-
-	/* green rect */
-	sstfb_drawrect_XY(info, 100, 100, 80, 80, 0x07e0, idx);
-	
-	/* red rect */
-	sstfb_drawrect_XY(info, 250, 250, 120, 100, 0xf800, idx);
-}
-
 module_init(sstfb_init);
-
-#ifdef MODULE
 module_exit(sstfb_exit);
-#endif
 
 MODULE_AUTHOR("(c) 2000,2002 Ghozlane Toumi <gtoumi@laposte.net>");
 MODULE_DESCRIPTION("FBDev driver for 3dfx Voodoo Graphics and Voodoo2 based video boards");
@@ -1652,3 +1524,6 @@
 MODULE_PARM_DESC(gfxclk, "Force graphic chip frequency in MHz. DANGEROUS. (default=auto)");
 module_param(slowpci, bool, 0);
 MODULE_PARM_DESC(slowpci, "Uses slow PCI settings (0 or 1) (default=0)");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Initial video mode (default=" DEFAULT_VIDEO_MODE ")");
+
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig
index d18d642..904e5ae 100644
--- a/drivers/w1/slaves/Kconfig
+++ b/drivers/w1/slaves/Kconfig
@@ -9,7 +9,7 @@
 	tristate "Thermal family implementation"
 	depends on W1
 	help
-	  Say Y here if you want to connect 1-wire thermal sensors to you
+	  Say Y here if you want to connect 1-wire thermal sensors to your
 	  wire.
 
 config W1_SLAVE_SMEM
@@ -17,7 +17,7 @@
 	depends on W1
 	help
 	  Say Y here if you want to connect 1-wire
-	  simple 64bit memory rom(ds2401/ds2411/ds1990*) to you wire.
+	  simple 64bit memory rom(ds2401/ds2411/ds1990*) to your wire.
 
 config W1_SLAVE_DS2433
 	tristate "4kb EEPROM family support (DS2433)"
diff --git a/fs/aio.c b/fs/aio.c
index d3a6ec2..5f577a6 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -586,7 +586,7 @@
 	 * Note that on UML this *requires* PF_BORROWED_MM to be set, otherwise
 	 * it won't work. Update it accordingly if you change it here
 	 */
-	activate_mm(active_mm, mm);
+	switch_mm(active_mm, mm, tsk);
 	task_unlock(tsk);
 
 	mmdrop(active_mm);
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 9c48250..e8f6c5a 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -313,7 +313,7 @@
 	struct autofs_sb_info *sbi;
 	struct autofs_info *ino;
 
-	sbi = (struct autofs_sb_info *) kmalloc(sizeof(*sbi), GFP_KERNEL);
+	sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
 	if ( !sbi )
 		goto fail_unlock;
 	DPRINTK("starting up, sbi = %p",sbi);
diff --git a/fs/befs/btree.c b/fs/befs/btree.c
index 81b042e..af5bb93 100644
--- a/fs/befs/btree.c
+++ b/fs/befs/btree.c
@@ -260,7 +260,7 @@
 		goto error;
 	}
 
-	this_node = (befs_btree_node *) kmalloc(sizeof (befs_btree_node),
+	this_node = kmalloc(sizeof (befs_btree_node),
 						GFP_NOFS);
 	if (!this_node) {
 		befs_error(sb, "befs_btree_find() failed to allocate %u "
diff --git a/fs/befs/debug.c b/fs/befs/debug.c
index e831a8f..b8e304a 100644
--- a/fs/befs/debug.c
+++ b/fs/befs/debug.c
@@ -28,7 +28,7 @@
 befs_error(const struct super_block *sb, const char *fmt, ...)
 {
 	va_list args;
-	char *err_buf = (char *) kmalloc(ERRBUFSIZE, GFP_KERNEL);
+	char *err_buf = kmalloc(ERRBUFSIZE, GFP_KERNEL);
 	if (err_buf == NULL) {
 		printk(KERN_ERR "could not allocate %d bytes\n", ERRBUFSIZE);
 		return;
@@ -46,7 +46,7 @@
 befs_warning(const struct super_block *sb, const char *fmt, ...)
 {
 	va_list args;
-	char *err_buf = (char *) kmalloc(ERRBUFSIZE, GFP_KERNEL);
+	char *err_buf = kmalloc(ERRBUFSIZE, GFP_KERNEL);
 	if (err_buf == NULL) {
 		printk(KERN_ERR "could not allocate %d bytes\n", ERRBUFSIZE);
 		return;
@@ -70,7 +70,7 @@
 	char *err_buf = NULL;
 
 	if (BEFS_SB(sb)->mount_opts.debug) {
-		err_buf = (char *) kmalloc(ERRBUFSIZE, GFP_KERNEL);
+		err_buf = kmalloc(ERRBUFSIZE, GFP_KERNEL);
 		if (err_buf == NULL) {
 			printk(KERN_ERR "could not allocate %d bytes\n",
 				ERRBUFSIZE);
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index eac175e..134c999 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -1,7 +1,7 @@
 /*
  *	fs/bfs/inode.c
  *	BFS superblock and inode operations.
- *	Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com>
+ *	Copyright (C) 1999-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
  *	From fs/minix, Copyright (C) 1991, 1992 Linus Torvalds.
  *
  *      Made endianness-clean by Andrew Stribblehill <ads@wompom.org>, 2005.
@@ -18,7 +18,7 @@
 #include <asm/uaccess.h>
 #include "bfs.h"
 
-MODULE_AUTHOR("Tigran A. Aivazian <tigran@veritas.com>");
+MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
 MODULE_DESCRIPTION("SCO UnixWare BFS filesystem for Linux");
 MODULE_LICENSE("GPL");
 
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 00687ea..c2e0825 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -311,7 +311,7 @@
 
 	err = -ENOMEM;
 	memsize = sizeof(Node) + count + 8;
-	e = (Node *) kmalloc(memsize, GFP_USER);
+	e = kmalloc(memsize, GFP_USER);
 	if (!e)
 		goto out;
 
diff --git a/fs/bio.c b/fs/bio.c
index 7ec737e..7618bcb 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -916,7 +916,7 @@
 	}
 }
 
-static void bio_release_pages(struct bio *bio)
+void bio_release_pages(struct bio *bio)
 {
 	struct bio_vec *bvec = bio->bi_io_vec;
 	int i;
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 197f939..1715d6b 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -129,43 +129,191 @@
 	return 0;
 }
 
-static int
-blkdev_get_blocks(struct inode *inode, sector_t iblock,
-		struct buffer_head *bh, int create)
+static int blk_end_aio(struct bio *bio, unsigned int bytes_done, int error)
 {
-	sector_t end_block = max_block(I_BDEV(inode));
-	unsigned long max_blocks = bh->b_size >> inode->i_blkbits;
+	struct kiocb *iocb = bio->bi_private;
+	atomic_t *bio_count = &iocb->ki_bio_count;
 
-	if ((iblock + max_blocks) > end_block) {
-		max_blocks = end_block - iblock;
-		if ((long)max_blocks <= 0) {
-			if (create)
-				return -EIO;	/* write fully beyond EOF */
-			/*
-			 * It is a read which is fully beyond EOF.  We return
-			 * a !buffer_mapped buffer
-			 */
-			max_blocks = 0;
-		}
+	if (bio_data_dir(bio) == READ)
+		bio_check_pages_dirty(bio);
+	else {
+		bio_release_pages(bio);
+		bio_put(bio);
 	}
 
-	bh->b_bdev = I_BDEV(inode);
-	bh->b_blocknr = iblock;
-	bh->b_size = max_blocks << inode->i_blkbits;
-	if (max_blocks)
-		set_buffer_mapped(bh);
+	/* iocb->ki_nbytes stores error code from LLDD */
+	if (error)
+		iocb->ki_nbytes = -EIO;
+
+	if (atomic_dec_and_test(bio_count)) {
+		if (iocb->ki_nbytes < 0)
+			aio_complete(iocb, iocb->ki_nbytes, 0);
+		else
+			aio_complete(iocb, iocb->ki_left, 0);
+	}
+
 	return 0;
 }
 
+#define VEC_SIZE	16
+struct pvec {
+	unsigned short nr;
+	unsigned short idx;
+	struct page *page[VEC_SIZE];
+};
+
+#define PAGES_SPANNED(addr, len)	\
+	(DIV_ROUND_UP((addr) + (len), PAGE_SIZE) - (addr) / PAGE_SIZE);
+
+/*
+ * get page pointer for user addr, we internally cache struct page array for
+ * (addr, count) range in pvec to avoid frequent call to get_user_pages.  If
+ * internal page list is exhausted, a batch count of up to VEC_SIZE is used
+ * to get next set of page struct.
+ */
+static struct page *blk_get_page(unsigned long addr, size_t count, int rw,
+				 struct pvec *pvec)
+{
+	int ret, nr_pages;
+	if (pvec->idx == pvec->nr) {
+		nr_pages = PAGES_SPANNED(addr, count);
+		nr_pages = min(nr_pages, VEC_SIZE);
+		down_read(&current->mm->mmap_sem);
+		ret = get_user_pages(current, current->mm, addr, nr_pages,
+				     rw == READ, 0, pvec->page, NULL);
+		up_read(&current->mm->mmap_sem);
+		if (ret < 0)
+			return ERR_PTR(ret);
+		pvec->nr = ret;
+		pvec->idx = 0;
+	}
+	return pvec->page[pvec->idx++];
+}
+
 static ssize_t
 blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
-			loff_t offset, unsigned long nr_segs)
+		 loff_t pos, unsigned long nr_segs)
 {
-	struct file *file = iocb->ki_filp;
-	struct inode *inode = file->f_mapping->host;
+	struct inode *inode = iocb->ki_filp->f_mapping->host;
+	unsigned blkbits = blksize_bits(bdev_hardsect_size(I_BDEV(inode)));
+	unsigned blocksize_mask = (1 << blkbits) - 1;
+	unsigned long seg = 0;	/* iov segment iterator */
+	unsigned long nvec;	/* number of bio vec needed */
+	unsigned long cur_off;	/* offset into current page */
+	unsigned long cur_len;	/* I/O len of current page, up to PAGE_SIZE */
 
-	return blockdev_direct_IO_no_locking(rw, iocb, inode, I_BDEV(inode),
-				iov, offset, nr_segs, blkdev_get_blocks, NULL);
+	unsigned long addr;	/* user iovec address */
+	size_t count;		/* user iovec len */
+	size_t nbytes = iocb->ki_nbytes = iocb->ki_left; /* total xfer size */
+	loff_t size;		/* size of block device */
+	struct bio *bio;
+	atomic_t *bio_count = &iocb->ki_bio_count;
+	struct page *page;
+	struct pvec pvec;
+
+	pvec.nr = 0;
+	pvec.idx = 0;
+
+	if (pos & blocksize_mask)
+		return -EINVAL;
+
+	size = i_size_read(inode);
+	if (pos + nbytes > size) {
+		nbytes = size - pos;
+		iocb->ki_left = nbytes;
+	}
+
+	/*
+	 * check first non-zero iov alignment, the remaining
+	 * iov alignment is checked inside bio loop below.
+	 */
+	do {
+		addr = (unsigned long) iov[seg].iov_base;
+		count = min(iov[seg].iov_len, nbytes);
+		if (addr & blocksize_mask || count & blocksize_mask)
+			return -EINVAL;
+	} while (!count && ++seg < nr_segs);
+	atomic_set(bio_count, 1);
+
+	while (nbytes) {
+		/* roughly estimate number of bio vec needed */
+		nvec = (nbytes + PAGE_SIZE - 1) / PAGE_SIZE;
+		nvec = max(nvec, nr_segs - seg);
+		nvec = min(nvec, (unsigned long) BIO_MAX_PAGES);
+
+		/* bio_alloc should not fail with GFP_KERNEL flag */
+		bio = bio_alloc(GFP_KERNEL, nvec);
+		bio->bi_bdev = I_BDEV(inode);
+		bio->bi_end_io = blk_end_aio;
+		bio->bi_private = iocb;
+		bio->bi_sector = pos >> blkbits;
+same_bio:
+		cur_off = addr & ~PAGE_MASK;
+		cur_len = PAGE_SIZE - cur_off;
+		if (count < cur_len)
+			cur_len = count;
+
+		page = blk_get_page(addr, count, rw, &pvec);
+		if (unlikely(IS_ERR(page)))
+			goto backout;
+
+		if (bio_add_page(bio, page, cur_len, cur_off)) {
+			pos += cur_len;
+			addr += cur_len;
+			count -= cur_len;
+			nbytes -= cur_len;
+
+			if (count)
+				goto same_bio;
+			while (++seg < nr_segs) {
+				addr = (unsigned long) iov[seg].iov_base;
+				count = iov[seg].iov_len;
+				if (!count)
+					continue;
+				if (unlikely(addr & blocksize_mask ||
+					     count & blocksize_mask)) {
+					page = ERR_PTR(-EINVAL);
+					goto backout;
+				}
+				count = min(count, nbytes);
+				goto same_bio;
+			}
+		}
+
+		/* bio is ready, submit it */
+		if (rw == READ)
+			bio_set_pages_dirty(bio);
+		atomic_inc(bio_count);
+		submit_bio(rw, bio);
+	}
+
+completion:
+	iocb->ki_left -= nbytes;
+	nbytes = iocb->ki_left;
+	iocb->ki_pos += nbytes;
+
+	blk_run_address_space(inode->i_mapping);
+	if (atomic_dec_and_test(bio_count))
+		aio_complete(iocb, nbytes, 0);
+
+	return -EIOCBQUEUED;
+
+backout:
+	/*
+	 * back out nbytes count constructed so far for this bio,
+	 * we will throw away current bio.
+	 */
+	nbytes += bio->bi_size;
+	bio_release_pages(bio);
+	bio_put(bio);
+
+	/*
+	 * if no bio was submmitted, return the error code.
+	 * otherwise, proceed with pending I/O completion.
+	 */
+	if (atomic_read(bio_count) == 1)
+		return PTR_ERR(page);
+	goto completion;
 }
 
 static int blkdev_writepage(struct page *page, struct writeback_control *wbc)
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 098790e..472e33e 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -4876,7 +4876,7 @@
 	} else {
 		/* Add file to outstanding requests */
 		/* BB change to kmem cache alloc */	
-		dnotify_req = (struct dir_notify_req *) kmalloc(
+		dnotify_req = kmalloc(
 						sizeof(struct dir_notify_req),
 						 GFP_KERNEL);
 		if(dnotify_req) {
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 137d76c..c692487 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -24,6 +24,7 @@
 #include <linux/kobject.h>
 #include <linux/namei.h>
 #include <linux/debugfs.h>
+#include <linux/fsnotify.h>
 
 #define DEBUGFS_MAGIC	0x64626720
 
@@ -54,7 +55,8 @@
 			inode->i_op = &simple_dir_inode_operations;
 			inode->i_fop = &simple_dir_operations;
 
-			/* directory inodes start off with i_nlink == 2 (for "." entry) */
+			/* directory inodes start off with i_nlink == 2
+			 * (for "." entry) */
 			inc_nlink(inode);
 			break;
 		}
@@ -87,15 +89,22 @@
 
 	mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
 	res = debugfs_mknod(dir, dentry, mode, 0);
-	if (!res)
+	if (!res) {
 		inc_nlink(dir);
+		fsnotify_mkdir(dir, dentry);
+	}
 	return res;
 }
 
 static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode)
 {
+	int res;
+
 	mode = (mode & S_IALLUGO) | S_IFREG;
-	return debugfs_mknod(dir, dentry, mode, 0);
+	res = debugfs_mknod(dir, dentry, mode, 0);
+	if (!res)
+		fsnotify_create(dir, dentry);
+	return res;
 }
 
 static inline int debugfs_positive(struct dentry *dentry)
@@ -135,7 +144,7 @@
 	 * block. A pointer to that is in the struct vfsmount that we
 	 * have around.
 	 */
-	if (!parent ) {
+	if (!parent) {
 		if (debugfs_mount && debugfs_mount->mnt_sb) {
 			parent = debugfs_mount->mnt_sb->s_root;
 		}
@@ -153,6 +162,7 @@
 			error = debugfs_mkdir(parent->d_inode, *dentry, mode);
 		else 
 			error = debugfs_create(parent->d_inode, *dentry, mode);
+		dput(*dentry);
 	} else
 		error = PTR_ERR(*dentry);
 	mutex_unlock(&parent->d_inode->i_mutex);
@@ -197,13 +207,15 @@
 
 	pr_debug("debugfs: creating file '%s'\n",name);
 
-	error = simple_pin_fs(&debug_fs_type, &debugfs_mount, &debugfs_mount_count);
+	error = simple_pin_fs(&debug_fs_type, &debugfs_mount,
+			      &debugfs_mount_count);
 	if (error)
 		goto exit;
 
 	error = debugfs_create_by_name(name, mode, parent, &dentry);
 	if (error) {
 		dentry = NULL;
+		simple_release_fs(&debugfs_mount, &debugfs_mount_count);
 		goto exit;
 	}
 
@@ -262,6 +274,7 @@
 void debugfs_remove(struct dentry *dentry)
 {
 	struct dentry *parent;
+	int ret = 0;
 	
 	if (!dentry)
 		return;
@@ -273,11 +286,19 @@
 	mutex_lock(&parent->d_inode->i_mutex);
 	if (debugfs_positive(dentry)) {
 		if (dentry->d_inode) {
-			if (S_ISDIR(dentry->d_inode->i_mode))
-				simple_rmdir(parent->d_inode, dentry);
-			else
+			dget(dentry);
+			if (S_ISDIR(dentry->d_inode->i_mode)) {
+				ret = simple_rmdir(parent->d_inode, dentry);
+				if (ret)
+					printk(KERN_ERR
+						"DebugFS rmdir on %s failed : "
+						"directory not empty.\n",
+						dentry->d_name.name);
+			} else
 				simple_unlink(parent->d_inode, dentry);
-		dput(dentry);
+			if (!ret)
+				d_delete(dentry);
+			dput(dentry);
 		}
 	}
 	mutex_unlock(&parent->d_inode->i_mutex);
diff --git a/fs/inode.c b/fs/inode.c
index d00de18..bf21dc6 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1144,7 +1144,6 @@
 		res = inode->i_mapping->a_ops->bmap(inode->i_mapping, block);
 	return res;
 }
-
 EXPORT_SYMBOL(bmap);
 
 /**
@@ -1163,27 +1162,43 @@
 
 	if (IS_RDONLY(inode))
 		return;
-
-	if ((inode->i_flags & S_NOATIME) ||
-	    (inode->i_sb->s_flags & MS_NOATIME) ||
-	    ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode)))
+	if (inode->i_flags & S_NOATIME)
+		return;
+	if (inode->i_sb->s_flags & MS_NOATIME)
+		return;
+	if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode))
 		return;
 
 	/*
 	 * We may have a NULL vfsmount when coming from NFSD
 	 */
-	if (mnt &&
-	    ((mnt->mnt_flags & MNT_NOATIME) ||
-	     ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))))
-		return;
+	if (mnt) {
+		if (mnt->mnt_flags & MNT_NOATIME)
+			return;
+		if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))
+			return;
+
+		if (mnt->mnt_flags & MNT_RELATIME) {
+			/*
+			 * With relative atime, only update atime if the
+			 * previous atime is earlier than either the ctime or
+			 * mtime.
+			 */
+			if (timespec_compare(&inode->i_mtime,
+						&inode->i_atime) < 0 &&
+			    timespec_compare(&inode->i_ctime,
+						&inode->i_atime) < 0)
+				return;
+		}
+	}
 
 	now = current_fs_time(inode->i_sb);
-	if (!timespec_equal(&inode->i_atime, &now)) {
-		inode->i_atime = now;
-		mark_inode_dirty_sync(inode);
-	}
-}
+	if (timespec_equal(&inode->i_atime, &now))
+		return;
 
+	inode->i_atime = now;
+	mark_inode_dirty_sync(inode);
+}
 EXPORT_SYMBOL(touch_atime);
 
 /**
diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
index 7b40c69..43baa1a 100644
--- a/fs/jffs/inode-v23.c
+++ b/fs/jffs/inode-v23.c
@@ -818,7 +818,7 @@
 
 	D1({
 	        int len = dentry->d_name.len;
-		char *_name = (char *) kmalloc(len + 1, GFP_KERNEL);
+		char *_name = kmalloc(len + 1, GFP_KERNEL);
 		memcpy(_name, dentry->d_name.name, len);
 		_name[len] = '\0';
 		printk("***jffs_mkdir(): dir = 0x%p, name = \"%s\", "
@@ -964,7 +964,7 @@
 	D1({
 		int len = dentry->d_name.len;
 		const char *name = dentry->d_name.name;
-		char *_name = (char *) kmalloc(len + 1, GFP_KERNEL);
+		char *_name = kmalloc(len + 1, GFP_KERNEL);
 		memcpy(_name, name, len);
 		_name[len] = '\0';
 		printk("***jffs_remove(): file = \"%s\", ino = %ld\n", _name, dentry->d_inode->i_ino);
diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c
index d0e783f..6dd1891 100644
--- a/fs/jffs/intrep.c
+++ b/fs/jffs/intrep.c
@@ -436,7 +436,7 @@
 	int i, length;
 
 	/* Allocate read buffer */
-	read_buf = (__u8 *) kmalloc (sizeof(__u8) * 4096, GFP_KERNEL);
+	read_buf = kmalloc(sizeof(__u8) * 4096, GFP_KERNEL);
 	if (!read_buf) {
 		printk(KERN_NOTICE "kmalloc failed in jffs_checksum_flash()\n");
 		return -ENOMEM;
@@ -744,11 +744,11 @@
 
 
 	/* Allocate read buffers */
-	read_buf1 = (__u8 *) kmalloc (sizeof(__u8) * READ_AHEAD_BYTES, GFP_KERNEL);
+	read_buf1 = kmalloc(sizeof(__u8) * READ_AHEAD_BYTES, GFP_KERNEL);
 	if (!read_buf1)
 		return -ENOMEM;
 
-	read_buf2 = (__u8 *) kmalloc (sizeof(__u8) * READ_AHEAD_BYTES, GFP_KERNEL);
+	read_buf2 = kmalloc(sizeof(__u8) * READ_AHEAD_BYTES, GFP_KERNEL);
 	if (!read_buf2) {
 		kfree(read_buf1);
 		return -ENOMEM;
@@ -876,7 +876,7 @@
 	}
 
 	/* Allocate read buffer */
-	read_buf = (__u8 *) kmalloc (sizeof(__u8) * 4096, GFP_KERNEL);
+	read_buf = kmalloc(sizeof(__u8) * 4096, GFP_KERNEL);
 	if (!read_buf) {
 		flash_safe_release(fmc->mtd);
 		return -ENOMEM;
@@ -1463,7 +1463,7 @@
 			kfree(f->name);
 			DJM(no_name--);
 		}
-		if (!(f->name = (char *) kmalloc(raw_inode->nsize + 1,
+		if (!(f->name = kmalloc(raw_inode->nsize + 1,
 						 GFP_KERNEL))) {
 			return -ENOMEM;
 		}
@@ -1737,7 +1737,7 @@
 		printk("jffs_find_child(): Found \"%s\".\n", f->name);
 	}
 	else {
-		char *copy = (char *) kmalloc(len + 1, GFP_KERNEL);
+		char *copy = kmalloc(len + 1, GFP_KERNEL);
 		if (copy) {
 			memcpy(copy, name, len);
 			copy[len] = '\0';
@@ -2627,7 +2627,7 @@
 		return;
 	}
 
-	if (!(space = (char *) kmalloc(indent + 1, GFP_KERNEL))) {
+	if (!(space = kmalloc(indent + 1, GFP_KERNEL))) {
 		printk("jffs_print_tree(): Out of memory!\n");
 		return;
 	}
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index 47bc0b5..6d62f32 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -3777,12 +3777,12 @@
 	struct component_name lkey;
 	struct component_name rkey;
 
-	lkey.name = (wchar_t *) kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
+	lkey.name = kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
 					GFP_KERNEL);
 	if (lkey.name == NULL)
 		return -ENOMEM;
 
-	rkey.name = (wchar_t *) kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
+	rkey.name = kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
 					GFP_KERNEL);
 	if (rkey.name == NULL) {
 		kfree(lkey.name);
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index ee9b473..53f63b4 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -120,7 +120,7 @@
 	 * allocate/initialize the in-memory inode map control structure
 	 */
 	/* allocate the in-memory inode map control structure. */
-	imap = (struct inomap *) kmalloc(sizeof(struct inomap), GFP_KERNEL);
+	imap = kmalloc(sizeof(struct inomap), GFP_KERNEL);
 	if (imap == NULL) {
 		jfs_err("diMount: kmalloc returned NULL!");
 		return -ENOMEM;
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index 92681c9..0627077 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -36,7 +36,7 @@
 	struct nlm_host *	b_host;
 	struct file_lock *	b_lock;		/* local file lock */
 	unsigned short		b_reclaim;	/* got to reclaim lock */
-	u32			b_status;	/* grant callback status */
+	__be32			b_status;	/* grant callback status */
 };
 
 static LIST_HEAD(nlm_blocked);
@@ -53,7 +53,7 @@
 		block->b_host = host;
 		block->b_lock = fl;
 		init_waitqueue_head(&block->b_wait);
-		block->b_status = NLM_LCK_BLOCKED;
+		block->b_status = nlm_lck_blocked;
 		list_add(&block->b_list, &nlm_blocked);
 	}
 	return block;
@@ -89,7 +89,7 @@
 	 * nlmclnt_lock for an explanation.
 	 */
 	ret = wait_event_interruptible_timeout(block->b_wait,
-			block->b_status != NLM_LCK_BLOCKED,
+			block->b_status != nlm_lck_blocked,
 			timeout);
 	if (ret < 0)
 		return -ERESTARTSYS;
@@ -131,7 +131,7 @@
 		/* Alright, we found a lock. Set the return status
 		 * and wake up the caller
 		 */
-		block->b_status = NLM_LCK_GRANTED;
+		block->b_status = nlm_granted;
 		wake_up(&block->b_wait);
 		res = nlm_granted;
 	}
@@ -211,7 +211,7 @@
 	/* Now, wake up all processes that sleep on a blocked lock */
 	list_for_each_entry(block, &nlm_blocked, b_list) {
 		if (block->b_host == host) {
-			block->b_status = NLM_LCK_DENIED_GRACE_PERIOD;
+			block->b_status = nlm_lck_denied_grace_period;
 			wake_up(&block->b_wait);
 		}
 	}
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 80a1a6d..0b4acc1 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -27,7 +27,7 @@
 static int	nlmclnt_test(struct nlm_rqst *, struct file_lock *);
 static int	nlmclnt_lock(struct nlm_rqst *, struct file_lock *);
 static int	nlmclnt_unlock(struct nlm_rqst *, struct file_lock *);
-static int	nlm_stat_to_errno(u32 stat);
+static int	nlm_stat_to_errno(__be32 stat);
 static void	nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host);
 static int	nlmclnt_cancel(struct nlm_host *, int , struct file_lock *);
 
@@ -325,7 +325,7 @@
 			}
 			break;
 		} else
-		if (resp->status == NLM_LCK_DENIED_GRACE_PERIOD) {
+		if (resp->status == nlm_lck_denied_grace_period) {
 			dprintk("lockd: server in grace period\n");
 			if (argp->reclaim) {
 				printk(KERN_WARNING
@@ -411,10 +411,10 @@
 		goto out;
 
 	switch (req->a_res.status) {
-		case NLM_LCK_GRANTED:
+		case nlm_granted:
 			fl->fl_type = F_UNLCK;
 			break;
-		case NLM_LCK_DENIED:
+		case nlm_lck_denied:
 			/*
 			 * Report the conflicting lock back to the application.
 			 */
@@ -524,9 +524,9 @@
 		if (!req->a_args.block)
 			break;
 		/* Did a reclaimer thread notify us of a server reboot? */
-		if (resp->status ==  NLM_LCK_DENIED_GRACE_PERIOD)
+		if (resp->status ==  nlm_lck_denied_grace_period)
 			continue;
-		if (resp->status != NLM_LCK_BLOCKED)
+		if (resp->status != nlm_lck_blocked)
 			break;
 		/* Wait on an NLM blocking lock */
 		status = nlmclnt_block(block, req, NLMCLNT_POLL_TIMEOUT);
@@ -535,11 +535,11 @@
 		 */
 		if (status < 0)
 			goto out_unblock;
-		if (resp->status != NLM_LCK_BLOCKED)
+		if (resp->status != nlm_lck_blocked)
 			break;
 	}
 
-	if (resp->status == NLM_LCK_GRANTED) {
+	if (resp->status == nlm_granted) {
 		down_read(&host->h_rwsem);
 		/* Check whether or not the server has rebooted */
 		if (fl->fl_u.nfs_fl.state != host->h_state) {
@@ -556,7 +556,7 @@
 out_unblock:
 	nlmclnt_finish_block(block);
 	/* Cancel the blocked request if it is still pending */
-	if (resp->status == NLM_LCK_BLOCKED)
+	if (resp->status == nlm_lck_blocked)
 		nlmclnt_cancel(host, req->a_args.block, fl);
 out:
 	nlm_release_call(req);
@@ -585,12 +585,12 @@
 	req->a_args.reclaim = 1;
 
 	if ((status = nlmclnt_call(req, NLMPROC_LOCK)) >= 0
-	 && req->a_res.status == NLM_LCK_GRANTED)
+	 && req->a_res.status == nlm_granted)
 		return 0;
 
 	printk(KERN_WARNING "lockd: failed to reclaim lock for pid %d "
 				"(errno %d, status %d)\n", fl->fl_pid,
-				status, req->a_res.status);
+				status, ntohl(req->a_res.status));
 
 	/*
 	 * FIXME: This is a serious failure. We can
@@ -637,10 +637,10 @@
 	if (status < 0)
 		goto out;
 
-	if (resp->status == NLM_LCK_GRANTED)
+	if (resp->status == nlm_granted)
 		goto out;
 
-	if (resp->status != NLM_LCK_DENIED_NOLOCKS)
+	if (resp->status != nlm_lck_denied_nolocks)
 		printk("lockd: unexpected unlock status: %d\n", resp->status);
 	/* What to do now? I'm out of my depth... */
 	status = -ENOLCK;
@@ -652,7 +652,7 @@
 static void nlmclnt_unlock_callback(struct rpc_task *task, void *data)
 {
 	struct nlm_rqst	*req = data;
-	int		status = req->a_res.status;
+	u32 status = ntohl(req->a_res.status);
 
 	if (RPC_ASSASSINATED(task))
 		goto die;
@@ -720,6 +720,7 @@
 static void nlmclnt_cancel_callback(struct rpc_task *task, void *data)
 {
 	struct nlm_rqst	*req = data;
+	u32 status = ntohl(req->a_res.status);
 
 	if (RPC_ASSASSINATED(task))
 		goto die;
@@ -731,9 +732,9 @@
 	}
 
 	dprintk("lockd: cancel status %u (task %u)\n",
-			req->a_res.status, task->tk_pid);
+			status, task->tk_pid);
 
-	switch (req->a_res.status) {
+	switch (status) {
 	case NLM_LCK_GRANTED:
 	case NLM_LCK_DENIED_GRACE_PERIOD:
 	case NLM_LCK_DENIED:
@@ -744,7 +745,7 @@
 		goto retry_cancel;
 	default:
 		printk(KERN_NOTICE "lockd: weird return %d for CANCEL call\n",
-			req->a_res.status);
+			status);
 	}
 
 die:
@@ -768,9 +769,9 @@
  * Convert an NLM status code to a generic kernel errno
  */
 static int
-nlm_stat_to_errno(u32 status)
+nlm_stat_to_errno(__be32 status)
 {
-	switch(status) {
+	switch(ntohl(status)) {
 	case NLM_LCK_GRANTED:
 		return 0;
 	case NLM_LCK_DENIED:
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 5c054b2..c7db0a5 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -645,7 +645,7 @@
  * block.
  */
 void
-nlmsvc_grant_reply(struct nlm_cookie *cookie, u32 status)
+nlmsvc_grant_reply(struct nlm_cookie *cookie, __be32 status)
 {
 	struct nlm_block	*block;
 
@@ -655,7 +655,7 @@
 		return;
 
 	if (block) {
-		if (status == NLM_LCK_DENIED_GRACE_PERIOD) {
+		if (status == nlm_lck_denied_grace_period) {
 			/* Try again in a couple of seconds */
 			nlmsvc_insert_block(block, 10 * HZ);
 		} else {
diff --git a/fs/lockd/svcshare.c b/fs/lockd/svcshare.c
index 6220dc2a..068886d 100644
--- a/fs/lockd/svcshare.c
+++ b/fs/lockd/svcshare.c
@@ -39,7 +39,7 @@
 			return nlm_lck_denied;
 	}
 
-	share = (struct nlm_share *) kmalloc(sizeof(*share) + oh->len,
+	share = kmalloc(sizeof(*share) + oh->len,
 						GFP_KERNEL);
 	if (share == NULL)
 		return nlm_lck_denied_nolocks;
diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index b7c9492..34dae5d 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -361,7 +361,7 @@
 {
 	if (!(p = nlm_decode_cookie(p, &resp->cookie)))
 		return 0;
-	resp->status = ntohl(*p++);
+	resp->status = *p++;
 	return xdr_argsize_check(rqstp, p);
 }
 
@@ -407,8 +407,8 @@
 {
 	if (!(p = nlm_decode_cookie(p, &resp->cookie)))
 		return -EIO;
-	resp->status = ntohl(*p++);
-	if (resp->status == NLM_LCK_DENIED) {
+	resp->status = *p++;
+	if (resp->status == nlm_lck_denied) {
 		struct file_lock	*fl = &resp->lock.fl;
 		u32			excl;
 		s32			start, len, end;
@@ -506,7 +506,7 @@
 {
 	if (!(p = nlm_decode_cookie(p, &resp->cookie)))
 		return -EIO;
-	resp->status = ntohl(*p++);
+	resp->status = *p++;
 	return 0;
 }
 
diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index f4c0b2b..a782405 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -367,7 +367,7 @@
 {
 	if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
 		return 0;
-	resp->status = ntohl(*p++);
+	resp->status = *p++;
 	return xdr_argsize_check(rqstp, p);
 }
 
@@ -413,8 +413,8 @@
 {
 	if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
 		return -EIO;
-	resp->status = ntohl(*p++);
-	if (resp->status == NLM_LCK_DENIED) {
+	resp->status = *p++;
+	if (resp->status == nlm_lck_denied) {
 		struct file_lock	*fl = &resp->lock.fl;
 		u32			excl;
 		s64			start, end, len;
@@ -512,7 +512,7 @@
 {
 	if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
 		return -EIO;
-	resp->status = ntohl(*p++);
+	resp->status = *p++;
 	return 0;
 }
 
diff --git a/fs/namespace.c b/fs/namespace.c
index fde8553..5ef336c 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -368,6 +368,7 @@
 		{ MNT_NOEXEC, ",noexec" },
 		{ MNT_NOATIME, ",noatime" },
 		{ MNT_NODIRATIME, ",nodiratime" },
+		{ MNT_RELATIME, ",relatime" },
 		{ 0, NULL }
 	};
 	struct proc_fs_info *fs_infop;
@@ -1405,9 +1406,11 @@
 		mnt_flags |= MNT_NOATIME;
 	if (flags & MS_NODIRATIME)
 		mnt_flags |= MNT_NODIRATIME;
+	if (flags & MS_RELATIME)
+		mnt_flags |= MNT_RELATIME;
 
 	flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE |
-		   MS_NOATIME | MS_NODIRATIME);
+		   MS_NOATIME | MS_NODIRATIME | MS_RELATIME);
 
 	/* ... and get the mountpoint */
 	retval = path_lookup(dir_name, LOOKUP_FOLLOW, &nd);
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index 47462ac..67a90bf 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -327,11 +327,12 @@
 	char *optarg;
 	unsigned long optint;
 	int version = 0;
+	int ret;
 
 	data->flags = 0;
 	data->int_flags = 0;
 	data->mounted_uid = 0;
-	data->wdog_pid = -1;
+	data->wdog_pid = NULL;
 	data->ncp_fd = ~0;
 	data->time_out = 10;
 	data->retry_count = 20;
@@ -343,8 +344,9 @@
 	data->mounted_vol[0] = 0;
 	
 	while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
-		if (optval < 0)
-			return optval;
+		ret = optval;
+		if (ret < 0)
+			goto err;
 		switch (optval) {
 			case 'u':
 				data->uid = optint;
@@ -371,7 +373,7 @@
 				data->flags = optint;
 				break;
 			case 'w':
-				data->wdog_pid = optint;
+				data->wdog_pid = find_get_pid(optint);
 				break;
 			case 'n':
 				data->ncp_fd = optint;
@@ -380,18 +382,21 @@
 				data->info_fd = optint;
 				break;
 			case 'v':
-				if (optint < NCP_MOUNT_VERSION_V4) {
-					return -ECHRNG;
-				}
-				if (optint > NCP_MOUNT_VERSION_V5) {
-					return -ECHRNG;
-				}
+				ret = -ECHRNG;
+				if (optint < NCP_MOUNT_VERSION_V4)
+					goto err;
+				if (optint > NCP_MOUNT_VERSION_V5)
+					goto err;
 				version = optint;
 				break;
 			
 		}
 	}
 	return 0;
+err:
+	put_pid(data->wdog_pid);
+	data->wdog_pid = NULL;
+	return ret;
 }
 
 static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
@@ -409,6 +414,7 @@
 #endif
 	struct ncp_entry_info finfo;
 
+	data.wdog_pid = NULL;
 	server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
 	if (!server)
 		return -ENOMEM;
@@ -425,7 +431,7 @@
 				data.flags = md->flags;
 				data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
 				data.mounted_uid = md->mounted_uid;
-				data.wdog_pid = md->wdog_pid;
+				data.wdog_pid = find_get_pid(md->wdog_pid);
 				data.ncp_fd = md->ncp_fd;
 				data.time_out = md->time_out;
 				data.retry_count = md->retry_count;
@@ -445,7 +451,7 @@
 				data.flags = md->flags;
 				data.int_flags = 0;
 				data.mounted_uid = md->mounted_uid;
-				data.wdog_pid = md->wdog_pid;
+				data.wdog_pid = find_get_pid(md->wdog_pid);
 				data.ncp_fd = md->ncp_fd;
 				data.time_out = md->time_out;
 				data.retry_count = md->retry_count;
@@ -679,6 +685,7 @@
 	 */
 	fput(ncp_filp);
 out:
+	put_pid(data.wdog_pid);
 	sb->s_fs_info = NULL;
 	kfree(server);
 	return error;
@@ -711,7 +718,8 @@
 	if (server->info_filp)
 		fput(server->info_filp);
 	fput(server->ncp_filp);
-	kill_proc(server->m.wdog_pid, SIGTERM, 1);
+	kill_pid(server->m.wdog_pid, SIGTERM, 1);
+	put_pid(server->m.wdog_pid);
 
 	kfree(server->priv.data);
 	kfree(server->auth.object_name);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index ee458ae..b3fd29b 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1877,7 +1877,7 @@
 	struct nfs_server *server = NFS_SERVER(dir->d_inode);
 	struct unlink_desc *up;
 
-	up = (struct unlink_desc *) kmalloc(sizeof(*up), GFP_KERNEL);
+	up = kmalloc(sizeof(*up), GFP_KERNEL);
 	if (!up)
 		return -ENOMEM;
 	
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index f37df46..248dd92 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -787,15 +787,20 @@
 	key.ex_dentry = dentry;
 
 	exp = svc_export_lookup(&key);
-	if (exp != NULL) 
-		switch (cache_check(&svc_export_cache, &exp->h, reqp)) {
+	if (exp != NULL)  {
+		int err;
+
+		err = cache_check(&svc_export_cache, &exp->h, reqp);
+		switch (err) {
 		case 0: break;
 		case -EAGAIN:
-			exp = ERR_PTR(-EAGAIN);
+		case -ETIMEDOUT:
+			exp = ERR_PTR(err);
 			break;
 		default:
 			exp = NULL;
 		}
+	}
 
 	return exp;
 }
@@ -950,6 +955,8 @@
 
 	exp = exp_get_by_name(clp, nd.mnt, nd.dentry, NULL);
 
+	memset(&new, 0, sizeof(new));
+
 	/* must make sure there won't be an ex_fsid clash */
 	if ((nxp->ex_flags & NFSEXP_FSID) &&
 	    (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) &&
@@ -980,6 +987,9 @@
 
 	new.h.expiry_time = NEVER;
 	new.h.flags = 0;
+	new.ex_path = kstrdup(nxp->ex_path, GFP_KERNEL);
+	if (!new.ex_path)
+		goto finish;
 	new.ex_client = clp;
 	new.ex_mnt = nd.mnt;
 	new.ex_dentry = nd.dentry;
@@ -1000,10 +1010,11 @@
 		/* failed to create at least one index */
 		exp_do_unexport(exp);
 		cache_flush();
-		err = -ENOMEM;
-	}
-
+	} else
+		err = 0;
 finish:
+	if (new.ex_path)
+		kfree(new.ex_path);
 	if (exp)
 		exp_put(exp);
 	if (fsid_key && !IS_ERR(fsid_key))
@@ -1104,6 +1115,10 @@
 		 path, nd.dentry, clp->name,
 		 inode->i_sb->s_id, inode->i_ino);
 	exp = exp_parent(clp, nd.mnt, nd.dentry, NULL);
+	if (IS_ERR(exp)) {
+		err = PTR_ERR(exp);
+		goto out;
+	}
 	if (!exp) {
 		dprintk("nfsd: exp_rootfh export not found.\n");
 		goto out;
@@ -1159,12 +1174,10 @@
 	mk_fsid_v1(fsidv, 0);
 
 	exp = exp_find(clp, 1, fsidv, creq);
-	if (IS_ERR(exp) && PTR_ERR(exp) == -EAGAIN)
-		return nfserr_dropit;
+	if (IS_ERR(exp))
+		return nfserrno(PTR_ERR(exp));
 	if (exp == NULL)
 		return nfserr_perm;
-	else if (IS_ERR(exp))
-		return nfserrno(PTR_ERR(exp));
 	rv = fh_compose(fhp, exp, exp->ex_dentry, NULL);
 	exp_put(exp);
 	return rv;
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 11fdaf7..221acd1 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -22,7 +22,7 @@
 /*
  * Note: we hold the dentry use count while the file is open.
  */
-static u32
+static __be32
 nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp)
 {
 	__be32		nfserr;
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 50bc942..8522729 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -33,13 +33,6 @@
  *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Note: some routines in this file are just trivial wrappers
- * (e.g. nfsd4_lookup()) defined solely for the sake of consistent
- * naming.  Since all such routines have been declared "inline",
- * there shouldn't be any associated overhead.  At some point in
- * the future, I might inline these "by hand" to clean up a
- * little.
  */
 
 #include <linux/param.h>
@@ -161,8 +154,9 @@
 }
 
 
-static inline __be32
-nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open, struct nfs4_stateowner **replay_owner)
+static __be32
+nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	   struct nfsd4_open *open)
 {
 	__be32 status;
 	dprintk("NFSD: nfsd4_open filename %.*s op_stateowner %p\n",
@@ -179,11 +173,11 @@
 	status = nfsd4_process_open1(open);
 	if (status == nfserr_replay_me) {
 		struct nfs4_replay *rp = &open->op_stateowner->so_replay;
-		fh_put(current_fh);
-		current_fh->fh_handle.fh_size = rp->rp_openfh_len;
-		memcpy(&current_fh->fh_handle.fh_base, rp->rp_openfh,
+		fh_put(&cstate->current_fh);
+		cstate->current_fh.fh_handle.fh_size = rp->rp_openfh_len;
+		memcpy(&cstate->current_fh.fh_handle.fh_base, rp->rp_openfh,
 				rp->rp_openfh_len);
-		status = fh_verify(rqstp, current_fh, 0, MAY_NOP);
+		status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
 		if (status)
 			dprintk("nfsd4_open: replay failed"
 				" restoring previous filehandle\n");
@@ -215,7 +209,8 @@
 			 * (3) set open->op_truncate if the file is to be
 			 * truncated after opening, (4) do permission checking.
 			 */
-			status = do_open_lookup(rqstp, current_fh, open);
+			status = do_open_lookup(rqstp, &cstate->current_fh,
+						open);
 			if (status)
 				goto out;
 			break;
@@ -227,7 +222,8 @@
 			 * open->op_truncate if the file is to be truncated
 			 * after opening, (3) do permission checking.
 			*/
-			status = do_open_fhandle(rqstp, current_fh, open);
+			status = do_open_fhandle(rqstp, &cstate->current_fh,
+						 open);
 			if (status)
 				goto out;
 			break;
@@ -248,11 +244,11 @@
 	 * successful, it (1) truncates the file if open->op_truncate was
 	 * set, (2) sets open->op_stateid, (3) sets open->op_delegation.
 	 */
-	status = nfsd4_process_open2(rqstp, current_fh, open);
+	status = nfsd4_process_open2(rqstp, &cstate->current_fh, open);
 out:
 	if (open->op_stateowner) {
 		nfs4_get_stateowner(open->op_stateowner);
-		*replay_owner = open->op_stateowner;
+		cstate->replay_owner = open->op_stateowner;
 	}
 	nfs4_unlock_state();
 	return status;
@@ -261,71 +257,80 @@
 /*
  * filehandle-manipulating ops.
  */
-static inline __be32
-nfsd4_getfh(struct svc_fh *current_fh, struct svc_fh **getfh)
+static __be32
+nfsd4_getfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	    struct svc_fh **getfh)
 {
-	if (!current_fh->fh_dentry)
+	if (!cstate->current_fh.fh_dentry)
 		return nfserr_nofilehandle;
 
-	*getfh = current_fh;
+	*getfh = &cstate->current_fh;
 	return nfs_ok;
 }
 
-static inline __be32
-nfsd4_putfh(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_putfh *putfh)
+static __be32
+nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	    struct nfsd4_putfh *putfh)
 {
-	fh_put(current_fh);
-	current_fh->fh_handle.fh_size = putfh->pf_fhlen;
-	memcpy(&current_fh->fh_handle.fh_base, putfh->pf_fhval, putfh->pf_fhlen);
-	return fh_verify(rqstp, current_fh, 0, MAY_NOP);
+	fh_put(&cstate->current_fh);
+	cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen;
+	memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval,
+	       putfh->pf_fhlen);
+	return fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
 }
 
-static inline __be32
-nfsd4_putrootfh(struct svc_rqst *rqstp, struct svc_fh *current_fh)
+static __be32
+nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+		void *arg)
 {
 	__be32 status;
 
-	fh_put(current_fh);
-	status = exp_pseudoroot(rqstp->rq_client, current_fh,
+	fh_put(&cstate->current_fh);
+	status = exp_pseudoroot(rqstp->rq_client, &cstate->current_fh,
 			      &rqstp->rq_chandle);
 	return status;
 }
 
-static inline __be32
-nfsd4_restorefh(struct svc_fh *current_fh, struct svc_fh *save_fh)
+static __be32
+nfsd4_restorefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+		void *arg)
 {
-	if (!save_fh->fh_dentry)
+	if (!cstate->save_fh.fh_dentry)
 		return nfserr_restorefh;
 
-	fh_dup2(current_fh, save_fh);
+	fh_dup2(&cstate->current_fh, &cstate->save_fh);
 	return nfs_ok;
 }
 
-static inline __be32
-nfsd4_savefh(struct svc_fh *current_fh, struct svc_fh *save_fh)
+static __be32
+nfsd4_savefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	     void *arg)
 {
-	if (!current_fh->fh_dentry)
+	if (!cstate->current_fh.fh_dentry)
 		return nfserr_nofilehandle;
 
-	fh_dup2(save_fh, current_fh);
+	fh_dup2(&cstate->save_fh, &cstate->current_fh);
 	return nfs_ok;
 }
 
 /*
  * misc nfsv4 ops
  */
-static inline __be32
-nfsd4_access(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_access *access)
+static __be32
+nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	     struct nfsd4_access *access)
 {
 	if (access->ac_req_access & ~NFS3_ACCESS_FULL)
 		return nfserr_inval;
 
 	access->ac_resp_access = access->ac_req_access;
-	return nfsd_access(rqstp, current_fh, &access->ac_resp_access, &access->ac_supported);
+	return nfsd_access(rqstp, &cstate->current_fh, &access->ac_resp_access,
+			   &access->ac_supported);
 }
 
-static inline __be32
-nfsd4_commit(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_commit *commit)
+static __be32
+nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	     struct nfsd4_commit *commit)
 {
 	__be32 status;
 
@@ -333,14 +338,16 @@
 	*p++ = nfssvc_boot.tv_sec;
 	*p++ = nfssvc_boot.tv_usec;
 
-	status = nfsd_commit(rqstp, current_fh, commit->co_offset, commit->co_count);
+	status = nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset,
+			     commit->co_count);
 	if (status == nfserr_symlink)
 		status = nfserr_inval;
 	return status;
 }
 
 static __be32
-nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_create *create)
+nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	     struct nfsd4_create *create)
 {
 	struct svc_fh resfh;
 	__be32 status;
@@ -348,7 +355,7 @@
 
 	fh_init(&resfh, NFS4_FHSIZE);
 
-	status = fh_verify(rqstp, current_fh, S_IFDIR, MAY_CREATE);
+	status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR, MAY_CREATE);
 	if (status == nfserr_symlink)
 		status = nfserr_notdir;
 	if (status)
@@ -365,9 +372,10 @@
 		 */
 		create->cr_linkname[create->cr_linklen] = 0;
 
-		status = nfsd_symlink(rqstp, current_fh, create->cr_name,
-				      create->cr_namelen, create->cr_linkname,
-				      create->cr_linklen, &resfh, &create->cr_iattr);
+		status = nfsd_symlink(rqstp, &cstate->current_fh,
+				      create->cr_name, create->cr_namelen,
+				      create->cr_linkname, create->cr_linklen,
+				      &resfh, &create->cr_iattr);
 		break;
 
 	case NF4BLK:
@@ -375,9 +383,9 @@
 		if (MAJOR(rdev) != create->cr_specdata1 ||
 		    MINOR(rdev) != create->cr_specdata2)
 			return nfserr_inval;
-		status = nfsd_create(rqstp, current_fh, create->cr_name,
-				     create->cr_namelen, &create->cr_iattr,
-				     S_IFBLK, rdev, &resfh);
+		status = nfsd_create(rqstp, &cstate->current_fh,
+				     create->cr_name, create->cr_namelen,
+				     &create->cr_iattr, S_IFBLK, rdev, &resfh);
 		break;
 
 	case NF4CHR:
@@ -385,28 +393,28 @@
 		if (MAJOR(rdev) != create->cr_specdata1 ||
 		    MINOR(rdev) != create->cr_specdata2)
 			return nfserr_inval;
-		status = nfsd_create(rqstp, current_fh, create->cr_name,
-				     create->cr_namelen, &create->cr_iattr,
-				     S_IFCHR, rdev, &resfh);
+		status = nfsd_create(rqstp, &cstate->current_fh,
+				     create->cr_name, create->cr_namelen,
+				     &create->cr_iattr,S_IFCHR, rdev, &resfh);
 		break;
 
 	case NF4SOCK:
-		status = nfsd_create(rqstp, current_fh, create->cr_name,
-				     create->cr_namelen, &create->cr_iattr,
-				     S_IFSOCK, 0, &resfh);
+		status = nfsd_create(rqstp, &cstate->current_fh,
+				     create->cr_name, create->cr_namelen,
+				     &create->cr_iattr, S_IFSOCK, 0, &resfh);
 		break;
 
 	case NF4FIFO:
-		status = nfsd_create(rqstp, current_fh, create->cr_name,
-				     create->cr_namelen, &create->cr_iattr,
-				     S_IFIFO, 0, &resfh);
+		status = nfsd_create(rqstp, &cstate->current_fh,
+				     create->cr_name, create->cr_namelen,
+				     &create->cr_iattr, S_IFIFO, 0, &resfh);
 		break;
 
 	case NF4DIR:
 		create->cr_iattr.ia_valid &= ~ATTR_SIZE;
-		status = nfsd_create(rqstp, current_fh, create->cr_name,
-				     create->cr_namelen, &create->cr_iattr,
-				     S_IFDIR, 0, &resfh);
+		status = nfsd_create(rqstp, &cstate->current_fh,
+				     create->cr_name, create->cr_namelen,
+				     &create->cr_iattr, S_IFDIR, 0, &resfh);
 		break;
 
 	default:
@@ -414,21 +422,22 @@
 	}
 
 	if (!status) {
-		fh_unlock(current_fh);
-		set_change_info(&create->cr_cinfo, current_fh);
-		fh_dup2(current_fh, &resfh);
+		fh_unlock(&cstate->current_fh);
+		set_change_info(&create->cr_cinfo, &cstate->current_fh);
+		fh_dup2(&cstate->current_fh, &resfh);
 	}
 
 	fh_put(&resfh);
 	return status;
 }
 
-static inline __be32
-nfsd4_getattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_getattr *getattr)
+static __be32
+nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	      struct nfsd4_getattr *getattr)
 {
 	__be32 status;
 
-	status = fh_verify(rqstp, current_fh, 0, MAY_NOP);
+	status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
 	if (status)
 		return status;
 
@@ -438,26 +447,28 @@
 	getattr->ga_bmval[0] &= NFSD_SUPPORTED_ATTRS_WORD0;
 	getattr->ga_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1;
 
-	getattr->ga_fhp = current_fh;
+	getattr->ga_fhp = &cstate->current_fh;
 	return nfs_ok;
 }
 
-static inline __be32
-nfsd4_link(struct svc_rqst *rqstp, struct svc_fh *current_fh,
-	   struct svc_fh *save_fh, struct nfsd4_link *link)
+static __be32
+nfsd4_link(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	   struct nfsd4_link *link)
 {
 	__be32 status = nfserr_nofilehandle;
 
-	if (!save_fh->fh_dentry)
+	if (!cstate->save_fh.fh_dentry)
 		return status;
-	status = nfsd_link(rqstp, current_fh, link->li_name, link->li_namelen, save_fh);
+	status = nfsd_link(rqstp, &cstate->current_fh,
+			   link->li_name, link->li_namelen, &cstate->save_fh);
 	if (!status)
-		set_change_info(&link->li_cinfo, current_fh);
+		set_change_info(&link->li_cinfo, &cstate->current_fh);
 	return status;
 }
 
 static __be32
-nfsd4_lookupp(struct svc_rqst *rqstp, struct svc_fh *current_fh)
+nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	      void *arg)
 {
 	struct svc_fh tmp_fh;
 	__be32 ret;
@@ -466,22 +477,27 @@
 	if((ret = exp_pseudoroot(rqstp->rq_client, &tmp_fh,
 			      &rqstp->rq_chandle)) != 0)
 		return ret;
-	if (tmp_fh.fh_dentry == current_fh->fh_dentry) {
+	if (tmp_fh.fh_dentry == cstate->current_fh.fh_dentry) {
 		fh_put(&tmp_fh);
 		return nfserr_noent;
 	}
 	fh_put(&tmp_fh);
-	return nfsd_lookup(rqstp, current_fh, "..", 2, current_fh);
+	return nfsd_lookup(rqstp, &cstate->current_fh,
+			   "..", 2, &cstate->current_fh);
 }
 
-static inline __be32
-nfsd4_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lookup *lookup)
+static __be32
+nfsd4_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	     struct nfsd4_lookup *lookup)
 {
-	return nfsd_lookup(rqstp, current_fh, lookup->lo_name, lookup->lo_len, current_fh);
+	return nfsd_lookup(rqstp, &cstate->current_fh,
+			   lookup->lo_name, lookup->lo_len,
+			   &cstate->current_fh);
 }
 
-static inline __be32
-nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read)
+static __be32
+nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	   struct nfsd4_read *read)
 {
 	__be32 status;
 
@@ -493,7 +509,8 @@
 
 	nfs4_lock_state();
 	/* check stateid */
-	if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid,
+	if ((status = nfs4_preprocess_stateid_op(&cstate->current_fh,
+				&read->rd_stateid,
 				CHECK_FH | RD_STATE, &read->rd_filp))) {
 		dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
 		goto out;
@@ -504,12 +521,13 @@
 out:
 	nfs4_unlock_state();
 	read->rd_rqstp = rqstp;
-	read->rd_fhp = current_fh;
+	read->rd_fhp = &cstate->current_fh;
 	return status;
 }
 
-static inline __be32
-nfsd4_readdir(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readdir *readdir)
+static __be32
+nfsd4_readdir(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	      struct nfsd4_readdir *readdir)
 {
 	u64 cookie = readdir->rd_cookie;
 	static const nfs4_verifier zeroverf;
@@ -527,48 +545,51 @@
 		return nfserr_bad_cookie;
 
 	readdir->rd_rqstp = rqstp;
-	readdir->rd_fhp = current_fh;
+	readdir->rd_fhp = &cstate->current_fh;
 	return nfs_ok;
 }
 
-static inline __be32
-nfsd4_readlink(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readlink *readlink)
+static __be32
+nfsd4_readlink(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	       struct nfsd4_readlink *readlink)
 {
 	readlink->rl_rqstp = rqstp;
-	readlink->rl_fhp = current_fh;
+	readlink->rl_fhp = &cstate->current_fh;
 	return nfs_ok;
 }
 
-static inline __be32
-nfsd4_remove(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_remove *remove)
+static __be32
+nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	     struct nfsd4_remove *remove)
 {
 	__be32 status;
 
 	if (nfs4_in_grace())
 		return nfserr_grace;
-	status = nfsd_unlink(rqstp, current_fh, 0, remove->rm_name, remove->rm_namelen);
+	status = nfsd_unlink(rqstp, &cstate->current_fh, 0,
+			     remove->rm_name, remove->rm_namelen);
 	if (status == nfserr_symlink)
 		return nfserr_notdir;
 	if (!status) {
-		fh_unlock(current_fh);
-		set_change_info(&remove->rm_cinfo, current_fh);
+		fh_unlock(&cstate->current_fh);
+		set_change_info(&remove->rm_cinfo, &cstate->current_fh);
 	}
 	return status;
 }
 
-static inline __be32
-nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh,
-	     struct svc_fh *save_fh, struct nfsd4_rename *rename)
+static __be32
+nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	     struct nfsd4_rename *rename)
 {
 	__be32 status = nfserr_nofilehandle;
 
-	if (!save_fh->fh_dentry)
+	if (!cstate->save_fh.fh_dentry)
 		return status;
-	if (nfs4_in_grace() && !(save_fh->fh_export->ex_flags
+	if (nfs4_in_grace() && !(cstate->save_fh.fh_export->ex_flags
 					& NFSEXP_NOSUBTREECHECK))
 		return nfserr_grace;
-	status = nfsd_rename(rqstp, save_fh, rename->rn_sname,
-			     rename->rn_snamelen, current_fh,
+	status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
+			     rename->rn_snamelen, &cstate->current_fh,
 			     rename->rn_tname, rename->rn_tnamelen);
 
 	/* the underlying filesystem returns different error's than required
@@ -576,27 +597,28 @@
 	if (status == nfserr_isdir)
 		status = nfserr_exist;
 	else if ((status == nfserr_notdir) &&
-                  (S_ISDIR(save_fh->fh_dentry->d_inode->i_mode) &&
-                   S_ISDIR(current_fh->fh_dentry->d_inode->i_mode)))
+                  (S_ISDIR(cstate->save_fh.fh_dentry->d_inode->i_mode) &&
+                   S_ISDIR(cstate->current_fh.fh_dentry->d_inode->i_mode)))
 		status = nfserr_exist;
 	else if (status == nfserr_symlink)
 		status = nfserr_notdir;
 
 	if (!status) {
-		set_change_info(&rename->rn_sinfo, current_fh);
-		set_change_info(&rename->rn_tinfo, save_fh);
+		set_change_info(&rename->rn_sinfo, &cstate->current_fh);
+		set_change_info(&rename->rn_tinfo, &cstate->save_fh);
 	}
 	return status;
 }
 
-static inline __be32
-nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_setattr *setattr)
+static __be32
+nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	      struct nfsd4_setattr *setattr)
 {
 	__be32 status = nfs_ok;
 
 	if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
 		nfs4_lock_state();
-		status = nfs4_preprocess_stateid_op(current_fh,
+		status = nfs4_preprocess_stateid_op(&cstate->current_fh,
 			&setattr->sa_stateid, CHECK_FH | WR_STATE, NULL);
 		nfs4_unlock_state();
 		if (status) {
@@ -606,16 +628,18 @@
 	}
 	status = nfs_ok;
 	if (setattr->sa_acl != NULL)
-		status = nfsd4_set_nfs4_acl(rqstp, current_fh, setattr->sa_acl);
+		status = nfsd4_set_nfs4_acl(rqstp, &cstate->current_fh,
+					    setattr->sa_acl);
 	if (status)
 		return status;
-	status = nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr,
+	status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr,
 				0, (time_t)0);
 	return status;
 }
 
-static inline __be32
-nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_write *write)
+static __be32
+nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	    struct nfsd4_write *write)
 {
 	stateid_t *stateid = &write->wr_stateid;
 	struct file *filp = NULL;
@@ -628,7 +652,7 @@
 		return nfserr_inval;
 
 	nfs4_lock_state();
-	status = nfs4_preprocess_stateid_op(current_fh, stateid,
+	status = nfs4_preprocess_stateid_op(&cstate->current_fh, stateid,
 					CHECK_FH | WR_STATE, &filp);
 	if (filp)
 		get_file(filp);
@@ -645,9 +669,9 @@
 	*p++ = nfssvc_boot.tv_sec;
 	*p++ = nfssvc_boot.tv_usec;
 
-	status =  nfsd_write(rqstp, current_fh, filp, write->wr_offset,
-			rqstp->rq_vec, write->wr_vlen, write->wr_buflen,
-			&write->wr_how_written);
+	status =  nfsd_write(rqstp, &cstate->current_fh, filp,
+			     write->wr_offset, rqstp->rq_vec, write->wr_vlen,
+			     write->wr_buflen, &write->wr_how_written);
 	if (filp)
 		fput(filp);
 
@@ -662,13 +686,14 @@
  * to NFS_OK after the call; NVERIFY by mapping NFSERR_NOT_SAME to NFS_OK.
  */
 static __be32
-nfsd4_verify(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_verify *verify)
+_nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	     struct nfsd4_verify *verify)
 {
 	__be32 *buf, *p;
 	int count;
 	__be32 status;
 
-	status = fh_verify(rqstp, current_fh, 0, MAY_NOP);
+	status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
 	if (status)
 		return status;
 
@@ -689,8 +714,9 @@
 	if (!buf)
 		return nfserr_resource;
 
-	status = nfsd4_encode_fattr(current_fh, current_fh->fh_export,
-				    current_fh->fh_dentry, buf,
+	status = nfsd4_encode_fattr(&cstate->current_fh,
+				    cstate->current_fh.fh_export,
+				    cstate->current_fh.fh_dentry, buf,
 				    &count, verify->ve_bmval,
 				    rqstp);
 
@@ -712,6 +738,26 @@
 	return status;
 }
 
+static __be32
+nfsd4_nverify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	      struct nfsd4_verify *verify)
+{
+	__be32 status;
+
+	status = _nfsd4_verify(rqstp, cstate, verify);
+	return status == nfserr_not_same ? nfs_ok : status;
+}
+
+static __be32
+nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	     struct nfsd4_verify *verify)
+{
+	__be32 status;
+
+	status = _nfsd4_verify(rqstp, cstate, verify);
+	return status == nfserr_same ? nfs_ok : status;
+}
+
 /*
  * NULL call.
  */
@@ -727,6 +773,42 @@
 		nfsdstats.nfs4_opcount[opnum]++;
 }
 
+static void cstate_free(struct nfsd4_compound_state *cstate)
+{
+	if (cstate == NULL)
+		return;
+	fh_put(&cstate->current_fh);
+	fh_put(&cstate->save_fh);
+	BUG_ON(cstate->replay_owner);
+	kfree(cstate);
+}
+
+static struct nfsd4_compound_state *cstate_alloc(void)
+{
+	struct nfsd4_compound_state *cstate;
+
+	cstate = kmalloc(sizeof(struct nfsd4_compound_state), GFP_KERNEL);
+	if (cstate == NULL)
+		return NULL;
+	fh_init(&cstate->current_fh, NFS4_FHSIZE);
+	fh_init(&cstate->save_fh, NFS4_FHSIZE);
+	cstate->replay_owner = NULL;
+	return cstate;
+}
+
+typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *,
+			      void *);
+
+struct nfsd4_operation {
+	nfsd4op_func op_func;
+	u32 op_flags;
+/* Most ops require a valid current filehandle; a few don't: */
+#define ALLOWED_WITHOUT_FH 1
+/* GETATTR and ops not listed as returning NFS4ERR_MOVED: */
+#define ALLOWED_ON_ABSENT_FS 2
+};
+
+static struct nfsd4_operation nfsd4_ops[];
 
 /*
  * COMPOUND call.
@@ -737,21 +819,15 @@
 		    struct nfsd4_compoundres *resp)
 {
 	struct nfsd4_op	*op;
-	struct svc_fh	*current_fh = NULL;
-	struct svc_fh	*save_fh = NULL;
-	struct nfs4_stateowner *replay_owner = NULL;
-	int		slack_space;    /* in words, not bytes! */
+	struct nfsd4_operation *opdesc;
+	struct nfsd4_compound_state *cstate = NULL;
+	int		slack_bytes;
 	__be32		status;
 
 	status = nfserr_resource;
-	current_fh = kmalloc(sizeof(*current_fh), GFP_KERNEL);
-	if (current_fh == NULL)
+	cstate = cstate_alloc();
+	if (cstate == NULL)
 		goto out;
-	fh_init(current_fh, NFS4_FHSIZE);
-	save_fh = kmalloc(sizeof(*save_fh), GFP_KERNEL);
-	if (save_fh == NULL)
-		goto out;
-	fh_init(save_fh, NFS4_FHSIZE);
 
 	resp->xbuf = &rqstp->rq_res;
 	resp->p = rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len;
@@ -790,164 +866,44 @@
 		 * failed response to the next operation.  If we don't
 		 * have enough room, fail with ERR_RESOURCE.
 		 */
-/* FIXME - is slack_space *really* words, or bytes??? - neilb */
-		slack_space = (char *)resp->end - (char *)resp->p;
-		if (slack_space < COMPOUND_SLACK_SPACE + COMPOUND_ERR_SLACK_SPACE) {
-			BUG_ON(slack_space < COMPOUND_ERR_SLACK_SPACE);
+		slack_bytes = (char *)resp->end - (char *)resp->p;
+		if (slack_bytes < COMPOUND_SLACK_SPACE
+				+ COMPOUND_ERR_SLACK_SPACE) {
+			BUG_ON(slack_bytes < COMPOUND_ERR_SLACK_SPACE);
 			op->status = nfserr_resource;
 			goto encode_op;
 		}
 
-		/* All operations except RENEW, SETCLIENTID, RESTOREFH
-		* SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH
-		* require a valid current filehandle
-		*/
-		if (!current_fh->fh_dentry) {
-			if (!((op->opnum == OP_PUTFH) ||
-			      (op->opnum == OP_PUTROOTFH) ||
-			      (op->opnum == OP_SETCLIENTID) ||
-			      (op->opnum == OP_SETCLIENTID_CONFIRM) ||
-			      (op->opnum == OP_RENEW) ||
-			      (op->opnum == OP_RESTOREFH) ||
-			      (op->opnum == OP_RELEASE_LOCKOWNER))) {
+		opdesc = &nfsd4_ops[op->opnum];
+
+		if (!cstate->current_fh.fh_dentry) {
+			if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) {
 				op->status = nfserr_nofilehandle;
 				goto encode_op;
 			}
-		}
-		/* Check must be done at start of each operation, except
-		 * for GETATTR and ops not listed as returning NFS4ERR_MOVED
-		 */
-		else if (current_fh->fh_export->ex_fslocs.migrated &&
-			 !((op->opnum == OP_GETATTR) ||
-			   (op->opnum == OP_PUTROOTFH) ||
-			   (op->opnum == OP_PUTPUBFH) ||
-			   (op->opnum == OP_RENEW) ||
-			   (op->opnum == OP_SETCLIENTID) ||
-			   (op->opnum == OP_RELEASE_LOCKOWNER))) {
+		} else if (cstate->current_fh.fh_export->ex_fslocs.migrated &&
+			  !(opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) {
 			op->status = nfserr_moved;
 			goto encode_op;
 		}
-		switch (op->opnum) {
-		case OP_ACCESS:
-			op->status = nfsd4_access(rqstp, current_fh, &op->u.access);
-			break;
-		case OP_CLOSE:
-			op->status = nfsd4_close(rqstp, current_fh, &op->u.close, &replay_owner);
-			break;
-		case OP_COMMIT:
-			op->status = nfsd4_commit(rqstp, current_fh, &op->u.commit);
-			break;
-		case OP_CREATE:
-			op->status = nfsd4_create(rqstp, current_fh, &op->u.create);
-			break;
-		case OP_DELEGRETURN:
-			op->status = nfsd4_delegreturn(rqstp, current_fh, &op->u.delegreturn);
-			break;
-		case OP_GETATTR:
-			op->status = nfsd4_getattr(rqstp, current_fh, &op->u.getattr);
-			break;
-		case OP_GETFH:
-			op->status = nfsd4_getfh(current_fh, &op->u.getfh);
-			break;
-		case OP_LINK:
-			op->status = nfsd4_link(rqstp, current_fh, save_fh, &op->u.link);
-			break;
-		case OP_LOCK:
-			op->status = nfsd4_lock(rqstp, current_fh, &op->u.lock, &replay_owner);
-			break;
-		case OP_LOCKT:
-			op->status = nfsd4_lockt(rqstp, current_fh, &op->u.lockt);
-			break;
-		case OP_LOCKU:
-			op->status = nfsd4_locku(rqstp, current_fh, &op->u.locku, &replay_owner);
-			break;
-		case OP_LOOKUP:
-			op->status = nfsd4_lookup(rqstp, current_fh, &op->u.lookup);
-			break;
-		case OP_LOOKUPP:
-			op->status = nfsd4_lookupp(rqstp, current_fh);
-			break;
-		case OP_NVERIFY:
-			op->status = nfsd4_verify(rqstp, current_fh, &op->u.nverify);
-			if (op->status == nfserr_not_same)
-				op->status = nfs_ok;
-			break;
-		case OP_OPEN:
-			op->status = nfsd4_open(rqstp, current_fh, &op->u.open, &replay_owner);
-			break;
-		case OP_OPEN_CONFIRM:
-			op->status = nfsd4_open_confirm(rqstp, current_fh, &op->u.open_confirm, &replay_owner);
-			break;
-		case OP_OPEN_DOWNGRADE:
-			op->status = nfsd4_open_downgrade(rqstp, current_fh, &op->u.open_downgrade, &replay_owner);
-			break;
-		case OP_PUTFH:
-			op->status = nfsd4_putfh(rqstp, current_fh, &op->u.putfh);
-			break;
-		case OP_PUTROOTFH:
-			op->status = nfsd4_putrootfh(rqstp, current_fh);
-			break;
-		case OP_READ:
-			op->status = nfsd4_read(rqstp, current_fh, &op->u.read);
-			break;
-		case OP_READDIR:
-			op->status = nfsd4_readdir(rqstp, current_fh, &op->u.readdir);
-			break;
-		case OP_READLINK:
-			op->status = nfsd4_readlink(rqstp, current_fh, &op->u.readlink);
-			break;
-		case OP_REMOVE:
-			op->status = nfsd4_remove(rqstp, current_fh, &op->u.remove);
-			break;
-		case OP_RENAME:
-			op->status = nfsd4_rename(rqstp, current_fh, save_fh, &op->u.rename);
-			break;
-		case OP_RENEW:
-			op->status = nfsd4_renew(&op->u.renew);
-			break;
-		case OP_RESTOREFH:
-			op->status = nfsd4_restorefh(current_fh, save_fh);
-			break;
-		case OP_SAVEFH:
-			op->status = nfsd4_savefh(current_fh, save_fh);
-			break;
-		case OP_SETATTR:
-			op->status = nfsd4_setattr(rqstp, current_fh, &op->u.setattr);
-			break;
-		case OP_SETCLIENTID:
-			op->status = nfsd4_setclientid(rqstp, &op->u.setclientid);
-			break;
-		case OP_SETCLIENTID_CONFIRM:
-			op->status = nfsd4_setclientid_confirm(rqstp, &op->u.setclientid_confirm);
-			break;
-		case OP_VERIFY:
-			op->status = nfsd4_verify(rqstp, current_fh, &op->u.verify);
-			if (op->status == nfserr_same)
-				op->status = nfs_ok;
-			break;
-		case OP_WRITE:
-			op->status = nfsd4_write(rqstp, current_fh, &op->u.write);
-			break;
-		case OP_RELEASE_LOCKOWNER:
-			op->status = nfsd4_release_lockowner(rqstp, &op->u.release_lockowner);
-			break;
-		default:
+
+		if (opdesc->op_func)
+			op->status = opdesc->op_func(rqstp, cstate, &op->u);
+		else
 			BUG_ON(op->status == nfs_ok);
-			break;
-		}
 
 encode_op:
 		if (op->status == nfserr_replay_me) {
-			op->replay = &replay_owner->so_replay;
+			op->replay = &cstate->replay_owner->so_replay;
 			nfsd4_encode_replay(resp, op);
 			status = op->status = op->replay->rp_status;
 		} else {
 			nfsd4_encode_operation(resp, op);
 			status = op->status;
 		}
-		if (replay_owner && (replay_owner != (void *)(-1))) {
-			nfs4_put_stateowner(replay_owner);
-			replay_owner = NULL;
+		if (cstate->replay_owner) {
+			nfs4_put_stateowner(cstate->replay_owner);
+			cstate->replay_owner = NULL;
 		}
 		/* XXX Ugh, we need to get rid of this kind of special case: */
 		if (op->opnum == OP_READ && op->u.read.rd_filp)
@@ -958,15 +914,124 @@
 
 out:
 	nfsd4_release_compoundargs(args);
-	if (current_fh)
-		fh_put(current_fh);
-	kfree(current_fh);
-	if (save_fh)
-		fh_put(save_fh);
-	kfree(save_fh);
+	cstate_free(cstate);
 	return status;
 }
 
+static struct nfsd4_operation nfsd4_ops[OP_RELEASE_LOCKOWNER+1] = {
+	[OP_ACCESS] = {
+		.op_func = (nfsd4op_func)nfsd4_access,
+	},
+	[OP_CLOSE] = {
+		.op_func = (nfsd4op_func)nfsd4_close,
+	},
+	[OP_COMMIT] = {
+		.op_func = (nfsd4op_func)nfsd4_commit,
+	},
+	[OP_CREATE] = {
+		.op_func = (nfsd4op_func)nfsd4_create,
+	},
+	[OP_DELEGRETURN] = {
+		.op_func = (nfsd4op_func)nfsd4_delegreturn,
+	},
+	[OP_GETATTR] = {
+		.op_func = (nfsd4op_func)nfsd4_getattr,
+		.op_flags = ALLOWED_ON_ABSENT_FS,
+	},
+	[OP_GETFH] = {
+		.op_func = (nfsd4op_func)nfsd4_getfh,
+	},
+	[OP_LINK] = {
+		.op_func = (nfsd4op_func)nfsd4_link,
+	},
+	[OP_LOCK] = {
+		.op_func = (nfsd4op_func)nfsd4_lock,
+	},
+	[OP_LOCKT] = {
+		.op_func = (nfsd4op_func)nfsd4_lockt,
+	},
+	[OP_LOCKU] = {
+		.op_func = (nfsd4op_func)nfsd4_locku,
+	},
+	[OP_LOOKUP] = {
+		.op_func = (nfsd4op_func)nfsd4_lookup,
+	},
+	[OP_LOOKUPP] = {
+		.op_func = (nfsd4op_func)nfsd4_lookupp,
+	},
+	[OP_NVERIFY] = {
+		.op_func = (nfsd4op_func)nfsd4_nverify,
+	},
+	[OP_OPEN] = {
+		.op_func = (nfsd4op_func)nfsd4_open,
+	},
+	[OP_OPEN_CONFIRM] = {
+		.op_func = (nfsd4op_func)nfsd4_open_confirm,
+	},
+	[OP_OPEN_DOWNGRADE] = {
+		.op_func = (nfsd4op_func)nfsd4_open_downgrade,
+	},
+	[OP_PUTFH] = {
+		.op_func = (nfsd4op_func)nfsd4_putfh,
+		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+	},
+	[OP_PUTPUBFH] = {
+		/* unsupported; just for future reference: */
+		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+	},
+	[OP_PUTROOTFH] = {
+		.op_func = (nfsd4op_func)nfsd4_putrootfh,
+		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+	},
+	[OP_READ] = {
+		.op_func = (nfsd4op_func)nfsd4_read,
+	},
+	[OP_READDIR] = {
+		.op_func = (nfsd4op_func)nfsd4_readdir,
+	},
+	[OP_READLINK] = {
+		.op_func = (nfsd4op_func)nfsd4_readlink,
+	},
+	[OP_REMOVE] = {
+		.op_func = (nfsd4op_func)nfsd4_remove,
+	},
+	[OP_RENAME] = {
+		.op_func = (nfsd4op_func)nfsd4_rename,
+	},
+	[OP_RENEW] = {
+		.op_func = (nfsd4op_func)nfsd4_renew,
+		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+	},
+	[OP_RESTOREFH] = {
+		.op_func = (nfsd4op_func)nfsd4_restorefh,
+		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+	},
+	[OP_SAVEFH] = {
+		.op_func = (nfsd4op_func)nfsd4_savefh,
+	},
+	[OP_SETATTR] = {
+		.op_func = (nfsd4op_func)nfsd4_setattr,
+	},
+	[OP_SETCLIENTID] = {
+		.op_func = (nfsd4op_func)nfsd4_setclientid,
+		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+	},
+	[OP_SETCLIENTID_CONFIRM] = {
+		.op_func = (nfsd4op_func)nfsd4_setclientid_confirm,
+		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+	},
+	[OP_VERIFY] = {
+		.op_func = (nfsd4op_func)nfsd4_verify,
+	},
+	[OP_WRITE] = {
+		.op_func = (nfsd4op_func)nfsd4_write,
+	},
+	[OP_RELEASE_LOCKOWNER] = {
+		.op_func = (nfsd4op_func)nfsd4_release_lockowner,
+		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+	},
+};
+
 #define nfs4svc_decode_voidargs		NULL
 #define nfs4svc_release_void		NULL
 #define nfsd4_voidres			nfsd4_voidargs
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index b7179bd..9de89df 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -711,7 +711,8 @@
  *
  */
 __be32
-nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
+nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+		  struct nfsd4_setclientid *setclid)
 {
 	__be32 			ip_addr = rqstp->rq_addr.sin_addr.s_addr;
 	struct xdr_netobj 	clname = { 
@@ -876,7 +877,9 @@
  * NOTE: callback information will be processed here in a future patch
  */
 __be32
-nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm)
+nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+			 struct nfsd4_compound_state *cstate,
+			 struct nfsd4_setclientid_confirm *setclientid_confirm)
 {
 	__be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
 	struct nfs4_client *conf, *unconf;
@@ -1833,7 +1836,8 @@
 static DECLARE_DELAYED_WORK(laundromat_work, laundromat_main);
 
 __be32
-nfsd4_renew(clientid_t *clid)
+nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	    clientid_t *clid)
 {
 	struct nfs4_client *clp;
 	__be32 status;
@@ -2241,24 +2245,25 @@
 }
 
 __be32
-nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc, struct nfs4_stateowner **replay_owner)
+nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+		   struct nfsd4_open_confirm *oc)
 {
 	__be32 status;
 	struct nfs4_stateowner *sop;
 	struct nfs4_stateid *stp;
 
 	dprintk("NFSD: nfsd4_open_confirm on file %.*s\n",
-			(int)current_fh->fh_dentry->d_name.len,
-			current_fh->fh_dentry->d_name.name);
+			(int)cstate->current_fh.fh_dentry->d_name.len,
+			cstate->current_fh.fh_dentry->d_name.name);
 
-	status = fh_verify(rqstp, current_fh, S_IFREG, 0);
+	status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0);
 	if (status)
 		return status;
 
 	nfs4_lock_state();
 
-	if ((status = nfs4_preprocess_seqid_op(current_fh, oc->oc_seqid,
-					&oc->oc_req_stateid,
+	if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+					oc->oc_seqid, &oc->oc_req_stateid,
 					CHECK_FH | CONFIRM | OPEN_STATE,
 					&oc->oc_stateowner, &stp, NULL)))
 		goto out; 
@@ -2278,7 +2283,7 @@
 out:
 	if (oc->oc_stateowner) {
 		nfs4_get_stateowner(oc->oc_stateowner);
-		*replay_owner = oc->oc_stateowner;
+		cstate->replay_owner = oc->oc_stateowner;
 	}
 	nfs4_unlock_state();
 	return status;
@@ -2310,22 +2315,25 @@
 }
 
 __be32
-nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od, struct nfs4_stateowner **replay_owner)
+nfsd4_open_downgrade(struct svc_rqst *rqstp,
+		     struct nfsd4_compound_state *cstate,
+		     struct nfsd4_open_downgrade *od)
 {
 	__be32 status;
 	struct nfs4_stateid *stp;
 	unsigned int share_access;
 
 	dprintk("NFSD: nfsd4_open_downgrade on file %.*s\n", 
-			(int)current_fh->fh_dentry->d_name.len,
-			current_fh->fh_dentry->d_name.name);
+			(int)cstate->current_fh.fh_dentry->d_name.len,
+			cstate->current_fh.fh_dentry->d_name.name);
 
 	if (!access_valid(od->od_share_access)
 			|| !deny_valid(od->od_share_deny))
 		return nfserr_inval;
 
 	nfs4_lock_state();
-	if ((status = nfs4_preprocess_seqid_op(current_fh, od->od_seqid, 
+	if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+					od->od_seqid,
 					&od->od_stateid, 
 					CHECK_FH | OPEN_STATE, 
 					&od->od_stateowner, &stp, NULL)))
@@ -2355,7 +2363,7 @@
 out:
 	if (od->od_stateowner) {
 		nfs4_get_stateowner(od->od_stateowner);
-		*replay_owner = od->od_stateowner;
+		cstate->replay_owner = od->od_stateowner;
 	}
 	nfs4_unlock_state();
 	return status;
@@ -2365,18 +2373,20 @@
  * nfs4_unlock_state() called after encode
  */
 __be32
-nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close, struct nfs4_stateowner **replay_owner)
+nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	    struct nfsd4_close *close)
 {
 	__be32 status;
 	struct nfs4_stateid *stp;
 
 	dprintk("NFSD: nfsd4_close on file %.*s\n", 
-			(int)current_fh->fh_dentry->d_name.len,
-			current_fh->fh_dentry->d_name.name);
+			(int)cstate->current_fh.fh_dentry->d_name.len,
+			cstate->current_fh.fh_dentry->d_name.name);
 
 	nfs4_lock_state();
 	/* check close_lru for replay */
-	if ((status = nfs4_preprocess_seqid_op(current_fh, close->cl_seqid, 
+	if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+					close->cl_seqid,
 					&close->cl_stateid, 
 					CHECK_FH | OPEN_STATE | CLOSE_STATE,
 					&close->cl_stateowner, &stp, NULL)))
@@ -2397,22 +2407,24 @@
 out:
 	if (close->cl_stateowner) {
 		nfs4_get_stateowner(close->cl_stateowner);
-		*replay_owner = close->cl_stateowner;
+		cstate->replay_owner = close->cl_stateowner;
 	}
 	nfs4_unlock_state();
 	return status;
 }
 
 __be32
-nfsd4_delegreturn(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_delegreturn *dr)
+nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+		  struct nfsd4_delegreturn *dr)
 {
 	__be32 status;
 
-	if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0)))
+	if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))
 		goto out;
 
 	nfs4_lock_state();
-	status = nfs4_preprocess_stateid_op(current_fh, &dr->dr_stateid, DELEG_RET, NULL);
+	status = nfs4_preprocess_stateid_op(&cstate->current_fh,
+					    &dr->dr_stateid, DELEG_RET, NULL);
 	nfs4_unlock_state();
 out:
 	return status;
@@ -2635,7 +2647,8 @@
  *  LOCK operation 
  */
 __be32
-nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock, struct nfs4_stateowner **replay_owner)
+nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	   struct nfsd4_lock *lock)
 {
 	struct nfs4_stateowner *open_sop = NULL;
 	struct nfs4_stateowner *lock_sop = NULL;
@@ -2654,7 +2667,8 @@
 	if (check_lock_length(lock->lk_offset, lock->lk_length))
 		 return nfserr_inval;
 
-	if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
+	if ((status = fh_verify(rqstp, &cstate->current_fh,
+				S_IFREG, MAY_LOCK))) {
 		dprintk("NFSD: nfsd4_lock: permission denied!\n");
 		return status;
 	}
@@ -2675,7 +2689,7 @@
 			goto out;
 
 		/* validate and update open stateid and open seqid */
-		status = nfs4_preprocess_seqid_op(current_fh, 
+		status = nfs4_preprocess_seqid_op(&cstate->current_fh,
 				        lock->lk_new_open_seqid,
 		                        &lock->lk_new_open_stateid,
 		                        CHECK_FH | OPEN_STATE,
@@ -2702,7 +2716,7 @@
 			goto out;
 	} else {
 		/* lock (lock owner + lock stateid) already exists */
-		status = nfs4_preprocess_seqid_op(current_fh,
+		status = nfs4_preprocess_seqid_op(&cstate->current_fh,
 				       lock->lk_old_lock_seqid, 
 				       &lock->lk_old_lock_stateid, 
 				       CHECK_FH | LOCK_STATE, 
@@ -2759,7 +2773,6 @@
 	conflock.fl_ops = NULL;
 	conflock.fl_lmops = NULL;
 	err = posix_lock_file_conf(filp, &file_lock, &conflock);
-	dprintk("NFSD: nfsd4_lock: posix_lock_file_conf status %d\n",status);
 	switch (-err) {
 	case 0: /* success! */
 		update_stateid(&lock_stp->st_stateid);
@@ -2785,7 +2798,7 @@
 		release_stateowner(lock_sop);
 	if (lock->lk_replay_owner) {
 		nfs4_get_stateowner(lock->lk_replay_owner);
-		*replay_owner = lock->lk_replay_owner;
+		cstate->replay_owner = lock->lk_replay_owner;
 	}
 	nfs4_unlock_state();
 	return status;
@@ -2795,7 +2808,8 @@
  * LOCKT operation
  */
 __be32
-nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lockt *lockt)
+nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	    struct nfsd4_lockt *lockt)
 {
 	struct inode *inode;
 	struct file file;
@@ -2816,14 +2830,14 @@
 	if (STALE_CLIENTID(&lockt->lt_clientid))
 		goto out;
 
-	if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0))) {
+	if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0))) {
 		dprintk("NFSD: nfsd4_lockt: fh_verify() failed!\n");
 		if (status == nfserr_symlink)
 			status = nfserr_inval;
 		goto out;
 	}
 
-	inode = current_fh->fh_dentry->d_inode;
+	inode = cstate->current_fh.fh_dentry->d_inode;
 	locks_init_lock(&file_lock);
 	switch (lockt->lt_type) {
 		case NFS4_READ_LT:
@@ -2862,7 +2876,7 @@
 	 * only the dentry:inode set.
 	 */
 	memset(&file, 0, sizeof (struct file));
-	file.f_path.dentry = current_fh->fh_dentry;
+	file.f_path.dentry = cstate->current_fh.fh_dentry;
 
 	status = nfs_ok;
 	if (posix_test_lock(&file, &file_lock, &conflock)) {
@@ -2875,7 +2889,8 @@
 }
 
 __be32
-nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku, struct nfs4_stateowner **replay_owner)
+nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	    struct nfsd4_locku *locku)
 {
 	struct nfs4_stateid *stp;
 	struct file *filp = NULL;
@@ -2892,7 +2907,7 @@
 
 	nfs4_lock_state();
 									        
-	if ((status = nfs4_preprocess_seqid_op(current_fh, 
+	if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
 					locku->lu_seqid, 
 					&locku->lu_stateid, 
 					CHECK_FH | LOCK_STATE, 
@@ -2933,7 +2948,7 @@
 out:
 	if (locku->lu_stateowner) {
 		nfs4_get_stateowner(locku->lu_stateowner);
-		*replay_owner = locku->lu_stateowner;
+		cstate->replay_owner = locku->lu_stateowner;
 	}
 	nfs4_unlock_state();
 	return status;
@@ -2968,7 +2983,9 @@
 }
 
 __be32
-nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *rlockowner)
+nfsd4_release_lockowner(struct svc_rqst *rqstp,
+			struct nfsd4_compound_state *cstate,
+			struct nfsd4_release_lockowner *rlockowner)
 {
 	clientid_t *clid = &rlockowner->rl_clientid;
 	struct nfs4_stateowner *sop;
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index f3f239d..fea4636 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1845,15 +1845,11 @@
 
 	exp_get(exp);
 	if (d_mountpoint(dentry)) {
-		if (nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp)) {
-		/*
-		 * -EAGAIN is the only error returned from
-		 * nfsd_cross_mnt() and it indicates that an
-		 * up-call has  been initiated to fill in the export
-		 * options on exp.  When the answer comes back,
-		 * this call will be retried.
-		 */
-			nfserr = nfserr_dropit;
+		int err;
+
+		err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp);
+		if (err) {
+			nfserr = nfserrno(err);
 			goto out_put;
 		}
 
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 727ab3b..b06bf9f 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -169,9 +169,11 @@
 			exp = exp_find(rqstp->rq_client, 0, tfh, &rqstp->rq_chandle);
 		}
 
-		error = nfserr_dropit;
-		if (IS_ERR(exp) && PTR_ERR(exp) == -EAGAIN)
+		if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN
+				|| PTR_ERR(exp) == -ETIMEDOUT)) {
+			error = nfserrno(PTR_ERR(exp));
 			goto out;
+		}
 
 		error = nfserr_stale; 
 		if (!exp || IS_ERR(exp))
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 4883d75..7a79c23 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -99,7 +99,7 @@
 /* 
  * Called from nfsd_lookup and encode_dirent. Check if we have crossed 
  * a mount point.
- * Returns -EAGAIN leaving *dpp and *expp unchanged, 
+ * Returns -EAGAIN or -ETIMEDOUT leaving *dpp and *expp unchanged,
  *  or nfs_ok having possibly changed *dpp and *expp
  */
 int
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index edc91ca..f27e5378 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -1959,7 +1959,7 @@
 		goto bail;
 	}
 
-	*tc = kcalloc(1, sizeof(struct ocfs2_truncate_context), GFP_KERNEL);
+	*tc = kzalloc(sizeof(struct ocfs2_truncate_context), GFP_KERNEL);
 	if (!(*tc)) {
 		status = -ENOMEM;
 		mlog_errno(status);
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index 4cd9a95..a25ef5a 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -1553,7 +1553,7 @@
 	struct o2hb_region *reg = NULL;
 	struct config_item *ret = NULL;
 
-	reg = kcalloc(1, sizeof(struct o2hb_region), GFP_KERNEL);
+	reg = kzalloc(sizeof(struct o2hb_region), GFP_KERNEL);
 	if (reg == NULL)
 		goto out; /* ENOMEM */
 
@@ -1679,7 +1679,7 @@
 	struct o2hb_heartbeat_group *hs = NULL;
 	struct config_group *ret = NULL;
 
-	hs = kcalloc(1, sizeof(struct o2hb_heartbeat_group), GFP_KERNEL);
+	hs = kzalloc(sizeof(struct o2hb_heartbeat_group), GFP_KERNEL);
 	if (hs == NULL)
 		goto out;
 
diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c
index 357f1d5..b17333a 100644
--- a/fs/ocfs2/cluster/nodemanager.c
+++ b/fs/ocfs2/cluster/nodemanager.c
@@ -714,7 +714,7 @@
 	if (strlen(name) > O2NM_MAX_NAME_LEN)
 		goto out; /* ENAMETOOLONG */
 
-	node = kcalloc(1, sizeof(struct o2nm_node), GFP_KERNEL);
+	node = kzalloc(sizeof(struct o2nm_node), GFP_KERNEL);
 	if (node == NULL)
 		goto out; /* ENOMEM */
 
@@ -825,8 +825,8 @@
 	if (o2nm_single_cluster)
 		goto out; /* ENOSPC */
 
-	cluster = kcalloc(1, sizeof(struct o2nm_cluster), GFP_KERNEL);
-	ns = kcalloc(1, sizeof(struct o2nm_node_group), GFP_KERNEL);
+	cluster = kzalloc(sizeof(struct o2nm_cluster), GFP_KERNEL);
+	ns = kzalloc(sizeof(struct o2nm_node_group), GFP_KERNEL);
 	defs = kcalloc(3, sizeof(struct config_group *), GFP_KERNEL);
 	o2hb_group = o2hb_alloc_hb_set();
 	if (cluster == NULL || ns == NULL || o2hb_group == NULL || defs == NULL)
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index 457753d..ae4ff4a 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -324,7 +324,7 @@
 	struct page *page = NULL;
 
 	page = alloc_page(GFP_NOFS);
-	sc = kcalloc(1, sizeof(*sc), GFP_NOFS);
+	sc = kzalloc(sizeof(*sc), GFP_NOFS);
 	if (sc == NULL || page == NULL)
 		goto out;
 
@@ -714,7 +714,7 @@
 		goto out;
 	}
 
-       	nmh = kcalloc(1, sizeof(struct o2net_msg_handler), GFP_NOFS);
+       	nmh = kzalloc(sizeof(struct o2net_msg_handler), GFP_NOFS);
 	if (nmh == NULL) {
 		ret = -ENOMEM;
 		goto out;
@@ -1918,9 +1918,9 @@
 
 	o2quo_init();
 
-	o2net_hand = kcalloc(1, sizeof(struct o2net_handshake), GFP_KERNEL);
-	o2net_keep_req = kcalloc(1, sizeof(struct o2net_msg), GFP_KERNEL);
-	o2net_keep_resp = kcalloc(1, sizeof(struct o2net_msg), GFP_KERNEL);
+	o2net_hand = kzalloc(sizeof(struct o2net_handshake), GFP_KERNEL);
+	o2net_keep_req = kzalloc(sizeof(struct o2net_msg), GFP_KERNEL);
+	o2net_keep_resp = kzalloc(sizeof(struct o2net_msg), GFP_KERNEL);
 	if (!o2net_hand || !o2net_keep_req || !o2net_keep_resp) {
 		kfree(o2net_hand);
 		kfree(o2net_keep_req);
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
index 420a375..f0b25f2 100644
--- a/fs/ocfs2/dlm/dlmdomain.c
+++ b/fs/ocfs2/dlm/dlmdomain.c
@@ -920,7 +920,7 @@
 
 	mlog_entry("%p", dlm);
 
-	ctxt = kcalloc(1, sizeof(*ctxt), GFP_KERNEL);
+	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
 	if (!ctxt) {
 		status = -ENOMEM;
 		mlog_errno(status);
@@ -1223,7 +1223,7 @@
 	int i;
 	struct dlm_ctxt *dlm = NULL;
 
-	dlm = kcalloc(1, sizeof(*dlm), GFP_KERNEL);
+	dlm = kzalloc(sizeof(*dlm), GFP_KERNEL);
 	if (!dlm) {
 		mlog_errno(-ENOMEM);
 		goto leave;
diff --git a/fs/ocfs2/dlm/dlmlock.c b/fs/ocfs2/dlm/dlmlock.c
index 42a1b91..e5ca3db 100644
--- a/fs/ocfs2/dlm/dlmlock.c
+++ b/fs/ocfs2/dlm/dlmlock.c
@@ -408,13 +408,13 @@
 	struct dlm_lock *lock;
 	int kernel_allocated = 0;
 
-	lock = kcalloc(1, sizeof(*lock), GFP_NOFS);
+	lock = kzalloc(sizeof(*lock), GFP_NOFS);
 	if (!lock)
 		return NULL;
 
 	if (!lksb) {
 		/* zero memory only if kernel-allocated */
-		lksb = kcalloc(1, sizeof(*lksb), GFP_NOFS);
+		lksb = kzalloc(sizeof(*lksb), GFP_NOFS);
 		if (!lksb) {
 			kfree(lock);
 			return NULL;
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index 856012b..0ad8720 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -1939,7 +1939,7 @@
 			       int ignore_higher, u8 request_from, u32 flags)
 {
 	struct dlm_work_item *item;
-	item = kcalloc(1, sizeof(*item), GFP_NOFS);
+	item = kzalloc(sizeof(*item), GFP_NOFS);
 	if (!item)
 		return -ENOMEM;
 
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index fb3e2b0..367a11e 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -757,7 +757,7 @@
 		}
 		BUG_ON(num == dead_node);
 
-		ndata = kcalloc(1, sizeof(*ndata), GFP_NOFS);
+		ndata = kzalloc(sizeof(*ndata), GFP_NOFS);
 		if (!ndata) {
 			dlm_destroy_recovery_area(dlm, dead_node);
 			return -ENOMEM;
@@ -842,7 +842,7 @@
 	}
 	BUG_ON(lr->dead_node != dlm->reco.dead_node);
 
-	item = kcalloc(1, sizeof(*item), GFP_NOFS);
+	item = kzalloc(sizeof(*item), GFP_NOFS);
 	if (!item) {
 		dlm_put(dlm);
 		return -ENOMEM;
@@ -1323,7 +1323,7 @@
 
 	ret = -ENOMEM;
 	buf = kmalloc(be16_to_cpu(msg->data_len), GFP_NOFS);
-	item = kcalloc(1, sizeof(*item), GFP_NOFS);
+	item = kzalloc(sizeof(*item), GFP_NOFS);
 	if (!buf || !item)
 		goto leave;
 
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index e9a82ad..9fd590b 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -153,6 +153,14 @@
 	    ((vfsmnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode)))
 		return 0;
 
+	if (vfsmnt->mnt_flags & MNT_RELATIME) {
+		if ((timespec_compare(&inode->i_atime, &inode->i_mtime) <= 0) ||
+		    (timespec_compare(&inode->i_atime, &inode->i_ctime) <= 0))
+			return 1;
+
+		return 0;
+	}
+
 	now = CURRENT_TIME;
 	if ((now.tv_sec - inode->i_atime.tv_sec <= osb->s_atime_quantum))
 		return 0;
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c
index 698d79a..4dedd97 100644
--- a/fs/ocfs2/localalloc.c
+++ b/fs/ocfs2/localalloc.c
@@ -776,7 +776,7 @@
 {
 	int status;
 
-	*ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
+	*ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
 	if (!(*ac)) {
 		status = -ENOMEM;
 		mlog_errno(status);
diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c
index aa6f5aa..2d3ac32 100644
--- a/fs/ocfs2/slot_map.c
+++ b/fs/ocfs2/slot_map.c
@@ -175,7 +175,7 @@
 	struct buffer_head *bh = NULL;
 	struct ocfs2_slot_info *si;
 
-	si = kcalloc(1, sizeof(struct ocfs2_slot_info), GFP_KERNEL);
+	si = kzalloc(sizeof(struct ocfs2_slot_info), GFP_KERNEL);
 	if (!si) {
 		status = -ENOMEM;
 		mlog_errno(status);
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index 000d71c..6dbb117 100644
--- a/fs/ocfs2/suballoc.c
+++ b/fs/ocfs2/suballoc.c
@@ -488,7 +488,7 @@
 	int status;
 	u32 slot;
 
-	*ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
+	*ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
 	if (!(*ac)) {
 		status = -ENOMEM;
 		mlog_errno(status);
@@ -530,7 +530,7 @@
 {
 	int status;
 
-	*ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
+	*ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
 	if (!(*ac)) {
 		status = -ENOMEM;
 		mlog_errno(status);
@@ -595,7 +595,7 @@
 
 	mlog_entry_void();
 
-	*ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
+	*ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
 	if (!(*ac)) {
 		status = -ENOMEM;
 		mlog_errno(status);
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index a6d2f8c..6e300a8 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -1231,7 +1231,7 @@
 
 	BUG_ON(uuid_bytes != OCFS2_VOL_UUID_LEN);
 
-	osb->uuid_str = kcalloc(1, OCFS2_VOL_UUID_LEN * 2 + 1, GFP_KERNEL);
+	osb->uuid_str = kzalloc(OCFS2_VOL_UUID_LEN * 2 + 1, GFP_KERNEL);
 	if (osb->uuid_str == NULL)
 		return -ENOMEM;
 
@@ -1262,7 +1262,7 @@
 
 	mlog_entry_void();
 
-	osb = kcalloc(1, sizeof(struct ocfs2_super), GFP_KERNEL);
+	osb = kzalloc(sizeof(struct ocfs2_super), GFP_KERNEL);
 	if (!osb) {
 		status = -ENOMEM;
 		mlog_errno(status);
@@ -1387,7 +1387,7 @@
 	 */
 	/* initialize our journal structure */
 
-	journal = kcalloc(1, sizeof(struct ocfs2_journal), GFP_KERNEL);
+	journal = kzalloc(sizeof(struct ocfs2_journal), GFP_KERNEL);
 	if (!journal) {
 		mlog(ML_ERROR, "unable to alloc journal\n");
 		status = -ENOMEM;
diff --git a/fs/ocfs2/vote.c b/fs/ocfs2/vote.c
index 0315a8b..0afd8b9 100644
--- a/fs/ocfs2/vote.c
+++ b/fs/ocfs2/vote.c
@@ -479,7 +479,7 @@
 {
 	struct ocfs2_net_wait_ctxt *w;
 
-	w = kcalloc(1, sizeof(*w), GFP_NOFS);
+	w = kzalloc(sizeof(*w), GFP_NOFS);
 	if (!w) {
 		mlog_errno(-ENOMEM);
 		goto bail;
@@ -642,7 +642,7 @@
 
 	BUG_ON(!ocfs2_is_valid_vote_request(type));
 
-	request = kcalloc(1, sizeof(*request), GFP_NOFS);
+	request = kzalloc(sizeof(*request), GFP_NOFS);
 	if (!request) {
 		mlog_errno(-ENOMEM);
 	} else {
diff --git a/fs/pipe.c b/fs/pipe.c
index f8b6bdc..9a06e8e 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -207,7 +207,7 @@
 	return 0;
 }
 
-static struct pipe_buf_operations anon_pipe_buf_ops = {
+static const struct pipe_buf_operations anon_pipe_buf_ops = {
 	.can_merge = 1,
 	.map = generic_pipe_buf_map,
 	.unmap = generic_pipe_buf_unmap,
@@ -243,7 +243,7 @@
 		if (bufs) {
 			int curbuf = pipe->curbuf;
 			struct pipe_buffer *buf = pipe->bufs + curbuf;
-			struct pipe_buf_operations *ops = buf->ops;
+			const struct pipe_buf_operations *ops = buf->ops;
 			void *addr;
 			size_t chars = buf->len;
 			int error, atomic;
@@ -365,7 +365,7 @@
 		int lastbuf = (pipe->curbuf + pipe->nrbufs - 1) &
 							(PIPE_BUFFERS-1);
 		struct pipe_buffer *buf = pipe->bufs + lastbuf;
-		struct pipe_buf_operations *ops = buf->ops;
+		const struct pipe_buf_operations *ops = buf->ops;
 		int offset = buf->offset + buf->len;
 
 		if (ops->can_merge && offset + chars <= PAGE_SIZE) {
@@ -756,7 +756,7 @@
 	.fasync		= pipe_rdwr_fasync,
 };
 
-static struct file_operations read_pipe_fops = {
+static const struct file_operations read_pipe_fops = {
 	.llseek		= no_llseek,
 	.read		= do_sync_read,
 	.aio_read	= pipe_read,
@@ -768,7 +768,7 @@
 	.fasync		= pipe_read_fasync,
 };
 
-static struct file_operations write_pipe_fops = {
+static const struct file_operations write_pipe_fops = {
 	.llseek		= no_llseek,
 	.read		= bad_pipe_r,
 	.write		= do_sync_write,
@@ -780,7 +780,7 @@
 	.fasync		= pipe_write_fasync,
 };
 
-static struct file_operations rdwr_pipe_fops = {
+static const struct file_operations rdwr_pipe_fops = {
 	.llseek		= no_llseek,
 	.read		= do_sync_read,
 	.aio_read	= pipe_read,
diff --git a/fs/read_write.c b/fs/read_write.c
index 1d3dda4..707ac21 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -450,8 +450,6 @@
 	return seg;
 }
 
-EXPORT_UNUSED_SYMBOL(iov_shorten);  /*  June 2006  */
-
 ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
 		unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn)
 {
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index 97ae1b9..5296a29 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -135,7 +135,7 @@
 	int n;
 
 	*size = reiserfs_acl_size(acl->a_count);
-	ext_acl = (reiserfs_acl_header *) kmalloc(sizeof(reiserfs_acl_header) +
+	ext_acl = kmalloc(sizeof(reiserfs_acl_header) +
 						  acl->a_count *
 						  sizeof(reiserfs_acl_entry),
 						  GFP_NOFS);
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index 4af4cd7..84dfe3f 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -482,12 +482,13 @@
 	smb_close_socket(server);
 
 	if (server->conn_pid)
-		kill_proc(server->conn_pid, SIGTERM, 1);
+		kill_pid(server->conn_pid, SIGTERM, 1);
 
 	kfree(server->ops);
 	smb_unload_nls(server);
 	sb->s_fs_info = NULL;
 	smb_unlock_server(server);
+	put_pid(server->conn_pid);
 	kfree(server);
 }
 
@@ -530,7 +531,7 @@
 	INIT_LIST_HEAD(&server->xmitq);
 	INIT_LIST_HEAD(&server->recvq);
 	server->conn_error = 0;
-	server->conn_pid = 0;
+	server->conn_pid = NULL;
 	server->state = CONN_INVALID; /* no connection yet */
 	server->generation = 0;
 
diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c
index a5ced9e..feac460 100644
--- a/fs/smbfs/proc.c
+++ b/fs/smbfs/proc.c
@@ -877,7 +877,7 @@
 		goto out_putf;
 
 	server->sock_file = filp;
-	server->conn_pid = current->pid;
+	server->conn_pid = get_pid(task_pid(current));
 	server->opt = *opt;
 	server->generation += 1;
 	server->state = CONN_VALID;
@@ -971,8 +971,8 @@
 	}
 
 	VERBOSE("protocol=%d, max_xmit=%d, pid=%d capabilities=0x%x\n",
-		server->opt.protocol, server->opt.max_xmit, server->conn_pid,
-		server->opt.capabilities);
+		server->opt.protocol, server->opt.max_xmit,
+		pid_nr(server->conn_pid), server->opt.capabilities);
 
 	/* FIXME: this really should be done by smbmount. */
 	if (server->opt.max_xmit > SMB_MAX_PACKET_SIZE) {
diff --git a/fs/smbfs/smbiod.c b/fs/smbfs/smbiod.c
index e675404..89eaf31 100644
--- a/fs/smbfs/smbiod.c
+++ b/fs/smbfs/smbiod.c
@@ -152,7 +152,7 @@
 {
 	struct list_head *head;
 	struct smb_request *req;
-	pid_t pid = server->conn_pid;
+	struct pid *pid = get_pid(server->conn_pid);
 	int result = 0;
 
 	VERBOSE("state: %d\n", server->state);
@@ -222,7 +222,7 @@
 	/*
 	 * Note: use the "priv" flag, as a user process may need to reconnect.
 	 */
-	result = kill_proc(pid, SIGUSR1, 1);
+	result = kill_pid(pid, SIGUSR1, 1);
 	if (result) {
 		/* FIXME: this is most likely fatal, umount? */
 		printk(KERN_ERR "smb_retry: signal failed [%d]\n", result);
@@ -233,6 +233,7 @@
 	/* FIXME: The retried requests should perhaps get a "time boost". */
 
 out:
+	put_pid(pid);
 	return result;
 }
 
diff --git a/fs/splice.c b/fs/splice.c
index bbd0aeb..2fca6eb 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -42,7 +42,7 @@
 	struct partial_page *partial;	/* pages[] may not be contig */
 	int nr_pages;			/* number of pages in map */
 	unsigned int flags;		/* splice flags */
-	struct pipe_buf_operations *ops;/* ops associated with output pipe */
+	const struct pipe_buf_operations *ops;/* ops associated with output pipe */
 };
 
 /*
@@ -139,7 +139,7 @@
 	return err;
 }
 
-static struct pipe_buf_operations page_cache_pipe_buf_ops = {
+static const struct pipe_buf_operations page_cache_pipe_buf_ops = {
 	.can_merge = 0,
 	.map = generic_pipe_buf_map,
 	.unmap = generic_pipe_buf_unmap,
@@ -159,7 +159,7 @@
 	return generic_pipe_buf_steal(pipe, buf);
 }
 
-static struct pipe_buf_operations user_page_pipe_buf_ops = {
+static const struct pipe_buf_operations user_page_pipe_buf_ops = {
 	.can_merge = 0,
 	.map = generic_pipe_buf_map,
 	.unmap = generic_pipe_buf_unmap,
@@ -724,7 +724,7 @@
 	for (;;) {
 		if (pipe->nrbufs) {
 			struct pipe_buffer *buf = pipe->bufs + pipe->curbuf;
-			struct pipe_buf_operations *ops = buf->ops;
+			const struct pipe_buf_operations *ops = buf->ops;
 
 			sd.len = buf->len;
 			if (sd.len > sd.total_len)
diff --git a/include/asm-alpha/cacheflush.h b/include/asm-alpha/cacheflush.h
index 805640b..b686cc7 100644
--- a/include/asm-alpha/cacheflush.h
+++ b/include/asm-alpha/cacheflush.h
@@ -6,6 +6,7 @@
 /* Caches aren't brain-dead on the Alpha. */
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_dup_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_dcache_page(page)			do { } while (0)
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h
index f084564..378a3a2 100644
--- a/include/asm-arm/cacheflush.h
+++ b/include/asm-arm/cacheflush.h
@@ -319,6 +319,8 @@
 				unsigned long len, int write);
 #endif
 
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
+
 /*
  * flush_cache_user_range is used when we want to ensure that the
  * Harvard caches are synchronised for the user space address range.
diff --git a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h
index d9b8bdd..5014794 100644
--- a/include/asm-arm/thread_info.h
+++ b/include/asm-arm/thread_info.h
@@ -147,6 +147,7 @@
 #define TIF_POLLING_NRFLAG	16
 #define TIF_USING_IWMMXT	17
 #define TIF_MEMDIE		18
+#define TIF_FREEZE		19
 
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
@@ -154,6 +155,7 @@
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
 #define _TIF_USING_IWMMXT	(1 << TIF_USING_IWMMXT)
+#define _TIF_FREEZE		(1 << TIF_FREEZE)
 
 /*
  * Change these and you break ASM code in entry-common.S
diff --git a/include/asm-arm26/cacheflush.h b/include/asm-arm26/cacheflush.h
index 9c1b9c7..14ae15b 100644
--- a/include/asm-arm26/cacheflush.h
+++ b/include/asm-arm26/cacheflush.h
@@ -22,6 +22,7 @@
 
 #define flush_cache_all()                       do { } while (0)
 #define flush_cache_mm(mm)                      do { } while (0)
+#define flush_cache_dup_mm(mm)                  do { } while (0)
 #define flush_cache_range(vma,start,end)        do { } while (0)
 #define flush_cache_page(vma,vmaddr,pfn)        do { } while (0)
 #define flush_cache_vmap(start, end)		do { } while (0)
diff --git a/include/asm-avr32/cacheflush.h b/include/asm-avr32/cacheflush.h
index f1bf170..dfaaa88 100644
--- a/include/asm-avr32/cacheflush.h
+++ b/include/asm-avr32/cacheflush.h
@@ -87,6 +87,7 @@
  */
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_dup_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_cache_vmap(start, end)		do { } while (0)
diff --git a/include/asm-avr32/pgalloc.h b/include/asm-avr32/pgalloc.h
index 7492cfb..bb82e70 100644
--- a/include/asm-avr32/pgalloc.h
+++ b/include/asm-avr32/pgalloc.h
@@ -28,7 +28,7 @@
 static __inline__ pgd_t *pgd_alloc(struct mm_struct *mm)
 {
 	unsigned int pgd_size = (USER_PTRS_PER_PGD * sizeof(pgd_t));
-	pgd_t *pgd = (pgd_t *)kmalloc(pgd_size, GFP_KERNEL);
+	pgd_t *pgd = kmalloc(pgd_size, GFP_KERNEL);
 
 	if (pgd)
 		memset(pgd, 0, pgd_size);
diff --git a/include/asm-cris/cacheflush.h b/include/asm-cris/cacheflush.h
index 72cc71d..01af2de 100644
--- a/include/asm-cris/cacheflush.h
+++ b/include/asm-cris/cacheflush.h
@@ -9,6 +9,7 @@
  */
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_dup_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_dcache_page(page)			do { } while (0)
diff --git a/include/asm-frv/cacheflush.h b/include/asm-frv/cacheflush.h
index eaa5826..0250040 100644
--- a/include/asm-frv/cacheflush.h
+++ b/include/asm-frv/cacheflush.h
@@ -20,6 +20,7 @@
  */
 #define flush_cache_all()			do {} while(0)
 #define flush_cache_mm(mm)			do {} while(0)
+#define flush_cache_dup_mm(mm)			do {} while(0)
 #define flush_cache_range(mm, start, end)	do {} while(0)
 #define flush_cache_page(vma, vmaddr, pfn)	do {} while(0)
 #define flush_cache_vmap(start, end)		do {} while(0)
diff --git a/include/asm-frv/thread_info.h b/include/asm-frv/thread_info.h
index d66c48e..d881f51 100644
--- a/include/asm-frv/thread_info.h
+++ b/include/asm-frv/thread_info.h
@@ -116,6 +116,7 @@
 #define TIF_RESTORE_SIGMASK	6	/* restore signal mask in do_signal() */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17	/* OOM killer killed process */
+#define TIF_FREEZE		18	/* freezing for suspend */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
@@ -125,6 +126,7 @@
 #define _TIF_IRET		(1 << TIF_IRET)
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
+#define _TIF_FREEZE		(1 << TIF_FREEZE)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
diff --git a/include/asm-h8300/cacheflush.h b/include/asm-h8300/cacheflush.h
index 1e4d95b..71210d1 100644
--- a/include/asm-h8300/cacheflush.h
+++ b/include/asm-h8300/cacheflush.h
@@ -12,6 +12,7 @@
 
 #define flush_cache_all()
 #define	flush_cache_mm(mm)
+#define	flush_cache_dup_mm(mm)		do { } while (0)
 #define	flush_cache_range(vma,a,b)
 #define	flush_cache_page(vma,p,pfn)
 #define	flush_dcache_page(page)
diff --git a/include/asm-i386/cacheflush.h b/include/asm-i386/cacheflush.h
index 7199f7b..74e03c8 100644
--- a/include/asm-i386/cacheflush.h
+++ b/include/asm-i386/cacheflush.h
@@ -7,6 +7,7 @@
 /* Caches aren't brain-dead on the intel. */
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_dup_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_dcache_page(page)			do { } while (0)
diff --git a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
index 46d32ad..4b187bb 100644
--- a/include/asm-i386/thread_info.h
+++ b/include/asm-i386/thread_info.h
@@ -134,6 +134,7 @@
 #define TIF_MEMDIE		16
 #define TIF_DEBUG		17	/* uses debug registers */
 #define TIF_IO_BITMAP		18	/* uses I/O bitmap */
+#define TIF_FREEZE		19	/* is freezing for suspend */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
@@ -147,6 +148,7 @@
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_DEBUG		(1<<TIF_DEBUG)
 #define _TIF_IO_BITMAP		(1<<TIF_IO_BITMAP)
+#define _TIF_FREEZE		(1<<TIF_FREEZE)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK \
diff --git a/include/asm-ia64/cacheflush.h b/include/asm-ia64/cacheflush.h
index f2dacb4..4906916 100644
--- a/include/asm-ia64/cacheflush.h
+++ b/include/asm-ia64/cacheflush.h
@@ -18,6 +18,7 @@
 
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_dup_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_icache_page(vma,page)		do { } while (0)
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
index 8adcde0..9b505b2 100644
--- a/include/asm-ia64/thread_info.h
+++ b/include/asm-ia64/thread_info.h
@@ -88,6 +88,7 @@
 #define TIF_MEMDIE		17
 #define TIF_MCA_INIT		18	/* this task is processing MCA or INIT */
 #define TIF_DB_DISABLED		19	/* debug trap disabled for fsyscall */
+#define TIF_FREEZE		20	/* is freezing for suspend */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
@@ -98,6 +99,7 @@
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
 #define _TIF_MCA_INIT		(1 << TIF_MCA_INIT)
 #define _TIF_DB_DISABLED	(1 << TIF_DB_DISABLED)
+#define _TIF_FREEZE		(1 << TIF_FREEZE)
 
 /* "work to do on user-return" bits */
 #define TIF_ALLWORK_MASK	(_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
diff --git a/include/asm-m32r/cacheflush.h b/include/asm-m32r/cacheflush.h
index 8b261b4..56961a9 100644
--- a/include/asm-m32r/cacheflush.h
+++ b/include/asm-m32r/cacheflush.h
@@ -9,6 +9,7 @@
 #if defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104)
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_dup_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_dcache_page(page)			do { } while (0)
@@ -29,6 +30,7 @@
 #elif defined(CONFIG_CHIP_M32102)
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_dup_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_dcache_page(page)			do { } while (0)
@@ -41,6 +43,7 @@
 #else
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_dup_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_dcache_page(page)			do { } while (0)
diff --git a/include/asm-m68k/cacheflush.h b/include/asm-m68k/cacheflush.h
index 24d3ff4..16bf375 100644
--- a/include/asm-m68k/cacheflush.h
+++ b/include/asm-m68k/cacheflush.h
@@ -89,6 +89,8 @@
 		__flush_cache_030();
 }
 
+#define flush_cache_dup_mm(mm)			flush_cache_mm(mm)
+
 /* flush_cache_range/flush_cache_page must be macros to avoid
    a dependency on linux/mm.h, which includes this file... */
 static inline void flush_cache_range(struct vm_area_struct *vma,
diff --git a/include/asm-m68k/swim_iop.h b/include/asm-m68k/swim_iop.h
deleted file mode 100644
index f29b678..0000000
--- a/include/asm-m68k/swim_iop.h
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * SWIM access through the IOP
- * Written by Joshua M. Thompson
- */
-
-/* IOP number and channel number for the SWIM */
-
-#define SWIM_IOP	IOP_NUM_ISM
-#define SWIM_CHAN	1
-
-/* Command code: */
-
-#define CMD_INIT		0x01	/* Initialize                  */
-#define CMD_SHUTDOWN		0x02	/* Shutdown                    */
-#define CMD_START_POLL		0x03	/* Start insert/eject polling  */
-#define CMD_STOP_POLL		0x04	/* Stop insert/eject polling   */
-#define CMD_SETHFSTAG		0x05	/* Set HFS tag buffer address  */
-#define CMD_STATUS		0x06	/* Status                      */
-#define CMD_EJECT		0x07	/* Eject                       */
-#define CMD_FORMAT		0x08	/* Format                      */
-#define CMD_FORMAT_VERIFY	0x09	/* Format and Verify           */
-#define CMD_WRITE		0x0A	/* Write                       */
-#define CMD_READ		0x0B	/* Read                        */
-#define CMD_READ_VERIFY		0x0C	/* Read and Verify             */
-#define CMD_CACHE_CTRL		0x0D	/* Cache control               */
-#define CMD_TAGBUFF_CTRL	0x0E	/* Tag buffer control          */
-#define CMD_GET_ICON		0x0F	/* Get Icon                    */
-
-/* Drive types: */
-
-/* note: apple sez DRV_FDHD is 4, but I get back a type */
-/*       of 5 when I do a drive status check on my FDHD */
-
-#define	DRV_NONE	0	/* No drive             */
-#define	DRV_UNKNOWN	1	/* Unspecified drive    */
-#define	DRV_400K	2	/* 400K                 */
-#define	DRV_800K	3	/* 400K/800K            */
-#define	DRV_FDHD	5	/* 400K/800K/720K/1440K */
-#define	DRV_HD20	7	/* Apple HD20           */
-
-/* Format types: */
-
-#define	FMT_HD20	0x0001	/*  Apple HD20 */
-#define	FMT_400K	0x0002	/*  400K (GCR) */
-#define	FMT_800K	0x0004	/*  800K (GCR) */
-#define	FMT_720K	0x0008	/*  720K (MFM) */
-#define	FMT_1440K	0x0010	/* 1.44M (MFM) */
-
-#define	FMD_KIND_400K	1
-#define	FMD_KIND_800K	2
-#define	FMD_KIND_720K	3
-#define	FMD_KIND_1440K	1
-
-/* Icon Flags: */
-
-#define	ICON_MEDIA	0x01	/* Have IOP supply media icon */
-#define	ICON_DRIVE	0x01	/* Have IOP supply drive icon */
-
-/* Error codes: */
-
-#define	gcrOnMFMErr	-400	/* GCR (400/800K) on HD media */
-#define	verErr		-84	/* verify failed */
-#define	fmt2Err		-83	/* can't get enough sync during format */
-#define	fmt1Err		-82	/* can't find sector 0 after track format */
-#define	sectNFErr	-81	/* can't find sector */
-#define	seekErr		-80	/* drive error during seek */
-#define	spdAdjErr	-79	/* can't set drive speed */
-#define	twoSideErr	-78	/* drive is single-sided */
-#define	initIWMErr	-77	/* error during initialization */
-#define	tk0badErr	-76	/* track zero is bad */
-#define	cantStepErr	-75	/* drive error during step */
-#define	wrUnderrun	-74	/* write underrun occurred */
-#define	badDBtSlp	-73	/* bad data bitslip marks */
-#define	badDCksum	-72	/* bad data checksum */
-#define	noDtaMkErr	-71	/* can't find data mark */
-#define	badBtSlpErr	-70	/* bad address bitslip marks */
-#define	badCksmErr	-69	/* bad address-mark checksum */
-#define	dataVerErr	-68	/* read-verify failed */
-#define	noAdrMkErr	-67	/* can't find an address mark */
-#define	noNybErr	-66	/* no nybbles? disk is probably degaussed */
-#define	offLinErr	-65	/* no disk in drive */
-#define	noDriveErr	-64	/* drive isn't connected */
-#define	nsDrvErr	-56	/* no such drive */
-#define	paramErr	-50	/* bad positioning information */
-#define	wPrErr		-44	/* write protected */
-#define	openErr		-23	/* already initialized */
-
-#ifndef __ASSEMBLY__
-
-struct swim_drvstatus {
-	__u16	curr_track;	/* Current track number                   */
-	__u8	write_prot;	/* 0x80 if disk is write protected        */
-	__u8	disk_in_drive;	/* 0x01 or 0x02 if a disk is in the drive */
-	__u8	installed;	/* 0x01 if drive installed, 0xFF if not   */
-	__u8	num_sides;	/* 0x80 if two-sided format supported     */
-	__u8	two_sided;	/* 0xff if two-sided format diskette      */
-	__u8	new_interface;	/* 0x00 if old 400K drive, 0xFF if newer  */
-	__u16	errors;		/* Disk error count                       */
-	struct {		/* 32 bits */
-		__u16	reserved;
-		__u16	:4;
-		__u16	external:1;	/* Drive is external        */
-		__u16	scsi:1;		/* Drive is a SCSI drive    */
-		__u16	fixed:1;	/* Drive has fixed media    */
-		__u16	secondary:1;	/* Drive is secondary drive */
-		__u8	type;		/* Drive type               */
-	} info;
-	__u8	mfm_drive;	/* 0xFF if this is an FDHD drive    */
-	__u8	mfm_disk;	/* 0xFF if 720K/1440K (MFM) disk    */
-	__u8	mfm_format;	/* 0x00 if 720K, 0xFF if 1440K      */
-	__u8	ctlr_type;	/* 0x00 if IWM, 0xFF if SWIM        */
-	__u16	curr_format;	/* Current format type              */
-	__u16	allowed_fmt;	/* Allowed format types             */
-	__u32	num_blocks;	/* Number of blocks on disk         */
-	__u8	icon_flags;	/* Icon flags                       */
-	__u8	unusued;
-};
-
-/* Commands issued from the host to the IOP: */
-
-struct swimcmd_init {
-	__u8	code;		/* CMD_INIT */
-	__u8	unusued;
-	__u16	error;
-	__u8	drives[28];	/* drive type list */
-};
-
-struct swimcmd_startpoll {
-	__u8	code;		/* CMD_START_POLL */
-	__u8	unusued;
-	__u16	error;
-};
-
-struct swimcmd_sethfstag {
-	__u8	code;		/* CMD_SETHFSTAG */
-	__u8	unusued;
-	__u16	error;
-	caddr_t	tagbuf;		/* HFS tag buffer address */
-};
-
-struct swimcmd_status {
-	__u8	code;		/* CMD_STATUS */
-	__u8	drive_num;
-	__u16	error;
-	struct swim_drvstatus status;
-};
-
-struct swimcmd_eject {
-	__u8	code;		/* CMD_EJECT */
-	__u8	drive_num;
-	__u16	error;
-	struct swim_drvstatus status;
-};
-
-struct swimcmd_format {
-	__u8	code;		/* CMD_FORMAT */
-	__u8	drive_num;
-	__u16	error;
-	union {
-		struct {
-			__u16 fmt;	   /* format kind                  */
-			__u8  hdrbyte;	   /* fmt byte for hdr (0=default) */
-			__u8  interleave;  /* interleave (0 = default)     */
-			caddr_t	databuf;   /* sector data buff (0=default  */
-			caddr_t	tagbuf;	   /* tag data buffer (0=default)  */
-		} f;
-		struct swim_drvstatus status;
-	} p;
-};
-
-struct swimcmd_fmtverify {
-	__u8	code;		/* CMD_FORMAT_VERIFY */
-	__u8	drive_num;
-	__u16	error;
-};
-
-struct swimcmd_rw {
-	__u8	code;		/* CMD_READ, CMD_WRITE or CMD_READ_VERIFY */
-	__u8	drive_num;
-	__u16	error;
-	caddr_t	buffer;		/* R/W buffer address */
-	__u32	first_block;	/* Starting block     */
-	__u32	num_blocks;	/* Number of blocks   */
-	__u8	tag[12];	/* tag data           */
-};
-
-struct swimcmd_cachectl {
-	__u8	code;		/* CMD_CACHE_CTRL */
-	__u8	unused;
-	__u16	error;
-	__u8	enable;		/* Nonzero to enable cache                */
-	__u8	install;	/* +1 = install, -1 = remove, 0 = neither */
-};
-
-struct swimcmd_tagbufctl {
-	__u8	code;		/* CMD_TAGBUFF_CTRL */
-	__u8	unused;
-	__u16	error;
-	caddr_t	buf;		/* buffer address or 0 to disable */
-};
-
-struct swimcmd_geticon {
-	__u8	code;		/* CMD_GET_ICON */
-	__u8	drive_num;
-	__u16	error;
-	caddr_t	buffer;		/* Nuffer address */
-	__u16	kind;		/* 0 = media icon, 1 = drive icon */
-	__u16	unused;
-	__u16	max_bytes;	/* maximum  byte count */
-};
-
-/* Messages from the SWIM IOP to the host CPU: */
-
-struct swimmsg_status {
-	__u8	code;		/* 1 = insert, 2 = eject, 3 = status changed */
-	__u8	drive_num;
-	__u16	error;
-	struct swim_drvstatus status;
-};
-
-#endif /* __ASSEMBLY__ */
diff --git a/include/asm-m68knommu/cacheflush.h b/include/asm-m68knommu/cacheflush.h
index c3aadf3..163dcb1 100644
--- a/include/asm-m68knommu/cacheflush.h
+++ b/include/asm-m68knommu/cacheflush.h
@@ -8,6 +8,7 @@
 
 #define flush_cache_all()			__flush_cache_all()
 #define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_dup_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	__flush_cache_all()
 #define flush_cache_page(vma, vmaddr)		do { } while (0)
 #define flush_dcache_range(start,len)		__flush_cache_all()
diff --git a/include/asm-mips/cacheflush.h b/include/asm-mips/cacheflush.h
index e3c9925..0ddada3 100644
--- a/include/asm-mips/cacheflush.h
+++ b/include/asm-mips/cacheflush.h
@@ -17,6 +17,7 @@
  *
  *  - flush_cache_all() flushes entire cache
  *  - flush_cache_mm(mm) flushes the specified mm context's cache lines
+ *  - flush_cache_dup mm(mm) handles cache flushing when forking
  *  - flush_cache_page(mm, vmaddr, pfn) flushes a single page
  *  - flush_cache_range(vma, start, end) flushes a range of pages
  *  - flush_icache_range(start, end) flush a range of instructions
@@ -31,6 +32,7 @@
 extern void (*flush_cache_all)(void);
 extern void (*__flush_cache_all)(void);
 extern void (*flush_cache_mm)(struct mm_struct *mm);
+#define flush_cache_dup_mm(mm)	do { (void) (mm); } while (0)
 extern void (*flush_cache_range)(struct vm_area_struct *vma,
 	unsigned long start, unsigned long end);
 extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn);
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index 0dc1a45..2f9e1a9 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -35,7 +35,6 @@
 #ifndef __ASSEMBLY__
 
 #include <linux/pfn.h>
-#include <asm/cpu-features.h>
 #include <asm/io.h>
 
 extern void clear_page(void * page);
@@ -61,16 +60,13 @@
 		flush_data_cache_page((unsigned long)addr);
 }
 
-static inline void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
-	struct page *to)
-{
-	extern void (*flush_data_cache_page)(unsigned long addr);
+extern void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
+	struct page *to);
+struct vm_area_struct;
+extern void copy_user_highpage(struct page *to, struct page *from,
+	unsigned long vaddr, struct vm_area_struct *vma);
 
-	copy_page(vto, vfrom);
-	if (!cpu_has_ic_fills_f_dc ||
-	    pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK))
-		flush_data_cache_page((unsigned long)vto);
-}
+#define __HAVE_ARCH_COPY_USER_HIGHPAGE
 
 /*
  * These are used to make use of C type-checking..
diff --git a/include/asm-parisc/cacheflush.h b/include/asm-parisc/cacheflush.h
index 2bc41f2..aedb051 100644
--- a/include/asm-parisc/cacheflush.h
+++ b/include/asm-parisc/cacheflush.h
@@ -15,6 +15,8 @@
 #define flush_cache_mm(mm) flush_cache_all_local()
 #endif
 
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
+
 #define flush_kernel_dcache_range(start,size) \
 	flush_kernel_dcache_range_asm((start), (start)+(size));
 
diff --git a/include/asm-powerpc/cacheflush.h b/include/asm-powerpc/cacheflush.h
index 8a740c8..08e93e7 100644
--- a/include/asm-powerpc/cacheflush.h
+++ b/include/asm-powerpc/cacheflush.h
@@ -18,6 +18,7 @@
  */
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_dup_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_icache_page(vma, page)		do { } while (0)
diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h
index d339e2e..3f32ca8 100644
--- a/include/asm-powerpc/thread_info.h
+++ b/include/asm-powerpc/thread_info.h
@@ -122,6 +122,7 @@
 #define TIF_RESTOREALL		12	/* Restore all regs (implies NOERROR) */
 #define TIF_NOERROR		14	/* Force successful syscall return */
 #define TIF_RESTORE_SIGMASK	15	/* Restore signal mask in do_signal */
+#define TIF_FREEZE		16	/* Freezing for suspend */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -138,6 +139,7 @@
 #define _TIF_RESTOREALL		(1<<TIF_RESTOREALL)
 #define _TIF_NOERROR		(1<<TIF_NOERROR)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
+#define _TIF_FREEZE		(1<<TIF_FREEZE)
 #define _TIF_SYSCALL_T_OR_A	(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
 
 #define _TIF_USER_WORK_MASK	(_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
diff --git a/include/asm-s390/cacheflush.h b/include/asm-s390/cacheflush.h
index e399a8b..f7cade8 100644
--- a/include/asm-s390/cacheflush.h
+++ b/include/asm-s390/cacheflush.h
@@ -7,6 +7,7 @@
 /* Caches aren't brain-dead on the s390. */
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_dup_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_dcache_page(page)			do { } while (0)
diff --git a/include/asm-sh/cpu-sh2/cacheflush.h b/include/asm-sh/cpu-sh2/cacheflush.h
index f556fa8..2979efb 100644
--- a/include/asm-sh/cpu-sh2/cacheflush.h
+++ b/include/asm-sh/cpu-sh2/cacheflush.h
@@ -15,6 +15,7 @@
  *
  *  - flush_cache_all() flushes entire cache
  *  - flush_cache_mm(mm) flushes the specified mm context's cache lines
+ *  - flush_cache_dup mm(mm) handles cache flushing when forking
  *  - flush_cache_page(mm, vmaddr, pfn) flushes a single page
  *  - flush_cache_range(vma, start, end) flushes a range of pages
  *
@@ -27,6 +28,7 @@
  */
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_dup_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_dcache_page(page)			do { } while (0)
diff --git a/include/asm-sh/cpu-sh3/cacheflush.h b/include/asm-sh/cpu-sh3/cacheflush.h
index 03fde97..f70d8ef7 100644
--- a/include/asm-sh/cpu-sh3/cacheflush.h
+++ b/include/asm-sh/cpu-sh3/cacheflush.h
@@ -15,6 +15,7 @@
  *
  *  - flush_cache_all() flushes entire cache
  *  - flush_cache_mm(mm) flushes the specified mm context's cache lines
+ *  - flush_cache_dup mm(mm) handles cache flushing when forking
  *  - flush_cache_page(mm, vmaddr, pfn) flushes a single page
  *  - flush_cache_range(vma, start, end) flushes a range of pages
  *
@@ -39,6 +40,7 @@
 
 void flush_cache_all(void);
 void flush_cache_mm(struct mm_struct *mm);
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
 void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
                               unsigned long end);
 void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn);
@@ -48,6 +50,7 @@
 #else
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_dup_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_dcache_page(page)			do { } while (0)
diff --git a/include/asm-sh/cpu-sh4/cacheflush.h b/include/asm-sh/cpu-sh4/cacheflush.h
index 515fd57..b01a10f 100644
--- a/include/asm-sh/cpu-sh4/cacheflush.h
+++ b/include/asm-sh/cpu-sh4/cacheflush.h
@@ -18,6 +18,7 @@
  */
 void flush_cache_all(void);
 void flush_cache_mm(struct mm_struct *mm);
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
 void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
 		       unsigned long end);
 void flush_cache_page(struct vm_area_struct *vma, unsigned long addr,
diff --git a/include/asm-sh/thread_info.h b/include/asm-sh/thread_info.h
index 0c01dc5..879f741 100644
--- a/include/asm-sh/thread_info.h
+++ b/include/asm-sh/thread_info.h
@@ -106,6 +106,7 @@
 #define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
 #define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		18
+#define TIF_FREEZE		19
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
@@ -114,6 +115,7 @@
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+#define _TIF_FREEZE		(1<<TIF_FREEZE)
 
 #define _TIF_WORK_MASK		0x000000FE	/* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK	0x000000FF	/* work to do on any return to u-space */
diff --git a/include/asm-sh64/cacheflush.h b/include/asm-sh64/cacheflush.h
index 55f71aa..1e53a47 100644
--- a/include/asm-sh64/cacheflush.h
+++ b/include/asm-sh64/cacheflush.h
@@ -21,6 +21,8 @@
 				    struct page *page, unsigned long addr,
 				    int len);
 
+#define flush_cache_dup_mm(mm)	flush_cache_mm(mm)
+
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
 
diff --git a/include/asm-sh64/pgalloc.h b/include/asm-sh64/pgalloc.h
index b29dd46..cb803e5 100644
--- a/include/asm-sh64/pgalloc.h
+++ b/include/asm-sh64/pgalloc.h
@@ -41,7 +41,7 @@
 static inline pgd_t *get_pgd_slow(void)
 {
 	unsigned int pgd_size = (USER_PTRS_PER_PGD * sizeof(pgd_t));
-	pgd_t *ret = (pgd_t *)kmalloc(pgd_size, GFP_KERNEL);
+	pgd_t *ret = kmalloc(pgd_size, GFP_KERNEL);
 	return ret;
 }
 
diff --git a/include/asm-sparc/cacheflush.h b/include/asm-sparc/cacheflush.h
index fc632f8..68ac109 100644
--- a/include/asm-sparc/cacheflush.h
+++ b/include/asm-sparc/cacheflush.h
@@ -48,6 +48,7 @@
 
 #define flush_cache_all() BTFIXUP_CALL(flush_cache_all)()
 #define flush_cache_mm(mm) BTFIXUP_CALL(flush_cache_mm)(mm)
+#define flush_cache_dup_mm(mm) BTFIXUP_CALL(flush_cache_mm)(mm)
 #define flush_cache_range(vma,start,end) BTFIXUP_CALL(flush_cache_range)(vma,start,end)
 #define flush_cache_page(vma,addr,pfn) BTFIXUP_CALL(flush_cache_page)(vma,addr)
 #define flush_icache_range(start, end)		do { } while (0)
diff --git a/include/asm-sparc64/cacheflush.h b/include/asm-sparc64/cacheflush.h
index 745d1ab..122e405 100644
--- a/include/asm-sparc64/cacheflush.h
+++ b/include/asm-sparc64/cacheflush.h
@@ -12,6 +12,7 @@
 /* These are the same regardless of whether this is an SMP kernel or not. */
 #define flush_cache_mm(__mm) \
 	do { if ((__mm) == current->mm) flushw_user(); } while(0)
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
 #define flush_cache_range(vma, start, end) \
 	flush_cache_mm((vma)->vm_mm)
 #define flush_cache_page(vma, page, pfn) \
diff --git a/include/asm-v850/cacheflush.h b/include/asm-v850/cacheflush.h
index e1a87f8..9ece05a 100644
--- a/include/asm-v850/cacheflush.h
+++ b/include/asm-v850/cacheflush.h
@@ -24,6 +24,7 @@
    systems with MMUs, so we don't need them.  */
 #define flush_cache_all()			((void)0)
 #define flush_cache_mm(mm)			((void)0)
+#define flush_cache_dup_mm(mm)			((void)0)
 #define flush_cache_range(vma, start, end)	((void)0)
 #define flush_cache_page(vma, vmaddr, pfn)	((void)0)
 #define flush_dcache_page(page)			((void)0)
diff --git a/include/asm-x86_64/cacheflush.h b/include/asm-x86_64/cacheflush.h
index d32f7f5..ab1cb5c 100644
--- a/include/asm-x86_64/cacheflush.h
+++ b/include/asm-x86_64/cacheflush.h
@@ -7,6 +7,7 @@
 /* Caches aren't brain-dead on the intel. */
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_dup_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_dcache_page(page)			do { } while (0)
diff --git a/include/asm-x86_64/thread_info.h b/include/asm-x86_64/thread_info.h
index 787a081..74a6c74 100644
--- a/include/asm-x86_64/thread_info.h
+++ b/include/asm-x86_64/thread_info.h
@@ -122,6 +122,7 @@
 #define TIF_MEMDIE		20
 #define TIF_DEBUG		21	/* uses debug registers */
 #define TIF_IO_BITMAP		22	/* uses I/O bitmap */
+#define TIF_FREEZE		23	/* is freezing for suspend */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
@@ -137,6 +138,7 @@
 #define _TIF_ABI_PENDING	(1<<TIF_ABI_PENDING)
 #define _TIF_DEBUG		(1<<TIF_DEBUG)
 #define _TIF_IO_BITMAP		(1<<TIF_IO_BITMAP)
+#define _TIF_FREEZE		(1<<TIF_FREEZE)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK \
diff --git a/include/asm-xtensa/cacheflush.h b/include/asm-xtensa/cacheflush.h
index 337765b..22ef901 100644
--- a/include/asm-xtensa/cacheflush.h
+++ b/include/asm-xtensa/cacheflush.h
@@ -75,6 +75,7 @@
 
 #define flush_cache_all()		__flush_invalidate_cache_all();
 #define flush_cache_mm(mm)		__flush_invalidate_cache_all();
+#define flush_cache_dup_mm(mm)		__flush_invalidate_cache_all();
 
 #define flush_cache_vmap(start,end)	__flush_invalidate_cache_all();
 #define flush_cache_vunmap(start,end)	__flush_invalidate_cache_all();
@@ -88,6 +89,7 @@
 
 #define flush_cache_all()				do { } while (0)
 #define flush_cache_mm(mm)				do { } while (0)
+#define flush_cache_dup_mm(mm)				do { } while (0)
 
 #define flush_cache_vmap(start,end)			do { } while (0)
 #define flush_cache_vunmap(start,end)			do { } while (0)
diff --git a/include/asm-xtensa/termbits.h b/include/asm-xtensa/termbits.h
index c780593..057b9a3 100644
--- a/include/asm-xtensa/termbits.h
+++ b/include/asm-xtensa/termbits.h
@@ -30,6 +30,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct ktermios {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 /* c_cc characters */
 
 #define VINTR 0
diff --git a/include/asm-xtensa/uaccess.h b/include/asm-xtensa/uaccess.h
index 88a64e1..d6352da0 100644
--- a/include/asm-xtensa/uaccess.h
+++ b/include/asm-xtensa/uaccess.h
@@ -23,7 +23,6 @@
 
 #ifdef __ASSEMBLY__
 
-#define _ASMLANGUAGE
 #include <asm/current.h>
 #include <asm/asm-offsets.h>
 #include <asm/processor.h>
diff --git a/include/linux/aio.h b/include/linux/aio.h
index 3372ec6..a30ef13 100644
--- a/include/linux/aio.h
+++ b/include/linux/aio.h
@@ -105,6 +105,7 @@
 	wait_queue_t		ki_wait;
 	loff_t			ki_pos;
 
+	atomic_t		ki_bio_count;	/* num bio used for this iocb */
 	void			*private;
 	/* State that we remember to be able to restart/retry  */
 	unsigned short		ki_opcode;
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 092dbd0..08daf32 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -309,6 +309,7 @@
 				gfp_t);
 extern void bio_set_pages_dirty(struct bio *bio);
 extern void bio_check_pages_dirty(struct bio *bio);
+extern void bio_release_pages(struct bio *bio);
 extern struct bio *bio_copy_user(struct request_queue *, unsigned long, unsigned int, int);
 extern int bio_uncopy_user(struct bio *);
 void zero_fill_bio(struct bio *bio);
diff --git a/include/linux/coda_linux.h b/include/linux/coda_linux.h
index be512cc..4c2632a 100644
--- a/include/linux/coda_linux.h
+++ b/include/linux/coda_linux.h
@@ -64,7 +64,7 @@
 
 #define CODA_ALLOC(ptr, cast, size) do { \
     if (size < PAGE_SIZE) \
-        ptr = (cast)kmalloc((unsigned long) size, GFP_KERNEL); \
+        ptr = kmalloc((unsigned long) size, GFP_KERNEL); \
     else \
         ptr = (cast)vmalloc((unsigned long) size); \
     if (!ptr) \
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index 8821e1f..826b15e 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -30,10 +30,19 @@
 		nodes_subset((nodes), current->mems_allowed)
 int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl);
 
-extern int __cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask);
-static int inline cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask)
+extern int __cpuset_zone_allowed_softwall(struct zone *z, gfp_t gfp_mask);
+extern int __cpuset_zone_allowed_hardwall(struct zone *z, gfp_t gfp_mask);
+
+static int inline cpuset_zone_allowed_softwall(struct zone *z, gfp_t gfp_mask)
 {
-	return number_of_cpusets <= 1 || __cpuset_zone_allowed(z, gfp_mask);
+	return number_of_cpusets <= 1 ||
+		__cpuset_zone_allowed_softwall(z, gfp_mask);
+}
+
+static int inline cpuset_zone_allowed_hardwall(struct zone *z, gfp_t gfp_mask)
+{
+	return number_of_cpusets <= 1 ||
+		__cpuset_zone_allowed_hardwall(z, gfp_mask);
 }
 
 extern int cpuset_excl_nodes_overlap(const struct task_struct *p);
@@ -94,7 +103,12 @@
 	return 1;
 }
 
-static inline int cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask)
+static inline int cpuset_zone_allowed_softwall(struct zone *z, gfp_t gfp_mask)
+{
+	return 1;
+}
+
+static inline int cpuset_zone_allowed_hardwall(struct zone *z, gfp_t gfp_mask)
 {
 	return 1;
 }
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 6fe56aa..64177ec 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -929,8 +929,6 @@
 #define FB_MODE_IS_FIRST	16
 #define FB_MODE_IS_FROM_VAR     32
 
-extern int fbmon_valid_timings(u_int pixclock, u_int htotal, u_int vtotal,
-			       const struct fb_info *fb_info);
 extern int fbmon_dpms(const struct fb_info *fb_info);
 extern int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var,
 		       struct fb_info *info);
diff --git a/include/linux/freezer.h b/include/linux/freezer.h
index 3930630..5e75e26 100644
--- a/include/linux/freezer.h
+++ b/include/linux/freezer.h
@@ -16,16 +16,15 @@
  */
 static inline int freezing(struct task_struct *p)
 {
-	return p->flags & PF_FREEZE;
+	return test_tsk_thread_flag(p, TIF_FREEZE);
 }
 
 /*
  * Request that a process be frozen
- * FIXME: SMP problem. We may not modify other process' flags!
  */
 static inline void freeze(struct task_struct *p)
 {
-	p->flags |= PF_FREEZE;
+	set_tsk_thread_flag(p, TIF_FREEZE);
 }
 
 /*
@@ -33,7 +32,7 @@
  */
 static inline void do_not_freeze(struct task_struct *p)
 {
-	p->flags &= ~PF_FREEZE;
+	clear_tsk_thread_flag(p, TIF_FREEZE);
 }
 
 /*
@@ -54,7 +53,9 @@
  */
 static inline void frozen_process(struct task_struct *p)
 {
-	p->flags = (p->flags & ~PF_FREEZE) | PF_FROZEN;
+	p->flags |= PF_FROZEN;
+	wmb();
+	clear_tsk_thread_flag(p, TIF_FREEZE);
 }
 
 extern void refrigerator(void);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index adce6e1..186da81 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -120,6 +120,7 @@
 #define MS_PRIVATE	(1<<18)	/* change to private */
 #define MS_SLAVE	(1<<19)	/* change to slave */
 #define MS_SHARED	(1<<20)	/* change to shared */
+#define MS_RELATIME	(1<<21)	/* Update atime relative to mtime/ctime. */
 #define MS_ACTIVE	(1<<30)
 #define MS_NOUSER	(1<<31)
 
diff --git a/include/linux/gameport.h b/include/linux/gameport.h
index 2cdba0c..afad952 100644
--- a/include/linux/gameport.h
+++ b/include/linux/gameport.h
@@ -105,7 +105,7 @@
 
 static inline struct gameport *gameport_allocate_port(void)
 {
-	struct gameport *gameport = kcalloc(1, sizeof(struct gameport), GFP_KERNEL);
+	struct gameport *gameport = kzalloc(sizeof(struct gameport), GFP_KERNEL);
 
 	return gameport;
 }
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index 3d8768b..ca9a602 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -96,7 +96,10 @@
 	kunmap_atomic(kaddr, KM_USER0);
 }
 
-static inline void copy_user_highpage(struct page *to, struct page *from, unsigned long vaddr)
+#ifndef __HAVE_ARCH_COPY_USER_HIGHPAGE
+
+static inline void copy_user_highpage(struct page *to, struct page *from,
+	unsigned long vaddr, struct vm_area_struct *vma)
 {
 	char *vfrom, *vto;
 
@@ -109,6 +112,8 @@
 	smp_wmb();
 }
 
+#endif
+
 static inline void copy_highpage(struct page *to, struct page *from)
 {
 	char *vfrom, *vto;
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index 7ae3c332..d38778f 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -142,7 +142,6 @@
 #define I2C_DRIVERID_MTP008 1023
 #define I2C_DRIVERID_DS1621 1024
 #define I2C_DRIVERID_ADM1024 1025
-#define I2C_DRIVERID_IT87 1026
 #define I2C_DRIVERID_CH700X 1027 /* single driver for CH7003-7009 digital pc to tv encoders */
 #define I2C_DRIVERID_FSCPOS 1028
 #define I2C_DRIVERID_FSCSCY 1029
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index b531515..6383d2d 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -75,7 +75,6 @@
 	.pid_ns		= &init_pid_ns,					\
 	.count		= ATOMIC_INIT(1),				\
 	.nslock		= __SPIN_LOCK_UNLOCKED(nsproxy.nslock),		\
-	.id		= 0,						\
 	.uts_ns		= &init_uts_ns,					\
 	.mnt_ns		= NULL,						\
 	INIT_IPC_NS(ipc_ns)						\
diff --git a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h
index aa50d89..246de1d 100644
--- a/include/linux/lockd/bind.h
+++ b/include/linux/lockd/bind.h
@@ -23,7 +23,7 @@
  * This is the set of functions for lockd->nfsd communication
  */
 struct nlmsvc_binding {
-	u32			(*fopen)(struct svc_rqst *,
+	__be32			(*fopen)(struct svc_rqst *,
 						struct nfs_fh *,
 						struct file **);
 	void			(*fclose)(struct file *);
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index 0c962b8..ac25b56 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -191,7 +191,7 @@
 unsigned long	  nlmsvc_retry_blocked(void);
 void		  nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *,
 					nlm_host_match_fn_t match);
-void		  nlmsvc_grant_reply(struct nlm_cookie *, u32);
+void		  nlmsvc_grant_reply(struct nlm_cookie *, __be32);
 
 /*
  * File handling for the server personality
diff --git a/include/linux/lockd/sm_inter.h b/include/linux/lockd/sm_inter.h
index fc61d40..22a6458 100644
--- a/include/linux/lockd/sm_inter.h
+++ b/include/linux/lockd/sm_inter.h
@@ -24,7 +24,7 @@
  * Arguments for all calls to statd
  */
 struct nsm_args {
-	u32		addr;		/* remote address */
+	__be32		addr;		/* remote address */
 	u32		prog;		/* RPC callback info */
 	u32		vers;
 	u32		proc;
diff --git a/include/linux/lockd/xdr.h b/include/linux/lockd/xdr.h
index 29e7d9f..83a1f9f 100644
--- a/include/linux/lockd/xdr.h
+++ b/include/linux/lockd/xdr.h
@@ -69,7 +69,7 @@
  */
 struct nlm_res {
 	struct nlm_cookie	cookie;
-	u32			status;
+	__be32			status;
 	struct nlm_lock		lock;
 };
 
@@ -80,9 +80,9 @@
 	char *		mon;
 	int		len;
 	u32		state;
-	u32		addr;
-	u32		vers;
-	u32		proto;
+	__be32		addr;
+	__be32		vers;
+	__be32		proto;
 };
 
 /*
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index 498bfbd..ea097dd 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -281,15 +281,25 @@
 #if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_GENERIC_HARDIRQS)
 extern void early_init_irq_lock_class(void);
 #else
-# define early_init_irq_lock_class()		do { } while (0)
+static inline void early_init_irq_lock_class(void)
+{
+}
 #endif
 
 #ifdef CONFIG_TRACE_IRQFLAGS
 extern void early_boot_irqs_off(void);
 extern void early_boot_irqs_on(void);
+extern void print_irqtrace_events(struct task_struct *curr);
 #else
-# define early_boot_irqs_off()			do { } while (0)
-# define early_boot_irqs_on()			do { } while (0)
+static inline void early_boot_irqs_off(void)
+{
+}
+static inline void early_boot_irqs_on(void)
+{
+}
+static inline void print_irqtrace_events(struct task_struct *curr)
+{
+}
 #endif
 
 /*
diff --git a/include/linux/mount.h b/include/linux/mount.h
index e357dc8..1b7e178 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -27,6 +27,7 @@
 #define MNT_NOEXEC	0x04
 #define MNT_NOATIME	0x08
 #define MNT_NODIRATIME	0x10
+#define MNT_RELATIME	0x20
 
 #define MNT_SHRINKABLE	0x100
 
diff --git a/include/linux/n_r3964.h b/include/linux/n_r3964.h
index db4f377..de24af7 100644
--- a/include/linux/n_r3964.h
+++ b/include/linux/n_r3964.h
@@ -116,7 +116,7 @@
 
 struct r3964_client_info {
 	spinlock_t     lock;
-	pid_t          pid;
+	struct pid    *pid;
 	unsigned int   sig_flags;
 
 	struct r3964_client_info *next;
diff --git a/include/linux/ncp_mount.h b/include/linux/ncp_mount.h
index f46bddc..a2b549e 100644
--- a/include/linux/ncp_mount.h
+++ b/include/linux/ncp_mount.h
@@ -75,7 +75,7 @@
 	unsigned int	 int_flags;	/* internal flags */
 #define NCP_IMOUNT_LOGGEDIN_POSSIBLE	0x0001
 	__kernel_uid32_t mounted_uid;	/* Who may umount() this filesystem? */
-	__kernel_pid_t   wdog_pid;		/* Who cares for our watchdog packets? */
+	struct pid      *wdog_pid;	/* Who cares for our watchdog packets? */
 	unsigned int     ncp_fd;	/* The socket to the ncp port */
 	unsigned int     time_out;	/* How long should I wait after
 					   sending a NCP request? */
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index edb54c3..0727774 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -275,12 +275,12 @@
  * we might process an operation with side effects, and be unable to
  * tell the client that the operation succeeded.
  *
- * COMPOUND_SLACK_SPACE - this is the minimum amount of buffer space
+ * COMPOUND_SLACK_SPACE - this is the minimum bytes of buffer space
  * needed to encode an "ordinary" _successful_ operation.  (GETATTR,
  * READ, READDIR, and READLINK have their own buffer checks.)  if we
  * fall below this level, we fail the next operation with NFS4ERR_RESOURCE.
  *
- * COMPOUND_ERR_SLACK_SPACE - this is the minimum amount of buffer space
+ * COMPOUND_ERR_SLACK_SPACE - this is the minimum bytes of buffer space
  * needed to encode an operation which has failed with NFS4ERR_RESOURCE.
  * care is taken to ensure that we never fall below this level for any
  * reason.
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index c3673f4..ab5c236 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -273,7 +273,6 @@
 	((err) != nfserr_stale_stateid) &&      \
 	((err) != nfserr_bad_stateid))
 
-extern __be32 nfsd4_renew(clientid_t *clid);
 extern __be32 nfs4_preprocess_stateid_op(struct svc_fh *current_fh,
 		stateid_t *stateid, int flags, struct file **filp);
 extern void nfs4_lock_state(void);
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index 45ca01b..09799bc 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -44,6 +44,12 @@
 #define NFSD4_MAX_TAGLEN	128
 #define XDR_LEN(n)                     (((n) + 3) & ~3)
 
+struct nfsd4_compound_state {
+	struct svc_fh current_fh;
+	struct svc_fh save_fh;
+	struct nfs4_stateowner *replay_owner;
+};
+
 struct nfsd4_change_info {
 	u32		atomic;
 	u32		before_ctime_sec;
@@ -430,35 +436,39 @@
 		       struct dentry *dentry, __be32 *buffer, int *countp,
 		       u32 *bmval, struct svc_rqst *);
 extern __be32 nfsd4_setclientid(struct svc_rqst *rqstp,
+		struct nfsd4_compound_state *,
 		struct nfsd4_setclientid *setclid);
 extern __be32 nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+		struct nfsd4_compound_state *,
 		struct nfsd4_setclientid_confirm *setclientid_confirm);
 extern __be32 nfsd4_process_open1(struct nfsd4_open *open);
 extern __be32 nfsd4_process_open2(struct svc_rqst *rqstp,
 		struct svc_fh *current_fh, struct nfsd4_open *open);
 extern __be32 nfsd4_open_confirm(struct svc_rqst *rqstp,
-		struct svc_fh *current_fh, struct nfsd4_open_confirm *oc,
-		struct nfs4_stateowner **);
-extern __be32 nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh,
-		struct nfsd4_close *close,
-		struct nfs4_stateowner **replay_owner);
+		struct nfsd4_compound_state *, struct nfsd4_open_confirm *oc);
+extern __be32 nfsd4_close(struct svc_rqst *rqstp,
+		struct nfsd4_compound_state *,
+		struct nfsd4_close *close);
 extern __be32 nfsd4_open_downgrade(struct svc_rqst *rqstp,
-		struct svc_fh *current_fh, struct nfsd4_open_downgrade *od,
-		struct nfs4_stateowner **replay_owner);
-extern __be32 nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh,
-		struct nfsd4_lock *lock,
-		struct nfs4_stateowner **replay_owner);
-extern __be32 nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh,
+		struct nfsd4_compound_state *,
+		struct nfsd4_open_downgrade *od);
+extern __be32 nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *,
+		struct nfsd4_lock *lock);
+extern __be32 nfsd4_lockt(struct svc_rqst *rqstp,
+		struct nfsd4_compound_state *,
 		struct nfsd4_lockt *lockt);
-extern __be32 nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh,
-		struct nfsd4_locku *locku,
-		struct nfs4_stateowner **replay_owner);
+extern __be32 nfsd4_locku(struct svc_rqst *rqstp,
+		struct nfsd4_compound_state *,
+		struct nfsd4_locku *locku);
 extern __be32
 nfsd4_release_lockowner(struct svc_rqst *rqstp,
+		struct nfsd4_compound_state *,
 		struct nfsd4_release_lockowner *rlockowner);
 extern void nfsd4_release_compoundargs(struct nfsd4_compoundargs *);
 extern __be32 nfsd4_delegreturn(struct svc_rqst *rqstp,
-		struct svc_fh *current_fh, struct nfsd4_delegreturn *dr);
+		struct nfsd4_compound_state *, struct nfsd4_delegreturn *dr);
+extern __be32 nfsd4_renew(struct svc_rqst *rqstp,
+			  struct nfsd4_compound_state *, clientid_t *clid);
 #endif
 
 /*
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index fdfb0e4..0b9f0dc 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -24,7 +24,6 @@
 struct nsproxy {
 	atomic_t count;
 	spinlock_t nslock;
-	unsigned long id;
 	struct uts_namespace *uts_ns;
 	struct ipc_namespace *ipc_ns;
 	struct mnt_namespace *mnt_ns;
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 51180db..95c1e74 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2067,6 +2067,10 @@
 #define PCI_DEVICE_ID_JMICRON_JMB366	0x2366
 #define PCI_DEVICE_ID_JMICRON_JMB368	0x2368
 
+#define PCI_VENDOR_ID_KORENIX		0x1982
+#define PCI_DEVICE_ID_KORENIX_JETCARDF0	0x1600
+#define PCI_DEVICE_ID_KORENIX_JETCARDF1	0x16ff
+
 #define PCI_VENDOR_ID_TEKRAM		0x1de1
 #define PCI_DEVICE_ID_TEKRAM_DC290	0xdc29
 
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index ea4f7cd..2e19478 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -12,7 +12,7 @@
 struct pipe_buffer {
 	struct page *page;
 	unsigned int offset, len;
-	struct pipe_buf_operations *ops;
+	const struct pipe_buf_operations *ops;
 	unsigned int flags;
 };
 
@@ -41,9 +41,7 @@
 struct pipe_inode_info {
 	wait_queue_head_t wait;
 	unsigned int nrbufs, curbuf;
-	struct pipe_buffer bufs[PIPE_BUFFERS];
 	struct page *tmp_page;
-	unsigned int start;
 	unsigned int readers;
 	unsigned int writers;
 	unsigned int waiting_writers;
@@ -52,6 +50,7 @@
 	struct fasync_struct *fasync_readers;
 	struct fasync_struct *fasync_writers;
 	struct inode *inode;
+	struct pipe_buffer bufs[PIPE_BUFFERS];
 };
 
 /* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 20f47b8..8bbd459 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -39,7 +39,7 @@
 
 extern struct platform_device *platform_device_alloc(const char *name, unsigned int id);
 extern int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num);
-extern int platform_device_add_data(struct platform_device *pdev, void *data, size_t size);
+extern int platform_device_add_data(struct platform_device *pdev, const void *data, size_t size);
 extern int platform_device_add(struct platform_device *pdev);
 extern void platform_device_del(struct platform_device *pdev);
 extern void platform_device_put(struct platform_device *pdev);
diff --git a/include/linux/reciprocal_div.h b/include/linux/reciprocal_div.h
new file mode 100644
index 0000000..f9c90b3
--- /dev/null
+++ b/include/linux/reciprocal_div.h
@@ -0,0 +1,32 @@
+#ifndef _LINUX_RECIPROCAL_DIV_H
+#define _LINUX_RECIPROCAL_DIV_H
+
+#include <linux/types.h>
+
+/*
+ * This file describes reciprocical division.
+ *
+ * This optimizes the (A/B) problem, when A and B are two u32
+ * and B is a known value (but not known at compile time)
+ *
+ * The math principle used is :
+ *   Let RECIPROCAL_VALUE(B) be (((1LL << 32) + (B - 1))/ B)
+ *   Then A / B = (u32)(((u64)(A) * (R)) >> 32)
+ *
+ * This replaces a divide by a multiply (and a shift), and
+ * is generally less expensive in CPU cycles.
+ */
+
+/*
+ * Computes the reciprocal value (R) for the value B of the divisor.
+ * Should not be called before each reciprocal_divide(),
+ * or else the performance is slower than a normal divide.
+ */
+extern u32 reciprocal_value(u32 B);
+
+
+static inline u32 reciprocal_divide(u32 A, u32 R)
+{
+	return (u32)(((u64)A * R) >> 32);
+}
+#endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index ea92e5c..4463735 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1144,7 +1144,6 @@
 #define PF_MEMALLOC	0x00000800	/* Allocating memory */
 #define PF_FLUSHER	0x00001000	/* responsible for disk writeback */
 #define PF_USED_MATH	0x00002000	/* if unset the fpu must be initialized before use */
-#define PF_FREEZE	0x00004000	/* this task is being frozen for suspend now */
 #define PF_NOFREEZE	0x00008000	/* this thread should not be frozen */
 #define PF_FROZEN	0x00010000	/* frozen for system suspend */
 #define PF_FSTRANS	0x00020000	/* inside a filesystem transaction */
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 2271886..1ef822e 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -1,7 +1,9 @@
 /*
- * linux/include/linux/slab.h
- * Written by Mark Hemment, 1996.
- * (markhe@nextd.demon.co.uk)
+ * Written by Mark Hemment, 1996 (markhe@nextd.demon.co.uk).
+ *
+ * (C) SGI 2006, Christoph Lameter <clameter@sgi.com>
+ * 	Cleaned up and restructured to ease the addition of alternative
+ * 	implementations of SLAB allocators.
  */
 
 #ifndef _LINUX_SLAB_H
@@ -10,64 +12,95 @@
 #ifdef __KERNEL__
 
 #include <linux/gfp.h>
-#include <linux/init.h>
 #include <linux/types.h>
-#include <asm/page.h>		/* kmalloc_sizes.h needs PAGE_SIZE */
-#include <asm/cache.h>		/* kmalloc_sizes.h needs L1_CACHE_BYTES */
-#include <linux/compiler.h>
 
-/* kmem_cache_t exists for legacy reasons and is not used by code in mm */
 typedef struct kmem_cache kmem_cache_t __deprecated;
 
-/* flags to pass to kmem_cache_create().
- * The first 3 are only valid when the allocator as been build
- * SLAB_DEBUG_SUPPORT.
+/*
+ * Flags to pass to kmem_cache_create().
+ * The ones marked DEBUG are only valid if CONFIG_SLAB_DEBUG is set.
  */
-#define	SLAB_DEBUG_FREE		0x00000100UL	/* Peform (expensive) checks on free */
-#define	SLAB_DEBUG_INITIAL	0x00000200UL	/* Call constructor (as verifier) */
-#define	SLAB_RED_ZONE		0x00000400UL	/* Red zone objs in a cache */
-#define	SLAB_POISON		0x00000800UL	/* Poison objects */
-#define	SLAB_HWCACHE_ALIGN	0x00002000UL	/* align objs on a h/w cache lines */
-#define SLAB_CACHE_DMA		0x00004000UL	/* use GFP_DMA memory */
-#define SLAB_MUST_HWCACHE_ALIGN	0x00008000UL	/* force alignment */
-#define SLAB_STORE_USER		0x00010000UL	/* store the last owner for bug hunting */
-#define SLAB_RECLAIM_ACCOUNT	0x00020000UL	/* track pages allocated to indicate
-						   what is reclaimable later*/
-#define SLAB_PANIC		0x00040000UL	/* panic if kmem_cache_create() fails */
-#define SLAB_DESTROY_BY_RCU	0x00080000UL	/* defer freeing pages to RCU */
+#define SLAB_DEBUG_FREE		0x00000100UL	/* DEBUG: Perform (expensive) checks on free */
+#define SLAB_DEBUG_INITIAL	0x00000200UL	/* DEBUG: Call constructor (as verifier) */
+#define SLAB_RED_ZONE		0x00000400UL	/* DEBUG: Red zone objs in a cache */
+#define SLAB_POISON		0x00000800UL	/* DEBUG: Poison objects */
+#define SLAB_HWCACHE_ALIGN	0x00002000UL	/* Align objs on cache lines */
+#define SLAB_CACHE_DMA		0x00004000UL	/* Use GFP_DMA memory */
+#define SLAB_MUST_HWCACHE_ALIGN	0x00008000UL	/* Force alignment even if debuggin is active */
+#define SLAB_STORE_USER		0x00010000UL	/* DEBUG: Store the last owner for bug hunting */
+#define SLAB_RECLAIM_ACCOUNT	0x00020000UL	/* Objects are reclaimable */
+#define SLAB_PANIC		0x00040000UL	/* Panic if kmem_cache_create() fails */
+#define SLAB_DESTROY_BY_RCU	0x00080000UL	/* Defer freeing slabs to RCU */
 #define SLAB_MEM_SPREAD		0x00100000UL	/* Spread some memory over cpuset */
 
-/* flags passed to a constructor func */
-#define	SLAB_CTOR_CONSTRUCTOR	0x001UL		/* if not set, then deconstructor */
-#define SLAB_CTOR_ATOMIC	0x002UL		/* tell constructor it can't sleep */
-#define	SLAB_CTOR_VERIFY	0x004UL		/* tell constructor it's a verify call */
+/* Flags passed to a constructor functions */
+#define SLAB_CTOR_CONSTRUCTOR	0x001UL		/* If not set, then deconstructor */
+#define SLAB_CTOR_ATOMIC	0x002UL		/* Tell constructor it can't sleep */
+#define SLAB_CTOR_VERIFY	0x004UL		/* Tell constructor it's a verify call */
 
-#ifndef CONFIG_SLOB
+/*
+ * struct kmem_cache related prototypes
+ */
+void __init kmem_cache_init(void);
+extern int slab_is_available(void);
 
-/* prototypes */
-extern void __init kmem_cache_init(void);
-
-extern struct kmem_cache *kmem_cache_create(const char *, size_t, size_t,
+struct kmem_cache *kmem_cache_create(const char *, size_t, size_t,
 			unsigned long,
 			void (*)(void *, struct kmem_cache *, unsigned long),
 			void (*)(void *, struct kmem_cache *, unsigned long));
-extern void kmem_cache_destroy(struct kmem_cache *);
-extern int kmem_cache_shrink(struct kmem_cache *);
-extern void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
-extern void *kmem_cache_zalloc(struct kmem_cache *, gfp_t);
-extern void kmem_cache_free(struct kmem_cache *, void *);
-extern unsigned int kmem_cache_size(struct kmem_cache *);
-extern const char *kmem_cache_name(struct kmem_cache *);
+void kmem_cache_destroy(struct kmem_cache *);
+int kmem_cache_shrink(struct kmem_cache *);
+void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
+void *kmem_cache_zalloc(struct kmem_cache *, gfp_t);
+void kmem_cache_free(struct kmem_cache *, void *);
+unsigned int kmem_cache_size(struct kmem_cache *);
+const char *kmem_cache_name(struct kmem_cache *);
+int kmem_ptr_validate(struct kmem_cache *cachep, const void *ptr);
 
-/* Size description struct for general caches. */
-struct cache_sizes {
-	size_t		 	cs_size;
-	struct kmem_cache	*cs_cachep;
-	struct kmem_cache	*cs_dmacachep;
-};
-extern struct cache_sizes malloc_sizes[];
+#ifdef CONFIG_NUMA
+extern void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
+#else
+static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep,
+					gfp_t flags, int node)
+{
+	return kmem_cache_alloc(cachep, flags);
+}
+#endif
 
-extern void *__kmalloc(size_t, gfp_t);
+/*
+ * Common kmalloc functions provided by all allocators
+ */
+void *__kmalloc(size_t, gfp_t);
+void *__kzalloc(size_t, gfp_t);
+void kfree(const void *);
+unsigned int ksize(const void *);
+
+/**
+ * kcalloc - allocate memory for an array. The memory is set to zero.
+ * @n: number of elements.
+ * @size: element size.
+ * @flags: the type of memory to allocate.
+ */
+static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
+{
+	if (n != 0 && size > ULONG_MAX / n)
+		return NULL;
+	return __kzalloc(n * size, flags);
+}
+
+/*
+ * Allocator specific definitions. These are mainly used to establish optimized
+ * ways to convert kmalloc() calls to kmem_cache_alloc() invocations by selecting
+ * the appropriate general cache at compile time.
+ */
+
+#ifdef CONFIG_SLAB
+#include <linux/slab_def.h>
+#else
+/*
+ * Fallback definitions for an allocator not wanting to provide
+ * its own optimized kmalloc definitions (like SLOB).
+ */
 
 /**
  * kmalloc - allocate memory
@@ -116,27 +149,32 @@
  */
 static inline void *kmalloc(size_t size, gfp_t flags)
 {
-	if (__builtin_constant_p(size)) {
-		int i = 0;
-#define CACHE(x) \
-		if (size <= x) \
-			goto found; \
-		else \
-			i++;
-#include "kmalloc_sizes.h"
-#undef CACHE
-		{
-			extern void __you_cannot_kmalloc_that_much(void);
-			__you_cannot_kmalloc_that_much();
-		}
-found:
-		return kmem_cache_alloc((flags & GFP_DMA) ?
-			malloc_sizes[i].cs_dmacachep :
-			malloc_sizes[i].cs_cachep, flags);
-	}
 	return __kmalloc(size, flags);
 }
 
+/**
+ * kzalloc - allocate memory. The memory is set to zero.
+ * @size: how many bytes of memory are required.
+ * @flags: the type of memory to allocate (see kmalloc).
+ */
+static inline void *kzalloc(size_t size, gfp_t flags)
+{
+	return __kzalloc(size, flags);
+}
+#endif
+
+#ifndef CONFIG_NUMA
+static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
+{
+	return kmalloc(size, flags);
+}
+
+static inline void *__kmalloc_node(size_t size, gfp_t flags, int node)
+{
+	return __kmalloc(size, flags);
+}
+#endif /* !CONFIG_NUMA */
+
 /*
  * kmalloc_track_caller is a special version of kmalloc that records the
  * calling function of the routine calling it for slab leak tracking instead
@@ -145,89 +183,16 @@
  * allocator where we care about the real place the memory allocation
  * request comes from.
  */
-#ifndef CONFIG_DEBUG_SLAB
-#define kmalloc_track_caller(size, flags) \
-	__kmalloc(size, flags)
-#else
+#ifdef CONFIG_DEBUG_SLAB
 extern void *__kmalloc_track_caller(size_t, gfp_t, void*);
 #define kmalloc_track_caller(size, flags) \
 	__kmalloc_track_caller(size, flags, __builtin_return_address(0))
-#endif
-
-extern void *__kzalloc(size_t, gfp_t);
-
-/**
- * kzalloc - allocate memory. The memory is set to zero.
- * @size: how many bytes of memory are required.
- * @flags: the type of memory to allocate (see kmalloc).
- */
-static inline void *kzalloc(size_t size, gfp_t flags)
-{
-	if (__builtin_constant_p(size)) {
-		int i = 0;
-#define CACHE(x) \
-		if (size <= x) \
-			goto found; \
-		else \
-			i++;
-#include "kmalloc_sizes.h"
-#undef CACHE
-		{
-			extern void __you_cannot_kzalloc_that_much(void);
-			__you_cannot_kzalloc_that_much();
-		}
-found:
-		return kmem_cache_zalloc((flags & GFP_DMA) ?
-			malloc_sizes[i].cs_dmacachep :
-			malloc_sizes[i].cs_cachep, flags);
-	}
-	return __kzalloc(size, flags);
-}
-
-/**
- * kcalloc - allocate memory for an array. The memory is set to zero.
- * @n: number of elements.
- * @size: element size.
- * @flags: the type of memory to allocate.
- */
-static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
-{
-	if (n != 0 && size > ULONG_MAX / n)
-		return NULL;
-	return kzalloc(n * size, flags);
-}
-
-extern void kfree(const void *);
-extern unsigned int ksize(const void *);
-extern int slab_is_available(void);
+#else
+#define kmalloc_track_caller(size, flags) \
+	__kmalloc(size, flags)
+#endif /* DEBUG_SLAB */
 
 #ifdef CONFIG_NUMA
-extern void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
-extern void *__kmalloc_node(size_t size, gfp_t flags, int node);
-
-static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
-{
-	if (__builtin_constant_p(size)) {
-		int i = 0;
-#define CACHE(x) \
-		if (size <= x) \
-			goto found; \
-		else \
-			i++;
-#include "kmalloc_sizes.h"
-#undef CACHE
-		{
-			extern void __you_cannot_kmalloc_that_much(void);
-			__you_cannot_kmalloc_that_much();
-		}
-found:
-		return kmem_cache_alloc_node((flags & GFP_DMA) ?
-			malloc_sizes[i].cs_dmacachep :
-			malloc_sizes[i].cs_cachep, flags, node);
-	}
-	return __kmalloc_node(size, flags, node);
-}
-
 /*
  * kmalloc_node_track_caller is a special version of kmalloc_node that
  * records the calling function of the routine calling it for slab leak
@@ -236,70 +201,23 @@
  * standard allocator where we care about the real place the memory
  * allocation request comes from.
  */
-#ifndef CONFIG_DEBUG_SLAB
-#define kmalloc_node_track_caller(size, flags, node) \
-	__kmalloc_node(size, flags, node)
-#else
+#ifdef CONFIG_DEBUG_SLAB
 extern void *__kmalloc_node_track_caller(size_t, gfp_t, int, void *);
 #define kmalloc_node_track_caller(size, flags, node) \
 	__kmalloc_node_track_caller(size, flags, node, \
 			__builtin_return_address(0))
+#else
+#define kmalloc_node_track_caller(size, flags, node) \
+	__kmalloc_node(size, flags, node)
 #endif
+
 #else /* CONFIG_NUMA */
-static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep,
-					gfp_t flags, int node)
-{
-	return kmem_cache_alloc(cachep, flags);
-}
-static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
-{
-	return kmalloc(size, flags);
-}
 
 #define kmalloc_node_track_caller(size, flags, node) \
 	kmalloc_track_caller(size, flags)
-#endif
 
-extern int FASTCALL(kmem_cache_reap(int));
-extern int FASTCALL(kmem_ptr_validate(struct kmem_cache *cachep, void *ptr));
-
-#else /* CONFIG_SLOB */
-
-/* SLOB allocator routines */
-
-void kmem_cache_init(void);
-struct kmem_cache *kmem_cache_create(const char *c, size_t, size_t,
-	unsigned long,
-	void (*)(void *, struct kmem_cache *, unsigned long),
-	void (*)(void *, struct kmem_cache *, unsigned long));
-void kmem_cache_destroy(struct kmem_cache *c);
-void *kmem_cache_alloc(struct kmem_cache *c, gfp_t flags);
-void *kmem_cache_zalloc(struct kmem_cache *, gfp_t);
-void kmem_cache_free(struct kmem_cache *c, void *b);
-const char *kmem_cache_name(struct kmem_cache *);
-void *kmalloc(size_t size, gfp_t flags);
-void *__kzalloc(size_t size, gfp_t flags);
-void kfree(const void *m);
-unsigned int ksize(const void *m);
-unsigned int kmem_cache_size(struct kmem_cache *c);
-
-static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
-{
-	return __kzalloc(n * size, flags);
-}
-
-#define kmem_cache_shrink(d) (0)
-#define kmem_cache_reap(a)
-#define kmem_ptr_validate(a, b) (0)
-#define kmem_cache_alloc_node(c, f, n) kmem_cache_alloc(c, f)
-#define kmalloc_node(s, f, n) kmalloc(s, f)
-#define kzalloc(s, f) __kzalloc(s, f)
-#define kmalloc_track_caller kmalloc
-
-#define kmalloc_node_track_caller kmalloc_node
-
-#endif /* CONFIG_SLOB */
+#endif /* DEBUG_SLAB */
 
 #endif	/* __KERNEL__ */
-
 #endif	/* _LINUX_SLAB_H */
+
diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h
new file mode 100644
index 0000000..4b463e6
--- /dev/null
+++ b/include/linux/slab_def.h
@@ -0,0 +1,100 @@
+#ifndef _LINUX_SLAB_DEF_H
+#define	_LINUX_SLAB_DEF_H
+
+/*
+ * Definitions unique to the original Linux SLAB allocator.
+ *
+ * What we provide here is a way to optimize the frequent kmalloc
+ * calls in the kernel by selecting the appropriate general cache
+ * if kmalloc was called with a size that can be established at
+ * compile time.
+ */
+
+#include <linux/init.h>
+#include <asm/page.h>		/* kmalloc_sizes.h needs PAGE_SIZE */
+#include <asm/cache.h>		/* kmalloc_sizes.h needs L1_CACHE_BYTES */
+#include <linux/compiler.h>
+
+/* Size description struct for general caches. */
+struct cache_sizes {
+	size_t		 	cs_size;
+	struct kmem_cache	*cs_cachep;
+	struct kmem_cache	*cs_dmacachep;
+};
+extern struct cache_sizes malloc_sizes[];
+
+static inline void *kmalloc(size_t size, gfp_t flags)
+{
+	if (__builtin_constant_p(size)) {
+		int i = 0;
+#define CACHE(x) \
+		if (size <= x) \
+			goto found; \
+		else \
+			i++;
+#include "kmalloc_sizes.h"
+#undef CACHE
+		{
+			extern void __you_cannot_kmalloc_that_much(void);
+			__you_cannot_kmalloc_that_much();
+		}
+found:
+		return kmem_cache_alloc((flags & GFP_DMA) ?
+			malloc_sizes[i].cs_dmacachep :
+			malloc_sizes[i].cs_cachep, flags);
+	}
+	return __kmalloc(size, flags);
+}
+
+static inline void *kzalloc(size_t size, gfp_t flags)
+{
+	if (__builtin_constant_p(size)) {
+		int i = 0;
+#define CACHE(x) \
+		if (size <= x) \
+			goto found; \
+		else \
+			i++;
+#include "kmalloc_sizes.h"
+#undef CACHE
+		{
+			extern void __you_cannot_kzalloc_that_much(void);
+			__you_cannot_kzalloc_that_much();
+		}
+found:
+		return kmem_cache_zalloc((flags & GFP_DMA) ?
+			malloc_sizes[i].cs_dmacachep :
+			malloc_sizes[i].cs_cachep, flags);
+	}
+	return __kzalloc(size, flags);
+}
+
+#ifdef CONFIG_NUMA
+extern void *__kmalloc_node(size_t size, gfp_t flags, int node);
+
+static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
+{
+	if (__builtin_constant_p(size)) {
+		int i = 0;
+#define CACHE(x) \
+		if (size <= x) \
+			goto found; \
+		else \
+			i++;
+#include "kmalloc_sizes.h"
+#undef CACHE
+		{
+			extern void __you_cannot_kmalloc_that_much(void);
+			__you_cannot_kmalloc_that_much();
+		}
+found:
+		return kmem_cache_alloc_node((flags & GFP_DMA) ?
+			malloc_sizes[i].cs_dmacachep :
+			malloc_sizes[i].cs_cachep, flags, node);
+	}
+	return __kmalloc_node(size, flags, node);
+}
+
+#endif	/* CONFIG_NUMA */
+
+#endif	/* _LINUX_SLAB_DEF_H */
diff --git a/include/linux/smb_fs_sb.h b/include/linux/smb_fs_sb.h
index 5b4ae2c..3aa97aa 100644
--- a/include/linux/smb_fs_sb.h
+++ b/include/linux/smb_fs_sb.h
@@ -55,7 +55,7 @@
 	 * generation is incremented.
 	 */
 	unsigned int generation;
-	pid_t conn_pid;
+	struct pid *conn_pid;
 	struct smb_conn_opt opt;
 	wait_queue_head_t conn_wq;
 	int conn_complete;
diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h
index 9df8833..98a1d8c 100644
--- a/include/linux/sysrq.h
+++ b/include/linux/sysrq.h
@@ -37,23 +37,37 @@
 
 #ifdef CONFIG_MAGIC_SYSRQ
 
+extern int sysrq_on(void);
+
+/*
+ * Do not use this one directly:
+ */
+extern int __sysrq_enabled;
+
 /* Generic SysRq interface -- you may call it from any device driver, supplying
  * ASCII code of the key, pointer to registers and kbd/tty structs (if they
  * are available -- else NULL's).
  */
 
-void handle_sysrq(int, struct tty_struct *);
-void __handle_sysrq(int, struct tty_struct *, int check_mask);
-int register_sysrq_key(int, struct sysrq_key_op *);
-int unregister_sysrq_key(int, struct sysrq_key_op *);
+void handle_sysrq(int key, struct tty_struct *tty);
+void __handle_sysrq(int key, struct tty_struct *tty, int check_mask);
+int register_sysrq_key(int key, struct sysrq_key_op *op);
+int unregister_sysrq_key(int key, struct sysrq_key_op *op);
 struct sysrq_key_op *__sysrq_get_key_op(int key);
 
 #else
 
+static inline int sysrq_on(void)
+{
+	return 0;
+}
 static inline int __reterr(void)
 {
 	return -EINVAL;
 }
+static inline void handle_sysrq(int key, struct tty_struct *tty)
+{
+}
 
 #define register_sysrq_key(ig,nore) __reterr()
 #define unregister_sysrq_key(ig,nore) __reterr()
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 10a3eec..41456c1 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -739,13 +739,13 @@
 struct hci_filter {
 	unsigned long type_mask;
 	unsigned long event_mask[2];
-	__u16   opcode;
+	__le16   opcode;
 };
 
 struct hci_ufilter {
 	__u32   type_mask;
 	__u32   event_mask[2];
-	__u16   opcode;
+	__le16   opcode;
 };
 
 #define HCI_FLT_TYPE_BITS	31
diff --git a/include/video/sstfb.h b/include/video/sstfb.h
index 5dbf5e7..baa163f 100644
--- a/include/video/sstfb.h
+++ b/include/video/sstfb.h
@@ -119,7 +119,7 @@
 #define BACKPORCH		0x0208
 #define VIDEODIMENSIONS		0x020c
 #define FBIINIT0		0x0210		/* misc+fifo  controls */
-#  define EN_VGA_PASSTHROUGH	  BIT(0)
+#  define DIS_VGA_PASSTHROUGH	  BIT(0)
 #  define FBI_RESET		  BIT(1)
 #  define FIFO_RESET		  BIT(2)
 #define FBIINIT1		0x0214		/* PCI + video controls */
@@ -251,7 +251,7 @@
 #  define DACREG_ICS_CLK1_A	  0	/* bit4 */
 
 /* sst default init registers */
-#define FBIINIT0_DEFAULT EN_VGA_PASSTHROUGH
+#define FBIINIT0_DEFAULT DIS_VGA_PASSTHROUGH
 
 #define FBIINIT1_DEFAULT 	\
 	(			\
@@ -296,6 +296,11 @@
  *
  */
 
+/* ioctl to enable/disable VGA passthrough */
+#define SSTFB_SET_VGAPASS	_IOW('F', 0xdd, __u32)
+#define SSTFB_GET_VGAPASS	_IOR('F', 0xdd, __u32)
+
+
 /* used to know witch clock to set */
 enum {
 	VID_CLOCK=0,
@@ -317,7 +322,7 @@
 };
 
 struct dac_switch {
-	char * name;
+	const char *name;
 	int (*detect) (struct fb_info *info);
 	int (*set_pll) (struct fb_info *info, const struct pll_timing *t, const int clock);
 	void (*set_vidmod) (struct fb_info *info, const int bpp);
@@ -345,7 +350,7 @@
 	struct pci_dev		*dev;
 	int	type;
 	u8	revision;
-	int	gfx_clock;	/* status */
+	u8	vgapass;	/* VGA pass through: 1=enabled, 0=disabled */
 };
 
 #endif /* _SSTFB_H_ */
diff --git a/ipc/msgutil.c b/ipc/msgutil.c
index 0992616..c82c215 100644
--- a/ipc/msgutil.c
+++ b/ipc/msgutil.c
@@ -36,7 +36,7 @@
 	if (alen > DATALEN_MSG)
 		alen = DATALEN_MSG;
 
-	msg = (struct msg_msg *)kmalloc(sizeof(*msg) + alen, GFP_KERNEL);
+	msg = kmalloc(sizeof(*msg) + alen, GFP_KERNEL);
 	if (msg == NULL)
 		return ERR_PTR(-ENOMEM);
 
@@ -56,7 +56,7 @@
 		alen = len;
 		if (alen > DATALEN_SEG)
 			alen = DATALEN_SEG;
-		seg = (struct msg_msgseg *)kmalloc(sizeof(*seg) + alen,
+		seg = kmalloc(sizeof(*seg) + alen,
 						 GFP_KERNEL);
 		if (seg == NULL) {
 			err = -ENOMEM;
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 2c3b443..232aed2 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -2342,32 +2342,48 @@
 }
 
 /**
- * cpuset_zone_allowed - Can we allocate memory on zone z's memory node?
+ * cpuset_zone_allowed_softwall - Can we allocate on zone z's memory node?
  * @z: is this zone on an allowed node?
- * @gfp_mask: memory allocation flags (we use __GFP_HARDWALL)
+ * @gfp_mask: memory allocation flags
  *
- * If we're in interrupt, yes, we can always allocate.  If zone
+ * If we're in interrupt, yes, we can always allocate.  If
+ * __GFP_THISNODE is set, yes, we can always allocate.  If zone
  * z's node is in our tasks mems_allowed, yes.  If it's not a
  * __GFP_HARDWALL request and this zone's nodes is in the nearest
  * mem_exclusive cpuset ancestor to this tasks cpuset, yes.
  * Otherwise, no.
  *
+ * If __GFP_HARDWALL is set, cpuset_zone_allowed_softwall()
+ * reduces to cpuset_zone_allowed_hardwall().  Otherwise,
+ * cpuset_zone_allowed_softwall() might sleep, and might allow a zone
+ * from an enclosing cpuset.
+ *
+ * cpuset_zone_allowed_hardwall() only handles the simpler case of
+ * hardwall cpusets, and never sleeps.
+ *
+ * The __GFP_THISNODE placement logic is really handled elsewhere,
+ * by forcibly using a zonelist starting at a specified node, and by
+ * (in get_page_from_freelist()) refusing to consider the zones for
+ * any node on the zonelist except the first.  By the time any such
+ * calls get to this routine, we should just shut up and say 'yes'.
+ *
  * GFP_USER allocations are marked with the __GFP_HARDWALL bit,
  * and do not allow allocations outside the current tasks cpuset.
  * GFP_KERNEL allocations are not so marked, so can escape to the
- * nearest mem_exclusive ancestor cpuset.
+ * nearest enclosing mem_exclusive ancestor cpuset.
  *
- * Scanning up parent cpusets requires callback_mutex.  The __alloc_pages()
- * routine only calls here with __GFP_HARDWALL bit _not_ set if
- * it's a GFP_KERNEL allocation, and all nodes in the current tasks
- * mems_allowed came up empty on the first pass over the zonelist.
- * So only GFP_KERNEL allocations, if all nodes in the cpuset are
- * short of memory, might require taking the callback_mutex mutex.
+ * Scanning up parent cpusets requires callback_mutex.  The
+ * __alloc_pages() routine only calls here with __GFP_HARDWALL bit
+ * _not_ set if it's a GFP_KERNEL allocation, and all nodes in the
+ * current tasks mems_allowed came up empty on the first pass over
+ * the zonelist.  So only GFP_KERNEL allocations, if all nodes in the
+ * cpuset are short of memory, might require taking the callback_mutex
+ * mutex.
  *
  * The first call here from mm/page_alloc:get_page_from_freelist()
- * has __GFP_HARDWALL set in gfp_mask, enforcing hardwall cpusets, so
- * no allocation on a node outside the cpuset is allowed (unless in
- * interrupt, of course).
+ * has __GFP_HARDWALL set in gfp_mask, enforcing hardwall cpusets,
+ * so no allocation on a node outside the cpuset is allowed (unless
+ * in interrupt, of course).
  *
  * The second pass through get_page_from_freelist() doesn't even call
  * here for GFP_ATOMIC calls.  For those calls, the __alloc_pages()
@@ -2380,12 +2396,12 @@
  *	GFP_USER     - only nodes in current tasks mems allowed ok.
  *
  * Rule:
- *    Don't call cpuset_zone_allowed() if you can't sleep, unless you
+ *    Don't call cpuset_zone_allowed_softwall if you can't sleep, unless you
  *    pass in the __GFP_HARDWALL flag set in gfp_flag, which disables
  *    the code that might scan up ancestor cpusets and sleep.
- **/
+ */
 
-int __cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask)
+int __cpuset_zone_allowed_softwall(struct zone *z, gfp_t gfp_mask)
 {
 	int node;			/* node that zone z is on */
 	const struct cpuset *cs;	/* current cpuset ancestors */
@@ -2415,6 +2431,40 @@
 	return allowed;
 }
 
+/*
+ * cpuset_zone_allowed_hardwall - Can we allocate on zone z's memory node?
+ * @z: is this zone on an allowed node?
+ * @gfp_mask: memory allocation flags
+ *
+ * If we're in interrupt, yes, we can always allocate.
+ * If __GFP_THISNODE is set, yes, we can always allocate.  If zone
+ * z's node is in our tasks mems_allowed, yes.   Otherwise, no.
+ *
+ * The __GFP_THISNODE placement logic is really handled elsewhere,
+ * by forcibly using a zonelist starting at a specified node, and by
+ * (in get_page_from_freelist()) refusing to consider the zones for
+ * any node on the zonelist except the first.  By the time any such
+ * calls get to this routine, we should just shut up and say 'yes'.
+ *
+ * Unlike the cpuset_zone_allowed_softwall() variant, above,
+ * this variant requires that the zone be in the current tasks
+ * mems_allowed or that we're in interrupt.  It does not scan up the
+ * cpuset hierarchy for the nearest enclosing mem_exclusive cpuset.
+ * It never sleeps.
+ */
+
+int __cpuset_zone_allowed_hardwall(struct zone *z, gfp_t gfp_mask)
+{
+	int node;			/* node that zone z is on */
+
+	if (in_interrupt() || (gfp_mask & __GFP_THISNODE))
+		return 1;
+	node = zone_to_nid(z);
+	if (node_isset(node, current->mems_allowed))
+		return 1;
+	return 0;
+}
+
 /**
  * cpuset_lock - lock out any changes to cpuset structures
  *
diff --git a/kernel/fork.c b/kernel/fork.c
index d16c566..fc723e5 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -203,7 +203,7 @@
 	struct mempolicy *pol;
 
 	down_write(&oldmm->mmap_sem);
-	flush_cache_mm(oldmm);
+	flush_cache_dup_mm(oldmm);
 	/*
 	 * Not linked in yet - no deadlock potential:
 	 */
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index b020324..01e7505 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -43,13 +43,49 @@
 #include "lockdep_internals.h"
 
 /*
- * hash_lock: protects the lockdep hashes and class/list/hash allocators.
+ * lockdep_lock: protects the lockdep graph, the hashes and the
+ *               class/list/hash allocators.
  *
  * This is one of the rare exceptions where it's justified
  * to use a raw spinlock - we really dont want the spinlock
- * code to recurse back into the lockdep code.
+ * code to recurse back into the lockdep code...
  */
-static raw_spinlock_t hash_lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
+static raw_spinlock_t lockdep_lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
+
+static int graph_lock(void)
+{
+	__raw_spin_lock(&lockdep_lock);
+	/*
+	 * Make sure that if another CPU detected a bug while
+	 * walking the graph we dont change it (while the other
+	 * CPU is busy printing out stuff with the graph lock
+	 * dropped already)
+	 */
+	if (!debug_locks) {
+		__raw_spin_unlock(&lockdep_lock);
+		return 0;
+	}
+	return 1;
+}
+
+static inline int graph_unlock(void)
+{
+	__raw_spin_unlock(&lockdep_lock);
+	return 0;
+}
+
+/*
+ * Turn lock debugging off and return with 0 if it was off already,
+ * and also release the graph lock:
+ */
+static inline int debug_locks_off_graph_unlock(void)
+{
+	int ret = debug_locks_off();
+
+	__raw_spin_unlock(&lockdep_lock);
+
+	return ret;
+}
 
 static int lockdep_initialized;
 
@@ -57,14 +93,15 @@
 static struct lock_list list_entries[MAX_LOCKDEP_ENTRIES];
 
 /*
- * Allocate a lockdep entry. (assumes hash_lock held, returns
+ * Allocate a lockdep entry. (assumes the graph_lock held, returns
  * with NULL on failure)
  */
 static struct lock_list *alloc_list_entry(void)
 {
 	if (nr_list_entries >= MAX_LOCKDEP_ENTRIES) {
-		__raw_spin_unlock(&hash_lock);
-		debug_locks_off();
+		if (!debug_locks_off_graph_unlock())
+			return NULL;
+
 		printk("BUG: MAX_LOCKDEP_ENTRIES too low!\n");
 		printk("turning off the locking correctness validator.\n");
 		return NULL;
@@ -145,9 +182,7 @@
  */
 
 #define VERBOSE			0
-#ifdef VERBOSE
-# define VERY_VERBOSE		0
-#endif
+#define VERY_VERBOSE		0
 
 #if VERBOSE
 # define HARDIRQ_VERBOSE	1
@@ -172,8 +207,8 @@
 			!strcmp(class->name, "&struct->lockfield"))
 		return 1;
 #endif
-	/* Allow everything else. 0 would be filter everything else */
-	return 1;
+	/* Filter everything else. 1 would be to allow everything else */
+	return 0;
 }
 #endif
 
@@ -207,7 +242,7 @@
 
 /*
  * Stack-trace: tightly packed array of stack backtrace
- * addresses. Protected by the hash_lock.
+ * addresses. Protected by the graph_lock.
  */
 unsigned long nr_stack_trace_entries;
 static unsigned long stack_trace[MAX_STACK_TRACE_ENTRIES];
@@ -226,18 +261,15 @@
 	trace->max_entries = trace->nr_entries;
 
 	nr_stack_trace_entries += trace->nr_entries;
-	if (DEBUG_LOCKS_WARN_ON(nr_stack_trace_entries > MAX_STACK_TRACE_ENTRIES)) {
-		__raw_spin_unlock(&hash_lock);
-		return 0;
-	}
 
 	if (nr_stack_trace_entries == MAX_STACK_TRACE_ENTRIES) {
-		__raw_spin_unlock(&hash_lock);
-		if (debug_locks_off()) {
-			printk("BUG: MAX_STACK_TRACE_ENTRIES too low!\n");
-			printk("turning off the locking correctness validator.\n");
-			dump_stack();
-		}
+		if (!debug_locks_off_graph_unlock())
+			return 0;
+
+		printk("BUG: MAX_STACK_TRACE_ENTRIES too low!\n");
+		printk("turning off the locking correctness validator.\n");
+		dump_stack();
+
 		return 0;
 	}
 
@@ -526,9 +558,7 @@
 {
 	struct task_struct *curr = current;
 
-	__raw_spin_unlock(&hash_lock);
-	debug_locks_off();
-	if (debug_locks_silent)
+	if (!debug_locks_off_graph_unlock() || debug_locks_silent)
 		return 0;
 
 	printk("\n=======================================================\n");
@@ -556,12 +586,10 @@
 	if (debug_locks_silent)
 		return 0;
 
-	/* hash_lock unlocked by the header */
-	__raw_spin_lock(&hash_lock);
 	this.class = check_source->class;
 	if (!save_trace(&this.trace))
 		return 0;
-	__raw_spin_unlock(&hash_lock);
+
 	print_circular_bug_entry(&this, 0);
 
 	printk("\nother info that might help us debug this:\n\n");
@@ -577,8 +605,10 @@
 
 static int noinline print_infinite_recursion_bug(void)
 {
-	__raw_spin_unlock(&hash_lock);
-	DEBUG_LOCKS_WARN_ON(1);
+	if (!debug_locks_off_graph_unlock())
+		return 0;
+
+	WARN_ON(1);
 
 	return 0;
 }
@@ -713,9 +743,7 @@
 			 enum lock_usage_bit bit2,
 			 const char *irqclass)
 {
-	__raw_spin_unlock(&hash_lock);
-	debug_locks_off();
-	if (debug_locks_silent)
+	if (!debug_locks_off_graph_unlock() || debug_locks_silent)
 		return 0;
 
 	printk("\n======================================================\n");
@@ -796,9 +824,7 @@
 print_deadlock_bug(struct task_struct *curr, struct held_lock *prev,
 		   struct held_lock *next)
 {
-	debug_locks_off();
-	__raw_spin_unlock(&hash_lock);
-	if (debug_locks_silent)
+	if (!debug_locks_off_graph_unlock() || debug_locks_silent)
 		return 0;
 
 	printk("\n=============================================\n");
@@ -974,14 +1000,14 @@
 	 * Debugging printouts:
 	 */
 	if (verbose(prev->class) || verbose(next->class)) {
-		__raw_spin_unlock(&hash_lock);
+		graph_unlock();
 		printk("\n new dependency: ");
 		print_lock_name(prev->class);
 		printk(" => ");
 		print_lock_name(next->class);
 		printk("\n");
 		dump_stack();
-		__raw_spin_lock(&hash_lock);
+		return graph_lock();
 	}
 	return 1;
 }
@@ -1046,8 +1072,10 @@
 	}
 	return 1;
 out_bug:
-	__raw_spin_unlock(&hash_lock);
-	DEBUG_LOCKS_WARN_ON(1);
+	if (!debug_locks_off_graph_unlock())
+		return 0;
+
+	WARN_ON(1);
 
 	return 0;
 }
@@ -1201,7 +1229,10 @@
 	hash_head = classhashentry(key);
 
 	raw_local_irq_save(flags);
-	__raw_spin_lock(&hash_lock);
+	if (!graph_lock()) {
+		raw_local_irq_restore(flags);
+		return NULL;
+	}
 	/*
 	 * We have to do the hash-walk again, to avoid races
 	 * with another CPU:
@@ -1214,9 +1245,12 @@
 	 * the hash:
 	 */
 	if (nr_lock_classes >= MAX_LOCKDEP_KEYS) {
-		__raw_spin_unlock(&hash_lock);
+		if (!debug_locks_off_graph_unlock()) {
+			raw_local_irq_restore(flags);
+			return NULL;
+		}
 		raw_local_irq_restore(flags);
-		debug_locks_off();
+
 		printk("BUG: MAX_LOCKDEP_KEYS too low!\n");
 		printk("turning off the locking correctness validator.\n");
 		return NULL;
@@ -1237,18 +1271,23 @@
 	list_add_tail_rcu(&class->hash_entry, hash_head);
 
 	if (verbose(class)) {
-		__raw_spin_unlock(&hash_lock);
+		graph_unlock();
 		raw_local_irq_restore(flags);
+
 		printk("\nnew class %p: %s", class->key, class->name);
 		if (class->name_version > 1)
 			printk("#%d", class->name_version);
 		printk("\n");
 		dump_stack();
+
 		raw_local_irq_save(flags);
-		__raw_spin_lock(&hash_lock);
+		if (!graph_lock()) {
+			raw_local_irq_restore(flags);
+			return NULL;
+		}
 	}
 out_unlock_set:
-	__raw_spin_unlock(&hash_lock);
+	graph_unlock();
 	raw_local_irq_restore(flags);
 
 	if (!subclass || force)
@@ -1264,7 +1303,7 @@
  * add it and return 0 - in this case the new dependency chain is
  * validated. If the key is already hashed, return 1.
  */
-static inline int lookup_chain_cache(u64 chain_key)
+static inline int lookup_chain_cache(u64 chain_key, struct lock_class *class)
 {
 	struct list_head *hash_head = chainhashentry(chain_key);
 	struct lock_chain *chain;
@@ -1278,34 +1317,32 @@
 		if (chain->chain_key == chain_key) {
 cache_hit:
 			debug_atomic_inc(&chain_lookup_hits);
-			/*
-			 * In the debugging case, force redundant checking
-			 * by returning 1:
-			 */
-#ifdef CONFIG_DEBUG_LOCKDEP
-			__raw_spin_lock(&hash_lock);
-			return 1;
-#endif
+			if (very_verbose(class))
+				printk("\nhash chain already cached, key: %016Lx tail class: [%p] %s\n", chain_key, class->key, class->name);
 			return 0;
 		}
 	}
+	if (very_verbose(class))
+		printk("\nnew hash chain, key: %016Lx tail class: [%p] %s\n", chain_key, class->key, class->name);
 	/*
 	 * Allocate a new chain entry from the static array, and add
 	 * it to the hash:
 	 */
-	__raw_spin_lock(&hash_lock);
+	if (!graph_lock())
+		return 0;
 	/*
 	 * We have to walk the chain again locked - to avoid duplicates:
 	 */
 	list_for_each_entry(chain, hash_head, entry) {
 		if (chain->chain_key == chain_key) {
-			__raw_spin_unlock(&hash_lock);
+			graph_unlock();
 			goto cache_hit;
 		}
 	}
 	if (unlikely(nr_lock_chains >= MAX_LOCKDEP_CHAINS)) {
-		__raw_spin_unlock(&hash_lock);
-		debug_locks_off();
+		if (!debug_locks_off_graph_unlock())
+			return 0;
+
 		printk("BUG: MAX_LOCKDEP_CHAINS too low!\n");
 		printk("turning off the locking correctness validator.\n");
 		return 0;
@@ -1381,9 +1418,7 @@
 			struct held_lock *this, int forwards,
 			const char *irqclass)
 {
-	__raw_spin_unlock(&hash_lock);
-	debug_locks_off();
-	if (debug_locks_silent)
+	if (!debug_locks_off_graph_unlock() || debug_locks_silent)
 		return 0;
 
 	printk("\n=========================================================\n");
@@ -1453,7 +1488,7 @@
 	return print_irq_inversion_bug(curr, backwards_match, this, 0, irqclass);
 }
 
-static inline void print_irqtrace_events(struct task_struct *curr)
+void print_irqtrace_events(struct task_struct *curr)
 {
 	printk("irq event stamp: %u\n", curr->irq_events);
 	printk("hardirqs last  enabled at (%u): ", curr->hardirq_enable_event);
@@ -1466,19 +1501,13 @@
 	print_ip_sym(curr->softirq_disable_ip);
 }
 
-#else
-static inline void print_irqtrace_events(struct task_struct *curr)
-{
-}
 #endif
 
 static int
 print_usage_bug(struct task_struct *curr, struct held_lock *this,
 		enum lock_usage_bit prev_bit, enum lock_usage_bit new_bit)
 {
-	__raw_spin_unlock(&hash_lock);
-	debug_locks_off();
-	if (debug_locks_silent)
+	if (!debug_locks_off_graph_unlock() || debug_locks_silent)
 		return 0;
 
 	printk("\n=================================\n");
@@ -1539,12 +1568,13 @@
 	if (likely(this->class->usage_mask & new_mask))
 		return 1;
 
-	__raw_spin_lock(&hash_lock);
+	if (!graph_lock())
+		return 0;
 	/*
 	 * Make sure we didnt race:
 	 */
 	if (unlikely(this->class->usage_mask & new_mask)) {
-		__raw_spin_unlock(&hash_lock);
+		graph_unlock();
 		return 1;
 	}
 
@@ -1730,16 +1760,16 @@
 		debug_atomic_dec(&nr_unused_locks);
 		break;
 	default:
-		__raw_spin_unlock(&hash_lock);
-		debug_locks_off();
+		if (!debug_locks_off_graph_unlock())
+			return 0;
 		WARN_ON(1);
 		return 0;
 	}
 
-	__raw_spin_unlock(&hash_lock);
+	graph_unlock();
 
 	/*
-	 * We must printk outside of the hash_lock:
+	 * We must printk outside of the graph_lock:
 	 */
 	if (ret == 2) {
 		printk("\nmarked lock as {%s}:\n", usage_str[new_bit]);
@@ -2137,9 +2167,9 @@
 	 * We look up the chain_key and do the O(N^2) check and update of
 	 * the dependencies only if this is a new dependency chain.
 	 * (If lookup_chain_cache() returns with 1 it acquires
-	 * hash_lock for us)
+	 * graph_lock for us)
 	 */
-	if (!trylock && (check == 2) && lookup_chain_cache(chain_key)) {
+	if (!trylock && (check == 2) && lookup_chain_cache(chain_key, class)) {
 		/*
 		 * Check whether last held lock:
 		 *
@@ -2170,7 +2200,7 @@
 		if (!chain_head && ret != 2)
 			if (!check_prevs_add(curr, hlock))
 				return 0;
-		__raw_spin_unlock(&hash_lock);
+		graph_unlock();
 	}
 	curr->lockdep_depth++;
 	check_chain_key(curr);
@@ -2433,6 +2463,7 @@
 void lockdep_reset(void)
 {
 	unsigned long flags;
+	int i;
 
 	raw_local_irq_save(flags);
 	current->curr_chain_key = 0;
@@ -2443,6 +2474,8 @@
 	nr_softirq_chains = 0;
 	nr_process_chains = 0;
 	debug_locks = 1;
+	for (i = 0; i < CHAINHASH_SIZE; i++)
+		INIT_LIST_HEAD(chainhash_table + i);
 	raw_local_irq_restore(flags);
 }
 
@@ -2479,7 +2512,7 @@
 	int i;
 
 	raw_local_irq_save(flags);
-	__raw_spin_lock(&hash_lock);
+	graph_lock();
 
 	/*
 	 * Unhash all classes that were created by this module:
@@ -2493,7 +2526,7 @@
 				zap_class(class);
 	}
 
-	__raw_spin_unlock(&hash_lock);
+	graph_unlock();
 	raw_local_irq_restore(flags);
 }
 
@@ -2521,20 +2554,20 @@
 	 * Debug check: in the end all mapped classes should
 	 * be gone.
 	 */
-	__raw_spin_lock(&hash_lock);
+	graph_lock();
 	for (i = 0; i < CLASSHASH_SIZE; i++) {
 		head = classhash_table + i;
 		if (list_empty(head))
 			continue;
 		list_for_each_entry_safe(class, next, head, hash_entry) {
 			if (unlikely(class == lock->class_cache)) {
-				__raw_spin_unlock(&hash_lock);
-				DEBUG_LOCKS_WARN_ON(1);
+				if (debug_locks_off_graph_unlock())
+					WARN_ON(1);
 				goto out_restore;
 			}
 		}
 	}
-	__raw_spin_unlock(&hash_lock);
+	graph_unlock();
 
 out_restore:
 	raw_local_irq_restore(flags);
diff --git a/kernel/module.c b/kernel/module.c
index d9eae45..b565eae 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -824,9 +824,34 @@
 }
 #endif /* CONFIG_MODULE_UNLOAD */
 
+static ssize_t show_initstate(struct module_attribute *mattr,
+			   struct module *mod, char *buffer)
+{
+	const char *state = "unknown";
+
+	switch (mod->state) {
+	case MODULE_STATE_LIVE:
+		state = "live";
+		break;
+	case MODULE_STATE_COMING:
+		state = "coming";
+		break;
+	case MODULE_STATE_GOING:
+		state = "going";
+		break;
+	}
+	return sprintf(buffer, "%s\n", state);
+}
+
+static struct module_attribute initstate = {
+	.attr = { .name = "initstate", .mode = 0444, .owner = THIS_MODULE },
+	.show = show_initstate,
+};
+
 static struct module_attribute *modinfo_attrs[] = {
 	&modinfo_version,
 	&modinfo_srcversion,
+	&initstate,
 #ifdef CONFIG_MODULE_UNLOAD
 	&refcnt,
 #endif
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index e2ce748..f5b9ee6 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -46,10 +46,8 @@
 	struct nsproxy *ns;
 
 	ns = kmemdup(orig, sizeof(struct nsproxy), GFP_KERNEL);
-	if (ns) {
+	if (ns)
 		atomic_set(&ns->count, 1);
-		ns->id = -1;
-	}
 	return ns;
 }
 
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 710ed08..ed29622 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -20,13 +20,14 @@
 	  sending the processor to sleep and saving power.
 
 config PM_LEGACY
-	bool "Legacy Power Management API"
+	bool "Legacy Power Management API (DEPRECATED)"
 	depends on PM
-	default y
+	default n
 	---help---
-	   Support for pm_register() and friends.
+	   Support for pm_register() and friends.  This old API is obsoleted
+	   by the driver model.
 
-	   If unsure, say Y.
+	   If unsure, say N.
 
 config PM_DEBUG
 	bool "Power Management Debug Support"
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 99eeb11..6d566bf 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -28,8 +28,7 @@
 	if ((p == current) || 
 	    (p->flags & PF_NOFREEZE) ||
 	    (p->exit_state == EXIT_ZOMBIE) ||
-	    (p->exit_state == EXIT_DEAD) ||
-	    (p->state == TASK_STOPPED))
+	    (p->exit_state == EXIT_DEAD))
 		return 0;
 	return 1;
 }
@@ -61,10 +60,16 @@
 	unsigned long flags;
 
 	if (!freezing(p)) {
-		freeze(p);
-		spin_lock_irqsave(&p->sighand->siglock, flags);
-		signal_wake_up(p, 0);
-		spin_unlock_irqrestore(&p->sighand->siglock, flags);
+		rmb();
+		if (!frozen(p)) {
+			if (p->state == TASK_STOPPED)
+				force_sig_specific(SIGSTOP, p);
+
+			freeze(p);
+			spin_lock_irqsave(&p->sighand->siglock, flags);
+			signal_wake_up(p, p->state == TASK_STOPPED);
+			spin_unlock_irqrestore(&p->sighand->siglock, flags);
+		}
 	}
 }
 
@@ -103,9 +108,7 @@
 			if (frozen(p))
 				continue;
 
-			if (p->state == TASK_TRACED &&
-			    (frozen(p->parent) ||
-			     p->parent->state == TASK_STOPPED)) {
+			if (p->state == TASK_TRACED && frozen(p->parent)) {
 				cancel_freezing(p);
 				continue;
 			}
diff --git a/kernel/relay.c b/kernel/relay.c
index 818e514..a4701e7 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -138,7 +138,7 @@
  */
 struct rchan_buf *relay_create_buf(struct rchan *chan)
 {
-	struct rchan_buf *buf = kcalloc(1, sizeof(struct rchan_buf), GFP_KERNEL);
+	struct rchan_buf *buf = kzalloc(sizeof(struct rchan_buf), GFP_KERNEL);
 	if (!buf)
 		return NULL;
 
@@ -479,7 +479,7 @@
 	if (!(subbuf_size && n_subbufs))
 		return NULL;
 
-	chan = kcalloc(1, sizeof(struct rchan), GFP_KERNEL);
+	chan = kzalloc(sizeof(struct rchan), GFP_KERNEL);
 	if (!chan)
 		return NULL;
 
diff --git a/kernel/sched.c b/kernel/sched.c
index 8a0afb9..5cd833b 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -3429,6 +3429,8 @@
 			"%s/0x%08x/%d\n",
 			current->comm, preempt_count(), current->pid);
 		debug_show_held_locks(current);
+		if (irqs_disabled())
+			print_irqtrace_events(current);
 		dump_stack();
 	}
 	profile_hit(SCHED_PROFILING, __builtin_return_address(0));
@@ -6977,6 +6979,8 @@
 		printk("in_atomic():%d, irqs_disabled():%d\n",
 			in_atomic(), irqs_disabled());
 		debug_show_held_locks(current);
+		if (irqs_disabled())
+			print_irqtrace_events(current);
 		dump_stack();
 	}
 #endif
diff --git a/kernel/signal.c b/kernel/signal.c
index 1921ffd..5630255 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1705,7 +1705,9 @@
 		read_unlock(&tasklist_lock);
 	}
 
-	schedule();
+	do {
+		schedule();
+	} while (try_to_freeze());
 	/*
 	 * Now we don't run again until continued.
 	 */
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 130c5ec..600b333 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -65,7 +65,6 @@
 extern int sysctl_overcommit_ratio;
 extern int sysctl_panic_on_oom;
 extern int max_threads;
-extern int sysrq_enabled;
 extern int core_uses_pid;
 extern int suid_dumpable;
 extern char core_pattern[];
@@ -543,7 +542,7 @@
 	{
 		.ctl_name	= KERN_SYSRQ,
 		.procname	= "sysrq",
-		.data		= &sysrq_enabled,
+		.data		= &__sysrq_enabled,
 		.maxlen		= sizeof (int),
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,
diff --git a/kernel/timer.c b/kernel/timer.c
index 0256ab4..feddf81 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -1146,11 +1146,15 @@
 	unsigned long active_tasks; /* fixed-point */
 	static int count = LOAD_FREQ;
 
-	active_tasks = count_active_tasks();
-	for (count -= ticks; count < 0; count += LOAD_FREQ) {
-		CALC_LOAD(avenrun[0], EXP_1, active_tasks);
-		CALC_LOAD(avenrun[1], EXP_5, active_tasks);
-		CALC_LOAD(avenrun[2], EXP_15, active_tasks);
+	count -= ticks;
+	if (unlikely(count < 0)) {
+		active_tasks = count_active_tasks();
+		do {
+			CALC_LOAD(avenrun[0], EXP_1, active_tasks);
+			CALC_LOAD(avenrun[1], EXP_5, active_tasks);
+			CALC_LOAD(avenrun[2], EXP_15, active_tasks);
+			count += LOAD_FREQ;
+		} while (count < 0);
 	}
 }
 
diff --git a/lib/Kconfig b/lib/Kconfig
index 47b172d..9b03581 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -101,4 +101,9 @@
 config PLIST
 	boolean
 
+config IOMAP_COPY
+	boolean
+	depends on !UML
+	default y
+
 endmenu
diff --git a/lib/Makefile b/lib/Makefile
index 2d6106a..77b4bad 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -5,20 +5,21 @@
 lib-y := ctype.o string.o vsprintf.o cmdline.o \
 	 bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
 	 idr.o div64.o int_sqrt.o bitmap.o extable.o prio_tree.o \
-	 sha1.o irq_regs.o
+	 sha1.o irq_regs.o reciprocal_div.o
 
 lib-$(CONFIG_MMU) += ioremap.o
 lib-$(CONFIG_SMP) += cpumask.o
 
 lib-y	+= kobject.o kref.o kobject_uevent.o klist.o
 
-obj-y += sort.o parser.o halfmd4.o iomap_copy.o debug_locks.o random32.o
+obj-y += sort.o parser.o halfmd4.o debug_locks.o random32.o
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
 CFLAGS_kobject.o += -DDEBUG
 CFLAGS_kobject_uevent.o += -DDEBUG
 endif
 
+obj-$(CONFIG_IOMAP_COPY) += iomap_copy.o
 obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
 obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
 lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
diff --git a/lib/ioremap.c b/lib/ioremap.c
index 99fa277..a9e4415 100644
--- a/lib/ioremap.c
+++ b/lib/ioremap.c
@@ -5,7 +5,6 @@
  *
  * (C) Copyright 1995 1996 Linus Torvalds
  */
-#include <linux/io.h>
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
 
diff --git a/lib/reciprocal_div.c b/lib/reciprocal_div.c
new file mode 100644
index 0000000..6a3bd48
--- /dev/null
+++ b/lib/reciprocal_div.c
@@ -0,0 +1,9 @@
+#include <asm/div64.h>
+#include <linux/reciprocal_div.h>
+
+u32 reciprocal_value(u32 k)
+{
+	u64 val = (1LL << 32) + (k - 1);
+	do_div(val, k);
+	return (u32)val;
+}
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 0ccc7f2..cb362f7 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -44,14 +44,14 @@
 }
 
 static void copy_huge_page(struct page *dst, struct page *src,
-			   unsigned long addr)
+			   unsigned long addr, struct vm_area_struct *vma)
 {
 	int i;
 
 	might_sleep();
 	for (i = 0; i < HPAGE_SIZE/PAGE_SIZE; i++) {
 		cond_resched();
-		copy_user_highpage(dst + i, src + i, addr + i*PAGE_SIZE);
+		copy_user_highpage(dst + i, src + i, addr + i*PAGE_SIZE, vma);
 	}
 }
 
@@ -73,7 +73,7 @@
 
 	for (z = zonelist->zones; *z; z++) {
 		nid = zone_to_nid(*z);
-		if (cpuset_zone_allowed(*z, GFP_HIGHUSER) &&
+		if (cpuset_zone_allowed_softwall(*z, GFP_HIGHUSER) &&
 		    !list_empty(&hugepage_freelists[nid]))
 			break;
 	}
@@ -442,7 +442,7 @@
 	}
 
 	spin_unlock(&mm->page_table_lock);
-	copy_huge_page(new_page, old_page, address);
+	copy_huge_page(new_page, old_page, address, vma);
 	spin_lock(&mm->page_table_lock);
 
 	ptep = huge_pte_offset(mm, address & HPAGE_MASK);
diff --git a/mm/memory.c b/mm/memory.c
index bf61002..c00bac6 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1441,7 +1441,7 @@
 	return pte;
 }
 
-static inline void cow_user_page(struct page *dst, struct page *src, unsigned long va)
+static inline void cow_user_page(struct page *dst, struct page *src, unsigned long va, struct vm_area_struct *vma)
 {
 	/*
 	 * If the source page was a PFN mapping, we don't have
@@ -1464,9 +1464,9 @@
 		kunmap_atomic(kaddr, KM_USER0);
 		flush_dcache_page(dst);
 		return;
-		
+
 	}
-	copy_user_highpage(dst, src, va);
+	copy_user_highpage(dst, src, va, vma);
 }
 
 /*
@@ -1577,7 +1577,7 @@
 		new_page = alloc_page_vma(GFP_HIGHUSER, vma, address);
 		if (!new_page)
 			goto oom;
-		cow_user_page(new_page, old_page, address);
+		cow_user_page(new_page, old_page, address, vma);
 	}
 
 	/*
@@ -2200,7 +2200,7 @@
 			page = alloc_page_vma(GFP_HIGHUSER, vma, address);
 			if (!page)
 				goto oom;
-			copy_user_highpage(page, new_page, address);
+			copy_user_highpage(page, new_page, address, vma);
 			page_cache_release(new_page);
 			new_page = page;
 			anon = 1;
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 223d9cc..64cf3c2 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -177,7 +177,7 @@
 	nodemask_t nodes = node_online_map;
 
 	for (z = zonelist->zones; *z; z++)
-		if (cpuset_zone_allowed(*z, gfp_mask))
+		if (cpuset_zone_allowed_softwall(*z, gfp_mask))
 			node_clear(zone_to_nid(*z), nodes);
 		else
 			return CONSTRAINT_CPUSET;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index e6b17b2..8c1a116 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1162,7 +1162,7 @@
 			zone->zone_pgdat != zonelist->zones[0]->zone_pgdat))
 				break;
 		if ((alloc_flags & ALLOC_CPUSET) &&
-			!cpuset_zone_allowed(zone, gfp_mask))
+			!cpuset_zone_allowed_softwall(zone, gfp_mask))
 				goto try_next_zone;
 
 		if (!(alloc_flags & ALLOC_NO_WATERMARKS)) {
diff --git a/mm/slab.c b/mm/slab.c
index 2c65553..909975f 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -109,6 +109,7 @@
 #include	<linux/mutex.h>
 #include	<linux/fault-inject.h>
 #include	<linux/rtmutex.h>
+#include	<linux/reciprocal_div.h>
 
 #include	<asm/cacheflush.h>
 #include	<asm/tlbflush.h>
@@ -386,6 +387,7 @@
 	unsigned int shared;
 
 	unsigned int buffer_size;
+	u32 reciprocal_buffer_size;
 /* 3) touched by every alloc & free from the backend */
 	struct kmem_list3 *nodelists[MAX_NUMNODES];
 
@@ -627,10 +629,17 @@
 	return slab->s_mem + cache->buffer_size * idx;
 }
 
-static inline unsigned int obj_to_index(struct kmem_cache *cache,
-					struct slab *slab, void *obj)
+/*
+ * We want to avoid an expensive divide : (offset / cache->buffer_size)
+ *   Using the fact that buffer_size is a constant for a particular cache,
+ *   we can replace (offset / cache->buffer_size) by
+ *   reciprocal_divide(offset, cache->reciprocal_buffer_size)
+ */
+static inline unsigned int obj_to_index(const struct kmem_cache *cache,
+					const struct slab *slab, void *obj)
 {
-	return (unsigned)(obj - slab->s_mem) / cache->buffer_size;
+	u32 offset = (obj - slab->s_mem);
+	return reciprocal_divide(offset, cache->reciprocal_buffer_size);
 }
 
 /*
@@ -1427,6 +1436,8 @@
 
 	cache_cache.buffer_size = ALIGN(cache_cache.buffer_size,
 					cache_line_size());
+	cache_cache.reciprocal_buffer_size =
+		reciprocal_value(cache_cache.buffer_size);
 
 	for (order = 0; order < MAX_ORDER; order++) {
 		cache_estimate(order, cache_cache.buffer_size,
@@ -2313,6 +2324,7 @@
 	if (flags & SLAB_CACHE_DMA)
 		cachep->gfpflags |= GFP_DMA;
 	cachep->buffer_size = size;
+	cachep->reciprocal_buffer_size = reciprocal_value(size);
 
 	if (flags & CFLGS_OFF_SLAB) {
 		cachep->slabp_cache = kmem_find_general_cachep(slab_size, 0u);
@@ -3252,6 +3264,7 @@
 	struct zone **z;
 	void *obj = NULL;
 	int nid;
+	gfp_t local_flags = (flags & GFP_LEVEL_MASK);
 
 retry:
 	/*
@@ -3261,7 +3274,7 @@
 	for (z = zonelist->zones; *z && !obj; z++) {
 		nid = zone_to_nid(*z);
 
-		if (cpuset_zone_allowed(*z, flags | __GFP_HARDWALL) &&
+		if (cpuset_zone_allowed_hardwall(*z, flags) &&
 			cache->nodelists[nid] &&
 			cache->nodelists[nid]->free_objects)
 				obj = ____cache_alloc_node(cache,
@@ -3275,7 +3288,12 @@
 		 * We may trigger various forms of reclaim on the allowed
 		 * set and go into memory reserves if necessary.
 		 */
+		if (local_flags & __GFP_WAIT)
+			local_irq_enable();
+		kmem_flagcheck(cache, flags);
 		obj = kmem_getpages(cache, flags, -1);
+		if (local_flags & __GFP_WAIT)
+			local_irq_disable();
 		if (obj) {
 			/*
 			 * Insert into the appropriate per node queues
@@ -3535,7 +3553,7 @@
  *
  * Currently only used for dentry validation.
  */
-int fastcall kmem_ptr_validate(struct kmem_cache *cachep, void *ptr)
+int fastcall kmem_ptr_validate(struct kmem_cache *cachep, const void *ptr)
 {
 	unsigned long addr = (unsigned long)ptr;
 	unsigned long min_addr = PAGE_OFFSET;
diff --git a/mm/slob.c b/mm/slob.c
index 5423941..2e9236e 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -157,7 +157,7 @@
 	return order;
 }
 
-void *kmalloc(size_t size, gfp_t gfp)
+void *__kmalloc(size_t size, gfp_t gfp)
 {
 	slob_t *m;
 	bigblock_t *bb;
@@ -186,8 +186,7 @@
 	slob_free(bb, sizeof(bigblock_t));
 	return 0;
 }
-
-EXPORT_SYMBOL(kmalloc);
+EXPORT_SYMBOL(__kmalloc);
 
 void kfree(const void *block)
 {
@@ -329,6 +328,17 @@
 static struct timer_list slob_timer = TIMER_INITIALIZER(
 	(void (*)(unsigned long))kmem_cache_init, 0, 0);
 
+int kmem_cache_shrink(struct kmem_cache *d)
+{
+	return 0;
+}
+EXPORT_SYMBOL(kmem_cache_shrink);
+
+int kmem_ptr_validate(struct kmem_cache *a, const void *b)
+{
+	return 0;
+}
+
 void kmem_cache_init(void)
 {
 	void *p = slob_alloc(PAGE_SIZE, 0, PAGE_SIZE-1);
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 093f5fe..e9813b0 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -984,7 +984,7 @@
 		if (!populated_zone(zone))
 			continue;
 
-		if (!cpuset_zone_allowed(zone, __GFP_HARDWALL))
+		if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
 			continue;
 
 		note_zone_scanning_priority(zone, priority);
@@ -1034,7 +1034,7 @@
 	for (i = 0; zones[i] != NULL; i++) {
 		struct zone *zone = zones[i];
 
-		if (!cpuset_zone_allowed(zone, __GFP_HARDWALL))
+		if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
 			continue;
 
 		lru_pages += zone->nr_active + zone->nr_inactive;
@@ -1089,7 +1089,7 @@
 	for (i = 0; zones[i] != 0; i++) {
 		struct zone *zone = zones[i];
 
-		if (!cpuset_zone_allowed(zone, __GFP_HARDWALL))
+		if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
 			continue;
 
 		zone->prev_priority = priority;
@@ -1354,7 +1354,7 @@
 		return;
 	if (pgdat->kswapd_max_order < order)
 		pgdat->kswapd_max_order = order;
-	if (!cpuset_zone_allowed(zone, __GFP_HARDWALL))
+	if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
 		return;
 	if (!waitqueue_active(&pgdat->kswapd_wait))
 		return;
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 711a085..dbf98c4 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -123,10 +123,10 @@
 			if (flt->opcode &&
 			    ((evt == HCI_EV_CMD_COMPLETE &&
 			      flt->opcode !=
-			      get_unaligned((__u16 *)(skb->data + 3))) ||
+			      get_unaligned((__le16 *)(skb->data + 3))) ||
 			     (evt == HCI_EV_CMD_STATUS &&
 			      flt->opcode !=
-			      get_unaligned((__u16 *)(skb->data + 4)))))
+			      get_unaligned((__le16 *)(skb->data + 4)))))
 				continue;
 		}
 
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 700353b..066c64a 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -804,19 +804,19 @@
 
 	integ_len = svc_getnl(&buf->head[0]);
 	if (integ_len & 3)
-		goto out;
+		return stat;
 	if (integ_len > buf->len)
-		goto out;
+		return stat;
 	if (xdr_buf_subsegment(buf, &integ_buf, 0, integ_len))
 		BUG();
 	/* copy out mic... */
 	if (read_u32_from_xdr_buf(buf, integ_len, &mic.len))
 		BUG();
 	if (mic.len > RPC_MAX_AUTH_SIZE)
-		goto out;
+		return stat;
 	mic.data = kmalloc(mic.len, GFP_KERNEL);
 	if (!mic.data)
-		goto out;
+		return stat;
 	if (read_bytes_from_xdr_buf(buf, integ_len + 4, mic.data, mic.len))
 		goto out;
 	maj_stat = gss_verify_mic(ctx, &integ_buf, &mic);
@@ -826,6 +826,7 @@
 		goto out;
 	stat = 0;
 out:
+	kfree(mic.data);
 	return stat;
 }
 
@@ -1065,7 +1066,7 @@
 		}
 		switch(cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle)) {
 		case -EAGAIN:
-			goto drop;
+		case -ETIMEDOUT:
 		case -ENOENT:
 			goto drop;
 		case 0:
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 80aff04..1427449 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -34,7 +34,7 @@
 
 #define	 RPCDBG_FACILITY RPCDBG_CACHE
 
-static void cache_defer_req(struct cache_req *req, struct cache_head *item);
+static int cache_defer_req(struct cache_req *req, struct cache_head *item);
 static void cache_revisit_request(struct cache_head *item);
 
 static void cache_init(struct cache_head *h)
@@ -185,6 +185,7 @@
  *
  * Returns 0 if the cache_head can be used, or cache_puts it and returns
  * -EAGAIN if upcall is pending,
+ * -ETIMEDOUT if upcall failed and should be retried,
  * -ENOENT if cache entry was negative
  */
 int cache_check(struct cache_detail *detail,
@@ -236,7 +237,8 @@
 	}
 
 	if (rv == -EAGAIN)
-		cache_defer_req(rqstp, h);
+		if (cache_defer_req(rqstp, h) != 0)
+			rv = -ETIMEDOUT;
 
 	if (rv)
 		cache_put(h, detail);
@@ -523,14 +525,21 @@
 static struct list_head cache_defer_hash[DFR_HASHSIZE];
 static int cache_defer_cnt;
 
-static void cache_defer_req(struct cache_req *req, struct cache_head *item)
+static int cache_defer_req(struct cache_req *req, struct cache_head *item)
 {
 	struct cache_deferred_req *dreq;
 	int hash = DFR_HASH(item);
 
+	if (cache_defer_cnt >= DFR_MAX) {
+		/* too much in the cache, randomly drop this one,
+		 * or continue and drop the oldest below
+		 */
+		if (net_random()&1)
+			return -ETIMEDOUT;
+	}
 	dreq = req->defer(req);
 	if (dreq == NULL)
-		return;
+		return -ETIMEDOUT;
 
 	dreq->item = item;
 	dreq->recv_time = get_seconds();
@@ -546,17 +555,8 @@
 	/* it is in, now maybe clean up */
 	dreq = NULL;
 	if (++cache_defer_cnt > DFR_MAX) {
-		/* too much in the cache, randomly drop
-		 * first or last
-		 */
-		if (net_random()&1) 
-			dreq = list_entry(cache_defer_list.next,
-					  struct cache_deferred_req,
-					  recent);
-		else
-			dreq = list_entry(cache_defer_list.prev,
-					  struct cache_deferred_req,
-					  recent);
+		dreq = list_entry(cache_defer_list.prev,
+				  struct cache_deferred_req, recent);
 		list_del(&dreq->recent);
 		list_del(&dreq->hash);
 		cache_defer_cnt--;
@@ -571,6 +571,7 @@
 		/* must have just been validated... */
 		cache_revisit_request(item);
 	}
+	return 0;
 }
 
 static void cache_revisit_request(struct cache_head *item)
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index eb44ec9..f3001f3 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -308,7 +308,7 @@
 
 	serv->sv_nrpools = npools;
 	serv->sv_pools =
-		kcalloc(sizeof(struct svc_pool), serv->sv_nrpools,
+		kcalloc(serv->sv_nrpools, sizeof(struct svc_pool),
 			GFP_KERNEL);
 	if (!serv->sv_pools) {
 		kfree(serv);
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index a0a953a..0d1e8fb 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -53,6 +53,10 @@
 			return NULL;
 		kref_init(&new->h.ref);
 		new->h.name = kstrdup(name, GFP_KERNEL);
+		if (new->h.name == NULL) {
+			kfree(new);
+			return NULL;
+		}
 		new->h.flavour = &svcauth_unix;
 		new->addr_changes = 0;
 		rv = auth_domain_lookup(name, &new->h);
@@ -435,6 +439,7 @@
 		default:
 			BUG();
 		case -EAGAIN:
+		case -ETIMEDOUT:
 			return SVC_DROP;
 		case -ENOENT:
 			return SVC_DENIED;
diff --git a/net/tipc/config.c b/net/tipc/config.c
index 458a2c4..baf55c4 100644
--- a/net/tipc/config.c
+++ b/net/tipc/config.c
@@ -208,7 +208,7 @@
 
 			if (mng.link_subscriptions > 64)
 				break;
-			sub = (struct subscr_data *)kmalloc(sizeof(*sub),
+			sub = kmalloc(sizeof(*sub),
 							    GFP_ATOMIC);
 			if (sub == NULL) {
 				warn("Memory squeeze; dropped remote link subscription\n");
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 4dcb886..124b341 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -600,7 +600,7 @@
 			input_mode = ask_silent;
 			valid_stdin = 1;
 		}
-	} else if (sym_change_count) {
+	} else if (conf_get_changed()) {
 		name = getenv("KCONFIG_NOSILENTUPDATE");
 		if (name && *name) {
 			fprintf(stderr, _("\n*** Kernel configuration requires explicit update.\n\n"));
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 66b15ef..664fe29 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -100,7 +100,7 @@
 		in = zconf_fopen(name);
 		if (in)
 			goto load;
-		sym_change_count++;
+		sym_add_change_count(1);
 		if (!sym_defconfig_list)
 			return 1;
 
@@ -312,7 +312,7 @@
 	struct expr *e;
 	int i, flags;
 
-	sym_change_count = 0;
+	sym_set_change_count(0);
 
 	if (conf_read_simple(name, S_DEF_USER))
 		return 1;
@@ -364,7 +364,7 @@
 		sym->flags &= flags | ~SYMBOL_DEF_USER;
 	}
 
-	sym_change_count += conf_warnings || conf_unsaved;
+	sym_add_change_count(conf_warnings || conf_unsaved);
 
 	return 0;
 }
@@ -432,7 +432,7 @@
 		     use_timestamp ? "# " : "",
 		     use_timestamp ? ctime(&now) : "");
 
-	if (!sym_change_count)
+	if (!conf_get_changed())
 		sym_clear_all_valid();
 
 	menu = rootmenu.list;
@@ -528,7 +528,7 @@
 		 "# configuration written to %s\n"
 		 "#\n"), newname);
 
-	sym_change_count = 0;
+	sym_set_change_count(0);
 
 	return 0;
 }
@@ -765,3 +765,30 @@
 
 	return 0;
 }
+
+static int sym_change_count;
+static void (*conf_changed_callback)(void);
+
+void sym_set_change_count(int count)
+{
+	int _sym_change_count = sym_change_count;
+	sym_change_count = count;
+	if (conf_changed_callback &&
+	    (bool)_sym_change_count != (bool)count)
+		conf_changed_callback();
+}
+
+void sym_add_change_count(int count)
+{
+	sym_set_change_count(count + sym_change_count);
+}
+
+bool conf_get_changed(void)
+{
+	return sym_change_count;
+}
+
+void conf_set_changed_callback(void (*fn)(void))
+{
+	conf_changed_callback = fn;
+}
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
index 7b0d3a9..61d8166 100644
--- a/scripts/kconfig/gconf.c
+++ b/scripts/kconfig/gconf.c
@@ -38,8 +38,6 @@
 static gboolean show_debug = FALSE;
 static gboolean resizeable = FALSE;
 
-static gboolean config_changed = FALSE;
-
 static char nohelp_text[] =
     N_("Sorry, no help available for this option yet.\n");
 
@@ -50,6 +48,8 @@
 GtkWidget *hpaned = NULL;
 GtkWidget *vpaned = NULL;
 GtkWidget *back_btn = NULL;
+GtkWidget *save_btn = NULL;
+GtkWidget *save_menu_item = NULL;
 
 GtkTextTag *tag1, *tag2;
 GdkColor color;
@@ -75,7 +75,7 @@
 static void update_tree(struct menu *src, GtkTreeIter * dst);
 static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row);
 static gchar **fill_row(struct menu *menu);
-
+static void conf_changed(void);
 
 /* Helping/Debugging Functions */
 
@@ -224,6 +224,10 @@
 	gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
 				       show_value);
 
+	save_btn = glade_xml_get_widget(xml, "button3");
+	save_menu_item = glade_xml_get_widget(xml, "save1");
+	conf_set_changed_callback(conf_changed);
+
 	style = gtk_widget_get_style(main_wnd);
 	widget = glade_xml_get_widget(xml, "toolbar1");
 
@@ -512,14 +516,14 @@
 
 /* Main Windows Callbacks */
 
-void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data);
+void on_save_activate(GtkMenuItem * menuitem, gpointer user_data);
 gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
 				 gpointer user_data)
 {
 	GtkWidget *dialog, *label;
 	gint result;
 
-	if (config_changed == FALSE)
+	if (!conf_get_changed())
 		return FALSE;
 
 	dialog = gtk_dialog_new_with_buttons(_("Warning !"),
@@ -543,7 +547,7 @@
 	result = gtk_dialog_run(GTK_DIALOG(dialog));
 	switch (result) {
 	case GTK_RESPONSE_YES:
-		on_save1_activate(NULL, NULL);
+		on_save_activate(NULL, NULL);
 		return FALSE;
 	case GTK_RESPONSE_NO:
 		return FALSE;
@@ -621,12 +625,10 @@
 }
 
 
-void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data)
+void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
 {
 	if (conf_write(NULL))
 		text_insert_msg(_("Error"), _("Unable to save configuration !"));
-
-	config_changed = FALSE;
 }
 
 
@@ -819,12 +821,6 @@
 }
 
 
-void on_save_clicked(GtkButton * button, gpointer user_data)
-{
-	on_save1_activate(NULL, user_data);
-}
-
-
 void on_single_clicked(GtkButton * button, gpointer user_data)
 {
 	view_mode = SINGLE_VIEW;
@@ -899,7 +895,6 @@
 
 	sym_set_string_value(sym, new_def);
 
-	config_changed = TRUE;
 	update_tree(&rootmenu, NULL);
 
 	gtk_tree_path_free(path);
@@ -930,7 +925,6 @@
 		if (!sym_tristate_within_range(sym, newval))
 			newval = yes;
 		sym_set_tristate_value(sym, newval);
-		config_changed = TRUE;
 		if (view_mode == FULL_VIEW)
 			update_tree(&rootmenu, NULL);
 		else if (view_mode == SPLIT_VIEW) {
@@ -1633,3 +1627,10 @@
 
 	return 0;
 }
+
+static void conf_changed(void)
+{
+	bool changed = conf_get_changed();
+	gtk_widget_set_sensitive(save_btn, changed);
+	gtk_widget_set_sensitive(save_menu_item, changed);
+}
diff --git a/scripts/kconfig/gconf.glade b/scripts/kconfig/gconf.glade
index f8744ed..803233f 100644
--- a/scripts/kconfig/gconf.glade
+++ b/scripts/kconfig/gconf.glade
@@ -70,7 +70,7 @@
 		      <property name="tooltip" translatable="yes">Save the config in .config</property>
 		      <property name="label" translatable="yes">_Save</property>
 		      <property name="use_underline">True</property>
-		      <signal name="activate" handler="on_save1_activate"/>
+		      <signal name="activate" handler="on_save_activate"/>
 		      <accelerator key="S" modifiers="GDK_CONTROL_MASK" signal="activate"/>
 
 		      <child internal-child="image">
@@ -380,7 +380,7 @@
 		  <property name="visible_horizontal">True</property>
 		  <property name="visible_vertical">True</property>
 		  <property name="is_important">False</property>
-		  <signal name="clicked" handler="on_save_clicked"/>
+		  <signal name="clicked" handler="on_save_activate"/>
 		</widget>
 		<packing>
 		  <property name="expand">False</property>
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index 2628023..9b2706a 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -65,6 +65,8 @@
 
 /* confdata.c */
 char *conf_get_default_confname(void);
+void sym_set_change_count(int count);
+void sym_add_change_count(int count);
 
 /* kconfig_load.c */
 void kconfig_load(void);
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
index a263746..1503077 100644
--- a/scripts/kconfig/lkc_proto.h
+++ b/scripts/kconfig/lkc_proto.h
@@ -5,6 +5,8 @@
 P(conf_read_simple,int,(const char *name, int));
 P(conf_write,int,(const char *name));
 P(conf_write_autoconf,int,(void));
+P(conf_get_changed,bool,(void));
+P(conf_set_changed_callback, void,(void (*fn)(void)));
 
 /* menu.c */
 P(rootmenu,struct menu,);
@@ -16,7 +18,6 @@
 
 /* symbol.c */
 P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
-P(sym_change_count,int,);
 
 P(sym_lookup,struct symbol *,(const char *name, int isconst));
 P(sym_find,struct symbol *,(const char *name));
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index 08a4c7a..3f9a132 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -890,14 +890,19 @@
 	do {
 		conf(&rootmenu);
 		dialog_clear();
-		res = dialog_yesno(NULL,
-				   _("Do you wish to save your "
-				     "new kernel configuration?\n"
-				     "<ESC><ESC> to continue."),
-				   6, 60);
+		if (conf_get_changed())
+			res = dialog_yesno(NULL,
+					   _("Do you wish to save your "
+					     "new kernel configuration?\n"
+					     "<ESC><ESC> to continue."),
+					   6, 60);
+		else
+			res = -1;
 	} while (res == KEY_ESC);
 	end_dialog();
-	if (res == 0) {
+
+	switch (res) {
+	case 0:
 		if (conf_write(NULL)) {
 			fprintf(stderr, _("\n\n"
 				"Error during writing of the kernel configuration.\n"
@@ -905,11 +910,13 @@
 				"\n\n"));
 			return 1;
 		}
+	case -1:
 		printf(_("\n\n"
 			"*** End of Linux kernel configuration.\n"
 			"*** Execute 'make' to build the kernel or try 'make help'."
 			"\n\n"));
-	} else {
+		break;
+	default:
 		fprintf(stderr, _("\n\n"
 			"Your kernel configuration changes were NOT saved."
 			"\n\n"));
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index f5628c5..0b2fcc4 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -38,6 +38,8 @@
 static QApplication *configApp;
 static ConfigSettings *configSettings;
 
+QAction *ConfigMainWindow::saveAction;
+
 static inline QString qgettext(const char* str)
 {
 	return QString::fromLocal8Bit(gettext(str));
@@ -1306,8 +1308,11 @@
 	  connect(quitAction, SIGNAL(activated()), SLOT(close()));
 	QAction *loadAction = new QAction("Load", QPixmap(xpm_load), "&Load", CTRL+Key_L, this);
 	  connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
-	QAction *saveAction = new QAction("Save", QPixmap(xpm_save), "&Save", CTRL+Key_S, this);
+	saveAction = new QAction("Save", QPixmap(xpm_save), "&Save", CTRL+Key_S, this);
 	  connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
+	conf_set_changed_callback(conf_changed);
+	// Set saveAction's initial state
+	conf_changed();
 	QAction *saveAsAction = new QAction("Save As...", "Save &As...", 0, this);
 	  connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
 	QAction *searchAction = new QAction("Search", "&Search", CTRL+Key_F, this);
@@ -1585,7 +1590,7 @@
  */
 void ConfigMainWindow::closeEvent(QCloseEvent* e)
 {
-	if (!sym_change_count) {
+	if (!conf_get_changed()) {
 		e->accept();
 		return;
 	}
@@ -1658,6 +1663,12 @@
 	configSettings->writeSizes("/split2", split2->sizes());
 }
 
+void ConfigMainWindow::conf_changed(void)
+{
+	if (saveAction)
+		saveAction->setEnabled(conf_get_changed());
+}
+
 void fixup_rootmenu(struct menu *menu)
 {
 	struct menu *child;
diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h
index 6a9e3b1..6fc1c5f 100644
--- a/scripts/kconfig/qconf.h
+++ b/scripts/kconfig/qconf.h
@@ -297,6 +297,9 @@
 
 class ConfigMainWindow : public QMainWindow {
 	Q_OBJECT
+
+	static QAction *saveAction;
+	static void conf_changed(void);
 public:
 	ConfigMainWindow(void);
 public slots:
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index ee225ce..8f06c47 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -30,7 +30,6 @@
 	.flags = SYMBOL_VALID,
 };
 
-int sym_change_count;
 struct symbol *sym_defconfig_list;
 struct symbol *modules_sym;
 tristate modules_val;
@@ -379,7 +378,7 @@
 
 	for_all_symbols(i, sym)
 		sym->flags &= ~SYMBOL_VALID;
-	sym_change_count++;
+	sym_add_change_count(1);
 	if (modules_sym)
 		sym_calc_value(modules_sym);
 }
diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped
index 2fb0a4f..d777fe8 100644
--- a/scripts/kconfig/zconf.tab.c_shipped
+++ b/scripts/kconfig/zconf.tab.c_shipped
@@ -2135,7 +2135,7 @@
 		sym_check_deps(sym);
         }
 
-	sym_change_count = 1;
+	sym_set_change_count(1);
 }
 
 const char *zconf_tokenname(int token)
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
index ab44feb..04a5864 100644
--- a/scripts/kconfig/zconf.y
+++ b/scripts/kconfig/zconf.y
@@ -504,7 +504,7 @@
 		sym_check_deps(sym);
         }
 
-	sym_change_count = 1;
+	sym_set_change_count(1);
 }
 
 const char *zconf_tokenname(int token)
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index ac0a582..15ab5d0 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -997,6 +997,7 @@
 		"__bug_table", /* used by powerpc for BUG() */
 		".exitcall.exit",
 		".eh_frame",
+		".parainstructions",
 		".stab",
 		"__ex_table",
 		".fixup",
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index f4c6704..3391f2a9 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -1023,7 +1023,7 @@
 	}
 	up_read(&mixer->card->controls_rwsem);
 	if (slot.present != 0) {
-		pslot = (struct slot *)kmalloc(sizeof(slot), GFP_KERNEL);
+		pslot = kmalloc(sizeof(slot), GFP_KERNEL);
 		if (! pslot)
 			return -ENOMEM;
 		*pslot = slot;
diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c
index 0ffa997..7cf9913 100644
--- a/sound/oss/ad1848.c
+++ b/sound/oss/ad1848.c
@@ -1992,7 +1992,7 @@
 			devc->audio_flags |= DMA_DUPLEX;
 	}
 
-	portc = (ad1848_port_info *) kmalloc(sizeof(ad1848_port_info), GFP_KERNEL);
+	portc = kmalloc(sizeof(ad1848_port_info), GFP_KERNEL);
 	if(portc==NULL) {
 		release_region(devc->base, 4);
 		return -1;
diff --git a/sound/oss/cs4232.c b/sound/oss/cs4232.c
index b6924c7..de40e21 100644
--- a/sound/oss/cs4232.c
+++ b/sound/oss/cs4232.c
@@ -408,7 +408,7 @@
 {
 	struct address_info *isapnpcfg;
 
-	isapnpcfg=(struct address_info*)kmalloc(sizeof(*isapnpcfg),GFP_KERNEL);
+	isapnpcfg = kmalloc(sizeof(*isapnpcfg),GFP_KERNEL);
 	if (!isapnpcfg)
 		return -ENOMEM;
 
diff --git a/sound/oss/emu10k1/audio.c b/sound/oss/emu10k1/audio.c
index 49f902f..efcf589 100644
--- a/sound/oss/emu10k1/audio.c
+++ b/sound/oss/emu10k1/audio.c
@@ -1139,7 +1139,7 @@
 
 match:
 
-	wave_dev = (struct emu10k1_wavedevice *) kmalloc(sizeof(struct emu10k1_wavedevice), GFP_KERNEL);
+	wave_dev = kmalloc(sizeof(struct emu10k1_wavedevice), GFP_KERNEL);
 
 	if (wave_dev == NULL) { 
 		ERROR();
@@ -1155,7 +1155,7 @@
 		/* Recording */
 		struct wiinst *wiinst;
 
-		if ((wiinst = (struct wiinst *) kmalloc(sizeof(struct wiinst), GFP_KERNEL)) == NULL) {
+		if ((wiinst = kmalloc(sizeof(struct wiinst), GFP_KERNEL)) == NULL) {
 			ERROR();
 			kfree(wave_dev);
 			return -ENOMEM;
@@ -1211,7 +1211,7 @@
 		struct woinst *woinst;
 		int i;
 
-		if ((woinst = (struct woinst *) kmalloc(sizeof(struct woinst), GFP_KERNEL)) == NULL) {
+		if ((woinst = kmalloc(sizeof(struct woinst), GFP_KERNEL)) == NULL) {
 			ERROR();
 			kfree(wave_dev);
 			return -ENOMEM;
diff --git a/sound/oss/emu10k1/cardmi.c b/sound/oss/emu10k1/cardmi.c
index 0545814..57674f8 100644
--- a/sound/oss/emu10k1/cardmi.c
+++ b/sound/oss/emu10k1/cardmi.c
@@ -157,7 +157,7 @@
 	midihdr->flags |= MIDIBUF_INQUEUE;	/* set */
 	midihdr->flags &= ~MIDIBUF_DONE;	/* clear */
 
-	if ((midiq = (struct midi_queue *) kmalloc(sizeof(struct midi_queue), GFP_ATOMIC)) == NULL) {
+	if ((midiq = kmalloc(sizeof(struct midi_queue), GFP_ATOMIC)) == NULL) {
 		/* Message lost */
 		return -1;
 	}
diff --git a/sound/oss/emu10k1/cardmo.c b/sound/oss/emu10k1/cardmo.c
index 5938d31..a8cc75d 100644
--- a/sound/oss/emu10k1/cardmo.c
+++ b/sound/oss/emu10k1/cardmo.c
@@ -117,7 +117,7 @@
 	midihdr->flags |= MIDIBUF_INQUEUE;
 	midihdr->flags &= ~MIDIBUF_DONE;
 
-	if ((midiq = (struct midi_queue *) kmalloc(sizeof(struct midi_queue), GFP_KERNEL)) == NULL) {
+	if ((midiq = kmalloc(sizeof(struct midi_queue), GFP_KERNEL)) == NULL) {
 		/* Message lost */
 		return -1;
 	}
diff --git a/sound/oss/emu10k1/midi.c b/sound/oss/emu10k1/midi.c
index 8ac77df..cca3dad 100644
--- a/sound/oss/emu10k1/midi.c
+++ b/sound/oss/emu10k1/midi.c
@@ -58,7 +58,7 @@
 {
 	struct midi_hdr *midihdr;
 
-	if ((midihdr = (struct midi_hdr *) kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL) {
+	if ((midihdr = kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL) {
 		ERROR();
 		return -EINVAL;
 	}
@@ -128,7 +128,7 @@
 		mutex_lock(&card->open_sem);
 	}
 
-	if ((midi_dev = (struct emu10k1_mididevice *) kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL)
+	if ((midi_dev = kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL)
 		return -EINVAL;
 
 	midi_dev->card = card;
@@ -328,7 +328,7 @@
 	if (!access_ok(VERIFY_READ, buffer, count))
 		return -EFAULT;
 
-	if ((midihdr = (struct midi_hdr *) kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL)
+	if ((midihdr = kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL)
 		return -EINVAL;
 
 	midihdr->bufferlength = count;
@@ -490,7 +490,7 @@
 			
 	DPF(2, "emu10k1_seq_midi_open()\n");
 	
-	if ((midi_dev = (struct emu10k1_mididevice *) kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL)
+	if ((midi_dev = kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL)
 		return -EINVAL;
 
 	midi_dev->card = card;
@@ -540,7 +540,7 @@
 
 	card = midi_devs[dev]->devc;
 
-	if ((midihdr = (struct midi_hdr *) kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL)
+	if ((midihdr = kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL)
 		return -EINVAL;
 
 	midihdr->bufferlength = 1;
diff --git a/sound/oss/emu10k1/mixer.c b/sound/oss/emu10k1/mixer.c
index cbcaaa3..6419796 100644
--- a/sound/oss/emu10k1/mixer.c
+++ b/sound/oss/emu10k1/mixer.c
@@ -194,7 +194,7 @@
 
 	case SOUND_MIXER_PRIVATE3:
 
-		ctl = (struct mixer_private_ioctl *) kmalloc(sizeof(struct mixer_private_ioctl), GFP_KERNEL);
+		ctl = kmalloc(sizeof(struct mixer_private_ioctl), GFP_KERNEL);
 		if (ctl == NULL)
 			return -ENOMEM;
 
diff --git a/sound/oss/hal2.c b/sound/oss/hal2.c
index 784bdd7..d18286c 100644
--- a/sound/oss/hal2.c
+++ b/sound/oss/hal2.c
@@ -1435,7 +1435,7 @@
 	int ret = 0;
 	struct hal2_card *hal2;
 
-	hal2 = (struct hal2_card *) kmalloc(sizeof(struct hal2_card), GFP_KERNEL);
+	hal2 = kmalloc(sizeof(struct hal2_card), GFP_KERNEL);
 	if (!hal2)
 		return -ENOMEM;
 	memset(hal2, 0, sizeof(struct hal2_card));
diff --git a/sound/oss/mpu401.c b/sound/oss/mpu401.c
index e962205..2796c0e 100644
--- a/sound/oss/mpu401.c
+++ b/sound/oss/mpu401.c
@@ -1023,7 +1023,7 @@
 				devc->capabilities |= MPU_CAP_INTLG;	/* Supports intelligent mode */
 
 
-	mpu401_synth_operations[m] = (struct synth_operations *)kmalloc(sizeof(struct synth_operations), GFP_KERNEL);
+	mpu401_synth_operations[m] = kmalloc(sizeof(struct synth_operations), GFP_KERNEL);
 
 	if (mpu401_synth_operations[m] == NULL)
 	{
diff --git a/sound/oss/opl3.c b/sound/oss/opl3.c
index 4799bc7..2e8cfa5 100644
--- a/sound/oss/opl3.c
+++ b/sound/oss/opl3.c
@@ -166,7 +166,7 @@
 		return 0;
 	}
 
-	devc = (struct opl_devinfo *)kmalloc(sizeof(*devc), GFP_KERNEL);
+	devc = kmalloc(sizeof(*devc), GFP_KERNEL);
 
 	if (devc == NULL)
 	{
diff --git a/sound/oss/sb_common.c b/sound/oss/sb_common.c
index 440537c..07cbacf 100644
--- a/sound/oss/sb_common.c
+++ b/sound/oss/sb_common.c
@@ -625,7 +625,7 @@
 	 */
 
 
-	detected_devc = (sb_devc *)kmalloc(sizeof(sb_devc), GFP_KERNEL);
+	detected_devc = kmalloc(sizeof(sb_devc), GFP_KERNEL);
 	if (detected_devc == NULL)
 	{
 		printk(KERN_ERR "sb: Can't allocate memory for device information\n");
diff --git a/sound/oss/sb_midi.c b/sound/oss/sb_midi.c
index 2e3bc04..8b79670 100644
--- a/sound/oss/sb_midi.c
+++ b/sound/oss/sb_midi.c
@@ -173,7 +173,7 @@
 		return;
 	}
 	std_midi_synth.midi_dev = devc->my_mididev = dev;
-	midi_devs[dev] = (struct midi_operations *)kmalloc(sizeof(struct midi_operations), GFP_KERNEL);
+	midi_devs[dev] = kmalloc(sizeof(struct midi_operations), GFP_KERNEL);
 	if (midi_devs[dev] == NULL)
 	{
 		printk(KERN_WARNING "Sound Blaster:  failed to allocate MIDI memory.\n");
@@ -189,7 +189,7 @@
 	midi_devs[dev]->devc = devc;
 
 
-	midi_devs[dev]->converter = (struct synth_operations *)kmalloc(sizeof(struct synth_operations), GFP_KERNEL);
+	midi_devs[dev]->converter = kmalloc(sizeof(struct synth_operations), GFP_KERNEL);
 	if (midi_devs[dev]->converter == NULL)
 	{
 		  printk(KERN_WARNING "Sound Blaster:  failed to allocate MIDI memory.\n");
diff --git a/sound/oss/sb_mixer.c b/sound/oss/sb_mixer.c
index 238e2cf..fad1a4f 100644
--- a/sound/oss/sb_mixer.c
+++ b/sound/oss/sb_mixer.c
@@ -734,7 +734,7 @@
 	if (m == -1)
 		return 0;
 
-	mixer_devs[m] = (struct mixer_operations *)kmalloc(sizeof(struct mixer_operations), GFP_KERNEL);
+	mixer_devs[m] = kmalloc(sizeof(struct mixer_operations), GFP_KERNEL);
 	if (mixer_devs[m] == NULL)
 	{
 		printk(KERN_ERR "sb_mixer: Can't allocate memory\n");
diff --git a/sound/oss/v_midi.c b/sound/oss/v_midi.c
index d952b22..103940f 100644
--- a/sound/oss/v_midi.c
+++ b/sound/oss/v_midi.c
@@ -183,7 +183,7 @@
 		return;
 	}
 	
-	m=(struct vmidi_memory *)kmalloc(sizeof(struct vmidi_memory), GFP_KERNEL);
+	m = kmalloc(sizeof(struct vmidi_memory), GFP_KERNEL);
 	if (m == NULL)
 	{
 		printk(KERN_WARNING "Loopback MIDI: Failed to allocate memory\n");
diff --git a/sound/oss/waveartist.c b/sound/oss/waveartist.c
index c5bf363..26a7c6a 100644
--- a/sound/oss/waveartist.c
+++ b/sound/oss/waveartist.c
@@ -1267,7 +1267,7 @@
 	conf_printf2(dev_name, devc->hw.io_base, devc->hw.irq,
 		     devc->hw.dma, devc->hw.dma2);
 
-	portc = (wavnc_port_info *)kmalloc(sizeof(wavnc_port_info), GFP_KERNEL);
+	portc = kmalloc(sizeof(wavnc_port_info), GFP_KERNEL);
 	if (portc == NULL)
 		goto nomem;