Merge branch 'drm-patches' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6

* 'drm-patches' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6:
  drm: possible cleanups
  drm: fixup r300 scratch on BE machines
diff --git a/Documentation/block/switching-sched.txt b/Documentation/block/switching-sched.txt
new file mode 100644
index 0000000..5fa130a
--- /dev/null
+++ b/Documentation/block/switching-sched.txt
@@ -0,0 +1,22 @@
+As of the Linux 2.6.10 kernel, it is now possible to change the
+IO scheduler for a given block device on the fly (thus making it possible,
+for instance, to set the CFQ scheduler for the system default, but
+set a specific device to use the anticipatory or noop schedulers - which
+can improve that device's throughput).
+
+To set a specific scheduler, simply do this:
+
+echo SCHEDNAME > /sys/block/DEV/queue/scheduler
+
+where SCHEDNAME is the name of a defined IO scheduler, and DEV is the
+device name (hda, hdb, sga, or whatever you happen to have).
+
+The list of defined schedulers can be found by simply doing
+a "cat /sys/block/DEV/queue/scheduler" - the list of valid names
+will be displayed, with the currently selected scheduler in brackets:
+
+# cat /sys/block/hda/queue/scheduler
+noop anticipatory deadline [cfq]
+# echo anticipatory > /sys/block/hda/queue/scheduler
+# cat /sys/block/hda/queue/scheduler
+noop [anticipatory] deadline cfq
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 293fed1..421bcff 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -25,8 +25,9 @@
 
 ---------------------------
 
-What:	drivers depending on OBSOLETE_OSS_DRIVER
-When:	January 2006
+What:	drivers that were depending on OBSOLETE_OSS_DRIVER
+        (config options already removed)
+When:	before 2.6.19
 Why:	OSS drivers with ALSA replacements
 Who:	Adrian Bunk <bunk@stusta.de>
 
diff --git a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt
index 2803f63..687104b 100644
--- a/Documentation/vm/hugetlbpage.txt
+++ b/Documentation/vm/hugetlbpage.txt
@@ -32,7 +32,16 @@
 .....
 HugePages_Total: xxx
 HugePages_Free:  yyy
-Hugepagesize:    zzz KB
+HugePages_Rsvd:  www
+Hugepagesize:    zzz kB
+
+where:
+HugePages_Total is the size of the pool of hugepages.
+HugePages_Free is the number of hugepages in the pool that are not yet
+allocated.
+HugePages_Rsvd is short for "reserved," and is the number of hugepages
+for which a commitment to allocate from the pool has been made, but no
+allocation has yet been made. It's vaguely analogous to overcommit.
 
 /proc/filesystems should also show a filesystem of type "hugetlbfs" configured
 in the kernel.
diff --git a/MAINTAINERS b/MAINTAINERS
index 78a2f5b..61060e8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1458,6 +1458,13 @@
 L:	openib-general@openib.org
 S:	Supported
 
+IPMI SUBSYSTEM
+P:	Corey Minyard
+M:	minyard@acm.org
+L:	openipmi-developer@lists.sourceforge.net
+W:	http://openipmi.sourceforge.net/
+S:	Supported
+
 IPX NETWORK LAYER
 P:	Arnaldo Carvalho de Melo
 M:	acme@conectiva.com.br
diff --git a/README b/README
index 05e0555..3e26472 100644
--- a/README
+++ b/README
@@ -165,10 +165,31 @@
 	"make xconfig"     X windows (Qt) based configuration tool.
 	"make gconfig"     X windows (Gtk) based configuration tool.
 	"make oldconfig"   Default all questions based on the contents of
-			   your existing ./.config file.
+			   your existing ./.config file and asking about
+			   new config symbols.
 	"make silentoldconfig"
 			   Like above, but avoids cluttering the screen
 			   with questions already answered.
+	"make defconfig"   Create a ./.config file by using the default
+			   symbol values from arch/$ARCH/defconfig.
+	"make allyesconfig"
+			   Create a ./.config file by setting symbol
+			   values to 'y' as much as possible.
+	"make allmodconfig"
+			   Create a ./.config file by setting symbol
+			   values to 'm' as much as possible.
+	"make allnoconfig" Create a ./.config file by setting symbol
+			   values to 'n' as much as possible.
+	"make randconfig"  Create a ./.config file by setting symbol
+			   values to random values.
+
+   The allyesconfig/allmodconfig/allnoconfig/randconfig variants can
+   also use the environment variable KCONFIG_ALLCONFIG to specify a
+   filename that contains config options that the user requires to be
+   set to a specific value.  If KCONFIG_ALLCONFIG=filename is not used,
+   "make *config" checks for a file named "all{yes/mod/no/random}.config"
+   for symbol values that are to be forced.  If this file is not found,
+   it checks for a file named "all.config" to contain forced values.
    
 	NOTES on "make config":
 	- having unnecessary drivers will make the kernel bigger, and can
diff --git a/arch/arm/configs/ep93xx_defconfig b/arch/arm/configs/ep93xx_defconfig
index 8dcc8e8..b69e88b 100644
--- a/arch/arm/configs/ep93xx_defconfig
+++ b/arch/arm/configs/ep93xx_defconfig
@@ -1,12 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16
-# Mon Mar 20 14:54:51 2006
+# Linux kernel version: 2.6.17-rc2
+# Wed Apr 19 21:21:01 2006
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
 
 #
 # Code maturity level options
@@ -28,6 +30,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_UID16=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -43,10 +46,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -59,7 +58,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
@@ -67,6 +65,7 @@
 #
 # Block layer
 #
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -94,6 +93,7 @@
 # CONFIG_ARCH_IOP3XX is not set
 # CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
 # CONFIG_ARCH_L7200 is not set
 # CONFIG_ARCH_PXA is not set
 # CONFIG_ARCH_RPC is not set
@@ -112,7 +112,6 @@
 #
 # Cirrus EP93xx Implementation Options
 #
-CONFIG_CRUNCH=y
 
 #
 # EP93xx Platforms
@@ -232,12 +231,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -346,7 +348,6 @@
 # CONFIG_MTD_OTP is not set
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
 CONFIG_MTD_CFI_STAA=y
 CONFIG_MTD_CFI_UTIL=y
 # CONFIG_MTD_RAM is not set
@@ -371,7 +372,6 @@
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
 # CONFIG_MTD_BLOCK2MTD is not set
 
 #
@@ -412,7 +412,7 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_UB is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
@@ -576,13 +576,13 @@
 # Watchdog Device Drivers
 #
 # CONFIG_SOFT_WATCHDOG is not set
+CONFIG_EP93XX_WATCHDOG=y
 
 #
 # USB-based Watchdog Cards
 #
 # CONFIG_USBPCWATCHDOG is not set
 # CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 
@@ -626,9 +626,7 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
 # CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
 CONFIG_I2C_DEBUG_CORE=y
 CONFIG_I2C_DEBUG_ALGO=y
 CONFIG_I2C_DEBUG_BUS=y
@@ -690,7 +688,16 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
 #
 
 #
@@ -702,6 +709,7 @@
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
@@ -718,6 +726,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 # CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 CONFIG_USB=y
 CONFIG_USB_DEBUG=y
 
@@ -776,15 +785,6 @@
 # CONFIG_USB_MICROTEK is not set
 
 #
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -813,6 +813,7 @@
 # CONFIG_USB_SERIAL_CYPRESS_M8 is not set
 # CONFIG_USB_SERIAL_EMPEG is not set
 # CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_FUNSOFT is not set
 # CONFIG_USB_SERIAL_VISOR is not set
 # CONFIG_USB_SERIAL_IPAQ is not set
 # CONFIG_USB_SERIAL_IR is not set
@@ -825,6 +826,7 @@
 # CONFIG_USB_SERIAL_KLSI is not set
 # CONFIG_USB_SERIAL_KOBIL_SCT is not set
 # CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
 CONFIG_USB_SERIAL_PL2303=y
 # CONFIG_USB_SERIAL_HP4X is not set
 # CONFIG_USB_SERIAL_SAFE is not set
@@ -865,6 +867,32 @@
 # CONFIG_MMC is not set
 
 #
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+CONFIG_RTC_DRV_M48T86=y
+CONFIG_RTC_DRV_EP93XX=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -912,7 +940,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1044,6 +1071,7 @@
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SLAB_LEAK is not set
 CONFIG_DEBUG_MUTEXES=y
 CONFIG_DEBUG_SPINLOCK=y
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
@@ -1053,6 +1081,7 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
 CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/ixp2000_defconfig b/arch/arm/configs/ixp2000_defconfig
index 7b02ca0..e6f3e48 100644
--- a/arch/arm/configs/ixp2000_defconfig
+++ b/arch/arm/configs/ixp2000_defconfig
@@ -1,18 +1,19 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc2
-# Wed Feb  8 04:49:11 2006
+# Linux kernel version: 2.6.17-rc2
+# Wed Apr 19 21:12:49 2006
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -29,6 +30,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_UID16=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -44,10 +46,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -60,7 +58,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
@@ -68,6 +65,7 @@
 #
 # Block layer
 #
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -89,11 +87,13 @@
 # CONFIG_ARCH_CLPS711X is not set
 # CONFIG_ARCH_CO285 is not set
 # CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
 # CONFIG_ARCH_INTEGRATOR is not set
 # CONFIG_ARCH_IOP3XX is not set
 # CONFIG_ARCH_IXP4XX is not set
 CONFIG_ARCH_IXP2000=y
+# CONFIG_ARCH_IXP23XX is not set
 # CONFIG_ARCH_L7200 is not set
 # CONFIG_ARCH_PXA is not set
 # CONFIG_ARCH_RPC is not set
@@ -123,6 +123,7 @@
 CONFIG_ARCH_IXDP2X00=y
 CONFIG_ARCH_IXDP2401=y
 CONFIG_ARCH_IXDP2801=y
+CONFIG_MACH_IXDP28X5=y
 CONFIG_ARCH_IXDP2X01=y
 # CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO is not set
 
@@ -147,7 +148,6 @@
 # Bus support
 #
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -160,6 +160,7 @@
 #
 # CONFIG_PREEMPT is not set
 # CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
 # CONFIG_AEABI is not set
 # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
 CONFIG_SELECT_MEMORY_MODEL=y
@@ -213,6 +214,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -232,12 +234,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -347,7 +352,6 @@
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
 # CONFIG_MTD_OBSOLETE_CHIPS is not set
-# CONFIG_MTD_XIP is not set
 
 #
 # Mapping drivers for chip access
@@ -366,7 +370,6 @@
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
 # CONFIG_MTD_BLOCK2MTD is not set
 
 #
@@ -614,8 +617,9 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=3
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=3
 # CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
@@ -623,6 +627,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -650,7 +655,6 @@
 # CONFIG_PCIPCWATCHDOG is not set
 # CONFIG_WDTPCI is not set
 # CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -696,7 +700,6 @@
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
@@ -715,9 +718,7 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
 # CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
@@ -730,6 +731,11 @@
 # CONFIG_SPI_MASTER is not set
 
 #
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
 # Hardware Monitoring support
 #
 CONFIG_HWMON=y
@@ -742,6 +748,7 @@
 # CONFIG_SENSORS_ASB100 is not set
 # CONFIG_SENSORS_ATXP1 is not set
 # CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_FSCPOS is not set
 # CONFIG_SENSORS_GL518SM is not set
@@ -776,7 +783,16 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
 #
 
 #
@@ -804,6 +820,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -821,6 +838,12 @@
 # CONFIG_MMC is not set
 
 #
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -870,7 +893,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -972,6 +994,7 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
 CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/ixp23xx_defconfig b/arch/arm/configs/ixp23xx_defconfig
index 1a2751e..9ce898a 100644
--- a/arch/arm/configs/ixp23xx_defconfig
+++ b/arch/arm/configs/ixp23xx_defconfig
@@ -1,12 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16
-# Tue Mar 21 03:27:20 2006
+# Linux kernel version: 2.6.17-rc2
+# Wed Apr 19 21:13:50 2006
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
 
 #
 # Code maturity level options
@@ -28,6 +30,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_UID16=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -43,10 +46,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -59,7 +58,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
@@ -67,6 +65,7 @@
 #
 # Block layer
 #
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -143,7 +142,6 @@
 # Bus support
 #
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -230,12 +228,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -365,7 +366,6 @@
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
 # CONFIG_MTD_BLOCK2MTD is not set
 
 #
@@ -527,7 +527,6 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
@@ -735,6 +734,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -776,7 +776,6 @@
 #
 # CONFIG_USBPCWATCHDOG is not set
 # CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -821,7 +820,6 @@
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
@@ -840,9 +838,7 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
 # CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
@@ -907,7 +903,16 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
 #
 
 #
@@ -919,6 +924,7 @@
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
@@ -935,6 +941,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -1000,9 +1007,7 @@
 # CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
@@ -1017,15 +1022,6 @@
 # CONFIG_USB_MICROTEK is not set
 
 #
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -1076,6 +1072,12 @@
 # CONFIG_MMC is not set
 
 #
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1127,7 +1129,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1268,6 +1269,7 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
 CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 8cff73e..9fc9af8 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -407,7 +407,7 @@
 }
 __early_param("initrd=", early_initrd);
 
-static void __init add_memory(unsigned long start, unsigned long size)
+static void __init arm_add_memory(unsigned long start, unsigned long size)
 {
 	/*
 	 * Ensure that start/size are aligned to a page boundary.
@@ -445,7 +445,7 @@
 	if (**p == '@')
 		start = memparse(*p + 1, p);
 
-	add_memory(start, size);
+	arm_add_memory(start, size);
 }
 __early_param("mem=", early_mem);
 
@@ -587,7 +587,7 @@
 			tag->u.mem.start, tag->u.mem.size / 1024);
 		return -EINVAL;
 	}
-	add_memory(tag->u.mem.start, tag->u.mem.size);
+	arm_add_memory(tag->u.mem.start, tag->u.mem.size);
 	return 0;
 }
 
@@ -807,7 +807,7 @@
 {
 	int cpu;
 
-	for_each_cpu(cpu)
+	for_each_possible_cpu(cpu)
 		register_cpu(&per_cpu(cpu_data, cpu).cpu, cpu, NULL);
 
 	return 0;
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index a0888e1..00b761f 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -91,7 +91,7 @@
 /*
  * IRQ -> GPIO mapping table
  */
-static char irq2gpio[32] = {
+static signed char irq2gpio[32] = {
 	-1, -1, -1, -1, -1, -1,  0,  1,
 	-1, -1, -1, -1, -1, -1, -1, -1,
 	-1, -1, -1,  2,  3,  4,  5,  6,
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index da30a37..df0e174 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -1079,7 +1079,7 @@
 			break;
 	}
 
-	if (error == APM_NOT_ENGAGED && state != APM_STATE_READY) {
+	if (error == APM_NOT_ENGAGED) {
 		static int tried;
 		int eng_error;
 		if (tried++ == 0) {
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
index ff2b215..786d1a5 100644
--- a/arch/i386/kernel/cpu/amd.c
+++ b/arch/i386/kernel/cpu/amd.c
@@ -207,6 +207,8 @@
 		set_bit(X86_FEATURE_K7, c->x86_capability); 
 		break;
 	}
+	if (c->x86 >= 6)
+		set_bit(X86_FEATURE_FXSAVE_LEAK, c->x86_capability);
 
 	display_cacheinfo(c);
 
diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c
index 006141d..1d9a4ab 100644
--- a/arch/i386/kernel/cpuid.c
+++ b/arch/i386/kernel/cpuid.c
@@ -168,7 +168,7 @@
 	return err;
 }
 
-static int __devinit cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
+static int cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 {
 	unsigned int cpu = (unsigned long)hcpu;
 
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index f197687..043f529 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -43,7 +43,7 @@
 DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
 
 /* insert a jmp code */
-static inline void set_jmp_op(void *from, void *to)
+static __always_inline void set_jmp_op(void *from, void *to)
 {
 	struct __arch_jmp_op {
 		char op;
@@ -57,7 +57,7 @@
 /*
  * returns non-zero if opcodes can be boosted.
  */
-static inline int can_boost(kprobe_opcode_t opcode)
+static __always_inline int can_boost(kprobe_opcode_t opcode)
 {
 	switch (opcode & 0xf0 ) {
 	case 0x70:
@@ -88,7 +88,7 @@
 /*
  * returns non-zero if opcode modifies the interrupt flag.
  */
-static inline int is_IF_modifier(kprobe_opcode_t opcode)
+static int __kprobes is_IF_modifier(kprobe_opcode_t opcode)
 {
 	switch (opcode) {
 	case 0xfa:		/* cli */
@@ -138,7 +138,7 @@
 	mutex_unlock(&kprobe_mutex);
 }
 
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	kcb->prev_kprobe.kp = kprobe_running();
 	kcb->prev_kprobe.status = kcb->kprobe_status;
@@ -146,7 +146,7 @@
 	kcb->prev_kprobe.saved_eflags = kcb->kprobe_saved_eflags;
 }
 
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
 	kcb->kprobe_status = kcb->prev_kprobe.status;
@@ -154,7 +154,7 @@
 	kcb->kprobe_saved_eflags = kcb->prev_kprobe.saved_eflags;
 }
 
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
 				struct kprobe_ctlblk *kcb)
 {
 	__get_cpu_var(current_kprobe) = p;
@@ -164,7 +164,7 @@
 		kcb->kprobe_saved_eflags &= ~IF_MASK;
 }
 
-static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
 {
 	regs->eflags |= TF_MASK;
 	regs->eflags &= ~IF_MASK;
@@ -507,7 +507,7 @@
  * Interrupts are disabled on entry as trap1 is an interrupt gate and they
  * remain disabled thoroughout this function.
  */
-static inline int post_kprobe_handler(struct pt_regs *regs)
+static int __kprobes post_kprobe_handler(struct pt_regs *regs)
 {
 	struct kprobe *cur = kprobe_running();
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -543,7 +543,7 @@
 	return 1;
 }
 
-static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
 	struct kprobe *cur = kprobe_running();
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c
index 1d0a55e..7a32823 100644
--- a/arch/i386/kernel/msr.c
+++ b/arch/i386/kernel/msr.c
@@ -251,7 +251,7 @@
 	return err;
 }
 
-static int __devinit msr_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
+static int msr_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 {
 	unsigned int cpu = (unsigned long)hcpu;
 
diff --git a/arch/i386/mach-voyager/voyager_cat.c b/arch/i386/mach-voyager/voyager_cat.c
index 3039539..10d21df 100644
--- a/arch/i386/mach-voyager/voyager_cat.c
+++ b/arch/i386/mach-voyager/voyager_cat.c
@@ -120,7 +120,6 @@
  * It writes num_bits of the data buffer in msg starting at start_bit.
  * Note: This function assumes that any unused bit in the data stream
  * is set to zero so that the ors will work correctly */
-#define BITS_PER_BYTE 8
 static void
 cat_pack(__u8 *msg, const __u16 start_bit, __u8 *data, const __u16 num_bits)
 {
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 789881c..f9039f8 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -251,7 +251,7 @@
 	update_kprobe_inst_flag(template, slot, major_opcode, kprobe_inst, p);
 }
 
-static inline void get_kprobe_inst(bundle_t *bundle, uint slot,
+static void __kprobes get_kprobe_inst(bundle_t *bundle, uint slot,
 	       	unsigned long *kprobe_inst, uint *major_opcode)
 {
 	unsigned long kprobe_inst_p0, kprobe_inst_p1;
@@ -278,7 +278,7 @@
 }
 
 /* Returns non-zero if the addr is in the Interrupt Vector Table */
-static inline int in_ivt_functions(unsigned long addr)
+static int __kprobes in_ivt_functions(unsigned long addr)
 {
 	return (addr >= (unsigned long)__start_ivt_text
 		&& addr < (unsigned long)__end_ivt_text);
@@ -308,19 +308,19 @@
 	return 0;
 }
 
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	kcb->prev_kprobe.kp = kprobe_running();
 	kcb->prev_kprobe.status = kcb->kprobe_status;
 }
 
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
 	kcb->kprobe_status = kcb->prev_kprobe.status;
 }
 
-static inline void set_current_kprobe(struct kprobe *p,
+static void __kprobes set_current_kprobe(struct kprobe *p,
 			struct kprobe_ctlblk *kcb)
 {
 	__get_cpu_var(current_kprobe) = p;
diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S
index 3871b65..920bb74 100644
--- a/arch/m32r/kernel/entry.S
+++ b/arch/m32r/kernel/entry.S
@@ -20,7 +20,7 @@
  * Stack layout in 'ret_from_system_call':
  * 	ptrace needs to have all regs on the stack.
  *	if the order here is changed, it needs to be
- *	updated in fork.c:copy_process, signal.c:do_signal,
+ *	updated in fork.c:copy_thread, signal.c:do_signal,
  *	ptrace.c and ptrace.h
  *
  * M32Rx/M32R2				M32R
@@ -41,18 +41,17 @@
  *       @(0x38,sp) - syscall_nr	ditto
  *       @(0x3c,sp) - acc0h		@(0x3c,sp) - acch
  *       @(0x40,sp) - acc0l		@(0x40,sp) - accl
- *       @(0x44,sp) - acc1h		@(0x44,sp) - psw
- *       @(0x48,sp) - acc1l		@(0x48,sp) - bpc
- *       @(0x4c,sp) - psw		@(0x4c,sp) - bbpsw
- *       @(0x50,sp) - bpc		@(0x50,sp) - bbpc
- *       @(0x54,sp) - bbpsw		@(0x54,sp) - spu (cr3)
- *       @(0x58,sp) - bbpc		@(0x58,sp) - fp (r13)
- *       @(0x5c,sp) - spu (cr3)		@(0x5c,sp) - lr (r14)
- *       @(0x60,sp) - fp (r13)		@(0x60,sp) - spi (cr12)
- *       @(0x64,sp) - lr (r14)		@(0x64,sp) - orig_r0
- *       @(0x68,sp) - spi (cr2)
- *       @(0x6c,sp) - orig_r0
- *
+ *       @(0x44,sp) - acc1h		@(0x44,sp) - dummy_acc1h
+ *       @(0x48,sp) - acc1l		@(0x48,sp) - dummy_acc1l
+ *       @(0x4c,sp) - psw		ditto
+ *       @(0x50,sp) - bpc		ditto
+ *       @(0x54,sp) - bbpsw		ditto
+ *       @(0x58,sp) - bbpc		ditto
+ *       @(0x5c,sp) - spu (cr3)		ditto
+ *       @(0x60,sp) - fp (r13)		ditto
+ *       @(0x64,sp) - lr (r14)		ditto
+ *       @(0x68,sp) - spi (cr2)		ditto
+ *       @(0x6c,sp) - orig_r0		ditto
  */
 
 #include <linux/config.h>
@@ -102,6 +101,12 @@
 #define ACC0L(reg)		@(0x40,reg)
 #define ACC1H(reg)		@(0x44,reg)
 #define ACC1L(reg)		@(0x48,reg)
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+#define ACCH(reg)		@(0x3C,reg)
+#define ACCL(reg)		@(0x40,reg)
+#else
+#error unknown isa configuration
+#endif
 #define PSW(reg)		@(0x4C,reg)
 #define BPC(reg)		@(0x50,reg)
 #define BBPSW(reg)		@(0x54,reg)
@@ -111,21 +116,6 @@
 #define LR(reg)			@(0x64,reg)
 #define SP(reg)			@(0x68,reg)
 #define ORIG_R0(reg)		@(0x6C,reg)
-#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
-#define ACCH(reg)		@(0x3C,reg)
-#define ACCL(reg)		@(0x40,reg)
-#define PSW(reg)		@(0x44,reg)
-#define BPC(reg)		@(0x48,reg)
-#define BBPSW(reg)		@(0x4C,reg)
-#define BBPC(reg)		@(0x50,reg)
-#define SPU(reg)		@(0x54,reg)
-#define FP(reg)			@(0x58,reg)  /* FP = R13 */
-#define LR(reg)			@(0x5C,reg)
-#define SP(reg)			@(0x60,reg)
-#define ORIG_R0(reg)		@(0x64,reg)
-#else
-#error unknown isa configuration
-#endif
 
 CF_MASK		= 0x00000001
 TF_MASK		= 0x00000100
@@ -142,7 +132,7 @@
 #endif
 
 ENTRY(ret_from_fork)
-	ld	r0, @sp+
+	pop	r0
 	bl	schedule_tail
 	GET_THREAD_INFO(r8)
 	bra	syscall_exit
@@ -231,7 +221,7 @@
 	RESTORE_ALL
 
 	# perform work that needs to be done immediately before resumption
-	# r9 : frags
+	# r9 : flags
 	ALIGN
 work_pending:
 	and3	r4, r9, #_TIF_NEED_RESCHED
@@ -320,7 +310,7 @@
 ;    GET_ICU_STATUS;
 	seth	r0, #shigh(M32R_ICU_ISTS_ADDR)
 	ld	r0, @(low(M32R_ICU_ISTS_ADDR),r0)
-	st	r0, @-sp
+	push	r0
 #if defined(CONFIG_SMP)
 	/*
 	 * If IRQ == 0      --> Nothing to do,  Not write IMASK
@@ -557,7 +547,7 @@
 #endif  /* CONFIG_PLAT_M32104UT */
 	bl	do_IRQ
 #endif  /* CONFIG_SMP */
-	ld	r14, @sp+
+	pop	r14
 	seth	r0, #shigh(M32R_ICU_IMASK_ADDR)
 	st	r14, @(low(M32R_ICU_IMASK_ADDR),r0)
 #else
@@ -1015,4 +1005,3 @@
 	.long sys_waitid
 
 syscall_table_size=(.-sys_call_table)
-
diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c
index 5dfc7ea..065f5e7 100644
--- a/arch/m32r/kernel/process.c
+++ b/arch/m32r/kernel/process.c
@@ -116,6 +116,10 @@
 
 void machine_restart(char *__unused)
 {
+#if defined(CONFIG_PLAT_MAPPI3)
+	outw(1, (unsigned long)PLD_REBOOT);
+#endif
+
 	printk("Please push reset button!\n");
 	while (1)
 		cpu_relax();
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c
index cb33097..6498ee7 100644
--- a/arch/m32r/kernel/signal.c
+++ b/arch/m32r/kernel/signal.c
@@ -118,6 +118,8 @@
 #elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
 	COPY(acch);
 	COPY(accl);
+	COPY(dummy_acc1h);
+	COPY(dummy_acc1l);
 #else
 #error unknown isa configuration
 #endif
@@ -203,6 +205,8 @@
 #elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
 	COPY(acch);
 	COPY(accl);
+	COPY(dummy_acc1h);
+	COPY(dummy_acc1l);
 #else
 #error unknown isa configuration
 #endif
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig
index 2c3fd20..a456275 100644
--- a/arch/powerpc/configs/g5_defconfig
+++ b/arch/powerpc/configs/g5_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc2
-# Fri Feb 10 17:33:08 2006
+# Linux kernel version: 2.6.17-rc1
+# Wed Apr 19 13:24:37 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -9,6 +9,7 @@
 CONFIG_MMU=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_PPC=y
 CONFIG_EARLY_PRINTK=y
@@ -29,6 +30,7 @@
 CONFIG_PPC_FPU=y
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
+CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=4
 
@@ -53,6 +55,7 @@
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_EMBEDDED is not set
@@ -67,10 +70,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -82,7 +81,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -91,6 +89,7 @@
 #
 # Block layer
 #
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -185,7 +184,6 @@
 # CONFIG_PPC_INDIRECT_PCI is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -227,6 +225,7 @@
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
 CONFIG_INET_TUNNEL=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
@@ -238,6 +237,8 @@
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -261,6 +262,7 @@
 CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_AMANDA=m
 # CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
 CONFIG_IP_NF_QUEUE=m
 
 #
@@ -513,6 +515,7 @@
 CONFIG_MD_RAID1=y
 CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=y
+# CONFIG_MD_RAID5_RESHAPE is not set
 CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
@@ -761,7 +764,6 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
 # CONFIG_DTLK is not set
@@ -772,6 +774,7 @@
 # Ftape, the floppy tape device driver
 #
 CONFIG_AGP=m
+# CONFIG_AGP_VIA is not set
 CONFIG_AGP_UNINORTH=m
 # CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=y
@@ -813,7 +816,6 @@
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
@@ -832,9 +834,7 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
 # CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
@@ -862,10 +862,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -874,6 +870,7 @@
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
@@ -883,6 +880,7 @@
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
 CONFIG_FB_MACMODES=y
+CONFIG_FB_FIRMWARE_EDID=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 # CONFIG_FB_CIRRUS is not set
@@ -901,7 +899,6 @@
 CONFIG_FB_NVIDIA_I2C=y
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
 CONFIG_FB_RADEON=y
 CONFIG_FB_RADEON_I2C=y
 # CONFIG_FB_RADEON_DEBUG is not set
@@ -958,9 +955,11 @@
 CONFIG_SND_OSSEMUL=y
 CONFIG_SND_MIXER_OSS=m
 CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
 CONFIG_SND_SEQUENCER_OSS=y
 # CONFIG_SND_DYNAMIC_MINORS is not set
 CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
 
@@ -977,6 +976,7 @@
 # PCI devices
 #
 # CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
 # CONFIG_SND_ALS4000 is not set
 # CONFIG_SND_ALI5451 is not set
 # CONFIG_SND_ATIIXP is not set
@@ -1009,6 +1009,7 @@
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
 # CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
 # CONFIG_SND_RME32 is not set
 # CONFIG_SND_RME96 is not set
 # CONFIG_SND_RME9652 is not set
@@ -1041,6 +1042,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -1068,7 +1070,6 @@
 #
 # USB Device Class drivers
 #
-# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 CONFIG_USB_ACM=m
 CONFIG_USB_PRINTER=y
 
@@ -1126,15 +1127,6 @@
 # CONFIG_USB_MICROTEK is not set
 
 #
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
 # USB Network Adapters
 #
 CONFIG_USB_CATC=m
@@ -1194,6 +1186,7 @@
 CONFIG_USB_SERIAL_KLSI=m
 CONFIG_USB_SERIAL_KOBIL_SCT=m
 CONFIG_USB_SERIAL_MCT_U232=m
+# CONFIG_USB_SERIAL_NAVMAN is not set
 CONFIG_USB_SERIAL_PL2303=m
 # CONFIG_USB_SERIAL_HP4X is not set
 CONFIG_USB_SERIAL_SAFE=m
@@ -1237,17 +1230,23 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
-# EDAC - error detection and reporting (RAS)
+# Real Time Clock
 #
+# CONFIG_RTC_CLASS is not set
 
 #
 # File systems
@@ -1319,7 +1318,6 @@
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig
index 1816a46..a95e455 100644
--- a/arch/powerpc/configs/iseries_defconfig
+++ b/arch/powerpc/configs/iseries_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc6
-# Wed Mar 15 16:19:52 2006
+# Linux kernel version: 2.6.17-rc1
+# Wed Apr 19 11:46:44 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -9,6 +9,7 @@
 CONFIG_MMU=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_PPC=y
 CONFIG_EARLY_PRINTK=y
@@ -30,6 +31,7 @@
 CONFIG_PPC_FPU=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
+CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=32
 
@@ -55,6 +57,7 @@
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_EMBEDDED is not set
@@ -69,10 +72,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -84,7 +83,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -93,6 +91,7 @@
 #
 # Block layer
 #
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -165,7 +164,6 @@
 # CONFIG_PPC_INDIRECT_PCI is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -207,6 +205,7 @@
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
 CONFIG_INET_TUNNEL=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
@@ -218,6 +217,8 @@
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -236,11 +237,14 @@
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 # CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -262,20 +266,19 @@
 CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_AMANDA=m
 # CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
 CONFIG_IP_NF_MATCH_TOS=m
 CONFIG_IP_NF_MATCH_RECENT=m
 CONFIG_IP_NF_MATCH_ECN=m
 CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
+# CONFIG_IP_NF_MATCH_AH is not set
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_MATCH_OWNER=m
 CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_POLICY=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_TARGET_LOG=m
@@ -479,6 +482,7 @@
 CONFIG_MD_RAID1=y
 CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=y
+# CONFIG_MD_RAID5_RESHAPE is not set
 CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
@@ -702,7 +706,6 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
 # CONFIG_DTLK is not set
@@ -751,10 +754,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -779,6 +778,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -796,6 +796,11 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
@@ -805,6 +810,11 @@
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -878,7 +888,6 @@
 # CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index daaf038..58e68ce 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc2
-# Fri Feb 10 17:33:32 2006
+# Linux kernel version: 2.6.17-rc1
+# Wed Apr 19 11:48:00 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -9,6 +9,7 @@
 CONFIG_MMU=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_PPC=y
 CONFIG_EARLY_PRINTK=y
@@ -30,6 +31,7 @@
 CONFIG_PPC_FPU=y
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
+CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=128
 
@@ -55,6 +57,7 @@
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_CPUSETS=y
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_EMBEDDED is not set
@@ -69,10 +72,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -84,7 +83,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -93,6 +91,7 @@
 #
 # Block layer
 #
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -188,7 +187,6 @@
 # CONFIG_PPC_INDIRECT_PCI is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -235,6 +233,7 @@
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
 CONFIG_INET_TUNNEL=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
@@ -246,6 +245,8 @@
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -272,6 +273,7 @@
 CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_AMANDA=m
 # CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
 CONFIG_IP_NF_QUEUE=m
 
 #
@@ -519,6 +521,7 @@
 CONFIG_MD_RAID1=y
 CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=y
+# CONFIG_MD_RAID5_RESHAPE is not set
 CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
@@ -750,6 +753,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -767,7 +771,9 @@
 # CONFIG_PRINTER is not set
 # CONFIG_PPDEV is not set
 # CONFIG_TIPAR is not set
+CONFIG_HVC_DRIVER=y
 CONFIG_HVC_CONSOLE=y
+# CONFIG_HVC_RTAS is not set
 CONFIG_HVCS=m
 
 #
@@ -779,7 +785,6 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
 # CONFIG_DTLK is not set
@@ -830,7 +835,6 @@
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
@@ -849,9 +853,7 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
 # CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
@@ -879,10 +881,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -891,6 +889,7 @@
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
@@ -900,6 +899,7 @@
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
 CONFIG_FB_MACMODES=y
+CONFIG_FB_FIRMWARE_EDID=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 # CONFIG_FB_CIRRUS is not set
@@ -919,7 +919,6 @@
 CONFIG_FB_MATROX_G=y
 # CONFIG_FB_MATROX_I2C is not set
 CONFIG_FB_MATROX_MULTIHEAD=y
-# CONFIG_FB_RADEON_OLD is not set
 CONFIG_FB_RADEON=y
 CONFIG_FB_RADEON_I2C=y
 # CONFIG_FB_RADEON_DEBUG is not set
@@ -968,6 +967,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -1048,15 +1048,6 @@
 # CONFIG_USB_MICROTEK is not set
 
 #
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -1109,6 +1100,11 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
 # InfiniBand support
 #
 CONFIG_INFINIBAND=m
@@ -1121,12 +1117,13 @@
 # CONFIG_INFINIBAND_SRP is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
-# EDAC - error detection and reporting (RAS)
+# Real Time Clock
 #
+# CONFIG_RTC_CLASS is not set
 
 #
 # File systems
@@ -1202,7 +1199,6 @@
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index d9a7fde..4eba60a 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -61,6 +61,7 @@
 static unsigned long iommu_range_alloc(struct iommu_table *tbl,
                                        unsigned long npages,
                                        unsigned long *handle,
+                                       unsigned long mask,
                                        unsigned int align_order)
 { 
 	unsigned long n, end, i, start;
@@ -97,9 +98,21 @@
 	 */
 	if (start >= limit)
 		start = largealloc ? tbl->it_largehint : tbl->it_hint;
-	
+
  again:
 
+	if (limit + tbl->it_offset > mask) {
+		limit = mask - tbl->it_offset + 1;
+		/* If we're constrained on address range, first try
+		 * at the masked hint to avoid O(n) search complexity,
+		 * but on second pass, start at 0.
+		 */
+		if ((start & mask) >= limit || pass > 0)
+			start = 0;
+		else
+			start &= mask;
+	}
+
 	n = find_next_zero_bit(tbl->it_map, limit, start);
 
 	/* Align allocation */
@@ -150,14 +163,14 @@
 
 static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *page,
 		       unsigned int npages, enum dma_data_direction direction,
-		       unsigned int align_order)
+		       unsigned long mask, unsigned int align_order)
 {
 	unsigned long entry, flags;
 	dma_addr_t ret = DMA_ERROR_CODE;
-	
+
 	spin_lock_irqsave(&(tbl->it_lock), flags);
 
-	entry = iommu_range_alloc(tbl, npages, NULL, align_order);
+	entry = iommu_range_alloc(tbl, npages, NULL, mask, align_order);
 
 	if (unlikely(entry == DMA_ERROR_CODE)) {
 		spin_unlock_irqrestore(&(tbl->it_lock), flags);
@@ -236,7 +249,7 @@
 
 int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
 		struct scatterlist *sglist, int nelems,
-		enum dma_data_direction direction)
+		unsigned long mask, enum dma_data_direction direction)
 {
 	dma_addr_t dma_next = 0, dma_addr;
 	unsigned long flags;
@@ -274,7 +287,7 @@
 		vaddr = (unsigned long)page_address(s->page) + s->offset;
 		npages = PAGE_ALIGN(vaddr + slen) - (vaddr & PAGE_MASK);
 		npages >>= PAGE_SHIFT;
-		entry = iommu_range_alloc(tbl, npages, &handle, 0);
+		entry = iommu_range_alloc(tbl, npages, &handle, mask >> PAGE_SHIFT, 0);
 
 		DBG("  - vaddr: %lx, size: %lx\n", vaddr, slen);
 
@@ -479,7 +492,8 @@
  * byte within the page as vaddr.
  */
 dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
-		size_t size, enum dma_data_direction direction)
+		size_t size, unsigned long mask,
+		enum dma_data_direction direction)
 {
 	dma_addr_t dma_handle = DMA_ERROR_CODE;
 	unsigned long uaddr;
@@ -492,7 +506,8 @@
 	npages >>= PAGE_SHIFT;
 
 	if (tbl) {
-		dma_handle = iommu_alloc(tbl, vaddr, npages, direction, 0);
+		dma_handle = iommu_alloc(tbl, vaddr, npages, direction,
+					 mask >> PAGE_SHIFT, 0);
 		if (dma_handle == DMA_ERROR_CODE) {
 			if (printk_ratelimit())  {
 				printk(KERN_INFO "iommu_alloc failed, "
@@ -521,7 +536,7 @@
  * to the dma address (mapping) of the first page.
  */
 void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
-		dma_addr_t *dma_handle, gfp_t flag)
+		dma_addr_t *dma_handle, unsigned long mask, gfp_t flag)
 {
 	void *ret = NULL;
 	dma_addr_t mapping;
@@ -551,7 +566,8 @@
 	memset(ret, 0, size);
 
 	/* Set up tces to cover the allocated range */
-	mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL, order);
+	mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL,
+			      mask >> PAGE_SHIFT, order);
 	if (mapping == DMA_ERROR_CODE) {
 		free_pages((unsigned long)ret, order);
 		ret = NULL;
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index ad7a902..856ef1a 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -88,7 +88,7 @@
 	mutex_unlock(&kprobe_mutex);
 }
 
-static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
 {
 	kprobe_opcode_t insn = *p->ainsn.insn;
 
@@ -101,21 +101,21 @@
 		regs->nip = (unsigned long)p->ainsn.insn;
 }
 
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	kcb->prev_kprobe.kp = kprobe_running();
 	kcb->prev_kprobe.status = kcb->kprobe_status;
 	kcb->prev_kprobe.saved_msr = kcb->kprobe_saved_msr;
 }
 
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
 	kcb->kprobe_status = kcb->prev_kprobe.status;
 	kcb->kprobe_saved_msr = kcb->prev_kprobe.saved_msr;
 }
 
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
 				struct kprobe_ctlblk *kcb)
 {
 	__get_cpu_var(current_kprobe) = p;
@@ -141,7 +141,7 @@
 	}
 }
 
-static inline int kprobe_handler(struct pt_regs *regs)
+static int __kprobes kprobe_handler(struct pt_regs *regs)
 {
 	struct kprobe *p;
 	int ret = 0;
@@ -334,7 +334,7 @@
 		regs->nip = (unsigned long)p->addr + 4;
 }
 
-static inline int post_kprobe_handler(struct pt_regs *regs)
+static int __kprobes post_kprobe_handler(struct pt_regs *regs)
 {
 	struct kprobe *cur = kprobe_running();
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -370,7 +370,7 @@
 	return 1;
 }
 
-static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
 	struct kprobe *cur = kprobe_running();
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
diff --git a/arch/powerpc/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c
index c336f3e..c1d95e1 100644
--- a/arch/powerpc/kernel/pci_iommu.c
+++ b/arch/powerpc/kernel/pci_iommu.c
@@ -59,6 +59,25 @@
 }
 
 
+static inline unsigned long device_to_mask(struct device *hwdev)
+{
+	struct pci_dev *pdev;
+
+	if (!hwdev) {
+		pdev = ppc64_isabridge_dev;
+		if (!pdev) /* This is the best guess we can do */
+			return 0xfffffffful;
+	} else
+		pdev = to_pci_dev(hwdev);
+
+	if (pdev->dma_mask)
+		return pdev->dma_mask;
+
+	/* Assume devices without mask can take 32 bit addresses */
+	return 0xfffffffful;
+}
+
+
 /* Allocates a contiguous real buffer and creates mappings over it.
  * Returns the virtual address of the buffer and sets dma_handle
  * to the dma address (mapping) of the first page.
@@ -67,7 +86,7 @@
 			   dma_addr_t *dma_handle, gfp_t flag)
 {
 	return iommu_alloc_coherent(devnode_table(hwdev), size, dma_handle,
-			flag);
+			device_to_mask(hwdev), flag);
 }
 
 static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
@@ -85,7 +104,8 @@
 static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr,
 		size_t size, enum dma_data_direction direction)
 {
-	return iommu_map_single(devnode_table(hwdev), vaddr, size, direction);
+	return iommu_map_single(devnode_table(hwdev), vaddr, size,
+			        device_to_mask(hwdev), direction);
 }
 
 
@@ -100,7 +120,7 @@
 		int nelems, enum dma_data_direction direction)
 {
 	return iommu_map_sg(pdev, devnode_table(pdev), sglist,
-			nelems, direction);
+			nelems, device_to_mask(pdev), direction);
 }
 
 static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist,
@@ -112,7 +132,19 @@
 /* We support DMA to/from any memory page via the iommu */
 static int pci_iommu_dma_supported(struct device *dev, u64 mask)
 {
-	return 1;
+	struct iommu_table *tbl = devnode_table(dev);
+
+	if (!tbl || tbl->it_offset > mask) {
+		printk(KERN_INFO "Warning: IOMMU table offset too big for device mask\n");
+		if (tbl)
+			printk(KERN_INFO "mask: 0x%08lx, table offset: 0x%08lx\n",
+				mask, tbl->it_offset);
+		else
+			printk(KERN_INFO "mask: 0x%08lx, table unavailable\n",
+				mask);
+		return 0;
+	} else
+		return 1;
 }
 
 void pci_iommu_init(void)
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index dfa5398..4b052ae 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -81,6 +81,7 @@
 EXPORT_SYMBOL(strlen);
 EXPORT_SYMBOL(strcmp);
 EXPORT_SYMBOL(strcasecmp);
+EXPORT_SYMBOL(strncasecmp);
 
 EXPORT_SYMBOL(csum_partial);
 EXPORT_SYMBOL(csum_partial_copy_generic);
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 4336390..1cb69e8 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -62,7 +62,7 @@
 static int __initdata dt_root_size_cells;
 
 #ifdef CONFIG_PPC64
-static int __initdata iommu_is_off;
+int __initdata iommu_is_off;
 int __initdata iommu_force_on;
 unsigned long tce_alloc_start, tce_alloc_end;
 #endif
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S
index a14c964..8d15226 100644
--- a/arch/powerpc/kernel/systbl.S
+++ b/arch/powerpc/kernel/systbl.S
@@ -324,3 +324,8 @@
 SYSCALL(unshare)
 SYSCALL(splice)
 SYSCALL(tee)
+
+/*
+ * please add new calls to arch/powerpc/platforms/cell/spu_callbacks.c
+ * as well when appropriate.
+ */
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 13c655b..971020c 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -202,7 +202,7 @@
 			  size_t size, enum dma_data_direction direction)
 {
 	return iommu_map_single(to_vio_dev(dev)->iommu_table, vaddr, size,
-			direction);
+			~0ul, direction);
 }
 
 static void vio_unmap_single(struct device *dev, dma_addr_t dma_handle,
@@ -216,7 +216,7 @@
 		int nelems, enum dma_data_direction direction)
 {
 	return iommu_map_sg(dev, to_vio_dev(dev)->iommu_table, sglist,
-			nelems, direction);
+			nelems, ~0ul, direction);
 }
 
 static void vio_unmap_sg(struct device *dev, struct scatterlist *sglist,
@@ -229,7 +229,7 @@
 			   dma_addr_t *dma_handle, gfp_t flag)
 {
 	return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size,
-			dma_handle, flag);
+			dma_handle, ~0ul, flag);
 }
 
 static void vio_free_coherent(struct device *dev, size_t size,
diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c
index 6594bec..deb3afb 100644
--- a/arch/powerpc/platforms/cell/spu_callbacks.c
+++ b/arch/powerpc/platforms/cell/spu_callbacks.c
@@ -317,17 +317,16 @@
 	[__NR_ppoll]			sys_ni_syscall, /* sys_ppoll */
 	[__NR_unshare]			sys_unshare,
 	[__NR_splice]			sys_splice,
+	[__NR_tee]			sys_tee,
 };
 
 long spu_sys_callback(struct spu_syscall_block *s)
 {
 	long (*syscall)(u64 a1, u64 a2, u64 a3, u64 a4, u64 a5, u64 a6);
 
-	BUILD_BUG_ON(ARRAY_SIZE(spu_syscall_table) != __NR_syscalls);
-
 	syscall = spu_syscall_table[s->nr_ret];
 
-	if (s->nr_ret >= __NR_syscalls) {
+	if (s->nr_ret >= ARRAY_SIZE(spu_syscall_table)) {
 		pr_debug("%s: invalid syscall #%ld", __FUNCTION__, s->nr_ret);
 		return -ENOSYS;
 	}
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index e14f9ac..df2343e 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -231,6 +231,14 @@
 	return isr;
 }
 
+static void kw_i2c_do_stop(struct pmac_i2c_host_kw *host, int result)
+{
+	kw_write_reg(reg_control, KW_I2C_CTL_STOP);
+	host->state = state_stop;
+	host->result = result;
+}
+
+
 static void kw_i2c_handle_interrupt(struct pmac_i2c_host_kw *host, u8 isr)
 {
 	u8 ack;
@@ -246,42 +254,36 @@
 	}
 
 	if (isr == 0) {
+		printk(KERN_WARNING "low_i2c: Timeout in i2c transfer"
+		       " on keywest !\n");
 		if (host->state != state_stop) {
-			DBG_LOW("KW: Timeout !\n");
-			host->result = -EIO;
-			goto stop;
+			kw_i2c_do_stop(host, -EIO);
+			return;
 		}
-		if (host->state == state_stop) {
-			ack = kw_read_reg(reg_status);
-			if (ack & KW_I2C_STAT_BUSY)
-				kw_write_reg(reg_status, 0);
-			host->state = state_idle;
-			kw_write_reg(reg_ier, 0x00);
-			if (!host->polled)
-				complete(&host->complete);
-		}
+		ack = kw_read_reg(reg_status);
+		if (ack & KW_I2C_STAT_BUSY)
+			kw_write_reg(reg_status, 0);
+		host->state = state_idle;
+		kw_write_reg(reg_ier, 0x00);
+		if (!host->polled)
+			complete(&host->complete);
 		return;
 	}
 
 	if (isr & KW_I2C_IRQ_ADDR) {
 		ack = kw_read_reg(reg_status);
 		if (host->state != state_addr) {
-			kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
 			WRONG_STATE("KW_I2C_IRQ_ADDR"); 
-			host->result = -EIO;
-			goto stop;
+			kw_i2c_do_stop(host, -EIO);
 		}
 		if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
-			host->result = -ENODEV;
-			DBG_LOW("KW: NAK on address\n");
+			host->result = -ENXIO;
 			host->state = state_stop;
-			return;
+			DBG_LOW("KW: NAK on address\n");
 		} else {
-			if (host->len == 0) {
-				kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
-				goto stop;
-			}
-			if (host->rw) {
+			if (host->len == 0)
+				kw_i2c_do_stop(host, 0);
+			else if (host->rw) {
 				host->state = state_read;
 				if (host->len > 1)
 					kw_write_reg(reg_control,
@@ -308,25 +310,19 @@
 			ack = kw_read_reg(reg_status);
 			if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
 				DBG_LOW("KW: nack on data write\n");
-				host->result = -EIO;
-				goto stop;
+				host->result = -EFBIG;
+				host->state = state_stop;
 			} else if (host->len) {
 				kw_write_reg(reg_data, *(host->data++));
 				host->len--;
-			} else {
-				kw_write_reg(reg_control, KW_I2C_CTL_STOP);
-				host->state = state_stop;
-				host->result = 0;
-			}
-			kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
+			} else
+				kw_i2c_do_stop(host, 0);
 		} else {
-			kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
 			WRONG_STATE("KW_I2C_IRQ_DATA"); 
-			if (host->state != state_stop) {
-				host->result = -EIO;
-				goto stop;
-			}
+			if (host->state != state_stop)
+				kw_i2c_do_stop(host, -EIO);
 		}
+		kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
 	}
 
 	if (isr & KW_I2C_IRQ_STOP) {
@@ -340,14 +336,10 @@
 			complete(&host->complete);
 	}
 
+	/* Below should only happen in manual mode which we don't use ... */
 	if (isr & KW_I2C_IRQ_START)
 		kw_write_reg(reg_isr, KW_I2C_IRQ_START);
 
-	return;
- stop:
-	kw_write_reg(reg_control, KW_I2C_CTL_STOP);	
-	host->state = state_stop;
-	return;
 }
 
 /* Interrupt handler */
@@ -544,11 +536,11 @@
 		return NULL;
 	}
 
-	/* Make sure IRA is disabled */
+	/* Make sure IRQ is disabled */
 	kw_write_reg(reg_ier, 0);
 
 	/* Request chip interrupt */
-	if (request_irq(host->irq, kw_i2c_irq, SA_SHIRQ, "keywest i2c", host))
+	if (request_irq(host->irq, kw_i2c_irq, 0, "keywest i2c", host))
 		host->irq = NO_IRQ;
 
 	printk(KERN_INFO "KeyWest i2c @0x%08x irq %d %s\n",
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 61d3174..38087bd 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -49,6 +49,7 @@
 
 #include "dart.h"
 
+extern int iommu_is_off;
 extern int iommu_force_on;
 
 /* Physical base address and size of the DART table */
@@ -329,10 +330,17 @@
 
 void __init alloc_dart_table(void)
 {
-	/* Only reserve DART space if machine has more than 2GB of RAM
+	/* Only reserve DART space if machine has more than 1GB of RAM
 	 * or if requested with iommu=on on cmdline.
+	 *
+	 * 1GB of RAM is picked as limit because some default devices
+	 * (i.e. Airport Extreme) have 30 bit address range limits.
 	 */
-	if (lmb_end_of_DRAM() <= 0x80000000ull && !iommu_force_on)
+
+	if (iommu_is_off)
+		return;
+
+	if (!iommu_force_on && lmb_end_of_DRAM() <= 0x40000000ull)
 		return;
 
 	/* 512 pages (2MB) is max DART tablesize. */
diff --git a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c
index 77e4dc7..cc7c4ae 100644
--- a/arch/ppc/kernel/asm-offsets.c
+++ b/arch/ppc/kernel/asm-offsets.c
@@ -134,6 +134,7 @@
 	DEFINE(TI_TASK, offsetof(struct thread_info, task));
 	DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
 	DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+	DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, flags));
 	DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
 	DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
 
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index 5891ecb..1adc914 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -128,29 +128,26 @@
 	stw	r12,4(r11)
 #endif
 	b	3f
+
 2:	/* if from kernel, check interrupted DOZE/NAP mode and
          * check for stack overflow
          */
+	lwz	r9,THREAD_INFO-THREAD(r12)
+	cmplw	r1,r9			/* if r1 <= current->thread_info */
+	ble-	stack_ovf		/* then the kernel stack overflowed */
+5:
 #ifdef CONFIG_6xx
-	mfspr	r11,SPRN_HID0
-	mtcr	r11
-BEGIN_FTR_SECTION
-	bt-	8,4f			/* Check DOZE */
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
-BEGIN_FTR_SECTION
-	bt-	9,4f			/* Check NAP */
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
+	tophys(r9,r9)			/* check local flags */
+	lwz	r12,TI_LOCAL_FLAGS(r9)
+	mtcrf	0x01,r12
+	bt-	31-TLF_NAPPING,4f
 #endif /* CONFIG_6xx */
 	.globl transfer_to_handler_cont
 transfer_to_handler_cont:
-	lwz	r11,THREAD_INFO-THREAD(r12)
-	cmplw	r1,r11			/* if r1 <= current->thread_info */
-	ble-	stack_ovf		/* then the kernel stack overflowed */
 3:
 	mflr	r9
 	lwz	r11,0(r9)		/* virtual address of handler */
 	lwz	r9,4(r9)		/* where to go when done */
-	FIX_SRR1(r10,r12)
 	mtspr	SPRN_SRR0,r11
 	mtspr	SPRN_SRR1,r10
 	mtlr	r9
@@ -158,7 +155,9 @@
 	RFI				/* jump to handler, enable MMU */
 
 #ifdef CONFIG_6xx
-4:	b	power_save_6xx_restore
+4:	rlwinm	r12,r12,0,~_TLF_NAPPING
+	stw	r12,TI_LOCAL_FLAGS(r9)
+	b	power_save_6xx_restore
 #endif
 
 /*
@@ -167,10 +166,10 @@
  */
 stack_ovf:
 	/* sometimes we use a statically-allocated stack, which is OK. */
-	lis	r11,_end@h
-	ori	r11,r11,_end@l
-	cmplw	r1,r11
-	ble	3b			/* r1 <= &_end is OK */
+	lis	r12,_end@h
+	ori	r12,r12,_end@l
+	cmplw	r1,r12
+	ble	5b			/* r1 <= &_end is OK */
 	SAVE_NVGPRS(r11)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	lis	r1,init_thread_union@ha
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 865ba74..b250b1b 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -94,6 +94,7 @@
 EXPORT_SYMBOL(strlen);
 EXPORT_SYMBOL(strcmp);
 EXPORT_SYMBOL(strcasecmp);
+EXPORT_SYMBOL(strncasecmp);
 EXPORT_SYMBOL(__div64_32);
 
 EXPORT_SYMBOL(csum_partial);
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index ffc7309..2e1c824 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -63,7 +63,7 @@
 	flushi(p->addr);
 }
 
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	kcb->prev_kprobe.kp = kprobe_running();
 	kcb->prev_kprobe.status = kcb->kprobe_status;
@@ -71,7 +71,7 @@
 	kcb->prev_kprobe.orig_tstate_pil = kcb->kprobe_orig_tstate_pil;
 }
 
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
 	kcb->kprobe_status = kcb->prev_kprobe.status;
@@ -79,7 +79,7 @@
 	kcb->kprobe_orig_tstate_pil = kcb->prev_kprobe.orig_tstate_pil;
 }
 
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
 				struct kprobe_ctlblk *kcb)
 {
 	__get_cpu_var(current_kprobe) = p;
@@ -87,7 +87,7 @@
 	kcb->kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL);
 }
 
-static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs,
 			struct kprobe_ctlblk *kcb)
 {
 	regs->tstate |= TSTATE_PIL;
@@ -273,7 +273,7 @@
 			kcb->kprobe_orig_tstate_pil);
 }
 
-static inline int post_kprobe_handler(struct pt_regs *regs)
+static int __kprobes post_kprobe_handler(struct pt_regs *regs)
 {
 	struct kprobe *cur = kprobe_running();
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -300,7 +300,7 @@
 	return 1;
 }
 
-static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
 	struct kprobe *cur = kprobe_running();
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c
index 0ec4052..6ab852b 100644
--- a/arch/um/drivers/cow_user.c
+++ b/arch/um/drivers/cow_user.c
@@ -100,7 +100,7 @@
 	__u32 alignment;
 	__u32 cow_format;
 	char backing_file[PATH_LEN_V3];
-};
+} __attribute__((packed));
 
 /* COW format definitions - for now, we have only the usual COW bitmap */
 #define COW_BITMAP 0
diff --git a/arch/um/include/longjmp.h b/arch/um/include/longjmp.h
index 018b381..8e70530 100644
--- a/arch/um/include/longjmp.h
+++ b/arch/um/include/longjmp.h
@@ -4,11 +4,11 @@
 #include <setjmp.h>
 #include "os.h"
 
-#define UML_SIGLONGJMP(buf, val) do { \
+#define UML_LONGJMP(buf, val) do { \
 	longjmp(*buf, val);	\
 } while(0)
 
-#define UML_SIGSETJMP(buf, enable) ({ \
+#define UML_SETJMP(buf, enable) ({ \
 	int n; \
 	enable = get_signals(); \
 	n = setjmp(*buf); \
diff --git a/arch/um/include/sysdep-i386/kernel-offsets.h b/arch/um/include/sysdep-i386/kernel-offsets.h
index 82f96c5..2c13de3 100644
--- a/arch/um/include/sysdep-i386/kernel-offsets.h
+++ b/arch/um/include/sysdep-i386/kernel-offsets.h
@@ -1,6 +1,7 @@
 #include <linux/stddef.h>
 #include <linux/sched.h>
 #include <linux/elf.h>
+#include <asm/mman.h>
 
 #define DEFINE(sym, val) \
 	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -16,6 +17,7 @@
 void foo(void)
 {
 	OFFSET(HOST_TASK_DEBUGREGS, task_struct, thread.arch.debugregs);
+	DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
 #ifdef CONFIG_MODE_TT
 	OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
 #endif
diff --git a/arch/um/include/sysdep-x86_64/kernel-offsets.h b/arch/um/include/sysdep-x86_64/kernel-offsets.h
index 5ce93abd..939cc47 100644
--- a/arch/um/include/sysdep-x86_64/kernel-offsets.h
+++ b/arch/um/include/sysdep-x86_64/kernel-offsets.h
@@ -4,6 +4,7 @@
 #include <linux/time.h>
 #include <linux/elf.h>
 #include <asm/page.h>
+#include <asm/mman.h>
 
 #define DEFINE(sym, val) \
 	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -18,6 +19,7 @@
 
 void foo(void)
 {
+	DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
 #ifdef CONFIG_MODE_TT
 	OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
 #endif
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 71bb90a..c6432e7 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -8,6 +8,7 @@
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/mman.h>
+#include <sys/statfs.h>
 #include "kern_util.h"
 #include "user.h"
 #include "user_util.h"
@@ -19,6 +20,7 @@
 
 #include <sys/param.h>
 
+static char *default_tmpdir = "/tmp";
 static char *tempdir = NULL;
 
 static void __init find_tempdir(void)
@@ -34,7 +36,7 @@
 			break;
 	}
 	if((dir == NULL) || (*dir == '\0'))
-		dir = "/tmp";
+		dir = default_tmpdir;
 
 	tempdir = malloc(strlen(dir) + 2);
 	if(tempdir == NULL){
@@ -46,6 +48,96 @@
 	strcat(tempdir, "/");
 }
 
+/* This will return 1, with the first character in buf being the
+ * character following the next instance of c in the file.  This will
+ * read the file as needed.  If there's an error, -errno is returned;
+ * if the end of the file is reached, 0 is returned.
+ */
+static int next(int fd, char *buf, int size, char c)
+{
+	int n;
+	char *ptr;
+
+	while((ptr = strchr(buf, c)) == NULL){
+		n = read(fd, buf, size - 1);
+		if(n == 0)
+			return 0;
+		else if(n < 0)
+			return -errno;
+
+		buf[n] = '\0';
+	}
+
+	ptr++;
+	memmove(buf, ptr, strlen(ptr) + 1);
+	return 1;
+}
+
+static int checked_tmpdir = 0;
+
+/* Look for a tmpfs mounted at /dev/shm.  I couldn't find a cleaner
+ * way to do this than to parse /proc/mounts.  statfs will return the
+ * same filesystem magic number and fs id for both /dev and /dev/shm
+ * when they are both tmpfs, so you can't tell if they are different
+ * filesystems.  Also, there seems to be no other way of finding the
+ * mount point of a filesystem from within it.
+ *
+ * If a /dev/shm tmpfs entry is found, then we switch to using it.
+ * Otherwise, we stay with the default /tmp.
+ */
+static void which_tmpdir(void)
+{
+	int fd, found;
+	char buf[128] = { '\0' };
+
+	if(checked_tmpdir)
+		return;
+
+	checked_tmpdir = 1;
+
+	printf("Checking for tmpfs mount on /dev/shm...");
+
+	fd = open("/proc/mounts", O_RDONLY);
+	if(fd < 0){
+		printf("failed to open /proc/mounts, errno = %d\n", errno);
+		return;
+	}
+
+	while(1){
+		found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' ');
+		if(found != 1)
+			break;
+
+		if(!strncmp(buf, "/dev/shm", strlen("/dev/shm")))
+			goto found;
+
+		found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), '\n');
+		if(found != 1)
+			break;
+	}
+
+err:
+	if(found == 0)
+		printf("nothing mounted on /dev/shm\n");
+	else if(found < 0)
+		printf("read returned errno %d\n", -found);
+
+	return;
+
+found:
+	found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' ');
+	if(found != 1)
+		goto err;
+
+	if(strncmp(buf, "tmpfs", strlen("tmpfs"))){
+		printf("not tmpfs\n");
+		return;
+	}
+
+	printf("OK\n");
+	default_tmpdir = "/dev/shm";
+}
+
 /*
  * This proc still used in tt-mode
  * (file: kernel/tt/ptproxy/proxy.c, proc: start_debugger).
@@ -56,6 +148,7 @@
 	char *tempname;
 	int fd;
 
+	which_tmpdir();
 	tempname = malloc(MAXPATHLEN);
 
 	find_tempdir();
@@ -137,3 +230,26 @@
 	}
 	return(fd);
 }
+
+
+void check_tmpexec(void)
+{
+	void *addr;
+	int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE);
+
+	addr = mmap(NULL, UM_KERN_PAGE_SIZE,
+		    PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
+	printf("Checking PROT_EXEC mmap in %s...",tempdir);
+	fflush(stdout);
+	if(addr == MAP_FAILED){
+		err = errno;
+		perror("failed");
+		if(err == EPERM)
+			printf("%s must be not mounted noexec\n",tempdir);
+		exit(1);
+	}
+	printf("OK\n");
+	munmap(addr, UM_KERN_PAGE_SIZE);
+
+	close(fd);
+}
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index 8176b0b..3505f44 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -190,7 +190,7 @@
 }
 
 #ifndef MADV_REMOVE
-#define MADV_REMOVE	0x5		/* remove these pages & resources */
+#define MADV_REMOVE KERNEL_MADV_REMOVE
 #endif
 
 int os_drop_memory(void *addr, int length)
@@ -216,7 +216,7 @@
 	}
 
 	addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
-		      MAP_PRIVATE, fd, 0);
+		      MAP_SHARED, fd, 0);
 	if(addr == MAP_FAILED){
 		printk("Mapping test memory file failed, err = %d\n", -errno);
 		return 0;
@@ -266,11 +266,11 @@
 
 int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
 {
-	sigjmp_buf buf;
+	jmp_buf buf;
 	int n, enable;
 
 	*jmp_ptr = &buf;
-	n = UML_SIGSETJMP(&buf, enable);
+	n = UML_SETJMP(&buf, enable);
 	if(n != 0)
 		return(n);
 	(*fn)(arg);
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 045ae00..0776bc1 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -434,7 +434,7 @@
 		void (*handler)(int))
 {
 	unsigned long flags;
-	sigjmp_buf switch_buf, fork_buf;
+	jmp_buf switch_buf, fork_buf;
 	int enable;
 
 	*switch_buf_ptr = &switch_buf;
@@ -450,7 +450,7 @@
 	 */
 	flags = get_signals();
 	block_signals();
-	if(UML_SIGSETJMP(&fork_buf, enable) == 0)
+	if(UML_SETJMP(&fork_buf, enable) == 0)
 		new_thread_proc(stack, handler);
 
 	remove_sigstack();
@@ -466,35 +466,35 @@
 
 void thread_wait(void *sw, void *fb)
 {
-	sigjmp_buf buf, **switch_buf = sw, *fork_buf;
+	jmp_buf buf, **switch_buf = sw, *fork_buf;
 	int enable;
 
 	*switch_buf = &buf;
 	fork_buf = fb;
-	if(UML_SIGSETJMP(&buf, enable) == 0)
+	if(UML_SETJMP(&buf, enable) == 0)
 		siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK);
 }
 
 void switch_threads(void *me, void *next)
 {
-	sigjmp_buf my_buf, **me_ptr = me, *next_buf = next;
+	jmp_buf my_buf, **me_ptr = me, *next_buf = next;
 	int enable;
 
 	*me_ptr = &my_buf;
-	if(UML_SIGSETJMP(&my_buf, enable) == 0)
-		UML_SIGLONGJMP(next_buf, 1);
+	if(UML_SETJMP(&my_buf, enable) == 0)
+		UML_LONGJMP(next_buf, 1);
 }
 
-static sigjmp_buf initial_jmpbuf;
+static jmp_buf initial_jmpbuf;
 
 /* XXX Make these percpu */
 static void (*cb_proc)(void *arg);
 static void *cb_arg;
-static sigjmp_buf *cb_back;
+static jmp_buf *cb_back;
 
 int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
 {
-	sigjmp_buf **switch_buf = switch_buf_ptr;
+	jmp_buf **switch_buf = switch_buf_ptr;
 	int n, enable;
 
 	set_handler(SIGWINCH, (__sighandler_t) sig_handler,
@@ -502,7 +502,7 @@
 		    SIGVTALRM, -1);
 
 	*fork_buf_ptr = &initial_jmpbuf;
-	n = UML_SIGSETJMP(&initial_jmpbuf, enable);
+	n = UML_SETJMP(&initial_jmpbuf, enable);
 	switch(n){
 	case INIT_JMP_NEW_THREAD:
 		new_thread_proc((void *) stack, new_thread_handler);
@@ -512,7 +512,7 @@
 		break;
 	case INIT_JMP_CALLBACK:
 		(*cb_proc)(cb_arg);
-		UML_SIGLONGJMP(cb_back, 1);
+		UML_LONGJMP(cb_back, 1);
 		break;
 	case INIT_JMP_HALT:
 		kmalloc_ok = 0;
@@ -523,12 +523,12 @@
 	default:
 		panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
 	}
-	UML_SIGLONGJMP(*switch_buf, 1);
+	UML_LONGJMP(*switch_buf, 1);
 }
 
 void initial_thread_cb_skas(void (*proc)(void *), void *arg)
 {
-	sigjmp_buf here;
+	jmp_buf here;
 	int enable;
 
 	cb_proc = proc;
@@ -536,8 +536,8 @@
 	cb_back = &here;
 
 	block_signals();
-	if(UML_SIGSETJMP(&here, enable) == 0)
-		UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
+	if(UML_SETJMP(&here, enable) == 0)
+		UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
 	unblock_signals();
 
 	cb_proc = NULL;
@@ -548,13 +548,13 @@
 void halt_skas(void)
 {
 	block_signals();
-	UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
+	UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
 }
 
 void reboot_skas(void)
 {
 	block_signals();
-	UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
+	UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
 }
 
 void switch_mm_skas(struct mm_id *mm_idp)
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 387e26a..5031485 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -296,29 +296,7 @@
 	check_sysemu();
 }
 
-extern int create_tmp_file(unsigned long long len);
-
-static void check_tmpexec(void)
-{
-	void *addr;
-	int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE);
-
-	addr = mmap(NULL, UM_KERN_PAGE_SIZE,
-		    PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
-	printf("Checking PROT_EXEC mmap in /tmp...");
-	fflush(stdout);
-	if(addr == MAP_FAILED){
-		err = errno;
-		perror("failed");
-		if(err == EPERM)
-			printf("/tmp must be not mounted noexec\n");
-		exit(1);
-	}
-	printf("OK\n");
-	munmap(addr, UM_KERN_PAGE_SIZE);
-
-	close(fd);
-}
+extern void check_tmpexec(void);
 
 void os_early_checks(void)
 {
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
index a9f6b26..90b29ae 100644
--- a/arch/um/os-Linux/trap.c
+++ b/arch/um/os-Linux/trap.c
@@ -35,7 +35,7 @@
 
 void do_longjmp(void *b, int val)
 {
-	sigjmp_buf *buf = b;
+	jmp_buf *buf = b;
 
-	UML_SIGLONGJMP(buf, val);
+	UML_LONGJMP(buf, val);
 }
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c
index 166fb66..e523719 100644
--- a/arch/um/os-Linux/uaccess.c
+++ b/arch/um/os-Linux/uaccess.c
@@ -16,9 +16,9 @@
 	unsigned long *faddrp = (unsigned long *) fault_addr, ret;
 	int enable;
 
-	sigjmp_buf jbuf;
+	jmp_buf jbuf;
 	*fault_catcher = &jbuf;
-	if(UML_SIGSETJMP(&jbuf, enable) == 0){
+	if(UML_SETJMP(&jbuf, enable) == 0){
 		(*op)(to, from, n);
 		ret = 0;
 		*faulted_out = 0;
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index e32065e..c47a2a7 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -104,7 +104,7 @@
 int setjmp_wrapper(void (*proc)(void *, void *), ...)
 {
 	va_list args;
-	sigjmp_buf buf;
+	jmp_buf buf;
 	int n;
 
 	n = sigsetjmp(buf, 1);
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 618fd85..0709fc6 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -57,7 +57,7 @@
 	return(0);
 }
 
-int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate __user *to_fp,
+int copy_sc_to_user_skas(struct sigcontext __user *to, struct _fpstate __user *to_fp,
                          struct pt_regs *regs, unsigned long sp)
 {
   	struct sigcontext sc;
@@ -132,7 +132,7 @@
 	return(err);
 }
 
-int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate __user *fp,
+int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp,
 		       struct sigcontext *from, int fpsize, unsigned long sp)
 {
 	struct _fpstate __user *to_fp;
@@ -167,7 +167,7 @@
 	return(ret);
 }
 
-static int copy_sc_to_user(struct sigcontext *to, struct _fpstate __user *fp,
+static int copy_sc_to_user(struct sigcontext __user *to, struct _fpstate __user *fp,
 			   struct pt_regs *from, unsigned long sp)
 {
 	return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c
index a37f672..2355dc1 100644
--- a/arch/um/sys-i386/stub_segv.c
+++ b/arch/um/sys-i386/stub_segv.c
@@ -27,6 +27,6 @@
 	 * the stack in its original form when we do the sigreturn here, by
 	 * hand.
 	 */
-	__asm__("mov %0,%%esp ; movl %1, %%eax ; "
-		"int $0x80" : : "a" (sc), "g" (__NR_sigreturn));
+	__asm__ __volatile__("mov %0,%%esp ; movl %1, %%eax ; "
+			     "int $0x80" : : "a" (sc), "g" (__NR_sigreturn));
 }
diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c
index a270995..1c96702 100644
--- a/arch/um/sys-x86_64/stub_segv.c
+++ b/arch/um/sys-x86_64/stub_segv.c
@@ -33,7 +33,7 @@
 	struct ucontext *uc;
         int pid;
 
-	__asm__("movq %%rdx, %0" : "=g" (uc) :);
+	__asm__ __volatile__("movq %%rdx, %0" : "=g" (uc) :);
 	GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA),
 			      &uc->uc_mcontext);
 
@@ -44,8 +44,8 @@
 	 * the signal frame.  So, we use the ucontext pointer, which we know
 	 * already, to get the signal frame pointer, and add 8 to that.
 	 */
-	__asm__("movq %0, %%rsp; movq %1, %%rax ; syscall": :
-		"g" ((unsigned long) container_of(uc, struct rt_sigframe, 
-						  uc) + 8),
-                "g" (__NR_rt_sigreturn));
+	__asm__ __volatile__("movq %0, %%rsp; movq %1, %%rax ; syscall": :
+                             "g" ((unsigned long)
+                                  container_of(uc, struct rt_sigframe, uc) + 8),
+                             "g" (__NR_rt_sigreturn));
 }
diff --git a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile
index 929e6b0..e9263b4 100644
--- a/arch/x86_64/ia32/Makefile
+++ b/arch/x86_64/ia32/Makefile
@@ -27,5 +27,5 @@
 $(obj)/vsyscall-%.so: $(src)/vsyscall.lds $(obj)/vsyscall-%.o FORCE
 	$(call if_changed,syscall)
 
-AFLAGS_vsyscall-sysenter.o = -m32
-AFLAGS_vsyscall-syscall.o = -m32
+AFLAGS_vsyscall-sysenter.o = -m32 -Wa,-32
+AFLAGS_vsyscall-syscall.o = -m32 -Wa,-32
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c
index accbff3..1eaa5da 100644
--- a/arch/x86_64/kernel/kprobes.c
+++ b/arch/x86_64/kernel/kprobes.c
@@ -53,7 +53,7 @@
 /*
  * returns non-zero if opcode modifies the interrupt flag.
  */
-static inline int is_IF_modifier(kprobe_opcode_t *insn)
+static __always_inline int is_IF_modifier(kprobe_opcode_t *insn)
 {
 	switch (*insn) {
 	case 0xfa:		/* cli */
@@ -84,7 +84,7 @@
  * If it does, return the address of the 32-bit displacement word.
  * If not, return null.
  */
-static inline s32 *is_riprel(u8 *insn)
+static s32 __kprobes *is_riprel(u8 *insn)
 {
 #define W(row,b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,ba,bb,bc,bd,be,bf)		      \
 	(((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) |   \
@@ -229,7 +229,7 @@
 	mutex_unlock(&kprobe_mutex);
 }
 
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	kcb->prev_kprobe.kp = kprobe_running();
 	kcb->prev_kprobe.status = kcb->kprobe_status;
@@ -237,7 +237,7 @@
 	kcb->prev_kprobe.saved_rflags = kcb->kprobe_saved_rflags;
 }
 
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
 	kcb->kprobe_status = kcb->prev_kprobe.status;
@@ -245,7 +245,7 @@
 	kcb->kprobe_saved_rflags = kcb->prev_kprobe.saved_rflags;
 }
 
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
 				struct kprobe_ctlblk *kcb)
 {
 	__get_cpu_var(current_kprobe) = p;
diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c
index a6c01e1..9d3d76c 100644
--- a/arch/x86_64/kernel/pci-gart.c
+++ b/arch/x86_64/kernel/pci-gart.c
@@ -112,10 +112,6 @@
 static void free_iommu(unsigned long offset, int size)
 { 
 	unsigned long flags;
-	if (size == 1) { 
-		clear_bit(offset, iommu_gart_bitmap); 
-		return;
-	}
 	spin_lock_irqsave(&iommu_bitmap_lock, flags);
 	__clear_bit_string(iommu_gart_bitmap, offset, size);
 	spin_unlock_irqrestore(&iommu_bitmap_lock, flags);
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 1c44b53..fb903e6 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -575,8 +575,10 @@
 	prev->userrsp = read_pda(oldrsp); 
 	write_pda(oldrsp, next->userrsp); 
 	write_pda(pcurrent, next_p); 
+
 	/* This must be here to ensure both math_state_restore() and
-	   kernel_fpu_begin() work consistently. */
+	   kernel_fpu_begin() work consistently. 
+	   And the AMD workaround requires it to be after DS reload. */
 	unlazy_fpu(prev_p);
 	write_pda(kernelstack,
 		  task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index c50b067..759070c 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -930,6 +930,10 @@
 	if (c->x86 == 15 && ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58))
 		set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
 
+	/* Enable workaround for FXSAVE leak */
+	if (c->x86 >= 6)
+		set_bit(X86_FEATURE_FXSAVE_LEAK, &c->x86_capability);
+
 	r = get_model_name(c);
 	if (!r) { 
 		switch (c->x86) { 
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
index cc02573..b2fac14 100644
--- a/arch/x86_64/mm/numa.c
+++ b/arch/x86_64/mm/numa.c
@@ -188,11 +188,13 @@
 	   memory. */
 	memmapsize = sizeof(struct page) * (end_pfn-start_pfn);
 	limit = end_pfn << PAGE_SHIFT;
+#ifdef CONFIG_FLAT_NODE_MEM_MAP
 	NODE_DATA(nodeid)->node_mem_map = 
 		__alloc_bootmem_core(NODE_DATA(nodeid)->bdata, 
 				memmapsize, SMP_CACHE_BYTES, 
 				round_down(limit - memmapsize, PAGE_SIZE), 
 				limit);
+#endif
 
 	size_zones(zones, holes, start_pfn, end_pfn);
 	free_area_init_node(nodeid, NODE_DATA(nodeid), zones,
diff --git a/block/elevator.c b/block/elevator.c
index 0d6be03..2982579 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -895,10 +895,8 @@
 EXPORT_SYMBOL(elv_dispatch_sort);
 EXPORT_SYMBOL(elv_add_request);
 EXPORT_SYMBOL(__elv_add_request);
-EXPORT_SYMBOL(elv_requeue_request);
 EXPORT_SYMBOL(elv_next_request);
 EXPORT_SYMBOL(elv_dequeue_request);
 EXPORT_SYMBOL(elv_queue_empty);
-EXPORT_SYMBOL(elv_completed_request);
 EXPORT_SYMBOL(elevator_exit);
 EXPORT_SYMBOL(elevator_init);
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index e112d1a..1755c05 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -1554,7 +1554,7 @@
 	 * don't plug a stopped queue, it must be paired with blk_start_queue()
 	 * which will restart the queueing
 	 */
-	if (test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags))
+	if (blk_queue_stopped(q))
 		return;
 
 	if (!test_and_set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) {
@@ -1587,7 +1587,7 @@
  */
 void __generic_unplug_device(request_queue_t *q)
 {
-	if (unlikely(test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags)))
+	if (unlikely(blk_queue_stopped(q)))
 		return;
 
 	if (!blk_remove_plug(q))
diff --git a/drivers/char/cs5535_gpio.c b/drivers/char/cs5535_gpio.c
index 5d72f50..46d6603 100644
--- a/drivers/char/cs5535_gpio.c
+++ b/drivers/char/cs5535_gpio.c
@@ -241,9 +241,10 @@
 static void __exit cs5535_gpio_cleanup(void)
 {
 	dev_t dev_id = MKDEV(major, 0);
+
+	cdev_del(&cs5535_gpio_cdev);
 	unregister_chrdev_region(dev_id, CS5535_GPIO_COUNT);
-	if (gpio_base != 0)
-		release_region(gpio_base, CS5535_GPIO_SIZE);
+	release_region(gpio_base, CS5535_GPIO_SIZE);
 }
 
 module_init(cs5535_gpio_init);
diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c
index 58dcdee..0030cd8 100644
--- a/drivers/char/ipmi/ipmi_bt_sm.c
+++ b/drivers/char/ipmi/ipmi_bt_sm.c
@@ -165,7 +165,7 @@
 {
 	unsigned int i;
 
-	if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH))
+	if ((size < 2) || (size > (IPMI_MAX_MSG_LENGTH - 2)))
 	       return -1;
 
 	if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED))
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index a86c0f2..b36eef0 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -2198,11 +2198,11 @@
 	}
 }
 
-static struct ipmi_default_vals
+static __devinitdata struct ipmi_default_vals
 {
 	int type;
 	int port;
-} __devinit ipmi_defaults[] =
+} ipmi_defaults[] =
 {
 	{ .type = SI_KCS, .port = 0xca2 },
 	{ .type = SI_SMIC, .port = 0xca9 },
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index b543821..56c8243 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -390,7 +390,8 @@
 			format_module_id(devnamep, geo_module(geoid),
 					 MODULE_FORMAT_BRIEF);
 			devnamep = devname + strlen(devname);
-			sprintf(devnamep, "#%d", geo_slab(geoid));
+			sprintf(devnamep, "^%d#%d", geo_slot(geoid),
+				geo_slab(geoid));
 
 			/* allocate sysctl device data */
 			scd = kzalloc(sizeof (struct sysctl_data_s),
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index f8dd852..a90f5d9 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -1341,6 +1341,9 @@
 	else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
 					  PCI_DEVICE_ID_INTEL_ICH6_1, NULL)))
 		sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3;
+	else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
+					  PCI_DEVICE_ID_INTEL_ICH7_1, NULL)))
+		sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3;
 	else
 		sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2;
 
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index a6873bf..1efde3b 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -20,9 +20,18 @@
 	  Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI
 	  and CONFIG_PNPACPI.
 
+config TCG_TIS
+	tristate "TPM Interface Specification 1.2 Interface"
+	depends on TCG_TPM
+	---help---
+	  If you have a TPM security chip that is compliant with the
+	  TCG TIS 1.2 TPM specification say Yes and it will be accessible
+	  from within Linux.  To compile this driver as a module, choose
+	  M here; the module will be called tpm_tis.
+
 config TCG_NSC
 	tristate "National Semiconductor TPM Interface"
-	depends on TCG_TPM
+	depends on TCG_TPM && PNPACPI
 	---help---
 	  If you have a TPM security chip from National Semicondutor 
 	  say Yes and it will be accessible from within Linux.  To 
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index ba4582d..ea3a1e0 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -5,6 +5,7 @@
 ifdef CONFIG_ACPI
 	obj-$(CONFIG_TCG_TPM) += tpm_bios.o
 endif
+obj-$(CONFIG_TCG_TIS) += tpm_tis.o
 obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
 obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
 obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 5a38704..6889e7d 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -32,12 +32,291 @@
 	TPM_MINOR = 224,	/* officially assigned */
 	TPM_BUFSIZE = 2048,
 	TPM_NUM_DEVICES = 256,
-	TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int))
 };
 
+enum tpm_duration {
+	TPM_SHORT = 0,
+	TPM_MEDIUM = 1,
+	TPM_LONG = 2,
+	TPM_UNDEFINED,
+};
+
+#define TPM_MAX_ORDINAL 243
+#define TPM_MAX_PROTECTED_ORDINAL 12
+#define TPM_PROTECTED_ORDINAL_MASK 0xFF
+
 static LIST_HEAD(tpm_chip_list);
 static DEFINE_SPINLOCK(driver_lock);
-static int dev_mask[TPM_NUM_MASK_ENTRIES];
+static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES);
+
+/*
+ * Array with one entry per ordinal defining the maximum amount
+ * of time the chip could take to return the result.  The ordinal
+ * designation of short, medium or long is defined in a table in
+ * TCG Specification TPM Main Part 2 TPM Structures Section 17. The
+ * values of the SHORT, MEDIUM, and LONG durations are retrieved
+ * from the chip during initialization with a call to tpm_get_timeouts.
+ */
+static const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = {
+	TPM_UNDEFINED,		/* 0 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 5 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 10 */
+	TPM_SHORT,
+};
+
+static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = {
+	TPM_UNDEFINED,		/* 0 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 5 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 10 */
+	TPM_SHORT,
+	TPM_MEDIUM,
+	TPM_LONG,
+	TPM_LONG,
+	TPM_MEDIUM,		/* 15 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_MEDIUM,
+	TPM_LONG,
+	TPM_SHORT,		/* 20 */
+	TPM_SHORT,
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_SHORT,		/* 25 */
+	TPM_SHORT,
+	TPM_MEDIUM,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_MEDIUM,		/* 30 */
+	TPM_LONG,
+	TPM_MEDIUM,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,		/* 35 */
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_MEDIUM,		/* 40 */
+	TPM_LONG,
+	TPM_MEDIUM,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,		/* 45 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_LONG,
+	TPM_MEDIUM,		/* 50 */
+	TPM_MEDIUM,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 55 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_MEDIUM,		/* 60 */
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_MEDIUM,		/* 65 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 70 */
+	TPM_SHORT,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 75 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_LONG,		/* 80 */
+	TPM_UNDEFINED,
+	TPM_MEDIUM,
+	TPM_LONG,
+	TPM_SHORT,
+	TPM_UNDEFINED,		/* 85 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 90 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_UNDEFINED,		/* 95 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_MEDIUM,		/* 100 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 105 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 110 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,		/* 115 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_LONG,		/* 120 */
+	TPM_LONG,
+	TPM_MEDIUM,
+	TPM_UNDEFINED,
+	TPM_SHORT,
+	TPM_SHORT,		/* 125 */
+	TPM_SHORT,
+	TPM_LONG,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,		/* 130 */
+	TPM_MEDIUM,
+	TPM_UNDEFINED,
+	TPM_SHORT,
+	TPM_MEDIUM,
+	TPM_UNDEFINED,		/* 135 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 140 */
+	TPM_SHORT,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 145 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 150 */
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_UNDEFINED,		/* 155 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 160 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 165 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_LONG,		/* 170 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 175 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_MEDIUM,		/* 180 */
+	TPM_SHORT,
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_MEDIUM,		/* 185 */
+	TPM_SHORT,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 190 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 195 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 200 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,
+	TPM_SHORT,		/* 205 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_MEDIUM,		/* 210 */
+	TPM_UNDEFINED,
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_UNDEFINED,		/* 215 */
+	TPM_MEDIUM,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,
+	TPM_SHORT,		/* 220 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_UNDEFINED,		/* 225 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 230 */
+	TPM_LONG,
+	TPM_MEDIUM,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 235 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 240 */
+	TPM_UNDEFINED,
+	TPM_MEDIUM,
+};
 
 static void user_reader_timeout(unsigned long ptr)
 {
@@ -46,7 +325,7 @@
 	schedule_work(&chip->work);
 }
 
-static void timeout_work(void * ptr)
+static void timeout_work(void *ptr)
 {
 	struct tpm_chip *chip = ptr;
 
@@ -57,17 +336,43 @@
 }
 
 /*
+ * Returns max number of jiffies to wait
+ */
+unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
+					   u32 ordinal)
+{
+	int duration_idx = TPM_UNDEFINED;
+	int duration = 0;
+
+	if (ordinal < TPM_MAX_ORDINAL)
+		duration_idx = tpm_ordinal_duration[ordinal];
+	else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) <
+		 TPM_MAX_PROTECTED_ORDINAL)
+		duration_idx =
+		    tpm_protected_ordinal_duration[ordinal &
+						   TPM_PROTECTED_ORDINAL_MASK];
+
+	if (duration_idx != TPM_UNDEFINED)
+		duration = chip->vendor.duration[duration_idx];
+	if (duration <= 0)
+		return 2 * 60 * HZ;
+	else
+		return duration;
+}
+EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration);
+
+/*
  * Internal kernel interface to transmit TPM commands
  */
 static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
 			    size_t bufsiz)
 {
 	ssize_t rc;
-	u32 count;
+	u32 count, ordinal;
 	unsigned long stop;
 
 	count = be32_to_cpu(*((__be32 *) (buf + 2)));
-
+	ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
 	if (count == 0)
 		return -ENODATA;
 	if (count > bufsiz) {
@@ -78,21 +383,23 @@
 
 	down(&chip->tpm_mutex);
 
-	if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
+	if ((rc = chip->vendor.send(chip, (u8 *) buf, count)) < 0) {
 		dev_err(chip->dev,
 			"tpm_transmit: tpm_send: error %zd\n", rc);
 		goto out;
 	}
 
-	stop = jiffies + 2 * 60 * HZ;
-	do {
-		u8 status = chip->vendor->status(chip);
-		if ((status & chip->vendor->req_complete_mask) ==
-		    chip->vendor->req_complete_val) {
-			goto out_recv;
-		}
+	if (chip->vendor.irq)
+		goto out_recv;
 
-		if ((status == chip->vendor->req_canceled)) {
+	stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal);
+	do {
+		u8 status = chip->vendor.status(chip);
+		if ((status & chip->vendor.req_complete_mask) ==
+		    chip->vendor.req_complete_val)
+			goto out_recv;
+
+		if ((status == chip->vendor.req_canceled)) {
 			dev_err(chip->dev, "Operation Canceled\n");
 			rc = -ECANCELED;
 			goto out;
@@ -102,14 +409,13 @@
 		rmb();
 	} while (time_before(jiffies, stop));
 
-
-	chip->vendor->cancel(chip);
+	chip->vendor.cancel(chip);
 	dev_err(chip->dev, "Operation Timed out\n");
 	rc = -ETIME;
 	goto out;
 
 out_recv:
-	rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
+	rc = chip->vendor.recv(chip, (u8 *) buf, bufsiz);
 	if (rc < 0)
 		dev_err(chip->dev,
 			"tpm_transmit: tpm_recv: error %zd\n", rc);
@@ -119,17 +425,247 @@
 }
 
 #define TPM_DIGEST_SIZE 20
-#define CAP_PCR_RESULT_SIZE 18
-static const u8 cap_pcr[] = {
+#define TPM_ERROR_SIZE 10
+#define TPM_RET_CODE_IDX 6
+#define TPM_GET_CAP_RET_SIZE_IDX 10
+#define TPM_GET_CAP_RET_UINT32_1_IDX 14
+#define TPM_GET_CAP_RET_UINT32_2_IDX 18
+#define TPM_GET_CAP_RET_UINT32_3_IDX 22
+#define TPM_GET_CAP_RET_UINT32_4_IDX 26
+#define TPM_GET_CAP_PERM_DISABLE_IDX 16
+#define TPM_GET_CAP_PERM_INACTIVE_IDX 18
+#define TPM_GET_CAP_RET_BOOL_1_IDX 14
+#define TPM_GET_CAP_TEMP_INACTIVE_IDX 16
+
+#define TPM_CAP_IDX 13
+#define TPM_CAP_SUBCAP_IDX 21
+
+enum tpm_capabilities {
+	TPM_CAP_FLAG = 4,
+	TPM_CAP_PROP = 5,
+};
+
+enum tpm_sub_capabilities {
+	TPM_CAP_PROP_PCR = 0x1,
+	TPM_CAP_PROP_MANUFACTURER = 0x3,
+	TPM_CAP_FLAG_PERM = 0x8,
+	TPM_CAP_FLAG_VOL = 0x9,
+	TPM_CAP_PROP_OWNER = 0x11,
+	TPM_CAP_PROP_TIS_TIMEOUT = 0x15,
+	TPM_CAP_PROP_TIS_DURATION = 0x20,
+};
+
+/*
+ * This is a semi generic GetCapability command for use
+ * with the capability type TPM_CAP_PROP or TPM_CAP_FLAG
+ * and their associated sub_capabilities.
+ */
+
+static const u8 tpm_cap[] = {
 	0, 193,			/* TPM_TAG_RQU_COMMAND */
 	0, 0, 0, 22,		/* length */
 	0, 0, 0, 101,		/* TPM_ORD_GetCapability */
-	0, 0, 0, 5,
-	0, 0, 0, 4,
-	0, 0, 1, 1
+	0, 0, 0, 0,		/* TPM_CAP_<TYPE> */
+	0, 0, 0, 4,		/* TPM_CAP_SUB_<TYPE> size */
+	0, 0, 1, 0		/* TPM_CAP_SUB_<TYPE> */
 };
 
-#define READ_PCR_RESULT_SIZE 30
+static ssize_t transmit_cmd(struct tpm_chip *chip, u8 *data, int len,
+			    char *desc)
+{
+	int err;
+
+	len = tpm_transmit(chip, data, len);
+	if (len <  0)
+		return len;
+	if (len == TPM_ERROR_SIZE) {
+		err = be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)));
+		dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc);
+		return err;
+	}
+	return 0;
+}
+
+void tpm_gen_interrupt(struct tpm_chip *chip)
+{
+	u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)];
+	ssize_t rc;
+
+	memcpy(data, tpm_cap, sizeof(tpm_cap));
+	data[TPM_CAP_IDX] = TPM_CAP_PROP;
+	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT;
+
+	rc = transmit_cmd(chip, data, sizeof(data),
+			"attempting to determine the timeouts");
+}
+EXPORT_SYMBOL_GPL(tpm_gen_interrupt);
+
+void tpm_get_timeouts(struct tpm_chip *chip)
+{
+	u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)];
+	ssize_t rc;
+	u32 timeout;
+
+	memcpy(data, tpm_cap, sizeof(tpm_cap));
+	data[TPM_CAP_IDX] = TPM_CAP_PROP;
+	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT;
+
+	rc = transmit_cmd(chip, data, sizeof(data),
+			"attempting to determine the timeouts");
+	if (rc)
+		goto duration;
+
+	if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX)))
+	    != 4 * sizeof(u32))
+		goto duration;
+
+	/* Don't overwrite default if value is 0 */
+	timeout =
+	    be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)));
+	if (timeout)
+		chip->vendor.timeout_a = msecs_to_jiffies(timeout);
+	timeout =
+	    be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX)));
+	if (timeout)
+		chip->vendor.timeout_b = msecs_to_jiffies(timeout);
+	timeout =
+	    be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX)));
+	if (timeout)
+		chip->vendor.timeout_c = msecs_to_jiffies(timeout);
+	timeout =
+	    be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_4_IDX)));
+	if (timeout)
+		chip->vendor.timeout_d = msecs_to_jiffies(timeout);
+
+duration:
+	memcpy(data, tpm_cap, sizeof(tpm_cap));
+	data[TPM_CAP_IDX] = TPM_CAP_PROP;
+	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_DURATION;
+
+	rc = transmit_cmd(chip, data, sizeof(data),
+			"attempting to determine the durations");
+	if (rc)
+		return;
+
+	if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX)))
+	    != 3 * sizeof(u32))
+		return;
+
+	chip->vendor.duration[TPM_SHORT] =
+	    msecs_to_jiffies(be32_to_cpu
+			     (*((__be32 *) (data +
+					    TPM_GET_CAP_RET_UINT32_1_IDX))));
+	chip->vendor.duration[TPM_MEDIUM] =
+	    msecs_to_jiffies(be32_to_cpu
+			     (*((__be32 *) (data +
+					    TPM_GET_CAP_RET_UINT32_2_IDX))));
+	chip->vendor.duration[TPM_LONG] =
+	    msecs_to_jiffies(be32_to_cpu
+			     (*((__be32 *) (data +
+					    TPM_GET_CAP_RET_UINT32_3_IDX))));
+}
+EXPORT_SYMBOL_GPL(tpm_get_timeouts);
+
+void tpm_continue_selftest(struct tpm_chip *chip)
+{
+	u8 data[] = {
+		0, 193,			/* TPM_TAG_RQU_COMMAND */
+		0, 0, 0, 10,		/* length */
+		0, 0, 0, 83,		/* TPM_ORD_GetCapability */
+	};
+
+	tpm_transmit(chip, data, sizeof(data));
+}
+EXPORT_SYMBOL_GPL(tpm_continue_selftest);
+
+ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr,
+			char *buf)
+{
+	u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)];
+	ssize_t rc;
+
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	if (chip == NULL)
+		return -ENODEV;
+
+	memcpy(data, tpm_cap, sizeof(tpm_cap));
+	data[TPM_CAP_IDX] = TPM_CAP_FLAG;
+	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM;
+
+	rc = transmit_cmd(chip, data, sizeof(data),
+			"attemtping to determine the permanent state");
+	if (rc)
+		return 0;
+	return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_enabled);
+
+ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr,
+			char *buf)
+{
+	u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)];
+	ssize_t rc;
+
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	if (chip == NULL)
+		return -ENODEV;
+
+	memcpy(data, tpm_cap, sizeof(tpm_cap));
+	data[TPM_CAP_IDX] = TPM_CAP_FLAG;
+	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM;
+
+	rc = transmit_cmd(chip, data, sizeof(data),
+			"attemtping to determine the permanent state");
+	if (rc)
+		return 0;
+	return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_active);
+
+ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr,
+			char *buf)
+{
+	u8 data[sizeof(tpm_cap)];
+	ssize_t rc;
+
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	if (chip == NULL)
+		return -ENODEV;
+
+	memcpy(data, tpm_cap, sizeof(tpm_cap));
+	data[TPM_CAP_IDX] = TPM_CAP_PROP;
+	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER;
+
+	rc = transmit_cmd(chip, data, sizeof(data),
+			"attempting to determine the owner state");
+	if (rc)
+		return 0;
+	return sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_owned);
+
+ssize_t tpm_show_temp_deactivated(struct device * dev,
+				struct device_attribute * attr, char *buf)
+{
+	u8 data[sizeof(tpm_cap)];
+	ssize_t rc;
+
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	if (chip == NULL)
+		return -ENODEV;
+
+	memcpy(data, tpm_cap, sizeof(tpm_cap));
+	data[TPM_CAP_IDX] = TPM_CAP_FLAG;
+	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL;
+
+	rc = transmit_cmd(chip, data, sizeof(data),
+			"attempting to determine the temporary state");
+	if (rc)
+		return 0;
+	return sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated);
+
 static const u8 pcrread[] = {
 	0, 193,			/* TPM_TAG_RQU_COMMAND */
 	0, 0, 0, 14,		/* length */
@@ -140,8 +676,8 @@
 ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
 		      char *buf)
 {
-	u8 data[READ_PCR_RESULT_SIZE];
-	ssize_t len;
+	u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(pcrread)), 30)];
+	ssize_t rc;
 	int i, j, num_pcrs;
 	__be32 index;
 	char *str = buf;
@@ -150,29 +686,24 @@
 	if (chip == NULL)
 		return -ENODEV;
 
-	memcpy(data, cap_pcr, sizeof(cap_pcr));
-	if ((len = tpm_transmit(chip, data, sizeof(data)))
-	    < CAP_PCR_RESULT_SIZE) {
-		dev_dbg(chip->dev, "A TPM error (%d) occurred "
-				"attempting to determine the number of PCRS\n",
-			be32_to_cpu(*((__be32 *) (data + 6))));
+	memcpy(data, tpm_cap, sizeof(tpm_cap));
+	data[TPM_CAP_IDX] = TPM_CAP_PROP;
+	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR;
+
+	rc = transmit_cmd(chip, data, sizeof(data),
+			"attempting to determine the number of PCRS");
+	if (rc)
 		return 0;
-	}
 
 	num_pcrs = be32_to_cpu(*((__be32 *) (data + 14)));
-
 	for (i = 0; i < num_pcrs; i++) {
 		memcpy(data, pcrread, sizeof(pcrread));
 		index = cpu_to_be32(i);
 		memcpy(data + 10, &index, 4);
-		if ((len = tpm_transmit(chip, data, sizeof(data)))
-		    < READ_PCR_RESULT_SIZE){
-			dev_dbg(chip->dev, "A TPM error (%d) occurred"
-				" attempting to read PCR %d of %d\n",
-				be32_to_cpu(*((__be32 *) (data + 6))),
-				i, num_pcrs);
+		rc = transmit_cmd(chip, data, sizeof(data),
+				"attempting to read a PCR");
+		if (rc)
 			goto out;
-		}
 		str += sprintf(str, "PCR-%02d: ", i);
 		for (j = 0; j < TPM_DIGEST_SIZE; j++)
 			str += sprintf(str, "%02X ", *(data + 10 + j));
@@ -194,7 +725,7 @@
 		       char *buf)
 {
 	u8 *data;
-	ssize_t len;
+	ssize_t err;
 	int i, rc;
 	char *str = buf;
 
@@ -208,14 +739,10 @@
 
 	memcpy(data, readpubek, sizeof(readpubek));
 
-	if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) <
-	    READ_PUBEK_RESULT_SIZE) {
-		dev_dbg(chip->dev, "A TPM error (%d) occurred "
-				"attempting to read the PUBEK\n",
-			    be32_to_cpu(*((__be32 *) (data + 6))));
-		rc = 0;
+	err = transmit_cmd(chip, data, READ_PUBEK_RESULT_SIZE,
+			"attempting to read the PUBEK");
+	if (err)
 		goto out;
-	}
 
 	/* 
 	   ignore header 10 bytes
@@ -245,36 +772,68 @@
 		if ((i + 1) % 16 == 0)
 			str += sprintf(str, "\n");
 	}
-	rc = str - buf;
 out:
+	rc = str - buf;
 	kfree(data);
 	return rc;
 }
 EXPORT_SYMBOL_GPL(tpm_show_pubek);
 
-#define CAP_VER_RESULT_SIZE 18
+#define CAP_VERSION_1_1 6
+#define CAP_VERSION_1_2 0x1A
+#define CAP_VERSION_IDX 13
 static const u8 cap_version[] = {
 	0, 193,			/* TPM_TAG_RQU_COMMAND */
 	0, 0, 0, 18,		/* length */
 	0, 0, 0, 101,		/* TPM_ORD_GetCapability */
-	0, 0, 0, 6,
+	0, 0, 0, 0,
 	0, 0, 0, 0
 };
 
-#define CAP_MANUFACTURER_RESULT_SIZE 18
-static const u8 cap_manufacturer[] = {
-	0, 193,			/* TPM_TAG_RQU_COMMAND */
-	0, 0, 0, 22,		/* length */
-	0, 0, 0, 101,		/* TPM_ORD_GetCapability */
-	0, 0, 0, 5,
-	0, 0, 0, 4,
-	0, 0, 1, 3
-};
-
 ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
 		      char *buf)
 {
-	u8 data[sizeof(cap_manufacturer)];
+	u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)];
+	ssize_t rc;
+	char *str = buf;
+
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	if (chip == NULL)
+		return -ENODEV;
+
+	memcpy(data, tpm_cap, sizeof(tpm_cap));
+	data[TPM_CAP_IDX] = TPM_CAP_PROP;
+	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER;
+
+	rc = transmit_cmd(chip, data, sizeof(data),
+			"attempting to determine the manufacturer");
+	if (rc)
+		return 0;
+
+	str += sprintf(str, "Manufacturer: 0x%x\n",
+		       be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))));
+
+	memcpy(data, cap_version, sizeof(cap_version));
+	data[CAP_VERSION_IDX] = CAP_VERSION_1_1;
+	rc = transmit_cmd(chip, data, sizeof(data),
+			"attempting to determine the 1.1 version");
+	if (rc)
+		goto out;
+
+	str += sprintf(str,
+		       "TCG version: %d.%d\nFirmware version: %d.%d\n",
+		       (int) data[14], (int) data[15], (int) data[16],
+		       (int) data[17]);
+
+out:
+	return str - buf;
+}
+EXPORT_SYMBOL_GPL(tpm_show_caps);
+
+ssize_t tpm_show_caps_1_2(struct device * dev,
+			  struct device_attribute * attr, char *buf)
+{
+	u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)];
 	ssize_t len;
 	char *str = buf;
 
@@ -282,29 +841,40 @@
 	if (chip == NULL)
 		return -ENODEV;
 
-	memcpy(data, cap_manufacturer, sizeof(cap_manufacturer));
+	memcpy(data, tpm_cap, sizeof(tpm_cap));
+	data[TPM_CAP_IDX] = TPM_CAP_PROP;
+	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER;
 
-	if ((len = tpm_transmit(chip, data, sizeof(data))) <
-	    CAP_MANUFACTURER_RESULT_SIZE)
-		return len;
+	if ((len = tpm_transmit(chip, data, sizeof(data))) <=
+	    TPM_ERROR_SIZE) {
+		dev_dbg(chip->dev, "A TPM error (%d) occurred "
+			"attempting to determine the manufacturer\n",
+			be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
+		return 0;
+	}
 
 	str += sprintf(str, "Manufacturer: 0x%x\n",
-		       be32_to_cpu(*((__be32 *) (data + 14))));
+		       be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))));
 
 	memcpy(data, cap_version, sizeof(cap_version));
+	data[CAP_VERSION_IDX] = CAP_VERSION_1_2;
 
-	if ((len = tpm_transmit(chip, data, sizeof(data))) <
-	    CAP_VER_RESULT_SIZE)
-		return len;
+	if ((len = tpm_transmit(chip, data, sizeof(data))) <=
+	    TPM_ERROR_SIZE) {
+		dev_err(chip->dev, "A TPM error (%d) occurred "
+			"attempting to determine the 1.2 version\n",
+			be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
+		goto out;
+	}
+	str += sprintf(str,
+		       "TCG version: %d.%d\nFirmware version: %d.%d\n",
+		       (int) data[16], (int) data[17], (int) data[18],
+		       (int) data[19]);
 
-	str +=
-	    sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n",
-		    (int) data[14], (int) data[15], (int) data[16],
-		    (int) data[17]);
-
+out:
 	return str - buf;
 }
-EXPORT_SYMBOL_GPL(tpm_show_caps);
+EXPORT_SYMBOL_GPL(tpm_show_caps_1_2);
 
 ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
@@ -313,7 +883,7 @@
 	if (chip == NULL)
 		return 0;
 
-	chip->vendor->cancel(chip);
+	chip->vendor.cancel(chip);
 	return count;
 }
 EXPORT_SYMBOL_GPL(tpm_store_cancel);
@@ -329,7 +899,7 @@
 	spin_lock(&driver_lock);
 
 	list_for_each_entry(pos, &tpm_chip_list, list) {
-		if (pos->vendor->miscdev.minor == minor) {
+		if (pos->vendor.miscdev.minor == minor) {
 			chip = pos;
 			break;
 		}
@@ -387,7 +957,7 @@
 EXPORT_SYMBOL_GPL(tpm_release);
 
 ssize_t tpm_write(struct file *file, const char __user *buf,
-		  size_t size, loff_t * off)
+		  size_t size, loff_t *off)
 {
 	struct tpm_chip *chip = file->private_data;
 	int in_size = size, out_size;
@@ -419,11 +989,10 @@
 
 	return in_size;
 }
-
 EXPORT_SYMBOL_GPL(tpm_write);
 
-ssize_t tpm_read(struct file * file, char __user *buf,
-		 size_t size, loff_t * off)
+ssize_t tpm_read(struct file *file, char __user *buf,
+		 size_t size, loff_t *off)
 {
 	struct tpm_chip *chip = file->private_data;
 	int ret_size;
@@ -462,14 +1031,13 @@
 	spin_unlock(&driver_lock);
 
 	dev_set_drvdata(dev, NULL);
-	misc_deregister(&chip->vendor->miscdev);
-	kfree(chip->vendor->miscdev.name);
+	misc_deregister(&chip->vendor.miscdev);
+	kfree(chip->vendor.miscdev.name);
 
-	sysfs_remove_group(&dev->kobj, chip->vendor->attr_group);
+	sysfs_remove_group(&dev->kobj, chip->vendor.attr_group);
 	tpm_bios_log_teardown(chip->bios_dir);
 
-	dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &=
-		~(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES));
+	clear_bit(chip->dev_num, dev_mask);
 
 	kfree(chip);
 
@@ -520,18 +1088,18 @@
  * upon errant exit from this function specific probe function should call
  * pci_disable_device
  */
-int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific *entry)
+struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vendor_specific
+				       *entry)
 {
 #define DEVNAME_SIZE 7
 
 	char *devname;
 	struct tpm_chip *chip;
-	int i, j;
 
 	/* Driver specific per-device data */
 	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
-		return -ENOMEM;
+		return NULL;
 
 	init_MUTEX(&chip->buffer_mutex);
 	init_MUTEX(&chip->tpm_mutex);
@@ -543,45 +1111,37 @@
 	chip->user_read_timer.function = user_reader_timeout;
 	chip->user_read_timer.data = (unsigned long) chip;
 
-	chip->vendor = entry;
+	memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific));
 
-	chip->dev_num = -1;
+	chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES);
 
-	for (i = 0; i < TPM_NUM_MASK_ENTRIES; i++)
-		for (j = 0; j < 8 * sizeof(int); j++)
-			if ((dev_mask[i] & (1 << j)) == 0) {
-				chip->dev_num =
-				    i * TPM_NUM_MASK_ENTRIES + j;
-				dev_mask[i] |= 1 << j;
-				goto dev_num_search_complete;
-			}
-
-dev_num_search_complete:
-	if (chip->dev_num < 0) {
+	if (chip->dev_num >= TPM_NUM_DEVICES) {
 		dev_err(dev, "No available tpm device numbers\n");
 		kfree(chip);
-		return -ENODEV;
+		return NULL;
 	} else if (chip->dev_num == 0)
-		chip->vendor->miscdev.minor = TPM_MINOR;
+		chip->vendor.miscdev.minor = TPM_MINOR;
 	else
-		chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR;
+		chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR;
+
+	set_bit(chip->dev_num, dev_mask);
 
 	devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL);
 	scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num);
-	chip->vendor->miscdev.name = devname;
+	chip->vendor.miscdev.name = devname;
 
-	chip->vendor->miscdev.dev = dev;
+	chip->vendor.miscdev.dev = dev;
 	chip->dev = get_device(dev);
 
-	if (misc_register(&chip->vendor->miscdev)) {
+	if (misc_register(&chip->vendor.miscdev)) {
 		dev_err(chip->dev,
 			"unable to misc_register %s, minor %d\n",
-			chip->vendor->miscdev.name,
-			chip->vendor->miscdev.minor);
+			chip->vendor.miscdev.name,
+			chip->vendor.miscdev.minor);
 		put_device(dev);
+		clear_bit(chip->dev_num, dev_mask);
 		kfree(chip);
-		dev_mask[i] &= !(1 << j);
-		return -ENODEV;
+		return NULL;
 	}
 
 	spin_lock(&driver_lock);
@@ -592,11 +1152,11 @@
 
 	spin_unlock(&driver_lock);
 
-	sysfs_create_group(&dev->kobj, chip->vendor->attr_group);
+	sysfs_create_group(&dev->kobj, chip->vendor.attr_group);
 
 	chip->bios_dir = tpm_bios_log_setup(devname);
 
-	return 0;
+	return chip;
 }
 EXPORT_SYMBOL_GPL(tpm_register_hardware);
 
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index dec0224..54a4c80 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -42,18 +42,30 @@
 				char *);
 extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr,
 				char *);
+extern ssize_t tpm_show_caps_1_2(struct device *, struct device_attribute *attr,
+				char *);
 extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr,
 				const char *, size_t);
+extern ssize_t tpm_show_enabled(struct device *, struct device_attribute *attr,
+				char *);
+extern ssize_t tpm_show_active(struct device *, struct device_attribute *attr,
+				char *);
+extern ssize_t tpm_show_owned(struct device *, struct device_attribute *attr,
+				char *);
+extern ssize_t tpm_show_temp_deactivated(struct device *,
+					 struct device_attribute *attr, char *);
 
 struct tpm_chip;
 
 struct tpm_vendor_specific {
-	u8 req_complete_mask;
-	u8 req_complete_val;
-	u8 req_canceled;
+	const u8 req_complete_mask;
+	const u8 req_complete_val;
+	const u8 req_canceled;
 	void __iomem *iobase;		/* ioremapped address */
 	unsigned long base;		/* TPM base address */
 
+	int irq;
+
 	int region_size;
 	int have_region;
 
@@ -63,6 +75,13 @@
 	u8 (*status) (struct tpm_chip *);
 	struct miscdevice miscdev;
 	struct attribute_group *attr_group;
+	struct list_head list;
+	int locality;
+	unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */
+	unsigned long duration[3]; /* jiffies */
+
+	wait_queue_head_t read_queue;
+	wait_queue_head_t int_queue;
 };
 
 struct tpm_chip {
@@ -81,13 +100,15 @@
 	struct work_struct work;
 	struct semaphore tpm_mutex;	/* tpm is processing */
 
-	struct tpm_vendor_specific *vendor;
+	struct tpm_vendor_specific vendor;
 
 	struct dentry **bios_dir;
 
 	struct list_head list;
 };
 
+#define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor)
+
 static inline int tpm_read_index(int base, int index)
 {
 	outb(index, base);
@@ -100,8 +121,12 @@
 	outb(value & 0xFF, base+1);
 }
 
-extern int tpm_register_hardware(struct device *,
-				 struct tpm_vendor_specific *);
+extern void tpm_get_timeouts(struct tpm_chip *);
+extern void tpm_gen_interrupt(struct tpm_chip *);
+extern void tpm_continue_selftest(struct tpm_chip *);
+extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32);
+extern struct tpm_chip* tpm_register_hardware(struct device *,
+				 const struct tpm_vendor_specific *);
 extern int tpm_open(struct inode *, struct file *);
 extern int tpm_release(struct inode *, struct file *);
 extern ssize_t tpm_write(struct file *, const char __user *, size_t,
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c
index ff36549..58a258c 100644
--- a/drivers/char/tpm/tpm_atmel.c
+++ b/drivers/char/tpm/tpm_atmel.c
@@ -47,12 +47,12 @@
 		return -EIO;
 
 	for (i = 0; i < 6; i++) {
-		status = ioread8(chip->vendor->iobase + 1);
+		status = ioread8(chip->vendor.iobase + 1);
 		if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
 			dev_err(chip->dev, "error reading header\n");
 			return -EIO;
 		}
-		*buf++ = ioread8(chip->vendor->iobase);
+		*buf++ = ioread8(chip->vendor.iobase);
 	}
 
 	/* size of the data received */
@@ -63,7 +63,7 @@
 		dev_err(chip->dev,
 			"Recv size(%d) less than available space\n", size);
 		for (; i < size; i++) {	/* clear the waiting data anyway */
-			status = ioread8(chip->vendor->iobase + 1);
+			status = ioread8(chip->vendor.iobase + 1);
 			if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
 				dev_err(chip->dev, "error reading data\n");
 				return -EIO;
@@ -74,16 +74,16 @@
 
 	/* read all the data available */
 	for (; i < size; i++) {
-		status = ioread8(chip->vendor->iobase + 1);
+		status = ioread8(chip->vendor.iobase + 1);
 		if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
 			dev_err(chip->dev, "error reading data\n");
 			return -EIO;
 		}
-		*buf++ = ioread8(chip->vendor->iobase);
+		*buf++ = ioread8(chip->vendor.iobase);
 	}
 
 	/* make sure data available is gone */
-	status = ioread8(chip->vendor->iobase + 1);
+	status = ioread8(chip->vendor.iobase + 1);
 
 	if (status & ATML_STATUS_DATA_AVAIL) {
 		dev_err(chip->dev, "data available is stuck\n");
@@ -100,7 +100,7 @@
 	dev_dbg(chip->dev, "tpm_atml_send:\n");
 	for (i = 0; i < count; i++) {
 		dev_dbg(chip->dev, "%d 0x%x(%d)\n",  i, buf[i], buf[i]);
- 		iowrite8(buf[i], chip->vendor->iobase);
+ 		iowrite8(buf[i], chip->vendor.iobase);
 	}
 
 	return count;
@@ -108,12 +108,12 @@
 
 static void tpm_atml_cancel(struct tpm_chip *chip)
 {
-	iowrite8(ATML_STATUS_ABORT, chip->vendor->iobase + 1);
+	iowrite8(ATML_STATUS_ABORT, chip->vendor.iobase + 1);
 }
 
 static u8 tpm_atml_status(struct tpm_chip *chip)
 {
-	return ioread8(chip->vendor->iobase + 1);
+	return ioread8(chip->vendor.iobase + 1);
 }
 
 static struct file_operations atmel_ops = {
@@ -140,7 +140,7 @@
 
 static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs };
 
-static struct tpm_vendor_specific tpm_atmel = {
+static const struct tpm_vendor_specific tpm_atmel = {
 	.recv = tpm_atml_recv,
 	.send = tpm_atml_send,
 	.cancel = tpm_atml_cancel,
@@ -159,10 +159,10 @@
 	struct tpm_chip *chip = dev_get_drvdata(&pdev->dev);
 
 	if (chip) {
-		if (chip->vendor->have_region)
-			atmel_release_region(chip->vendor->base,
-					     chip->vendor->region_size);
-		atmel_put_base_addr(chip->vendor);
+		if (chip->vendor.have_region)
+			atmel_release_region(chip->vendor.base,
+					     chip->vendor.region_size);
+		atmel_put_base_addr(chip->vendor.iobase);
 		tpm_remove_hardware(chip->dev);
 		platform_device_unregister(pdev);
 	}
@@ -179,18 +179,22 @@
 static int __init init_atmel(void)
 {
 	int rc = 0;
+	void __iomem *iobase = NULL;
+	int have_region, region_size;
+	unsigned long base;
+	struct  tpm_chip *chip;
 
 	driver_register(&atml_drv);
 
-	if ((tpm_atmel.iobase = atmel_get_base_addr(&tpm_atmel)) == NULL) {
+	if ((iobase = atmel_get_base_addr(&base, &region_size)) == NULL) {
 		rc = -ENODEV;
 		goto err_unreg_drv;
 	}
 
-	tpm_atmel.have_region =
+	have_region =
 	    (atmel_request_region
-	     (tpm_atmel.base, tpm_atmel.region_size,
-	      "tpm_atmel0") == NULL) ? 0 : 1;
+	     (tpm_atmel.base, region_size, "tpm_atmel0") == NULL) ? 0 : 1;
+
 
 	if (IS_ERR
 	    (pdev =
@@ -199,17 +203,25 @@
 		goto err_rel_reg;
 	}
 
-	if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0)
+	if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_atmel))) {
+		rc = -ENODEV;
 		goto err_unreg_dev;
+	}
+
+	chip->vendor.iobase = iobase;
+	chip->vendor.base = base;
+	chip->vendor.have_region = have_region;
+	chip->vendor.region_size = region_size;
+
 	return 0;
 
 err_unreg_dev:
 	platform_device_unregister(pdev);
 err_rel_reg:
-	atmel_put_base_addr(&tpm_atmel);
-	if (tpm_atmel.have_region)
-		atmel_release_region(tpm_atmel.base,
-				     tpm_atmel.region_size);
+	atmel_put_base_addr(iobase);
+	if (have_region)
+		atmel_release_region(base,
+				     region_size);
 err_unreg_drv:
 	driver_unregister(&atml_drv);
 	return rc;
diff --git a/drivers/char/tpm/tpm_atmel.h b/drivers/char/tpm/tpm_atmel.h
index d3478aa..2e68eeb 100644
--- a/drivers/char/tpm/tpm_atmel.h
+++ b/drivers/char/tpm/tpm_atmel.h
@@ -28,13 +28,12 @@
 #define atmel_request_region request_mem_region
 #define atmel_release_region release_mem_region
 
-static inline void atmel_put_base_addr(struct tpm_vendor_specific
-					 *vendor)
+static inline void atmel_put_base_addr(void __iomem *iobase)
 {
-	iounmap(vendor->iobase);
+	iounmap(iobase);
 }
 
-static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific *vendor)
+static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
 {
 	struct device_node *dn;
 	unsigned long address, size;
@@ -71,9 +70,9 @@
 	else
 		size = reg[naddrc];
 
-	vendor->base = address;
-	vendor->region_size = size;
-	return ioremap(vendor->base, vendor->region_size);
+	*base = address;
+	*region_size = size;
+	return ioremap(*base, *region_size);
 }
 #else
 #define atmel_getb(chip, offset) inb(chip->vendor->base + offset)
@@ -106,14 +105,12 @@
 	return 0;
 }
 
-static inline void atmel_put_base_addr(struct tpm_vendor_specific
-					 *vendor)
+static inline void atmel_put_base_addr(void __iomem *iobase)
 {
 }
 
 /* Determine where to talk to device */
-static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific
-					 *vendor)
+static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
 {
 	int lo, hi;
 
@@ -123,9 +120,9 @@
 	lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
 	hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
 
-	vendor->base = (hi << 8) | lo;
-	vendor->region_size = 2;
+	*base = (hi << 8) | lo;
+	*region_size = 2;
 
-	return ioport_map(vendor->base, vendor->region_size);
+	return ioport_map(*base, *region_size);
 }
 #endif
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c
index 537aa45..e45f0d3 100644
--- a/drivers/char/tpm/tpm_bios.c
+++ b/drivers/char/tpm/tpm_bios.c
@@ -29,6 +29,11 @@
 #define MAX_TEXT_EVENT		1000	/* Max event string length */
 #define ACPI_TCPA_SIG		"TCPA"	/* 0x41504354 /'TCPA' */
 
+enum bios_platform_class {
+	BIOS_CLIENT = 0x00,
+	BIOS_SERVER = 0x01,
+};
+
 struct tpm_bios_log {
 	void *bios_event_log;
 	void *bios_event_log_end;
@@ -36,9 +41,18 @@
 
 struct acpi_tcpa {
 	struct acpi_table_header hdr;
-	u16 reserved;
-	u32 log_max_len __attribute__ ((packed));
-	u32 log_start_addr __attribute__ ((packed));
+	u16 platform_class;
+	union {
+		struct client_hdr {
+			u32 log_max_len __attribute__ ((packed));
+			u64 log_start_addr __attribute__ ((packed));
+		} client;
+		struct server_hdr {
+			u16 reserved;
+			u64 log_max_len __attribute__ ((packed));
+			u64 log_start_addr __attribute__ ((packed));
+		} server;
+	};
 };
 
 struct tcpa_event {
@@ -120,6 +134,7 @@
 	"S-CRTM Version",
 	"S-CRTM Contents",
 	"S-CRTM POST Contents",
+	"POST Contents",
 };
 
 /* returns pointer to start of pos. entry of tcg log */
@@ -306,6 +321,7 @@
 	/* 5th: delimiter */
 	seq_putc(m, '\0');
 
+	kfree(eventname);
 	return 0;
 }
 
@@ -353,6 +369,7 @@
 	/* 4th: eventname <= max + \'0' delimiter */
 	seq_printf(m, " %s\n", eventname);
 
+	kfree(eventname);
 	return 0;
 }
 
@@ -376,6 +393,7 @@
 	struct acpi_tcpa *buff;
 	acpi_status status;
 	struct acpi_table_header *virt;
+	u64 len, start;
 
 	if (log->bios_event_log != NULL) {
 		printk(KERN_ERR
@@ -396,27 +414,37 @@
 		return -EIO;
 	}
 
-	if (buff->log_max_len == 0) {
+	switch(buff->platform_class) {
+	case BIOS_SERVER:
+		len = buff->server.log_max_len;
+		start = buff->server.log_start_addr;
+		break;
+	case BIOS_CLIENT:
+	default:
+		len = buff->client.log_max_len;
+		start = buff->client.log_start_addr;
+		break;
+	}
+	if (!len) {
 		printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
 		return -EIO;
 	}
 
 	/* malloc EventLog space */
-	log->bios_event_log = kmalloc(buff->log_max_len, GFP_KERNEL);
+	log->bios_event_log = kmalloc(len, GFP_KERNEL);
 	if (!log->bios_event_log) {
-		printk
-		    ("%s: ERROR - Not enough  Memory for BIOS measurements\n",
-		     __func__);
+		printk("%s: ERROR - Not enough  Memory for BIOS measurements\n",
+			__func__);
 		return -ENOMEM;
 	}
 
-	log->bios_event_log_end = log->bios_event_log + buff->log_max_len;
+	log->bios_event_log_end = log->bios_event_log + len;
 
-	acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, (void *) &virt);
+	acpi_os_map_memory(start, len, (void *) &virt);
 
-	memcpy(log->bios_event_log, virt, buff->log_max_len);
+	memcpy(log->bios_event_log, virt, len);
 
-	acpi_os_unmap_memory(virt, buff->log_max_len);
+	acpi_os_unmap_memory(virt, len);
 	return 0;
 }
 
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
index 24095f6..adfff21 100644
--- a/drivers/char/tpm/tpm_infineon.c
+++ b/drivers/char/tpm/tpm_infineon.c
@@ -15,6 +15,7 @@
  * License.
  */
 
+#include <linux/init.h>
 #include <linux/pnp.h>
 #include "tpm.h"
 
@@ -104,7 +105,7 @@
 
 	if (clear_wrfifo) {
 		for (i = 0; i < 4096; i++) {
-			status = inb(chip->vendor->base + WRFIFO);
+			status = inb(chip->vendor.base + WRFIFO);
 			if (status == 0xff) {
 				if (check == 5)
 					break;
@@ -124,8 +125,8 @@
 	 */
 	i = 0;
 	do {
-		status = inb(chip->vendor->base + RDFIFO);
-		status = inb(chip->vendor->base + STAT);
+		status = inb(chip->vendor.base + RDFIFO);
+		status = inb(chip->vendor.base + STAT);
 		i++;
 		if (i == TPM_MAX_TRIES)
 			return -EIO;
@@ -138,7 +139,7 @@
 	int status;
 	int i;
 	for (i = 0; i < TPM_MAX_TRIES; i++) {
-		status = inb(chip->vendor->base + STAT);
+		status = inb(chip->vendor.base + STAT);
 		/* check the status-register if wait_for_bit is set */
 		if (status & 1 << wait_for_bit)
 			break;
@@ -157,7 +158,7 @@
 static void wait_and_send(struct tpm_chip *chip, u8 sendbyte)
 {
 	wait(chip, STAT_XFE);
-	outb(sendbyte, chip->vendor->base + WRFIFO);
+	outb(sendbyte, chip->vendor.base + WRFIFO);
 }
 
     /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more
@@ -204,7 +205,7 @@
 		ret = wait(chip, STAT_RDA);
 		if (ret)
 			return -EIO;
-		buf[i] = inb(chip->vendor->base + RDFIFO);
+		buf[i] = inb(chip->vendor.base + RDFIFO);
 	}
 
 	if (buf[0] != TPM_VL_VER) {
@@ -219,7 +220,7 @@
 
 		for (i = 0; i < size; i++) {
 			wait(chip, STAT_RDA);
-			buf[i] = inb(chip->vendor->base + RDFIFO);
+			buf[i] = inb(chip->vendor.base + RDFIFO);
 		}
 
 		if ((size == 0x6D00) && (buf[1] == 0x80)) {
@@ -268,7 +269,7 @@
 	u8 count_high, count_low, count_4, count_3, count_2, count_1;
 
 	/* Disabling Reset, LP and IRQC */
-	outb(RESET_LP_IRQC_DISABLE, chip->vendor->base + CMD);
+	outb(RESET_LP_IRQC_DISABLE, chip->vendor.base + CMD);
 
 	ret = empty_fifo(chip, 1);
 	if (ret) {
@@ -319,7 +320,7 @@
 
 static u8 tpm_inf_status(struct tpm_chip *chip)
 {
-	return inb(chip->vendor->base + STAT);
+	return inb(chip->vendor.base + STAT);
 }
 
 static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
@@ -346,7 +347,7 @@
 	.release = tpm_release,
 };
 
-static struct tpm_vendor_specific tpm_inf = {
+static const struct tpm_vendor_specific tpm_inf = {
 	.recv = tpm_inf_recv,
 	.send = tpm_inf_send,
 	.cancel = tpm_inf_cancel,
@@ -375,6 +376,7 @@
 	int version[2];
 	int productid[2];
 	char chipname[20];
+	struct tpm_chip *chip;
 
 	/* read IO-ports through PnP */
 	if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
@@ -395,14 +397,13 @@
 			goto err_last;
 		}
 		/* publish my base address and request region */
-		tpm_inf.base = TPM_INF_BASE;
 		if (request_region
-		    (tpm_inf.base, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) {
+		    (TPM_INF_BASE, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) {
 			rc = -EINVAL;
 			goto err_last;
 		}
-		if (request_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN,
-				"tpm_infineon0") == NULL) {
+		if (request_region
+		    (TPM_INF_ADDR, TPM_INF_ADDR_LEN, "tpm_infineon0") == NULL) {
 			rc = -EINVAL;
 			goto err_last;
 		}
@@ -442,9 +443,9 @@
 
 		/* configure TPM with IO-ports */
 		outb(IOLIMH, TPM_INF_ADDR);
-		outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA);
+		outb(((TPM_INF_BASE >> 8) & 0xff), TPM_INF_DATA);
 		outb(IOLIML, TPM_INF_ADDR);
-		outb((tpm_inf.base & 0xff), TPM_INF_DATA);
+		outb((TPM_INF_BASE & 0xff), TPM_INF_DATA);
 
 		/* control if IO-ports are set correctly */
 		outb(IOLIMH, TPM_INF_ADDR);
@@ -452,10 +453,10 @@
 		outb(IOLIML, TPM_INF_ADDR);
 		iol = inb(TPM_INF_DATA);
 
-		if ((ioh << 8 | iol) != tpm_inf.base) {
+		if ((ioh << 8 | iol) != TPM_INF_BASE) {
 			dev_err(&dev->dev,
-				"Could not set IO-ports to 0x%lx\n",
-				tpm_inf.base);
+				"Could not set IO-ports to 0x%x\n",
+				TPM_INF_BASE);
 			rc = -EIO;
 			goto err_release_region;
 		}
@@ -466,15 +467,15 @@
 		outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
 
 		/* disable RESET, LP and IRQC */
-		outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD);
+		outb(RESET_LP_IRQC_DISABLE, TPM_INF_BASE + CMD);
 
 		/* Finally, we're done, print some infos */
 		dev_info(&dev->dev, "TPM found: "
 			 "config base 0x%x, "
 			 "io base 0x%x, "
-			 "chip version %02x%02x, "
-			 "vendor id %x%x (Infineon), "
-			 "product id %02x%02x"
+			 "chip version 0x%02x%02x, "
+			 "vendor id 0x%x%x (Infineon), "
+			 "product id 0x%02x%02x"
 			 "%s\n",
 			 TPM_INF_ADDR,
 			 TPM_INF_BASE,
@@ -482,11 +483,10 @@
 			 vendorid[0], vendorid[1],
 			 productid[0], productid[1], chipname);
 
-		rc = tpm_register_hardware(&dev->dev, &tpm_inf);
-		if (rc < 0) {
-			rc = -ENODEV;
+		if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf))) {
 			goto err_release_region;
 		}
+		chip->vendor.base = TPM_INF_BASE;
 		return 0;
 	} else {
 		rc = -ENODEV;
@@ -494,7 +494,7 @@
 	}
 
 err_release_region:
-	release_region(tpm_inf.base, TPM_INF_PORT_LEN);
+	release_region(TPM_INF_BASE, TPM_INF_PORT_LEN);
 	release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN);
 
 err_last:
@@ -506,7 +506,8 @@
 	struct tpm_chip *chip = pnp_get_drvdata(dev);
 
 	if (chip) {
-		release_region(chip->vendor->base, TPM_INF_PORT_LEN);
+		release_region(TPM_INF_BASE, TPM_INF_PORT_LEN);
+		release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN);
 		tpm_remove_hardware(chip->dev);
 	}
 }
@@ -520,7 +521,7 @@
 	},
 	.id_table = tpm_pnp_tbl,
 	.probe = tpm_inf_pnp_probe,
-	.remove = tpm_inf_pnp_remove,
+	.remove = __devexit_p(tpm_inf_pnp_remove),
 };
 
 static int __init init_inf(void)
@@ -538,5 +539,5 @@
 
 MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>");
 MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
-MODULE_VERSION("1.7");
+MODULE_VERSION("1.8");
 MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
index 680a8e3..4c8bc06 100644
--- a/drivers/char/tpm/tpm_nsc.c
+++ b/drivers/char/tpm/tpm_nsc.c
@@ -71,7 +71,7 @@
 	unsigned long stop;
 
 	/* status immediately available check */
-	*data = inb(chip->vendor->base + NSC_STATUS);
+	*data = inb(chip->vendor.base + NSC_STATUS);
 	if ((*data & mask) == val)
 		return 0;
 
@@ -79,7 +79,7 @@
 	stop = jiffies + 10 * HZ;
 	do {
 		msleep(TPM_TIMEOUT);
-		*data = inb(chip->vendor->base + 1);
+		*data = inb(chip->vendor.base + 1);
 		if ((*data & mask) == val)
 			return 0;
 	}
@@ -94,9 +94,9 @@
 	unsigned long stop;
 
 	/* status immediately available check */
-	status = inb(chip->vendor->base + NSC_STATUS);
+	status = inb(chip->vendor.base + NSC_STATUS);
 	if (status & NSC_STATUS_OBF)
-		status = inb(chip->vendor->base + NSC_DATA);
+		status = inb(chip->vendor.base + NSC_DATA);
 	if (status & NSC_STATUS_RDY)
 		return 0;
 
@@ -104,9 +104,9 @@
 	stop = jiffies + 100;
 	do {
 		msleep(TPM_TIMEOUT);
-		status = inb(chip->vendor->base + NSC_STATUS);
+		status = inb(chip->vendor.base + NSC_STATUS);
 		if (status & NSC_STATUS_OBF)
-			status = inb(chip->vendor->base + NSC_DATA);
+			status = inb(chip->vendor.base + NSC_DATA);
 		if (status & NSC_STATUS_RDY)
 			return 0;
 	}
@@ -132,7 +132,7 @@
 		return -EIO;
 	}
 	if ((data =
-	     inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
+	     inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
 		dev_err(chip->dev, "not in normal mode (0x%x)\n",
 			data);
 		return -EIO;
@@ -148,7 +148,7 @@
 		}
 		if (data & NSC_STATUS_F0)
 			break;
-		*p = inb(chip->vendor->base + NSC_DATA);
+		*p = inb(chip->vendor.base + NSC_DATA);
 	}
 
 	if ((data & NSC_STATUS_F0) == 0 &&
@@ -156,7 +156,7 @@
 		dev_err(chip->dev, "F0 not set\n");
 		return -EIO;
 	}
-	if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_EOC) {
+	if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_EOC) {
 		dev_err(chip->dev,
 			"expected end of command(0x%x)\n", data);
 		return -EIO;
@@ -182,7 +182,7 @@
 	 * fix it. Not sure why this is needed, we followed the flow
 	 * chart in the manual to the letter.
 	 */
-	outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
+	outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND);
 
 	if (nsc_wait_for_ready(chip) != 0)
 		return -EIO;
@@ -192,7 +192,7 @@
 		return -EIO;
 	}
 
-	outb(NSC_COMMAND_NORMAL, chip->vendor->base + NSC_COMMAND);
+	outb(NSC_COMMAND_NORMAL, chip->vendor.base + NSC_COMMAND);
 	if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) {
 		dev_err(chip->dev, "IBR timeout\n");
 		return -EIO;
@@ -204,26 +204,26 @@
 				"IBF timeout (while writing data)\n");
 			return -EIO;
 		}
-		outb(buf[i], chip->vendor->base + NSC_DATA);
+		outb(buf[i], chip->vendor.base + NSC_DATA);
 	}
 
 	if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
 		dev_err(chip->dev, "IBF timeout\n");
 		return -EIO;
 	}
-	outb(NSC_COMMAND_EOC, chip->vendor->base + NSC_COMMAND);
+	outb(NSC_COMMAND_EOC, chip->vendor.base + NSC_COMMAND);
 
 	return count;
 }
 
 static void tpm_nsc_cancel(struct tpm_chip *chip)
 {
-	outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
+	outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND);
 }
 
 static u8 tpm_nsc_status(struct tpm_chip *chip)
 {
-	return inb(chip->vendor->base + NSC_STATUS);
+	return inb(chip->vendor.base + NSC_STATUS);
 }
 
 static struct file_operations nsc_ops = {
@@ -250,7 +250,7 @@
 
 static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs };
 
-static struct tpm_vendor_specific tpm_nsc = {
+static const struct tpm_vendor_specific tpm_nsc = {
 	.recv = tpm_nsc_recv,
 	.send = tpm_nsc_send,
 	.cancel = tpm_nsc_cancel,
@@ -268,7 +268,7 @@
 {
 	struct tpm_chip *chip = dev_get_drvdata(dev);
 	if ( chip ) {
-		release_region(chip->vendor->base, 2);
+		release_region(chip->vendor.base, 2);
 		tpm_remove_hardware(chip->dev);
 	}
 }
@@ -286,7 +286,8 @@
 	int rc = 0;
 	int lo, hi;
 	int nscAddrBase = TPM_ADDR;
-
+	struct tpm_chip *chip;
+	unsigned long base;
 
 	/* verify that it is a National part (SID) */
 	if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) {
@@ -300,7 +301,7 @@
 
 	hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI);
 	lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO);
-	tpm_nsc.base = (hi<<8) | lo;
+	base = (hi<<8) | lo;
 
 	/* enable the DPM module */
 	tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01);
@@ -320,13 +321,15 @@
 	if ((rc = platform_device_register(pdev)) < 0)
 		goto err_free_dev;
 
-	if (request_region(tpm_nsc.base, 2, "tpm_nsc0") == NULL ) {
+	if (request_region(base, 2, "tpm_nsc0") == NULL ) {
 		rc = -EBUSY;
 		goto err_unreg_dev;
 	}
 
-	if ((rc = tpm_register_hardware(&pdev->dev, &tpm_nsc)) < 0)
+	if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) {
+		rc = -ENODEV;
 		goto err_rel_reg;
+	}
 
 	dev_dbg(&pdev->dev, "NSC TPM detected\n");
 	dev_dbg(&pdev->dev,
@@ -361,10 +364,12 @@
 		 "NSC TPM revision %d\n",
 		 tpm_read_index(nscAddrBase, 0x27) & 0x1F);
 
+	chip->vendor.base = base;
+
 	return 0;
 
 err_rel_reg:
-	release_region(tpm_nsc.base, 2);
+	release_region(base, 2);
 err_unreg_dev:
 	platform_device_unregister(pdev);
 err_free_dev:
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
new file mode 100644
index 0000000..b9cae9a
--- /dev/null
+++ b/drivers/char/tpm/tpm_tis.c
@@ -0,0 +1,669 @@
+/*
+ * Copyright (C) 2005, 2006 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@watson.ibm.com>
+ * Kylene Hall <kjhall@us.ibm.com>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This device driver implements the TPM interface as defined in
+ * the TCG TPM Interface Spec version 1.2, revision 1.0.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pnp.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include "tpm.h"
+
+#define TPM_HEADER_SIZE 10
+
+enum tis_access {
+	TPM_ACCESS_VALID = 0x80,
+	TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
+	TPM_ACCESS_REQUEST_PENDING = 0x04,
+	TPM_ACCESS_REQUEST_USE = 0x02,
+};
+
+enum tis_status {
+	TPM_STS_VALID = 0x80,
+	TPM_STS_COMMAND_READY = 0x40,
+	TPM_STS_GO = 0x20,
+	TPM_STS_DATA_AVAIL = 0x10,
+	TPM_STS_DATA_EXPECT = 0x08,
+};
+
+enum tis_int_flags {
+	TPM_GLOBAL_INT_ENABLE = 0x80000000,
+	TPM_INTF_BURST_COUNT_STATIC = 0x100,
+	TPM_INTF_CMD_READY_INT = 0x080,
+	TPM_INTF_INT_EDGE_FALLING = 0x040,
+	TPM_INTF_INT_EDGE_RISING = 0x020,
+	TPM_INTF_INT_LEVEL_LOW = 0x010,
+	TPM_INTF_INT_LEVEL_HIGH = 0x008,
+	TPM_INTF_LOCALITY_CHANGE_INT = 0x004,
+	TPM_INTF_STS_VALID_INT = 0x002,
+	TPM_INTF_DATA_AVAIL_INT = 0x001,
+};
+
+enum tis_defaults {
+	TIS_MEM_BASE = 0xFED4000,
+	TIS_MEM_LEN = 0x5000,
+	TIS_SHORT_TIMEOUT = 750,	/* ms */
+	TIS_LONG_TIMEOUT = 2000,	/* 2 sec */
+};
+
+#define	TPM_ACCESS(l)			(0x0000 | ((l) << 12))
+#define	TPM_INT_ENABLE(l)		(0x0008 | ((l) << 12))
+#define	TPM_INT_VECTOR(l)		(0x000C | ((l) << 12))
+#define	TPM_INT_STATUS(l)		(0x0010 | ((l) << 12))
+#define	TPM_INTF_CAPS(l)		(0x0014 | ((l) << 12))
+#define	TPM_STS(l)			(0x0018 | ((l) << 12))
+#define	TPM_DATA_FIFO(l)		(0x0024 | ((l) << 12))
+
+#define	TPM_DID_VID(l)			(0x0F00 | ((l) << 12))
+#define	TPM_RID(l)			(0x0F04 | ((l) << 12))
+
+static LIST_HEAD(tis_chips);
+static DEFINE_SPINLOCK(tis_lock);
+
+static int check_locality(struct tpm_chip *chip, int l)
+{
+	if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
+	     (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
+	    (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
+		return chip->vendor.locality = l;
+
+	return -1;
+}
+
+static void release_locality(struct tpm_chip *chip, int l, int force)
+{
+	if (force || (ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
+		      (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
+	    (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID))
+		iowrite8(TPM_ACCESS_ACTIVE_LOCALITY,
+			 chip->vendor.iobase + TPM_ACCESS(l));
+}
+
+static int request_locality(struct tpm_chip *chip, int l)
+{
+	unsigned long stop;
+	long rc;
+
+	if (check_locality(chip, l) >= 0)
+		return l;
+
+	iowrite8(TPM_ACCESS_REQUEST_USE,
+		 chip->vendor.iobase + TPM_ACCESS(l));
+
+	if (chip->vendor.irq) {
+		rc = wait_event_interruptible_timeout(chip->vendor.int_queue,
+						      (check_locality
+						       (chip, l) >= 0),
+						      chip->vendor.timeout_a);
+		if (rc > 0)
+			return l;
+
+	} else {
+		/* wait for burstcount */
+		stop = jiffies + chip->vendor.timeout_a;
+		do {
+			if (check_locality(chip, l) >= 0)
+				return l;
+			msleep(TPM_TIMEOUT);
+		}
+		while (time_before(jiffies, stop));
+	}
+	return -1;
+}
+
+static u8 tpm_tis_status(struct tpm_chip *chip)
+{
+	return ioread8(chip->vendor.iobase +
+		       TPM_STS(chip->vendor.locality));
+}
+
+static void tpm_tis_ready(struct tpm_chip *chip)
+{
+	/* this causes the current command to be aborted */
+	iowrite8(TPM_STS_COMMAND_READY,
+		 chip->vendor.iobase + TPM_STS(chip->vendor.locality));
+}
+
+static int get_burstcount(struct tpm_chip *chip)
+{
+	unsigned long stop;
+	int burstcnt;
+
+	/* wait for burstcount */
+	/* which timeout value, spec has 2 answers (c & d) */
+	stop = jiffies + chip->vendor.timeout_d;
+	do {
+		burstcnt = ioread8(chip->vendor.iobase +
+				   TPM_STS(chip->vendor.locality) + 1);
+		burstcnt += ioread8(chip->vendor.iobase +
+				    TPM_STS(chip->vendor.locality) +
+				    2) << 8;
+		if (burstcnt)
+			return burstcnt;
+		msleep(TPM_TIMEOUT);
+	} while (time_before(jiffies, stop));
+	return -EBUSY;
+}
+
+static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
+			 wait_queue_head_t *queue)
+{
+	unsigned long stop;
+	long rc;
+	u8 status;
+
+	/* check current status */
+	status = tpm_tis_status(chip);
+	if ((status & mask) == mask)
+		return 0;
+
+	if (chip->vendor.irq) {
+		rc = wait_event_interruptible_timeout(*queue,
+						      ((tpm_tis_status
+							(chip) & mask) ==
+						       mask), timeout);
+		if (rc > 0)
+			return 0;
+	} else {
+		stop = jiffies + timeout;
+		do {
+			msleep(TPM_TIMEOUT);
+			status = tpm_tis_status(chip);
+			if ((status & mask) == mask)
+				return 0;
+		} while (time_before(jiffies, stop));
+	}
+	return -ETIME;
+}
+
+static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	int size = 0, burstcnt;
+	while (size < count &&
+	       wait_for_stat(chip,
+			     TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+			     chip->vendor.timeout_c,
+			     &chip->vendor.read_queue)
+	       == 0) {
+		burstcnt = get_burstcount(chip);
+		for (; burstcnt > 0 && size < count; burstcnt--)
+			buf[size++] = ioread8(chip->vendor.iobase +
+					      TPM_DATA_FIFO(chip->vendor.
+							    locality));
+	}
+	return size;
+}
+
+static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	int size = 0;
+	int expected, status;
+
+	if (count < TPM_HEADER_SIZE) {
+		size = -EIO;
+		goto out;
+	}
+
+	/* read first 10 bytes, including tag, paramsize, and result */
+	if ((size =
+	     recv_data(chip, buf, TPM_HEADER_SIZE)) < TPM_HEADER_SIZE) {
+		dev_err(chip->dev, "Unable to read header\n");
+		goto out;
+	}
+
+	expected = be32_to_cpu(*(__be32 *) (buf + 2));
+	if (expected > count) {
+		size = -EIO;
+		goto out;
+	}
+
+	if ((size +=
+	     recv_data(chip, &buf[TPM_HEADER_SIZE],
+		       expected - TPM_HEADER_SIZE)) < expected) {
+		dev_err(chip->dev, "Unable to read remainder of result\n");
+		size = -ETIME;
+		goto out;
+	}
+
+	wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+		      &chip->vendor.int_queue);
+	status = tpm_tis_status(chip);
+	if (status & TPM_STS_DATA_AVAIL) {	/* retry? */
+		dev_err(chip->dev, "Error left over data\n");
+		size = -EIO;
+		goto out;
+	}
+
+out:
+	tpm_tis_ready(chip);
+	release_locality(chip, chip->vendor.locality, 0);
+	return size;
+}
+
+/*
+ * If interrupts are used (signaled by an irq set in the vendor structure)
+ * tpm.c can skip polling for the data to be available as the interrupt is
+ * waited for here
+ */
+static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
+{
+	int rc, status, burstcnt;
+	size_t count = 0;
+	u32 ordinal;
+
+	if (request_locality(chip, 0) < 0)
+		return -EBUSY;
+
+	status = tpm_tis_status(chip);
+	if ((status & TPM_STS_COMMAND_READY) == 0) {
+		tpm_tis_ready(chip);
+		if (wait_for_stat
+		    (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b,
+		     &chip->vendor.int_queue) < 0) {
+			rc = -ETIME;
+			goto out_err;
+		}
+	}
+
+	while (count < len - 1) {
+		burstcnt = get_burstcount(chip);
+		for (; burstcnt > 0 && count < len - 1; burstcnt--) {
+			iowrite8(buf[count], chip->vendor.iobase +
+				 TPM_DATA_FIFO(chip->vendor.locality));
+			count++;
+		}
+
+		wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+			      &chip->vendor.int_queue);
+		status = tpm_tis_status(chip);
+		if ((status & TPM_STS_DATA_EXPECT) == 0) {
+			rc = -EIO;
+			goto out_err;
+		}
+	}
+
+	/* write last byte */
+	iowrite8(buf[count],
+		 chip->vendor.iobase +
+		 TPM_DATA_FIFO(chip->vendor.locality));
+	wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+		      &chip->vendor.int_queue);
+	status = tpm_tis_status(chip);
+	if ((status & TPM_STS_DATA_EXPECT) != 0) {
+		rc = -EIO;
+		goto out_err;
+	}
+
+	/* go and do it */
+	iowrite8(TPM_STS_GO,
+		 chip->vendor.iobase + TPM_STS(chip->vendor.locality));
+
+	if (chip->vendor.irq) {
+		ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
+		if (wait_for_stat
+		    (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+		     tpm_calc_ordinal_duration(chip, ordinal),
+		     &chip->vendor.read_queue) < 0) {
+			rc = -ETIME;
+			goto out_err;
+		}
+	}
+	return len;
+out_err:
+	tpm_tis_ready(chip);
+	release_locality(chip, chip->vendor.locality, 0);
+	return rc;
+}
+
+static struct file_operations tis_ops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.open = tpm_open,
+	.read = tpm_read,
+	.write = tpm_write,
+	.release = tpm_release,
+};
+
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
+static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
+static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
+static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated,
+		   NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
+
+static struct attribute *tis_attrs[] = {
+	&dev_attr_pubek.attr,
+	&dev_attr_pcrs.attr,
+	&dev_attr_enabled.attr,
+	&dev_attr_active.attr,
+	&dev_attr_owned.attr,
+	&dev_attr_temp_deactivated.attr,
+	&dev_attr_caps.attr,
+	&dev_attr_cancel.attr, NULL,
+};
+
+static struct attribute_group tis_attr_grp = {
+	.attrs = tis_attrs
+};
+
+static struct tpm_vendor_specific tpm_tis = {
+	.status = tpm_tis_status,
+	.recv = tpm_tis_recv,
+	.send = tpm_tis_send,
+	.cancel = tpm_tis_ready,
+	.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+	.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+	.req_canceled = TPM_STS_COMMAND_READY,
+	.attr_group = &tis_attr_grp,
+	.miscdev = {
+		    .fops = &tis_ops,},
+};
+
+static irqreturn_t tis_int_probe(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct tpm_chip *chip = (struct tpm_chip *) dev_id;
+	u32 interrupt;
+
+	interrupt = ioread32(chip->vendor.iobase +
+			     TPM_INT_STATUS(chip->vendor.locality));
+
+	if (interrupt == 0)
+		return IRQ_NONE;
+
+	chip->vendor.irq = irq;
+
+	/* Clear interrupts handled with TPM_EOI */
+	iowrite32(interrupt,
+		  chip->vendor.iobase +
+		  TPM_INT_STATUS(chip->vendor.locality));
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t tis_int_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct tpm_chip *chip = (struct tpm_chip *) dev_id;
+	u32 interrupt;
+	int i;
+
+	interrupt = ioread32(chip->vendor.iobase +
+			     TPM_INT_STATUS(chip->vendor.locality));
+
+	if (interrupt == 0)
+		return IRQ_NONE;
+
+	if (interrupt & TPM_INTF_DATA_AVAIL_INT)
+		wake_up_interruptible(&chip->vendor.read_queue);
+	if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT)
+		for (i = 0; i < 5; i++)
+			if (check_locality(chip, i) >= 0)
+				break;
+	if (interrupt &
+	    (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT |
+	     TPM_INTF_CMD_READY_INT))
+		wake_up_interruptible(&chip->vendor.int_queue);
+
+	/* Clear interrupts handled with TPM_EOI */
+	iowrite32(interrupt,
+		  chip->vendor.iobase +
+		  TPM_INT_STATUS(chip->vendor.locality));
+	return IRQ_HANDLED;
+}
+
+static int interrupts = 1;
+module_param(interrupts, bool, 0444);
+MODULE_PARM_DESC(interrupts, "Enable interrupts");
+
+static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
+				      const struct pnp_device_id *pnp_id)
+{
+	u32 vendor, intfcaps, intmask;
+	int rc, i;
+	unsigned long start, len;
+	struct tpm_chip *chip;
+
+	start = pnp_mem_start(pnp_dev, 0);
+	len = pnp_mem_len(pnp_dev, 0);
+
+	if (!start)
+		start = TIS_MEM_BASE;
+	if (!len)
+		len = TIS_MEM_LEN;
+
+	if (!(chip = tpm_register_hardware(&pnp_dev->dev, &tpm_tis)))
+		return -ENODEV;
+
+	chip->vendor.iobase = ioremap(start, len);
+	if (!chip->vendor.iobase) {
+		rc = -EIO;
+		goto out_err;
+	}
+
+	vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
+	if ((vendor & 0xFFFF) == 0xFFFF) {
+		rc = -ENODEV;
+		goto out_err;
+	}
+
+	/* Default timeouts */
+	chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+	chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
+	chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+	chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+
+	dev_info(&pnp_dev->dev,
+		 "1.2 TPM (device-id 0x%X, rev-id %d)\n",
+		 vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
+
+	/* Figure out the capabilities */
+	intfcaps =
+	    ioread32(chip->vendor.iobase +
+		     TPM_INTF_CAPS(chip->vendor.locality));
+	dev_dbg(&pnp_dev->dev, "TPM interface capabilities (0x%x):\n",
+		intfcaps);
+	if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
+		dev_dbg(&pnp_dev->dev, "\tBurst Count Static\n");
+	if (intfcaps & TPM_INTF_CMD_READY_INT)
+		dev_dbg(&pnp_dev->dev, "\tCommand Ready Int Support\n");
+	if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
+		dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Falling\n");
+	if (intfcaps & TPM_INTF_INT_EDGE_RISING)
+		dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Rising\n");
+	if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
+		dev_dbg(&pnp_dev->dev, "\tInterrupt Level Low\n");
+	if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
+		dev_dbg(&pnp_dev->dev, "\tInterrupt Level High\n");
+	if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT)
+		dev_dbg(&pnp_dev->dev, "\tLocality Change Int Support\n");
+	if (intfcaps & TPM_INTF_STS_VALID_INT)
+		dev_dbg(&pnp_dev->dev, "\tSts Valid Int Support\n");
+	if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
+		dev_dbg(&pnp_dev->dev, "\tData Avail Int Support\n");
+
+	if (request_locality(chip, 0) != 0) {
+		rc = -ENODEV;
+		goto out_err;
+	}
+
+	/* INTERRUPT Setup */
+	init_waitqueue_head(&chip->vendor.read_queue);
+	init_waitqueue_head(&chip->vendor.int_queue);
+
+	intmask =
+	    ioread32(chip->vendor.iobase +
+		     TPM_INT_ENABLE(chip->vendor.locality));
+
+	intmask |= TPM_INTF_CMD_READY_INT
+	    | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
+	    | TPM_INTF_STS_VALID_INT;
+
+	iowrite32(intmask,
+		  chip->vendor.iobase +
+		  TPM_INT_ENABLE(chip->vendor.locality));
+	if (interrupts) {
+		chip->vendor.irq =
+		    ioread8(chip->vendor.iobase +
+			    TPM_INT_VECTOR(chip->vendor.locality));
+
+		for (i = 3; i < 16 && chip->vendor.irq == 0; i++) {
+			iowrite8(i, chip->vendor.iobase +
+				    TPM_INT_VECTOR(chip->vendor.locality));
+			if (request_irq
+			    (i, tis_int_probe, SA_SHIRQ,
+			     chip->vendor.miscdev.name, chip) != 0) {
+				dev_info(chip->dev,
+					 "Unable to request irq: %d for probe\n",
+					 i);
+				continue;
+			}
+
+			/* Clear all existing */
+			iowrite32(ioread32
+				  (chip->vendor.iobase +
+				   TPM_INT_STATUS(chip->vendor.locality)),
+				  chip->vendor.iobase +
+				  TPM_INT_STATUS(chip->vendor.locality));
+
+			/* Turn on */
+			iowrite32(intmask | TPM_GLOBAL_INT_ENABLE,
+				  chip->vendor.iobase +
+				  TPM_INT_ENABLE(chip->vendor.locality));
+
+			/* Generate Interrupts */
+			tpm_gen_interrupt(chip);
+
+			/* Turn off */
+			iowrite32(intmask,
+				  chip->vendor.iobase +
+				  TPM_INT_ENABLE(chip->vendor.locality));
+			free_irq(i, chip);
+		}
+	}
+	if (chip->vendor.irq) {
+		iowrite8(chip->vendor.irq,
+			 chip->vendor.iobase +
+			 TPM_INT_VECTOR(chip->vendor.locality));
+		if (request_irq
+		    (chip->vendor.irq, tis_int_handler, SA_SHIRQ,
+		     chip->vendor.miscdev.name, chip) != 0) {
+			dev_info(chip->dev,
+				 "Unable to request irq: %d for use\n",
+				 chip->vendor.irq);
+			chip->vendor.irq = 0;
+		} else {
+			/* Clear all existing */
+			iowrite32(ioread32
+				  (chip->vendor.iobase +
+				   TPM_INT_STATUS(chip->vendor.locality)),
+				  chip->vendor.iobase +
+				  TPM_INT_STATUS(chip->vendor.locality));
+
+			/* Turn on */
+			iowrite32(intmask | TPM_GLOBAL_INT_ENABLE,
+				  chip->vendor.iobase +
+				  TPM_INT_ENABLE(chip->vendor.locality));
+		}
+	}
+
+	INIT_LIST_HEAD(&chip->vendor.list);
+	spin_lock(&tis_lock);
+	list_add(&chip->vendor.list, &tis_chips);
+	spin_unlock(&tis_lock);
+
+	tpm_get_timeouts(chip);
+	tpm_continue_selftest(chip);
+
+	return 0;
+out_err:
+	if (chip->vendor.iobase)
+		iounmap(chip->vendor.iobase);
+	tpm_remove_hardware(chip->dev);
+	return rc;
+}
+
+static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg)
+{
+	return tpm_pm_suspend(&dev->dev, msg);
+}
+
+static int tpm_tis_pnp_resume(struct pnp_dev *dev)
+{
+	return tpm_pm_resume(&dev->dev);
+}
+
+static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
+	{"PNP0C31", 0},		/* TPM */
+	{"ATM1200", 0},		/* Atmel */
+	{"IFX0102", 0},		/* Infineon */
+	{"BCM0101", 0},		/* Broadcom */
+	{"NSC1200", 0},		/* National */
+	/* Add new here */
+	{"", 0},		/* User Specified */
+	{"", 0}			/* Terminator */
+};
+
+static struct pnp_driver tis_pnp_driver = {
+	.name = "tpm_tis",
+	.id_table = tpm_pnp_tbl,
+	.probe = tpm_tis_pnp_init,
+	.suspend = tpm_tis_pnp_suspend,
+	.resume = tpm_tis_pnp_resume,
+};
+
+#define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2
+module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id,
+		    sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444);
+MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");
+
+static int __init init_tis(void)
+{
+	return pnp_register_driver(&tis_pnp_driver);
+}
+
+static void __exit cleanup_tis(void)
+{
+	struct tpm_vendor_specific *i, *j;
+	struct tpm_chip *chip;
+	spin_lock(&tis_lock);
+	list_for_each_entry_safe(i, j, &tis_chips, list) {
+		chip = to_tpm_chip(i);
+		iowrite32(~TPM_GLOBAL_INT_ENABLE &
+			  ioread32(chip->vendor.iobase +
+				   TPM_INT_ENABLE(chip->vendor.
+						  locality)),
+			  chip->vendor.iobase +
+			  TPM_INT_ENABLE(chip->vendor.locality));
+		release_locality(chip, chip->vendor.locality, 1);
+		if (chip->vendor.irq)
+			free_irq(chip->vendor.irq, chip);
+		iounmap(i->iobase);
+		list_del(&i->list);
+		tpm_remove_hardware(chip->dev);
+	}
+	spin_unlock(&tis_lock);
+	pnp_unregister_driver(&tis_pnp_driver);
+}
+
+module_init(init_tis);
+module_exit(cleanup_tis);
+MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
+MODULE_DESCRIPTION("TPM Driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 841f0bd..f07637a 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -2723,7 +2723,11 @@
 		}
 		task_lock(p);
 		if (p->files) {
-			rcu_read_lock();
+			/*
+			 * We don't take a ref to the file, so we must
+			 * hold ->file_lock instead.
+			 */
+			spin_lock(&p->files->file_lock);
 			fdt = files_fdtable(p->files);
 			for (i=0; i < fdt->max_fds; i++) {
 				filp = fcheck_files(p->files, i);
@@ -2738,7 +2742,7 @@
 					break;
 				}
 			}
-			rcu_read_unlock();
+			spin_unlock(&p->files->file_lock);
 		}
 		task_unlock(p);
 	} while_each_thread(g, p);
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 8e0f315..dfca749 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -478,6 +478,11 @@
 		ret = i801_transaction();
 	}
 
+	/* Some BIOSes don't like it when PEC is enabled at reboot or resume
+	   time, so we forcibly disable it after every transaction. */
+	if (hwpec)
+		outb_p(0, SMBAUXCTL);
+
 	if(block)
 		return ret;
 	if(ret)
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
index 27fc9ff..99ab4ec 100644
--- a/drivers/i2c/chips/m41t00.c
+++ b/drivers/i2c/chips/m41t00.c
@@ -131,13 +131,13 @@
 	if ((i2c_smbus_write_byte_data(save_client, 0, tm.tm_sec & 0x7f) < 0)
 		|| (i2c_smbus_write_byte_data(save_client, 1, tm.tm_min & 0x7f)
 			< 0)
-		|| (i2c_smbus_write_byte_data(save_client, 2, tm.tm_hour & 0x7f)
+		|| (i2c_smbus_write_byte_data(save_client, 2, tm.tm_hour & 0x3f)
 			< 0)
-		|| (i2c_smbus_write_byte_data(save_client, 4, tm.tm_mday & 0x7f)
+		|| (i2c_smbus_write_byte_data(save_client, 4, tm.tm_mday & 0x3f)
 			< 0)
-		|| (i2c_smbus_write_byte_data(save_client, 5, tm.tm_mon & 0x7f)
+		|| (i2c_smbus_write_byte_data(save_client, 5, tm.tm_mon & 0x1f)
 			< 0)
-		|| (i2c_smbus_write_byte_data(save_client, 6, tm.tm_year & 0x7f)
+		|| (i2c_smbus_write_byte_data(save_client, 6, tm.tm_year & 0xff)
 			< 0))
 
 		dev_warn(&save_client->dev,"m41t00: can't write to rtc chip\n");
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index cf84350..8b24b4f 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -731,6 +731,8 @@
 	
 	if(m5229_revision <= 0x20)
 		tmpbyte = (tmpbyte & (~0x02)) | 0x01;
+	else if (m5229_revision == 0xc7)
+		tmpbyte |= 0x03;
 	else
 		tmpbyte |= 0x01;
 
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
index df9ee9a..900efd1 100644
--- a/drivers/ide/pci/atiixp.c
+++ b/drivers/ide/pci/atiixp.c
@@ -348,6 +348,7 @@
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index 6f8f864..7ce5bf7 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -798,7 +798,6 @@
 		.autodma	= AUTODMA,
 		.bootable	= OFF_BOARD,
 		.extra		= 48,
-		.flags		= IDEPCI_FLAG_FORCE_PDC,
 	},{	/* 2 */
 		.name		= "PDC20263",
 		.init_setup	= init_setup_pdc202ata4,
@@ -819,7 +818,6 @@
 		.autodma	= AUTODMA,
 		.bootable	= OFF_BOARD,
 		.extra		= 48,
-		.flags		= IDEPCI_FLAG_FORCE_PDC,
 	},{	/* 4 */
 		.name		= "PDC20267",
 		.init_setup	= init_setup_pdc202xx,
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 7ebf992..462ed30 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -580,7 +580,6 @@
 	int port;
 	int at_least_one_hwif_enabled = 0;
 	ide_hwif_t *hwif, *mate = NULL;
-	static int secondpdc = 0;
 	u8 tmp;
 
 	index->all = 0xf0f0;
@@ -592,21 +591,9 @@
 	for (port = 0; port <= 1; ++port) {
 		ide_pci_enablebit_t *e = &(d->enablebits[port]);
 	
-		/* 
-		 * If this is a Promise FakeRaid controller,
-		 * the 2nd controller will be marked as 
-		 * disabled while it is actually there and enabled
-		 * by the bios for raid purposes. 
-		 * Skip the normal "is it enabled" test for those.
-		 */
-		if ((d->flags & IDEPCI_FLAG_FORCE_PDC) &&
-		    (secondpdc++==1) && (port==1))
-			goto controller_ok;
-			
 		if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) ||
 		    (tmp & e->mask) != e->val))
 			continue;	/* port not enabled */
-controller_ok:
 
 		if (d->channels	<= port)
 			break;
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 3a702da..469b692 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -228,10 +228,7 @@
 				goto error1;
 		}
 		/* Make sure class supplied is consistent with RMPP */
-		if (ib_is_mad_class_rmpp(mad_reg_req->mgmt_class)) {
-			if (!rmpp_version)
-				goto error1;
-		} else {
+		if (!ib_is_mad_class_rmpp(mad_reg_req->mgmt_class)) {
 			if (rmpp_version)
 				goto error1;
 		}
diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c
index cd533cf..7d3fb69 100644
--- a/drivers/infiniband/hw/ipath/ipath_diag.c
+++ b/drivers/infiniband/hw/ipath/ipath_diag.c
@@ -365,15 +365,3 @@
 bail:
 	return ret;
 }
-
-void ipath_diag_bringup_link(struct ipath_devdata *dd)
-{
-	if (diag_set_link || (dd->ipath_flags & IPATH_LINKACTIVE))
-		return;
-
-	diag_set_link = 1;
-	ipath_cdbg(VERBOSE, "Trying to set to set link active for "
-		   "diag pkt\n");
-	ipath_layer_set_linkstate(dd, IPATH_IB_LINKARM);
-	ipath_layer_set_linkstate(dd, IPATH_IB_LINKACTIVE);
-}
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
index 58a94ef..e7617c3 100644
--- a/drivers/infiniband/hw/ipath/ipath_driver.c
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -1729,7 +1729,7 @@
 	}
 }
 
-int __init infinipath_init(void)
+static int __init infinipath_init(void)
 {
 	int ret;
 
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c
index 60f5f41..0bcb428 100644
--- a/drivers/infiniband/hw/ipath/ipath_intr.c
+++ b/drivers/infiniband/hw/ipath/ipath_intr.c
@@ -172,8 +172,8 @@
 				   "was %s\n", dd->ipath_unit,
 				   ib_linkstate(lstate),
 				   ib_linkstate((unsigned)
-				   		dd->ipath_lastibcstat
-				   		& IPATH_IBSTATE_MASK));
+						dd->ipath_lastibcstat
+						& IPATH_IBSTATE_MASK));
 	}
 	else {
 		lstate = dd->ipath_lastibcstat & IPATH_IBSTATE_MASK;
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
index 159d0ae..0ce5f19 100644
--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -528,7 +528,6 @@
 extern struct ipath_devdata *ipath_lookup(int unit);
 
 extern u16 ipath_layer_rcv_opcode;
-extern int ipath_verbs_registered;
 extern int __ipath_layer_intr(struct ipath_devdata *, u32);
 extern int ipath_layer_intr(struct ipath_devdata *, u32);
 extern int __ipath_layer_rcv(struct ipath_devdata *, void *,
diff --git a/drivers/infiniband/hw/ipath/ipath_layer.c b/drivers/infiniband/hw/ipath/ipath_layer.c
index 2cabf63..69ed110 100644
--- a/drivers/infiniband/hw/ipath/ipath_layer.c
+++ b/drivers/infiniband/hw/ipath/ipath_layer.c
@@ -52,7 +52,7 @@
 static int (*layer_rcv_lid)(void *, void *);
 static int (*verbs_piobufavail)(void *);
 static void (*verbs_rcv)(void *, void *, void *, u32);
-int ipath_verbs_registered;
+static int ipath_verbs_registered;
 
 static void *(*layer_add_one)(int, struct ipath_devdata *);
 static void (*layer_remove_one)(void *);
diff --git a/drivers/infiniband/hw/ipath/ipath_pe800.c b/drivers/infiniband/hw/ipath/ipath_pe800.c
index e693a7a..e1dc4f7 100644
--- a/drivers/infiniband/hw/ipath/ipath_pe800.c
+++ b/drivers/infiniband/hw/ipath/ipath_pe800.c
@@ -305,8 +305,8 @@
  * we'll print them and continue.  We reuse the same message buffer as
  * ipath_handle_errors() to avoid excessive stack usage.
  */
-void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
-	size_t msgl)
+static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
+				     size_t msgl)
 {
 	ipath_err_t hwerrs;
 	u32 bits, ctrl;
@@ -552,7 +552,7 @@
  * freeze mode), and enable hardware errors as errors (along with
  * everything else) in errormask
  */
-void ipath_pe_init_hwerrors(struct ipath_devdata *dd)
+static void ipath_pe_init_hwerrors(struct ipath_devdata *dd)
 {
 	ipath_err_t val;
 	u64 extsval;
@@ -577,7 +577,7 @@
  * ipath_pe_bringup_serdes - bring up the serdes
  * @dd: the infinipath device
  */
-int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
+static int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
 {
 	u64 val, tmp, config1;
 	int ret = 0, change = 0;
@@ -694,7 +694,7 @@
  * @dd: the infinipath device
  * Called when driver is being unloaded
  */
-void ipath_pe_quiet_serdes(struct ipath_devdata *dd)
+static void ipath_pe_quiet_serdes(struct ipath_devdata *dd)
 {
 	u64 val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
 
diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c
index 6058d70..1889071 100644
--- a/drivers/infiniband/hw/ipath/ipath_qp.c
+++ b/drivers/infiniband/hw/ipath/ipath_qp.c
@@ -188,8 +188,8 @@
  * Allocate the next available QPN and put the QP into the hash table.
  * The hash table holds a reference to the QP.
  */
-int ipath_alloc_qpn(struct ipath_qp_table *qpt, struct ipath_qp *qp,
-		    enum ib_qp_type type)
+static int ipath_alloc_qpn(struct ipath_qp_table *qpt, struct ipath_qp *qp,
+			   enum ib_qp_type type)
 {
 	unsigned long flags;
 	u32 qpn;
@@ -232,7 +232,7 @@
  * Remove the QP from the table so it can't be found asynchronously by
  * the receive interrupt routine.
  */
-void ipath_free_qp(struct ipath_qp_table *qpt, struct ipath_qp *qp)
+static void ipath_free_qp(struct ipath_qp_table *qpt, struct ipath_qp *qp)
 {
 	struct ipath_qp *q, **qpp;
 	unsigned long flags;
@@ -358,6 +358,65 @@
 }
 
 /**
+ * ipath_error_qp - put a QP into an error state
+ * @qp: the QP to put into an error state
+ *
+ * Flushes both send and receive work queues.
+ * QP r_rq.lock and s_lock should be held.
+ */
+
+static void ipath_error_qp(struct ipath_qp *qp)
+{
+	struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+	struct ib_wc wc;
+
+	_VERBS_INFO("QP%d/%d in error state\n",
+		    qp->ibqp.qp_num, qp->remote_qpn);
+
+	spin_lock(&dev->pending_lock);
+	/* XXX What if its already removed by the timeout code? */
+	if (qp->timerwait.next != LIST_POISON1)
+		list_del(&qp->timerwait);
+	if (qp->piowait.next != LIST_POISON1)
+		list_del(&qp->piowait);
+	spin_unlock(&dev->pending_lock);
+
+	wc.status = IB_WC_WR_FLUSH_ERR;
+	wc.vendor_err = 0;
+	wc.byte_len = 0;
+	wc.imm_data = 0;
+	wc.qp_num = qp->ibqp.qp_num;
+	wc.src_qp = 0;
+	wc.wc_flags = 0;
+	wc.pkey_index = 0;
+	wc.slid = 0;
+	wc.sl = 0;
+	wc.dlid_path_bits = 0;
+	wc.port_num = 0;
+
+	while (qp->s_last != qp->s_head) {
+		struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last);
+
+		wc.wr_id = wqe->wr.wr_id;
+		wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+		if (++qp->s_last >= qp->s_size)
+			qp->s_last = 0;
+		ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 1);
+	}
+	qp->s_cur = qp->s_tail = qp->s_head;
+	qp->s_hdrwords = 0;
+	qp->s_ack_state = IB_OPCODE_RC_ACKNOWLEDGE;
+
+	wc.opcode = IB_WC_RECV;
+	while (qp->r_rq.tail != qp->r_rq.head) {
+		wc.wr_id = get_rwqe_ptr(&qp->r_rq, qp->r_rq.tail)->wr_id;
+		if (++qp->r_rq.tail >= qp->r_rq.size)
+			qp->r_rq.tail = 0;
+		ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1);
+	}
+}
+
+/**
  * ipath_modify_qp - modify the attributes of a queue pair
  * @ibqp: the queue pair who's attributes we're modifying
  * @attr: the new attributes
@@ -821,65 +880,6 @@
 }
 
 /**
- * ipath_error_qp - put a QP into an error state
- * @qp: the QP to put into an error state
- *
- * Flushes both send and receive work queues.
- * QP r_rq.lock and s_lock should be held.
- */
-
-void ipath_error_qp(struct ipath_qp *qp)
-{
-	struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
-	struct ib_wc wc;
-
-	_VERBS_INFO("QP%d/%d in error state\n",
-		    qp->ibqp.qp_num, qp->remote_qpn);
-
-	spin_lock(&dev->pending_lock);
-	/* XXX What if its already removed by the timeout code? */
-	if (qp->timerwait.next != LIST_POISON1)
-		list_del(&qp->timerwait);
-	if (qp->piowait.next != LIST_POISON1)
-		list_del(&qp->piowait);
-	spin_unlock(&dev->pending_lock);
-
-	wc.status = IB_WC_WR_FLUSH_ERR;
-	wc.vendor_err = 0;
-	wc.byte_len = 0;
-	wc.imm_data = 0;
-	wc.qp_num = qp->ibqp.qp_num;
-	wc.src_qp = 0;
-	wc.wc_flags = 0;
-	wc.pkey_index = 0;
-	wc.slid = 0;
-	wc.sl = 0;
-	wc.dlid_path_bits = 0;
-	wc.port_num = 0;
-
-	while (qp->s_last != qp->s_head) {
-		struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last);
-
-		wc.wr_id = wqe->wr.wr_id;
-		wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
-		if (++qp->s_last >= qp->s_size)
-			qp->s_last = 0;
-		ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 1);
-	}
-	qp->s_cur = qp->s_tail = qp->s_head;
-	qp->s_hdrwords = 0;
-	qp->s_ack_state = IB_OPCODE_RC_ACKNOWLEDGE;
-
-	wc.opcode = IB_WC_RECV;
-	while (qp->r_rq.tail != qp->r_rq.head) {
-		wc.wr_id = get_rwqe_ptr(&qp->r_rq, qp->r_rq.tail)->wr_id;
-		if (++qp->r_rq.tail >= qp->r_rq.size)
-			qp->r_rq.tail = 0;
-		ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1);
-	}
-}
-
-/**
  * ipath_get_credit - flush the send work queue of a QP
  * @qp: the qp who's send work queue to flush
  * @aeth: the Acknowledge Extended Transport Header
diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c
index 5ff3de6..01cfb30 100644
--- a/drivers/infiniband/hw/ipath/ipath_ud.c
+++ b/drivers/infiniband/hw/ipath/ipath_ud.c
@@ -46,8 +46,8 @@
  * This is called from ipath_post_ud_send() to forward a WQE addressed
  * to the same HCA.
  */
-void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_sge_state *ss,
-		       u32 length, struct ib_send_wr *wr, struct ib_wc *wc)
+static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_sge_state *ss,
+			      u32 length, struct ib_send_wr *wr, struct ib_wc *wc)
 {
 	struct ipath_ibdev *dev = to_idev(sqp->ibqp.device);
 	struct ipath_qp *qp;
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c
index 9f27fd3..8d2558a 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.c
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
@@ -41,7 +41,7 @@
 /* Not static, because we don't want the compiler removing it */
 const char ipath_verbs_version[] = "ipath_verbs " IPATH_IDSTR;
 
-unsigned int ib_ipath_qp_table_size = 251;
+static unsigned int ib_ipath_qp_table_size = 251;
 module_param_named(qp_table_size, ib_ipath_qp_table_size, uint, S_IRUGO);
 MODULE_PARM_DESC(qp_table_size, "QP table size");
 
@@ -87,7 +87,7 @@
 /*
  * System image GUID.
  */
-__be64 sys_image_guid;
+static __be64 sys_image_guid;
 
 /**
  * ipath_copy_sge - copy data to SGE memory
@@ -1110,7 +1110,7 @@
 	ib_dealloc_device(ibdev);
 }
 
-int __init ipath_verbs_init(void)
+static int __init ipath_verbs_init(void)
 {
 	return ipath_verbs_register(ipath_register_ib_device,
 				    ipath_unregister_ib_device,
@@ -1118,33 +1118,33 @@
 				    ipath_ib_timer);
 }
 
-void __exit ipath_verbs_cleanup(void)
+static void __exit ipath_verbs_cleanup(void)
 {
 	ipath_verbs_unregister();
 }
 
 static ssize_t show_rev(struct class_device *cdev, char *buf)
 {
-        struct ipath_ibdev *dev =
-                container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
-        int vendor, boardrev, majrev, minrev;
+	struct ipath_ibdev *dev =
+		container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
+	int vendor, boardrev, majrev, minrev;
 
-        ipath_layer_query_device(dev->dd, &vendor, &boardrev,
-                                 &majrev, &minrev);
-        return sprintf(buf, "%d.%d\n", majrev, minrev);
+	ipath_layer_query_device(dev->dd, &vendor, &boardrev,
+				 &majrev, &minrev);
+	return sprintf(buf, "%d.%d\n", majrev, minrev);
 }
 
 static ssize_t show_hca(struct class_device *cdev, char *buf)
 {
-        struct ipath_ibdev *dev =
-                container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
-        int ret;
+	struct ipath_ibdev *dev =
+		container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
+	int ret;
 
-        ret = ipath_layer_get_boardname(dev->dd, buf, 128);
-        if (ret < 0)
-                goto bail;
-        strcat(buf, "\n");
-        ret = strlen(buf);
+	ret = ipath_layer_get_boardname(dev->dd, buf, 128);
+	if (ret < 0)
+		goto bail;
+	strcat(buf, "\n");
+	ret = strlen(buf);
 
 bail:
 	return ret;
@@ -1152,40 +1152,40 @@
 
 static ssize_t show_stats(struct class_device *cdev, char *buf)
 {
-        struct ipath_ibdev *dev =
-                container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
-        int i;
-        int len;
+	struct ipath_ibdev *dev =
+		container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
+	int i;
+	int len;
 
-        len = sprintf(buf,
-                      "RC resends  %d\n"
-                      "RC QACKs    %d\n"
-                      "RC ACKs     %d\n"
-                      "RC SEQ NAKs %d\n"
-                      "RC RDMA seq %d\n"
-                      "RC RNR NAKs %d\n"
-                      "RC OTH NAKs %d\n"
-                      "RC timeouts %d\n"
-                      "RC RDMA dup %d\n"
-                      "piobuf wait %d\n"
-                      "no piobuf   %d\n"
-                      "PKT drops   %d\n"
-                      "WQE errs    %d\n",
-                      dev->n_rc_resends, dev->n_rc_qacks, dev->n_rc_acks,
-                      dev->n_seq_naks, dev->n_rdma_seq, dev->n_rnr_naks,
-                      dev->n_other_naks, dev->n_timeouts,
-                      dev->n_rdma_dup_busy, dev->n_piowait,
-                      dev->n_no_piobuf, dev->n_pkt_drops, dev->n_wqe_errs);
-        for (i = 0; i < ARRAY_SIZE(dev->opstats); i++) {
+	len = sprintf(buf,
+		      "RC resends  %d\n"
+		      "RC QACKs    %d\n"
+		      "RC ACKs     %d\n"
+		      "RC SEQ NAKs %d\n"
+		      "RC RDMA seq %d\n"
+		      "RC RNR NAKs %d\n"
+		      "RC OTH NAKs %d\n"
+		      "RC timeouts %d\n"
+		      "RC RDMA dup %d\n"
+		      "piobuf wait %d\n"
+		      "no piobuf   %d\n"
+		      "PKT drops   %d\n"
+		      "WQE errs    %d\n",
+		      dev->n_rc_resends, dev->n_rc_qacks, dev->n_rc_acks,
+		      dev->n_seq_naks, dev->n_rdma_seq, dev->n_rnr_naks,
+		      dev->n_other_naks, dev->n_timeouts,
+		      dev->n_rdma_dup_busy, dev->n_piowait,
+		      dev->n_no_piobuf, dev->n_pkt_drops, dev->n_wqe_errs);
+	for (i = 0; i < ARRAY_SIZE(dev->opstats); i++) {
 		const struct ipath_opcode_stats *si = &dev->opstats[i];
 
-                if (!si->n_packets && !si->n_bytes)
-                        continue;
-                len += sprintf(buf + len, "%02x %llu/%llu\n", i,
+		if (!si->n_packets && !si->n_bytes)
+			continue;
+		len += sprintf(buf + len, "%02x %llu/%llu\n", i,
 			       (unsigned long long) si->n_packets,
-                               (unsigned long long) si->n_bytes);
-        }
-        return len;
+			       (unsigned long long) si->n_bytes);
+	}
+	return len;
 }
 
 static CLASS_DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
@@ -1194,25 +1194,25 @@
 static CLASS_DEVICE_ATTR(stats, S_IRUGO, show_stats, NULL);
 
 static struct class_device_attribute *ipath_class_attributes[] = {
-        &class_device_attr_hw_rev,
-        &class_device_attr_hca_type,
-        &class_device_attr_board_id,
-        &class_device_attr_stats
+	&class_device_attr_hw_rev,
+	&class_device_attr_hca_type,
+	&class_device_attr_board_id,
+	&class_device_attr_stats
 };
 
 static int ipath_verbs_register_sysfs(struct ib_device *dev)
 {
-        int i;
+	int i;
 	int ret;
 
-        for (i = 0; i < ARRAY_SIZE(ipath_class_attributes); ++i)
-                if (class_device_create_file(&dev->class_dev,
-                                             ipath_class_attributes[i])) {
-                        ret = 1;
+	for (i = 0; i < ARRAY_SIZE(ipath_class_attributes); ++i)
+		if (class_device_create_file(&dev->class_dev,
+					     ipath_class_attributes[i])) {
+			ret = 1;
 			goto bail;
 		}
 
-        ret = 0;
+	ret = 0;
 
 bail:
 	return ret;
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h
index b824632..fcafbc7 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.h
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.h
@@ -577,8 +577,6 @@
 
 void ipath_sqerror_qp(struct ipath_qp *qp, struct ib_wc *wc);
 
-void ipath_error_qp(struct ipath_qp *qp);
-
 void ipath_get_credit(struct ipath_qp *qp, u32 aeth);
 
 void ipath_do_rc_send(unsigned long data);
@@ -607,9 +605,6 @@
 
 void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc);
 
-void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_sge_state *ss,
-		       u32 length, struct ib_send_wr *wr, struct ib_wc *wc);
-
 int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr);
 
 void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c
index f235c7ea..4730863 100644
--- a/drivers/infiniband/hw/mthca/mthca_mad.c
+++ b/drivers/infiniband/hw/mthca/mthca_mad.c
@@ -49,7 +49,7 @@
 	MTHCA_VENDOR_CLASS2 = 0xa
 };
 
-int mthca_update_rate(struct mthca_dev *dev, u8 port_num)
+static int mthca_update_rate(struct mthca_dev *dev, u8 port_num)
 {
 	struct ib_port_attr *tprops = NULL;
 	int                  ret;
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 5f2b3f6..5bb5574 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -617,6 +617,14 @@
 		     scmnd->sc_data_direction);
 }
 
+static void srp_remove_req(struct srp_target_port *target, struct srp_request *req,
+			   int index)
+{
+	list_del(&req->list);
+	req->next = target->req_head;
+	target->req_head = index;
+}
+
 static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
 {
 	struct srp_request *req;
@@ -664,9 +672,7 @@
 			scmnd->host_scribble = (void *) -1L;
 			scmnd->scsi_done(scmnd);
 
-			list_del(&req->list);
-			req->next = target->req_head;
-			target->req_head = rsp->tag & ~SRP_TAG_TSK_MGMT;
+			srp_remove_req(target, req, rsp->tag & ~SRP_TAG_TSK_MGMT);
 		} else
 			req->cmd_done = 1;
 	}
@@ -1188,12 +1194,10 @@
 	spin_lock_irq(target->scsi_host->host_lock);
 
 	if (req->cmd_done) {
-		list_del(&req->list);
-		req->next = target->req_head;
-		target->req_head = req_index;
-
+		srp_remove_req(target, req, req_index);
 		scmnd->scsi_done(scmnd);
 	} else if (!req->tsk_status) {
+		srp_remove_req(target, req, req_index);
 		scmnd->result = DID_ABORT << 16;
 		ret = SUCCESS;
 	}
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index f86ed6a..eb41aba 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -5,8 +5,6 @@
  *                       Tilman Schmidt <tilman@imap.cc>,
  *                       Stefan Eilers.
  *
- * Based on usb-gigaset.c.
- *
  * =====================================================================
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License as
@@ -46,19 +44,20 @@
 #define GIGASET_DEVFSNAME  "gig/bas/"
 #define GIGASET_DEVNAME    "ttyGB"
 
-#define IF_WRITEBUF 256 //FIXME
+/* length limit according to Siemens 3070usb-protokoll.doc ch. 2.1 */
+#define IF_WRITEBUF 264
 
 /* Values for the Gigaset 307x */
 #define USB_GIGA_VENDOR_ID      0x0681
-#define USB_GIGA_PRODUCT_ID     0x0001
-#define USB_4175_PRODUCT_ID     0x0002
+#define USB_3070_PRODUCT_ID     0x0001
+#define USB_3075_PRODUCT_ID     0x0002
 #define USB_SX303_PRODUCT_ID    0x0021
 #define USB_SX353_PRODUCT_ID    0x0022
 
 /* table of devices that work with this driver */
 static struct usb_device_id gigaset_table [] = {
-	{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_GIGA_PRODUCT_ID) },
-	{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_4175_PRODUCT_ID) },
+	{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3070_PRODUCT_ID) },
+	{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3075_PRODUCT_ID) },
 	{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX303_PRODUCT_ID) },
 	{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX353_PRODUCT_ID) },
 	{ } /* Terminating entry */
@@ -77,6 +76,10 @@
 /* Function will be called if the device is unplugged */
 static void gigaset_disconnect(struct usb_interface *interface);
 
+static void read_ctrl_callback(struct urb *, struct pt_regs *);
+static void stopurbs(struct bas_bc_state *);
+static int atwrite_submit(struct cardstate *, unsigned char *, int);
+static int start_cbsend(struct cardstate *);
 
 /*==============================================================================*/
 
@@ -111,12 +114,14 @@
 };
 
 /* status of direct USB connection to 307x base (bits in basstate) */
-#define BS_ATOPEN	0x001
-#define BS_B1OPEN	0x002
-#define BS_B2OPEN	0x004
-#define BS_ATREADY	0x008
-#define BS_INIT		0x010
-#define BS_ATTIMER	0x020
+#define BS_ATOPEN	0x001	/* AT channel open */
+#define BS_B1OPEN	0x002	/* B channel 1 open */
+#define BS_B2OPEN	0x004	/* B channel 2 open */
+#define BS_ATREADY	0x008	/* base ready for AT command */
+#define BS_INIT		0x010	/* base has signalled INIT_OK */
+#define BS_ATTIMER	0x020	/* waiting for HD_READY_SEND_ATDATA */
+#define BS_ATRDPEND	0x040	/* urb_cmd_in in use */
+#define BS_ATWRPEND	0x080	/* urb_cmd_out in use */
 
 
 static struct gigaset_driver *driver = NULL;
@@ -130,6 +135,47 @@
 	.id_table =     gigaset_table,
 };
 
+/* get message text for usb_submit_urb return code
+ */
+static char *get_usb_rcmsg(int rc)
+{
+	static char unkmsg[28];
+
+	switch (rc) {
+	case 0:
+		return "success";
+	case -ENOMEM:
+		return "out of memory";
+	case -ENODEV:
+		return "device not present";
+	case -ENOENT:
+		return "endpoint not present";
+	case -ENXIO:
+		return "URB type not supported";
+	case -EINVAL:
+		return "invalid argument";
+	case -EAGAIN:
+		return "start frame too early or too much scheduled";
+	case -EFBIG:
+		return "too many isochronous frames requested";
+	case -EPIPE:
+		return "endpoint stalled";
+	case -EMSGSIZE:
+		return "invalid packet size";
+	case -ENOSPC:
+		return "would overcommit USB bandwidth";
+	case -ESHUTDOWN:
+		return "device shut down";
+	case -EPERM:
+		return "reject flag set";
+	case -EHOSTUNREACH:
+		return "device suspended";
+	default:
+		snprintf(unkmsg, sizeof(unkmsg), "unknown error %d", rc);
+		return unkmsg;
+	}
+}
+
 /* get message text for USB status code
  */
 static char *get_usb_statmsg(int status)
@@ -140,43 +186,37 @@
 	case 0:
 		return "success";
 	case -ENOENT:
-		return "canceled";
-	case -ECONNRESET:
-		return "canceled (async)";
+		return "unlinked (sync)";
 	case -EINPROGRESS:
 		return "pending";
 	case -EPROTO:
-		return "bit stuffing or unknown USB error";
+		return "bit stuffing error, timeout, or unknown USB error";
 	case -EILSEQ:
-		return "Illegal byte sequence (CRC mismatch)";
-	case -EPIPE:
-		return "babble detect or endpoint stalled";
-	case -ENOSR:
-		return "buffer error";
+		return "CRC mismatch, timeout, or unknown USB error";
 	case -ETIMEDOUT:
 		return "timed out";
-	case -ENODEV:
-		return "device not present";
+	case -EPIPE:
+		return "endpoint stalled";
+	case -ECOMM:
+		return "IN buffer overrun";
+	case -ENOSR:
+		return "OUT buffer underrun";
+	case -EOVERFLOW:
+		return "too much data";
 	case -EREMOTEIO:
 		return "short packet detected";
+	case -ENODEV:
+		return "device removed";
 	case -EXDEV:
 		return "partial isochronous transfer";
 	case -EINVAL:
 		return "invalid argument";
-	case -ENXIO:
-		return "URB already queued";
-	case -EAGAIN:
-		return "isochronous start frame too early or too much scheduled";
-	case -EFBIG:
-		return "too many isochronous frames requested";
-	case -EMSGSIZE:
-		return "endpoint message size zero";
+	case -ECONNRESET:
+		return "unlinked (async)";
 	case -ESHUTDOWN:
-		return "endpoint shutdown";
-	case -EBUSY:
-		return "another request pending";
+		return "device shut down";
 	default:
-		snprintf(unkmsg, sizeof(unkmsg), "unknown error %d", status);
+		snprintf(unkmsg, sizeof(unkmsg), "unknown status %d", status);
 		return unkmsg;
 	}
 }
@@ -277,18 +317,17 @@
 	gig_dbg(DEBUG_ANY, "%s: scheduling HUP for channel %d",
 		__func__, bcs->channel);
 
-	if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) {
-		//FIXME what should we do?
-		return;
-	}
+	if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL))
+		dev_err(cs->dev, "event queue full\n");
 
 	gigaset_schedule_event(cs);
 }
 
 /* error_reset
  * reset Gigaset device because of an unrecoverable error
- * This function may be called from any context and takes care of scheduling
- * the necessary actions for execution outside of interrupt context.
+ * This function may be called from any context, and should take care of
+ * scheduling the necessary actions for execution outside of interrupt context.
+ * Right now, it just generates a kernel message calling for help.
  * argument:
  *	controller state structure
  */
@@ -364,36 +403,38 @@
 {
 	struct cardstate *cs = (struct cardstate *) data;
 	struct bas_cardstate *ucs = cs->hw.bas;
-	unsigned long flags;
 
-	spin_lock_irqsave(&cs->lock, flags);
-	if (unlikely(!cs->connected)) {
-		gig_dbg(DEBUG_USBREQ, "%s: disconnected", __func__);
-		spin_unlock_irqrestore(&cs->lock, flags);
-		return;
-	}
 	if (!ucs->rcvbuf_size) {
 		gig_dbg(DEBUG_USBREQ, "%s: no receive in progress", __func__);
-		spin_unlock_irqrestore(&cs->lock, flags);
 		return;
 	}
-	spin_unlock_irqrestore(&cs->lock, flags);
 
 	dev_err(cs->dev, "timeout reading AT response\n");
 	error_reset(cs);	//FIXME retry?
 }
 
+/* set/clear bits in base connection state, return previous state
+ */
+inline static int update_basstate(struct bas_cardstate *ucs,
+				  int set, int clear)
+{
+	unsigned long flags;
+	int state;
 
-static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs);
+	spin_lock_irqsave(&ucs->lock, flags);
+	state = atomic_read(&ucs->basstate);
+	atomic_set(&ucs->basstate, (state & ~clear) | set);
+	spin_unlock_irqrestore(&ucs->lock, flags);
+	return state;
+}
 
 /* atread_submit
- * submit an HD_READ_ATMESSAGE command URB
+ * submit an HD_READ_ATMESSAGE command URB and optionally start a timeout
  * parameters:
  *	cs	controller state structure
  *	timeout	timeout in 1/10 sec., 0: none
  * return value:
  *	0 on success
- *	-EINVAL if a NULL pointer is encountered somewhere
  *	-EBUSY if another request is pending
  *	any URB submission error code
  */
@@ -405,7 +446,7 @@
 	gig_dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)",
 		ucs->rcvbuf_size);
 
-	if (ucs->urb_cmd_in->status == -EINPROGRESS) {
+	if (update_basstate(ucs, BS_ATRDPEND, 0) & BS_ATRDPEND) {
 		dev_err(cs->dev,
 			"could not submit HD_READ_ATMESSAGE: URB busy\n");
 		return -EBUSY;
@@ -423,6 +464,7 @@
 			     read_ctrl_callback, cs->inbuf);
 
 	if ((ret = usb_submit_urb(ucs->urb_cmd_in, SLAB_ATOMIC)) != 0) {
+		update_basstate(ucs, 0, BS_ATRDPEND);
 		dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n",
 			get_usb_statmsg(ret));
 		return ret;
@@ -438,26 +480,6 @@
 	return 0;
 }
 
-static void stopurbs(struct bas_bc_state *);
-static int start_cbsend(struct cardstate *);
-
-/* set/clear bits in base connection state
- */
-inline static void update_basstate(struct bas_cardstate *ucs,
-				   int set, int clear)
-{
-	unsigned long flags;
-	int state;
-
-	spin_lock_irqsave(&ucs->lock, flags);
-	state = atomic_read(&ucs->basstate);
-	state &= ~clear;
-	state |= set;
-	atomic_set(&ucs->basstate, state);
-	spin_unlock_irqrestore(&ucs->lock, flags);
-}
-
-
 /* read_int_callback
  * USB completion handler for interrupt pipe input
  * called by the USB subsystem in interrupt context
@@ -471,20 +493,25 @@
 	struct bas_cardstate *ucs = cs->hw.bas;
 	struct bc_state *bcs;
 	unsigned long flags;
-	int status;
+	int rc;
 	unsigned l;
 	int channel;
 
 	switch (urb->status) {
 	case 0:			/* success */
 		break;
-	case -ENOENT:			/* canceled */
-	case -ECONNRESET:		/* canceled (async) */
+	case -ENOENT:			/* cancelled */
+	case -ECONNRESET:		/* cancelled (async) */
 	case -EINPROGRESS:		/* pending */
 		/* ignore silently */
 		gig_dbg(DEBUG_USBREQ, "%s: %s",
 			__func__, get_usb_statmsg(urb->status));
 		return;
+	case -ENODEV:			/* device removed */
+	case -ESHUTDOWN:		/* device shut down */
+		//FIXME use this as disconnect indicator?
+		gig_dbg(DEBUG_USBREQ, "%s: device disconnected", __func__);
+		return;
 	default:		/* severe trouble */
 		dev_warn(cs->dev, "interrupt read: %s\n",
 			 get_usb_statmsg(urb->status));
@@ -492,6 +519,13 @@
 		goto resubmit;
 	}
 
+	/* drop incomplete packets even if the missing bytes wouldn't matter */
+	if (unlikely(urb->actual_length < 3)) {
+		dev_warn(cs->dev, "incomplete interrupt packet (%d bytes)\n",
+			 urb->actual_length);
+		goto resubmit;
+	}
+
 	l = (unsigned) ucs->int_in_buf[1] +
 	    (((unsigned) ucs->int_in_buf[2]) << 8);
 
@@ -558,25 +592,28 @@
 		}
 		spin_lock_irqsave(&cs->lock, flags);
 		if (ucs->rcvbuf_size) {
-			spin_unlock_irqrestore(&cs->lock, flags);
+			/* throw away previous buffer - we have no queue */
 			dev_err(cs->dev,
-				"receive AT data overrun, %d bytes lost\n", l);
-			error_reset(cs);	//FIXME reschedule
-			break;
+				"receive AT data overrun, %d bytes lost\n",
+				ucs->rcvbuf_size);
+			kfree(ucs->rcvbuf);
+			ucs->rcvbuf_size = 0;
 		}
 		if ((ucs->rcvbuf = kmalloc(l, GFP_ATOMIC)) == NULL) {
 			spin_unlock_irqrestore(&cs->lock, flags);
-			dev_err(cs->dev, "out of memory, %d bytes lost\n", l);
-			error_reset(cs);	//FIXME reschedule
+			dev_err(cs->dev, "out of memory receiving AT data\n");
+			error_reset(cs);
 			break;
 		}
 		ucs->rcvbuf_size = l;
 		ucs->retry_cmd_in = 0;
-		if ((status = atread_submit(cs, BAS_TIMEOUT)) < 0) {
+		if ((rc = atread_submit(cs, BAS_TIMEOUT)) < 0) {
 			kfree(ucs->rcvbuf);
 			ucs->rcvbuf = NULL;
 			ucs->rcvbuf_size = 0;
-			error_reset(cs);	//FIXME reschedule
+			if (rc != -ENODEV)
+				//FIXME corrective action?
+				error_reset(cs);
 		}
 		spin_unlock_irqrestore(&cs->lock, flags);
 		break;
@@ -598,12 +635,10 @@
 	check_pending(ucs);
 
 resubmit:
-	spin_lock_irqsave(&cs->lock, flags);
-	status = cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV;
-	spin_unlock_irqrestore(&cs->lock, flags);
-	if (unlikely(status)) {
+	rc = usb_submit_urb(urb, SLAB_ATOMIC);
+	if (unlikely(rc != 0 && rc != -ENODEV)) {
 		dev_err(cs->dev, "could not resubmit interrupt URB: %s\n",
-			get_usb_statmsg(status));
+			get_usb_rcmsg(rc));
 		error_reset(cs);
 	}
 }
@@ -622,18 +657,12 @@
 	struct bas_cardstate *ucs = cs->hw.bas;
 	int have_data = 0;
 	unsigned numbytes;
-	unsigned long flags;
+	int rc;
 
-	spin_lock_irqsave(&cs->lock, flags);
-	if (unlikely(!cs->connected)) {
-		warn("%s: disconnected", __func__);
-		spin_unlock_irqrestore(&cs->lock, flags);
-		return;
-	}
+	update_basstate(ucs, 0, BS_ATRDPEND);
 
 	if (!ucs->rcvbuf_size) {
 		dev_warn(cs->dev, "%s: no receive in progress\n", __func__);
-		spin_unlock_irqrestore(&cs->lock, flags);
 		return;
 	}
 
@@ -666,9 +695,11 @@
 		}
 		break;
 
-	case -ENOENT:			/* canceled */
-	case -ECONNRESET:		/* canceled (async) */
+	case -ENOENT:			/* cancelled */
+	case -ECONNRESET:		/* cancelled (async) */
 	case -EINPROGRESS:		/* pending */
+	case -ENODEV:			/* device removed */
+	case -ESHUTDOWN:		/* device shut down */
 		/* no action necessary */
 		gig_dbg(DEBUG_USBREQ, "%s: %s",
 			__func__, get_usb_statmsg(urb->status));
@@ -681,11 +712,11 @@
 		if (ucs->retry_cmd_in++ < BAS_RETRY) {
 			dev_notice(cs->dev, "control read: retry %d\n",
 				   ucs->retry_cmd_in);
-			if (atread_submit(cs, BAS_TIMEOUT) >= 0) {
-				/* resubmitted - bypass regular exit block */
-				spin_unlock_irqrestore(&cs->lock, flags);
+			rc = atread_submit(cs, BAS_TIMEOUT);
+			if (rc >= 0 || rc == -ENODEV)
+				/* resubmitted or disconnected */
+				/* - bypass regular exit block */
 				return;
-			}
 		} else {
 			dev_err(cs->dev,
 				"control read: giving up after %d tries\n",
@@ -697,7 +728,6 @@
 	kfree(ucs->rcvbuf);
 	ucs->rcvbuf = NULL;
 	ucs->rcvbuf_size = 0;
-	spin_unlock_irqrestore(&cs->lock, flags);
 	if (have_data) {
 		gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
 		gigaset_schedule_event(cs);
@@ -719,8 +749,11 @@
 	int i, rc;
 
 	/* status codes not worth bothering the tasklet with */
-	if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET ||
-		     urb->status == -EINPROGRESS)) {
+	if (unlikely(urb->status == -ENOENT ||
+		     urb->status == -ECONNRESET ||
+		     urb->status == -EINPROGRESS ||
+		     urb->status == -ENODEV ||
+		     urb->status == -ESHUTDOWN)) {
 		gig_dbg(DEBUG_ISO, "%s: %s",
 			__func__, get_usb_statmsg(urb->status));
 		return;
@@ -740,9 +773,9 @@
 		for (i = 0; i < BAS_NUMFRAMES; i++) {
 			ubc->isoinlost += urb->iso_frame_desc[i].actual_length;
 			if (unlikely(urb->iso_frame_desc[i].status != 0 &&
-				     urb->iso_frame_desc[i].status != -EINPROGRESS)) {
+				     urb->iso_frame_desc[i].status !=
+								-EINPROGRESS))
 				ubc->loststatus = urb->iso_frame_desc[i].status;
-			}
 			urb->iso_frame_desc[i].status = 0;
 			urb->iso_frame_desc[i].actual_length = 0;
 		}
@@ -754,10 +787,10 @@
 			gig_dbg(DEBUG_ISO, "%s: isoc read overrun/resubmit",
 				__func__);
 			rc = usb_submit_urb(urb, SLAB_ATOMIC);
-			if (unlikely(rc != 0)) {
+			if (unlikely(rc != 0 && rc != -ENODEV)) {
 				dev_err(bcs->cs->dev,
 					"could not resubmit isochronous read "
-					"URB: %s\n", get_usb_statmsg(rc));
+					"URB: %s\n", get_usb_rcmsg(rc));
 				dump_urb(DEBUG_ISO, "isoc read", urb);
 				error_hangup(bcs);
 			}
@@ -780,8 +813,11 @@
 	unsigned long flags;
 
 	/* status codes not worth bothering the tasklet with */
-	if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET ||
-		     urb->status == -EINPROGRESS)) {
+	if (unlikely(urb->status == -ENOENT ||
+		     urb->status == -ECONNRESET ||
+		     urb->status == -EINPROGRESS ||
+		     urb->status == -ENODEV ||
+		     urb->status == -ESHUTDOWN)) {
 		gig_dbg(DEBUG_ISO, "%s: %s",
 			__func__, get_usb_statmsg(urb->status));
 		return;
@@ -822,7 +858,6 @@
 	for (k = 0; k < BAS_INURBS; k++) {
 		urb = ubc->isoinurbs[k];
 		if (!urb) {
-			dev_err(bcs->cs->dev, "isoinurbs[%d]==NULL\n", k);
 			rc = -EFAULT;
 			goto error;
 		}
@@ -844,12 +879,8 @@
 		}
 
 		dump_urb(DEBUG_ISO, "Initial isoc read", urb);
-		if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) {
-			dev_err(bcs->cs->dev,
-			       "could not submit isochronous read URB %d: %s\n",
-				k, get_usb_statmsg(rc));
+		if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0)
 			goto error;
-		}
 	}
 
 	/* initialize L2 transmission */
@@ -859,7 +890,6 @@
 	for (k = 0; k < BAS_OUTURBS; ++k) {
 		urb = ubc->isoouturbs[k].urb;
 		if (!urb) {
-			dev_err(bcs->cs->dev, "isoouturbs[%d].urb==NULL\n", k);
 			rc = -EFAULT;
 			goto error;
 		}
@@ -885,12 +915,8 @@
 	for (k = 0; k < 2; ++k) {
 		dump_urb(DEBUG_ISO, "Initial isoc write", urb);
 		rc = usb_submit_urb(ubc->isoouturbs[k].urb, SLAB_ATOMIC);
-		if (rc != 0) {
-			dev_err(bcs->cs->dev,
-			      "could not submit isochronous write URB %d: %s\n",
-				k, get_usb_statmsg(rc));
+		if (rc != 0)
 			goto error;
-		}
 	}
 	dump_urb(DEBUG_ISO, "Initial isoc write (free)", urb);
 	ubc->isooutfree = &ubc->isoouturbs[2];
@@ -916,15 +942,15 @@
 	for (k = 0; k < BAS_INURBS; ++k) {
 		rc = usb_unlink_urb(ubc->isoinurbs[k]);
 		gig_dbg(DEBUG_ISO,
-			"%s: isoc input URB %d unlinked, result = %d",
-			__func__, k, rc);
+			"%s: isoc input URB %d unlinked, result = %s",
+			__func__, k, get_usb_rcmsg(rc));
 	}
 
 	for (k = 0; k < BAS_OUTURBS; ++k) {
 		rc = usb_unlink_urb(ubc->isoouturbs[k].urb);
 		gig_dbg(DEBUG_ISO,
-			"%s: isoc output URB %d unlinked, result = %d",
-			__func__, k, rc);
+			"%s: isoc output URB %d unlinked, result = %s",
+			__func__, k, get_usb_rcmsg(rc));
 	}
 }
 
@@ -934,7 +960,7 @@
 /* submit_iso_write_urb
  * fill and submit the next isochronous write URB
  * parameters:
- *	bcs	B channel state structure
+ *	ucx	context structure containing URB
  * return value:
  *	number of frames submitted in URB
  *	0 if URB not submitted because no data available (isooutbuf busy)
@@ -946,7 +972,6 @@
 	struct bas_bc_state *ubc = ucx->bcs->hw.bas;
 	struct usb_iso_packet_descriptor *ifd;
 	int corrbytes, nframe, rc;
-	unsigned long flags;
 
 	/* urb->dev is clobbered by USB subsystem */
 	urb->dev = ucx->bcs->cs->hw.bas->udev;
@@ -992,20 +1017,22 @@
 		ifd->status = 0;
 		ifd->actual_length = 0;
 	}
-	if ((urb->number_of_packets = nframe) > 0) {
-		spin_lock_irqsave(&ucx->bcs->cs->lock, flags);
-		rc = ucx->bcs->cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV;
-		spin_unlock_irqrestore(&ucx->bcs->cs->lock, flags);
+	if (unlikely(nframe == 0))
+		return 0;	/* no data to send */
+	urb->number_of_packets = nframe;
 
-		if (rc) {
+	rc = usb_submit_urb(urb, SLAB_ATOMIC);
+	if (unlikely(rc)) {
+		if (rc == -ENODEV)
+			/* device removed - give up silently */
+			gig_dbg(DEBUG_ISO, "%s: disconnected", __func__);
+		else
 			dev_err(ucx->bcs->cs->dev,
 				"could not submit isochronous write URB: %s\n",
-				get_usb_statmsg(rc));
-			dump_urb(DEBUG_ISO, "isoc write", urb);
-			return rc;
-		}
-		++ubc->numsub;
+				get_usb_rcmsg(rc));
+		return rc;
 	}
+	++ubc->numsub;
 	return nframe;
 }
 
@@ -1028,6 +1055,7 @@
 	int i;
 	struct sk_buff *skb;
 	int len;
+	int rc;
 
 	/* loop while completed URBs arrive in time */
 	for (;;) {
@@ -1057,7 +1085,8 @@
 		ubc->isooutfree = NULL;
 		spin_unlock_irqrestore(&ubc->isooutlock, flags);
 		if (next) {
-			if (submit_iso_write_urb(next) <= 0) {
+			rc = submit_iso_write_urb(next);
+			if (unlikely(rc <= 0 && rc != -ENODEV)) {
 				/* could not submit URB, put it back */
 				spin_lock_irqsave(&ubc->isooutlock, flags);
 				if (ubc->isooutfree == NULL) {
@@ -1077,17 +1106,18 @@
 		/* process completed URB */
 		urb = done->urb;
 		switch (urb->status) {
+		case -EXDEV:			/* partial completion */
+			gig_dbg(DEBUG_ISO, "%s: URB partially completed",
+				__func__);
+			/* fall through - what's the difference anyway? */
 		case 0:				/* normal completion */
-			break;
-		case -EXDEV:			/* inspect individual frames */
-			/* assumptions (for lack of documentation):
-			 * - actual_length bytes of the frame in error are
+			/* inspect individual frames
+			 * assumptions (for lack of documentation):
+			 * - actual_length bytes of first frame in error are
 			 *   successfully sent
 			 * - all following frames are not sent at all
 			 */
-			gig_dbg(DEBUG_ISO, "%s: URB partially completed",
-				__func__);
-			offset = done->limit;	/* just in case */
+			offset = done->limit;	/* default (no error) */
 			for (i = 0; i < BAS_NUMFRAMES; i++) {
 				ifd = &urb->iso_frame_desc[i];
 				if (ifd->status ||
@@ -1122,7 +1152,7 @@
 			}
 #endif
 			break;
-		case -EPIPE:		//FIXME is this the code for "underrun"?
+		case -EPIPE:			/* stall - probably underrun */
 			dev_err(cs->dev, "isochronous write stalled\n");
 			error_hangup(bcs);
 			break;
@@ -1142,7 +1172,8 @@
 		spin_unlock_irqrestore(&ubc->isooutlock, flags);
 		if (next) {
 			/* only one URB still active - resubmit one */
-			if (submit_iso_write_urb(next) <= 0) {
+			rc = submit_iso_write_urb(next);
+			if (unlikely(rc <= 0 && rc != -ENODEV)) {
 				/* couldn't submit */
 				error_hangup(bcs);
 			}
@@ -1222,10 +1253,9 @@
 			break;
 		case -ENOENT:
 		case -ECONNRESET:
-			gig_dbg(DEBUG_ISO, "%s: URB canceled", __func__);
-			continue;		/* -> skip */
-		case -EINPROGRESS:		/* huh? */
-			gig_dbg(DEBUG_ISO, "%s: URB still pending", __func__);
+		case -EINPROGRESS:
+			gig_dbg(DEBUG_ISO, "%s: %s",
+				__func__, get_usb_statmsg(urb->status));
 			continue;		/* -> skip */
 		case -EPIPE:
 			dev_err(cs->dev, "isochronous read stalled\n");
@@ -1290,13 +1320,11 @@
 		urb->dev = bcs->cs->hw.bas->udev;
 		urb->transfer_flags = URB_ISO_ASAP;
 		urb->number_of_packets = BAS_NUMFRAMES;
-		spin_lock_irqsave(&cs->lock, flags);
-		rc = cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV;
-		spin_unlock_irqrestore(&cs->lock, flags);
-		if (rc) {
+		rc = usb_submit_urb(urb, SLAB_ATOMIC);
+		if (unlikely(rc != 0 && rc != -ENODEV)) {
 			dev_err(cs->dev,
 				"could not resubmit isochronous read URB: %s\n",
-				get_usb_statmsg(rc));
+				get_usb_rcmsg(rc));
 			dump_urb(DEBUG_ISO, "resubmit iso read", urb);
 			error_hangup(bcs);
 		}
@@ -1397,7 +1425,6 @@
  *	timeout	timeout in seconds (0: no timeout)
  * return value:
  *	0 on success
- *	-EINVAL if a NULL pointer is encountered somewhere
  *	-EBUSY if another request is pending
  *	any URB submission error code
  */
@@ -1418,12 +1445,6 @@
 			req, ucs->pending);
 		return -EBUSY;
 	}
-	if (ucs->urb_ctrl->status == -EINPROGRESS) {
-		spin_unlock_irqrestore(&ucs->lock, flags);
-		dev_err(bcs->cs->dev,
-			"could not submit request 0x%02x: URB busy\n", req);
-		return -EBUSY;
-	}
 
 	ucs->dr_ctrl.bRequestType = OUT_VENDOR_REQ;
 	ucs->dr_ctrl.bRequest = req;
@@ -1465,22 +1486,36 @@
 static int gigaset_init_bchannel(struct bc_state *bcs)
 {
 	int req, ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bcs->cs->lock, flags);
+	if (unlikely(!bcs->cs->connected)) {
+		gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__);
+		spin_unlock_irqrestore(&bcs->cs->lock, flags);
+		return -ENODEV;
+	}
 
 	if ((ret = starturbs(bcs)) < 0) {
 		dev_err(bcs->cs->dev,
-			"could not start isochronous I/O for channel %d\n",
-			bcs->channel + 1);
-		error_hangup(bcs);
+			"could not start isochronous I/O for channel B%d: %s\n",
+			bcs->channel + 1,
+			ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret));
+		if (ret != -ENODEV)
+			error_hangup(bcs);
+		spin_unlock_irqrestore(&bcs->cs->lock, flags);
 		return ret;
 	}
 
 	req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL;
 	if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) {
-		dev_err(bcs->cs->dev, "could not open channel %d: %s\n",
-			bcs->channel + 1, get_usb_statmsg(ret));
+		dev_err(bcs->cs->dev, "could not open channel B%d\n",
+			bcs->channel + 1);
 		stopurbs(bcs->hw.bas);
-		error_hangup(bcs);
+		if (ret != -ENODEV)
+			error_hangup(bcs);
 	}
+
+	spin_unlock_irqrestore(&bcs->cs->lock, flags);
 	return ret;
 }
 
@@ -1497,19 +1532,30 @@
 static int gigaset_close_bchannel(struct bc_state *bcs)
 {
 	int req, ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bcs->cs->lock, flags);
+	if (unlikely(!bcs->cs->connected)) {
+		spin_unlock_irqrestore(&bcs->cs->lock, flags);
+		gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__);
+		return -ENODEV;
+	}
 
 	if (!(atomic_read(&bcs->cs->hw.bas->basstate) &
 	      (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) {
 		/* channel not running: just signal common.c */
+		spin_unlock_irqrestore(&bcs->cs->lock, flags);
 		gigaset_bchannel_down(bcs);
 		return 0;
 	}
 
+	/* channel running: tell device to close it */
 	req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL;
 	if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0)
-		dev_err(bcs->cs->dev,
-			"could not submit HD_CLOSE_BxCHANNEL request: %s\n",
-			get_usb_statmsg(ret));
+		dev_err(bcs->cs->dev, "closing channel B%d failed\n",
+			bcs->channel + 1);
+
+	spin_unlock_irqrestore(&bcs->cs->lock, flags);
 	return ret;
 }
 
@@ -1545,8 +1591,6 @@
 	kfree(cb);
 }
 
-static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len);
-
 /* write_command_callback
  * USB completion handler for AT command transmission
  * called by the USB subsystem in interrupt context
@@ -1560,13 +1604,17 @@
 	struct bas_cardstate *ucs = cs->hw.bas;
 	unsigned long flags;
 
+	update_basstate(ucs, 0, BS_ATWRPEND);
+
 	/* check status */
 	switch (urb->status) {
 	case 0:					/* normal completion */
 		break;
-	case -ENOENT:			/* canceled */
-	case -ECONNRESET:		/* canceled (async) */
+	case -ENOENT:			/* cancelled */
+	case -ECONNRESET:		/* cancelled (async) */
 	case -EINPROGRESS:		/* pending */
+	case -ENODEV:			/* device removed */
+	case -ESHUTDOWN:		/* device shut down */
 		/* ignore silently */
 		gig_dbg(DEBUG_USBREQ, "%s: %s",
 			__func__, get_usb_statmsg(urb->status));
@@ -1627,19 +1675,17 @@
  *	len	length of command to send
  * return value:
  *	0 on success
- *	-EFAULT if a NULL pointer is encountered somewhere
  *	-EBUSY if another request is pending
  *	any URB submission error code
  */
 static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len)
 {
 	struct bas_cardstate *ucs = cs->hw.bas;
-	unsigned long flags;
-	int ret;
+	int rc;
 
 	gig_dbg(DEBUG_USBREQ, "-------> HD_WRITE_ATMESSAGE (%d)", len);
 
-	if (ucs->urb_cmd_out->status == -EINPROGRESS) {
+	if (update_basstate(ucs, BS_ATWRPEND, 0) & BS_ATWRPEND) {
 		dev_err(cs->dev,
 			"could not submit HD_WRITE_ATMESSAGE: URB busy\n");
 		return -EBUSY;
@@ -1654,29 +1700,22 @@
 			     usb_sndctrlpipe(ucs->udev, 0),
 			     (unsigned char*) &ucs->dr_cmd_out, buf, len,
 			     write_command_callback, cs);
-
-	spin_lock_irqsave(&cs->lock, flags);
-	ret = cs->connected ? usb_submit_urb(ucs->urb_cmd_out, SLAB_ATOMIC) : -ENODEV;
-	spin_unlock_irqrestore(&cs->lock, flags);
-
-	if (ret) {
+	rc = usb_submit_urb(ucs->urb_cmd_out, SLAB_ATOMIC);
+	if (unlikely(rc)) {
+		update_basstate(ucs, 0, BS_ATWRPEND);
 		dev_err(cs->dev, "could not submit HD_WRITE_ATMESSAGE: %s\n",
-			get_usb_statmsg(ret));
-		return ret;
+			get_usb_rcmsg(rc));
+		return rc;
 	}
 
-	/* submitted successfully */
-	update_basstate(ucs, 0, BS_ATREADY);
-
-	/* start timeout if necessary */
-	if (!(atomic_read(&ucs->basstate) & BS_ATTIMER)) {
+	/* submitted successfully, start timeout if necessary */
+	if (!(update_basstate(ucs, BS_ATTIMER, BS_ATREADY) & BS_ATTIMER)) {
 		gig_dbg(DEBUG_OUTPUT, "setting ATREADY timeout of %d/10 secs",
 			ATRDY_TIMEOUT);
 		ucs->timer_atrdy.expires = jiffies + ATRDY_TIMEOUT * HZ / 10;
 		ucs->timer_atrdy.data = (unsigned long) cs;
 		ucs->timer_atrdy.function = atrdy_timeout;
 		add_timer(&ucs->timer_atrdy);
-		update_basstate(ucs, BS_ATTIMER, 0);
 	}
 	return 0;
 }
@@ -1702,7 +1741,6 @@
 		gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "AT channel not open");
 		rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT);
 		if (rc < 0) {
-			dev_err(cs->dev, "could not open AT channel\n");
 			/* flush command queue */
 			spin_lock_irqsave(&cs->cmdlock, flags);
 			while (cs->cmdbuf != NULL)
@@ -1786,8 +1824,14 @@
 	cs->lastcmdbuf = cb;
 	spin_unlock_irqrestore(&cs->cmdlock, flags);
 
+	spin_lock_irqsave(&cs->lock, flags);
+	if (unlikely(!cs->connected)) {
+		spin_unlock_irqrestore(&cs->lock, flags);
+		gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__);
+		return -ENODEV;
+	}
 	status = start_cbsend(cs);
-
+	spin_unlock_irqrestore(&cs->lock, flags);
 	return status < 0 ? status : len;
 }
 
@@ -1849,12 +1893,32 @@
  */
 static int gigaset_freebcshw(struct bc_state *bcs)
 {
-	if (!bcs->hw.bas)
+	struct bas_bc_state *ubc = bcs->hw.bas;
+	int i;
+
+	if (!ubc)
 		return 0;
 
-	if (bcs->hw.bas->isooutbuf)
-		kfree(bcs->hw.bas->isooutbuf);
-	kfree(bcs->hw.bas);
+	/* 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]);
+		}
+	tasklet_kill(&ubc->sent_tasklet);
+	tasklet_kill(&ubc->rcvd_tasklet);
+	kfree(ubc->isooutbuf);
+	kfree(ubc);
 	bcs->hw.bas = NULL;
 	return 1;
 }
@@ -1931,13 +1995,9 @@
 
 static void gigaset_freecshw(struct cardstate *cs)
 {
-	struct bas_cardstate *ucs = cs->hw.bas;
-
-	del_timer(&ucs->timer_ctrl);
-	del_timer(&ucs->timer_atrdy);
-	del_timer(&ucs->timer_cmd_in);
-
+	/* timers, URBs and rcvbuf are disposed of in disconnect */
 	kfree(cs->hw.bas);
+	cs->hw.bas = NULL;
 }
 
 static int gigaset_initcshw(struct cardstate *cs)
@@ -2041,23 +2101,13 @@
 	struct bas_bc_state *ubc;
 	struct usb_endpoint_descriptor *endpoint;
 	int i, j;
-	int ret;
+	int rc;
 
 	gig_dbg(DEBUG_ANY,
 		"%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)",
 		__func__, le16_to_cpu(udev->descriptor.idVendor),
 		le16_to_cpu(udev->descriptor.idProduct));
 
-	/* See if the device offered us matches what we can accept */
-	if ((le16_to_cpu(udev->descriptor.idVendor)  != USB_GIGA_VENDOR_ID) ||
-	    (le16_to_cpu(udev->descriptor.idProduct) != USB_GIGA_PRODUCT_ID &&
-	     le16_to_cpu(udev->descriptor.idProduct) != USB_4175_PRODUCT_ID &&
-	     le16_to_cpu(udev->descriptor.idProduct) != USB_SX303_PRODUCT_ID &&
-	     le16_to_cpu(udev->descriptor.idProduct) != USB_SX353_PRODUCT_ID)) {
-		gig_dbg(DEBUG_ANY, "%s: unmatched ID - exiting", __func__);
-		return -ENODEV;
-	}
-
 	/* set required alternate setting */
 	hostif = interface->cur_altsetting;
 	if (hostif->desc.bAlternateSetting != 3) {
@@ -2105,45 +2155,22 @@
 	 * - three for the different uses of the default control pipe
 	 * - three for each isochronous pipe
 	 */
-	ucs->urb_int_in = usb_alloc_urb(0, SLAB_KERNEL);
-	if (!ucs->urb_int_in) {
-		dev_err(cs->dev, "no free urbs available\n");
-		goto error;
-	}
-	ucs->urb_cmd_in = usb_alloc_urb(0, SLAB_KERNEL);
-	if (!ucs->urb_cmd_in) {
-		dev_err(cs->dev, "no free urbs available\n");
-		goto error;
-	}
-	ucs->urb_cmd_out = usb_alloc_urb(0, SLAB_KERNEL);
-	if (!ucs->urb_cmd_out) {
-		dev_err(cs->dev, "no free urbs available\n");
-		goto error;
-	}
-	ucs->urb_ctrl = usb_alloc_urb(0, SLAB_KERNEL);
-	if (!ucs->urb_ctrl) {
-		dev_err(cs->dev, "no free urbs available\n");
-		goto error;
-	}
+	if (!(ucs->urb_int_in = usb_alloc_urb(0, SLAB_KERNEL)) ||
+	    !(ucs->urb_cmd_in = usb_alloc_urb(0, SLAB_KERNEL)) ||
+	    !(ucs->urb_cmd_out = usb_alloc_urb(0, SLAB_KERNEL)) ||
+	    !(ucs->urb_ctrl = usb_alloc_urb(0, SLAB_KERNEL)))
+		goto allocerr;
 
 	for (j = 0; j < 2; ++j) {
 		ubc = cs->bcs[j].hw.bas;
-		for (i = 0; i < BAS_OUTURBS; ++i) {
-			ubc->isoouturbs[i].urb =
-				usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL);
-			if (!ubc->isoouturbs[i].urb) {
-				dev_err(cs->dev, "no free urbs available\n");
-				goto error;
-			}
-		}
-		for (i = 0; i < BAS_INURBS; ++i) {
-			ubc->isoinurbs[i] =
-				usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL);
-			if (!ubc->isoinurbs[i]) {
-				dev_err(cs->dev, "no free urbs available\n");
-				goto error;
-			}
-		}
+		for (i = 0; i < BAS_OUTURBS; ++i)
+			if (!(ubc->isoouturbs[i].urb =
+			      usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL)))
+				goto allocerr;
+		for (i = 0; i < BAS_INURBS; ++i)
+			if (!(ubc->isoinurbs[i] =
+			      usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL)))
+				goto allocerr;
 	}
 
 	ucs->rcvbuf = NULL;
@@ -2156,15 +2183,14 @@
 					(endpoint->bEndpointAddress) & 0x0f),
 			 ucs->int_in_buf, 3, read_int_callback, cs,
 			 endpoint->bInterval);
-	ret = usb_submit_urb(ucs->urb_int_in, SLAB_KERNEL);
-	if (ret) {
+	if ((rc = usb_submit_urb(ucs->urb_int_in, SLAB_KERNEL)) != 0) {
 		dev_err(cs->dev, "could not submit interrupt URB: %s\n",
-			get_usb_statmsg(ret));
+			get_usb_rcmsg(rc));
 		goto error;
 	}
 
 	/* tell the device that the driver is ready */
-	if ((ret = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0)) != 0)
+	if ((rc = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0)) != 0)
 		goto error;
 
 	/* tell common part that the device is ready */
@@ -2179,6 +2205,8 @@
 
 	return 0;
 
+allocerr:
+	dev_err(cs->dev, "could not allocate URBs\n");
 error:
 	freeurbs(cs);
 	usb_set_intfdata(interface, NULL);
@@ -2193,19 +2221,34 @@
 {
 	struct cardstate *cs;
 	struct bas_cardstate *ucs;
+	int j;
 
 	cs = usb_get_intfdata(interface);
 
 	ucs = cs->hw.bas;
 
 	dev_info(cs->dev, "disconnecting Gigaset base\n");
+
+	/* mark base as not ready, all channels disconnected */
+	atomic_set(&ucs->basstate, 0);
+
+	/* tell LL all channels are down */
+	//FIXME shouldn't gigaset_stop() do this?
+	for (j = 0; j < 2; ++j)
+		gigaset_bchannel_down(cs->bcs + j);
+
+	/* stop driver (common part) */
 	gigaset_stop(cs);
+
+	/* stop timers and URBs, free ressources */
+	del_timer_sync(&ucs->timer_ctrl);
+	del_timer_sync(&ucs->timer_atrdy);
+	del_timer_sync(&ucs->timer_cmd_in);
 	freeurbs(cs);
 	usb_set_intfdata(interface, NULL);
 	kfree(ucs->rcvbuf);
 	ucs->rcvbuf = NULL;
 	ucs->rcvbuf_size = 0;
-	atomic_set(&ucs->basstate, 0);
 	usb_put_dev(ucs->udev);
 	ucs->interface = NULL;
 	ucs->udev = NULL;
@@ -2277,6 +2320,8 @@
  */
 static void __exit bas_gigaset_exit(void)
 {
+	struct bas_cardstate *ucs = cardstate->hw.bas;
+
 	gigaset_blockdriver(driver); /* => probe will fail
 				      * => no gigaset_start any more
 				      */
@@ -2284,14 +2329,26 @@
 	gigaset_shutdown(cardstate);
 	/* from now on, no isdn callback should be possible */
 
-	if (atomic_read(&cardstate->hw.bas->basstate) & BS_ATOPEN) {
-		gig_dbg(DEBUG_ANY, "closing AT channel");
-		if (req_submit(cardstate->bcs,
-			       HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT) >= 0) {
-			/* successfully submitted */
-			//FIXME wait for completion?
-		}
+	/* close all still open channels */
+	if (atomic_read(&ucs->basstate) & BS_B1OPEN) {
+		gig_dbg(DEBUG_INIT, "closing B1 channel");
+		usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0),
+				HD_CLOSE_B1CHANNEL, OUT_VENDOR_REQ, 0, 0,
+				NULL, 0, BAS_TIMEOUT);
 	}
+	if (atomic_read(&ucs->basstate) & BS_B2OPEN) {
+		gig_dbg(DEBUG_INIT, "closing B2 channel");
+		usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0),
+				HD_CLOSE_B2CHANNEL, OUT_VENDOR_REQ, 0, 0,
+				NULL, 0, BAS_TIMEOUT);
+	}
+	if (atomic_read(&ucs->basstate) & BS_ATOPEN) {
+		gig_dbg(DEBUG_INIT, "closing AT channel");
+		usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0),
+				HD_CLOSE_ATCHANNEL, OUT_VENDOR_REQ, 0, 0,
+				NULL, 0, BAS_TIMEOUT);
+	}
+	atomic_set(&ucs->basstate, 0);
 
 	/* deregister this driver with the USB subsystem */
 	usb_deregister(&gigaset_usb_driver);
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index 749b3da..e55767b 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -781,8 +781,7 @@
 }
 EXPORT_SYMBOL_GPL(gigaset_initcs);
 
-/* ReInitialize the b-channel structure */
-/* e.g. called on hangup, disconnect */
+/* ReInitialize the b-channel structure on hangup */
 void gigaset_bcs_reinit(struct bc_state *bcs)
 {
 	struct sk_buff *skb;
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c
index 1ba3424..18e05c0 100644
--- a/drivers/isdn/gigaset/ev-layer.c
+++ b/drivers/isdn/gigaset/ev-layer.c
@@ -373,6 +373,9 @@
 
 	{EV_TIMEOUT,  750,750, -1,                  0, 0, {ACT_CONNTIMEOUT}},
 
+	/* B channel closed (general case) */
+	{EV_BC_CLOSED, -1, -1, -1,                 -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME
+
 	/* misc. */
 	{EV_PROTO_L2,  -1, -1, -1,                 -1,-1, {ACT_PROTO_L2}}, //FIXME
 
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index 9d21ba8..22b9693 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -75,7 +75,7 @@
  * e.g. 'insmod usb_gigaset.o debug=0x2c' will set DEBUG_OPEN, DEBUG_CMD and
  * DEBUG_INTR.
  */
-enum debuglevel { /* up to 24 bits (atomic_t) */
+enum debuglevel {
 	DEBUG_REG	  = 0x0002, /* serial port I/O register operations */
 	DEBUG_OPEN	  = 0x0004, /* open/close serial port */
 	DEBUG_INTR	  = 0x0008, /* interrupt processing */
@@ -141,7 +141,7 @@
 			printk(KERN_DEBUG KBUILD_MODNAME ": " format "\n", \
 			       ## arg); \
 	} while (0)
-#define DEBUG_DEFAULT (DEBUG_INIT | DEBUG_TRANSCMD | DEBUG_CMD | DEBUG_USBREQ)
+#define DEBUG_DEFAULT (DEBUG_TRANSCMD | DEBUG_CMD | DEBUG_USBREQ)
 
 #else
 
@@ -627,8 +627,7 @@
 	/* Called by gigaset_freecs() for freeing bcs->hw.xxx */
 	int (*freebcshw)(struct bc_state *bcs);
 
-	/* Called by gigaset_stop() or gigaset_bchannel_down() for resetting
-	   bcs->hw.xxx */
+	/* Called by gigaset_bchannel_down() for resetting bcs->hw.xxx */
 	void (*reinitbcshw)(struct bc_state *bcs);
 
 	/* Called by gigaset_initcs() for setting up cs->hw.xxx */
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c
index 0815dbf..1654fa4 100644
--- a/drivers/isdn/gigaset/i4l.c
+++ b/drivers/isdn/gigaset/i4l.c
@@ -73,7 +73,7 @@
 		len, skblen, (unsigned) skb->head[0], (unsigned) skb->head[1]);
 
 	/* pass to device-specific module */
-	return cs->ops->send_skb(bcs, skb); //FIXME cs->ops->send_skb() must handle !cs->connected correctly
+	return cs->ops->send_skb(bcs, skb);
 }
 
 void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb)
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c
index 45f017e..8667daa 100644
--- a/drivers/isdn/gigaset/isocdata.c
+++ b/drivers/isdn/gigaset/isocdata.c
@@ -992,14 +992,18 @@
 	int len = skb->len;
 	unsigned long flags;
 
+	spin_lock_irqsave(&bcs->cs->lock, flags);
+	if (!bcs->cs->connected) {
+		spin_unlock_irqrestore(&bcs->cs->lock, flags);
+		return -ENODEV;
+	}
+
 	skb_queue_tail(&bcs->squeue, skb);
 	gig_dbg(DEBUG_ISO, "%s: skb queued, qlen=%d",
 		__func__, skb_queue_len(&bcs->squeue));
 
 	/* tasklet submits URB if necessary */
-	spin_lock_irqsave(&bcs->cs->lock, flags);
-	if (bcs->cs->connected)
-		tasklet_schedule(&bcs->hw.bas->sent_tasklet);
+	tasklet_schedule(&bcs->hw.bas->sent_tasklet);
 	spin_unlock_irqrestore(&bcs->cs->lock, flags);
 
 	return len;	/* ok so far */
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index 5ebfd1d..5282fec 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -627,8 +627,8 @@
 	if(therm_type == ADT7460)
 		device_create_file(&of_dev->dev, &dev_attr_sensor2_fan_speed);
 
-#ifndef CONFIG_I2C_KEYWEST
-	request_module("i2c-keywest");
+#ifndef CONFIG_I2C_POWERMAC
+	request_module("i2c-powermac");
 #endif
 
 	return i2c_add_driver(&thermostat_driver);
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 434ca39..d7316b8 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -279,11 +279,6 @@
 	return mutex_lock_interruptible(&mddev->reconfig_mutex);
 }
 
-static inline void mddev_lock_uninterruptible(mddev_t * mddev)
-{
-	mutex_lock(&mddev->reconfig_mutex);
-}
-
 static inline int mddev_trylock(mddev_t * mddev)
 {
 	return mutex_trylock(&mddev->reconfig_mutex);
@@ -2458,9 +2453,11 @@
 
 	if (!entry->show)
 		return -EIO;
-	mddev_lock(mddev);
-	rv = entry->show(mddev, page);
-	mddev_unlock(mddev);
+	rv = mddev_lock(mddev);
+	if (!rv) {
+		rv = entry->show(mddev, page);
+		mddev_unlock(mddev);
+	}
 	return rv;
 }
 
@@ -2474,9 +2471,11 @@
 
 	if (!entry->store)
 		return -EIO;
-	mddev_lock(mddev);
-	rv = entry->store(mddev, page, length);
-	mddev_unlock(mddev);
+	rv = mddev_lock(mddev);
+	if (!rv) {
+		rv = entry->store(mddev, page, length);
+		mddev_unlock(mddev);
+	}
 	return rv;
 }
 
@@ -4341,8 +4340,9 @@
 		return 0;
 	}
 
-	if (mddev_lock(mddev)!=0) 
+	if (mddev_lock(mddev) < 0)
 		return -EINTR;
+
 	if (mddev->pers || mddev->raid_disks || !list_empty(&mddev->disks)) {
 		seq_printf(seq, "%s : %sactive", mdname(mddev),
 						mddev->pers ? "" : "in");
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index 08b218c..93c494b 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -226,7 +226,7 @@
 	netdev_boot_setup_check(dev);
 
 #ifdef CONFIG_TOSHIBA_RBTX4938
-	dev->base_addr = 0x07f20280;
+	dev->base_addr = RBTX4938_RTL_8019_BASE;
 	dev->irq = RBTX4938_RTL_8019_IRQ;
 #endif
 	err = do_ne_probe(dev);
diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c
index cb0aba9..046371e 100644
--- a/drivers/net/sungem_phy.c
+++ b/drivers/net/sungem_phy.c
@@ -275,7 +275,7 @@
 	return 0;
 }
 
-static int bcm5411_suspend(struct mii_phy* phy)
+static int generic_suspend(struct mii_phy* phy)
 {
 	phy_write(phy, MII_BMCR, BMCR_PDOWN);
 
@@ -738,7 +738,7 @@
 /* Broadcom BCM 5411 */
 static struct mii_phy_ops bcm5411_phy_ops = {
 	.init		= bcm5411_init,
-	.suspend	= bcm5411_suspend,
+	.suspend	= generic_suspend,
 	.setup_aneg	= bcm54xx_setup_aneg,
 	.setup_forced	= bcm54xx_setup_forced,
 	.poll_link	= genmii_poll_link,
@@ -757,7 +757,7 @@
 /* Broadcom BCM 5421 */
 static struct mii_phy_ops bcm5421_phy_ops = {
 	.init		= bcm5421_init,
-	.suspend	= bcm5411_suspend,
+	.suspend	= generic_suspend,
 	.setup_aneg	= bcm54xx_setup_aneg,
 	.setup_forced	= bcm54xx_setup_forced,
 	.poll_link	= genmii_poll_link,
@@ -776,7 +776,7 @@
 /* Broadcom BCM 5421 built-in K2 */
 static struct mii_phy_ops bcm5421k2_phy_ops = {
 	.init		= bcm5421_init,
-	.suspend	= bcm5411_suspend,
+	.suspend	= generic_suspend,
 	.setup_aneg	= bcm54xx_setup_aneg,
 	.setup_forced	= bcm54xx_setup_forced,
 	.poll_link	= genmii_poll_link,
@@ -795,7 +795,7 @@
 /* Broadcom BCM 5462 built-in Vesta */
 static struct mii_phy_ops bcm5462V_phy_ops = {
 	.init		= bcm5421_init,
-	.suspend	= bcm5411_suspend,
+	.suspend	= generic_suspend,
 	.setup_aneg	= bcm54xx_setup_aneg,
 	.setup_forced	= bcm54xx_setup_forced,
 	.poll_link	= genmii_poll_link,
@@ -816,6 +816,7 @@
  * would be useful here) --BenH.
  */
 static struct mii_phy_ops marvell_phy_ops = {
+	.suspend	= generic_suspend,
 	.setup_aneg	= marvell_setup_aneg,
 	.setup_forced	= marvell_setup_forced,
 	.poll_link	= genmii_poll_link,
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index bad09eb..e0874cb 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -6,7 +6,7 @@
 	depends on NETDEVICES
 
 config NET_RADIO
-	bool "Wireless LAN drivers (non-hamradio)"
+	bool "Wireless LAN drivers (non-hamradio) & Wireless Extensions"
 	select WIRELESS_EXT
 	---help---
 	  Support for wireless LANs and everything having to do with radio,
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 108d9fe..00764dd 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -3139,6 +3139,7 @@
 		}
 		if ( status & EV_LINK ) {
 			union iwreq_data	wrqu;
+			int scan_forceloss = 0;
 			/* The link status has changed, if you want to put a
 			   monitor hook in, do it here.  (Remember that
 			   interrupts are still disabled!)
@@ -3157,7 +3158,8 @@
 			  code) */
 #define AUTHFAIL 0x0300 /* Authentication failure (low byte is reason
 			   code) */
-#define ASSOCIATED 0x0400 /* Assocatied */
+#define ASSOCIATED 0x0400 /* Associated */
+#define REASSOCIATED 0x0600 /* Reassociated?  Only on firmware >= 5.30.17 */
 #define RC_RESERVED 0 /* Reserved return code */
 #define RC_NOREASON 1 /* Unspecified reason */
 #define RC_AUTHINV 2 /* Previous authentication invalid */
@@ -3174,44 +3176,30 @@
 			  leaving BSS */
 #define RC_NOAUTH 9 /* Station requesting (Re)Association is not
 		       Authenticated with the responding station */
-			if (newStatus != ASSOCIATED) {
-				if (auto_wep && !apriv->expires) {
-					apriv->expires = RUN_AT(3*HZ);
-					wake_up_interruptible(&apriv->thr_wait);
-				}
-			} else {
-				struct task_struct *task = apriv->task;
+			if (newStatus == FORCELOSS && apriv->scan_timeout > 0)
+				scan_forceloss = 1;
+			if(newStatus == ASSOCIATED || newStatus == REASSOCIATED) {
 				if (auto_wep)
 					apriv->expires = 0;
-				if (task)
-					wake_up_process (task);
+				if (apriv->task)
+					wake_up_process (apriv->task);
 				set_bit(FLAG_UPDATE_UNI, &apriv->flags);
 				set_bit(FLAG_UPDATE_MULTI, &apriv->flags);
-			}
-			/* Question : is ASSOCIATED the only status
-			 * that is valid ? We want to catch handover
-			 * and reassociations as valid status
-			 * Jean II */
-			if(newStatus == ASSOCIATED) {
-#if 0
-				/* FIXME: Grabbing scan results here
-				 * seems to be too early???  Just wait for
-				 * timeout instead. */
-				if (apriv->scan_timeout > 0) {
-					set_bit(JOB_SCAN_RESULTS, &apriv->flags);
-					wake_up_interruptible(&apriv->thr_wait);
-				}
-#endif
+
 				if (down_trylock(&apriv->sem) != 0) {
 					set_bit(JOB_EVENT, &apriv->flags);
 					wake_up_interruptible(&apriv->thr_wait);
 				} else
 					airo_send_event(dev);
-			} else {
-				memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
-				wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+			} else if (!scan_forceloss) {
+				if (auto_wep && !apriv->expires) {
+					apriv->expires = RUN_AT(3*HZ);
+					wake_up_interruptible(&apriv->thr_wait);
+				}
 
 				/* Send event to user space */
+				memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
+				wrqu.ap_addr.sa_family = ARPHRD_ETHER;
 				wireless_send_event(dev, SIOCGIWAP, &wrqu,NULL);
 			}
 		}
@@ -7136,10 +7124,10 @@
 		goto out;
 
 	/* Initiate a scan command */
+	ai->scan_timeout = RUN_AT(3*HZ);
 	memset(&cmd, 0, sizeof(cmd));
 	cmd.cmd=CMD_LISTBSS;
 	issuecommand(ai, &cmd, &rsp);
-	ai->scan_timeout = RUN_AT(3*HZ);
 	wake = 1;
 
 out:
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 87afa68..8606c88 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -3463,6 +3463,7 @@
 	u8 status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET));
 	u8 command = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET));
 	int fast_scan;
+	union iwreq_data wrqu;
 
 	if (status == CMD_STATUS_IDLE ||
 	    status == CMD_STATUS_IN_PROGRESS)
@@ -3487,6 +3488,7 @@
 			atmel_scan(priv, 1);
 		} else {
 			int bss_index = retrieve_bss(priv);
+			int notify_scan_complete = 1;
 			if (bss_index != -1) {
 				atmel_join_bss(priv, bss_index);
 			} else if (priv->operating_mode == IW_MODE_ADHOC &&
@@ -3495,8 +3497,14 @@
 			} else {
 				priv->fast_scan = !fast_scan;
 				atmel_scan(priv, 1);
+				notify_scan_complete = 0;
 			}
 			priv->site_survey_state = SITE_SURVEY_COMPLETED;
+			if (notify_scan_complete) {
+				wrqu.data.length = 0;
+				wrqu.data.flags = 0;
+				wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
+			}
 		}
 		break;
 
@@ -3509,6 +3517,9 @@
 		priv->site_survey_state = SITE_SURVEY_COMPLETED;
 		if (priv->station_is_associated) {
 			atmel_enter_state(priv, STATION_STATE_READY);
+			wrqu.data.length = 0;
+			wrqu.data.flags = 0;
+			wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
 		} else {
 			atmel_scan(priv, 1);
 		}
diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig
index 4184656..25ea474 100644
--- a/drivers/net/wireless/bcm43xx/Kconfig
+++ b/drivers/net/wireless/bcm43xx/Kconfig
@@ -17,8 +17,11 @@
 
 config BCM43XX_DMA
 	bool
+	depends on BCM43XX
+
 config BCM43XX_PIO
 	bool
+	depends on BCM43XX
 
 choice
 	prompt "BCM43xx data transfer mode"
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index dcadd29..2e83083 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -15,7 +15,6 @@
 
 #include "bcm43xx_debugfs.h"
 #include "bcm43xx_leds.h"
-#include "bcm43xx_sysfs.h"
 
 
 #define PFX				KBUILD_MODNAME ": "
@@ -638,8 +637,6 @@
 };
 
 struct bcm43xx_private {
-	struct bcm43xx_sysfs sysfs;
-
 	struct ieee80211_device *ieee;
 	struct ieee80211softmac_device *softmac;
 
@@ -772,6 +769,20 @@
 	return ieee80211softmac_priv(dev);
 }
 
+struct device;
+
+static inline
+struct bcm43xx_private * dev_to_bcm(struct device *dev)
+{
+	struct net_device *net_dev;
+	struct bcm43xx_private *bcm;
+
+	net_dev = dev_get_drvdata(dev);
+	bcm = bcm43xx_priv(net_dev);
+
+	return bcm;
+}
+
 
 /* Helper function, which returns a boolean.
  * TRUE, if PIO is used; FALSE, if DMA is used.
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
index d2c3401..35a4fcb 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
@@ -452,12 +452,12 @@
 	size_t i;
 	char c;
 
-	printk(KERN_INFO PFX "Data dump (%s, %u bytes):",
+	printk(KERN_INFO PFX "Data dump (%s, %zd bytes):",
 	       description, size);
 	for (i = 0; i < size; i++) {
 		c = data[i];
 		if (i % 8 == 0)
-			printk("\n" KERN_INFO PFX "0x%08x:  0x%02x, ", i, c & 0xff);
+			printk("\n" KERN_INFO PFX "0x%08zx:  0x%02x, ", i, c & 0xff);
 		else
 			printk("0x%02x, ", c & 0xff);
 	}
@@ -472,12 +472,12 @@
 	int j;
 	const unsigned char *d;
 
-	printk(KERN_INFO PFX "*** Bitdump (%s, %u bytes, %s) ***",
+	printk(KERN_INFO PFX "*** Bitdump (%s, %zd bytes, %s) ***",
 	       description, bytes, msb_to_lsb ? "MSB to LSB" : "LSB to MSB");
 	for (i = 0; i < bytes; i++) {
 		d = data + i;
 		if (i % 8 == 0)
-			printk("\n" KERN_INFO PFX "0x%08x:  ", i);
+			printk("\n" KERN_INFO PFX "0x%08zx:  ", i);
 		if (msb_to_lsb) {
 			for (j = 7; j >= 0; j--) {
 				if (*d & (1 << j))
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
index c3681b8..bbecba0 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
@@ -196,8 +196,9 @@
 	}
 	if (ring->dmabase + BCM43xx_DMA_RINGMEMSIZE > BCM43xx_DMA_BUSADDRMAX) {
 		printk(KERN_ERR PFX ">>>FATAL ERROR<<<  DMA RINGMEMORY >1G "
-				    "(0x%08x, len: %lu)\n",
-		       ring->dmabase, BCM43xx_DMA_RINGMEMSIZE);
+				    "(0x%llx, len: %lu)\n",
+				(unsigned long long)ring->dmabase,
+				BCM43xx_DMA_RINGMEMSIZE);
 		dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
 				  ring->vbase, ring->dmabase);
 		return -ENOMEM;
@@ -307,8 +308,8 @@
 		unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0);
 		dev_kfree_skb_any(skb);
 		printk(KERN_ERR PFX ">>>FATAL ERROR<<<  DMA RX SKB >1G "
-				    "(0x%08x, len: %u)\n",
-		       dmaaddr, ring->rx_buffersize);
+				    "(0x%llx, len: %u)\n",
+			(unsigned long long)dmaaddr, ring->rx_buffersize);
 		return -ENOMEM;
 	}
 	meta->skb = skb;
@@ -729,8 +730,8 @@
 	if (unlikely(meta->dmaaddr + skb->len > BCM43xx_DMA_BUSADDRMAX)) {
 		return_slot(ring, slot);
 		printk(KERN_ERR PFX ">>>FATAL ERROR<<<  DMA TX SKB >1G "
-				    "(0x%08x, len: %u)\n",
-		       meta->dmaaddr, skb->len);
+				    "(0x%llx, len: %u)\n",
+			(unsigned long long)meta->dmaaddr, skb->len);
 		return -ENOMEM;
 	}
 
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index c37371f..9a06e61d 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -52,6 +52,7 @@
 #include "bcm43xx_wx.h"
 #include "bcm43xx_ethtool.h"
 #include "bcm43xx_xmit.h"
+#include "bcm43xx_sysfs.h"
 
 
 MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver");
@@ -3522,6 +3523,7 @@
 		err = bcm43xx_pio_tx(bcm, txb);
 	else
 		err = bcm43xx_dma_tx(bcm, txb);
+	bcm->net_dev->trans_start = jiffies;
 
 	return err;
 }
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
index 0a66f43..3313716 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -2151,6 +2151,7 @@
 				phy->tssi2dbm = NULL;
 				printk(KERN_ERR PFX "Could not generate "
 						    "tssi2dBm table\n");
+				kfree(dyn_tssi2dbm);
 				return -ENODEV;
 			}
 		phy->tssi2dbm = dyn_tssi2dbm;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.c b/drivers/net/wireless/bcm43xx/bcm43xx_power.c
index 3c92b62..6569da3 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_power.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_power.c
@@ -35,77 +35,101 @@
 #include "bcm43xx_main.h"
 
 
+/* Get the Slow Clock Source */
+static int bcm43xx_pctl_get_slowclksrc(struct bcm43xx_private *bcm)
+{
+	u32 tmp;
+	int err;
+
+	assert(bcm->current_core == &bcm->core_chipcommon);
+	if (bcm->current_core->rev < 6) {
+		if (bcm->bustype == BCM43xx_BUSTYPE_PCMCIA ||
+		    bcm->bustype == BCM43xx_BUSTYPE_SB)
+			return BCM43xx_PCTL_CLKSRC_XTALOS;
+		if (bcm->bustype == BCM43xx_BUSTYPE_PCI) {
+			err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp);
+			assert(!err);
+			if (tmp & 0x10)
+				return BCM43xx_PCTL_CLKSRC_PCI;
+			return BCM43xx_PCTL_CLKSRC_XTALOS;
+		}
+	}
+	if (bcm->current_core->rev < 10) {
+		tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+		tmp &= 0x7;
+		if (tmp == 0)
+			return BCM43xx_PCTL_CLKSRC_LOPWROS;
+		if (tmp == 1)
+			return BCM43xx_PCTL_CLKSRC_XTALOS;
+		if (tmp == 2)
+			return BCM43xx_PCTL_CLKSRC_PCI;
+	}
+
+	return BCM43xx_PCTL_CLKSRC_XTALOS;
+}
+
 /* Get max/min slowclock frequency
  * as described in http://bcm-specs.sipsolutions.net/PowerControl
  */
 static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm,
 				       int get_max)
 {
-	int limit = 0;
+	int limit;
+	int clocksrc;
 	int divisor;
-	int selection;
-	int err;
 	u32 tmp;
-	struct bcm43xx_coreinfo *old_core;
 
-	if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL))
-		goto out;
-	old_core = bcm->current_core;
-	err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
-	if (err)
-		goto out;
+	assert(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL);
+	assert(bcm->current_core == &bcm->core_chipcommon);
 
+	clocksrc = bcm43xx_pctl_get_slowclksrc(bcm);
 	if (bcm->current_core->rev < 6) {
-		if ((bcm->bustype == BCM43xx_BUSTYPE_PCMCIA) ||
-			(bcm->bustype == BCM43xx_BUSTYPE_SB)) {
-			selection = 1;
+		switch (clocksrc) {
+		case BCM43xx_PCTL_CLKSRC_PCI:
+			divisor = 64;
+			break;
+		case BCM43xx_PCTL_CLKSRC_XTALOS:
 			divisor = 32;
-		} else {
-			err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp);
-			if (err) {
-				printk(KERN_ERR PFX "clockfreqlimit pcicfg read failure\n");
-				goto out_switchback;
-			}
-			if (tmp & 0x10) {
-				/* PCI */
-				selection = 2;
-				divisor = 64;
-			} else {
-				/* XTAL */
-				selection = 1;
-				divisor = 32;
-			}
+			break;
+		default:
+			assert(0);
+			divisor = 1;
 		}
 	} else if (bcm->current_core->rev < 10) {
-		selection = (tmp & 0x07);
-		if (selection) {
-			tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
-			divisor = 4 * (1 + ((tmp & 0xFFFF0000) >> 16));
-		} else
+		switch (clocksrc) {
+		case BCM43xx_PCTL_CLKSRC_LOPWROS:
 			divisor = 1;
+			break;
+		case BCM43xx_PCTL_CLKSRC_XTALOS:
+		case BCM43xx_PCTL_CLKSRC_PCI:
+			tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+			divisor = ((tmp & 0xFFFF0000) >> 16) + 1;
+			divisor *= 4;
+			break;
+		default:
+			assert(0);
+			divisor = 1;
+		}
 	} else {
 		tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL);
-		divisor = 4 * (1 + ((tmp & 0xFFFF0000) >> 16));
-		selection = 1;
+		divisor = ((tmp & 0xFFFF0000) >> 16) + 1;
+		divisor *= 4;
 	}
-	
-	switch (selection) {
-	case 0:
-		/* LPO */
+
+	switch (clocksrc) {
+	case BCM43xx_PCTL_CLKSRC_LOPWROS:
 		if (get_max)
 			limit = 43000;
 		else
 			limit = 25000;
 		break;
-	case 1:
-		/* XTAL */
+	case BCM43xx_PCTL_CLKSRC_XTALOS:
 		if (get_max)
 			limit = 20200000;
 		else
 			limit = 19800000;
 		break;
-	case 2:
-		/* PCI */
+	case BCM43xx_PCTL_CLKSRC_PCI:
 		if (get_max)
 			limit = 34000000;
 		else
@@ -113,17 +137,14 @@
 		break;
 	default:
 		assert(0);
+		limit = 0;
 	}
 	limit /= divisor;
 
-out_switchback:
-	err = bcm43xx_switch_core(bcm, old_core);
-	assert(err == 0);
-
-out:
 	return limit;
 }
 
+
 /* init power control
  * as described in http://bcm-specs.sipsolutions.net/PowerControl
  */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.h b/drivers/net/wireless/bcm43xx/bcm43xx_power.h
index 5f63640..c966ab3 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_power.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_power.h
@@ -33,6 +33,15 @@
 
 #include <linux/types.h>
 
+/* Clock sources */
+enum {
+	/* PCI clock */
+	BCM43xx_PCTL_CLKSRC_PCI,
+	/* Crystal slow clock oscillator */
+	BCM43xx_PCTL_CLKSRC_XTALOS,
+	/* Low power oscillator */
+	BCM43xx_PCTL_CLKSRC_LOPWROS,
+};
 
 struct bcm43xx_private;
 
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
index c44d890..b438f48 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
@@ -71,14 +71,46 @@
 	return -EINVAL;
 }
 
+static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len)
+{
+	int i, pos = 0;
+
+	for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
+		pos += snprintf(buf + pos, buf_len - pos - 1,
+				"%04X", swab16(sprom[i]) & 0xFFFF);
+	}
+	pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
+
+	return pos + 1;
+}
+
+static int hex2sprom(u16 *sprom, const char *dump, size_t len)
+{
+	char tmp[5] = { 0 };
+	int cnt = 0;
+	unsigned long parsed;
+
+	if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2)
+		return -EINVAL;
+
+	while (cnt < BCM43xx_SPROM_SIZE) {
+		memcpy(tmp, dump, 4);
+		dump += 4;
+		parsed = simple_strtoul(tmp, NULL, 16);
+		sprom[cnt++] = swab16((u16)parsed);
+	}
+
+	return 0;
+}
+
 static ssize_t bcm43xx_attr_sprom_show(struct device *dev,
 				       struct device_attribute *attr,
 				       char *buf)
 {
-	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_sprom);
+	struct bcm43xx_private *bcm = dev_to_bcm(dev);
 	u16 *sprom;
 	unsigned long flags;
-	int i, err;
+	int err;
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
@@ -91,55 +123,53 @@
 	bcm43xx_lock_mmio(bcm, flags);
 	assert(bcm->initialized);
 	err = bcm43xx_sprom_read(bcm, sprom);
-	if (!err) {
-		for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
-			buf[i * 2] = sprom[i] & 0x00FF;
-			buf[i * 2 + 1] = (sprom[i] & 0xFF00) >> 8;
-		}
-	}
+	if (!err)
+		err = sprom2hex(sprom, buf, PAGE_SIZE);
 	bcm43xx_unlock_mmio(bcm, flags);
 	kfree(sprom);
 
-	return err ? err : BCM43xx_SPROM_SIZE * sizeof(u16);
+	return err;
 }
 
 static ssize_t bcm43xx_attr_sprom_store(struct device *dev,
 					struct device_attribute *attr,
 					const char *buf, size_t count)
 {
-	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_sprom);
+	struct bcm43xx_private *bcm = dev_to_bcm(dev);
 	u16 *sprom;
 	unsigned long flags;
-	int i, err;
+	int err;
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
 
-	if (count != BCM43xx_SPROM_SIZE * sizeof(u16))
-		return -EINVAL;
 	sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
 			GFP_KERNEL);
 	if (!sprom)
 		return -ENOMEM;
-	for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
-		sprom[i] = buf[i * 2] & 0xFF;
-		sprom[i] |= ((u16)(buf[i * 2 + 1] & 0xFF)) << 8;
-	}
+	err = hex2sprom(sprom, buf, count);
+	if (err)
+		goto out_kfree;
 	bcm43xx_lock_mmio(bcm, flags);
 	assert(bcm->initialized);
 	err = bcm43xx_sprom_write(bcm, sprom);
 	bcm43xx_unlock_mmio(bcm, flags);
+out_kfree:
 	kfree(sprom);
 
 	return err ? err : count;
 
 }
 
+static DEVICE_ATTR(sprom, 0600,
+		   bcm43xx_attr_sprom_show,
+		   bcm43xx_attr_sprom_store);
+
 static ssize_t bcm43xx_attr_interfmode_show(struct device *dev,
 					    struct device_attribute *attr,
 					    char *buf)
 {
-	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_interfmode);
+	struct bcm43xx_private *bcm = dev_to_bcm(dev);
 	unsigned long flags;
 	int err;
 	ssize_t count = 0;
@@ -175,7 +205,7 @@
 					     struct device_attribute *attr,
 					     const char *buf, size_t count)
 {
-	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_interfmode);
+	struct bcm43xx_private *bcm = dev_to_bcm(dev);
 	unsigned long flags;
 	int err;
 	int mode;
@@ -215,11 +245,15 @@
 	return err ? err : count;
 }
 
+static DEVICE_ATTR(interference, 0644,
+		   bcm43xx_attr_interfmode_show,
+		   bcm43xx_attr_interfmode_store);
+
 static ssize_t bcm43xx_attr_preamble_show(struct device *dev,
 					  struct device_attribute *attr,
 					  char *buf)
 {
-	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_preamble);
+	struct bcm43xx_private *bcm = dev_to_bcm(dev);
 	unsigned long flags;
 	int err;
 	ssize_t count;
@@ -245,7 +279,7 @@
 					   struct device_attribute *attr,
 					   const char *buf, size_t count)
 {
-	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_preamble);
+	struct bcm43xx_private *bcm = dev_to_bcm(dev);
 	unsigned long flags;
 	int err;
 	int value;
@@ -267,56 +301,41 @@
 	return err ? err : count;
 }
 
+static DEVICE_ATTR(shortpreamble, 0644,
+		   bcm43xx_attr_preamble_show,
+		   bcm43xx_attr_preamble_store);
+
 int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
 {
 	struct device *dev = &bcm->pci_dev->dev;
-	struct bcm43xx_sysfs *sysfs = &bcm->sysfs;
 	int err;
 
 	assert(bcm->initialized);
 
-	sysfs->attr_sprom.attr.name = "sprom";
-	sysfs->attr_sprom.attr.owner = THIS_MODULE;
-	sysfs->attr_sprom.attr.mode = 0600;
-	sysfs->attr_sprom.show = bcm43xx_attr_sprom_show;
-	sysfs->attr_sprom.store = bcm43xx_attr_sprom_store;
-	err = device_create_file(dev, &sysfs->attr_sprom);
+	err = device_create_file(dev, &dev_attr_sprom);
 	if (err)
 		goto out;
-
-	sysfs->attr_interfmode.attr.name = "interference";
-	sysfs->attr_interfmode.attr.owner = THIS_MODULE;
-	sysfs->attr_interfmode.attr.mode = 0600;
-	sysfs->attr_interfmode.show = bcm43xx_attr_interfmode_show;
-	sysfs->attr_interfmode.store = bcm43xx_attr_interfmode_store;
-	err = device_create_file(dev, &sysfs->attr_interfmode);
+	err = device_create_file(dev, &dev_attr_interference);
 	if (err)
 		goto err_remove_sprom;
-
-	sysfs->attr_preamble.attr.name = "shortpreamble";
-	sysfs->attr_preamble.attr.owner = THIS_MODULE;
-	sysfs->attr_preamble.attr.mode = 0600;
-	sysfs->attr_preamble.show = bcm43xx_attr_preamble_show;
-	sysfs->attr_preamble.store = bcm43xx_attr_preamble_store;
-	err = device_create_file(dev, &sysfs->attr_preamble);
+	err = device_create_file(dev, &dev_attr_shortpreamble);
 	if (err)
 		goto err_remove_interfmode;
 
 out:
 	return err;
 err_remove_interfmode:
-	device_remove_file(dev, &sysfs->attr_interfmode);
+	device_remove_file(dev, &dev_attr_interference);
 err_remove_sprom:
-	device_remove_file(dev, &sysfs->attr_sprom);
+	device_remove_file(dev, &dev_attr_sprom);
 	goto out;
 }
 
 void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm)
 {
 	struct device *dev = &bcm->pci_dev->dev;
-	struct bcm43xx_sysfs *sysfs = &bcm->sysfs;
 
-	device_remove_file(dev, &sysfs->attr_preamble);
-	device_remove_file(dev, &sysfs->attr_interfmode);
-	device_remove_file(dev, &sysfs->attr_sprom);
+	device_remove_file(dev, &dev_attr_shortpreamble);
+	device_remove_file(dev, &dev_attr_interference);
+	device_remove_file(dev, &dev_attr_sprom);
 }
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h
index 57f1451..cc701df 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h
@@ -1,22 +1,6 @@
 #ifndef BCM43xx_SYSFS_H_
 #define BCM43xx_SYSFS_H_
 
-#include <linux/device.h>
-
-
-struct bcm43xx_sysfs {
-	struct device_attribute attr_sprom;
-	struct device_attribute attr_interfmode;
-	struct device_attribute attr_preamble;
-};
-
-#define devattr_to_bcm(attr, attr_name)	({				\
-	struct bcm43xx_sysfs *__s; struct bcm43xx_private *__p;		\
-	__s = container_of((attr), struct bcm43xx_sysfs, attr_name);	\
-	__p = container_of(__s, struct bcm43xx_private, sysfs);		\
-	__p;								\
-					})
-
 struct bcm43xx_private;
 
 int bcm43xx_sysfs_register(struct bcm43xx_private *bcm);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
index 3daee82..3edbb48 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
@@ -962,22 +962,22 @@
 	{
 		.cmd		= PRIV_WX_SET_SHORTPREAMBLE,
 		.set_args	= IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-		.name		= "set_shortpreambl",
+		.name		= "set_shortpreamb",
 	},
 	{
 		.cmd		= PRIV_WX_GET_SHORTPREAMBLE,
 		.get_args	= IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
-		.name		= "get_shortpreambl",
+		.name		= "get_shortpreamb",
 	},
 	{
 		.cmd		= PRIV_WX_SET_SWENCRYPTION,
 		.set_args	= IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-		.name		= "set_swencryption",
+		.name		= "set_swencrypt",
 	},
 	{
 		.cmd		= PRIV_WX_GET_SWENCRYPTION,
 		.get_args	= IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
-		.name		= "get_swencryption",
+		.name		= "get_swencrypt",
 	},
 	{
 		.cmd		= PRIV_WX_SPROM_WRITE,
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 8dfdfbd..06523e2 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -390,7 +390,7 @@
 		}
 	} else {
 		struct {
-			__le16 qual, signal, noise;
+			__le16 qual, signal, noise, unused;
 		} __attribute__ ((packed)) cq;
 
 		err = HERMES_READ_RECORD(hw, USER_BAP,
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index d589002..48bbf32 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -97,7 +97,7 @@
 	int io;
 	int irq;
 	int dma;
-} superios[NR_SUPERIOS] __devinitdata = { {0,},};
+} superios[NR_SUPERIOS] = { {0,},};
 
 static int user_specified;
 #if defined(CONFIG_PARPORT_PC_SUPERIO) || \
@@ -1557,7 +1557,7 @@
 	return PARPORT_DMA_NONE;
 }
 
-static int __devinit get_superio_irq (struct parport *p)
+static int get_superio_irq (struct parport *p)
 {
 	int i=0;
         while( (superios[i].io != p->base) && (i<NR_SUPERIOS))
@@ -1579,7 +1579,7 @@
  *                         this shall always be the case!)
  *
  */
-static int __devinit parport_SPP_supported(struct parport *pb)
+static int parport_SPP_supported(struct parport *pb)
 {
 	unsigned char r, w;
 
@@ -1660,7 +1660,7 @@
  * two bits of ECR aren't writable, so we check by writing ECR and
  * reading it back to see if it's what we expect.
  */
-static int __devinit parport_ECR_present(struct parport *pb)
+static int parport_ECR_present(struct parport *pb)
 {
 	struct parport_pc_private *priv = pb->private_data;
 	unsigned char r = 0xc;
@@ -1712,7 +1712,7 @@
  * be misdetected here is rather academic. 
  */
 
-static int __devinit parport_PS2_supported(struct parport *pb)
+static int parport_PS2_supported(struct parport *pb)
 {
 	int ok = 0;
   
@@ -1868,7 +1868,7 @@
 }
 #endif
 
-static int __devinit parport_ECPPS2_supported(struct parport *pb)
+static int parport_ECPPS2_supported(struct parport *pb)
 {
 	const struct parport_pc_private *priv = pb->private_data;
 	int result;
@@ -1886,7 +1886,7 @@
 
 /* EPP mode detection  */
 
-static int __devinit parport_EPP_supported(struct parport *pb)
+static int parport_EPP_supported(struct parport *pb)
 {
 	const struct parport_pc_private *priv = pb->private_data;
 
@@ -1931,7 +1931,7 @@
 	return 1;
 }
 
-static int __devinit parport_ECPEPP_supported(struct parport *pb)
+static int parport_ECPEPP_supported(struct parport *pb)
 {
 	struct parport_pc_private *priv = pb->private_data;
 	int result;
@@ -2073,7 +2073,7 @@
  * When ECP is available we can autoprobe for IRQs.
  * NOTE: If we can autoprobe it, we can register the IRQ.
  */
-static int __devinit parport_irq_probe(struct parport *pb)
+static int parport_irq_probe(struct parport *pb)
 {
 	struct parport_pc_private *priv = pb->private_data;
 
@@ -2779,7 +2779,7 @@
 	/* If set, this is called after probing for ports.  If 'failed'
 	 * is non-zero we couldn't use any of the ports. */
 	void (*postinit_hook) (struct pci_dev *pdev, int failed);
-} cards[] __devinitdata = {
+} cards[] = {
 	/* siig_1p_10x */		{ 1, { { 2, 3 }, } },
 	/* siig_2p_10x */		{ 2, { { 2, 3 }, { 4, 5 }, } },
 	/* siig_1p_20x */		{ 1, { { 0, 1 }, } },
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 827550d..c42ae2c 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -865,6 +865,35 @@
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82375,	quirk_eisa_bridge );
 
 /*
+ * On the MSI-K8T-Neo2Fir Board, the internal Soundcard is disabled
+ * when a PCI-Soundcard is added. The BIOS only gives Options
+ * "Disabled" and "AUTO". This Quirk Sets the corresponding
+ * Register-Value to enable the Soundcard.
+ */
+static void __init k8t_sound_hostbridge(struct pci_dev *dev)
+{
+	unsigned char val;
+
+	printk(KERN_INFO "PCI: Quirk-MSI-K8T Soundcard On\n");
+	pci_read_config_byte(dev, 0x50, &val);
+	if (val == 0x88 || val == 0xc8) {
+		pci_write_config_byte(dev, 0x50, val & (~0x40));
+
+		/* Verify the Change for Status output */
+		pci_read_config_byte(dev, 0x50, &val);
+		if (val & 0x40)
+			printk(KERN_INFO "PCI: MSI-K8T soundcard still off\n");
+		else
+			printk(KERN_INFO "PCI: MSI-K8T soundcard on\n");
+	} else {
+		printk(KERN_INFO "PCI: Unexpected Value in PCI-Register: "
+					"no Change!\n");
+	}
+
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_hostbridge);
+
+/*
  * On ASUS P4B boards, the SMBus PCI Device within the ICH2/4 southbridge
  * is not activated. The myth is that Asus said that they do not want the
  * users to be irritated by just another PCI Device in the Win98 device
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index c4256aa..6fff109 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -479,7 +479,7 @@
 int pnp_start_dev(struct pnp_dev *dev)
 {
 	if (!pnp_can_write(dev)) {
-		pnp_info("Device %s does not supported activation.", dev->dev.bus_id);
+		pnp_info("Device %s does not support activation.", dev->dev.bus_id);
 		return -EINVAL;
 	}
 
@@ -503,7 +503,7 @@
 int pnp_stop_dev(struct pnp_dev *dev)
 {
 	if (!pnp_can_disable(dev)) {
-		pnp_info("Device %s does not supported disabling.", dev->dev.bus_id);
+		pnp_info("Device %s does not support disabling.", dev->dev.bus_id);
 		return -EINVAL;
 	}
 	if (dev->protocol->disable(dev)<0) {
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
index e9c10c0..321a40f 100644
--- a/drivers/serial/m32r_sio.c
+++ b/drivers/serial/m32r_sio.c
@@ -1057,7 +1057,6 @@
 {
 	struct uart_sio_port *up = &m32r_sio_ports[co->index];
 	unsigned int ier;
-	int i;
 
 	/*
 	 *	First save the UER then disable the interrupts
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 9a6b5b3..387a18a 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -2265,7 +2265,7 @@
 };
 
 
-static int radeonfb_pci_register (struct pci_dev *pdev,
+static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
 				  const struct pci_device_id *ent)
 {
 	struct fb_info *info;
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 8d8eadb..372aa17 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -674,13 +674,19 @@
 		total_size = info->fix.smem_len;
 
 	if (p > total_size)
-		return 0;
+		return -EFBIG;
 
-	if (count >= total_size)
+	if (count > total_size) {
+		err = -EFBIG;
 		count = total_size;
+	}
 
-	if (count + p > total_size)
+	if (count + p > total_size) {
+		if (!err)
+			err = -ENOSPC;
+
 		count = total_size - p;
+	}
 
 	buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
 			 GFP_KERNEL);
@@ -722,7 +728,7 @@
 
 	kfree(buffer);
 
-	return (err) ? err : cnt;
+	return (cnt) ? cnt : err;
 }
 
 #ifdef CONFIG_KMOD
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 5fe1979..4e96393 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -73,8 +73,8 @@
  * these flags allow the user to specify that requests for +ve sync
  * should be silently turned in -ve sync.
  */
-static int lowhsync __devinitdata = 0;
-static int lowvsync __devinitdata = 0;
+static int lowhsync;
+static int lowvsync;
 
 /*
  * The hardware state of the graphics card that isn't part of the
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 10e6b3a..0da624e 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -73,7 +73,7 @@
 /* --------------------------------------------------------------------- */
 
 
-static char *mode_option __initdata = NULL;
+static char *mode_option __devinitdata = NULL;
 
 #ifdef MODULE
 
@@ -1545,7 +1545,7 @@
 	return 0;
 }
 
-static void __devinit savage_unmap_mmio (struct fb_info *info)
+static void savage_unmap_mmio (struct fb_info *info)
 {
 	struct savagefb_par *par = info->par;
 	DBG ("savage_unmap_mmio");
@@ -1597,7 +1597,7 @@
 	return 0;
 }
 
-static void __devinit savage_unmap_video (struct fb_info *info)
+static void savage_unmap_video (struct fb_info *info)
 {
 	struct savagefb_par *par = info->par;
 
@@ -1614,7 +1614,7 @@
 	}
 }
 
-static int __devinit savage_init_hw (struct savagefb_par *par)
+static int savage_init_hw (struct savagefb_par *par)
 {
 	unsigned char config1, m, n, n1, n2, sr8, cr3f, cr66 = 0, tmp;
 
diff --git a/fs/Kconfig b/fs/Kconfig
index 2524629..f9b5842 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -842,6 +842,12 @@
 config HUGETLBFS
 	bool "HugeTLB file system support"
 	depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN
+	help
+	  hugetlbfs is a filesystem backing for HugeTLB pages, based on
+	  ramfs. For architectures that support it, say Y here and read
+	  <file:Documentation/vm/hugetlbpage.txt> for details.
+
+	  If unsure, say N.
 
 config HUGETLB_PAGE
 	def_bool HUGETLBFS
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 8a2de03..1a27ecb 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,7 +1,11 @@
 Version 1.42
 ------------
 Fix slow oplock break when mounted to different servers at the same time and
-the tids match and we try to find matching fid on wrong server.
+the tids match and we try to find matching fid on wrong server. Fix read
+looping when signing required by server (2.6.16 kernel only). Fix readdir
+vs. rename race which could cause each to hang. Return . and .. even
+if server does not.  Allow searches to skip first three entries and
+begin at any location. Fix oops in find_writeable_file.
 
 Version 1.41
 ------------
diff --git a/fs/cifs/README b/fs/cifs/README
index b2b4d08..0355003 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -511,6 +511,14 @@
 			support and want to map the uid and gid fields 
 			to values supplied at mount (rather than the 
 			actual values, then set this to zero. (default 1)
+Experimental            When set to 1 used to enable certain experimental
+			features (currently enables multipage writes
+			when signing is enabled, the multipage write
+			performance enhancement was disabled when
+			signing turned on in case buffer was modified
+			just before it was sent, also this flag will
+			be used to use the new experimental sessionsetup
+			code).
 
 These experimental features and tracing can be enabled by changing flags in 
 /proc/fs/cifs (after the cifs module has been installed or built into the 
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index d4b713e..c262d88 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -33,6 +33,7 @@
 #include <linux/vfs.h>
 #include <linux/mempool.h>
 #include <linux/delay.h>
+#include <linux/kthread.h>
 #include "cifsfs.h"
 #include "cifspdu.h"
 #define DECLARE_GLOBALS_HERE
@@ -75,9 +76,6 @@
 module_param(cifs_max_pending, int, 0);
 MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256");
 
-static DECLARE_COMPLETION(cifs_oplock_exited);
-static DECLARE_COMPLETION(cifs_dnotify_exited);
-
 extern mempool_t *cifs_sm_req_poolp;
 extern mempool_t *cifs_req_poolp;
 extern mempool_t *cifs_mid_poolp;
@@ -841,10 +839,6 @@
 	__u16  netfid;
 	int rc;
 
-	daemonize("cifsoplockd");
-	allow_signal(SIGTERM);
-
-	oplockThread = current;
 	do {
 		if (try_to_freeze()) 
 			continue;
@@ -900,9 +894,9 @@
 			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout(1);  /* yield in case q were corrupt */
 		}
-	} while(!signal_pending(current));
-	oplockThread = NULL;
-	complete_and_exit (&cifs_oplock_exited, 0);
+	} while (!kthread_should_stop());
+
+	return 0;
 }
 
 static int cifs_dnotify_thread(void * dummyarg)
@@ -910,10 +904,6 @@
 	struct list_head *tmp;
 	struct cifsSesInfo *ses;
 
-	daemonize("cifsdnotifyd");
-	allow_signal(SIGTERM);
-
-	dnotifyThread = current;
 	do {
 		if(try_to_freeze())
 			continue;
@@ -931,8 +921,9 @@
 				wake_up_all(&ses->server->response_q);
 		}
 		read_unlock(&GlobalSMBSeslock);
-	} while(!signal_pending(current));
-	complete_and_exit (&cifs_dnotify_exited, 0);
+	} while (!kthread_should_stop());
+
+	return 0;
 }
 
 static int __init
@@ -982,32 +973,48 @@
 	}
 
 	rc = cifs_init_inodecache();
-	if (!rc) {
-		rc = cifs_init_mids();
-		if (!rc) {
-			rc = cifs_init_request_bufs();
-			if (!rc) {
-				rc = register_filesystem(&cifs_fs_type);
-				if (!rc) {                
-					rc = (int)kernel_thread(cifs_oplock_thread, NULL, 
-						CLONE_FS | CLONE_FILES | CLONE_VM);
-					if(rc > 0) {
-						rc = (int)kernel_thread(cifs_dnotify_thread, NULL,
-							CLONE_FS | CLONE_FILES | CLONE_VM);
-						if(rc > 0)
-							return 0;
-						else
-							cERROR(1,("error %d create dnotify thread", rc));
-					} else {
-						cERROR(1,("error %d create oplock thread",rc));
-					}
-				}
-				cifs_destroy_request_bufs();
-			}
-			cifs_destroy_mids();
-		}
-		cifs_destroy_inodecache();
+	if (rc)
+		goto out_clean_proc;
+
+	rc = cifs_init_mids();
+	if (rc)
+		goto out_destroy_inodecache;
+
+	rc = cifs_init_request_bufs();
+	if (rc)
+		goto out_destroy_mids;
+
+	rc = register_filesystem(&cifs_fs_type);
+	if (rc)
+		goto out_destroy_request_bufs;
+
+	oplockThread = kthread_run(cifs_oplock_thread, NULL, "cifsoplockd");
+	if (IS_ERR(oplockThread)) {
+		rc = PTR_ERR(oplockThread);
+		cERROR(1,("error %d create oplock thread", rc));
+		goto out_unregister_filesystem;
 	}
+
+	dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd");
+	if (IS_ERR(dnotifyThread)) {
+		rc = PTR_ERR(dnotifyThread);
+		cERROR(1,("error %d create dnotify thread", rc));
+		goto out_stop_oplock_thread;
+	}
+
+	return 0;
+
+ out_stop_oplock_thread:
+	kthread_stop(oplockThread);
+ out_unregister_filesystem:
+	unregister_filesystem(&cifs_fs_type);
+ out_destroy_request_bufs:
+	cifs_destroy_request_bufs();
+ out_destroy_mids:
+	cifs_destroy_mids();
+ out_destroy_inodecache:
+	cifs_destroy_inodecache();
+ out_clean_proc:
 #ifdef CONFIG_PROC_FS
 	cifs_proc_clean();
 #endif
@@ -1025,14 +1032,8 @@
 	cifs_destroy_inodecache();
 	cifs_destroy_mids();
 	cifs_destroy_request_bufs();
-	if(oplockThread) {
-		send_sig(SIGTERM, oplockThread, 1);
-		wait_for_completion(&cifs_oplock_exited);
-	}
-	if(dnotifyThread) {
-		send_sig(SIGTERM, dnotifyThread, 1);
-		wait_for_completion(&cifs_dnotify_exited);
-	}
+	kthread_stop(oplockThread);
+	kthread_stop(dnotifyThread);
 }
 
 MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index d705500..fd36892 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -3119,7 +3119,7 @@
 				psrch_inf->endOfSearch = FALSE;
 
 			psrch_inf->entries_in_buffer  = le16_to_cpu(parms->SearchCount);
-			psrch_inf->index_of_last_entry = 
+			psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
 				psrch_inf->entries_in_buffer;
 			*pnetfid = parms->SearchHandle;
 		} else {
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 0b86d5c..aaf151c 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -3447,7 +3447,10 @@
 			pSesInfo->server->secMode,
 			pSesInfo->server->capabilities,
 			pSesInfo->server->timeZone));
-		if (extended_security
+		if(experimEnabled > 1)
+			rc = CIFS_SessSetup(xid, pSesInfo, CIFS_NTLM /* type */,
+					    &ntlmv2_flag, nls_info);	
+		else if (extended_security
 				&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
 				&& (pSesInfo->server->secType == NTLMSSP)) {
 			cFYI(1, ("New style sesssetup"));
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 1d0ca3e..82315ed 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -139,9 +139,7 @@
 	cifs_sb = CIFS_SB(inode->i_sb);
 	pTcon = cifs_sb->tcon;
 
-	mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(direntry);
-	mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);
 	if(full_path == NULL) {
 		FreeXid(xid);
 		return -ENOMEM;
@@ -316,9 +314,7 @@
 	cifs_sb = CIFS_SB(inode->i_sb);
 	pTcon = cifs_sb->tcon;
 
-	mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(direntry);
-	mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);
 	if(full_path == NULL)
 		rc = -ENOMEM;
 	else if (pTcon->ses->capabilities & CAP_UNIX) {
@@ -440,6 +436,20 @@
 	cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
 	pTcon = cifs_sb->tcon;
 
+	/*
+	 * Don't allow the separator character in a path component.
+	 * The VFS will not allow "/", but "\" is allowed by posix.
+	 */
+	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
+		int i;
+		for (i = 0; i < direntry->d_name.len; i++)
+			if (direntry->d_name.name[i] == '\\') {
+				cFYI(1, ("Invalid file name"));
+				FreeXid(xid);
+				return ERR_PTR(-EINVAL);
+			}
+	}
+
 	/* can not grab the rename sem here since it would
 	deadlock in the cases (beginning of sys_rename itself)
 	in which we already have the sb rename sem */
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
index ec4dfe9..633a938 100644
--- a/fs/cifs/fcntl.c
+++ b/fs/cifs/fcntl.c
@@ -86,9 +86,7 @@
 	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
 	pTcon = cifs_sb->tcon;
 
-	mutex_lock(&file->f_dentry->d_sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(file->f_dentry);
-	mutex_unlock(&file->f_dentry->d_sb->s_vfs_rename_mutex);
 
 	if(full_path == NULL) {
 		rc = -ENOMEM;
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 5c497c5..e152bf6 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -203,9 +203,7 @@
 		}
 	}
 
-	mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(file->f_dentry);
-	mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
 	if (full_path == NULL) {
 		FreeXid(xid);
 		return -ENOMEM;
@@ -906,8 +904,7 @@
 				if (rc != 0)
 					break;
 			}
-			/* BB FIXME We can not sign across two buffers yet */
-			if((pTcon->ses->server->secMode & 
+			if(experimEnabled || (pTcon->ses->server->secMode & 
 			 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0) {
 				struct kvec iov[2];
 				unsigned int len;
@@ -923,13 +920,13 @@
 						*poffset, &bytes_written,
 						iov, 1, long_op);
 			} else
-			/* BB FIXME fixup indentation of line below */
-			rc = CIFSSMBWrite(xid, pTcon,
-				 open_file->netfid,
-				 min_t(const int, cifs_sb->wsize, 
-				       write_size - total_written),
-				 *poffset, &bytes_written,
-				 write_data + total_written, NULL, long_op);
+				rc = CIFSSMBWrite(xid, pTcon,
+					 open_file->netfid,
+					 min_t(const int, cifs_sb->wsize,
+					       write_size - total_written),
+					 *poffset, &bytes_written,
+					 write_data + total_written,
+					 NULL, long_op);
 		}
 		if (rc || (bytes_written == 0)) {
 			if (total_written)
@@ -968,6 +965,16 @@
 	struct cifsFileInfo *open_file;
 	int rc;
 
+	/* Having a null inode here (because mapping->host was set to zero by
+	the VFS or MM) should not happen but we had reports of on oops (due to
+	it being zero) during stress testcases so we need to check for it */
+
+	if(cifs_inode == NULL) {
+		cERROR(1,("Null inode passed to cifs_writeable_file"));
+		dump_stack();
+		return NULL;
+	}
+
 	read_lock(&GlobalSMBSeslock);
 	list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
 		if (open_file->closePend)
@@ -1093,12 +1100,11 @@
 	if (cifs_sb->wsize < PAGE_CACHE_SIZE)
 		return generic_writepages(mapping, wbc);
 
-	/* BB FIXME we do not have code to sign across multiple buffers yet,
-	   so go to older writepage style write which we can sign if needed */
 	if((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
 		if(cifs_sb->tcon->ses->server->secMode &
                           (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
-			return generic_writepages(mapping, wbc);
+			if(!experimEnabled)
+				return generic_writepages(mapping, wbc);
 
 	/*
 	 * BB: Is this meaningful for a non-block-device file system?
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 957ddd1..4093764 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -722,9 +722,7 @@
 	cifs_sb = CIFS_SB(inode->i_sb);
 	pTcon = cifs_sb->tcon;
 
-	mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(direntry);
-	mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
 	if (full_path == NULL) {
 		FreeXid(xid);
 		return -ENOMEM;
@@ -807,9 +805,7 @@
 	cifs_sb = CIFS_SB(inode->i_sb);
 	pTcon = cifs_sb->tcon;
 
-	mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(direntry);
-	mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
 	if (full_path == NULL) {
 		FreeXid(xid);
 		return -ENOMEM;
@@ -1141,9 +1137,7 @@
 			rc = 0;
 	}
 		
-	mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(direntry);
-	mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);
 	if (full_path == NULL) {
 		FreeXid(xid);
 		return -ENOMEM;
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 9562f5b..2ec99f8 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -48,10 +48,8 @@
 /* No need to check for cross device links since server will do that
    BB note DFS case in future though (when we may have to check) */
 
-	mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
 	fromName = build_path_from_dentry(old_file);
 	toName = build_path_from_dentry(direntry);
-	mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
 	if((fromName == NULL) || (toName == NULL)) {
 		rc = -ENOMEM;
 		goto cifs_hl_exit;
@@ -103,9 +101,7 @@
 
 	xid = GetXid();
 
-	mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(direntry);
-	mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);
 
 	if (!full_path)
 		goto out_no_free;
@@ -164,9 +160,7 @@
 	cifs_sb = CIFS_SB(inode->i_sb);
 	pTcon = cifs_sb->tcon;
 
-	mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(direntry);
-	mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
 
 	if(full_path == NULL) {
 		FreeXid(xid);
diff --git a/fs/cifs/ntlmssp.c b/fs/cifs/ntlmssp.c
index 78866f9..115359c 100644
--- a/fs/cifs/ntlmssp.c
+++ b/fs/cifs/ntlmssp.c
@@ -121,6 +121,20 @@
 	}
 
 
+	/* copy session key */
+
+	/* if Unicode, align strings to two byte boundary */
+
+	/* copy user name */ /* BB Do we need to special case null user name? */
+
+	/* copy domain name */
+
+	/* copy Linux version */
+
+	/* copy network operating system name */
+
+	/* update bcc and smb buffer length */
+
 /*	rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buf_type, 0); */
 	/* SMB request buf freed in SendReceive2 */
 
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 2f6e282..b689c50 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -404,9 +404,7 @@
 	if(pTcon == NULL)
 		return -EINVAL;
 
-	mutex_lock(&file->f_dentry->d_sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(file->f_dentry);
-	mutex_unlock(&file->f_dentry->d_sb->s_vfs_rename_mutex);
 
 	if(full_path == NULL) {
 		return -ENOMEM;
@@ -592,6 +590,13 @@
 	first_entry_in_buffer = 
 		cifsFile->srch_inf.index_of_last_entry - 
 			cifsFile->srch_inf.entries_in_buffer;
+
+	/* if first entry in buf is zero then is first buffer
+	in search response data which means it is likely . and ..
+	will be in this buffer, although some servers do not return
+	. and .. for the root of a drive and for those we need
+	to start two entries earlier */
+
 /*	dump_cifs_file_struct(file, "In fce ");*/
 	if(((index_to_find < cifsFile->srch_inf.index_of_last_entry) && 
 	     is_dir_changed(file)) || 
@@ -634,23 +639,14 @@
 		char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + 
 			smbCalcSize((struct smb_hdr *)
 				cifsFile->srch_inf.ntwrk_buf_start);
+
+		current_entry = cifsFile->srch_inf.srch_entries_start;
 		first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
 					- cifsFile->srch_inf.entries_in_buffer;
 		pos_in_buf = index_to_find - first_entry_in_buffer;
 		cFYI(1,("found entry - pos_in_buf %d",pos_in_buf)); 
-		current_entry = cifsFile->srch_inf.srch_entries_start;
 		for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) {
 			/* go entry by entry figuring out which is first */
-			/* if( . or ..)
-				skip */
-			rc = cifs_entry_is_dot(current_entry,cifsFile);
-			if(rc == 1) /* is . or .. so skip */ {
-				cFYI(1,("Entry is .")); /* BB removeme BB */
-				/* continue; */
-			} else if (rc == 2 ) {
-				cFYI(1,("Entry is ..")); /* BB removeme BB */
-				/* continue; */
-			}
 			current_entry = nxt_dir_entry(current_entry,end_of_smb);
 		}
 		if((current_entry == NULL) && (i < pos_in_buf)) {
@@ -770,6 +766,11 @@
 	if(file->f_dentry == NULL)
 		return -ENOENT;
 
+	rc = cifs_entry_is_dot(pfindEntry,pCifsF);
+	/* skip . and .. since we added them first */
+	if(rc != 0) 
+		return 0;
+
 	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
 
 	qstring.name = scratch_buf;
@@ -898,22 +899,22 @@
 
 	switch ((int) file->f_pos) {
 	case 0:
-		/*if (filldir(direntry, ".", 1, file->f_pos,
+		if (filldir(direntry, ".", 1, file->f_pos,
 		     file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
-			cERROR(1, ("Filldir for current dir failed "));
+			cERROR(1, ("Filldir for current dir failed"));
 			rc = -ENOMEM;
 			break;
 		}
-		file->f_pos++; */
+		file->f_pos++;
 	case 1:
-		/* if (filldir(direntry, "..", 2, file->f_pos,
+		if (filldir(direntry, "..", 2, file->f_pos,
 		     file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
 			cERROR(1, ("Filldir for parent dir failed "));
 			rc = -ENOMEM;
 			break;
 		}
-		file->f_pos++; */
-	case 2:
+		file->f_pos++;
+	default:
 		/* 1) If search is active, 
 			is in current search buffer? 
 			if it before then restart search
@@ -927,7 +928,6 @@
 				return rc;
 			}
 		}
-	default:
 		if(file->private_data == NULL) {
 			rc = -EINVAL;
 			FreeXid(xid);
@@ -947,8 +947,6 @@
 		kfree(cifsFile->search_resume_name);
 		cifsFile->search_resume_name = NULL; */
 
-		/* BB account for . and .. in f_pos as special case */
-
 		rc = find_cifs_entry(xid,pTcon, file,
 				&current_entry,&num_to_fill);
 		if(rc) {
@@ -977,7 +975,8 @@
 					  num_to_fill, i));
 				break;
 			}
-
+			/* if buggy server returns . and .. late do
+			we want to check for that here? */
 			rc = cifs_filldir(current_entry, file, 
 					filldir, direntry,tmp_buf);
 			file->f_pos++;
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index 3938444..7754d64 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -62,9 +62,7 @@
 	cifs_sb = CIFS_SB(sb);
 	pTcon = cifs_sb->tcon;
                                                                                      
-	mutex_lock(&sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(direntry);
-	mutex_unlock(&sb->s_vfs_rename_mutex);
 	if(full_path == NULL) {
 		FreeXid(xid);
 		return -ENOMEM;
@@ -116,9 +114,7 @@
 	cifs_sb = CIFS_SB(sb);
 	pTcon = cifs_sb->tcon;
 
-	mutex_lock(&sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(direntry);
-	mutex_unlock(&sb->s_vfs_rename_mutex);
 	if(full_path == NULL) {
 		FreeXid(xid);
 		return -ENOMEM;
@@ -223,9 +219,7 @@
 	cifs_sb = CIFS_SB(sb);
 	pTcon = cifs_sb->tcon;
 
-	mutex_lock(&sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(direntry);
-	mutex_unlock(&sb->s_vfs_rename_mutex);
 	if(full_path == NULL) {
 		FreeXid(xid);
 		return -ENOMEM;
@@ -341,9 +335,7 @@
 	cifs_sb = CIFS_SB(sb);
 	pTcon = cifs_sb->tcon;
 
-	mutex_lock(&sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(direntry);
-	mutex_unlock(&sb->s_vfs_rename_mutex);
 	if(full_path == NULL) {
 		FreeXid(xid);
 		return -ENOMEM;
diff --git a/fs/exec.c b/fs/exec.c
index 4121bb5..3a79d97 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -712,7 +712,7 @@
 		attach_pid(current, PIDTYPE_PID,  current->pid);
 		attach_pid(current, PIDTYPE_PGID, current->signal->pgrp);
 		attach_pid(current, PIDTYPE_SID,  current->signal->session);
-		list_add_tail(&current->tasks, &init_task.tasks);
+		list_add_tail_rcu(&current->tasks, &init_task.tasks);
 
 		current->group_leader = current;
 		leader->group_leader = current;
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index d2b66ba..3ef7391 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -650,7 +650,7 @@
 	svc_wake_up(block->b_daemon);
 }
 
-void nlmsvc_grant_release(void *data)
+static void nlmsvc_grant_release(void *data)
 {
 	struct nlm_rqst		*call = data;
 
diff --git a/fs/locks.c b/fs/locks.c
index dda83d6..efad7988 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -2230,7 +2230,12 @@
 
 	lock_kernel();
 	j = 0;
-	rcu_read_lock();
+
+	/*
+	 * We are not taking a ref to the file structures, so
+	 * we need to acquire ->file_lock.
+	 */
+	spin_lock(&files->file_lock);
 	fdt = files_fdtable(files);
 	for (;;) {
 		unsigned long set;
@@ -2248,7 +2253,7 @@
 			set >>= 1;
 		}
 	}
-	rcu_read_unlock();
+	spin_unlock(&files->file_lock);
 	unlock_kernel();
 }
 EXPORT_SYMBOL(steal_locks);
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index a23f348..cae74dd 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -128,15 +128,14 @@
 static int
 nfs_opendir(struct inode *inode, struct file *filp)
 {
-	int res = 0;
+	int res;
 
 	dfprintk(VFS, "NFS: opendir(%s/%ld)\n",
 			inode->i_sb->s_id, inode->i_ino);
 
 	lock_kernel();
 	/* Call generic open code in order to cache credentials */
-	if (!res)
-		res = nfs_open(inode, filp);
+	res = nfs_open(inode, filp);
 	unlock_kernel();
 	return res;
 }
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 0f583cb..3c72b0c 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -112,10 +112,9 @@
  */
 ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t pos, unsigned long nr_segs)
 {
-	struct dentry *dentry = iocb->ki_filp->f_dentry;
-
 	dprintk("NFS: nfs_direct_IO (%s) off/no(%Ld/%lu) EINVAL\n",
-			dentry->d_name.name, (long long) pos, nr_segs);
+			iocb->ki_filp->f_dentry->d_name.name,
+			(long long) pos, nr_segs);
 
 	return -EINVAL;
 }
@@ -468,7 +467,6 @@
 static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
 {
 	struct nfs_write_data *data = dreq->commit_data;
-	struct rpc_task *task = &data->task;
 
 	data->inode = dreq->inode;
 	data->cred = dreq->ctx->cred;
@@ -489,7 +487,7 @@
 	/* Note: task.tk_ops->rpc_release will free dreq->commit_data */
 	dreq->commit_data = NULL;
 
-	dprintk("NFS: %5u initiated commit call\n", task->tk_pid);
+	dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid);
 
 	lock_kernel();
 	rpc_execute(&data->task);
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index f1df2c8..fade02c 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -534,10 +534,9 @@
  */
 static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
 {
-	struct inode * inode = filp->f_mapping->host;
-
 	dprintk("NFS: nfs_flock(f=%s/%ld, t=%x, fl=%x)\n",
-			inode->i_sb->s_id, inode->i_ino,
+			filp->f_dentry->d_inode->i_sb->s_id,
+			filp->f_dentry->d_inode->i_ino,
 			fl->fl_type, fl->fl_flags);
 
 	/*
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 2f7656b..d0b991a 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -700,12 +700,9 @@
 	/*
 	 * Display superblock I/O counters
 	 */
-	for (cpu = 0; cpu < NR_CPUS; cpu++) {
+	for_each_possible_cpu(cpu) {
 		struct nfs_iostats *stats;
 
-		if (!cpu_possible(cpu))
-			continue;
-
 		preempt_disable();
 		stats = per_cpu_ptr(nfss->io_stats, cpu);
 
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 47ece1d..d86c0db 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1218,7 +1218,7 @@
 	return status;
 }
 
-static void nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, struct nfs4_state *state)
+static int nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, struct nfs4_state *state)
 {
 	struct file *filp;
 
@@ -1227,8 +1227,10 @@
 		struct nfs_open_context *ctx;
 		ctx = (struct nfs_open_context *)filp->private_data;
 		ctx->state = state;
-	} else
-		nfs4_close_state(state, nd->intent.open.flags);
+		return 0;
+	}
+	nfs4_close_state(state, nd->intent.open.flags);
+	return PTR_ERR(filp);
 }
 
 struct dentry *
@@ -1835,7 +1837,7 @@
 			nfs_setattr_update_inode(state->inode, sattr);
 	}
 	if (status == 0 && nd != NULL && (nd->flags & LOOKUP_OPEN))
-		nfs4_intent_set_file(nd, dentry, state);
+		status = nfs4_intent_set_file(nd, dentry, state);
 	else
 		nfs4_close_state(state, flags);
 out:
diff --git a/fs/proc/base.c b/fs/proc/base.c
index a3a3eec..6cc77dc 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -297,16 +297,20 @@
 
 	files = get_files_struct(task);
 	if (files) {
-		rcu_read_lock();
+		/*
+		 * We are not taking a ref to the file structure, so we must
+		 * hold ->file_lock.
+		 */
+		spin_lock(&files->file_lock);
 		file = fcheck_files(files, fd);
 		if (file) {
 			*mnt = mntget(file->f_vfsmnt);
 			*dentry = dget(file->f_dentry);
-			rcu_read_unlock();
+			spin_unlock(&files->file_lock);
 			put_files_struct(files);
 			return 0;
 		}
-		rcu_read_unlock();
+		spin_unlock(&files->file_lock);
 		put_files_struct(files);
 	}
 	return -ENOENT;
@@ -1523,7 +1527,12 @@
 	if (!files)
 		goto out_unlock;
 	inode->i_mode = S_IFLNK;
-	rcu_read_lock();
+
+	/*
+	 * We are not taking a ref to the file structure, so we must
+	 * hold ->file_lock.
+	 */
+	spin_lock(&files->file_lock);
 	file = fcheck_files(files, fd);
 	if (!file)
 		goto out_unlock2;
@@ -1531,7 +1540,7 @@
 		inode->i_mode |= S_IRUSR | S_IXUSR;
 	if (file->f_mode & 2)
 		inode->i_mode |= S_IWUSR | S_IXUSR;
-	rcu_read_unlock();
+	spin_unlock(&files->file_lock);
 	put_files_struct(files);
 	inode->i_op = &proc_pid_link_inode_operations;
 	inode->i_size = 64;
@@ -1541,7 +1550,7 @@
 	return NULL;
 
 out_unlock2:
-	rcu_read_unlock();
+	spin_unlock(&files->file_lock);
 	put_files_struct(files);
 out_unlock:
 	iput(inode);
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index 58c418f..97ae1b9 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -408,8 +408,9 @@
 		acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT);
 		reiserfs_read_unlock_xattrs(inode->i_sb);
 		reiserfs_read_unlock_xattr_i(inode);
-		ret = acl ? 1 : 0;
-		posix_acl_release(acl);
+		ret = (acl && !IS_ERR(acl));
+		if (ret)
+			posix_acl_release(acl);
 	}
 
 	return ret;
diff --git a/fs/splice.c b/fs/splice.c
index 8d57e89..0559e75 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -50,7 +50,8 @@
 	struct page *page = buf->page;
 	struct address_space *mapping = page_mapping(page);
 
-	WARN_ON(!PageLocked(page));
+	lock_page(page);
+
 	WARN_ON(!PageUptodate(page));
 
 	/*
@@ -65,8 +66,10 @@
 	if (PagePrivate(page))
 		try_to_release_page(page, mapping_gfp_mask(mapping));
 
-	if (!remove_mapping(mapping, page))
+	if (!remove_mapping(mapping, page)) {
+		unlock_page(page);
 		return 1;
+	}
 
 	buf->flags |= PIPE_BUF_FLAG_STOLEN | PIPE_BUF_FLAG_LRU;
 	return 0;
@@ -145,8 +148,8 @@
  * pipe buffer operations. Otherwise very similar to the regular pipe_writev().
  */
 static ssize_t move_to_pipe(struct pipe_inode_info *pipe, struct page **pages,
-			    int nr_pages, unsigned long offset,
-			    unsigned long len, unsigned int flags)
+			    int nr_pages, unsigned long len,
+			    unsigned int offset, unsigned int flags)
 {
 	int ret, do_wakeup, i;
 
@@ -243,14 +246,16 @@
 			   unsigned int flags)
 {
 	struct address_space *mapping = in->f_mapping;
-	unsigned int offset, nr_pages;
+	unsigned int loff, offset, nr_pages;
 	struct page *pages[PIPE_BUFFERS];
 	struct page *page;
-	pgoff_t index;
+	pgoff_t index, end_index;
+	loff_t isize;
+	size_t bytes;
 	int i, error;
 
 	index = *ppos >> PAGE_CACHE_SHIFT;
-	offset = *ppos & ~PAGE_CACHE_MASK;
+	loff = offset = *ppos & ~PAGE_CACHE_MASK;
 	nr_pages = (len + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 
 	if (nr_pages > PIPE_BUFFERS)
@@ -268,7 +273,17 @@
 	 * Now fill in the holes:
 	 */
 	error = 0;
+	bytes = 0;
 	for (i = 0; i < nr_pages; i++, index++) {
+		unsigned int this_len;
+
+		if (!len)
+			break;
+
+		/*
+		 * this_len is the max we'll use from this page
+		 */
+		this_len = min(len, PAGE_CACHE_SIZE - loff);
 find_page:
 		/*
 		 * lookup the page for this index
@@ -276,14 +291,6 @@
 		page = find_get_page(mapping, index);
 		if (!page) {
 			/*
-			 * If in nonblock mode then dont block on
-			 * readpage (we've kicked readahead so there
-			 * will be asynchronous progress):
-			 */
-			if (flags & SPLICE_F_NONBLOCK)
-				break;
-
-			/*
 			 * page didn't exist, allocate one
 			 */
 			page = page_cache_alloc_cold(mapping);
@@ -304,6 +311,13 @@
 		 * If the page isn't uptodate, we may need to start io on it
 		 */
 		if (!PageUptodate(page)) {
+			/*
+			 * If in nonblock mode then dont block on waiting
+			 * for an in-flight io page
+			 */
+			if (flags & SPLICE_F_NONBLOCK)
+				break;
+
 			lock_page(page);
 
 			/*
@@ -336,13 +350,43 @@
 					goto find_page;
 				break;
 			}
+
+			/*
+			 * i_size must be checked after ->readpage().
+			 */
+			isize = i_size_read(mapping->host);
+			end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
+			if (unlikely(!isize || index > end_index)) {
+				page_cache_release(page);
+				break;
+			}
+
+			/*
+			 * if this is the last page, see if we need to shrink
+			 * the length and stop
+			 */
+			if (end_index == index) {
+				loff = PAGE_CACHE_SIZE - (isize & ~PAGE_CACHE_MASK);
+				if (bytes + loff > isize) {
+					page_cache_release(page);
+					break;
+				}
+				/*
+				 * force quit after adding this page
+				 */
+				nr_pages = i;
+				this_len = min(this_len, loff);
+			}
 		}
 fill_it:
 		pages[i] = page;
+		bytes += this_len;
+		len -= this_len;
+		loff = 0;
 	}
 
 	if (i)
-		return move_to_pipe(pipe, pages, i, offset, len, flags);
+		return move_to_pipe(pipe, pages, i, bytes, offset, flags);
 
 	return error;
 }
@@ -369,17 +413,20 @@
 	while (len) {
 		ret = __generic_file_splice_read(in, ppos, pipe, len, flags);
 
-		if (ret <= 0)
+		if (ret < 0)
 			break;
+		else if (!ret) {
+			if (spliced)
+				break;
+			if (flags & SPLICE_F_NONBLOCK) {
+				ret = -EAGAIN;
+				break;
+			}
+		}
 
 		*ppos += ret;
 		len -= ret;
 		spliced += ret;
-
-		if (!(flags & SPLICE_F_NONBLOCK))
-			continue;
-		ret = -EAGAIN;
-		break;
 	}
 
 	if (spliced)
@@ -474,14 +521,12 @@
 	if (sd->flags & SPLICE_F_MOVE) {
 		/*
 		 * If steal succeeds, buf->page is now pruned from the vm
-		 * side (LRU and page cache) and we can reuse it.
+		 * side (LRU and page cache) and we can reuse it. The page
+		 * will also be looked on successful return.
 		 */
 		if (buf->ops->steal(info, buf))
 			goto find_page;
 
-		/*
-		 * this will also set the page locked
-		 */
 		page = buf->page;
 		if (add_to_page_cache(page, mapping, index, gfp_mask))
 			goto find_page;
@@ -490,15 +535,27 @@
 			lru_cache_add(page);
 	} else {
 find_page:
-		ret = -ENOMEM;
-		page = find_or_create_page(mapping, index, gfp_mask);
-		if (!page)
-			goto out_nomem;
+		page = find_lock_page(mapping, index);
+		if (!page) {
+			ret = -ENOMEM;
+			page = page_cache_alloc_cold(mapping);
+			if (unlikely(!page))
+				goto out_nomem;
+
+			/*
+			 * This will also lock the page
+			 */
+			ret = add_to_page_cache_lru(page, mapping, index,
+						    gfp_mask);
+			if (unlikely(ret))
+				goto out;
+		}
 
 		/*
-		 * If the page is uptodate, it is also locked. If it isn't
-		 * uptodate, we can mark it uptodate if we are filling the
-		 * full page. Otherwise we need to read it in first...
+		 * We get here with the page locked. If the page is also
+		 * uptodate, we don't need to do more. If it isn't, we
+		 * may need to bring it in if we are not going to overwrite
+		 * the full page.
 		 */
 		if (!PageUptodate(page)) {
 			if (sd->len < PAGE_CACHE_SIZE) {
@@ -520,10 +577,8 @@
 					ret = -EIO;
 					goto out;
 				}
-			} else {
-				WARN_ON(!PageLocked(page));
+			} else
 				SetPageUptodate(page);
-			}
 		}
 	}
 
@@ -552,10 +607,10 @@
 	mark_page_accessed(page);
 	balance_dirty_pages_ratelimited(mapping);
 out:
-	if (!(buf->flags & PIPE_BUF_FLAG_STOLEN)) {
+	if (!(buf->flags & PIPE_BUF_FLAG_STOLEN))
 		page_cache_release(page);
-		unlock_page(page);
-	}
+
+	unlock_page(page);
 out_nomem:
 	buf->ops->unmap(info, buf);
 	return ret;
@@ -687,22 +742,26 @@
 	ssize_t ret;
 
 	ret = move_from_pipe(pipe, out, ppos, len, flags, pipe_to_file);
-
-	/*
-	 * If file or inode is SYNC and we actually wrote some data, sync it.
-	 */
-	if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(mapping->host))
-	    && ret > 0) {
+	if (ret > 0) {
 		struct inode *inode = mapping->host;
-		int err;
 
-		mutex_lock(&inode->i_mutex);
-		err = generic_osync_inode(mapping->host, mapping,
-					  OSYNC_METADATA|OSYNC_DATA);
-		mutex_unlock(&inode->i_mutex);
+		*ppos += ret;
 
-		if (err)
-			ret = err;
+		/*
+		 * If file or inode is SYNC and we actually wrote some data,
+		 * sync it.
+		 */
+		if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) {
+			int err;
+
+			mutex_lock(&inode->i_mutex);
+			err = generic_osync_inode(inode, mapping,
+						  OSYNC_METADATA|OSYNC_DATA);
+			mutex_unlock(&inode->i_mutex);
+
+			if (err)
+				ret = err;
+		}
 	}
 
 	return ret;
@@ -904,6 +963,7 @@
 {
 	struct pipe_inode_info *pipe;
 	loff_t offset, *off;
+	long ret;
 
 	pipe = in->f_dentry->d_inode->i_pipe;
 	if (pipe) {
@@ -918,7 +978,12 @@
 		} else
 			off = &out->f_pos;
 
-		return do_splice_from(pipe, out, off, len, flags);
+		ret = do_splice_from(pipe, out, off, len, flags);
+
+		if (off_out && copy_to_user(off_out, off, sizeof(loff_t)))
+			ret = -EFAULT;
+
+		return ret;
 	}
 
 	pipe = out->f_dentry->d_inode->i_pipe;
@@ -934,7 +999,12 @@
 		} else
 			off = &in->f_pos;
 
-		return do_splice_to(in, off, pipe, len, flags);
+		ret = do_splice_to(in, off, pipe, len, flags);
+
+		if (off_in && copy_to_user(off_in, off, sizeof(loff_t)))
+			ret = -EFAULT;
+
+		return ret;
 	}
 
 	return -EINVAL;
@@ -979,7 +1049,9 @@
 		     size_t len, unsigned int flags)
 {
 	struct pipe_buffer *ibuf, *obuf;
-	int ret = 0, do_wakeup = 0, i;
+	int ret, do_wakeup, i, ipipe_first;
+
+	ret = do_wakeup = ipipe_first = 0;
 
 	/*
 	 * Potential ABBA deadlock, work around it by ordering lock
@@ -987,6 +1059,7 @@
 	 * could deadlock (one doing tee from A -> B, the other from B -> A).
 	 */
 	if (ipipe->inode < opipe->inode) {
+		ipipe_first = 1;
 		mutex_lock(&ipipe->inode->i_mutex);
 		mutex_lock(&opipe->inode->i_mutex);
 	} else {
@@ -1035,9 +1108,11 @@
 
 			/*
 			 * We have input available, but no output room.
-			 * If we already copied data, return that.
+			 * If we already copied data, return that. If we
+			 * need to drop the opipe lock, it must be ordered
+			 * last to avoid deadlocks.
 			 */
-			if (flags & SPLICE_F_NONBLOCK) {
+			if ((flags & SPLICE_F_NONBLOCK) || !ipipe_first) {
 				if (!ret)
 					ret = -EAGAIN;
 				break;
@@ -1071,7 +1146,12 @@
 			if (ret)
 				break;
 		}
-		if (flags & SPLICE_F_NONBLOCK) {
+		/*
+		 * pipe_wait() drops the ipipe mutex. To avoid deadlocks
+		 * with another process, we can only safely do that if
+		 * the ipipe lock is ordered last.
+		 */
+		if ((flags & SPLICE_F_NONBLOCK) || ipipe_first) {
 			if (!ret)
 				ret = -EAGAIN;
 			break;
diff --git a/include/asm-i386/atomic.h b/include/asm-i386/atomic.h
index 22d80ec..4ddce52 100644
--- a/include/asm-i386/atomic.h
+++ b/include/asm-i386/atomic.h
@@ -183,6 +183,7 @@
 {
 	int __i;
 #ifdef CONFIG_M386
+	unsigned long flags;
 	if(unlikely(boot_cpu_data.x86==3))
 		goto no_xadd;
 #endif
@@ -196,10 +197,10 @@
 
 #ifdef CONFIG_M386
 no_xadd: /* Legacy 386 processor */
-	local_irq_disable();
+	local_irq_save(flags);
 	__i = atomic_read(v);
 	atomic_set(v, i + __i);
-	local_irq_enable();
+	local_irq_restore(flags);
 	return i + __i;
 #endif
 }
diff --git a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h
index 5c0b587..b44bfc6 100644
--- a/include/asm-i386/cpufeature.h
+++ b/include/asm-i386/cpufeature.h
@@ -71,6 +71,7 @@
 #define X86_FEATURE_P4		(3*32+ 7) /* P4 */
 #define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant rate */
 #define X86_FEATURE_UP		(3*32+ 9) /* smp kernel running on up */
+#define X86_FEATURE_FXSAVE_LEAK (3*32+10) /* FXSAVE leaks FOP/FIP/FOP */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
 #define X86_FEATURE_XMM3	(4*32+ 0) /* Streaming SIMD Extensions-3 */
diff --git a/include/asm-i386/i387.h b/include/asm-i386/i387.h
index 152d0ba..7b1f011 100644
--- a/include/asm-i386/i387.h
+++ b/include/asm-i386/i387.h
@@ -13,6 +13,7 @@
 
 #include <linux/sched.h>
 #include <linux/init.h>
+#include <linux/kernel_stat.h>
 #include <asm/processor.h>
 #include <asm/sigcontext.h>
 #include <asm/user.h>
@@ -38,17 +39,38 @@
 extern void kernel_fpu_begin(void);
 #define kernel_fpu_end() do { stts(); preempt_enable(); } while(0)
 
+/* We need a safe address that is cheap to find and that is already
+   in L1 during context switch. The best choices are unfortunately
+   different for UP and SMP */
+#ifdef CONFIG_SMP
+#define safe_address (__per_cpu_offset[0])
+#else
+#define safe_address (kstat_cpu(0).cpustat.user)
+#endif
+
 /*
  * These must be called with preempt disabled
  */
 static inline void __save_init_fpu( struct task_struct *tsk )
 {
+	/* Use more nops than strictly needed in case the compiler
+	   varies code */
 	alternative_input(
-		"fnsave %1 ; fwait ;" GENERIC_NOP2,
-		"fxsave %1 ; fnclex",
+		"fnsave %[fx] ;fwait;" GENERIC_NOP8 GENERIC_NOP4,
+		"fxsave %[fx]\n"
+		"bt $7,%[fsw] ; jc 1f ; fnclex\n1:",
 		X86_FEATURE_FXSR,
-		"m" (tsk->thread.i387.fxsave)
-		:"memory");
+		[fx] "m" (tsk->thread.i387.fxsave),
+		[fsw] "m" (tsk->thread.i387.fxsave.swd) : "memory");
+	/* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
+	   is pending.  Clear the x87 state here by setting it to fixed
+   	   values. __per_cpu_offset[0] is a random variable that should be in L1 */
+	alternative_input(
+		GENERIC_NOP8 GENERIC_NOP2,
+		"emms\n\t"	  	/* clear stack tags */
+		"fildl %[addr]", 	/* set F?P to defined value */
+		X86_FEATURE_FXSAVE_LEAK,
+		[addr] "m" (safe_address));
 	task_thread_info(tsk)->status &= ~TS_USEDFPU;
 }
 
diff --git a/include/asm-m32r/assembler.h b/include/asm-m32r/assembler.h
index b7f4d8a..1a1aa17 100644
--- a/include/asm-m32r/assembler.h
+++ b/include/asm-m32r/assembler.h
@@ -109,6 +109,9 @@
 	push	r13
 	mvfachi	r13
 	push	r13
+	ldi	r13, #0
+	push	r13		; dummy push acc1h
+	push	r13		; dummy push acc1l
 #else
 #error unknown isa configuration
 #endif
@@ -156,6 +159,8 @@
 	pop	r13
 	mvtaclo	r13, a1
 #elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+	pop	r13		; dummy pop acc1h
+	pop	r13		; dummy pop acc1l
 	pop	r13
 	mvtachi	r13
 	pop	r13
diff --git a/include/asm-m32r/mappi3/mappi3_pld.h b/include/asm-m32r/mappi3/mappi3_pld.h
index 1d3c25d..031369a 100644
--- a/include/asm-m32r/mappi3/mappi3_pld.h
+++ b/include/asm-m32r/mappi3/mappi3_pld.h
@@ -53,16 +53,14 @@
 /* Power Control of MMC and CF */
 #define PLD_CPCR		__reg16(PLD_BASE + 0x14000)
 
-
-/*==== ICU ====*/
-#define  M32R_IRQ_PC104        (5)   /* INT4(PC/104) */
-#define  M32R_IRQ_I2C          (28)  /* I2C-BUS     */
-#define  PLD_IRQ_CFIREQ       (6)  /* INT5 CFC Card Interrupt */
-#define  PLD_IRQ_CFC_INSERT   (7)  /* INT6 CFC Card Insert */
-#define  PLD_IRQ_IDEIREQ      (8)  /* INT7 IDE Interrupt   */
-#define  PLD_IRQ_MMCCARD      (43)  /* MMC Card Insert */
-#define  PLD_IRQ_MMCIRQ       (44)  /* MMC Transfer Done */
-
+/* ICU */
+#define M32R_IRQ_PC104		(5)	/* INT4(PC/104) */
+#define M32R_IRQ_I2C		(28)	/* I2C-BUS */
+#define PLD_IRQ_CFIREQ		(6)	/* INT5 CFC Card Interrupt */
+#define PLD_IRQ_CFC_INSERT	(7)	/* INT6 CFC Card Insert & Eject */
+#define PLD_IRQ_IDEIREQ		(8)	/* INT7 IDE Interrupt */
+#define PLD_IRQ_MMCCARD		(43)	/* MMC Card Insert */
+#define PLD_IRQ_MMCIRQ		(44)	/* MMC Transfer Done */
 
 #if 0
 /* LED Control
@@ -97,7 +95,6 @@
 #define PLD_CRC16ADATA		__reg16(PLD_BASE + 0x18008)
 #define PLD_CRC16AINDATA	__reg16(PLD_BASE + 0x1800a)
 
-
 #if 0
 /* RTC */
 #define PLD_RTCCR		__reg16(PLD_BASE + 0x1c000)
@@ -140,4 +137,7 @@
 
 #endif
 
+/* Reset Control */
+#define PLD_REBOOT		__reg16(PLD_BASE + 0x38000)
+
 #endif	/* _MAPPI3_PLD.H */
diff --git a/include/asm-m32r/ptrace.h b/include/asm-m32r/ptrace.h
index 0d058b2..53c7924 100644
--- a/include/asm-m32r/ptrace.h
+++ b/include/asm-m32r/ptrace.h
@@ -43,6 +43,14 @@
 #define PT_ACC1L	18
 #define PT_ACCH		PT_ACC0H
 #define PT_ACCL		PT_ACC0L
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+#define PT_ACCH		15
+#define PT_ACCL		16
+#define PT_DUMMY_ACC1H	17
+#define PT_DUMMY_ACC1L	18
+#else
+#error unknown isa conifiguration
+#endif
 #define PT_PSW		19
 #define PT_BPC		20
 #define PT_BBPSW	21
@@ -52,21 +60,6 @@
 #define PT_LR		25
 #define PT_SPI		26
 #define PT_ORIGR0	27
-#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
-#define PT_ACCH		15
-#define PT_ACCL		16
-#define PT_PSW		17
-#define PT_BPC		18
-#define PT_BBPSW	19
-#define PT_BBPC		20
-#define PT_SPU		21
-#define PT_FP		22
-#define PT_LR		23
-#define PT_SPI		24
-#define PT_ORIGR0	25
-#else
-#error unknown isa conifiguration
-#endif
 
 /* virtual pt_reg entry for gdb */
 #define PT_PC		30
@@ -121,6 +114,8 @@
 #elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
 	unsigned long acch;
 	unsigned long accl;
+	unsigned long dummy_acc1h;
+	unsigned long dummy_acc1l;
 #else
 #error unknown isa configuration
 #endif
diff --git a/include/asm-m32r/semaphore.h b/include/asm-m32r/semaphore.h
index bf447c5..81750ed 100644
--- a/include/asm-m32r/semaphore.h
+++ b/include/asm-m32r/semaphore.h
@@ -9,7 +9,7 @@
  * SMP- and interrupt-safe semaphores..
  *
  * Copyright (C) 1996  Linus Torvalds
- * Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
  */
 
 #include <linux/config.h>
@@ -77,27 +77,8 @@
  */
 static inline void down(struct semaphore * sem)
 {
-	unsigned long flags;
-	long count;
-
 	might_sleep();
-	local_irq_save(flags);
-	__asm__ __volatile__ (
-		"# down				\n\t"
-		DCACHE_CLEAR("%0", "r4", "%1")
-		M32R_LOCK" %0, @%1;		\n\t"
-		"addi	%0, #-1;		\n\t"
-		M32R_UNLOCK" %0, @%1;		\n\t"
-		: "=&r" (count)
-		: "r" (&sem->count)
-		: "memory"
-#ifdef CONFIG_CHIP_M32700_TS1
-		, "r4"
-#endif	/* CONFIG_CHIP_M32700_TS1 */
-	);
-	local_irq_restore(flags);
-
-	if (unlikely(count < 0))
+	if (unlikely(atomic_dec_return(&sem->count) < 0))
 		__down(sem);
 }
 
@@ -107,28 +88,10 @@
  */
 static inline int down_interruptible(struct semaphore * sem)
 {
-	unsigned long flags;
-	long count;
 	int result = 0;
 
 	might_sleep();
-	local_irq_save(flags);
-	__asm__ __volatile__ (
-		"# down_interruptible		\n\t"
-		DCACHE_CLEAR("%0", "r4", "%1")
-		M32R_LOCK" %0, @%1;		\n\t"
-		"addi	%0, #-1;		\n\t"
-		M32R_UNLOCK" %0, @%1;		\n\t"
-		: "=&r" (count)
-		: "r" (&sem->count)
-		: "memory"
-#ifdef CONFIG_CHIP_M32700_TS1
-		, "r4"
-#endif	/* CONFIG_CHIP_M32700_TS1 */
-	);
-	local_irq_restore(flags);
-
-	if (unlikely(count < 0))
+	if (unlikely(atomic_dec_return(&sem->count) < 0))
 		result = __down_interruptible(sem);
 
 	return result;
@@ -174,26 +137,7 @@
  */
 static inline void up(struct semaphore * sem)
 {
-	unsigned long flags;
-	long count;
-
-	local_irq_save(flags);
-	__asm__ __volatile__ (
-		"# up				\n\t"
-		DCACHE_CLEAR("%0", "r4", "%1")
-		M32R_LOCK" %0, @%1;		\n\t"
-		"addi	%0, #1;			\n\t"
-		M32R_UNLOCK" %0, @%1;		\n\t"
-		: "=&r" (count)
-		: "r" (&sem->count)
-		: "memory"
-#ifdef CONFIG_CHIP_M32700_TS1
-		, "r4"
-#endif	/* CONFIG_CHIP_M32700_TS1 */
-	);
-	local_irq_restore(flags);
-
-	if (unlikely(count <= 0))
+	if (unlikely(atomic_inc_return(&sem->count) <= 0))
 		__up(sem);
 }
 
diff --git a/include/asm-m32r/sigcontext.h b/include/asm-m32r/sigcontext.h
index c233e2d..942b8a3 100644
--- a/include/asm-m32r/sigcontext.h
+++ b/include/asm-m32r/sigcontext.h
@@ -32,6 +32,8 @@
 #elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
 	unsigned long sc_acch;
 	unsigned long sc_accl;
+	unsigned long sc_dummy_acc1h;
+	unsigned long sc_dummy_acc1l;
 #else
 #error unknown isa configuration
 #endif
diff --git a/include/asm-m32r/system.h b/include/asm-m32r/system.h
index c5ab5da..e55013f 100644
--- a/include/asm-m32r/system.h
+++ b/include/asm-m32r/system.h
@@ -6,8 +6,8 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2001  by Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
- * Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ * Copyright (C) 2001  Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
+ * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
  */
 
 #include <linux/config.h>
@@ -19,49 +19,28 @@
  * switch_to(prev, next) should switch from task `prev' to `next'
  * `prev' will never be the same as `next'.
  *
- * `next' and `prev' should be struct task_struct, but it isn't always defined
+ * `next' and `prev' should be task_t, but it isn't always defined
  */
 
 #define switch_to(prev, next, last)  do { \
-	register unsigned long  arg0 __asm__ ("r0") = (unsigned long)prev; \
-	register unsigned long  arg1 __asm__ ("r1") = (unsigned long)next; \
-	register unsigned long  *oldsp __asm__ ("r2") = &(prev->thread.sp); \
-	register unsigned long  *newsp __asm__ ("r3") = &(next->thread.sp); \
-	register unsigned long  *oldlr __asm__ ("r4") = &(prev->thread.lr); \
-	register unsigned long  *newlr __asm__ ("r5") = &(next->thread.lr); \
-	register struct task_struct  *__last __asm__ ("r6"); \
 	__asm__ __volatile__ ( \
-		"st     r8, @-r15                                 \n\t" \
-		"st     r9, @-r15                                 \n\t" \
-		"st    r10, @-r15                                 \n\t" \
-		"st    r11, @-r15                                 \n\t" \
-		"st    r12, @-r15                                 \n\t" \
-		"st    r13, @-r15                                 \n\t" \
-		"st    r14, @-r15                                 \n\t" \
-		"seth  r14, #high(1f)                             \n\t" \
-		"or3   r14, r14, #low(1f)                         \n\t" \
-		"st    r14, @r4    ; store old LR                 \n\t" \
-		"st    r15, @r2    ; store old SP                 \n\t" \
-		"ld    r15, @r3    ; load new SP                  \n\t" \
-		"st     r0, @-r15  ; store 'prev' onto new stack  \n\t" \
-		"ld    r14, @r5    ; load new LR                  \n\t" \
-		"jmp   r14                                        \n\t" \
-		".fillinsn                                        \n  " \
-		"1:                                               \n\t" \
-		"ld     r6, @r15+  ; load 'prev' from new stack   \n\t" \
-		"ld    r14, @r15+                                 \n\t" \
-		"ld    r13, @r15+                                 \n\t" \
-		"ld    r12, @r15+                                 \n\t" \
-		"ld    r11, @r15+                                 \n\t" \
-		"ld    r10, @r15+                                 \n\t" \
-		"ld     r9, @r15+                                 \n\t" \
-		"ld     r8, @r15+                                 \n\t" \
-		: "=&r" (__last) \
-		: "r" (arg0), "r" (arg1), "r" (oldsp), "r" (newsp), \
-		  "r" (oldlr), "r" (newlr) \
-		: "memory" \
+		"	seth	lr, #high(1f)				\n" \
+		"	or3	lr, lr, #low(1f)			\n" \
+		"	st	lr, @%4  ; store old LR			\n" \
+		"	ld	lr, @%5  ; load new LR			\n" \
+		"	st	sp, @%2  ; store old SP			\n" \
+		"	ld	sp, @%3  ; load new SP			\n" \
+		"	push	%1  ; store `prev' on new stack		\n" \
+		"	jmp	lr					\n" \
+		"	.fillinsn					\n" \
+		"1:							\n" \
+		"	pop	%0  ; restore `__last' from new stack	\n" \
+		: "=r" (last) \
+		: "0" (prev), \
+		  "r" (&(prev->thread.sp)), "r" (&(next->thread.sp)), \
+		  "r" (&(prev->thread.lr)), "r" (&(next->thread.lr)) \
+		: "memory", "lr" \
 	); \
-	last = __last; \
 } while(0)
 
 /*
@@ -167,8 +146,8 @@
 #define DCACHE_CLEAR(reg0, reg1, addr)
 #endif	/* CONFIG_CHIP_M32700_TS1 */
 
-static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr,
-	int size)
+static inline unsigned long
+__xchg(unsigned long x, volatile void * ptr, int size)
 {
 	unsigned long flags;
 	unsigned long tmp = 0;
@@ -220,7 +199,7 @@
 
 #define __HAVE_ARCH_CMPXCHG	1
 
-static __inline__ unsigned long
+static inline unsigned long
 __cmpxchg_u32(volatile unsigned int *p, unsigned int old, unsigned int new)
 {
 	unsigned long flags;
@@ -254,7 +233,7 @@
    if something tries to do an invalid cmpxchg().  */
 extern void __cmpxchg_called_with_bad_pointer(void);
 
-static __inline__ unsigned long
+static inline unsigned long
 __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
 {
 	switch (size) {
diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h
index d5677cb..18ca29e 100644
--- a/include/asm-powerpc/iommu.h
+++ b/include/asm-powerpc/iommu.h
@@ -70,17 +70,18 @@
 extern struct iommu_table *iommu_init_table(struct iommu_table * tbl);
 
 extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
-		struct scatterlist *sglist, int nelems,
+		struct scatterlist *sglist, int nelems, unsigned long mask,
 		enum dma_data_direction direction);
 extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
 		int nelems, enum dma_data_direction direction);
 
 extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
-		dma_addr_t *dma_handle, gfp_t flag);
+		dma_addr_t *dma_handle, unsigned long mask, gfp_t flag);
 extern void iommu_free_coherent(struct iommu_table *tbl, size_t size,
 		void *vaddr, dma_addr_t dma_handle);
 extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
-		size_t size, enum dma_data_direction direction);
+		size_t size, unsigned long mask,
+		enum dma_data_direction direction);
 extern void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
 		size_t size, enum dma_data_direction direction);
 
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
index 5ed8476..0f9254c 100644
--- a/include/asm-powerpc/machdep.h
+++ b/include/asm-powerpc/machdep.h
@@ -253,7 +253,11 @@
 
 #define __machine_desc __attribute__ ((__section__ (".machine.desc")))
 
-#define define_machine(name) struct machdep_calls mach_##name __machine_desc =
+#define define_machine(name)					\
+	extern struct machdep_calls mach_##name;		\
+	EXPORT_SYMBOL(mach_##name);				\
+	struct machdep_calls mach_##name __machine_desc =
+
 #define machine_is(name) \
 	({ \
 		extern struct machdep_calls mach_##name \
diff --git a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h
index 2a911aa..45feff8 100644
--- a/include/asm-sparc/unistd.h
+++ b/include/asm-sparc/unistd.h
@@ -248,7 +248,7 @@
 #define __NR_setfsgid           229 /* Linux Specific                              */
 #define __NR__newselect         230 /* Linux Specific                              */
 #define __NR_time               231 /* Linux Specific                              */
-#define __NR_sys_splice         232 /* Linux Specific                              */
+#define __NR_splice             232 /* Linux Specific                              */
 #define __NR_stime              233 /* Linux Specific                              */
 #define __NR_statfs64           234 /* Linux Specific                              */
 #define __NR_fstatfs64          235 /* Linux Specific                              */
diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
index 6ada6a8..597f692 100644
--- a/include/asm-sparc64/unistd.h
+++ b/include/asm-sparc64/unistd.h
@@ -250,7 +250,7 @@
 #ifdef __KERNEL__
 #define __NR_time		231 /* Linux sparc32                               */
 #endif
-#define __NR_sys_splice         232 /* Linux Specific                              */
+#define __NR_splice             232 /* Linux Specific                              */
 #define __NR_stime              233 /* Linux Specific                              */
 #define __NR_statfs64           234 /* Linux Specific                              */
 #define __NR_fstatfs64          235 /* Linux Specific                              */
diff --git a/include/asm-x86_64/cache.h b/include/asm-x86_64/cache.h
index c8043a1..f8dff1c 100644
--- a/include/asm-x86_64/cache.h
+++ b/include/asm-x86_64/cache.h
@@ -20,8 +20,8 @@
        __attribute__((__section__(".data.page_aligned")))
 #endif
 
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
-
 #endif
 
+#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+
 #endif
diff --git a/include/asm-x86_64/cpufeature.h b/include/asm-x86_64/cpufeature.h
index 76bb619..662964b 100644
--- a/include/asm-x86_64/cpufeature.h
+++ b/include/asm-x86_64/cpufeature.h
@@ -64,6 +64,7 @@
 #define X86_FEATURE_REP_GOOD	(3*32+ 4) /* rep microcode works well on this CPU */
 #define X86_FEATURE_CONSTANT_TSC (3*32+5) /* TSC runs at constant rate */
 #define X86_FEATURE_SYNC_RDTSC  (3*32+6)  /* RDTSC syncs CPU core */
+#define X86_FEATURE_FXSAVE_LEAK (3*32+7)  /* FIP/FOP/FDP leaks through FXSAVE */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
 #define X86_FEATURE_XMM3	(4*32+ 0) /* Streaming SIMD Extensions-3 */
diff --git a/include/asm-x86_64/i387.h b/include/asm-x86_64/i387.h
index 876eb9a..cba8a3b 100644
--- a/include/asm-x86_64/i387.h
+++ b/include/asm-x86_64/i387.h
@@ -72,6 +72,23 @@
 #define set_fpu_swd(t,val) ((t)->thread.i387.fxsave.swd = (val))
 #define set_fpu_fxsr_twd(t,val) ((t)->thread.i387.fxsave.twd = (val))
 
+#define X87_FSW_ES (1 << 7)	/* Exception Summary */
+
+/* AMD CPUs don't save/restore FDP/FIP/FOP unless an exception
+   is pending. Clear the x87 state here by setting it to fixed
+   values. The kernel data segment can be sometimes 0 and sometimes
+   new user value. Both should be ok.
+   Use the PDA as safe address because it should be already in L1. */
+static inline void clear_fpu_state(struct i387_fxsave_struct *fx)
+{
+	if (unlikely(fx->swd & X87_FSW_ES))
+		 asm volatile("fnclex");
+	alternative_input(ASM_NOP8 ASM_NOP2,
+	     	     "    emms\n"		/* clear stack tags */
+	     	     "    fildl %%gs:0",	/* load to clear state */
+		     X86_FEATURE_FXSAVE_LEAK);
+}
+
 static inline int restore_fpu_checking(struct i387_fxsave_struct *fx) 
 { 
 	int err;
@@ -119,6 +136,7 @@
 #endif
 	if (unlikely(err))
 		__clear_user(fx, sizeof(struct i387_fxsave_struct));
+	/* No need to clear here because the caller clears USED_MATH */
 	return err;
 } 
 
@@ -149,7 +167,7 @@
 				"i" (offsetof(__typeof__(*tsk),
 					      thread.i387.fxsave)));
 #endif
-	__asm__ __volatile__("fnclex");
+	clear_fpu_state(&tsk->thread.i387.fxsave);
 }
 
 static inline void kernel_fpu_begin(void)
diff --git a/include/asm-x86_64/percpu.h b/include/asm-x86_64/percpu.h
index 4405b4a..7f33aaf 100644
--- a/include/asm-x86_64/percpu.h
+++ b/include/asm-x86_64/percpu.h
@@ -26,7 +26,7 @@
 #define percpu_modcopy(pcpudst, src, size)			\
 do {								\
 	unsigned int __i;					\
-	for_each_cpu(__i)					\
+	for_each_possible_cpu(__i)				\
 		memcpy((pcpudst)+__per_cpu_offset(__i),		\
 		       (src), (size));				\
 } while (0)
diff --git a/include/asm-xtensa/ioctls.h b/include/asm-xtensa/ioctls.h
index 10c4434..3b89a77 100644
--- a/include/asm-xtensa/ioctls.h
+++ b/include/asm-xtensa/ioctls.h
@@ -107,6 +107,6 @@
 #define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* Set multiport config */
 
 #define TIOCMIWAIT	_IO('T', 92) /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	_IOR('T', 93, struct async_icount) /* read serial port inline interrupt counts */
+#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 
 #endif /* _XTENSA_IOCTLS_H */
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 8d2db41..a8bef1d 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -1220,7 +1220,6 @@
 enum {
 	/* Uses ISA control ports not PCI ones. */
 	IDEPCI_FLAG_ISA_PORTS		= (1 << 0),
-	IDEPCI_FLAG_FORCE_PDC		= (1 << 1),
 };
 
 typedef struct ide_pci_device_s {
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index 4ca3e6a..9112063 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -99,10 +99,7 @@
 	return -ENOSYS;
 }
 
-#if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \
-	|| defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)
 extern int add_memory(u64 start, u64 size);
 extern int remove_memory(u64 start, u64 size);
-#endif
 
 #endif /* __LINUX_MEMORY_HOTPLUG_H */
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 8d03e10..d6fe048 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -356,6 +356,10 @@
 #define PCI_DEVICE_ID_ATI_IXP300_SATA   0x436e
 #define PCI_DEVICE_ID_ATI_IXP400_IDE	0x4376
 #define PCI_DEVICE_ID_ATI_IXP400_SATA   0x4379
+#define PCI_DEVICE_ID_ATI_IXP400_SATA2	0x437a
+#define PCI_DEVICE_ID_ATI_IXP600_SATA	0x4380
+#define PCI_DEVICE_ID_ATI_IXP600_SRAID	0x4381
+#define PCI_DEVICE_ID_ATI_IXP600_IDE	0x438c
 
 #define PCI_VENDOR_ID_VLSI		0x1004
 #define PCI_DEVICE_ID_VLSI_82C592	0x0005
diff --git a/include/linux/sched.h b/include/linux/sched.h
index b7d31e2..29b7d4f 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1192,8 +1192,7 @@
 #define remove_parent(p)	list_del_init(&(p)->sibling)
 #define add_parent(p)		list_add_tail(&(p)->sibling,&(p)->parent->children)
 
-#define next_task(p)	list_entry((p)->tasks.next, struct task_struct, tasks)
-#define prev_task(p)	list_entry((p)->tasks.prev, struct task_struct, tasks)
+#define next_task(p)	list_entry(rcu_dereference((p)->tasks.next), struct task_struct, tasks)
 
 #define for_each_process(p) \
 	for (p = &init_task ; (p = next_task(p)) != &init_task ; )
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index c4619a4..f8f2347 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -344,6 +344,13 @@
 				     void *here);
 extern void	      skb_under_panic(struct sk_buff *skb, int len,
 				      void *here);
+extern void	      skb_truesize_bug(struct sk_buff *skb);
+
+static inline void skb_truesize_check(struct sk_buff *skb)
+{
+	if (unlikely((int)skb->truesize < sizeof(struct sk_buff) + skb->len))
+		skb_truesize_bug(skb);
+}
 
 extern int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
 			int getfrag(void *from, char *to, int offset,
diff --git a/include/linux/sunrpc/metrics.h b/include/linux/sunrpc/metrics.h
index 8f96e9d..77f78e5 100644
--- a/include/linux/sunrpc/metrics.h
+++ b/include/linux/sunrpc/metrics.h
@@ -69,9 +69,21 @@
 /*
  * EXPORTed functions for managing rpc_iostats structures
  */
+
+#ifdef CONFIG_PROC_FS
+
 struct rpc_iostats *	rpc_alloc_iostats(struct rpc_clnt *);
 void			rpc_count_iostats(struct rpc_task *);
 void			rpc_print_iostats(struct seq_file *, struct rpc_clnt *);
 void			rpc_free_iostats(struct rpc_iostats *);
 
+#else  /*  CONFIG_PROC_FS  */
+
+static inline struct rpc_iostats *rpc_alloc_iostats(struct rpc_clnt *clnt) { return NULL; }
+static inline void rpc_count_iostats(struct rpc_task *task) {}
+static inline void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) {}
+static inline void rpc_free_iostats(struct rpc_iostats *stats) {}
+
+#endif  /*  CONFIG_PROC_FS  */
+
 #endif /* _LINUX_SUNRPC_METRICS_H */
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 7eebbab..e8bbe81 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -53,6 +53,7 @@
 
 struct rpc_task;
 struct rpc_xprt;
+struct seq_file;
 
 /*
  * This describes a complete RPC request
diff --git a/include/net/ieee80211softmac.h b/include/net/ieee80211softmac.h
index b971d8c..6b3693f 100644
--- a/include/net/ieee80211softmac.h
+++ b/include/net/ieee80211softmac.h
@@ -267,8 +267,9 @@
 #define IEEE80211SOFTMAC_EVENT_AUTH_FAILED		5
 #define IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT		6
 #define IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND	7
+#define IEEE80211SOFTMAC_EVENT_DISASSOCIATED		8
 /* keep this updated! */
-#define IEEE80211SOFTMAC_EVENT_LAST			7
+#define IEEE80211SOFTMAC_EVENT_LAST			8
 /*
  * If you want to be notified of certain events, you can call
  * ieee80211softmac_notify[_atomic] with
diff --git a/include/net/sock.h b/include/net/sock.h
index af2b054..ff8b0da 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -454,6 +454,7 @@
 
 static inline void sk_stream_free_skb(struct sock *sk, struct sk_buff *skb)
 {
+	skb_truesize_check(skb);
 	sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
 	sk->sk_wmem_queued   -= skb->truesize;
 	sk->sk_forward_alloc += skb->truesize;
diff --git a/kernel/exit.c b/kernel/exit.c
index 1a9787a..f86434d 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -56,7 +56,7 @@
 		detach_pid(p, PIDTYPE_PGID);
 		detach_pid(p, PIDTYPE_SID);
 
-		list_del_init(&p->tasks);
+		list_del_rcu(&p->tasks);
 		__get_cpu_var(process_counts)--;
 	}
 	list_del_rcu(&p->thread_group);
diff --git a/kernel/fork.c b/kernel/fork.c
index 54b15f8..d2fa57d 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -180,6 +180,7 @@
 	atomic_set(&tsk->usage,2);
 	atomic_set(&tsk->fs_excl, 0);
 	tsk->btrace_seq = 0;
+	tsk->splice_pipe = NULL;
 	return tsk;
 }
 
@@ -1204,7 +1205,7 @@
 			attach_pid(p, PIDTYPE_PGID, process_group(p));
 			attach_pid(p, PIDTYPE_SID, p->signal->session);
 
-			list_add_tail(&p->tasks, &init_task.tasks);
+			list_add_tail_rcu(&p->tasks, &init_task.tasks);
 			__get_cpu_var(process_counts)++;
 		}
 		attach_pid(p, PIDTYPE_PID, p->pid);
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 1156eb0..1fbf466 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -585,6 +585,9 @@
 	int i;
 
 	rp->kp.pre_handler = pre_handler_kretprobe;
+	rp->kp.post_handler = NULL;
+	rp->kp.fault_handler = NULL;
+	rp->kp.break_handler = NULL;
 
 	/* Pre-allocate memory for max kretprobe instances */
 	if (rp->maxactive <= 0) {
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index c5863d0..3eeedbb 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -240,14 +240,15 @@
  *	free_pagedir - free pages allocated with alloc_pagedir()
  */
 
-static void free_pagedir(struct pbe *pblist)
+static void free_pagedir(struct pbe *pblist, int clear_nosave_free)
 {
 	struct pbe *pbe;
 
 	while (pblist) {
 		pbe = (pblist + PB_PAGE_SKIP)->next;
 		ClearPageNosave(virt_to_page(pblist));
-		ClearPageNosaveFree(virt_to_page(pblist));
+		if (clear_nosave_free)
+			ClearPageNosaveFree(virt_to_page(pblist));
 		free_page((unsigned long)pblist);
 		pblist = pbe;
 	}
@@ -389,7 +390,7 @@
 		pbe->next = alloc_image_page(gfp_mask, safe_needed);
 	}
 	if (!pbe) { /* get_zeroed_page() failed */
-		free_pagedir(pblist);
+		free_pagedir(pblist, 1);
 		pblist = NULL;
         } else
 		create_pbe_list(pblist, nr_pages);
@@ -736,7 +737,7 @@
 		pblist = alloc_pagedir(nr_copy_pages, GFP_ATOMIC, 1);
 		if (pblist)
 			copy_page_backup_list(pblist, p);
-		free_pagedir(p);
+		free_pagedir(p, 0);
 		if (!pblist)
 			error = -ENOMEM;
 	}
diff --git a/kernel/uid16.c b/kernel/uid16.c
index aa25605..187e2a4 100644
--- a/kernel/uid16.c
+++ b/kernel/uid16.c
@@ -20,43 +20,67 @@
 
 asmlinkage long sys_chown16(const char __user * filename, old_uid_t user, old_gid_t group)
 {
-	return sys_chown(filename, low2highuid(user), low2highgid(group));
+	long ret = sys_chown(filename, low2highuid(user), low2highgid(group));
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 
 asmlinkage long sys_lchown16(const char __user * filename, old_uid_t user, old_gid_t group)
 {
-	return sys_lchown(filename, low2highuid(user), low2highgid(group));
+	long ret = sys_lchown(filename, low2highuid(user), low2highgid(group));
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 
 asmlinkage long sys_fchown16(unsigned int fd, old_uid_t user, old_gid_t group)
 {
-	return sys_fchown(fd, low2highuid(user), low2highgid(group));
+	long ret = sys_fchown(fd, low2highuid(user), low2highgid(group));
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 
 asmlinkage long sys_setregid16(old_gid_t rgid, old_gid_t egid)
 {
-	return sys_setregid(low2highgid(rgid), low2highgid(egid));
+	long ret = sys_setregid(low2highgid(rgid), low2highgid(egid));
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 
 asmlinkage long sys_setgid16(old_gid_t gid)
 {
-	return sys_setgid(low2highgid(gid));
+	long ret = sys_setgid(low2highgid(gid));
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 
 asmlinkage long sys_setreuid16(old_uid_t ruid, old_uid_t euid)
 {
-	return sys_setreuid(low2highuid(ruid), low2highuid(euid));
+	long ret = sys_setreuid(low2highuid(ruid), low2highuid(euid));
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 
 asmlinkage long sys_setuid16(old_uid_t uid)
 {
-	return sys_setuid(low2highuid(uid));
+	long ret = sys_setuid(low2highuid(uid));
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 
 asmlinkage long sys_setresuid16(old_uid_t ruid, old_uid_t euid, old_uid_t suid)
 {
-	return sys_setresuid(low2highuid(ruid), low2highuid(euid),
-		low2highuid(suid));
+	long ret = sys_setresuid(low2highuid(ruid), low2highuid(euid),
+				 low2highuid(suid));
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 
 asmlinkage long sys_getresuid16(old_uid_t __user *ruid, old_uid_t __user *euid, old_uid_t __user *suid)
@@ -72,8 +96,11 @@
 
 asmlinkage long sys_setresgid16(old_gid_t rgid, old_gid_t egid, old_gid_t sgid)
 {
-	return sys_setresgid(low2highgid(rgid), low2highgid(egid),
-		low2highgid(sgid));
+	long ret = sys_setresgid(low2highgid(rgid), low2highgid(egid),
+				 low2highgid(sgid));
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 
 asmlinkage long sys_getresgid16(old_gid_t __user *rgid, old_gid_t __user *egid, old_gid_t __user *sgid)
@@ -89,12 +116,18 @@
 
 asmlinkage long sys_setfsuid16(old_uid_t uid)
 {
-	return sys_setfsuid(low2highuid(uid));
+	long ret = sys_setfsuid(low2highuid(uid));
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 
 asmlinkage long sys_setfsgid16(old_gid_t gid)
 {
-	return sys_setfsgid(low2highgid(gid));
+	long ret = sys_setfsgid(low2highgid(gid));
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 
 static int groups16_to_user(old_gid_t __user *grouplist,
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index d57fd91..6ecc180 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -101,7 +101,7 @@
 
 config DEBUG_MUTEXES
 	bool "Mutex debugging, deadlock detection"
-	default y
+	default n
 	depends on DEBUG_KERNEL
 	help
 	 This allows mutex semantics violations and mutex related deadlocks
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index dec8249..8778f58 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -1761,7 +1761,6 @@
 		md->mapcount_max = count;
 
 	md->node[page_to_nid(page)]++;
-	cond_resched();
 }
 
 #ifdef CONFIG_HUGETLB_PAGE
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 78747af..042e643 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -46,15 +46,25 @@
 unsigned long badness(struct task_struct *p, unsigned long uptime)
 {
 	unsigned long points, cpu_time, run_time, s;
-	struct list_head *tsk;
+	struct mm_struct *mm;
+	struct task_struct *child;
 
-	if (!p->mm)
+	task_lock(p);
+	mm = p->mm;
+	if (!mm) {
+		task_unlock(p);
 		return 0;
+	}
 
 	/*
 	 * The memory size of the process is the basis for the badness.
 	 */
-	points = p->mm->total_vm;
+	points = mm->total_vm;
+
+	/*
+	 * After this unlock we can no longer dereference local variable `mm'
+	 */
+	task_unlock(p);
 
 	/*
 	 * Processes which fork a lot of child processes are likely
@@ -64,11 +74,11 @@
 	 * child is eating the vast majority of memory, adding only half
 	 * to the parents will make the child our kill candidate of choice.
 	 */
-	list_for_each(tsk, &p->children) {
-		struct task_struct *chld;
-		chld = list_entry(tsk, struct task_struct, sibling);
-		if (chld->mm != p->mm && chld->mm)
-			points += chld->mm->total_vm/2 + 1;
+	list_for_each_entry(child, &p->children, sibling) {
+		task_lock(child);
+		if (child->mm != mm && child->mm)
+			points += child->mm->total_vm/2 + 1;
+		task_unlock(child);
 	}
 
 	/*
@@ -244,17 +254,24 @@
 	force_sig(SIGKILL, p);
 }
 
-static struct mm_struct *oom_kill_task(task_t *p, const char *message)
+static int oom_kill_task(task_t *p, const char *message)
 {
-	struct mm_struct *mm = get_task_mm(p);
+	struct mm_struct *mm;
 	task_t * g, * q;
 
-	if (!mm)
-		return NULL;
-	if (mm == &init_mm) {
-		mmput(mm);
-		return NULL;
-	}
+	mm = p->mm;
+
+	/* WARNING: mm may not be dereferenced since we did not obtain its
+	 * value from get_task_mm(p).  This is OK since all we need to do is
+	 * compare mm to q->mm below.
+	 *
+	 * Furthermore, even if mm contains a non-NULL value, p->mm may
+	 * change to NULL at any time since we do not hold task_lock(p).
+	 * However, this is of no concern to us.
+	 */
+
+	if (mm == NULL || mm == &init_mm)
+		return 1;
 
 	__oom_kill_task(p, message);
 	/*
@@ -266,13 +283,12 @@
 			__oom_kill_task(q, message);
 	while_each_thread(g, q);
 
-	return mm;
+	return 0;
 }
 
-static struct mm_struct *oom_kill_process(struct task_struct *p,
-				unsigned long points, const char *message)
+static int oom_kill_process(struct task_struct *p, unsigned long points,
+		const char *message)
 {
- 	struct mm_struct *mm;
 	struct task_struct *c;
 	struct list_head *tsk;
 
@@ -283,9 +299,8 @@
 		c = list_entry(tsk, struct task_struct, sibling);
 		if (c->mm == p->mm)
 			continue;
-		mm = oom_kill_task(c, message);
-		if (mm)
-			return mm;
+		if (!oom_kill_task(c, message))
+			return 0;
 	}
 	return oom_kill_task(p, message);
 }
@@ -300,7 +315,6 @@
  */
 void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order)
 {
-	struct mm_struct *mm = NULL;
 	task_t *p;
 	unsigned long points = 0;
 
@@ -320,12 +334,12 @@
 	 */
 	switch (constrained_alloc(zonelist, gfp_mask)) {
 	case CONSTRAINT_MEMORY_POLICY:
-		mm = oom_kill_process(current, points,
+		oom_kill_process(current, points,
 				"No available memory (MPOL_BIND)");
 		break;
 
 	case CONSTRAINT_CPUSET:
-		mm = oom_kill_process(current, points,
+		oom_kill_process(current, points,
 				"No available memory in cpuset");
 		break;
 
@@ -347,8 +361,7 @@
 			panic("Out of memory and no killable processes...\n");
 		}
 
-		mm = oom_kill_process(p, points, "Out of memory");
-		if (!mm)
+		if (oom_kill_process(p, points, "Out of memory"))
 			goto retry;
 
 		break;
@@ -357,8 +370,6 @@
 out:
 	read_unlock(&tasklist_lock);
 	cpuset_unlock();
-	if (mm)
-		mmput(mm);
 
 	/*
 	 * Give "p" a good chance of killing itself before we
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 97d6827..123c605 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -232,11 +232,13 @@
  * zone->lock is already acquired when we use these.
  * So, we don't need atomic page->flags operations here.
  */
-static inline unsigned long page_order(struct page *page) {
+static inline unsigned long page_order(struct page *page)
+{
 	return page_private(page);
 }
 
-static inline void set_page_order(struct page *page, int order) {
+static inline void set_page_order(struct page *page, int order)
+{
 	set_page_private(page, order);
 	__SetPageBuddy(page);
 }
@@ -299,9 +301,9 @@
 
 	if (PageBuddy(page) && page_order(page) == order) {
 		BUG_ON(page_count(page) != 0);
-               return 1;
+		return 1;
 	}
-       return 0;
+	return 0;
 }
 
 /*
diff --git a/mm/shmem.c b/mm/shmem.c
index 37eaf42e..4c5e68e 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -46,6 +46,8 @@
 #include <linux/mempolicy.h>
 #include <linux/namei.h>
 #include <linux/ctype.h>
+#include <linux/migrate.h>
+
 #include <asm/uaccess.h>
 #include <asm/div64.h>
 #include <asm/pgtable.h>
@@ -2173,6 +2175,7 @@
 	.prepare_write	= shmem_prepare_write,
 	.commit_write	= simple_commit_write,
 #endif
+	.migratepage	= migrate_page,
 };
 
 static struct file_operations shmem_file_operations = {
diff --git a/mm/slob.c b/mm/slob.c
index 9bcc7e2..a68255b 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -354,9 +354,7 @@
 	if (!pdata)
 		return NULL;
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!cpu_possible(i))
-			continue;
+	for_each_possible_cpu(i) {
 		pdata->ptrs[i] = kmalloc(size, GFP_KERNEL);
 		if (!pdata->ptrs[i])
 			goto unwind_oom;
@@ -383,11 +381,9 @@
 	int i;
 	struct percpu_data *p = (struct percpu_data *) (~(unsigned long) objp);
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!cpu_possible(i))
-			continue;
+	for_each_possible_cpu(i)
 		kfree(p->ptrs[i]);
-	}
+
 	kfree(p);
 }
 EXPORT_SYMBOL(free_percpu);
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 84b9af7..3a13ed6 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -831,7 +831,7 @@
 			return -ENOMEM;
 		for_each_possible_cpu(i) {
 			newinfo->chainstack[i] =
-			   vmalloc(udc_cnt * sizeof(struct ebt_chainstack));
+			  vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0])));
 			if (!newinfo->chainstack[i]) {
 				while (i)
 					vfree(newinfo->chainstack[--i]);
@@ -841,8 +841,7 @@
 			}
 		}
 
-		cl_s = (struct ebt_cl_stack *)
-		   vmalloc(udc_cnt * sizeof(struct ebt_cl_stack));
+		cl_s = vmalloc(udc_cnt * sizeof(*cl_s));
 		if (!cl_s)
 			return -ENOMEM;
 		i = 0; /* the i'th udc */
@@ -944,8 +943,7 @@
 
 	countersize = COUNTER_OFFSET(tmp.nentries) * 
 					(highest_possible_processor_id()+1);
-	newinfo = (struct ebt_table_info *)
-	   vmalloc(sizeof(struct ebt_table_info) + countersize);
+	newinfo = vmalloc(sizeof(*newinfo) + countersize);
 	if (!newinfo)
 		return -ENOMEM;
 
@@ -967,8 +965,7 @@
 	/* the user wants counters back
 	   the check on the size is done later, when we have the lock */
 	if (tmp.num_counters) {
-		counterstmp = (struct ebt_counter *)
-		   vmalloc(tmp.num_counters * sizeof(struct ebt_counter));
+		counterstmp = vmalloc(tmp.num_counters * sizeof(*counterstmp));
 		if (!counterstmp) {
 			ret = -ENOMEM;
 			goto free_entries;
@@ -1148,8 +1145,7 @@
 
 	countersize = COUNTER_OFFSET(table->table->nentries) *
 					(highest_possible_processor_id()+1);
-	newinfo = (struct ebt_table_info *)
-	   vmalloc(sizeof(struct ebt_table_info) + countersize);
+	newinfo = vmalloc(sizeof(*newinfo) + countersize);
 	ret = -ENOMEM;
 	if (!newinfo)
 		return -ENOMEM;
@@ -1247,8 +1243,7 @@
 	if (hlp.num_counters == 0)
 		return -EINVAL;
 
-	if ( !(tmp = (struct ebt_counter *)
-	   vmalloc(hlp.num_counters * sizeof(struct ebt_counter))) ){
+	if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) {
 		MEMPRINT("Update_counters && nomemory\n");
 		return -ENOMEM;
 	}
@@ -1377,8 +1372,7 @@
 			BUGPRINT("Num_counters wrong\n");
 			return -EINVAL;
 		}
-		counterstmp = (struct ebt_counter *)
-		   vmalloc(nentries * sizeof(struct ebt_counter));
+		counterstmp = vmalloc(nentries * sizeof(*counterstmp));
 		if (!counterstmp) {
 			MEMPRINT("Couldn't copy counters, out of memory\n");
 			return -ENOMEM;
diff --git a/net/core/dev.c b/net/core/dev.c
index 83231a2..3bad1af 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2698,7 +2698,8 @@
 				/* If command is `set a parameter', or
 				 * `get the encoding parameters', check if
 				 * the user has the right to do it */
-				if (IW_IS_SET(cmd) || cmd == SIOCGIWENCODE) {
+				if (IW_IS_SET(cmd) || cmd == SIOCGIWENCODE
+				    || cmd == SIOCGIWENCODEEXT) {
 					if (!capable(CAP_NET_ADMIN))
 						return -EPERM;
 				}
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 09464fa..fb3770f 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -112,6 +112,14 @@
 	BUG();
 }
 
+void skb_truesize_bug(struct sk_buff *skb)
+{
+	printk(KERN_ERR "SKB BUG: Invalid truesize (%u) "
+	       "len=%u, sizeof(sk_buff)=%Zd\n",
+	       skb->truesize, skb->len, sizeof(struct sk_buff));
+}
+EXPORT_SYMBOL(skb_truesize_bug);
+
 /* 	Allocate a new skbuff. We do this ourselves so we can fill in a few
  *	'private' fields and also do memory statistics to find all the
  *	[BEEP] leaks.
diff --git a/net/core/stream.c b/net/core/stream.c
index 35e2525..e948969 100644
--- a/net/core/stream.c
+++ b/net/core/stream.c
@@ -176,6 +176,7 @@
 {
 	struct sock *sk = skb->sk;
 
+	skb_truesize_check(skb);
 	atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
 	sk->sk_forward_alloc += skb->truesize;
 }
diff --git a/net/core/wireless.c b/net/core/wireless.c
index 81d6995..d2bc72d 100644
--- a/net/core/wireless.c
+++ b/net/core/wireless.c
@@ -1726,6 +1726,14 @@
 	if(!IW_IS_GET(request->cmd))
 		return -EOPNOTSUPP;
 
+	/* If command is `get the encoding parameters', check if
+	 * the user has the right to do it */
+	if (request->cmd == SIOCGIWENCODE ||
+	    request->cmd == SIOCGIWENCODEEXT) {
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+	}
+
 	/* Special cases */
 	if(request->cmd == SIOCGIWSTATS)
 		/* Get Wireless Stats */
diff --git a/net/ieee80211/softmac/Kconfig b/net/ieee80211/softmac/Kconfig
index 6cd9f34..f2a27cc 100644
--- a/net/ieee80211/softmac/Kconfig
+++ b/net/ieee80211/softmac/Kconfig
@@ -1,6 +1,7 @@
 config IEEE80211_SOFTMAC
 	tristate "Software MAC add-on to the IEEE 802.11 networking stack"
 	depends on IEEE80211 && EXPERIMENTAL
+	select WIRELESS_EXT
 	---help---
 	This option enables the hardware independent software MAC addon
 	for the IEEE 802.11 networking stack.
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
index be61de78..4498023 100644
--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
+++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c
@@ -101,6 +101,7 @@
 	/* Do NOT clear bssvalid as that will break ieee80211softmac_assoc_work! */
 	mac->associated = 0;
 	mac->associnfo.associating = 0;
+	ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
 	spin_unlock_irqrestore(&mac->lock, flags);
 }
 
@@ -373,6 +374,7 @@
 	spin_lock_irqsave(&mac->lock, flags);
 	mac->associnfo.bssvalid = 0;
 	mac->associated = 0;
+	ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
 	schedule_work(&mac->associnfo.work);
 	spin_unlock_irqrestore(&mac->lock, flags);
 	
@@ -391,6 +393,7 @@
 		dprintkl(KERN_INFO PFX "reassoc request from unknown network\n");
 		return 0;
 	}
-	ieee80211softmac_assoc(mac, network);
+	schedule_work(&mac->associnfo.work);
+
 	return 0;
 }
diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c
index 0a52bbd..8cc8f3f 100644
--- a/net/ieee80211/softmac/ieee80211softmac_event.c
+++ b/net/ieee80211/softmac/ieee80211softmac_event.c
@@ -67,6 +67,7 @@
 	"authenticating failed",
 	"authenticating timed out",
 	"associating failed because no suitable network was found",
+	"disassociated",
 };
 
 
@@ -128,13 +129,42 @@
 ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx)
 {
 	struct ieee80211softmac_event *eventptr, *tmp;
-	union iwreq_data wrqu;
-	char *msg;
+	struct ieee80211softmac_network *network;
 	
 	if (event >= 0) {
-		msg = event_descriptions[event];
-		wrqu.data.length = strlen(msg);
-		wireless_send_event(mac->dev, IWEVCUSTOM, &wrqu, msg);
+		union iwreq_data wrqu;
+		int we_event;
+		char *msg = NULL;
+
+		switch(event) {
+		case IEEE80211SOFTMAC_EVENT_ASSOCIATED:
+			network = (struct ieee80211softmac_network *)event_ctx;
+			wrqu.data.length = 0;
+			wrqu.data.flags = 0;
+			memcpy(wrqu.ap_addr.sa_data, &network->bssid[0], ETH_ALEN);
+			wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+			we_event = SIOCGIWAP;
+			break;
+		case IEEE80211SOFTMAC_EVENT_DISASSOCIATED:
+			wrqu.data.length = 0;
+			wrqu.data.flags = 0;
+			memset(&wrqu, '\0', sizeof (union iwreq_data));
+			wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+			we_event = SIOCGIWAP;
+			break;
+		case IEEE80211SOFTMAC_EVENT_SCAN_FINISHED:
+			wrqu.data.length = 0;
+			wrqu.data.flags = 0;
+			memset(&wrqu, '\0', sizeof (union iwreq_data));
+			we_event = SIOCGIWSCAN;
+			break;
+		default:
+			msg = event_descriptions[event];
+			wrqu.data.length = strlen(msg);
+			we_event = IWEVCUSTOM;
+			break;
+		}
+		wireless_send_event(mac->dev, we_event, &wrqu, msg);
 	}
 
 	if (!list_empty(&mac->events))
diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c
index febc51d..cc6cd56 100644
--- a/net/ieee80211/softmac/ieee80211softmac_io.c
+++ b/net/ieee80211/softmac/ieee80211softmac_io.c
@@ -180,9 +180,21 @@
 	ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid);
 
 	/* Fill in capability Info */
-	(*pkt)->capability = (mac->ieee->iw_mode == IW_MODE_MASTER) || (mac->ieee->iw_mode == IW_MODE_INFRA) ?
-		cpu_to_le16(WLAN_CAPABILITY_ESS) :
-		cpu_to_le16(WLAN_CAPABILITY_IBSS);
+	switch (mac->ieee->iw_mode) {
+	case IW_MODE_INFRA:
+		(*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
+		break;
+	case IW_MODE_ADHOC:
+		(*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_IBSS);
+		break;
+	case IW_MODE_AUTO:
+		(*pkt)->capability = net->capabilities & (WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS);
+		break;
+	default:
+		/* bleh. we don't ever go to these modes */
+		printk(KERN_ERR PFX "invalid iw_mode!\n");
+		break;
+	}
 	/* Need to add this
 	(*pkt)->capability |= mac->ieee->short_slot ? 
 			cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0;
diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c
index bb9ab8b..2b9e7ed 100644
--- a/net/ieee80211/softmac/ieee80211softmac_scan.c
+++ b/net/ieee80211/softmac/ieee80211softmac_scan.c
@@ -47,6 +47,7 @@
 	sm->scanning = 1;
 	spin_unlock_irqrestore(&sm->lock, flags);
 
+	netif_tx_disable(sm->ieee->dev);
 	ret = sm->start_scan(sm->dev);
 	if (ret) {
 		spin_lock_irqsave(&sm->lock, flags);
@@ -239,6 +240,7 @@
 		if (net)
 			sm->set_channel(sm->dev, net->channel);
 	}
+	netif_wake_queue(sm->ieee->dev);
 	ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL);
 }
 EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished);
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c
index b559aa9..00f0d4f 100644
--- a/net/ieee80211/softmac/ieee80211softmac_wx.c
+++ b/net/ieee80211/softmac/ieee80211softmac_wx.c
@@ -41,13 +41,23 @@
 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan);
 
 
+/* if we're still scanning, return -EAGAIN so that userspace tools
+ * can get the complete scan results, otherwise return 0. */
 int
 ieee80211softmac_wx_get_scan_results(struct net_device *net_dev,
 				     struct iw_request_info *info,
 				     union iwreq_data *data,
 				     char *extra)
 {
+	unsigned long flags;
 	struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
+
+	spin_lock_irqsave(&sm->lock, flags);
+	if (sm->scanning) {
+		spin_unlock_irqrestore(&sm->lock, flags);
+		return -EAGAIN;
+	}
+	spin_unlock_irqrestore(&sm->lock, flags);
 	return ieee80211_wx_get_scan(sm->ieee, info, data, extra);
 }
 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 44df1db..a28ae59 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -533,6 +533,7 @@
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct sk_buff *buff;
 	int nsize, old_factor;
+	int nlen;
 	u16 flags;
 
 	BUG_ON(len > skb->len);
@@ -552,8 +553,10 @@
 	if (buff == NULL)
 		return -ENOMEM; /* We'll just try again later. */
 
-	buff->truesize = skb->len - len;
-	skb->truesize -= buff->truesize;
+	sk_charge_skb(sk, buff);
+	nlen = skb->len - len - nsize;
+	buff->truesize += nlen;
+	skb->truesize -= nlen;
 
 	/* Correct the sequence numbers. */
 	TCP_SKB_CB(buff)->seq = TCP_SKB_CB(skb)->seq + len;
@@ -1039,7 +1042,8 @@
 	if (unlikely(buff == NULL))
 		return -ENOMEM;
 
-	buff->truesize = nlen;
+	sk_charge_skb(sk, buff);
+	buff->truesize += nlen;
 	skb->truesize -= nlen;
 
 	/* Correct the sequence numbers. */
diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c
index 8f3addf0..d62e0f9 100644
--- a/net/llc/llc_input.c
+++ b/net/llc/llc_input.c
@@ -118,7 +118,8 @@
 		u16 pdulen = eth_hdr(skb)->h_proto,
 		    data_size = ntohs(pdulen) - llc_len;
 
-		skb_trim(skb, data_size);
+		if (unlikely(pskb_trim_rcsum(skb, data_size)))
+			return 0;
 	}
 	return 1;
 }
diff --git a/net/socket.c b/net/socket.c
index 23898f4..0ce12df 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -490,6 +490,7 @@
 	struct file *file;
 	struct socket *sock;
 
+	*err = -EBADF;
 	file = fget_light(fd, fput_needed);
 	if (file) {
 		sock = sock_from_file(file, err);
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 900ef31..519ebc1 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -794,7 +794,6 @@
 
 out_err:
 	dprintk("RPC:      gss_create_cred failed with error %d\n", err);
-	if (cred) gss_destroy_cred(&cred->gc_base);
 	return ERR_PTR(err);
 }
 
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index 97c981f..76b969e 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -212,7 +212,6 @@
 	char                            *cksumname;
 	struct crypto_tfm               *tfm = NULL; /* XXX add to ctx? */
 	struct scatterlist              sg[1];
-	u32                             code = GSS_S_FAILURE;
 
 	switch (cksumtype) {
 		case CKSUMTYPE_RSA_MD5:
@@ -221,13 +220,11 @@
 		default:
 			dprintk("RPC:      krb5_make_checksum:"
 				" unsupported checksum %d", cksumtype);
-			goto out;
+			return GSS_S_FAILURE;
 	}
 	if (!(tfm = crypto_alloc_tfm(cksumname, CRYPTO_TFM_REQ_MAY_SLEEP)))
-		goto out;
+		return GSS_S_FAILURE;
 	cksum->len = crypto_tfm_alg_digestsize(tfm);
-	if ((cksum->data = kmalloc(cksum->len, GFP_KERNEL)) == NULL)
-		goto out;
 
 	crypto_digest_init(tfm);
 	sg_set_buf(sg, header, hdrlen);
@@ -235,10 +232,8 @@
 	process_xdr_buf(body, body_offset, body->len - body_offset,
 			checksummer, tfm);
 	crypto_digest_final(tfm, cksum->data);
-	code = 0;
-out:
 	crypto_free_tfm(tfm);
-	return code;
+	return 0;
 }
 
 EXPORT_SYMBOL(make_checksum);
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
index dea5296..15c2db2 100644
--- a/net/sunrpc/stats.c
+++ b/net/sunrpc/stats.c
@@ -176,7 +176,8 @@
 	op_metrics->om_execute += execute;
 }
 
-void _print_name(struct seq_file *seq, unsigned int op, struct rpc_procinfo *procs)
+static void _print_name(struct seq_file *seq, unsigned int op,
+			struct rpc_procinfo *procs)
 {
 	if (procs[op].p_name)
 		seq_printf(seq, "\t%12s: ", procs[op].p_name);
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index ae5ab98..8012d10 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -5,6 +5,7 @@
 
 #include <ctype.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include <time.h>
@@ -531,7 +532,7 @@
 			break;
 		case 'h':
 		case '?':
-			printf("%s [-o|-s] config\n", av[0]);
+			fprintf(stderr, "See README for usage info\n");
 			exit(0);
 		}
 	}
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 640d0bf..84047f6 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -264,7 +264,7 @@
 
 	if (!selinux_mls_enabled) {
 		if (def_sid != SECSID_NULL && oldc)
-			*scontext += strlen(*scontext);
+			*scontext += strlen(*scontext)+1;
 		return 0;
 	}
 
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index 8687ae3..b49a45c 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -183,7 +183,8 @@
 
  */
 
-static void snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, int ack)
+static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd,
+		int ack)
 {
 	unsigned long flags;
 	int timeout, ok;
@@ -218,9 +219,11 @@
 		ok = 1;
 	}
 	spin_unlock_irqrestore(&mpu->input_lock, flags);
-	if (! ok)
+	if (!ok) {
 		snd_printk("cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu)));
-	// snd_printk("cmd: 0x%x at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu)));
+		return 1;
+	}
+	return 0;
 }
 
 /*
@@ -235,12 +238,19 @@
 	if (mpu->open_input && (err = mpu->open_input(mpu)) < 0)
 		return err;
 	if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) {
-		snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1);
-		snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
+		if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1))
+			goto error_out;
+		if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1))
+			goto error_out;
 	}
 	mpu->substream_input = substream;
 	set_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
 	return 0;
+
+error_out:
+	if (mpu->open_input && mpu->close_input)
+		mpu->close_input(mpu);
+	return -EIO;
 }
 
 static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream)
@@ -252,39 +262,52 @@
 	if (mpu->open_output && (err = mpu->open_output(mpu)) < 0)
 		return err;
 	if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
-		snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1);
-		snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
+		if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1))
+			goto error_out;
+		if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1))
+			goto error_out;
 	}
 	mpu->substream_output = substream;
 	set_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
 	return 0;
+
+error_out:
+	if (mpu->open_output && mpu->close_output)
+		mpu->close_output(mpu);
+	return -EIO;
 }
 
 static int snd_mpu401_uart_input_close(struct snd_rawmidi_substream *substream)
 {
 	struct snd_mpu401 *mpu;
+	int err = 0;
 
 	mpu = substream->rmidi->private_data;
 	clear_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
 	mpu->substream_input = NULL;
 	if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode))
-		snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
+		err = snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
 	if (mpu->close_input)
 		mpu->close_input(mpu);
+	if (err)
+		return -EIO;
 	return 0;
 }
 
 static int snd_mpu401_uart_output_close(struct snd_rawmidi_substream *substream)
 {
 	struct snd_mpu401 *mpu;
+	int err = 0;
 
 	mpu = substream->rmidi->private_data;
 	clear_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
 	mpu->substream_output = NULL;
 	if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode))
-		snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
+		err = snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
 	if (mpu->close_output)
 		mpu->close_output(mpu);
+	if (err)
+		return -EIO;
 	return 0;
 }
 
@@ -316,6 +339,7 @@
 			snd_mpu401_uart_remove_timer(mpu, 1);
 		clear_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode);
 	}
+
 }
 
 /*
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index 88e52dc..6275266 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -5,23 +5,9 @@
 #
 # Prompt user for primary drivers.
 
-config OBSOLETE_OSS_DRIVER
-	bool "Obsolete OSS drivers"
-	depends on SOUND_PRIME
-	help
-	  This option enables support for obsolete OSS drivers that
-	  are scheduled for removal in the near future since there
-	  are ALSA drivers for the same hardware.
-
-	  Please contact Adrian Bunk <bunk@stusta.de> if you had to
-	  say Y here because your soundcard is not properly supported
-	  by ALSA.
-
-	  If unsure, say N.
-
 config SOUND_BT878
 	tristate "BT878 audio dma"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+	depends on SOUND_PRIME && PCI
 	---help---
 	  Audio DMA support for bt878 based grabber boards.  As you might have
 	  already noticed, bt878 is listed with two functions in /proc/pci.
@@ -35,48 +21,9 @@
 	  To compile this driver as a module, choose M here: the module will
 	  be called btaudio.
 
-config SOUND_CMPCI
-	tristate "C-Media PCI (CMI8338/8738)"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y or M if you have a PCI sound card using the CMI8338
-	  or the CMI8738 chipset.  Data on these chips are available at
-	  <http://www.cmedia.com.tw/>.
-
-	  A userspace utility to control some internal registers of these
-	  chips is available at
-	  <http://member.nifty.ne.jp/Breeze/softwares/unix/cmictl-e.html>.
-
-config SOUND_CMPCI_FM
-	bool "Enable legacy FM"
-	depends on SOUND_CMPCI && X86
-	help
-	  Say Y here to enable the legacy FM (frequency-modulation) synthesizer
-	  support on a card using the CMI8338 or CMI8378 chipset. Even it is
-	  enabled, you need to set fmio as proper value to enable it.
-	  Say N here if you don't need this.
-
-config SOUND_CMPCI_MIDI
-	bool "Enable legacy MPU-401"
-	depends on SOUND_CMPCI && X86
-	help
-	  Say Y here to enable the legacy MPU401 MIDI synthesizer support on a
-	  card using the CMI8338 or CMI8378 chipset. Even it is enabled,
-	  you need to set mpuio as proper value to enable it.
-	  Say N here if you don't need this.
-
-config SOUND_CMPCI_JOYSTICK
-	bool "Enable joystick"
-	depends on SOUND_CMPCI && X86 && (GAMEPORT=y || SOUND_CMPCI=GAMEPORT)
-	help
-	  Say Y here in order to enable the joystick port on a sound card using
-	  the CMI8338 or the CMI8738 chipset.  You need to config the
-	  gameport support and set joystick parameter as 1 to use it.
-	  Say N here if you don't need this.
-
 config SOUND_EMU10K1
 	tristate "Creative SBLive! (EMU10K1)"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+	depends on SOUND_PRIME && PCI
 	---help---
 	  Say Y or M if you have a PCI sound card using the EMU10K1 chipset,
 	  such as the Creative SBLive!, SB PCI512 or Emu-APS.
@@ -108,13 +55,6 @@
 	  series) when wired as native sound drivers with AC97 codecs.  If
 	  this driver does not work try the CS4232 driver.
 
-config SOUND_CS4281
-	tristate "Crystal Sound CS4281"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-	help
-	  Picture and feature list at
-	  <http://www.pcbroker.com/crystal4281.html>.
-
 config SOUND_BCM_CS4297A
 	tristate "Crystal Sound CS4297a (for Swarm)"
 	depends on SOUND_PRIME && SIBYTE_SWARM
@@ -125,22 +65,9 @@
 	  note that CONFIG_KGDB should not be enabled at the same
 	  time, since it also attempts to use this UART port.
 
-config SOUND_ES1370
-	tristate "Ensoniq AudioPCI (ES1370)"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y or M if you have a PCI sound card utilizing the Ensoniq
-	  ES1370 chipset, such as Ensoniq's AudioPCI (non-97). To find
-	  out if your sound card uses an ES1370 without removing your
-	  computer's cover, use lspci -n and look for the PCI ID
-	  1274:5000. Since Ensoniq was bought by Creative Labs,
-	  Sound Blaster 64/PCI models are either ES1370 or ES1371 based.
-	  This driver differs slightly from OSS/Free, so PLEASE READ
-	  <file:Documentation/sound/oss/es1370>.
-
 config SOUND_ES1371
 	tristate "Creative Ensoniq AudioPCI 97 (ES1371)"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+	depends on SOUND_PRIME && PCI
 	help
 	  Say Y or M if you have a PCI sound card utilizing the Ensoniq
 	  ES1371 chipset, such as Ensoniq's AudioPCI97. To find out if
@@ -151,33 +78,6 @@
 	  slightly from OSS/Free, so PLEASE READ
 	  <file:Documentation/sound/oss/es1371>.
 
-config SOUND_ESSSOLO1
-	tristate "ESS Technology Solo1" 
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y or M if you have a PCI sound card utilizing the ESS Technology
-	  Solo1 chip. To find out if your sound card uses a
-	  Solo1 chip without removing your computer's cover, use
-	  lspci -n and look for the PCI ID 125D:1969. This driver
-	  differs slightly from OSS/Free, so PLEASE READ
-	  <file:Documentation/sound/oss/solo1>.
-
-config SOUND_MAESTRO
-	tristate "ESS Maestro, Maestro2, Maestro2E driver"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y or M if you have a sound system driven by ESS's Maestro line
-	  of PCI sound chips.  These include the Maestro 1, Maestro 2, and
-	  Maestro 2E.  See <file:Documentation/sound/oss/Maestro> for more
-	  details.
-
-config SOUND_MAESTRO3
-	tristate "ESS Maestro3/Allegro driver (EXPERIMENTAL)"
-	depends on SOUND_PRIME && PCI && EXPERIMENTAL && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y or M if you have a sound system driven by ESS's Maestro 3
-	  PCI sound chip.
-
 config SOUND_ICH
 	tristate "Intel ICH (i8xx) audio support"
 	depends on SOUND_PRIME && PCI
@@ -185,24 +85,6 @@
 	  Support for integral audio in Intel's I/O Controller Hub (ICH)
 	  chipset, as used on the 810/820/840 motherboards.
 
-config SOUND_HARMONY
-	tristate "PA Harmony audio driver"
-	depends on GSC_LASI && SOUND_PRIME && OBSOLETE_OSS_DRIVER
-	help
-	  Say 'Y' or 'M' to include support for Harmony soundchip
-	  on HP 712, 715/new and many other GSC based machines.
-
-config SOUND_SONICVIBES
-	tristate "S3 SonicVibes"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y or M if you have a PCI sound card utilizing the S3
-	  SonicVibes chipset. To find out if your sound card uses a
-	  SonicVibes chip without removing your computer's cover, use
-	  lspci -n and look for the PCI ID 5333:CA00. This driver
-	  differs slightly from OSS/Free, so PLEASE READ
-	  <file:Documentation/sound/oss/sonicvibes>.
-
 config SOUND_VWSND
 	tristate "SGI Visual Workstation Sound"
 	depends on SOUND_PRIME && X86_VISWS
@@ -231,10 +113,6 @@
 	  integrated, multi-function controller chip for MIPS CPUs.  Works
 	  with the AC97 codec.
 
-config SOUND_AU1000
-	tristate "Au1000 Sound"
-	depends on SOUND_PRIME && (SOC_AU1000 || SOC_AU1100 || SOC_AU1500) && OBSOLETE_OSS_DRIVER
-
 config SOUND_AU1550_AC97
 	tristate "Au1550 AC97 Sound"
 	depends on SOUND_PRIME && SOC_AU1550
@@ -507,7 +385,7 @@
 
 config SOUND_VIA82CXXX
 	tristate "VIA 82C686 Audio Codec"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+	depends on SOUND_PRIME && PCI
 	help
 	  Say Y here to include support for the audio codec found on VIA
 	  82Cxxx-based chips. Typically these are built into a motherboard.
@@ -576,18 +454,6 @@
 	  Say M here if you have a sound card based on the Analog Devices
 	  AD1889 chip.
 
-config SOUND_SGALAXY
-	tristate "Aztech Sound Galaxy (non-PnP) cards"
-	depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
-	help
-	  This module initializes the older non Plug and Play sound galaxy
-	  cards from Aztech. It supports the Waverider Pro 32 - 3D and the
-	  Galaxy Washington 16.
-
-	  If you compile the driver into the kernel, you have to add
-	  "sgalaxy=<io>,<irq>,<dma>,<dma2>,<sgbase>" to the kernel command
-	  line.
-
 config SOUND_ADLIB
 	tristate "Adlib Cards"
 	depends on SOUND_OSS
@@ -612,56 +478,6 @@
 
 	  This driver is also available as a module and will be called aci.
 
-config SOUND_CS4232
-	tristate "Crystal CS4232 based (PnP) cards"
-	depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y here if you have a card based on the Crystal CS4232 chip set,
-	  which uses its own Plug and Play protocol.
-
-	  If you compile the driver into the kernel, you have to add
-	  "cs4232=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the kernel
-	  command line.
-
-	  See <file:Documentation/sound/oss/CS4232> for more information on
-	  configuring this card.
-
-config SOUND_SSCAPE
-	tristate "Ensoniq SoundScape support"
-	depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
-	help
-	  Answer Y if you have a sound card based on the Ensoniq SoundScape
-	  chipset. Such cards are being manufactured at least by Ensoniq, Spea
-	  and Reveal (Reveal makes also other cards).
-
-	  If you compile the driver into the kernel, you have to add
-	  "sscape=<io>,<irq>,<dma>,<mpuio>,<mpuirq>" to the kernel command
-	  line.
-
-config SOUND_GUS
-	tristate "Gravis Ultrasound support"
-	depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y here for any type of Gravis Ultrasound card, including the GUS
-	  or GUS MAX.  See also <file:Documentation/sound/oss/ultrasound> for more
-	  information on configuring this card with modules.
-
-	  If you compile the driver into the kernel, you have to add
-	  "gus=<io>,<irq>,<dma>,<dma2>" to the kernel command line.
-
-config SOUND_GUS16
-	bool "16 bit sampling option of GUS (_NOT_ GUS MAX)"
-	depends on SOUND_GUS
-	help
-	  Support for Gravis Ulstrasound (GUS) cards (other than the GUS),
-	  sampling at 16-bit width.
-
-config SOUND_GUSMAX
-	bool "GUS MAX support"
-	depends on SOUND_GUS
-	help
-	  Support for Gravis Ulstrasound MAX.
-
 config SOUND_VMIDI
 	tristate "Loopback MIDI device support"
 	depends on SOUND_OSS
@@ -742,7 +558,7 @@
 
 config SOUND_NM256
 	tristate "NM256AV/NM256ZX audio support"
-	depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
+	depends on SOUND_OSS
 	help
 	  Say M here to include audio support for the NeoMagic 256AV/256ZX
 	  chipsets. These are the audio chipsets found in the Sony
@@ -752,35 +568,6 @@
 
 	  See <file:Documentation/sound/oss/NM256> for further information.
 
-config SOUND_MAD16
-	tristate "OPTi MAD16 and/or Mozart based cards"
-	depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
-	---help---
-	  Answer Y if your card has a Mozart (OAK OTI-601) or MAD16 (OPTi
-	  82C928 or 82C929 or 82C931) audio interface chip. These chips are
-	  quite common so it's possible that many no-name cards have one of
-	  them. In addition the MAD16 chip is used in some cards made by known
-	  manufacturers such as Turtle Beach (Tropez), Reveal (some models)
-	  and Diamond (latest ones). Note however that the Tropez sound cards
-	  have their own driver; if you have one of those, say N here and Y or
-	  M to "Full support for Turtle Beach WaveFront", below.
-
-	  If you compile the driver into the kernel, you have to add
-	  "mad16=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the
-	  kernel command line.
-
-	  See also <file:Documentation/sound/oss/Opti> and
-	  <file:Documentation/sound/oss/MAD16> for more information on setting
-	  these cards up as modules.
-
-config MAD16_OLDCARD
-	bool "Support MIDI in older MAD16 based cards (requires SB)"
-	depends on SOUND_MAD16
-	help
-	  Answer Y (or M) if you have an older card based on the C928 or
-	  Mozart chipset and you want to have MIDI support. If you enable this
-	  option you also need to enable support for Sound Blaster.
-
 config SOUND_PAS
 	tristate "ProAudioSpectrum 16 support"
 	depends on SOUND_OSS
@@ -873,53 +660,9 @@
 	  You can say M here to compile this driver as a module; the module is
 	  called sb.
 
-config SOUND_AWE32_SYNTH
-	tristate "AWE32 synth"
-	depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y here if you have a Sound Blaster SB32, AWE32-PnP, SB AWE64 or
-	  similar sound card. See <file:Documentation/sound/oss/README.awe>,
-	  <file:Documentation/sound/oss/AWE32> and the Soundblaster-AWE
-	  mini-HOWTO, available from <http://www.tldp.org/docs.html#howto>
-	  for more info.
-
-config SOUND_WAVEFRONT
-	tristate "Full support for Turtle Beach WaveFront (Tropez Plus, Tropez, Maui) synth/soundcards"
-	depends on SOUND_OSS && m && OBSOLETE_OSS_DRIVER
-	help
-	  Answer Y or M if you have a Tropez Plus, Tropez or Maui sound card
-	  and read the files <file:Documentation/sound/oss/Wavefront> and
-	  <file:Documentation/sound/oss/Tropez+>.
-
-config SOUND_MAUI
-	tristate "Limited support for Turtle Beach Wave Front (Maui, Tropez) synthesizers"
-	depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y here if you have a Turtle Beach Wave Front, Maui, or Tropez
-	  sound card.
-
-	  If you compile the driver into the kernel, you have to add
-	  "maui=<io>,<irq>" to the kernel command line.
-
-config MAUI_HAVE_BOOT
-	bool "Have OSWF.MOT firmware file"
-	depends on SOUND_MAUI=y && !STANDALONE
-	help
-	  Turtle Beach Maui and Tropez sound cards have a microcontroller
-	  which needs to be initialized prior to use. OSWF.MOT is a file
-	  distributed with the card's DOS/Windows drivers. Answer Y if you
-	  have this file.
-
-config MAUI_BOOT_FILE
-	string "Full pathname of OSWF.MOT firmware file"
-	depends on MAUI_HAVE_BOOT
-	default "/etc/sound/oswf.mot"
-	help
-	  Enter the full pathname of your OSWF.MOT file, starting from /.
-
 config SOUND_YM3812
 	tristate "Yamaha FM synthesizer (YM3812/OPL-3) support"
-	depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
+	depends on SOUND_OSS
 	---help---
 	  Answer Y if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4).
 	  Answering Y is usually a safe and recommended choice, however some
@@ -933,18 +676,6 @@
 
 	  If unsure, say Y.
 
-config SOUND_OPL3SA1
-	tristate "Yamaha OPL3-SA1 audio controller"
-	depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y or M if you have a Yamaha OPL3-SA1 sound chip, which is
-	  usually built into motherboards. Read
-	  <file:Documentation/sound/oss/OPL3-SA> for details.
-
-	  If you compile the driver into the kernel, you have to add
-	  "opl3sa=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the kernel
-	  command line.
-
 config SOUND_OPL3SA2
 	tristate "Yamaha OPL3-SA2 and SA3 based PnP cards"
 	depends on SOUND_OSS
@@ -959,19 +690,6 @@
 	  "opl3sa2=<io>,<irq>,<dma>,<dma2>,<mssio>,<mpuio>" to the kernel
 	  command line.
 
-config SOUND_YMFPCI
-	tristate "Yamaha YMF7xx PCI audio (native mode)"
-	depends on SOUND_OSS && PCI && OBSOLETE_OSS_DRIVER
-	help
-	  Support for Yamaha cards including the YMF711, YMF715, YMF718,
-	  YMF719, YMF724, Waveforce 192XG, and Waveforce 192 Digital.
-
-config SOUND_YMFPCI_LEGACY
-	bool "Yamaha PCI legacy ports support"
-	depends on SOUND_YMFPCI
-	help
-	  Support for YMF7xx PCI cards emulating an MP401.
-
 config SOUND_UART6850
 	tristate "6850 UART support"
 	depends on SOUND_OSS
@@ -1101,30 +819,6 @@
 	tristate "XpressAudio Sound Blaster emulation"
 	depends on SOUND_SB
 
-config SOUND_ALI5455
-	tristate "ALi5455 audio support"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-
-config SOUND_FORTE
-	tristate "ForteMedia FM801 driver"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y or M if you want driver support for the ForteMedia FM801 PCI
-	  audio controller (Abit AU10, Genius Sound Maker, HP Workstation
-	  zx2000, and others).
-
-config SOUND_RME96XX
-	tristate "RME Hammerfall (RME96XX) support"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y or M if you have a Hammerfall or Hammerfall light
-	  multichannel card from RME. If you want to access advanced
-	  features of the card, read <file:Documentation/sound/oss/rme96xx>.
-
-config SOUND_AD1980
-	tristate "AD1980 front/back switch plugin"
-	depends on SOUND_PRIME && OBSOLETE_OSS_DRIVER
-
 config SOUND_SH_DAC_AUDIO
 	tristate "SuperH DAC audio support"
 	depends on SOUND_PRIME && CPU_SH3
diff --git a/sound/oss/dmasound/tas_common.c b/sound/oss/dmasound/tas_common.c
index 8131599..882ae98 100644
--- a/sound/oss/dmasound/tas_common.c
+++ b/sound/oss/dmasound/tas_common.c
@@ -195,8 +195,8 @@
 
 	printk(KERN_INFO "tas driver [%s])\n", driver_name);
 
-#ifndef CONFIG_I2C_KEYWEST
-	request_module("i2c-keywest");
+#ifndef CONFIG_I2C_POWERMAC
+	request_module("i2c-powermac");
 #endif
 	tas_node = find_devices("deq");
 	if (tas_node == NULL)
diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c
index aa09ebd..46eebf5 100644
--- a/sound/ppc/daca.c
+++ b/sound/ppc/daca.c
@@ -255,7 +255,7 @@
 
 #ifdef CONFIG_KMOD
 	if (current->fs->root)
-		request_module("i2c-keywest");
+		request_module("i2c-powermac");
 #endif /* CONFIG_KMOD */	
 
 	mix = kmalloc(sizeof(*mix), GFP_KERNEL);
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index 1146dd8..70e4ebc 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -1313,7 +1313,7 @@
 
 #ifdef CONFIG_KMOD
 	if (current->fs->root)
-		request_module("i2c-keywest");
+		request_module("i2c-powermac");
 #endif /* CONFIG_KMOD */	
 
 	mix = kmalloc(sizeof(*mix), GFP_KERNEL);
diff --git a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c
index 33dbcbf..83acd6c 100644
--- a/usr/gen_init_cpio.c
+++ b/usr/gen_init_cpio.c
@@ -471,6 +471,7 @@
 				"ERROR: incorrect format, could not locate file type line %d: '%s'\n",
 				line_nr, line);
 			ec = -1;
+			break;
 		}
 
 		if ('\n' == *type) {
@@ -506,7 +507,8 @@
 				line_nr, line);
 		}
 	}
-	cpio_trailer();
+	if (ec == 0)
+		cpio_trailer();
 
 	exit(ec);
 }