diff --git a/CREDITS b/CREDITS
index 787564bc248b1d6125fc42f3932966b60aa2f7f4..9bf714a1c7d97e92a634161c3538ee93e30f07d3 100644
--- a/CREDITS
+++ b/CREDITS
@@ -1194,15 +1194,9 @@ S: Brecksville, OH  44141-1334
 S: USA
 
 N: Tristan Greaves
-E: Tristan.Greaves@icl.com
-E: tmg296@ecs.soton.ac.uk
-W: http://www.ecs.soton.ac.uk/~tmg296
+E: tristan@extricate.org
+W: http://www.extricate.org/
 D: Miscellaneous ipv4 sysctl patches
-S: 15 Little Mead
-S: Denmead
-S: Hampshire
-S: PO7 6HS
-S: United Kingdom
 
 N: Michael A. Griffith
 E: grif@cs.ucr.edu
@@ -3247,14 +3241,9 @@ S: 12725 SW Millikan Way, Suite 400
 S: Beaverton, Oregon 97005
 S: USA
 
-N: Marcelo W. Tosatti
-E: marcelo.tosatti@cyclades.com
-D: Miscellaneous kernel hacker
+N: Marcelo Tosatti
+E: marcelo@kvack.org
 D: v2.4 kernel maintainer
-D: Current pc300/cyclades maintainer
-S: Cyclades Corporation
-S: Av Cristovao Colombo, 462. Floresta.
-S: Porto Alegre
 S: Brazil
 
 N: Stefan Traby
diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index 3c406acd4dfae8c65e4f88ab5552416972c98276..b369a8c46a7311c8d5561d730a95a6049cee2ff2 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -1721,11 +1721,6 @@ Your cooperation is appreciated.
 		These devices support the same API as the generic SCSI
 		devices.
 
- 97 block	Packet writing for CD/DVD devices
-		  0 = /dev/pktcdvd0	First packet-writing module
-		  1 = /dev/pktcdvd1	Second packet-writing module
-		    ...
-
  98 char	Control and Measurement Device (comedi)
 		  0 = /dev/comedi0	First comedi device
 		  1 = /dev/comedi1	Second comedi device
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 421bcfff6ad21be680fcf819243ca9d750fa8ab2..43ab119963d5ef706f1f5c602526a4a9caf28ae9 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -57,6 +57,15 @@ Who:	Jody McIntyre <scjody@steamballoon.com>
 
 ---------------------------
 
+What:	sbp2: module parameter "force_inquiry_hack"
+When:	July 2006
+Why:	Superceded by parameter "workarounds". Both parameters are meant to be
+	used ad-hoc and for single devices only, i.e. not in modprobe.conf,
+	therefore the impact of this feature replacement should be low.
+Who:	Stefan Richter <stefanr@s5r6.in-berlin.de>
+
+---------------------------
+
 What:	Video4Linux API 1 ioctls and video_decoder.h from Video devices.
 When:	July 2006
 Why:	V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index 92f0056d928c1f5ff485e250a93a843bb60058bc..c61d8b876fdbcba484a3ad149ac3d057dfb76bba 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -1031,7 +1031,7 @@ conflict on any particular lock.
 LOCKS VS MEMORY ACCESSES
 ------------------------
 
-Consider the following: the system has a pair of spinlocks (N) and (Q), and
+Consider the following: the system has a pair of spinlocks (M) and (Q), and
 three CPUs; then should the following sequence of events occur:
 
 	CPU 1				CPU 2
@@ -1678,7 +1678,7 @@ CPU's caches by some other cache event:
 	smp_wmb();
 	<A:modify v=2>	<C:busy>
 			<C:queue v=2>
-	p = &b;		q = p;
+	p = &v;		q = p;
 			<D:request p>
 	<B:modify p=&v>	<D:commit p=&v>
 		  	<D:read p>
diff --git a/Documentation/networking/operstates.txt b/Documentation/networking/operstates.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4a21d9bb836b7345350b25f68e7bf0e1e76a508c
--- /dev/null
+++ b/Documentation/networking/operstates.txt
@@ -0,0 +1,161 @@
+
+1. Introduction
+
+Linux distinguishes between administrative and operational state of an
+interface. Admininstrative state is the result of "ip link set dev
+<dev> up or down" and reflects whether the administrator wants to use
+the device for traffic.
+
+However, an interface is not usable just because the admin enabled it
+- ethernet requires to be plugged into the switch and, depending on
+a site's networking policy and configuration, an 802.1X authentication
+to be performed before user data can be transferred. Operational state
+shows the ability of an interface to transmit this user data.
+
+Thanks to 802.1X, userspace must be granted the possibility to
+influence operational state. To accommodate this, operational state is
+split into two parts: Two flags that can be set by the driver only, and
+a RFC2863 compatible state that is derived from these flags, a policy,
+and changeable from userspace under certain rules.
+
+
+2. Querying from userspace
+
+Both admin and operational state can be queried via the netlink
+operation RTM_GETLINK. It is also possible to subscribe to RTMGRP_LINK
+to be notified of updates. This is important for setting from userspace.
+
+These values contain interface state:
+
+ifinfomsg::if_flags & IFF_UP:
+ Interface is admin up
+ifinfomsg::if_flags & IFF_RUNNING:
+ Interface is in RFC2863 operational state UP or UNKNOWN. This is for
+ backward compatibility, routing daemons, dhcp clients can use this
+ flag to determine whether they should use the interface.
+ifinfomsg::if_flags & IFF_LOWER_UP:
+ Driver has signaled netif_carrier_on()
+ifinfomsg::if_flags & IFF_DORMANT:
+ Driver has signaled netif_dormant_on()
+
+These interface flags can also be queried without netlink using the
+SIOCGIFFLAGS ioctl.
+
+TLV IFLA_OPERSTATE
+
+contains RFC2863 state of the interface in numeric representation:
+
+IF_OPER_UNKNOWN (0):
+ Interface is in unknown state, neither driver nor userspace has set
+ operational state. Interface must be considered for user data as
+ setting operational state has not been implemented in every driver.
+IF_OPER_NOTPRESENT (1):
+ Unused in current kernel (notpresent interfaces normally disappear),
+ just a numerical placeholder.
+IF_OPER_DOWN (2):
+ Interface is unable to transfer data on L1, f.e. ethernet is not
+ plugged or interface is ADMIN down.
+IF_OPER_LOWERLAYERDOWN (3):
+ Interfaces stacked on an interface that is IF_OPER_DOWN show this
+ state (f.e. VLAN).
+IF_OPER_TESTING (4):
+ Unused in current kernel.
+IF_OPER_DORMANT (5):
+ Interface is L1 up, but waiting for an external event, f.e. for a
+ protocol to establish. (802.1X)
+IF_OPER_UP (6):
+ Interface is operational up and can be used.
+
+This TLV can also be queried via sysfs.
+
+TLV IFLA_LINKMODE
+
+contains link policy. This is needed for userspace interaction
+described below.
+
+This TLV can also be queried via sysfs.
+
+
+3. Kernel driver API
+
+Kernel drivers have access to two flags that map to IFF_LOWER_UP and
+IFF_DORMANT. These flags can be set from everywhere, even from
+interrupts. It is guaranteed that only the driver has write access,
+however, if different layers of the driver manipulate the same flag,
+the driver has to provide the synchronisation needed.
+
+__LINK_STATE_NOCARRIER, maps to !IFF_LOWER_UP:
+
+The driver uses netif_carrier_on() to clear and netif_carrier_off() to
+set this flag. On netif_carrier_off(), the scheduler stops sending
+packets. The name 'carrier' and the inversion are historical, think of
+it as lower layer.
+
+netif_carrier_ok() can be used to query that bit.
+
+__LINK_STATE_DORMANT, maps to IFF_DORMANT:
+
+Set by the driver to express that the device cannot yet be used
+because some driver controlled protocol establishment has to
+complete. Corresponding functions are netif_dormant_on() to set the
+flag, netif_dormant_off() to clear it and netif_dormant() to query.
+
+On device allocation, networking core sets the flags equivalent to
+netif_carrier_ok() and !netif_dormant().
+
+
+Whenever the driver CHANGES one of these flags, a workqueue event is
+scheduled to translate the flag combination to IFLA_OPERSTATE as
+follows:
+
+!netif_carrier_ok():
+ IF_OPER_LOWERLAYERDOWN if the interface is stacked, IF_OPER_DOWN
+ otherwise. Kernel can recognise stacked interfaces because their
+ ifindex != iflink.
+
+netif_carrier_ok() && netif_dormant():
+ IF_OPER_DORMANT
+
+netif_carrier_ok() && !netif_dormant():
+ IF_OPER_UP if userspace interaction is disabled. Otherwise
+ IF_OPER_DORMANT with the possibility for userspace to initiate the
+ IF_OPER_UP transition afterwards.
+
+
+4. Setting from userspace
+
+Applications have to use the netlink interface to influence the
+RFC2863 operational state of an interface. Setting IFLA_LINKMODE to 1
+via RTM_SETLINK instructs the kernel that an interface should go to
+IF_OPER_DORMANT instead of IF_OPER_UP when the combination
+netif_carrier_ok() && !netif_dormant() is set by the
+driver. Afterwards, the userspace application can set IFLA_OPERSTATE
+to IF_OPER_DORMANT or IF_OPER_UP as long as the driver does not set
+netif_carrier_off() or netif_dormant_on(). Changes made by userspace
+are multicasted on the netlink group RTMGRP_LINK.
+
+So basically a 802.1X supplicant interacts with the kernel like this:
+
+-subscribe to RTMGRP_LINK
+-set IFLA_LINKMODE to 1 via RTM_SETLINK
+-query RTM_GETLINK once to get initial state
+-if initial flags are not (IFF_LOWER_UP && !IFF_DORMANT), wait until
+ netlink multicast signals this state
+-do 802.1X, eventually abort if flags go down again
+-send RTM_SETLINK to set operstate to IF_OPER_UP if authentication
+ succeeds, IF_OPER_DORMANT otherwise
+-see how operstate and IFF_RUNNING is echoed via netlink multicast
+-set interface back to IF_OPER_DORMANT if 802.1X reauthentication
+ fails
+-restart if kernel changes IFF_LOWER_UP or IFF_DORMANT flag
+
+if supplicant goes down, bring back IFLA_LINKMODE to 0 and
+IFLA_OPERSTATE to a sane value.
+
+A routing daemon or dhcp client just needs to care for IFF_RUNNING or
+waiting for operstate to go IF_OPER_UP/IF_OPER_UNKNOWN before
+considering the interface / querying a DHCP address.
+
+
+For technical questions and/or comments please e-mail to Stefan Rompf
+(stefan at loplof.de).
diff --git a/Documentation/scsi/ChangeLog.megaraid b/Documentation/scsi/ChangeLog.megaraid
index 09f6300eda4bef7262c5955abbe9e0bc5b41f905..c173806c91face5d6c1046d83268525a42c8de87 100644
--- a/Documentation/scsi/ChangeLog.megaraid
+++ b/Documentation/scsi/ChangeLog.megaraid
@@ -1,3 +1,28 @@
+Release Date	: Mon Apr 11 12:27:22 EST 2006 - Seokmann Ju <sju@lsil.com>
+Current Version : 2.20.4.8 (scsi module), 2.20.2.6 (cmm module)
+Older Version	: 2.20.4.7 (scsi module), 2.20.2.6 (cmm module)
+
+1.	Fixed a bug in megaraid_reset_handler().
+	Customer reported "Unable to handle kernel NULL pointer dereference
+	at virtual address 00000000" when system goes to reset condition
+	for some reason. It happened randomly.
+	Root Cause: in the megaraid_reset_handler(), there is possibility not
+	returning pending packets in the pend_list if there are multiple
+	pending packets.
+	Fix: Made the change in the driver so that it will return all packets
+	in the pend_list.
+
+2.	Added change request.
+	As found in the following URL, rmb() only didn't help the
+	problem. I had to increase the loop counter to 0xFFFFFF. (6 F's)
+	http://marc.theaimsgroup.com/?l=linux-scsi&m=110971060502497&w=2
+
+	I attached a patch for your reference, too.
+	Could you check and get this fix in your driver?
+
+	Best Regards,
+	Jun'ichi Nomura
+
 Release Date	: Fri Nov 11 12:27:22 EST 2005 - Seokmann Ju <sju@lsil.com>
 Current Version : 2.20.4.7 (scsi module), 2.20.2.6 (cmm module)
 Older Version	: 2.20.4.6 (scsi module), 2.20.2.6 (cmm module)
diff --git a/Documentation/spi/pxa2xx b/Documentation/spi/pxa2xx
new file mode 100644
index 0000000000000000000000000000000000000000..9c45f3df2e1844ca27ce38d88d74fb02678968ba
--- /dev/null
+++ b/Documentation/spi/pxa2xx
@@ -0,0 +1,234 @@
+PXA2xx SPI on SSP driver HOWTO
+===================================================
+This a mini howto on the pxa2xx_spi driver.  The driver turns a PXA2xx
+synchronous serial port into a SPI master controller
+(see Documentation/spi/spi_summary). The driver has the following features
+
+- Support for any PXA2xx SSP
+- SSP PIO and SSP DMA data transfers.
+- External and Internal (SSPFRM) chip selects.
+- Per slave device (chip) configuration.
+- Full suspend, freeze, resume support.
+
+The driver is built around a "spi_message" fifo serviced by workqueue and a
+tasklet. The workqueue, "pump_messages", drives message fifo and the tasklet
+(pump_transfer) is responsible for queuing SPI transactions and setting up and
+launching the dma/interrupt driven transfers.
+
+Declaring PXA2xx Master Controllers
+-----------------------------------
+Typically a SPI master is defined in the arch/.../mach-*/board-*.c as a
+"platform device".  The master configuration is passed to the driver via a table
+found in include/asm-arm/arch-pxa/pxa2xx_spi.h:
+
+struct pxa2xx_spi_master {
+	enum pxa_ssp_type ssp_type;
+	u32 clock_enable;
+	u16 num_chipselect;
+	u8 enable_dma;
+};
+
+The "pxa2xx_spi_master.ssp_type" field must have a value between 1 and 3 and
+informs the driver which features a particular SSP supports.
+
+The "pxa2xx_spi_master.clock_enable" field is used to enable/disable the
+corresponding SSP peripheral block in the "Clock Enable Register (CKEN"). See
+the "PXA2xx Developer Manual" section "Clocks and Power Management".
+
+The "pxa2xx_spi_master.num_chipselect" field is used to determine the number of
+slave device (chips) attached to this SPI master.
+
+The "pxa2xx_spi_master.enable_dma" field informs the driver that SSP DMA should
+be used.  This caused the driver to acquire two DMA channels: rx_channel and
+tx_channel.  The rx_channel has a higher DMA service priority the tx_channel.
+See the "PXA2xx Developer Manual" section "DMA Controller".
+
+NSSP MASTER SAMPLE
+------------------
+Below is a sample configuration using the PXA255 NSSP.
+
+static struct resource pxa_spi_nssp_resources[] = {
+	[0] = {
+		.start	= __PREG(SSCR0_P(2)), /* Start address of NSSP */
+		.end	= __PREG(SSCR0_P(2)) + 0x2c, /* Range of registers */
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_NSSP, /* NSSP IRQ */
+		.end	= IRQ_NSSP,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct pxa2xx_spi_master pxa_nssp_master_info = {
+	.ssp_type = PXA25x_NSSP, /* Type of SSP */
+	.clock_enable = CKEN9_NSSP, /* NSSP Peripheral clock */
+	.num_chipselect = 1, /* Matches the number of chips attached to NSSP */
+	.enable_dma = 1, /* Enables NSSP DMA */
+};
+
+static struct platform_device pxa_spi_nssp = {
+	.name = "pxa2xx-spi", /* MUST BE THIS VALUE, so device match driver */
+	.id = 2, /* Bus number, MUST MATCH SSP number 1..n */
+	.resource = pxa_spi_nssp_resources,
+	.num_resources = ARRAY_SIZE(pxa_spi_nssp_resources),
+	.dev = {
+		.platform_data = &pxa_nssp_master_info, /* Passed to driver */
+	},
+};
+
+static struct platform_device *devices[] __initdata = {
+	&pxa_spi_nssp,
+};
+
+static void __init board_init(void)
+{
+	(void)platform_add_device(devices, ARRAY_SIZE(devices));
+}
+
+Declaring Slave Devices
+-----------------------
+Typically each SPI slave (chip) is defined in the arch/.../mach-*/board-*.c
+using the "spi_board_info" structure found in "linux/spi/spi.h". See
+"Documentation/spi/spi_summary" for additional information.
+
+Each slave device attached to the PXA must provide slave specific configuration
+information via the structure "pxa2xx_spi_chip" found in
+"include/asm-arm/arch-pxa/pxa2xx_spi.h".  The pxa2xx_spi master controller driver
+will uses the configuration whenever the driver communicates with the slave
+device.
+
+struct pxa2xx_spi_chip {
+	u8 tx_threshold;
+	u8 rx_threshold;
+	u8 dma_burst_size;
+	u32 timeout_microsecs;
+	u8 enable_loopback;
+	void (*cs_control)(u32 command);
+};
+
+The "pxa2xx_spi_chip.tx_threshold" and "pxa2xx_spi_chip.rx_threshold" fields are
+used to configure the SSP hardware fifo.  These fields are critical to the
+performance of pxa2xx_spi driver and misconfiguration will result in rx
+fifo overruns (especially in PIO mode transfers). Good default values are
+
+	.tx_threshold = 12,
+	.rx_threshold = 4,
+
+The "pxa2xx_spi_chip.dma_burst_size" field is used to configure PXA2xx DMA
+engine and is related the "spi_device.bits_per_word" field.  Read and understand
+the PXA2xx "Developer Manual" sections on the DMA controller and SSP Controllers
+to determine the correct value. An SSP configured for byte-wide transfers would
+use a value of 8.
+
+The "pxa2xx_spi_chip.timeout_microsecs" fields is used to efficiently handle
+trailing bytes in the SSP receiver fifo.  The correct value for this field is
+dependent on the SPI bus speed ("spi_board_info.max_speed_hz") and the specific
+slave device.  Please note the the PXA2xx SSP 1 does not support trailing byte
+timeouts and must busy-wait any trailing bytes.
+
+The "pxa2xx_spi_chip.enable_loopback" field is used to place the SSP porting
+into internal loopback mode.  In this mode the SSP controller internally
+connects the SSPTX pin the the SSPRX pin.  This is useful for initial setup
+testing.
+
+The "pxa2xx_spi_chip.cs_control" field is used to point to a board specific
+function for asserting/deasserting a slave device chip select.  If the field is
+NULL, the pxa2xx_spi master controller driver assumes that the SSP port is
+configured to use SSPFRM instead.
+
+NSSP SALVE SAMPLE
+-----------------
+The pxa2xx_spi_chip structure is passed to the pxa2xx_spi driver in the
+"spi_board_info.controller_data" field. Below is a sample configuration using
+the PXA255 NSSP.
+
+/* Chip Select control for the CS8415A SPI slave device */
+static void cs8415a_cs_control(u32 command)
+{
+	if (command & PXA2XX_CS_ASSERT)
+		GPCR(2) = GPIO_bit(2);
+	else
+		GPSR(2) = GPIO_bit(2);
+}
+
+/* Chip Select control for the CS8405A SPI slave device */
+static void cs8405a_cs_control(u32 command)
+{
+	if (command & PXA2XX_CS_ASSERT)
+		GPCR(3) = GPIO_bit(3);
+	else
+		GPSR(3) = GPIO_bit(3);
+}
+
+static struct pxa2xx_spi_chip cs8415a_chip_info = {
+	.tx_threshold = 12, /* SSP hardward FIFO threshold */
+	.rx_threshold = 4, /* SSP hardward FIFO threshold */
+	.dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */
+	.timeout_microsecs = 64, /* Wait at least 64usec to handle trailing */
+	.cs_control = cs8415a_cs_control, /* Use external chip select */
+};
+
+static struct pxa2xx_spi_chip cs8405a_chip_info = {
+	.tx_threshold = 12, /* SSP hardward FIFO threshold */
+	.rx_threshold = 4, /* SSP hardward FIFO threshold */
+	.dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */
+	.timeout_microsecs = 64, /* Wait at least 64usec to handle trailing */
+	.cs_control = cs8405a_cs_control, /* Use external chip select */
+};
+
+static struct spi_board_info streetracer_spi_board_info[] __initdata = {
+	{
+		.modalias = "cs8415a", /* Name of spi_driver for this device */
+		.max_speed_hz = 3686400, /* Run SSP as fast a possbile */
+		.bus_num = 2, /* Framework bus number */
+		.chip_select = 0, /* Framework chip select */
+		.platform_data = NULL; /* No spi_driver specific config */
+		.controller_data = &cs8415a_chip_info, /* Master chip config */
+		.irq = STREETRACER_APCI_IRQ, /* Slave device interrupt */
+	},
+	{
+		.modalias = "cs8405a", /* Name of spi_driver for this device */
+		.max_speed_hz = 3686400, /* Run SSP as fast a possbile */
+		.bus_num = 2, /* Framework bus number */
+		.chip_select = 1, /* Framework chip select */
+		.controller_data = &cs8405a_chip_info, /* Master chip config */
+		.irq = STREETRACER_APCI_IRQ, /* Slave device interrupt */
+	},
+};
+
+static void __init streetracer_init(void)
+{
+	spi_register_board_info(streetracer_spi_board_info,
+				ARRAY_SIZE(streetracer_spi_board_info));
+}
+
+
+DMA and PIO I/O Support
+-----------------------
+The pxa2xx_spi driver support both DMA and interrupt driven PIO message
+transfers.  The driver defaults to PIO mode and DMA transfers must enabled by
+setting the "enable_dma" flag in the "pxa2xx_spi_master" structure and and
+ensuring that the "pxa2xx_spi_chip.dma_burst_size" field is non-zero.  The DMA
+mode support both coherent and stream based DMA mappings.
+
+The following logic is used to determine the type of I/O to be used on
+a per "spi_transfer" basis:
+
+if !enable_dma or dma_burst_size == 0 then
+	always use PIO transfers
+
+if spi_message.is_dma_mapped and rx_dma_buf != 0 and tx_dma_buf != 0 then
+	use coherent DMA mode
+
+if rx_buf and tx_buf are aligned on 8 byte boundary then
+	use streaming DMA mode
+
+otherwise
+	use PIO transfer
+
+THANKS TO
+---------
+
+David Brownell and others for mentoring the development of this driver.
+
diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary
index a5ffba33a35188a0d858871c06c090361de81b88..068732d32276b1f32bf285c10522b7e103e781e4 100644
--- a/Documentation/spi/spi-summary
+++ b/Documentation/spi/spi-summary
@@ -414,7 +414,33 @@ to get the driver-private data allocated for that device.
 The driver will initialize the fields of that spi_master, including the
 bus number (maybe the same as the platform device ID) and three methods
 used to interact with the SPI core and SPI protocol drivers.  It will
-also initialize its own internal state.
+also initialize its own internal state.  (See below about bus numbering
+and those methods.)
+
+After you initialize the spi_master, then use spi_register_master() to
+publish it to the rest of the system.  At that time, device nodes for
+the controller and any predeclared spi devices will be made available,
+and the driver model core will take care of binding them to drivers.
+
+If you need to remove your SPI controller driver, spi_unregister_master()
+will reverse the effect of spi_register_master().
+
+
+BUS NUMBERING
+
+Bus numbering is important, since that's how Linux identifies a given
+SPI bus (shared SCK, MOSI, MISO).  Valid bus numbers start at zero.  On
+SOC systems, the bus numbers should match the numbers defined by the chip
+manufacturer.  For example, hardware controller SPI2 would be bus number 2,
+and spi_board_info for devices connected to it would use that number.
+
+If you don't have such hardware-assigned bus number, and for some reason
+you can't just assign them, then provide a negative bus number.  That will
+then be replaced by a dynamically assigned number. You'd then need to treat
+this as a non-static configuration (see above).
+
+
+SPI MASTER METHODS
 
     master->setup(struct spi_device *spi)
 	This sets up the device clock rate, SPI mode, and word sizes.
@@ -431,6 +457,9 @@ also initialize its own internal state.
 	state it dynamically associates with that device.  If you do that,
 	be sure to provide the cleanup() method to free that state.
 
+
+SPI MESSAGE QUEUE
+
 The bulk of the driver will be managing the I/O queue fed by transfer().
 
 That queue could be purely conceptual.  For example, a driver used only
@@ -440,6 +469,9 @@ But the queue will probably be very real, using message->queue, PIO,
 often DMA (especially if the root filesystem is in SPI flash), and
 execution contexts like IRQ handlers, tasklets, or workqueues (such
 as keventd).  Your driver can be as fancy, or as simple, as you need.
+Such a transfer() method would normally just add the message to a
+queue, and then start some asynchronous transfer engine (unless it's
+already running).
 
 
 THANKS TO
diff --git a/Documentation/watchdog/watchdog-api.txt b/Documentation/watchdog/watchdog-api.txt
index c5beb548cfc42b781fd825ff9345f411f087897d..21ed5117366240d2a33af5af7f5605733bd514c1 100644
--- a/Documentation/watchdog/watchdog-api.txt
+++ b/Documentation/watchdog/watchdog-api.txt
@@ -36,6 +36,9 @@ timeout or margin.  The simplest way to ping the watchdog is to write
 some data to the device.  So a very simple watchdog daemon would look
 like this:
 
+#include <stdlib.h>
+#include <fcntl.h>
+
 int main(int argc, const char *argv[]) {
 	int fd=open("/dev/watchdog",O_WRONLY);
 	if (fd==-1) {
diff --git a/MAINTAINERS b/MAINTAINERS
index 3d5501059d563baa449d477b0a149699a5148541..69398f0bfc27c2d5d456da87d3f4abf109768056 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1486,10 +1486,11 @@ L:	netdev@vger.kernel.org
 S:	Maintained
 
 IRDA SUBSYSTEM
-P:	Jean Tourrilhes
+P:	Samuel Ortiz
+M:	samuel@sortiz.org
 L:	irda-users@lists.sourceforge.net (subscribers-only)
 W:	http://irda.sourceforge.net/
-S:	Odd Fixes
+S:	Maintained
 
 ISAPNP
 P:	Jaroslav Kysela
@@ -1608,6 +1609,11 @@ M:	James.Bottomley@HansenPartnership.com
 L:	linux-scsi@vger.kernel.org
 S:	Maintained
 
+LED SUBSYSTEM
+P:	Richard Purdie
+M:	rpurdie@rpsys.net
+S:	Maintained
+
 LEGO USB Tower driver
 P:	Juergen Stuber
 M:	starblue@users.sourceforge.net
@@ -1667,7 +1673,7 @@ S:	Maintained
 
 LINUX FOR POWERPC EMBEDDED PPC8XX
 P:	Marcelo Tosatti
-M:	marcelo.tosatti@cyclades.com
+M:	marcelo@kvack.org
 W:	http://www.penguinppc.org/
 L:	linuxppc-embedded@ozlabs.org
 S:	Maintained
@@ -2518,6 +2524,12 @@ M:	perex@suse.cz
 L:	alsa-devel@alsa-project.org
 S:	Maintained
 
+SPI SUBSYSTEM
+P:	David Brownell
+M:	dbrownell@users.sourceforge.net
+L:	spi-devel-general@lists.sourceforge.net
+S:	Maintained
+
 TPM DEVICE DRIVER
 P:	Kylene Hall
 M:	kjhall@us.ibm.com
diff --git a/Makefile b/Makefile
index 6bf99624bd4c5705b4b5bd6f96385a012dc0a736..3494c17c9fb9fe437134057e01bac2f4ffc887aa 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 17
-EXTRAVERSION =-rc3
+EXTRAVERSION =-rc4
 NAME=Sliding Snow Leopard
 
 # *DOCUMENTATION*
@@ -344,16 +344,14 @@ scripts_basic:
 scripts/basic/%: scripts_basic ;
 
 PHONY += outputmakefile
-# outputmakefile generate a Makefile to be placed in output directory, if
-# using a seperate output directory. This allows convinient use
-# of make in output directory
+# outputmakefile generates a Makefile in the output directory, if using a
+# separate output directory. This allows convenient use of make in the
+# output directory.
 outputmakefile:
-	$(Q)if test ! $(srctree) -ef $(objtree); then \
-	$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile              \
-	    $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)         \
-	    > $(objtree)/Makefile;                                 \
-	    echo '  GEN    $(objtree)/Makefile';                   \
-	fi
+ifneq ($(KBUILD_SRC),)
+	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \
+	    $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
+endif
 
 # To make sure we do not include .config for any of the *config targets
 # catch them early, and hand them over to scripts/kconfig/Makefile
@@ -796,8 +794,8 @@ prepare2: prepare3 outputmakefile
 prepare1: prepare2 include/linux/version.h include/asm \
                    include/config/MARKER
 ifneq ($(KBUILD_MODULES),)
-	$(Q)rm -rf $(MODVERDIR)
 	$(Q)mkdir -p $(MODVERDIR)
+	$(Q)rm -f $(MODVERDIR)/*
 endif
 
 archprepare: prepare1 scripts_basic
@@ -1086,8 +1084,8 @@ else # KBUILD_EXTMOD
 KBUILD_MODULES := 1
 PHONY += crmodverdir
 crmodverdir:
-	$(Q)rm -rf $(MODVERDIR)
 	$(Q)mkdir -p $(MODVERDIR)
+	$(Q)rm -f $(MODVERDIR)/*
 
 PHONY += $(objtree)/Module.symvers
 $(objtree)/Module.symvers:
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 1dbf6ddb300d2b5a9cfafd9e064dffee468dec52..08b7cc900cae5cd87c817b4c54d345c866d9182c 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -150,8 +150,6 @@ config ARCH_IOP3XX
 
 config ARCH_IXP4XX
 	bool "IXP4xx-based"
-	select DMABOUNCE
-	select PCI
 	help
 	  Support for Intel's IXP4XX (XScale) family of processors.
 
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c
index 0af3772efcb79c56e0e08f4659fed0292071c427..ace3fb5835d9278833a0c539b8fff0b74e8af885 100644
--- a/arch/arm/boot/compressed/misc.c
+++ b/arch/arm/boot/compressed/misc.c
@@ -38,10 +38,10 @@ static void icedcc_putc(int ch)
 		if (--i < 0)
 			return;
 
-		asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (status));
+		asm volatile ("mrc p14, 0, %0, c0, c0, 0" : "=r" (status));
 	} while (status & 2);
 
-	asm("mcr p15, 0, %0, c1, c0, 0" : : "r" (ch));
+	asm("mcr p14, 0, %0, c1, c0, 0" : : "r" (ch));
 }
 
 #define putc(ch)	icedcc_putc(ch)
diff --git a/arch/arm/configs/collie_defconfig b/arch/arm/configs/collie_defconfig
index c9aa878e610acd0fe9a7736456515113149987ce..074c47a4fb2e20170169259fa003d822df4c6e3a 100644
--- a/arch/arm/configs/collie_defconfig
+++ b/arch/arm/configs/collie_defconfig
@@ -1,21 +1,21 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.14-rc3
-# Sun Oct  9 16:55:14 2005
+# Linux kernel version: 2.6.17-rc1
+# Fri Apr 14 19:09:52 2006
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
-CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_VECTORS_BASE=0xffff0000
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
-CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
@@ -23,45 +23,58 @@ CONFIG_INIT_ENV_ARG_LIMIT=32
 #
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
+# CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
-CONFIG_BSD_PROCESS_ACCT=y
-# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
-CONFIG_BASE_FULL=y
+CONFIG_ELF_CORE=y
+# CONFIG_BASE_FULL is not set
 CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_EPOLL is not set
 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 is not set
+CONFIG_DOUBLEFAULT=y
 # CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
+CONFIG_BASE_SMALL=1
+CONFIG_SLOB=y
+CONFIG_OBSOLETE_INTERMODULE=y
 
 #
 # Loadable module support
 #
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
+# CONFIG_MODULES is not set
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
 
 #
 # System Type
@@ -70,11 +83,13 @@ CONFIG_KMOD=y
 # 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 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
@@ -84,9 +99,11 @@ CONFIG_ARCH_SA1100=y
 # CONFIG_ARCH_LH7A40X is not set
 # CONFIG_ARCH_OMAP is not set
 # CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
 # CONFIG_ARCH_IMX is not set
 # CONFIG_ARCH_H720X is not set
 # CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
 
 #
 # SA11x0 Implementations
@@ -128,20 +145,32 @@ CONFIG_SHARP_SCOOP=y
 # Bus support
 #
 CONFIG_ISA=y
-CONFIG_ISA_DMA_API=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
-# CONFIG_PCCARD is not set
+CONFIG_PCCARD=y
+CONFIG_PCMCIA_DEBUG=y
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_SA1100=y
 
 #
 # Kernel Features
 #
-# CONFIG_SMP is not set
-CONFIG_PREEMPT=y
+# CONFIG_PREEMPT is not set
 # CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
 CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_NODES_SHIFT=2
 CONFIG_SELECT_MEMORY_MODEL=y
 # CONFIG_FLATMEM_MANUAL is not set
 CONFIG_DISCONTIGMEM_MANUAL=y
@@ -150,6 +179,7 @@ CONFIG_DISCONTIGMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 CONFIG_NEED_MULTIPLE_NODES=y
 # CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
 # CONFIG_LEDS is not set
 CONFIG_ALIGNMENT_TRAP=y
 
@@ -158,7 +188,7 @@ CONFIG_ALIGNMENT_TRAP=y
 #
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyS0,115200n8 console=tty1 noinitrd root=/dev/mtdblock2 rootfstype=jffs2   debug"
+CONFIG_CMDLINE="noinitrd root=/dev/mtdblock2 rootfstype=jffs2 fbcon=rotate:1"
 # CONFIG_XIP_KERNEL is not set
 
 #
@@ -181,14 +211,16 @@ CONFIG_FPE_NWFPE=y
 # Userspace binary formats
 #
 CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_AOUT=m
-CONFIG_BINFMT_MISC=m
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
 # CONFIG_ARTHUR is not set
 
 #
 # Power management options
 #
 CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
 CONFIG_APM=y
 
 #
@@ -199,6 +231,7 @@ CONFIG_NET=y
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -211,16 +244,19 @@ CONFIG_IP_FIB_HASH=y
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
+# CONFIG_SYN_COOKIES is not set
 # 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
 
 #
@@ -232,6 +268,11 @@ CONFIG_TCP_CONG_BIC=y
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -244,8 +285,11 @@ CONFIG_TCP_CONG_BIC=y
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
 # CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
@@ -265,9 +309,14 @@ CONFIG_TCP_CONG_BIC=y
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
+CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
 
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
 #
 # Memory Technology Devices (MTD)
 #
@@ -287,32 +336,49 @@ CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
 
 #
 # RAM/ROM/Flash chip drivers
 #
-# CONFIG_MTD_CFI is not set
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_2 is not set
 CONFIG_MTD_MAP_BANK_WIDTH_4=y
 # CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
 # CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
 # CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I1 is not set
+# CONFIG_MTD_CFI_I2 is not set
+CONFIG_MTD_CFI_I4=y
 # CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
 CONFIG_MTD_OBSOLETE_CHIPS=y
 CONFIG_MTD_SHARP=y
+# CONFIG_MTD_XIP is not set
 
 #
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_SA1100=y
+# CONFIG_MTD_IMPA7 is not set
 # CONFIG_MTD_PLATRAM is not set
 
 #
@@ -321,7 +387,6 @@ CONFIG_MTD_SHARP=y
 # 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
 
 #
@@ -336,6 +401,11 @@ CONFIG_MTD_SHARP=y
 #
 # CONFIG_MTD_NAND is not set
 
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
 #
 # Parallel port support
 #
@@ -349,7 +419,6 @@ CONFIG_MTD_SHARP=y
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_XD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
@@ -359,20 +428,35 @@ CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=1024
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
 
 #
-# IO Schedulers
+# ATA/ATAPI/MFM/RLL support
 #
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_ATA_OVER_ETH=m
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
 
 #
-# ATA/ATAPI/MFM/RLL support
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
 #
-# CONFIG_IDE is not set
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
 
 #
 # SCSI device support
@@ -402,6 +486,39 @@ CONFIG_ATA_OVER_ETH=m
 # Network device support
 #
 # CONFIG_NETDEVICES is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+
+#
+# Ethernet (10 or 100Mbit)
+#
+# CONFIG_NET_ETHERNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=y
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
 
@@ -424,7 +541,7 @@ CONFIG_INPUT_TSDEV=y
 CONFIG_INPUT_TSDEV_SCREEN_X=240
 CONFIG_INPUT_TSDEV_SCREEN_Y=320
 CONFIG_INPUT_EVDEV=y
-CONFIG_INPUT_EVBUG=y
+# CONFIG_INPUT_EVBUG is not set
 
 #
 # Input Device Drivers
@@ -438,7 +555,11 @@ CONFIG_KEYBOARD_LOCOMO=y
 # CONFIG_KEYBOARD_NEWTON is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
 # CONFIG_INPUT_MISC is not set
 
 #
@@ -461,7 +582,16 @@ CONFIG_HW_CONSOLE=y
 #
 # Serial drivers
 #
-# CONFIG_SERIAL_8250 is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_CONSOLE is not set
+CONFIG_SERIAL_8250_CS=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
 
 #
 # Non-8250 serial port support
@@ -483,94 +613,48 @@ CONFIG_UNIX98_PTYS=y
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_RAW_DRIVER is not set
 
 #
-# TPM devices
+# PCMCIA character devices
 #
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
 
 #
-# I2C support
+# TPM devices
 #
-CONFIG_I2C=m
-# CONFIG_I2C_CHARDEV is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
 
 #
-# I2C Algorithms
+# I2C support
 #
-CONFIG_I2C_ALGOBIT=m
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
+# CONFIG_I2C is not set
 
 #
-# I2C Hardware Bus support
+# SPI support
 #
-# CONFIG_I2C_ELEKTOR is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_PCA_ISA is not set
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
 
 #
-# Miscellaneous I2C Chip support
+# Dallas's 1-wire bus
 #
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
-# CONFIG_SENSORS_EEPROM is not set
-# 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_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
 #
-CONFIG_HWMON=y
+# CONFIG_HWMON is not set
 # CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_ATXP1 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_LM92 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83792D is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Misc devices
@@ -579,42 +663,33 @@ CONFIG_HWMON=y
 #
 # Multimedia Capabilities Port drivers
 #
-# CONFIG_MCP_SA11X0 is not set
+CONFIG_MCP=y
+CONFIG_MCP_SA11X0=y
+CONFIG_MCP_UCB1200=y
+CONFIG_MCP_UCB1200_TS=y
 
 #
-# Multimedia devices
+# LED devices
 #
-CONFIG_VIDEO_DEV=m
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
 
 #
-# Video For Linux
+# LED drivers
 #
+CONFIG_LEDS_LOCOMO=y
 
 #
-# Video Adapters
+# LED Triggers
 #
-# CONFIG_VIDEO_PMS is not set
-# CONFIG_VIDEO_CPIA is not set
-# CONFIG_VIDEO_SAA5246A is not set
-# CONFIG_VIDEO_SAA5249 is not set
-# CONFIG_TUNER_3036 is not set
-# CONFIG_VIDEO_OVCAMCHIP is not set
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
 
 #
-# Radio Adapters
+# Multimedia devices
 #
-# CONFIG_RADIO_CADET is not set
-# CONFIG_RADIO_RTRACK is not set
-# CONFIG_RADIO_RTRACK2 is not set
-# CONFIG_RADIO_AZTECH is not set
-# CONFIG_RADIO_GEMTEK is not set
-# CONFIG_RADIO_MAESTRO is not set
-# CONFIG_RADIO_SF16FMI is not set
-# CONFIG_RADIO_SF16FMR2 is not set
-# CONFIG_RADIO_TERRATEC is not set
-# CONFIG_RADIO_TRUST is not set
-# CONFIG_RADIO_TYPHOON is not set
-# CONFIG_RADIO_ZOLTRIX is not set
+# CONFIG_VIDEO_DEV is not set
 
 #
 # Digital Video Broadcasting Devices
@@ -628,8 +703,8 @@ CONFIG_FB=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
-CONFIG_FB_SOFT_CURSOR=y
 # CONFIG_FB_MACMODES is not set
+# CONFIG_FB_FIRMWARE_EDID is not set
 CONFIG_FB_MODE_HELPERS=y
 # CONFIG_FB_TILEBLITTING is not set
 CONFIG_FB_SA1100=y
@@ -643,14 +718,15 @@ CONFIG_FB_SA1100=y
 # CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
 CONFIG_FONTS=y
-CONFIG_FONT_8x8=y
+# CONFIG_FONT_8x8 is not set
 # CONFIG_FONT_8x16 is not set
 # CONFIG_FONT_6x11 is not set
 # CONFIG_FONT_7x14 is not set
 # CONFIG_FONT_PEARL_8x8 is not set
 # CONFIG_FONT_ACORN_8x8 is not set
-# CONFIG_FONT_MINI_4x6 is not set
+CONFIG_FONT_MINI_4x6=y
 # CONFIG_FONT_SUN8x16 is not set
 # CONFIG_FONT_SUN12x22 is not set
 # CONFIG_FONT_10x18 is not set
@@ -659,7 +735,11 @@ CONFIG_FONT_8x8=y
 # Logo configuration
 #
 # CONFIG_LOGO is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_DEVICE=y
 
 #
 # Sound
@@ -671,44 +751,42 @@ CONFIG_FONT_8x8=y
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 # CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 # CONFIG_USB is not set
 
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
 #
 # USB Gadget Support
 #
-CONFIG_USB_GADGET=y
-# CONFIG_USB_GADGET_DEBUG_FILES is not set
-# CONFIG_USB_GADGET_NET2280 is not set
-# CONFIG_USB_GADGET_PXA2XX is not set
-# CONFIG_USB_GADGET_GOKU is not set
-# CONFIG_USB_GADGET_LH7A40X is not set
-# CONFIG_USB_GADGET_OMAP is not set
-# CONFIG_USB_GADGET_DUMMY_HCD is not set
-# CONFIG_USB_GADGET_DUALSPEED is not set
+# CONFIG_USB_GADGET is not set
 
 #
 # MMC/SD Card support
 #
 # CONFIG_MMC is not set
 
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
 #
 # File systems
 #
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT2_FS is not set
 # CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_ROMFS_FS=y
-CONFIG_INOTIFY=y
+# CONFIG_INOTIFY is not set
 # CONFIG_QUOTA is not set
 # CONFIG_DNOTIFY is not set
 # CONFIG_AUTOFS_FS is not set
@@ -725,7 +803,7 @@ CONFIG_INOTIFY=y
 # DOS/FAT/NT Filesystems
 #
 CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
+# CONFIG_MSDOS_FS is not set
 CONFIG_VFAT_FS=y
 CONFIG_FAT_DEFAULT_CODEPAGE=437
 CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
@@ -739,7 +817,7 @@ CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -755,11 +833,12 @@ CONFIG_RAMFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
 # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 CONFIG_JFFS2_ZLIB=y
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
-CONFIG_CRAMFS=y
+# CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
@@ -789,7 +868,7 @@ CONFIG_MSDOS_PARTITION=y
 #
 CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="cp437"
-CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_437=y
 # CONFIG_NLS_CODEPAGE_737 is not set
 # CONFIG_NLS_CODEPAGE_775 is not set
 # CONFIG_NLS_CODEPAGE_850 is not set
@@ -813,7 +892,7 @@ CONFIG_NLS_CODEPAGE_437=m
 # CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
 # CONFIG_NLS_ASCII is not set
-CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_1=y
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
 # CONFIG_NLS_ISO8859_4 is not set
@@ -826,7 +905,7 @@ CONFIG_NLS_ISO8859_1=m
 # CONFIG_NLS_ISO8859_15 is not set
 # CONFIG_NLS_KOI8_R is not set
 # CONFIG_NLS_KOI8_U is not set
-CONFIG_NLS_UTF8=m
+# CONFIG_NLS_UTF8 is not set
 
 #
 # Profiling support
@@ -837,20 +916,23 @@ CONFIG_NLS_UTF8=m
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_DETECT_SOFTLOCKUP is not set
 # CONFIG_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_INFO is not set
 # 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 is not set
 # CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
@@ -874,7 +956,7 @@ CONFIG_DEBUG_ERRORS=y
 #
 # Library routines
 #
-# CONFIG_CRC_CCITT is not set
+CONFIG_CRC_CCITT=y
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
diff --git a/arch/arm/configs/versatile_defconfig b/arch/arm/configs/versatile_defconfig
index 2687a225aa6ac20fe4c4e5c6c2a26a273c4de378..96b7a77624265c54010d1e8b206833ee0c8ee978 100644
--- a/arch/arm/configs/versatile_defconfig
+++ b/arch/arm/configs/versatile_defconfig
@@ -1,50 +1,55 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Mon Mar 28 00:20:50 2005
+# Linux kernel version: 2.6.17-rc3
+# Mon May  8 20:15:57 2006
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
-CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=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
 
 #
 # General setup
 #
 CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=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
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
 
 #
 # Loadable module support
@@ -52,11 +57,28 @@ CONFIG_BASE_SMALL=0
 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
 
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
 #
 # System Type
 #
@@ -64,11 +86,13 @@ CONFIG_KMOD=y
 # 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 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
@@ -78,14 +102,17 @@ CONFIG_KMOD=y
 # CONFIG_ARCH_LH7A40X is not set
 # CONFIG_ARCH_OMAP is not set
 CONFIG_ARCH_VERSATILE=y
+# CONFIG_ARCH_REALVIEW is not set
 # CONFIG_ARCH_IMX is not set
 # CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
 
 #
 # Versatile platform type
 #
 CONFIG_ARCH_VERSATILE_PB=y
-# CONFIG_MACH_VERSATILE_AB is not set
+CONFIG_MACH_VERSATILE_AB=y
 
 #
 # Processor Type
@@ -106,12 +133,14 @@ CONFIG_ARM_THUMB=y
 # CONFIG_CPU_DCACHE_DISABLE is not set
 # CONFIG_CPU_DCACHE_WRITETHROUGH is not set
 # CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+CONFIG_ARM_VIC=y
 CONFIG_ICST307=y
 
 #
 # Bus support
 #
 CONFIG_ARM_AMBA=y
+# CONFIG_PCI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -122,6 +151,18 @@ CONFIG_ARM_AMBA=y
 # Kernel Features
 #
 # 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
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
 CONFIG_LEDS=y
 CONFIG_LEDS_TIMER=y
 CONFIG_LEDS_CPU=y
@@ -145,7 +186,7 @@ CONFIG_CMDLINE="root=1f03 mem=32M"
 CONFIG_FPE_NWFPE=y
 # CONFIG_FPE_NWFPE_XP is not set
 # CONFIG_FPE_FASTFPE is not set
-# CONFIG_VFP is not set
+CONFIG_VFP=y
 
 #
 # Userspace binary formats
@@ -159,8 +200,91 @@ CONFIG_BINFMT_ELF=y
 # Power management options
 #
 CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
 # CONFIG_APM is not set
 
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# 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 is not set
+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
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
 #
 # Device Drivers
 #
@@ -173,6 +297,11 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
 
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
 #
 # Memory Technology Devices (MTD)
 #
@@ -192,6 +321,7 @@ CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -214,6 +344,7 @@ CONFIG_MTD_CFI_I1=y
 CONFIG_MTD_CFI_I2=y
 # CONFIG_MTD_CFI_I4 is not set
 # CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
 CONFIG_MTD_CFI_INTELEXT=y
 # CONFIG_MTD_CFI_AMDSTD is not set
 # CONFIG_MTD_CFI_STAA is not set
@@ -221,7 +352,7 @@ CONFIG_MTD_CFI_UTIL=y
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_XIP is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
 
 #
 # Mapping drivers for chip access
@@ -229,7 +360,7 @@ CONFIG_MTD_CFI_UTIL=y
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 # CONFIG_MTD_PHYSMAP is not set
 CONFIG_MTD_ARM_INTEGRATOR=y
-# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
@@ -237,7 +368,6 @@ CONFIG_MTD_ARM_INTEGRATOR=y
 # 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
 
 #
@@ -252,6 +382,11 @@ CONFIG_MTD_ARM_INTEGRATOR=y
 #
 # CONFIG_MTD_NAND is not set
 
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
 #
 # Parallel port support
 #
@@ -264,7 +399,6 @@ CONFIG_MTD_ARM_INTEGRATOR=y
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
@@ -272,21 +406,13 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 
 #
@@ -297,6 +423,7 @@ CONFIG_IOSCHED_CFQ=y
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -307,83 +434,26 @@ CONFIG_IOSCHED_CFQ=y
 #
 
 #
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-# CONFIG_IP_TCPDIAG is not set
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
+# Network device support
 #
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
 
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
 CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -410,6 +480,8 @@ CONFIG_SMC91X=y
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -459,7 +531,6 @@ CONFIG_SERIO_AMBAKMI=y
 CONFIG_SERIO_LIBPS2=y
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -474,17 +545,16 @@ CONFIG_HW_CONSOLE=y
 #
 CONFIG_SERIAL_8250=m
 CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 # CONFIG_SERIAL_8250_DETECT_IRQ is not set
-CONFIG_SERIAL_8250_MULTIPORT=y
 CONFIG_SERIAL_8250_RSA=y
 
 #
 # Non-8250 serial port support
 #
-# CONFIG_SERIAL_AMBA_PL010 is not set
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 CONFIG_SERIAL_CORE=y
@@ -503,20 +573,19 @@ CONFIG_LEGACY_PTY_COUNT=16
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -534,59 +603,59 @@ CONFIG_I2C_ALGOBIT=y
 #
 # I2C Hardware Bus support
 #
-# CONFIG_I2C_ISA is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_STUB is not set
 # CONFIG_I2C_PCA_ISA is not set
 
 #
-# Hardware Sensors Chip support
-#
-CONFIG_I2C_SENSOR=m
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-
-#
-# Other I2C Chip support
+# Miscellaneous I2C Chip support
 #
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
 CONFIG_SENSORS_EEPROM=m
 # 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_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
 #
 # Misc devices
 #
 
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
 #
 # Multimedia devices
 #
@@ -604,27 +673,31 @@ CONFIG_FB=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
-CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_FIRMWARE_EDID is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
 CONFIG_FB_ARMCLCD=y
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
 # Console display driver support
 #
-# CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
 CONFIG_FONTS=y
 # CONFIG_FONT_8x8 is not set
 # CONFIG_FONT_8x16 is not set
 # CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
 # CONFIG_FONT_PEARL_8x8 is not set
 CONFIG_FONT_ACORN_8x8=y
 # CONFIG_FONT_MINI_4x6 is not set
 # CONFIG_FONT_SUN8x16 is not set
 # CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
 
 #
 # Logo configuration
@@ -647,12 +720,18 @@ CONFIG_SND_PCM=m
 CONFIG_SND_OSSEMUL=y
 CONFIG_SND_MIXER_OSS=m
 CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=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
 
 #
 # Generic devices
 #
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
 # CONFIG_SND_DUMMY is not set
 # CONFIG_SND_MTPAV is not set
 # CONFIG_SND_SERIAL_U16550 is not set
@@ -661,6 +740,7 @@ CONFIG_SND_PCM_OSS=m
 #
 # ALSA ARM devices
 #
+CONFIG_SND_ARMAACI=m
 
 #
 # Open Sound System
@@ -672,8 +752,13 @@ CONFIG_SND_PCM_OSS=m
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 # CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 # CONFIG_USB is not set
 
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
 #
 # USB Gadget Support
 #
@@ -687,26 +772,32 @@ CONFIG_MMC=y
 CONFIG_MMC_BLOCK=y
 CONFIG_MMC_ARMMMCI=m
 
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
 CONFIG_MINIX_FS=y
 CONFIG_ROMFS_FS=y
+# CONFIG_INOTIFY is not set
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -729,11 +820,10 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 #
 CONFIG_PROC_FS=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -748,8 +838,8 @@ CONFIG_RAMFS=y
 # CONFIG_JFFS_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
 # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 CONFIG_JFFS2_ZLIB=y
 CONFIG_JFFS2_RTIME=y
@@ -766,16 +856,19 @@ CONFIG_CRAMFS=y
 #
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
 # CONFIG_NFSD_V4 is not set
 # CONFIG_NFSD_TCP is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -784,6 +877,7 @@ CONFIG_SUNRPC=y
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -803,6 +897,7 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 
 #
@@ -858,18 +953,24 @@ CONFIG_NLS_ISO8859_1=m
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_MUTEXES is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
 # 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
 # CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
@@ -895,6 +996,7 @@ CONFIG_DEBUG_LL=y
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index b324dcac1c561c8564d1473a0a8113b4733f2cdc..396efba9bacd2d6fb6351e18149576cc1d779665 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -95,5 +95,13 @@ int main(void)
   DEFINE(SYS_ERROR0,		0x9f0000);
   BLANK();
   DEFINE(SIZEOF_MACHINE_DESC,	sizeof(struct machine_desc));
+  DEFINE(MACHINFO_TYPE,		offsetof(struct machine_desc, nr));
+  DEFINE(MACHINFO_NAME,		offsetof(struct machine_desc, name));
+  DEFINE(MACHINFO_PHYSIO,	offsetof(struct machine_desc, phys_io));
+  DEFINE(MACHINFO_PGOFFIO,	offsetof(struct machine_desc, io_pg_offst));
+  BLANK();
+  DEFINE(PROC_INFO_SZ,		sizeof(struct proc_info_list));
+  DEFINE(PROCINFO_INITFUNC,	offsetof(struct proc_info_list, __cpu_flush));
+  DEFINE(PROCINFO_MMUFLAGS,	offsetof(struct proc_info_list, __cpu_mmu_flags));
   return 0; 
 }
diff --git a/arch/arm/kernel/dma-isa.c b/arch/arm/kernel/dma-isa.c
index 03532769a97f38840bea46f2969c914d857eb9d4..0a3e9ad297d8ba8be45967e811be5d226941eb90 100644
--- a/arch/arm/kernel/dma-isa.c
+++ b/arch/arm/kernel/dma-isa.c
@@ -143,12 +143,23 @@ static struct dma_ops isa_dma_ops = {
 	.residue	= isa_get_dma_residue,
 };
 
-static struct resource dma_resources[] = {
-	{ "dma1",		0x0000, 0x000f },
-	{ "dma low page", 	0x0080, 0x008f },
-	{ "dma2",		0x00c0, 0x00df },
-	{ "dma high page",	0x0480, 0x048f }
-};
+static struct resource dma_resources[] = { {
+	.name	= "dma1",
+	.start	= 0x0000,
+	.end	= 0x000f
+}, {
+	.name	= "dma low page",
+	.start	= 0x0080,
+	.end 	= 0x008f
+}, {
+	.name	= "dma2",
+	.start	= 0x00c0,
+	.end	= 0x00df
+}, {
+	.name	= "dma high page",
+	.start	= 0x0480,
+	.end	= 0x048f
+} };
 
 void __init isa_init_dma(dma_t *dma)
 {
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index 0bea65864051a28b2babe2f4ac42b123f66566b8..adf62e5eaad7a7f8ba120a76b9c39c00bc64d458 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -20,12 +20,10 @@
 #include <asm/mach-types.h>
 #include <asm/procinfo.h>
 #include <asm/ptrace.h>
+#include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/system.h>
 
-#define PROCINFO_INITFUNC       12
-#define MACHINFO_TYPE		0
-
 /*
  * Kernel startup entry point.
  * ---------------------------
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 04b66a9328ef8fbeeb51d7eed141b1cc0f1353ff..04f7344e356a30b12b5b7b7b4d8695c222960d55 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -24,14 +24,6 @@
 #include <asm/thread_info.h>
 #include <asm/system.h>
 
-#define PROCINFO_MMUFLAGS	8
-#define PROCINFO_INITFUNC	12
-
-#define MACHINFO_TYPE		0
-#define MACHINFO_PHYSIO		4
-#define MACHINFO_PGOFFIO	8
-#define MACHINFO_NAME		12
-
 #define KERNEL_RAM_ADDR	(PAGE_OFFSET + TEXT_OFFSET)
 
 /*
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 1ff75cee4b0dd0d3cf60efedada3f37805775bca..7df6e1aaa323b83ae0cedad37a943404d106868f 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -264,8 +264,12 @@ void show_fpregs(struct user_fp *regs)
 /*
  * Task structure and kernel stack allocation.
  */
-static unsigned long *thread_info_head;
-static unsigned int nr_thread_info;
+struct thread_info_list {
+	unsigned long *head;
+	unsigned int nr;
+};
+
+static DEFINE_PER_CPU(struct thread_info_list, thread_info_list) = { NULL, 0 };
 
 #define EXTRA_TASK_STRUCT	4
 
@@ -274,12 +278,15 @@ struct thread_info *alloc_thread_info(struct task_struct *task)
 	struct thread_info *thread = NULL;
 
 	if (EXTRA_TASK_STRUCT) {
-		unsigned long *p = thread_info_head;
+		struct thread_info_list *th = &get_cpu_var(thread_info_list);
+		unsigned long *p = th->head;
 
 		if (p) {
-			thread_info_head = (unsigned long *)p[0];
-			nr_thread_info -= 1;
+			th->head = (unsigned long *)p[0];
+			th->nr -= 1;
 		}
+		put_cpu_var(thread_info_list);
+
 		thread = (struct thread_info *)p;
 	}
 
@@ -300,13 +307,19 @@ struct thread_info *alloc_thread_info(struct task_struct *task)
 
 void free_thread_info(struct thread_info *thread)
 {
-	if (EXTRA_TASK_STRUCT && nr_thread_info < EXTRA_TASK_STRUCT) {
-		unsigned long *p = (unsigned long *)thread;
-		p[0] = (unsigned long)thread_info_head;
-		thread_info_head = p;
-		nr_thread_info += 1;
-	} else
-		free_pages((unsigned long)thread, THREAD_SIZE_ORDER);
+	if (EXTRA_TASK_STRUCT) {
+		struct thread_info_list *th = &get_cpu_var(thread_info_list);
+		if (th->nr < EXTRA_TASK_STRUCT) {
+			unsigned long *p = (unsigned long *)thread;
+			p[0] = (unsigned long)th->head;
+			th->head = p;
+			th->nr += 1;
+			put_cpu_var(thread_info_list);
+			return;
+		}
+		put_cpu_var(thread_info_list);
+	}
+	free_pages((unsigned long)thread, THREAD_SIZE_ORDER);
 }
 
 /*
diff --git a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S
index 3bdc8c6949c59aabf7ef812c2b890307bb0ab43f..16153c86c3f871a69674f7c293784981431f6b56 100644
--- a/arch/arm/lib/backtrace.S
+++ b/arch/arm/lib/backtrace.S
@@ -122,7 +122,7 @@ ENTRY(c_backtrace)
 #define reg   r5
 #define stack r6
 
-.Ldumpstm:	stmfd	sp!, {instr, reg, stack, r7, lr}
+.Ldumpstm:	stmfd	sp!, {instr, reg, stack, r7, r8, lr}
 		mov	stack, r0
 		mov	instr, r1
 		mov	reg, #9
@@ -145,7 +145,7 @@ ENTRY(c_backtrace)
 		adrne	r0, .Lcr
 		blne	printk
 		mov	r0, stack
-		LOADREGS(fd, sp!, {instr, reg, stack, r7, pc})
+		LOADREGS(fd, sp!, {instr, reg, stack, r7, r8, pc})
 
 .Lfp:		.asciz	" r%d = %08X%c"
 .Lcr:		.asciz	"\n"
diff --git a/arch/arm/lib/div64.S b/arch/arm/lib/div64.S
index ec9a1cd6176fddb9c97fbb79992ac6699d6ad07f..58eef66076293a923d00a81e03370bcc1c734f83 100644
--- a/arch/arm/lib/div64.S
+++ b/arch/arm/lib/div64.S
@@ -189,12 +189,12 @@ ENTRY(__do_div64)
 	moveq	pc, lr
 
 	@ Division by 0:
-	str	lr, [sp, #-4]!
+	str	lr, [sp, #-8]!
 	bl	__div0
 
 	@ as wrong as it could be...
 	mov	yl, #0
 	mov	yh, #0
 	mov	xh, #0
-	ldr	pc, [sp], #4
+	ldr	pc, [sp], #8
 
diff --git a/arch/arm/mach-aaec2000/aaed2000.c b/arch/arm/mach-aaec2000/aaed2000.c
index dc5fa8e5ebefa35121f5cc5aa6d5e65bc1f974a7..83f57da3184cceea1dd3ba64bd860b1fb9435993 100644
--- a/arch/arm/mach-aaec2000/aaed2000.c
+++ b/arch/arm/mach-aaec2000/aaed2000.c
@@ -79,7 +79,12 @@ static void __init aaed2000_init(void)
 }
 
 static struct map_desc aaed2000_io_desc[] __initdata = {
-  { EXT_GPIO_VBASE, EXT_GPIO_PBASE, EXT_GPIO_LENGTH, MT_DEVICE }, /* Ext GPIO */
+	{
+		.virtual	= EXT_GPIO_VBASE,
+		.pfn            = __phys_to_pfn(EXT_GPIO_PBASE),
+		.length         = EXT_GPIO_LENGTH,
+		.type           = MT_DEVICE
+	},
 };
 
 static void __init aaed2000_map_io(void)
diff --git a/arch/arm/mach-aaec2000/core.c b/arch/arm/mach-aaec2000/core.c
index dce4815cf53cd6c808cea279e58954d12f0db5bc..65be5efd633c7b618c71f1a2e478ea8501b3c110 100644
--- a/arch/arm/mach-aaec2000/core.c
+++ b/arch/arm/mach-aaec2000/core.c
@@ -20,7 +20,6 @@
 #include <linux/interrupt.h>
 #include <linux/timex.h>
 #include <linux/signal.h>
-#include <linux/amba/bus.h>
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
@@ -50,12 +49,12 @@
 static struct map_desc standard_io_desc[] __initdata = {
 	{
 		.virtual	= VIO_APB_BASE,
-		.physical	= __phys_to_pfn(PIO_APB_BASE),
+		.pfn		= __phys_to_pfn(PIO_APB_BASE),
 		.length		= IO_APB_LENGTH,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= VIO_AHB_BASE,
-		.physical	= __phys_to_pfn(PIO_AHB_BASE),
+		.pfn		= __phys_to_pfn(PIO_AHB_BASE),
 		.length		= IO_AHB_LENGTH,
 		.type		= MT_DEVICE
 	}
diff --git a/arch/arm/mach-aaec2000/core.h b/arch/arm/mach-aaec2000/core.h
index b6029a95f19cfe9dfaec885e9c61f1aefd439969..59501b5731674b5a99c5119916b335fec7300c85 100644
--- a/arch/arm/mach-aaec2000/core.h
+++ b/arch/arm/mach-aaec2000/core.h
@@ -9,6 +9,7 @@
  *
  */
 
+#include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
 
 struct sys_timer;
diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c
index 9d8331be2b58ec359d8b262352be12f3b0f2056c..12ea58a3b84f2472ac96a3d869f4e26ba01e0d00 100644
--- a/arch/arm/mach-imx/generic.c
+++ b/arch/arm/mach-imx/generic.c
@@ -195,56 +195,6 @@ void __init imx_set_mmc_info(struct imxmmc_platform_data *info)
 }
 EXPORT_SYMBOL(imx_set_mmc_info);
 
-static struct resource imx_uart1_resources[] = {
-	[0] = {
-		.start	= 0x00206000,
-		.end	= 0x002060FF,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= (UART1_MINT_RX),
-		.end	= (UART1_MINT_RX),
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= (UART1_MINT_TX),
-		.end	= (UART1_MINT_TX),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device imx_uart1_device = {
-	.name		= "imx-uart",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(imx_uart1_resources),
-	.resource	= imx_uart1_resources,
-};
-
-static struct resource imx_uart2_resources[] = {
-	[0] = {
-		.start	= 0x00207000,
-		.end	= 0x002070FF,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= (UART2_MINT_RX),
-		.end	= (UART2_MINT_RX),
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= (UART2_MINT_TX),
-		.end	= (UART2_MINT_TX),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device imx_uart2_device = {
-	.name		= "imx-uart",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(imx_uart2_resources),
-	.resource	= imx_uart2_resources,
-};
-
 static struct imxfb_mach_info imx_fb_info;
 
 void __init set_imx_fb_info(struct imxfb_mach_info *hard_imx_fb_info)
@@ -283,8 +233,6 @@ static struct platform_device imxfb_device = {
 static struct platform_device *devices[] __initdata = {
 	&imx_mmc_device,
 	&imxfb_device,
-	&imx_uart1_device,
-	&imx_uart2_device,
 };
 
 static struct map_desc imx_io_desc[] __initdata = {
diff --git a/arch/arm/mach-imx/mx1ads.c b/arch/arm/mach-imx/mx1ads.c
index e34d0df90aed897e606d44a4ab8f5f607bbfd25a..da893c80d471550c59a51acbeeb31d97437c730b 100644
--- a/arch/arm/mach-imx/mx1ads.c
+++ b/arch/arm/mach-imx/mx1ads.c
@@ -26,6 +26,7 @@
 
 #include <asm/mach/arch.h>
 #include <asm/arch/mmc.h>
+#include <asm/arch/imx-uart.h>
 #include <linux/interrupt.h>
 #include "generic.h"
 
@@ -48,8 +49,70 @@ static struct platform_device cs89x0_device = {
 	.resource	= cs89x0_resources,
 };
 
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct resource imx_uart1_resources[] = {
+	[0] = {
+		.start	= 0x00206000,
+		.end	= 0x002060FF,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= (UART1_MINT_RX),
+		.end	= (UART1_MINT_RX),
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= (UART1_MINT_TX),
+		.end	= (UART1_MINT_TX),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device imx_uart1_device = {
+	.name		= "imx-uart",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(imx_uart1_resources),
+	.resource	= imx_uart1_resources,
+	.dev = {
+		.platform_data = &uart_pdata,
+	}
+};
+
+static struct resource imx_uart2_resources[] = {
+	[0] = {
+		.start	= 0x00207000,
+		.end	= 0x002070FF,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= (UART2_MINT_RX),
+		.end	= (UART2_MINT_RX),
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= (UART2_MINT_TX),
+		.end	= (UART2_MINT_TX),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device imx_uart2_device = {
+	.name		= "imx-uart",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(imx_uart2_resources),
+	.resource	= imx_uart2_resources,
+	.dev = {
+		.platform_data = &uart_pdata,
+	}
+};
+
 static struct platform_device *devices[] __initdata = {
 	&cs89x0_device,
+	&imx_uart1_device,
+	&imx_uart2_device,
 };
 
 #ifdef CONFIG_MMC_IMX
@@ -75,6 +138,17 @@ mx1ads_init(void)
 	imx_gpio_mode(GPIO_PORTB | GPIO_GIUS | GPIO_IN | 20);
 	imx_set_mmc_info(&mx1ads_mmc_info);
 #endif
+
+	imx_gpio_mode(PC9_PF_UART1_CTS);
+	imx_gpio_mode(PC10_PF_UART1_RTS);
+	imx_gpio_mode(PC11_PF_UART1_TXD);
+	imx_gpio_mode(PC12_PF_UART1_RXD);
+
+	imx_gpio_mode(PB28_PF_UART2_CTS);
+	imx_gpio_mode(PB29_PF_UART2_RTS);
+	imx_gpio_mode(PB30_PF_UART2_TXD);
+	imx_gpio_mode(PB31_PF_UART2_RXD);
+
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
@@ -87,7 +161,7 @@ mx1ads_map_io(void)
 MACHINE_START(MX1ADS, "Motorola MX1ADS")
 	/* Maintainer: Sascha Hauer, Pengutronix */
 	.phys_io	= 0x00200000,
-	.io_pg_offst	= ((0xe0200000) >> 18) & 0xfffc,
+	.io_pg_offst	= ((0xe0000000) >> 18) & 0xfffc,
 	.boot_params	= 0x08000100,
 	.map_io		= mx1ads_map_io,
 	.init_irq	= imx_init_irq,
diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig
index 5bf50a2a737ddcff4ee342560828519f6f876b9a..2a39f9e481ad2d455ae6f00b13f26042755f37d8 100644
--- a/arch/arm/mach-ixp4xx/Kconfig
+++ b/arch/arm/mach-ixp4xx/Kconfig
@@ -11,6 +11,7 @@ comment "IXP4xx Platforms"
 config MACH_NSLU2
 	bool
 	prompt "Linksys NSLU2"
+	select PCI
 	help
 	  Say 'Y' here if you want your kernel to support Linksys's
 	  NSLU2 NAS device. For more information on this platform,
@@ -18,6 +19,7 @@ config MACH_NSLU2
 
 config ARCH_AVILA
 	bool "Avila"
+	select PCI
 	help
 	  Say 'Y' here if you want your kernel to support the Gateworks
 	  Avila Network Platform. For more information on this platform,
@@ -25,6 +27,7 @@ config ARCH_AVILA
 
 config ARCH_ADI_COYOTE
 	bool "Coyote"
+	select PCI
 	help
 	  Say 'Y' here if you want your kernel to support the ADI 
 	  Engineering Coyote Gateway Reference Platform. For more
@@ -32,6 +35,7 @@ config ARCH_ADI_COYOTE
 
 config ARCH_IXDP425
 	bool "IXDP425"
+	select PCI
 	help
 	  Say 'Y' here if you want your kernel to support Intel's 
 	  IXDP425 Development Platform (Also known as Richfield).  
@@ -39,6 +43,7 @@ config ARCH_IXDP425
 
 config MACH_IXDPG425
 	bool "IXDPG425"
+	select PCI
 	help
 	  Say 'Y' here if you want your kernel to support Intel's
 	  IXDPG425 Development Platform (Also known as Montajade).
@@ -46,6 +51,7 @@ config MACH_IXDPG425
 
 config MACH_IXDP465
 	bool "IXDP465"
+	select PCI
 	help
 	  Say 'Y' here if you want your kernel to support Intel's
 	  IXDP465 Development Platform (Also known as BMP).
@@ -72,6 +78,7 @@ config ARCH_PRPMC1100
 config MACH_NAS100D
 	bool
 	prompt "NAS100D"
+	select PCI
 	help
 	  Say 'Y' here if you want your kernel to support Iomega's
 	  NAS 100d device. For more information on this platform,
@@ -96,6 +103,7 @@ config CPU_IXP46X
 config MACH_GTWX5715
 	bool "Gemtek WX5715 (Linksys WRV54G)"
 	depends on ARCH_IXP4XX
+	select PCI
 	help
 		This board is currently inside the Linksys WRV54G Gateways.
 
@@ -110,11 +118,16 @@ config MACH_GTWX5715
 		"High Speed" UART is n/c (as far as I can tell)
 		20 Pin ARM/Xscale JTAG interface on J2
 
-
 comment "IXP4xx Options"
 
+config DMABOUNCE
+	bool
+	default y
+	depends on PCI
+
 config IXP4XX_INDIRECT_PCI
 	bool "Use indirect PCI memory access"
+	depends on PCI
 	help
           IXP4xx provides two methods of accessing PCI memory space:
 
diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile
index 0471044fa179869a26ac07b41d63274dfd595c3b..5a4aaa0e0a0977f8d993a1ceb91f2d2af4dd9c71 100644
--- a/arch/arm/mach-ixp4xx/Makefile
+++ b/arch/arm/mach-ixp4xx/Makefile
@@ -2,8 +2,9 @@
 # Makefile for the linux kernel.
 #
 
-obj-y	+= common.o common-pci.o 
+obj-y	+= common.o
 
+obj-$(CONFIG_PCI)		+= common-pci.o
 obj-$(CONFIG_ARCH_IXDP4XX)	+= ixdp425-pci.o ixdp425-setup.o
 obj-$(CONFIG_MACH_IXDPG425)	+= ixdpg425-pci.o coyote-setup.o
 obj-$(CONFIG_ARCH_ADI_COYOTE)	+= coyote-pci.o coyote-setup.o
diff --git a/arch/arm/mach-pxa/dma.c b/arch/arm/mach-pxa/dma.c
index 458112b21e25df5008783edab1d288d51e338dd5..7d8c85486c669065554d1857b4359ce94ee9b6c8 100644
--- a/arch/arm/mach-pxa/dma.c
+++ b/arch/arm/mach-pxa/dma.c
@@ -45,23 +45,16 @@ int pxa_request_dma (char *name, pxa_dma_prio prio,
 
 	local_irq_save(flags);
 
-	/* try grabbing a DMA channel with the requested priority */
-	for (i = prio; i < prio + PXA_DMA_NBCH(prio); i++) {
-		if (!dma_channels[i].name) {
-			found = 1;
-			break;
-		}
-	}
-
-	if (!found) {
-		/* requested prio group is full, try hier priorities */
-		for (i = prio-1; i >= 0; i--) {
+	do {
+		/* try grabbing a DMA channel with the requested priority */
+		pxa_for_each_dma_prio (i, prio) {
 			if (!dma_channels[i].name) {
 				found = 1;
 				break;
 			}
 		}
-	}
+		/* if requested prio group is full, try a hier priority */
+	} while (!found && prio--);
 
 	if (found) {
 		DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 98356f810007fad31d4fdc2cc39bea2e9b1b5c68..02e188d98e7d6d8565c4d06a2ddf9988776126e1 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -95,7 +95,10 @@ static void __init mainstone_init_irq(void)
 	for(irq = MAINSTONE_IRQ(0); irq <= MAINSTONE_IRQ(15); irq++) {
 		set_irq_chip(irq, &mainstone_irq_chip);
 		set_irq_handler(irq, do_level_IRQ);
-		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+		if (irq == MAINSTONE_IRQ(10) || irq == MAINSTONE_IRQ(14))
+			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE | IRQF_NOAUTOEN);
+		else
+			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 	set_irq_flags(MAINSTONE_IRQ(8), 0);
 	set_irq_flags(MAINSTONE_IRQ(12), 0);
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index d4a586e38d5b2665c797b9558ff24abdc8937a54..693fb1e396e033e95ecd6afdce8552dec4ef4591 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -137,8 +137,11 @@ static struct amba_device *amba_devs[] __initdata = {
 static void __init gic_init_irq(void)
 {
 #ifdef CONFIG_REALVIEW_MPCORE
+	unsigned int pldctrl;
 	writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK));
-	writel(0x008003c0, __io_address(REALVIEW_SYS_BASE) + 0xd8);
+	pldctrl = readl(__io_address(REALVIEW_SYS_BASE)	+ 0xd8);
+	pldctrl |= 0x00800000;	/* New irq mode */
+	writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + 0xd8);
 	writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
 #endif
 	gic_dist_init(__io_address(REALVIEW_GIC_DIST_BASE));
diff --git a/arch/arm/mach-s3c2410/sleep.S b/arch/arm/mach-s3c2410/sleep.S
index 832fb86a03b430343dd26e9e5be83168ab644c17..73de2eaca22a1c136db339177eb95d1acc4a7610 100644
--- a/arch/arm/mach-s3c2410/sleep.S
+++ b/arch/arm/mach-s3c2410/sleep.S
@@ -59,8 +59,7 @@ ENTRY(s3c2410_cpu_suspend)
 	mrc	p15, 0, r5, c13, c0, 0	@ PID
 	mrc	p15, 0, r6, c3, c0, 0	@ Domain ID
 	mrc	p15, 0, r7, c2, c0, 0	@ translation table base address
-	mrc	p15, 0, r8, c2, c0, 0	@ auxiliary control register
-	mrc	p15, 0, r9, c1, c0, 0	@ control register
+	mrc	p15, 0, r8, c1, c0, 0	@ control register
 
 	stmia	r0, { r4 - r13 }
 
@@ -165,7 +164,6 @@ ENTRY(s3c2410_cpu_resume)
 	mcr	p15, 0, r5, c13, c0, 0		@ PID
 	mcr	p15, 0, r6, c3, c0, 0		@ Domain ID
 	mcr	p15, 0, r7, c2, c0, 0		@ translation table base
-	mcr	p15, 0, r8, c1, c1, 0		@ auxilliary control
 
 #ifdef CONFIG_DEBUG_RESUME
 	mov	r3, #'R'
@@ -173,7 +171,7 @@ ENTRY(s3c2410_cpu_resume)
 #endif
 
 	ldr	r2, =resume_with_mmu
-	mcr	p15, 0, r9, c1, c0, 0		@ turn on MMU, etc
+	mcr	p15, 0, r8, c1, c0, 0		@ turn on MMU, etc
 	nop					@ second-to-last before mmu
 	mov	pc, r2				@ go back to virtual address
 
diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
index c131a5201b5ba885ba9448381cfaab27ab345634..b3a56024182ee6ac15cc3e679e815661ee7095f4 100644
--- a/arch/arm/mach-sa1100/irq.c
+++ b/arch/arm/mach-sa1100/irq.c
@@ -199,10 +199,26 @@ static void sa1100_unmask_irq(unsigned int irq)
 	ICMR |= (1 << irq);
 }
 
+/*
+ * Apart form GPIOs, only the RTC alarm can be a wakeup event.
+ */
+static int sa1100_set_wake(unsigned int irq, unsigned int on)
+{
+	if (irq == IRQ_RTCAlrm) {
+		if (on)
+			PWER |= PWER_RTC;
+		else
+			PWER &= ~PWER_RTC;
+		return 0;
+	}
+	return -EINVAL;
+}
+
 static struct irqchip sa1100_normal_chip = {
 	.ack		= sa1100_mask_irq,
 	.mask		= sa1100_mask_irq,
 	.unmask		= sa1100_unmask_irq,
+	.set_wake	= sa1100_set_wake,
 };
 
 static struct resource irq_resource = {
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 25e0ca3e598cfc97ac0140aaa383effaf5e76b77..c1f7180c7beda07ff35d3211880902b8a83c2a2c 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -141,7 +141,7 @@ __ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
  		return NULL;
  	addr = (unsigned long)area->addr;
  	if (remap_area_pages(addr, pfn, size, flags)) {
- 		vfree((void *)addr);
+ 		vunmap((void *)addr);
  		return NULL;
  	}
  	return (void __iomem *) (offset + (char *)addr);
@@ -173,7 +173,7 @@ EXPORT_SYMBOL(__ioremap);
 
 void __iounmap(void __iomem *addr)
 {
-	vfree((void *) (PAGE_MASK & (unsigned long) addr));
+	vunmap((void *)(PAGE_MASK & (unsigned long)addr));
 }
 EXPORT_SYMBOL(__iounmap);
 
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 8ab5300dcb9468a1b9d446f1e82aeb6813888d83..6d7de9c0412f6dcc8901291175590b3107e58e54 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -12,7 +12,7 @@
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
-# Last update: Mon Feb 20 10:18:02 2006
+# Last update: Mon May 8 20:11:05 2006
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -566,8 +566,8 @@ switchgrass		MACH_SWITCHGRASS	SWITCHGRASS		549
 ens_cmu			MACH_ENS_CMU		ENS_CMU			550
 mm6_sdb			MACH_MM6_SDB		MM6_SDB			551
 saturn			MACH_SATURN		SATURN			552
-argonplusevb		MACH_ARGONPLUSEVB	ARGONPLUSEVB		553
-scma11evb		MACH_SCMA11EVB		SCMA11EVB		554
+i30030evb		MACH_ARGONPLUSEVB	ARGONPLUSEVB		553
+mxc27530evb		MACH_SCMA11EVB		SCMA11EVB		554
 smdk2800		MACH_SMDK2800		SMDK2800		555
 mtwilson		MACH_MTWILSON		MTWILSON		556
 ziti			MACH_ZITI		ZITI			557
@@ -647,7 +647,7 @@ sendt			MACH_SENDT		SENDT			630
 mx2jazz			MACH_MX2JAZZ		MX2JAZZ			631
 multiio			MACH_MULTIIO		MULTIIO			632
 hrdisplay		MACH_HRDISPLAY		HRDISPLAY		633
-scma11bb		MACH_SCMA11BB		SCMA11BB		634
+mxc27530ads		MACH_SCMA11BB		SCMA11BB		634
 trizeps3		MACH_TRIZEPS3		TRIZEPS3		635
 zefeerdza		MACH_ZEFEERDZA		ZEFEERDZA		636
 zefeerdzb		MACH_ZEFEERDZB		ZEFEERDZB		637
@@ -721,7 +721,7 @@ gp32			MACH_GP32		GP32			706
 gem			MACH_GEM		GEM			707
 i858			MACH_I858		I858			708
 hx2750			MACH_HX2750		HX2750			709
-zeusevb			MACH_ZEUSEVB		ZEUSEVB			710
+mxc91131evb		MACH_ZEUSEVB		ZEUSEVB			710
 p700			MACH_P700		P700			711
 cpe			MACH_CPE		CPE			712
 spitz			MACH_SPITZ		SPITZ			713
@@ -802,7 +802,7 @@ cpuat91			MACH_CPUAT91		CPUAT91			787
 rea9200			MACH_REA9200		REA9200			788
 acts_pune_sa1110	MACH_ACTS_PUNE_SA1110	ACTS_PUNE_SA1110	789
 ixp425			MACH_IXP425		IXP425			790
-argonplusodyssey	MACH_ARGONPLUSODYSSEY	ARGONPLUSODYSSEY	791
+i30030ads		MACH_ARGONPLUSODYSSEY	ARGONPLUSODYSSEY	791
 perch			MACH_PERCH		PERCH			792
 eis05r1			MACH_EIS05R1		EIS05R1			793
 pepperpad		MACH_PEPPERPAD		PEPPERPAD		794
@@ -827,7 +827,7 @@ micro9l			MACH_MICRO9L		MICRO9L			812
 uc5471dsp		MACH_UC5471DSP		UC5471DSP		813
 sj5471eng		MACH_SJ5471ENG		SJ5471ENG		814
 none			MACH_CMPXA26X		CMPXA26X		815
-nc			MACH_NC			NC			816
+nc1			MACH_NC			NC			816
 omap_palmte		MACH_OMAP_PALMTE	OMAP_PALMTE		817
 ajax52x			MACH_AJAX52X		AJAX52X			818
 siriustar		MACH_SIRIUSTAR		SIRIUSTAR		819
@@ -930,7 +930,7 @@ netclient		MACH_NETCLIENT		NETCLIENT		916
 xscale_palmtt5		MACH_XSCALE_PALMTT5	XSCALE_PALMTT5		917
 xscale_palmtc		MACH_OMAP_PALMTC	OMAP_PALMTC		918
 omap_apollon		MACH_OMAP_APOLLON	OMAP_APOLLON		919
-argonlvevb		MACH_ARGONLVEVB		ARGONLVEVB		920
+mxc30030evb		MACH_ARGONLVEVB		ARGONLVEVB		920
 rea_2d			MACH_REA_2D		REA_2D			921
 eti3e524		MACH_TI3E524		TI3E524			922
 ateb9200		MACH_ATEB9200		ATEB9200		923
@@ -965,7 +965,78 @@ sisteron		MACH_SISTERON		SISTERON		951
 rx1950			MACH_RX1950		RX1950			952
 tsc_venus		MACH_TSC_VENUS		TSC_VENUS		953
 ds101j			MACH_DS101J		DS101J			954
-mxc300_30ads		MACH_MXC30030ADS	MXC30030ADS		955
+mxc30030ads		MACH_MXC30030ADS	MXC30030ADS		955
 fujitsu_wimaxsoc	MACH_FUJITSU_WIMAXSOC	FUJITSU_WIMAXSOC	956
 dualpcmodem		MACH_DUALPCMODEM	DUALPCMODEM		957
 gesbc9312		MACH_GESBC9312		GESBC9312		958
+htcapache		MACH_HTCAPACHE		HTCAPACHE		959
+ixdp435			MACH_IXDP435		IXDP435			960
+catprovt100		MACH_CATPROVT100	CATPROVT100		961
+picotux1xx		MACH_PICOTUX1XX		PICOTUX1XX		962
+picotux2xx		MACH_PICOTUX2XX		PICOTUX2XX		963
+dsmg600			MACH_DSMG600		DSMG600			964
+empc2			MACH_EMPC2		EMPC2			965
+ventura			MACH_VENTURA		VENTURA			966
+phidget_sbc		MACH_PHIDGET_SBC	PHIDGET_SBC		967
+ij3k			MACH_IJ3K		IJ3K			968
+pisgah			MACH_PISGAH		PISGAH			969
+omap_fsample		MACH_OMAP_FSAMPLE	OMAP_FSAMPLE		970
+sg720			MACH_SG720		SG720			971
+redfox			MACH_REDFOX		REDFOX			972
+mysh_ep9315_1		MACH_MYSH_EP9315_1	MYSH_EP9315_1		973
+tpf106			MACH_TPF106		TPF106			974
+at91rm9200kg		MACH_AT91RM9200KG	AT91RM9200KG		975
+racemt2			MACH_SLEDB		SLEDB			976
+ontrack			MACH_ONTRACK		ONTRACK			977
+pm1200			MACH_PM1200		PM1200			978
+ess24562		MACH_ESS24XXX		ESS24XXX		979
+coremp7			MACH_COREMP7		COREMP7			980
+nexcoder_6446		MACH_NEXCODER_6446	NEXCODER_6446		981
+stvc8380		MACH_STVC8380		STVC8380		982
+teklynx			MACH_TEKLYNX		TEKLYNX			983
+carbonado		MACH_CARBONADO		CARBONADO		984
+sysmos_mp730		MACH_SYSMOS_MP730	SYSMOS_MP730		985
+snapper_cl15		MACH_SNAPPER_CL15	SNAPPER_CL15		986
+pgigim			MACH_PGIGIM		PGIGIM			987
+ptx9160p2		MACH_PTX9160P2		PTX9160P2		988
+dcore1			MACH_DCORE1		DCORE1			989
+victorpxa		MACH_VICTORPXA		VICTORPXA		990
+mx2dtb			MACH_MX2DTB		MX2DTB			991
+pxa_irex_er0100		MACH_PXA_IREX_ER0100	PXA_IREX_ER0100		992
+omap_palmz71		MACH_OMAP_PALMZ71	OMAP_PALMZ71		993
+bartec_deg		MACH_BARTEC_DEG		BARTEC_DEG		994
+hw50251			MACH_HW50251		HW50251			995
+ibox			MACH_IBOX		IBOX			996
+atlaslh7a404		MACH_ATLASLH7A404	ATLASLH7A404		997
+pt2026			MACH_PT2026		PT2026			998
+htcalpine		MACH_HTCALPINE		HTCALPINE		999
+bartec_vtu		MACH_BARTEC_VTU		BARTEC_VTU		1000
+vcoreii			MACH_VCOREII		VCOREII			1001
+pdnb3			MACH_PDNB3		PDNB3			1002
+htcbeetles		MACH_HTCBEETLES		HTCBEETLES		1003
+s3c6400			MACH_S3C6400		S3C6400			1004
+s3c2443			MACH_S3C2443		S3C2443			1005
+omap_ldk		MACH_OMAP_LDK		OMAP_LDK		1006
+smdk2460		MACH_SMDK2460		SMDK2460		1007
+smdk2440		MACH_SMDK2440		SMDK2440		1008
+smdk2412		MACH_SMDK2412		SMDK2412		1009
+webbox			MACH_WEBBOX		WEBBOX			1010
+cwwndp			MACH_CWWNDP		CWWNDP			1011
+dragon			MACH_DRAGON		DRAGON			1012
+opendo_cpu_board	MACH_OPENDO_CPU_BOARD	OPENDO_CPU_BOARD	1013
+ccm2200			MACH_CCM2200		CCM2200			1014
+etwarm			MACH_ETWARM		ETWARM			1015
+m93030			MACH_M93030		M93030			1016
+cc7u			MACH_CC7U		CC7U			1017
+mtt_ranger		MACH_MTT_RANGER		MTT_RANGER		1018
+nexus			MACH_NEXUS		NEXUS			1019
+desman			MACH_DESMAN		DESMAN			1020
+bkde303			MACH_BKDE303		BKDE303			1021
+smdk2413		MACH_SMDK2413		SMDK2413		1022
+aml_m7200		MACH_AML_M7200		AML_M7200		1023
+aml_m5900		MACH_AML_M5900		AML_M5900		1024
+sg640			MACH_SG640		SG640			1025
+edg79524		MACH_EDG79524		EDG79524		1026
+ai2410			MACH_AI2410		AI2410			1027
+ixp465			MACH_IXP465		IXP465			1028
+balloon3		MACH_BALLOON3		BALLOON3		1029
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 37ff8145b5b50bf52ea9f22f5212068764167e5f..03486be04193e0497f8258d45d4be1ef02656258 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -245,7 +245,7 @@ void VFP9_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
 	 */
 	barrier();
 	trigger = fmrx(FPINST2);
-	fpscr = fmrx(FPSCR);
+	orig_fpscr = fpscr = fmrx(FPSCR);
 
  emulate:
 	exceptions = vfp_emulate_instruction(trigger, fpscr, regs);
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index c6fe99e57a0526ae2884eb49d500023ca3ef6ea0..8dfa3054f10fb0ce83576277f080caccf7644535 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -758,10 +758,10 @@ config HOTPLUG_CPU
 	bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
 	depends on SMP && HOTPLUG && EXPERIMENTAL && !X86_VOYAGER
 	---help---
-	  Say Y here to experiment with turning CPUs off and on.  CPUs
-	  can be controlled through /sys/devices/system/cpu.
+	  Say Y here to experiment with turning CPUs off and on, and to
+	  enable suspend on SMP systems. CPUs can be controlled through
+	  /sys/devices/system/cpu.
 
-	  Say N.
 
 endmenu
 
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index 4c785a67d5852d4fd1fecbd40cb4c9db2dc9868f..daee69579b1c6cd6dba672b79c48a2197453f56a 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -1066,6 +1066,14 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = {
 		     DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
 		     },
 	 },
+	{
+	 .callback = disable_acpi_pci,
+	 .ident = "HP xw9300",
+	 .matches = {
+		    DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+		    DMI_MATCH(DMI_PRODUCT_NAME, "HP xw9300 Workstation"),
+		    },
+	},
 	{}
 };
 
@@ -1102,9 +1110,6 @@ int __init acpi_boot_table_init(void)
 	dmi_check_system(acpi_dmi_table);
 #endif
 
-	if (!cpu_has_apic)
-		return -ENODEV;
-
 	/*
 	 * If acpi_disabled, bail out
 	 * One exception: acpi=ht continues far enough to enumerate LAPICs
@@ -1151,9 +1156,6 @@ int __init acpi_boot_init(void)
 
 	acpi_table_parse(ACPI_BOOT, acpi_parse_sbf);
 
-	if (!cpu_has_apic)
-		return -ENODEV;
-
 	/*
 	 * set sci_int and PM timer address
 	 */
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index f8f132aa54725fe937a016ae5dd0bb99b6be8d18..d70f2ade5cde47818a94ef3539a8d64cefb880f1 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -2238,6 +2238,8 @@ static inline void unlock_ExtINT_logic(void)
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
+int timer_uses_ioapic_pin_0;
+
 /*
  * This code may look a bit paranoid, but it's supposed to cooperate with
  * a wide range of boards and BIOS bugs.  Fortunately only the timer IRQ
@@ -2274,6 +2276,9 @@ static inline void check_timer(void)
 	pin2  = ioapic_i8259.pin;
 	apic2 = ioapic_i8259.apic;
 
+	if (pin1 == 0)
+		timer_uses_ioapic_pin_0 = 1;
+
 	printk(KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
 		vector, apic1, pin1, apic2, pin2);
 
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
index 34d21e21e0124b89830fa2db7589a9ba06217e96..6b1392d33ed51d6fcb424b9c839d7768cc840a09 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -1130,7 +1130,17 @@ int mp_register_gsi (u32 gsi, int triggering, int polarity)
 		 */
 		int irq = gsi;
 		if (gsi < MAX_GSI_NUM) {
-			if (gsi > 15)
+			/*
+			 * Retain the VIA chipset work-around (gsi > 15), but
+			 * avoid a problem where the 8254 timer (IRQ0) is setup
+			 * via an override (so it's not on pin 0 of the ioapic),
+			 * and at the same time, the pin 0 interrupt is a PCI
+			 * type.  The gsi > 15 test could cause these two pins
+			 * to be shared as IRQ0, and they are not shareable.
+			 * So test for this condition, and if necessary, avoid
+			 * the pin collision.
+			 */
+			if (gsi > 15 || (gsi == 0 && !timer_uses_ioapic_pin_0))
 				gsi = pci_irq++;
 			/*
 			 * Don't assign IRQ used by ACPI SCI
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index d77e89ac0d540361c06da2854d8450fb4c81044e..846e1639ef7ce4bb928673b1705a1590345db247 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -1320,6 +1320,8 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat
 	probe_roms();
 	for (i = 0; i < e820.nr_map; i++) {
 		struct resource *res;
+		if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)
+			continue;
 		res = kzalloc(sizeof(struct resource), GFP_ATOMIC);
 		switch (e820.map[i].type) {
 		case E820_RAM:	res->name = "System RAM"; break;
diff --git a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c
index 1a2076ce6f6a7107346a46ce29cfb8a956d2aed9..ec0fd3cfa774aa575fe6c3cf42da2af2c0e56f96 100644
--- a/arch/i386/oprofile/nmi_int.c
+++ b/arch/i386/oprofile/nmi_int.c
@@ -332,10 +332,11 @@ static int __init ppro_init(char ** cpu_type)
 {
 	__u8 cpu_model = boot_cpu_data.x86_model;
 
-	if (cpu_model > 0xd)
+	if (cpu_model == 14)
+		*cpu_type = "i386/core";
+	else if (cpu_model > 0xd)
 		return 0;
-
-	if (cpu_model == 9) {
+	else if (cpu_model == 9) {
 		*cpu_type = "i386/p6_mobile";
 	} else if (cpu_model > 5) {
 		*cpu_type = "i386/piii";
diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig
index f6a8853cd1b48fb8df9bbdab6beeca4ed886cc4a..9ea35398e10d0b9a28d43152d274a3b40dd05258 100644
--- a/arch/ia64/configs/sn2_defconfig
+++ b/arch/ia64/configs/sn2_defconfig
@@ -134,7 +134,7 @@ CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
 CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y
 CONFIG_NUMA=y
-CONFIG_NODES_SHIFT=8
+CONFIG_NODES_SHIFT=10
 CONFIG_VIRTUAL_MEM_MAP=y
 CONFIG_HOLES_IN_ZONE=y
 CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
@@ -1159,7 +1159,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 CONFIG_DEBUG_PREEMPT=y
-CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_MUTEXES is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index 7956eb9058fcb873a65b5889d66f6eb6208e4c76..d58c1c5c903a9cfdae0981411ae53604fce020f1 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -416,7 +416,7 @@ iosapic_end_level_irq (unsigned int irq)
 	ia64_vector vec = irq_to_vector(irq);
 	struct iosapic_rte_info *rte;
 
-	move_irq(irq);
+	move_native_irq(irq);
 	list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list)
 		iosapic_eoi(rte->addr, vec);
 }
@@ -458,7 +458,7 @@ iosapic_ack_edge_irq (unsigned int irq)
 {
 	irq_desc_t *idesc = irq_descp(irq);
 
-	move_irq(irq);
+	move_native_irq(irq);
 	/*
 	 * Once we have recorded IRQ_PENDING already, we can mask the
 	 * interrupt for real. This prevents IRQ storms from unhandled
diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
index 5ce908ef9c9585f5f0350503fa39caf0e3e732bf..9c72ea3f6432d115ca32090d0c8bd9c8365d5c07 100644
--- a/arch/ia64/kernel/irq.c
+++ b/arch/ia64/kernel/irq.c
@@ -101,7 +101,6 @@ void set_irq_affinity_info (unsigned int irq, int hwid, int redir)
 
 	if (irq < NR_IRQS) {
 		irq_affinity[irq] = mask;
-		set_irq_info(irq, mask);
 		irq_redir[irq] = (char) (redir & 0xff);
 	}
 }
diff --git a/arch/ia64/lib/memcpy_mck.S b/arch/ia64/lib/memcpy_mck.S
index 46c9331e7ab5f81181b5e19745c154a80c4b852e..9e534d52b1d52289a90f49417db3edb5874fd2de 100644
--- a/arch/ia64/lib/memcpy_mck.S
+++ b/arch/ia64/lib/memcpy_mck.S
@@ -6,7 +6,9 @@
  *	in1:	source address
  *	in2:	number of bytes to copy
  * Output:
- * 	0 if success, or number of byte NOT copied if error occurred.
+ *	for memcpy:    return dest
+ * 	for copy_user: return 0 if success,
+ *		       or number of byte NOT copied if error occurred.
  *
  * Copyright (C) 2002 Intel Corp.
  * Copyright (C) 2002 Ken Chen <kenneth.w.chen@intel.com>
@@ -73,6 +75,7 @@ GLOBAL_ENTRY(memcpy)
 	and	r28=0x7,in0
 	and	r29=0x7,in1
 	mov	f6=f0
+	mov	retval=in0
 	br.cond.sptk .common_code
 	;;
 END(memcpy)
@@ -84,7 +87,7 @@ GLOBAL_ENTRY(__copy_user)
 	mov	f6=f1
 	mov	saved_in0=in0	// save dest pointer
 	mov	saved_in1=in1	// save src pointer
-	mov	saved_in2=in2	// save len
+	mov	retval=r0	// initialize return value
 	;;
 .common_code:
 	cmp.gt	p15,p0=8,in2	// check for small size
@@ -92,7 +95,7 @@ GLOBAL_ENTRY(__copy_user)
 	cmp.ne	p14,p0=0,r29	// check src alignment
 	add	src0=0,in1
 	sub	r30=8,r28	// for .align_dest
-	mov	retval=r0	// initialize return value
+	mov	saved_in2=in2	// save len
 	;;
 	add	dst0=0,in0
 	add	dst1=1,in0	// dest odd index
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index 856ef1a832b9466031309cd9b20f4dda31242396..f78866367b70b2abbee2f0ba1e746b775daca6b4 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -90,15 +90,15 @@ void __kprobes arch_remove_kprobe(struct kprobe *p)
 
 static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
 {
-	kprobe_opcode_t insn = *p->ainsn.insn;
-
 	regs->msr |= MSR_SE;
 
-	/* single step inline if it is a trap variant */
-	if (is_trap(insn))
-		regs->nip = (unsigned long)p->addr;
-	else
-		regs->nip = (unsigned long)p->ainsn.insn;
+	/*
+	 * On powerpc we should single step on the original
+	 * instruction even if the probed insn is a trap
+	 * variant as values in regs could play a part in
+	 * if the trap is taken or not
+	 */
+	regs->nip = (unsigned long)p->ainsn.insn;
 }
 
 static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 1cb69e8fb0b10139f2f83531854f40cde57b63a0..9a07f97f0712d78ce271b6ec35190cf92032be26 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -885,6 +885,74 @@ void __init unflatten_device_tree(void)
 	DBG(" <- unflatten_device_tree()\n");
 }
 
+/*
+ * ibm,pa-features is a per-cpu property that contains a string of
+ * attribute descriptors, each of which has a 2 byte header plus up
+ * to 254 bytes worth of processor attribute bits.  First header
+ * byte specifies the number of bytes following the header.
+ * Second header byte is an "attribute-specifier" type, of which
+ * zero is the only currently-defined value.
+ * Implementation:  Pass in the byte and bit offset for the feature
+ * that we are interested in.  The function will return -1 if the
+ * pa-features property is missing, or a 1/0 to indicate if the feature
+ * is supported/not supported.  Note that the bit numbers are
+ * big-endian to match the definition in PAPR.
+ */
+static struct ibm_pa_feature {
+	unsigned long	cpu_features;	/* CPU_FTR_xxx bit */
+	unsigned int	cpu_user_ftrs;	/* PPC_FEATURE_xxx bit */
+	unsigned char	pabyte;		/* byte number in ibm,pa-features */
+	unsigned char	pabit;		/* bit number (big-endian) */
+	unsigned char	invert;		/* if 1, pa bit set => clear feature */
+} ibm_pa_features[] __initdata = {
+	{0, PPC_FEATURE_HAS_MMU,	0, 0, 0},
+	{0, PPC_FEATURE_HAS_FPU,	0, 1, 0},
+	{CPU_FTR_SLB, 0,		0, 2, 0},
+	{CPU_FTR_CTRL, 0,		0, 3, 0},
+	{CPU_FTR_NOEXECUTE, 0,		0, 6, 0},
+	{CPU_FTR_NODSISRALIGN, 0,	1, 1, 1},
+	{CPU_FTR_CI_LARGE_PAGE, 0,	1, 2, 0},
+};
+
+static void __init check_cpu_pa_features(unsigned long node)
+{
+	unsigned char *pa_ftrs;
+	unsigned long len, tablelen, i, bit;
+
+	pa_ftrs = of_get_flat_dt_prop(node, "ibm,pa-features", &tablelen);
+	if (pa_ftrs == NULL)
+		return;
+
+	/* find descriptor with type == 0 */
+	for (;;) {
+		if (tablelen < 3)
+			return;
+		len = 2 + pa_ftrs[0];
+		if (tablelen < len)
+			return;		/* descriptor 0 not found */
+		if (pa_ftrs[1] == 0)
+			break;
+		tablelen -= len;
+		pa_ftrs += len;
+	}
+
+	/* loop over bits we know about */
+	for (i = 0; i < ARRAY_SIZE(ibm_pa_features); ++i) {
+		struct ibm_pa_feature *fp = &ibm_pa_features[i];
+
+		if (fp->pabyte >= pa_ftrs[0])
+			continue;
+		bit = (pa_ftrs[2 + fp->pabyte] >> (7 - fp->pabit)) & 1;
+		if (bit ^ fp->invert) {
+			cur_cpu_spec->cpu_features |= fp->cpu_features;
+			cur_cpu_spec->cpu_user_features |= fp->cpu_user_ftrs;
+		} else {
+			cur_cpu_spec->cpu_features &= ~fp->cpu_features;
+			cur_cpu_spec->cpu_user_features &= ~fp->cpu_user_ftrs;
+		}
+	}
+}
+
 static int __init early_init_dt_scan_cpus(unsigned long node,
 					  const char *uname, int depth,
 					  void *data)
@@ -969,6 +1037,8 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
 	}
 #endif /* CONFIG_ALTIVEC */
 
+	check_cpu_pa_features(node);
+
 #ifdef CONFIG_PPC_PSERIES
 	if (nthreads > 1)
 		cur_cpu_spec->cpu_features |= CPU_FTR_SMT;
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 078fb5533541d001db70eb618fb59a791d0b35f6..2d80653aa2af54e866eee220d8193dde6d663c49 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -1636,7 +1636,7 @@ static int __init prom_find_machine_type(void)
 			   compat, sizeof(compat)-1);
 	if (len <= 0)
 		return PLATFORM_GENERIC;
-	if (strncmp(compat, RELOC("chrp"), 4))
+	if (strcmp(compat, RELOC("chrp")))
 		return PLATFORM_GENERIC;
 
 	/* Default to pSeries. We need to know if we are running LPAR */
diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c
index a1bda6f96fd1ff2c4a50f7d2221779e3b6629124..40020c65c89e4da0e2365fac47316593ee712c12 100644
--- a/arch/powerpc/platforms/pseries/eeh_event.c
+++ b/arch/powerpc/platforms/pseries/eeh_event.c
@@ -118,7 +118,15 @@ int eeh_send_failure_event (struct device_node *dn,
 {
 	unsigned long flags;
 	struct eeh_event *event;
+	char *location;
 
+	if (!mem_init_done) {
+		printk(KERN_ERR "EEH: event during early boot not handled\n");
+		location = (char *) get_property(dn, "ibm,loc-code", NULL);
+		printk(KERN_ERR "EEH: device node = %s\n", dn->full_name);
+		printk(KERN_ERR "EEH: PCI location = %s\n", location);
+		return 1;
+	}
 	event = kmalloc(sizeof(*event), GFP_ATOMIC);
 	if (event == NULL) {
 		printk (KERN_ERR "EEH: out of memory, event not handled\n");
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 5eb55ef1c91cd20a99ffe811596458c7d8acf326..5f79f01c44f2aff1d88c8edf2375d783195584d1 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -255,7 +255,7 @@ static int __init pSeries_init_panel(void)
 {
 	/* Manually leave the kernel version on the panel. */
 	ppc_md.progress("Linux ppc64\n", 0);
-	ppc_md.progress(system_utsname.version, 0);
+	ppc_md.progress(system_utsname.release, 0);
 
 	return 0;
 }
diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
index ec53c7d65f2b39e7a43a07d50d4d22d228523986..7a2f20583be406beb0f42cb16f64e3a514fd1a04 100644
--- a/arch/ppc/kernel/head_8xx.S
+++ b/arch/ppc/kernel/head_8xx.S
@@ -355,9 +355,7 @@ InstructionTLBMiss:
 
 	. = 0x1200
 DataStoreTLBMiss:
-#ifdef CONFIG_8xx_CPU6
 	stw	r3, 8(r0)
-#endif
 	DO_8xx_CPU6(0x3f80, r3)
 	mtspr	SPRN_M_TW, r10	/* Save a couple of working registers */
 	mfcr	r10
@@ -417,9 +415,7 @@ DataStoreTLBMiss:
 	lwz	r11, 0(r0)
 	mtcr	r11
 	lwz	r11, 4(r0)
-#ifdef CONFIG_8xx_CPU6
 	lwz	r3, 8(r0)
-#endif
 	rfi
 
 /* This is an instruction TLB error on the MPC8xx.  This could be due
diff --git a/arch/ppc/platforms/mpc866ads_setup.c b/arch/ppc/platforms/mpc866ads_setup.c
index 6ce3b842defee25ffb7fb23f7ac8fd704719777a..d919dab6134768ae67249071c7ba2577ccb5cf73 100644
--- a/arch/ppc/platforms/mpc866ads_setup.c
+++ b/arch/ppc/platforms/mpc866ads_setup.c
@@ -378,7 +378,7 @@ int __init mpc866ads_init(void)
 	ppc_sys_device_setfunc(MPC8xx_CPM_SMC1, PPC_SYS_FUNC_UART);
 #endif
 
-#ifdef CONFIG_SERIAL_CPM_SMCer
+#ifdef CONFIG_SERIAL_CPM_SMC
 	ppc_sys_device_enable(MPC8xx_CPM_SMC2);
 	ppc_sys_device_setfunc(MPC8xx_CPM_SMC2, PPC_SYS_FUNC_UART);
 #endif
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index ef5b9c44b86b50ac5c7f80fd3e0ddda66dcf3f1a..4d53b2739357d21aa707d838184dedf29486e220 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1650,3 +1650,11 @@ sys_tee_wrapper:
 	llgfr	%r4,%r4			# size_t
 	llgfr	%r5,%r5			# unsigned int
 	jg	sys_tee
+
+	.globl compat_sys_vmsplice_wrapper
+compat_sys_vmsplice_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# compat_iovec *
+	llgfr	%r4,%r4			# unsigned int
+	llgfr	%r5,%r5			# unsigned int
+	jg	compat_sys_vmsplice
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index fc2c0767202b22d6595f940dc7f278d36e704810..93be1d56c03662d46da46e1effc788a954dbc096 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -317,3 +317,4 @@ SYSCALL(sys_get_robust_list,sys_get_robust_list,compat_sys_get_robust_list_wrapp
 SYSCALL(sys_splice,sys_splice,sys_splice_wrapper)
 SYSCALL(sys_sync_file_range,sys_sync_file_range,sys_sync_file_range_wrapper)
 SYSCALL(sys_tee,sys_tee,sys_tee_wrapper)
+SYSCALL(sys_vmsplice,sys_vmsplice,compat_sys_vmsplice_wrapper)
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index fea043b69b913953c95d5c9ab97307d26e0083c5..029f09901b851fbd561e18d3be858e805df2bcb8 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -249,18 +249,19 @@ static inline void stop_hz_timer(void)
 	unsigned long flags;
 	unsigned long seq, next;
 	__u64 timer, todval;
+	int cpu = smp_processor_id();
 
 	if (sysctl_hz_timer != 0)
 		return;
 
-	cpu_set(smp_processor_id(), nohz_cpu_mask);
+	cpu_set(cpu, nohz_cpu_mask);
 
 	/*
 	 * Leave the clock comparator set up for the next timer
 	 * tick if either rcu or a softirq is pending.
 	 */
-	if (rcu_pending(smp_processor_id()) || local_softirq_pending()) {
-		cpu_clear(smp_processor_id(), nohz_cpu_mask);
+	if (rcu_needs_cpu(cpu) || local_softirq_pending()) {
+		cpu_clear(cpu, nohz_cpu_mask);
 		return;
 	}
 
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 460f72e640e6593e37005bc62f5a8af0b46bbdd8..f9ff29734848709b56dfb873d0e530b5aebf79db 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -274,6 +274,11 @@ void *sbus_alloc_consistent(struct sbus_dev *sdev, long len, u32 *dma_addrp)
 	if (mmu_map_dma_area(dma_addrp, va, res->start, len_total) != 0)
 		goto err_noiommu;
 
+	/* Set the resource name, if known. */
+	if (sdev) {
+		res->name = sdev->prom_name;
+	}
+
 	return (void *)res->start;
 
 err_noiommu:
diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c
index 787d5f1347ec48de6538bc46e44d712acbddab40..598682f31ebfd942eec586fc23fd6919ce42d710 100644
--- a/arch/sparc/kernel/module.c
+++ b/arch/sparc/kernel/module.c
@@ -113,6 +113,7 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
 
 		switch (ELF32_R_TYPE(rel[i].r_info)) {
 		case R_SPARC_32:
+		case R_SPARC_UA32:
 			location[0] = v >> 24;
 			location[1] = v >> 16;
 			location[2] = v >>  8;
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index ec1c9687d67920312df790ec0b550d3740c1c08c..4b376fae752c464cf2f2426619a26a3a606c703a 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -251,19 +251,9 @@ EXPORT_SYMBOL(__prom_getchild);
 EXPORT_SYMBOL(__prom_getsibling);
 
 /* sparc library symbols */
-EXPORT_SYMBOL(memchr);
 EXPORT_SYMBOL(memscan);
 EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strcpy);
-EXPORT_SYMBOL(strncpy);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strcmp);
 EXPORT_SYMBOL(strncmp);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(page_kernel);
 
 /* Special internal versions of library functions. */
@@ -317,6 +307,3 @@ EXPORT_SYMBOL(do_BUG);
 
 /* Sun Power Management Idle Handler */
 EXPORT_SYMBOL(pm_idle);
-
-/* Binfmt_misc needs this */
-EXPORT_SYMBOL(sys_close);
diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
index db8faa75f94dd318515ad2bcb86b59bf5df5e942..6e1135cc03b08a42e4def9f77511ef0322bd09bc 100644
--- a/arch/sparc/kernel/systbls.S
+++ b/arch/sparc/kernel/systbls.S
@@ -23,7 +23,7 @@ sys_call_table:
 /*10*/  .long sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys_mknod
 /*15*/	.long sys_chmod, sys_lchown16, sparc_brk, sys_nis_syscall, sys_lseek
 /*20*/	.long sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16
-/*25*/	.long sys_time, sys_ptrace, sys_alarm, sys_sigaltstack, sys_pause
+/*25*/	.long sys_vmsplice, sys_ptrace, sys_alarm, sys_sigaltstack, sys_pause
 /*30*/	.long sys_utime, sys_lchown, sys_fchown, sys_access, sys_nice
 /*35*/	.long sys_chown, sys_sync, sys_kill, sys_newstat, sys_sendfile
 /*40*/	.long sys_newlstat, sys_dup, sys_pipe, sys_times, sys_getuid
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 1317380fa93779899be32254c629629fec2c84a3..f09a70b8aabd30bad84454ef1df39ba54cccd52f 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16
-# Sun Apr  2 19:31:04 2006
+# Linux kernel version: 2.6.17-rc3
+# Fri May 12 12:43:49 2006
 #
 CONFIG_SPARC=y
 CONFIG_SPARC64=y
@@ -114,6 +114,7 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_HUGETLB_PAGE_SIZE_4MB=y
 # CONFIG_HUGETLB_PAGE_SIZE_512K is not set
 # CONFIG_HUGETLB_PAGE_SIZE_64K is not set
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
 CONFIG_ARCH_SPARSEMEM_DEFAULT=y
 CONFIG_LARGE_ALLOCS=y
@@ -430,7 +431,6 @@ CONFIG_ISCSI_TCP=m
 # 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_QLOGICPTI is not set
 # CONFIG_SCSI_QLA_FC is not set
@@ -1042,9 +1042,7 @@ CONFIG_USB_HIDDEV=y
 # 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
@@ -1114,6 +1112,14 @@ CONFIG_USB_HIDDEV=y
 #
 # CONFIG_NEW_LEDS is not set
 
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
 #
 # InfiniBand support
 #
@@ -1303,6 +1309,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_VM is not set
+# CONFIG_UNWIND_INFO is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
diff --git a/arch/sparc64/kernel/module.c b/arch/sparc64/kernel/module.c
index 6c83e372f75d8ae71f57a9ce0dcec13c91582a76..579871527699ed616a7a5c838be648a88884ca1a 100644
--- a/arch/sparc64/kernel/module.c
+++ b/arch/sparc64/kernel/module.c
@@ -143,6 +143,11 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
 			location[3] = v >>  0;
 			break;
 
+		case R_SPARC_DISP32:
+			v -= (Elf64_Addr) location;
+			*loc32 = v;
+			break;
+
 		case R_SPARC_WDISP30:
 			v -= (Elf64_Addr) location;
 			*loc32 = (*loc32 & ~0x3fffffff) |
diff --git a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S
index f9b75760163c4b9a95fc55806d7ef4da006d0c36..bdf1f4d02e3f41844ec4334383cb05f0fe62ac67 100644
--- a/arch/sparc64/kernel/sys32.S
+++ b/arch/sparc64/kernel/sys32.S
@@ -139,6 +139,7 @@ SIGN3(sys32_ioprio_set, sys_ioprio_set, %o0, %o1, %o2)
 SIGN2(sys32_splice, sys_splice, %o0, %o1)
 SIGN2(sys32_sync_file_range, compat_sync_file_range, %o0, %o5)
 SIGN2(sys32_tee, sys_tee, %o0, %o1)
+SIGN1(sys32_vmsplice, compat_sys_vmsplice, %o0)
 
 	.globl		sys32_mmap2
 sys32_mmap2:
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 62672cd92eca6f216d2fa7a611f68fa9d44ab308..d4b39cd30310047356858a500f696f234ce01509 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -25,7 +25,7 @@ sys_call_table32:
 /*10*/  .word sys_unlink, sunos_execv, sys_chdir, sys32_chown16, sys32_mknod
 /*15*/	.word sys_chmod, sys32_lchown16, sparc_brk, sys32_perfctr, sys32_lseek
 /*20*/	.word sys_getpid, sys_capget, sys_capset, sys32_setuid16, sys32_getuid16
-/*25*/	.word compat_sys_time, sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause
+/*25*/	.word sys32_vmsplice, sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause
 /*30*/	.word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice
 	.word sys_chown, sys_sync, sys32_kill, compat_sys_newstat, sys32_sendfile
 /*40*/	.word compat_sys_newlstat, sys_dup, sys_pipe, compat_sys_times, sys_getuid
@@ -94,7 +94,7 @@ sys_call_table:
 /*10*/  .word sys_unlink, sys_nis_syscall, sys_chdir, sys_chown, sys_mknod
 /*15*/	.word sys_chmod, sys_lchown, sparc_brk, sys_perfctr, sys_lseek
 /*20*/	.word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid
-/*25*/	.word sys_nis_syscall, sys_ptrace, sys_alarm, sys_sigaltstack, sys_nis_syscall
+/*25*/	.word sys_vmsplice, sys_ptrace, sys_alarm, sys_sigaltstack, sys_nis_syscall
 /*30*/	.word sys_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice
 	.word sys_nis_syscall, sys_sync, sys_kill, sys_newstat, sys_sendfile64
 /*40*/	.word sys_newlstat, sys_dup, sys_pipe, sys_times, sys_nis_syscall
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c
index 3c7626cdba4be3c2a1364d7c429f317d232f20b8..528cf623f8b4144cbf77b4c0337a1ee6ab423185 100644
--- a/arch/um/kernel/time_kern.c
+++ b/arch/um/kernel/time_kern.c
@@ -209,4 +209,4 @@ int __init timer_init(void)
 	return(0);
 }
 
-__initcall(timer_init);
+arch_initcall(timer_init);
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index 62776c07cff15deec7f772096ddf51693ba2303e..222b5b46d2b2df6546ab01e67be1d1b92d713667 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -76,6 +76,12 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size)
 		*addrp = __pa_symbol(&_end);
 		return 1;
 	}
+
+	if (last >= ebda_addr && addr < ebda_addr + ebda_size) {
+		*addrp = ebda_addr + ebda_size;
+		return 1;
+	}
+
 	/* XXX ramdisk image here? */ 
 	return 0;
 } 
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 77b4c608cca0fdc6e1cc98d2329120847d050d09..0de3ea938830f6f8934e39a537fecaec6237b29e 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -1777,6 +1777,8 @@ static inline void unlock_ExtINT_logic(void)
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
+int timer_uses_ioapic_pin_0;
+
 /*
  * This code may look a bit paranoid, but it's supposed to cooperate with
  * a wide range of boards and BIOS bugs.  Fortunately only the timer IRQ
@@ -1814,6 +1816,9 @@ static inline void check_timer(void)
 	pin2  = ioapic_i8259.pin;
 	apic2 = ioapic_i8259.apic;
 
+	if (pin1 == 0)
+		timer_uses_ioapic_pin_0 = 1;
+
 	apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
 		vector, apic1, pin1, apic2, pin2);
 
diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c
index b17cf3eba35944c22134ee419efef71fc00ba4b7..083da7e606b1e6a88ca89f997276dbd9556a76d4 100644
--- a/arch/x86_64/kernel/mpparse.c
+++ b/arch/x86_64/kernel/mpparse.c
@@ -968,7 +968,17 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
 		 */
 		int irq = gsi;
 		if (gsi < MAX_GSI_NUM) {
-			if (gsi > 15)
+			/*
+			 * Retain the VIA chipset work-around (gsi > 15), but
+			 * avoid a problem where the 8254 timer (IRQ0) is setup
+			 * via an override (so it's not on pin 0 of the ioapic),
+			 * and at the same time, the pin 0 interrupt is a PCI
+			 * type.  The gsi > 15 test could cause these two pins
+			 * to be shared as IRQ0, and they are not shareable.
+			 * So test for this condition, and if necessary, avoid
+			 * the pin collision.
+			 */
+			if (gsi > 15 || (gsi == 0 && !timer_uses_ioapic_pin_0))
 				gsi = pci_irq++;
 			/*
 			 * Don't assign IRQ used by ACPI SCI
diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c
index 9d3d76c85ae7160ea9def9af5ccb4d133370ffbe..2480d3f08a470865b90f1dd8cb35e2c6c30a9e1a 100644
--- a/arch/x86_64/kernel/pci-gart.c
+++ b/arch/x86_64/kernel/pci-gart.c
@@ -639,6 +639,14 @@ static int __init pci_iommu_init(void)
 		return -1;
 	}
 
+	i = 0;
+	for_all_nb(dev)
+		i++;
+	if (i > MAX_NB) {
+		printk(KERN_ERR "PCI-GART: Too many northbridges (%ld). Disabled\n", i);
+		return -1;
+	}
+
 	printk(KERN_INFO "PCI-DMA: using GART IOMMU.\n");
 	aper_size = info.aper_size * 1024 * 1024;	
 	iommu_size = check_iommu_size(info.aper_base, aper_size); 
diff --git a/arch/x86_64/kernel/pci-nommu.c b/arch/x86_64/kernel/pci-nommu.c
index 44adcc2d5e5be43299d8f640161c6ec50658c285..1f6ecc62061d9121633e53edf672dec81b2da7c3 100644
--- a/arch/x86_64/kernel/pci-nommu.c
+++ b/arch/x86_64/kernel/pci-nommu.c
@@ -12,9 +12,10 @@ static int
 check_addr(char *name, struct device *hwdev, dma_addr_t bus, size_t size)
 {
         if (hwdev && bus + size > *hwdev->dma_mask) {
-		printk(KERN_ERR
-		    "nommu_%s: overflow %Lx+%lu of device mask %Lx\n",
-	       name, (long long)bus, size, (long long)*hwdev->dma_mask);
+		if (*hwdev->dma_mask >= 0xffffffffULL)
+			printk(KERN_ERR
+			    "nommu_%s: overflow %Lx+%lu of device mask %Lx\n",
+	       			name, (long long)bus, size, (long long)*hwdev->dma_mask);
 		return 0;
 	}
 	return 1;
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index ebc3c33b1c6c9a940fe47feb78f7b425255393ec..f0870bef24d114b521f625952b79e973ed2a5e1c 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -571,17 +571,28 @@ static inline void copy_edd(void)
 #endif
 
 #define EBDA_ADDR_POINTER 0x40E
-static void __init reserve_ebda_region(void)
+
+unsigned __initdata ebda_addr;
+unsigned __initdata ebda_size;
+
+static void discover_ebda(void)
 {
-	unsigned int addr;
-	/** 
+	/*
 	 * there is a real-mode segmented pointer pointing to the 
 	 * 4K EBDA area at 0x40E
 	 */
-	addr = *(unsigned short *)phys_to_virt(EBDA_ADDR_POINTER);
-	addr <<= 4;
-	if (addr)
-		reserve_bootmem_generic(addr, PAGE_SIZE);
+	ebda_addr = *(unsigned short *)EBDA_ADDR_POINTER;
+	ebda_addr <<= 4;
+
+	ebda_size = *(unsigned short *)(unsigned long)ebda_addr;
+
+	/* Round EBDA up to pages */
+	if (ebda_size == 0)
+		ebda_size = 1;
+	ebda_size <<= 10;
+	ebda_size = round_up(ebda_size + (ebda_addr & ~PAGE_MASK), PAGE_SIZE);
+	if (ebda_size > 64*1024)
+		ebda_size = 64*1024;
 }
 
 void __init setup_arch(char **cmdline_p)
@@ -627,6 +638,8 @@ void __init setup_arch(char **cmdline_p)
 
 	check_efer();
 
+	discover_ebda();
+
 	init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT));
 
 	dmi_scan_machine();
@@ -669,7 +682,8 @@ void __init setup_arch(char **cmdline_p)
 	reserve_bootmem_generic(0, PAGE_SIZE);
 
 	/* reserve ebda region */
-	reserve_ebda_region();
+	if (ebda_addr)
+		reserve_bootmem_generic(ebda_addr, ebda_size);
 
 #ifdef CONFIG_SMP
 	/*
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 2700b1375c1fe27c864d60ec41e15258d7c90cd6..cea335e8746ca451b6b8571dfa052785e07a27aa 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -102,6 +102,8 @@ static inline void preempt_conditional_cli(struct pt_regs *regs)
 {
 	if (regs->eflags & X86_EFLAGS_IF)
 		local_irq_disable();
+	/* Make sure to not schedule here because we could be running
+	   on an exception stack. */
 	preempt_enable_no_resched();
 }
 
@@ -385,6 +387,7 @@ void out_of_line_bug(void)
 
 static DEFINE_SPINLOCK(die_lock);
 static int die_owner = -1;
+static unsigned int die_nest_count;
 
 unsigned __kprobes long oops_begin(void)
 {
@@ -399,6 +402,7 @@ unsigned __kprobes long oops_begin(void)
 		else
 			spin_lock(&die_lock);
 	}
+	die_nest_count++;
 	die_owner = cpu;
 	console_verbose();
 	bust_spinlocks(1);
@@ -409,7 +413,13 @@ void __kprobes oops_end(unsigned long flags)
 { 
 	die_owner = -1;
 	bust_spinlocks(0);
-	spin_unlock_irqrestore(&die_lock, flags);
+	die_nest_count--;
+	if (die_nest_count)
+		/* We still own the lock */
+		local_irq_restore(flags);
+	else
+		/* Nest count reaches zero, release the lock. */
+		spin_unlock_irqrestore(&die_lock, flags);
 	if (panic_on_oops)
 		panic("Oops");
 }
@@ -464,6 +474,8 @@ void __kprobes die_nmi(char *str, struct pt_regs *regs)
 		panic("nmi watchdog");
 	printk("console shuts up ...\n");
 	oops_end(flags);
+	nmi_exit();
+	local_irq_enable();
 	do_exit(SIGSEGV);
 }
 
@@ -473,8 +485,6 @@ static void __kprobes do_trap(int trapnr, int signr, char *str,
 {
 	struct task_struct *tsk = current;
 
-	conditional_sti(regs);
-
 	tsk->thread.error_code = error_code;
 	tsk->thread.trap_no = trapnr;
 
@@ -511,6 +521,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
 	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
 							== NOTIFY_STOP) \
 		return; \
+	conditional_sti(regs);						\
 	do_trap(trapnr, signr, str, regs, error_code, NULL); \
 }
 
@@ -525,6 +536,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
 	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
 							== NOTIFY_STOP) \
 		return; \
+	conditional_sti(regs);						\
 	do_trap(trapnr, signr, str, regs, error_code, &info); \
 }
 
@@ -538,7 +550,17 @@ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
 DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
 DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
 DO_ERROR(18, SIGSEGV, "reserved", reserved)
-DO_ERROR(12, SIGBUS,  "stack segment", stack_segment)
+
+/* Runs on IST stack */
+asmlinkage void do_stack_segment(struct pt_regs *regs, long error_code)
+{
+	if (notify_die(DIE_TRAP, "stack segment", regs, error_code,
+			12, SIGBUS) == NOTIFY_STOP)
+		return;
+	preempt_conditional_sti(regs);
+	do_trap(12, SIGBUS, "stack segment", regs, error_code, NULL);
+	preempt_conditional_cli(regs);
+}
 
 asmlinkage void do_double_fault(struct pt_regs * regs, long error_code)
 {
@@ -672,8 +694,9 @@ asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code)
 	if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) {
 		return;
 	}
+	preempt_conditional_sti(regs);
 	do_trap(3, SIGTRAP, "int3", regs, error_code, NULL);
-	return;
+	preempt_conditional_cli(regs);
 }
 
 /* Help handler running on IST stack to switch back to user stack
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c
index 15ae9fcd65a700c9f9060860f0fce56f7f6f3fcf..e1513532df293447a529cd7477b6bbca67363e18 100644
--- a/arch/x86_64/mm/srat.c
+++ b/arch/x86_64/mm/srat.c
@@ -34,7 +34,10 @@ static nodemask_t nodes_found __initdata;
 static struct bootnode nodes[MAX_NUMNODES] __initdata;
 static struct bootnode nodes_add[MAX_NUMNODES] __initdata;
 static int found_add_area __initdata;
-int hotadd_percent __initdata = 10;
+int hotadd_percent __initdata = 0;
+#ifndef RESERVE_HOTADD
+#define hotadd_percent 0	/* Ignore all settings */
+#endif
 static u8 pxm2node[256] = { [0 ... 255] = 0xff };
 
 /* Too small nodes confuse the VM badly. Usually they result
@@ -103,6 +106,7 @@ static __init void bad_srat(void)
 	int i;
 	printk(KERN_ERR "SRAT: SRAT not used.\n");
 	acpi_numa = -1;
+	found_add_area = 0;
 	for (i = 0; i < MAX_LOCAL_APIC; i++)
 		apicid_to_node[i] = NUMA_NO_NODE;
 	for (i = 0; i < MAX_NUMNODES; i++)
@@ -154,7 +158,8 @@ acpi_numa_processor_affinity_init(struct acpi_table_processor_affinity *pa)
 	int pxm, node;
 	if (srat_disabled())
 		return;
-	if (pa->header.length != sizeof(struct acpi_table_processor_affinity)) {		bad_srat();
+	if (pa->header.length != sizeof(struct acpi_table_processor_affinity)) {
+		bad_srat();
 		return;
 	}
 	if (pa->flags.enabled == 0)
@@ -191,15 +196,17 @@ static int hotadd_enough_memory(struct bootnode *nd)
 	allowed = (end_pfn - e820_hole_size(0, end_pfn)) * PAGE_SIZE;
 	allowed = (allowed / 100) * hotadd_percent;
 	if (allocated + mem > allowed) {
+		unsigned long range;
 		/* Give them at least part of their hotadd memory upto hotadd_percent
 		   It would be better to spread the limit out
 		   over multiple hotplug areas, but that is too complicated
 		   right now */
 		if (allocated >= allowed)
 			return 0;
-		pages = (allowed - allocated + mem) / sizeof(struct page);
+		range = allowed - allocated;
+		pages = (range / PAGE_SIZE);
 		mem = pages * sizeof(struct page);
-		nd->end = nd->start + pages*PAGE_SIZE;
+		nd->end = nd->start + range;
 	}
 	/* Not completely fool proof, but a good sanity check */
 	addr = find_e820_area(last_area_end, end_pfn<<PAGE_SHIFT, mem);
diff --git a/block/elevator.c b/block/elevator.c
index 29825792cbd5305cfbea9c1f6063710ec4b46be8..8768a367fdded922a17b1c7c47ac24ec993a1628 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -333,6 +333,7 @@ void elv_insert(request_queue_t *q, struct request *rq, int where)
 {
 	struct list_head *pos;
 	unsigned ordseq;
+	int unplug_it = 1;
 
 	blk_add_trace_rq(q, rq, BLK_TA_INSERT);
 
@@ -399,6 +400,11 @@ void elv_insert(request_queue_t *q, struct request *rq, int where)
 		}
 
 		list_add_tail(&rq->queuelist, pos);
+		/*
+		 * most requeues happen because of a busy condition, don't
+		 * force unplug of the queue for that case.
+		 */
+		unplug_it = 0;
 		break;
 
 	default:
@@ -407,7 +413,7 @@ void elv_insert(request_queue_t *q, struct request *rq, int where)
 		BUG();
 	}
 
-	if (blk_queue_plugged(q)) {
+	if (unplug_it && blk_queue_plugged(q)) {
 		int nrq = q->rq.count[READ] + q->rq.count[WRITE]
 			- q->in_flight;
 
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index e5041a02e21f5c7ee4e93597ef95967643380462..eac48bec14791533a594af0e2909b7ed5347c091 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -1732,8 +1732,21 @@ void blk_run_queue(struct request_queue *q)
 
 	spin_lock_irqsave(q->queue_lock, flags);
 	blk_remove_plug(q);
-	if (!elv_queue_empty(q))
-		q->request_fn(q);
+
+	/*
+	 * Only recurse once to avoid overrunning the stack, let the unplug
+	 * handling reinvoke the handler shortly if we already got there.
+	 */
+	if (!elv_queue_empty(q)) {
+		if (!test_and_set_bit(QUEUE_FLAG_REENTER, &q->queue_flags)) {
+			q->request_fn(q);
+			clear_bit(QUEUE_FLAG_REENTER, &q->queue_flags);
+		} else {
+			blk_plug_device(q);
+			kblockd_schedule_work(&q->unplug_work);
+		}
+	}
+
 	spin_unlock_irqrestore(q->queue_lock, flags);
 }
 EXPORT_SYMBOL(blk_run_queue);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 0e71dff327cd896509060a66f9fe348972253460..b1ea4df85c7dde7fc3289e27529bf1b85e785dda 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -456,6 +456,35 @@ static void class_device_remove_attrs(struct class_device * cd)
 	}
 }
 
+static int class_device_add_groups(struct class_device * cd)
+{
+	int i;
+	int error = 0;
+
+	if (cd->groups) {
+		for (i = 0; cd->groups[i]; i++) {
+			error = sysfs_create_group(&cd->kobj, cd->groups[i]);
+			if (error) {
+				while (--i >= 0)
+					sysfs_remove_group(&cd->kobj, cd->groups[i]);
+				goto out;
+			}
+		}
+	}
+out:
+	return error;
+}
+
+static void class_device_remove_groups(struct class_device * cd)
+{
+	int i;
+	if (cd->groups) {
+		for (i = 0; cd->groups[i]; i++) {
+			sysfs_remove_group(&cd->kobj, cd->groups[i]);
+		}
+	}
+}
+
 static ssize_t show_dev(struct class_device *class_dev, char *buf)
 {
 	return print_dev_t(buf, class_dev->devt);
@@ -559,6 +588,8 @@ int class_device_add(struct class_device *class_dev)
 				  class_name);
 	}
 
+	class_device_add_groups(class_dev);
+
 	kobject_uevent(&class_dev->kobj, KOBJ_ADD);
 
 	/* notify any interfaces this device is now here */
@@ -672,6 +703,7 @@ void class_device_del(struct class_device *class_dev)
 	if (class_dev->devt_attr)
 		class_device_remove_file(class_dev, class_dev->devt_attr);
 	class_device_remove_attrs(class_dev);
+	class_device_remove_groups(class_dev);
 
 	kobject_uevent(&class_dev->kobj, KOBJ_REMOVE);
 	kobject_del(&class_dev->kobj);
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index f73446f580dff85b4f074393cdff8cac422fe801..c688c25992e44b0a914624735c448e7e7abb1429 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -536,6 +536,9 @@ static void ub_cleanup(struct ub_dev *sc)
 		kfree(lun);
 	}
 
+	usb_set_intfdata(sc->intf, NULL);
+	usb_put_intf(sc->intf);
+	usb_put_dev(sc->dev);
 	kfree(sc);
 }
 
@@ -2221,7 +2224,12 @@ static int ub_probe(struct usb_interface *intf,
 	// sc->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
 	usb_set_intfdata(intf, sc);
 	usb_get_dev(sc->dev);
-	// usb_get_intf(sc->intf);	/* Do we need this? */
+	/*
+	 * Since we give the interface struct to the block level through
+	 * disk->driverfs_dev, we have to pin it. Otherwise, block_uevent
+	 * oopses on close after a disconnect (kernels 2.6.16 and up).
+	 */
+	usb_get_intf(sc->intf);
 
 	snprintf(sc->name, 12, DRV_NAME "(%d.%d)",
 	    sc->dev->bus->busnum, sc->dev->devnum);
@@ -2286,7 +2294,7 @@ static int ub_probe(struct usb_interface *intf,
 
 err_dev_desc:
 	usb_set_intfdata(intf, NULL);
-	// usb_put_intf(sc->intf);
+	usb_put_intf(sc->intf);
 	usb_put_dev(sc->dev);
 	kfree(sc);
 err_core:
@@ -2461,12 +2469,6 @@ static void ub_disconnect(struct usb_interface *intf)
 	 * and no URBs left in transit.
 	 */
 
-	usb_set_intfdata(intf, NULL);
-	// usb_put_intf(sc->intf);
-	sc->intf = NULL;
-	usb_put_dev(sc->dev);
-	sc->dev = NULL;
-
 	ub_put(sc);
 }
 
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 402296670d3a555acfecbe66ceff162edb887e99..78d928f9d9f1abaa3c3a0b46e7deb69cd9f65a16 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -291,7 +291,7 @@ config SX
 
 config RIO
 	tristate "Specialix RIO system support"
-	depends on SERIAL_NONSTANDARD && !64BIT
+	depends on SERIAL_NONSTANDARD
 	help
 	  This is a driver for the Specialix RIO, a smart serial card which
 	  drives an outboard box that can support up to 128 ports.  Product
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index 02114a0bd0d9d4aadc5a7df96fb93801c6acbfbc..128b2632512d07f693d5925ce97791943cf9e3dd 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -1981,10 +1981,6 @@ static int __init cmm_init(void)
 	if (!cmm_class)
 		return -1;
 
-	rc = pcmcia_register_driver(&cm4000_driver);
-	if (rc < 0)
-		return rc;
-
 	major = register_chrdev(0, DEVICE_NAME, &cm4000_fops);
 	if (major < 0) {
 		printk(KERN_WARNING MODULE_NAME
@@ -1992,6 +1988,12 @@ static int __init cmm_init(void)
 		return -1;
 	}
 
+	rc = pcmcia_register_driver(&cm4000_driver);
+	if (rc < 0) {
+		unregister_chrdev(major, DEVICE_NAME);
+		return rc;
+	}
+
 	return 0;
 }
 
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index 29efa64580a89bf11d8d88050ac471575884cc9e..47a8465bf95beed694105640b1847f5589b8e2a3 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -724,16 +724,19 @@ static int __init cm4040_init(void)
 	if (!cmx_class)
 		return -1;
 
-	rc = pcmcia_register_driver(&reader_driver);
-	if (rc < 0)
-		return rc;
-
 	major = register_chrdev(0, DEVICE_NAME, &reader_fops);
 	if (major < 0) {
 		printk(KERN_WARNING MODULE_NAME
 			": could not get major number\n");
 		return -1;
 	}
+
+	rc = pcmcia_register_driver(&reader_driver);
+	if (rc < 0) {
+		unregister_chrdev(major, DEVICE_NAME);
+		return rc;
+	}
+
 	return 0;
 }
 
diff --git a/drivers/char/rio/host.h b/drivers/char/rio/host.h
index 3ec73d1a279abf0b23e9676bb21ddaef54cd3cef..179cdbea712bc829467ae54b60a6e80fd3b2c4c3 100644
--- a/drivers/char/rio/host.h
+++ b/drivers/char/rio/host.h
@@ -33,12 +33,6 @@
 #ifndef __rio_host_h__
 #define __rio_host_h__
 
-#ifdef SCCS_LABELS
-#ifndef lint
-static char *_host_h_sccs_ = "@(#)host.h	1.2";
-#endif
-#endif
-
 /*
 ** the host structure - one per host card in the system.
 */
@@ -77,9 +71,6 @@ struct Host {
 #define RC_STARTUP            1
 #define RC_RUNNING            2
 #define RC_STUFFED            3
-#define RC_SOMETHING          4
-#define RC_SOMETHING_NEW      5
-#define RC_SOMETHING_ELSE     6
 #define RC_READY              7
 #define RUN_STATE             7
 /*
diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c
index acda9326c2efa900a04636ccbd1c128a364e71bf..290143addd34cc8be99c1dbf5252746c48e3f5bc 100644
--- a/drivers/char/rio/rioboot.c
+++ b/drivers/char/rio/rioboot.c
@@ -34,6 +34,7 @@
 #include <linux/slab.h>
 #include <linux/termios.h>
 #include <linux/serial.h>
+#include <linux/vmalloc.h>
 #include <asm/semaphore.h>
 #include <linux/generic_serial.h>
 #include <linux/errno.h>
diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c
index d31aba62bb7f362d87d8e38961f0abc2ba197abc..75b2557c37ec77c83cabb51ce01e9afcc5bccb00 100644
--- a/drivers/char/rio/rioctrl.c
+++ b/drivers/char/rio/rioctrl.c
@@ -1394,14 +1394,17 @@ int RIOPreemptiveCmd(struct rio_info *p, struct Port *PortP, u8 Cmd)
 		return RIO_FAIL;
 	}
 
-	if (((int) ((char) PortP->InUse) == -1) || !(CmdBlkP = RIOGetCmdBlk())) {
-		rio_dprintk(RIO_DEBUG_CTRL, "Cannot allocate command block for command %d on port %d\n", Cmd, PortP->PortNum);
+	if ((PortP->InUse == (typeof(PortP->InUse))-1) ||
+			!(CmdBlkP = RIOGetCmdBlk())) {
+		rio_dprintk(RIO_DEBUG_CTRL, "Cannot allocate command block "
+			"for command %d on port %d\n", Cmd, PortP->PortNum);
 		return RIO_FAIL;
 	}
 
-	rio_dprintk(RIO_DEBUG_CTRL, "Command blk %p - InUse now %d\n", CmdBlkP, PortP->InUse);
+	rio_dprintk(RIO_DEBUG_CTRL, "Command blk %p - InUse now %d\n",
+			CmdBlkP, PortP->InUse);
 
-	PktCmdP = (struct PktCmd_M *) &CmdBlkP->Packet.data[0];
+	PktCmdP = (struct PktCmd_M *)&CmdBlkP->Packet.data[0];
 
 	CmdBlkP->Packet.src_unit = 0;
 	if (PortP->SecondBlock)
@@ -1425,38 +1428,46 @@ int RIOPreemptiveCmd(struct rio_info *p, struct Port *PortP, u8 Cmd)
 
 	switch (Cmd) {
 	case MEMDUMP:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue MEMDUMP command blk %p (addr 0x%x)\n", CmdBlkP, (int) SubCmd.Addr);
+		rio_dprintk(RIO_DEBUG_CTRL, "Queue MEMDUMP command blk %p "
+				"(addr 0x%x)\n", CmdBlkP, (int) SubCmd.Addr);
 		PktCmdP->SubCommand = MEMDUMP;
 		PktCmdP->SubAddr = SubCmd.Addr;
 		break;
 	case FCLOSE:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue FCLOSE command blk %p\n", CmdBlkP);
+		rio_dprintk(RIO_DEBUG_CTRL, "Queue FCLOSE command blk %p\n",
+				CmdBlkP);
 		break;
 	case READ_REGISTER:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) command blk %p\n", (int) SubCmd.Addr, CmdBlkP);
+		rio_dprintk(RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) "
+				"command blk %p\n", (int) SubCmd.Addr, CmdBlkP);
 		PktCmdP->SubCommand = READ_REGISTER;
 		PktCmdP->SubAddr = SubCmd.Addr;
 		break;
 	case RESUME:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue RESUME command blk %p\n", CmdBlkP);
+		rio_dprintk(RIO_DEBUG_CTRL, "Queue RESUME command blk %p\n",
+				CmdBlkP);
 		break;
 	case RFLUSH:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue RFLUSH command blk %p\n", CmdBlkP);
+		rio_dprintk(RIO_DEBUG_CTRL, "Queue RFLUSH command blk %p\n",
+				CmdBlkP);
 		CmdBlkP->PostFuncP = RIORFlushEnable;
 		break;
 	case SUSPEND:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue SUSPEND command blk %p\n", CmdBlkP);
+		rio_dprintk(RIO_DEBUG_CTRL, "Queue SUSPEND command blk %p\n",
+				CmdBlkP);
 		break;
 
 	case MGET:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue MGET command blk %p\n", CmdBlkP);
+		rio_dprintk(RIO_DEBUG_CTRL, "Queue MGET command blk %p\n",
+				CmdBlkP);
 		break;
 
 	case MSET:
 	case MBIC:
 	case MBIS:
 		CmdBlkP->Packet.data[4] = (char) PortP->ModemLines;
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command blk %p\n", CmdBlkP);
+		rio_dprintk(RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command "
+				"blk %p\n", CmdBlkP);
 		break;
 
 	case WFLUSH:
@@ -1465,12 +1476,14 @@ int RIOPreemptiveCmd(struct rio_info *p, struct Port *PortP, u8 Cmd)
 		 ** allowed then we should not bother sending any more to the
 		 ** RTA.
 		 */
-		if ((int) ((char) PortP->WflushFlag) == (int) -1) {
-			rio_dprintk(RIO_DEBUG_CTRL, "Trashed WFLUSH, WflushFlag about to wrap!");
+		if (PortP->WflushFlag == (typeof(PortP->WflushFlag))-1) {
+			rio_dprintk(RIO_DEBUG_CTRL, "Trashed WFLUSH, "
+					"WflushFlag about to wrap!");
 			RIOFreeCmdBlk(CmdBlkP);
 			return (RIO_FAIL);
 		} else {
-			rio_dprintk(RIO_DEBUG_CTRL, "Queue WFLUSH command blk %p\n", CmdBlkP);
+			rio_dprintk(RIO_DEBUG_CTRL, "Queue WFLUSH command "
+					"blk %p\n", CmdBlkP);
 			CmdBlkP->PostFuncP = RIOWFlushMark;
 		}
 		break;
diff --git a/drivers/char/rio/rioioctl.h b/drivers/char/rio/rioioctl.h
index 14b83fae75c8ed1abc890615337e546decfa7850..e8af5b30519e39e64381c58e1a0e709a67340cbe 100644
--- a/drivers/char/rio/rioioctl.h
+++ b/drivers/char/rio/rioioctl.h
@@ -33,10 +33,6 @@
 #ifndef	__rioioctl_h__
 #define	__rioioctl_h__
 
-#ifdef SCCS_LABELS
-static char *_rioioctl_h_sccs_ = "@(#)rioioctl.h	1.2";
-#endif
-
 /*
 ** RIO device driver - user ioctls and associated structures.
 */
@@ -44,55 +40,13 @@ static char *_rioioctl_h_sccs_ = "@(#)rioioctl.h	1.2";
 struct portStats {
 	int port;
 	int gather;
-	ulong txchars;
-	ulong rxchars;
-	ulong opens;
-	ulong closes;
-	ulong ioctls;
+	unsigned long txchars;
+	unsigned long rxchars;
+	unsigned long opens;
+	unsigned long closes;
+	unsigned long ioctls;
 };
 
-
-#define rIOC	('r'<<8)
-#define	TCRIOSTATE	(rIOC | 1)
-#define	TCRIOXPON	(rIOC | 2)
-#define	TCRIOXPOFF	(rIOC | 3)
-#define	TCRIOXPCPS	(rIOC | 4)
-#define	TCRIOXPRINT	(rIOC | 5)
-#define TCRIOIXANYON	(rIOC | 6)
-#define	TCRIOIXANYOFF	(rIOC | 7)
-#define TCRIOIXONON	(rIOC | 8)
-#define	TCRIOIXONOFF	(rIOC | 9)
-#define	TCRIOMBIS	(rIOC | 10)
-#define	TCRIOMBIC	(rIOC | 11)
-#define	TCRIOTRIAD	(rIOC | 12)
-#define TCRIOTSTATE	(rIOC | 13)
-
-/*
-** 15.10.1998 ARG - ESIL 0761 part fix
-** Add RIO ioctls for manipulating RTS and CTS flow control, (as LynxOS
-** appears to not support hardware flow control).
-*/
-#define TCRIOCTSFLOWEN	(rIOC | 14)	/* enable CTS flow control */
-#define TCRIOCTSFLOWDIS	(rIOC | 15)	/* disable CTS flow control */
-#define TCRIORTSFLOWEN	(rIOC | 16)	/* enable RTS flow control */
-#define TCRIORTSFLOWDIS	(rIOC | 17)	/* disable RTS flow control */
-
-/*
-** 09.12.1998 ARG - ESIL 0776 part fix
-** Definition for 'RIOC' also appears in daemon.h, so we'd better do a
-** #ifndef here first.
-** 'RIO_QUICK_CHECK' also #define'd here as this ioctl is now
-** allowed to be used by customers.
-**
-** 05.02.1999 ARG -
-** This is what I've decied to do with ioctls etc., which are intended to be
-** invoked from users applications :
-** Anything that needs to be defined here will be removed from daemon.h, that
-** way it won't end up having to be defined/maintained in two places. The only
-** consequence of this is that this file should now be #include'd by daemon.h
-**
-** 'stats' ioctls now #define'd here as they are to be used by customers.
-*/
 #define	RIOC	('R'<<8)|('i'<<16)|('o'<<24)
 
 #define	RIO_QUICK_CHECK	  	(RIOC | 105)
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index 1efde3b27619b4113ca95ee1ca3116f6409b0ca2..fe00c7dfb649bf054376aa30522cb6c1ed2098e7 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -22,7 +22,7 @@ config TCG_TPM
 
 config TCG_TIS
 	tristate "TPM Interface Specification 1.2 Interface"
-	depends on TCG_TPM
+	depends on TCG_TPM && PNPACPI
 	---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
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 54a4c804e25f30fc38eed78e5a4b32d2e07f1bc9..050ced247f68018224addcc572e7faa7f6f47fec 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -140,7 +140,7 @@ extern int tpm_pm_resume(struct device *);
 extern struct dentry ** tpm_bios_log_setup(char *);
 extern void tpm_bios_log_teardown(struct dentry **);
 #else
-static inline struct dentry* tpm_bios_log_setup(char *name)
+static inline struct dentry ** tpm_bios_log_setup(char *name)
 {
 	return NULL;
 }
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index b9cae9a238bb651d7814740b013ae39899d9f727..f621168f38aec754a418cf4390d9460506a08dec 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -55,7 +55,7 @@ enum tis_int_flags {
 };
 
 enum tis_defaults {
-	TIS_MEM_BASE = 0xFED4000,
+	TIS_MEM_BASE = 0xFED40000,
 	TIS_MEM_LEN = 0x5000,
 	TIS_SHORT_TIMEOUT = 750,	/* ms */
 	TIS_LONG_TIMEOUT = 2000,	/* 2 sec */
diff --git a/drivers/char/watchdog/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c
index a13395e2c372a9b27355040c9c94eae21040992b..fa2ba9ebe42aacf3478212143547c460d877402e 100644
--- a/drivers/char/watchdog/i8xx_tco.c
+++ b/drivers/char/watchdog/i8xx_tco.c
@@ -33,11 +33,6 @@
  *	82801E   (C-ICH)  : document number 273599-001, 273645-002,
  *	82801EB  (ICH5)   : document number 252516-001, 252517-003,
  *	82801ER  (ICH5R)  : document number 252516-001, 252517-003,
- *	82801FB  (ICH6)   : document number 301473-002, 301474-007,
- *	82801FR  (ICH6R)  : document number 301473-002, 301474-007,
- *	82801FBM (ICH6-M) : document number 301473-002, 301474-007,
- *	82801FW  (ICH6W)  : document number 301473-001, 301474-007,
- *	82801FRW (ICH6RW) : document number 301473-001, 301474-007
  *
  *  20000710 Nils Faerber
  *	Initial Version 0.01
@@ -66,6 +61,10 @@
  *  20050807 Wim Van Sebroeck <wim@iguana.be>
  *	0.08 Make sure that the watchdog is only "armed" when started.
  *	     (Kernel Bug 4251)
+ *  20060416 Wim Van Sebroeck <wim@iguana.be>
+ *	0.09 Remove support for the ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW and
+ *	     ICH7 chipsets. (See Kernel Bug 6031 - other code will support these
+ *	     chipsets)
  */
 
 /*
@@ -90,7 +89,7 @@
 #include "i8xx_tco.h"
 
 /* Module and version information */
-#define TCO_VERSION "0.08"
+#define TCO_VERSION "0.09"
 #define TCO_MODULE_NAME "i8xx TCO timer"
 #define TCO_DRIVER_NAME   TCO_MODULE_NAME ", v" TCO_VERSION
 #define PFX TCO_MODULE_NAME ": "
@@ -391,11 +390,6 @@ static struct pci_device_id i8xx_tco_pci_tbl[] = {
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12,	PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0,	PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0,	PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0,	PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1,	PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2,	PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0,	PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1,	PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1,	PCI_ANY_ID, PCI_ANY_ID, },
 	{ 0, },			/* End of list */
 };
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c
index 9dc54736e4eb627d5e843bda4e2bc2a243aa0840..1ea04e9b2b0b0938cfc2cbfa04b2eed12b4da01b 100644
--- a/drivers/char/watchdog/s3c2410_wdt.c
+++ b/drivers/char/watchdog/s3c2410_wdt.c
@@ -423,6 +423,12 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
 	if (tmr_atboot && started == 0) {
 		printk(KERN_INFO PFX "Starting Watchdog Timer\n");
 		s3c2410wdt_start();
+	} else if (!tmr_atboot) {
+		/* if we're not enabling the watchdog, then ensure it is
+		 * disabled if it has been left running from the bootloader
+		 * or other source */
+
+		s3c2410wdt_stop();
 	}
 
 	return 0;
diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c
index 515ce757204996c188589e74ce29341f8b41ab76..20b88f9b7be20d9081c58a72e217a89a394661f2 100644
--- a/drivers/char/watchdog/sc1200wdt.c
+++ b/drivers/char/watchdog/sc1200wdt.c
@@ -377,7 +377,7 @@ static int __init sc1200wdt_init(void)
 {
 	int ret;
 
-	printk(banner);
+	printk("%s\n", banner);
 
 	spin_lock_init(&sc1200wdt_lock);
 	sema_init(&open_sem, 1);
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 956d121cb16151c2c3f564c4ccabde21250afbac..3e6ffcaa5af4c2a10941c2ad6d30478aead32897 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -74,6 +74,8 @@ static unsigned int dbs_enable;	/* number of CPUs using this policy */
 static DEFINE_MUTEX (dbs_mutex);
 static DECLARE_WORK	(dbs_work, do_dbs_timer, NULL);
 
+static struct workqueue_struct *dbs_workq;
+
 struct dbs_tuners {
 	unsigned int sampling_rate;
 	unsigned int sampling_down_factor;
@@ -364,23 +366,29 @@ static void do_dbs_timer(void *data)
 	mutex_lock(&dbs_mutex);
 	for_each_online_cpu(i)
 		dbs_check_cpu(i);
-	schedule_delayed_work(&dbs_work,
-			usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
+	queue_delayed_work(dbs_workq, &dbs_work,
+			   usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
 	mutex_unlock(&dbs_mutex);
 }
 
 static inline void dbs_timer_init(void)
 {
 	INIT_WORK(&dbs_work, do_dbs_timer, NULL);
-	schedule_delayed_work(&dbs_work,
-			usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
+	if (!dbs_workq)
+		dbs_workq = create_singlethread_workqueue("ondemand");
+	if (!dbs_workq) {
+		printk(KERN_ERR "ondemand: Cannot initialize kernel thread\n");
+		return;
+	}
+	queue_delayed_work(dbs_workq, &dbs_work,
+			   usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
 	return;
 }
 
 static inline void dbs_timer_exit(void)
 {
-	cancel_delayed_work(&dbs_work);
-	return;
+	if (dbs_workq)
+		cancel_rearming_delayed_workqueue(dbs_workq, &dbs_work);
 }
 
 static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
@@ -489,8 +497,12 @@ static int __init cpufreq_gov_dbs_init(void)
 
 static void __exit cpufreq_gov_dbs_exit(void)
 {
-	/* Make sure that the scheduled work is indeed not running */
-	flush_scheduled_work();
+	/* Make sure that the scheduled work is indeed not running.
+	   Assumes the timer has been cancelled first. */
+	if (dbs_workq) {
+		flush_workqueue(dbs_workq);
+		destroy_workqueue(dbs_workq);
+	}
 
 	cpufreq_unregister_governor(&cpufreq_gov_dbs);
 }
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c
index 66572c5323ad1a9490097752fc6899708805eddd..fce31936e6d718ac4a5b620ceb60babc3b1a3718 100644
--- a/drivers/edac/e752x_edac.c
+++ b/drivers/edac/e752x_edac.c
@@ -25,6 +25,8 @@
 #include <linux/slab.h>
 #include "edac_mc.h"
 
+static int force_function_unhide;
+
 #define e752x_printk(level, fmt, arg...) \
 	edac_printk(level, "e752x", fmt, ##arg)
 
@@ -782,8 +784,16 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
 	debugf0("%s(): mci\n", __func__);
 	debugf0("Starting Probe1\n");
 
-	/* enable device 0 function 1 */
+	/* check to see if device 0 function 1 is enabled; if it isn't, we
+	 * assume the BIOS has reserved it for a reason and is expecting
+	 * exclusive access, we take care not to violate that assumption and
+	 * fail the probe. */
 	pci_read_config_byte(pdev, E752X_DEVPRES1, &stat8);
+	if (!force_function_unhide && !(stat8 & (1 << 5))) {
+		printk(KERN_INFO "Contact your BIOS vendor to see if the "
+			"E752x error registers can be safely un-hidden\n");
+		goto fail;
+	}
 	stat8 |= (1 << 5);
 	pci_write_config_byte(pdev, E752X_DEVPRES1, stat8);
 
@@ -1063,3 +1073,8 @@ module_exit(e752x_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Linux Networx (http://lnxi.com) Tom Zimmerman\n");
 MODULE_DESCRIPTION("MC support for Intel e752x memory controllers");
+
+module_param(force_function_unhide, int, 0444);
+MODULE_PARM_DESC(force_function_unhide, "if BIOS sets Dev0:Fun1 up as hidden:"
+" 1=force unhide and hope BIOS doesn't fight driver for Dev0:Fun1 access");
+
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index 8bd305e47f0d1d87ce5718a04a6812865b6841a0..a140e4536a4ee277fb7fe89e46fa9fdac847debf 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -133,6 +133,9 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status)
 
 		outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
 		outb(ACBST_STASTR | ACBST_NEGACK, ACBST);
+
+		/* Reset the status register */
+		outb(0, ACBST);
 		return;
 	}
 
@@ -228,6 +231,10 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface)
 	timeout = jiffies + POLL_TIMEOUT;
 	while (time_before(jiffies, timeout)) {
 		status = inb(ACBST);
+
+		/* Reset the status register to avoid the hang */
+		outb(0, ACBST);
+
 		if ((status & (ACBST_SDAST|ACBST_BER|ACBST_NEGACK)) != 0) {
 			scx200_acb_machine(iface, status);
 			return;
@@ -415,7 +422,6 @@ static int  __init scx200_acb_create(const char *text, int base, int index)
 	struct scx200_acb_iface *iface;
 	struct i2c_adapter *adapter;
 	int rc;
-	char description[64];
 
 	iface = kzalloc(sizeof(*iface), GFP_KERNEL);
 	if (!iface) {
@@ -434,10 +440,7 @@ static int  __init scx200_acb_create(const char *text, int base, int index)
 
 	mutex_init(&iface->mutex);
 
-	snprintf(description, sizeof(description), "%s ACCESS.bus [%s]",
-		 text, adapter->name);
-
-	if (request_region(base, 8, description) == 0) {
+	if (!request_region(base, 8, adapter->name)) {
 		printk(KERN_ERR NAME ": can't allocate io 0x%x-0x%x\n",
 			base, base + 8-1);
 		rc = -EBUSY;
@@ -524,6 +527,9 @@ static int __init scx200_acb_init(void)
 	} else if (pci_dev_present(divil_pci))
 		rc = scx200_add_cs553x();
 
+	/* If at least one bus was created, init must succeed */
+	if (scx200_acb_list)
+		return 0;
 	return rc;
 }
 
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index 4961f1e764a755bf4729951b7447620dea02d04f..602797a4420877f6fc74e659a05b4c50be8d54d6 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -392,6 +392,7 @@ static struct pcmcia_device_id ide_ids[] = {
 	PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
 	PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
 	PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
+	PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
 	PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
 	PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2      ", 0x547e66dc, 0x8671043b),
 	PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index 19222878aae92943f5528d09e67582a517048024..11f13778f13915e35bea6075dae7676e717952f9 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -553,7 +553,7 @@ static void ohci_initialize(struct ti_ohci *ohci)
 	 * register content.
 	 * To actually enable physical responses is the job of our interrupt
 	 * handler which programs the physical request filter. */
-	reg_write(ohci, OHCI1394_PhyUpperBound, 0xffff0000);
+	reg_write(ohci, OHCI1394_PhyUpperBound, 0x01000000);
 
 	DBGMSG("physUpperBoundOffset=%08x",
 	       reg_read(ohci, OHCI1394_PhyUpperBound));
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index f4206604db0378fb33fda046cb403f4a346cdb45..8a23fb54c6939bdbdac285570a45974e74740b48 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -42,6 +42,7 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/string.h>
+#include <linux/stringify.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/fs.h>
@@ -117,7 +118,8 @@ MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers (default
  */
 static int max_sectors = SBP2_MAX_SECTORS;
 module_param(max_sectors, int, 0444);
-MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported (default = 255)");
+MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported (default = "
+		 __stringify(SBP2_MAX_SECTORS) ")");
 
 /*
  * Exclusive login to sbp2 device? In most cases, the sbp2 driver should
@@ -135,18 +137,45 @@ module_param(exclusive_login, int, 0644);
 MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device (default = 1)");
 
 /*
- * SCSI inquiry hack for really badly behaved sbp2 devices. Turn this on
- * if your sbp2 device is not properly handling the SCSI inquiry command.
- * This hack makes the inquiry look more like a typical MS Windows inquiry
- * by enforcing 36 byte inquiry and avoiding access to mode_sense page 8.
+ * If any of the following workarounds is required for your device to work,
+ * please submit the kernel messages logged by sbp2 to the linux1394-devel
+ * mailing list.
  *
- * If force_inquiry_hack=1 is required for your device to work,
- * please submit the logged sbp2_firmware_revision value of this device to
- * the linux1394-devel mailing list.
+ * - 128kB max transfer
+ *   Limit transfer size. Necessary for some old bridges.
+ *
+ * - 36 byte inquiry
+ *   When scsi_mod probes the device, let the inquiry command look like that
+ *   from MS Windows.
+ *
+ * - skip mode page 8
+ *   Suppress sending of mode_sense for mode page 8 if the device pretends to
+ *   support the SCSI Primary Block commands instead of Reduced Block Commands.
+ *
+ * - fix capacity
+ *   Tell sd_mod to correct the last sector number reported by read_capacity.
+ *   Avoids access beyond actual disk limits on devices with an off-by-one bug.
+ *   Don't use this with devices which don't have this bug.
+ *
+ * - override internal blacklist
+ *   Instead of adding to the built-in blacklist, use only the workarounds
+ *   specified in the module load parameter.
+ *   Useful if a blacklist entry interfered with a non-broken device.
  */
+static int sbp2_default_workarounds;
+module_param_named(workarounds, sbp2_default_workarounds, int, 0644);
+MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0"
+	", 128kB max transfer = " __stringify(SBP2_WORKAROUND_128K_MAX_TRANS)
+	", 36 byte inquiry = "    __stringify(SBP2_WORKAROUND_INQUIRY_36)
+	", skip mode page 8 = "   __stringify(SBP2_WORKAROUND_MODE_SENSE_8)
+	", fix capacity = "       __stringify(SBP2_WORKAROUND_FIX_CAPACITY)
+	", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE)
+	", or a combination)");
+
+/* legacy parameter */
 static int force_inquiry_hack;
 module_param(force_inquiry_hack, int, 0644);
-MODULE_PARM_DESC(force_inquiry_hack, "Force SCSI inquiry hack (default = 0)");
+MODULE_PARM_DESC(force_inquiry_hack, "Deprecated, use 'workarounds'");
 
 /*
  * Export information about protocols/devices supported by this driver.
@@ -266,14 +295,55 @@ static struct hpsb_protocol_driver sbp2_driver = {
 };
 
 /*
- * List of device firmwares that require the inquiry hack.
- * Yields a few false positives but did not break other devices so far.
+ * List of devices with known bugs.
+ *
+ * The firmware_revision field, masked with 0xffff00, is the best indicator
+ * for the type of bridge chip of a device.  It yields a few false positives
+ * but this did not break correctly behaving devices so far.
  */
-static u32 sbp2_broken_inquiry_list[] = {
-	0x00002800,	/* Stefan Richter <stefanr@s5r6.in-berlin.de> */
-			/* DViCO Momobay CX-1 */
-	0x00000200	/* Andreas Plesch <plesch@fas.harvard.edu> */
-			/* QPS Fire DVDBurner */
+static const struct {
+	u32 firmware_revision;
+	u32 model_id;
+	unsigned workarounds;
+} sbp2_workarounds_table[] = {
+	/* TSB42AA9 */ {
+		.firmware_revision	= 0x002800,
+		.workarounds		= SBP2_WORKAROUND_INQUIRY_36 |
+					  SBP2_WORKAROUND_MODE_SENSE_8,
+	},
+	/* Initio bridges, actually only needed for some older ones */ {
+		.firmware_revision	= 0x000200,
+		.workarounds		= SBP2_WORKAROUND_INQUIRY_36,
+	},
+	/* Symbios bridge */ {
+		.firmware_revision	= 0xa0b800,
+		.workarounds		= SBP2_WORKAROUND_128K_MAX_TRANS,
+	},
+	/*
+	 * Note about the following Apple iPod blacklist entries:
+	 *
+	 * There are iPods (2nd gen, 3rd gen) with model_id==0.  Since our
+	 * matching logic treats 0 as a wildcard, we cannot match this ID
+	 * without rewriting the matching routine.  Fortunately these iPods
+	 * do not feature the read_capacity bug according to one report.
+	 * Read_capacity behaviour as well as model_id could change due to
+	 * Apple-supplied firmware updates though.
+	 */
+	/* iPod 4th generation */ {
+		.firmware_revision	= 0x0a2700,
+		.model_id		= 0x000021,
+		.workarounds		= SBP2_WORKAROUND_FIX_CAPACITY,
+	},
+	/* iPod mini */ {
+		.firmware_revision	= 0x0a2700,
+		.model_id		= 0x000023,
+		.workarounds		= SBP2_WORKAROUND_FIX_CAPACITY,
+	},
+	/* iPod Photo */ {
+		.firmware_revision	= 0x0a2700,
+		.model_id		= 0x00007e,
+		.workarounds		= SBP2_WORKAROUND_FIX_CAPACITY,
+	}
 };
 
 /**************************************
@@ -765,11 +835,16 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
 
 	/* Register the status FIFO address range. We could use the same FIFO
 	 * for targets at different nodes. However we need different FIFOs per
-	 * target in order to support multi-unit devices. */
+	 * target in order to support multi-unit devices.
+	 * The FIFO is located out of the local host controller's physical range
+	 * but, if possible, within the posted write area. Status writes will
+	 * then be performed as unified transactions. This slightly reduces
+	 * bandwidth usage, and some Prolific based devices seem to require it.
+	 */
 	scsi_id->status_fifo_addr = hpsb_allocate_and_register_addrspace(
 			&sbp2_highlevel, ud->ne->host, &sbp2_ops,
 			sizeof(struct sbp2_status_block), sizeof(quadlet_t),
-			~0ULL, ~0ULL);
+			0x010000000000ULL, CSR1212_ALL_SPACE_END);
 	if (!scsi_id->status_fifo_addr) {
 		SBP2_ERR("failed to allocate status FIFO address range");
 		goto failed_alloc;
@@ -1450,7 +1525,8 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
 	struct csr1212_dentry *dentry;
 	u64 management_agent_addr;
 	u32 command_set_spec_id, command_set, unit_characteristics,
-	    firmware_revision, workarounds;
+	    firmware_revision;
+	unsigned workarounds;
 	int i;
 
 	SBP2_DEBUG_ENTER();
@@ -1506,12 +1582,8 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
 		case SBP2_FIRMWARE_REVISION_KEY:
 			/* Firmware revision */
 			firmware_revision = kv->value.immediate;
-			if (force_inquiry_hack)
-				SBP2_INFO("sbp2_firmware_revision = %x",
-					  (unsigned int)firmware_revision);
-			else
-				SBP2_DEBUG("sbp2_firmware_revision = %x",
-					   (unsigned int)firmware_revision);
+			SBP2_DEBUG("sbp2_firmware_revision = %x",
+				   (unsigned int)firmware_revision);
 			break;
 
 		default:
@@ -1519,41 +1591,44 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
 		}
 	}
 
-	/* This is the start of our broken device checking. We try to hack
-	 * around oddities and known defects.  */
-	workarounds = 0x0;
+	workarounds = sbp2_default_workarounds;
+	if (force_inquiry_hack) {
+		SBP2_WARN("force_inquiry_hack is deprecated. "
+			  "Use parameter 'workarounds' instead.");
+		workarounds |= SBP2_WORKAROUND_INQUIRY_36;
+	}
 
-	/* If the vendor id is 0xa0b8 (Symbios vendor id), then we have a
-	 * bridge with 128KB max transfer size limitation. For sanity, we
-	 * only voice this when the current max_sectors setting
-	 * exceeds the 128k limit. By default, that is not the case.
-	 *
-	 * It would be really nice if we could detect this before the scsi
-	 * host gets initialized. That way we can down-force the
-	 * max_sectors to account for it. That is not currently
-	 * possible.  */
-	if ((firmware_revision & 0xffff00) ==
-			SBP2_128KB_BROKEN_FIRMWARE &&
-			(max_sectors * 512) > (128*1024)) {
-		SBP2_WARN("Node " NODE_BUS_FMT ": Bridge only supports 128KB max transfer size.",
-				NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid));
-		SBP2_WARN("WARNING: Current max_sectors setting is larger than 128KB (%d sectors)!",
-				max_sectors);
-		workarounds |= SBP2_BREAKAGE_128K_MAX_TRANSFER;
-	}
-
-	/* Check for a blacklisted set of devices that require us to force
-	 * a 36 byte host inquiry. This can be overriden as a module param
-	 * (to force all hosts).  */
-	for (i = 0; i < ARRAY_SIZE(sbp2_broken_inquiry_list); i++) {
-		if ((firmware_revision & 0xffff00) ==
-				sbp2_broken_inquiry_list[i]) {
-			SBP2_WARN("Node " NODE_BUS_FMT ": Using 36byte inquiry workaround",
-					NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid));
-			workarounds |= SBP2_BREAKAGE_INQUIRY_HACK;
-			break; /* No need to continue. */
+	if (!(workarounds & SBP2_WORKAROUND_OVERRIDE))
+		for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) {
+			if (sbp2_workarounds_table[i].firmware_revision &&
+			    sbp2_workarounds_table[i].firmware_revision !=
+			    (firmware_revision & 0xffff00))
+				continue;
+			if (sbp2_workarounds_table[i].model_id &&
+			    sbp2_workarounds_table[i].model_id != ud->model_id)
+				continue;
+			workarounds |= sbp2_workarounds_table[i].workarounds;
+			break;
 		}
-	}
+
+	if (workarounds)
+		SBP2_INFO("Workarounds for node " NODE_BUS_FMT ": 0x%x "
+			  "(firmware_revision 0x%06x, vendor_id 0x%06x,"
+			  " model_id 0x%06x)",
+			  NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid),
+			  workarounds, firmware_revision,
+			  ud->vendor_id ? ud->vendor_id : ud->ne->vendor_id,
+			  ud->model_id);
+
+	/* We would need one SCSI host template for each target to adjust
+	 * max_sectors on the fly, therefore warn only. */
+	if (workarounds & SBP2_WORKAROUND_128K_MAX_TRANS &&
+	    (max_sectors * 512) > (128 * 1024))
+		SBP2_WARN("Node " NODE_BUS_FMT ": Bridge only supports 128KB "
+			  "max transfer size. WARNING: Current max_sectors "
+			  "setting is larger than 128KB (%d sectors)",
+			  NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid),
+			  max_sectors);
 
 	/* If this is a logical unit directory entry, process the parent
 	 * to get the values. */
@@ -2447,19 +2522,25 @@ static int sbp2scsi_slave_alloc(struct scsi_device *sdev)
 
 	scsi_id->sdev = sdev;
 
-	if (force_inquiry_hack ||
-	    scsi_id->workarounds & SBP2_BREAKAGE_INQUIRY_HACK) {
+	if (scsi_id->workarounds & SBP2_WORKAROUND_INQUIRY_36)
 		sdev->inquiry_len = 36;
-		sdev->skip_ms_page_8 = 1;
-	}
 	return 0;
 }
 
 static int sbp2scsi_slave_configure(struct scsi_device *sdev)
 {
+	struct scsi_id_instance_data *scsi_id =
+		(struct scsi_id_instance_data *)sdev->host->hostdata[0];
+
 	blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
 	sdev->use_10_for_rw = 1;
 	sdev->use_10_for_ms = 1;
+
+	if (sdev->type == TYPE_DISK &&
+	    scsi_id->workarounds & SBP2_WORKAROUND_MODE_SENSE_8)
+		sdev->skip_ms_page_8 = 1;
+	if (scsi_id->workarounds & SBP2_WORKAROUND_FIX_CAPACITY)
+		sdev->fix_capacity = 1;
 	return 0;
 }
 
@@ -2603,7 +2684,9 @@ static int sbp2_module_init(void)
 		scsi_driver_template.cmd_per_lun = 1;
 	}
 
-	/* Set max sectors (module load option). Default is 255 sectors. */
+	if (sbp2_default_workarounds & SBP2_WORKAROUND_128K_MAX_TRANS &&
+	    (max_sectors * 512) > (128 * 1024))
+		max_sectors = 128 * 1024 / 512;
 	scsi_driver_template.max_sectors = max_sectors;
 
 	/* Register our high level driver with 1394 stack */
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
index e2d357a9ea3a46d9f3a13328f1f3a3f1b3412149..f4ccc9d0fba4106d6a8da4e6f886b45f3172993f 100644
--- a/drivers/ieee1394/sbp2.h
+++ b/drivers/ieee1394/sbp2.h
@@ -226,11 +226,6 @@ struct sbp2_status_block {
 #define SBP2_UNIT_SPEC_ID_ENTRY					0x0000609e
 #define SBP2_SW_VERSION_ENTRY					0x00010483
 
-/*
- * Other misc defines
- */
-#define SBP2_128KB_BROKEN_FIRMWARE				0xa0b800
-
 /*
  * SCSI specific stuff
  */
@@ -239,6 +234,13 @@ struct sbp2_status_block {
 #define SBP2_MAX_SECTORS		255	/* Max sectors supported */
 #define SBP2_MAX_CMDS			8	/* This should be safe */
 
+/* Flags for detected oddities and brokeness */
+#define SBP2_WORKAROUND_128K_MAX_TRANS	0x1
+#define SBP2_WORKAROUND_INQUIRY_36	0x2
+#define SBP2_WORKAROUND_MODE_SENSE_8	0x4
+#define SBP2_WORKAROUND_FIX_CAPACITY	0x8
+#define SBP2_WORKAROUND_OVERRIDE	0x100
+
 /* This is the two dma types we use for cmd_dma below */
 enum cmd_dma_types {
 	CMD_DMA_NONE,
@@ -268,10 +270,6 @@ struct sbp2_command_info {
 
 };
 
-/* A list of flags for detected oddities and brokeness. */
-#define SBP2_BREAKAGE_128K_MAX_TRANSFER		0x1
-#define SBP2_BREAKAGE_INQUIRY_HACK		0x2
-
 struct sbp2scsi_host_info;
 
 /*
@@ -345,7 +343,7 @@ struct scsi_id_instance_data {
 	struct Scsi_Host *scsi_host;
 
 	/* Device specific workarounds/brokeness */
-	u32 workarounds;
+	unsigned workarounds;
 };
 
 /* Sbp2 host data structure (one per IEEE1394 host) */
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 7cfedb8d9bcd963dc81a04ad11eac0322f30eee8..86fee43502cd2a977030d48fad69810fc7f0ac0f 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -34,6 +34,8 @@
  *
  * $Id: cm.c 2821 2005-07-08 17:07:28Z sean.hefty $
  */
+
+#include <linux/completion.h>
 #include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/idr.h>
@@ -122,7 +124,7 @@ struct cm_id_private {
 	struct rb_node service_node;
 	struct rb_node sidr_id_node;
 	spinlock_t lock;	/* Do not acquire inside cm.lock */
-	wait_queue_head_t wait;
+	struct completion comp;
 	atomic_t refcount;
 
 	struct ib_mad_send_buf *msg;
@@ -159,7 +161,7 @@ static void cm_work_handler(void *data);
 static inline void cm_deref_id(struct cm_id_private *cm_id_priv)
 {
 	if (atomic_dec_and_test(&cm_id_priv->refcount))
-		wake_up(&cm_id_priv->wait);
+		complete(&cm_id_priv->comp);
 }
 
 static int cm_alloc_msg(struct cm_id_private *cm_id_priv,
@@ -559,7 +561,7 @@ struct ib_cm_id *ib_create_cm_id(struct ib_device *device,
 		goto error;
 
 	spin_lock_init(&cm_id_priv->lock);
-	init_waitqueue_head(&cm_id_priv->wait);
+	init_completion(&cm_id_priv->comp);
 	INIT_LIST_HEAD(&cm_id_priv->work_list);
 	atomic_set(&cm_id_priv->work_count, -1);
 	atomic_set(&cm_id_priv->refcount, 1);
@@ -724,8 +726,8 @@ retest:
 	}
 
 	cm_free_id(cm_id->local_id);
-	atomic_dec(&cm_id_priv->refcount);
-	wait_event(cm_id_priv->wait, !atomic_read(&cm_id_priv->refcount));
+	cm_deref_id(cm_id_priv);
+	wait_for_completion(&cm_id_priv->comp);
 	while ((work = cm_dequeue_work(cm_id_priv)) != NULL)
 		cm_free_work(work);
 	if (cm_id_priv->private_data && cm_id_priv->private_data_len)
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 469b6923a2e2e0a2c59b388d8f93fedc2e961fac..5ad41a64314cd5b050f67dd4980c6ba0264419a4 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -352,7 +352,7 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
 	INIT_WORK(&mad_agent_priv->local_work, local_completions,
 		   mad_agent_priv);
 	atomic_set(&mad_agent_priv->refcount, 1);
-	init_waitqueue_head(&mad_agent_priv->wait);
+	init_completion(&mad_agent_priv->comp);
 
 	return &mad_agent_priv->agent;
 
@@ -467,7 +467,7 @@ struct ib_mad_agent *ib_register_mad_snoop(struct ib_device *device,
 	mad_snoop_priv->agent.qp = port_priv->qp_info[qpn].qp;
 	mad_snoop_priv->agent.port_num = port_num;
 	mad_snoop_priv->mad_snoop_flags = mad_snoop_flags;
-	init_waitqueue_head(&mad_snoop_priv->wait);
+	init_completion(&mad_snoop_priv->comp);
 	mad_snoop_priv->snoop_index = register_snoop_agent(
 						&port_priv->qp_info[qpn],
 						mad_snoop_priv);
@@ -486,6 +486,18 @@ error1:
 }
 EXPORT_SYMBOL(ib_register_mad_snoop);
 
+static inline void deref_mad_agent(struct ib_mad_agent_private *mad_agent_priv)
+{
+	if (atomic_dec_and_test(&mad_agent_priv->refcount))
+		complete(&mad_agent_priv->comp);
+}
+
+static inline void deref_snoop_agent(struct ib_mad_snoop_private *mad_snoop_priv)
+{
+	if (atomic_dec_and_test(&mad_snoop_priv->refcount))
+		complete(&mad_snoop_priv->comp);
+}
+
 static void unregister_mad_agent(struct ib_mad_agent_private *mad_agent_priv)
 {
 	struct ib_mad_port_private *port_priv;
@@ -509,9 +521,8 @@ static void unregister_mad_agent(struct ib_mad_agent_private *mad_agent_priv)
 	flush_workqueue(port_priv->wq);
 	ib_cancel_rmpp_recvs(mad_agent_priv);
 
-	atomic_dec(&mad_agent_priv->refcount);
-	wait_event(mad_agent_priv->wait,
-		   !atomic_read(&mad_agent_priv->refcount));
+	deref_mad_agent(mad_agent_priv);
+	wait_for_completion(&mad_agent_priv->comp);
 
 	kfree(mad_agent_priv->reg_req);
 	ib_dereg_mr(mad_agent_priv->agent.mr);
@@ -529,9 +540,8 @@ static void unregister_mad_snoop(struct ib_mad_snoop_private *mad_snoop_priv)
 	atomic_dec(&qp_info->snoop_count);
 	spin_unlock_irqrestore(&qp_info->snoop_lock, flags);
 
-	atomic_dec(&mad_snoop_priv->refcount);
-	wait_event(mad_snoop_priv->wait,
-		   !atomic_read(&mad_snoop_priv->refcount));
+	deref_snoop_agent(mad_snoop_priv);
+	wait_for_completion(&mad_snoop_priv->comp);
 
 	kfree(mad_snoop_priv);
 }
@@ -600,8 +610,7 @@ static void snoop_send(struct ib_mad_qp_info *qp_info,
 		spin_unlock_irqrestore(&qp_info->snoop_lock, flags);
 		mad_snoop_priv->agent.snoop_handler(&mad_snoop_priv->agent,
 						    send_buf, mad_send_wc);
-		if (atomic_dec_and_test(&mad_snoop_priv->refcount))
-			wake_up(&mad_snoop_priv->wait);
+		deref_snoop_agent(mad_snoop_priv);
 		spin_lock_irqsave(&qp_info->snoop_lock, flags);
 	}
 	spin_unlock_irqrestore(&qp_info->snoop_lock, flags);
@@ -626,8 +635,7 @@ static void snoop_recv(struct ib_mad_qp_info *qp_info,
 		spin_unlock_irqrestore(&qp_info->snoop_lock, flags);
 		mad_snoop_priv->agent.recv_handler(&mad_snoop_priv->agent,
 						   mad_recv_wc);
-		if (atomic_dec_and_test(&mad_snoop_priv->refcount))
-			wake_up(&mad_snoop_priv->wait);
+		deref_snoop_agent(mad_snoop_priv);
 		spin_lock_irqsave(&qp_info->snoop_lock, flags);
 	}
 	spin_unlock_irqrestore(&qp_info->snoop_lock, flags);
@@ -968,8 +976,7 @@ void ib_free_send_mad(struct ib_mad_send_buf *send_buf)
 
 	free_send_rmpp_list(mad_send_wr);
 	kfree(send_buf->mad);
-	if (atomic_dec_and_test(&mad_agent_priv->refcount))
-		wake_up(&mad_agent_priv->wait);
+	deref_mad_agent(mad_agent_priv);
 }
 EXPORT_SYMBOL(ib_free_send_mad);
 
@@ -1757,8 +1764,7 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
 		mad_recv_wc = ib_process_rmpp_recv_wc(mad_agent_priv,
 						      mad_recv_wc);
 		if (!mad_recv_wc) {
-			if (atomic_dec_and_test(&mad_agent_priv->refcount))
-				wake_up(&mad_agent_priv->wait);
+			deref_mad_agent(mad_agent_priv);
 			return;
 		}
 	}
@@ -1770,8 +1776,7 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
 		if (!mad_send_wr) {
 			spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
 			ib_free_recv_mad(mad_recv_wc);
-			if (atomic_dec_and_test(&mad_agent_priv->refcount))
-				wake_up(&mad_agent_priv->wait);
+			deref_mad_agent(mad_agent_priv);
 			return;
 		}
 		ib_mark_mad_done(mad_send_wr);
@@ -1790,8 +1795,7 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
 	} else {
 		mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent,
 						   mad_recv_wc);
-		if (atomic_dec_and_test(&mad_agent_priv->refcount))
-			wake_up(&mad_agent_priv->wait);
+		deref_mad_agent(mad_agent_priv);
 	}
 }
 
@@ -2021,8 +2025,7 @@ void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr,
 						   mad_send_wc);
 
 	/* Release reference on agent taken when sending */
-	if (atomic_dec_and_test(&mad_agent_priv->refcount))
-		wake_up(&mad_agent_priv->wait);
+	deref_mad_agent(mad_agent_priv);
 	return;
 done:
 	spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h
index 6c9c133d71ef465ca1c7df621b1773cd3bdaa5cb..b4fa28d3160fc5abd2dc076e92bfb2f81928fb62 100644
--- a/drivers/infiniband/core/mad_priv.h
+++ b/drivers/infiniband/core/mad_priv.h
@@ -37,6 +37,7 @@
 #ifndef __IB_MAD_PRIV_H__
 #define __IB_MAD_PRIV_H__
 
+#include <linux/completion.h>
 #include <linux/pci.h>
 #include <linux/kthread.h>
 #include <linux/workqueue.h>
@@ -108,7 +109,7 @@ struct ib_mad_agent_private {
 	struct list_head rmpp_list;
 
 	atomic_t refcount;
-	wait_queue_head_t wait;
+	struct completion comp;
 };
 
 struct ib_mad_snoop_private {
@@ -117,7 +118,7 @@ struct ib_mad_snoop_private {
 	int snoop_index;
 	int mad_snoop_flags;
 	atomic_t refcount;
-	wait_queue_head_t wait;
+	struct completion comp;
 };
 
 struct ib_mad_send_wr_private {
diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c
index dfd4e588ce031ec8f5edb092f20fddfbc6d322bb..d4704e054e30746cdb5a377c1fa31ffddbdabafd 100644
--- a/drivers/infiniband/core/mad_rmpp.c
+++ b/drivers/infiniband/core/mad_rmpp.c
@@ -49,7 +49,7 @@ struct mad_rmpp_recv {
 	struct list_head list;
 	struct work_struct timeout_work;
 	struct work_struct cleanup_work;
-	wait_queue_head_t wait;
+	struct completion comp;
 	enum rmpp_state state;
 	spinlock_t lock;
 	atomic_t refcount;
@@ -69,10 +69,16 @@ struct mad_rmpp_recv {
 	u8 method;
 };
 
+static inline void deref_rmpp_recv(struct mad_rmpp_recv *rmpp_recv)
+{
+	if (atomic_dec_and_test(&rmpp_recv->refcount))
+		complete(&rmpp_recv->comp);
+}
+
 static void destroy_rmpp_recv(struct mad_rmpp_recv *rmpp_recv)
 {
-	atomic_dec(&rmpp_recv->refcount);
-	wait_event(rmpp_recv->wait, !atomic_read(&rmpp_recv->refcount));
+	deref_rmpp_recv(rmpp_recv);
+	wait_for_completion(&rmpp_recv->comp);
 	ib_destroy_ah(rmpp_recv->ah);
 	kfree(rmpp_recv);
 }
@@ -253,7 +259,7 @@ create_rmpp_recv(struct ib_mad_agent_private *agent,
 		goto error;
 
 	rmpp_recv->agent = agent;
-	init_waitqueue_head(&rmpp_recv->wait);
+	init_completion(&rmpp_recv->comp);
 	INIT_WORK(&rmpp_recv->timeout_work, recv_timeout_handler, rmpp_recv);
 	INIT_WORK(&rmpp_recv->cleanup_work, recv_cleanup_handler, rmpp_recv);
 	spin_lock_init(&rmpp_recv->lock);
@@ -279,12 +285,6 @@ error:	kfree(rmpp_recv);
 	return NULL;
 }
 
-static inline void deref_rmpp_recv(struct mad_rmpp_recv *rmpp_recv)
-{
-	if (atomic_dec_and_test(&rmpp_recv->refcount))
-		wake_up(&rmpp_recv->wait);
-}
-
 static struct mad_rmpp_recv *
 find_rmpp_recv(struct ib_mad_agent_private *agent,
 	       struct ib_mad_recv_wc *mad_recv_wc)
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 15121cb5a1f6a3d2b5e69b19011bb122ad247055..21f9282c1b25d00dcddef4fd2ccba530ad05f543 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -336,7 +336,7 @@ static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr,
 	switch (width) {
 	case 4:
 		ret = sprintf(buf, "%u\n", (out_mad->data[40 + offset / 8] >>
-					    (offset % 4)) & 0xf);
+					    (4 - (offset % 8))) & 0xf);
 		break;
 	case 8:
 		ret = sprintf(buf, "%u\n", out_mad->data[40 + offset / 8]);
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index f6a05965a4e8ab79c3529fa71884c792ea8e8c4e..9164a09b6ccd1d0aeea7153d29c8307e3c5903ca 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -32,6 +32,8 @@
  *
  * $Id: ucm.c 2594 2005-06-13 19:46:02Z libor $
  */
+
+#include <linux/completion.h>
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/module.h>
@@ -72,7 +74,7 @@ struct ib_ucm_file {
 
 struct ib_ucm_context {
 	int                 id;
-	wait_queue_head_t   wait;
+	struct completion   comp;
 	atomic_t            ref;
 	int		    events_reported;
 
@@ -138,7 +140,7 @@ static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id)
 static void ib_ucm_ctx_put(struct ib_ucm_context *ctx)
 {
 	if (atomic_dec_and_test(&ctx->ref))
-		wake_up(&ctx->wait);
+		complete(&ctx->comp);
 }
 
 static inline int ib_ucm_new_cm_id(int event)
@@ -178,7 +180,7 @@ static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file)
 		return NULL;
 
 	atomic_set(&ctx->ref, 1);
-	init_waitqueue_head(&ctx->wait);
+	init_completion(&ctx->comp);
 	ctx->file = file;
 	INIT_LIST_HEAD(&ctx->events);
 
@@ -586,8 +588,8 @@ static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file,
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
 
-	atomic_dec(&ctx->ref);
-	wait_event(ctx->wait, !atomic_read(&ctx->ref));
+	ib_ucm_ctx_put(ctx);
+	wait_for_completion(&ctx->comp);
 
 	/* No new events will be generated after destroying the cm_id. */
 	ib_destroy_cm_id(ctx->cm_id);
diff --git a/drivers/infiniband/core/uverbs_mem.c b/drivers/infiniband/core/uverbs_mem.c
index 36a32c315668cebbc7e34be30704b0c4851bcf66..efe147dbeb42137e695298e19c525e1acf027a07 100644
--- a/drivers/infiniband/core/uverbs_mem.c
+++ b/drivers/infiniband/core/uverbs_mem.c
@@ -211,8 +211,10 @@ void ib_umem_release_on_close(struct ib_device *dev, struct ib_umem *umem)
 	 */
 
 	work = kmalloc(sizeof *work, GFP_KERNEL);
-	if (!work)
+	if (!work) {
+		mmput(mm);
 		return;
+	}
 
 	INIT_WORK(&work->work, ib_umem_account, work);
 	work->mm   = mm;
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
index 398add4d4cb1f4a7a5d0a7923b8bf6ce23bc8da5..3697edafd6d25f7caf05fe202e92cf7f591cb34c 100644
--- a/drivers/infiniband/hw/ipath/ipath_driver.c
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -116,10 +116,9 @@ static int __devinit ipath_init_one(struct pci_dev *,
 #define PCI_DEVICE_ID_INFINIPATH_PE800 0x10
 
 static const struct pci_device_id ipath_pci_tbl[] = {
-	{PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE,
-		    PCI_DEVICE_ID_INFINIPATH_HT)},
-	{PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE,
-		    PCI_DEVICE_ID_INFINIPATH_PE800)},
+	{ PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_INFINIPATH_HT) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_INFINIPATH_PE800) },
+	{ 0, }
 };
 
 MODULE_DEVICE_TABLE(pci, ipath_pci_tbl);
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index 1985b5dfa481bdb91efaf5611bba73f83de3a1b1..798e13e14faf826695d8b64a0493a5580e24bd73 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -182,7 +182,7 @@ struct mthca_cmd_context {
 	u8                status;
 };
 
-static int fw_cmd_doorbell = 1;
+static int fw_cmd_doorbell = 0;
 module_param(fw_cmd_doorbell, int, 0644);
 MODULE_PARM_DESC(fw_cmd_doorbell, "post FW commands through doorbell page if nonzero "
 		 "(and supported by FW)");
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
index 312cf90731ea856e09c7c4a0b31a1adf845497c4..205854e9c662809b49576b1ea8c3eb213e44ce72 100644
--- a/drivers/infiniband/hw/mthca/mthca_cq.c
+++ b/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -238,9 +238,9 @@ void mthca_cq_event(struct mthca_dev *dev, u32 cqn,
 	spin_lock(&dev->cq_table.lock);
 
 	cq = mthca_array_get(&dev->cq_table.cq, cqn & (dev->limits.num_cqs - 1));
-
 	if (cq)
-		atomic_inc(&cq->refcount);
+		++cq->refcount;
+
 	spin_unlock(&dev->cq_table.lock);
 
 	if (!cq) {
@@ -254,8 +254,10 @@ void mthca_cq_event(struct mthca_dev *dev, u32 cqn,
 	if (cq->ibcq.event_handler)
 		cq->ibcq.event_handler(&event, cq->ibcq.cq_context);
 
-	if (atomic_dec_and_test(&cq->refcount))
+	spin_lock(&dev->cq_table.lock);
+	if (!--cq->refcount)
 		wake_up(&cq->wait);
+	spin_unlock(&dev->cq_table.lock);
 }
 
 static inline int is_recv_cqe(struct mthca_cqe *cqe)
@@ -267,23 +269,13 @@ static inline int is_recv_cqe(struct mthca_cqe *cqe)
 		return !(cqe->is_send & 0x80);
 }
 
-void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
+void mthca_cq_clean(struct mthca_dev *dev, struct mthca_cq *cq, u32 qpn,
 		    struct mthca_srq *srq)
 {
-	struct mthca_cq *cq;
 	struct mthca_cqe *cqe;
 	u32 prod_index;
 	int nfreed = 0;
 
-	spin_lock_irq(&dev->cq_table.lock);
-	cq = mthca_array_get(&dev->cq_table.cq, cqn & (dev->limits.num_cqs - 1));
-	if (cq)
-		atomic_inc(&cq->refcount);
-	spin_unlock_irq(&dev->cq_table.lock);
-
-	if (!cq)
-		return;
-
 	spin_lock_irq(&cq->lock);
 
 	/*
@@ -301,7 +293,7 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
 
 	if (0)
 		mthca_dbg(dev, "Cleaning QPN %06x from CQN %06x; ci %d, pi %d\n",
-			  qpn, cqn, cq->cons_index, prod_index);
+			  qpn, cq->cqn, cq->cons_index, prod_index);
 
 	/*
 	 * Now sweep backwards through the CQ, removing CQ entries
@@ -325,8 +317,6 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
 	}
 
 	spin_unlock_irq(&cq->lock);
-	if (atomic_dec_and_test(&cq->refcount))
-		wake_up(&cq->wait);
 }
 
 void mthca_cq_resize_copy_cqes(struct mthca_cq *cq)
@@ -821,7 +811,7 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
 	}
 
 	spin_lock_init(&cq->lock);
-	atomic_set(&cq->refcount, 1);
+	cq->refcount = 1;
 	init_waitqueue_head(&cq->wait);
 
 	memset(cq_context, 0, sizeof *cq_context);
@@ -896,6 +886,17 @@ err_out:
 	return err;
 }
 
+static inline int get_cq_refcount(struct mthca_dev *dev, struct mthca_cq *cq)
+{
+	int c;
+
+	spin_lock_irq(&dev->cq_table.lock);
+	c = cq->refcount;
+	spin_unlock_irq(&dev->cq_table.lock);
+
+	return c;
+}
+
 void mthca_free_cq(struct mthca_dev *dev,
 		   struct mthca_cq *cq)
 {
@@ -929,6 +930,7 @@ void mthca_free_cq(struct mthca_dev *dev,
 	spin_lock_irq(&dev->cq_table.lock);
 	mthca_array_clear(&dev->cq_table.cq,
 			  cq->cqn & (dev->limits.num_cqs - 1));
+	--cq->refcount;
 	spin_unlock_irq(&dev->cq_table.lock);
 
 	if (dev->mthca_flags & MTHCA_FLAG_MSI_X)
@@ -936,8 +938,7 @@ void mthca_free_cq(struct mthca_dev *dev,
 	else
 		synchronize_irq(dev->pdev->irq);
 
-	atomic_dec(&cq->refcount);
-	wait_event(cq->wait, !atomic_read(&cq->refcount));
+	wait_event(cq->wait, !get_cq_refcount(dev, cq));
 
 	if (cq->is_kernel) {
 		mthca_free_cq_buf(dev, &cq->buf, cq->ibcq.cqe);
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
index 4c1dcb4c18222056844f29999c9e2f61e61f0cff..f8160b8de0908ed51b160c880634c1394a6b0712 100644
--- a/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -496,7 +496,7 @@ void mthca_free_cq(struct mthca_dev *dev,
 void mthca_cq_completion(struct mthca_dev *dev, u32 cqn);
 void mthca_cq_event(struct mthca_dev *dev, u32 cqn,
 		    enum ib_event_type event_type);
-void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
+void mthca_cq_clean(struct mthca_dev *dev, struct mthca_cq *cq, u32 qpn,
 		    struct mthca_srq *srq);
 void mthca_cq_resize_copy_cqes(struct mthca_cq *cq);
 int mthca_alloc_cq_buf(struct mthca_dev *dev, struct mthca_cq_buf *buf, int nent);
diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c
index 25e1c1db9a405cca1b5c2fc457944e82dc6778d9..a486dec1707e27a648b1c6276c0bddb8fe48da99 100644
--- a/drivers/infiniband/hw/mthca/mthca_mr.c
+++ b/drivers/infiniband/hw/mthca/mthca_mr.c
@@ -761,6 +761,7 @@ void mthca_arbel_fmr_unmap(struct mthca_dev *dev, struct mthca_fmr *fmr)
 
 int __devinit mthca_init_mr_table(struct mthca_dev *dev)
 {
+	unsigned long addr;
 	int err, i;
 
 	err = mthca_alloc_init(&dev->mr_table.mpt_alloc,
@@ -796,9 +797,12 @@ int __devinit mthca_init_mr_table(struct mthca_dev *dev)
 			goto err_fmr_mpt;
 		}
 
+		addr = pci_resource_start(dev->pdev, 4) +
+			((pci_resource_len(dev->pdev, 4) - 1) &
+			 dev->mr_table.mpt_base);
+
 		dev->mr_table.tavor_fmr.mpt_base =
-			ioremap(dev->mr_table.mpt_base,
-				(1 << i) * sizeof (struct mthca_mpt_entry));
+			ioremap(addr, (1 << i) * sizeof(struct mthca_mpt_entry));
 
 		if (!dev->mr_table.tavor_fmr.mpt_base) {
 			mthca_warn(dev, "MPT ioremap for FMR failed.\n");
@@ -806,9 +810,12 @@ int __devinit mthca_init_mr_table(struct mthca_dev *dev)
 			goto err_fmr_mpt;
 		}
 
+		addr = pci_resource_start(dev->pdev, 4) +
+			((pci_resource_len(dev->pdev, 4) - 1) &
+			 dev->mr_table.mtt_base);
+
 		dev->mr_table.tavor_fmr.mtt_base =
-			ioremap(dev->mr_table.mtt_base,
-				(1 << i) * MTHCA_MTT_SEG_SIZE);
+			ioremap(addr, (1 << i) * MTHCA_MTT_SEG_SIZE);
 		if (!dev->mr_table.tavor_fmr.mtt_base) {
 			mthca_warn(dev, "MTT ioremap for FMR failed.\n");
 			err = -ENOMEM;
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.h b/drivers/infiniband/hw/mthca/mthca_provider.h
index 6676a786d69091118d459ab428c794b829808367..179a8f610d0f00ded795bfa0b07310a9ac1fc986 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.h
+++ b/drivers/infiniband/hw/mthca/mthca_provider.h
@@ -139,11 +139,12 @@ struct mthca_ah {
  * a qp may be locked, with the send cq locked first.  No other
  * nesting should be done.
  *
- * Each struct mthca_cq/qp also has an atomic_t ref count.  The
- * pointer from the cq/qp_table to the struct counts as one reference.
- * This reference also is good for access through the consumer API, so
- * modifying the CQ/QP etc doesn't need to take another reference.
- * Access because of a completion being polled does need a reference.
+ * Each struct mthca_cq/qp also has an ref count, protected by the
+ * corresponding table lock.  The pointer from the cq/qp_table to the
+ * struct counts as one reference.  This reference also is good for
+ * access through the consumer API, so modifying the CQ/QP etc doesn't
+ * need to take another reference.  Access to a QP because of a
+ * completion being polled does not need a reference either.
  *
  * Finally, each struct mthca_cq/qp has a wait_queue_head_t for the
  * destroy function to sleep on.
@@ -159,8 +160,9 @@ struct mthca_ah {
  * - decrement ref count; if zero, wake up waiters
  *
  * To destroy a CQ/QP, we can do the following:
- * - lock cq/qp_table, remove pointer, unlock cq/qp_table lock
- * - decrement ref count
+ * - lock cq/qp_table
+ * - remove pointer and decrement ref count
+ * - unlock cq/qp_table lock
  * - wait_event until ref count is zero
  *
  * It is the consumer's responsibilty to make sure that no QP
@@ -197,7 +199,7 @@ struct mthca_cq_resize {
 struct mthca_cq {
 	struct ib_cq		ibcq;
 	spinlock_t		lock;
-	atomic_t		refcount;
+	int			refcount;
 	int			cqn;
 	u32			cons_index;
 	struct mthca_cq_buf	buf;
@@ -217,7 +219,7 @@ struct mthca_cq {
 struct mthca_srq {
 	struct ib_srq		ibsrq;
 	spinlock_t		lock;
-	atomic_t		refcount;
+	int			refcount;
 	int			srqn;
 	int			max;
 	int			max_gs;
@@ -254,7 +256,7 @@ struct mthca_wq {
 
 struct mthca_qp {
 	struct ib_qp           ibqp;
-	atomic_t               refcount;
+	int                    refcount;
 	u32                    qpn;
 	int                    is_direct;
 	u8                     port; /* for SQP and memfree use only */
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index f37b0e3673230aa1d1bbd17b65d17ddc89d2de4b..07c13be07a4a5da858a975fe6d11059b0da3a35b 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -240,7 +240,7 @@ void mthca_qp_event(struct mthca_dev *dev, u32 qpn,
 	spin_lock(&dev->qp_table.lock);
 	qp = mthca_array_get(&dev->qp_table.qp, qpn & (dev->limits.num_qps - 1));
 	if (qp)
-		atomic_inc(&qp->refcount);
+		++qp->refcount;
 	spin_unlock(&dev->qp_table.lock);
 
 	if (!qp) {
@@ -257,8 +257,10 @@ void mthca_qp_event(struct mthca_dev *dev, u32 qpn,
 	if (qp->ibqp.event_handler)
 		qp->ibqp.event_handler(&event, qp->ibqp.qp_context);
 
-	if (atomic_dec_and_test(&qp->refcount))
+	spin_lock(&dev->qp_table.lock);
+	if (!--qp->refcount)
 		wake_up(&qp->wait);
+	spin_unlock(&dev->qp_table.lock);
 }
 
 static int to_mthca_state(enum ib_qp_state ib_state)
@@ -833,10 +835,10 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
 	 * entries and reinitialize the QP.
 	 */
 	if (new_state == IB_QPS_RESET && !qp->ibqp.uobject) {
-		mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq)->cqn, qp->qpn,
+		mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq), qp->qpn,
 			       qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
 		if (qp->ibqp.send_cq != qp->ibqp.recv_cq)
-			mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq)->cqn, qp->qpn,
+			mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq), qp->qpn,
 				       qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
 
 		mthca_wq_init(&qp->sq);
@@ -1096,7 +1098,7 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev,
 	int ret;
 	int i;
 
-	atomic_set(&qp->refcount, 1);
+	qp->refcount = 1;
 	init_waitqueue_head(&qp->wait);
 	qp->state    	 = IB_QPS_RESET;
 	qp->atomic_rd_en = 0;
@@ -1318,6 +1320,17 @@ int mthca_alloc_sqp(struct mthca_dev *dev,
 	return err;
 }
 
+static inline int get_qp_refcount(struct mthca_dev *dev, struct mthca_qp *qp)
+{
+	int c;
+
+	spin_lock_irq(&dev->qp_table.lock);
+	c = qp->refcount;
+	spin_unlock_irq(&dev->qp_table.lock);
+
+	return c;
+}
+
 void mthca_free_qp(struct mthca_dev *dev,
 		   struct mthca_qp *qp)
 {
@@ -1339,14 +1352,14 @@ void mthca_free_qp(struct mthca_dev *dev,
 	spin_lock(&dev->qp_table.lock);
 	mthca_array_clear(&dev->qp_table.qp,
 			  qp->qpn & (dev->limits.num_qps - 1));
+	--qp->refcount;
 	spin_unlock(&dev->qp_table.lock);
 
 	if (send_cq != recv_cq)
 		spin_unlock(&recv_cq->lock);
 	spin_unlock_irq(&send_cq->lock);
 
-	atomic_dec(&qp->refcount);
-	wait_event(qp->wait, !atomic_read(&qp->refcount));
+	wait_event(qp->wait, !get_qp_refcount(dev, qp));
 
 	if (qp->state != IB_QPS_RESET)
 		mthca_MODIFY_QP(dev, qp->state, IB_QPS_RESET, qp->qpn, 0,
@@ -1358,10 +1371,10 @@ void mthca_free_qp(struct mthca_dev *dev,
 	 * unref the mem-free tables and free the QPN in our table.
 	 */
 	if (!qp->ibqp.uobject) {
-		mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq)->cqn, qp->qpn,
+		mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq), qp->qpn,
 			       qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
 		if (qp->ibqp.send_cq != qp->ibqp.recv_cq)
-			mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq)->cqn, qp->qpn,
+			mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq), qp->qpn,
 				       qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
 
 		mthca_free_memfree(dev, qp);
@@ -1714,23 +1727,7 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
 
 	ind = qp->rq.next_ind;
 
-	for (nreq = 0; wr; ++nreq, wr = wr->next) {
-		if (unlikely(nreq == MTHCA_TAVOR_MAX_WQES_PER_RECV_DB)) {
-			nreq = 0;
-
-			doorbell[0] = cpu_to_be32((qp->rq.next_ind << qp->rq.wqe_shift) | size0);
-			doorbell[1] = cpu_to_be32(qp->qpn << 8);
-
-			wmb();
-
-			mthca_write64(doorbell,
-				      dev->kar + MTHCA_RECEIVE_DOORBELL,
-				      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
-
-			qp->rq.head += MTHCA_TAVOR_MAX_WQES_PER_RECV_DB;
-			size0 = 0;
-		}
-
+	for (nreq = 0; wr; wr = wr->next) {
 		if (mthca_wq_overflow(&qp->rq, nreq, qp->ibqp.recv_cq)) {
 			mthca_err(dev, "RQ %06x full (%u head, %u tail,"
 					" %d max, %d nreq)\n", qp->qpn,
@@ -1784,6 +1781,23 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
 		++ind;
 		if (unlikely(ind >= qp->rq.max))
 			ind -= qp->rq.max;
+
+		++nreq;
+		if (unlikely(nreq == MTHCA_TAVOR_MAX_WQES_PER_RECV_DB)) {
+			nreq = 0;
+
+			doorbell[0] = cpu_to_be32((qp->rq.next_ind << qp->rq.wqe_shift) | size0);
+			doorbell[1] = cpu_to_be32(qp->qpn << 8);
+
+			wmb();
+
+			mthca_write64(doorbell,
+				      dev->kar + MTHCA_RECEIVE_DOORBELL,
+				      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+
+			qp->rq.head += MTHCA_TAVOR_MAX_WQES_PER_RECV_DB;
+			size0 = 0;
+		}
 	}
 
 out:
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index adcaf85355ae6a33adb03dabb09c37f3ec85f0d3..1ea433291fa71883e06fa0743c3f9fd443fe55bd 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -241,7 +241,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
 		goto err_out_mailbox;
 
 	spin_lock_init(&srq->lock);
-	atomic_set(&srq->refcount, 1);
+	srq->refcount = 1;
 	init_waitqueue_head(&srq->wait);
 
 	if (mthca_is_memfree(dev))
@@ -308,6 +308,17 @@ err_out:
 	return err;
 }
 
+static inline int get_srq_refcount(struct mthca_dev *dev, struct mthca_srq *srq)
+{
+	int c;
+
+	spin_lock_irq(&dev->srq_table.lock);
+	c = srq->refcount;
+	spin_unlock_irq(&dev->srq_table.lock);
+
+	return c;
+}
+
 void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq)
 {
 	struct mthca_mailbox *mailbox;
@@ -329,10 +340,10 @@ void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq)
 	spin_lock_irq(&dev->srq_table.lock);
 	mthca_array_clear(&dev->srq_table.srq,
 			  srq->srqn & (dev->limits.num_srqs - 1));
+	--srq->refcount;
 	spin_unlock_irq(&dev->srq_table.lock);
 
-	atomic_dec(&srq->refcount);
-	wait_event(srq->wait, !atomic_read(&srq->refcount));
+	wait_event(srq->wait, !get_srq_refcount(dev, srq));
 
 	if (!srq->ibsrq.uobject) {
 		mthca_free_srq_buf(dev, srq);
@@ -414,7 +425,7 @@ void mthca_srq_event(struct mthca_dev *dev, u32 srqn,
 	spin_lock(&dev->srq_table.lock);
 	srq = mthca_array_get(&dev->srq_table.srq, srqn & (dev->limits.num_srqs - 1));
 	if (srq)
-		atomic_inc(&srq->refcount);
+		++srq->refcount;
 	spin_unlock(&dev->srq_table.lock);
 
 	if (!srq) {
@@ -431,8 +442,10 @@ void mthca_srq_event(struct mthca_dev *dev, u32 srqn,
 	srq->ibsrq.event_handler(&event, srq->ibsrq.srq_context);
 
 out:
-	if (atomic_dec_and_test(&srq->refcount))
+	spin_lock(&dev->srq_table.lock);
+	if (!--srq->refcount)
 		wake_up(&srq->wait);
+	spin_unlock(&dev->srq_table.lock);
 }
 
 /*
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
index 4ca175553f9f71201ff6a6ad604093e24e88950b..f887780e809348b5f10240b52728d71758a51c8f 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
@@ -158,10 +158,8 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
 		if (priv->pkey == pkey) {
 			unregister_netdev(priv->dev);
 			ipoib_dev_cleanup(priv->dev);
-
 			list_del(&priv->list);
-
-			kfree(priv);
+			free_netdev(priv->dev);
 
 			ret = 0;
 			break;
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 5bb55742ada68d34249d11ae9390150b30e078f5..9cbdffa08dc2bca6da821638efc0078b24792374 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -340,7 +340,10 @@ static void srp_disconnect_target(struct srp_target_port *target)
 	/* XXX should send SRP_I_LOGOUT request */
 
 	init_completion(&target->done);
-	ib_send_cm_dreq(target->cm_id, NULL, 0);
+	if (ib_send_cm_dreq(target->cm_id, NULL, 0)) {
+		printk(KERN_DEBUG PFX "Sending CM DREQ failed\n");
+		return;
+	}
 	wait_for_completion(&target->done);
 }
 
@@ -351,7 +354,6 @@ static void srp_remove_work(void *target_ptr)
 	spin_lock_irq(target->scsi_host->host_lock);
 	if (target->state != SRP_TARGET_DEAD) {
 		spin_unlock_irq(target->scsi_host->host_lock);
-		scsi_host_put(target->scsi_host);
 		return;
 	}
 	target->state = SRP_TARGET_REMOVED;
@@ -365,8 +367,6 @@ static void srp_remove_work(void *target_ptr)
 	ib_destroy_cm_id(target->cm_id);
 	srp_free_target_ib(target);
 	scsi_host_put(target->scsi_host);
-	/* And another put to really free the target port... */
-	scsi_host_put(target->scsi_host);
 }
 
 static int srp_connect_target(struct srp_target_port *target)
@@ -409,6 +409,34 @@ static int srp_connect_target(struct srp_target_port *target)
 	}
 }
 
+static void srp_unmap_data(struct scsi_cmnd *scmnd,
+			   struct srp_target_port *target,
+			   struct srp_request *req)
+{
+	struct scatterlist *scat;
+	int nents;
+
+	if (!scmnd->request_buffer ||
+	    (scmnd->sc_data_direction != DMA_TO_DEVICE &&
+	     scmnd->sc_data_direction != DMA_FROM_DEVICE))
+		return;
+
+	/*
+	 * This handling of non-SG commands can be killed when the
+	 * SCSI midlayer no longer generates non-SG commands.
+	 */
+	if (likely(scmnd->use_sg)) {
+		nents = scmnd->use_sg;
+		scat  = scmnd->request_buffer;
+	} else {
+		nents = 1;
+		scat  = &req->fake_sg;
+	}
+
+	dma_unmap_sg(target->srp_host->dev->dma_device, scat, nents,
+		     scmnd->sc_data_direction);
+}
+
 static int srp_reconnect_target(struct srp_target_port *target)
 {
 	struct ib_cm_id *new_cm_id;
@@ -455,16 +483,16 @@ static int srp_reconnect_target(struct srp_target_port *target)
 	list_for_each_entry(req, &target->req_queue, list) {
 		req->scmnd->result = DID_RESET << 16;
 		req->scmnd->scsi_done(req->scmnd);
+		srp_unmap_data(req->scmnd, target, req);
 	}
 
 	target->rx_head	 = 0;
 	target->tx_head	 = 0;
 	target->tx_tail  = 0;
-	target->req_head = 0;
-	for (i = 0; i < SRP_SQ_SIZE - 1; ++i)
-		target->req_ring[i].next = i + 1;
-	target->req_ring[SRP_SQ_SIZE - 1].next = -1;
+	INIT_LIST_HEAD(&target->free_reqs);
 	INIT_LIST_HEAD(&target->req_queue);
+	for (i = 0; i < SRP_SQ_SIZE; ++i)
+		list_add_tail(&target->req_ring[i].list, &target->free_reqs);
 
 	ret = srp_connect_target(target);
 	if (ret)
@@ -589,40 +617,10 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
 	return len;
 }
 
-static void srp_unmap_data(struct scsi_cmnd *scmnd,
-			   struct srp_target_port *target,
-			   struct srp_request *req)
-{
-	struct scatterlist *scat;
-	int nents;
-
-	if (!scmnd->request_buffer ||
-	    (scmnd->sc_data_direction != DMA_TO_DEVICE &&
-	     scmnd->sc_data_direction != DMA_FROM_DEVICE))
-		return;
-
-	/*
-	 * This handling of non-SG commands can be killed when the
-	 * SCSI midlayer no longer generates non-SG commands.
-	 */
-	if (likely(scmnd->use_sg)) {
-		nents = scmnd->use_sg;
-		scat  = scmnd->request_buffer;
-	} else {
-		nents = 1;
-		scat  = &req->fake_sg;
-	}
-
-	dma_unmap_sg(target->srp_host->dev->dma_device, scat, nents,
-		     scmnd->sc_data_direction);
-}
-
-static void srp_remove_req(struct srp_target_port *target, struct srp_request *req,
-			   int index)
+static void srp_remove_req(struct srp_target_port *target, struct srp_request *req)
 {
-	list_del(&req->list);
-	req->next = target->req_head;
-	target->req_head = index;
+	srp_unmap_data(req->scmnd, target, req);
+	list_move_tail(&req->list, &target->free_reqs);
 }
 
 static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
@@ -647,7 +645,7 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
 			req->tsk_status = rsp->data[3];
 		complete(&req->done);
 	} else {
-		scmnd 	      = req->scmnd;
+		scmnd = req->scmnd;
 		if (!scmnd)
 			printk(KERN_ERR "Null scmnd for RSP w/tag %016llx\n",
 			       (unsigned long long) rsp->tag);
@@ -665,14 +663,11 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
 		else if (rsp->flags & (SRP_RSP_FLAG_DIOVER | SRP_RSP_FLAG_DIUNDER))
 			scmnd->resid = be32_to_cpu(rsp->data_in_res_cnt);
 
-		srp_unmap_data(scmnd, target, req);
-
 		if (!req->tsk_mgmt) {
-			req->scmnd = NULL;
 			scmnd->host_scribble = (void *) -1L;
 			scmnd->scsi_done(scmnd);
 
-			srp_remove_req(target, req, rsp->tag & ~SRP_TAG_TSK_MGMT);
+			srp_remove_req(target, req);
 		} else
 			req->cmd_done = 1;
 	}
@@ -859,7 +854,6 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
 	struct srp_request *req;
 	struct srp_iu *iu;
 	struct srp_cmd *cmd;
-	long req_index;
 	int len;
 
 	if (target->state == SRP_TARGET_CONNECTING)
@@ -879,22 +873,20 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
 	dma_sync_single_for_cpu(target->srp_host->dev->dma_device, iu->dma,
 				SRP_MAX_IU_LEN, DMA_TO_DEVICE);
 
-	req_index = target->req_head;
+	req = list_entry(target->free_reqs.next, struct srp_request, list);
 
 	scmnd->scsi_done     = done;
 	scmnd->result        = 0;
-	scmnd->host_scribble = (void *) req_index;
+	scmnd->host_scribble = (void *) (long) req->index;
 
 	cmd = iu->buf;
 	memset(cmd, 0, sizeof *cmd);
 
 	cmd->opcode = SRP_CMD;
 	cmd->lun    = cpu_to_be64((u64) scmnd->device->lun << 48);
-	cmd->tag    = req_index;
+	cmd->tag    = req->index;
 	memcpy(cmd->cdb, scmnd->cmnd, scmnd->cmd_len);
 
-	req = &target->req_ring[req_index];
-
 	req->scmnd    = scmnd;
 	req->cmd      = iu;
 	req->cmd_done = 0;
@@ -919,8 +911,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
 		goto err_unmap;
 	}
 
-	target->req_head = req->next;
-	list_add_tail(&req->list, &target->req_queue);
+	list_move_tail(&req->list, &target->req_queue);
 
 	return 0;
 
@@ -1143,30 +1134,20 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
 	return 0;
 }
 
-static int srp_send_tsk_mgmt(struct scsi_cmnd *scmnd, u8 func)
+static int srp_send_tsk_mgmt(struct srp_target_port *target,
+			     struct srp_request *req, u8 func)
 {
-	struct srp_target_port *target = host_to_target(scmnd->device->host);
-	struct srp_request *req;
 	struct srp_iu *iu;
 	struct srp_tsk_mgmt *tsk_mgmt;
-	int req_index;
-	int ret = FAILED;
 
 	spin_lock_irq(target->scsi_host->host_lock);
 
 	if (target->state == SRP_TARGET_DEAD ||
 	    target->state == SRP_TARGET_REMOVED) {
-		scmnd->result = DID_BAD_TARGET << 16;
+		req->scmnd->result = DID_BAD_TARGET << 16;
 		goto out;
 	}
 
-	if (scmnd->host_scribble == (void *) -1L)
-		goto out;
-
-	req_index = (long) scmnd->host_scribble;
-	printk(KERN_ERR "Abort for req_index %d\n", req_index);
-
-	req = &target->req_ring[req_index];
 	init_completion(&req->done);
 
 	iu = __srp_get_tx_iu(target);
@@ -1177,10 +1158,10 @@ static int srp_send_tsk_mgmt(struct scsi_cmnd *scmnd, u8 func)
 	memset(tsk_mgmt, 0, sizeof *tsk_mgmt);
 
 	tsk_mgmt->opcode 	= SRP_TSK_MGMT;
-	tsk_mgmt->lun 		= cpu_to_be64((u64) scmnd->device->lun << 48);
-	tsk_mgmt->tag 		= req_index | SRP_TAG_TSK_MGMT;
+	tsk_mgmt->lun 		= cpu_to_be64((u64) req->scmnd->device->lun << 48);
+	tsk_mgmt->tag 		= req->index | SRP_TAG_TSK_MGMT;
 	tsk_mgmt->tsk_mgmt_func = func;
-	tsk_mgmt->task_tag 	= req_index;
+	tsk_mgmt->task_tag 	= req->index;
 
 	if (__srp_post_send(target, iu, sizeof *tsk_mgmt))
 		goto out;
@@ -1188,37 +1169,85 @@ static int srp_send_tsk_mgmt(struct scsi_cmnd *scmnd, u8 func)
 	req->tsk_mgmt = iu;
 
 	spin_unlock_irq(target->scsi_host->host_lock);
+
 	if (!wait_for_completion_timeout(&req->done,
 					 msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS)))
-		return FAILED;
-	spin_lock_irq(target->scsi_host->host_lock);
+		return -1;
 
-	if (req->cmd_done) {
-		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;
-	}
+	return 0;
 
 out:
 	spin_unlock_irq(target->scsi_host->host_lock);
-	return ret;
+	return -1;
+}
+
+static int srp_find_req(struct srp_target_port *target,
+			struct scsi_cmnd *scmnd,
+			struct srp_request **req)
+{
+	if (scmnd->host_scribble == (void *) -1L)
+		return -1;
+
+	*req = &target->req_ring[(long) scmnd->host_scribble];
+
+	return 0;
 }
 
 static int srp_abort(struct scsi_cmnd *scmnd)
 {
+	struct srp_target_port *target = host_to_target(scmnd->device->host);
+	struct srp_request *req;
+	int ret = SUCCESS;
+
 	printk(KERN_ERR "SRP abort called\n");
 
-	return srp_send_tsk_mgmt(scmnd, SRP_TSK_ABORT_TASK);
+	if (srp_find_req(target, scmnd, &req))
+		return FAILED;
+	if (srp_send_tsk_mgmt(target, req, SRP_TSK_ABORT_TASK))
+		return FAILED;
+
+	spin_lock_irq(target->scsi_host->host_lock);
+
+	if (req->cmd_done) {
+		srp_remove_req(target, req);
+		scmnd->scsi_done(scmnd);
+	} else if (!req->tsk_status) {
+		srp_remove_req(target, req);
+		scmnd->result = DID_ABORT << 16;
+	} else
+		ret = FAILED;
+
+	spin_unlock_irq(target->scsi_host->host_lock);
+
+	return ret;
 }
 
 static int srp_reset_device(struct scsi_cmnd *scmnd)
 {
+	struct srp_target_port *target = host_to_target(scmnd->device->host);
+	struct srp_request *req, *tmp;
+
 	printk(KERN_ERR "SRP reset_device called\n");
 
-	return srp_send_tsk_mgmt(scmnd, SRP_TSK_LUN_RESET);
+	if (srp_find_req(target, scmnd, &req))
+		return FAILED;
+	if (srp_send_tsk_mgmt(target, req, SRP_TSK_LUN_RESET))
+		return FAILED;
+	if (req->tsk_status)
+		return FAILED;
+
+	spin_lock_irq(target->scsi_host->host_lock);
+
+	list_for_each_entry_safe(req, tmp, &target->req_queue, list)
+		if (req->scmnd->device == scmnd->device) {
+			req->scmnd->result = DID_RESET << 16;
+			req->scmnd->scsi_done(req->scmnd);
+			srp_remove_req(target, req);
+		}
+
+	spin_unlock_irq(target->scsi_host->host_lock);
+
+	return SUCCESS;
 }
 
 static int srp_reset_host(struct scsi_cmnd *scmnd)
@@ -1518,10 +1547,12 @@ static ssize_t srp_create_target(struct class_device *class_dev,
 
 	INIT_WORK(&target->work, srp_reconnect_work, target);
 
-	for (i = 0; i < SRP_SQ_SIZE - 1; ++i)
-		target->req_ring[i].next = i + 1;
-	target->req_ring[SRP_SQ_SIZE - 1].next = -1;
+	INIT_LIST_HEAD(&target->free_reqs);
 	INIT_LIST_HEAD(&target->req_queue);
+	for (i = 0; i < SRP_SQ_SIZE; ++i) {
+		target->req_ring[i].index = i;
+		list_add_tail(&target->req_ring[i].list, &target->free_reqs);
+	}
 
 	ret = srp_parse_options(buf, target);
 	if (ret)
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index bd7f7c3115de8f0078ce17f66655c0ce5acb0081..c5cd43aae8604af42fb349b160e608a10a84c16d 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -101,7 +101,7 @@ struct srp_request {
 	 */
 	struct scatterlist	fake_sg;
 	struct completion	done;
-	short			next;
+	short			index;
 	u8			cmd_done;
 	u8			tsk_status;
 };
@@ -133,7 +133,7 @@ struct srp_target_port {
 	unsigned		tx_tail;
 	struct srp_iu	       *tx_ring[SRP_SQ_SIZE + 1];
 
-	int			req_head;
+	struct list_head	free_reqs;
 	struct list_head	req_queue;
 	struct srp_request	req_ring[SRP_SQ_SIZE];
 
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
index 1042987856f7227012be466649e8336fd3b062c8..5013703db0e6261808872d4ac9cfb05153b1fb7a 100644
--- a/drivers/input/touchscreen/corgi_ts.c
+++ b/drivers/input/touchscreen/corgi_ts.c
@@ -17,7 +17,7 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <asm/irq.h>
+//#include <asm/irq.h>
 
 #include <asm/arch/sharpsl.h>
 #include <asm/arch/hardware.h>
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 9b493f0becc4d370541742a7fec7f4ef6aed43df..173c899a1fb40cb9eca8ff5b02844a95519b2527 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -1499,7 +1499,6 @@ static int __init capi_init(void)
 		printk(KERN_ERR "capi20: unable to get major %d\n", capi_major);
 		return major_ret;
 	}
-	capi_major = major_ret;
 	capi_class = class_create(THIS_MODULE, "capi");
 	if (IS_ERR(capi_class)) {
 		unregister_chrdev(capi_major, "capi20");
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c
index bfb73fd5077e85aa148a48dbbf5165f5185c5c19..d86ab68114b0c7848126661c2009816658093c9d 100644
--- a/drivers/isdn/gigaset/usb-gigaset.c
+++ b/drivers/isdn/gigaset/usb-gigaset.c
@@ -710,8 +710,8 @@ static int gigaset_probe(struct usb_interface *interface,
 	retval = -ENODEV; //FIXME
 
 	/* See if the device offered us matches what we can accept */
-	if ((le16_to_cpu(udev->descriptor.idVendor  != USB_M105_VENDOR_ID)) ||
-	    (le16_to_cpu(udev->descriptor.idProduct != USB_M105_PRODUCT_ID)))
+	if ((le16_to_cpu(udev->descriptor.idVendor)  != USB_M105_VENDOR_ID) ||
+	    (le16_to_cpu(udev->descriptor.idProduct) != USB_M105_PRODUCT_ID))
 		return -ENODEV;
 
 	/* this starts to become ascii art... */
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 3f5b647945426d5db0c1ffa7793b6fa8dc37e482..626506234b76ca62b29b34708e820f122470e2db 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -4,8 +4,11 @@ menu "LED devices"
 config NEW_LEDS
 	bool "LED Support"
 	help
-	  Say Y to enable Linux LED support.  This is not related to standard
-	  keyboard LEDs which are controlled via the input system.
+	  Say Y to enable Linux LED support.  This allows control of supported
+	  LEDs from both userspace and optionally, by kernel events (triggers).
+
+	  This is not related to standard keyboard LEDs which are controlled
+	  via the input system.
 
 config LEDS_CLASS
 	tristate "LED Class Support"
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index b0b5d05fadd62a106c5e49f027608ad55fb093a4..c75d0ef1609cb900d0cc014620bccbe8fbff2e7c 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -19,6 +19,7 @@
 #include <linux/sysdev.h>
 #include <linux/timer.h>
 #include <linux/err.h>
+#include <linux/ctype.h>
 #include <linux/leds.h>
 #include "leds.h"
 
@@ -43,9 +44,13 @@ static ssize_t led_brightness_store(struct class_device *dev,
 	ssize_t ret = -EINVAL;
 	char *after;
 	unsigned long state = simple_strtoul(buf, &after, 10);
+	size_t count = after - buf;
 
-	if (after - buf > 0) {
-		ret = after - buf;
+	if (*after && isspace(*after))
+		count++;
+
+	if (count == size) {
+		ret = count;
 		led_set_brightness(led_cdev, state);
 	}
 
diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c
index f484b5d6dbf86494ad9eb0f3c07cd276743a30b9..fbf141ef46ec3488779a54c616cdff600f38890d 100644
--- a/drivers/leds/ledtrig-timer.c
+++ b/drivers/leds/ledtrig-timer.c
@@ -20,6 +20,7 @@
 #include <linux/device.h>
 #include <linux/sysdev.h>
 #include <linux/timer.h>
+#include <linux/ctype.h>
 #include <linux/leds.h>
 #include "leds.h"
 
@@ -69,11 +70,15 @@ static ssize_t led_delay_on_store(struct class_device *dev, const char *buf,
 	int ret = -EINVAL;
 	char *after;
 	unsigned long state = simple_strtoul(buf, &after, 10);
+	size_t count = after - buf;
 
-	if (after - buf > 0) {
+	if (*after && isspace(*after))
+		count++;
+
+	if (count == size) {
 		timer_data->delay_on = state;
 		mod_timer(&timer_data->timer, jiffies + 1);
-		ret = after - buf;
+		ret = count;
 	}
 
 	return ret;
@@ -97,11 +102,15 @@ static ssize_t led_delay_off_store(struct class_device *dev, const char *buf,
 	int ret = -EINVAL;
 	char *after;
 	unsigned long state = simple_strtoul(buf, &after, 10);
+	size_t count = after - buf;
+
+	if (*after && isspace(*after))
+		count++;
 
-	if (after - buf > 0) {
+	if (count == size) {
 		timer_data->delay_off = state;
 		mod_timer(&timer_data->timer, jiffies + 1);
-		ret = after - buf;
+		ret = count;
 	}
 
 	return ret;
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 266414ca2814e935b1d589f4c68aa7eed49c028e..9080853fe283554c986f6636b34ee3bc42008b43 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -1189,7 +1189,6 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
 	ioc->diagPending = 0;
 	spin_lock_init(&ioc->diagLock);
 	spin_lock_init(&ioc->fc_rescan_work_lock);
-	spin_lock_init(&ioc->fc_rport_lock);
 	spin_lock_init(&ioc->initializing_hba_lock);
 
 	/* Initialize the event logging.
@@ -5736,11 +5735,13 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
 	return rc;
 }
 
+# define EVENT_DESCR_STR_SZ		100
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static void
 EventDescriptionStr(u8 event, u32 evData0, char *evStr)
 {
-	char *ds;
+	char *ds = NULL;
 
 	switch(event) {
 	case MPI_EVENT_NONE:
@@ -5777,9 +5778,9 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
 		if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
 			ds = "Loop State(LIP) Change";
 		else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
-			ds = "Loop State(LPE) Change";			/* ??? */
+			ds = "Loop State(LPE) Change";		/* ??? */
 		else
-			ds = "Loop State(LPB) Change";			/* ??? */
+			ds = "Loop State(LPB) Change";		/* ??? */
 		break;
 	case MPI_EVENT_LOGOUT:
 		ds = "Logout";
@@ -5841,27 +5842,32 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
 		break;
 	case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
 	{
-		char buf[50];
 		u8 id = (u8)(evData0);
 		u8 ReasonCode = (u8)(evData0 >> 16);
 		switch (ReasonCode) {
 		case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
-			sprintf(buf,"SAS Device Status Change: Added: id=%d", id);
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "SAS Device Status Change: Added: id=%d", id);
 			break;
 		case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
-			sprintf(buf,"SAS Device Status Change: Deleted: id=%d", id);
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "SAS Device Status Change: Deleted: id=%d", id);
 			break;
 		case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
-			sprintf(buf,"SAS Device Status Change: SMART Data: id=%d", id);
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "SAS Device Status Change: SMART Data: id=%d",
+			    id);
 			break;
 		case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
-			sprintf(buf,"SAS Device Status Change: No Persistancy Added: id=%d", id);
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "SAS Device Status Change: No Persistancy "
+			    "Added: id=%d", id);
 			break;
 		default:
-			sprintf(buf,"SAS Device Status Change: Unknown: id=%d", id);
-		break;
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "SAS Device Status Change: Unknown: id=%d", id);
+			break;
 		}
-		ds = buf;
 		break;
 	}
 	case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
@@ -5878,41 +5884,46 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
 		break;
 	case MPI_EVENT_SAS_PHY_LINK_STATUS:
 	{
-		char buf[50];
 		u8 LinkRates = (u8)(evData0 >> 8);
 		u8 PhyNumber = (u8)(evData0);
 		LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
 			MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
 		switch (LinkRates) {
 		case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
-			sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			   "SAS PHY Link Status: Phy=%d:"
 			   " Rate Unknown",PhyNumber);
 			break;
 		case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
-			sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			   "SAS PHY Link Status: Phy=%d:"
 			   " Phy Disabled",PhyNumber);
 			break;
 		case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
-			sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			   "SAS PHY Link Status: Phy=%d:"
 			   " Failed Speed Nego",PhyNumber);
 			break;
 		case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
-			sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			   "SAS PHY Link Status: Phy=%d:"
 			   " Sata OOB Completed",PhyNumber);
 			break;
 		case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
-			sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			   "SAS PHY Link Status: Phy=%d:"
 			   " Rate 1.5 Gbps",PhyNumber);
 			break;
 		case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
-			sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			   "SAS PHY Link Status: Phy=%d:"
 			   " Rate 3.0 Gpbs",PhyNumber);
 			break;
 		default:
-			sprintf(buf,"SAS PHY Link Status: Phy=%d", PhyNumber);
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			   "SAS PHY Link Status: Phy=%d", PhyNumber);
 			break;
 		}
-		ds = buf;
 		break;
 	}
 	case MPI_EVENT_SAS_DISCOVERY_ERROR:
@@ -5921,9 +5932,8 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
 	case MPI_EVENT_IR_RESYNC_UPDATE:
 	{
 		u8 resync_complete = (u8)(evData0 >> 16);
-		char buf[40];
-		sprintf(buf,"IR Resync Update: Complete = %d:",resync_complete);
-		ds = buf;
+		snprintf(evStr, EVENT_DESCR_STR_SZ,
+		    "IR Resync Update: Complete = %d:",resync_complete);
 		break;
 	}
 	case MPI_EVENT_IR2:
@@ -5976,7 +5986,8 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
 		ds = "Unknown";
 		break;
 	}
-	strcpy(evStr,ds);
+	if (ds)
+		strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -5998,7 +6009,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
 	int ii;
 	int r = 0;
 	int handlers = 0;
-	char evStr[100];
+	char evStr[EVENT_DESCR_STR_SZ];
 	u8 event;
 
 	/*
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index be7e8501b53c1d4243691625003cd690c0b75932..f673cca507e12890c82f4e772a88d3647a0f4416 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -76,8 +76,8 @@
 #define COPYRIGHT	"Copyright (c) 1999-2005 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON	"3.03.08"
-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.03.08"
+#define MPT_LINUX_VERSION_COMMON	"3.03.09"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.03.09"
 #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -489,7 +489,6 @@ typedef	struct _RaidCfgData {
 
 #define MPT_RPORT_INFO_FLAGS_REGISTERED	0x01	/* rport registered */
 #define MPT_RPORT_INFO_FLAGS_MISSING	0x02	/* missing from DevPage0 scan */
-#define MPT_RPORT_INFO_FLAGS_MAPPED_VDEV 0x04	/* target mapped in vdev */
 
 /*
  * data allocated for each fc rport device
@@ -501,7 +500,6 @@ struct mptfc_rport_info
 	struct scsi_target *starget;
 	FCDevicePage0_t pg0;
 	u8		flags;
-	u8		remap_needed;
 };
 
 /*
@@ -628,11 +626,11 @@ typedef struct _MPT_ADAPTER
 	struct work_struct	 mptscsih_persistTask;
 
 	struct list_head	 fc_rports;
-	spinlock_t		 fc_rport_lock; /* list and ri flags */
 	spinlock_t		 fc_rescan_work_lock;
 	int			 fc_rescan_work_count;
 	struct work_struct	 fc_rescan_work;
-
+	char			 fc_rescan_work_q_name[KOBJ_NAME_LEN];
+	struct workqueue_struct *fc_rescan_work_q;
 } MPT_ADAPTER;
 
 /*
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index b343f2a68b1c755ceff84c70aaa774f8eff3576f..856487741ef43b0f2458e6dc6bc55a2edc354fa1 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -341,9 +341,6 @@ mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
 	rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;
 	rid->port_id =   pg0->PortIdentifier;
 	rid->roles = FC_RPORT_ROLE_UNKNOWN;
-	rid->roles |= FC_RPORT_ROLE_FCP_TARGET;
-	if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
-		rid->roles |= FC_RPORT_ROLE_FCP_INITIATOR;
 
 	return 0;
 }
@@ -355,15 +352,18 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
 	struct fc_rport		*rport;
 	struct mptfc_rport_info	*ri;
 	int			new_ri = 1;
-	u64			pn;
-	unsigned long		flags;
+	u64			pn, nn;
 	VirtTarget		*vtarget;
+	u32			roles = FC_RPORT_ROLE_UNKNOWN;
 
 	if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
 		return;
 
+	roles |= FC_RPORT_ROLE_FCP_TARGET;
+	if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
+		roles |= FC_RPORT_ROLE_FCP_INITIATOR;
+
 	/* scan list looking for a match */
-	spin_lock_irqsave(&ioc->fc_rport_lock, flags);
 	list_for_each_entry(ri, &ioc->fc_rports, list) {
 		pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
 		if (pn == rport_ids.port_name) {	/* match */
@@ -373,11 +373,9 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
 		}
 	}
 	if (new_ri) {	/* allocate one */
-		spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
 		ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
 		if (!ri)
 			return;
-		spin_lock_irqsave(&ioc->fc_rport_lock, flags);
 		list_add_tail(&ri->list, &ioc->fc_rports);
 	}
 
@@ -387,14 +385,11 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
 	/* MPT_RPORT_INFO_FLAGS_REGISTERED - rport not previously deleted */
 	if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
 		ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
-		spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
 		rport = fc_remote_port_add(ioc->sh, channel, &rport_ids);
-		spin_lock_irqsave(&ioc->fc_rport_lock, flags);
 		if (rport) {
 			ri->rport = rport;
 			if (new_ri) /* may have been reset by user */
 				rport->dev_loss_tmo = mptfc_dev_loss_tmo;
-			*((struct mptfc_rport_info **)rport->dd_data) = ri;
 			/*
 			 * if already mapped, remap here.  If not mapped,
 			 * target_alloc will allocate vtarget and map,
@@ -406,16 +401,21 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
 					vtarget->target_id = pg0->CurrentTargetID;
 					vtarget->bus_id = pg0->CurrentBus;
 				}
-				ri->remap_needed = 0;
 			}
+			*((struct mptfc_rport_info **)rport->dd_data) = ri;
+			/* scan will be scheduled once rport becomes a target */
+			fc_remote_port_rolechg(rport,roles);
+
+			pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
+			nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
 			dfcprintk ((MYIOC_s_INFO_FMT
 				"mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
 				"rport tid %d, tmo %d\n",
 					ioc->name,
 					ioc->sh->host_no,
 					pg0->PortIdentifier,
-					pg0->WWNN,
-					pg0->WWPN,
+					(unsigned long long)nn,
+					(unsigned long long)pn,
 					pg0->CurrentTargetID,
 					ri->rport->scsi_target_id,
 					ri->rport->dev_loss_tmo));
@@ -425,8 +425,6 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
 			ri = NULL;
 		}
 	}
-	spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
-
 }
 
 /*
@@ -476,7 +474,6 @@ mptfc_target_alloc(struct scsi_target *starget)
 			vtarget->target_id = ri->pg0.CurrentTargetID;
 			vtarget->bus_id = ri->pg0.CurrentBus;
 			ri->starget = starget;
-			ri->remap_needed = 0;
 			rc = 0;
 		}
 	}
@@ -502,10 +499,10 @@ mptfc_slave_alloc(struct scsi_device *sdev)
 	VirtDevice		*vdev;
 	struct scsi_target	*starget;
 	struct fc_rport		*rport;
-	unsigned long		flags;
 
 
-	rport = starget_to_rport(scsi_target(sdev));
+	starget = scsi_target(sdev);
+	rport = starget_to_rport(starget);
 
 	if (!rport || fc_remote_port_chkready(rport))
 		return -ENXIO;
@@ -519,10 +516,8 @@ mptfc_slave_alloc(struct scsi_device *sdev)
 		return -ENOMEM;
 	}
 
-	spin_lock_irqsave(&hd->ioc->fc_rport_lock,flags);
 
 	sdev->hostdata = vdev;
-	starget = scsi_target(sdev);
 	vtarget = starget->hostdata;
 
 	if (vtarget->num_luns == 0) {
@@ -535,14 +530,16 @@ mptfc_slave_alloc(struct scsi_device *sdev)
 	vdev->vtarget = vtarget;
 	vdev->lun = sdev->lun;
 
-	spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
-
 	vtarget->num_luns++;
 
+
 #ifdef DMPT_DEBUG_FC
-	 {
+	{
+	u64 nn, pn;
 	struct mptfc_rport_info *ri;
 	ri = *((struct mptfc_rport_info **)rport->dd_data);
+	pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
+	nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
 	dfcprintk ((MYIOC_s_INFO_FMT
 		"mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
 	        "CurrentTargetID %d, %x %llx %llx\n",
@@ -550,7 +547,9 @@ mptfc_slave_alloc(struct scsi_device *sdev)
 		sdev->host->host_no,
 		vtarget->num_luns,
 		sdev->id, ri->pg0.CurrentTargetID,
-		ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN));
+		ri->pg0.PortIdentifier,
+		(unsigned long long)pn,
+		(unsigned long long)nn));
 	}
 #endif
 
@@ -570,11 +569,31 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 		done(SCpnt);
 		return 0;
 	}
+
+	/* dd_data is null until finished adding target */
 	ri = *((struct mptfc_rport_info **)rport->dd_data);
-	if (unlikely(ri->remap_needed))
-		return SCSI_MLQUEUE_HOST_BUSY;
+	if (unlikely(!ri)) {
+		dfcprintk ((MYIOC_s_INFO_FMT
+			"mptfc_qcmd.%d: %d:%d, dd_data is null.\n",
+			((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
+			((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
+			SCpnt->device->id,SCpnt->device->lun));
+		SCpnt->result = DID_IMM_RETRY << 16;
+		done(SCpnt);
+		return 0;
+	}
 
-	return mptscsih_qcmd(SCpnt,done);
+	err = mptscsih_qcmd(SCpnt,done);
+#ifdef DMPT_DEBUG_FC
+	if (unlikely(err)) {
+		dfcprintk ((MYIOC_s_INFO_FMT
+			"mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero.\n",
+			((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
+			((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
+			SCpnt->device->id,SCpnt->device->lun));
+	}
+#endif
+	return err;
 }
 
 static void
@@ -615,18 +634,17 @@ mptfc_rescan_devices(void *arg)
 	MPT_ADAPTER		*ioc = (MPT_ADAPTER *)arg;
 	int			ii;
 	int			work_to_do;
+	u64			pn;
 	unsigned long		flags;
 	struct mptfc_rport_info *ri;
 
 	do {
 		/* start by tagging all ports as missing */
-		spin_lock_irqsave(&ioc->fc_rport_lock,flags);
 		list_for_each_entry(ri, &ioc->fc_rports, list) {
 			if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
 				ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
 			}
 		}
-		spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
 
 		/*
 		 * now rescan devices known to adapter,
@@ -639,33 +657,24 @@ mptfc_rescan_devices(void *arg)
 		}
 
 		/* delete devices still missing */
-		spin_lock_irqsave(&ioc->fc_rport_lock, flags);
 		list_for_each_entry(ri, &ioc->fc_rports, list) {
 			/* if newly missing, delete it */
-			if ((ri->flags & (MPT_RPORT_INFO_FLAGS_REGISTERED |
-					  MPT_RPORT_INFO_FLAGS_MISSING))
-			  == (MPT_RPORT_INFO_FLAGS_REGISTERED |
-			      MPT_RPORT_INFO_FLAGS_MISSING)) {
+			if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) {
 
 				ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
 					       MPT_RPORT_INFO_FLAGS_MISSING);
-				ri->remap_needed = 1;
-				fc_remote_port_delete(ri->rport);
-				/*
-				 * remote port not really deleted 'cause
-				 * binding is by WWPN and driver only
-				 * registers FCP_TARGETs but cannot trust
-				 * data structures.
-				 */
+				fc_remote_port_delete(ri->rport);	/* won't sleep */
 				ri->rport = NULL;
+
+				pn = (u64)ri->pg0.WWPN.High << 32 |
+				     (u64)ri->pg0.WWPN.Low;
 				dfcprintk ((MYIOC_s_INFO_FMT
 					"mptfc_rescan.%d: %llx deleted\n",
 					ioc->name,
 					ioc->sh->host_no,
-					ri->pg0.WWPN));
+					(unsigned long long)pn));
 			}
 		}
-		spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
 
 		/*
 		 * allow multiple passes as target state
@@ -870,10 +879,23 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		goto out_mptfc_probe;
 	}
 
-	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
-		mptfc_init_host_attr(ioc,ii);
-		mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
-	}
+	/* initialize workqueue */
+
+	snprintf(ioc->fc_rescan_work_q_name, KOBJ_NAME_LEN, "mptfc_wq_%d",
+		sh->host_no);
+	ioc->fc_rescan_work_q =
+		create_singlethread_workqueue(ioc->fc_rescan_work_q_name);
+	if (!ioc->fc_rescan_work_q)
+		goto out_mptfc_probe;
+
+	/*
+	 * scan for rports -
+	 *	by doing it via the workqueue, some locking is eliminated
+	 */
+
+	ioc->fc_rescan_work_count = 1;
+	queue_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work);
+	flush_workqueue(ioc->fc_rescan_work_q);
 
 	return 0;
 
@@ -949,8 +971,18 @@ mptfc_init(void)
 static void __devexit
 mptfc_remove(struct pci_dev *pdev)
 {
-	MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
-	struct mptfc_rport_info *p, *n;
+	MPT_ADAPTER		*ioc = pci_get_drvdata(pdev);
+	struct mptfc_rport_info	*p, *n;
+	struct workqueue_struct *work_q;
+	unsigned long		flags;
+
+	/* destroy workqueue */
+	if ((work_q=ioc->fc_rescan_work_q)) {
+		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+		ioc->fc_rescan_work_q = NULL;
+		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+		destroy_workqueue(work_q);
+	}
 
 	fc_remove_host(ioc->sh);
 
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index e9716b10acea68dba88d3c29b9a96dd220efeb21..af6ec553ff7ca54c3cf4ee14c7e43e32cd9e73a2 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -91,6 +91,7 @@ enum mptsas_hotplug_action {
 	MPTSAS_DEL_DEVICE,
 	MPTSAS_ADD_RAID,
 	MPTSAS_DEL_RAID,
+	MPTSAS_IGNORE_EVENT,
 };
 
 struct mptsas_hotplug_event {
@@ -298,6 +299,26 @@ mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
 	return rc;
 }
 
+/*
+ * Returns true if there is a scsi end device
+ */
+static inline int
+mptsas_is_end_device(struct mptsas_devinfo * attached)
+{
+	if ((attached->handle) &&
+	    (attached->device_info &
+	    MPI_SAS_DEVICE_INFO_END_DEVICE) &&
+	    ((attached->device_info &
+	    MPI_SAS_DEVICE_INFO_SSP_TARGET) |
+	    (attached->device_info &
+	    MPI_SAS_DEVICE_INFO_STP_TARGET) |
+	    (attached->device_info &
+	    MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
+		return 1;
+	else
+		return 0;
+}
+
 static int
 mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
 		u32 form, u32 form_specific)
@@ -872,7 +893,11 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
 	SasDevicePage0_t *buffer;
 	dma_addr_t dma_handle;
 	__le64 sas_address;
-	int error;
+	int error=0;
+
+	if (ioc->sas_discovery_runtime &&
+		mptsas_is_end_device(device_info))
+			goto out;
 
 	hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
 	hdr.ExtPageLength = 0;
@@ -1009,7 +1034,11 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
 	CONFIGPARMS cfg;
 	SasExpanderPage1_t *buffer;
 	dma_addr_t dma_handle;
-	int error;
+	int error=0;
+
+	if (ioc->sas_discovery_runtime &&
+		mptsas_is_end_device(&phy_info->attached))
+			goto out;
 
 	hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
 	hdr.ExtPageLength = 0;
@@ -1068,26 +1097,6 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
 	return error;
 }
 
-/*
- * Returns true if there is a scsi end device
- */
-static inline int
-mptsas_is_end_device(struct mptsas_devinfo * attached)
-{
-	if ((attached->handle) &&
-	    (attached->device_info &
-	    MPI_SAS_DEVICE_INFO_END_DEVICE) &&
-	    ((attached->device_info &
-	    MPI_SAS_DEVICE_INFO_SSP_TARGET) |
-	    (attached->device_info &
-	    MPI_SAS_DEVICE_INFO_STP_TARGET) |
-	    (attached->device_info &
-	    MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
-		return 1;
-	else
-		return 0;
-}
-
 static void
 mptsas_parse_device_info(struct sas_identify *identify,
 		struct mptsas_devinfo *device_info)
@@ -1737,6 +1746,9 @@ mptsas_hotplug_work(void *arg)
 		break;
 	case MPTSAS_ADD_DEVICE:
 
+		if (ev->phys_disk_num_valid)
+			mpt_findImVolumes(ioc);
+
 		/*
 		 * Refresh sas device pg0 data
 		 */
@@ -1868,6 +1880,9 @@ mptsas_hotplug_work(void *arg)
 		scsi_device_put(sdev);
 		mpt_findImVolumes(ioc);
 		break;
+	case MPTSAS_IGNORE_EVENT:
+	default:
+		break;
 	}
 
 	kfree(ev);
@@ -1940,7 +1955,8 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc,
 		EVENT_DATA_RAID *raid_event_data)
 {
 	struct mptsas_hotplug_event *ev;
-	RAID_VOL0_STATUS * volumeStatus;
+	int status = le32_to_cpu(raid_event_data->SettingsStatus);
+	int state = (status >> 8) & 0xff;
 
 	if (ioc->bus_type != SAS)
 		return;
@@ -1955,6 +1971,7 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc,
 	INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
 	ev->ioc = ioc;
 	ev->id = raid_event_data->VolumeID;
+	ev->event_type = MPTSAS_IGNORE_EVENT;
 
 	switch (raid_event_data->ReasonCode) {
 	case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
@@ -1966,6 +1983,25 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc,
 		ev->phys_disk_num = raid_event_data->PhysDiskNum;
 		ev->event_type = MPTSAS_DEL_DEVICE;
 		break;
+	case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
+		switch (state) {
+		case MPI_PD_STATE_ONLINE:
+			ioc->raid_data.isRaid = 1;
+			ev->phys_disk_num_valid = 1;
+			ev->phys_disk_num = raid_event_data->PhysDiskNum;
+			ev->event_type = MPTSAS_ADD_DEVICE;
+			break;
+		case MPI_PD_STATE_MISSING:
+		case MPI_PD_STATE_NOT_COMPATIBLE:
+		case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
+		case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
+		case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
+			ev->event_type = MPTSAS_DEL_DEVICE;
+			break;
+		default:
+			break;
+		}
+		break;
 	case MPI_EVENT_RAID_RC_VOLUME_DELETED:
 		ev->event_type = MPTSAS_DEL_RAID;
 		break;
@@ -1973,11 +2009,18 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc,
 		ev->event_type = MPTSAS_ADD_RAID;
 		break;
 	case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
-		volumeStatus = (RAID_VOL0_STATUS *) &
-		    raid_event_data->SettingsStatus;
-		ev->event_type = (volumeStatus->State ==
-		    MPI_RAIDVOL0_STATUS_STATE_FAILED) ?
-		    MPTSAS_DEL_RAID : MPTSAS_ADD_RAID;
+		switch (state) {
+		case MPI_RAIDVOL0_STATUS_STATE_FAILED:
+		case MPI_RAIDVOL0_STATUS_STATE_MISSING:
+			ev->event_type = MPTSAS_DEL_RAID;
+			break;
+		case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
+		case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
+			ev->event_type = MPTSAS_ADD_RAID;
+			break;
+		default:
+			break;
+		}
 		break;
 	default:
 		break;
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 3729062db3177a2fd6c57c992a6d0c9b09bb1fa2..84fa271eb8f47fd93cf869841055f5e6e037abd9 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -632,7 +632,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 
 		case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:	/* 0x0043 */
 			/* Spoof to SCSI Selection Timeout! */
-			sc->result = DID_NO_CONNECT << 16;
+			if (ioc->bus_type != FC)
+				sc->result = DID_NO_CONNECT << 16;
+			/* else fibre, just stall until rescan event */
+			else
+				sc->result = DID_REQUEUE << 16;
 
 			if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
 				hd->sel_timeout[pScsiReq->TargetID]++;
@@ -877,7 +881,7 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
 	struct scsi_cmnd *sc;
 
 	dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
-			vdevice->target_id, vdevice->lun, max));
+			vdevice->vtarget->target_id, vdevice->lun, max));
 
 	for (ii=0; ii < max; ii++) {
 		if ((sc = hd->ScsiLookup[ii]) != NULL) {
@@ -1645,7 +1649,6 @@ int
 mptscsih_abort(struct scsi_cmnd * SCpnt)
 {
 	MPT_SCSI_HOST	*hd;
-	MPT_ADAPTER	*ioc;
 	MPT_FRAME_HDR	*mf;
 	u32		 ctx2abort;
 	int		 scpnt_idx;
@@ -1663,14 +1666,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 		return FAILED;
 	}
 
-	ioc = hd->ioc;
-	if (hd->resetPending) {
-		return FAILED;
-	}
-
-	if (hd->timeouts < -1)
-		hd->timeouts++;
-
 	/* Find this command
 	 */
 	if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
@@ -1684,6 +1679,13 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 		return SUCCESS;
 	}
 
+	if (hd->resetPending) {
+		return FAILED;
+	}
+
+	if (hd->timeouts < -1)
+		hd->timeouts++;
+
 	printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
 	       hd->ioc->name, SCpnt);
 	scsi_print_command(SCpnt);
@@ -1703,7 +1705,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 	vdev = SCpnt->device->hostdata;
 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
 		vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun,
-		ctx2abort, mptscsih_get_tm_timeout(ioc));
+		ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
 
 	printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
 		hd->ioc->name,
@@ -2521,15 +2523,15 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 
 		/* 7. FC: Rescan for blocked rports which might have returned.
 		 */
-		else if (ioc->bus_type == FC) {
-			int work_count;
-			unsigned long flags;
-
+		if (ioc->bus_type == FC) {
 			spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
-			work_count = ++ioc->fc_rescan_work_count;
+			if (ioc->fc_rescan_work_q) {
+				if (ioc->fc_rescan_work_count++ == 0) {
+					queue_work(ioc->fc_rescan_work_q,
+						   &ioc->fc_rescan_work);
+				}
+			}
 			spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
-			if (work_count == 1)
-				schedule_work(&ioc->fc_rescan_work);
 		}
 		dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
 
@@ -2544,7 +2546,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 {
 	MPT_SCSI_HOST *hd;
 	u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
-	int work_count;
 	unsigned long flags;
 
 	devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
@@ -2569,10 +2570,13 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 
 	case MPI_EVENT_RESCAN:				/* 06 */
 		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
-		work_count = ++ioc->fc_rescan_work_count;
+		if (ioc->fc_rescan_work_q) {
+			if (ioc->fc_rescan_work_count++ == 0) {
+				queue_work(ioc->fc_rescan_work_q,
+					   &ioc->fc_rescan_work);
+			}
+		}
 		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
-		if (work_count == 1)
-			schedule_work(&ioc->fc_rescan_work);
 		break;
 
 		/*
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 09c745b19cc8443a3f86f93737d7f29d2bdba098..f2a4d382ea19e5403b2d2643b5a301476ae3f718 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -783,6 +783,70 @@ static struct pci_device_id mptspi_pci_table[] = {
 };
 MODULE_DEVICE_TABLE(pci, mptspi_pci_table);
 
+
+/*
+ * renegotiate for a given target
+ */
+static void
+mptspi_dv_renegotiate_work(void *data)
+{
+	struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data;
+	struct _MPT_SCSI_HOST *hd = wqw->hd;
+	struct scsi_device *sdev;
+
+	kfree(wqw);
+
+	shost_for_each_device(sdev, hd->ioc->sh)
+		mptspi_dv_device(hd, sdev);
+}
+
+static void
+mptspi_dv_renegotiate(struct _MPT_SCSI_HOST *hd)
+{
+	struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC);
+
+	if (!wqw)
+		return;
+
+	INIT_WORK(&wqw->work, mptspi_dv_renegotiate_work, wqw);
+	wqw->hd = hd;
+
+	schedule_work(&wqw->work);
+}
+
+/*
+ * spi module reset handler
+ */
+static int
+mptspi_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
+{
+	struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
+	int rc;
+
+	rc = mptscsih_ioc_reset(ioc, reset_phase);
+
+	if (reset_phase == MPT_IOC_POST_RESET)
+		mptspi_dv_renegotiate(hd);
+
+	return rc;
+}
+
+/*
+ * spi module resume handler
+ */
+static int
+mptspi_resume(struct pci_dev *pdev)
+{
+	MPT_ADAPTER 	*ioc = pci_get_drvdata(pdev);
+	struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
+	int rc;
+
+	rc = mptscsih_resume(pdev);
+	mptspi_dv_renegotiate(hd);
+
+	return rc;
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -1032,7 +1096,7 @@ static struct pci_driver mptspi_driver = {
 	.shutdown	= mptscsih_shutdown,
 #ifdef CONFIG_PM
 	.suspend	= mptscsih_suspend,
-	.resume		= mptscsih_resume,
+	.resume		= mptspi_resume,
 #endif
 };
 
@@ -1061,7 +1125,7 @@ mptspi_init(void)
 		  ": Registered for IOC event notifications\n"));
 	}
 
-	if (mpt_reset_register(mptspiDoneCtx, mptscsih_ioc_reset) == 0) {
+	if (mpt_reset_register(mptspiDoneCtx, mptspi_ioc_reset) == 0) {
 		dprintk((KERN_INFO MYNAM
 		  ": Registered for IOC reset notifications\n"));
 	}
diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c
index 6061c2d101a06af5635ac49fbfe1cb835dcfa3fb..88f0eef9cf33a9b375689dae3c0ea16f17b425f7 100644
--- a/drivers/mmc/at91_mci.c
+++ b/drivers/mmc/at91_mci.c
@@ -621,9 +621,6 @@ static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	struct at91mci_host *host = mmc_priv(mmc);
 	unsigned long at91_master_clock = clk_get_rate(mci_clk);
 
-	DBG("Clock %uHz, busmode %u, powermode %u, Vdd %u\n",
-		ios->clock, ios->bus_mode, ios->power_mode, ios->vdd);
-
 	if (host)
 		host->bus_mode = ios->bus_mode;
 	else
diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c
index c0326bbc5f283d08e36b9d5a49075494a731f83d..5dc4bee7abebfb9c8685e61306ae54bdff754060 100644
--- a/drivers/mmc/au1xmmc.c
+++ b/drivers/mmc/au1xmmc.c
@@ -310,7 +310,7 @@ static void au1xmmc_data_complete(struct au1xmmc_host *host, u32 status)
 		}
 		else
 			data->bytes_xfered =
-				(data->blocks * (1 << data->blksz_bits)) -
+				(data->blocks * data->blksz) -
 				host->pio.len;
 	}
 
@@ -575,7 +575,7 @@ static int
 au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data)
 {
 
-	int datalen = data->blocks * (1 << data->blksz_bits);
+	int datalen = data->blocks * data->blksz;
 
 	if (dma != 0)
 		host->flags |= HOST_F_DMA;
@@ -596,7 +596,7 @@ au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data)
 	if (host->dma.len == 0)
 		return MMC_ERR_TIMEOUT;
 
-	au_writel((1 << data->blksz_bits) - 1, HOST_BLKSIZE(host));
+	au_writel(data->blksz - 1, HOST_BLKSIZE(host));
 
 	if (host->flags & HOST_F_DMA) {
 		int i;
@@ -720,10 +720,6 @@ static void au1xmmc_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
 {
 	struct au1xmmc_host *host = mmc_priv(mmc);
 
-	DBG("set_ios (power=%u, clock=%uHz, vdd=%u, mode=%u)\n",
-	      host->id, ios->power_mode, ios->clock, ios->vdd,
-	      ios->bus_mode);
-
 	if (ios->power_mode == MMC_POWER_OFF)
 		au1xmmc_set_power(host, 0);
 	else if (ios->power_mode == MMC_POWER_ON) {
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c
index ffb7f55d34676eb3a96b6a727d4bfabf8e5d6390..a4eb1d0e7a7169e381847c978c71b7bcb4dd72f1 100644
--- a/drivers/mmc/imxmmc.c
+++ b/drivers/mmc/imxmmc.c
@@ -102,6 +102,7 @@ struct imxmci_host {
 #define IMXMCI_PEND_CPU_DATA_b	5
 #define IMXMCI_PEND_CARD_XCHG_b	6
 #define IMXMCI_PEND_SET_INIT_b	7
+#define IMXMCI_PEND_STARTED_b	8
 
 #define IMXMCI_PEND_IRQ_m	(1 << IMXMCI_PEND_IRQ_b)
 #define IMXMCI_PEND_DMA_END_m	(1 << IMXMCI_PEND_DMA_END_b)
@@ -111,6 +112,7 @@ struct imxmci_host {
 #define IMXMCI_PEND_CPU_DATA_m	(1 << IMXMCI_PEND_CPU_DATA_b)
 #define IMXMCI_PEND_CARD_XCHG_m	(1 << IMXMCI_PEND_CARD_XCHG_b)
 #define IMXMCI_PEND_SET_INIT_m	(1 << IMXMCI_PEND_SET_INIT_b)
+#define IMXMCI_PEND_STARTED_m	(1 << IMXMCI_PEND_STARTED_b)
 
 static void imxmci_stop_clock(struct imxmci_host *host)
 {
@@ -131,23 +133,52 @@ static void imxmci_stop_clock(struct imxmci_host *host)
 	dev_dbg(mmc_dev(host->mmc), "imxmci_stop_clock blocked, no luck\n");
 }
 
-static void imxmci_start_clock(struct imxmci_host *host)
+static int imxmci_start_clock(struct imxmci_host *host)
 {
-	int i = 0;
+	unsigned int trials = 0;
+	unsigned int delay_limit = 128;
+	unsigned long flags;
+
 	MMC_STR_STP_CLK &= ~STR_STP_CLK_STOP_CLK;
-	while(i < 0x1000) {
-	        if(!(i & 0x7f))
-			MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK;
 
-		if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN) {
-			/* Check twice before cut */
+	clear_bit(IMXMCI_PEND_STARTED_b, &host->pending_events);
+
+	/*
+	 * Command start of the clock, this usually succeeds in less
+	 * then 6 delay loops, but during card detection (low clockrate)
+	 * it takes up to 5000 delay loops and sometimes fails for the first time
+	 */
+	MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK;
+
+	do {
+		unsigned int delay = delay_limit;
+
+		while(delay--){
 			if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN)
-				return;
+				/* Check twice before cut */
+				if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN)
+					return 0;
+
+			if(test_bit(IMXMCI_PEND_STARTED_b, &host->pending_events))
+				return 0;
 		}
 
-		i++;
-	}
-	dev_dbg(mmc_dev(host->mmc), "imxmci_start_clock blocked, no luck\n");
+		local_irq_save(flags);
+		/*
+		 * Ensure, that request is not doubled under all possible circumstances.
+		 * It is possible, that cock running state is missed, because some other
+		 * IRQ or schedule delays this function execution and the clocks has
+		 * been already stopped by other means (response processing, SDHC HW)
+		 */
+		if(!test_bit(IMXMCI_PEND_STARTED_b, &host->pending_events))
+			MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK;
+		local_irq_restore(flags);
+
+	} while(++trials<256);
+
+	dev_err(mmc_dev(host->mmc), "imxmci_start_clock blocked, no luck\n");
+
+	return -1;
 }
 
 static void imxmci_softreset(void)
@@ -187,8 +218,10 @@ static int imxmci_busy_wait_for_status(struct imxmci_host *host,
 	if(!loops)
 		return 0;
 
-	dev_info(mmc_dev(host->mmc), "busy wait for %d usec in %s, STATUS = 0x%x (0x%x)\n",
-		loops, where, *pstat, stat_mask);
+	/* The busy-wait is expected there for clock <8MHz due to SDHC hardware flaws */
+	if(!(stat_mask & STATUS_END_CMD_RESP) || (host->mmc->ios.clock>=8000000))
+		dev_info(mmc_dev(host->mmc), "busy wait for %d usec in %s, STATUS = 0x%x (0x%x)\n",
+			loops, where, *pstat, stat_mask);
 	return loops;
 }
 
@@ -302,6 +335,9 @@ static void imxmci_start_cmd(struct imxmci_host *host, struct mmc_command *cmd,
 	WARN_ON(host->cmd != NULL);
 	host->cmd = cmd;
 
+	/* Ensure, that clock are stopped else command programming and start fails */
+	imxmci_stop_clock(host);
+
 	if (cmd->flags & MMC_RSP_BUSY)
 		cmdat |= CMD_DAT_CONT_BUSY;
 
@@ -498,7 +534,7 @@ static int imxmci_data_done(struct imxmci_host *host, unsigned int stat)
 
 	data_error = imxmci_finish_data(host, stat);
 
-	if (host->req->stop && (data_error == MMC_ERR_NONE)) {
+	if (host->req->stop) {
 		imxmci_stop_clock(host);
 		imxmci_start_cmd(host, host->req->stop, 0);
 	} else {
@@ -522,7 +558,7 @@ static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat)
 	int trans_done = 0;
 	unsigned int stat = *pstat;
 
-	if(host->actual_bus_width == MMC_BUS_WIDTH_4)
+	if(host->actual_bus_width != MMC_BUS_WIDTH_4)
 		burst_len = 16;
 	else
 		burst_len = 64;
@@ -560,8 +596,7 @@ static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat)
 			stat = MMC_STATUS;
 
 			/* Flush extra bytes from FIFO */
-			while(flush_len >= 2){
-				flush_len -= 2;
+			while(flush_len && !(stat & STATUS_DATA_TRANS_DONE)){
 				i = MMC_BUFFER_ACCESS;
 				stat = MMC_STATUS;
 				stat &= ~STATUS_CRC_READ_ERR; /* Stupid but required there */
@@ -622,6 +657,7 @@ static irqreturn_t imxmci_irq(int irq, void *devid, struct pt_regs *regs)
 	atomic_set(&host->stuck_timeout, 0);
 	host->status_reg = stat;
 	set_bit(IMXMCI_PEND_IRQ_b, &host->pending_events);
+	set_bit(IMXMCI_PEND_STARTED_b, &host->pending_events);
 	tasklet_schedule(&host->tasklet);
 
 	return IRQ_RETVAL(handled);;
@@ -714,10 +750,6 @@ static void imxmci_tasklet_fnc(unsigned long data)
 			data_dir_mask = STATUS_DATA_TRANS_DONE;
 		}
 
-		imxmci_busy_wait_for_status(host, &stat,
-				data_dir_mask,
-				50, "imxmci_tasklet_fnc data");
-
 		if(stat & data_dir_mask) {
 			clear_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events);
 			imxmci_data_done(host, stat);
@@ -775,10 +807,6 @@ static void imxmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	struct imxmci_host *host = mmc_priv(mmc);
 	int prescaler;
 
-	dev_dbg(mmc_dev(host->mmc), "clock %u power %u vdd %u width %u\n",
-		ios->clock, ios->power_mode, ios->vdd,
-		(ios->bus_width==MMC_BUS_WIDTH_4)?4:1);
-
 	if( ios->bus_width==MMC_BUS_WIDTH_4 ) {
 		host->actual_bus_width = MMC_BUS_WIDTH_4;
 		imx_gpio_mode(PB11_PF_SD_DAT3);
@@ -837,7 +865,11 @@ static void imxmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 
 		imxmci_stop_clock(host);
 		MMC_CLK_RATE = (prescaler<<3) | clk;
-		imxmci_start_clock(host);
+		/*
+		 * Under my understanding, clock should not be started there, because it would
+		 * initiate SDHC sequencer and send last or random command into card
+		 */
+		/*imxmci_start_clock(host);*/
 
 		dev_dbg(mmc_dev(host->mmc), "MMC_CLK_RATE: 0x%08x\n", MMC_CLK_RATE);
 	} else {
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index da6ddd910fc513d8ad8552fa575984485899a653..6201f3086a0226d1810aab52067d0a33e22206fe 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -59,21 +59,23 @@ static const unsigned int tacc_mant[] = {
 
 
 /**
- *	mmc_request_done - finish processing an MMC command
- *	@host: MMC host which completed command
- *	@mrq: MMC request which completed
+ *	mmc_request_done - finish processing an MMC request
+ *	@host: MMC host which completed request
+ *	@mrq: MMC request which request
  *
  *	MMC drivers should call this function when they have completed
- *	their processing of a command.  This should be called before the
- *	data part of the command has completed.
+ *	their processing of a request.
  */
 void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
 {
 	struct mmc_command *cmd = mrq->cmd;
-	int err = mrq->cmd->error;
-	pr_debug("MMC: req done (%02x): %d: %08x %08x %08x %08x\n",
-		 cmd->opcode, err, cmd->resp[0], cmd->resp[1],
-		 cmd->resp[2], cmd->resp[3]);
+	int err = cmd->error;
+
+	pr_debug("%s: req done (CMD%u): %d/%d/%d: %08x %08x %08x %08x\n",
+		 mmc_hostname(host), cmd->opcode, err,
+		 mrq->data ? mrq->data->error : 0,
+		 mrq->stop ? mrq->stop->error : 0,
+		 cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
 
 	if (err && cmd->retries) {
 		cmd->retries--;
@@ -97,8 +99,9 @@ EXPORT_SYMBOL(mmc_request_done);
 void
 mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
 {
-	pr_debug("MMC: starting cmd %02x arg %08x flags %08x\n",
-		 mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags);
+	pr_debug("%s: starting CMD%u arg %08x flags %08x\n",
+		 mmc_hostname(host), mrq->cmd->opcode,
+		 mrq->cmd->arg, mrq->cmd->flags);
 
 	WARN_ON(host->card_busy == NULL);
 
@@ -312,6 +315,18 @@ void mmc_release_host(struct mmc_host *host)
 
 EXPORT_SYMBOL(mmc_release_host);
 
+static inline void mmc_set_ios(struct mmc_host *host)
+{
+	struct mmc_ios *ios = &host->ios;
+
+	pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
+		 mmc_hostname(host), ios->clock, ios->bus_mode,
+		 ios->power_mode, ios->chip_select, ios->vdd,
+		 ios->bus_width);
+	
+	host->ops->set_ios(host, ios);
+}
+
 static int mmc_select_card(struct mmc_host *host, struct mmc_card *card)
 {
 	int err;
@@ -364,7 +379,7 @@ static int mmc_select_card(struct mmc_host *host, struct mmc_card *card)
 		}
 	}
 
-	host->ops->set_ios(host, &host->ios);
+	mmc_set_ios(host);
 
 	return MMC_ERR_NONE;
 }
@@ -415,7 +430,7 @@ static u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
 		ocr = 3 << bit;
 
 		host->ios.vdd = bit;
-		host->ops->set_ios(host, &host->ios);
+		mmc_set_ios(host);
 	} else {
 		ocr = 0;
 	}
@@ -549,6 +564,7 @@ static void mmc_decode_csd(struct mmc_card *card)
 		csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
 		csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
 		csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+		csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
 		csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
 		csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
 	} else {
@@ -583,6 +599,7 @@ static void mmc_decode_csd(struct mmc_card *card)
 		csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
 		csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
 		csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+		csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
 		csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
 		csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
 	}
@@ -666,7 +683,7 @@ static void mmc_idle_cards(struct mmc_host *host)
 	struct mmc_command cmd;
 
 	host->ios.chip_select = MMC_CS_HIGH;
-	host->ops->set_ios(host, &host->ios);
+	mmc_set_ios(host);
 
 	mmc_delay(1);
 
@@ -679,7 +696,7 @@ static void mmc_idle_cards(struct mmc_host *host)
 	mmc_delay(1);
 
 	host->ios.chip_select = MMC_CS_DONTCARE;
-	host->ops->set_ios(host, &host->ios);
+	mmc_set_ios(host);
 
 	mmc_delay(1);
 }
@@ -704,13 +721,13 @@ static void mmc_power_up(struct mmc_host *host)
 	host->ios.chip_select = MMC_CS_DONTCARE;
 	host->ios.power_mode = MMC_POWER_UP;
 	host->ios.bus_width = MMC_BUS_WIDTH_1;
-	host->ops->set_ios(host, &host->ios);
+	mmc_set_ios(host);
 
 	mmc_delay(1);
 
 	host->ios.clock = host->f_min;
 	host->ios.power_mode = MMC_POWER_ON;
-	host->ops->set_ios(host, &host->ios);
+	mmc_set_ios(host);
 
 	mmc_delay(2);
 }
@@ -723,7 +740,7 @@ static void mmc_power_off(struct mmc_host *host)
 	host->ios.chip_select = MMC_CS_DONTCARE;
 	host->ios.power_mode = MMC_POWER_OFF;
 	host->ios.bus_width = MMC_BUS_WIDTH_1;
-	host->ops->set_ios(host, &host->ios);
+	mmc_set_ios(host);
 }
 
 static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
@@ -934,6 +951,7 @@ static void mmc_read_scrs(struct mmc_host *host)
 		data.timeout_ns = card->csd.tacc_ns * 10;
 		data.timeout_clks = card->csd.tacc_clks * 10;
 		data.blksz_bits = 3;
+		data.blksz = 1 << 3;
 		data.blocks = 1;
 		data.flags = MMC_DATA_READ;
 		data.sg = &sg;
@@ -971,7 +989,8 @@ static unsigned int mmc_calculate_clock(struct mmc_host *host)
 		if (!mmc_card_dead(card) && max_dtr > card->csd.max_dtr)
 			max_dtr = card->csd.max_dtr;
 
-	pr_debug("MMC: selected %d.%03dMHz transfer rate\n",
+	pr_debug("%s: selected %d.%03dMHz transfer rate\n",
+		 mmc_hostname(host),
 		 max_dtr / 1000000, (max_dtr / 1000) % 1000);
 
 	return max_dtr;
@@ -1046,7 +1065,7 @@ static void mmc_setup(struct mmc_host *host)
 	} else {
 		host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
 		host->ios.clock = host->f_min;
-		host->ops->set_ios(host, &host->ios);
+		mmc_set_ios(host);
 
 		/*
 		 * We should remember the OCR mask from the existing
@@ -1082,7 +1101,7 @@ static void mmc_setup(struct mmc_host *host)
 	 * Ok, now switch to push-pull mode.
 	 */
 	host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
-	host->ops->set_ios(host, &host->ios);
+	mmc_set_ios(host);
 
 	mmc_read_csds(host);
 
@@ -1128,7 +1147,7 @@ static void mmc_rescan(void *data)
 		 * attached cards and the host support.
 		 */
 		host->ios.clock = mmc_calculate_clock(host);
-		host->ops->set_ios(host, &host->ios);
+		mmc_set_ios(host);
 	}
 
 	mmc_release_host(host);
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index 8eb2a2ede64b5c1272515c7f2d37150a5eb792df..e39cc05c64c258536cae1ece7c88d24969e036cb 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -175,6 +175,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 		brq.data.timeout_ns = card->csd.tacc_ns * 10;
 		brq.data.timeout_clks = card->csd.tacc_clks * 10;
 		brq.data.blksz_bits = md->block_bits;
+		brq.data.blksz = 1 << md->block_bits;
 		brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
 		brq.stop.opcode = MMC_STOP_TRANSMISSION;
 		brq.stop.arg = 0;
@@ -187,6 +188,12 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 			brq.cmd.opcode = MMC_WRITE_BLOCK;
 			brq.data.flags |= MMC_DATA_WRITE;
 			brq.data.blocks = 1;
+
+			/*
+			 * Scale up the timeout by the r2w factor
+			 */
+			brq.data.timeout_ns <<= card->csd.r2w_factor;
+			brq.data.timeout_clks <<= card->csd.r2w_factor;
 		}
 
 		if (brq.data.blocks > 1) {
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
index df7e861e2fc75f2c5cfa5e5196b70b597378ecd9..da8e4d7339cc42f6d2cc7c58106e6bf9604ffe40 100644
--- a/drivers/mmc/mmci.c
+++ b/drivers/mmc/mmci.c
@@ -402,9 +402,6 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	struct mmci_host *host = mmc_priv(mmc);
 	u32 clk = 0, pwr = 0;
 
-	DBG(host, "clock %uHz busmode %u powermode %u Vdd %u\n",
-	    ios->clock, ios->bus_mode, ios->power_mode, ios->vdd);
-
 	if (ios->clock) {
 		if (ios->clock >= host->mclk) {
 			clk = MCI_CLK_BYPASS;
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c
index eb42cb3494205f4140982d31ae45c8837426e571..b49368fd96b82b051d59fe85ec00c9127ca05390 100644
--- a/drivers/mmc/pxamci.c
+++ b/drivers/mmc/pxamci.c
@@ -119,7 +119,7 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
 		nob = 0xffff;
 
 	writel(nob, host->base + MMC_NOB);
-	writel(1 << data->blksz_bits, host->base + MMC_BLKLEN);
+	writel(data->blksz, host->base + MMC_BLKLEN);
 
 	clks = (unsigned long long)data->timeout_ns * CLOCKRATE;
 	do_div(clks, 1000000000UL);
@@ -198,7 +198,6 @@ static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd,
 
 static void pxamci_finish_request(struct pxamci_host *host, struct mmc_request *mrq)
 {
-	pr_debug("PXAMCI: request done\n");
 	host->mrq = NULL;
 	host->cmd = NULL;
 	host->data = NULL;
@@ -284,14 +283,14 @@ static int pxamci_data_done(struct pxamci_host *host, unsigned int stat)
 	 * data blocks as being in error.
 	 */
 	if (data->error == MMC_ERR_NONE)
-		data->bytes_xfered = data->blocks << data->blksz_bits;
+		data->bytes_xfered = data->blocks * data->blksz;
 	else
 		data->bytes_xfered = 0;
 
 	pxamci_disable_irq(host, DATA_TRAN_DONE);
 
 	host->data = NULL;
-	if (host->mrq->stop && data->error == MMC_ERR_NONE) {
+	if (host->mrq->stop) {
 		pxamci_stop_clock(host);
 		pxamci_start_cmd(host, host->mrq->stop, 0);
 	} else {
@@ -309,12 +308,10 @@ static irqreturn_t pxamci_irq(int irq, void *devid, struct pt_regs *regs)
 
 	ireg = readl(host->base + MMC_I_REG);
 
-	pr_debug("PXAMCI: irq %08x\n", ireg);
-
 	if (ireg) {
 		unsigned stat = readl(host->base + MMC_STAT);
 
-		pr_debug("PXAMCI: stat %08x\n", stat);
+		pr_debug("PXAMCI: irq %08x stat %08x\n", ireg, stat);
 
 		if (ireg & END_CMD_RES)
 			handled |= pxamci_cmd_done(host, stat);
@@ -368,10 +365,6 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct pxamci_host *host = mmc_priv(mmc);
 
-	pr_debug("pxamci_set_ios: clock %u power %u vdd %u.%02u\n",
-		 ios->clock, ios->power_mode, ios->vdd / 100,
-		 ios->vdd % 100);
-
 	if (ios->clock) {
 		unsigned int clk = CLOCKRATE / ios->clock;
 		if (CLOCKRATE / clk > ios->clock)
@@ -397,7 +390,7 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 			host->cmdat |= CMDAT_INIT;
 	}
 
-	pr_debug("pxamci_set_ios: clkrt = %x cmdat = %x\n",
+	pr_debug("PXAMCI: clkrt = %x cmdat = %x\n",
 		 host->clkrt, host->cmdat);
 }
 
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index bdbfca050029a91548bd1d4e59a64ab8bb1705a4..b0053280ff2db61725a7bddba23287e36907428f 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -570,10 +570,6 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 
 	spin_lock_irqsave(&host->lock, flags);
 
-	DBG("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
-	     ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select,
-	     ios->vdd, ios->bus_width);
-
 	/*
 	 * Reset the chip on each power off.
 	 * Should clear out any weird states.
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index 511f7b0b31d21c02c12ad98b717e2ace407d60dd..8167332d4013d3e7701f108d2aea0dcd241ea700 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -662,14 +662,14 @@ static void wbsd_prepare_data(struct wbsd_host *host, struct mmc_data *data)
 	unsigned long dmaflags;
 
 	DBGF("blksz %04x blks %04x flags %08x\n",
-		1 << data->blksz_bits, data->blocks, data->flags);
+		data->blksz, data->blocks, data->flags);
 	DBGF("tsac %d ms nsac %d clk\n",
 		data->timeout_ns / 1000000, data->timeout_clks);
 
 	/*
 	 * Calculate size.
 	 */
-	host->size = data->blocks << data->blksz_bits;
+	host->size = data->blocks * data->blksz;
 
 	/*
 	 * Check timeout values for overflow.
@@ -696,12 +696,12 @@ static void wbsd_prepare_data(struct wbsd_host *host, struct mmc_data *data)
 	 * Two bytes are needed for each data line.
 	 */
 	if (host->bus_width == MMC_BUS_WIDTH_1) {
-		blksize = (1 << data->blksz_bits) + 2;
+		blksize = data->blksz + 2;
 
 		wbsd_write_index(host, WBSD_IDX_PBSMSB, (blksize >> 4) & 0xF0);
 		wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
 	} else if (host->bus_width == MMC_BUS_WIDTH_4) {
-		blksize = (1 << data->blksz_bits) + 2 * 4;
+		blksize = data->blksz + 2 * 4;
 
 		wbsd_write_index(host, WBSD_IDX_PBSMSB,
 			((blksize >> 4) & 0xF0) | WBSD_DATA_WIDTH);
@@ -931,10 +931,6 @@ static void wbsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	struct wbsd_host *host = mmc_priv(mmc);
 	u8 clk, setup, pwr;
 
-	DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
-		ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select,
-		ios->vdd, ios->bus_width);
-
 	spin_lock_bh(&host->lock);
 
 	/*
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index d5dfc784bccd565a6f99ef347d4e315c907a7212..e1fe960d71b371a520f7a0c9869ee67d25bed17c 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -52,6 +52,7 @@
 #include <linux/mii.h>
 #include <linux/skbuff.h>
 #include <linux/delay.h>
+#include <linux/crc32.h>
 #include <asm/mipsregs.h>
 #include <asm/irq.h>
 #include <asm/io.h>
@@ -2038,23 +2039,6 @@ static void au1000_tx_timeout(struct net_device *dev)
 	netif_wake_queue(dev);
 }
 
-
-static unsigned const ethernet_polynomial = 0x04c11db7U;
-static inline u32 ether_crc(int length, unsigned char *data)
-{
-    int crc = -1;
-
-    while(--length >= 0) {
-		unsigned char current_octet = *data++;
-		int bit;
-		for (bit = 0; bit < 8; bit++, current_octet >>= 1)
-			crc = (crc << 1) ^
-				((crc < 0) ^ (current_octet & 1) ? 
-				 ethernet_polynomial : 0);
-    }
-    return crc;
-}
-
 static void set_rx_mode(struct net_device *dev)
 {
 	struct au1000_private *aup = (struct au1000_private *) dev->priv;
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 3d306681919e12bdc923ae95c1e282faa724dbad..d8233e0b789952c9047e2b7158e0f291b9efe772 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -650,9 +650,11 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
 
 	/* Hardware bug work-around, the chip is unable to do PCI DMA
 	   to/from anything above 1GB :-( */
-	if (mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) {
+	if (dma_mapping_error(mapping) ||
+		mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) {
 		/* Sigh... */
-		pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
+		if (!dma_mapping_error(mapping))
+			pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
 		dev_kfree_skb_any(skb);
 		skb = __dev_alloc_skb(RX_PKT_BUF_SZ,GFP_DMA);
 		if (skb == NULL)
@@ -660,8 +662,10 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
 		mapping = pci_map_single(bp->pdev, skb->data,
 					 RX_PKT_BUF_SZ,
 					 PCI_DMA_FROMDEVICE);
-		if (mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) {
-			pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
+		if (dma_mapping_error(mapping) ||
+			mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) {
+			if (!dma_mapping_error(mapping))
+				pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
 			dev_kfree_skb_any(skb);
 			return -ENOMEM;
 		}
@@ -967,9 +971,10 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	}
 
 	mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
-	if (mapping + len > B44_DMA_MASK) {
+	if (dma_mapping_error(mapping) || mapping + len > B44_DMA_MASK) {
 		/* Chip can't handle DMA to/from >1GB, use bounce buffer */
-		pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE);
+		if (!dma_mapping_error(mapping))
+			pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE);
 
 		bounce_skb = __dev_alloc_skb(TX_PKT_BUF_SZ,
 					     GFP_ATOMIC|GFP_DMA);
@@ -978,8 +983,9 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 		mapping = pci_map_single(bp->pdev, bounce_skb->data,
 					 len, PCI_DMA_TODEVICE);
-		if (mapping + len > B44_DMA_MASK) {
-			pci_unmap_single(bp->pdev, mapping,
+		if (dma_mapping_error(mapping) || mapping + len > B44_DMA_MASK) {
+			if (!dma_mapping_error(mapping))
+				pci_unmap_single(bp->pdev, mapping,
 					 len, PCI_DMA_TODEVICE);
 			dev_kfree_skb_any(bounce_skb);
 			goto err_out;
@@ -1203,7 +1209,8 @@ static int b44_alloc_consistent(struct b44 *bp)
 		                             DMA_TABLE_BYTES,
 		                             DMA_BIDIRECTIONAL);
 
-		if (rx_ring_dma + size > B44_DMA_MASK) {
+		if (dma_mapping_error(rx_ring_dma) ||
+			rx_ring_dma + size > B44_DMA_MASK) {
 			kfree(rx_ring);
 			goto out_err;
 		}
@@ -1229,7 +1236,8 @@ static int b44_alloc_consistent(struct b44 *bp)
 		                             DMA_TABLE_BYTES,
 		                             DMA_TO_DEVICE);
 
-		if (tx_ring_dma + size > B44_DMA_MASK) {
+		if (dma_mapping_error(tx_ring_dma) ||
+			tx_ring_dma + size > B44_DMA_MASK) {
 			kfree(tx_ring);
 			goto out_err;
 		}
diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c
index 1f3627470c958972da00dcba432fe27fd893788c..038447fb5c5ee82ef17110189497e029c01d42fd 100644
--- a/drivers/net/dl2k.c
+++ b/drivers/net/dl2k.c
@@ -53,6 +53,7 @@
 #define DRV_VERSION	"v1.17b"
 #define DRV_RELDATE	"2006/03/10"
 #include "dl2k.h"
+#include <linux/dma-mapping.h>
 
 static char version[] __devinitdata =
       KERN_INFO DRV_NAME " " DRV_VERSION " " DRV_RELDATE "\n";	
@@ -765,7 +766,7 @@ rio_free_tx (struct net_device *dev, int irq)
 			break;
 		skb = np->tx_skbuff[entry];
 		pci_unmap_single (np->pdev,
-				  np->tx_ring[entry].fraginfo & 0xffffffffffff,
+				  np->tx_ring[entry].fraginfo & DMA_48BIT_MASK,
 				  skb->len, PCI_DMA_TODEVICE);
 		if (irq)
 			dev_kfree_skb_irq (skb);
@@ -893,7 +894,7 @@ receive_packet (struct net_device *dev)
 			/* Small skbuffs for short packets */
 			if (pkt_len > copy_thresh) {
 				pci_unmap_single (np->pdev,
-						  desc->fraginfo & 0xffffffffffff,
+						  desc->fraginfo & DMA_48BIT_MASK,
 						  np->rx_buf_sz,
 						  PCI_DMA_FROMDEVICE);
 				skb_put (skb = np->rx_skbuff[entry], pkt_len);
@@ -901,7 +902,7 @@ receive_packet (struct net_device *dev)
 			} else if ((skb = dev_alloc_skb (pkt_len + 2)) != NULL) {
 				pci_dma_sync_single_for_cpu(np->pdev,
 				  			    desc->fraginfo & 
-							    	0xffffffffffff,
+							    	DMA_48BIT_MASK,
 							    np->rx_buf_sz,
 							    PCI_DMA_FROMDEVICE);
 				skb->dev = dev;
@@ -913,7 +914,7 @@ receive_packet (struct net_device *dev)
 				skb_put (skb, pkt_len);
 				pci_dma_sync_single_for_device(np->pdev,
 				  			       desc->fraginfo &
-							       	 0xffffffffffff,
+							       	 DMA_48BIT_MASK,
 							       np->rx_buf_sz,
 							       PCI_DMA_FROMDEVICE);
 			}
@@ -1800,7 +1801,7 @@ rio_close (struct net_device *dev)
 		skb = np->rx_skbuff[i];
 		if (skb) {
 			pci_unmap_single(np->pdev, 
-					 np->rx_ring[i].fraginfo & 0xffffffffffff,
+					 np->rx_ring[i].fraginfo & DMA_48BIT_MASK,
 					 skb->len, PCI_DMA_FROMDEVICE);
 			dev_kfree_skb (skb);
 			np->rx_skbuff[i] = NULL;
@@ -1810,7 +1811,7 @@ rio_close (struct net_device *dev)
 		skb = np->tx_skbuff[i];
 		if (skb) {
 			pci_unmap_single(np->pdev, 
-					 np->tx_ring[i].fraginfo & 0xffffffffffff,
+					 np->tx_ring[i].fraginfo & DMA_48BIT_MASK,
 					 skb->len, PCI_DMA_TODEVICE);
 			dev_kfree_skb (skb);
 			np->tx_skbuff[i] = NULL;
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index 79a8fbcf5f93bb4881c43a06094af73064a0450d..0d5fccc984bb2cf888b785447c43c4fcc19282eb 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -582,7 +582,6 @@ static int __init setup_adapter(int card_base, int type, int n)
 		INIT_WORK(&priv->rx_work, rx_bh, priv);
 		dev->priv = priv;
 		sprintf(dev->name, "dmascc%i", 2 * n + i);
-		SET_MODULE_OWNER(dev);
 		dev->base_addr = card_base;
 		dev->irq = irq;
 		dev->open = scc_open;
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index 6ace0e914fd1f2705a00609d23df8e07f44941dd..5927784df3f9373a035e4003c3758c9d56d44b3c 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -1550,7 +1550,6 @@ static unsigned char ax25_nocall[AX25_ADDR_LEN] =
 
 static void scc_net_setup(struct net_device *dev)
 {
-	SET_MODULE_OWNER(dev);
 	dev->tx_queue_len    = 16;	/* should be enough... */
 
 	dev->open            = scc_net_open;
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index fe22479eb2028097213e5f987a1768e453477fc3..b49884048caa29df1cb6f09764e1528a0d99c79b 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -1098,7 +1098,6 @@ static void yam_setup(struct net_device *dev)
 
 	dev->base_addr = yp->iobase;
 	dev->irq = yp->irq;
-	SET_MODULE_OWNER(dev);
 
 	dev->open = yam_open;
 	dev->stop = yam_close;
diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
index 27ab75f20799d5c52a09c9fdf3bc0bc7ebf6784f..c1ce2398efeaa0854f98cef201c4aa6f55144a7b 100644
--- a/drivers/net/irda/Makefile
+++ b/drivers/net/irda/Makefile
@@ -46,4 +46,4 @@ obj-$(CONFIG_MA600_DONGLE)	+= ma600-sir.o
 obj-$(CONFIG_TOIM3232_DONGLE)	+= toim3232-sir.o
 
 # The SIR helper module
-sir-dev-objs := sir_dev.o sir_dongle.o sir_kthread.o
+sir-dev-objs := sir_dev.o sir_dongle.o
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 96bdb73c2283bb3cbcd8bcdc964062f660b5f15d..cd87593e4e8ae6cfe464a5926c91d1db9469b5e0 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -1778,7 +1778,7 @@ static int irda_usb_probe(struct usb_interface *intf,
 
 	if (self->needspatch) {
 		ret = usb_control_msg (self->usbdev, usb_sndctrlpipe (self->usbdev, 0),
-				       0x02, 0x40, 0, 0, 0, 0, msecs_to_jiffies(500));
+				       0x02, 0x40, 0, 0, NULL, 0, 500);
 		if (ret < 0) {
 			IRDA_DEBUG (0, "usb_control_msg failed %d\n", ret);
 			goto err_out_3;
diff --git a/drivers/net/irda/sir-dev.h b/drivers/net/irda/sir-dev.h
index f69fb4cec76f8a90e3b63e78f955c9d58469e4af..9fa294a546d625bd78070ac9f5947b30607f6674 100644
--- a/drivers/net/irda/sir-dev.h
+++ b/drivers/net/irda/sir-dev.h
@@ -15,23 +15,14 @@
 #define IRDA_SIR_H
 
 #include <linux/netdevice.h>
+#include <linux/workqueue.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/irda_device.h>		// iobuff_t
 
-/* FIXME: unify irda_request with sir_fsm! */
-
-struct irda_request {
-	struct list_head lh_request;
-	unsigned long pending;
-	void (*func)(void *);
-	void *data;
-	struct timer_list timer;
-};
-
 struct sir_fsm {
 	struct semaphore	sem;
-	struct irda_request	rq;
+	struct work_struct      work;
 	unsigned		state, substate;
 	int			param;
 	int			result;
diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c
index ea7c9464d46aecb0506934b8c3fe1fc8cabe1165..3b5854d10c17f348ffb6482c738c4a865a61cc0d 100644
--- a/drivers/net/irda/sir_dev.c
+++ b/drivers/net/irda/sir_dev.c
@@ -23,6 +23,298 @@
 
 #include "sir-dev.h"
 
+
+static struct workqueue_struct *irda_sir_wq;
+
+/* STATE MACHINE */
+
+/* substate handler of the config-fsm to handle the cases where we want
+ * to wait for transmit completion before changing the port configuration
+ */
+
+static int sirdev_tx_complete_fsm(struct sir_dev *dev)
+{
+	struct sir_fsm *fsm = &dev->fsm;
+	unsigned next_state, delay;
+	unsigned bytes_left;
+
+	do {
+		next_state = fsm->substate;	/* default: stay in current substate */
+		delay = 0;
+
+		switch(fsm->substate) {
+
+		case SIRDEV_STATE_WAIT_XMIT:
+			if (dev->drv->chars_in_buffer)
+				bytes_left = dev->drv->chars_in_buffer(dev);
+			else
+				bytes_left = 0;
+			if (!bytes_left) {
+				next_state = SIRDEV_STATE_WAIT_UNTIL_SENT;
+				break;
+			}
+
+			if (dev->speed > 115200)
+				delay = (bytes_left*8*10000) / (dev->speed/100);
+			else if (dev->speed > 0)
+				delay = (bytes_left*10*10000) / (dev->speed/100);
+			else
+				delay = 0;
+			/* expected delay (usec) until remaining bytes are sent */
+			if (delay < 100) {
+				udelay(delay);
+				delay = 0;
+				break;
+			}
+			/* sleep some longer delay (msec) */
+			delay = (delay+999) / 1000;
+			break;
+
+		case SIRDEV_STATE_WAIT_UNTIL_SENT:
+			/* block until underlaying hardware buffer are empty */
+			if (dev->drv->wait_until_sent)
+				dev->drv->wait_until_sent(dev);
+			next_state = SIRDEV_STATE_TX_DONE;
+			break;
+
+		case SIRDEV_STATE_TX_DONE:
+			return 0;
+
+		default:
+			IRDA_ERROR("%s - undefined state\n", __FUNCTION__);
+			return -EINVAL;
+		}
+		fsm->substate = next_state;
+	} while (delay == 0);
+	return delay;
+}
+
+/*
+ * Function sirdev_config_fsm
+ *
+ * State machine to handle the configuration of the device (and attached dongle, if any).
+ * This handler is scheduled for execution in kIrDAd context, so we can sleep.
+ * however, kIrDAd is shared by all sir_dev devices so we better don't sleep there too
+ * long. Instead, for longer delays we start a timer to reschedule us later.
+ * On entry, fsm->sem is always locked and the netdev xmit queue stopped.
+ * Both must be unlocked/restarted on completion - but only on final exit.
+ */
+
+static void sirdev_config_fsm(void *data)
+{
+	struct sir_dev *dev = data;
+	struct sir_fsm *fsm = &dev->fsm;
+	int next_state;
+	int ret = -1;
+	unsigned delay;
+
+	IRDA_DEBUG(2, "%s(), <%ld>\n", __FUNCTION__, jiffies);
+
+	do {
+		IRDA_DEBUG(3, "%s - state=0x%04x / substate=0x%04x\n",
+			__FUNCTION__, fsm->state, fsm->substate);
+
+		next_state = fsm->state;
+		delay = 0;
+
+		switch(fsm->state) {
+
+		case SIRDEV_STATE_DONGLE_OPEN:
+			if (dev->dongle_drv != NULL) {
+				ret = sirdev_put_dongle(dev);
+				if (ret) {
+					fsm->result = -EINVAL;
+					next_state = SIRDEV_STATE_ERROR;
+					break;
+				}
+			}
+
+			/* Initialize dongle */
+			ret = sirdev_get_dongle(dev, fsm->param);
+			if (ret) {
+				fsm->result = ret;
+				next_state = SIRDEV_STATE_ERROR;
+				break;
+			}
+
+			/* Dongles are powered through the modem control lines which
+			 * were just set during open. Before resetting, let's wait for
+			 * the power to stabilize. This is what some dongle drivers did
+			 * in open before, while others didn't - should be safe anyway.
+			 */
+
+			delay = 50;
+			fsm->substate = SIRDEV_STATE_DONGLE_RESET;
+			next_state = SIRDEV_STATE_DONGLE_RESET;
+
+			fsm->param = 9600;
+
+			break;
+
+		case SIRDEV_STATE_DONGLE_CLOSE:
+			/* shouldn't we just treat this as success=? */
+			if (dev->dongle_drv == NULL) {
+				fsm->result = -EINVAL;
+				next_state = SIRDEV_STATE_ERROR;
+				break;
+			}
+
+			ret = sirdev_put_dongle(dev);
+			if (ret) {
+				fsm->result = ret;
+				next_state = SIRDEV_STATE_ERROR;
+				break;
+			}
+			next_state = SIRDEV_STATE_DONE;
+			break;
+
+		case SIRDEV_STATE_SET_DTR_RTS:
+			ret = sirdev_set_dtr_rts(dev,
+				(fsm->param&0x02) ? TRUE : FALSE,
+				(fsm->param&0x01) ? TRUE : FALSE);
+			next_state = SIRDEV_STATE_DONE;
+			break;
+
+		case SIRDEV_STATE_SET_SPEED:
+			fsm->substate = SIRDEV_STATE_WAIT_XMIT;
+			next_state = SIRDEV_STATE_DONGLE_CHECK;
+			break;
+
+		case SIRDEV_STATE_DONGLE_CHECK:
+			ret = sirdev_tx_complete_fsm(dev);
+			if (ret < 0) {
+				fsm->result = ret;
+				next_state = SIRDEV_STATE_ERROR;
+				break;
+			}
+			if ((delay=ret) != 0)
+				break;
+
+			if (dev->dongle_drv) {
+				fsm->substate = SIRDEV_STATE_DONGLE_RESET;
+				next_state = SIRDEV_STATE_DONGLE_RESET;
+			}
+			else {
+				dev->speed = fsm->param;
+				next_state = SIRDEV_STATE_PORT_SPEED;
+			}
+			break;
+
+		case SIRDEV_STATE_DONGLE_RESET:
+			if (dev->dongle_drv->reset) {
+				ret = dev->dongle_drv->reset(dev);
+				if (ret < 0) {
+					fsm->result = ret;
+					next_state = SIRDEV_STATE_ERROR;
+					break;
+				}
+			}
+			else
+				ret = 0;
+			if ((delay=ret) == 0) {
+				/* set serial port according to dongle default speed */
+				if (dev->drv->set_speed)
+					dev->drv->set_speed(dev, dev->speed);
+				fsm->substate = SIRDEV_STATE_DONGLE_SPEED;
+				next_state = SIRDEV_STATE_DONGLE_SPEED;
+			}
+			break;
+
+		case SIRDEV_STATE_DONGLE_SPEED:
+			if (dev->dongle_drv->reset) {
+				ret = dev->dongle_drv->set_speed(dev, fsm->param);
+				if (ret < 0) {
+					fsm->result = ret;
+					next_state = SIRDEV_STATE_ERROR;
+					break;
+				}
+			}
+			else
+				ret = 0;
+			if ((delay=ret) == 0)
+				next_state = SIRDEV_STATE_PORT_SPEED;
+			break;
+
+		case SIRDEV_STATE_PORT_SPEED:
+			/* Finally we are ready to change the serial port speed */
+			if (dev->drv->set_speed)
+				dev->drv->set_speed(dev, dev->speed);
+			dev->new_speed = 0;
+			next_state = SIRDEV_STATE_DONE;
+			break;
+
+		case SIRDEV_STATE_DONE:
+			/* Signal network layer so it can send more frames */
+			netif_wake_queue(dev->netdev);
+			next_state = SIRDEV_STATE_COMPLETE;
+			break;
+
+		default:
+			IRDA_ERROR("%s - undefined state\n", __FUNCTION__);
+			fsm->result = -EINVAL;
+			/* fall thru */
+
+		case SIRDEV_STATE_ERROR:
+			IRDA_ERROR("%s - error: %d\n", __FUNCTION__, fsm->result);
+
+#if 0	/* don't enable this before we have netdev->tx_timeout to recover */
+			netif_stop_queue(dev->netdev);
+#else
+			netif_wake_queue(dev->netdev);
+#endif
+			/* fall thru */
+
+		case SIRDEV_STATE_COMPLETE:
+			/* config change finished, so we are not busy any longer */
+			sirdev_enable_rx(dev);
+			up(&fsm->sem);
+			return;
+		}
+		fsm->state = next_state;
+	} while(!delay);
+
+	queue_delayed_work(irda_sir_wq, &fsm->work, msecs_to_jiffies(delay));
+}
+
+/* schedule some device configuration task for execution by kIrDAd
+ * on behalf of the above state machine.
+ * can be called from process or interrupt/tasklet context.
+ */
+
+int sirdev_schedule_request(struct sir_dev *dev, int initial_state, unsigned param)
+{
+	struct sir_fsm *fsm = &dev->fsm;
+
+	IRDA_DEBUG(2, "%s - state=0x%04x / param=%u\n", __FUNCTION__, initial_state, param);
+
+	if (down_trylock(&fsm->sem)) {
+		if (in_interrupt()  ||  in_atomic()  ||  irqs_disabled()) {
+			IRDA_DEBUG(1, "%s(), state machine busy!\n", __FUNCTION__);
+			return -EWOULDBLOCK;
+		} else
+			down(&fsm->sem);
+	}
+
+	if (fsm->state == SIRDEV_STATE_DEAD) {
+		/* race with sirdev_close should never happen */
+		IRDA_ERROR("%s(), instance staled!\n", __FUNCTION__);
+		up(&fsm->sem);
+		return -ESTALE;		/* or better EPIPE? */
+	}
+
+	netif_stop_queue(dev->netdev);
+	atomic_set(&dev->enable_rx, 0);
+
+	fsm->state = initial_state;
+	fsm->param = param;
+	fsm->result = 0;
+
+	INIT_WORK(&fsm->work, sirdev_config_fsm, dev);
+	queue_work(irda_sir_wq, &fsm->work);
+	return 0;
+}
+
+
 /***************************************************************************/
 
 void sirdev_enable_rx(struct sir_dev *dev)
@@ -619,10 +911,6 @@ struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *n
 	spin_lock_init(&dev->tx_lock);
 	init_MUTEX(&dev->fsm.sem);
 
-	INIT_LIST_HEAD(&dev->fsm.rq.lh_request);
-	dev->fsm.rq.pending = 0;
-	init_timer(&dev->fsm.rq.timer);
-
 	dev->drv = drv;
 	dev->netdev = ndev;
 
@@ -682,3 +970,22 @@ int sirdev_put_instance(struct sir_dev *dev)
 }
 EXPORT_SYMBOL(sirdev_put_instance);
 
+static int __init sir_wq_init(void)
+{
+	irda_sir_wq = create_singlethread_workqueue("irda_sir_wq");
+	if (!irda_sir_wq)
+		return -ENOMEM;
+	return 0;
+}
+
+static void __exit sir_wq_exit(void)
+{
+	destroy_workqueue(irda_sir_wq);
+}
+
+module_init(sir_wq_init);
+module_exit(sir_wq_exit);
+
+MODULE_AUTHOR("Martin Diehl <info@mdiehl.de>");
+MODULE_DESCRIPTION("IrDA SIR core");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/irda/sir_kthread.c b/drivers/net/irda/sir_kthread.c
deleted file mode 100644
index e3904d6bfecd53d258cddcd60c28f7a9f890233b..0000000000000000000000000000000000000000
--- a/drivers/net/irda/sir_kthread.c
+++ /dev/null
@@ -1,508 +0,0 @@
-/*********************************************************************
- *
- *	sir_kthread.c:		dedicated thread to process scheduled
- *				sir device setup requests
- *
- *	Copyright (c) 2002 Martin Diehl
- *
- *	This program is free software; you can redistribute it and/or 
- *	modify it under the terms of the GNU General Public License as 
- *	published by the Free Software Foundation; either version 2 of 
- *	the License, or (at your option) any later version.
- *
- ********************************************************************/    
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/version.h>
-#include <linux/init.h>
-#include <linux/smp_lock.h>
-#include <linux/completion.h>
-#include <linux/delay.h>
-
-#include <net/irda/irda.h>
-
-#include "sir-dev.h"
-
-/**************************************************************************
- *
- * kIrDAd kernel thread and config state machine
- *
- */
-
-struct irda_request_queue {
-	struct list_head request_list;
-	spinlock_t lock;
-	task_t *thread;
-	struct completion exit;
-	wait_queue_head_t kick, done;
-	atomic_t num_pending;
-};
-
-static struct irda_request_queue irda_rq_queue;
-
-static int irda_queue_request(struct irda_request *rq)
-{
-	int ret = 0;
-	unsigned long flags;
-
-	if (!test_and_set_bit(0, &rq->pending)) {
-		spin_lock_irqsave(&irda_rq_queue.lock, flags);
-		list_add_tail(&rq->lh_request, &irda_rq_queue.request_list);
-		wake_up(&irda_rq_queue.kick);
-		atomic_inc(&irda_rq_queue.num_pending);
-		spin_unlock_irqrestore(&irda_rq_queue.lock, flags);
-		ret = 1;
-	}
-	return ret;
-}
-
-static void irda_request_timer(unsigned long data)
-{
-	struct irda_request *rq = (struct irda_request *)data;
-	unsigned long flags;
-	
-	spin_lock_irqsave(&irda_rq_queue.lock, flags);
-	list_add_tail(&rq->lh_request, &irda_rq_queue.request_list);
-	wake_up(&irda_rq_queue.kick);
-	spin_unlock_irqrestore(&irda_rq_queue.lock, flags);
-}
-
-static int irda_queue_delayed_request(struct irda_request *rq, unsigned long delay)
-{
-	int ret = 0;
-	struct timer_list *timer = &rq->timer;
-
-	if (!test_and_set_bit(0, &rq->pending)) {
-		timer->expires = jiffies + delay;
-		timer->function = irda_request_timer;
-		timer->data = (unsigned long)rq;
-		atomic_inc(&irda_rq_queue.num_pending);
-		add_timer(timer);
-		ret = 1;
-	}
-	return ret;
-}
-
-static void run_irda_queue(void)
-{
-	unsigned long flags;
-	struct list_head *entry, *tmp;
-	struct irda_request *rq;
-
-	spin_lock_irqsave(&irda_rq_queue.lock, flags);
-	list_for_each_safe(entry, tmp, &irda_rq_queue.request_list) {
-		rq = list_entry(entry, struct irda_request, lh_request);
-		list_del_init(entry);
-		spin_unlock_irqrestore(&irda_rq_queue.lock, flags);
-
-		clear_bit(0, &rq->pending);
-		rq->func(rq->data);
-
-		if (atomic_dec_and_test(&irda_rq_queue.num_pending))
-			wake_up(&irda_rq_queue.done);
-
-		spin_lock_irqsave(&irda_rq_queue.lock, flags);
-	}
-	spin_unlock_irqrestore(&irda_rq_queue.lock, flags);
-}		
-
-static int irda_thread(void *startup)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
-	daemonize("kIrDAd");
-
-	irda_rq_queue.thread = current;
-
-	complete((struct completion *)startup);
-
-	while (irda_rq_queue.thread != NULL) {
-
-		/* We use TASK_INTERRUPTIBLE, rather than
-		 * TASK_UNINTERRUPTIBLE.  Andrew Morton made this
-		 * change ; he told me that it is safe, because "signal
-		 * blocking is now handled in daemonize()", he added
-		 * that the problem is that "uninterruptible sleep
-		 * contributes to load average", making user worry.
-		 * Jean II */
-		set_task_state(current, TASK_INTERRUPTIBLE);
-		add_wait_queue(&irda_rq_queue.kick, &wait);
-		if (list_empty(&irda_rq_queue.request_list))
-			schedule();
-		else
-			__set_task_state(current, TASK_RUNNING);
-		remove_wait_queue(&irda_rq_queue.kick, &wait);
-
-		/* make swsusp happy with our thread */
-		try_to_freeze();
-
-		run_irda_queue();
-	}
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,35)
-	reparent_to_init();
-#endif
-	complete_and_exit(&irda_rq_queue.exit, 0);
-	/* never reached */
-	return 0;
-}
-
-
-static void flush_irda_queue(void)
-{
-	if (atomic_read(&irda_rq_queue.num_pending)) {
-
-		DECLARE_WAITQUEUE(wait, current);
-
-		if (!list_empty(&irda_rq_queue.request_list))
-			run_irda_queue();
-
-		set_task_state(current, TASK_UNINTERRUPTIBLE);
-		add_wait_queue(&irda_rq_queue.done, &wait);
-		if (atomic_read(&irda_rq_queue.num_pending))
-			schedule();
-		else
-			__set_task_state(current, TASK_RUNNING);
-		remove_wait_queue(&irda_rq_queue.done, &wait);
-	}
-}
-
-/* substate handler of the config-fsm to handle the cases where we want
- * to wait for transmit completion before changing the port configuration
- */
-
-static int irda_tx_complete_fsm(struct sir_dev *dev)
-{
-	struct sir_fsm *fsm = &dev->fsm;
-	unsigned next_state, delay;
-	unsigned bytes_left;
-
-	do {
-		next_state = fsm->substate;	/* default: stay in current substate */
-		delay = 0;
-
-		switch(fsm->substate) {
-
-		case SIRDEV_STATE_WAIT_XMIT:
-			if (dev->drv->chars_in_buffer)
-				bytes_left = dev->drv->chars_in_buffer(dev);
-			else
-				bytes_left = 0;
-			if (!bytes_left) {
-				next_state = SIRDEV_STATE_WAIT_UNTIL_SENT;
-				break;
-			}
-
-			if (dev->speed > 115200)
-				delay = (bytes_left*8*10000) / (dev->speed/100);
-			else if (dev->speed > 0)
-				delay = (bytes_left*10*10000) / (dev->speed/100);
-			else
-				delay = 0;
-			/* expected delay (usec) until remaining bytes are sent */
-			if (delay < 100) {
-				udelay(delay);
-				delay = 0;
-				break;
-			}
-			/* sleep some longer delay (msec) */
-			delay = (delay+999) / 1000;
-			break;
-
-		case SIRDEV_STATE_WAIT_UNTIL_SENT:
-			/* block until underlaying hardware buffer are empty */
-			if (dev->drv->wait_until_sent)
-				dev->drv->wait_until_sent(dev);
-			next_state = SIRDEV_STATE_TX_DONE;
-			break;
-
-		case SIRDEV_STATE_TX_DONE:
-			return 0;
-
-		default:
-			IRDA_ERROR("%s - undefined state\n", __FUNCTION__);
-			return -EINVAL;
-		}
-		fsm->substate = next_state;
-	} while (delay == 0);
-	return delay;
-}
-
-/*
- * Function irda_config_fsm
- *
- * State machine to handle the configuration of the device (and attached dongle, if any).
- * This handler is scheduled for execution in kIrDAd context, so we can sleep.
- * however, kIrDAd is shared by all sir_dev devices so we better don't sleep there too
- * long. Instead, for longer delays we start a timer to reschedule us later.
- * On entry, fsm->sem is always locked and the netdev xmit queue stopped.
- * Both must be unlocked/restarted on completion - but only on final exit.
- */
-
-static void irda_config_fsm(void *data)
-{
-	struct sir_dev *dev = data;
-	struct sir_fsm *fsm = &dev->fsm;
-	int next_state;
-	int ret = -1;
-	unsigned delay;
-
-	IRDA_DEBUG(2, "%s(), <%ld>\n", __FUNCTION__, jiffies); 
-
-	do {
-		IRDA_DEBUG(3, "%s - state=0x%04x / substate=0x%04x\n",
-			__FUNCTION__, fsm->state, fsm->substate);
-
-		next_state = fsm->state;
-		delay = 0;
-
-		switch(fsm->state) {
-
-		case SIRDEV_STATE_DONGLE_OPEN:
-			if (dev->dongle_drv != NULL) {
-				ret = sirdev_put_dongle(dev);
-				if (ret) {
-					fsm->result = -EINVAL;
-					next_state = SIRDEV_STATE_ERROR;
-					break;
-				}
-			}
-
-			/* Initialize dongle */
-			ret = sirdev_get_dongle(dev, fsm->param);
-			if (ret) {
-				fsm->result = ret;
-				next_state = SIRDEV_STATE_ERROR;
-				break;
-			}
-
-			/* Dongles are powered through the modem control lines which
-			 * were just set during open. Before resetting, let's wait for
-			 * the power to stabilize. This is what some dongle drivers did
-			 * in open before, while others didn't - should be safe anyway.
-			 */
-
-			delay = 50;
-			fsm->substate = SIRDEV_STATE_DONGLE_RESET;
-			next_state = SIRDEV_STATE_DONGLE_RESET;
-
-			fsm->param = 9600;
-
-			break;
-
-		case SIRDEV_STATE_DONGLE_CLOSE:
-			/* shouldn't we just treat this as success=? */
-			if (dev->dongle_drv == NULL) {
-				fsm->result = -EINVAL;
-				next_state = SIRDEV_STATE_ERROR;
-				break;
-			}
-
-			ret = sirdev_put_dongle(dev);
-			if (ret) {
-				fsm->result = ret;
-				next_state = SIRDEV_STATE_ERROR;
-				break;
-			}
-			next_state = SIRDEV_STATE_DONE;
-			break;
-
-		case SIRDEV_STATE_SET_DTR_RTS:
-			ret = sirdev_set_dtr_rts(dev,
-				(fsm->param&0x02) ? TRUE : FALSE,
-				(fsm->param&0x01) ? TRUE : FALSE);
-			next_state = SIRDEV_STATE_DONE;
-			break;
-
-		case SIRDEV_STATE_SET_SPEED:
-			fsm->substate = SIRDEV_STATE_WAIT_XMIT;
-			next_state = SIRDEV_STATE_DONGLE_CHECK;
-			break;
-
-		case SIRDEV_STATE_DONGLE_CHECK:
-			ret = irda_tx_complete_fsm(dev);
-			if (ret < 0) {
-				fsm->result = ret;
-				next_state = SIRDEV_STATE_ERROR;
-				break;
-			}
-			if ((delay=ret) != 0)
-				break;
-
-			if (dev->dongle_drv) {
-				fsm->substate = SIRDEV_STATE_DONGLE_RESET;
-				next_state = SIRDEV_STATE_DONGLE_RESET;
-			}
-			else {
-				dev->speed = fsm->param;
-				next_state = SIRDEV_STATE_PORT_SPEED;
-			}
-			break;
-
-		case SIRDEV_STATE_DONGLE_RESET:
-			if (dev->dongle_drv->reset) {
-				ret = dev->dongle_drv->reset(dev);	
-				if (ret < 0) {
-					fsm->result = ret;
-					next_state = SIRDEV_STATE_ERROR;
-					break;
-				}
-			}
-			else
-				ret = 0;
-			if ((delay=ret) == 0) {
-				/* set serial port according to dongle default speed */
-				if (dev->drv->set_speed)
-					dev->drv->set_speed(dev, dev->speed);
-				fsm->substate = SIRDEV_STATE_DONGLE_SPEED;
-				next_state = SIRDEV_STATE_DONGLE_SPEED;
-			}
-			break;
-
-		case SIRDEV_STATE_DONGLE_SPEED:				
-			if (dev->dongle_drv->reset) {
-				ret = dev->dongle_drv->set_speed(dev, fsm->param);
-				if (ret < 0) {
-					fsm->result = ret;
-					next_state = SIRDEV_STATE_ERROR;
-					break;
-				}
-			}
-			else
-				ret = 0;
-			if ((delay=ret) == 0)
-				next_state = SIRDEV_STATE_PORT_SPEED;
-			break;
-
-		case SIRDEV_STATE_PORT_SPEED:
-			/* Finally we are ready to change the serial port speed */
-			if (dev->drv->set_speed)
-				dev->drv->set_speed(dev, dev->speed);
-			dev->new_speed = 0;
-			next_state = SIRDEV_STATE_DONE;
-			break;
-
-		case SIRDEV_STATE_DONE:
-			/* Signal network layer so it can send more frames */
-			netif_wake_queue(dev->netdev);
-			next_state = SIRDEV_STATE_COMPLETE;
-			break;
-
-		default:
-			IRDA_ERROR("%s - undefined state\n", __FUNCTION__);
-			fsm->result = -EINVAL;
-			/* fall thru */
-
-		case SIRDEV_STATE_ERROR:
-			IRDA_ERROR("%s - error: %d\n", __FUNCTION__, fsm->result);
-
-#if 0	/* don't enable this before we have netdev->tx_timeout to recover */
-			netif_stop_queue(dev->netdev);
-#else
-			netif_wake_queue(dev->netdev);
-#endif
-			/* fall thru */
-
-		case SIRDEV_STATE_COMPLETE:
-			/* config change finished, so we are not busy any longer */
-			sirdev_enable_rx(dev);
-			up(&fsm->sem);
-			return;
-		}
-		fsm->state = next_state;
-	} while(!delay);
-
-	irda_queue_delayed_request(&fsm->rq, msecs_to_jiffies(delay));
-}
-
-/* schedule some device configuration task for execution by kIrDAd
- * on behalf of the above state machine.
- * can be called from process or interrupt/tasklet context.
- */
-
-int sirdev_schedule_request(struct sir_dev *dev, int initial_state, unsigned param)
-{
-	struct sir_fsm *fsm = &dev->fsm;
-	int xmit_was_down;
-
-	IRDA_DEBUG(2, "%s - state=0x%04x / param=%u\n", __FUNCTION__, initial_state, param);
-
-	if (down_trylock(&fsm->sem)) {
-		if (in_interrupt()  ||  in_atomic()  ||  irqs_disabled()) {
-			IRDA_DEBUG(1, "%s(), state machine busy!\n", __FUNCTION__);
-			return -EWOULDBLOCK;
-		} else
-			down(&fsm->sem);
-	}
-
-	if (fsm->state == SIRDEV_STATE_DEAD) {
-		/* race with sirdev_close should never happen */
-		IRDA_ERROR("%s(), instance staled!\n", __FUNCTION__);
-		up(&fsm->sem);
-		return -ESTALE;		/* or better EPIPE? */
-	}
-
-	xmit_was_down = netif_queue_stopped(dev->netdev);
-	netif_stop_queue(dev->netdev);
-	atomic_set(&dev->enable_rx, 0);
-
-	fsm->state = initial_state;
-	fsm->param = param;
-	fsm->result = 0;
-
-	INIT_LIST_HEAD(&fsm->rq.lh_request);
-	fsm->rq.pending = 0;
-	fsm->rq.func = irda_config_fsm;
-	fsm->rq.data = dev;
-
-	if (!irda_queue_request(&fsm->rq)) {	/* returns 0 on error! */
-		atomic_set(&dev->enable_rx, 1);
-		if (!xmit_was_down)
-			netif_wake_queue(dev->netdev);		
-		up(&fsm->sem);
-		return -EAGAIN;
-	}
-	return 0;
-}
-
-static int __init irda_thread_create(void)
-{
-	struct completion startup;
-	int pid;
-
-	spin_lock_init(&irda_rq_queue.lock);
-	irda_rq_queue.thread = NULL;
-	INIT_LIST_HEAD(&irda_rq_queue.request_list);
-	init_waitqueue_head(&irda_rq_queue.kick);
-	init_waitqueue_head(&irda_rq_queue.done);
-	atomic_set(&irda_rq_queue.num_pending, 0);
-
-	init_completion(&startup);
-	pid = kernel_thread(irda_thread, &startup, CLONE_FS|CLONE_FILES);
-	if (pid <= 0)
-		return -EAGAIN;
-	else
-		wait_for_completion(&startup);
-
-	return 0;
-}
-
-static void __exit irda_thread_join(void)
-{
-	if (irda_rq_queue.thread) {
-		flush_irda_queue();
-		init_completion(&irda_rq_queue.exit);
-		irda_rq_queue.thread = NULL;
-		wake_up(&irda_rq_queue.kick);		
-		wait_for_completion(&irda_rq_queue.exit);
-	}
-}
-
-module_init(irda_thread_create);
-module_exit(irda_thread_join);
-
-MODULE_AUTHOR("Martin Diehl <info@mdiehl.de>");
-MODULE_DESCRIPTION("IrDA SIR core");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index 58f76cefbc8394c0a82fb33eaa8119a7c7480e00..a4674044bd6f3c536b7abf195c7d4b480268ec97 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -54,6 +54,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/serial_reg.h>
 #include <linux/dma-mapping.h>
+#include <linux/pnp.h>
 #include <linux/platform_device.h>
 
 #include <asm/io.h>
@@ -358,6 +359,16 @@ static inline void register_bank(int iobase, int bank)
                iobase + IRCC_MASTER);
 }
 
+#ifdef	CONFIG_PNP
+/* PNP hotplug support */
+static const struct pnp_device_id smsc_ircc_pnp_table[] = {
+	{ .id = "SMCf010", .driver_data = 0 },
+	/* and presumably others */
+	{ }
+};
+MODULE_DEVICE_TABLE(pnp, smsc_ircc_pnp_table);
+#endif
+
 
 /*******************************************************************************
  *
@@ -2072,7 +2083,8 @@ static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self)
 
 /* PROBING
  *
- *
+ * REVISIT we can be told about the device by PNP, and should use that info
+ * instead of probing hardware and creating a platform_device ...
  */
 
 static int __init smsc_ircc_look_for_chips(void)
diff --git a/drivers/net/ixp2000/enp2611.c b/drivers/net/ixp2000/enp2611.c
index 6f7dce8eba51c329dd7412334823131749ab6ac8..b67f586d7392ab199e29181517d18af00cc9a8e1 100644
--- a/drivers/net/ixp2000/enp2611.c
+++ b/drivers/net/ixp2000/enp2611.c
@@ -149,6 +149,8 @@ static void enp2611_check_link_status(unsigned long __dummy)
 		int status;
 
 		dev = nds[i];
+		if (dev == NULL)
+			continue;
 
 		status = pm3386_is_link_up(i);
 		if (status && !netif_carrier_ok(dev)) {
@@ -191,6 +193,7 @@ static void enp2611_set_port_admin_status(int port, int up)
 
 static int __init enp2611_init_module(void)
 { 
+	int ports;
 	int i;
 
 	if (!machine_is_enp2611())
@@ -199,7 +202,8 @@ static int __init enp2611_init_module(void)
 	caleb_reset();
 	pm3386_reset();
 
-	for (i = 0; i < 3; i++) {
+	ports = pm3386_port_count();
+	for (i = 0; i < ports; i++) {
 		nds[i] = ixpdev_alloc(i, sizeof(struct enp2611_ixpdev_priv));
 		if (nds[i] == NULL) {
 			while (--i >= 0)
@@ -215,9 +219,10 @@ static int __init enp2611_init_module(void)
 
 	ixp2400_msf_init(&enp2611_msf_parameters);
 
-	if (ixpdev_init(3, nds, enp2611_set_port_admin_status)) {
-		for (i = 0; i < 3; i++)
-			free_netdev(nds[i]);
+	if (ixpdev_init(ports, nds, enp2611_set_port_admin_status)) {
+		for (i = 0; i < ports; i++)
+			if (nds[i])
+				free_netdev(nds[i]);
 		return -EINVAL;
 	}
 
diff --git a/drivers/net/ixp2000/pm3386.c b/drivers/net/ixp2000/pm3386.c
index 5c7ab7564053af12a291f2be7875329cb6ac6e1d..5224651c9aac30e3ab308286c7d01f93c987ee79 100644
--- a/drivers/net/ixp2000/pm3386.c
+++ b/drivers/net/ixp2000/pm3386.c
@@ -86,40 +86,53 @@ static void pm3386_port_reg_write(int port, int _reg, int spacing, u16 value)
 	pm3386_reg_write(port >> 1, reg, value);
 }
 
+int pm3386_secondary_present(void)
+{
+	return pm3386_reg_read(1, 0) == 0x3386;
+}
 
 void pm3386_reset(void)
 {
 	u8 mac[3][6];
+	int secondary;
+
+	secondary = pm3386_secondary_present();
 
 	/* Save programmed MAC addresses.  */
 	pm3386_get_mac(0, mac[0]);
 	pm3386_get_mac(1, mac[1]);
-	pm3386_get_mac(2, mac[2]);
+	if (secondary)
+		pm3386_get_mac(2, mac[2]);
 
 	/* Assert analog and digital reset.  */
 	pm3386_reg_write(0, 0x002, 0x0060);
-	pm3386_reg_write(1, 0x002, 0x0060);
+	if (secondary)
+		pm3386_reg_write(1, 0x002, 0x0060);
 	mdelay(1);
 
 	/* Deassert analog reset.  */
 	pm3386_reg_write(0, 0x002, 0x0062);
-	pm3386_reg_write(1, 0x002, 0x0062);
+	if (secondary)
+		pm3386_reg_write(1, 0x002, 0x0062);
 	mdelay(10);
 
 	/* Deassert digital reset.  */
 	pm3386_reg_write(0, 0x002, 0x0063);
-	pm3386_reg_write(1, 0x002, 0x0063);
+	if (secondary)
+		pm3386_reg_write(1, 0x002, 0x0063);
 	mdelay(10);
 
 	/* Restore programmed MAC addresses.  */
 	pm3386_set_mac(0, mac[0]);
 	pm3386_set_mac(1, mac[1]);
-	pm3386_set_mac(2, mac[2]);
+	if (secondary)
+		pm3386_set_mac(2, mac[2]);
 
 	/* Disable carrier on all ports.  */
 	pm3386_set_carrier(0, 0);
 	pm3386_set_carrier(1, 0);
-	pm3386_set_carrier(2, 0);
+	if (secondary)
+		pm3386_set_carrier(2, 0);
 }
 
 static u16 swaph(u16 x)
@@ -127,6 +140,11 @@ static u16 swaph(u16 x)
 	return ((x << 8) | (x >> 8)) & 0xffff;
 }
 
+int pm3386_port_count(void)
+{
+	return 2 + pm3386_secondary_present();
+}
+
 void pm3386_init_port(int port)
 {
 	int pm = port >> 1;
diff --git a/drivers/net/ixp2000/pm3386.h b/drivers/net/ixp2000/pm3386.h
index fe92bb056ac424c9279ca8501016d2f3452187c3..cc4183dca9116959be453b1354065719c850fe4a 100644
--- a/drivers/net/ixp2000/pm3386.h
+++ b/drivers/net/ixp2000/pm3386.h
@@ -13,6 +13,7 @@
 #define __PM3386_H
 
 void pm3386_reset(void);
+int pm3386_port_count(void);
 void pm3386_init_port(int port);
 void pm3386_get_mac(int port, u8 *mac);
 void pm3386_set_mac(int port, u8 *mac);
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index 93c494bcd18d67beaf035473f37a77dd7c45171b..b32765215f75c12d983df36349d4f6acbe4e453f 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -139,8 +139,9 @@ bad_clone_list[] __initdata = {
 
 #if defined(CONFIG_PLAT_MAPPI)
 #  define DCR_VAL 0x4b
-#elif defined(CONFIG_PLAT_OAKS32R)
-#  define DCR_VAL 0x48
+#elif defined(CONFIG_PLAT_OAKS32R)  || \
+   defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
+#  define DCR_VAL 0x48		/* 8-bit mode */
 #else
 #  define DCR_VAL 0x49
 #endif
@@ -396,10 +397,22 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
 		/* We must set the 8390 for word mode. */
 		outb_p(DCR_VAL, ioaddr + EN0_DCFG);
 		start_page = NESM_START_PG;
-		stop_page = NESM_STOP_PG;
+
+		/*
+		 * Realtek RTL8019AS datasheet says that the PSTOP register
+		 * shouldn't exceed 0x60 in 8-bit mode.
+		 * This chip can be identified by reading the signature from
+		 * the  remote byte count registers (otherwise write-only)...
+		 */
+		if ((DCR_VAL & 0x01) == 0 &&		/* 8-bit mode */
+		    inb(ioaddr + EN0_RCNTLO) == 0x50 &&
+		    inb(ioaddr + EN0_RCNTHI) == 0x70)
+			stop_page = 0x60;
+		else
+			stop_page = NESM_STOP_PG;
 	} else {
 		start_page = NE1SM_START_PG;
-		stop_page = NE1SM_STOP_PG;
+		stop_page  = NE1SM_STOP_PG;
 	}
 
 #if  defined(CONFIG_PLAT_MAPPI) || defined(CONFIG_PLAT_OAKS32R)
@@ -509,15 +522,9 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
 	ei_status.name = name;
 	ei_status.tx_start_page = start_page;
 	ei_status.stop_page = stop_page;
-#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
-	wordlength = 1;
-#endif
 
-#ifdef CONFIG_PLAT_OAKS32R
-	ei_status.word16 = 0;
-#else
-	ei_status.word16 = (wordlength == 2);
-#endif
+	/* Use 16-bit mode only if this wasn't overridden by DCR_VAL */
+	ei_status.word16 = (wordlength == 2 && (DCR_VAL & 0x01));
 
 	ei_status.rx_start_page = start_page + TX_PAGES;
 #ifdef PACKETBUF_MEMSIZE
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 459443b572cef542a6757c1f02443f6ee42cbe7f..1b236bdf6b928d0dafa81c64ddcd3ac679c32e6c 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -60,8 +60,10 @@ int mdiobus_register(struct mii_bus *bus)
 	for (i = 0; i < PHY_MAX_ADDR; i++) {
 		struct phy_device *phydev;
 
-		if (bus->phy_mask & (1 << i))
+		if (bus->phy_mask & (1 << i)) {
+			bus->phy_map[i] = NULL;
 			continue;
+		}
 
 		phydev = get_phy_device(bus, i);
 
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 3b3e1046d0a47077a4a5c9b98dde97c13a369d23..d058741722091c3555f1b3cf0f399c0a67b83a6e 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -128,6 +128,7 @@ static const struct mii_chip_info {
 } mii_chip_table[] = {
 	{ "SiS 900 Internal MII PHY", 		0x001d, 0x8000, LAN },
 	{ "SiS 7014 Physical Layer Solution", 	0x0016, 0xf830, LAN },
+	{ "SiS 900 on Foxconn 661 7MI",         0x0143, 0xBC70, LAN },
 	{ "Altimata AC101LF PHY",               0x0022, 0x5520, LAN },
 	{ "ADM 7001 LAN PHY",			0x002e, 0xcc60, LAN },
 	{ "AMD 79C901 10BASE-T PHY",  		0x0000, 0x6B70, LAN },
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 227df9876a2c67aa6f53a9e225586a8ac525acb4..62be6d99d05cd3623e1d0df74cff1495adc9b47c 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -51,7 +51,7 @@
 #include "sky2.h"
 
 #define DRV_NAME		"sky2"
-#define DRV_VERSION		"1.2"
+#define DRV_VERSION		"1.3"
 #define PFX			DRV_NAME " "
 
 /*
@@ -79,6 +79,8 @@
 #define NAPI_WEIGHT		64
 #define PHY_RETRIES		1000
 
+#define RING_NEXT(x,s)	(((x)+1) & ((s)-1))
+
 static const u32 default_msg =
     NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK
     | NETIF_MSG_TIMER | NETIF_MSG_TX_ERR | NETIF_MSG_RX_ERR
@@ -96,6 +98,10 @@ static int disable_msi = 0;
 module_param(disable_msi, int, 0);
 MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
 
+static int idle_timeout = 100;
+module_param(idle_timeout, int, 0);
+MODULE_PARM_DESC(idle_timeout, "Idle timeout workaround for lost interrupts (ms)");
+
 static const struct pci_device_id sky2_id_table[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) },
@@ -122,6 +128,7 @@ MODULE_DEVICE_TABLE(pci, sky2_id_table);
 /* Avoid conditionals by using array */
 static const unsigned txqaddr[] = { Q_XA1, Q_XA2 };
 static const unsigned rxqaddr[] = { Q_R1, Q_R2 };
+static const u32 portirq_msk[] = { Y2_IS_PORT_1, Y2_IS_PORT_2 };
 
 /* This driver supports yukon2 chipset only */
 static const char *yukon2_name[] = {
@@ -298,7 +305,8 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
 	struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
 	u16 ctrl, ct1000, adv, pg, ledctrl, ledover;
 
-	if (sky2->autoneg == AUTONEG_ENABLE && hw->chip_id != CHIP_ID_YUKON_XL) {
+	if (sky2->autoneg == AUTONEG_ENABLE &&
+	    (hw->chip_id != CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) {
 		u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
 
 		ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
@@ -326,7 +334,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
 			ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO);
 
 			if (sky2->autoneg == AUTONEG_ENABLE &&
-			    hw->chip_id == CHIP_ID_YUKON_XL) {
+			    (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) {
 				ctrl &= ~PHY_M_PC_DSC_MSK;
 				ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA;
 			}
@@ -442,10 +450,11 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
 		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
 
 		/* set LED Function Control register */
-		gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, (PHY_M_LEDC_LOS_CTRL(1) |	/* LINK/ACT */
-							   PHY_M_LEDC_INIT_CTRL(7) |	/* 10 Mbps */
-							   PHY_M_LEDC_STA1_CTRL(7) |	/* 100 Mbps */
-							   PHY_M_LEDC_STA0_CTRL(7)));	/* 1000 Mbps */
+		gm_phy_write(hw, port, PHY_MARV_PHY_CTRL,
+			     (PHY_M_LEDC_LOS_CTRL(1) |	/* LINK/ACT */
+			      PHY_M_LEDC_INIT_CTRL(7) |	/* 10 Mbps */
+			      PHY_M_LEDC_STA1_CTRL(7) |	/* 100 Mbps */
+			      PHY_M_LEDC_STA0_CTRL(7)));	/* 1000 Mbps */
 
 		/* set Polarity Control register */
 		gm_phy_write(hw, port, PHY_MARV_PHY_STAT,
@@ -459,6 +468,25 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
 		/* restore page register */
 		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
 		break;
+	case CHIP_ID_YUKON_EC_U:
+		pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+
+		/* select page 3 to access LED control register */
+		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
+
+		/* set LED Function Control register */
+		gm_phy_write(hw, port, PHY_MARV_PHY_CTRL,
+			     (PHY_M_LEDC_LOS_CTRL(1) |	/* LINK/ACT */
+			      PHY_M_LEDC_INIT_CTRL(8) |	/* 10 Mbps */
+			      PHY_M_LEDC_STA1_CTRL(7) |	/* 100 Mbps */
+			      PHY_M_LEDC_STA0_CTRL(7)));/* 1000 Mbps */
+
+		/* set Blink Rate in LED Timer Control Register */
+		gm_phy_write(hw, port, PHY_MARV_INT_MASK,
+			     ledctrl | PHY_M_LED_BLINK_RT(BLINK_84MS));
+		/* restore page register */
+		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
+		break;
 
 	default:
 		/* set Tx LED (LED_TX) to blink mode on Rx OR Tx activity */
@@ -467,19 +495,21 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
 		ledover |= PHY_M_LED_MO_RX(MO_LED_OFF);
 	}
 
-	if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev >= 2) {
+	if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev == CHIP_REV_YU_EC_A1) {
 		/* apply fixes in PHY AFE */
-		gm_phy_write(hw, port, 22, 255);
+		pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 255);
+
 		/* increase differential signal amplitude in 10BASE-T */
-		gm_phy_write(hw, port, 24, 0xaa99);
-		gm_phy_write(hw, port, 23, 0x2011);
+		gm_phy_write(hw, port, 0x18, 0xaa99);
+		gm_phy_write(hw, port, 0x17, 0x2011);
 
 		/* fix for IEEE A/B Symmetry failure in 1000BASE-T */
-		gm_phy_write(hw, port, 24, 0xa204);
-		gm_phy_write(hw, port, 23, 0x2002);
+		gm_phy_write(hw, port, 0x18, 0xa204);
+		gm_phy_write(hw, port, 0x17, 0x2002);
 
 		/* set page register to 0 */
-		gm_phy_write(hw, port, 22, 0);
+		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
 	} else {
 		gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
 
@@ -553,6 +583,11 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
 
 		if (sky2->duplex == DUPLEX_FULL)
 			reg |= GM_GPCR_DUP_FULL;
+
+		/* turn off pause in 10/100mbps half duplex */
+		else if (sky2->speed != SPEED_1000 &&
+			 hw->chip_id != CHIP_ID_YUKON_EC_U)
+			sky2->tx_pause = sky2->rx_pause = 0;
 	} else
 		reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL;
 
@@ -719,7 +754,7 @@ static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2)
 {
 	struct sky2_tx_le *le = sky2->tx_le + sky2->tx_prod;
 
-	sky2->tx_prod = (sky2->tx_prod + 1) % TX_RING_SIZE;
+	sky2->tx_prod = RING_NEXT(sky2->tx_prod, TX_RING_SIZE);
 	return le;
 }
 
@@ -735,7 +770,7 @@ static inline void sky2_put_idx(struct sky2_hw *hw, unsigned q, u16 idx)
 static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2)
 {
 	struct sky2_rx_le *le = sky2->rx_le + sky2->rx_put;
-	sky2->rx_put = (sky2->rx_put + 1) % RX_LE_SIZE;
+	sky2->rx_put = RING_NEXT(sky2->rx_put, RX_LE_SIZE);
 	return le;
 }
 
@@ -985,8 +1020,19 @@ static int sky2_up(struct net_device *dev)
 	struct sky2_hw *hw = sky2->hw;
 	unsigned port = sky2->port;
 	u32 ramsize, rxspace, imask;
-	int err = -ENOMEM;
+	int err;
+	struct net_device *otherdev = hw->dev[sky2->port^1];
 
+	/* Block bringing up both ports at the same time on a dual port card.
+	 * There is an unfixed bug where receiver gets confused and picks up
+	 * packets out of order. Until this is fixed, prevent data corruption.
+	 */
+	if (otherdev && netif_running(otherdev)) {
+		printk(KERN_INFO PFX "dual port support is disabled.\n");
+		return -EBUSY;
+	}
+
+	err = -ENOMEM;
 	if (netif_msg_ifup(sky2))
 		printk(KERN_INFO PFX "%s: enabling interface\n", dev->name);
 
@@ -1050,7 +1096,7 @@ static int sky2_up(struct net_device *dev)
 
 	/* Enable interrupts from phy/mac for port */
 	imask = sky2_read32(hw, B0_IMSK);
-	imask |= (port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2;
+	imask |= portirq_msk[port];
 	sky2_write32(hw, B0_IMSK, imask);
 
 	return 0;
@@ -1078,7 +1124,7 @@ err_out:
 /* Modular subtraction in ring */
 static inline int tx_dist(unsigned tail, unsigned head)
 {
-	return (head - tail) % TX_RING_SIZE;
+	return (head - tail) & (TX_RING_SIZE - 1);
 }
 
 /* Number of list elements available for next tx */
@@ -1255,7 +1301,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
 		le->opcode = OP_BUFFER | HW_OWNER;
 
 		fre = sky2->tx_ring
-		    + ((re - sky2->tx_ring) + i + 1) % TX_RING_SIZE;
+		    + RING_NEXT((re - sky2->tx_ring) + i, TX_RING_SIZE);
 		pci_unmap_addr_set(fre, mapaddr, mapping);
 	}
 
@@ -1315,7 +1361,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
 
 		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 			struct tx_ring_info *fre;
-			fre = sky2->tx_ring + (put + i + 1) % TX_RING_SIZE;
+			fre = sky2->tx_ring + RING_NEXT(put + i, TX_RING_SIZE);
 			pci_unmap_page(pdev, pci_unmap_addr(fre, mapaddr),
 				       skb_shinfo(skb)->frags[i].size,
 				       PCI_DMA_TODEVICE);
@@ -1401,7 +1447,7 @@ static int sky2_down(struct net_device *dev)
 
 	/* Disable port IRQ */
 	imask = sky2_read32(hw, B0_IMSK);
-	imask &= ~(sky2->port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2;
+	imask &= ~portirq_msk[port];
 	sky2_write32(hw, B0_IMSK, imask);
 
 	/* turn off LED's */
@@ -1498,17 +1544,26 @@ static void sky2_link_up(struct sky2_port *sky2)
 	sky2_write8(hw, SK_REG(port, LNK_LED_REG),
 		    LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF);
 
-	if (hw->chip_id == CHIP_ID_YUKON_XL) {
+	if (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U) {
 		u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+		u16 led = PHY_M_LEDC_LOS_CTRL(1);	/* link active */
+
+		switch(sky2->speed) {
+		case SPEED_10:
+			led |= PHY_M_LEDC_INIT_CTRL(7);
+			break;
+
+		case SPEED_100:
+			led |= PHY_M_LEDC_STA1_CTRL(7);
+			break;
+
+		case SPEED_1000:
+			led |= PHY_M_LEDC_STA0_CTRL(7);
+			break;
+		}
 
 		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
-		gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, PHY_M_LEDC_LOS_CTRL(1) |	/* LINK/ACT */
-			     PHY_M_LEDC_INIT_CTRL(sky2->speed ==
-						  SPEED_10 ? 7 : 0) |
-			     PHY_M_LEDC_STA1_CTRL(sky2->speed ==
-						  SPEED_100 ? 7 : 0) |
-			     PHY_M_LEDC_STA0_CTRL(sky2->speed ==
-						  SPEED_1000 ? 7 : 0));
+		gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, led);
 		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
 	}
 
@@ -1583,7 +1638,7 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux)
 	sky2->speed = sky2_phy_speed(hw, aux);
 
 	/* Pause bits are offset (9..8) */
-	if (hw->chip_id == CHIP_ID_YUKON_XL)
+	if (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)
 		aux >>= 6;
 
 	sky2->rx_pause = (aux & PHY_M_PS_RX_P_EN) != 0;
@@ -1859,35 +1914,28 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last)
 static int sky2_status_intr(struct sky2_hw *hw, int to_do)
 {
 	int work_done = 0;
+	u16 hwidx = sky2_read16(hw, STAT_PUT_IDX);
 
 	rmb();
 
-	for(;;) {
+	while (hw->st_idx != hwidx) {
 		struct sky2_status_le *le  = hw->st_le + hw->st_idx;
 		struct net_device *dev;
 		struct sky2_port *sky2;
 		struct sk_buff *skb;
 		u32 status;
 		u16 length;
-		u8  link, opcode;
-
-		opcode = le->opcode;
-		if (!opcode)
-			break;
-		opcode &= ~HW_OWNER;
 
-		hw->st_idx = (hw->st_idx + 1) % STATUS_RING_SIZE;
-		le->opcode = 0;
+		hw->st_idx = RING_NEXT(hw->st_idx, STATUS_RING_SIZE);
 
-		link = le->link;
-		BUG_ON(link >= 2);
-		dev = hw->dev[link];
+		BUG_ON(le->link >= 2);
+		dev = hw->dev[le->link];
 
 		sky2 = netdev_priv(dev);
 		length = le->length;
 		status = le->status;
 
-		switch (opcode) {
+		switch (le->opcode & ~HW_OWNER) {
 		case OP_RXSTAT:
 			skb = sky2_receive(sky2, length, status);
 			if (!skb)
@@ -1927,7 +1975,8 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
 
 		case OP_TXINDEXLE:
 			/* TX index reports status for both ports */
-			sky2_tx_done(hw->dev[0], status & 0xffff);
+			BUILD_BUG_ON(TX_RING_SIZE > 0x1000);
+			sky2_tx_done(hw->dev[0], status & 0xfff);
 			if (hw->dev[1])
 				sky2_tx_done(hw->dev[1],
 				     ((status >> 24) & 0xff)
@@ -1937,8 +1986,8 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
 		default:
 			if (net_ratelimit())
 				printk(KERN_WARNING PFX
-				       "unknown status opcode 0x%x\n", opcode);
-			break;
+				       "unknown status opcode 0x%x\n", le->opcode);
+			goto exit_loop;
 		}
 	}
 
@@ -2089,12 +2138,13 @@ static void sky2_descriptor_error(struct sky2_hw *hw, unsigned port,
  */
 static void sky2_idle(unsigned long arg)
 {
-	struct net_device *dev = (struct net_device *) arg;
+	struct sky2_hw *hw = (struct sky2_hw *) arg;
+	struct net_device *dev = hw->dev[0];
 
-	local_irq_disable();
 	if (__netif_rx_schedule_prep(dev))
 		__netif_rx_schedule(dev);
-	local_irq_enable();
+
+	mod_timer(&hw->idle_timer, jiffies + msecs_to_jiffies(idle_timeout));
 }
 
 
@@ -2105,65 +2155,46 @@ static int sky2_poll(struct net_device *dev0, int *budget)
 	int work_done = 0;
 	u32 status = sky2_read32(hw, B0_Y2_SP_EISR);
 
- restart_poll:
-	if (unlikely(status & ~Y2_IS_STAT_BMU)) {
-		if (status & Y2_IS_HW_ERR)
-			sky2_hw_intr(hw);
-
-		if (status & Y2_IS_IRQ_PHY1)
-			sky2_phy_intr(hw, 0);
+	if (status & Y2_IS_HW_ERR)
+		sky2_hw_intr(hw);
 
-		if (status & Y2_IS_IRQ_PHY2)
-			sky2_phy_intr(hw, 1);
+	if (status & Y2_IS_IRQ_PHY1)
+		sky2_phy_intr(hw, 0);
 
-		if (status & Y2_IS_IRQ_MAC1)
-			sky2_mac_intr(hw, 0);
+	if (status & Y2_IS_IRQ_PHY2)
+		sky2_phy_intr(hw, 1);
 
-		if (status & Y2_IS_IRQ_MAC2)
-			sky2_mac_intr(hw, 1);
+	if (status & Y2_IS_IRQ_MAC1)
+		sky2_mac_intr(hw, 0);
 
-		if (status & Y2_IS_CHK_RX1)
-			sky2_descriptor_error(hw, 0, "receive", Y2_IS_CHK_RX1);
+	if (status & Y2_IS_IRQ_MAC2)
+		sky2_mac_intr(hw, 1);
 
-		if (status & Y2_IS_CHK_RX2)
-			sky2_descriptor_error(hw, 1, "receive", Y2_IS_CHK_RX2);
+	if (status & Y2_IS_CHK_RX1)
+		sky2_descriptor_error(hw, 0, "receive", Y2_IS_CHK_RX1);
 
-		if (status & Y2_IS_CHK_TXA1)
-			sky2_descriptor_error(hw, 0, "transmit", Y2_IS_CHK_TXA1);
+	if (status & Y2_IS_CHK_RX2)
+		sky2_descriptor_error(hw, 1, "receive", Y2_IS_CHK_RX2);
 
-		if (status & Y2_IS_CHK_TXA2)
-			sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2);
-	}
-
-	if (status & Y2_IS_STAT_BMU) {
-		work_done += sky2_status_intr(hw, work_limit - work_done);
-		*budget -= work_done;
-		dev0->quota -= work_done;
+	if (status & Y2_IS_CHK_TXA1)
+		sky2_descriptor_error(hw, 0, "transmit", Y2_IS_CHK_TXA1);
 
-		if (work_done >= work_limit)
-			return 1;
+	if (status & Y2_IS_CHK_TXA2)
+		sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2);
 
+	if (status & Y2_IS_STAT_BMU)
 		sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
-	}
 
-	mod_timer(&hw->idle_timer, jiffies + HZ);
+	work_done = sky2_status_intr(hw, work_limit);
+	*budget -= work_done;
+	dev0->quota -= work_done;
 
-	local_irq_disable();
-	__netif_rx_complete(dev0);
+	if (work_done >= work_limit)
+		return 1;
 
-	status = sky2_read32(hw, B0_Y2_SP_LISR);
-
-	if (unlikely(status)) {
-		/* More work pending, try and keep going */
-		if (__netif_rx_schedule_prep(dev0)) {
-			__netif_rx_reschedule(dev0, work_done);
-			status = sky2_read32(hw, B0_Y2_SP_EISR);
-			local_irq_enable();
-			goto restart_poll;
-		}
-	}
+	netif_rx_complete(dev0);
 
-	local_irq_enable();
+	status = sky2_read32(hw, B0_Y2_SP_LISR);
 	return 0;
 }
 
@@ -2244,13 +2275,6 @@ static int __devinit sky2_reset(struct sky2_hw *hw)
 		return -EOPNOTSUPP;
 	}
 
-	/* This chip is new and not tested yet */
-	if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
-		pr_info(PFX "%s: is a version of Yukon 2 chipset that has not been tested yet.\n",
-			pci_name(hw->pdev));
-		pr_info("Please report success/failure to maintainer <shemminger@osdl.org>\n");
-	}
-
 	/* disable ASF */
 	if (hw->chip_id <= CHIP_ID_YUKON_EC) {
 		sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET);
@@ -3302,7 +3326,10 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
 
 	sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
 
-	setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) dev);
+	setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw);
+	if (idle_timeout > 0)
+		mod_timer(&hw->idle_timer,
+			  jiffies + msecs_to_jiffies(idle_timeout));
 
 	pci_set_drvdata(pdev, hw);
 
@@ -3342,6 +3369,8 @@ static void __devexit sky2_remove(struct pci_dev *pdev)
 	del_timer_sync(&hw->idle_timer);
 
 	sky2_write32(hw, B0_IMSK, 0);
+	synchronize_irq(hw->pdev->irq);
+
 	dev0 = hw->dev[0];
 	dev1 = hw->dev[1];
 	if (dev1)
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index b026f5653f049bb9cf9a4b3b43a8efbeae4e7569..8012994c9b93213480ac4734d053abb84efdad9a 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -378,6 +378,9 @@ enum {
 	CHIP_REV_YU_EC_A1    = 0,  /* Chip Rev. for Yukon-EC A1/A0 */
 	CHIP_REV_YU_EC_A2    = 1,  /* Chip Rev. for Yukon-EC A2 */
 	CHIP_REV_YU_EC_A3    = 2,  /* Chip Rev. for Yukon-EC A3 */
+
+	CHIP_REV_YU_EC_U_A0  = 0,
+	CHIP_REV_YU_EC_U_A1  = 1,
 };
 
 /*	B2_Y2_CLK_GATE	 8 bit	Clock Gating (Yukon-2 only) */
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 43f5e86fc55937e8d81d62f263a4e9c6a272ffa3..394339d5e87c0494c300fad7f60eaf9984e8c78f 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -1652,6 +1652,8 @@ spider_net_enable_card(struct spider_net_card *card)
 		{ SPIDER_NET_GFTRESTRT, SPIDER_NET_RESTART_VALUE },
 
 		{ SPIDER_NET_GMRWOLCTRL, 0 },
+		{ SPIDER_NET_GTESTMD, 0x10000000 },
+		{ SPIDER_NET_GTTQMSK, 0x00400040 },
 		{ SPIDER_NET_GTESTMD, 0 },
 
 		{ SPIDER_NET_GMACINTEN, 0 },
@@ -1792,15 +1794,7 @@ spider_net_setup_phy(struct spider_net_card *card)
 	if (phy->def->ops->setup_forced)
 		phy->def->ops->setup_forced(phy, SPEED_1000, DUPLEX_FULL);
 
-	/* the following two writes could be moved to sungem_phy.c */
-	/* enable fiber mode */
-	spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0x9020);
-	/* LEDs active in both modes, autosense prio = fiber */
-	spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0x945f);
-
-	/* switch off fibre autoneg */
-	spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0xfc01);
-	spider_net_write_phy(card->netdev, 1, 0x0b, 0x0004);
+	phy->def->ops->enable_fiber(phy);
 
 	phy->def->ops->read_link(phy);
 	pr_info("Found %s with %i Mbps, %s-duplex.\n", phy->def->name,
diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h
index 5922b529a04866991ed3dfeb875c46396e0962ee..3b8d951cf73c62c641fec8372e8ed9e21b2821c3 100644
--- a/drivers/net/spider_net.h
+++ b/drivers/net/spider_net.h
@@ -120,6 +120,8 @@ extern char spider_net_driver_name[];
 #define SPIDER_NET_GMRUAFILnR		0x00000500
 #define SPIDER_NET_GMRUA0FIL15R		0x00000578
 
+#define SPIDER_NET_GTTQMSK		0x00000934
+
 /* RX DMA controller registers, all 0x00000a.. are for DMA controller A,
  * 0x00000b.. for DMA controller B, etc. */
 #define SPIDER_NET_GDADCHA		0x00000a00
diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c
index 046371ee5bbe25a5d98da69f6ff28612c9dc959d..b2ddd5e793035d3fa12742a7c4b8484662fff7e4 100644
--- a/drivers/net/sungem_phy.c
+++ b/drivers/net/sungem_phy.c
@@ -329,6 +329,30 @@ static int bcm5421_init(struct mii_phy* phy)
 	return 0;
 }
 
+static int bcm5421_enable_fiber(struct mii_phy* phy)
+{
+	/* enable fiber mode */
+	phy_write(phy, MII_NCONFIG, 0x9020);
+	/* LEDs active in both modes, autosense prio = fiber */
+	phy_write(phy, MII_NCONFIG, 0x945f);
+
+	/* switch off fibre autoneg */
+	phy_write(phy, MII_NCONFIG, 0xfc01);
+	phy_write(phy, 0x0b, 0x0004);
+
+	return 0;
+}
+
+static int bcm5461_enable_fiber(struct mii_phy* phy)
+{
+        phy_write(phy, MII_NCONFIG, 0xfc0c);
+        phy_write(phy, MII_BMCR, 0x4140);
+        phy_write(phy, MII_NCONFIG, 0xfc0b);
+	phy_write(phy, MII_BMCR, 0x0140);
+
+	return 0;
+}
+
 static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise)
 {
 	u16 ctl, adv;
@@ -762,6 +786,7 @@ static struct mii_phy_ops bcm5421_phy_ops = {
 	.setup_forced	= bcm54xx_setup_forced,
 	.poll_link	= genmii_poll_link,
 	.read_link	= bcm54xx_read_link,
+	.enable_fiber   = bcm5421_enable_fiber,
 };
 
 static struct mii_phy_def bcm5421_phy_def = {
@@ -792,6 +817,25 @@ static struct mii_phy_def bcm5421k2_phy_def = {
 	.ops		= &bcm5421k2_phy_ops
 };
 
+static struct mii_phy_ops bcm5461_phy_ops = {
+	.init		= bcm5421_init,
+	.suspend	= generic_suspend,
+	.setup_aneg	= bcm54xx_setup_aneg,
+	.setup_forced	= bcm54xx_setup_forced,
+	.poll_link	= genmii_poll_link,
+	.read_link	= bcm54xx_read_link,
+	.enable_fiber   = bcm5461_enable_fiber,
+};
+
+static struct mii_phy_def bcm5461_phy_def = {
+	.phy_id		= 0x002060c0,
+	.phy_id_mask	= 0xfffffff0,
+	.name		= "BCM5461",
+	.features	= MII_GBIT_FEATURES,
+	.magic_aneg	= 1,
+	.ops		= &bcm5461_phy_ops
+};
+
 /* Broadcom BCM 5462 built-in Vesta */
 static struct mii_phy_ops bcm5462V_phy_ops = {
 	.init		= bcm5421_init,
@@ -857,6 +901,7 @@ static struct mii_phy_def* mii_phy_table[] = {
 	&bcm5411_phy_def,
 	&bcm5421_phy_def,
 	&bcm5421k2_phy_def,
+	&bcm5461_phy_def,
 	&bcm5462V_phy_def,
 	&marvell_phy_def,
 	&genmii_phy_def,
diff --git a/drivers/net/sungem_phy.h b/drivers/net/sungem_phy.h
index 430544496c52689502f0e1991a1e17d6e11cd797..69e125197fcf198d477897eba04092ae0bf6f4f8 100644
--- a/drivers/net/sungem_phy.h
+++ b/drivers/net/sungem_phy.h
@@ -12,6 +12,7 @@ struct mii_phy_ops
 	int		(*setup_forced)(struct mii_phy *phy, int speed, int fd);
 	int		(*poll_link)(struct mii_phy *phy);
 	int		(*read_link)(struct mii_phy *phy);
+	int		(*enable_fiber)(struct mii_phy *phy);
 };
 
 /* Structure used to statically define an mii/gii based PHY */
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index beeb612be98f2b2e9664b5a688ee40f8cb53a670..e1b33a25a25f504e2c246aa326471c0d76c2ea38 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -7653,21 +7653,23 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 		cmd->supported |= (SUPPORTED_1000baseT_Half |
 				   SUPPORTED_1000baseT_Full);
 
-	if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES))
+	if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)) {
 		cmd->supported |= (SUPPORTED_100baseT_Half |
 				  SUPPORTED_100baseT_Full |
 				  SUPPORTED_10baseT_Half |
 				  SUPPORTED_10baseT_Full |
 				  SUPPORTED_MII);
-	else
+		cmd->port = PORT_TP;
+	} else {
 		cmd->supported |= SUPPORTED_FIBRE;
+		cmd->port = PORT_FIBRE;
+	}
   
 	cmd->advertising = tp->link_config.advertising;
 	if (netif_running(dev)) {
 		cmd->speed = tp->link_config.active_speed;
 		cmd->duplex = tp->link_config.active_duplex;
 	}
-	cmd->port = 0;
 	cmd->phy_address = PHY_ADDR;
 	cmd->transceiver = 0;
 	cmd->autoneg = tp->link_config.autoneg;
@@ -8454,6 +8456,9 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
 
 	tx_len = 1514;
 	skb = dev_alloc_skb(tx_len);
+	if (!skb)
+		return -ENOMEM;
+
 	tx_data = skb_put(skb, tx_len);
 	memcpy(tx_data, tp->dev->dev_addr, 6);
 	memset(tx_data + 6, 0x0, 8);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 198528660721b14a8847a0c6b7476e38b6c1bfb5..8d0f61816c1976a996377b8c8ca5cbbd09e10a47 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -939,9 +939,9 @@ static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm)
 	return 0;
 }
 
-static void bcm43xx_geo_init(struct bcm43xx_private *bcm)
+static int bcm43xx_geo_init(struct bcm43xx_private *bcm)
 {
-	struct ieee80211_geo geo;
+	struct ieee80211_geo *geo;
 	struct ieee80211_channel *chan;
 	int have_a = 0, have_bg = 0;
 	int i;
@@ -949,7 +949,10 @@ static void bcm43xx_geo_init(struct bcm43xx_private *bcm)
 	struct bcm43xx_phyinfo *phy;
 	const char *iso_country;
 
-	memset(&geo, 0, sizeof(geo));
+	geo = kzalloc(sizeof(*geo), GFP_KERNEL);
+	if (!geo)
+		return -ENOMEM;
+
 	for (i = 0; i < bcm->nr_80211_available; i++) {
 		phy = &(bcm->core_80211_ext[i].phy);
 		switch (phy->type) {
@@ -967,31 +970,36 @@ static void bcm43xx_geo_init(struct bcm43xx_private *bcm)
 	iso_country = bcm43xx_locale_iso(bcm->sprom.locale);
 
  	if (have_a) {
-		for (i = 0, channel = 0; channel < 201; channel++) {
-			chan = &geo.a[i++];
+		for (i = 0, channel = IEEE80211_52GHZ_MIN_CHANNEL;
+		      channel <= IEEE80211_52GHZ_MAX_CHANNEL; channel++) {
+			chan = &geo->a[i++];
 			chan->freq = bcm43xx_channel_to_freq_a(channel);
 			chan->channel = channel;
 		}
-		geo.a_channels = i;
+		geo->a_channels = i;
 	}
 	if (have_bg) {
-		for (i = 0, channel = 1; channel < 15; channel++) {
-			chan = &geo.bg[i++];
+		for (i = 0, channel = IEEE80211_24GHZ_MIN_CHANNEL;
+		      channel <= IEEE80211_24GHZ_MAX_CHANNEL; channel++) {
+			chan = &geo->bg[i++];
 			chan->freq = bcm43xx_channel_to_freq_bg(channel);
 			chan->channel = channel;
 		}
-		geo.bg_channels = i;
+		geo->bg_channels = i;
 	}
-	memcpy(geo.name, iso_country, 2);
+	memcpy(geo->name, iso_country, 2);
 	if (0 /*TODO: Outdoor use only */)
-		geo.name[2] = 'O';
+		geo->name[2] = 'O';
 	else if (0 /*TODO: Indoor use only */)
-		geo.name[2] = 'I';
+		geo->name[2] = 'I';
 	else
-		geo.name[2] = ' ';
-	geo.name[3] = '\0';
+		geo->name[2] = ' ';
+	geo->name[3] = '\0';
+
+	ieee80211_set_geo(bcm->ieee, geo);
+	kfree(geo);
 
-	ieee80211_set_geo(bcm->ieee, &geo);
+	return 0;
 }
 
 /* DummyTransmission function, as documented on 
@@ -3464,16 +3472,17 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm)
 			goto err_80211_unwind;
 		bcm43xx_wireless_core_disable(bcm);
 	}
+	err = bcm43xx_geo_init(bcm);
+	if (err)
+		goto err_80211_unwind;
 	bcm43xx_pctl_set_crystal(bcm, 0);
 
 	/* Set the MAC address in the networking subsystem */
-	if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
+	if (is_valid_ether_addr(bcm->sprom.et1macaddr))
 		memcpy(bcm->net_dev->dev_addr, bcm->sprom.et1macaddr, 6);
 	else
 		memcpy(bcm->net_dev->dev_addr, bcm->sprom.il0macaddr, 6);
 
-	bcm43xx_geo_init(bcm);
-
 	snprintf(bcm->nick, IW_ESSID_MAX_SIZE,
 		 "Broadcom %04X", bcm->chip_id);
 
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
index eca79a38594a88daeaa05aab40a0612e0bd23afa..30a202b258b535bfc6451a1d0d13ca0b687ffc8c 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
@@ -118,12 +118,14 @@ int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm,
 static inline
 int bcm43xx_is_valid_channel_a(u8 channel)
 {
-	return (channel <= 200);
+	return (channel >= IEEE80211_52GHZ_MIN_CHANNEL
+	       && channel <= IEEE80211_52GHZ_MAX_CHANNEL);
 }
 static inline
 int bcm43xx_is_valid_channel_bg(u8 channel)
 {
-	return (channel >= 1 && channel <= 14);
+	return (channel >= IEEE80211_24GHZ_MIN_CHANNEL
+	       && channel <= IEEE80211_24GHZ_MAX_CHANNEL);
 }
 static inline
 int bcm43xx_is_valid_channel(struct bcm43xx_private *bcm,
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
index 33137165727f7c69c054a9507324beda7fcd2830..b0abac5155300390791f441b891b2bd97f41525e 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -1287,7 +1287,7 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm)
 	if (radio->revision == 8)
 		bcm43xx_phy_write(bcm, 0x0805, 0x3230);
 	bcm43xx_phy_init_pctl(bcm);
-	if (bcm->chip_id == 0x4306 && bcm->chip_package != 2) {
+	if (bcm->chip_id == 0x4306 && bcm->chip_package == 2) {
 		bcm43xx_phy_write(bcm, 0x0429,
 				  bcm43xx_phy_read(bcm, 0x0429) & 0xBFFF);
 		bcm43xx_phy_write(bcm, 0x04C3,
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
index 3edbb481a0a035ebd957decbe43a76cad3c294e6..b45063974ae9dd196b93bb7a310bf2c62c7b5f3a 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
@@ -182,8 +182,11 @@ static int bcm43xx_wx_set_mode(struct net_device *net_dev,
 		mode = BCM43xx_INITIAL_IWMODE;
 
 	bcm43xx_lock_mmio(bcm, flags);
-	if (bcm->ieee->iw_mode != mode)
-		bcm43xx_set_iwmode(bcm, mode);
+	if (bcm->initialized) {
+		if (bcm->ieee->iw_mode != mode)
+			bcm43xx_set_iwmode(bcm, mode);
+	} else
+		bcm->ieee->iw_mode = mode;
 	bcm43xx_unlock_mmio(bcm, flags);
 
 	return 0;
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 19e2b174d33cc777bf38d506bc82f96121d1fb1b..d378478612fb76d862b4b584aff1cc14b190f228 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -634,6 +634,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_4,	quirk_vi
  * non-x86 architectures (yes Via exists on PPC among other places),
  * we must mask the PCI_INTERRUPT_LINE value versus 0xf to get
  * interrupts delivered properly.
+ *
+ * Some of the on-chip devices are actually '586 devices' so they are
+ * listed here.
  */
 static void quirk_via_irq(struct pci_dev *dev)
 {
@@ -648,6 +651,10 @@ static void quirk_via_irq(struct pci_dev *dev)
 		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);
 	}
 }
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_via_irq);
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, quirk_via_irq);
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irq);
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_irq);
 DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_irq);
 DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_irq);
 DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irq);
@@ -895,6 +902,7 @@ static void __init k8t_sound_hostbridge(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_hostbridge);
 
+#ifndef CONFIG_ACPI_SLEEP
 /*
  * 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
@@ -906,8 +914,12 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_ho
  * bridge. Unfortunately, this device has no subvendor/subdevice ID. So it 
  * becomes necessary to do this tweak in two steps -- I've chosen the Host
  * bridge as trigger.
+ *
+ * Actually, leaving it unhidden and not redoing the quirk over suspend2ram
+ * will cause thermal management to break down, and causing machine to
+ * overheat.
  */
-static int __initdata asus_hides_smbus = 0;
+static int __initdata asus_hides_smbus;
 
 static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
 {
@@ -1050,6 +1062,8 @@ static void __init asus_hides_smbus_lpc_ich6(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH6_1,	asus_hides_smbus_lpc_ich6 );
 
+#endif
+
 /*
  * SiS 96x south bridge: BIOS typically hides SMBus device...
  */
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
index c53db7ceda5e2ab12770964dc18216fa819ab4c8..738b1ef595a3506fd595f9f742da4c6f966b7e47 100644
--- a/drivers/pcmcia/pcmcia_ioctl.c
+++ b/drivers/pcmcia/pcmcia_ioctl.c
@@ -426,7 +426,7 @@ static int ds_open(struct inode *inode, struct file *file)
 
     if (!warning_printed) {
 	    printk(KERN_INFO "pcmcia: Detected deprecated PCMCIA ioctl "
-			"usage.\n");
+			"usage from process: %s.\n", current->comm);
 	    printk(KERN_INFO "pcmcia: This interface will soon be removed from "
 			"the kernel; please expect breakage unless you upgrade "
 			"to new tools.\n");
@@ -601,8 +601,12 @@ static int ds_ioctl(struct inode * inode, struct file * file,
 	    ret = CS_BAD_ARGS;
 	else {
 	    struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->config.Function);
-	    ret = pccard_get_configuration_info(s, p_dev, &buf->config);
-	    pcmcia_put_dev(p_dev);
+	    if (p_dev == NULL)
+		    ret = CS_BAD_ARGS;
+	    else {
+		    ret = pccard_get_configuration_info(s, p_dev, &buf->config);
+		    pcmcia_put_dev(p_dev);
+	    }
 	}
 	break;
     case DS_GET_FIRST_TUPLE:
@@ -632,8 +636,12 @@ static int ds_ioctl(struct inode * inode, struct file * file,
 		    ret = CS_BAD_ARGS;
 	    else {
 		    struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->status.Function);
-		    ret = pccard_get_status(s, p_dev, &buf->status);
-		    pcmcia_put_dev(p_dev);
+		    if (p_dev == NULL)
+			    ret = CS_BAD_ARGS;
+		    else {
+			    ret = pccard_get_status(s, p_dev, &buf->status);
+			    pcmcia_put_dev(p_dev);
+		    }
 	    }
 	    break;
     case DS_VALIDATE_CIS:
@@ -665,9 +673,10 @@ static int ds_ioctl(struct inode * inode, struct file * file,
 	if (!(buf->conf_reg.Function &&
 	     (buf->conf_reg.Function >= s->functions))) {
 		struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->conf_reg.Function);
-		if (p_dev)
+		if (p_dev) {
 			ret = pcmcia_access_configuration_register(p_dev, &buf->conf_reg);
-		pcmcia_put_dev(p_dev);
+			pcmcia_put_dev(p_dev);
+		}
 	}
 	break;
     case DS_GET_FIRST_REGION:
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index a23ec54989f6dbad436d1d91397b542511136346..2bc8aad47219180f58799a4b89523a9cf8298234 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -178,9 +178,9 @@ static int sa1100_rtc_open(struct device *dev)
 	return 0;
 
  fail_pi:
-	free_irq(IRQ_RTCAlrm, NULL);
+	free_irq(IRQ_RTCAlrm, dev);
  fail_ai:
-	free_irq(IRQ_RTC1Hz, NULL);
+	free_irq(IRQ_RTC1Hz, dev);
  fail_ui:
 	return ret;
 }
@@ -295,7 +295,7 @@ static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 
 static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
 {
-	seq_printf(seq, "trim/divider\t: 0x%08x\n", RTTR);
+	seq_printf(seq, "trim/divider\t: 0x%08lx\n", RTTR);
 	seq_printf(seq, "alarm_IRQ\t: %s\n",
 			(RTSR & RTSR_ALE) ? "yes" : "no" );
 	seq_printf(seq, "update_IRQ\t: %s\n",
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index 5d6b7a57b02f16e81bb1a343480e64e3ff464d5d..e65da921a827da68fb941b1f90aa4025e666636e 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -1348,7 +1348,7 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
 		index = (struct ccw1 *) __va((addr_t) irb->scsw.cpa) 
 			- channel->ccws;
 		if ((irb->scsw.actl & SCSW_ACTL_SUSPENDED) ||
-		    (irb->scsw.cstat | SCHN_STAT_PCI))
+		    (irb->scsw.cstat & SCHN_STAT_PCI))
 			/* Bloody io subsystem tells us lies about cpa... */
 			index = (index - 1) & (LCS_NUM_BUFFS - 1);
 		while (channel->io_idx != index) {
diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c
index 383a95f34a0da4e8adec682df992786d572efe27..239e108b8ed1e16cb45d51fa89591418a5410bac 100644
--- a/drivers/sbus/char/openprom.c
+++ b/drivers/sbus/char/openprom.c
@@ -392,13 +392,16 @@ static int openprom_bsd_ioctl(struct inode * inode, struct file * file,
 			return -ENOMEM;
 		}
 
-		prom_getproperty(op.op_nodeid, str, tmp, len);
-
-		tmp[len] = '\0';
+		cnt = prom_getproperty(op.op_nodeid, str, tmp, len);
+		if (cnt <= 0) {
+			error = -EINVAL;
+		} else {
+			tmp[len] = '\0';
 
-		if (__copy_to_user(argp, &op, sizeof(op)) != 0
-		    || copy_to_user(op.op_buf, tmp, len) != 0)
-			error = -EFAULT;
+			if (__copy_to_user(argp, &op, sizeof(op)) != 0 ||
+			    copy_to_user(op.op_buf, tmp, len) != 0)
+				error = -EFAULT;
+		}
 
 		kfree(tmp);
 		kfree(str);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
index cb30d9c1153d5394c08db57f6b64486bfcd1592a..0c9c2f400bf6b21982c4fdb5e1fa0974bb372f5c 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
@@ -219,6 +219,7 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		ahc->flags |= AHC_39BIT_ADDRESSING;
 	} else {
 		if (dma_set_mask(dev, DMA_32BIT_MASK)) {
+			ahc_free(ahc);
 			printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n");
                 	return (-ENODEV);
 		}
diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c
index 5f586140e05717a575f2f1a8103dd0edfe635486..3adecef21783468c3399da474ee1b9d34c3359a5 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c
@@ -2036,12 +2036,12 @@ ahc_pci_resume(struct ahc_softc *ahc)
 	 * that the OS doesn't know about and rely on our chip
 	 * reset handler to handle the rest.
 	 */
-	ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4,
-			     ahc->bus_softc.pci_softc.devconfig);
-	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1,
-			     ahc->bus_softc.pci_softc.command);
-	ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1,
-			     ahc->bus_softc.pci_softc.csize_lattime);
+	ahc_pci_write_config(ahc->dev_softc, DEVCONFIG,
+			     ahc->bus_softc.pci_softc.devconfig, /*bytes*/4);
+	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
+			     ahc->bus_softc.pci_softc.command, /*bytes*/1);
+	ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME,
+			     ahc->bus_softc.pci_softc.csize_lattime, /*bytes*/1);
 	if ((ahc->flags & AHC_HAS_TERM_LOGIC) != 0) {
 		struct	seeprom_descriptor sd;
 		u_int	sxfrctl1;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 0a8ad37ae8998407528f8c710e9ecb9b1cb82828..2e9be83a697feb90a36fbccfac58599ce19af58a 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -739,7 +739,8 @@ static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata)
 {
 	struct viosrp_adapter_info *req;
 	struct srp_event_struct *evt_struct;
-	
+	dma_addr_t addr;
+
 	evt_struct = get_event_struct(&hostdata->pool);
 	if (!evt_struct) {
 		printk(KERN_ERR "ibmvscsi: couldn't allocate an event "
@@ -757,10 +758,10 @@ static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata)
 	
 	req->common.type = VIOSRP_ADAPTER_INFO_TYPE;
 	req->common.length = sizeof(hostdata->madapter_info);
-	req->buffer = dma_map_single(hostdata->dev,
-				     &hostdata->madapter_info,
-				     sizeof(hostdata->madapter_info),
-				     DMA_BIDIRECTIONAL);
+	req->buffer = addr = dma_map_single(hostdata->dev,
+					    &hostdata->madapter_info,
+					    sizeof(hostdata->madapter_info),
+					    DMA_BIDIRECTIONAL);
 
 	if (dma_mapping_error(req->buffer)) {
 		printk(KERN_ERR
@@ -770,8 +771,13 @@ static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata)
 		return;
 	}
 	
-	if (ibmvscsi_send_srp_event(evt_struct, hostdata))
+	if (ibmvscsi_send_srp_event(evt_struct, hostdata)) {
 		printk(KERN_ERR "ibmvscsi: couldn't send ADAPTER_INFO_REQ!\n");
+		dma_unmap_single(hostdata->dev,
+				 addr,
+				 sizeof(hostdata->madapter_info),
+				 DMA_BIDIRECTIONAL);
+	}
 };
 
 /**
@@ -1259,6 +1265,7 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata,
 {
 	struct viosrp_host_config *host_config;
 	struct srp_event_struct *evt_struct;
+	dma_addr_t addr;
 	int rc;
 
 	evt_struct = get_event_struct(&hostdata->pool);
@@ -1279,8 +1286,9 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata,
 	memset(host_config, 0x00, sizeof(*host_config));
 	host_config->common.type = VIOSRP_HOST_CONFIG_TYPE;
 	host_config->common.length = length;
-	host_config->buffer = dma_map_single(hostdata->dev, buffer, length,
-					    DMA_BIDIRECTIONAL);
+	host_config->buffer = addr = dma_map_single(hostdata->dev, buffer,
+						    length,
+						    DMA_BIDIRECTIONAL);
 
 	if (dma_mapping_error(host_config->buffer)) {
 		printk(KERN_ERR
@@ -1291,11 +1299,9 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata,
 
 	init_completion(&evt_struct->comp);
 	rc = ibmvscsi_send_srp_event(evt_struct, hostdata);
-	if (rc == 0) {
+	if (rc == 0)
 		wait_for_completion(&evt_struct->comp);
-		dma_unmap_single(hostdata->dev, host_config->buffer,
-				 length, DMA_BIDIRECTIONAL);
-	}
+	dma_unmap_single(hostdata->dev, addr, length, DMA_BIDIRECTIONAL);
 
 	return rc;
 }
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index fad607b2e6f4d47eaf4087c10b2ae62a0d5bdd5e..ee22173fce43c664cc2a352b580d8984bf60f718 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -27,7 +27,6 @@ void lpfc_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
 int lpfc_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_read_config(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_read_lnk_stat(struct lpfc_hba *, LPFC_MBOXQ_t *);
-void lpfc_set_slim(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);
 int lpfc_reg_login(struct lpfc_hba *, uint32_t, uint8_t *, LPFC_MBOXQ_t *,
 		   uint32_t);
 void lpfc_unreg_login(struct lpfc_hba *, uint32_t, LPFC_MBOXQ_t *);
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
index 8932b1be2b60cfbf849b4689c4d00043a5147d23..41cf5d3ea6ce53597b7b0e0f733d7b83991112e6 100644
--- a/drivers/scsi/lpfc/lpfc_disc.h
+++ b/drivers/scsi/lpfc/lpfc_disc.h
@@ -113,6 +113,7 @@ struct lpfc_nodelist {
 #define NLP_NPR_ADISC      0x2000000	/* Issue ADISC when dq'ed from
 					   NPR list */
 #define NLP_DELAY_REMOVE   0x4000000	/* Defer removal till end of DSM */
+#define NLP_NODEV_REMOVE   0x8000000	/* Defer removal till discovery ends */
 
 /* Defines for list searchs */
 #define NLP_SEARCH_MAPPED    0x1	/* search mapped */
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 4813beaaca8f95a7f4f4f03c3bec1da2ee2eef45..283b7d824c34fae6693f5a2e71ae60e1008219b6 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -302,10 +302,6 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
 	if (lpfc_reg_login(phba, Fabric_DID, (uint8_t *) sp, mbox, 0))
 		goto fail_free_mbox;
 
-	/*
-	 * set_slim mailbox command needs to execute first,
-	 * queue this command to be processed later.
-	 */
 	mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login;
 	mbox->context2 = ndlp;
 
@@ -781,25 +777,26 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
 	if (disc && phba->num_disc_nodes) {
 		/* Check to see if there are more PLOGIs to be sent */
 		lpfc_more_plogi(phba);
-	}
 
-	if (phba->num_disc_nodes == 0) {
-		spin_lock_irq(phba->host->host_lock);
-		phba->fc_flag &= ~FC_NDISC_ACTIVE;
-		spin_unlock_irq(phba->host->host_lock);
+		if (phba->num_disc_nodes == 0) {
+			spin_lock_irq(phba->host->host_lock);
+			phba->fc_flag &= ~FC_NDISC_ACTIVE;
+			spin_unlock_irq(phba->host->host_lock);
 
-		lpfc_can_disctmo(phba);
-		if (phba->fc_flag & FC_RSCN_MODE) {
-			/* Check to see if more RSCNs came in while we were
-			 * processing this one.
-			 */
-			if ((phba->fc_rscn_id_cnt == 0) &&
-			    (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
-				spin_lock_irq(phba->host->host_lock);
-				phba->fc_flag &= ~FC_RSCN_MODE;
-				spin_unlock_irq(phba->host->host_lock);
-			} else {
-				lpfc_els_handle_rscn(phba);
+			lpfc_can_disctmo(phba);
+			if (phba->fc_flag & FC_RSCN_MODE) {
+				/*
+				 * Check to see if more RSCNs came in while
+				 * we were processing this one.
+				 */
+				if ((phba->fc_rscn_id_cnt == 0) &&
+			    	(!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
+					spin_lock_irq(phba->host->host_lock);
+					phba->fc_flag &= ~FC_RSCN_MODE;
+					spin_unlock_irq(phba->host->host_lock);
+				} else {
+					lpfc_els_handle_rscn(phba);
+				}
 			}
 		}
 	}
@@ -1263,7 +1260,7 @@ lpfc_issue_els_logo(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
 	psli = &phba->sli;
 	pring = &psli->ring[LPFC_ELS_RING];
 
-	cmdsize = 2 * (sizeof (uint32_t) + sizeof (struct lpfc_name));
+	cmdsize = (2 * sizeof (uint32_t)) + sizeof (struct lpfc_name);
 	elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
 						ndlp->nlp_DID, ELS_CMD_LOGO);
 	if (!elsiocb)
@@ -1451,22 +1448,23 @@ lpfc_cancel_retry_delay_tmo(struct lpfc_hba *phba, struct lpfc_nodelist * nlp)
 			 * PLOGIs to be sent
 			 */
 			lpfc_more_plogi(phba);
-		}
 
-		if (phba->num_disc_nodes == 0) {
-			phba->fc_flag &= ~FC_NDISC_ACTIVE;
-			lpfc_can_disctmo(phba);
-			if (phba->fc_flag & FC_RSCN_MODE) {
-				/* Check to see if more RSCNs
-				 * came in while we were
-				 * processing this one.
-				 */
-				if((phba->fc_rscn_id_cnt==0) &&
-				   (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
-					phba->fc_flag &= ~FC_RSCN_MODE;
-				}
-				else {
-					lpfc_els_handle_rscn(phba);
+			if (phba->num_disc_nodes == 0) {
+				phba->fc_flag &= ~FC_NDISC_ACTIVE;
+				lpfc_can_disctmo(phba);
+				if (phba->fc_flag & FC_RSCN_MODE) {
+					/*
+					 * Check to see if more RSCNs
+					 * came in while we were
+					 * processing this one.
+					 */
+					if((phba->fc_rscn_id_cnt==0) &&
+					 !(phba->fc_flag & FC_RSCN_DISCOVERY)) {
+						phba->fc_flag &= ~FC_RSCN_MODE;
+					}
+					else {
+						lpfc_els_handle_rscn(phba);
+					}
 				}
 			}
 		}
@@ -1872,9 +1870,6 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
 	if (mbox) {
 		if ((rspiocb->iocb.ulpStatus == 0)
 		    && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) {
-			/* set_slim mailbox command needs to execute first,
-			 * queue this command to be processed later.
-			 */
 			lpfc_unreg_rpi(phba, ndlp);
 			mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
 			mbox->context2 = ndlp;
@@ -1920,6 +1915,7 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag,
 	uint8_t *pcmd;
 	uint16_t cmdsize;
 	int rc;
+	ELS_PKT *els_pkt_ptr;
 
 	psli = &phba->sli;
 	pring = &psli->ring[LPFC_ELS_RING];	/* ELS ring */
@@ -1958,6 +1954,23 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag,
 		pcmd += sizeof (uint32_t);
 		memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));
 		break;
+	case ELS_CMD_PRLO:
+		cmdsize = sizeof (uint32_t) + sizeof (PRLO);
+		elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
+					     ndlp, ndlp->nlp_DID, ELS_CMD_PRLO);
+		if (!elsiocb)
+			return 1;
+
+		icmd = &elsiocb->iocb;
+		icmd->ulpContext = oldcmd->ulpContext; /* Xri */
+		pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+
+		memcpy(pcmd, ((struct lpfc_dmabuf *) oldiocb->context2)->virt,
+		       sizeof (uint32_t) + sizeof (PRLO));
+		*((uint32_t *) (pcmd)) = ELS_CMD_PRLO_ACC;
+		els_pkt_ptr = (ELS_PKT *) pcmd;
+		els_pkt_ptr->un.prlo.acceptRspCode = PRLO_REQ_EXECUTED;
+		break;
 	default:
 		return 1;
 	}
@@ -2498,7 +2511,7 @@ lpfc_els_rcv_rscn(struct lpfc_hba * phba,
 	/* If we are about to begin discovery, just ACC the RSCN.
 	 * Discovery processing will satisfy it.
 	 */
-	if (phba->hba_state < LPFC_NS_QRY) {
+	if (phba->hba_state <= LPFC_NS_QRY) {
 		lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
 								newnode);
 		return 0;
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 6721e679df6281fc19d3b95f7d05638998f260cc..adb086009ae09fb0221c5ec06deeb2d772914609 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -311,8 +311,8 @@ lpfc_workq_post_event(struct lpfc_hba * phba, void *arg1, void *arg2,
 	evtp->evt_arg2  = arg2;
 	evtp->evt       = evt;
 
-	list_add_tail(&evtp->evt_listp, &phba->work_list);
 	spin_lock_irq(phba->host->host_lock);
+	list_add_tail(&evtp->evt_listp, &phba->work_list);
 	if (phba->work_wait)
 		wake_up(phba->work_wait);
 	spin_unlock_irq(phba->host->host_lock);
@@ -1071,10 +1071,6 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
 	/* initialize static port data */
 	rport->maxframe_size = ndlp->nlp_maxframe;
 	rport->supported_classes = ndlp->nlp_class_sup;
-	if ((rport->scsi_target_id != -1) &&
-		(rport->scsi_target_id < MAX_FCP_TARGET)) {
-		ndlp->nlp_sid = rport->scsi_target_id;
-	}
 	rdata = rport->dd_data;
 	rdata->pnode = ndlp;
 
@@ -1087,6 +1083,10 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
 	if (rport_ids.roles !=  FC_RPORT_ROLE_UNKNOWN)
 		fc_remote_port_rolechg(rport, rport_ids.roles);
 
+	if ((rport->scsi_target_id != -1) &&
+		(rport->scsi_target_id < MAX_FCP_TARGET)) {
+		ndlp->nlp_sid = rport->scsi_target_id;
+	}
 
 	return;
 }
@@ -1238,6 +1238,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
 						evt_listp);
 
 		}
+		nlp->nlp_flag &= ~NLP_NODEV_REMOVE;
 		nlp->nlp_type |= NLP_FC_NODE;
 		break;
 	case NLP_MAPPED_LIST:
@@ -1258,6 +1259,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
 						evt_listp);
 
 		}
+		nlp->nlp_flag &= ~NLP_NODEV_REMOVE;
 		break;
 	case NLP_NPR_LIST:
 		nlp->nlp_flag |= list;
@@ -1402,6 +1404,8 @@ lpfc_check_sli_ndlp(struct lpfc_hba * phba,
 			if (icmd->ulpContext == (volatile ushort)ndlp->nlp_rpi)
 				return 1;
 		case CMD_ELS_REQUEST64_CR:
+			if (icmd->un.elsreq64.remoteID == ndlp->nlp_DID)
+				return 1;
 		case CMD_XMIT_ELS_RSP64_CX:
 			if (iocb->context1 == (uint8_t *) ndlp)
 				return 1;
@@ -1901,10 +1905,8 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did)
 			 */
 			if (ndlp->nlp_flag & NLP_DELAY_TMO)
 				lpfc_cancel_retry_delay_tmo(phba, ndlp);
-		} else {
-			ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+		} else
 			ndlp = NULL;
-		}
 	} else {
 		flg = ndlp->nlp_flag & NLP_LIST_MASK;
 		if ((flg == NLP_ADISC_LIST) || (flg == NLP_PLOGI_LIST))
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 54d04188f7ccaf5d420c6c3ca4b4766c884442f0..eedf98801366790ee7ff1e496754b00b8e593d5b 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -449,6 +449,7 @@ struct serv_parm {	/* Structure is in Big Endian format */
 #define ELS_CMD_RRQ       0x12000000
 #define ELS_CMD_PRLI      0x20100014
 #define ELS_CMD_PRLO      0x21100014
+#define ELS_CMD_PRLO_ACC  0x02100014
 #define ELS_CMD_PDISC     0x50000000
 #define ELS_CMD_FDISC     0x51000000
 #define ELS_CMD_ADISC     0x52000000
@@ -484,6 +485,7 @@ struct serv_parm {	/* Structure is in Big Endian format */
 #define ELS_CMD_RRQ       0x12
 #define ELS_CMD_PRLI      0x14001020
 #define ELS_CMD_PRLO      0x14001021
+#define ELS_CMD_PRLO_ACC  0x14001002
 #define ELS_CMD_PDISC     0x50
 #define ELS_CMD_FDISC     0x51
 #define ELS_CMD_ADISC     0x52
@@ -1539,6 +1541,7 @@ typedef struct {
 
 #define FLAGS_TOPOLOGY_FAILOVER      0x0400	/* Bit 10 */
 #define FLAGS_LINK_SPEED             0x0800	/* Bit 11 */
+#define FLAGS_IMED_ABORT             0x04000	/* Bit 14 */
 
 	uint32_t link_speed;
 #define LINK_SPEED_AUTO 0       /* Auto selection */
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 66d5d003555db94d208719a05ed533d40816d598..908d0f27706f9cc55591e6833161c7a41b7eefd0 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -294,15 +294,6 @@ lpfc_config_port_post(struct lpfc_hba * phba)
 		}
 	}
 
-	/* This should turn on DELAYED ABTS for ELS timeouts */
-	lpfc_set_slim(phba, pmb, 0x052198, 0x1);
-	if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
-		phba->hba_state = LPFC_HBA_ERROR;
-		mempool_free( pmb, phba->mbox_mem_pool);
-		return -EIO;
-	}
-
-
 	lpfc_read_config(phba, pmb);
 	if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
 		lpfc_printf_log(phba,
@@ -804,7 +795,7 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
 		int    max_speed;
 		char * ports;
 		char * bus;
-	} m;
+	} m = {"<Unknown>", 0, "", ""};
 
 	pci_read_config_byte(phba->pcidev, PCI_HEADER_TYPE, &hdrtype);
 	ports = (hdrtype == 0x80) ? "2-port " : "";
@@ -1627,7 +1618,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
 
 	error = lpfc_alloc_sysfs_attr(phba);
 	if (error)
-		goto out_kthread_stop;
+		goto out_remove_host;
 
 	error =	request_irq(phba->pcidev->irq, lpfc_intr_handler, SA_SHIRQ,
 							LPFC_DRIVER_NAME, phba);
@@ -1644,8 +1635,10 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
 	phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;
 
 	error = lpfc_sli_hba_setup(phba);
-	if (error)
+	if (error) {
+		error = -ENODEV;
 		goto out_free_irq;
+	}
 
 	if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
 		spin_lock_irq(phba->host->host_lock);
@@ -1700,6 +1693,9 @@ out_free_irq:
 	free_irq(phba->pcidev->irq, phba);
 out_free_sysfs_attr:
 	lpfc_free_sysfs_attr(phba);
+out_remove_host:
+	fc_remove_host(phba->host);
+	scsi_remove_host(phba->host);
 out_kthread_stop:
 	kthread_stop(phba->worker_thread);
 out_free_iocbq:
@@ -1721,12 +1717,14 @@ out_iounmap_slim:
 out_idr_remove:
 	idr_remove(&lpfc_hba_index, phba->brd_no);
 out_put_host:
+	phba->host = NULL;
 	scsi_host_put(host);
 out_release_regions:
 	pci_release_regions(pdev);
 out_disable_device:
 	pci_disable_device(pdev);
 out:
+	pci_set_drvdata(pdev, NULL);
 	return error;
 }
 
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index c585e2b2e589f60fcd12117d01c0db4a2b73678c..e42f22aaf71b07f3c3d045887a4646e2bb059d9f 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -200,6 +200,9 @@ lpfc_init_link(struct lpfc_hba * phba,
 		break;
 	}
 
+	/* Enable asynchronous ABTS responses from firmware */
+	mb->un.varInitLnk.link_flags |= FLAGS_IMED_ABORT;
+
 	/* NEW_FEATURE
 	 * Setting up the link speed
 	 */
@@ -292,36 +295,6 @@ lpfc_unreg_did(struct lpfc_hba * phba, uint32_t did, LPFC_MBOXQ_t * pmb)
 	return;
 }
 
-/***********************************************/
-
-/*                  command to write slim      */
-/***********************************************/
-void
-lpfc_set_slim(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint32_t addr,
-	      uint32_t value)
-{
-	MAILBOX_t *mb;
-
-	mb = &pmb->mb;
-	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
-
-	/* addr = 0x090597 is AUTO ABTS disable for ELS commands */
-	/* addr = 0x052198 is DELAYED ABTS enable for ELS commands */
-
-	/*
-	 * Always turn on DELAYED ABTS for ELS timeouts
-	 */
-	if ((addr == 0x052198) && (value == 0))
-		value = 1;
-
-	mb->un.varWords[0] = addr;
-	mb->un.varWords[1] = value;
-
-	mb->mbxCommand = MBX_SET_SLIM;
-	mb->mbxOwner = OWN_HOST;
-	return;
-}
-
 /**********************************************/
 /*  lpfc_read_nv  Issue a READ CONFIG         */
 /*                mailbox command             */
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 3d77bd999b70bca83daa57bad3f051a515ad444c..27d60ad897cdc81de79fde9dd2fab98a568a3211 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -465,14 +465,18 @@ lpfc_rcv_padisc(struct lpfc_hba * phba,
 static int
 lpfc_rcv_logo(struct lpfc_hba * phba,
 		      struct lpfc_nodelist * ndlp,
-		      struct lpfc_iocbq *cmdiocb)
+		      struct lpfc_iocbq *cmdiocb,
+		      uint32_t els_cmd)
 {
 	/* Put ndlp on NPR list with 1 sec timeout for plogi, ACC logo */
 	/* Only call LOGO ACC for first LOGO, this avoids sending unnecessary
 	 * PLOGIs during LOGO storms from a device.
 	 */
 	ndlp->nlp_flag |= NLP_LOGO_ACC;
-	lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+	if (els_cmd == ELS_CMD_PRLO)
+		lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
+	else
+		lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
 
 	if (!(ndlp->nlp_type & NLP_FABRIC) ||
 		(ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) {
@@ -681,7 +685,7 @@ lpfc_rcv_logo_plogi_issue(struct lpfc_hba * phba,
 	/* software abort outstanding PLOGI */
 	lpfc_els_abort(phba, ndlp, 1);
 
-	lpfc_rcv_logo(phba, ndlp, cmdiocb);
+	lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
 	return ndlp->nlp_state;
 }
 
@@ -788,10 +792,6 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba,
 	if (lpfc_reg_login
 	    (phba, irsp->un.elsreq64.remoteID,
 	     (uint8_t *) sp, mbox, 0) == 0) {
-		/* set_slim mailbox command needs to
-		 * execute first, queue this command to
-		 * be processed later.
-		 */
 		switch (ndlp->nlp_DID) {
 		case NameServer_DID:
 			mbox->mbox_cmpl =
@@ -832,11 +832,17 @@ static uint32_t
 lpfc_device_rm_plogi_issue(struct lpfc_hba * phba,
 			   struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
 {
-	/* software abort outstanding PLOGI */
-	lpfc_els_abort(phba, ndlp, 1);
+	if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+		ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+		return ndlp->nlp_state;
+	}
+	else {
+		/* software abort outstanding PLOGI */
+		lpfc_els_abort(phba, ndlp, 1);
 
-	lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
-	return NLP_STE_FREED_NODE;
+		lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+		return NLP_STE_FREED_NODE;
+	}
 }
 
 static uint32_t
@@ -851,7 +857,7 @@ lpfc_device_recov_plogi_issue(struct lpfc_hba * phba,
 	ndlp->nlp_state = NLP_STE_NPR_NODE;
 	lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
 	spin_lock_irq(phba->host->host_lock);
-	ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+	ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
 	spin_unlock_irq(phba->host->host_lock);
 
 	return ndlp->nlp_state;
@@ -905,7 +911,7 @@ lpfc_rcv_logo_adisc_issue(struct lpfc_hba * phba,
 	/* software abort outstanding ADISC */
 	lpfc_els_abort(phba, ndlp, 0);
 
-	lpfc_rcv_logo(phba, ndlp, cmdiocb);
+	lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
 	return ndlp->nlp_state;
 }
 
@@ -932,7 +938,7 @@ lpfc_rcv_prlo_adisc_issue(struct lpfc_hba * phba,
 	cmdiocb = (struct lpfc_iocbq *) arg;
 
 	/* Treat like rcv logo */
-	lpfc_rcv_logo(phba, ndlp, cmdiocb);
+	lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_PRLO);
 	return ndlp->nlp_state;
 }
 
@@ -987,11 +993,17 @@ lpfc_device_rm_adisc_issue(struct lpfc_hba * phba,
 			    struct lpfc_nodelist * ndlp, void *arg,
 			    uint32_t evt)
 {
-	/* software abort outstanding ADISC */
-	lpfc_els_abort(phba, ndlp, 1);
+	if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+		ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+		return ndlp->nlp_state;
+	}
+	else {
+		/* software abort outstanding ADISC */
+		lpfc_els_abort(phba, ndlp, 1);
 
-	lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
-	return NLP_STE_FREED_NODE;
+		lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+		return NLP_STE_FREED_NODE;
+	}
 }
 
 static uint32_t
@@ -1006,7 +1018,7 @@ lpfc_device_recov_adisc_issue(struct lpfc_hba * phba,
 	ndlp->nlp_state = NLP_STE_NPR_NODE;
 	lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
 	spin_lock_irq(phba->host->host_lock);
-	ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+	ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
 	ndlp->nlp_flag |= NLP_NPR_ADISC;
 	spin_unlock_irq(phba->host->host_lock);
 
@@ -1048,7 +1060,7 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_hba * phba,
 
 	cmdiocb = (struct lpfc_iocbq *) arg;
 
-	lpfc_rcv_logo(phba, ndlp, cmdiocb);
+	lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
 	return ndlp->nlp_state;
 }
 
@@ -1073,7 +1085,7 @@ lpfc_rcv_prlo_reglogin_issue(struct lpfc_hba * phba,
 	struct lpfc_iocbq *cmdiocb;
 
 	cmdiocb = (struct lpfc_iocbq *) arg;
-	lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+	lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
 	return ndlp->nlp_state;
 }
 
@@ -1133,8 +1145,14 @@ lpfc_device_rm_reglogin_issue(struct lpfc_hba * phba,
 			      struct lpfc_nodelist * ndlp, void *arg,
 			      uint32_t evt)
 {
-	lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
-	return NLP_STE_FREED_NODE;
+	if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+		ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+		return ndlp->nlp_state;
+	}
+	else {
+		lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+		return NLP_STE_FREED_NODE;
+	}
 }
 
 static uint32_t
@@ -1146,7 +1164,7 @@ lpfc_device_recov_reglogin_issue(struct lpfc_hba * phba,
 	ndlp->nlp_state = NLP_STE_NPR_NODE;
 	lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
 	spin_lock_irq(phba->host->host_lock);
-	ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+	ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
 	spin_unlock_irq(phba->host->host_lock);
 	return ndlp->nlp_state;
 }
@@ -1186,7 +1204,7 @@ lpfc_rcv_logo_prli_issue(struct lpfc_hba * phba,
 	/* Software abort outstanding PRLI before sending acc */
 	lpfc_els_abort(phba, ndlp, 1);
 
-	lpfc_rcv_logo(phba, ndlp, cmdiocb);
+	lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
 	return ndlp->nlp_state;
 }
 
@@ -1214,7 +1232,7 @@ lpfc_rcv_prlo_prli_issue(struct lpfc_hba * phba,
 	struct lpfc_iocbq *cmdiocb;
 
 	cmdiocb = (struct lpfc_iocbq *) arg;
-	lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+	lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
 	return ndlp->nlp_state;
 }
 
@@ -1278,11 +1296,17 @@ static uint32_t
 lpfc_device_rm_prli_issue(struct lpfc_hba * phba,
 			  struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
 {
-	/* software abort outstanding PRLI */
-	lpfc_els_abort(phba, ndlp, 1);
+	if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+		ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+		return ndlp->nlp_state;
+	}
+	else {
+		/* software abort outstanding PLOGI */
+		lpfc_els_abort(phba, ndlp, 1);
 
-	lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
-	return NLP_STE_FREED_NODE;
+		lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+		return NLP_STE_FREED_NODE;
+	}
 }
 
 
@@ -1313,7 +1337,7 @@ lpfc_device_recov_prli_issue(struct lpfc_hba * phba,
 	ndlp->nlp_state = NLP_STE_NPR_NODE;
 	lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
 	spin_lock_irq(phba->host->host_lock);
-	ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+	ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
 	spin_unlock_irq(phba->host->host_lock);
 	return ndlp->nlp_state;
 }
@@ -1351,7 +1375,7 @@ lpfc_rcv_logo_unmap_node(struct lpfc_hba * phba,
 
 	cmdiocb = (struct lpfc_iocbq *) arg;
 
-	lpfc_rcv_logo(phba, ndlp, cmdiocb);
+	lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
 	return ndlp->nlp_state;
 }
 
@@ -1375,7 +1399,7 @@ lpfc_rcv_prlo_unmap_node(struct lpfc_hba * phba,
 
 	cmdiocb = (struct lpfc_iocbq *) arg;
 
-	lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+	lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
 	return ndlp->nlp_state;
 }
 
@@ -1386,7 +1410,7 @@ lpfc_device_recov_unmap_node(struct lpfc_hba * phba,
 	ndlp->nlp_prev_state = NLP_STE_UNMAPPED_NODE;
 	ndlp->nlp_state = NLP_STE_NPR_NODE;
 	lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
-	ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+	ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
 	lpfc_disc_set_adisc(phba, ndlp);
 
 	return ndlp->nlp_state;
@@ -1424,7 +1448,7 @@ lpfc_rcv_logo_mapped_node(struct lpfc_hba * phba,
 
 	cmdiocb = (struct lpfc_iocbq *) arg;
 
-	lpfc_rcv_logo(phba, ndlp, cmdiocb);
+	lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
 	return ndlp->nlp_state;
 }
 
@@ -1456,7 +1480,7 @@ lpfc_rcv_prlo_mapped_node(struct lpfc_hba * phba,
 	spin_unlock_irq(phba->host->host_lock);
 
 	/* Treat like rcv logo */
-	lpfc_rcv_logo(phba, ndlp, cmdiocb);
+	lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_PRLO);
 	return ndlp->nlp_state;
 }
 
@@ -1469,7 +1493,7 @@ lpfc_device_recov_mapped_node(struct lpfc_hba * phba,
 	ndlp->nlp_state = NLP_STE_NPR_NODE;
 	lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
 	spin_lock_irq(phba->host->host_lock);
-	ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+	ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
 	spin_unlock_irq(phba->host->host_lock);
 	lpfc_disc_set_adisc(phba, ndlp);
 	return ndlp->nlp_state;
@@ -1551,7 +1575,7 @@ lpfc_rcv_logo_npr_node(struct lpfc_hba * phba,
 
 	cmdiocb = (struct lpfc_iocbq *) arg;
 
-	lpfc_rcv_logo(phba, ndlp, cmdiocb);
+	lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
 	return ndlp->nlp_state;
 }
 
@@ -1617,9 +1641,16 @@ lpfc_cmpl_plogi_npr_node(struct lpfc_hba * phba,
 			  struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
 {
 	struct lpfc_iocbq *cmdiocb, *rspiocb;
+	IOCB_t *irsp;
 
 	cmdiocb = (struct lpfc_iocbq *) arg;
 	rspiocb = cmdiocb->context_un.rsp_iocb;
+
+	irsp = &rspiocb->iocb;
+	if (irsp->ulpStatus) {
+		lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+		return NLP_STE_FREED_NODE;
+	}
 	return ndlp->nlp_state;
 }
 
@@ -1628,9 +1659,16 @@ lpfc_cmpl_prli_npr_node(struct lpfc_hba * phba,
 			  struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
 {
 	struct lpfc_iocbq *cmdiocb, *rspiocb;
+	IOCB_t *irsp;
 
 	cmdiocb = (struct lpfc_iocbq *) arg;
 	rspiocb = cmdiocb->context_un.rsp_iocb;
+
+	irsp = &rspiocb->iocb;
+	if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
+		lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+		return NLP_STE_FREED_NODE;
+	}
 	return ndlp->nlp_state;
 }
 
@@ -1649,9 +1687,16 @@ lpfc_cmpl_adisc_npr_node(struct lpfc_hba * phba,
 			    uint32_t evt)
 {
 	struct lpfc_iocbq *cmdiocb, *rspiocb;
+	IOCB_t *irsp;
 
 	cmdiocb = (struct lpfc_iocbq *) arg;
 	rspiocb = cmdiocb->context_un.rsp_iocb;
+
+	irsp = &rspiocb->iocb;
+	if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
+		lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+		return NLP_STE_FREED_NODE;
+	}
 	return ndlp->nlp_state;
 }
 
@@ -1668,7 +1713,12 @@ lpfc_cmpl_reglogin_npr_node(struct lpfc_hba * phba,
 
 	if (!mb->mbxStatus)
 		ndlp->nlp_rpi = mb->un.varWords[0];
-
+	else {
+		if (ndlp->nlp_flag & NLP_NODEV_REMOVE) {
+			lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+			return NLP_STE_FREED_NODE;
+		}
+	}
 	return ndlp->nlp_state;
 }
 
@@ -1677,6 +1727,10 @@ lpfc_device_rm_npr_node(struct lpfc_hba * phba,
 			    struct lpfc_nodelist * ndlp, void *arg,
 			    uint32_t evt)
 {
+	if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+		ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+		return ndlp->nlp_state;
+	}
 	lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
 	return NLP_STE_FREED_NODE;
 }
@@ -1687,7 +1741,7 @@ lpfc_device_recov_npr_node(struct lpfc_hba * phba,
 			    uint32_t evt)
 {
 	spin_lock_irq(phba->host->host_lock);
-	ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+	ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
 	spin_unlock_irq(phba->host->host_lock);
 	if (ndlp->nlp_flag & NLP_DELAY_TMO) {
 		lpfc_cancel_retry_delay_tmo(phba, ndlp);
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index f93799873721290c38b774b9668ad5bb0dd91365..7dc4c2e6bed2bbc6ba625be3cf60a32bc83ed291 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -629,8 +629,7 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
 	struct lpfc_iocbq *piocbq;
 	IOCB_t *piocb;
 	struct fcp_cmnd *fcp_cmnd;
-	struct scsi_device *scsi_dev = lpfc_cmd->pCmd->device;
-	struct lpfc_rport_data *rdata = scsi_dev->hostdata;
+	struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
 	struct lpfc_nodelist *ndlp = rdata->pnode;
 
 	if ((ndlp == NULL) || (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
@@ -665,56 +664,18 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
 		piocb->ulpTimeout = lpfc_cmd->timeout;
 	}
 
-	lpfc_cmd->rdata = rdata;
-
-	switch (task_mgmt_cmd) {
-	case FCP_LUN_RESET:
-		/* Issue LUN Reset to TGT <num> LUN <num> */
-		lpfc_printf_log(phba,
-				KERN_INFO,
-				LOG_FCP,
-				"%d:0703 Issue LUN Reset to TGT %d LUN %d "
-				"Data: x%x x%x\n",
-				phba->brd_no,
-				scsi_dev->id, scsi_dev->lun,
-				ndlp->nlp_rpi, ndlp->nlp_flag);
-
-		break;
-	case FCP_ABORT_TASK_SET:
-		/* Issue Abort Task Set to TGT <num> LUN <num> */
-		lpfc_printf_log(phba,
-				KERN_INFO,
-				LOG_FCP,
-				"%d:0701 Issue Abort Task Set to TGT %d LUN %d "
-				"Data: x%x x%x\n",
-				phba->brd_no,
-				scsi_dev->id, scsi_dev->lun,
-				ndlp->nlp_rpi, ndlp->nlp_flag);
-
-		break;
-	case FCP_TARGET_RESET:
-		/* Issue Target Reset to TGT <num> */
-		lpfc_printf_log(phba,
-				KERN_INFO,
-				LOG_FCP,
-				"%d:0702 Issue Target Reset to TGT %d "
-				"Data: x%x x%x\n",
-				phba->brd_no,
-				scsi_dev->id, ndlp->nlp_rpi,
-				ndlp->nlp_flag);
-		break;
-	}
-
 	return (1);
 }
 
 static int
-lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba)
+lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba,
+		    unsigned  tgt_id, struct lpfc_rport_data *rdata)
 {
 	struct lpfc_iocbq *iocbq;
 	struct lpfc_iocbq *iocbqrsp;
 	int ret;
 
+	lpfc_cmd->rdata = rdata;
 	ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, FCP_TARGET_RESET);
 	if (!ret)
 		return FAILED;
@@ -726,6 +687,13 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba)
 	if (!iocbqrsp)
 		return FAILED;
 
+	/* Issue Target Reset to TGT <num> */
+	lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+			"%d:0702 Issue Target Reset to TGT %d "
+			"Data: x%x x%x\n",
+			phba->brd_no, tgt_id, rdata->pnode->nlp_rpi,
+			rdata->pnode->nlp_flag);
+
 	ret = lpfc_sli_issue_iocb_wait(phba,
 				       &phba->sli.ring[phba->sli.fcp_ring],
 				       iocbq, iocbqrsp, lpfc_cmd->timeout);
@@ -1021,6 +989,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
 	lpfc_cmd->pCmd = cmnd;
 	lpfc_cmd->timeout = 60;
 	lpfc_cmd->scsi_hba = phba;
+	lpfc_cmd->rdata = rdata;
 
 	ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, FCP_LUN_RESET);
 	if (!ret)
@@ -1033,6 +1002,11 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
 	if (iocbqrsp == NULL)
 		goto out_free_scsi_buf;
 
+	lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+			"%d:0703 Issue LUN Reset to TGT %d LUN %d "
+			"Data: x%x x%x\n", phba->brd_no, cmnd->device->id,
+			cmnd->device->lun, pnode->nlp_rpi, pnode->nlp_flag);
+
 	ret = lpfc_sli_issue_iocb_wait(phba,
 				       &phba->sli.ring[phba->sli.fcp_ring],
 				       iocbq, iocbqrsp, lpfc_cmd->timeout);
@@ -1104,7 +1078,6 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
 	int match;
 	int ret = FAILED, i, err_count = 0;
 	int cnt, loopcnt;
-	unsigned int midlayer_id = 0;
 	struct lpfc_scsi_buf * lpfc_cmd;
 
 	lpfc_block_requests(phba);
@@ -1124,7 +1097,6 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
 	 * targets known to the driver.  Should any target reset
 	 * fail, this routine returns failure to the midlayer.
 	 */
-	midlayer_id = cmnd->device->id;
 	for (i = 0; i < MAX_FCP_TARGET; i++) {
 		/* Search the mapped list for this target ID */
 		match = 0;
@@ -1137,9 +1109,8 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
 		if (!match)
 			continue;
 
-		lpfc_cmd->pCmd->device->id = i;
-		lpfc_cmd->pCmd->device->hostdata = ndlp->rport->dd_data;
-		ret = lpfc_scsi_tgt_reset(lpfc_cmd, phba);
+		ret = lpfc_scsi_tgt_reset(lpfc_cmd, phba,
+					  i, ndlp->rport->dd_data);
 		if (ret != SUCCESS) {
 			lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
 				"%d:0713 Bus Reset on target %d failed\n",
@@ -1158,7 +1129,6 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
 	 * the targets.  Unfortunately, some targets do not abide by
 	 * this forcing the driver to double check.
 	 */
-	cmnd->device->id = midlayer_id;
 	cnt = lpfc_sli_sum_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
 				0, 0, LPFC_CTX_HOST);
 	if (cnt)
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 4cf1366108b7f0469a703f58f12c62551d1d595b..6b737568b8310cb29bdf717ac00d18d5371de10e 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -18,7 +18,7 @@
  * included with this package.                                     *
  *******************************************************************/
 
-#define LPFC_DRIVER_VERSION "8.1.4"
+#define LPFC_DRIVER_VERSION "8.1.6"
 
 #define LPFC_DRIVER_NAME "lpfc"
 
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 80b68a2481b39210229a4ca7520c015707a06478..de35ffe2f79d04eaa1cf2afb397921d1bd4e0245 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -4471,7 +4471,6 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru)
 {
 	Scsi_Cmnd	*scmd;
 	struct	scsi_device *sdev;
-	unsigned long	flags = 0;
 	scb_t	*scb;
 	int	rval;
 
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index c11e5ce6865e71c18ca6d14fd584b325ffbb1919..bec1424eda850f0f5b121ed9e6fcb15c10506a7b 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -10,7 +10,7 @@
  *	   2 of the License, or (at your option) any later version.
  *
  * FILE		: megaraid_mbox.c
- * Version	: v2.20.4.7 (Nov 14 2005)
+ * Version	: v2.20.4.8 (Apr 11 2006)
  *
  * Authors:
  * 	Atul Mukker		<Atul.Mukker@lsil.com>
@@ -2278,6 +2278,7 @@ megaraid_mbox_dpc(unsigned long devp)
 	unsigned long		flags;
 	uint8_t			c;
 	int			status;
+	uioc_t			*kioc;
 
 
 	if (!adapter) return;
@@ -2320,6 +2321,9 @@ megaraid_mbox_dpc(unsigned long devp)
 			// remove from local clist
 			list_del_init(&scb->list);
 
+			kioc			= (uioc_t *)scb->gp;
+			kioc->status		= 0;
+
 			megaraid_mbox_mm_done(adapter, scb);
 
 			continue;
@@ -2636,6 +2640,7 @@ megaraid_reset_handler(struct scsi_cmnd *scp)
 	int		recovery_window;
 	int		recovering;
 	int		i;
+	uioc_t		*kioc;
 
 	adapter		= SCP2ADAPTER(scp);
 	raid_dev	= ADAP2RAIDDEV(adapter);
@@ -2655,32 +2660,51 @@ megaraid_reset_handler(struct scsi_cmnd *scp)
 	// Also, reset all the commands currently owned by the driver
 	spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);
 	list_for_each_entry_safe(scb, tmp, &adapter->pend_list, list) {
-
 		list_del_init(&scb->list);	// from pending list
 
-		con_log(CL_ANN, (KERN_WARNING
-			"megaraid: %ld:%d[%d:%d], reset from pending list\n",
-				scp->serial_number, scb->sno,
-				scb->dev_channel, scb->dev_target));
+		if (scb->sno >= MBOX_MAX_SCSI_CMDS) {
+			con_log(CL_ANN, (KERN_WARNING
+			"megaraid: IOCTL packet with %d[%d:%d] being reset\n",
+			scb->sno, scb->dev_channel, scb->dev_target));
 
-		scp->result = (DID_RESET << 16);
-		scp->scsi_done(scp);
+			scb->status = -1;
 
-		megaraid_dealloc_scb(adapter, scb);
+			kioc			= (uioc_t *)scb->gp;
+			kioc->status		= -EFAULT;
+
+			megaraid_mbox_mm_done(adapter, scb);
+		} else {
+			if (scb->scp == scp) {	// Found command
+				con_log(CL_ANN, (KERN_WARNING
+					"megaraid: %ld:%d[%d:%d], reset from pending list\n",
+					scp->serial_number, scb->sno,
+					scb->dev_channel, scb->dev_target));
+			} else {
+				con_log(CL_ANN, (KERN_WARNING
+				"megaraid: IO packet with %d[%d:%d] being reset\n",
+				scb->sno, scb->dev_channel, scb->dev_target));
+			}
+
+			scb->scp->result = (DID_RESET << 16);
+			scb->scp->scsi_done(scb->scp);
+
+			megaraid_dealloc_scb(adapter, scb);
+		}
 	}
 	spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);
 
 	if (adapter->outstanding_cmds) {
 		con_log(CL_ANN, (KERN_NOTICE
 			"megaraid: %d outstanding commands. Max wait %d sec\n",
-			adapter->outstanding_cmds, MBOX_RESET_WAIT));
+			adapter->outstanding_cmds,
+			(MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT)));
 	}
 
 	recovery_window = MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT;
 
 	recovering = adapter->outstanding_cmds;
 
-	for (i = 0; i < recovery_window && adapter->outstanding_cmds; i++) {
+	for (i = 0; i < recovery_window; i++) {
 
 		megaraid_ack_sequence(adapter);
 
@@ -2689,12 +2713,11 @@ megaraid_reset_handler(struct scsi_cmnd *scp)
 			con_log(CL_ANN, (
 			"megaraid mbox: Wait for %d commands to complete:%d\n",
 				adapter->outstanding_cmds,
-				MBOX_RESET_WAIT - i));
+				(MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT) - i));
 		}
 
 		// bailout if no recovery happended in reset time
-		if ((i == MBOX_RESET_WAIT) &&
-			(recovering == adapter->outstanding_cmds)) {
+		if (adapter->outstanding_cmds == 0) {
 			break;
 		}
 
@@ -2918,12 +2941,13 @@ mbox_post_sync_cmd_fast(adapter_t *adapter, uint8_t raw_mbox[])
 	wmb();
 	WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1);
 
-	for (i = 0; i < 0xFFFFF; i++) {
+	for (i = 0; i < MBOX_SYNC_WAIT_CNT; i++) {
 		if (mbox->numstatus != 0xFF) break;
 		rmb();
+		udelay(MBOX_SYNC_DELAY_200);
 	}
 
-	if (i == 0xFFFFF) {
+	if (i == MBOX_SYNC_WAIT_CNT) {
 		// We may need to re-calibrate the counter
 		con_log(CL_ANN, (KERN_CRIT
 			"megaraid: fast sync command timed out\n"));
@@ -3475,7 +3499,7 @@ megaraid_cmm_register(adapter_t *adapter)
 	adp.drvr_data		= (unsigned long)adapter;
 	adp.pdev		= adapter->pdev;
 	adp.issue_uioc		= megaraid_mbox_mm_handler;
-	adp.timeout		= 300;
+	adp.timeout		= MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT;
 	adp.max_kioc		= MBOX_MAX_USER_CMDS;
 
 	if ((rval = mraid_mm_register_adp(&adp)) != 0) {
@@ -3702,7 +3726,6 @@ megaraid_mbox_mm_done(adapter_t *adapter, scb_t *scb)
 	unsigned long		flags;
 
 	kioc			= (uioc_t *)scb->gp;
-	kioc->status		= 0;
 	mbox64			= (mbox64_t *)(unsigned long)kioc->cmdbuf;
 	mbox64->mbox32.status	= scb->status;
 	raw_mbox		= (uint8_t *)&mbox64->mbox32;
diff --git a/drivers/scsi/megaraid/megaraid_mbox.h b/drivers/scsi/megaraid/megaraid_mbox.h
index 882fb1a0b57560ca493fc6cc7e16cb2d4e1a0d66..868fb0ec93e70580d5dbeb2920f80bfb0b3145a3 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.h
+++ b/drivers/scsi/megaraid/megaraid_mbox.h
@@ -21,8 +21,8 @@
 #include "megaraid_ioctl.h"
 
 
-#define MEGARAID_VERSION	"2.20.4.7"
-#define MEGARAID_EXT_VERSION	"(Release Date: Mon Nov 14 12:27:22 EST 2005)"
+#define MEGARAID_VERSION	"2.20.4.8"
+#define MEGARAID_EXT_VERSION	"(Release Date: Mon Apr 11 12:27:22 EST 2006)"
 
 
 /*
@@ -100,6 +100,9 @@
 #define MBOX_BUSY_WAIT		10	// max usec to wait for busy mailbox
 #define MBOX_RESET_WAIT		180	// wait these many seconds in reset
 #define MBOX_RESET_EXT_WAIT	120	// extended wait reset
+#define MBOX_SYNC_WAIT_CNT	0xFFFF	// wait loop index for synchronous mode
+
+#define MBOX_SYNC_DELAY_200	200	// 200 micro-seconds
 
 /*
  * maximum transfer that can happen through the firmware commands issued
diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c
index 8f3ce0432295b38424903a339cfb39bb1dee39d8..e8f534fb336bac17c4fd20e2a6fc6fc374046d03 100644
--- a/drivers/scsi/megaraid/megaraid_mm.c
+++ b/drivers/scsi/megaraid/megaraid_mm.c
@@ -898,10 +898,8 @@ mraid_mm_register_adp(mraid_mmadp_t *lld_adp)
 
 	adapter = kmalloc(sizeof(mraid_mmadp_t), GFP_KERNEL);
 
-	if (!adapter) {
-		rval = -ENOMEM;
-		goto memalloc_error;
-	}
+	if (!adapter)
+		return -ENOMEM;
 
 	memset(adapter, 0, sizeof(mraid_mmadp_t));
 
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 017729c59a49957d93b150fe80a85319a9fb5cff..584fe5d8e50789312776a50125d76464e6be2e9b 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -599,6 +599,7 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha)
 *    Either SUCCESS or FAILED.
 *
 * Note:
+*    Only return FAILED if command not returned by firmware.
 **************************************************************************/
 int
 qla2xxx_eh_abort(struct scsi_cmnd *cmd)
@@ -609,11 +610,12 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
 	unsigned int id, lun;
 	unsigned long serial;
 	unsigned long flags;
+	int wait = 0;
 
 	if (!CMD_SP(cmd))
-		return FAILED;
+		return SUCCESS;
 
-	ret = FAILED;
+	ret = SUCCESS;
 
 	id = cmd->device->id;
 	lun = cmd->device->lun;
@@ -642,7 +644,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
 		} else {
 			DEBUG3(printk("%s(%ld): abort_command "
 			    "mbx success.\n", __func__, ha->host_no));
-			ret = SUCCESS;
+			wait = 1;
 		}
 		spin_lock_irqsave(&ha->hardware_lock, flags);
 
@@ -651,17 +653,18 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
 	/* Wait for the command to be returned. */
-	if (ret == SUCCESS) {
+	if (wait) {
 		if (qla2x00_eh_wait_on_command(ha, cmd) != QLA_SUCCESS) {
 			qla_printk(KERN_ERR, ha,
 			    "scsi(%ld:%d:%d): Abort handler timed out -- %lx "
 			    "%x.\n", ha->host_no, id, lun, serial, ret);
+			ret = FAILED;
 		}
 	}
 
 	qla_printk(KERN_INFO, ha,
-	    "scsi(%ld:%d:%d): Abort command issued -- %lx %x.\n", ha->host_no,
-	    id, lun, serial, ret);
+	    "scsi(%ld:%d:%d): Abort command issued -- %d %lx %x.\n",
+	    ha->host_no, id, lun, wait, serial, ret);
 
 	return ret;
 }
@@ -1700,8 +1703,8 @@ qla2x00_free_device(scsi_qla_host_t *ha)
 	ha->flags.online = 0;
 
 	/* Detach interrupts */
-	if (ha->pdev->irq)
-		free_irq(ha->pdev->irq, ha);
+	if (ha->host->irq)
+		free_irq(ha->host->irq, ha);
 
 	/* release io space registers  */
 	if (ha->iobase)
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index c750d3399a97835bbf774a6a2ab5e3dece5f330f..941c1e15c8992cfe19a3fdeb2deddbc424afafa7 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -56,6 +56,8 @@ static struct {
 	{"DENON", "DRD-25X", "V", BLIST_NOLUN},			/* locks up */
 	{"HITACHI", "DK312C", "CM81", BLIST_NOLUN},	/* responds to all lun */
 	{"HITACHI", "DK314C", "CR21", BLIST_NOLUN},	/* responds to all lun */
+	{"IBM", "2104-DU3", NULL, BLIST_NOLUN},		/* locks up */
+	{"IBM", "2104-TU3", NULL, BLIST_NOLUN},		/* locks up */
 	{"IMS", "CDD521/10", "2.06", BLIST_NOLUN},	/* locks up */
 	{"MAXTOR", "XT-3280", "PR02", BLIST_NOLUN},	/* locks up */
 	{"MAXTOR", "XT-4380S", "B3C", BLIST_NOLUN},	/* locks up */
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 7b0f9a3810d2fba1ac0794f820193e9a832e82ae..764a8b375ead1005ff2a49e130f1f80418748be7 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1067,16 +1067,29 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
 			break;
 		case NOT_READY:
 			/*
-			 * If the device is in the process of becoming ready,
-			 * retry.
+			 * If the device is in the process of becoming
+			 * ready, or has a temporary blockage, retry.
 			 */
-			if (sshdr.asc == 0x04 && sshdr.ascq == 0x01) {
-				scsi_requeue_command(q, cmd);
-				return;
+			if (sshdr.asc == 0x04) {
+				switch (sshdr.ascq) {
+				case 0x01: /* becoming ready */
+				case 0x04: /* format in progress */
+				case 0x05: /* rebuild in progress */
+				case 0x06: /* recalculation in progress */
+				case 0x07: /* operation in progress */
+				case 0x08: /* Long write in progress */
+				case 0x09: /* self test in progress */
+					scsi_requeue_command(q, cmd);
+					return;
+				default:
+					break;
+				}
 			}
-			if (!(req->flags & REQ_QUIET))
+			if (!(req->flags & REQ_QUIET)) {
 				scmd_printk(KERN_INFO, cmd,
-					   "Device not ready.\n");
+					   "Device not ready: ");
+				scsi_print_sense_hdr("", &sshdr);
+			}
 			scsi_end_request(cmd, 0, this_count, 1);
 			return;
 		case VOLUME_OVERFLOW:
diff --git a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c
index 3274ab76c8d39bbdd7cedac4362590ce2a698e46..255886a9ac55c29b88660dd4dfdc7f7a09b0ef81 100644
--- a/drivers/scsi/sim710.c
+++ b/drivers/scsi/sim710.c
@@ -75,7 +75,7 @@ param_setup(char *str)
 		else if(!strncmp(pos, "id:", 3)) {
 			if(slot == -1) {
 				printk(KERN_WARNING "sim710: Must specify slot for id parameter\n");
-			} else if(slot > MAX_SLOTS) {
+			} else if(slot >= MAX_SLOTS) {
 				printk(KERN_WARNING "sim710: Illegal slot %d for id %d\n", slot, val);
 			} else {
 				id_array[slot] = val;
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 674b15c78f680ab190b308dbbffaa01fd7482f6c..bbf78aaf9e01f074d15bf6db21042feb9dec5591 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -362,6 +362,40 @@ serial_out(struct uart_8250_port *up, int offset, int value)
 #define serial_inp(up, offset)		serial_in(up, offset)
 #define serial_outp(up, offset, value)	serial_out(up, offset, value)
 
+/* Uart divisor latch read */
+static inline int _serial_dl_read(struct uart_8250_port *up)
+{
+	return serial_inp(up, UART_DLL) | serial_inp(up, UART_DLM) << 8;
+}
+
+/* Uart divisor latch write */
+static inline void _serial_dl_write(struct uart_8250_port *up, int value)
+{
+	serial_outp(up, UART_DLL, value & 0xff);
+	serial_outp(up, UART_DLM, value >> 8 & 0xff);
+}
+
+#ifdef CONFIG_SERIAL_8250_AU1X00
+/* Au1x00 haven't got a standard divisor latch */
+static int serial_dl_read(struct uart_8250_port *up)
+{
+	if (up->port.iotype == UPIO_AU)
+		return __raw_readl(up->port.membase + 0x28);
+	else
+		return _serial_dl_read(up);
+}
+
+static void serial_dl_write(struct uart_8250_port *up, int value)
+{
+	if (up->port.iotype == UPIO_AU)
+		__raw_writel(value, up->port.membase + 0x28);
+	else
+		_serial_dl_write(up, value);
+}
+#else
+#define serial_dl_read(up) _serial_dl_read(up)
+#define serial_dl_write(up, value) _serial_dl_write(up, value)
+#endif
 
 /*
  * For the 16C950
@@ -494,7 +528,8 @@ static void disable_rsa(struct uart_8250_port *up)
  */
 static int size_fifo(struct uart_8250_port *up)
 {
-	unsigned char old_fcr, old_mcr, old_dll, old_dlm, old_lcr;
+	unsigned char old_fcr, old_mcr, old_lcr;
+	unsigned short old_dl;
 	int count;
 
 	old_lcr = serial_inp(up, UART_LCR);
@@ -505,10 +540,8 @@ static int size_fifo(struct uart_8250_port *up)
 		    UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
 	serial_outp(up, UART_MCR, UART_MCR_LOOP);
 	serial_outp(up, UART_LCR, UART_LCR_DLAB);
-	old_dll = serial_inp(up, UART_DLL);
-	old_dlm = serial_inp(up, UART_DLM);
-	serial_outp(up, UART_DLL, 0x01);
-	serial_outp(up, UART_DLM, 0x00);
+	old_dl = serial_dl_read(up);
+	serial_dl_write(up, 0x0001);
 	serial_outp(up, UART_LCR, 0x03);
 	for (count = 0; count < 256; count++)
 		serial_outp(up, UART_TX, count);
@@ -519,8 +552,7 @@ static int size_fifo(struct uart_8250_port *up)
 	serial_outp(up, UART_FCR, old_fcr);
 	serial_outp(up, UART_MCR, old_mcr);
 	serial_outp(up, UART_LCR, UART_LCR_DLAB);
-	serial_outp(up, UART_DLL, old_dll);
-	serial_outp(up, UART_DLM, old_dlm);
+	serial_dl_write(up, old_dl);
 	serial_outp(up, UART_LCR, old_lcr);
 
 	return count;
@@ -750,8 +782,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
 
 			serial_outp(up, UART_LCR, 0xE0);
 
-			quot = serial_inp(up, UART_DLM) << 8;
-			quot += serial_inp(up, UART_DLL);
+			quot = serial_dl_read(up);
 			quot <<= 3;
 
 			status1 = serial_in(up, 0x04); /* EXCR1 */
@@ -759,8 +790,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
 			status1 |= 0x10;  /* 1.625 divisor for baud_base --> 921600 */
 			serial_outp(up, 0x04, status1);
 			
-			serial_outp(up, UART_DLL, quot & 0xff);
-			serial_outp(up, UART_DLM, quot >> 8);
+			serial_dl_write(up, quot);
 
 			serial_outp(up, UART_LCR, 0);
 
@@ -1862,8 +1892,7 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios,
 		serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
 	}
 
-	serial_outp(up, UART_DLL, quot & 0xff);		/* LS of divisor */
-	serial_outp(up, UART_DLM, quot >> 8);		/* MS of divisor */
+	serial_dl_write(up, quot);
 
 	/*
 	 * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
@@ -1906,6 +1935,9 @@ static int serial8250_request_std_resource(struct uart_8250_port *up)
 	int ret = 0;
 
 	switch (up->port.iotype) {
+	case UPIO_AU:
+		size = 0x100000;
+		/* fall thru */
 	case UPIO_MEM:
 		if (!up->port.mapbase)
 			break;
@@ -1938,6 +1970,9 @@ static void serial8250_release_std_resource(struct uart_8250_port *up)
 	unsigned int size = 8 << up->port.regshift;
 
 	switch (up->port.iotype) {
+	case UPIO_AU:
+		size = 0x100000;
+		/* fall thru */
 	case UPIO_MEM:
 		if (!up->port.mapbase)
 			break;
@@ -2200,10 +2235,17 @@ static void
 serial8250_console_write(struct console *co, const char *s, unsigned int count)
 {
 	struct uart_8250_port *up = &serial8250_ports[co->index];
+	unsigned long flags;
 	unsigned int ier;
+	int locked = 1;
 
 	touch_nmi_watchdog();
 
+	if (oops_in_progress) {
+		locked = spin_trylock_irqsave(&up->port.lock, flags);
+	} else
+		spin_lock_irqsave(&up->port.lock, flags);
+
 	/*
 	 *	First save the IER then disable the interrupts
 	 */
@@ -2221,8 +2263,10 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
 	 *	and restore the IER
 	 */
 	wait_for_xmitr(up, BOTH_EMPTY);
-	up->ier |= UART_IER_THRI;
-	serial_out(up, UART_IER, ier | UART_IER_THRI);
+	serial_out(up, UART_IER, ier);
+
+	if (locked)
+		spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
 static int serial8250_console_setup(struct console *co, char *options)
diff --git a/drivers/serial/8250_au1x00.c b/drivers/serial/8250_au1x00.c
index 3d1bfd07208df18cd9634b870ca430a23077ce43..58015fd14be9ec42d1b606cb103a515a751ee4b1 100644
--- a/drivers/serial/8250_au1x00.c
+++ b/drivers/serial/8250_au1x00.c
@@ -30,13 +30,12 @@
 	{						\
 		.iobase		= _base,		\
 		.membase	= (void __iomem *)_base,\
-		.mapbase	= _base,		\
+		.mapbase	= CPHYSADDR(_base),	\
 		.irq		= _irq,			\
 		.uartclk	= 0,	/* filled */	\
 		.regshift	= 2,			\
 		.iotype		= UPIO_AU,		\
-		.flags		= UPF_SKIP_TEST | 	\
-				  UPF_IOREMAP,		\
+		.flags		= UPF_SKIP_TEST 	\
 	}
 
 static struct plat_serial8250_port au1x00_data[] = {
diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h
index aa5eb7ddeda9adf3b41a61ecbc716502fb2392c0..3b35cb779539a891c40b433411a0111ac4226daa 100644
--- a/drivers/serial/cpm_uart/cpm_uart.h
+++ b/drivers/serial/cpm_uart/cpm_uart.h
@@ -5,6 +5,13 @@
  *
  *  Copyright (C) 2004 Freescale Semiconductor, Inc.
  *
+ *  2006 (c) MontaVista Software, Inc.
+ * 	Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
  */
 #ifndef CPM_UART_H
 #define CPM_UART_H
@@ -101,12 +108,13 @@ static inline unsigned long cpu2cpm_addr(void* addr, struct uart_cpm_port *pinfo
 	int offset;
 	u32 val = (u32)addr;
 	/* sane check */
-	if ((val >= (u32)pinfo->mem_addr) &&
+	if (likely((val >= (u32)pinfo->mem_addr)) &&
 			(val<((u32)pinfo->mem_addr + pinfo->mem_size))) {
 		offset = val - (u32)pinfo->mem_addr;
 		return pinfo->dma_addr+offset;
 	}
-	printk("%s(): address %x to translate out of range!\n", __FUNCTION__, val);
+	/* something nasty happened */
+	BUG();
 	return 0;
 }
 
@@ -115,12 +123,13 @@ static inline void *cpm2cpu_addr(unsigned long addr, struct uart_cpm_port *pinfo
 	int offset;
 	u32 val = addr;
 	/* sane check */
-	if ((val >= pinfo->dma_addr) &&
-			(val<(pinfo->dma_addr + pinfo->mem_size))) {
+	if (likely((val >= pinfo->dma_addr) &&
+			(val<(pinfo->dma_addr + pinfo->mem_size)))) {
 		offset = val - (u32)pinfo->dma_addr;
 		return (void*)(pinfo->mem_addr+offset);
 	}
-	printk("%s(): address %x to translate out of range!\n", __FUNCTION__, val);
+	/* something nasty happened */
+	BUG();
 	return 0;
 }
 
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index ced193bf9e1ebbcec6df30924f8c8285cc079970..969f949004318b1080f16643fd0b07d41f280d53 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -12,7 +12,8 @@
  *
  *  Copyright (C) 2004 Freescale Semiconductor, Inc.
  *            (C) 2004 Intracom, S.A.
- *            (C) 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@ru.mvista.com>
+ *            (C) 2005-2006 MontaVista Software, Inc.
+ * 		Vitaly Bordug <vbordug@ru.mvista.com>
  *
  * 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
@@ -81,7 +82,7 @@ early_uart_get_pdev(int index)
 }
 
 
-void cpm_uart_count(void)
+static void cpm_uart_count(void)
 {
 	cpm_uart_nr = 0;
 #ifdef CONFIG_SERIAL_CPM_SMC1
@@ -104,6 +105,21 @@ void cpm_uart_count(void)
 #endif
 }
 
+/* Get UART number by its id */
+static int cpm_uart_id2nr(int id)
+{
+	int i;
+	if (id < UART_NR) {
+		for (i=0; i<UART_NR; i++) {
+			if (cpm_uart_port_map[i] == id)
+				return i;
+		}
+	}
+
+	/* not found or invalid argument */
+	return -1;
+}
+
 /*
  * Check, if transmit buffers are processed
 */
@@ -457,7 +473,11 @@ static void cpm_uart_shutdown(struct uart_port *port)
 		}
 
 		/* Shut them really down and reinit buffer descriptors */
-		cpm_line_cr_cmd(line, CPM_CR_STOP_TX);
+		if (IS_SMC(pinfo))
+			cpm_line_cr_cmd(line, CPM_CR_STOP_TX);
+		else
+			cpm_line_cr_cmd(line, CPM_CR_GRA_STOP_TX);
+
 		cpm_uart_initbd(pinfo);
 	}
 }
@@ -1008,7 +1028,11 @@ int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con)
 	int line;
 	u32 mem, pram;
 
-	for (line=0; line<UART_NR && cpm_uart_port_map[line]!=pdata->fs_no; line++);
+	line = cpm_uart_id2nr(idx);
+	if(line < 0) {
+		printk(KERN_ERR"%s(): port %d is not registered", __FUNCTION__, idx);
+		return -1;
+	}
 
 	pinfo = (struct uart_cpm_port *) &cpm_uart_ports[idx];
 
@@ -1241,8 +1265,7 @@ static int cpm_uart_drv_probe(struct device *dev)
 	}
 
 	pdata = pdev->dev.platform_data;
-	pr_debug("cpm_uart_drv_probe: Adding CPM UART %d\n",
-			cpm_uart_port_map[pdata->fs_no]);
+	pr_debug("cpm_uart_drv_probe: Adding CPM UART %d\n", cpm_uart_id2nr(pdata->fs_no));
 
 	if ((ret = cpm_uart_drv_get_platform_data(pdev, 0)))
 		return ret;
@@ -1261,7 +1284,7 @@ static int cpm_uart_drv_remove(struct device *dev)
 	struct fs_uart_platform_info *pdata = pdev->dev.platform_data;
 
 	pr_debug("cpm_uart_drv_remove: Removing CPM UART %d\n",
-			cpm_uart_port_map[pdata->fs_no]);
+			cpm_uart_id2nr(pdata->fs_no));
 
         uart_remove_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port);
         return 0;
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
index a5a30622637a33d1ed80dbacbbdd41b33b1d0d37..17406a05ce1f8f0336e509e9d5917e9ba1a9898b 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
@@ -8,6 +8,8 @@
  *
  *  Copyright (C) 2004 Freescale Semiconductor, Inc.
  *            (C) 2004 Intracom, S.A.
+ *            (C) 2006 MontaVista Software, Inc.
+ * 		Vitaly Bordug <vbordug@ru.mvista.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
index 7c6b07aeea9254cf2ca2f214e372af9615ab1a35..4b2de08f46d0ef7f58462e3144326743c3a6390f 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
@@ -8,6 +8,8 @@
  * 
  *  Copyright (C) 2004 Freescale Semiconductor, Inc.
  *            (C) 2004 Intracom, S.A.
+ *            (C) 2006 MontaVista Software, Inc.
+ * 		Vitaly Bordug <vbordug@ru.mvista.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index c3b7a6673e9c81a8bea851513c61fc900b552fde..d202eb4f3848f0cade4b4b2ed841f34f76703241 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -45,6 +45,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/hardware.h>
+#include <asm/arch/imx-uart.h>
 
 /* We've been assigned a range on the "Low-density serial ports" major */
 #define SERIAL_IMX_MAJOR	204
@@ -73,7 +74,8 @@ struct imx_port {
 	struct uart_port	port;
 	struct timer_list	timer;
 	unsigned int		old_status;
-	int txirq,rxirq,rtsirq;
+	int			txirq,rxirq,rtsirq;
+	int			have_rtscts:1;
 };
 
 /*
@@ -491,8 +493,12 @@ imx_set_termios(struct uart_port *port, struct termios *termios,
 		ucr2 = UCR2_SRST | UCR2_IRTS;
 
 	if (termios->c_cflag & CRTSCTS) {
-		ucr2 &= ~UCR2_IRTS;
-		ucr2 |= UCR2_CTSC;
+		if( sport->have_rtscts ) {
+			ucr2 &= ~UCR2_IRTS;
+			ucr2 |= UCR2_CTSC;
+		} else {
+			termios->c_cflag &= ~CRTSCTS;
+		}
 	}
 
 	if (termios->c_cflag & CSTOPB)
@@ -719,27 +725,6 @@ static void __init imx_init_ports(void)
 		imx_ports[i].timer.function = imx_timeout;
 		imx_ports[i].timer.data     = (unsigned long)&imx_ports[i];
 	}
-
-	imx_gpio_mode(PC9_PF_UART1_CTS);
-	imx_gpio_mode(PC10_PF_UART1_RTS);
-	imx_gpio_mode(PC11_PF_UART1_TXD);
-	imx_gpio_mode(PC12_PF_UART1_RXD);
-	imx_gpio_mode(PB28_PF_UART2_CTS);
-	imx_gpio_mode(PB29_PF_UART2_RTS);
-
-	imx_gpio_mode(PB30_PF_UART2_TXD);
-	imx_gpio_mode(PB31_PF_UART2_RXD);
-
-#if 0 /* We don't need these, on the mx1 the _modem_ side of the uart
-       * is implemented.
-       */
-	imx_gpio_mode(PD7_AF_UART2_DTR);
-	imx_gpio_mode(PD8_AF_UART2_DCD);
-	imx_gpio_mode(PD9_AF_UART2_RI);
-	imx_gpio_mode(PD10_AF_UART2_DSR);
-#endif
-
-
 }
 
 #ifdef CONFIG_SERIAL_IMX_CONSOLE
@@ -932,7 +917,14 @@ static int serial_imx_resume(struct platform_device *dev)
 
 static int serial_imx_probe(struct platform_device *dev)
 {
+	struct imxuart_platform_data *pdata;
+
 	imx_ports[dev->id].port.dev = &dev->dev;
+
+	pdata = (struct imxuart_platform_data *)dev->dev.platform_data;
+	if(pdata && (pdata->flags & IMXUART_HAVE_RTSCTS))
+		imx_ports[dev->id].have_rtscts = 1;
+
 	uart_add_one_port(&imx_reg, &imx_ports[dev->id].port);
 	platform_set_drvdata(dev, &imx_ports[dev->id]);
 	return 0;
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index fcd7744c4253fa390b28806baf3b093d97d82339..17839e753e4cfb1fb550832d8613b0ec579c83ef 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -1500,20 +1500,18 @@ uart_block_til_ready(struct file *filp, struct uart_state *state)
 static struct uart_state *uart_get(struct uart_driver *drv, int line)
 {
 	struct uart_state *state;
+	int ret = 0;
 
-	mutex_lock(&port_mutex);
 	state = drv->state + line;
 	if (mutex_lock_interruptible(&state->mutex)) {
-		state = ERR_PTR(-ERESTARTSYS);
-		goto out;
+		ret = -ERESTARTSYS;
+		goto err;
 	}
 
 	state->count++;
-	if (!state->port) {
-		state->count--;
-		mutex_unlock(&state->mutex);
-		state = ERR_PTR(-ENXIO);
-		goto out;
+	if (!state->port || state->port->flags & UPF_DEAD) {
+		ret = -ENXIO;
+		goto err_unlock;
 	}
 
 	if (!state->info) {
@@ -1531,15 +1529,17 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line)
 			tasklet_init(&state->info->tlet, uart_tasklet_action,
 				     (unsigned long)state);
 		} else {
-			state->count--;
-			mutex_unlock(&state->mutex);
-			state = ERR_PTR(-ENOMEM);
+			ret = -ENOMEM;
+			goto err_unlock;
 		}
 	}
-
- out:
-	mutex_unlock(&port_mutex);
 	return state;
+
+ err_unlock:
+	state->count--;
+	mutex_unlock(&state->mutex);
+ err:
+	return ERR_PTR(ret);
 }
 
 /*
@@ -1907,9 +1907,12 @@ uart_set_options(struct uart_port *port, struct console *co,
 static void uart_change_pm(struct uart_state *state, int pm_state)
 {
 	struct uart_port *port = state->port;
-	if (port->ops->pm)
-		port->ops->pm(port, pm_state, state->pm_state);
-	state->pm_state = pm_state;
+
+	if (state->pm_state != pm_state) {
+		if (port->ops->pm)
+			port->ops->pm(port, pm_state, state->pm_state);
+		state->pm_state = pm_state;
+	}
 }
 
 int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
@@ -2085,45 +2088,6 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
 	}
 }
 
-/*
- * This reverses the effects of uart_configure_port, hanging up the
- * port before removal.
- */
-static void
-uart_unconfigure_port(struct uart_driver *drv, struct uart_state *state)
-{
-	struct uart_port *port = state->port;
-	struct uart_info *info = state->info;
-
-	if (info && info->tty)
-		tty_vhangup(info->tty);
-
-	mutex_lock(&state->mutex);
-
-	state->info = NULL;
-
-	/*
-	 * Free the port IO and memory resources, if any.
-	 */
-	if (port->type != PORT_UNKNOWN)
-		port->ops->release_port(port);
-
-	/*
-	 * Indicate that there isn't a port here anymore.
-	 */
-	port->type = PORT_UNKNOWN;
-
-	/*
-	 * Kill the tasklet, and free resources.
-	 */
-	if (info) {
-		tasklet_kill(&info->tlet);
-		kfree(info);
-	}
-
-	mutex_unlock(&state->mutex);
-}
-
 static struct tty_operations uart_ops = {
 	.open		= uart_open,
 	.close		= uart_close,
@@ -2270,6 +2234,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
 	state = drv->state + port->line;
 
 	mutex_lock(&port_mutex);
+	mutex_lock(&state->mutex);
 	if (state->port) {
 		ret = -EINVAL;
 		goto out;
@@ -2304,7 +2269,13 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
 	    port->cons && !(port->cons->flags & CON_ENABLED))
 		register_console(port->cons);
 
+	/*
+	 * Ensure UPF_DEAD is not set.
+	 */
+	port->flags &= ~UPF_DEAD;
+
  out:
+	mutex_unlock(&state->mutex);
 	mutex_unlock(&port_mutex);
 
 	return ret;
@@ -2322,6 +2293,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
 int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
 {
 	struct uart_state *state = drv->state + port->line;
+	struct uart_info *info;
 
 	BUG_ON(in_interrupt());
 
@@ -2331,12 +2303,49 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
 
 	mutex_lock(&port_mutex);
 
+	/*
+	 * Mark the port "dead" - this prevents any opens from
+	 * succeeding while we shut down the port.
+	 */
+	mutex_lock(&state->mutex);
+	port->flags |= UPF_DEAD;
+	mutex_unlock(&state->mutex);
+
 	/*
 	 * Remove the devices from devfs
 	 */
 	tty_unregister_device(drv->tty_driver, port->line);
 
-	uart_unconfigure_port(drv, state);
+	info = state->info;
+	if (info && info->tty)
+		tty_vhangup(info->tty);
+
+	/*
+	 * All users of this port should now be disconnected from
+	 * this driver, and the port shut down.  We should be the
+	 * only thread fiddling with this port from now on.
+	 */
+	state->info = NULL;
+
+	/*
+	 * Free the port IO and memory resources, if any.
+	 */
+	if (port->type != PORT_UNKNOWN)
+		port->ops->release_port(port);
+
+	/*
+	 * Indicate that there isn't a port here anymore.
+	 */
+	port->type = PORT_UNKNOWN;
+
+	/*
+	 * Kill the tasklet, and free resources.
+	 */
+	if (info) {
+		tasklet_kill(&info->tlet);
+		kfree(info);
+	}
+
 	state->port = NULL;
 	mutex_unlock(&port_mutex);
 
diff --git a/drivers/sn/ioc4.c b/drivers/sn/ioc4.c
index 67140a5804f574b97eb6a8823f3affb3b2088830..cdeff909403e8f831870814b945df11a5e8cb4b2 100644
--- a/drivers/sn/ioc4.c
+++ b/drivers/sn/ioc4.c
@@ -310,7 +310,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
 	pci_set_drvdata(idd->idd_pdev, idd);
 
 	mutex_lock(&ioc4_mutex);
-	list_add(&idd->idd_list, &ioc4_devices);
+	list_add_tail(&idd->idd_list, &ioc4_devices);
 
 	/* Add this IOC4 to all submodules */
 	list_for_each_entry(is, &ioc4_submodules, is_list) {
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 7a75faeb0526d6f89c37dbe854c52b5cddd5ebeb..9ce1d01469b19d3c93e61193bd8bce400b9206a8 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -75,6 +75,14 @@ config SPI_BUTTERFLY
 	  inexpensive battery powered microcontroller evaluation board.
 	  This same cable can be used to flash new firmware.
 
+config SPI_PXA2XX
+	tristate "PXA2xx SSP SPI master"
+	depends on SPI_MASTER && ARCH_PXA && EXPERIMENTAL
+	help
+	  This enables using a PXA2xx SSP port as a SPI master controller.
+	  The driver can be configured to use any SSP port and additional
+	  documentation can be found a Documentation/spi/pxa2xx.
+
 #
 # Add new SPI master controllers in alphabetical order above this line
 #
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index c2c87e845abf8d71f3742f29fc16b664d2493d09..1bca5f95de251d00c4775a8e3898da2751b29102 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_SPI_MASTER)		+= spi.o
 # SPI master controller drivers (bus)
 obj-$(CONFIG_SPI_BITBANG)		+= spi_bitbang.o
 obj-$(CONFIG_SPI_BUTTERFLY)		+= spi_butterfly.o
+obj-$(CONFIG_SPI_PXA2XX)		+= pxa2xx_spi.o
 # 	... add above this line ...
 
 # SPI protocol drivers (device/link on bus)
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
new file mode 100644
index 0000000000000000000000000000000000000000..596bf820b70c655b9720093e81936ec25f393d99
--- /dev/null
+++ b/drivers/spi/pxa2xx_spi.c
@@ -0,0 +1,1467 @@
+/*
+ * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/spi/spi.h>
+#include <linux/workqueue.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/delay.h>
+#include <asm/dma.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx_spi.h>
+
+MODULE_AUTHOR("Stephen Street");
+MODULE_DESCRIPTION("PXA2xx SSP SPI Contoller");
+MODULE_LICENSE("GPL");
+
+#define MAX_BUSES 3
+
+#define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
+#define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK)
+#define IS_DMA_ALIGNED(x) (((u32)(x)&0x07)==0)
+
+#define DEFINE_SSP_REG(reg, off) \
+static inline u32 read_##reg(void *p) { return __raw_readl(p + (off)); } \
+static inline void write_##reg(u32 v, void *p) { __raw_writel(v, p + (off)); }
+
+DEFINE_SSP_REG(SSCR0, 0x00)
+DEFINE_SSP_REG(SSCR1, 0x04)
+DEFINE_SSP_REG(SSSR, 0x08)
+DEFINE_SSP_REG(SSITR, 0x0c)
+DEFINE_SSP_REG(SSDR, 0x10)
+DEFINE_SSP_REG(SSTO, 0x28)
+DEFINE_SSP_REG(SSPSP, 0x2c)
+
+#define START_STATE ((void*)0)
+#define RUNNING_STATE ((void*)1)
+#define DONE_STATE ((void*)2)
+#define ERROR_STATE ((void*)-1)
+
+#define QUEUE_RUNNING 0
+#define QUEUE_STOPPED 1
+
+struct driver_data {
+	/* Driver model hookup */
+	struct platform_device *pdev;
+
+	/* SPI framework hookup */
+	enum pxa_ssp_type ssp_type;
+	struct spi_master *master;
+
+	/* PXA hookup */
+	struct pxa2xx_spi_master *master_info;
+
+	/* DMA setup stuff */
+	int rx_channel;
+	int tx_channel;
+	u32 *null_dma_buf;
+
+	/* SSP register addresses */
+	void *ioaddr;
+	u32 ssdr_physical;
+
+	/* SSP masks*/
+	u32 dma_cr1;
+	u32 int_cr1;
+	u32 clear_sr;
+	u32 mask_sr;
+
+	/* Driver message queue */
+	struct workqueue_struct	*workqueue;
+	struct work_struct pump_messages;
+	spinlock_t lock;
+	struct list_head queue;
+	int busy;
+	int run;
+
+	/* Message Transfer pump */
+	struct tasklet_struct pump_transfers;
+
+	/* Current message transfer state info */
+	struct spi_message* cur_msg;
+	struct spi_transfer* cur_transfer;
+	struct chip_data *cur_chip;
+	size_t len;
+	void *tx;
+	void *tx_end;
+	void *rx;
+	void *rx_end;
+	int dma_mapped;
+	dma_addr_t rx_dma;
+	dma_addr_t tx_dma;
+	size_t rx_map_len;
+	size_t tx_map_len;
+	u8 n_bytes;
+	u32 dma_width;
+	int cs_change;
+	void (*write)(struct driver_data *drv_data);
+	void (*read)(struct driver_data *drv_data);
+	irqreturn_t (*transfer_handler)(struct driver_data *drv_data);
+	void (*cs_control)(u32 command);
+};
+
+struct chip_data {
+	u32 cr0;
+	u32 cr1;
+	u32 to;
+	u32 psp;
+	u32 timeout;
+	u8 n_bytes;
+	u32 dma_width;
+	u32 dma_burst_size;
+	u32 threshold;
+	u32 dma_threshold;
+	u8 enable_dma;
+	u8 bits_per_word;
+	u32 speed_hz;
+	void (*write)(struct driver_data *drv_data);
+	void (*read)(struct driver_data *drv_data);
+	void (*cs_control)(u32 command);
+};
+
+static void pump_messages(void *data);
+
+static int flush(struct driver_data *drv_data)
+{
+	unsigned long limit = loops_per_jiffy << 1;
+
+	void *reg = drv_data->ioaddr;
+
+	do {
+		while (read_SSSR(reg) & SSSR_RNE) {
+			read_SSDR(reg);
+		}
+	} while ((read_SSSR(reg) & SSSR_BSY) && limit--);
+	write_SSSR(SSSR_ROR, reg);
+
+	return limit;
+}
+
+static void restore_state(struct driver_data *drv_data)
+{
+	void *reg = drv_data->ioaddr;
+
+	/* Clear status and disable clock */
+	write_SSSR(drv_data->clear_sr, reg);
+	write_SSCR0(drv_data->cur_chip->cr0 & ~SSCR0_SSE, reg);
+
+	/* Load the registers */
+	write_SSCR1(drv_data->cur_chip->cr1, reg);
+	write_SSCR0(drv_data->cur_chip->cr0, reg);
+	if (drv_data->ssp_type != PXA25x_SSP) {
+		write_SSTO(0, reg);
+		write_SSPSP(drv_data->cur_chip->psp, reg);
+	}
+}
+
+static void null_cs_control(u32 command)
+{
+}
+
+static void null_writer(struct driver_data *drv_data)
+{
+	void *reg = drv_data->ioaddr;
+	u8 n_bytes = drv_data->n_bytes;
+
+	while ((read_SSSR(reg) & SSSR_TNF)
+			&& (drv_data->tx < drv_data->tx_end)) {
+		write_SSDR(0, reg);
+		drv_data->tx += n_bytes;
+	}
+}
+
+static void null_reader(struct driver_data *drv_data)
+{
+	void *reg = drv_data->ioaddr;
+	u8 n_bytes = drv_data->n_bytes;
+
+	while ((read_SSSR(reg) & SSSR_RNE)
+			&& (drv_data->rx < drv_data->rx_end)) {
+		read_SSDR(reg);
+		drv_data->rx += n_bytes;
+	}
+}
+
+static void u8_writer(struct driver_data *drv_data)
+{
+	void *reg = drv_data->ioaddr;
+
+	while ((read_SSSR(reg) & SSSR_TNF)
+			&& (drv_data->tx < drv_data->tx_end)) {
+		write_SSDR(*(u8 *)(drv_data->tx), reg);
+		++drv_data->tx;
+	}
+}
+
+static void u8_reader(struct driver_data *drv_data)
+{
+	void *reg = drv_data->ioaddr;
+
+	while ((read_SSSR(reg) & SSSR_RNE)
+			&& (drv_data->rx < drv_data->rx_end)) {
+		*(u8 *)(drv_data->rx) = read_SSDR(reg);
+		++drv_data->rx;
+	}
+}
+
+static void u16_writer(struct driver_data *drv_data)
+{
+	void *reg = drv_data->ioaddr;
+
+	while ((read_SSSR(reg) & SSSR_TNF)
+			&& (drv_data->tx < drv_data->tx_end)) {
+		write_SSDR(*(u16 *)(drv_data->tx), reg);
+		drv_data->tx += 2;
+	}
+}
+
+static void u16_reader(struct driver_data *drv_data)
+{
+	void *reg = drv_data->ioaddr;
+
+	while ((read_SSSR(reg) & SSSR_RNE)
+			&& (drv_data->rx < drv_data->rx_end)) {
+		*(u16 *)(drv_data->rx) = read_SSDR(reg);
+		drv_data->rx += 2;
+	}
+}
+static void u32_writer(struct driver_data *drv_data)
+{
+	void *reg = drv_data->ioaddr;
+
+	while ((read_SSSR(reg) & SSSR_TNF)
+			&& (drv_data->tx < drv_data->tx_end)) {
+		write_SSDR(*(u32 *)(drv_data->tx), reg);
+		drv_data->tx += 4;
+	}
+}
+
+static void u32_reader(struct driver_data *drv_data)
+{
+	void *reg = drv_data->ioaddr;
+
+	while ((read_SSSR(reg) & SSSR_RNE)
+			&& (drv_data->rx < drv_data->rx_end)) {
+		*(u32 *)(drv_data->rx) = read_SSDR(reg);
+		drv_data->rx += 4;
+	}
+}
+
+static void *next_transfer(struct driver_data *drv_data)
+{
+	struct spi_message *msg = drv_data->cur_msg;
+	struct spi_transfer *trans = drv_data->cur_transfer;
+
+	/* Move to next transfer */
+	if (trans->transfer_list.next != &msg->transfers) {
+		drv_data->cur_transfer =
+			list_entry(trans->transfer_list.next,
+					struct spi_transfer,
+					transfer_list);
+		return RUNNING_STATE;
+	} else
+		return DONE_STATE;
+}
+
+static int map_dma_buffers(struct driver_data *drv_data)
+{
+	struct spi_message *msg = drv_data->cur_msg;
+	struct device *dev = &msg->spi->dev;
+
+	if (!drv_data->cur_chip->enable_dma)
+		return 0;
+
+	if (msg->is_dma_mapped)
+		return  drv_data->rx_dma && drv_data->tx_dma;
+
+	if (!IS_DMA_ALIGNED(drv_data->rx) || !IS_DMA_ALIGNED(drv_data->tx))
+		return 0;
+
+	/* Modify setup if rx buffer is null */
+	if (drv_data->rx == NULL) {
+		*drv_data->null_dma_buf = 0;
+		drv_data->rx = drv_data->null_dma_buf;
+		drv_data->rx_map_len = 4;
+	} else
+		drv_data->rx_map_len = drv_data->len;
+
+
+	/* Modify setup if tx buffer is null */
+	if (drv_data->tx == NULL) {
+		*drv_data->null_dma_buf = 0;
+		drv_data->tx = drv_data->null_dma_buf;
+		drv_data->tx_map_len = 4;
+	} else
+		drv_data->tx_map_len = drv_data->len;
+
+	/* Stream map the rx buffer */
+	drv_data->rx_dma = dma_map_single(dev, drv_data->rx,
+						drv_data->rx_map_len,
+						DMA_FROM_DEVICE);
+	if (dma_mapping_error(drv_data->rx_dma))
+		return 0;
+
+	/* Stream map the tx buffer */
+	drv_data->tx_dma = dma_map_single(dev, drv_data->tx,
+						drv_data->tx_map_len,
+						DMA_TO_DEVICE);
+
+	if (dma_mapping_error(drv_data->tx_dma)) {
+		dma_unmap_single(dev, drv_data->rx_dma,
+					drv_data->rx_map_len, DMA_FROM_DEVICE);
+		return 0;
+	}
+
+	return 1;
+}
+
+static void unmap_dma_buffers(struct driver_data *drv_data)
+{
+	struct device *dev;
+
+	if (!drv_data->dma_mapped)
+		return;
+
+	if (!drv_data->cur_msg->is_dma_mapped) {
+		dev = &drv_data->cur_msg->spi->dev;
+		dma_unmap_single(dev, drv_data->rx_dma,
+					drv_data->rx_map_len, DMA_FROM_DEVICE);
+		dma_unmap_single(dev, drv_data->tx_dma,
+					drv_data->tx_map_len, DMA_TO_DEVICE);
+	}
+
+	drv_data->dma_mapped = 0;
+}
+
+/* caller already set message->status; dma and pio irqs are blocked */
+static void giveback(struct spi_message *message, struct driver_data *drv_data)
+{
+	struct spi_transfer* last_transfer;
+
+	last_transfer = list_entry(message->transfers.prev,
+					struct spi_transfer,
+					transfer_list);
+
+	if (!last_transfer->cs_change)
+		drv_data->cs_control(PXA2XX_CS_DEASSERT);
+
+	message->state = NULL;
+	if (message->complete)
+		message->complete(message->context);
+
+	drv_data->cur_msg = NULL;
+	drv_data->cur_transfer = NULL;
+	drv_data->cur_chip = NULL;
+	queue_work(drv_data->workqueue, &drv_data->pump_messages);
+}
+
+static int wait_ssp_rx_stall(void *ioaddr)
+{
+	unsigned long limit = loops_per_jiffy << 1;
+
+	while ((read_SSSR(ioaddr) & SSSR_BSY) && limit--)
+		cpu_relax();
+
+	return limit;
+}
+
+static int wait_dma_channel_stop(int channel)
+{
+	unsigned long limit = loops_per_jiffy << 1;
+
+	while (!(DCSR(channel) & DCSR_STOPSTATE) && limit--)
+		cpu_relax();
+
+	return limit;
+}
+
+static void dma_handler(int channel, void *data, struct pt_regs *regs)
+{
+	struct driver_data *drv_data = data;
+	struct spi_message *msg = drv_data->cur_msg;
+	void *reg = drv_data->ioaddr;
+	u32 irq_status = DCSR(channel) & DMA_INT_MASK;
+	u32 trailing_sssr = 0;
+
+	if (irq_status & DCSR_BUSERR) {
+
+		/* Disable interrupts, clear status and reset DMA */
+		if (drv_data->ssp_type != PXA25x_SSP)
+			write_SSTO(0, reg);
+		write_SSSR(drv_data->clear_sr, reg);
+		write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
+		DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
+		DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
+
+		if (flush(drv_data) == 0)
+			dev_err(&drv_data->pdev->dev,
+					"dma_handler: flush fail\n");
+
+		unmap_dma_buffers(drv_data);
+
+		if (channel == drv_data->tx_channel)
+			dev_err(&drv_data->pdev->dev,
+				"dma_handler: bad bus address on "
+				"tx channel %d, source %x target = %x\n",
+				channel, DSADR(channel), DTADR(channel));
+		else
+			dev_err(&drv_data->pdev->dev,
+				"dma_handler: bad bus address on "
+				"rx channel %d, source %x target = %x\n",
+				channel, DSADR(channel), DTADR(channel));
+
+		msg->state = ERROR_STATE;
+		tasklet_schedule(&drv_data->pump_transfers);
+	}
+
+	/* PXA255x_SSP has no timeout interrupt, wait for tailing bytes */
+	if ((drv_data->ssp_type == PXA25x_SSP)
+		&& (channel == drv_data->tx_channel)
+		&& (irq_status & DCSR_ENDINTR)) {
+
+		/* Wait for rx to stall */
+		if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
+			dev_err(&drv_data->pdev->dev,
+				"dma_handler: ssp rx stall failed\n");
+
+		/* Clear and disable interrupts on SSP and DMA channels*/
+		write_SSSR(drv_data->clear_sr, reg);
+		write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
+		DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
+		DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
+		if (wait_dma_channel_stop(drv_data->rx_channel) == 0)
+			dev_err(&drv_data->pdev->dev,
+				"dma_handler: dma rx channel stop failed\n");
+
+		unmap_dma_buffers(drv_data);
+
+		/* Read trailing bytes */
+		/* Calculate number of trailing bytes, read them */
+		trailing_sssr = read_SSSR(reg);
+		if ((trailing_sssr & 0xf008) != 0xf000) {
+			drv_data->rx = drv_data->rx_end -
+					(((trailing_sssr >> 12) & 0x0f) + 1);
+			drv_data->read(drv_data);
+		}
+		msg->actual_length += drv_data->len;
+
+		/* Release chip select if requested, transfer delays are
+		 * handled in pump_transfers */
+		if (drv_data->cs_change)
+			drv_data->cs_control(PXA2XX_CS_DEASSERT);
+
+		/* Move to next transfer */
+		msg->state = next_transfer(drv_data);
+
+		/* Schedule transfer tasklet */
+		tasklet_schedule(&drv_data->pump_transfers);
+	}
+}
+
+static irqreturn_t dma_transfer(struct driver_data *drv_data)
+{
+	u32 irq_status;
+	u32 trailing_sssr = 0;
+	struct spi_message *msg = drv_data->cur_msg;
+	void *reg = drv_data->ioaddr;
+
+	irq_status = read_SSSR(reg) & drv_data->mask_sr;
+	if (irq_status & SSSR_ROR) {
+		/* Clear and disable interrupts on SSP and DMA channels*/
+		if (drv_data->ssp_type != PXA25x_SSP)
+			write_SSTO(0, reg);
+		write_SSSR(drv_data->clear_sr, reg);
+		write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
+		DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
+		DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
+		unmap_dma_buffers(drv_data);
+
+		if (flush(drv_data) == 0)
+			dev_err(&drv_data->pdev->dev,
+					"dma_transfer: flush fail\n");
+
+		dev_warn(&drv_data->pdev->dev, "dma_transfer: fifo overun\n");
+
+		drv_data->cur_msg->state = ERROR_STATE;
+		tasklet_schedule(&drv_data->pump_transfers);
+
+		return IRQ_HANDLED;
+	}
+
+	/* Check for false positive timeout */
+	if ((irq_status & SSSR_TINT) && DCSR(drv_data->tx_channel) & DCSR_RUN) {
+		write_SSSR(SSSR_TINT, reg);
+		return IRQ_HANDLED;
+	}
+
+	if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) {
+
+		/* Clear and disable interrupts on SSP and DMA channels*/
+		if (drv_data->ssp_type != PXA25x_SSP)
+			write_SSTO(0, reg);
+		write_SSSR(drv_data->clear_sr, reg);
+		write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
+		DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
+		DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
+
+		if (wait_dma_channel_stop(drv_data->rx_channel) == 0)
+			dev_err(&drv_data->pdev->dev,
+				"dma_transfer: dma rx channel stop failed\n");
+
+		if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
+			dev_err(&drv_data->pdev->dev,
+				"dma_transfer: ssp rx stall failed\n");
+
+		unmap_dma_buffers(drv_data);
+
+		/* Calculate number of trailing bytes, read them */
+		trailing_sssr = read_SSSR(reg);
+		if ((trailing_sssr & 0xf008) != 0xf000) {
+			drv_data->rx = drv_data->rx_end -
+					(((trailing_sssr >> 12) & 0x0f) + 1);
+			drv_data->read(drv_data);
+		}
+		msg->actual_length += drv_data->len;
+
+		/* Release chip select if requested, transfer delays are
+		 * handled in pump_transfers */
+		if (drv_data->cs_change)
+			drv_data->cs_control(PXA2XX_CS_DEASSERT);
+
+		/* Move to next transfer */
+		msg->state = next_transfer(drv_data);
+
+		/* Schedule transfer tasklet */
+		tasklet_schedule(&drv_data->pump_transfers);
+
+		return IRQ_HANDLED;
+	}
+
+	/* Opps problem detected */
+	return IRQ_NONE;
+}
+
+static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
+{
+	u32 irq_status;
+	struct spi_message *msg = drv_data->cur_msg;
+	void *reg = drv_data->ioaddr;
+	irqreturn_t handled = IRQ_NONE;
+	unsigned long limit = loops_per_jiffy << 1;
+
+	while ((irq_status = (read_SSSR(reg) & drv_data->mask_sr))) {
+
+		if (irq_status & SSSR_ROR) {
+
+			/* Clear and disable interrupts */
+			if (drv_data->ssp_type != PXA25x_SSP)
+				write_SSTO(0, reg);
+			write_SSSR(drv_data->clear_sr, reg);
+			write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
+
+			if (flush(drv_data) == 0)
+				dev_err(&drv_data->pdev->dev,
+					"interrupt_transfer: flush fail\n");
+
+			dev_warn(&drv_data->pdev->dev,
+					"interrupt_transfer: fifo overun\n");
+
+			msg->state = ERROR_STATE;
+			tasklet_schedule(&drv_data->pump_transfers);
+
+			return IRQ_HANDLED;
+		}
+
+		/* Look for false positive timeout */
+		if ((irq_status & SSSR_TINT)
+				&& (drv_data->rx < drv_data->rx_end))
+			write_SSSR(SSSR_TINT, reg);
+
+		/* Pump data */
+		drv_data->read(drv_data);
+		drv_data->write(drv_data);
+
+		if (drv_data->tx == drv_data->tx_end) {
+			/* Disable tx interrupt */
+			write_SSCR1(read_SSCR1(reg) & ~SSCR1_TIE, reg);
+
+			/* PXA25x_SSP has no timeout, read trailing bytes */
+			if (drv_data->ssp_type == PXA25x_SSP) {
+				while ((read_SSSR(reg) & SSSR_BSY) && limit--)
+					drv_data->read(drv_data);
+
+				if (limit == 0)
+					dev_err(&drv_data->pdev->dev,
+						"interrupt_transfer: "
+						"trailing byte read failed\n");
+			}
+		}
+
+		if ((irq_status & SSSR_TINT)
+				|| (drv_data->rx == drv_data->rx_end)) {
+
+			/* Clear timeout */
+			if (drv_data->ssp_type != PXA25x_SSP)
+				write_SSTO(0, reg);
+			write_SSSR(drv_data->clear_sr, reg);
+			write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
+
+			/* Update total byte transfered */
+			msg->actual_length += drv_data->len;
+
+			/* Release chip select if requested, transfer delays are
+			 * handled in pump_transfers */
+			if (drv_data->cs_change)
+				drv_data->cs_control(PXA2XX_CS_DEASSERT);
+
+			/* Move to next transfer */
+			msg->state = next_transfer(drv_data);
+
+			/* Schedule transfer tasklet */
+			tasklet_schedule(&drv_data->pump_transfers);
+
+			return IRQ_HANDLED;
+		}
+
+		/* We did something */
+		handled = IRQ_HANDLED;
+	}
+
+	return handled;
+}
+
+static irqreturn_t ssp_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct driver_data *drv_data = (struct driver_data *)dev_id;
+
+	if (!drv_data->cur_msg) {
+		dev_err(&drv_data->pdev->dev, "bad message state "
+				"in interrupt handler\n");
+		/* Never fail */
+		return IRQ_HANDLED;
+	}
+
+	return drv_data->transfer_handler(drv_data);
+}
+
+static void pump_transfers(unsigned long data)
+{
+	struct driver_data *drv_data = (struct driver_data *)data;
+	struct spi_message *message = NULL;
+	struct spi_transfer *transfer = NULL;
+	struct spi_transfer *previous = NULL;
+	struct chip_data *chip = NULL;
+	void *reg = drv_data->ioaddr;
+	u32 clk_div = 0;
+	u8 bits = 0;
+	u32 speed = 0;
+	u32 cr0;
+
+	/* Get current state information */
+	message = drv_data->cur_msg;
+	transfer = drv_data->cur_transfer;
+	chip = drv_data->cur_chip;
+
+	/* Handle for abort */
+	if (message->state == ERROR_STATE) {
+		message->status = -EIO;
+		giveback(message, drv_data);
+		return;
+	}
+
+	/* Handle end of message */
+	if (message->state == DONE_STATE) {
+		message->status = 0;
+		giveback(message, drv_data);
+		return;
+	}
+
+	/* Delay if requested at end of transfer*/
+	if (message->state == RUNNING_STATE) {
+		previous = list_entry(transfer->transfer_list.prev,
+					struct spi_transfer,
+					transfer_list);
+		if (previous->delay_usecs)
+			udelay(previous->delay_usecs);
+	}
+
+	/* Setup the transfer state based on the type of transfer */
+	if (flush(drv_data) == 0) {
+		dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n");
+		message->status = -EIO;
+		giveback(message, drv_data);
+		return;
+	}
+	drv_data->n_bytes = chip->n_bytes;
+	drv_data->dma_width = chip->dma_width;
+	drv_data->cs_control = chip->cs_control;
+	drv_data->tx = (void *)transfer->tx_buf;
+	drv_data->tx_end = drv_data->tx + transfer->len;
+	drv_data->rx = transfer->rx_buf;
+	drv_data->rx_end = drv_data->rx + transfer->len;
+	drv_data->rx_dma = transfer->rx_dma;
+	drv_data->tx_dma = transfer->tx_dma;
+	drv_data->len = transfer->len;
+	drv_data->write = drv_data->tx ? chip->write : null_writer;
+	drv_data->read = drv_data->rx ? chip->read : null_reader;
+	drv_data->cs_change = transfer->cs_change;
+
+	/* Change speed and bit per word on a per transfer */
+	if (transfer->speed_hz || transfer->bits_per_word) {
+
+		/* Disable clock */
+		write_SSCR0(chip->cr0 & ~SSCR0_SSE, reg);
+		cr0 = chip->cr0;
+		bits = chip->bits_per_word;
+		speed = chip->speed_hz;
+
+		if (transfer->speed_hz)
+			speed = transfer->speed_hz;
+
+		if (transfer->bits_per_word)
+			bits = transfer->bits_per_word;
+
+		if (reg == SSP1_VIRT)
+			clk_div = SSP1_SerClkDiv(speed);
+		else if (reg == SSP2_VIRT)
+			clk_div = SSP2_SerClkDiv(speed);
+		else if (reg == SSP3_VIRT)
+			clk_div = SSP3_SerClkDiv(speed);
+
+		if (bits <= 8) {
+			drv_data->n_bytes = 1;
+			drv_data->dma_width = DCMD_WIDTH1;
+			drv_data->read = drv_data->read != null_reader ?
+						u8_reader : null_reader;
+			drv_data->write = drv_data->write != null_writer ?
+						u8_writer : null_writer;
+		} else if (bits <= 16) {
+			drv_data->n_bytes = 2;
+			drv_data->dma_width = DCMD_WIDTH2;
+			drv_data->read = drv_data->read != null_reader ?
+						u16_reader : null_reader;
+			drv_data->write = drv_data->write != null_writer ?
+						u16_writer : null_writer;
+		} else if (bits <= 32) {
+			drv_data->n_bytes = 4;
+			drv_data->dma_width = DCMD_WIDTH4;
+			drv_data->read = drv_data->read != null_reader ?
+						u32_reader : null_reader;
+			drv_data->write = drv_data->write != null_writer ?
+						u32_writer : null_writer;
+		}
+
+		cr0 = clk_div
+			| SSCR0_Motorola
+			| SSCR0_DataSize(bits & 0x0f)
+			| SSCR0_SSE
+			| (bits > 16 ? SSCR0_EDSS : 0);
+
+		/* Start it back up */
+		write_SSCR0(cr0, reg);
+	}
+
+	message->state = RUNNING_STATE;
+
+	/* Try to map dma buffer and do a dma transfer if successful */
+	if ((drv_data->dma_mapped = map_dma_buffers(drv_data))) {
+
+		/* Ensure we have the correct interrupt handler */
+		drv_data->transfer_handler = dma_transfer;
+
+		/* Setup rx DMA Channel */
+		DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
+		DSADR(drv_data->rx_channel) = drv_data->ssdr_physical;
+		DTADR(drv_data->rx_channel) = drv_data->rx_dma;
+		if (drv_data->rx == drv_data->null_dma_buf)
+			/* No target address increment */
+			DCMD(drv_data->rx_channel) = DCMD_FLOWSRC
+							| drv_data->dma_width
+							| chip->dma_burst_size
+							| drv_data->len;
+		else
+			DCMD(drv_data->rx_channel) = DCMD_INCTRGADDR
+							| DCMD_FLOWSRC
+							| drv_data->dma_width
+							| chip->dma_burst_size
+							| drv_data->len;
+
+		/* Setup tx DMA Channel */
+		DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
+		DSADR(drv_data->tx_channel) = drv_data->tx_dma;
+		DTADR(drv_data->tx_channel) = drv_data->ssdr_physical;
+		if (drv_data->tx == drv_data->null_dma_buf)
+			/* No source address increment */
+			DCMD(drv_data->tx_channel) = DCMD_FLOWTRG
+							| drv_data->dma_width
+							| chip->dma_burst_size
+							| drv_data->len;
+		else
+			DCMD(drv_data->tx_channel) = DCMD_INCSRCADDR
+							| DCMD_FLOWTRG
+							| drv_data->dma_width
+							| chip->dma_burst_size
+							| drv_data->len;
+
+		/* Enable dma end irqs on SSP to detect end of transfer */
+		if (drv_data->ssp_type == PXA25x_SSP)
+			DCMD(drv_data->tx_channel) |= DCMD_ENDIRQEN;
+
+		/* Fix me, need to handle cs polarity */
+		drv_data->cs_control(PXA2XX_CS_ASSERT);
+
+		/* Go baby, go */
+		write_SSSR(drv_data->clear_sr, reg);
+		DCSR(drv_data->rx_channel) |= DCSR_RUN;
+		DCSR(drv_data->tx_channel) |= DCSR_RUN;
+		if (drv_data->ssp_type != PXA25x_SSP)
+			write_SSTO(chip->timeout, reg);
+		write_SSCR1(chip->cr1
+				| chip->dma_threshold
+				| drv_data->dma_cr1,
+				reg);
+	} else {
+		/* Ensure we have the correct interrupt handler	*/
+		drv_data->transfer_handler = interrupt_transfer;
+
+		/* Fix me, need to handle cs polarity */
+		drv_data->cs_control(PXA2XX_CS_ASSERT);
+
+		/* Go baby, go */
+		write_SSSR(drv_data->clear_sr, reg);
+		if (drv_data->ssp_type != PXA25x_SSP)
+			write_SSTO(chip->timeout, reg);
+		write_SSCR1(chip->cr1
+				| chip->threshold
+				| drv_data->int_cr1,
+				reg);
+	}
+}
+
+static void pump_messages(void *data)
+{
+	struct driver_data *drv_data = data;
+	unsigned long flags;
+
+	/* Lock queue and check for queue work */
+	spin_lock_irqsave(&drv_data->lock, flags);
+	if (list_empty(&drv_data->queue) || drv_data->run == QUEUE_STOPPED) {
+		drv_data->busy = 0;
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return;
+	}
+
+	/* Make sure we are not already running a message */
+	if (drv_data->cur_msg) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return;
+	}
+
+	/* Extract head of queue */
+	drv_data->cur_msg = list_entry(drv_data->queue.next,
+					struct spi_message, queue);
+	list_del_init(&drv_data->cur_msg->queue);
+	drv_data->busy = 1;
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	/* Initial message state*/
+	drv_data->cur_msg->state = START_STATE;
+	drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
+						struct spi_transfer,
+						transfer_list);
+
+	/* Setup the SSP using the per chip configuration */
+	drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
+	restore_state(drv_data);
+
+	/* Mark as busy and launch transfers */
+	tasklet_schedule(&drv_data->pump_transfers);
+}
+
+static int transfer(struct spi_device *spi, struct spi_message *msg)
+{
+	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+
+	if (drv_data->run == QUEUE_STOPPED) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return -ESHUTDOWN;
+	}
+
+	msg->actual_length = 0;
+	msg->status = -EINPROGRESS;
+	msg->state = START_STATE;
+
+	list_add_tail(&msg->queue, &drv_data->queue);
+
+	if (drv_data->run == QUEUE_RUNNING && !drv_data->busy)
+		queue_work(drv_data->workqueue, &drv_data->pump_messages);
+
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	return 0;
+}
+
+static int setup(struct spi_device *spi)
+{
+	struct pxa2xx_spi_chip *chip_info = NULL;
+	struct chip_data *chip;
+	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
+	unsigned int clk_div;
+
+	if (!spi->bits_per_word)
+		spi->bits_per_word = 8;
+
+	if (drv_data->ssp_type != PXA25x_SSP
+			&& (spi->bits_per_word < 4 || spi->bits_per_word > 32))
+		return -EINVAL;
+	else if (spi->bits_per_word < 4 || spi->bits_per_word > 16)
+		return -EINVAL;
+
+	/* Only alloc (or use chip_info) on first setup */
+	chip = spi_get_ctldata(spi);
+	if (chip == NULL) {
+		chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
+		if (!chip)
+			return -ENOMEM;
+
+		chip->cs_control = null_cs_control;
+		chip->enable_dma = 0;
+		chip->timeout = 5;
+		chip->threshold = SSCR1_RxTresh(1) | SSCR1_TxTresh(1);
+		chip->dma_burst_size = drv_data->master_info->enable_dma ?
+					DCMD_BURST8 : 0;
+
+		chip_info = spi->controller_data;
+	}
+
+	/* chip_info isn't always needed */
+	if (chip_info) {
+		if (chip_info->cs_control)
+			chip->cs_control = chip_info->cs_control;
+
+		chip->timeout = (chip_info->timeout_microsecs * 10000) / 2712;
+
+		chip->threshold = SSCR1_RxTresh(chip_info->rx_threshold)
+					| SSCR1_TxTresh(chip_info->tx_threshold);
+
+		chip->enable_dma = chip_info->dma_burst_size != 0
+					&& drv_data->master_info->enable_dma;
+		chip->dma_threshold = 0;
+
+		if (chip->enable_dma) {
+			if (chip_info->dma_burst_size <= 8) {
+				chip->dma_threshold = SSCR1_RxTresh(8)
+							| SSCR1_TxTresh(8);
+				chip->dma_burst_size = DCMD_BURST8;
+			} else if (chip_info->dma_burst_size <= 16) {
+				chip->dma_threshold = SSCR1_RxTresh(16)
+							| SSCR1_TxTresh(16);
+				chip->dma_burst_size = DCMD_BURST16;
+			} else {
+				chip->dma_threshold = SSCR1_RxTresh(32)
+							| SSCR1_TxTresh(32);
+				chip->dma_burst_size = DCMD_BURST32;
+			}
+		}
+
+
+		if (chip_info->enable_loopback)
+			chip->cr1 = SSCR1_LBM;
+	}
+
+	if (drv_data->ioaddr == SSP1_VIRT)
+		clk_div = SSP1_SerClkDiv(spi->max_speed_hz);
+	else if (drv_data->ioaddr == SSP2_VIRT)
+		clk_div = SSP2_SerClkDiv(spi->max_speed_hz);
+	else if (drv_data->ioaddr == SSP3_VIRT)
+		clk_div = SSP3_SerClkDiv(spi->max_speed_hz);
+	else
+		return -ENODEV;
+	chip->speed_hz = spi->max_speed_hz;
+
+	chip->cr0 = clk_div
+			| SSCR0_Motorola
+			| SSCR0_DataSize(spi->bits_per_word & 0x0f)
+			| SSCR0_SSE
+			| (spi->bits_per_word > 16 ? SSCR0_EDSS : 0);
+	chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) << 4)
+			| (((spi->mode & SPI_CPOL) != 0) << 3);
+
+	/* NOTE:  PXA25x_SSP _could_ use external clocking ... */
+	if (drv_data->ssp_type != PXA25x_SSP)
+		dev_dbg(&spi->dev, "%d bits/word, %d Hz, mode %d\n",
+				spi->bits_per_word,
+				(CLOCK_SPEED_HZ)
+					/ (1 + ((chip->cr0 & SSCR0_SCR) >> 8)),
+				spi->mode & 0x3);
+	else
+		dev_dbg(&spi->dev, "%d bits/word, %d Hz, mode %d\n",
+				spi->bits_per_word,
+				(CLOCK_SPEED_HZ/2)
+					/ (1 + ((chip->cr0 & SSCR0_SCR) >> 8)),
+				spi->mode & 0x3);
+
+	if (spi->bits_per_word <= 8) {
+		chip->n_bytes = 1;
+		chip->dma_width = DCMD_WIDTH1;
+		chip->read = u8_reader;
+		chip->write = u8_writer;
+	} else if (spi->bits_per_word <= 16) {
+		chip->n_bytes = 2;
+		chip->dma_width = DCMD_WIDTH2;
+		chip->read = u16_reader;
+		chip->write = u16_writer;
+	} else if (spi->bits_per_word <= 32) {
+		chip->cr0 |= SSCR0_EDSS;
+		chip->n_bytes = 4;
+		chip->dma_width = DCMD_WIDTH4;
+		chip->read = u32_reader;
+		chip->write = u32_writer;
+	} else {
+		dev_err(&spi->dev, "invalid wordsize\n");
+		kfree(chip);
+		return -ENODEV;
+	}
+	chip->bits_per_word = spi->bits_per_word;
+
+	spi_set_ctldata(spi, chip);
+
+	return 0;
+}
+
+static void cleanup(const struct spi_device *spi)
+{
+	struct chip_data *chip = spi_get_ctldata((struct spi_device *)spi);
+
+	kfree(chip);
+}
+
+static int init_queue(struct driver_data *drv_data)
+{
+	INIT_LIST_HEAD(&drv_data->queue);
+	spin_lock_init(&drv_data->lock);
+
+	drv_data->run = QUEUE_STOPPED;
+	drv_data->busy = 0;
+
+	tasklet_init(&drv_data->pump_transfers,
+			pump_transfers,	(unsigned long)drv_data);
+
+	INIT_WORK(&drv_data->pump_messages, pump_messages, drv_data);
+	drv_data->workqueue = create_singlethread_workqueue(
+					drv_data->master->cdev.dev->bus_id);
+	if (drv_data->workqueue == NULL)
+		return -EBUSY;
+
+	return 0;
+}
+
+static int start_queue(struct driver_data *drv_data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+
+	if (drv_data->run == QUEUE_RUNNING || drv_data->busy) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return -EBUSY;
+	}
+
+	drv_data->run = QUEUE_RUNNING;
+	drv_data->cur_msg = NULL;
+	drv_data->cur_transfer = NULL;
+	drv_data->cur_chip = NULL;
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	queue_work(drv_data->workqueue, &drv_data->pump_messages);
+
+	return 0;
+}
+
+static int stop_queue(struct driver_data *drv_data)
+{
+	unsigned long flags;
+	unsigned limit = 500;
+	int status = 0;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+
+	/* This is a bit lame, but is optimized for the common execution path.
+	 * A wait_queue on the drv_data->busy could be used, but then the common
+	 * execution path (pump_messages) would be required to call wake_up or
+	 * friends on every SPI message. Do this instead */
+	drv_data->run = QUEUE_STOPPED;
+	while (!list_empty(&drv_data->queue) && drv_data->busy && limit--) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		msleep(10);
+		spin_lock_irqsave(&drv_data->lock, flags);
+	}
+
+	if (!list_empty(&drv_data->queue) || drv_data->busy)
+		status = -EBUSY;
+
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	return status;
+}
+
+static int destroy_queue(struct driver_data *drv_data)
+{
+	int status;
+
+	status = stop_queue(drv_data);
+	if (status != 0)
+		return status;
+
+	destroy_workqueue(drv_data->workqueue);
+
+	return 0;
+}
+
+static int pxa2xx_spi_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct pxa2xx_spi_master *platform_info;
+	struct spi_master *master;
+	struct driver_data *drv_data = 0;
+	struct resource *memory_resource;
+	int irq;
+	int status = 0;
+
+	platform_info = dev->platform_data;
+
+	if (platform_info->ssp_type == SSP_UNDEFINED) {
+		dev_err(&pdev->dev, "undefined SSP\n");
+		return -ENODEV;
+	}
+
+	/* Allocate master with space for drv_data and null dma buffer */
+	master = spi_alloc_master(dev, sizeof(struct driver_data) + 16);
+	if (!master) {
+		dev_err(&pdev->dev, "can not alloc spi_master\n");
+		return -ENOMEM;
+	}
+	drv_data = spi_master_get_devdata(master);
+	drv_data->master = master;
+	drv_data->master_info = platform_info;
+	drv_data->pdev = pdev;
+
+	master->bus_num = pdev->id;
+	master->num_chipselect = platform_info->num_chipselect;
+	master->cleanup = cleanup;
+	master->setup = setup;
+	master->transfer = transfer;
+
+	drv_data->ssp_type = platform_info->ssp_type;
+	drv_data->null_dma_buf = (u32 *)ALIGN((u32)(drv_data +
+						sizeof(struct driver_data)), 8);
+
+	/* Setup register addresses */
+	memory_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!memory_resource) {
+		dev_err(&pdev->dev, "memory resources not defined\n");
+		status = -ENODEV;
+		goto out_error_master_alloc;
+	}
+
+	drv_data->ioaddr = (void *)io_p2v(memory_resource->start);
+	drv_data->ssdr_physical = memory_resource->start + 0x00000010;
+	if (platform_info->ssp_type == PXA25x_SSP) {
+		drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE;
+		drv_data->dma_cr1 = 0;
+		drv_data->clear_sr = SSSR_ROR;
+		drv_data->mask_sr = SSSR_RFS | SSSR_TFS | SSSR_ROR;
+	} else {
+		drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE;
+		drv_data->dma_cr1 = SSCR1_TSRE | SSCR1_RSRE | SSCR1_TINTE;
+		drv_data->clear_sr = SSSR_ROR | SSSR_TINT;
+		drv_data->mask_sr = SSSR_TINT | SSSR_RFS | SSSR_TFS | SSSR_ROR;
+	}
+
+	/* Attach to IRQ */
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "irq resource not defined\n");
+		status = -ENODEV;
+		goto out_error_master_alloc;
+	}
+
+	status = request_irq(irq, ssp_int, SA_INTERRUPT, dev->bus_id, drv_data);
+	if (status < 0) {
+		dev_err(&pdev->dev, "can not get IRQ\n");
+		goto out_error_master_alloc;
+	}
+
+	/* Setup DMA if requested */
+	drv_data->tx_channel = -1;
+	drv_data->rx_channel = -1;
+	if (platform_info->enable_dma) {
+
+		/* Get two DMA channels	(rx and tx) */
+		drv_data->rx_channel = pxa_request_dma("pxa2xx_spi_ssp_rx",
+							DMA_PRIO_HIGH,
+							dma_handler,
+							drv_data);
+		if (drv_data->rx_channel < 0) {
+			dev_err(dev, "problem (%d) requesting rx channel\n",
+				drv_data->rx_channel);
+			status = -ENODEV;
+			goto out_error_irq_alloc;
+		}
+		drv_data->tx_channel = pxa_request_dma("pxa2xx_spi_ssp_tx",
+							DMA_PRIO_MEDIUM,
+							dma_handler,
+							drv_data);
+		if (drv_data->tx_channel < 0) {
+			dev_err(dev, "problem (%d) requesting tx channel\n",
+				drv_data->tx_channel);
+			status = -ENODEV;
+			goto out_error_dma_alloc;
+		}
+
+		if (drv_data->ioaddr == SSP1_VIRT) {
+				DRCMRRXSSDR = DRCMR_MAPVLD
+						| drv_data->rx_channel;
+				DRCMRTXSSDR = DRCMR_MAPVLD
+						| drv_data->tx_channel;
+		} else if (drv_data->ioaddr == SSP2_VIRT) {
+				DRCMRRXSS2DR = DRCMR_MAPVLD
+						| drv_data->rx_channel;
+				DRCMRTXSS2DR = DRCMR_MAPVLD
+						| drv_data->tx_channel;
+		} else if (drv_data->ioaddr == SSP3_VIRT) {
+				DRCMRRXSS3DR = DRCMR_MAPVLD
+						| drv_data->rx_channel;
+				DRCMRTXSS3DR = DRCMR_MAPVLD
+						| drv_data->tx_channel;
+		} else {
+			dev_err(dev, "bad SSP type\n");
+			goto out_error_dma_alloc;
+		}
+	}
+
+	/* Enable SOC clock */
+	pxa_set_cken(platform_info->clock_enable, 1);
+
+	/* Load default SSP configuration */
+	write_SSCR0(0, drv_data->ioaddr);
+	write_SSCR1(SSCR1_RxTresh(4) | SSCR1_TxTresh(12), drv_data->ioaddr);
+	write_SSCR0(SSCR0_SerClkDiv(2)
+			| SSCR0_Motorola
+			| SSCR0_DataSize(8),
+			drv_data->ioaddr);
+	if (drv_data->ssp_type != PXA25x_SSP)
+		write_SSTO(0, drv_data->ioaddr);
+	write_SSPSP(0, drv_data->ioaddr);
+
+	/* Initial and start queue */
+	status = init_queue(drv_data);
+	if (status != 0) {
+		dev_err(&pdev->dev, "problem initializing queue\n");
+		goto out_error_clock_enabled;
+	}
+	status = start_queue(drv_data);
+	if (status != 0) {
+		dev_err(&pdev->dev, "problem starting queue\n");
+		goto out_error_clock_enabled;
+	}
+
+	/* Register with the SPI framework */
+	platform_set_drvdata(pdev, drv_data);
+	status = spi_register_master(master);
+	if (status != 0) {
+		dev_err(&pdev->dev, "problem registering spi master\n");
+		goto out_error_queue_alloc;
+	}
+
+	return status;
+
+out_error_queue_alloc:
+	destroy_queue(drv_data);
+
+out_error_clock_enabled:
+	pxa_set_cken(platform_info->clock_enable, 0);
+
+out_error_dma_alloc:
+	if (drv_data->tx_channel != -1)
+		pxa_free_dma(drv_data->tx_channel);
+	if (drv_data->rx_channel != -1)
+		pxa_free_dma(drv_data->rx_channel);
+
+out_error_irq_alloc:
+	free_irq(irq, drv_data);
+
+out_error_master_alloc:
+	spi_master_put(master);
+	return status;
+}
+
+static int pxa2xx_spi_remove(struct platform_device *pdev)
+{
+	struct driver_data *drv_data = platform_get_drvdata(pdev);
+	int irq;
+	int status = 0;
+
+	if (!drv_data)
+		return 0;
+
+	/* Remove the queue */
+	status = destroy_queue(drv_data);
+	if (status != 0)
+		return status;
+
+	/* Disable the SSP at the peripheral and SOC level */
+	write_SSCR0(0, drv_data->ioaddr);
+	pxa_set_cken(drv_data->master_info->clock_enable, 0);
+
+	/* Release DMA */
+	if (drv_data->master_info->enable_dma) {
+		if (drv_data->ioaddr == SSP1_VIRT) {
+			DRCMRRXSSDR = 0;
+			DRCMRTXSSDR = 0;
+		} else if (drv_data->ioaddr == SSP2_VIRT) {
+			DRCMRRXSS2DR = 0;
+			DRCMRTXSS2DR = 0;
+		} else if (drv_data->ioaddr == SSP3_VIRT) {
+			DRCMRRXSS3DR = 0;
+			DRCMRTXSS3DR = 0;
+		}
+		pxa_free_dma(drv_data->tx_channel);
+		pxa_free_dma(drv_data->rx_channel);
+	}
+
+	/* Release IRQ */
+	irq = platform_get_irq(pdev, 0);
+	if (irq >= 0)
+		free_irq(irq, drv_data);
+
+	/* Disconnect from the SPI framework */
+	spi_unregister_master(drv_data->master);
+
+	/* Prevent double remove */
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static void pxa2xx_spi_shutdown(struct platform_device *pdev)
+{
+	int status = 0;
+
+	if ((status = pxa2xx_spi_remove(pdev)) != 0)
+		dev_err(&pdev->dev, "shutdown failed with %d\n", status);
+}
+
+#ifdef CONFIG_PM
+static int suspend_devices(struct device *dev, void *pm_message)
+{
+	pm_message_t *state = pm_message;
+
+	if (dev->power.power_state.event != state->event) {
+		dev_warn(dev, "pm state does not match request\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int pxa2xx_spi_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct driver_data *drv_data = platform_get_drvdata(pdev);
+	int status = 0;
+
+	/* Check all childern for current power state */
+	if (device_for_each_child(&pdev->dev, &state, suspend_devices) != 0) {
+		dev_warn(&pdev->dev, "suspend aborted\n");
+		return -1;
+	}
+
+	status = stop_queue(drv_data);
+	if (status != 0)
+		return status;
+	write_SSCR0(0, drv_data->ioaddr);
+	pxa_set_cken(drv_data->master_info->clock_enable, 0);
+
+	return 0;
+}
+
+static int pxa2xx_spi_resume(struct platform_device *pdev)
+{
+	struct driver_data *drv_data = platform_get_drvdata(pdev);
+	int status = 0;
+
+	/* Enable the SSP clock */
+	pxa_set_cken(drv_data->master_info->clock_enable, 1);
+
+	/* Start the queue running */
+	status = start_queue(drv_data);
+	if (status != 0) {
+		dev_err(&pdev->dev, "problem starting queue (%d)\n", status);
+		return status;
+	}
+
+	return 0;
+}
+#else
+#define pxa2xx_spi_suspend NULL
+#define pxa2xx_spi_resume NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver driver = {
+	.driver = {
+		.name = "pxa2xx-spi",
+		.bus = &platform_bus_type,
+		.owner = THIS_MODULE,
+	},
+	.probe = pxa2xx_spi_probe,
+	.remove = __devexit_p(pxa2xx_spi_remove),
+	.shutdown = pxa2xx_spi_shutdown,
+	.suspend = pxa2xx_spi_suspend,
+	.resume = pxa2xx_spi_resume,
+};
+
+static int __init pxa2xx_spi_init(void)
+{
+	platform_driver_register(&driver);
+
+	return 0;
+}
+module_init(pxa2xx_spi_init);
+
+static void __exit pxa2xx_spi_exit(void)
+{
+	platform_driver_unregister(&driver);
+}
+module_exit(pxa2xx_spi_exit);
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 94f5e8ed83a7a8427105201aaa81f14ff5c710c7..7a3f733051e9ce8a2c6102fcf7ddd9add2d620b6 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -395,7 +395,7 @@ EXPORT_SYMBOL_GPL(spi_alloc_master);
 int __init_or_module
 spi_register_master(struct spi_master *master)
 {
-	static atomic_t		dyn_bus_id = ATOMIC_INIT(0);
+	static atomic_t		dyn_bus_id = ATOMIC_INIT((1<<16) - 1);
 	struct device		*dev = master->cdev.dev;
 	int			status = -ENODEV;
 	int			dynamic = 0;
@@ -404,7 +404,7 @@ spi_register_master(struct spi_master *master)
 		return -ENODEV;
 
 	/* convention:  dynamically assigned bus IDs count down from the max */
-	if (master->bus_num == 0) {
+	if (master->bus_num < 0) {
 		master->bus_num = atomic_dec_return(&dyn_bus_id);
 		dynamic = 1;
 	}
@@ -522,7 +522,8 @@ int spi_sync(struct spi_device *spi, struct spi_message *message)
 }
 EXPORT_SYMBOL_GPL(spi_sync);
 
-#define	SPI_BUFSIZ	(SMP_CACHE_BYTES)
+/* portable code must never pass more than 32 bytes */
+#define	SPI_BUFSIZ	max(32,SMP_CACHE_BYTES)
 
 static u8	*buf;
 
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c
index f037e5593269e8a79f700e7acf917919e0b13762..dd2f950b21a734ca753a48ddf55fdd31d1b573bc 100644
--- a/drivers/spi/spi_bitbang.c
+++ b/drivers/spi/spi_bitbang.c
@@ -138,6 +138,45 @@ static unsigned bitbang_txrx_32(
 	return t->len - count;
 }
 
+int spi_bitbang_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct spi_bitbang_cs	*cs = spi->controller_state;
+	u8			bits_per_word;
+	u32			hz;
+
+	if (t) {
+		bits_per_word = t->bits_per_word;
+		hz = t->speed_hz;
+	} else {
+		bits_per_word = 0;
+		hz = 0;
+	}
+
+	/* spi_transfer level calls that work per-word */
+	if (!bits_per_word)
+		bits_per_word = spi->bits_per_word;
+	if (bits_per_word <= 8)
+		cs->txrx_bufs = bitbang_txrx_8;
+	else if (bits_per_word <= 16)
+		cs->txrx_bufs = bitbang_txrx_16;
+	else if (bits_per_word <= 32)
+		cs->txrx_bufs = bitbang_txrx_32;
+	else
+		return -EINVAL;
+
+	/* nsecs = (clock period)/2 */
+	if (!hz)
+		hz = spi->max_speed_hz;
+	if (hz) {
+		cs->nsecs = (1000000000/2) / hz;
+		if (cs->nsecs > (MAX_UDELAY_MS * 1000 * 1000))
+			return -EINVAL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(spi_bitbang_setup_transfer);
+
 /**
  * spi_bitbang_setup - default setup for per-word I/O loops
  */
@@ -145,8 +184,16 @@ int spi_bitbang_setup(struct spi_device *spi)
 {
 	struct spi_bitbang_cs	*cs = spi->controller_state;
 	struct spi_bitbang	*bitbang;
+	int			retval;
 
-	if (!spi->max_speed_hz)
+	bitbang = spi_master_get_devdata(spi->master);
+
+	/* REVISIT: some systems will want to support devices using lsb-first
+	 * bit encodings on the wire.  In pure software that would be trivial,
+	 * just bitbang_txrx_le_cphaX() routines shifting the other way, and
+	 * some hardware controllers also have this support.
+	 */
+	if ((spi->mode & SPI_LSB_FIRST) != 0)
 		return -EINVAL;
 
 	if (!cs) {
@@ -155,32 +202,20 @@ int spi_bitbang_setup(struct spi_device *spi)
 			return -ENOMEM;
 		spi->controller_state = cs;
 	}
-	bitbang = spi_master_get_devdata(spi->master);
 
 	if (!spi->bits_per_word)
 		spi->bits_per_word = 8;
 
-	/* spi_transfer level calls that work per-word */
-	if (spi->bits_per_word <= 8)
-		cs->txrx_bufs = bitbang_txrx_8;
-	else if (spi->bits_per_word <= 16)
-		cs->txrx_bufs = bitbang_txrx_16;
-	else if (spi->bits_per_word <= 32)
-		cs->txrx_bufs = bitbang_txrx_32;
-	else
-		return -EINVAL;
-
 	/* per-word shift register access, in hardware or bitbanging */
 	cs->txrx_word = bitbang->txrx_word[spi->mode & (SPI_CPOL|SPI_CPHA)];
 	if (!cs->txrx_word)
 		return -EINVAL;
 
-	/* nsecs = (clock period)/2 */
-	cs->nsecs = (1000000000/2) / (spi->max_speed_hz);
-	if (cs->nsecs > MAX_UDELAY_MS * 1000)
-		return -EINVAL;
+	retval = spi_bitbang_setup_transfer(spi, NULL);
+	if (retval < 0)
+		return retval;
 
-	dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec\n",
+	dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n",
 			__FUNCTION__, spi->mode & (SPI_CPOL | SPI_CPHA),
 			spi->bits_per_word, 2 * cs->nsecs);
 
@@ -246,6 +281,8 @@ static void bitbang_work(void *_bitbang)
 		unsigned		tmp;
 		unsigned		cs_change;
 		int			status;
+		int			(*setup_transfer)(struct spi_device *,
+						struct spi_transfer *);
 
 		m = container_of(bitbang->queue.next, struct spi_message,
 				queue);
@@ -262,6 +299,7 @@ static void bitbang_work(void *_bitbang)
 		tmp = 0;
 		cs_change = 1;
 		status = 0;
+		setup_transfer = NULL;
 
 		list_for_each_entry (t, &m->transfers, transfer_list) {
 			if (bitbang->shutdown) {
@@ -269,6 +307,20 @@ static void bitbang_work(void *_bitbang)
 				break;
 			}
 
+			/* override or restore speed and wordsize */
+			if (t->speed_hz || t->bits_per_word) {
+				setup_transfer = bitbang->setup_transfer;
+				if (!setup_transfer) {
+					status = -ENOPROTOOPT;
+					break;
+				}
+			}
+			if (setup_transfer) {
+				status = setup_transfer(spi, t);
+				if (status < 0)
+					break;
+			}
+
 			/* set up default clock polarity, and activate chip;
 			 * this implicitly updates clock and spi modes as
 			 * previously recorded for this device via setup().
@@ -325,6 +377,10 @@ static void bitbang_work(void *_bitbang)
 		m->status = status;
 		m->complete(m->context);
 
+		/* restore speed and wordsize */
+		if (setup_transfer)
+			setup_transfer(spi, NULL);
+
 		/* normally deactivate chipselect ... unless no error and
 		 * cs_change has hinted that the next message will probably
 		 * be for this chip too.
@@ -348,6 +404,7 @@ int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m)
 {
 	struct spi_bitbang	*bitbang;
 	unsigned long		flags;
+	int			status = 0;
 
 	m->actual_length = 0;
 	m->status = -EINPROGRESS;
@@ -357,11 +414,15 @@ int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m)
 		return -ESHUTDOWN;
 
 	spin_lock_irqsave(&bitbang->lock, flags);
-	list_add_tail(&m->queue, &bitbang->queue);
-	queue_work(bitbang->workqueue, &bitbang->work);
+	if (!spi->max_speed_hz)
+		status = -ENETDOWN;
+	else {
+		list_add_tail(&m->queue, &bitbang->queue);
+		queue_work(bitbang->workqueue, &bitbang->work);
+	}
 	spin_unlock_irqrestore(&bitbang->lock, flags);
 
-	return 0;
+	return status;
 }
 EXPORT_SYMBOL_GPL(spi_bitbang_transfer);
 
@@ -406,6 +467,9 @@ int spi_bitbang_start(struct spi_bitbang *bitbang)
 		bitbang->use_dma = 0;
 		bitbang->txrx_bufs = spi_bitbang_bufs;
 		if (!bitbang->master->setup) {
+			if (!bitbang->setup_transfer)
+				bitbang->setup_transfer =
+					 spi_bitbang_setup_transfer;
 			bitbang->master->setup = spi_bitbang_setup;
 			bitbang->master->cleanup = spi_bitbang_cleanup;
 		}
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index 7860c8a5800d5a184adc8abea047dbef16c37b89..956b7a1e8af98c0a37056f280c371b6dd785a5dd 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -69,7 +69,7 @@ static const char speedtch_driver_name[] = "speedtch";
 #define RESUBMIT_DELAY		1000	/* milliseconds */
 
 #define DEFAULT_BULK_ALTSETTING	1
-#define DEFAULT_ISOC_ALTSETTING	2
+#define DEFAULT_ISOC_ALTSETTING	3
 #define DEFAULT_DL_512_FIRST	0
 #define DEFAULT_ENABLE_ISOC	0
 #define DEFAULT_SW_BUFFERING	0
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index c1211fc037d997b8a30cee323ded090d72d9da63..546249843b8e5fe3613ada68e512484d5382d73b 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -99,11 +99,11 @@ static const char usbatm_driver_name[] = "usbatm";
 
 #define UDSL_MAX_RCV_URBS		16
 #define UDSL_MAX_SND_URBS		16
-#define UDSL_MAX_BUF_SIZE		64 * 1024	/* bytes */
+#define UDSL_MAX_BUF_SIZE		65536
 #define UDSL_DEFAULT_RCV_URBS		4
 #define UDSL_DEFAULT_SND_URBS		4
-#define UDSL_DEFAULT_RCV_BUF_SIZE	64 * ATM_CELL_SIZE	/* bytes */
-#define UDSL_DEFAULT_SND_BUF_SIZE	64 * ATM_CELL_SIZE	/* bytes */
+#define UDSL_DEFAULT_RCV_BUF_SIZE	3392	/* 64 * ATM_CELL_SIZE */
+#define UDSL_DEFAULT_SND_BUF_SIZE	3392	/* 64 * ATM_CELL_SIZE */
 
 #define ATM_CELL_HEADER			(ATM_CELL_SIZE - ATM_CELL_PAYLOAD)
 
@@ -135,7 +135,7 @@ MODULE_PARM_DESC(rcv_buf_bytes,
 module_param(snd_buf_bytes, uint, S_IRUGO);
 MODULE_PARM_DESC(snd_buf_bytes,
 		 "Size of the buffers used for transmission, in bytes (range: 1-"
-		 __MODULE_STRING(UDSL_MAX_SND_BUF_SIZE) ", default: "
+		 __MODULE_STRING(UDSL_MAX_BUF_SIZE) ", default: "
 		 __MODULE_STRING(UDSL_DEFAULT_SND_BUF_SIZE) ")");
 
 
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index fbd938d4ea589cc9d558d1f41cae0fad0dccd18b..e2e00ba4e1e6dd5b20aff7dda22316cd02a39e97 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1805,6 +1805,12 @@ int usb_add_hcd(struct usb_hcd *hcd,
 			USB_SPEED_FULL;
 	hcd->self.root_hub = rhdev;
 
+	/* wakeup flag init defaults to "everything works" for root hubs,
+	 * but drivers can override it in reset() if needed, along with
+	 * recording the overall controller's system wakeup capability.
+	 */
+	device_init_wakeup(&rhdev->dev, 1);
+
 	/* "reset" is misnamed; its role is now one-time init. the controller
 	 * should already have been reset (and boot firmware kicked off etc).
 	 */
@@ -1813,13 +1819,6 @@ int usb_add_hcd(struct usb_hcd *hcd,
 		goto err_hcd_driver_setup;
 	}
 
-	/* wakeup flag init is in transition; for now we can't rely on PCI to
-	 * initialize these bits properly, so we let reset() override it.
-	 * This init should _precede_ the reset() once PCI behaves.
-	 */
-	device_init_wakeup(&rhdev->dev,
-			device_can_wakeup(hcd->self.controller));
-
 	/* NOTE: root hub and controller capabilities may not be the same */
 	if (device_can_wakeup(hcd->self.controller)
 			&& device_can_wakeup(&hcd->self.root_hub->dev))
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 0c87f73f29332d9bbf71e688b97acaa5ac4a668f..90b8d43c6b339eb233045dc8d550176ea67192f6 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1168,19 +1168,9 @@ static inline const char *plural(int n)
 static int choose_configuration(struct usb_device *udev)
 {
 	int i;
-	u16 devstatus;
-	int bus_powered;
 	int num_configs;
 	struct usb_host_config *c, *best;
 
-	/* If this fails, assume the device is bus-powered */
-	devstatus = 0;
-	usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
-	le16_to_cpus(&devstatus);
-	bus_powered = ((devstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0);
-	dev_dbg(&udev->dev, "device is %s-powered\n",
-			bus_powered ? "bus" : "self");
-
 	best = NULL;
 	c = udev->config;
 	num_configs = udev->descriptor.bNumConfigurations;
@@ -1197,6 +1187,19 @@ static int choose_configuration(struct usb_device *udev)
 		 * similar errors in their descriptors.  If the next test
 		 * were allowed to execute, such configurations would always
 		 * be rejected and the devices would not work as expected.
+		 * In the meantime, we run the risk of selecting a config
+		 * that requires external power at a time when that power
+		 * isn't available.  It seems to be the lesser of two evils.
+		 *
+		 * Bugzilla #6448 reports a device that appears to crash
+		 * when it receives a GET_DEVICE_STATUS request!  We don't
+		 * have any other way to tell whether a device is self-powered,
+		 * but since we don't use that information anywhere but here,
+		 * the call has been removed.
+		 *
+		 * Maybe the GET_DEVICE_STATUS call and the test below can
+		 * be reinstated when device firmwares become more reliable.
+		 * Don't hold your breath.
 		 */
 #if 0
 		/* Rule out self-powered configs for a bus-powered device */
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 544f7589912f714337cae4832a6478fd5fc50160..73f5a379d9b332a37e73b100862ad3c817e0df9e 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -863,7 +863,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
 		i = ohci->num_ports;
 		while (i--)
 			ohci_writel (ohci, RH_PS_PSS,
-				&ohci->regs->roothub.portstatus [temp]);
+				&ohci->regs->roothub.portstatus [i]);
 		ohci_dbg (ohci, "restart complete\n");
 	}
 	return 0;
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index f419bd82ab7f5bd00fc78979c4e56369d4de77f1..435273e7c85cb5912ec9cc22ded58dec3b6e76aa 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1557,6 +1557,9 @@ void hid_init_reports(struct hid_device *hid)
 #define USB_VENDOR_ID_HP		0x03f0
 #define USB_DEVICE_ID_HP_USBHUB_KB	0x020c
 
+#define USB_VENDOR_ID_IBM		0x04b3
+#define USB_DEVICE_ID_IBM_USBHUB_KB	0x3005
+
 #define USB_VENDOR_ID_CREATIVELABS	0x062a
 #define USB_DEVICE_ID_CREATIVELABS_SILVERCREST	0x0201
 
@@ -1681,6 +1684,7 @@ static const struct hid_blacklist {
 	{ USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET},
 	{ USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVELABS_SILVERCREST, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_HP, USB_DEVICE_ID_HP_USBHUB_KB, HID_QUIRK_NOGET },
+	{ USB_VENDOR_ID_IBM, USB_DEVICE_ID_IBM_USBHUB_KB, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_SILVERCREST, USB_DEVICE_ID_SILVERCREST_KB, HID_QUIRK_NOGET },
diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c
index 3824df33094e237d10a26058ebb91945f7ba2bad..1fd9cb85f4ca3aa9014e542d0a517d508dcad1e6 100644
--- a/drivers/usb/misc/emi26.c
+++ b/drivers/usb/misc/emi26.c
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/usb.h>
+#include <linux/delay.h>
 
 #define MAX_INTEL_HEX_RECORD_LENGTH 16
 typedef struct _INTEL_HEX_RECORD
@@ -114,6 +115,7 @@ static int emi26_load_firmware (struct usb_device *dev)
 
 	/* De-assert reset (let the CPU run) */
 	err = emi26_set_reset(dev,0);
+	msleep(250);	/* let device settle */
 
 	/* 2. We upload the FPGA firmware into the EMI
 	 * Note: collect up to 1023 (yes!) bytes and send them with
@@ -150,6 +152,7 @@ static int emi26_load_firmware (struct usb_device *dev)
 			goto wraperr;
 		}
 	}
+	msleep(250);	/* let device settle */
 
 	/* De-assert reset (let the CPU run) */
 	err = emi26_set_reset(dev,0);
@@ -192,6 +195,7 @@ static int emi26_load_firmware (struct usb_device *dev)
 		err("%s - error loading firmware: error = %d", __FUNCTION__, err);
 		goto wraperr;
 	}
+	msleep(250);	/* let device settle */
 
 	/* return 1 to fail the driver inialization
 	 * and give real driver change to load */
diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c
index 52fea2e08db87358f0d1073dfba5e2bc555b323b..fe351371f274e11e6b576dcce1a671cd2b8ef0f8 100644
--- a/drivers/usb/misc/emi62.c
+++ b/drivers/usb/misc/emi62.c
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/usb.h>
+#include <linux/delay.h>
 
 #define MAX_INTEL_HEX_RECORD_LENGTH 16
 typedef struct _INTEL_HEX_RECORD
@@ -123,6 +124,7 @@ static int emi62_load_firmware (struct usb_device *dev)
 
 	/* De-assert reset (let the CPU run) */
 	err = emi62_set_reset(dev,0);
+	msleep(250);	/* let device settle */
 
 	/* 2. We upload the FPGA firmware into the EMI
 	 * Note: collect up to 1023 (yes!) bytes and send them with
@@ -166,6 +168,7 @@ static int emi62_load_firmware (struct usb_device *dev)
 		err("%s - error loading firmware: error = %d", __FUNCTION__, err);
 		goto wraperr;
 	}
+	msleep(250);	/* let device settle */
 
 	/* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */
 
@@ -228,6 +231,7 @@ static int emi62_load_firmware (struct usb_device *dev)
 		err("%s - error loading firmware: error = %d", __FUNCTION__, err);
 		goto wraperr;
 	}
+	msleep(250);	/* let device settle */
 
 	kfree(buf);
 
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index 2deb4c01539e8466ef97766e408ff0b6689e71b5..7683926a1b6f19c5fae68caa07a6727691acfc17 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -318,6 +318,8 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
 	set_register(pegasus, PhyCtrl, (indx | PHY_READ));
 	for (i = 0; i < REG_TIMEOUT; i++) {
 		ret = get_registers(pegasus, PhyCtrl, 1, data);
+		if (ret == -ESHUTDOWN)
+			goto fail;
 		if (data[0] & PHY_DONE)
 			break;
 	}
@@ -326,6 +328,7 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
 		*regd = le16_to_cpu(regdi);
 		return ret;
 	}
+fail:
 	if (netif_msg_drv(pegasus))
 		dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
 
@@ -354,12 +357,15 @@ static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd)
 	set_register(pegasus, PhyCtrl, (indx | PHY_WRITE));
 	for (i = 0; i < REG_TIMEOUT; i++) {
 		ret = get_registers(pegasus, PhyCtrl, 1, data);
+		if (ret == -ESHUTDOWN)
+			goto fail;
 		if (data[0] & PHY_DONE)
 			break;
 	}
 	if (i < REG_TIMEOUT)
 		return ret;
 
+fail:
 	if (netif_msg_drv(pegasus))
 		dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
 	return -ETIMEDOUT;
@@ -387,6 +393,8 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata)
 		ret = get_registers(pegasus, EpromCtrl, 1, &tmp);
 		if (tmp & EPROM_DONE)
 			break;
+		if (ret == -ESHUTDOWN)
+			goto fail;
 	}
 	if (i < REG_TIMEOUT) {
 		ret = get_registers(pegasus, EpromData, 2, &retdatai);
@@ -394,6 +402,7 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata)
 		return ret;
 	}
 
+fail:
 	if (netif_msg_drv(pegasus))
 		dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
 	return -ETIMEDOUT;
@@ -433,12 +442,15 @@ static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data)
 
 	for (i = 0; i < REG_TIMEOUT; i++) {
 		ret = get_registers(pegasus, EpromCtrl, 1, &tmp);
+		if (ret == -ESHUTDOWN)
+			goto fail;
 		if (tmp & EPROM_DONE)
 			break;
 	}
 	disable_eprom_write(pegasus);
 	if (i < REG_TIMEOUT)
 		return ret;
+fail:
 	if (netif_msg_drv(pegasus))
 		dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
 	return -ETIMEDOUT;
@@ -1378,9 +1390,8 @@ static int pegasus_suspend (struct usb_interface *intf, pm_message_t message)
 	struct pegasus *pegasus = usb_get_intfdata(intf);
 	
 	netif_device_detach (pegasus->net);
+	cancel_delayed_work(&pegasus->carrier_check);
 	if (netif_running(pegasus->net)) {
-		cancel_delayed_work(&pegasus->carrier_check);
-
 		usb_kill_urb(pegasus->rx_urb);
 		usb_kill_urb(pegasus->intr_urb);
 	}
@@ -1400,10 +1411,9 @@ static int pegasus_resume (struct usb_interface *intf)
 		pegasus->intr_urb->status = 0;
 		pegasus->intr_urb->actual_length = 0;
 		intr_callback(pegasus->intr_urb, NULL);
-
-		queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check,
-					CARRIER_CHECK_DELAY);
 	}
+	queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check,
+				CARRIER_CHECK_DELAY);
 	return 0;
 }
 
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index f96b73f54bf1cdb7d4840d7b3c1c0600c8e4d6a0..5c60be521561a5fdeed21d5bd4df5a37b5a9ee9b 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -71,6 +71,16 @@ config USB_SERIAL_ANYDATA
 	  To compile this driver as a module, choose M here: the
 	  module will be called anydata.
 
+config USB_SERIAL_ARK3116
+	tristate "USB ARK Micro 3116 USB Serial Driver (EXPERIMENTAL)"
+	depends on USB_SERIAL && EXPERIMENTAL
+	help
+	  Say Y here if you want to use a ARK Micro 3116 USB to Serial
+	  device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ark3116
+
 config USB_SERIAL_BELKIN
 	tristate "USB Belkin and Peracom Single Port Serial Driver"
 	depends on USB_SERIAL
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 93c21245b1af713d52974d7eec80097073f52ee1..5a0960fc9d3e3facbfce9e90a0175e0fa25e4e46 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -13,6 +13,7 @@ usbserial-objs	:= usb-serial.o generic.o bus.o $(usbserial-obj-y)
 
 obj-$(CONFIG_USB_SERIAL_AIRPRIME)		+= airprime.o
 obj-$(CONFIG_USB_SERIAL_ANYDATA)		+= anydata.o
+obj-$(CONFIG_USB_SERIAL_ARK3116)		+= ark3116.o
 obj-$(CONFIG_USB_SERIAL_BELKIN)			+= belkin_sa.o
 obj-$(CONFIG_USB_SERIAL_CP2101)			+= cp2101.o
 obj-$(CONFIG_USB_SERIAL_CYBERJACK)		+= cyberjack.o
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index dbf1f063098c58f7c6424bff49e4d8e56a34034b..694b205f9b736e90f42e995b9d90de1a2d5bc72a 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -18,6 +18,7 @@
 static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(0xf3d, 0x0112) },  /* AirPrime CDMA Wireless PC Card */
 	{ USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */
+	{ USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless Aircard 580 */
 	{ },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
new file mode 100644
index 0000000000000000000000000000000000000000..8dec796222a0ac8fe8210b125a45227dc9ead4ad
--- /dev/null
+++ b/drivers/usb/serial/ark3116.c
@@ -0,0 +1,465 @@
+/*
+ * ark3116
+ * - implements a driver for the arkmicro ark3116 chipset (vendor=0x6547,
+ *   productid=0x0232) (used in a datacable called KQ-U8A)
+ *
+ * - based on code by krisfx -> thanks !!
+ *   (see http://www.linuxquestions.org/questions/showthread.php?p=2184457#post2184457)
+ *
+ *  - based on logs created by usbsnoopy
+ *
+ *  Author   : Simon Schulz [ark3116_driver<AT>auctionant.de]
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "usb-serial.h"
+
+
+static int debug;
+
+static struct usb_device_id id_table [] = {
+	{ USB_DEVICE(0x6547, 0x0232) },
+	{ },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+struct ark3116_private {
+	spinlock_t lock;
+	u8 termios_initialized;
+};
+
+static inline void ARK3116_SND(struct usb_serial *serial, int seq,
+			       __u8 request, __u8 requesttype,
+			       __u16 value, __u16 index)
+{
+	int result;
+	result = usb_control_msg(serial->dev,
+				 usb_sndctrlpipe(serial->dev,0),
+				 request, requesttype, value, index,
+				 NULL,0x00, 1000);
+	dbg("%03d > ok",seq);
+}
+
+static inline void ARK3116_RCV(struct usb_serial *serial, int seq,
+			       __u8 request, __u8 requesttype,
+			       __u16 value, __u16 index, __u8 expected,
+			       char *buf)
+{
+	int result;
+	result = usb_control_msg(serial->dev,
+			      usb_rcvctrlpipe(serial->dev,0),
+			      request, requesttype, value, index,
+			      buf, 0x0000001, 1000);
+	if (result)
+		dbg("%03d < %d bytes [0x%02X]",seq, result, buf[0]);
+	else
+		dbg("%03d < 0 bytes", seq);
+}
+
+
+static inline void ARK3116_RCV_QUIET(struct usb_serial *serial,
+				     __u8 request, __u8 requesttype,
+				     __u16 value, __u16 index, char *buf)
+{
+	usb_control_msg(serial->dev,
+			usb_rcvctrlpipe(serial->dev,0),
+			request, requesttype, value, index,
+			buf, 0x0000001, 1000);
+}
+
+
+static int ark3116_attach(struct usb_serial *serial)
+{
+	char *buf;
+	struct ark3116_private *priv;
+	int i;
+
+	for (i = 0; i < serial->num_ports; ++i) {
+		priv = kmalloc (sizeof (struct ark3116_private), GFP_KERNEL);
+		if (!priv)
+			goto cleanup;
+		memset (priv, 0x00, sizeof (struct ark3116_private));
+		spin_lock_init(&priv->lock);
+
+		usb_set_serial_port_data(serial->port[i], priv);
+	}
+
+	buf = kmalloc(1, GFP_KERNEL);
+	if (!buf) {
+		dbg("error kmalloc -> out of mem ?");
+		goto cleanup;
+	}
+
+	/* 3 */
+	ARK3116_SND(serial, 3,0xFE,0x40,0x0008,0x0002);
+	ARK3116_SND(serial, 4,0xFE,0x40,0x0008,0x0001);
+	ARK3116_SND(serial, 5,0xFE,0x40,0x0000,0x0008);
+	ARK3116_SND(serial, 6,0xFE,0x40,0x0000,0x000B);
+
+	/* <-- seq7 */
+	ARK3116_RCV(serial, 7,0xFE,0xC0,0x0000,0x0003, 0x00, buf);
+	ARK3116_SND(serial, 8,0xFE,0x40,0x0080,0x0003);
+	ARK3116_SND(serial, 9,0xFE,0x40,0x001A,0x0000);
+	ARK3116_SND(serial,10,0xFE,0x40,0x0000,0x0001);
+	ARK3116_SND(serial,11,0xFE,0x40,0x0000,0x0003);
+
+	/* <-- seq12 */
+	ARK3116_RCV(serial,12,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
+	ARK3116_SND(serial,13,0xFE,0x40,0x0000,0x0004);
+
+	/* 14 */
+	ARK3116_RCV(serial,14,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
+	ARK3116_SND(serial,15,0xFE,0x40,0x0000,0x0004);
+
+	/* 16 */
+	ARK3116_RCV(serial,16,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
+	/* --> seq17 */
+	ARK3116_SND(serial,17,0xFE,0x40,0x0001,0x0004);
+
+	/* <-- seq18 */
+	ARK3116_RCV(serial,18,0xFE,0xC0,0x0000,0x0004, 0x01, buf);
+
+	/* --> seq19 */
+	ARK3116_SND(serial,19,0xFE,0x40,0x0003,0x0004);
+
+
+	/* <-- seq20 */
+	/* seems like serial port status info (RTS, CTS,...) */
+	/* returns modem control line status ?! */
+	ARK3116_RCV(serial,20,0xFE,0xC0,0x0000,0x0006, 0xFF, buf);
+
+	/* set 9600 baud & do some init ?! */
+	ARK3116_SND(serial,147,0xFE,0x40,0x0083,0x0003);
+	ARK3116_SND(serial,148,0xFE,0x40,0x0038,0x0000);
+	ARK3116_SND(serial,149,0xFE,0x40,0x0001,0x0001);
+	ARK3116_SND(serial,150,0xFE,0x40,0x0003,0x0003);
+	ARK3116_RCV(serial,151,0xFE,0xC0,0x0000,0x0004,0x03, buf);
+	ARK3116_SND(serial,152,0xFE,0x40,0x0000,0x0003);
+	ARK3116_RCV(serial,153,0xFE,0xC0,0x0000,0x0003,0x00, buf);
+	ARK3116_SND(serial,154,0xFE,0x40,0x0003,0x0003);
+
+	kfree(buf);
+	return(0);
+
+cleanup:
+	for (--i; i>=0; --i)
+		usb_set_serial_port_data(serial->port[i], NULL);
+	return -ENOMEM;
+}
+
+static void ark3116_set_termios(struct usb_serial_port *port,
+				struct termios *old_termios)
+{
+	struct usb_serial *serial = port->serial;
+	struct ark3116_private *priv = usb_get_serial_port_data(port);
+	unsigned int cflag = port->tty->termios->c_cflag;
+	unsigned long flags;
+	int baud;
+	int ark3116_baud;
+	char *buf;
+	char config;
+
+	config = 0;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	if ((!port->tty) || (!port->tty->termios)) {
+		dbg("%s - no tty structures", __FUNCTION__);
+		return;
+	}
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (!priv->termios_initialized) {
+		*(port->tty->termios) = tty_std_termios;
+		port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+		priv->termios_initialized = 1;
+	}
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	cflag = port->tty->termios->c_cflag;
+
+	/* check that they really want us to change something: */
+	if (old_termios) {
+		if ((cflag == old_termios->c_cflag) &&
+		    (RELEVANT_IFLAG(port->tty->termios->c_iflag) ==
+		     RELEVANT_IFLAG(old_termios->c_iflag))) {
+			dbg("%s - nothing to change...", __FUNCTION__);
+			return;
+		}
+	}
+
+	buf = kmalloc(1, GFP_KERNEL);
+	if (!buf) {
+		dbg("error kmalloc");
+		return;
+	}
+
+	/* set data bit count (8/7/6/5) */
+	if (cflag & CSIZE){
+		switch (cflag & CSIZE){
+		case CS5:
+			config |= 0x00;
+			dbg("setting CS5");
+			break;
+		case CS6:
+			config |= 0x01;
+			dbg("setting CS6");
+			break;
+		case CS7:
+			config |= 0x02;
+			dbg("setting CS7");
+			break;
+		default:
+			err ("CSIZE was set but not CS5-CS8, using CS8!");
+		case CS8:
+			config |= 0x03;
+			dbg("setting CS8");
+			break;
+		}
+	}
+
+	/* set parity (NONE,EVEN,ODD) */
+	if (cflag & PARENB){
+		if (cflag & PARODD) {
+			config |= 0x08;
+			dbg("setting parity to ODD");
+		} else {
+			config |= 0x18;
+			dbg("setting parity to EVEN");
+		}
+	} else {
+		dbg("setting parity to NONE");
+	}
+
+	/* SET STOPBIT (1/2) */
+	if (cflag & CSTOPB) {
+		config |= 0x04;
+		dbg ("setting 2 stop bits");
+	} else {
+		dbg ("setting 1 stop bit");
+	}
+
+
+	/* set baudrate: */
+	baud = 0;
+	switch (cflag & CBAUD){
+		case B0:
+			err("can't set 0baud, using 9600 instead");
+			break;
+		case B75:	baud = 75;	break;
+		case B150:	baud = 150;	break;
+		case B300:	baud = 300;	break;
+		case B600:	baud = 600;	break;
+		case B1200:	baud = 1200;	break;
+		case B1800:	baud = 1800;	break;
+		case B2400:	baud = 2400;	break;
+		case B4800:	baud = 4800;	break;
+		case B9600:	baud = 9600;	break;
+		case B19200:	baud = 19200;	break;
+		case B38400:	baud = 38400;	break;
+		case B57600:	baud = 57600;	break;
+		case B115200:	baud = 115200;	break;
+		case B230400:	baud = 230400;	break;
+		case B460800:	baud = 460800;	break;
+		default:
+			dbg("does not support the baudrate requested (fix it)");
+			break;
+	}
+
+	/* set 9600 as default (if given baudrate is invalid for example) */
+	if (baud == 0)
+		baud = 9600;
+
+	/*
+	 * found by try'n'error, be careful, maybe there are other options
+	 * for multiplicator etc!
+	 */
+	if (baud == 460800)
+		/* strange, for 460800 the formula is wrong
+		 * (dont use round(), then 9600baud is wrong) */
+		ark3116_baud = 7;
+	else
+		ark3116_baud = 3000000 / baud;
+
+	/* ? */
+	ARK3116_RCV(serial,0,0xFE,0xC0,0x0000,0x0003, 0x03, buf);
+	/* offset = buf[0]; */
+	/* offset = 0x03; */
+	/* dbg("using 0x%04X as target for 0x0003:",0x0080+offset); */
+
+
+	/* set baudrate */
+	dbg("setting baudrate to %d (->reg=%d)",baud,ark3116_baud);
+	ARK3116_SND(serial,147,0xFE,0x40,0x0083,0x0003);
+	ARK3116_SND(serial,148,0xFE,0x40,(ark3116_baud & 0x00FF)   ,0x0000);
+	ARK3116_SND(serial,149,0xFE,0x40,(ark3116_baud & 0xFF00)>>8,0x0001);
+	ARK3116_SND(serial,150,0xFE,0x40,0x0003,0x0003);
+
+	/* ? */
+	ARK3116_RCV(serial,151,0xFE,0xC0,0x0000,0x0004,0x03, buf);
+	ARK3116_SND(serial,152,0xFE,0x40,0x0000,0x0003);
+
+	/* set data bit count, stop bit count & parity: */
+	dbg("updating bit count, stop bit or parity (cfg=0x%02X)", config);
+	ARK3116_RCV(serial,153,0xFE,0xC0,0x0000,0x0003,0x00, buf);
+	ARK3116_SND(serial,154,0xFE,0x40,config,0x0003);
+
+	if (cflag & CRTSCTS)
+		dbg("CRTSCTS not supported by chipset ?!");
+
+	/* TEST ARK3116_SND(154,0xFE,0x40,0xFFFF, 0x0006); */
+
+	kfree(buf);
+	return;
+}
+
+static int ark3116_open(struct usb_serial_port *port, struct file *filp)
+{
+	struct termios tmp_termios;
+	struct usb_serial *serial = port->serial;
+	char *buf;
+	int result = 0;
+
+	dbg("%s -  port %d", __FUNCTION__, port->number);
+
+	buf = kmalloc(1, GFP_KERNEL);
+	if (!buf) {
+		dbg("error kmalloc -> out of mem ?");
+		return -ENOMEM;
+	}
+
+	result = usb_serial_generic_open(port, filp);
+	if (result)
+		return result;
+
+	/* open */
+	ARK3116_RCV(serial,111,0xFE,0xC0,0x0000,0x0003, 0x02, buf);
+
+	ARK3116_SND(serial,112,0xFE,0x40,0x0082,0x0003);
+	ARK3116_SND(serial,113,0xFE,0x40,0x001A,0x0000);
+	ARK3116_SND(serial,114,0xFE,0x40,0x0000,0x0001);
+	ARK3116_SND(serial,115,0xFE,0x40,0x0002,0x0003);
+
+	ARK3116_RCV(serial,116,0xFE,0xC0,0x0000,0x0004, 0x03, buf);
+	ARK3116_SND(serial,117,0xFE,0x40,0x0002,0x0004);
+
+	ARK3116_RCV(serial,118,0xFE,0xC0,0x0000,0x0004, 0x02, buf);
+	ARK3116_SND(serial,119,0xFE,0x40,0x0000,0x0004);
+
+	ARK3116_RCV(serial,120,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
+
+	ARK3116_SND(serial,121,0xFE,0x40,0x0001,0x0004);
+
+	ARK3116_RCV(serial,122,0xFE,0xC0,0x0000,0x0004, 0x01, buf);
+
+	ARK3116_SND(serial,123,0xFE,0x40,0x0003,0x0004);
+
+	/* returns different values (control lines ?!) */
+	ARK3116_RCV(serial,124,0xFE,0xC0,0x0000,0x0006, 0xFF, buf);
+
+	/* initialise termios: */
+	if (port->tty)
+		ark3116_set_termios(port, &tmp_termios);
+
+	kfree(buf);
+
+	return result;
+
+}
+
+static int ark3116_ioctl(struct usb_serial_port *port, struct file *file,
+			 unsigned int cmd, unsigned long arg)
+{
+	dbg("ioctl not supported yet...");
+	return -ENOIOCTLCMD;
+}
+
+static int ark3116_tiocmget(struct usb_serial_port *port, struct file *file)
+{
+	struct usb_serial *serial = port->serial;
+	char *buf;
+	char temp;
+
+	/* seems like serial port status info (RTS, CTS,...) is stored
+	 * in reg(?) 0x0006
+	 * pcb connection point 11 = GND -> sets bit4 of response
+	 * pcb connection point  7 = GND -> sets bit6 of response
+	 */
+
+	buf = kmalloc(1, GFP_KERNEL);
+	if (!buf) {
+		dbg("error kmalloc");
+		return -ENOMEM;
+	}
+
+	/* read register: */
+	ARK3116_RCV_QUIET(serial,0xFE,0xC0,0x0000,0x0006,buf);
+	temp = buf[0];
+	kfree(buf);
+
+	/* i do not really know if bit4=CTS and bit6=DSR... was just a
+	 * quick guess !!
+	 */
+	return  (temp & (1<<4) ? TIOCM_CTS : 0) |
+	        (temp & (1<<6) ? TIOCM_DSR : 0);
+}
+
+static struct usb_driver ark3116_driver = {
+	.name =		"ark3116",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table,
+};
+
+static struct usb_serial_driver ark3116_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"ark3116",
+	},
+	.id_table =		id_table,
+	.num_interrupt_in =	1,
+	.num_bulk_in =		1,
+	.num_bulk_out =		1,
+	.num_ports =		1,
+	.attach =		ark3116_attach,
+	.set_termios =		ark3116_set_termios,
+	.ioctl =		ark3116_ioctl,
+	.tiocmget =		ark3116_tiocmget,
+	.open =			ark3116_open,
+};
+
+static int __init ark3116_init(void)
+{
+	int retval;
+
+	retval = usb_serial_register(&ark3116_device);
+	if (retval)
+		return retval;
+	retval = usb_register(&ark3116_driver);
+	if (retval)
+		usb_serial_deregister(&ark3116_device);
+	return retval;
+}
+
+static void __exit ark3116_exit(void)
+{
+	usb_deregister(&ark3116_driver);
+	usb_serial_deregister(&ark3116_device);
+}
+
+module_init(ark3116_init);
+module_exit(ark3116_exit);
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 82151207d814674d38de9c5f94323e006b6b50aa..986d7622273d319e1ae4178aada87170fe246918 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -307,6 +307,7 @@ static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = {
 
 
 static struct usb_device_id id_table_combined [] = {
+	{ USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
@@ -498,6 +499,7 @@ static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) },
 	{ USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) },
 	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 2c55a5ea9c992adcb94db8f58cd82b6813d44e5b..d69a917e768f2e445851b7fea27442c3e023e48d 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -32,6 +32,10 @@
 #define FTDI_NF_RIC_PID	0x0001	/* Product Id */
 
 
+/* ACT Solutions HomePro ZWave interface (http://www.act-solutions.com/HomePro.htm) */
+#define FTDI_ACTZWAVE_PID	0xF2D0
+
+
 /* www.irtrans.de device */
 #define FTDI_IRTRANS_PID 0xFC60 /* Product Id */
 
@@ -426,6 +430,11 @@
 #define PAPOUCH_VID			0x5050	/* Vendor ID */
 #define PAPOUCH_TMU_PID			0x0400	/* TMU USB Thermometer */
 
+/*
+ * ACG Identification Technologies GmbH products (http://www.acg.de/).
+ * Submitted by anton -at- goto10 -dot- org.
+ */
+#define FTDI_ACG_HFDUAL_PID		0xDD20	/* HF Dual ISO Reader (RFID) */
 
 /* Commands */
 #define FTDI_SIO_RESET 		0 /* Reset the port */
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 476cda107f4fa8bcf0ef2fe53a04d9f37f4a698d..c62cc2876519629a6bd39e8b6284b84a51d201ab 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -138,6 +138,7 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
 
 	return result;
 }
+EXPORT_SYMBOL_GPL(usb_serial_generic_open);
 
 static void generic_cleanup (struct usb_serial_port *port)
 {
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 4d40704dea2cf157d30673bdbae47f27844dc201..238033a87092fc841c7c6ac225ff921ec381139a 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -257,14 +257,14 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
 		return (0);
 	}
 
-	spin_lock(&port->lock);
-	if (port->write_urb_busy) {
-		spin_unlock(&port->lock);
+	spin_lock(&wport->lock);
+	if (wport->write_urb_busy) {
+		spin_unlock(&wport->lock);
 		dbg("%s - already writing", __FUNCTION__);
 		return 0;
 	}
-	port->write_urb_busy = 1;
-	spin_unlock(&port->lock);
+	wport->write_urb_busy = 1;
+	spin_unlock(&wport->lock);
 
 	count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count;
 
@@ -283,7 +283,7 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
 	wport->write_urb->dev = serial->dev;
 	result = usb_submit_urb(wport->write_urb, GFP_ATOMIC);
 	if (result) {
-		port->write_urb_busy = 0;
+		wport->write_urb_busy = 0;
 		err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
 	} else
 		result = count;
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 071f86a59c086222ecf89c8705080b064b4d8fdc..9c36f0ece20ff6b43631e860621198f694400d5f 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -189,11 +189,15 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
 
 	portNumber = tty->index - serial->minor;
 	port = serial->port[portNumber];
-	if (!port)
-		return -ENODEV;
+	if (!port) {
+		retval = -ENODEV;
+		goto bailout_kref_put;
+	}
 
-	if (mutex_lock_interruptible(&port->mutex))
-		return -ERESTARTSYS;
+	if (mutex_lock_interruptible(&port->mutex)) {
+		retval = -ERESTARTSYS;
+		goto bailout_kref_put;
+	}
 	 
 	++port->open_count;
 
@@ -209,7 +213,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
 		 * safe because we are called with BKL held */
 		if (!try_module_get(serial->type->driver.owner)) {
 			retval = -ENODEV;
-			goto bailout_kref_put;
+			goto bailout_mutex_unlock;
 		}
 
 		/* only call the device specific open if this 
@@ -224,10 +228,11 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
 
 bailout_module_put:
 	module_put(serial->type->driver.owner);
-bailout_kref_put:
-	kref_put(&serial->kref, destroy_serial);
+bailout_mutex_unlock:
 	port->open_count = 0;
 	mutex_unlock(&port->mutex);
+bailout_kref_put:
+	kref_put(&serial->kref, destroy_serial);
 	return retval;
 }
 
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 334b1db1bd7cc42f52e3a5c3353dd28b7b1c032d..27597c576eff3f4cb0a116dee1d682f8ce4f9383 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -29,12 +29,15 @@ static ssize_t backlight_show_power(struct class_device *cdev, char *buf)
 
 static ssize_t backlight_store_power(struct class_device *cdev, const char *buf, size_t count)
 {
-	int rc = -ENXIO, power;
+	int rc = -ENXIO;
 	char *endp;
 	struct backlight_device *bd = to_backlight_device(cdev);
+	int power = simple_strtoul(buf, &endp, 0);
+	size_t size = endp - buf;
 
-	power = simple_strtoul(buf, &endp, 0);
-	if (*endp && !isspace(*endp))
+	if (*endp && isspace(*endp))
+		size++;
+	if (size != count)
 		return -EINVAL;
 
 	down(&bd->sem);
@@ -65,12 +68,15 @@ static ssize_t backlight_show_brightness(struct class_device *cdev, char *buf)
 
 static ssize_t backlight_store_brightness(struct class_device *cdev, const char *buf, size_t count)
 {
-	int rc = -ENXIO, brightness;
+	int rc = -ENXIO;
 	char *endp;
 	struct backlight_device *bd = to_backlight_device(cdev);
+	int brightness = simple_strtoul(buf, &endp, 0);
+	size_t size = endp - buf;
 
-	brightness = simple_strtoul(buf, &endp, 0);
-	if (*endp && !isspace(*endp))
+	if (*endp && isspace(*endp))
+		size++;
+	if (size != count)
 		return -EINVAL;
 
 	down(&bd->sem);
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index 86908a60c630d9624fab519c24d1ab0f28091e3b..bc8ab005a3fb174a9eecc050a76301469ed2916f 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -31,12 +31,15 @@ static ssize_t lcd_show_power(struct class_device *cdev, char *buf)
 
 static ssize_t lcd_store_power(struct class_device *cdev, const char *buf, size_t count)
 {
-	int rc, power;
+	int rc = -ENXIO;
 	char *endp;
 	struct lcd_device *ld = to_lcd_device(cdev);
+	int power = simple_strtoul(buf, &endp, 0);
+	size_t size = endp - buf;
 
-	power = simple_strtoul(buf, &endp, 0);
-	if (*endp && !isspace(*endp))
+	if (*endp && isspace(*endp))
+		size++;
+	if (size != count)
 		return -EINVAL;
 
 	down(&ld->sem);
@@ -44,8 +47,7 @@ static ssize_t lcd_store_power(struct class_device *cdev, const char *buf, size_
 		pr_debug("lcd: set power to %d\n", power);
 		ld->props->set_power(ld, power);
 		rc = count;
-	} else
-		rc = -ENXIO;
+	}
 	up(&ld->sem);
 
 	return rc;
@@ -53,14 +55,12 @@ static ssize_t lcd_store_power(struct class_device *cdev, const char *buf, size_
 
 static ssize_t lcd_show_contrast(struct class_device *cdev, char *buf)
 {
-	int rc;
+	int rc = -ENXIO;
 	struct lcd_device *ld = to_lcd_device(cdev);
 
 	down(&ld->sem);
 	if (likely(ld->props && ld->props->get_contrast))
 		rc = sprintf(buf, "%d\n", ld->props->get_contrast(ld));
-	else
-		rc = -ENXIO;
 	up(&ld->sem);
 
 	return rc;
@@ -68,12 +68,15 @@ static ssize_t lcd_show_contrast(struct class_device *cdev, char *buf)
 
 static ssize_t lcd_store_contrast(struct class_device *cdev, const char *buf, size_t count)
 {
-	int rc, contrast;
+	int rc = -ENXIO;
 	char *endp;
 	struct lcd_device *ld = to_lcd_device(cdev);
+	int contrast = simple_strtoul(buf, &endp, 0);
+	size_t size = endp - buf;
 
-	contrast = simple_strtoul(buf, &endp, 0);
-	if (*endp && !isspace(*endp))
+	if (*endp && isspace(*endp))
+		size++;
+	if (size != count)
 		return -EINVAL;
 
 	down(&ld->sem);
@@ -81,8 +84,7 @@ static ssize_t lcd_store_contrast(struct class_device *cdev, const char *buf, si
 		pr_debug("lcd: set contrast to %d\n", contrast);
 		ld->props->set_contrast(ld, contrast);
 		rc = count;
-	} else
-		rc = -ENXIO;
+	}
 	up(&ld->sem);
 
 	return rc;
@@ -90,14 +92,12 @@ static ssize_t lcd_store_contrast(struct class_device *cdev, const char *buf, si
 
 static ssize_t lcd_show_max_contrast(struct class_device *cdev, char *buf)
 {
-	int rc;
+	int rc = -ENXIO;
 	struct lcd_device *ld = to_lcd_device(cdev);
 
 	down(&ld->sem);
 	if (likely(ld->props))
 		rc = sprintf(buf, "%d\n", ld->props->max_contrast);
-	else
-		rc = -ENXIO;
 	up(&ld->sem);
 
 	return rc;
diff --git a/drivers/video/logo/Makefile b/drivers/video/logo/Makefile
index 4ef5cd19609d650623890238e1b9055ab8699712..b985dfad6c63fb369c812e1d198e5d66c5f30670 100644
--- a/drivers/video/logo/Makefile
+++ b/drivers/video/logo/Makefile
@@ -34,7 +34,7 @@ extra-y += $(call logo-cfiles,_clut224,ppm)
 extra-y += $(call logo-cfiles,_gray256,pgm)
 
 # Create commands like "pnmtologo -t mono -n logo_mac_mono -o ..."
-quiet_cmd_logo = LOGO	$@
+quiet_cmd_logo = LOGO    $@
 	cmd_logo = scripts/pnmtologo \
 			-t $(patsubst $*_%,%,$(notdir $(basename $<))) \
 			-n $(notdir $(basename $<)) -o $@ $<
diff --git a/fs/9p/fcall.c b/fs/9p/fcall.c
index 71742ba150c44f12a4abb3b4ce45c15fcc15e775..6f2617820a4ef3ad001bad832978ea55ad379774 100644
--- a/fs/9p/fcall.c
+++ b/fs/9p/fcall.c
@@ -98,23 +98,20 @@ v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname,
 static void v9fs_t_clunk_cb(void *a, struct v9fs_fcall *tc,
 	struct v9fs_fcall *rc, int err)
 {
-	int fid;
+	int fid, id;
 	struct v9fs_session_info *v9ses;
 
-	if (err)
-		return;
-
+	id = 0;
 	fid = tc->params.tclunk.fid;
-	kfree(tc);
-
-	if (!rc)
-		return;
-
-	v9ses = a;
-	if (rc->id == RCLUNK)
-		v9fs_put_idpool(fid, &v9ses->fidpool);
+	if (rc)
+		id = rc->id;
 
+	kfree(tc);
 	kfree(rc);
+	if (id == RCLUNK) {
+		v9ses = a;
+		v9fs_put_idpool(fid, &v9ses->fidpool);
+	}
 }
 
 /**
diff --git a/fs/9p/mux.c b/fs/9p/mux.c
index 3e5b124a72123d4c50a99c44351d87a0a21d5388..f4407eb276c7cfa7d350061792b08e0393d4ae3b 100644
--- a/fs/9p/mux.c
+++ b/fs/9p/mux.c
@@ -50,15 +50,23 @@ enum {
 	Wpending = 8,		/* can write */
 };
 
+enum {
+	None,
+	Flushing,
+	Flushed,
+};
+
 struct v9fs_mux_poll_task;
 
 struct v9fs_req {
+	spinlock_t lock;
 	int tag;
 	struct v9fs_fcall *tcall;
 	struct v9fs_fcall *rcall;
 	int err;
 	v9fs_mux_req_callback cb;
 	void *cba;
+	int flush;
 	struct list_head req_list;
 };
 
@@ -96,8 +104,8 @@ struct v9fs_mux_poll_task {
 
 struct v9fs_mux_rpc {
 	struct v9fs_mux_data *m;
-	struct v9fs_req *req;
 	int err;
+	struct v9fs_fcall *tcall;
 	struct v9fs_fcall *rcall;
 	wait_queue_head_t wqueue;
 };
@@ -524,10 +532,9 @@ again:
 
 static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req)
 {
-	int ecode, tag;
+	int ecode;
 	struct v9fs_str *ename;
 
-	tag = req->tag;
 	if (!req->err && req->rcall->id == RERROR) {
 		ecode = req->rcall->params.rerror.errno;
 		ename = &req->rcall->params.rerror.error;
@@ -553,23 +560,6 @@ static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req)
 		if (!req->err)
 			req->err = -EIO;
 	}
-
-	if (req->err == ERREQFLUSH)
-		return;
-
-	if (req->cb) {
-		dprintk(DEBUG_MUX, "calling callback tcall %p rcall %p\n",
-			req->tcall, req->rcall);
-
-		(*req->cb) (req->cba, req->tcall, req->rcall, req->err);
-		req->cb = NULL;
-	} else
-		kfree(req->rcall);
-
-	v9fs_mux_put_tag(m, tag);
-
-	wake_up(&m->equeue);
-	kfree(req);
 }
 
 /**
@@ -669,17 +659,26 @@ static void v9fs_read_work(void *a)
 		list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) {
 			if (rreq->tag == rcall->tag) {
 				req = rreq;
-				req->rcall = rcall;
-				list_del(&req->req_list);
-				spin_unlock(&m->lock);
-				process_request(m, req);
+				if (req->flush != Flushing)
+					list_del(&req->req_list);
 				break;
 			}
-
 		}
+		spin_unlock(&m->lock);
 
-		if (!req) {
-			spin_unlock(&m->lock);
+		if (req) {
+			req->rcall = rcall;
+			process_request(m, req);
+
+			if (req->flush != Flushing) {
+				if (req->cb)
+					(*req->cb) (req, req->cba);
+				else
+					kfree(req->rcall);
+
+				wake_up(&m->equeue);
+			}
+		} else {
 			if (err >= 0 && rcall->id != RFLUSH)
 				dprintk(DEBUG_ERROR,
 					"unexpected response mux %p id %d tag %d\n",
@@ -746,7 +745,6 @@ static struct v9fs_req *v9fs_send_request(struct v9fs_mux_data *m,
 		return ERR_PTR(-ENOMEM);
 
 	v9fs_set_tag(tc, n);
-
 	if ((v9fs_debug_level&DEBUG_FCALL) == DEBUG_FCALL) {
 		char buf[150];
 
@@ -754,12 +752,14 @@ static struct v9fs_req *v9fs_send_request(struct v9fs_mux_data *m,
 		printk(KERN_NOTICE "<<< %p %s\n", m, buf);
 	}
 
+	spin_lock_init(&req->lock);
 	req->tag = n;
 	req->tcall = tc;
 	req->rcall = NULL;
 	req->err = 0;
 	req->cb = cb;
 	req->cba = cba;
+	req->flush = None;
 
 	spin_lock(&m->lock);
 	list_add_tail(&req->req_list, &m->unsent_req_list);
@@ -776,72 +776,108 @@ static struct v9fs_req *v9fs_send_request(struct v9fs_mux_data *m,
 	return req;
 }
 
-static void v9fs_mux_flush_cb(void *a, struct v9fs_fcall *tc,
-			      struct v9fs_fcall *rc, int err)
+static void v9fs_mux_free_request(struct v9fs_mux_data *m, struct v9fs_req *req)
+{
+	v9fs_mux_put_tag(m, req->tag);
+	kfree(req);
+}
+
+static void v9fs_mux_flush_cb(struct v9fs_req *freq, void *a)
 {
 	v9fs_mux_req_callback cb;
 	int tag;
 	struct v9fs_mux_data *m;
-	struct v9fs_req *req, *rptr;
+	struct v9fs_req *req, *rreq, *rptr;
 
 	m = a;
-	dprintk(DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m, tc,
-		rc, err, tc->params.tflush.oldtag);
+	dprintk(DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m,
+		freq->tcall, freq->rcall, freq->err,
+		freq->tcall->params.tflush.oldtag);
 
 	spin_lock(&m->lock);
 	cb = NULL;
-	tag = tc->params.tflush.oldtag;
-	list_for_each_entry_safe(req, rptr, &m->req_list, req_list) {
-		if (req->tag == tag) {
+	tag = freq->tcall->params.tflush.oldtag;
+	req = NULL;
+	list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) {
+		if (rreq->tag == tag) {
+			req = rreq;
 			list_del(&req->req_list);
-			if (req->cb) {
-				cb = req->cb;
-				req->cb = NULL;
-				spin_unlock(&m->lock);
-				(*cb) (req->cba, req->tcall, req->rcall,
-				       req->err);
-			}
-			kfree(req);
-			wake_up(&m->equeue);
 			break;
 		}
 	}
+	spin_unlock(&m->lock);
 
-	if (!cb)
-		spin_unlock(&m->lock);
+	if (req) {
+		spin_lock(&req->lock);
+		req->flush = Flushed;
+		spin_unlock(&req->lock);
+
+		if (req->cb)
+			(*req->cb) (req, req->cba);
+		else
+			kfree(req->rcall);
+
+		wake_up(&m->equeue);
+	}
 
-	v9fs_mux_put_tag(m, tag);
-	kfree(tc);
-	kfree(rc);
+	kfree(freq->tcall);
+	kfree(freq->rcall);
+	v9fs_mux_free_request(m, freq);
 }
 
-static void
+static int
 v9fs_mux_flush_request(struct v9fs_mux_data *m, struct v9fs_req *req)
 {
 	struct v9fs_fcall *fc;
+	struct v9fs_req *rreq, *rptr;
 
 	dprintk(DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag);
 
+	/* if a response was received for a request, do nothing */
+	spin_lock(&req->lock);
+	if (req->rcall || req->err) {
+		spin_unlock(&req->lock);
+		dprintk(DEBUG_MUX, "mux %p req %p response already received\n", m, req);
+		return 0;
+	}
+
+	req->flush = Flushing;
+	spin_unlock(&req->lock);
+
+	spin_lock(&m->lock);
+	/* if the request is not sent yet, just remove it from the list */
+	list_for_each_entry_safe(rreq, rptr, &m->unsent_req_list, req_list) {
+		if (rreq->tag == req->tag) {
+			dprintk(DEBUG_MUX, "mux %p req %p request is not sent yet\n", m, req);
+			list_del(&rreq->req_list);
+			req->flush = Flushed;
+			spin_unlock(&m->lock);
+			if (req->cb)
+				(*req->cb) (req, req->cba);
+			return 0;
+		}
+	}
+	spin_unlock(&m->lock);
+
+	clear_thread_flag(TIF_SIGPENDING);
 	fc = v9fs_create_tflush(req->tag);
 	v9fs_send_request(m, fc, v9fs_mux_flush_cb, m);
+	return 1;
 }
 
 static void
-v9fs_mux_rpc_cb(void *a, struct v9fs_fcall *tc, struct v9fs_fcall *rc, int err)
+v9fs_mux_rpc_cb(struct v9fs_req *req, void *a)
 {
 	struct v9fs_mux_rpc *r;
 
-	if (err == ERREQFLUSH) {
-		kfree(rc);
-		dprintk(DEBUG_MUX, "err req flush\n");
-		return;
-	}
-
+	dprintk(DEBUG_MUX, "req %p r %p\n", req, a);
 	r = a;
-	dprintk(DEBUG_MUX, "mux %p req %p tc %p rc %p err %d\n", r->m, r->req,
-		tc, rc, err);
-	r->rcall = rc;
-	r->err = err;
+	r->rcall = req->rcall;
+	r->err = req->err;
+
+	if (req->flush!=None && !req->err)
+		r->err = -ERESTARTSYS;
+
 	wake_up(&r->wqueue);
 }
 
@@ -856,12 +892,13 @@ int
 v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
 	     struct v9fs_fcall **rc)
 {
-	int err;
+	int err, sigpending;
 	unsigned long flags;
 	struct v9fs_req *req;
 	struct v9fs_mux_rpc r;
 
 	r.err = 0;
+	r.tcall = tc;
 	r.rcall = NULL;
 	r.m = m;
 	init_waitqueue_head(&r.wqueue);
@@ -869,48 +906,50 @@ v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
 	if (rc)
 		*rc = NULL;
 
+	sigpending = 0;
+	if (signal_pending(current)) {
+		sigpending = 1;
+		clear_thread_flag(TIF_SIGPENDING);
+	}
+
 	req = v9fs_send_request(m, tc, v9fs_mux_rpc_cb, &r);
 	if (IS_ERR(req)) {
 		err = PTR_ERR(req);
 		dprintk(DEBUG_MUX, "error %d\n", err);
-		return PTR_ERR(req);
+		return err;
 	}
 
-	r.req = req;
-	dprintk(DEBUG_MUX, "mux %p tc %p tag %d rpc %p req %p\n", m, tc,
-		req->tag, &r, req);
 	err = wait_event_interruptible(r.wqueue, r.rcall != NULL || r.err < 0);
 	if (r.err < 0)
 		err = r.err;
 
 	if (err == -ERESTARTSYS && m->trans->status == Connected && m->err == 0) {
-		spin_lock(&m->lock);
-		req->tcall = NULL;
-		req->err = ERREQFLUSH;
-		spin_unlock(&m->lock);
+		if (v9fs_mux_flush_request(m, req)) {
+			/* wait until we get response of the flush message */
+			do {
+				clear_thread_flag(TIF_SIGPENDING);
+				err = wait_event_interruptible(r.wqueue,
+					r.rcall || r.err);
+			} while (!r.rcall && !r.err && err==-ERESTARTSYS &&
+				m->trans->status==Connected && !m->err);
+		}
+		sigpending = 1;
+	}
 
-		clear_thread_flag(TIF_SIGPENDING);
-		v9fs_mux_flush_request(m, req);
+	if (sigpending) {
 		spin_lock_irqsave(&current->sighand->siglock, flags);
 		recalc_sigpending();
 		spin_unlock_irqrestore(&current->sighand->siglock, flags);
 	}
 
-	if (!err) {
-		if (r.rcall)
-			dprintk(DEBUG_MUX, "got response id %d tag %d\n",
-				r.rcall->id, r.rcall->tag);
-
-		if (rc)
-			*rc = r.rcall;
-		else
-			kfree(r.rcall);
-	} else {
+	if (rc)
+		*rc = r.rcall;
+	else
 		kfree(r.rcall);
-		dprintk(DEBUG_MUX, "got error %d\n", err);
-		if (err > 0)
-			err = -EIO;
-	}
+
+	v9fs_mux_free_request(m, req);
+	if (err > 0)
+		err = -EIO;
 
 	return err;
 }
@@ -951,12 +990,15 @@ void v9fs_mux_cancel(struct v9fs_mux_data *m, int err)
 	struct v9fs_req *req, *rtmp;
 	LIST_HEAD(cancel_list);
 
-	dprintk(DEBUG_MUX, "mux %p err %d\n", m, err);
+	dprintk(DEBUG_ERROR, "mux %p err %d\n", m, err);
 	m->err = err;
 	spin_lock(&m->lock);
 	list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) {
 		list_move(&req->req_list, &cancel_list);
 	}
+	list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) {
+		list_move(&req->req_list, &cancel_list);
+	}
 	spin_unlock(&m->lock);
 
 	list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) {
@@ -965,11 +1007,9 @@ void v9fs_mux_cancel(struct v9fs_mux_data *m, int err)
 			req->err = err;
 
 		if (req->cb)
-			(*req->cb) (req->cba, req->tcall, req->rcall, req->err);
+			(*req->cb) (req, req->cba);
 		else
 			kfree(req->rcall);
-
-		kfree(req);
 	}
 
 	wake_up(&m->equeue);
diff --git a/fs/9p/mux.h b/fs/9p/mux.h
index e90bfd32ea42335ebd411e0d82423b34a38e5d0d..fb10c50186a11b6bb23323d845f918d535936a3c 100644
--- a/fs/9p/mux.h
+++ b/fs/9p/mux.h
@@ -24,6 +24,7 @@
  */
 
 struct v9fs_mux_data;
+struct v9fs_req;
 
 /**
  * v9fs_mux_req_callback - callback function that is called when the
@@ -36,8 +37,7 @@ struct v9fs_mux_data;
  * @rc - response call
  * @err - error code (non-zero if error occured)
  */
-typedef void (*v9fs_mux_req_callback)(void *a, struct v9fs_fcall *tc,
-	struct v9fs_fcall *rc, int err);
+typedef void (*v9fs_mux_req_callback)(struct v9fs_req *req, void *a);
 
 int v9fs_mux_global_init(void);
 void v9fs_mux_global_exit(void);
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 083dcfcd158e1cd3df4e445fdecabdd3c286f8eb..1a8e46084f0e1b25f14dc12417429dd79e94529f 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -72,11 +72,17 @@ int v9fs_file_open(struct inode *inode, struct file *file)
 		return -ENOSPC;
 	}
 
-	err = v9fs_t_walk(v9ses, vfid->fid, fid, NULL, NULL);
+	err = v9fs_t_walk(v9ses, vfid->fid, fid, NULL, &fcall);
 	if (err < 0) {
 		dprintk(DEBUG_ERROR, "rewalk didn't work\n");
-		goto put_fid;
+		if (fcall && fcall->id == RWALK)
+			goto clunk_fid;
+		else {
+			v9fs_put_idpool(fid, &v9ses->fidpool);
+			goto free_fcall;
+		}
 	}
+	kfree(fcall);
 
 	/* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */
 	/* translate open mode appropriately */
@@ -109,8 +115,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
 clunk_fid:
 	v9fs_t_clunk(v9ses, fid);
 
-put_fid:
-	v9fs_put_idpool(fid, &v9ses->fidpool);
+free_fcall:
 	kfree(fcall);
 
 	return err;
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 133db366d30659aad05be2c18a383e5722eb1f71..2cb87ba4b1c1fa76ab685d213ae6e0f33a53dcf8 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -270,7 +270,10 @@ v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name, u32 perm,
 	err = v9fs_t_walk(v9ses, pfid, fid, NULL, &fcall);
 	if (err < 0) {
 		PRINT_FCALL_ERROR("clone error", fcall);
-		goto put_fid;
+		if (fcall && fcall->id == RWALK)
+			goto clunk_fid;
+		else
+			goto put_fid;
 	}
 	kfree(fcall);
 
@@ -322,6 +325,9 @@ v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry)
 		&fcall);
 
 	if (err < 0) {
+		if (fcall && fcall->id == RWALK)
+			goto clunk_fid;
+
 		PRINT_FCALL_ERROR("walk error", fcall);
 		v9fs_put_idpool(nfid, &v9ses->fidpool);
 		goto error;
@@ -640,19 +646,26 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
 	}
 
 	result = v9fs_t_walk(v9ses, dirfidnum, newfid,
-		(char *)dentry->d_name.name, NULL);
+		(char *)dentry->d_name.name, &fcall);
+
 	if (result < 0) {
-		v9fs_put_idpool(newfid, &v9ses->fidpool);
+		if (fcall && fcall->id == RWALK)
+			v9fs_t_clunk(v9ses, newfid);
+		else
+			v9fs_put_idpool(newfid, &v9ses->fidpool);
+
 		if (result == -ENOENT) {
 			d_add(dentry, NULL);
 			dprintk(DEBUG_VFS,
 				"Return negative dentry %p count %d\n",
 				dentry, atomic_read(&dentry->d_count));
+			kfree(fcall);
 			return NULL;
 		}
 		dprintk(DEBUG_ERROR, "walk error:%d\n", result);
 		goto FreeFcall;
 	}
+	kfree(fcall);
 
 	result = v9fs_t_stat(v9ses, newfid, &fcall);
 	if (result < 0) {
diff --git a/fs/Makefile b/fs/Makefile
index 83bf478e786b3f64f1d5a90826f5d92622077950..078d3d1191a511f3ad88ac0167142fda8c10c5a9 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_DNOTIFY)		+= dnotify.o
 obj-$(CONFIG_PROC_FS)		+= proc/
 obj-y				+= partitions/
 obj-$(CONFIG_SYSFS)		+= sysfs/
+obj-$(CONFIG_CONFIGFS_FS)	+= configfs/
 obj-y				+= devpts/
 
 obj-$(CONFIG_PROFILING)		+= dcookies.o
@@ -100,5 +101,4 @@ obj-$(CONFIG_BEFS_FS)		+= befs/
 obj-$(CONFIG_HOSTFS)		+= hostfs/
 obj-$(CONFIG_HPPFS)		+= hppfs/
 obj-$(CONFIG_DEBUG_FS)		+= debugfs/
-obj-$(CONFIG_CONFIGFS_FS)	+= configfs/
 obj-$(CONFIG_OCFS2_FS)		+= ocfs2/
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index 57c4903614e58c29a2eae1462f1f46c1ca8083ec..d6603d02304ceed0d0a1c0e6c80e497bcaf58394 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -74,8 +74,8 @@ struct autofs_wait_queue {
 	struct autofs_wait_queue *next;
 	autofs_wqt_t wait_queue_token;
 	/* We use the following to see what we are waiting for */
-	int hash;
-	int len;
+	unsigned int hash;
+	unsigned int len;
 	char *name;
 	u32 dev;
 	u64 ino;
@@ -85,7 +85,6 @@ struct autofs_wait_queue {
 	pid_t tgid;
 	/* This is for status reporting upon return */
 	int status;
-	atomic_t notify;
 	atomic_t wait_ctr;
 };
 
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 84e030c8ddd0f99047473308afc4d26f555e2c14..5100f984783faa123caabf76ad97e1718bdea70e 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -327,6 +327,7 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags)
 static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
 	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+	struct autofs_info *ino = autofs4_dentry_ino(dentry);
 	int oz_mode = autofs4_oz_mode(sbi);
 	unsigned int lookup_type;
 	int status;
@@ -340,13 +341,8 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
 	if (oz_mode || !lookup_type)
 		goto done;
 
-	/*
-	 * If a request is pending wait for it.
-	 * If it's a mount then it won't be expired till at least
-	 * a liitle later and if it's an expire then we might need
-	 * to mount it again.
-	 */
-	if (autofs4_ispending(dentry)) {
+	/* If an expire request is pending wait for it. */
+	if (ino && (ino->flags & AUTOFS_INF_EXPIRING)) {
 		DPRINTK("waiting for active request %p name=%.*s",
 			dentry, dentry->d_name.len, dentry->d_name.name);
 
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 142ab6aa2aa1516e6480d24c0ce3830b19852107..ce103e7b0bc360f684a2556c55ea9ed8be0e38f2 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -189,14 +189,30 @@ static int autofs4_getpath(struct autofs_sb_info *sbi,
 	return len;
 }
 
+static struct autofs_wait_queue *
+autofs4_find_wait(struct autofs_sb_info *sbi,
+		  char *name, unsigned int hash, unsigned int len)
+{
+	struct autofs_wait_queue *wq;
+
+	for (wq = sbi->queues; wq; wq = wq->next) {
+		if (wq->hash == hash &&
+		    wq->len == len &&
+		    wq->name && !memcmp(wq->name, name, len))
+			break;
+	}
+	return wq;
+}
+
 int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
 		enum autofs_notify notify)
 {
+	struct autofs_info *ino;
 	struct autofs_wait_queue *wq;
 	char *name;
 	unsigned int len = 0;
 	unsigned int hash = 0;
-	int status;
+	int status, type;
 
 	/* In catatonic mode, we don't wait for nobody */
 	if (sbi->catatonic)
@@ -223,21 +239,41 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
 		return -EINTR;
 	}
 
-	for (wq = sbi->queues ; wq ; wq = wq->next) {
-		if (wq->hash == dentry->d_name.hash &&
-		    wq->len == len &&
-		    wq->name && !memcmp(wq->name, name, len))
-			break;
-	}
+	wq = autofs4_find_wait(sbi, name, hash, len);
+	ino = autofs4_dentry_ino(dentry);
+	if (!wq && ino && notify == NFY_NONE) {
+		/*
+		 * Either we've betean the pending expire to post it's
+		 * wait or it finished while we waited on the mutex.
+		 * So we need to wait till either, the wait appears
+		 * or the expire finishes.
+		 */
+
+		while (ino->flags & AUTOFS_INF_EXPIRING) {
+			mutex_unlock(&sbi->wq_mutex);
+			schedule_timeout_interruptible(HZ/10);
+			if (mutex_lock_interruptible(&sbi->wq_mutex)) {
+				kfree(name);
+				return -EINTR;
+			}
+			wq = autofs4_find_wait(sbi, name, hash, len);
+			if (wq)
+				break;
+		}
 
-	if (!wq) {
-		/* Can't wait for an expire if there's no mount */
-		if (notify == NFY_NONE && !d_mountpoint(dentry)) {
+		/*
+		 * Not ideal but the status has already gone. Of the two
+		 * cases where we wait on NFY_NONE neither depend on the
+		 * return status of the wait.
+		 */
+		if (!wq) {
 			kfree(name);
 			mutex_unlock(&sbi->wq_mutex);
-			return -ENOENT;
+			return 0;
 		}
+	}
 
+	if (!wq) {
 		/* Create a new wait queue */
 		wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL);
 		if (!wq) {
@@ -263,20 +299,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
 		wq->tgid = current->tgid;
 		wq->status = -EINTR; /* Status return if interrupted */
 		atomic_set(&wq->wait_ctr, 2);
-		atomic_set(&wq->notify, 1);
-		mutex_unlock(&sbi->wq_mutex);
-	} else {
-		atomic_inc(&wq->wait_ctr);
 		mutex_unlock(&sbi->wq_mutex);
-		kfree(name);
-		DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d",
-			(unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
-	}
-
-	if (notify != NFY_NONE && atomic_read(&wq->notify)) {
-		int type;
-
-		atomic_dec(&wq->notify);
 
 		if (sbi->version < 5) {
 			if (notify == NFY_MOUNT)
@@ -299,6 +322,12 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
 
 		/* autofs4_notify_daemon() may block */
 		autofs4_notify_daemon(sbi, wq, type);
+	} else {
+		atomic_inc(&wq->wait_ctr);
+		mutex_unlock(&sbi->wq_mutex);
+		kfree(name);
+		DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d",
+			(unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
 	}
 
 	/* wq->name is NULL if and only if the lock is already released */
diff --git a/fs/compat.c b/fs/compat.c
index 3f3e8f4d43d69230b7c4e36eb9a629e27221a22e..01f39f87f372ec08bfd932dd92a3dc5e646d20d6 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1323,7 +1323,7 @@ compat_sys_vmsplice(int fd, const struct compat_iovec __user *iov32,
 {
 	unsigned i;
 	struct iovec *iov;
-	if (nr_segs >= UIO_MAXIOV)
+	if (nr_segs > UIO_MAXIOV)
 		return -EINVAL;
 	iov = compat_alloc_user_space(nr_segs * sizeof(struct iovec));
 	for (i = 0; i < nr_segs; i++) {
@@ -1913,7 +1913,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
 	}
 
 	if (sigmask) {
-		if (sigsetsize |= sizeof(compat_sigset_t))
+		if (sigsetsize != sizeof(compat_sigset_t))
 			return -EINVAL;
 		if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
 			return -EFAULT;
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 5638c8f9362f9222419e1cff3f80e50dca646abc..5f952187fc53575795358785cdb586bd7093b8c9 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -505,13 +505,15 @@ static int populate_groups(struct config_group *group)
 	int i;
 
 	if (group->default_groups) {
-		/* FYI, we're faking mkdir here
+		/*
+		 * FYI, we're faking mkdir here
 		 * I'm not sure we need this semaphore, as we're called
 		 * from our parent's mkdir.  That holds our parent's
 		 * i_mutex, so afaik lookup cannot continue through our
 		 * parent to find us, let alone mess with our tree.
 		 * That said, taking our i_mutex is closer to mkdir
-		 * emulation, and shouldn't hurt. */
+		 * emulation, and shouldn't hurt.
+		 */
 		mutex_lock(&dentry->d_inode->i_mutex);
 
 		for (i = 0; group->default_groups[i]; i++) {
@@ -546,20 +548,34 @@ static void unlink_obj(struct config_item *item)
 
 		item->ci_group = NULL;
 		item->ci_parent = NULL;
+
+		/* Drop the reference for ci_entry */
 		config_item_put(item);
 
+		/* Drop the reference for ci_parent */
 		config_group_put(group);
 	}
 }
 
 static void link_obj(struct config_item *parent_item, struct config_item *item)
 {
-	/* Parent seems redundant with group, but it makes certain
-	 * traversals much nicer. */
+	/*
+	 * Parent seems redundant with group, but it makes certain
+	 * traversals much nicer.
+	 */
 	item->ci_parent = parent_item;
+
+	/*
+	 * We hold a reference on the parent for the child's ci_parent
+	 * link.
+	 */
 	item->ci_group = config_group_get(to_config_group(parent_item));
 	list_add_tail(&item->ci_entry, &item->ci_group->cg_children);
 
+	/*
+	 * We hold a reference on the child for ci_entry on the parent's
+	 * cg_children
+	 */
 	config_item_get(item);
 }
 
@@ -684,6 +700,10 @@ static void client_drop_item(struct config_item *parent_item,
 	type = parent_item->ci_type;
 	BUG_ON(!type);
 
+	/*
+	 * If ->drop_item() exists, it is responsible for the
+	 * config_item_put().
+	 */
 	if (type->ct_group_ops && type->ct_group_ops->drop_item)
 		type->ct_group_ops->drop_item(to_config_group(parent_item),
 						item);
@@ -694,23 +714,28 @@ static void client_drop_item(struct config_item *parent_item,
 
 static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
-	int ret;
+	int ret, module_got = 0;
 	struct config_group *group;
 	struct config_item *item;
 	struct config_item *parent_item;
 	struct configfs_subsystem *subsys;
 	struct configfs_dirent *sd;
 	struct config_item_type *type;
-	struct module *owner;
+	struct module *owner = NULL;
 	char *name;
 
-	if (dentry->d_parent == configfs_sb->s_root)
-		return -EPERM;
+	if (dentry->d_parent == configfs_sb->s_root) {
+		ret = -EPERM;
+		goto out;
+	}
 
 	sd = dentry->d_parent->d_fsdata;
-	if (!(sd->s_type & CONFIGFS_USET_DIR))
-		return -EPERM;
+	if (!(sd->s_type & CONFIGFS_USET_DIR)) {
+		ret = -EPERM;
+		goto out;
+	}
 
+	/* Get a working ref for the duration of this function */
 	parent_item = configfs_get_config_item(dentry->d_parent);
 	type = parent_item->ci_type;
 	subsys = to_config_group(parent_item)->cg_subsys;
@@ -719,15 +744,16 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 	if (!type || !type->ct_group_ops ||
 	    (!type->ct_group_ops->make_group &&
 	     !type->ct_group_ops->make_item)) {
-		config_item_put(parent_item);
-		return -EPERM;  /* What lack-of-mkdir returns */
+		ret = -EPERM;  /* Lack-of-mkdir returns -EPERM */
+		goto out_put;
 	}
 
 	name = kmalloc(dentry->d_name.len + 1, GFP_KERNEL);
 	if (!name) {
-		config_item_put(parent_item);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto out_put;
 	}
+
 	snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name);
 
 	down(&subsys->su_sem);
@@ -748,40 +774,67 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
 	kfree(name);
 	if (!item) {
-		config_item_put(parent_item);
-		return -ENOMEM;
+		/*
+		 * If item == NULL, then link_obj() was never called.
+		 * There are no extra references to clean up.
+		 */
+		ret = -ENOMEM;
+		goto out_put;
 	}
 
-	ret = -EINVAL;
+	/*
+	 * link_obj() has been called (via link_group() for groups).
+	 * From here on out, errors must clean that up.
+	 */
+
 	type = item->ci_type;
-	if (type) {
-		owner = type->ct_owner;
-		if (try_module_get(owner)) {
-			if (group) {
-				ret = configfs_attach_group(parent_item,
-							    item,
-							    dentry);
-			} else {
-				ret = configfs_attach_item(parent_item,
-							   item,
-							   dentry);
-			}
+	if (!type) {
+		ret = -EINVAL;
+		goto out_unlink;
+	}
 
-			if (ret) {
-				down(&subsys->su_sem);
-				if (group)
-					unlink_group(group);
-				else
-					unlink_obj(item);
-				client_drop_item(parent_item, item);
-				up(&subsys->su_sem);
+	owner = type->ct_owner;
+	if (!try_module_get(owner)) {
+		ret = -EINVAL;
+		goto out_unlink;
+	}
 
-				config_item_put(parent_item);
-				module_put(owner);
-			}
-		}
+	/*
+	 * I hate doing it this way, but if there is
+	 * an error,  module_put() probably should
+	 * happen after any cleanup.
+	 */
+	module_got = 1;
+
+	if (group)
+		ret = configfs_attach_group(parent_item, item, dentry);
+	else
+		ret = configfs_attach_item(parent_item, item, dentry);
+
+out_unlink:
+	if (ret) {
+		/* Tear down everything we built up */
+		down(&subsys->su_sem);
+		if (group)
+			unlink_group(group);
+		else
+			unlink_obj(item);
+		client_drop_item(parent_item, item);
+		up(&subsys->su_sem);
+
+		if (module_got)
+			module_put(owner);
 	}
 
+out_put:
+	/*
+	 * link_obj()/link_group() took a reference from child->parent,
+	 * so the parent is safely pinned.  We can drop our working
+	 * reference.
+	 */
+	config_item_put(parent_item);
+
+out:
 	return ret;
 }
 
@@ -801,6 +854,7 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
 	if (sd->s_type & CONFIGFS_USET_DEFAULT)
 		return -EPERM;
 
+	/* Get a working ref until we have the child */
 	parent_item = configfs_get_config_item(dentry->d_parent);
 	subsys = to_config_group(parent_item)->cg_subsys;
 	BUG_ON(!subsys);
@@ -817,6 +871,7 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
 		return ret;
 	}
 
+	/* Get a working ref for the duration of this function */
 	item = configfs_get_config_item(dentry);
 
 	/* Drop reference from above, item already holds one. */
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 48ae0339af175a1df095f6de4fa04f21a5af2c7f..2edd7eec88fd90295338042bd39dcc525ae78460 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -711,7 +711,7 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode,
 	 * direct blocks blocks
 	 */
 	if (num == 0 && blks > 1) {
-		current_block = le32_to_cpu(where->key + 1);
+		current_block = le32_to_cpu(where->key) + 1;
 		for (i = 1; i < blks; i++)
 			*(where->p + i ) = cpu_to_le32(current_block++);
 	}
@@ -724,7 +724,7 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode,
 	if (block_i) {
 		block_i->last_alloc_logical_block = block + blks - 1;
 		block_i->last_alloc_physical_block =
-				le32_to_cpu(where[num].key + blks - 1);
+				le32_to_cpu(where[num].key) + blks - 1;
 	}
 
 	/* We are done with atomic stuff, now do the rest of housekeeping */
@@ -814,11 +814,13 @@ int ext3_get_blocks_handle(handle_t *handle, struct inode *inode,
 
 	/* Simplest case - block found, no allocation needed */
 	if (!partial) {
-		first_block = chain[depth - 1].key;
+		first_block = le32_to_cpu(chain[depth - 1].key);
 		clear_buffer_new(bh_result);
 		count++;
 		/*map more blocks*/
 		while (count < maxblocks && count <= blocks_to_boundary) {
+			unsigned long blk;
+
 			if (!verify_chain(chain, partial)) {
 				/*
 				 * Indirect block might be removed by
@@ -831,8 +833,9 @@ int ext3_get_blocks_handle(handle_t *handle, struct inode *inode,
 				count = 0;
 				break;
 			}
-			if (le32_to_cpu(*(chain[depth-1].p+count) ==
-					(first_block + count)))
+			blk = le32_to_cpu(*(chain[depth-1].p + count));
+
+			if (blk == first_block + count)
 				count++;
 			else
 				break;
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index d4d0c41490cddad3a99c89727dd848a405693520..1d46677afd172b5742a4ccd2472b4d59f82a2800 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -438,7 +438,8 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info
 	if (c->mtd->point) {
 		err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer);
 		if (!err && retlen < tn->csize) {
-			JFFS2_WARNING("MTD point returned len too short: %u instead of %u.\n", retlen, tn->csize);
+			JFFS2_WARNING("MTD point returned len too short: %zu "
+					"instead of %u.\n", retlen, tn->csize);
 			c->mtd->unpoint(c->mtd, buffer, ofs, len);
 		} else if (err)
 			JFFS2_WARNING("MTD point failed: error code %d.\n", err);
@@ -461,7 +462,8 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info
 		}
 
 		if (retlen != len) {
-			JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", ofs, retlen, len);
+			JFFS2_ERROR("short read at %#08x: %zd instead of %d.\n",
+					ofs, retlen, len);
 			err = -EIO;
 			goto free_out;
 		}
diff --git a/fs/locks.c b/fs/locks.c
index efad798824dc19913b7aace09dbee47b8c6ca6a7..6f99c0a6f83629fbaa3eaaaf853fb6b7b9a9cfcc 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -446,15 +446,14 @@ static struct lock_manager_operations lease_manager_ops = {
  */
 static int lease_init(struct file *filp, int type, struct file_lock *fl)
  {
+	if (assign_type(fl, type) != 0)
+		return -EINVAL;
+
 	fl->fl_owner = current->files;
 	fl->fl_pid = current->tgid;
 
 	fl->fl_file = filp;
 	fl->fl_flags = FL_LEASE;
-	if (assign_type(fl, type) != 0) {
-		locks_free_lock(fl);
-		return -EINVAL;
-	}
 	fl->fl_start = 0;
 	fl->fl_end = OFFSET_MAX;
 	fl->fl_ops = NULL;
@@ -466,16 +465,19 @@ static int lease_init(struct file *filp, int type, struct file_lock *fl)
 static int lease_alloc(struct file *filp, int type, struct file_lock **flp)
 {
 	struct file_lock *fl = locks_alloc_lock();
-	int error;
+	int error = -ENOMEM;
 
 	if (fl == NULL)
-		return -ENOMEM;
+		goto out;
 
 	error = lease_init(filp, type, fl);
-	if (error)
-		return error;
+	if (error) {
+		locks_free_lock(fl);
+		fl = NULL;
+	}
+out:
 	*flp = fl;
-	return 0;
+	return error;
 }
 
 /* Check if two locks overlap each other.
@@ -1372,6 +1374,7 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp)
 		goto out;
 
 	if (my_before != NULL) {
+		*flp = *my_before;
 		error = lease->fl_lmops->fl_change(my_before, arg);
 		goto out;
 	}
diff --git a/fs/namespace.c b/fs/namespace.c
index 2c5f1f80bdc28b868cb81aabecdae71bc9c6b480..bf478addb852b70c1ec036e33100f93031c5dc6b 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -899,13 +899,11 @@ static int do_change_type(struct nameidata *nd, int flag)
 /*
  * do loopback mount.
  */
-static int do_loopback(struct nameidata *nd, char *old_name, unsigned long flags, int mnt_flags)
+static int do_loopback(struct nameidata *nd, char *old_name, int recurse)
 {
 	struct nameidata old_nd;
 	struct vfsmount *mnt = NULL;
-	int recurse = flags & MS_REC;
 	int err = mount_is_safe(nd);
-
 	if (err)
 		return err;
 	if (!old_name || !*old_name)
@@ -939,7 +937,6 @@ static int do_loopback(struct nameidata *nd, char *old_name, unsigned long flags
 		spin_unlock(&vfsmount_lock);
 		release_mounts(&umount_list);
 	}
-	mnt->mnt_flags = mnt_flags;
 
 out:
 	up_write(&namespace_sem);
@@ -1353,7 +1350,7 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
 		retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
 				    data_page);
 	else if (flags & MS_BIND)
-		retval = do_loopback(&nd, dev_name, flags, mnt_flags);
+		retval = do_loopback(&nd, dev_name, flags & MS_REC);
 	else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
 		retval = do_change_type(&nd, flags);
 	else if (flags & MS_MOVE)
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 0d858d0b25be70f496e1fb0ec863ec4778ae3c57..47152bf9a7f26cdfb82cd02240e5546ba3e47485 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -276,13 +276,29 @@ static int ocfs2_writepage(struct page *page, struct writeback_control *wbc)
 	return ret;
 }
 
+/* This can also be called from ocfs2_write_zero_page() which has done
+ * it's own cluster locking. */
+int ocfs2_prepare_write_nolock(struct inode *inode, struct page *page,
+			       unsigned from, unsigned to)
+{
+	int ret;
+
+	down_read(&OCFS2_I(inode)->ip_alloc_sem);
+
+	ret = block_prepare_write(page, from, to, ocfs2_get_block);
+
+	up_read(&OCFS2_I(inode)->ip_alloc_sem);
+
+	return ret;
+}
+
 /*
  * ocfs2_prepare_write() can be an outer-most ocfs2 call when it is called
  * from loopback.  It must be able to perform its own locking around
  * ocfs2_get_block().
  */
-int ocfs2_prepare_write(struct file *file, struct page *page,
-			unsigned from, unsigned to)
+static int ocfs2_prepare_write(struct file *file, struct page *page,
+			       unsigned from, unsigned to)
 {
 	struct inode *inode = page->mapping->host;
 	int ret;
@@ -295,11 +311,7 @@ int ocfs2_prepare_write(struct file *file, struct page *page,
 		goto out;
 	}
 
-	down_read(&OCFS2_I(inode)->ip_alloc_sem);
-
-	ret = block_prepare_write(page, from, to, ocfs2_get_block);
-
-	up_read(&OCFS2_I(inode)->ip_alloc_sem);
+	ret = ocfs2_prepare_write_nolock(inode, page, from, to);
 
 	ocfs2_meta_unlock(inode, 0);
 out:
@@ -625,11 +637,31 @@ static ssize_t ocfs2_direct_IO(int rw,
 	int ret;
 
 	mlog_entry_void();
+
+	/*
+	 * We get PR data locks even for O_DIRECT.  This allows
+	 * concurrent O_DIRECT I/O but doesn't let O_DIRECT with
+	 * extending and buffered zeroing writes race.  If they did
+	 * race then the buffered zeroing could be written back after
+	 * the O_DIRECT I/O.  It's one thing to tell people not to mix
+	 * buffered and O_DIRECT writes, but expecting them to
+	 * understand that file extension is also an implicit buffered
+	 * write is too much.  By getting the PR we force writeback of
+	 * the buffered zeroing before proceeding.
+	 */
+	ret = ocfs2_data_lock(inode, 0);
+	if (ret < 0) {
+		mlog_errno(ret);
+		goto out;
+	}
+	ocfs2_data_unlock(inode, 0);
+
 	ret = blockdev_direct_IO_no_locking(rw, iocb, inode,
 					    inode->i_sb->s_bdev, iov, offset,
 					    nr_segs, 
 					    ocfs2_direct_IO_get_blocks,
 					    ocfs2_dio_end_io);
+out:
 	mlog_exit(ret);
 	return ret;
 }
diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h
index d40456d509a00e8ddecac4e28a26d1482140f23f..e88c3f0b8fa9f3bfc5078f992360cd3cbea8f69c 100644
--- a/fs/ocfs2/aops.h
+++ b/fs/ocfs2/aops.h
@@ -22,8 +22,8 @@
 #ifndef OCFS2_AOPS_H
 #define OCFS2_AOPS_H
 
-int ocfs2_prepare_write(struct file *file, struct page *page,
-			unsigned from, unsigned to);
+int ocfs2_prepare_write_nolock(struct inode *inode, struct page *page,
+			       unsigned from, unsigned to);
 
 struct ocfs2_journal_handle *ocfs2_start_walk_page_trans(struct inode *inode,
 							 struct page *page,
diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c
index 4601fc256f111254e41d124d08e95f216357b11e..1a5c69071df642afbe99a04ed348b33c955c9861 100644
--- a/fs/ocfs2/extent_map.c
+++ b/fs/ocfs2/extent_map.c
@@ -569,7 +569,7 @@ static int ocfs2_extent_map_insert(struct inode *inode,
 
 	ret = -ENOMEM;
 	ctxt.new_ent = kmem_cache_alloc(ocfs2_em_ent_cachep,
-					GFP_KERNEL);
+					GFP_NOFS);
 	if (!ctxt.new_ent) {
 		mlog_errno(ret);
 		return ret;
@@ -583,14 +583,14 @@ static int ocfs2_extent_map_insert(struct inode *inode,
 		if (ctxt.need_left && !ctxt.left_ent) {
 			ctxt.left_ent =
 				kmem_cache_alloc(ocfs2_em_ent_cachep,
-						 GFP_KERNEL);
+						 GFP_NOFS);
 			if (!ctxt.left_ent)
 				break;
 		}
 		if (ctxt.need_right && !ctxt.right_ent) {
 			ctxt.right_ent =
 				kmem_cache_alloc(ocfs2_em_ent_cachep,
-						 GFP_KERNEL);
+						 GFP_NOFS);
 			if (!ctxt.right_ent)
 				break;
 		}
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 581eb451a41a36796a2a2d55b7463028d4dae10e..a9559c874530ebee3e5ccacefbccc03058af3ca7 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -613,7 +613,8 @@ leave:
 
 /* Some parts of this taken from generic_cont_expand, which turned out
  * to be too fragile to do exactly what we need without us having to
- * worry about recursive locking in ->commit_write(). */
+ * worry about recursive locking in ->prepare_write() and
+ * ->commit_write(). */
 static int ocfs2_write_zero_page(struct inode *inode,
 				 u64 size)
 {
@@ -641,7 +642,7 @@ static int ocfs2_write_zero_page(struct inode *inode,
 		goto out;
 	}
 
-	ret = ocfs2_prepare_write(NULL, page, offset, offset);
+	ret = ocfs2_prepare_write_nolock(inode, page, offset, offset);
 	if (ret < 0) {
 		mlog_errno(ret);
 		goto out_unlock;
@@ -695,13 +696,26 @@ out:
 	return ret;
 }
 
+/* 
+ * A tail_to_skip value > 0 indicates that we're being called from
+ * ocfs2_file_aio_write(). This has the following implications:
+ *
+ * - we don't want to update i_size
+ * - di_bh will be NULL, which is fine because it's only used in the
+ *   case where we want to update i_size.
+ * - ocfs2_zero_extend() will then only be filling the hole created
+ *   between i_size and the start of the write.
+ */
 static int ocfs2_extend_file(struct inode *inode,
 			     struct buffer_head *di_bh,
-			     u64 new_i_size)
+			     u64 new_i_size,
+			     size_t tail_to_skip)
 {
 	int ret = 0;
 	u32 clusters_to_add;
 
+	BUG_ON(!tail_to_skip && !di_bh);
+
 	/* setattr sometimes calls us like this. */
 	if (new_i_size == 0)
 		goto out;
@@ -714,27 +728,44 @@ static int ocfs2_extend_file(struct inode *inode,
 		OCFS2_I(inode)->ip_clusters;
 
 	if (clusters_to_add) {
-		ret = ocfs2_extend_allocation(inode, clusters_to_add);
+		/* 
+		 * protect the pages that ocfs2_zero_extend is going to
+		 * be pulling into the page cache.. we do this before the
+		 * metadata extend so that we don't get into the situation
+		 * where we've extended the metadata but can't get the data
+		 * lock to zero.
+		 */
+		ret = ocfs2_data_lock(inode, 1);
 		if (ret < 0) {
 			mlog_errno(ret);
 			goto out;
 		}
 
-		ret = ocfs2_zero_extend(inode, new_i_size);
+		ret = ocfs2_extend_allocation(inode, clusters_to_add);
 		if (ret < 0) {
 			mlog_errno(ret);
-			goto out;
+			goto out_unlock;
 		}
-	} 
 
-	/* No allocation required, we just use this helper to
-	 * do a trivial update of i_size. */
-	ret = ocfs2_simple_size_update(inode, di_bh, new_i_size);
-	if (ret < 0) {
-		mlog_errno(ret);
-		goto out;
+		ret = ocfs2_zero_extend(inode, (u64)new_i_size - tail_to_skip);
+		if (ret < 0) {
+			mlog_errno(ret);
+			goto out_unlock;
+		}
+	}
+
+	if (!tail_to_skip) {
+		/* We're being called from ocfs2_setattr() which wants
+		 * us to update i_size */
+		ret = ocfs2_simple_size_update(inode, di_bh, new_i_size);
+		if (ret < 0)
+			mlog_errno(ret);
 	}
 
+out_unlock:
+	if (clusters_to_add) /* this is the only case in which we lock */
+		ocfs2_data_unlock(inode, 1);
+
 out:
 	return ret;
 }
@@ -793,7 +824,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
 		if (i_size_read(inode) > attr->ia_size)
 			status = ocfs2_truncate_file(inode, bh, attr->ia_size);
 		else
-			status = ocfs2_extend_file(inode, bh, attr->ia_size);
+			status = ocfs2_extend_file(inode, bh, attr->ia_size, 0);
 		if (status < 0) {
 			if (status != -ENOSPC)
 				mlog_errno(status);
@@ -1049,21 +1080,12 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
 		if (!clusters)
 			break;
 
-		ret = ocfs2_extend_allocation(inode, clusters);
+		ret = ocfs2_extend_file(inode, NULL, newsize, count);
 		if (ret < 0) {
 			if (ret != -ENOSPC)
 				mlog_errno(ret);
 			goto out;
 		}
-
-		/* Fill any holes which would've been created by this
-		 * write. If we're O_APPEND, this will wind up
-		 * (correctly) being a noop. */
-		ret = ocfs2_zero_extend(inode, (u64) newsize - count);
-		if (ret < 0) {
-			mlog_errno(ret);
-			goto out;
-		}
 		break;
 	}
 
@@ -1146,6 +1168,22 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
 		ocfs2_iocb_set_rw_locked(iocb);
 	}
 
+	/*
+	 * We're fine letting folks race truncates and extending
+	 * writes with read across the cluster, just like they can
+	 * locally. Hence no rw_lock during read.
+	 * 
+	 * Take and drop the meta data lock to update inode fields
+	 * like i_size. This allows the checks down below
+	 * generic_file_aio_read() a chance of actually working. 
+	 */
+	ret = ocfs2_meta_lock(inode, NULL, NULL, 0);
+	if (ret < 0) {
+		mlog_errno(ret);
+		goto bail;
+	}
+	ocfs2_meta_unlock(inode, 0);
+
 	ret = generic_file_aio_read(iocb, buf, count, iocb->ki_pos);
 	if (ret == -EINVAL)
 		mlog(ML_ERROR, "generic_file_aio_read returned -EINVAL\n");
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index 6a610ae5358394710688e518d022f25e85a51b41..eebc3cfa6be8c89dd5a55a8910ad4b1f3c9d2827 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -117,7 +117,7 @@ struct ocfs2_journal_handle *ocfs2_alloc_handle(struct ocfs2_super *osb)
 {
 	struct ocfs2_journal_handle *retval = NULL;
 
-	retval = kcalloc(1, sizeof(*retval), GFP_KERNEL);
+	retval = kcalloc(1, sizeof(*retval), GFP_NOFS);
 	if (!retval) {
 		mlog(ML_ERROR, "Failed to allocate memory for journal "
 		     "handle!\n");
@@ -870,9 +870,11 @@ static int ocfs2_force_read_journal(struct inode *inode)
 		if (p_blocks > CONCURRENT_JOURNAL_FILL)
 			p_blocks = CONCURRENT_JOURNAL_FILL;
 
+		/* We are reading journal data which should not
+		 * be put in the uptodate cache */
 		status = ocfs2_read_blocks(OCFS2_SB(inode->i_sb),
 					   p_blkno, p_blocks, bhs, 0,
-					   inode);
+					   NULL);
 		if (status < 0) {
 			mlog_errno(status);
 			goto bail;
@@ -982,7 +984,7 @@ static void ocfs2_queue_recovery_completion(struct ocfs2_journal *journal,
 {
 	struct ocfs2_la_recovery_item *item;
 
-	item = kmalloc(sizeof(struct ocfs2_la_recovery_item), GFP_KERNEL);
+	item = kmalloc(sizeof(struct ocfs2_la_recovery_item), GFP_NOFS);
 	if (!item) {
 		/* Though we wish to avoid it, we are in fact safe in
 		 * skipping local alloc cleanup as fsck.ocfs2 is more
diff --git a/fs/ocfs2/uptodate.c b/fs/ocfs2/uptodate.c
index 04a684dfdd96be735036db62b4c67a1a7cb65197..b8a00a79332676dd8956a10180926a2b580a7213 100644
--- a/fs/ocfs2/uptodate.c
+++ b/fs/ocfs2/uptodate.c
@@ -337,7 +337,7 @@ static void __ocfs2_set_buffer_uptodate(struct ocfs2_inode_info *oi,
 	     (unsigned long long)oi->ip_blkno,
 	     (unsigned long long)block, expand_tree);
 
-	new = kmem_cache_alloc(ocfs2_uptodate_cachep, GFP_KERNEL);
+	new = kmem_cache_alloc(ocfs2_uptodate_cachep, GFP_NOFS);
 	if (!new) {
 		mlog_errno(-ENOMEM);
 		return;
@@ -349,7 +349,7 @@ static void __ocfs2_set_buffer_uptodate(struct ocfs2_inode_info *oi,
 		 * has no way of tracking that. */
 		for(i = 0; i < OCFS2_INODE_MAX_CACHE_ARRAY; i++) {
 			tree[i] = kmem_cache_alloc(ocfs2_uptodate_cachep,
-						   GFP_KERNEL);
+						   GFP_NOFS);
 			if (!tree[i]) {
 				mlog_errno(-ENOMEM);
 				goto out_free;
diff --git a/fs/ocfs2/vote.c b/fs/ocfs2/vote.c
index 53049a20419768b3c00eea23fb6acf4ff4c71c0a..ee42765a8553e9c5ed51e47805f9bd1440679399 100644
--- a/fs/ocfs2/vote.c
+++ b/fs/ocfs2/vote.c
@@ -586,7 +586,7 @@ static struct ocfs2_net_wait_ctxt *ocfs2_new_net_wait_ctxt(unsigned int response
 {
 	struct ocfs2_net_wait_ctxt *w;
 
-	w = kcalloc(1, sizeof(*w), GFP_KERNEL);
+	w = kcalloc(1, sizeof(*w), GFP_NOFS);
 	if (!w) {
 		mlog_errno(-ENOMEM);
 		goto bail;
@@ -749,7 +749,7 @@ static struct ocfs2_vote_msg * ocfs2_new_vote_request(struct ocfs2_super *osb,
 
 	BUG_ON(!ocfs2_is_valid_vote_request(type));
 
-	request = kcalloc(1, sizeof(*request), GFP_KERNEL);
+	request = kcalloc(1, sizeof(*request), GFP_NOFS);
 	if (!request) {
 		mlog_errno(-ENOMEM);
 	} else {
@@ -1129,7 +1129,7 @@ static int ocfs2_handle_vote_message(struct o2net_msg *msg,
 	struct ocfs2_super *osb = data;
 	struct ocfs2_vote_work *work;
 
-	work = kmalloc(sizeof(struct ocfs2_vote_work), GFP_KERNEL);
+	work = kmalloc(sizeof(struct ocfs2_vote_work), GFP_NOFS);
 	if (!work) {
 		status = -ENOMEM;
 		mlog_errno(status);
diff --git a/fs/open.c b/fs/open.c
index 53ec28c367770d5704ecdb24f7549470cb0ccf6a..317b7c7f38a73aac8cc8f3edc463919dabb2f947 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -1124,7 +1124,6 @@ asmlinkage long sys_openat(int dfd, const char __user *filename, int flags,
 	prevent_tail_call(ret);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(sys_openat);
 
 #ifndef __alpha__
 
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 45ae7dd3c650399baafe5c8d20cc3b6734181d7a..7ef1f094de911998a88fe76bda393f136d60ec3c 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -533,6 +533,7 @@ void del_gendisk(struct gendisk *disk)
 
 	devfs_remove_disk(disk);
 
+	kobject_uevent(&disk->kobj, KOBJ_REMOVE);
 	if (disk->holder_dir)
 		kobject_unregister(disk->holder_dir);
 	if (disk->slave_dir)
@@ -545,7 +546,7 @@ void del_gendisk(struct gendisk *disk)
 			kfree(disk_name);
 		}
 		put_device(disk->driverfs_dev);
+		disk->driverfs_dev = NULL;
 	}
-	kobject_uevent(&disk->kobj, KOBJ_REMOVE);
 	kobject_del(&disk->kobj);
 }
diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c
index 34c7a11d91f0ebbb29854a0116d8c558825fbbbc..70d9c5a37f5a3c6f7d5cad12e7bad8e1d2e21136 100644
--- a/fs/smbfs/dir.c
+++ b/fs/smbfs/dir.c
@@ -434,6 +434,11 @@ smb_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 	if (dentry->d_name.len > SMB_MAXNAMELEN)
 		goto out;
 
+	/* Do not allow lookup of names with backslashes in */
+	error = -EINVAL;
+	if (memchr(dentry->d_name.name, '\\', dentry->d_name.len))
+		goto out;
+
 	lock_kernel();
 	error = smb_proc_getattr(dentry, &finfo);
 #ifdef SMBFS_PARANOIA
diff --git a/fs/smbfs/request.c b/fs/smbfs/request.c
index c71c375863cc473a254462d8187365cecb302367..c71dd2760d3254da61b60a06ea2a9732837ea072 100644
--- a/fs/smbfs/request.c
+++ b/fs/smbfs/request.c
@@ -339,9 +339,11 @@ int smb_add_request(struct smb_request *req)
 		/*
 		 * On timeout or on interrupt we want to try and remove the
 		 * request from the recvq/xmitq.
+		 * First check if the request is still part of a queue. (May
+		 * have been removed by some error condition)
 		 */
 		smb_lock_server(server);
-		if (!(req->rq_flags & SMB_REQ_RECEIVED)) {
+		if (!list_empty(&req->rq_queue)) {
 			list_del_init(&req->rq_queue);
 			smb_rput(req);
 		}
diff --git a/fs/splice.c b/fs/splice.c
index 7fb04970c72d853e53874e4ec03d9df48911dcb3..a285fd746dc0d34aa97762a6e138416acae292e7 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -51,7 +51,7 @@ struct splice_pipe_desc {
  * addition of remove_mapping(). If success is returned, the caller may
  * attempt to reuse this page for another destination.
  */
-static int page_cache_pipe_buf_steal(struct pipe_inode_info *info,
+static int page_cache_pipe_buf_steal(struct pipe_inode_info *pipe,
 				     struct pipe_buffer *buf)
 {
 	struct page *page = buf->page;
@@ -78,16 +78,18 @@ static int page_cache_pipe_buf_steal(struct pipe_inode_info *info,
 		return 1;
 	}
 
+	buf->flags |= PIPE_BUF_FLAG_LRU;
 	return 0;
 }
 
-static void page_cache_pipe_buf_release(struct pipe_inode_info *info,
+static void page_cache_pipe_buf_release(struct pipe_inode_info *pipe,
 					struct pipe_buffer *buf)
 {
 	page_cache_release(buf->page);
+	buf->flags &= ~PIPE_BUF_FLAG_LRU;
 }
 
-static int page_cache_pipe_buf_pin(struct pipe_inode_info *info,
+static int page_cache_pipe_buf_pin(struct pipe_inode_info *pipe,
 				   struct pipe_buffer *buf)
 {
 	struct page *page = buf->page;
@@ -141,6 +143,7 @@ static int user_page_pipe_buf_steal(struct pipe_inode_info *pipe,
 	if (!(buf->flags & PIPE_BUF_FLAG_GIFT))
 		return 1;
 
+	buf->flags |= PIPE_BUF_FLAG_LRU;
 	return generic_pipe_buf_steal(pipe, buf);
 }
 
@@ -321,6 +324,8 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
 					      mapping_gfp_mask(mapping));
 			if (unlikely(error)) {
 				page_cache_release(page);
+				if (error == -EEXIST)
+					continue;
 				break;
 			}
 			/*
@@ -497,14 +502,14 @@ EXPORT_SYMBOL(generic_file_splice_read);
  * Send 'sd->len' bytes to socket from 'sd->file' at position 'sd->pos'
  * using sendpage(). Return the number of bytes sent.
  */
-static int pipe_to_sendpage(struct pipe_inode_info *info,
+static int pipe_to_sendpage(struct pipe_inode_info *pipe,
 			    struct pipe_buffer *buf, struct splice_desc *sd)
 {
 	struct file *file = sd->file;
 	loff_t pos = sd->pos;
 	int ret, more;
 
-	ret = buf->ops->pin(info, buf);
+	ret = buf->ops->pin(pipe, buf);
 	if (!ret) {
 		more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len;
 
@@ -535,7 +540,7 @@ static int pipe_to_sendpage(struct pipe_inode_info *info,
  * SPLICE_F_MOVE isn't set, or we cannot move the page, we simply create
  * a new page in the output file page cache and fill/dirty that.
  */
-static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf,
+static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
 			struct splice_desc *sd)
 {
 	struct file *file = sd->file;
@@ -549,7 +554,7 @@ static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf,
 	/*
 	 * make sure the data in this buffer is uptodate
 	 */
-	ret = buf->ops->pin(info, buf);
+	ret = buf->ops->pin(pipe, buf);
 	if (unlikely(ret))
 		return ret;
 
@@ -566,37 +571,23 @@ static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf,
 	 */
 	if ((sd->flags & SPLICE_F_MOVE) && this_len == PAGE_CACHE_SIZE) {
 		/*
-		 * If steal succeeds, buf->page is now pruned from the vm
-		 * side (page cache) and we can reuse it. The page will also
-		 * be locked on successful return.
+		 * If steal succeeds, buf->page is now pruned from the
+		 * pagecache and we can reuse it. The page will also be
+		 * locked on successful return.
 		 */
-		if (buf->ops->steal(info, buf))
+		if (buf->ops->steal(pipe, buf))
 			goto find_page;
 
 		page = buf->page;
-		page_cache_get(page);
-
-		/*
-		 * page must be on the LRU for adding to the pagecache.
-		 * Check this without grabbing the zone lock, if it isn't
-		 * the do grab the zone lock, recheck, and add if necessary.
-		 */
-		if (!PageLRU(page)) {
-			struct zone *zone = page_zone(page);
-
-			spin_lock_irq(&zone->lru_lock);
-			if (!PageLRU(page)) {
-				SetPageLRU(page);
-				add_page_to_inactive_list(zone, page);
-			}
-			spin_unlock_irq(&zone->lru_lock);
-		}
-
 		if (add_to_page_cache(page, mapping, index, gfp_mask)) {
-			page_cache_release(page);
 			unlock_page(page);
 			goto find_page;
 		}
+
+		page_cache_get(page);
+
+		if (!(buf->flags & PIPE_BUF_FLAG_LRU))
+			lru_cache_add(page);
 	} else {
 find_page:
 		page = find_lock_page(mapping, index);
@@ -647,23 +638,36 @@ find_page:
 	}
 
 	ret = mapping->a_ops->prepare_write(file, page, offset, offset+this_len);
-	if (ret == AOP_TRUNCATED_PAGE) {
+	if (unlikely(ret)) {
+		loff_t isize = i_size_read(mapping->host);
+
+		if (ret != AOP_TRUNCATED_PAGE)
+			unlock_page(page);
 		page_cache_release(page);
-		goto find_page;
-	} else if (ret)
+		if (ret == AOP_TRUNCATED_PAGE)
+			goto find_page;
+
+		/*
+		 * prepare_write() may have instantiated a few blocks
+		 * outside i_size.  Trim these off again.
+		 */
+		if (sd->pos + this_len > isize)
+			vmtruncate(mapping->host, isize);
+
 		goto out;
+	}
 
 	if (buf->page != page) {
 		/*
 		 * Careful, ->map() uses KM_USER0!
 		 */
-		char *src = buf->ops->map(info, buf, 1);
+		char *src = buf->ops->map(pipe, buf, 1);
 		char *dst = kmap_atomic(page, KM_USER1);
 
 		memcpy(dst + offset, src + buf->offset, this_len);
 		flush_dcache_page(page);
 		kunmap_atomic(dst, KM_USER1);
-		buf->ops->unmap(info, buf, src);
+		buf->ops->unmap(pipe, buf, src);
 	}
 
 	ret = mapping->a_ops->commit_write(file, page, offset, offset+this_len);
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 64ee07db0d5e15d19f7429ce2673d70ee1ff3afb..8558226281c45a61d7a0bc056505246e705a372b 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -1942,8 +1942,10 @@ xfs_alloc_fix_freelist(
 		/*
 		 * Allocate as many blocks as possible at once.
 		 */
-		if ((error = xfs_alloc_ag_vextent(&targs)))
+		if ((error = xfs_alloc_ag_vextent(&targs))) {
+			xfs_trans_brelse(tp, agflbp);
 			return error;
+		}
 		/*
 		 * Stop if we run out.  Won't happen if callers are obeying
 		 * the restrictions correctly.  Can happen for free calls
@@ -1960,6 +1962,7 @@ xfs_alloc_fix_freelist(
 				return error;
 		}
 	}
+	xfs_trans_brelse(tp, agflbp);
 	args->agbp = agbp;
 	return 0;
 }
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c
index 81a05cfd77d2b5f60fa2429366ae07af19ca4843..1f148762eb28e01b7854e4e7d412242a0e8c6cec 100644
--- a/fs/xfs/xfs_rename.c
+++ b/fs/xfs/xfs_rename.c
@@ -316,6 +316,18 @@ xfs_rename(
 		}
 	}
 
+	/*
+	 * If we are using project inheritance, we only allow renames
+	 * into our tree when the project IDs are the same; else the
+	 * tree quota mechanism would be circumvented.
+	 */
+	if (unlikely((target_dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
+		     (target_dp->i_d.di_projid != src_ip->i_d.di_projid))) {
+		error = XFS_ERROR(EXDEV);
+		xfs_rename_unlock4(inodes, XFS_ILOCK_SHARED);
+		goto rele_return;
+	}
+
 	new_parent = (src_dp != target_dp);
 	src_is_directory = ((src_ip->i_d.di_mode & S_IFMT) == S_IFDIR);
 
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index f0e09ca1413933fa01993a0555beb80e38bbe14b..36ea1b2094f29cf6c2a475fce994e8e15a4e0008 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -669,31 +669,22 @@ xfs_mntupdate(
 	xfs_mount_t	*mp = XFS_BHVTOM(bdp);
 	int		error;
 
-	if (args->flags & XFSMNT_BARRIER)
-		mp->m_flags |= XFS_MOUNT_BARRIER;
-	else
-		mp->m_flags &= ~XFS_MOUNT_BARRIER;
-
-	if ((vfsp->vfs_flag & VFS_RDONLY) &&
-	    !(*flags & MS_RDONLY)) {
-		vfsp->vfs_flag &= ~VFS_RDONLY;
-
-		if (args->flags & XFSMNT_BARRIER)
+	if (!(*flags & MS_RDONLY)) {			/* rw/ro -> rw */
+		if (vfsp->vfs_flag & VFS_RDONLY)
+			vfsp->vfs_flag &= ~VFS_RDONLY;
+		if (args->flags & XFSMNT_BARRIER) {
+			mp->m_flags |= XFS_MOUNT_BARRIER;
 			xfs_mountfs_check_barriers(mp);
-	}
-
-	if (!(vfsp->vfs_flag & VFS_RDONLY) &&
-	    (*flags & MS_RDONLY)) {
+		} else {
+			mp->m_flags &= ~XFS_MOUNT_BARRIER;
+		}
+	} else if (!(vfsp->vfs_flag & VFS_RDONLY)) {	/* rw -> ro */
 		VFS_SYNC(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL, error);
-
 		xfs_quiesce_fs(mp);
-
-		/* Ok now write out an unmount record */
 		xfs_log_unmount_write(mp);
 		xfs_unmountfs_writesb(mp);
 		vfsp->vfs_flag |= VFS_RDONLY;
 	}
-
 	return 0;
 }
 
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index fa71b305ba5c0e56231fb48ec57eed1f16f4b0e6..7027ae68ee38e6491897eb88033886b7c6fb0ea5 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -2663,7 +2663,7 @@ xfs_link(
 	 */
 	if (unlikely((tdp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
 		     (tdp->i_d.di_projid != sip->i_d.di_projid))) {
-		error = XFS_ERROR(EPERM);
+		error = XFS_ERROR(EXDEV);
 		goto error_return;
 	}
 
diff --git a/include/asm-arm/arch-aaec2000/debug-macro.S b/include/asm-arm/arch-aaec2000/debug-macro.S
index e4f1fa539a7434ccb8bf4e3339130fe16d9cb30e..7b1fce021d8a6c497c1817cb21750cf563c8d6f7 100644
--- a/include/asm-arm/arch-aaec2000/debug-macro.S
+++ b/include/asm-arm/arch-aaec2000/debug-macro.S
@@ -9,6 +9,7 @@
  *  published by the Free Software Foundation.
  */
 
+#include "hardware.h"
 		.macro	addruart,rx
 		mrc	p15, 0, \rx, c1, c0
 		tst	\rx, #1			@ MMU enabled?
diff --git a/include/asm-arm/arch-aaec2000/entry-macro.S b/include/asm-arm/arch-aaec2000/entry-macro.S
index df31313ab07eee1a0ab1435570db35f02b0d6009..1eb3503bd16e1a78303a610eb4723422cde8988a 100644
--- a/include/asm-arm/arch-aaec2000/entry-macro.S
+++ b/include/asm-arm/arch-aaec2000/entry-macro.S
@@ -10,6 +10,7 @@
  *  published by the Free Software Foundation.
  *
  */
+#include <asm/arch/irqs.h>
 
 		.macro	disable_fiq
 		.endm
diff --git a/include/asm-arm/arch-imx/debug-macro.S b/include/asm-arm/arch-imx/debug-macro.S
index 83f552f7bcc142eddd9b850575a38d1ac5c3690b..c611871643a287ea08f1a37a151f765329d35b6b 100644
--- a/include/asm-arm/arch-imx/debug-macro.S
+++ b/include/asm-arm/arch-imx/debug-macro.S
@@ -16,7 +16,7 @@
 		tst	\rx, #1			@ MMU enabled?
 		moveq	\rx, #0x00000000	@ physical
 		movne	\rx, #0xe0000000	@ virtual
-		orr	\rx, \rx, #0x00200000
+		orreq	\rx, \rx, #0x00200000	@ physical
 		orr	\rx, \rx, #0x00006000	@ UART1 offset
 		.endm
 
diff --git a/include/asm-arm/arch-imx/imx-uart.h b/include/asm-arm/arch-imx/imx-uart.h
new file mode 100644
index 0000000000000000000000000000000000000000..3a685e1780ea3ab138e9a5a0c6af6dfd6224215e
--- /dev/null
+++ b/include/asm-arm/arch-imx/imx-uart.h
@@ -0,0 +1,10 @@
+#ifndef ASMARM_ARCH_UART_H
+#define ASMARM_ARCH_UART_H
+
+#define IMXUART_HAVE_RTSCTS (1<<0)
+
+struct imxuart_platform_data {
+	unsigned int flags;
+};
+
+#endif
diff --git a/include/asm-arm/arch-ixp4xx/io.h b/include/asm-arm/arch-ixp4xx/io.h
index 942b622455bc438ad2a164580ce190c03bcdeea4..b59520e56fc7fee72bc8262a08c9af2d8d690985 100644
--- a/include/asm-arm/arch-ixp4xx/io.h
+++ b/include/asm-arm/arch-ixp4xx/io.h
@@ -260,6 +260,12 @@ out:
 
 #endif
 
+#ifndef CONFIG_PCI
+
+#define	__io(v)		v
+
+#else
+
 /*
  * IXP4xx does not have a transparent cpu -> PCI I/O translation
  * window.  Instead, it has a set of registers that must be tweaked
@@ -578,6 +584,7 @@ __ixp4xx_iowrite32_rep(void __iomem *addr, const void *vaddr, u32 count)
 
 #define	ioport_map(port, nr)		((void __iomem*)(port + PIO_OFFSET))
 #define	ioport_unmap(addr)
+#endif	// !CONFIG_PCI
 
 #endif	//  __ASM_ARM_ARCH_IO_H
 
diff --git a/include/asm-arm/arch-ixp4xx/memory.h b/include/asm-arm/arch-ixp4xx/memory.h
index ee211d28a3ef3260ae315a0ca0e4bd161e5f4c5b..af9667b57ab379be02824371929a47b19653ccc9 100644
--- a/include/asm-arm/arch-ixp4xx/memory.h
+++ b/include/asm-arm/arch-ixp4xx/memory.h
@@ -14,7 +14,7 @@
  */
 #define PHYS_OFFSET	UL(0x00000000)
 
-#ifndef __ASSEMBLY__
+#if !defined(__ASSEMBLY__) && defined(CONFIG_PCI)
 
 void ixp4xx_adjust_zones(int node, unsigned long *size, unsigned long *holes);
 
diff --git a/include/asm-arm/arch-pxa/dma.h b/include/asm-arm/arch-pxa/dma.h
index 3e88a2a02a0fdd01186107439eed4711d38b9a7f..a008150abc59f2775e8ce25e03b3bb0f2b1476ec 100644
--- a/include/asm-arm/arch-pxa/dma.h
+++ b/include/asm-arm/arch-pxa/dma.h
@@ -24,27 +24,29 @@ typedef struct pxa_dma_desc {
 	volatile u32 dcmd;	/* DCMD value for the current transfer */
 } pxa_dma_desc;
 
+typedef enum {
+	DMA_PRIO_HIGH = 0,
+	DMA_PRIO_MEDIUM = 1,
+	DMA_PRIO_LOW = 2
+} pxa_dma_prio;
+
 #if defined(CONFIG_PXA27x)
 
 #define PXA_DMA_CHANNELS	32
-#define PXA_DMA_NBCH(prio)	((prio == DMA_PRIO_LOW) ? 16 : 8)
 
-typedef enum {
-	DMA_PRIO_HIGH = 0,
-	DMA_PRIO_MEDIUM = 8,
-	DMA_PRIO_LOW = 16
-} pxa_dma_prio;
+#define pxa_for_each_dma_prio(ch, prio)					\
+for (									\
+	ch = prio * 4;							\
+	ch != (4 << prio) + 16;						\
+	ch = (ch + 1 == (4 << prio)) ? (prio * 4 + 16) : (ch + 1)	\
+)
 
 #elif defined(CONFIG_PXA25x)
 
 #define PXA_DMA_CHANNELS	16
-#define PXA_DMA_NBCH(prio)	((prio == DMA_PRIO_LOW) ? 8 : 4)
 
-typedef enum {
-	DMA_PRIO_HIGH = 0,
-	DMA_PRIO_MEDIUM = 4,
-	DMA_PRIO_LOW = 8
-} pxa_dma_prio;
+#define pxa_for_each_dma_prio(ch, prio)					\
+	for (ch = prio * 4; ch != (4 << prio); ch++)
 
 #endif
 
diff --git a/include/asm-arm/arch-pxa/pxa2xx_spi.h b/include/asm-arm/arch-pxa/pxa2xx_spi.h
new file mode 100644
index 0000000000000000000000000000000000000000..1e70908b816f59b1bf172c9445d294c6aab3bb81
--- /dev/null
+++ b/include/asm-arm/arch-pxa/pxa2xx_spi.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PXA2XX_SPI_H_
+#define PXA2XX_SPI_H_
+
+#define PXA2XX_CS_ASSERT (0x01)
+#define PXA2XX_CS_DEASSERT (0x02)
+
+#if defined(CONFIG_PXA25x)
+#define CLOCK_SPEED_HZ 3686400
+#define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/2/(x+1))<<8)&0x0000ff00)
+#define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
+#define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
+#elif defined(CONFIG_PXA27x)
+#define CLOCK_SPEED_HZ 13000000
+#define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
+#define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
+#define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
+#endif
+
+#define SSP1_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(1)))))
+#define SSP2_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(2)))))
+#define SSP3_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(3)))))
+
+enum pxa_ssp_type {
+	SSP_UNDEFINED = 0,
+	PXA25x_SSP,  /* pxa 210, 250, 255, 26x */
+	PXA25x_NSSP, /* pxa 255, 26x (including ASSP) */
+	PXA27x_SSP,
+};
+
+/* device.platform_data for SSP controller devices */
+struct pxa2xx_spi_master {
+	enum pxa_ssp_type ssp_type;
+	u32 clock_enable;
+	u16 num_chipselect;
+	u8 enable_dma;
+};
+
+/* spi_board_info.controller_data for SPI slave devices,
+ * copied to spi_device.platform_data ... mostly for dma tuning
+ */
+struct pxa2xx_spi_chip {
+	u8 tx_threshold;
+	u8 rx_threshold;
+	u8 dma_burst_size;
+	u32 timeout_microsecs;
+	u8 enable_loopback;
+	void (*cs_control)(u32 command);
+};
+
+#endif /*PXA2XX_SPI_H_*/
diff --git a/include/asm-arm/bug.h b/include/asm-arm/bug.h
index 7fb02138f585985dd810407a82a8643bb3874d9f..5ab8216f5204aa7f204cd5b34fffb228428ff618 100644
--- a/include/asm-arm/bug.h
+++ b/include/asm-arm/bug.h
@@ -2,6 +2,7 @@
 #define _ASMARM_BUG_H
 
 #include <linux/config.h>
+#include <linux/stddef.h>
 
 #ifdef CONFIG_BUG
 #ifdef CONFIG_DEBUG_BUGVERBOSE
diff --git a/include/asm-arm/procinfo.h b/include/asm-arm/procinfo.h
index a9c75b2c314f588bc279e9b59f8de3e72408cad8..842526055225a02e88a7cc9d8ed34a8c49ef8c21 100644
--- a/include/asm-arm/procinfo.h
+++ b/include/asm-arm/procinfo.h
@@ -45,8 +45,6 @@ extern unsigned int elf_hwcap;
 
 #endif	/* __ASSEMBLY__ */
 
-#define PROC_INFO_SZ	48
-
 #define HWCAP_SWP	1
 #define HWCAP_HALF	2
 #define HWCAP_THUMB	4
diff --git a/include/asm-arm/spinlock.h b/include/asm-arm/spinlock.h
index 43ad4e55878c7961a535e6ce427b842adecb2372..406ca97a8ab29f99d381565ab3c9b745c1f147a3 100644
--- a/include/asm-arm/spinlock.h
+++ b/include/asm-arm/spinlock.h
@@ -142,6 +142,9 @@ static inline void __raw_write_unlock(raw_rwlock_t *rw)
 	: "cc");
 }
 
+/* write_can_lock - would write_trylock() succeed? */
+#define __raw_write_can_lock(x)		((x)->lock == 0x80000000)
+
 /*
  * Read locks are a bit more hairy:
  *  - Exclusively load the lock value.
@@ -198,4 +201,7 @@ static inline void __raw_read_unlock(raw_rwlock_t *rw)
 
 #define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
 
+/* read_can_lock - would read_trylock() succeed? */
+#define __raw_read_can_lock(x)		((x)->lock < 0x80000000)
+
 #endif /* __ASM_SPINLOCK_H */
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
index ee8dfea549bc324239b1e60f0cdd9ef984e75dfb..cbf39a56dbe768db84f96396ebf77823cc525c3d 100644
--- a/include/asm-arm/unistd.h
+++ b/include/asm-arm/unistd.h
@@ -363,7 +363,7 @@
 /*
  * The following syscalls are obsolete and no longer available for EABI.
  */
-#if defined(__ARM_EABI__)
+#if defined(__ARM_EABI__) && !defined(__KERNEL__)
 #undef __NR_time
 #undef __NR_umount
 #undef __NR_stime
@@ -410,7 +410,8 @@ type name(void) {							\
   __asm__ __volatile__ (						\
   __syscall(name)							\
 	: "=r" (__res_r0)						\
-	: __SYS_REG_LIST() );						\
+	: __SYS_REG_LIST()						\
+	: "memory" );							\
   __res = __res_r0;							\
   __syscall_return(type,__res);						\
 }
@@ -424,7 +425,8 @@ type name(type1 arg1) { 						\
   __asm__ __volatile__ (						\
   __syscall(name)							\
 	: "=r" (__res_r0)						\
-	: __SYS_REG_LIST( "0" (__r0) ) );				\
+	: __SYS_REG_LIST( "0" (__r0) )					\
+	: "memory" );							\
   __res = __res_r0;							\
   __syscall_return(type,__res);						\
 }
@@ -439,7 +441,8 @@ type name(type1 arg1,type2 arg2) {					\
   __asm__ __volatile__ (						\
   __syscall(name)							\
 	: "=r" (__res_r0)						\
-	: __SYS_REG_LIST( "0" (__r0), "r" (__r1) ) );			\
+	: __SYS_REG_LIST( "0" (__r0), "r" (__r1) )			\
+	: "memory" );							\
   __res = __res_r0;							\
   __syscall_return(type,__res);						\
 }
@@ -456,7 +459,8 @@ type name(type1 arg1,type2 arg2,type3 arg3) {				\
   __asm__ __volatile__ (						\
   __syscall(name)							\
 	: "=r" (__res_r0)						\
-	: __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2) ) );	\
+	: __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2) )		\
+	: "memory" );							\
   __res = __res_r0;							\
   __syscall_return(type,__res);						\
 }
@@ -474,7 +478,8 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) {		\
   __asm__ __volatile__ (						\
   __syscall(name)							\
 	: "=r" (__res_r0)						\
-	: __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) ) ); \
+	: __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) ) \
+	: "memory" );							\
   __res = __res_r0;							\
   __syscall_return(type,__res);						\
 }
@@ -494,7 +499,8 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) {	\
   __syscall(name)							\
 	: "=r" (__res_r0)						\
 	: __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2),		\
-			  "r" (__r3), "r" (__r4) ) );			\
+			  "r" (__r3), "r" (__r4) )			\
+	: "memory" );							\
   __res = __res_r0;							\
   __syscall_return(type,__res);						\
 }
@@ -514,7 +520,8 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6
   __syscall(name)							\
 	: "=r" (__res_r0)						\
 	: __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2),		\
-			  "r" (__r3), "r" (__r4), "r" (__r5) ) );	\
+			  "r" (__r3), "r" (__r4), "r" (__r5) )		\
+	: "memory" );							\
   __res = __res_r0;							\
   __syscall_return(type,__res);						\
 }
diff --git a/include/asm-i386/io_apic.h b/include/asm-i386/io_apic.h
index 51c4e5fe6062d0e239f257521804d342f008b33e..d92e253f7f6f2963076ff7b7280396603a814685 100644
--- a/include/asm-i386/io_apic.h
+++ b/include/asm-i386/io_apic.h
@@ -200,6 +200,7 @@ extern int io_apic_get_unique_id (int ioapic, int apic_id);
 extern int io_apic_get_version (int ioapic);
 extern int io_apic_get_redir_entries (int ioapic);
 extern int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low);
+extern int timer_uses_ioapic_pin_0;
 #endif /* CONFIG_ACPI */
 
 extern int (*ioapic_renumber_irq)(int ioapic, int irq);
diff --git a/include/asm-ia64/bitops.h b/include/asm-ia64/bitops.h
index 90921e162793e22f4861e78ebda066d971c4fbc0..6cc517e212a92ee94e461c2e1944f3fe9af0c627 100644
--- a/include/asm-ia64/bitops.h
+++ b/include/asm-ia64/bitops.h
@@ -11,7 +11,6 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
-#include <asm/bitops.h>
 #include <asm/intrinsics.h>
 
 /**
diff --git a/include/asm-powerpc/uaccess.h b/include/asm-powerpc/uaccess.h
index 3872e924cdd6f7c6fca25a8983467d80e47dc79c..d83fc29c2bbf13ed8deed9244e7f71c78dd4c78c 100644
--- a/include/asm-powerpc/uaccess.h
+++ b/include/asm-powerpc/uaccess.h
@@ -7,6 +7,7 @@
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <asm/processor.h>
+#include <asm/page.h>
 
 #define VERIFY_READ	0
 #define VERIFY_WRITE	1
@@ -179,9 +180,11 @@ do {								\
 #define __put_user_nocheck(x, ptr, size)			\
 ({								\
 	long __pu_err;						\
-	might_sleep();						\
+	__typeof__(*(ptr)) __user *__pu_addr = (ptr);		\
+	if (!is_kernel_addr((unsigned long)__pu_addr))		\
+		might_sleep();					\
 	__chk_user_ptr(ptr);					\
-	__put_user_size((x), (ptr), (size), __pu_err);		\
+	__put_user_size((x), __pu_addr, (size), __pu_err);	\
 	__pu_err;						\
 })
 
@@ -258,9 +261,11 @@ do {								\
 ({								\
 	long __gu_err;						\
 	unsigned long __gu_val;					\
+	const __typeof__(*(ptr)) __user *__gu_addr = (ptr);	\
 	__chk_user_ptr(ptr);					\
-	might_sleep();						\
-	__get_user_size(__gu_val, (ptr), (size), __gu_err);	\
+	if (!is_kernel_addr((unsigned long)__gu_addr))		\
+		might_sleep();					\
+	__get_user_size(__gu_val, __gu_addr, (size), __gu_err);	\
 	(x) = (__typeof__(*(ptr)))__gu_val;			\
 	__gu_err;						\
 })
@@ -270,9 +275,11 @@ do {								\
 ({								\
 	long __gu_err;						\
 	long long __gu_val;					\
+	const __typeof__(*(ptr)) __user *__gu_addr = (ptr);	\
 	__chk_user_ptr(ptr);					\
-	might_sleep();						\
-	__get_user_size(__gu_val, (ptr), (size), __gu_err);	\
+	if (!is_kernel_addr((unsigned long)__gu_addr))		\
+		might_sleep();					\
+	__get_user_size(__gu_val, __gu_addr, (size), __gu_err);	\
 	(x) = (__typeof__(*(ptr)))__gu_val;			\
 	__gu_err;						\
 })
diff --git a/include/asm-ppc/commproc.h b/include/asm-ppc/commproc.h
index 973e6090823482052c343a568c253882c2defc85..31f362966a58856295b44838b91ed7633cdc2133 100644
--- a/include/asm-ppc/commproc.h
+++ b/include/asm-ppc/commproc.h
@@ -35,6 +35,7 @@
 #define CPM_CR_INIT_TX		((ushort)0x0002)
 #define CPM_CR_HUNT_MODE	((ushort)0x0003)
 #define CPM_CR_STOP_TX		((ushort)0x0004)
+#define CPM_CR_GRA_STOP_TX	((ushort)0x0005)
 #define CPM_CR_RESTART_TX	((ushort)0x0006)
 #define CPM_CR_CLOSE_RX_BD	((ushort)0x0007)
 #define CPM_CR_SET_GADDR	((ushort)0x0008)
diff --git a/include/asm-ppc/cpm2.h b/include/asm-ppc/cpm2.h
index b638b87cebe3381a0312e34bd7618810463e0df0..c70344b910492d8633b98eb3d5f7b212264f80ae 100644
--- a/include/asm-ppc/cpm2.h
+++ b/include/asm-ppc/cpm2.h
@@ -69,7 +69,7 @@
 #define CPM_CR_INIT_TX		((ushort)0x0002)
 #define CPM_CR_HUNT_MODE	((ushort)0x0003)
 #define CPM_CR_STOP_TX		((ushort)0x0004)
-#define CPM_CR_GRA_STOP_TX      ((ushort)0x0005)
+#define CPM_CR_GRA_STOP_TX	((ushort)0x0005)
 #define CPM_CR_RESTART_TX	((ushort)0x0006)
 #define CPM_CR_SET_GADDR	((ushort)0x0008)
 #define CPM_CR_START_IDMA	((ushort)0x0009)
diff --git a/include/asm-ppc/page.h b/include/asm-ppc/page.h
index a70ba2ee552d8f4f722aa87d19597155fb9ff4f9..0fb68a0b0181c311eae08877d29809980639a76e 100644
--- a/include/asm-ppc/page.h
+++ b/include/asm-ppc/page.h
@@ -20,6 +20,7 @@
 /* This must match what is in arch/ppc/Makefile */
 #define PAGE_OFFSET	CONFIG_KERNEL_START
 #define KERNELBASE	PAGE_OFFSET
+#define is_kernel_addr(x)	((x) >= PAGE_OFFSET)
 
 #ifndef __ASSEMBLY__
 
diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h
index 657d582e8149504e331e65dc7e30cf85aceb7117..41c2792ff6b04cd9d0be3d98c774549113ba2552 100644
--- a/include/asm-s390/unistd.h
+++ b/include/asm-s390/unistd.h
@@ -296,8 +296,14 @@
 #define __NR_pselect6		301
 #define __NR_ppoll		302
 #define __NR_unshare		303
+#define __NR_set_robust_list	304
+#define __NR_get_robust_list	305
+#define __NR_splice		306
+#define __NR_sync_file_range	307
+#define __NR_tee		308
+#define __NR_vmsplice		309
 
-#define NR_syscalls 304
+#define NR_syscalls 310
 
 /* 
  * There are some system calls that are not present on 64 bit, some
diff --git a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h
index 32a48f623e2bcb326e026cef7cb201f92baab378..f5611a721fbd6e5024d172faaffd4e0ee3a5fc28 100644
--- a/include/asm-sparc/unistd.h
+++ b/include/asm-sparc/unistd.h
@@ -41,7 +41,7 @@
 #define __NR_capset		 22 /* Linux Specific				   */
 #define __NR_setuid              23 /* Implemented via setreuid in SunOS           */
 #define __NR_getuid              24 /* Common                                      */
-/* #define __NR_time alias	 25    ENOSYS under SunOS			   */
+#define __NR_vmsplice	         25 /* ENOSYS under SunOS			   */
 #define __NR_ptrace              26 /* Common                                      */
 #define __NR_alarm               27 /* Implemented via setitimer in SunOS          */
 #define __NR_sigaltstack	 28 /* Common					   */
diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
index ca80e8aca128bf94cc0b33b0b3afc5043a5a4c58..68705748bec0f164b52a2bebc83b8c265fbe1d73 100644
--- a/include/asm-sparc64/unistd.h
+++ b/include/asm-sparc64/unistd.h
@@ -41,7 +41,7 @@
 #define __NR_capset		 22 /* Linux Specific				   */
 #define __NR_setuid              23 /* Implemented via setreuid in SunOS           */
 #define __NR_getuid              24 /* Common                                      */
-/* #define __NR_time alias	 25    ENOSYS under SunOS			   */
+#define __NR_vmsplice	         25 /* ENOSYS under SunOS			   */
 #define __NR_ptrace              26 /* Common                                      */
 #define __NR_alarm               27 /* Implemented via setitimer in SunOS          */
 #define __NR_sigaltstack	 28 /* Common					   */
diff --git a/include/asm-x86_64/e820.h b/include/asm-x86_64/e820.h
index 93b51df5168770547bb0fa8393348af343a7e2a8..670a3388e70a20cc2591e637b698d0649de211f9 100644
--- a/include/asm-x86_64/e820.h
+++ b/include/asm-x86_64/e820.h
@@ -59,6 +59,8 @@ extern void __init parse_memopt(char *p, char **end);
 extern void __init parse_memmapopt(char *p, char **end);
 
 extern struct e820map e820;
+
+extern unsigned ebda_addr, ebda_size;
 #endif/*!__ASSEMBLY__*/
 
 #endif/*__E820_HEADER*/
diff --git a/include/asm-x86_64/io_apic.h b/include/asm-x86_64/io_apic.h
index ee1bc69aec9ce56386f3acddc7de60a80e9c968f..52484e82c641d884dd7da4f8b63b743073402a80 100644
--- a/include/asm-x86_64/io_apic.h
+++ b/include/asm-x86_64/io_apic.h
@@ -205,6 +205,7 @@ extern int skip_ioapic_setup;
 extern int io_apic_get_version (int ioapic);
 extern int io_apic_get_redir_entries (int ioapic);
 extern int io_apic_set_pci_routing (int ioapic, int pin, int irq, int, int);
+extern int timer_uses_ioapic_pin_0;
 #endif
 
 extern int sis_apic_bug; /* dummy */ 
diff --git a/include/linux/device.h b/include/linux/device.h
index f6e72a65a3f21c1f6b8cb92b32c6542ab4537753..e8e53b9accc67345908ecbb27c947b6035438e4f 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -200,6 +200,7 @@ extern int class_device_create_file(struct class_device *,
  * @node: for internal use by the driver core only.
  * @kobj: for internal use by the driver core only.
  * @devt_attr: for internal use by the driver core only.
+ * @groups: optional additional groups to be created
  * @dev: if set, a symlink to the struct device is created in the sysfs
  * directory for this struct class device.
  * @class_data: pointer to whatever you want to store here for this struct
@@ -228,6 +229,7 @@ struct class_device {
 	struct device		* dev;		/* not necessary, but nice to have */
 	void			* class_data;	/* class-specific data */
 	struct class_device	*parent;	/* parent of this child device, if there is one */
+	struct attribute_group  ** groups;	/* optional groups */
 
 	void	(*release)(struct class_device *dev);
 	int	(*uevent)(struct class_device *dev, char **envp,
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index ff61817082fa80271a24f4b2ad70623c013dfc26..635690cf3e3dc77ff54f8d07555da2ffc4dff165 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -14,6 +14,7 @@ enum dma_data_direction {
 };
 
 #define DMA_64BIT_MASK	0xffffffffffffffffULL
+#define DMA_48BIT_MASK	0x0000ffffffffffffULL
 #define DMA_40BIT_MASK	0x000000ffffffffffULL
 #define DMA_39BIT_MASK	0x0000007fffffffffULL
 #define DMA_32BIT_MASK	0x00000000ffffffffULL
diff --git a/include/linux/fs_uart_pd.h b/include/linux/fs_uart_pd.h
new file mode 100644
index 0000000000000000000000000000000000000000..f5975126b712261fc12e62c101630fe4856d1dde
--- /dev/null
+++ b/include/linux/fs_uart_pd.h
@@ -0,0 +1,60 @@
+/*
+ * Platform information definitions for the CPM Uart driver.
+ *
+ * 2006 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef FS_UART_PD_H
+#define FS_UART_PD_H
+
+#include <linux/version.h>
+#include <asm/types.h>
+
+enum fs_uart_id {
+	fsid_smc1_uart,
+	fsid_smc2_uart,
+	fsid_scc1_uart,
+	fsid_scc2_uart,
+	fsid_scc3_uart,
+	fsid_scc4_uart,
+	fs_uart_nr,
+};
+
+static inline int fs_uart_id_scc2fsid(int id)
+{
+    return fsid_scc1_uart + id - 1;
+}
+
+static inline int fs_uart_id_fsid2scc(int id)
+{
+    return id - fsid_scc1_uart + 1;
+}
+
+static inline int fs_uart_id_smc2fsid(int id)
+{
+    return fsid_smc1_uart + id - 1;
+}
+
+static inline int fs_uart_id_fsid2smc(int id)
+{
+    return id - fsid_smc1_uart + 1;
+}
+
+struct fs_uart_platform_info {
+        void(*init_ioports)(void);
+	/* device specific information */
+	int fs_no;		/* controller index */
+	u32 uart_clk;
+	u8 tx_num_fifo;
+	u8 tx_buf_size;
+	u8 rx_num_fifo;
+	u8 rx_buf_size;
+	u8 brg;
+};
+
+#endif
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index e1bd0842f6a13e71ad0b781d4a5bdf6605986fbe..f4fc576ed4c40c6d28dd940a869801a138a0a5e6 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -124,6 +124,7 @@ extern int get_option(char **str, int *pint);
 extern char *get_options(const char *str, int nints, int *ints);
 extern unsigned long long memparse(char *ptr, char **retptr);
 
+extern int core_kernel_text(unsigned long addr);
 extern int __kernel_text_address(unsigned long addr);
 extern int kernel_text_address(unsigned long addr);
 extern int session_of_pgrp(int pgrp);
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 30dd978c1ec88e43f66a7e2e08c61a064a6a963e..991a37382a22e84ec1e15894688046a9e77a077e 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -28,6 +28,7 @@ struct mmc_csd {
 	unsigned short		cmdclass;
 	unsigned short		tacc_clks;
 	unsigned int		tacc_ns;
+	unsigned int		r2w_factor;
 	unsigned int		max_dtr;
 	unsigned int		read_blkbits;
 	unsigned int		write_blkbits;
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index bdc556d884989c9e51f6c46b915f4efb146e162b..03a14a30c46a1230d57443007783e466b519450b 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -69,6 +69,7 @@ struct mmc_data {
 	unsigned int		timeout_ns;	/* data timeout (in ns, max 80ms) */
 	unsigned int		timeout_clks;	/* data timeout (in clocks) */
 	unsigned int		blksz_bits;	/* data block size */
+	unsigned int		blksz;		/* data block size */
 	unsigned int		blocks;		/* number of blocks */
 	unsigned int		error;		/* data error */
 	unsigned int		flags;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 01db7b88a2b1c626f668085364ca6181ba9ca641..f4169bbb60eb8036d021ba64e9270f6b5ffcaabb 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -433,8 +433,7 @@ struct net_device
 
 	/* register/unregister state machine */
 	enum { NETREG_UNINITIALIZED=0,
-	       NETREG_REGISTERING,	/* called register_netdevice */
-	       NETREG_REGISTERED,	/* completed register todo */
+	       NETREG_REGISTERED,	/* completed register_netdevice */
 	       NETREG_UNREGISTERING,	/* called unregister_netdevice */
 	       NETREG_UNREGISTERED,	/* completed unregister todo */
 	       NETREG_RELEASED,		/* called free_netdev */
@@ -506,6 +505,8 @@ struct net_device
 
 	/* class/net/name entry */
 	struct class_device	class_dev;
+	/* space for optional statistics and wireless sysfs groups */
+	struct attribute_group  *sysfs_groups[3];
 };
 
 #define	NETDEV_ALIGN		32
@@ -829,21 +830,19 @@ static inline void netif_rx_schedule(struct net_device *dev)
 		__netif_rx_schedule(dev);
 }
 
-
-static inline void  __netif_rx_reschedule(struct net_device *dev, int undo)
-{
-	dev->quota += undo;
-	list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list);
-	__raise_softirq_irqoff(NET_RX_SOFTIRQ);
-}
-
-/* Try to reschedule poll. Called by dev->poll() after netif_rx_complete(). */
+/* Try to reschedule poll. Called by dev->poll() after netif_rx_complete().
+ * Do not inline this?
+ */
 static inline int netif_rx_reschedule(struct net_device *dev, int undo)
 {
 	if (netif_rx_schedule_prep(dev)) {
 		unsigned long flags;
+
+		dev->quota += undo;
+
 		local_irq_save(flags);
-		__netif_rx_reschedule(dev, undo);
+		list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list);
+		__raise_softirq_irqoff(NET_RX_SOFTIRQ);
 		local_irq_restore(flags);
 		return 1;
 	}
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h
index 0bd828081c0c428690305d8a63188d52207d2acc..c6e9a0b6d30ba0e5f8e64171cf15977705bf816f 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h
@@ -2,7 +2,7 @@
  * ip_conntrack_helper_h323_asn1.h - BER and PER decoding library for H.323
  * 			      	     conntrack/NAT module.
  *
- * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@hotmail.com>
+ * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@users.sourceforge.net>
  *
  * This source code is licensed under General Public License version 2.
  *
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index ba73108cbf8b038e11ed5e45e8ff54874cb2a1b7..ea4f7cd7bfd85425c96a1d17faa358a2d7cb509f 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -5,8 +5,9 @@
 
 #define PIPE_BUFFERS (16)
 
-#define PIPE_BUF_FLAG_ATOMIC	0x01	/* was atomically mapped */
-#define PIPE_BUF_FLAG_GIFT	0x02	/* page is a gift */
+#define PIPE_BUF_FLAG_LRU	0x01	/* page is on the LRU */
+#define PIPE_BUF_FLAG_ATOMIC	0x02	/* was atomically mapped */
+#define PIPE_BUF_FLAG_GIFT	0x04	/* page is a gift */
 
 struct pipe_buffer {
 	struct page *page;
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 5673008b61e11ae127608228fdbe6eacd9cec27d..970284f571a6d522f60362c0f585ba7d837b1cb2 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -132,6 +132,7 @@ static inline void rcu_bh_qsctr_inc(int cpu)
 }
 
 extern int rcu_pending(int cpu);
+extern int rcu_needs_cpu(int cpu);
 
 /**
  * rcu_read_lock - mark the beginning of an RCU read-side critical section.
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index c32e60e79dea43b51b317b6d34e1d027165e6f93..bd14858121ea2065fdd399c58c48dd6e1f513812 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -254,6 +254,7 @@ struct uart_port {
 #define UPF_CONS_FLOW		((__force upf_t) (1 << 23))
 #define UPF_SHARE_IRQ		((__force upf_t) (1 << 24))
 #define UPF_BOOT_AUTOCONF	((__force upf_t) (1 << 28))
+#define UPF_DEAD		((__force upf_t) (1 << 30))
 #define UPF_IOREMAP		((__force upf_t) (1 << 31))
 
 #define UPF_CHANGE_MASK		((__force upf_t) (0x17fff))
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 3af03b19c9830275c77ef99f98c6a22e76a79a7f..2d985d59c7b86759663761c3ec333ec196730026 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -150,6 +150,7 @@ static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
 
 extern void kfree(const void *);
 extern unsigned int ksize(const void *);
+extern int slab_is_available(void);
 
 #ifdef CONFIG_NUMA
 extern void *kmem_cache_alloc_node(kmem_cache_t *, gfp_t flags, int node);
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index b05f1463a2676de35237dda137772ad70dc1c93d..e928c0dcc29755d31c2ba5b7f1d96b1f3ac50b1e 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -31,18 +31,23 @@ extern struct bus_type spi_bus_type;
  * @master: SPI controller used with the device.
  * @max_speed_hz: Maximum clock rate to be used with this chip
  *	(on this board); may be changed by the device's driver.
+ *	The spi_transfer.speed_hz can override this for each transfer.
  * @chip-select: Chipselect, distinguishing chips handled by "master".
  * @mode: The spi mode defines how data is clocked out and in.
  *	This may be changed by the device's driver.
+ *	The "active low" default for chipselect mode can be overridden,
+ *	as can the "MSB first" default for each word in a transfer.
  * @bits_per_word: Data transfers involve one or more words; word sizes
- * 	like eight or 12 bits are common.  In-memory wordsizes are
+ *	like eight or 12 bits are common.  In-memory wordsizes are
  *	powers of two bytes (e.g. 20 bit samples use 32 bits).
- *	This may be changed by the device's driver.
+ *	This may be changed by the device's driver, or left at the
+ *	default (0) indicating protocol words are eight bit bytes.
+ *	The spi_transfer.bits_per_word can override this for each transfer.
  * @irq: Negative, or the number passed to request_irq() to receive
- * 	interrupts from this device.
+ *	interrupts from this device.
  * @controller_state: Controller's runtime state
  * @controller_data: Board-specific definitions for controller, such as
- * 	FIFO initialization parameters; from board_info.controller_data
+ *	FIFO initialization parameters; from board_info.controller_data
  *
  * An spi_device is used to interchange data between an SPI slave
  * (usually a discrete chip) and CPU memory.
@@ -65,6 +70,7 @@ struct spi_device {
 #define	SPI_MODE_2	(SPI_CPOL|0)
 #define	SPI_MODE_3	(SPI_CPOL|SPI_CPHA)
 #define	SPI_CS_HIGH	0x04			/* chipselect active high? */
+#define	SPI_LSB_FIRST	0x08			/* per-word bits-on-wire */
 	u8			bits_per_word;
 	int			irq;
 	void			*controller_state;
@@ -73,7 +79,6 @@ struct spi_device {
 
 	// likely need more hooks for more protocol options affecting how
 	// the controller talks to each chip, like:
-	//  - bit order (default is wordwise msb-first)
 	//  - memory packing (12 bit samples into low bits, others zeroed)
 	//  - priority
 	//  - drop chipselect after each word
@@ -143,13 +148,13 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  * struct spi_master - interface to SPI master controller
  * @cdev: class interface to this driver
  * @bus_num: board-specific (and often SOC-specific) identifier for a
- * 	given SPI controller.
+ *	given SPI controller.
  * @num_chipselect: chipselects are used to distinguish individual
- * 	SPI slaves, and are numbered from zero to num_chipselects.
- * 	each slave has a chipselect signal, but it's common that not
- * 	every chipselect is connected to a slave.
+ *	SPI slaves, and are numbered from zero to num_chipselects.
+ *	each slave has a chipselect signal, but it's common that not
+ *	every chipselect is connected to a slave.
  * @setup: updates the device mode and clocking records used by a
- * 	device's SPI controller; protocol code may call this.
+ *	device's SPI controller; protocol code may call this.
  * @transfer: adds a message to the controller's transfer queue.
  * @cleanup: frees controller-specific state
  *
@@ -167,13 +172,13 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
 struct spi_master {
 	struct class_device	cdev;
 
-	/* other than zero (== assign one dynamically), bus_num is fully
+	/* other than negative (== assign one dynamically), bus_num is fully
 	 * board-specific.  usually that simplifies to being SOC-specific.
-	 * example:  one SOC has three SPI controllers, numbered 1..3,
+	 * example:  one SOC has three SPI controllers, numbered 0..2,
 	 * and one board's schematics might show it using SPI-2.  software
 	 * would normally use bus_num=2 for that controller.
 	 */
-	u16			bus_num;
+	s16			bus_num;
 
 	/* chipselects will be integral to many controllers; some others
 	 * might use board-specific GPIOs.
@@ -268,10 +273,14 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum);
  * @tx_dma: DMA address of tx_buf, if spi_message.is_dma_mapped
  * @rx_dma: DMA address of rx_buf, if spi_message.is_dma_mapped
  * @len: size of rx and tx buffers (in bytes)
+ * @speed_hz: Select a speed other then the device default for this
+ *      transfer. If 0 the default (from spi_device) is used.
+ * @bits_per_word: select a bits_per_word other then the device default
+ *      for this transfer. If 0 the default (from spi_device) is used.
  * @cs_change: affects chipselect after this transfer completes
  * @delay_usecs: microseconds to delay after this transfer before
- * 	(optionally) changing the chipselect status, then starting
- * 	the next transfer or completing this spi_message.
+ *	(optionally) changing the chipselect status, then starting
+ *	the next transfer or completing this spi_message.
  * @transfer_list: transfers are sequenced through spi_message.transfers
  *
  * SPI transfers always write the same number of bytes as they read.
@@ -322,7 +331,9 @@ struct spi_transfer {
 	dma_addr_t	rx_dma;
 
 	unsigned	cs_change:1;
+	u8		bits_per_word;
 	u16		delay_usecs;
+	u32		speed_hz;
 
 	struct list_head transfer_list;
 };
@@ -356,7 +367,7 @@ struct spi_transfer {
  * and its transfers, ignore them until its completion callback.
  */
 struct spi_message {
-	struct list_head 	transfers;
+	struct list_head	transfers;
 
 	struct spi_device	*spi;
 
@@ -374,7 +385,7 @@ struct spi_message {
 	 */
 
 	/* completion is reported through a callback */
-	void 			(*complete)(void *context);
+	void			(*complete)(void *context);
 	void			*context;
 	unsigned		actual_length;
 	int			status;
diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h
index c961fe9bf3eb48f3576035a7ec62bc5c743bc008..16ce178f54d7a0de40a69ebabfdddc488f4039fa 100644
--- a/include/linux/spi/spi_bitbang.h
+++ b/include/linux/spi/spi_bitbang.h
@@ -30,6 +30,12 @@ struct spi_bitbang {
 
 	struct spi_master	*master;
 
+	/* setup_transfer() changes clock and/or wordsize to match settings
+	 * for this transfer; zeroes restore defaults from spi_device.
+	 */
+	int	(*setup_transfer)(struct spi_device *spi,
+			struct spi_transfer *t);
+
 	void	(*chipselect)(struct spi_device *spi, int is_on);
 #define	BITBANG_CS_ACTIVE	1	/* normally nCS, active low */
 #define	BITBANG_CS_INACTIVE	0
@@ -51,6 +57,8 @@ struct spi_bitbang {
 extern int spi_bitbang_setup(struct spi_device *spi);
 extern void spi_bitbang_cleanup(const struct spi_device *spi);
 extern int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m);
+extern int spi_bitbang_setup_transfer(struct spi_device *spi,
+				      struct spi_transfer *t);
 
 /* start or stop queue processing */
 extern int spi_bitbang_start(struct spi_bitbang *spi);
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 5b1fdf1cff4f057a67eb1c81e487acad031a89b2..f03c247193022ae3ec7ee7457db7ce3f44cbce80 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -296,7 +296,7 @@ static inline void disable_swap_token(void)
 #define read_swap_cache_async(swp,vma,addr)	NULL
 #define lookup_swap_cache(swp)			NULL
 #define valid_swaphandles(swp, off)		0
-#define can_share_swap_page(p)			0
+#define can_share_swap_page(p)			(page_mapcount(p) == 1)
 #define move_to_swap_cache(p, swp)		1
 #define move_from_swap_cache(p, i, m)		1
 #define __delete_from_swap_cache(p)		/*NOTHING*/
diff --git a/include/net/ax25.h b/include/net/ax25.h
index d052b221dbcd4b5ce124e9ee3a0c64358a2dbf1d..5bd997487054c3d9125d38ca0f89f5372387164d 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -145,14 +145,14 @@ enum {
 #define	AX25_DEF_CONMODE	2			/* Connected mode allowed */
 #define	AX25_DEF_WINDOW		2			/* Window=2 */
 #define	AX25_DEF_EWINDOW	32			/* Module-128 Window=32 */
-#define	AX25_DEF_T1		(10 * HZ)		/* T1=10s */
-#define	AX25_DEF_T2		(3 * HZ)		/* T2=3s  */
-#define	AX25_DEF_T3		(300 * HZ)		/* T3=300s */
+#define	AX25_DEF_T1		10000			/* T1=10s */
+#define	AX25_DEF_T2		3000			/* T2=3s  */
+#define	AX25_DEF_T3		300000			/* T3=300s */
 #define	AX25_DEF_N2		10			/* N2=10 */
-#define AX25_DEF_IDLE		(0 * 60 * HZ)		/* Idle=None */
+#define AX25_DEF_IDLE		0			/* Idle=None */
 #define AX25_DEF_PACLEN		256			/* Paclen=256 */
 #define	AX25_DEF_PROTOCOL	AX25_PROTO_STD_SIMPLEX	/* Standard AX.25 */
-#define AX25_DEF_DS_TIMEOUT	(3 * 60 * HZ)		/* DAMA timeout 3 minutes */
+#define AX25_DEF_DS_TIMEOUT	180000			/* DAMA timeout 3 minutes */
 
 typedef struct ax25_uid_assoc {
 	struct hlist_node	uid_node;
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 4087dfc4709485d94d93cbdfdf868aacae07cff2..293e920ca59d7686cc2a591bdfa53dfe9d7995c9 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -958,11 +958,13 @@ enum ieee80211_state {
 
 #define IEEE80211_24GHZ_MIN_CHANNEL 1
 #define IEEE80211_24GHZ_MAX_CHANNEL 14
-#define IEEE80211_24GHZ_CHANNELS    14
+#define IEEE80211_24GHZ_CHANNELS (IEEE80211_24GHZ_MAX_CHANNEL - \
+				  IEEE80211_24GHZ_MIN_CHANNEL + 1)
 
 #define IEEE80211_52GHZ_MIN_CHANNEL 34
 #define IEEE80211_52GHZ_MAX_CHANNEL 165
-#define IEEE80211_52GHZ_CHANNELS    131
+#define IEEE80211_52GHZ_CHANNELS (IEEE80211_52GHZ_MAX_CHANNEL - \
+				  IEEE80211_52GHZ_MIN_CHANNEL + 1)
 
 enum {
 	IEEE80211_CH_PASSIVE_ONLY = (1 << 0),
diff --git a/include/net/ieee80211softmac.h b/include/net/ieee80211softmac.h
index b1ebfbae397f7d1b050252f2accccbaf46d18610..052ed596a4e487de798d0513f472ce842b66ba21 100644
--- a/include/net/ieee80211softmac.h
+++ b/include/net/ieee80211softmac.h
@@ -204,7 +204,8 @@ struct ieee80211softmac_device {
 	
 	/* couple of flags */
 	u8 scanning:1, /* protects scanning from being done multiple times at once */
-	   associated:1;
+	   associated:1,
+	   running:1;
 	
 	struct ieee80211softmac_scaninfo *scaninfo;
 	struct ieee80211softmac_assoc_info associnfo;
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index b0666d66293fd545f63163bc54350c0ca6ac1204..4901ee446879e59795f0df8d57a1c18ce9c7ce92 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -211,6 +211,7 @@ struct neigh_table
 #define NEIGH_UPDATE_F_ADMIN			0x80000000
 
 extern void			neigh_table_init(struct neigh_table *tbl);
+extern void			neigh_table_init_no_netlink(struct neigh_table *tbl);
 extern int			neigh_table_clear(struct neigh_table *tbl);
 extern struct neighbour *	neigh_lookup(struct neigh_table *tbl,
 					     const void *pkey,
diff --git a/include/net/netrom.h b/include/net/netrom.h
index a5ee53bce62fc1fe546f2331f56190e960178016..e0ca112024a390155d2b75e6f0f9255ce98451d9 100644
--- a/include/net/netrom.h
+++ b/include/net/netrom.h
@@ -42,11 +42,11 @@ enum {
 #define	NR_COND_PEER_RX_BUSY		0x04
 #define	NR_COND_OWN_RX_BUSY		0x08
 
-#define NR_DEFAULT_T1			(120 * HZ)	/* Outstanding frames - 120 seconds */
-#define NR_DEFAULT_T2			(5   * HZ)	/* Response delay     - 5 seconds */
+#define NR_DEFAULT_T1			120000		/* Outstanding frames - 120 seconds */
+#define NR_DEFAULT_T2			5000		/* Response delay     - 5 seconds */
 #define NR_DEFAULT_N2			3		/* Number of Retries - 3 */
-#define	NR_DEFAULT_T4			(180 * HZ)	/* Busy Delay - 180 seconds */
-#define	NR_DEFAULT_IDLE			(0 * 60 * HZ)	/* No Activity Timeout - none */
+#define	NR_DEFAULT_T4			180000		/* Busy Delay - 180 seconds */
+#define	NR_DEFAULT_IDLE			0		/* No Activity Timeout - none */
 #define	NR_DEFAULT_WINDOW		4		/* Default Window Size - 4 */
 #define	NR_DEFAULT_OBS			6		/* Default Obsolescence Count - 6 */
 #define	NR_DEFAULT_QUAL			10		/* Default Neighbour Quality - 10 */
diff --git a/include/net/rose.h b/include/net/rose.h
index 3249b979605a2de9aed8d38b75f48235a4e3c59a..012b09ed24015ffffad4732e49be73aa82c1e7a9 100644
--- a/include/net/rose.h
+++ b/include/net/rose.h
@@ -49,14 +49,14 @@ enum {
 	ROSE_STATE_5			/* Deferred Call Acceptance */
 };
 
-#define ROSE_DEFAULT_T0			(180 * HZ)	/* Default T10 T20 value */
-#define ROSE_DEFAULT_T1			(200 * HZ)	/* Default T11 T21 value */
-#define ROSE_DEFAULT_T2			(180 * HZ)	/* Default T12 T22 value */
-#define	ROSE_DEFAULT_T3			(180 * HZ)	/* Default T13 T23 value */
-#define	ROSE_DEFAULT_HB			(5 * HZ)	/* Default Holdback value */
-#define	ROSE_DEFAULT_IDLE		(0 * 60 * HZ)	/* No Activity Timeout - none */
+#define ROSE_DEFAULT_T0			180000		/* Default T10 T20 value */
+#define ROSE_DEFAULT_T1			200000		/* Default T11 T21 value */
+#define ROSE_DEFAULT_T2			180000		/* Default T12 T22 value */
+#define	ROSE_DEFAULT_T3			180000		/* Default T13 T23 value */
+#define	ROSE_DEFAULT_HB			5000		/* Default Holdback value */
+#define	ROSE_DEFAULT_IDLE		0		/* No Activity Timeout - none */
 #define	ROSE_DEFAULT_ROUTING		1		/* Default routing flag */
-#define	ROSE_DEFAULT_FAIL_TIMEOUT	(120 * HZ)	/* Time until link considered usable */
+#define	ROSE_DEFAULT_FAIL_TIMEOUT	120000		/* Time until link considered usable */
 #define	ROSE_DEFAULT_MAXVC		50		/* Maximum number of VCs per neighbour */
 #define	ROSE_DEFAULT_WINDOW_SIZE	7		/* Default window size */
 
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index 34a1a09e5aeff93927fb058be18e79e6afbf32df..807d6f1ef4b505bd302de0281aee75fc71a2b50a 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -99,6 +99,7 @@ typedef enum {
 	SCTP_CMD_DEL_NON_PRIMARY, /* Removes non-primary peer transports. */
 	SCTP_CMD_T3_RTX_TIMERS_STOP, /* Stops T3-rtx pending timers */
 	SCTP_CMD_FORCE_PRIM_RETRAN,  /* Forces retrans. over primary path. */
+	SCTP_CMD_SET_SK_ERR,	 /* Set sk_err */
 	SCTP_CMD_LAST
 } sctp_verb_t;
 
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index e673b2c984e931c9a80d7c5e677bfdc1984fa4c3..aa6033ca7cd859d3614406a54b0d4885e79a94dc 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -461,12 +461,12 @@ static inline int sctp_frag_point(const struct sctp_sock *sp, int pmtu)
  * there is room for a param header too.
  */
 #define sctp_walk_params(pos, chunk, member)\
-_sctp_walk_params((pos), (chunk), WORD_ROUND(ntohs((chunk)->chunk_hdr.length)), member)
+_sctp_walk_params((pos), (chunk), ntohs((chunk)->chunk_hdr.length), member)
 
 #define _sctp_walk_params(pos, chunk, end, member)\
 for (pos.v = chunk->member;\
      pos.v <= (void *)chunk + end - sizeof(sctp_paramhdr_t) &&\
-     pos.v <= (void *)chunk + end - WORD_ROUND(ntohs(pos.p->length)) &&\
+     pos.v <= (void *)chunk + end - ntohs(pos.p->length) &&\
      ntohs(pos.p->length) >= sizeof(sctp_paramhdr_t);\
      pos.v += WORD_ROUND(ntohs(pos.p->length)))
 
@@ -477,7 +477,7 @@ _sctp_walk_errors((err), (chunk_hdr), ntohs((chunk_hdr)->length))
 for (err = (sctp_errhdr_t *)((void *)chunk_hdr + \
 	    sizeof(sctp_chunkhdr_t));\
      (void *)err <= (void *)chunk_hdr + end - sizeof(sctp_errhdr_t) &&\
-     (void *)err <= (void *)chunk_hdr + end - WORD_ROUND(ntohs(err->length)) &&\
+     (void *)err <= (void *)chunk_hdr + end - ntohs(err->length) &&\
      ntohs(err->length) >= sizeof(sctp_errhdr_t); \
      err = (sctp_errhdr_t *)((void *)err + WORD_ROUND(ntohs(err->length))))
 
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index eba99f375517ac5ea0e56058feb89f5238ac67af..7f4fea173fb1a5bf1c11eb4099f3558c01be2220 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -712,6 +712,7 @@ struct sctp_chunk {
 	__u8 tsn_gap_acked;	/* Is this chunk acked by a GAP ACK? */
 	__s8 fast_retransmit;	 /* Is this chunk fast retransmitted? */
 	__u8 tsn_missing_report; /* Data chunk missing counter. */
+	__u8 data_accepted; 	/* At least 1 chunk in this packet accepted */
 };
 
 void sctp_chunk_hold(struct sctp_chunk *);
diff --git a/include/scsi/srp.h b/include/scsi/srp.h
index 6c2681dc5b46737e21ad139ae9a7863728bc98f7..637f77eccf0c77d491a6c6a4e7d6b54ed115f645 100644
--- a/include/scsi/srp.h
+++ b/include/scsi/srp.h
@@ -95,14 +95,15 @@ struct srp_direct_buf {
 
 /*
  * We need the packed attribute because the SRP spec puts the list of
- * descriptors at an offset of 20, which is not aligned to the size
- * of struct srp_direct_buf.
+ * descriptors at an offset of 20, which is not aligned to the size of
+ * struct srp_direct_buf.  The whole structure must be packed to avoid
+ * having the 20-byte structure padded to 24 bytes on 64-bit architectures.
  */
 struct srp_indirect_buf {
 	struct srp_direct_buf	table_desc;
 	__be32			len;
-	struct srp_direct_buf	desc_list[0] __attribute__((packed));
-};
+	struct srp_direct_buf	desc_list[0];
+} __attribute__((packed));
 
 enum {
 	SRP_MULTICHAN_SINGLE = 0,
@@ -122,6 +123,11 @@ struct srp_login_req {
 	u8	target_port_id[16];
 };
 
+/*
+ * The SRP spec defines the size of the LOGIN_RSP structure to be 52
+ * bytes, so it needs to be packed to avoid having it padded to 56
+ * bytes on 64-bit architectures.
+ */
 struct srp_login_rsp {
 	u8	opcode;
 	u8	reserved1[3];
@@ -132,7 +138,7 @@ struct srp_login_rsp {
 	__be16	buf_fmt;
 	u8	rsp_flags;
 	u8	reserved2[25];
-};
+} __attribute__((packed));
 
 struct srp_login_rej {
 	u8	opcode;
@@ -207,6 +213,11 @@ enum {
 	SRP_RSP_FLAG_DIUNDER  = 1 << 5
 };
 
+/*
+ * The SRP spec defines the size of the RSP structure to be 36 bytes,
+ * so it needs to be packed to avoid having it padded to 40 bytes on
+ * 64-bit architectures.
+ */
 struct srp_rsp {
 	u8	opcode;
 	u8	sol_not;
@@ -221,6 +232,6 @@ struct srp_rsp {
 	__be32	sense_data_len;
 	__be32	resp_data_len;
 	u8	data[0];
-};
+} __attribute__((packed));
 
 #endif /* SCSI_SRP_H */
diff --git a/init/do_mounts.c b/init/do_mounts.c
index adb7cad3e6eec17165efdf88acf1f0f936fc4c9d..f4b7b9d278cd3bf040cdac1a1ee123401549f103 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -310,6 +310,11 @@ retry:
 
 		panic("VFS: Unable to mount root fs on %s", b);
 	}
+
+	printk("No filesystem could mount root, tried: ");
+	for (p = fs_names; *p; p += strlen(p)+1)
+		printk(" %s", p);
+	printk("\n");
 	panic("VFS: Unable to mount root fs on %s", __bdevname(ROOT_DEV, b));
 out:
 	putname(fs_names);
diff --git a/init/initramfs.c b/init/initramfs.c
index 679d870d991b760438a95d133c9684b9f381eb0d..f81cfa40a719858a003ab50448f3d0925005d5ff 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -26,10 +26,12 @@ static void __init free(void *where)
 
 /* link hash */
 
+#define N_ALIGN(len) ((((len) + 1) & ~3) + 2)
+
 static __initdata struct hash {
 	int ino, minor, major;
 	struct hash *next;
-	char *name;
+	char name[N_ALIGN(PATH_MAX)];
 } *head[32];
 
 static inline int hash(int major, int minor, int ino)
@@ -57,7 +59,7 @@ static char __init *find_link(int major, int minor, int ino, char *name)
 	q->ino = ino;
 	q->minor = minor;
 	q->major = major;
-	q->name = name;
+	strcpy(q->name, name);
 	q->next = NULL;
 	*p = q;
 	return NULL;
@@ -133,8 +135,6 @@ static inline void eat(unsigned n)
 	count -= n;
 }
 
-#define N_ALIGN(len) ((((len) + 1) & ~3) + 2)
-
 static __initdata char *collected;
 static __initdata int remains;
 static __initdata char *collect;
diff --git a/kernel/extable.c b/kernel/extable.c
index 7501b531ceedab97f969402822be75d6819b042f..7fe2628553172eadc0d49a3cbaf9d779b80b5a7c 100644
--- a/kernel/extable.c
+++ b/kernel/extable.c
@@ -40,7 +40,7 @@ const struct exception_table_entry *search_exception_tables(unsigned long addr)
 	return e;
 }
 
-static int core_kernel_text(unsigned long addr)
+int core_kernel_text(unsigned long addr)
 {
 	if (addr >= (unsigned long)_stext &&
 	    addr <= (unsigned long)_etext)
diff --git a/kernel/module.c b/kernel/module.c
index d24deb0dbbc9488e91ba855342399c22c3f9d309..bbe04862e1b09113dd12dd49749f551cd9fbeecf 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -705,14 +705,14 @@ EXPORT_SYMBOL(__symbol_put);
 
 void symbol_put_addr(void *addr)
 {
-	unsigned long flags;
+	struct module *modaddr;
 
-	spin_lock_irqsave(&modlist_lock, flags);
-	if (!kernel_text_address((unsigned long)addr))
-		BUG();
+	if (core_kernel_text((unsigned long)addr))
+		return;
 
-	module_put(module_text_address((unsigned long)addr));
-	spin_unlock_irqrestore(&modlist_lock, flags);
+	if (!(modaddr = module_text_address((unsigned long)addr)))
+		BUG();
+	module_put(modaddr);
 }
 EXPORT_SYMBOL_GPL(symbol_put_addr);
 
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 4e0f0ec003f751a0aa91e2d8388365f042f072d9..921c22ad16e40e898b2cdceda7db6ea13babb36f 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -148,12 +148,34 @@ int ptrace_may_attach(struct task_struct *task)
 int ptrace_attach(struct task_struct *task)
 {
 	int retval;
-	task_lock(task);
+
 	retval = -EPERM;
 	if (task->pid <= 1)
-		goto bad;
+		goto out;
 	if (task->tgid == current->tgid)
-		goto bad;
+		goto out;
+
+repeat:
+	/*
+	 * Nasty, nasty.
+	 *
+	 * We want to hold both the task-lock and the
+	 * tasklist_lock for writing at the same time.
+	 * But that's against the rules (tasklist_lock
+	 * is taken for reading by interrupts on other
+	 * cpu's that may have task_lock).
+	 */
+	task_lock(task);
+	local_irq_disable();
+	if (!write_trylock(&tasklist_lock)) {
+		local_irq_enable();
+		task_unlock(task);
+		do {
+			cpu_relax();
+		} while (!write_can_lock(&tasklist_lock));
+		goto repeat;
+	}
+
 	/* the same process cannot be attached many times */
 	if (task->ptrace & PT_PTRACED)
 		goto bad;
@@ -166,17 +188,15 @@ int ptrace_attach(struct task_struct *task)
 				      ? PT_ATTACHED : 0);
 	if (capable(CAP_SYS_PTRACE))
 		task->ptrace |= PT_PTRACE_CAP;
-	task_unlock(task);
 
-	write_lock_irq(&tasklist_lock);
 	__ptrace_link(task, current);
-	write_unlock_irq(&tasklist_lock);
 
 	force_sig_specific(SIGSTOP, task);
-	return 0;
 
 bad:
+	write_unlock_irq(&tasklist_lock);
 	task_unlock(task);
+out:
 	return retval;
 }
 
@@ -417,21 +437,22 @@ int ptrace_request(struct task_struct *child, long request,
  */
 int ptrace_traceme(void)
 {
-	int ret;
+	int ret = -EPERM;
 
 	/*
 	 * Are we already being traced?
 	 */
-	if (current->ptrace & PT_PTRACED)
-		return -EPERM;
-	ret = security_ptrace(current->parent, current);
-	if (ret)
-		return -EPERM;
-	/*
-	 * Set the ptrace bit in the process ptrace flags.
-	 */
-	current->ptrace |= PT_PTRACED;
-	return 0;
+	task_lock(current);
+	if (!(current->ptrace & PT_PTRACED)) {
+		ret = security_ptrace(current->parent, current);
+		/*
+		 * Set the ptrace bit in the process ptrace flags.
+		 */
+		if (!ret)
+			current->ptrace |= PT_PTRACED;
+	}
+	task_unlock(current);
+	return ret;
 }
 
 /**
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index 6d32ff26f9484190f4588107277d08f7dee40909..2058f88c7bbb3d9c9d0c7e195f3d67f25d8f64ed 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -479,12 +479,31 @@ static int __rcu_pending(struct rcu_ctrlblk *rcp, struct rcu_data *rdp)
 	return 0;
 }
 
+/*
+ * Check to see if there is any immediate RCU-related work to be done
+ * by the current CPU, returning 1 if so.  This function is part of the
+ * RCU implementation; it is -not- an exported member of the RCU API.
+ */
 int rcu_pending(int cpu)
 {
 	return __rcu_pending(&rcu_ctrlblk, &per_cpu(rcu_data, cpu)) ||
 		__rcu_pending(&rcu_bh_ctrlblk, &per_cpu(rcu_bh_data, cpu));
 }
 
+/*
+ * Check to see if any future RCU-related work will need to be done
+ * by the current CPU, even if none need be done immediately, returning
+ * 1 if so.  This function is part of the RCU implementation; it is -not-
+ * an exported member of the RCU API.
+ */
+int rcu_needs_cpu(int cpu)
+{
+	struct rcu_data *rdp = &per_cpu(rcu_data, cpu);
+	struct rcu_data *rdp_bh = &per_cpu(rcu_bh_data, cpu);
+
+	return (!!rdp->curlist || !!rdp_bh->curlist || rcu_pending(cpu));
+}
+
 void rcu_check_callbacks(int cpu, int user)
 {
 	if (user || 
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 6ecc180beb7145c5c649f36bc2b7961eab7af13e..ccb0c1fdf1b5de0c6beeb37f53c36f0430ba70da 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -189,7 +189,7 @@ config FRAME_POINTER
 config UNWIND_INFO
 	bool "Compile the kernel with frame unwind information"
 	depends on !IA64
-	depends on !MODULES || !(MIPS || PARISC || PPC || SUPERH || SPARC64 || V850)
+	depends on !MODULES || !(MIPS || PARISC || PPC || SUPERH || V850)
 	help
 	  If you say Y here the resulting kernel image will be slightly larger
 	  but not slower, and it will give very useful debugging information.
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index ea77c999047ec634746d3b6457724bcb7c5eac5c..813b4ec1298a23ee10e0d091305bd8520ba6fad0 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -39,6 +39,7 @@
 #include <linux/mempolicy.h>
 
 #include <asm/tlbflush.h>
+#include <asm/div64.h>
 #include "internal.h"
 
 /*
@@ -2566,9 +2567,11 @@ void setup_per_zone_pages_min(void)
 	}
 
 	for_each_zone(zone) {
-		unsigned long tmp;
+		u64 tmp;
+
 		spin_lock_irqsave(&zone->lru_lock, flags);
-		tmp = (pages_min * zone->present_pages) / lowmem_pages;
+		tmp = (u64)pages_min * zone->present_pages;
+		do_div(tmp, lowmem_pages);
 		if (is_highmem(zone)) {
 			/*
 			 * __GFP_HIGH and PF_MEMALLOC allocations usually don't
@@ -2595,8 +2598,8 @@ void setup_per_zone_pages_min(void)
 			zone->pages_min = tmp;
 		}
 
-		zone->pages_low   = zone->pages_min + tmp / 4;
-		zone->pages_high  = zone->pages_min + tmp / 2;
+		zone->pages_low   = zone->pages_min + (tmp >> 2);
+		zone->pages_high  = zone->pages_min + (tmp >> 1);
 		spin_unlock_irqrestore(&zone->lru_lock, flags);
 	}
 
diff --git a/mm/slab.c b/mm/slab.c
index c32af7e7581ef0ff11ef112f94b6a84da50cafc4..d31a06bfbea5c78998e3c68a5a484b98b3e4579f 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -700,6 +700,14 @@ static enum {
 	FULL
 } g_cpucache_up;
 
+/*
+ * used by boot code to determine if it can use slab based allocator
+ */
+int slab_is_available(void)
+{
+	return g_cpucache_up == FULL;
+}
+
 static DEFINE_PER_CPU(struct work_struct, reap_work);
 
 static void free_block(struct kmem_cache *cachep, void **objpp, int len,
@@ -2192,11 +2200,14 @@ static void drain_cpu_caches(struct kmem_cache *cachep)
 	check_irq_on();
 	for_each_online_node(node) {
 		l3 = cachep->nodelists[node];
-		if (l3) {
+		if (l3 && l3->alien)
+			drain_alien_cache(cachep, l3->alien);
+	}
+
+	for_each_online_node(node) {
+		l3 = cachep->nodelists[node];
+		if (l3)
 			drain_array(cachep, l3, l3->shared, 1, node);
-			if (l3->alien)
-				drain_alien_cache(cachep, l3->alien);
-		}
 	}
 }
 
diff --git a/mm/sparse.c b/mm/sparse.c
index d7c32de99ee8c49d0e850a06084d5efe508a7625..c5e89eb9ac8ff10e1e15fced114de41058df4a7e 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -32,7 +32,7 @@ static struct mem_section *sparse_index_alloc(int nid)
 	unsigned long array_size = SECTIONS_PER_ROOT *
 				   sizeof(struct mem_section);
 
-	if (system_state == SYSTEM_RUNNING)
+	if (slab_is_available())
 		section = kmalloc_node(array_size, GFP_KERNEL, nid);
 	else
 		section = alloc_bootmem_node(NODE_DATA(nid), array_size);
diff --git a/net/802/tr.c b/net/802/tr.c
index afd8385c0c9c319bff792f714cc3326881db95d9..e9dc803f2fe0a67de78c4219227f4876352cd89a 100644
--- a/net/802/tr.c
+++ b/net/802/tr.c
@@ -643,6 +643,5 @@ static int __init rif_init(void)
 
 module_init(rif_init);
 
-EXPORT_SYMBOL(tr_source_route);
 EXPORT_SYMBOL(tr_type_trans);
 EXPORT_SYMBOL(alloc_trdev);
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 1a786bfaa416c8d6972ef974dd31577caf14cc9e..72d8529826646e35018514046c3afac4197885a8 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -963,7 +963,7 @@ static struct file_operations arp_seq_fops = {
 static int __init atm_clip_init(void)
 {
 	struct proc_dir_entry *p;
-	neigh_table_init(&clip_tbl);
+	neigh_table_init_no_netlink(&clip_tbl);
 
 	clip_tbl_hook = &clip_tbl;
 	register_atm_ioctl(&clip_ioctl_ops);
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index dbf9b47681f72c119b217c44f4a883d1345ba6f9..a2e0dd047e9f66be4798cd2fadb2cec6d33c498a 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -228,6 +228,8 @@ ax25_cb *ax25_find_cb(ax25_address *src_addr, ax25_address *dest_addr,
 	return NULL;
 }
 
+EXPORT_SYMBOL(ax25_find_cb);
+
 void ax25_send_to_raw(ax25_address *addr, struct sk_buff *skb, int proto)
 {
 	ax25_cb *s;
@@ -424,6 +426,26 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void __user *arg)
 	return 0;
 }
 
+static void ax25_fillin_cb_from_dev(ax25_cb *ax25, ax25_dev *ax25_dev)
+{
+	ax25->rtt     = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T1]) / 2;
+	ax25->t1      = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T1]);
+	ax25->t2      = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T2]);
+	ax25->t3      = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T3]);
+	ax25->n2      = ax25_dev->values[AX25_VALUES_N2];
+	ax25->paclen  = ax25_dev->values[AX25_VALUES_PACLEN];
+	ax25->idle    = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_IDLE]);
+	ax25->backoff = ax25_dev->values[AX25_VALUES_BACKOFF];
+
+	if (ax25_dev->values[AX25_VALUES_AXDEFMODE]) {
+		ax25->modulus = AX25_EMODULUS;
+		ax25->window  = ax25_dev->values[AX25_VALUES_EWINDOW];
+	} else {
+		ax25->modulus = AX25_MODULUS;
+		ax25->window  = ax25_dev->values[AX25_VALUES_WINDOW];
+	}
+}
+
 /*
  *	Fill in a created AX.25 created control block with the default
  *	values for a particular device.
@@ -433,39 +455,28 @@ void ax25_fillin_cb(ax25_cb *ax25, ax25_dev *ax25_dev)
 	ax25->ax25_dev = ax25_dev;
 
 	if (ax25->ax25_dev != NULL) {
-		ax25->rtt     = ax25_dev->values[AX25_VALUES_T1] / 2;
-		ax25->t1      = ax25_dev->values[AX25_VALUES_T1];
-		ax25->t2      = ax25_dev->values[AX25_VALUES_T2];
-		ax25->t3      = ax25_dev->values[AX25_VALUES_T3];
-		ax25->n2      = ax25_dev->values[AX25_VALUES_N2];
-		ax25->paclen  = ax25_dev->values[AX25_VALUES_PACLEN];
-		ax25->idle    = ax25_dev->values[AX25_VALUES_IDLE];
-		ax25->backoff = ax25_dev->values[AX25_VALUES_BACKOFF];
-
-		if (ax25_dev->values[AX25_VALUES_AXDEFMODE]) {
-			ax25->modulus = AX25_EMODULUS;
-			ax25->window  = ax25_dev->values[AX25_VALUES_EWINDOW];
-		} else {
-			ax25->modulus = AX25_MODULUS;
-			ax25->window  = ax25_dev->values[AX25_VALUES_WINDOW];
-		}
+		ax25_fillin_cb_from_dev(ax25, ax25_dev);
+		return;
+	}
+
+	/*
+	 * No device, use kernel / AX.25 spec default values
+	 */
+	ax25->rtt     = msecs_to_jiffies(AX25_DEF_T1) / 2;
+	ax25->t1      = msecs_to_jiffies(AX25_DEF_T1);
+	ax25->t2      = msecs_to_jiffies(AX25_DEF_T2);
+	ax25->t3      = msecs_to_jiffies(AX25_DEF_T3);
+	ax25->n2      = AX25_DEF_N2;
+	ax25->paclen  = AX25_DEF_PACLEN;
+	ax25->idle    = msecs_to_jiffies(AX25_DEF_IDLE);
+	ax25->backoff = AX25_DEF_BACKOFF;
+
+	if (AX25_DEF_AXDEFMODE) {
+		ax25->modulus = AX25_EMODULUS;
+		ax25->window  = AX25_DEF_EWINDOW;
 	} else {
-		ax25->rtt     = AX25_DEF_T1 / 2;
-		ax25->t1      = AX25_DEF_T1;
-		ax25->t2      = AX25_DEF_T2;
-		ax25->t3      = AX25_DEF_T3;
-		ax25->n2      = AX25_DEF_N2;
-		ax25->paclen  = AX25_DEF_PACLEN;
-		ax25->idle    = AX25_DEF_IDLE;
-		ax25->backoff = AX25_DEF_BACKOFF;
-
-		if (AX25_DEF_AXDEFMODE) {
-			ax25->modulus = AX25_EMODULUS;
-			ax25->window  = AX25_DEF_EWINDOW;
-		} else {
-			ax25->modulus = AX25_MODULUS;
-			ax25->window  = AX25_DEF_WINDOW;
-		}
+		ax25->modulus = AX25_MODULUS;
+		ax25->window  = AX25_DEF_WINDOW;
 	}
 }
 
@@ -1979,24 +1990,6 @@ static struct notifier_block ax25_dev_notifier = {
 	.notifier_call =ax25_device_event,
 };
 
-EXPORT_SYMBOL(ax25_hard_header);
-EXPORT_SYMBOL(ax25_rebuild_header);
-EXPORT_SYMBOL(ax25_findbyuid);
-EXPORT_SYMBOL(ax25_find_cb);
-EXPORT_SYMBOL(ax25_linkfail_register);
-EXPORT_SYMBOL(ax25_linkfail_release);
-EXPORT_SYMBOL(ax25_listen_register);
-EXPORT_SYMBOL(ax25_listen_release);
-EXPORT_SYMBOL(ax25_protocol_register);
-EXPORT_SYMBOL(ax25_protocol_release);
-EXPORT_SYMBOL(ax25_send_frame);
-EXPORT_SYMBOL(ax25_uid_policy);
-EXPORT_SYMBOL(ax25cmp);
-EXPORT_SYMBOL(ax2asc);
-EXPORT_SYMBOL(asc2ax);
-EXPORT_SYMBOL(null_ax25_address);
-EXPORT_SYMBOL(ax25_display_timer);
-
 static int __init ax25_init(void)
 {
 	int rc = proto_register(&ax25_proto, 0);
diff --git a/net/ax25/ax25_addr.c b/net/ax25/ax25_addr.c
index 0164a155b8c492b2ef6918d3b8010d7150126119..5f0896ad0042d59662d33e351853a83538e13a96 100644
--- a/net/ax25/ax25_addr.c
+++ b/net/ax25/ax25_addr.c
@@ -11,6 +11,7 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
@@ -33,6 +34,8 @@
  */
 ax25_address null_ax25_address = {{0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00}};
 
+EXPORT_SYMBOL(null_ax25_address);
+
 /*
  *	ax25 -> ascii conversion
  */
@@ -64,6 +67,8 @@ char *ax2asc(char *buf, ax25_address *a)
 
 }
 
+EXPORT_SYMBOL(ax2asc);
+
 /*
  *	ascii -> ax25 conversion
  */
@@ -97,6 +102,8 @@ void asc2ax(ax25_address *addr, char *callsign)
 	addr->ax25_call[6] &= 0x1E;
 }
 
+EXPORT_SYMBOL(asc2ax);
+
 /*
  *	Compare two ax.25 addresses
  */
@@ -116,6 +123,8 @@ int ax25cmp(ax25_address *a, ax25_address *b)
  	return 2;			/* Partial match */
 }
 
+EXPORT_SYMBOL(ax25cmp);
+
 /*
  *	Compare two AX.25 digipeater paths.
  */
diff --git a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.c
index 061083efc1dcddc70cf900fbc43e77b69bfafa41..5961459935eb4f0d13497b4b6b0ecda79f7ca6dc 100644
--- a/net/ax25/ax25_ds_timer.c
+++ b/net/ax25/ax25_ds_timer.c
@@ -61,7 +61,8 @@ void ax25_ds_set_timer(ax25_dev *ax25_dev)
 		return;
 
 	del_timer(&ax25_dev->dama.slave_timer);
-	ax25_dev->dama.slave_timeout = ax25_dev->values[AX25_VALUES_DS_TIMEOUT] / 10;
+	ax25_dev->dama.slave_timeout =
+		msecs_to_jiffies(ax25_dev->values[AX25_VALUES_DS_TIMEOUT]) / 10;
 	ax25_ds_add_timer(ax25_dev);
 }
 
diff --git a/net/ax25/ax25_iface.c b/net/ax25/ax25_iface.c
index d68aff100729abbfa51f2677ae565f6a156ad08d..3bb152710b77cbe07cdc556b3700a42fc36094dc 100644
--- a/net/ax25/ax25_iface.c
+++ b/net/ax25/ax25_iface.c
@@ -12,6 +12,7 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/timer.h>
@@ -74,6 +75,8 @@ int ax25_protocol_register(unsigned int pid,
 	return 1;
 }
 
+EXPORT_SYMBOL(ax25_protocol_register);
+
 void ax25_protocol_release(unsigned int pid)
 {
 	struct protocol_struct *s, *protocol;
@@ -106,6 +109,8 @@ void ax25_protocol_release(unsigned int pid)
 	write_unlock(&protocol_list_lock);
 }
 
+EXPORT_SYMBOL(ax25_protocol_release);
+
 int ax25_linkfail_register(void (*func)(ax25_cb *, int))
 {
 	struct linkfail_struct *linkfail;
@@ -123,6 +128,8 @@ int ax25_linkfail_register(void (*func)(ax25_cb *, int))
 	return 1;
 }
 
+EXPORT_SYMBOL(ax25_linkfail_register);
+
 void ax25_linkfail_release(void (*func)(ax25_cb *, int))
 {
 	struct linkfail_struct *s, *linkfail;
@@ -155,6 +162,8 @@ void ax25_linkfail_release(void (*func)(ax25_cb *, int))
 	spin_unlock_bh(&linkfail_lock);
 }
 
+EXPORT_SYMBOL(ax25_linkfail_release);
+
 int ax25_listen_register(ax25_address *callsign, struct net_device *dev)
 {
 	struct listen_struct *listen;
@@ -176,6 +185,8 @@ int ax25_listen_register(ax25_address *callsign, struct net_device *dev)
 	return 1;
 }
 
+EXPORT_SYMBOL(ax25_listen_register);
+
 void ax25_listen_release(ax25_address *callsign, struct net_device *dev)
 {
 	struct listen_struct *s, *listen;
@@ -208,6 +219,8 @@ void ax25_listen_release(ax25_address *callsign, struct net_device *dev)
 	spin_unlock_bh(&listen_lock);
 }
 
+EXPORT_SYMBOL(ax25_listen_release);
+
 int (*ax25_protocol_function(unsigned int pid))(struct sk_buff *, ax25_cb *)
 {
 	int (*res)(struct sk_buff *, ax25_cb *) = NULL;
diff --git a/net/ax25/ax25_ip.c b/net/ax25/ax25_ip.c
index d643dac3eccc6981b8d56b1a9c1ba20fa3b5bcf4..a0b534f80f1774fc76a8daad66df1b2dc09aa656 100644
--- a/net/ax25/ax25_ip.c
+++ b/net/ax25/ax25_ip.c
@@ -12,6 +12,7 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
@@ -221,3 +222,5 @@ int ax25_rebuild_header(struct sk_buff *skb)
 
 #endif
 
+EXPORT_SYMBOL(ax25_hard_header);
+EXPORT_SYMBOL(ax25_rebuild_header);
diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c
index 5fc048dcd39ab29089b4140785f75315d4348f6f..5d99852b239cd9b932ddfe197a191acddf72ed11 100644
--- a/net/ax25/ax25_out.c
+++ b/net/ax25/ax25_out.c
@@ -14,6 +14,7 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
@@ -104,6 +105,8 @@ ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, ax25_address *src, ax2
 	return ax25;			/* We had to create it */
 }
 
+EXPORT_SYMBOL(ax25_send_frame);
+
 /*
  *	All outgoing AX.25 I frames pass via this routine. Therefore this is
  *	where the fragmentation of frames takes place. If fragment is set to
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
index f04f8630fd2835e61cef28562cb7e4bd12203767..5ac98250797bf8de2e1a0e5b158ce19315d55bd3 100644
--- a/net/ax25/ax25_route.c
+++ b/net/ax25/ax25_route.c
@@ -360,7 +360,7 @@ struct file_operations ax25_route_fops = {
 /*
  *	Find AX.25 route
  *
- *	Only routes with a refernce rout of zero can be destroyed.
+ *	Only routes with a reference count of zero can be destroyed.
  */
 static ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev)
 {
diff --git a/net/ax25/ax25_timer.c b/net/ax25/ax25_timer.c
index 7a6b50a14554d5cbc1390c11288c0dce4c8f7cca..ec254057f21239b8ab8124e9a16a2d90b2e1a5a7 100644
--- a/net/ax25/ax25_timer.c
+++ b/net/ax25/ax25_timer.c
@@ -18,6 +18,7 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/jiffies.h>
 #include <linux/timer.h>
 #include <linux/string.h>
@@ -137,6 +138,8 @@ unsigned long ax25_display_timer(struct timer_list *timer)
 	return timer->expires - jiffies;
 }
 
+EXPORT_SYMBOL(ax25_display_timer);
+
 static void ax25_heartbeat_expiry(unsigned long param)
 {
 	int proto = AX25_PROTO_STD_SIMPLEX;
diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c
index b8b5854bce9ab2d35c16bb25b286bd794aa8e4e2..5e9a81e8b214fe4fa96a7977be12c1fbe9378a05 100644
--- a/net/ax25/ax25_uid.c
+++ b/net/ax25/ax25_uid.c
@@ -49,6 +49,8 @@ static DEFINE_RWLOCK(ax25_uid_lock);
 
 int ax25_uid_policy = 0;
 
+EXPORT_SYMBOL(ax25_uid_policy);
+
 ax25_uid_assoc *ax25_findbyuid(uid_t uid)
 {
 	ax25_uid_assoc *ax25_uid, *res = NULL;
@@ -67,6 +69,8 @@ ax25_uid_assoc *ax25_findbyuid(uid_t uid)
 	return res;
 }
 
+EXPORT_SYMBOL(ax25_findbyuid);
+
 int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
 {
 	ax25_uid_assoc *ax25_uid;
diff --git a/net/ax25/sysctl_net_ax25.c b/net/ax25/sysctl_net_ax25.c
index 894a22558d9dc7fb2604c0d84c64cf62873e4803..bdb64c36df12dc1b45d51ec0fa79a60c826b2629 100644
--- a/net/ax25/sysctl_net_ax25.c
+++ b/net/ax25/sysctl_net_ax25.c
@@ -18,14 +18,14 @@ static int min_backoff[1],		max_backoff[] = {2};
 static int min_conmode[1],		max_conmode[] = {2};
 static int min_window[] = {1},		max_window[] = {7};
 static int min_ewindow[] = {1},		max_ewindow[] = {63};
-static int min_t1[] = {1},		max_t1[] = {30 * HZ};
-static int min_t2[] = {1},		max_t2[] = {20 * HZ};
-static int min_t3[1],   		max_t3[] = {3600 * HZ};
-static int min_idle[1],  		max_idle[] = {65535 * HZ};
+static int min_t1[] = {1},		max_t1[] = {30000};
+static int min_t2[] = {1},		max_t2[] = {20000};
+static int min_t3[1],			max_t3[] = {3600000};
+static int min_idle[1],			max_idle[] = {65535000};
 static int min_n2[] = {1},		max_n2[] = {31};
 static int min_paclen[] = {1},		max_paclen[] = {512};
 static int min_proto[1],		max_proto[] = { AX25_PROTO_MAX };
-static int min_ds_timeout[1],   	max_ds_timeout[] = {65535 * HZ};
+static int min_ds_timeout[1],		max_ds_timeout[] = {65535000};
 
 static struct ctl_table_header *ax25_table_header;
 
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 59eef42d4a4259052c67dbe91f07f908767c9437..ad1c7af65ec8dcb944b59d2310df3c9ec539805d 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -308,26 +308,19 @@ int br_add_bridge(const char *name)
 	if (ret)
 		goto err2;
 
-	/* network device kobject is not setup until
-	 * after rtnl_unlock does it's hotplug magic.
-	 * so hold reference to avoid race.
-	 */
-	dev_hold(dev);
-	rtnl_unlock();
-
 	ret = br_sysfs_addbr(dev);
-	dev_put(dev);
-
-	if (ret) 
-		unregister_netdev(dev);
- out:
-	return ret;
+	if (ret)
+		goto err3;
+	rtnl_unlock();
+	return 0;
 
+ err3:
+	unregister_netdev(dev);
  err2:
 	free_netdev(dev);
  err1:
 	rtnl_unlock();
-	goto out;
+	return ret;
 }
 
 int br_del_bridge(const char *name)
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index b0b7f55c1edd38f2901cfc450ac638ca6589dd80..bfa4d8c333f7b727946e40c4c33e159d4fdbfe2f 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -66,6 +66,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
 	}
 
 	if (is_multicast_ether_addr(dest)) {
+		br->statistics.multicast++;
 		br_flood_forward(br, skb, !passedup);
 		if (!passedup)
 			br_pass_frame_up(br, skb);
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index d159c92cca84a0482757c5d58f12bd73a193adfa..466ed3440b7446b3c6d976963b3056eb7f6dc9f5 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -168,7 +168,7 @@ static void ebt_log(const struct sk_buff *skb, unsigned int hooknr,
 
 	if (info->bitmask & EBT_LOG_NFLOG)
 		nf_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li,
-		              info->prefix);
+		              "%s", info->prefix);
 	else
 		ebt_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li,
 		               info->prefix);
diff --git a/net/core/dev.c b/net/core/dev.c
index 3bad1afc89fa48b505c001a24da094de18f14cab..2dce673a039b6f4f71888e4780678b35924e7d3e 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -193,7 +193,7 @@ static inline struct hlist_head *dev_index_hash(int ifindex)
  *	Our notifier list
  */
 
-static BLOCKING_NOTIFIER_HEAD(netdev_chain);
+static RAW_NOTIFIER_HEAD(netdev_chain);
 
 /*
  *	Device drivers call our routines to queue packets here. We empty the
@@ -736,7 +736,7 @@ int dev_change_name(struct net_device *dev, char *newname)
 	if (!err) {
 		hlist_del(&dev->name_hlist);
 		hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name));
-		blocking_notifier_call_chain(&netdev_chain,
+		raw_notifier_call_chain(&netdev_chain,
 				NETDEV_CHANGENAME, dev);
 	}
 
@@ -751,7 +751,7 @@ int dev_change_name(struct net_device *dev, char *newname)
  */
 void netdev_features_change(struct net_device *dev)
 {
-	blocking_notifier_call_chain(&netdev_chain, NETDEV_FEAT_CHANGE, dev);
+	raw_notifier_call_chain(&netdev_chain, NETDEV_FEAT_CHANGE, dev);
 }
 EXPORT_SYMBOL(netdev_features_change);
 
@@ -766,7 +766,7 @@ EXPORT_SYMBOL(netdev_features_change);
 void netdev_state_change(struct net_device *dev)
 {
 	if (dev->flags & IFF_UP) {
-		blocking_notifier_call_chain(&netdev_chain,
+		raw_notifier_call_chain(&netdev_chain,
 				NETDEV_CHANGE, dev);
 		rtmsg_ifinfo(RTM_NEWLINK, dev, 0);
 	}
@@ -864,7 +864,7 @@ int dev_open(struct net_device *dev)
 		/*
 		 *	... and announce new interface.
 		 */
-		blocking_notifier_call_chain(&netdev_chain, NETDEV_UP, dev);
+		raw_notifier_call_chain(&netdev_chain, NETDEV_UP, dev);
 	}
 	return ret;
 }
@@ -887,7 +887,7 @@ int dev_close(struct net_device *dev)
 	 *	Tell people we are going down, so that they can
 	 *	prepare to death, when device is still operating.
 	 */
-	blocking_notifier_call_chain(&netdev_chain, NETDEV_GOING_DOWN, dev);
+	raw_notifier_call_chain(&netdev_chain, NETDEV_GOING_DOWN, dev);
 
 	dev_deactivate(dev);
 
@@ -924,7 +924,7 @@ int dev_close(struct net_device *dev)
 	/*
 	 * Tell people we are down
 	 */
-	blocking_notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev);
+	raw_notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev);
 
 	return 0;
 }
@@ -955,7 +955,7 @@ int register_netdevice_notifier(struct notifier_block *nb)
 	int err;
 
 	rtnl_lock();
-	err = blocking_notifier_chain_register(&netdev_chain, nb);
+	err = raw_notifier_chain_register(&netdev_chain, nb);
 	if (!err) {
 		for (dev = dev_base; dev; dev = dev->next) {
 			nb->notifier_call(nb, NETDEV_REGISTER, dev);
@@ -983,7 +983,7 @@ int unregister_netdevice_notifier(struct notifier_block *nb)
 	int err;
 
 	rtnl_lock();
-	err = blocking_notifier_chain_unregister(&netdev_chain, nb);
+	err = raw_notifier_chain_unregister(&netdev_chain, nb);
 	rtnl_unlock();
 	return err;
 }
@@ -994,12 +994,12 @@ int unregister_netdevice_notifier(struct notifier_block *nb)
  *      @v:   pointer passed unmodified to notifier function
  *
  *	Call all network notifier blocks.  Parameters and return value
- *	are as for blocking_notifier_call_chain().
+ *	are as for raw_notifier_call_chain().
  */
 
 int call_netdevice_notifiers(unsigned long val, void *v)
 {
-	return blocking_notifier_call_chain(&netdev_chain, val, v);
+	return raw_notifier_call_chain(&netdev_chain, val, v);
 }
 
 /* When > 0 there are consumers of rx skb time stamps */
@@ -2308,7 +2308,7 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
 	if (dev->flags & IFF_UP &&
 	    ((old_flags ^ dev->flags) &~ (IFF_UP | IFF_PROMISC | IFF_ALLMULTI |
 					  IFF_VOLATILE)))
-		blocking_notifier_call_chain(&netdev_chain,
+		raw_notifier_call_chain(&netdev_chain,
 				NETDEV_CHANGE, dev);
 
 	if ((flags ^ dev->gflags) & IFF_PROMISC) {
@@ -2353,7 +2353,7 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
 	else
 		dev->mtu = new_mtu;
 	if (!err && dev->flags & IFF_UP)
-		blocking_notifier_call_chain(&netdev_chain,
+		raw_notifier_call_chain(&netdev_chain,
 				NETDEV_CHANGEMTU, dev);
 	return err;
 }
@@ -2370,7 +2370,7 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa)
 		return -ENODEV;
 	err = dev->set_mac_address(dev, sa);
 	if (!err)
-		blocking_notifier_call_chain(&netdev_chain,
+		raw_notifier_call_chain(&netdev_chain,
 				NETDEV_CHANGEADDR, dev);
 	return err;
 }
@@ -2427,7 +2427,7 @@ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
 				return -EINVAL;
 			memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data,
 			       min(sizeof ifr->ifr_hwaddr.sa_data, (size_t) dev->addr_len));
-			blocking_notifier_call_chain(&netdev_chain,
+			raw_notifier_call_chain(&netdev_chain,
 					    NETDEV_CHANGEADDR, dev);
 			return 0;
 
@@ -2777,6 +2777,8 @@ int register_netdevice(struct net_device *dev)
 	BUG_ON(dev_boot_phase);
 	ASSERT_RTNL();
 
+	might_sleep();
+
 	/* When net_device's are persistent, this will be fatal. */
 	BUG_ON(dev->reg_state != NETREG_UNINITIALIZED);
 
@@ -2863,6 +2865,11 @@ int register_netdevice(struct net_device *dev)
 	if (!dev->rebuild_header)
 		dev->rebuild_header = default_rebuild_header;
 
+	ret = netdev_register_sysfs(dev);
+	if (ret)
+		goto out_err;
+	dev->reg_state = NETREG_REGISTERED;
+
 	/*
 	 *	Default initial state at registry is that the
 	 *	device is present.
@@ -2878,14 +2885,11 @@ int register_netdevice(struct net_device *dev)
 	hlist_add_head(&dev->name_hlist, head);
 	hlist_add_head(&dev->index_hlist, dev_index_hash(dev->ifindex));
 	dev_hold(dev);
-	dev->reg_state = NETREG_REGISTERING;
 	write_unlock_bh(&dev_base_lock);
 
 	/* Notify protocols, that a new device appeared. */
-	blocking_notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
+	raw_notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
 
-	/* Finish registration after unlock */
-	net_set_todo(dev);
 	ret = 0;
 
 out:
@@ -2961,7 +2965,7 @@ static void netdev_wait_allrefs(struct net_device *dev)
 			rtnl_lock();
 
 			/* Rebroadcast unregister notification */
-			blocking_notifier_call_chain(&netdev_chain,
+			raw_notifier_call_chain(&netdev_chain,
 					    NETDEV_UNREGISTER, dev);
 
 			if (test_bit(__LINK_STATE_LINKWATCH_PENDING,
@@ -3008,7 +3012,7 @@ static void netdev_wait_allrefs(struct net_device *dev)
  *
  * We are invoked by rtnl_unlock() after it drops the semaphore.
  * This allows us to deal with problems:
- * 1) We can create/delete sysfs objects which invoke hotplug
+ * 1) We can delete sysfs objects which invoke hotplug
  *    without deadlocking with linkwatch via keventd.
  * 2) Since we run with the RTNL semaphore not held, we can sleep
  *    safely in order to wait for the netdev refcnt to drop to zero.
@@ -3017,8 +3021,6 @@ static DEFINE_MUTEX(net_todo_run_mutex);
 void netdev_run_todo(void)
 {
 	struct list_head list = LIST_HEAD_INIT(list);
-	int err;
-
 
 	/* Need to guard against multiple cpu's getting out of order. */
 	mutex_lock(&net_todo_run_mutex);
@@ -3041,40 +3043,29 @@ void netdev_run_todo(void)
 			= list_entry(list.next, struct net_device, todo_list);
 		list_del(&dev->todo_list);
 
-		switch(dev->reg_state) {
-		case NETREG_REGISTERING:
-			dev->reg_state = NETREG_REGISTERED;
-			err = netdev_register_sysfs(dev);
-			if (err)
-				printk(KERN_ERR "%s: failed sysfs registration (%d)\n",
-				       dev->name, err);
-			break;
-
-		case NETREG_UNREGISTERING:
-			netdev_unregister_sysfs(dev);
-			dev->reg_state = NETREG_UNREGISTERED;
-
-			netdev_wait_allrefs(dev);
+		if (unlikely(dev->reg_state != NETREG_UNREGISTERING)) {
+			printk(KERN_ERR "network todo '%s' but state %d\n",
+			       dev->name, dev->reg_state);
+			dump_stack();
+			continue;
+		}
 
-			/* paranoia */
-			BUG_ON(atomic_read(&dev->refcnt));
-			BUG_TRAP(!dev->ip_ptr);
-			BUG_TRAP(!dev->ip6_ptr);
-			BUG_TRAP(!dev->dn_ptr);
+		netdev_unregister_sysfs(dev);
+		dev->reg_state = NETREG_UNREGISTERED;
 
+		netdev_wait_allrefs(dev);
 
-			/* It must be the very last action, 
-			 * after this 'dev' may point to freed up memory.
-			 */
-			if (dev->destructor)
-				dev->destructor(dev);
-			break;
+		/* paranoia */
+		BUG_ON(atomic_read(&dev->refcnt));
+		BUG_TRAP(!dev->ip_ptr);
+		BUG_TRAP(!dev->ip6_ptr);
+		BUG_TRAP(!dev->dn_ptr);
 
-		default:
-			printk(KERN_ERR "network todo '%s' but state %d\n",
-			       dev->name, dev->reg_state);
-			break;
-		}
+		/* It must be the very last action,
+		 * after this 'dev' may point to freed up memory.
+		 */
+		if (dev->destructor)
+			dev->destructor(dev);
 	}
 
 out:
@@ -3216,7 +3207,7 @@ int unregister_netdevice(struct net_device *dev)
 	/* Notify protocols, that we are about to destroy
 	   this device. They should clean all the things.
 	*/
-	blocking_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
+	raw_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
 	
 	/*
 	 *	Flush the multicast chain
diff --git a/net/core/link_watch.c b/net/core/link_watch.c
index 341de44c7ed1e884f1d036ff74c94d884f6714ea..646937cc2d84db521aeff0b4eedb7a1bc89670d5 100644
--- a/net/core/link_watch.c
+++ b/net/core/link_watch.c
@@ -170,13 +170,13 @@ void linkwatch_fire_event(struct net_device *dev)
 		spin_unlock_irqrestore(&lweventlist_lock, flags);
 
 		if (!test_and_set_bit(LW_RUNNING, &linkwatch_flags)) {
-			unsigned long thisevent = jiffies;
+			unsigned long delay = linkwatch_nextevent - jiffies;
 
-			if (thisevent >= linkwatch_nextevent) {
+			/* If we wrap around we'll delay it by at most HZ. */
+			if (!delay || delay > HZ)
 				schedule_work(&linkwatch_work);
-			} else {
-				schedule_delayed_work(&linkwatch_work, linkwatch_nextevent - thisevent);
-			}
+			else
+				schedule_delayed_work(&linkwatch_work, delay);
 		}
 	}
 }
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 4cf878efdb49eb9fc7d02b7b41f83601ab29d079..50a8c73caf972ae64b963a02322f801669d77eaf 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1326,8 +1326,7 @@ void neigh_parms_destroy(struct neigh_parms *parms)
 	kfree(parms);
 }
 
-
-void neigh_table_init(struct neigh_table *tbl)
+void neigh_table_init_no_netlink(struct neigh_table *tbl)
 {
 	unsigned long now = jiffies;
 	unsigned long phsize;
@@ -1383,10 +1382,27 @@ void neigh_table_init(struct neigh_table *tbl)
 
 	tbl->last_flush = now;
 	tbl->last_rand	= now + tbl->parms.reachable_time * 20;
+}
+
+void neigh_table_init(struct neigh_table *tbl)
+{
+	struct neigh_table *tmp;
+
+	neigh_table_init_no_netlink(tbl);
 	write_lock(&neigh_tbl_lock);
+	for (tmp = neigh_tables; tmp; tmp = tmp->next) {
+		if (tmp->family == tbl->family)
+			break;
+	}
 	tbl->next	= neigh_tables;
 	neigh_tables	= tbl;
 	write_unlock(&neigh_tbl_lock);
+
+	if (unlikely(tmp)) {
+		printk(KERN_ERR "NEIGH: Registering multiple tables for "
+		       "family %d\n", tbl->family);
+		dump_stack();
+	}
 }
 
 int neigh_table_clear(struct neigh_table *tbl)
@@ -2657,6 +2673,7 @@ EXPORT_SYMBOL(neigh_rand_reach_time);
 EXPORT_SYMBOL(neigh_resolve_output);
 EXPORT_SYMBOL(neigh_table_clear);
 EXPORT_SYMBOL(neigh_table_init);
+EXPORT_SYMBOL(neigh_table_init_no_netlink);
 EXPORT_SYMBOL(neigh_update);
 EXPORT_SYMBOL(neigh_update_hhs);
 EXPORT_SYMBOL(pneigh_enqueue);
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index c12990c9c603ebb0403ffaab710139409cde81de..47a6fceb6771b00943ee9d845aff91c1ea9e5977 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -29,7 +29,7 @@ static const char fmt_ulong[] = "%lu\n";
 
 static inline int dev_isalive(const struct net_device *dev) 
 {
-	return dev->reg_state == NETREG_REGISTERED;
+	return dev->reg_state <= NETREG_REGISTERED;
 }
 
 /* use same locking rules as GIF* ioctl's */
@@ -445,58 +445,33 @@ static struct class net_class = {
 
 void netdev_unregister_sysfs(struct net_device * net)
 {
-	struct class_device * class_dev = &(net->class_dev);
-
-	if (net->get_stats)
-		sysfs_remove_group(&class_dev->kobj, &netstat_group);
-
-#ifdef WIRELESS_EXT
-	if (net->get_wireless_stats || (net->wireless_handlers &&
-			net->wireless_handlers->get_wireless_stats))
-		sysfs_remove_group(&class_dev->kobj, &wireless_group);
-#endif
-	class_device_del(class_dev);
-
+	class_device_del(&(net->class_dev));
 }
 
 /* Create sysfs entries for network device. */
 int netdev_register_sysfs(struct net_device *net)
 {
 	struct class_device *class_dev = &(net->class_dev);
-	int ret;
+	struct attribute_group **groups = net->sysfs_groups;
 
+	class_device_initialize(class_dev);
 	class_dev->class = &net_class;
 	class_dev->class_data = net;
+	class_dev->groups = groups;
 
+	BUILD_BUG_ON(BUS_ID_SIZE < IFNAMSIZ);
 	strlcpy(class_dev->class_id, net->name, BUS_ID_SIZE);
-	if ((ret = class_device_register(class_dev)))
-		goto out;
 
-	if (net->get_stats &&
-	    (ret = sysfs_create_group(&class_dev->kobj, &netstat_group)))
-		goto out_unreg; 
+	if (net->get_stats)
+		*groups++ = &netstat_group;
 
 #ifdef WIRELESS_EXT
-	if (net->get_wireless_stats || (net->wireless_handlers &&
-			net->wireless_handlers->get_wireless_stats)) {
-		ret = sysfs_create_group(&class_dev->kobj, &wireless_group);
-		if (ret)
-			goto out_cleanup;
-	}
-	return 0;
-out_cleanup:
-	if (net->get_stats)
-		sysfs_remove_group(&class_dev->kobj, &netstat_group);
-#else
-	return 0;
+	if (net->get_wireless_stats
+	    || (net->wireless_handlers && net->wireless_handlers->get_wireless_stats))
+		*groups++ = &wireless_group;
 #endif
 
-out_unreg:
-	printk(KERN_WARNING "%s: sysfs attribute registration failed %d\n",
-	       net->name, ret);
-	class_device_unregister(class_dev);
-out:
-	return ret;
+	return class_device_add(class_dev);
 }
 
 int netdev_sysfs_init(void)
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 1ff7328b0e170bf137819ab03a76b3a4acdd9572..2e0ee8355c415d24d13644e20ecb6d8e837d10c1 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -848,6 +848,7 @@ static int dccp_close_state(struct sock *sk)
 void dccp_close(struct sock *sk, long timeout)
 {
 	struct sk_buff *skb;
+	int state;
 
 	lock_sock(sk);
 
@@ -882,6 +883,11 @@ void dccp_close(struct sock *sk, long timeout)
 	sk_stream_wait_close(sk, timeout);
 
 adjudge_to_death:
+	state = sk->sk_state;
+	sock_hold(sk);
+	sock_orphan(sk);
+	atomic_inc(sk->sk_prot->orphan_count);
+
 	/*
 	 * It is the last release_sock in its life. It will remove backlog.
 	 */
@@ -894,8 +900,9 @@ adjudge_to_death:
 	bh_lock_sock(sk);
 	BUG_TRAP(!sock_owned_by_user(sk));
 
-	sock_hold(sk);
-	sock_orphan(sk);
+	/* Have we already been destroyed by a softirq or backlog? */
+	if (state != DCCP_CLOSED && sk->sk_state == DCCP_CLOSED)
+		goto out;
 
 	/*
 	 * The last release_sock may have processed the CLOSE or RESET
@@ -915,12 +922,12 @@ adjudge_to_death:
 #endif
 	}
 
-	atomic_inc(sk->sk_prot->orphan_count);
 	if (sk->sk_state == DCCP_CLOSED)
 		inet_csk_destroy_sock(sk);
 
 	/* Otherwise, socket is reprieved until protocol close. */
 
+out:
 	bh_unlock_sock(sk);
 	local_bh_enable();
 	sock_put(sk);
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index 7c8692c26bfe5940f054927daf602799acc53212..66e230c3b3287072124fa52e16c2577bdde9c7a9 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -493,7 +493,6 @@ struct elist_cb_state {
 static void neigh_elist_cb(struct neighbour *neigh, void *_info)
 {
 	struct elist_cb_state *s = _info;
-	struct dn_dev *dn_db;
 	struct dn_neigh *dn;
 
 	if (neigh->dev != s->dev)
@@ -503,10 +502,6 @@ static void neigh_elist_cb(struct neighbour *neigh, void *_info)
 	if (!(dn->flags & (DN_NDFLAG_R1|DN_NDFLAG_R2)))
 		return;
 
-	dn_db = (struct dn_dev *) s->dev->dn_ptr;
-	if (dn_db->parms.forwarding == 1 && (dn->flags & DN_NDFLAG_R2))
-		return;
-
 	if (s->t == s->n)
 		s->rs = dn_find_slot(s->ptr, s->n, dn->priority);
 	else
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
index ea9f5aacce85fc4547eba87b5c1e1b8e68130b29..d4c79ce16871447ef17f411c7feae1ffbc227d59 100644
--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
+++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c
@@ -51,11 +51,12 @@ ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211soft
 	spin_lock_irqsave(&mac->lock, flags);
 	mac->associnfo.associating = 1;
 	mac->associated = 0; /* just to make sure */
-	spin_unlock_irqrestore(&mac->lock, flags);
 
 	/* Set a timer for timeout */
 	/* FIXME: make timeout configurable */
-	schedule_delayed_work(&mac->associnfo.timeout, 5 * HZ);
+	if (likely(mac->running))
+		schedule_delayed_work(&mac->associnfo.timeout, 5 * HZ);
+	spin_unlock_irqrestore(&mac->lock, flags);
 }
 
 void
@@ -319,6 +320,9 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev,
 	u16 status = le16_to_cpup(&resp->status);
 	struct ieee80211softmac_network *network = NULL;
 	unsigned long flags;
+
+	if (unlikely(!mac->running))
+		return -ENODEV;
 	
 	spin_lock_irqsave(&mac->lock, flags);
 
@@ -377,10 +381,16 @@ ieee80211softmac_handle_disassoc(struct net_device * dev,
 {
 	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
 	unsigned long flags;
+
+	if (unlikely(!mac->running))
+		return -ENODEV;
+
 	if (memcmp(disassoc->header.addr2, mac->associnfo.bssid, ETH_ALEN))
 		return 0;
+
 	if (memcmp(disassoc->header.addr1, mac->dev->dev_addr, ETH_ALEN))
 		return 0;
+
 	dprintk(KERN_INFO PFX "got disassoc frame\n");
 	netif_carrier_off(dev);
 	spin_lock_irqsave(&mac->lock, flags);
@@ -400,6 +410,9 @@ ieee80211softmac_handle_reassoc_req(struct net_device * dev,
 	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
 	struct ieee80211softmac_network *network;
 
+	if (unlikely(!mac->running))
+		return -ENODEV;
+
 	network = ieee80211softmac_get_network_by_bssid(mac, resp->header.addr3);
 	if (!network) {
 		dprintkl(KERN_INFO PFX "reassoc request from unknown network\n");
diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c
index 9a0eac6c61eb2f307a9a36198848bfec46f2d3c9..06e332624665e8d456c505a376788993451d4ccb 100644
--- a/net/ieee80211/softmac/ieee80211softmac_auth.c
+++ b/net/ieee80211/softmac/ieee80211softmac_auth.c
@@ -86,6 +86,11 @@ ieee80211softmac_auth_queue(void *data)
 		
 		/* Lock and set flags */
 		spin_lock_irqsave(&mac->lock, flags);
+		if (unlikely(!mac->running)) {
+			/* Prevent reschedule on workqueue flush */
+			spin_unlock_irqrestore(&mac->lock, flags);
+			return;
+		}
 		net->authenticated = 0;
 		net->authenticating = 1;
 		/* add a timeout call so we eventually give up waiting for an auth reply */
@@ -124,6 +129,9 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
 	unsigned long flags;
 	u8 * data;
 	
+	if (unlikely(!mac->running))
+		return -ENODEV;
+
 	/* Find correct auth queue item */
 	spin_lock_irqsave(&mac->lock, flags);
 	list_for_each(list_ptr, &mac->auth_queue) {
@@ -298,8 +306,6 @@ ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac,
 	
 	/* can't transmit data right now... */
 	netif_carrier_off(mac->dev);
-	/* let's try to re-associate */
-	schedule_work(&mac->associnfo.work);
 	spin_unlock_irqrestore(&mac->lock, flags);
 }
 
@@ -338,6 +344,9 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de
 	struct ieee80211softmac_network *net = NULL;
 	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
 	
+	if (unlikely(!mac->running))
+		return -ENODEV;
+
 	if (!deauth) {
 		dprintk("deauth without deauth packet. eek!\n");
 		return 0;
@@ -360,5 +369,8 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de
 	}
 
 	ieee80211softmac_deauth_from_net(mac, net);
+
+	/* let's try to re-associate */
+	schedule_work(&mac->associnfo.work);
 	return 0;
 }
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c
index be83bdc1644a54e35b64a0ad21a5e1e23208f71a..6252be2c0db9af8a60e35e503e94a2bab0e482f2 100644
--- a/net/ieee80211/softmac/ieee80211softmac_module.c
+++ b/net/ieee80211/softmac/ieee80211softmac_module.c
@@ -89,6 +89,8 @@ ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm)
 	ieee80211softmac_wait_for_scan(sm);
 	
 	spin_lock_irqsave(&sm->lock, flags);
+	sm->running = 0;
+
 	/* Free all pending assoc work items */
 	cancel_delayed_work(&sm->associnfo.work);
 	
@@ -204,6 +206,8 @@ void ieee80211softmac_start(struct net_device *dev)
 		assert(0);
 	if (mac->txrates_change)
 		mac->txrates_change(dev, change, &oldrates);
+
+	mac->running = 1;
 }
 EXPORT_SYMBOL_GPL(ieee80211softmac_start);
 
diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c
index 2b9e7edfa3ce4719d5783bd1b822bd825c763cce..d31cf77498c4a38ccd768303802b5805e16615a1 100644
--- a/net/ieee80211/softmac/ieee80211softmac_scan.c
+++ b/net/ieee80211/softmac/ieee80211softmac_scan.c
@@ -115,7 +115,15 @@ void ieee80211softmac_scan(void *d)
 			// TODO: is this if correct, or should we do this only if scanning from assoc request?
 			if (sm->associnfo.req_essid.len)
 				ieee80211softmac_send_mgt_frame(sm, &sm->associnfo.req_essid, IEEE80211_STYPE_PROBE_REQ, 0);
+
+			spin_lock_irqsave(&sm->lock, flags);
+			if (unlikely(!sm->running)) {
+				/* Prevent reschedule on workqueue flush */
+				spin_unlock_irqrestore(&sm->lock, flags);
+				break;
+			}
 			schedule_delayed_work(&si->softmac_scan, IEEE80211SOFTMAC_PROBE_DELAY);
+			spin_unlock_irqrestore(&sm->lock, flags);
 			return;
 		} else {
 			dprintk(PFX "Not probing Channel %d (not allowed here)\n", si->channels[current_channel_idx].channel);
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 18d7fad474d72510e18177837912e5ff26ea4acb..c9026dbf4c9342cca958490aed1dec45aa36abfa 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -337,7 +337,7 @@ static inline int ip_rcv_finish(struct sk_buff *skb)
 	 *	Initialise the virtual path cache for the packet. It describes
 	 *	how the packet travels inside Linux networking.
 	 */ 
-	if (likely(skb->dst == NULL)) {
+	if (skb->dst == NULL) {
 		int err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos,
 					 skb->dev);
 		if (unlikely(err)) {
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
index 9bebad07bf2ec4baea772a654e7d37808504928c..cbcae6544622932cbb7f0a57d648338bd699ceb9 100644
--- a/net/ipv4/ip_options.c
+++ b/net/ipv4/ip_options.c
@@ -209,7 +209,7 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb)
 
 void ip_options_fragment(struct sk_buff * skb) 
 {
-	unsigned char * optptr = skb->nh.raw;
+	unsigned char * optptr = skb->nh.raw + sizeof(struct iphdr);
 	struct ip_options * opt = &(IPCB(skb)->opt);
 	int  l = opt->optlen;
 	int  optlen;
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index c2d92f99a2b8b0b18bc1f17e1ec742a2c6051de5..d0d19192026d9eb2327cf68a47a4ba1b23dc7fe5 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -948,7 +948,7 @@ static int do_add_counters(void __user *user, unsigned int len)
 
 	write_lock_bh(&t->lock);
 	private = t->private;
-	if (private->number != paddc->num_counters) {
+	if (private->number != tmp.num_counters) {
 		ret = -EINVAL;
 		goto unlock_up_free;
 	}
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
index 2c2fb700d835364e76f5f479bec02aacafa80074..518f581d39ece6058670ad9efda9df57d2191e68 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
@@ -162,6 +162,8 @@ static int get_tpkt_data(struct sk_buff **pskb, struct ip_conntrack *ct,
 
 	/* Validate TPKT length */
 	tpktlen = tpkt[2] * 256 + tpkt[3];
+	if (tpktlen < 4)
+		goto clear_out;
 	if (tpktlen > tcpdatalen) {
 		if (tcpdatalen == 4) {	/* Separate TPKT header */
 			/* Netmeeting sends TPKT header and data separately */
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
index 48078002e45075292624ea748bc2386b8e841728..355a53a5b6cddf81c5fa42257b3d6a611ab603d7 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
@@ -2,7 +2,7 @@
  * ip_conntrack_helper_h323_asn1.c - BER and PER decoding library for H.323
  * 			      	     conntrack/NAT module.
  *
- * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@hotmail.com>
+ * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@users.sourceforge.net>
  *
  * This source code is licensed under General Public License version 2.
  *
@@ -703,6 +703,10 @@ int decode_choice(bitstr_t * bs, field_t * f, char *base, int level)
 		type = get_bits(bs, f->sz);
 	}
 
+	/* Write Type */
+	if (base)
+		*(unsigned *) base = type;
+
 	/* Check Range */
 	if (type >= f->ub) {	/* Newer version? */
 		BYTE_ALIGN(bs);
@@ -712,10 +716,6 @@ int decode_choice(bitstr_t * bs, field_t * f, char *base, int level)
 		return H323_ERROR_NONE;
 	}
 
-	/* Write Type */
-	if (base)
-		*(unsigned *) base = type;
-
 	/* Transfer to son level */
 	son = &f->fields[type];
 	if (son->attr & STOP) {
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
index 5259abd0fb426bd6845c73dd27f7ecc0096837c1..0416073c5600c109c56d85d3a49359a829fbc4cb 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
@@ -235,12 +235,15 @@ static int do_basic_checks(struct ip_conntrack *conntrack,
 			flag = 1;
 		}
 
-		/* Cookie Ack/Echo chunks not the first OR 
-		   Init / Init Ack / Shutdown compl chunks not the only chunks */
-		if ((sch->type == SCTP_CID_COOKIE_ACK 
+		/*
+		 * Cookie Ack/Echo chunks not the first OR
+		 * Init / Init Ack / Shutdown compl chunks not the only chunks
+		 * OR zero-length.
+		 */
+		if (((sch->type == SCTP_CID_COOKIE_ACK
 			|| sch->type == SCTP_CID_COOKIE_ECHO
 			|| flag)
-		     && count !=0 ) {
+		      && count !=0) || !sch->length) {
 			DEBUGP("Basic checks failed\n");
 			return 1;
 		}
diff --git a/net/ipv4/netfilter/ip_nat_proto_gre.c b/net/ipv4/netfilter/ip_nat_proto_gre.c
index 6c4899d8046a5b3265555869e9c8528f3a5553c2..96ceabaec4027932854f46479b112d45a4ac53d6 100644
--- a/net/ipv4/netfilter/ip_nat_proto_gre.c
+++ b/net/ipv4/netfilter/ip_nat_proto_gre.c
@@ -49,15 +49,15 @@ gre_in_range(const struct ip_conntrack_tuple *tuple,
 	     const union ip_conntrack_manip_proto *min,
 	     const union ip_conntrack_manip_proto *max)
 {
-	u_int32_t key;
+	__be16 key;
 
 	if (maniptype == IP_NAT_MANIP_SRC)
 		key = tuple->src.u.gre.key;
 	else
 		key = tuple->dst.u.gre.key;
 
-	return ntohl(key) >= ntohl(min->gre.key)
-		&& ntohl(key) <= ntohl(max->gre.key);
+	return ntohs(key) >= ntohs(min->gre.key)
+		&& ntohs(key) <= ntohs(max->gre.key);
 }
 
 /* generate unique tuple ... */
@@ -81,14 +81,14 @@ gre_unique_tuple(struct ip_conntrack_tuple *tuple,
 		min = 1;
 		range_size = 0xffff;
 	} else {
-		min = ntohl(range->min.gre.key);
-		range_size = ntohl(range->max.gre.key) - min + 1;
+		min = ntohs(range->min.gre.key);
+		range_size = ntohs(range->max.gre.key) - min + 1;
 	}
 
 	DEBUGP("min = %u, range_size = %u\n", min, range_size); 
 
 	for (i = 0; i < range_size; i++, key++) {
-		*keyptr = htonl(min + key % range_size);
+		*keyptr = htons(min + key % range_size);
 		if (!ip_nat_used_tuple(tuple, conntrack))
 			return 1;
 	}
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 8f760b28617e8c5b62f456c77e92f5032a264599..67e676783da9bd9cdf46fea59fcc287d5f9cf277 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -219,8 +219,10 @@ ip_nat_out(unsigned int hooknum,
 	   const struct net_device *out,
 	   int (*okfn)(struct sk_buff *))
 {
+#ifdef CONFIG_XFRM
 	struct ip_conntrack *ct;
 	enum ip_conntrack_info ctinfo;
+#endif
 	unsigned int ret;
 
 	/* root is playing with raw sockets. */
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 6d1c11563943f1cdfa35fcded77e30f5d0b14c02..cee3397ec27765dcdeab77890847ac59b2cb2434 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -1441,7 +1441,7 @@ static int compat_copy_entry_to_user(struct ipt_entry *e,
 	ret = -EFAULT;
 	origsize = *size;
 	ce = (struct compat_ipt_entry __user *)*dstptr;
-	if (__copy_to_user(ce, e, sizeof(struct ipt_entry)))
+	if (copy_to_user(ce, e, sizeof(struct ipt_entry)))
 		goto out;
 
 	*dstptr += sizeof(struct compat_ipt_entry);
@@ -1459,9 +1459,9 @@ static int compat_copy_entry_to_user(struct ipt_entry *e,
 		goto out;
 	ret = -EFAULT;
 	next_offset = e->next_offset - (origsize - *size);
-	if (__put_user(target_offset, &ce->target_offset))
+	if (put_user(target_offset, &ce->target_offset))
 		goto out;
-	if (__put_user(next_offset, &ce->next_offset))
+	if (put_user(next_offset, &ce->next_offset))
 		goto out;
 	return 0;
 out:
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index 39fd4c2a2386248421a74795665bd50dda749293..b98f7b08b084586478ec431ec83485aa6118ff8c 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -428,7 +428,7 @@ ipt_log_target(struct sk_buff **pskb,
 
 	if (loginfo->logflags & IPT_LOG_NFLOG)
 		nf_log_packet(PF_INET, hooknum, *pskb, in, out, &li,
-		              loginfo->prefix);
+		              "%s", loginfo->prefix);
 	else
 		ipt_log_packet(PF_INET, hooknum, *pskb, in, out, &li,
 		               loginfo->prefix);
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 1438432857021b1ebd09486362cd9243f5f9554e..b847ee409efbb7146987f526998ccb8ea51422fe 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -821,6 +821,7 @@ checkentry(const char *tablename,
 	/* Create our proc 'status' entry. */
 	curr_table->status_proc = create_proc_entry(curr_table->name, ip_list_perms, proc_net_ipt_recent);
 	if (!curr_table->status_proc) {
+		vfree(hold);
 		printk(KERN_INFO RECENT_NAME ": checkentry: unable to allocate for /proc entry.\n");
 		/* Destroy the created table */
 		spin_lock_bh(&recent_lock);
@@ -845,7 +846,6 @@ checkentry(const char *tablename,
 		spin_unlock_bh(&recent_lock);
 		vfree(curr_table->time_info);
 		vfree(curr_table->hash_table);
-		vfree(hold);
 		vfree(curr_table->table);
 		vfree(curr_table);
 		return 0;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 87f68e787d0c62d0d1fcd8ee53566c0a4a8467bd..e2b7b80550371dd836d3b32635c999b2a46f6fcc 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1468,6 +1468,7 @@ void tcp_close(struct sock *sk, long timeout)
 {
 	struct sk_buff *skb;
 	int data_was_unread = 0;
+	int state;
 
 	lock_sock(sk);
 	sk->sk_shutdown = SHUTDOWN_MASK;
@@ -1544,6 +1545,11 @@ void tcp_close(struct sock *sk, long timeout)
 	sk_stream_wait_close(sk, timeout);
 
 adjudge_to_death:
+	state = sk->sk_state;
+	sock_hold(sk);
+	sock_orphan(sk);
+	atomic_inc(sk->sk_prot->orphan_count);
+
 	/* It is the last release_sock in its life. It will remove backlog. */
 	release_sock(sk);
 
@@ -1555,8 +1561,9 @@ adjudge_to_death:
 	bh_lock_sock(sk);
 	BUG_TRAP(!sock_owned_by_user(sk));
 
-	sock_hold(sk);
-	sock_orphan(sk);
+	/* Have we already been destroyed by a softirq or backlog? */
+	if (state != TCP_CLOSE && sk->sk_state == TCP_CLOSE)
+		goto out;
 
 	/*	This is a (useful) BSD violating of the RFC. There is a
 	 *	problem with TCP as specified in that the other end could
@@ -1584,7 +1591,6 @@ adjudge_to_death:
 			if (tmo > TCP_TIMEWAIT_LEN) {
 				inet_csk_reset_keepalive_timer(sk, tcp_fin_time(sk));
 			} else {
-				atomic_inc(sk->sk_prot->orphan_count);
 				tcp_time_wait(sk, TCP_FIN_WAIT2, tmo);
 				goto out;
 			}
@@ -1603,7 +1609,6 @@ adjudge_to_death:
 			NET_INC_STATS_BH(LINUX_MIB_TCPABORTONMEMORY);
 		}
 	}
-	atomic_inc(sk->sk_prot->orphan_count);
 
 	if (sk->sk_state == TCP_CLOSE)
 		inet_csk_destroy_sock(sk);
diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c
index e0e9d1383c7c7e894a1019c3e2ce28785aea5dc4..b72fa55dfb84d114484bf6f7d1b4751449d9c4e3 100644
--- a/net/ipv4/tcp_highspeed.c
+++ b/net/ipv4/tcp_highspeed.c
@@ -137,8 +137,8 @@ static void hstcp_cong_avoid(struct sock *sk, u32 adk, u32 rtt,
 		if (tp->snd_cwnd < tp->snd_cwnd_clamp) {
 			tp->snd_cwnd_cnt += ca->ai;
 			if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
-				tp->snd_cwnd++;
 				tp->snd_cwnd_cnt -= tp->snd_cwnd;
+				tp->snd_cwnd++;
 			}
 		}
 	}
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 9f0cca4c4fae2021e52ee5655f9b89b9ade7f753..4a538bc1683d69827f46952a537841bb4360b58c 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1662,6 +1662,8 @@ static void tcp_update_scoreboard(struct sock *sk, struct tcp_sock *tp)
 			if (!(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) {
 				TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
 				tp->lost_out += tcp_skb_pcount(skb);
+				if (IsReno(tp))
+					tcp_remove_reno_sacks(sk, tp, tcp_skb_pcount(skb) + 1);
 
 				/* clear xmit_retrans hint */
 				if (tp->retransmit_skb_hint &&
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index f8f3a37a14948f4d291ba85cac267b33ebdf3079..eb2865d5ae286cdfffa2c098aa881c7c752b526e 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -173,6 +173,7 @@ int inet6_csk_xmit(struct sk_buff *skb, int ipfragok)
 
 		if (err) {
 			sk->sk_err_soft = -err;
+			kfree_skb(skb);
 			return err;
 		}
 
@@ -181,6 +182,7 @@ int inet6_csk_xmit(struct sk_buff *skb, int ipfragok)
 
 		if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
 			sk->sk_route_caps = 0;
+			kfree_skb(skb);
 			return err;
 		}
 
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 0a673038344fe30142e0d095f3f6bb5c6a8854a8..2e72f89a7019929f2da18cb74ef1ba26e9d1d74b 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1103,7 +1103,7 @@ do_add_counters(void __user *user, unsigned int len)
 
 	write_lock_bh(&t->lock);
 	private = t->private;
-	if (private->number != paddc->num_counters) {
+	if (private->number != tmp.num_counters) {
 		ret = -EINVAL;
 		goto unlock_up_free;
 	}
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index a96c0de14b00ed963b52a221cbaca428b46f483b..73c6300109d61d7243e89f5268d3d9fbe3ec3e30 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -439,7 +439,7 @@ ip6t_log_target(struct sk_buff **pskb,
 
 	if (loginfo->logflags & IP6T_LOG_NFLOG)
 		nf_log_packet(PF_INET6, hooknum, *pskb, in, out, &li,
-		              loginfo->prefix);
+		              "%s", loginfo->prefix);
 	else
 		ip6t_log_packet(PF_INET6, hooknum, *pskb, in, out, &li,
 		                loginfo->prefix);
diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c
index 94dbdb8b458d01fa1dc85cd42da93e5d84b85024..4f6b84c8f4ab6567cc70301d7bdcc2460eabb38a 100644
--- a/net/ipv6/netfilter/ip6t_eui64.c
+++ b/net/ipv6/netfilter/ip6t_eui64.c
@@ -40,7 +40,7 @@ match(const struct sk_buff *skb,
 
 	memset(eui64, 0, sizeof(eui64));
 
-	if (eth_hdr(skb)->h_proto == ntohs(ETH_P_IPV6)) {
+	if (eth_hdr(skb)->h_proto == htons(ETH_P_IPV6)) {
 		if (skb->nh.ipv6h->version == 0x6) {
 			memcpy(eui64, eth_hdr(skb)->h_source, 3);
 			memcpy(eui64 + 5, eth_hdr(skb)->h_source + 3, 3);
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 2dbf134d5266068e633896e909a71d2f5572c8b4..811d998725bc6728bec208ad90ef81157f8235a0 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -944,9 +944,9 @@ out:
 	return rc;
 }
 
-static int ipx_map_frame_type(unsigned char type)
+static __be16 ipx_map_frame_type(unsigned char type)
 {
-	int rc = 0;
+	__be16 rc = 0;
 
 	switch (type) {
 	case IPX_FRAME_ETHERII:	rc = htons(ETH_P_IPX);		break;
diff --git a/net/ipx/ipx_route.c b/net/ipx/ipx_route.c
index 67774448efd966eb801dc822d0788e09a530be54..a394c6fe19a26839e07dbed3f7015224d03c1161 100644
--- a/net/ipx/ipx_route.c
+++ b/net/ipx/ipx_route.c
@@ -119,7 +119,7 @@ out:
 	return rc;
 }
 
-static int ipxrtr_delete(long net)
+static int ipxrtr_delete(__u32 net)
 {
 	struct ipx_route *r, *tmp;
 	int rc;
diff --git a/net/irda/irias_object.c b/net/irda/irias_object.c
index c6d169fbdceb7f16521a797a029f7ea33f95af1f..82e665c7999183b6300283370a1b463865bc5c7d 100644
--- a/net/irda/irias_object.c
+++ b/net/irda/irias_object.c
@@ -257,7 +257,6 @@ struct ias_attrib *irias_find_attrib(struct ias_object *obj, char *name)
 	/* Unsafe (locking), attrib might change */
 	return attrib;
 }
-EXPORT_SYMBOL(irias_find_attrib);
 
 /*
  * Function irias_add_attribute (obj, attrib)
@@ -484,7 +483,6 @@ struct ias_value *irias_new_string_value(char *string)
 
 	return value;
 }
-EXPORT_SYMBOL(irias_new_string_value);
 
 /*
  * Function irias_new_octseq_value (octets, len)
@@ -519,7 +517,6 @@ struct ias_value *irias_new_octseq_value(__u8 *octseq , int len)
 	memcpy(value->t.oct_seq, octseq , len);
 	return value;
 }
-EXPORT_SYMBOL(irias_new_octseq_value);
 
 struct ias_value *irias_new_missing_value(void)
 {
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index 9cccc325b687839b57111670d0a4479a35f36709..0c6da496cfa9fc5311115b81b26b1b8176fcaa9d 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -240,12 +240,15 @@ static int do_basic_checks(struct nf_conn *conntrack,
 			flag = 1;
 		}
 
-		/* Cookie Ack/Echo chunks not the first OR 
-		   Init / Init Ack / Shutdown compl chunks not the only chunks */
-		if ((sch->type == SCTP_CID_COOKIE_ACK 
+		/*
+		 * Cookie Ack/Echo chunks not the first OR
+		 * Init / Init Ack / Shutdown compl chunks not the only chunks
+		 * OR zero-length.
+		 */
+		if (((sch->type == SCTP_CID_COOKIE_ACK
 			|| sch->type == SCTP_CID_COOKIE_ECHO
 			|| flag)
-		     && count !=0 ) {
+		      && count !=0) || !sch->length) {
 			DEBUGP("Basic checks failed\n");
 			return 1;
 		}
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index c60273cad778ed1c3cdc7eda166aafc6b21d9802..61cdda4e5d3ba8b25f02af19a7bbb634fc9a0d84 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -321,7 +321,7 @@ static int
 nfulnl_set_flags(struct nfulnl_instance *inst, u_int16_t flags)
 {
 	spin_lock_bh(&inst->lock);
-	inst->flags = ntohs(flags);
+	inst->flags = flags;
 	spin_unlock_bh(&inst->lock);
 
 	return 0;
@@ -902,7 +902,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
 	if (nfula[NFULA_CFG_FLAGS-1]) {
 		u_int16_t flags =
 			*(u_int16_t *)NFA_DATA(nfula[NFULA_CFG_FLAGS-1]);
-		nfulnl_set_flags(inst, ntohl(flags));
+		nfulnl_set_flags(inst, ntohs(flags));
 	}
 
 out_put:
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 17abf60f957003f3e9f3df5904f6255c8995e93b..99293c63ff7348c71c38c9eaf3a3406876a0a3f3 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -289,7 +289,7 @@ int xt_compat_match(void *match, void **dstptr, int *size, int convert)
 		case COMPAT_TO_USER:
 			pm = (struct xt_entry_match *)match;
 			msize = pm->u.user.match_size;
-			if (__copy_to_user(*dstptr, pm, msize)) {
+			if (copy_to_user(*dstptr, pm, msize)) {
 				ret = -EFAULT;
 				break;
 			}
@@ -366,7 +366,7 @@ int xt_compat_target(void *target, void **dstptr, int *size, int convert)
 		case COMPAT_TO_USER:
 			pt = (struct xt_entry_target *)target;
 			tsize = pt->u.user.target_size;
-			if (__copy_to_user(*dstptr, pt, tsize)) {
+			if (copy_to_user(*dstptr, pt, tsize)) {
 				ret = -EFAULT;
 				break;
 			}
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index d44981f5a6195b4a017552b16e5a4ca82db98c88..3669cb953e6e7d49c05eb82c39ba1d43e80f9e3d 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -425,11 +425,16 @@ static int nr_create(struct socket *sock, int protocol)
 
 	nr_init_timers(sk);
 
-	nr->t1     = sysctl_netrom_transport_timeout;
-	nr->t2     = sysctl_netrom_transport_acknowledge_delay;
-	nr->n2     = sysctl_netrom_transport_maximum_tries;
-	nr->t4     = sysctl_netrom_transport_busy_delay;
-	nr->idle   = sysctl_netrom_transport_no_activity_timeout;
+	nr->t1     =
+		msecs_to_jiffies(sysctl_netrom_transport_timeout);
+	nr->t2     =
+		msecs_to_jiffies(sysctl_netrom_transport_acknowledge_delay);
+	nr->n2     =
+		msecs_to_jiffies(sysctl_netrom_transport_maximum_tries);
+	nr->t4     =
+		msecs_to_jiffies(sysctl_netrom_transport_busy_delay);
+	nr->idle   =
+		msecs_to_jiffies(sysctl_netrom_transport_no_activity_timeout);
 	nr->window = sysctl_netrom_transport_requested_window_size;
 
 	nr->bpqext = 1;
@@ -1365,8 +1370,6 @@ static struct notifier_block nr_dev_notifier = {
 
 static struct net_device **dev_nr;
 
-static char banner[] __initdata = KERN_INFO "G4KLX NET/ROM for Linux. Version 0.7 for AX25.037 Linux 2.4\n";
-
 static int __init nr_proto_init(void)
 {
 	int i;
@@ -1414,7 +1417,6 @@ static int __init nr_proto_init(void)
 	}
 		
 	register_netdevice_notifier(&nr_dev_notifier);
-	printk(banner);
 
 	ax25_protocol_register(AX25_P_NETROM, nr_route_frame);
 	ax25_linkfail_register(nr_link_failed);
diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c
index 509afddae5694a4aae228127c2e379f618bdd40a..621e5586ab030c93d2f30aea69b39c4d8624b70c 100644
--- a/net/netrom/nr_dev.c
+++ b/net/netrom/nr_dev.c
@@ -185,7 +185,6 @@ static struct net_device_stats *nr_get_stats(struct net_device *dev)
 
 void nr_setup(struct net_device *dev)
 {
-	SET_MODULE_OWNER(dev);
 	dev->mtu		= NR_MAX_PACKET_SIZE;
 	dev->hard_start_xmit	= nr_xmit;
 	dev->open		= nr_open;
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index ea65396d1619a5344b6b1c742dd4575dbf8a0088..55564efccf1153fc051df3e8b9b26a7d515fa32c 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -518,11 +518,11 @@ static int rose_create(struct socket *sock, int protocol)
 	init_timer(&rose->timer);
 	init_timer(&rose->idletimer);
 
-	rose->t1   = sysctl_rose_call_request_timeout;
-	rose->t2   = sysctl_rose_reset_request_timeout;
-	rose->t3   = sysctl_rose_clear_request_timeout;
-	rose->hb   = sysctl_rose_ack_hold_back_timeout;
-	rose->idle = sysctl_rose_no_activity_timeout;
+	rose->t1   = msecs_to_jiffies(sysctl_rose_call_request_timeout);
+	rose->t2   = msecs_to_jiffies(sysctl_rose_reset_request_timeout);
+	rose->t3   = msecs_to_jiffies(sysctl_rose_clear_request_timeout);
+	rose->hb   = msecs_to_jiffies(sysctl_rose_ack_hold_back_timeout);
+	rose->idle = msecs_to_jiffies(sysctl_rose_no_activity_timeout);
 
 	rose->state = ROSE_STATE_0;
 
@@ -1469,8 +1469,6 @@ static struct notifier_block rose_dev_notifier = {
 
 static struct net_device **dev_rose;
 
-static const char banner[] = KERN_INFO "F6FBB/G4KLX ROSE for Linux. Version 0.62 for AX25.037 Linux 2.4\n";
-
 static int __init rose_proto_init(void)
 {
 	int i;
@@ -1519,7 +1517,6 @@ static int __init rose_proto_init(void)
 
 	sock_register(&rose_family_ops);
 	register_netdevice_notifier(&rose_dev_notifier);
-	printk(banner);
 
 	ax25_protocol_register(AX25_P_ROSE, rose_route_frame);
 	ax25_linkfail_register(rose_link_failed);
diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c
index d297af737d1023a41c88f028a8628d91e52bc3eb..2a1bf8e119e52c4c45904bd8a47bd4d132195081 100644
--- a/net/rose/rose_dev.c
+++ b/net/rose/rose_dev.c
@@ -135,7 +135,6 @@ static struct net_device_stats *rose_get_stats(struct net_device *dev)
 
 void rose_setup(struct net_device *dev)
 {
-	SET_MODULE_OWNER(dev);
 	dev->mtu		= ROSE_MAX_PACKET_SIZE - 2;
 	dev->hard_start_xmit	= rose_xmit;
 	dev->open		= rose_open;
diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c
index 09e9e9d04d92a9a8b0198e6b5cef4c66d845c26c..bd86a63960ce3114ad4c6c3ae8a90804d6b66d66 100644
--- a/net/rose/rose_link.c
+++ b/net/rose/rose_link.c
@@ -40,7 +40,8 @@ void rose_start_ftimer(struct rose_neigh *neigh)
 
 	neigh->ftimer.data     = (unsigned long)neigh;
 	neigh->ftimer.function = &rose_ftimer_expiry;
-	neigh->ftimer.expires  = jiffies + sysctl_rose_link_fail_timeout;
+	neigh->ftimer.expires  =
+		jiffies + msecs_to_jiffies(sysctl_rose_link_fail_timeout);
 
 	add_timer(&neigh->ftimer);
 }
@@ -51,7 +52,8 @@ static void rose_start_t0timer(struct rose_neigh *neigh)
 
 	neigh->t0timer.data     = (unsigned long)neigh;
 	neigh->t0timer.function = &rose_t0timer_expiry;
-	neigh->t0timer.expires  = jiffies + sysctl_rose_restart_request_timeout;
+	neigh->t0timer.expires  =
+		jiffies + msecs_to_jiffies(sysctl_rose_restart_request_timeout);
 
 	add_timer(&neigh->t0timer);
 }
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index 8631b65a7312c830d35e4d843163024432bac54e..a22542fa1bc848cedef82a914a49f40ededae771 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -48,8 +48,6 @@ static DEFINE_SPINLOCK(rose_route_list_lock);
 
 struct rose_neigh *rose_loopback_neigh;
 
-static void rose_remove_neigh(struct rose_neigh *);
-
 /*
  *	Add a new route to a node, and in the process add the node and the
  *	neighbour if it is new.
@@ -235,11 +233,8 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh)
 
 	skb_queue_purge(&rose_neigh->queue);
 
-	spin_lock_bh(&rose_neigh_list_lock);
-
 	if ((s = rose_neigh_list) == rose_neigh) {
 		rose_neigh_list = rose_neigh->next;
-		spin_unlock_bh(&rose_neigh_list_lock);
 		kfree(rose_neigh->digipeat);
 		kfree(rose_neigh);
 		return;
@@ -248,7 +243,6 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh)
 	while (s != NULL && s->next != NULL) {
 		if (s->next == rose_neigh) {
 			s->next = rose_neigh->next;
-			spin_unlock_bh(&rose_neigh_list_lock);
 			kfree(rose_neigh->digipeat);
 			kfree(rose_neigh);
 			return;
@@ -256,7 +250,6 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh)
 
 		s = s->next;
 	}
-	spin_unlock_bh(&rose_neigh_list_lock);
 }
 
 /*
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 31eb83717c267a799b013f073cfe3e99301709d9..138ea92ed268457b99d9c6b44a1a9580cc7c016a 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -193,8 +193,10 @@ static void dev_watchdog(unsigned long arg)
 		    netif_running(dev) &&
 		    netif_carrier_ok(dev)) {
 			if (netif_queue_stopped(dev) &&
-			    (jiffies - dev->trans_start) > dev->watchdog_timeo) {
-				printk(KERN_INFO "NETDEV WATCHDOG: %s: transmit timed out\n", dev->name);
+			    time_after(jiffies, dev->trans_start + dev->watchdog_timeo)) {
+
+				printk(KERN_INFO "NETDEV WATCHDOG: %s: transmit timed out\n",
+				       dev->name);
 				dev->tx_timeout(dev);
 			}
 			if (!mod_timer(&dev->watchdog_timer, jiffies + dev->watchdog_timeo))
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 91132f6871d76ee42fa4e9dc53fcf643b32b779d..f1c7bd29f2cdc3932941c86e529426923484dee1 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -974,10 +974,10 @@ hfsc_adjust_levels(struct hfsc_class *cl)
 	do {
 		level = 0;
 		list_for_each_entry(p, &cl->children, siblings) {
-			if (p->level > level)
-				level = p->level;
+			if (p->level >= level)
+				level = p->level + 1;
 		}
-		cl->level = level + 1;
+		cl->level = level;
 	} while ((cl = cl->cl_parent) != NULL);
 }
 
diff --git a/net/sctp/input.c b/net/sctp/input.c
index d117ebc75cf87ce25aa8699f61b4338b12fc1053..1662f9cc869e0a1cd463b7f3575c0c243dfc4ded 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -73,6 +73,8 @@ static struct sctp_association *__sctp_lookup_association(
 					const union sctp_addr *peer,
 					struct sctp_transport **pt);
 
+static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb);
+
 
 /* Calculate the SCTP checksum of an SCTP packet.  */
 static inline int sctp_rcv_checksum(struct sk_buff *skb)
@@ -186,7 +188,6 @@ int sctp_rcv(struct sk_buff *skb)
 	 */
 	if (sk->sk_bound_dev_if && (sk->sk_bound_dev_if != af->skb_iif(skb)))
 	{
-		sock_put(sk);
 		if (asoc) {
 			sctp_association_put(asoc);
 			asoc = NULL;
@@ -197,7 +198,6 @@ int sctp_rcv(struct sk_buff *skb)
 		sk = sctp_get_ctl_sock();
 		ep = sctp_sk(sk)->ep;
 		sctp_endpoint_hold(ep);
-		sock_hold(sk);
 		rcvr = &ep->base;
 	}
 
@@ -253,25 +253,18 @@ int sctp_rcv(struct sk_buff *skb)
 	 */
 	sctp_bh_lock_sock(sk);
 
-	/* It is possible that the association could have moved to a different
-	 * socket if it is peeled off. If so, update the sk.
-	 */ 
-	if (sk != rcvr->sk) {
-		sctp_bh_lock_sock(rcvr->sk);
-		sctp_bh_unlock_sock(sk);
-		sk = rcvr->sk;
-	}
-
 	if (sock_owned_by_user(sk))
-		sk_add_backlog(sk, skb);
+		sctp_add_backlog(sk, skb);
 	else
-		sctp_backlog_rcv(sk, skb);
+		sctp_inq_push(&chunk->rcvr->inqueue, chunk);
 
-	/* Release the sock and the sock ref we took in the lookup calls.
-	 * The asoc/ep ref will be released in sctp_backlog_rcv.
-	 */
 	sctp_bh_unlock_sock(sk);
-	sock_put(sk);
+
+	/* Release the asoc/ep ref we took in the lookup calls. */
+	if (asoc)
+		sctp_association_put(asoc);
+	else
+		sctp_endpoint_put(ep);
 
 	return 0;
 
@@ -280,8 +273,7 @@ discard_it:
 	return 0;
 
 discard_release:
-	/* Release any structures we may be holding. */
-	sock_put(sk);
+	/* Release the asoc/ep ref we took in the lookup calls. */
 	if (asoc)
 		sctp_association_put(asoc);
 	else
@@ -290,56 +282,87 @@ discard_release:
 	goto discard_it;
 }
 
-/* Handle second half of inbound skb processing.  If the sock was busy,
- * we may have need to delay processing until later when the sock is
- * released (on the backlog).   If not busy, we call this routine
- * directly from the bottom half.
+/* Process the backlog queue of the socket.  Every skb on
+ * the backlog holds a ref on an association or endpoint.
+ * We hold this ref throughout the state machine to make
+ * sure that the structure we need is still around.
  */
 int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 {
 	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
- 	struct sctp_inq *inqueue = NULL;
+ 	struct sctp_inq *inqueue = &chunk->rcvr->inqueue;
  	struct sctp_ep_common *rcvr = NULL;
+	int backloged = 0;
 
  	rcvr = chunk->rcvr;
 
-	BUG_TRAP(rcvr->sk == sk);
-
- 	if (rcvr->dead) {
- 		sctp_chunk_free(chunk);
- 	} else {
- 		inqueue = &chunk->rcvr->inqueue;
- 		sctp_inq_push(inqueue, chunk);
- 	}
-
-	/* Release the asoc/ep ref we took in the lookup calls in sctp_rcv. */ 
- 	if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type)
- 		sctp_association_put(sctp_assoc(rcvr));
- 	else
- 		sctp_endpoint_put(sctp_ep(rcvr));
-  
+	/* If the rcvr is dead then the association or endpoint
+	 * has been deleted and we can safely drop the chunk
+	 * and refs that we are holding.
+	 */
+	if (rcvr->dead) {
+		sctp_chunk_free(chunk);
+		goto done;
+	}
+
+	if (unlikely(rcvr->sk != sk)) {
+		/* In this case, the association moved from one socket to
+		 * another.  We are currently sitting on the backlog of the
+		 * old socket, so we need to move.
+		 * However, since we are here in the process context we
+		 * need to take make sure that the user doesn't own
+		 * the new socket when we process the packet.
+		 * If the new socket is user-owned, queue the chunk to the
+		 * backlog of the new socket without dropping any refs.
+		 * Otherwise, we can safely push the chunk on the inqueue.
+		 */
+
+		sk = rcvr->sk;
+		sctp_bh_lock_sock(sk);
+
+		if (sock_owned_by_user(sk)) {
+			sk_add_backlog(sk, skb);
+			backloged = 1;
+		} else
+			sctp_inq_push(inqueue, chunk);
+
+		sctp_bh_unlock_sock(sk);
+
+		/* If the chunk was backloged again, don't drop refs */
+		if (backloged)
+			return 0;
+	} else {
+		sctp_inq_push(inqueue, chunk);
+	}
+
+done:
+	/* Release the refs we took in sctp_add_backlog */
+	if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type)
+		sctp_association_put(sctp_assoc(rcvr));
+	else if (SCTP_EP_TYPE_SOCKET == rcvr->type)
+		sctp_endpoint_put(sctp_ep(rcvr));
+	else
+		BUG();
+
         return 0;
 }
 
-void sctp_backlog_migrate(struct sctp_association *assoc, 
-			  struct sock *oldsk, struct sock *newsk)
+static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
 {
-	struct sk_buff *skb;
-	struct sctp_chunk *chunk;
+	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
+	struct sctp_ep_common *rcvr = chunk->rcvr;
 
-	skb = oldsk->sk_backlog.head;
-	oldsk->sk_backlog.head = oldsk->sk_backlog.tail = NULL;
-	while (skb != NULL) {
-		struct sk_buff *next = skb->next;
-
-		chunk = SCTP_INPUT_CB(skb)->chunk;
-		skb->next = NULL;
-		if (&assoc->base == chunk->rcvr)
-			sk_add_backlog(newsk, skb);
-		else
-			sk_add_backlog(oldsk, skb);
-		skb = next;
-	}
+	/* Hold the assoc/ep while hanging on the backlog queue.
+	 * This way, we know structures we need will not disappear from us
+	 */
+	if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type)
+		sctp_association_hold(sctp_assoc(rcvr));
+	else if (SCTP_EP_TYPE_SOCKET == rcvr->type)
+		sctp_endpoint_hold(sctp_ep(rcvr));
+	else
+		BUG();
+
+	sk_add_backlog(sk, skb);
 }
 
 /* Handle icmp frag needed error. */
@@ -412,7 +435,7 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb,
 	union sctp_addr daddr;
 	struct sctp_af *af;
 	struct sock *sk = NULL;
-	struct sctp_association *asoc = NULL;
+	struct sctp_association *asoc;
 	struct sctp_transport *transport = NULL;
 
 	*app = NULL; *tpp = NULL;
@@ -453,7 +476,6 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb,
 	return sk;
 
 out:
-	sock_put(sk);
 	if (asoc)
 		sctp_association_put(asoc);
 	return NULL;
@@ -463,7 +485,6 @@ out:
 void sctp_err_finish(struct sock *sk, struct sctp_association *asoc)
 {
 	sctp_bh_unlock_sock(sk);
-	sock_put(sk);
 	if (asoc)
 		sctp_association_put(asoc);
 }
@@ -490,7 +511,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
 	int type = skb->h.icmph->type;
 	int code = skb->h.icmph->code;
 	struct sock *sk;
-	struct sctp_association *asoc;
+	struct sctp_association *asoc = NULL;
 	struct sctp_transport *transport;
 	struct inet_sock *inet;
 	char *saveip, *savesctp;
@@ -716,7 +737,6 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *l
 
 hit:
 	sctp_endpoint_hold(ep);
-	sock_hold(epb->sk);
 	read_unlock(&head->lock);
 	return ep;
 }
@@ -818,7 +838,6 @@ static struct sctp_association *__sctp_lookup_association(
 hit:
 	*pt = transport;
 	sctp_association_hold(asoc);
-	sock_hold(epb->sk);
 	read_unlock(&head->lock);
 	return asoc;
 }
@@ -846,7 +865,6 @@ int sctp_has_association(const union sctp_addr *laddr,
 	struct sctp_transport *transport;
 
 	if ((asoc = sctp_lookup_association(laddr, paddr, &transport))) {
-		sock_put(asoc->base.sk);
 		sctp_association_put(asoc);
 		return 1;
 	}
diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c
index 297b8951463e80293da9a029384607e5f094c121..cf0c767d43ae34835c5dd4ccca70e3629fcdd182 100644
--- a/net/sctp/inqueue.c
+++ b/net/sctp/inqueue.c
@@ -149,6 +149,7 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue)
 		/* This is the first chunk in the packet.  */
 		chunk->singleton = 1;
 		ch = (sctp_chunkhdr_t *) chunk->skb->data;
+		chunk->data_accepted = 0;
 	}
 
         chunk->chunk_hdr = ch;
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 8d1dc24bab4c1f1da541c760e13955ca54b77d29..c5beb2ad7ef7a442798a669faea2c393d5f422f8 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -498,10 +498,6 @@ static void sctp_cmd_assoc_failed(sctp_cmd_seq_t *commands,
 	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
 			SCTP_STATE(SCTP_STATE_CLOSED));
 
-	/* Set sk_err to ECONNRESET on a 1-1 style socket. */
-	if (!sctp_style(asoc->base.sk, UDP))
-		asoc->base.sk->sk_err = ECONNRESET; 
-
 	/* SEND_FAILED sent later when cleaning up the association. */
 	asoc->outqueue.error = error;
 	sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
@@ -838,6 +834,15 @@ static void sctp_cmd_del_non_primary(struct sctp_association *asoc)
 	return;
 }
 
+/* Helper function to set sk_err on a 1-1 style socket. */
+static void sctp_cmd_set_sk_err(struct sctp_association *asoc, int error)
+{
+	struct sock *sk = asoc->base.sk;
+
+	if (!sctp_style(sk, UDP))
+		sk->sk_err = error;
+}
+
 /* These three macros allow us to pull the debugging code out of the
  * main flow of sctp_do_sm() to keep attention focused on the real
  * functionality there.
@@ -1458,6 +1463,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
 			local_cork = 0;
 			asoc->peer.retran_path = t;
 			break;
+		case SCTP_CMD_SET_SK_ERR:
+			sctp_cmd_set_sk_err(asoc, cmd->obj.error);
+			break;
 		default:
 			printk(KERN_WARNING "Impossible command: %u, %p\n",
 			       cmd->verb, cmd->obj.ptr);
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 2b9a832b29a70bdbb46d0ce401d680c9a0121654..8bc279219a72ca3b8e4e107eaeba562e87a79e4a 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -93,7 +93,7 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
 static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk);
 
 static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
-					   __u16 error,
+					   __u16 error, int sk_err,
 					   const struct sctp_association *asoc,
 					   struct sctp_transport *transport);
 
@@ -448,7 +448,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
 	__u32 init_tag;
 	struct sctp_chunk *err_chunk;
 	struct sctp_packet *packet;
-	sctp_disposition_t ret;
+	__u16 error;
 
 	if (!sctp_vtag_verify(chunk, asoc))
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -480,11 +480,9 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
 			goto nomem;
 
 		sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));
-		sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
-				SCTP_STATE(SCTP_STATE_CLOSED));
-		SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
-		sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
-		return SCTP_DISPOSITION_DELETE_TCB;
+		return sctp_stop_t1_and_abort(commands, SCTP_ERROR_INV_PARAM,
+					      ECONNREFUSED, asoc,
+					      chunk->transport);
 	}
 
 	/* Verify the INIT chunk before processing it. */
@@ -511,27 +509,16 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
 				sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
 						SCTP_PACKET(packet));
 				SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
-				sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
-						SCTP_STATE(SCTP_STATE_CLOSED));
-				sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB,
-						SCTP_NULL());
-				return SCTP_DISPOSITION_CONSUME;
+				error = SCTP_ERROR_INV_PARAM;
 			} else {
-				sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
-						SCTP_STATE(SCTP_STATE_CLOSED));
-				sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB,
-						SCTP_NULL());
-				return SCTP_DISPOSITION_NOMEM;
+				error = SCTP_ERROR_NO_RESOURCE;
 			}
 		} else {
-			ret = sctp_sf_tabort_8_4_8(ep, asoc, type, arg,
-						   commands);
-			sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
-					SCTP_STATE(SCTP_STATE_CLOSED));
-			sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB,
-					SCTP_NULL());
-			return ret;
+			sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
+			error = SCTP_ERROR_INV_PARAM;
 		}
+		return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED,
+						asoc, chunk->transport);
 	}
 
 	/* Tag the variable length parameters.  Note that we never
@@ -636,8 +623,9 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
 	 */
         chunk->subh.cookie_hdr =
 		(struct sctp_signed_cookie *)chunk->skb->data;
-	skb_pull(chunk->skb,
-		 ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t));
+	if (!pskb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) -
+					 sizeof(sctp_chunkhdr_t)))
+		goto nomem;
 
 	/* 5.1 D) Upon reception of the COOKIE ECHO chunk, Endpoint
 	 * "Z" will reply with a COOKIE ACK chunk after building a TCB
@@ -885,6 +873,8 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep,
 	struct sctp_transport *transport = (struct sctp_transport *) arg;
 
 	if (asoc->overall_error_count >= asoc->max_retrans) {
+		sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+				SCTP_ERROR(ETIMEDOUT));
 		/* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
 		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
 				SCTP_U32(SCTP_ERROR_NO_ERROR));
@@ -965,7 +955,8 @@ sctp_disposition_t sctp_sf_beat_8_3(const struct sctp_endpoint *ep,
 	 */
 	chunk->subh.hb_hdr = (sctp_heartbeathdr_t *) chunk->skb->data;
 	paylen = ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t);
-	skb_pull(chunk->skb, paylen);
+	if (!pskb_pull(chunk->skb, paylen))
+		goto nomem;
 
 	reply = sctp_make_heartbeat_ack(asoc, chunk,
 					chunk->subh.hb_hdr, paylen);
@@ -1028,6 +1019,12 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
 						  commands);
 
 	hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data;
+	/* Make sure that the length of the parameter is what we expect */
+	if (ntohs(hbinfo->param_hdr.length) !=
+				    sizeof(sctp_sender_hb_info_t)) {
+		return SCTP_DISPOSITION_DISCARD;
+	}
+
 	from_addr = hbinfo->daddr;
 	link = sctp_assoc_lookup_paddr(asoc, &from_addr);
 
@@ -1860,8 +1857,9 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const struct sctp_endpoint *ep,
 	 * are in good shape.
 	 */
         chunk->subh.cookie_hdr = (struct sctp_signed_cookie *)chunk->skb->data;
-	skb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) -
-		 sizeof(sctp_chunkhdr_t));
+	if (!pskb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) -
+					sizeof(sctp_chunkhdr_t)))
+		goto nomem;
 
 	/* In RFC 2960 5.2.4 3, if both Verification Tags in the State Cookie
 	 * of a duplicate COOKIE ECHO match the Verification Tags of the
@@ -2123,6 +2121,8 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
 	int attempts = asoc->init_err_counter + 1;
 
 	if (attempts > asoc->max_init_attempts) {
+		sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+				SCTP_ERROR(ETIMEDOUT));
 		sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
 				SCTP_U32(SCTP_ERROR_STALE_COOKIE));
 		return SCTP_DISPOSITION_DELETE_TCB;
@@ -2259,6 +2259,7 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
 	if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr))
 		error = ((sctp_errhdr_t *)chunk->skb->data)->cause;
 
+	sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNRESET));
  	/* ASSOC_FAILED will DELETE_TCB. */
 	sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(error));
 	SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
@@ -2303,7 +2304,8 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep,
 	if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr))
 		error = ((sctp_errhdr_t *)chunk->skb->data)->cause;
 
-	return sctp_stop_t1_and_abort(commands, error, asoc, chunk->transport);
+	return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED, asoc,
+				      chunk->transport);
 }
 
 /*
@@ -2315,7 +2317,8 @@ sctp_disposition_t sctp_sf_cookie_wait_icmp_abort(const struct sctp_endpoint *ep
 					void *arg,
 					sctp_cmd_seq_t *commands)
 {
-	return sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR, asoc,
+	return sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR,
+				      ENOPROTOOPT, asoc,
 				      (struct sctp_transport *)arg);
 }
 
@@ -2340,7 +2343,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep,
  * This is common code called by several sctp_sf_*_abort() functions above.
  */
 static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
-					   __u16 error,
+					   __u16 error, int sk_err,
 					   const struct sctp_association *asoc,
 					   struct sctp_transport *transport)
 {
@@ -2350,6 +2353,7 @@ static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
 	SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
 	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
 			SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
+	sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(sk_err));
 	/* CMD_INIT_FAILED will DELETE_TCB. */
 	sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
 			SCTP_U32(error));
@@ -3333,6 +3337,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
 		sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
 				SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
 		sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
+		sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+			        SCTP_ERROR(ECONNABORTED));
 		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
 				SCTP_U32(SCTP_ERROR_ASCONF_ACK));
 		SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
@@ -3359,6 +3365,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
 		 * processing the rest of the chunks in the packet.
 		 */
 		sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
+		sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+			        SCTP_ERROR(ECONNABORTED));
 		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
 				SCTP_U32(SCTP_ERROR_ASCONF_ACK));
 		SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
@@ -3711,9 +3719,13 @@ static sctp_disposition_t sctp_sf_violation_chunklen(
 	if (asoc->state <= SCTP_STATE_COOKIE_ECHOED) {
 		sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
 				SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
+		sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+				SCTP_ERROR(ECONNREFUSED));
 		sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
 				SCTP_U32(SCTP_ERROR_PROTO_VIOLATION));
 	} else {
+		sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+			        SCTP_ERROR(ECONNABORTED));
 		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
 				SCTP_U32(SCTP_ERROR_PROTO_VIOLATION));
 		SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
@@ -4031,6 +4043,8 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(
 	 * TCB.  This is a departure from our typical NOMEM handling.
 	 */
 
+	sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+			SCTP_ERROR(ECONNABORTED));
 	/* Delete the established association. */
 	sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
 			SCTP_U32(SCTP_ERROR_USER_ABORT));
@@ -4172,6 +4186,8 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(
 	 * TCB.  This is a departure from our typical NOMEM handling.
 	 */
 
+	sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+			SCTP_ERROR(ECONNREFUSED));
 	/* Delete the established association. */
 	sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
 			SCTP_U32(SCTP_ERROR_USER_ABORT));
@@ -4540,6 +4556,8 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep,
 	struct sctp_transport *transport = arg;
 
 	if (asoc->overall_error_count >= asoc->max_retrans) {
+		sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+				SCTP_ERROR(ETIMEDOUT));
 		/* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
 		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
 				SCTP_U32(SCTP_ERROR_NO_ERROR));
@@ -4659,6 +4677,8 @@ sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep,
 		SCTP_DEBUG_PRINTK("Giving up on INIT, attempts: %d"
 				  " max_init_attempts: %d\n",
 				  attempts, asoc->max_init_attempts);
+		sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+				SCTP_ERROR(ETIMEDOUT));
 		sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
 				SCTP_U32(SCTP_ERROR_NO_ERROR));
 		return SCTP_DISPOSITION_DELETE_TCB;
@@ -4708,6 +4728,8 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep
 
 		sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
 	} else {
+		sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+				SCTP_ERROR(ETIMEDOUT));
 		sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
 				SCTP_U32(SCTP_ERROR_NO_ERROR));
 		return SCTP_DISPOSITION_DELETE_TCB;
@@ -4739,6 +4761,8 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep,
 
 	SCTP_DEBUG_PRINTK("Timer T2 expired.\n");
 	if (asoc->overall_error_count >= asoc->max_retrans) {
+		sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+				SCTP_ERROR(ETIMEDOUT));
 		/* Note:  CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
 		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
 				SCTP_U32(SCTP_ERROR_NO_ERROR));
@@ -4814,6 +4838,8 @@ sctp_disposition_t sctp_sf_t4_timer_expire(
 	if (asoc->overall_error_count >= asoc->max_retrans) {
 		sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
 				SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
+		sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+				SCTP_ERROR(ETIMEDOUT));
 		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
 				SCTP_U32(SCTP_ERROR_NO_ERROR));
 		SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
@@ -4867,6 +4893,8 @@ sctp_disposition_t sctp_sf_t5_timer_expire(const struct sctp_endpoint *ep,
 		goto nomem;
 
 	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));
+	sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+			SCTP_ERROR(ETIMEDOUT));
 	sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
 			SCTP_U32(SCTP_ERROR_NO_ERROR));
 
@@ -5151,7 +5179,9 @@ static int sctp_eat_data(const struct sctp_association *asoc,
 	int tmp;
 	__u32 tsn;
 	int account_value;
+	struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map;
 	struct sock *sk = asoc->base.sk;
+	int rcvbuf_over = 0;
 
 	data_hdr = chunk->subh.data_hdr = (sctp_datahdr_t *)chunk->skb->data;
 	skb_pull(chunk->skb, sizeof(sctp_datahdr_t));
@@ -5162,10 +5192,16 @@ static int sctp_eat_data(const struct sctp_association *asoc,
 	/* ASSERT:  Now skb->data is really the user data.  */
 
 	/*
-	 * if we are established, and we have used up our receive
-	 * buffer memory, drop the frame
-	 */
-	if (asoc->state == SCTP_STATE_ESTABLISHED) {
+	 * If we are established, and we have used up our receive buffer
+	 * memory, think about droping the frame.
+	 * Note that we have an opportunity to improve performance here.
+	 * If we accept one chunk from an skbuff, we have to keep all the
+	 * memory of that skbuff around until the chunk is read into user
+	 * space. Therefore, once we accept 1 chunk we may as well accept all
+	 * remaining chunks in the skbuff. The data_accepted flag helps us do
+	 * that.
+	 */
+	if ((asoc->state == SCTP_STATE_ESTABLISHED) && (!chunk->data_accepted)) {
 		/*
 		 * If the receive buffer policy is 1, then each
 		 * association can allocate up to sk_rcvbuf bytes
@@ -5176,9 +5212,25 @@ static int sctp_eat_data(const struct sctp_association *asoc,
 			account_value = atomic_read(&asoc->rmem_alloc);
 		else
 			account_value = atomic_read(&sk->sk_rmem_alloc);
-
-		if (account_value > sk->sk_rcvbuf)
-			return SCTP_IERROR_IGNORE_TSN;
+		if (account_value > sk->sk_rcvbuf) {
+			/*
+			 * We need to make forward progress, even when we are
+			 * under memory pressure, so we always allow the
+			 * next tsn after the ctsn ack point to be accepted.
+			 * This lets us avoid deadlocks in which we have to
+			 * drop frames that would otherwise let us drain the
+			 * receive queue.
+			 */
+			if ((sctp_tsnmap_get_ctsn(map) + 1) != tsn)
+				return SCTP_IERROR_IGNORE_TSN;
+
+			/*
+			 * We're going to accept the frame but we should renege
+			 * to make space for it. This will send us down that
+			 * path later in this function.
+			 */
+			rcvbuf_over = 1;
+		}
 	}
 
 	/* Process ECN based congestion.
@@ -5226,6 +5278,7 @@ static int sctp_eat_data(const struct sctp_association *asoc,
 	datalen -= sizeof(sctp_data_chunk_t);
 
 	deliver = SCTP_CMD_CHUNK_ULP;
+	chunk->data_accepted = 1;
 
 	/* Think about partial delivery. */
 	if ((datalen >= asoc->rwnd) && (!asoc->ulpq.pd_mode)) {
@@ -5242,7 +5295,8 @@ static int sctp_eat_data(const struct sctp_association *asoc,
 	 * large spill over.
 	 */
 	if (!asoc->rwnd || asoc->rwnd_over ||
-	    (datalen > asoc->rwnd + asoc->frag_point)) {
+	    (datalen > asoc->rwnd + asoc->frag_point) ||
+	    rcvbuf_over) {
 
 		/* If this is the next TSN, consider reneging to make
 		 * room.   Note: Playing nice with a confused sender.  A
@@ -5250,8 +5304,8 @@ static int sctp_eat_data(const struct sctp_association *asoc,
 		 * space and in the future we may want to detect and
 		 * do more drastic reneging.
 		 */
-		if (sctp_tsnmap_has_gap(&asoc->peer.tsn_map) &&
-		    (sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + 1) == tsn) {
+		if (sctp_tsnmap_has_gap(map) &&
+		    (sctp_tsnmap_get_ctsn(map) + 1) == tsn) {
 			SCTP_DEBUG_PRINTK("Reneging for tsn:%u\n", tsn);
 			deliver = SCTP_CMD_RENEGE;
 		} else {
@@ -5280,6 +5334,8 @@ static int sctp_eat_data(const struct sctp_association *asoc,
 		 * processing the rest of the chunks in the packet.
 		 */
 		sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
+		sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+				SCTP_ERROR(ECONNABORTED));
 		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
 				SCTP_U32(SCTP_ERROR_NO_DATA));
 		SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index 75ef10408764247ec5999ad662dfc022a2660303..8bcca5676151b346d1fb1e9cc96d5dce1aa1340d 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -366,9 +366,9 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
 	/* SCTP_STATE_EMPTY */ \
 	{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
 	/* SCTP_STATE_CLOSED */ \
-	{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
 	/* SCTP_STATE_COOKIE_WAIT */ \
-	{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
 	/* SCTP_STATE_COOKIE_ECHOED */ \
 	{.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \
 	/* SCTP_STATE_ESTABLISHED */ \
@@ -380,7 +380,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
 	/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
 	{.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \
 	/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
-	{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
 } /* TYPE_SCTP_ECN_ECNE */
 
 #define TYPE_SCTP_ECN_CWR { \
@@ -401,7 +401,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
 	/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
 	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
 	/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
-	{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
 } /* TYPE_SCTP_ECN_CWR */
 
 #define TYPE_SCTP_SHUTDOWN_COMPLETE { \
@@ -647,7 +647,7 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = {
 	/* SCTP_STATE_EMPTY */ \
 	{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
 	/* SCTP_STATE_CLOSED */ \
-	{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+	{.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \
 	/* SCTP_STATE_COOKIE_WAIT */ \
 	{.fn = sctp_sf_do_prm_requestheartbeat,		      \
 	 .name = "sctp_sf_do_prm_requestheartbeat"},          \
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index b6e4b89539b3178216037c53350f5591dde8a1b6..174d4d35e951590d7bef5d10df113afe36f88ae6 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1057,6 +1057,7 @@ static int __sctp_connect(struct sock* sk,
 	inet_sk(sk)->dport = htons(asoc->peer.port);
 	af = sctp_get_af_specific(to.sa.sa_family);
 	af->to_sk_daddr(&to, sk);
+	sk->sk_err = 0;
 
 	timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK);
 	err = sctp_wait_for_connect(asoc, &timeo);
@@ -1228,7 +1229,7 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
 
 	ep = sctp_sk(sk)->ep;
 
-	/* Walk all associations on a socket, not on an endpoint.  */
+	/* Walk all associations on an endpoint.  */
 	list_for_each_safe(pos, temp, &ep->asocs) {
 		asoc = list_entry(pos, struct sctp_association, asocs);
 
@@ -1241,13 +1242,13 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
 			if (sctp_state(asoc, CLOSED)) {
 				sctp_unhash_established(asoc);
 				sctp_association_free(asoc);
+				continue;
+			}
+		}
 
-			} else if (sock_flag(sk, SOCK_LINGER) &&
-				   !sk->sk_lingertime)
-				sctp_primitive_ABORT(asoc, NULL);
-			else
-				sctp_primitive_SHUTDOWN(asoc, NULL);
-		} else
+		if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime)
+			sctp_primitive_ABORT(asoc, NULL);
+		else
 			sctp_primitive_SHUTDOWN(asoc, NULL);
 	}
 
@@ -5317,6 +5318,7 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p,
 		 */
 		sctp_release_sock(sk);
 		current_timeo = schedule_timeout(current_timeo);
+		BUG_ON(sk != asoc->base.sk);
 		sctp_lock_sock(sk);
 
 		*timeo_p = current_timeo;
@@ -5604,12 +5606,14 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
 	 */
 	newsp->type = type;
 
-	spin_lock_bh(&oldsk->sk_lock.slock);
-	/* Migrate the backlog from oldsk to newsk. */
-	sctp_backlog_migrate(assoc, oldsk, newsk);
-	/* Migrate the association to the new socket. */
+	/* Mark the new socket "in-use" by the user so that any packets
+	 * that may arrive on the association after we've moved it are
+	 * queued to the backlog.  This prevents a potential race between
+	 * backlog processing on the old socket and new-packet processing
+	 * on the new socket.
+	 */
+	sctp_lock_sock(newsk);
 	sctp_assoc_migrate(assoc, newsk);
-	spin_unlock_bh(&oldsk->sk_lock.slock);
 
 	/* If the association on the newsk is already closed before accept()
 	 * is called, set RCV_SHUTDOWN flag.
@@ -5618,6 +5622,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
 		newsk->sk_shutdown |= RCV_SHUTDOWN;
 
 	newsk->sk_state = SCTP_SS_ESTABLISHED;
+	sctp_release_sock(newsk);
 }
 
 /* This proto struct describes the ULP interface for SCTP.  */
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
index 2080b2d28c98e97297fae432fc1a3a97a68f2646..575e556aeb3eb58c30dd80f86c6158defb3c664f 100644
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -279,6 +279,7 @@ static inline void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq,
 static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *queue, struct sk_buff *f_frag, struct sk_buff *l_frag)
 {
 	struct sk_buff *pos;
+	struct sk_buff *new = NULL;
 	struct sctp_ulpevent *event;
 	struct sk_buff *pnext, *last;
 	struct sk_buff *list = skb_shinfo(f_frag)->frag_list;
@@ -297,11 +298,33 @@ static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *qu
 	 */
 	if (last)
 		last->next = pos;
-	else
-		skb_shinfo(f_frag)->frag_list = pos;
+ 	else {
+ 		if (skb_cloned(f_frag)) {
+ 			/* This is a cloned skb, we can't just modify
+ 			 * the frag_list.  We need a new skb to do that.
+ 			 * Instead of calling skb_unshare(), we'll do it
+ 			 * ourselves since we need to delay the free.
+ 			 */
+ 			new = skb_copy(f_frag, GFP_ATOMIC);
+ 			if (!new)
+ 				return NULL;	/* try again later */
+
+ 			new->sk = f_frag->sk;
+
+ 			skb_shinfo(new)->frag_list = pos;
+ 		} else
+ 			skb_shinfo(f_frag)->frag_list = pos;
+ 	}
 
 	/* Remove the first fragment from the reassembly queue.  */
 	__skb_unlink(f_frag, queue);
+
+ 	/* if we did unshare, then free the old skb and re-assign */
+ 	if (new) {
+ 		kfree_skb(f_frag);
+ 		f_frag = new;
+ 	}
+
 	while (pos) {
 
 		pnext = pos->next;
diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh
index 56b3bed1108f4132b297eee6dbc5255ce81d028c..331c079f029b7c516fe4c32510d445defc3a6c53 100644
--- a/scripts/gen_initramfs_list.sh
+++ b/scripts/gen_initramfs_list.sh
@@ -200,7 +200,11 @@ input_file() {
 			print_mtime "$1" >> ${output}
 			cat "$1"         >> ${output}
 		else
-			grep ^file "$1" | cut -d ' ' -f 3
+			cat "$1" | while read type dir file perm ; do
+				if [ "$type" == "file" ]; then
+					echo "$file \\";
+				fi
+			done
 		fi
 	elif [ -d "$1" ]; then
 		dir_filelist "$1"
diff --git a/scripts/mkmakefile b/scripts/mkmakefile
index a22cbedd3b3ec0738379c283d4fb2df5b33209ec..7f9d544f9b6c07339021bdb80762feeb7b95f9bf 100644
--- a/scripts/mkmakefile
+++ b/scripts/mkmakefile
@@ -10,7 +10,10 @@
 # $4 - patchlevel
 
 
-cat << EOF
+test ! -r $2/Makefile -o -O $2/Makefile || exit 0
+echo "  GEN     $2/Makefile"
+
+cat << EOF > $2/Makefile
 # Automatically generated by $0: don't edit
 
 VERSION = $3
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index cd00e9f0758995e5d027ff9dc96835256b10860c..6d04504b2fc111a0bbd7ac8745fa9f96e008e72a 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -487,14 +487,14 @@ static int strrcmp(const char *s, const char *sub)
  *   atsym   =__param*
  *
  * Pattern 2:
- *   Many drivers utilise a *_driver container with references to
+ *   Many drivers utilise a *driver container with references to
  *   add, remove, probe functions etc.
  *   These functions may often be marked __init and we do not want to
  *   warn here.
  *   the pattern is identified by:
  *   tosec   = .init.text | .exit.text | .init.data
  *   fromsec = .data
- *   atsym = *_driver, *_template, *_sht, *_ops, *_probe, *probe_one
+ *   atsym = *driver, *_template, *_sht, *_ops, *_probe, *probe_one
  **/
 static int secref_whitelist(const char *tosec, const char *fromsec,
 			    const char *atsym)
@@ -502,7 +502,7 @@ static int secref_whitelist(const char *tosec, const char *fromsec,
 	int f1 = 1, f2 = 1;
 	const char **s;
 	const char *pat2sym[] = {
-		"_driver",
+		"driver",
 		"_template", /* scsi uses *_template a lot */
 		"_sht",      /* scsi also used *_sht to some extent */
 		"_ops",
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 3cf368a16448c54a4fccd4686765fd8569cee50a..d987048d3f330526b31185d5023ea8fd4c891027 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -101,6 +101,8 @@ static int __init selinux_enabled_setup(char *str)
 	return 1;
 }
 __setup("selinux=", selinux_enabled_setup);
+#else
+int selinux_enabled = 1;
 #endif
 
 /* Original (dummy) security module. */
@@ -4535,6 +4537,7 @@ int selinux_disable(void)
 	printk(KERN_INFO "SELinux:  Disabled at runtime.\n");
 
 	selinux_disabled = 1;
+	selinux_enabled = 0;
 
 	/* Reset security_ops to the secondary module, dummy or capability. */
 	security_ops = secondary_ops;
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 5f016c98056f53e35491c779fcb3dd2dc23c54c9..063af47bb23175b4887fd634ea541fd2ae6eef05 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -29,12 +29,7 @@
 #define POLICYDB_VERSION_MIN   POLICYDB_VERSION_BASE
 #define POLICYDB_VERSION_MAX   POLICYDB_VERSION_AVTAB
 
-#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
 extern int selinux_enabled;
-#else
-#define selinux_enabled 1
-#endif
-
 extern int selinux_mls_enabled;
 
 int security_load_policy(void * data, size_t len);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 7177e98df7f33a4e06b521fbb2bb987150838246..c284dbb8b8c02fbba51aa562d5e4fd4551e641f3 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -594,6 +594,10 @@ int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
 
 			*scontext_len = strlen(initial_sid_to_string[sid]) + 1;
 			scontextp = kmalloc(*scontext_len,GFP_ATOMIC);
+			if (!scontextp) {
+				rc = -ENOMEM;
+				goto out;
+			}
 			strcpy(scontextp, initial_sid_to_string[sid]);
 			*scontext = scontextp;
 			goto out;