Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6:
  sparc: Set CONFIG_HAVE_ARCH_TRACEHOOK
  sparc: Add task_pt_regs().
  sparc: Add call to tracehook_signal_handler().
  sparc: Create and use TIF_NOTIFY_RESUME.
  sparc: Use tracehook routines in syscall_trace().
  sparc64: tracehook: CONFIG_HAVE_ARCH_TRACEHOOK
  sparc: Add user_stack_pointer().
  sparc64: tracehook_signal_handler
  sparc64: tracehook: TIF_NOTIFY_RESUME
  sparc: Add asm/syscall.h
  sparc64: tracehook syscall
  sparc: enable headers_export again
  sparc, sparc64: use arch/sparc/include
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 118ca6e..f79ad9f 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -528,7 +528,33 @@
 references.
 
 
+16) Sending "git pull" requests  (from Linus emails)
 
+Please write the git repo address and branch name alone on the same line
+so that I can't even by mistake pull from the wrong branch, and so
+that a triple-click just selects the whole thing.
+
+So the proper format is something along the lines of:
+
+	"Please pull from
+
+		git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus
+
+	 to get these changes:"
+
+so that I don't have to hunt-and-peck for the address and inevitably
+get it wrong (actually, I've only gotten it wrong a few times, and
+checking against the diffstat tells me when I get it wrong, but I'm
+just a lot more comfortable when I don't have to "look for" the right
+thing to pull, and double-check that I have the right branch-name).
+
+
+Please use "git diff -M --stat --summary" to generate the diffstat:
+the -M enables rename detection, and the summary enables a summary of
+new/deleted or renamed files.
+
+With rename detection, the statistics are rather different [...]
+because git will notice that a fair number of the changes are renames.
 
 -----------------------------------
 SECTION 2 - HINTS, TIPS, AND TRICKS
diff --git a/Documentation/i2c/upgrading-clients b/Documentation/i2c/upgrading-clients
new file mode 100644
index 0000000..9a45f9b
--- /dev/null
+++ b/Documentation/i2c/upgrading-clients
@@ -0,0 +1,281 @@
+Upgrading I2C Drivers to the new 2.6 Driver Model
+=================================================
+
+Ben Dooks <ben-linux@fluff.org>
+
+Introduction
+------------
+
+This guide outlines how to alter existing Linux 2.6 client drivers from
+the old to the new new binding methods.
+
+
+Example old-style driver
+------------------------
+
+
+struct example_state {
+	struct i2c_client	client;
+	....
+};
+
+static struct i2c_driver example_driver;
+
+static unsigned short ignore[] = { I2C_CLIENT_END };
+static unsigned short normal_addr[] = { OUR_ADDR, I2C_CLIENT_END };
+
+I2C_CLIENT_INSMOD;
+
+static int example_attach(struct i2c_adapter *adap, int addr, int kind)
+{
+	struct example_state *state;
+	struct device *dev = &adap->dev;  /* to use for dev_ reports */
+	int ret;
+
+	state = kzalloc(sizeof(struct example_state), GFP_KERNEL);
+	if (state == NULL) {
+		dev_err(dev, "failed to create our state\n");
+		return -ENOMEM;
+	}
+
+	example->client.addr    = addr;
+	example->client.flags   = 0;
+	example->client.adapter = adap;
+
+	i2c_set_clientdata(&state->i2c_client, state);
+	strlcpy(client->i2c_client.name, "example", I2C_NAME_SIZE);
+
+	ret = i2c_attach_client(&state->i2c_client);
+	if (ret < 0) {
+		dev_err(dev, "failed to attach client\n");
+		kfree(state);
+		return ret;
+	}
+
+	dev = &state->i2c_client.dev;
+
+	/* rest of the initialisation goes here. */
+
+	dev_info(dev, "example client created\n");
+
+	return 0;
+}
+
+static int __devexit example_detach(struct i2c_client *client)
+{
+	struct example_state *state = i2c_get_clientdata(client);
+
+	i2c_detach_client(client);
+	kfree(state);
+	return 0;
+}
+
+static int example_attach_adapter(struct i2c_adapter *adap)
+{
+	return i2c_probe(adap, &addr_data, example_attach);
+}
+
+static struct i2c_driver example_driver = {
+ 	.driver		= {
+		.owner		= THIS_MODULE,
+		.name		= "example",
+	},
+	.attach_adapter = example_attach_adapter,
+	.detach_client	= __devexit_p(example_detach),
+	.suspend	= example_suspend,
+	.resume		= example_resume,
+};
+
+
+Updating the client
+-------------------
+
+The new style binding model will check against a list of supported
+devices and their associated address supplied by the code registering
+the busses. This means that the driver .attach_adapter and
+.detach_adapter methods can be removed, along with the addr_data,
+as follows:
+
+- static struct i2c_driver example_driver;
+
+- static unsigned short ignore[] = { I2C_CLIENT_END };
+- static unsigned short normal_addr[] = { OUR_ADDR, I2C_CLIENT_END };
+
+- I2C_CLIENT_INSMOD;
+
+- static int example_attach_adapter(struct i2c_adapter *adap)
+- {
+- 	return i2c_probe(adap, &addr_data, example_attach);
+- }
+
+ static struct i2c_driver example_driver = {
+-	.attach_adapter = example_attach_adapter,
+-	.detach_client	= __devexit_p(example_detach),
+ }
+
+Add the probe and remove methods to the i2c_driver, as so:
+
+ static struct i2c_driver example_driver = {
++	.probe		= example_probe,
++	.remove		= __devexit_p(example_remove),
+ }
+
+Change the example_attach method to accept the new parameters
+which include the i2c_client that it will be working with:
+
+- static int example_attach(struct i2c_adapter *adap, int addr, int kind)
++ static int example_probe(struct i2c_client *client,
++			   const struct i2c_device_id *id)
+
+Change the name of example_attach to example_probe to align it with the
+i2c_driver entry names. The rest of the probe routine will now need to be
+changed as the i2c_client has already been setup for use.
+
+The necessary client fields have already been setup before
+the probe function is called, so the following client setup
+can be removed:
+
+-	example->client.addr    = addr;
+-	example->client.flags   = 0;
+-	example->client.adapter = adap;
+-
+-	strlcpy(client->i2c_client.name, "example", I2C_NAME_SIZE);
+
+The i2c_set_clientdata is now:
+
+-	i2c_set_clientdata(&state->client, state);
++	i2c_set_clientdata(client, state);
+
+The call to i2c_attach_client is no longer needed, if the probe
+routine exits successfully, then the driver will be automatically
+attached by the core. Change the probe routine as so:
+
+-	ret = i2c_attach_client(&state->i2c_client);
+-	if (ret < 0) {
+-		dev_err(dev, "failed to attach client\n");
+-		kfree(state);
+-		return ret;
+-	}
+
+
+Remove the storage of 'struct i2c_client' from the 'struct example_state'
+as we are provided with the i2c_client in our example_probe. Instead we
+store a pointer to it for when it is needed.
+
+struct example_state {
+-	struct i2c_client	client;
++	struct i2c_client	*client;
+
+the new i2c client as so:
+
+-	struct device *dev = &adap->dev;  /* to use for dev_ reports */
++ 	struct device *dev = &i2c_client->dev;  /* to use for dev_ reports */
+
+And remove the change after our client is attached, as the driver no
+longer needs to register a new client structure with the core:
+
+-	dev = &state->i2c_client.dev;
+
+In the probe routine, ensure that the new state has the client stored
+in it:
+
+static int example_probe(struct i2c_client *i2c_client,
+			 const struct i2c_device_id *id)
+{
+	struct example_state *state;
+ 	struct device *dev = &i2c_client->dev;
+	int ret;
+
+	state = kzalloc(sizeof(struct example_state), GFP_KERNEL);
+	if (state == NULL) {
+		dev_err(dev, "failed to create our state\n");
+		return -ENOMEM;
+	}
+
++	state->client = i2c_client;
+
+Update the detach method, by changing the name to _remove and
+to delete the i2c_detach_client call. It is possible that you
+can also remove the ret variable as it is not not needed for
+any of the core functions.
+
+- static int __devexit example_detach(struct i2c_client *client)
++ static int __devexit example_remove(struct i2c_client *client)
+{
+	struct example_state *state = i2c_get_clientdata(client);
+
+-	i2c_detach_client(client);
+
+And finally ensure that we have the correct ID table for the i2c-core
+and other utilities:
+
++ struct i2c_device_id example_idtable[] = {
++       { "example", 0 },
++       { }
++};
++
++MODULE_DEVICE_TABLE(i2c, example_idtable);
+
+static struct i2c_driver example_driver = {
+ 	.driver		= {
+		.owner		= THIS_MODULE,
+		.name		= "example",
+	},
++	.id_table	= example_ids,
+
+
+Our driver should now look like this:
+
+struct example_state {
+	struct i2c_client	*client;
+	....
+};
+
+static int example_probe(struct i2c_client *client,
+		     	 const struct i2c_device_id *id)
+{
+	struct example_state *state;
+	struct device *dev = &client->dev;
+
+	state = kzalloc(sizeof(struct example_state), GFP_KERNEL);
+	if (state == NULL) {
+		dev_err(dev, "failed to create our state\n");
+		return -ENOMEM;
+	}
+
+	state->client = client;
+	i2c_set_clientdata(client, state);
+
+	/* rest of the initialisation goes here. */
+
+	dev_info(dev, "example client created\n");
+
+	return 0;
+}
+
+static int __devexit example_remove(struct i2c_client *client)
+{
+	struct example_state *state = i2c_get_clientdata(client);
+
+	kfree(state);
+	return 0;
+}
+
+static struct i2c_device_id example_idtable[] = {
+	{ "example", 0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, example_idtable);
+
+static struct i2c_driver example_driver = {
+ 	.driver		= {
+		.owner		= THIS_MODULE,
+		.name		= "example",
+	},
+	.id_table	= example_idtable,
+	.probe		= example_probe,
+	.remove		= __devexit_p(example_remove),
+	.suspend	= example_suspend,
+	.resume		= example_resume,
+};
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index b7f2963..283c08f 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -1332,9 +1332,15 @@
 	if (!pr->flags.power_setup_done)
 		return -ENODEV;
 
-	/* Fall back to the default idle loop */
-	pm_idle = pm_idle_save;
-	synchronize_sched();	/* Relies on interrupts forcing exit from idle. */
+	/*
+	 * Fall back to the default idle loop, when pm_idle_save had
+	 * been initialized.
+	 */
+	if (pm_idle_save) {
+		pm_idle = pm_idle_save;
+		/* Relies on interrupts forcing exit from idle. */
+		synchronize_sched();
+	}
 
 	pr->flags.power = 0;
 	result = acpi_processor_get_power_info(pr);
@@ -1896,7 +1902,8 @@
 
 	/* Unregister the idle handler when processor #0 is removed. */
 	if (pr->id == 0) {
-		pm_idle = pm_idle_save;
+		if (pm_idle_save)
+			pm_idle = pm_idle_save;
 
 		/*
 		 * We are about to unload the current idle thread pm callback
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 3ad49a0..af0d175 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -103,7 +103,8 @@
 /*
  * Show whether the section of memory is likely to be hot-removable
  */
-static ssize_t show_mem_removable(struct sys_device *dev, char *buf)
+static ssize_t show_mem_removable(struct sys_device *dev,
+			struct sysdev_attribute *attr, char *buf)
 {
 	unsigned long start_pfn;
 	int ret;
diff --git a/drivers/char/pcmcia/ipwireless/hardware.c b/drivers/char/pcmcia/ipwireless/hardware.c
index 929101e..7d500f8 100644
--- a/drivers/char/pcmcia/ipwireless/hardware.c
+++ b/drivers/char/pcmcia/ipwireless/hardware.c
@@ -30,11 +30,11 @@
 static void ipw_send_setup_packet(struct ipw_hardware *hw);
 static void handle_received_SETUP_packet(struct ipw_hardware *ipw,
 					 unsigned int address,
-					 unsigned char *data, int len,
+					 const unsigned char *data, int len,
 					 int is_last);
 static void ipwireless_setup_timer(unsigned long data);
 static void handle_received_CTRL_packet(struct ipw_hardware *hw,
-		unsigned int channel_idx, unsigned char *data, int len);
+		unsigned int channel_idx, const unsigned char *data, int len);
 
 /*#define TIMING_DIAGNOSTICS*/
 
@@ -79,8 +79,7 @@
 		timing_stats.last_report_time = jiffies;
 		if (!first)
 			printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-			       ": %u us elapsed - read %lu bytes in %u us, "
-			       "wrote %lu bytes in %u us\n",
+			       ": %u us elapsed - read %lu bytes in %u us, wrote %lu bytes in %u us\n",
 			       jiffies_to_usecs(since),
 			       timing_stats.read_bytes,
 			       jiffies_to_usecs(timing_stats.read_time),
@@ -133,29 +132,17 @@
 #define NL_FOLLOWING_PACKET_HEADER_SIZE    1
 
 struct nl_first_packet_header {
-#if defined(__BIG_ENDIAN_BITFIELD)
-	unsigned char packet_rank:2;
-	unsigned char address:3;
-	unsigned char protocol:3;
-#else
 	unsigned char protocol:3;
 	unsigned char address:3;
 	unsigned char packet_rank:2;
-#endif
 	unsigned char length_lsb;
 	unsigned char length_msb;
 };
 
 struct nl_packet_header {
-#if defined(__BIG_ENDIAN_BITFIELD)
-	unsigned char packet_rank:2;
-	unsigned char address:3;
-	unsigned char protocol:3;
-#else
 	unsigned char protocol:3;
 	unsigned char address:3;
 	unsigned char packet_rank:2;
-#endif
 };
 
 /* Value of 'packet_rank' above */
@@ -227,15 +214,12 @@
 	unsigned short memreg_tx_new;	/* TX2 (new) Register (R/W) */
 };
 
-#define IODMADPR 0x00		/* DMA Data Port Register (R/W) */
-
 #define CARD_PRESENT_VALUE (0xBEEFCAFEUL)
 
 #define MEMTX_TX                       0x0001
 #define MEMRX_RX                       0x0001
 #define MEMRX_RX_DONE                  0x0001
 #define MEMRX_PCINTACKK                0x0001
-#define MEMRX_MEMSPURIOUSINT           0x0001
 
 #define NL_NUM_OF_PRIORITIES       3
 #define NL_NUM_OF_PROTOCOLS        3
@@ -245,7 +229,7 @@
 	unsigned int base_port;
 	short hw_version;
 	unsigned short ll_mtu;
-	spinlock_t spinlock;
+	spinlock_t lock;
 
 	int initializing;
 	int init_loops;
@@ -386,26 +370,52 @@
 			length < DUMP_MAX_BYTES ? length : DUMP_MAX_BYTES);
 }
 
-static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data,
+static void swap_packet_bitfield_to_le(unsigned char *data)
+{
+#ifdef __BIG_ENDIAN_BITFIELD
+	unsigned char tmp = *data, ret = 0;
+
+	/*
+	 * transform bits from aa.bbb.ccc to ccc.bbb.aa
+	 */
+	ret |= tmp & 0xc0 >> 6;
+	ret |= tmp & 0x38 >> 1;
+	ret |= tmp & 0x07 << 5;
+	*data = ret & 0xff;
+#endif
+}
+
+static void swap_packet_bitfield_from_le(unsigned char *data)
+{
+#ifdef __BIG_ENDIAN_BITFIELD
+	unsigned char tmp = *data, ret = 0;
+
+	/*
+	 * transform bits from ccc.bbb.aa to aa.bbb.ccc
+	 */
+	ret |= tmp & 0xe0 >> 5;
+	ret |= tmp & 0x1c << 1;
+	ret |= tmp & 0x03 << 6;
+	*data = ret & 0xff;
+#endif
+}
+
+static void do_send_fragment(struct ipw_hardware *hw, unsigned char *data,
 			    unsigned length)
 {
-	int i;
+	unsigned i;
 	unsigned long flags;
 
 	start_timing();
-
-	if (length == 0)
-		return 0;
-
-	if (length > hw->ll_mtu)
-		return -1;
+	BUG_ON(length > hw->ll_mtu);
 
 	if (ipwireless_debug)
 		dump_data_bytes("send", data, length);
 
-	spin_lock_irqsave(&hw->spinlock, flags);
+	spin_lock_irqsave(&hw->lock, flags);
 
 	hw->tx_ready = 0;
+	swap_packet_bitfield_to_le(data);
 
 	if (hw->hw_version == HW_VERSION_1) {
 		outw((unsigned short) length, hw->base_port + IODWR);
@@ -414,7 +424,7 @@
 			unsigned short d = data[i];
 			__le16 raw_data;
 
-			if (likely(i + 1 < length))
+			if (i + 1 < length)
 				d |= data[i + 1] << 8;
 			raw_data = cpu_to_le16(d);
 			outw(raw_data, hw->base_port + IODWR);
@@ -422,32 +432,30 @@
 
 		outw(DCR_TXDONE, hw->base_port + IODCR);
 	} else if (hw->hw_version == HW_VERSION_2) {
-		outw((unsigned short) length, hw->base_port + IODMADPR);
+		outw((unsigned short) length, hw->base_port);
 
 		for (i = 0; i < length; i += 2) {
 			unsigned short d = data[i];
 			__le16 raw_data;
 
-			if ((i + 1 < length))
+			if (i + 1 < length)
 				d |= data[i + 1] << 8;
 			raw_data = cpu_to_le16(d);
-			outw(raw_data, hw->base_port + IODMADPR);
+			outw(raw_data, hw->base_port);
 		}
 		while ((i & 3) != 2) {
-			outw((unsigned short) 0xDEAD, hw->base_port + IODMADPR);
+			outw((unsigned short) 0xDEAD, hw->base_port);
 			i += 2;
 		}
 		writew(MEMRX_RX, &hw->memory_info_regs->memreg_rx);
 	}
 
-	spin_unlock_irqrestore(&hw->spinlock, flags);
+	spin_unlock_irqrestore(&hw->lock, flags);
 
 	end_write_timing(length);
-
-	return 0;
 }
 
-static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet)
+static void do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet)
 {
 	unsigned short fragment_data_len;
 	unsigned short data_left = packet->length - packet->offset;
@@ -462,6 +470,10 @@
 	if (data_left < fragment_data_len)
 		fragment_data_len = data_left;
 
+	/*
+	 * hdr_first is now in machine bitfield order, which will be swapped
+	 * to le just before it goes to hw
+	 */
 	pkt.hdr_first.protocol = packet->protocol;
 	pkt.hdr_first.address = packet->dest_addr;
 	pkt.hdr_first.packet_rank = 0;
@@ -493,25 +505,23 @@
 		 */
 		unsigned long flags;
 
-		spin_lock_irqsave(&hw->spinlock, flags);
+		spin_lock_irqsave(&hw->lock, flags);
 		list_add(&packet->queue, &hw->tx_queue[0]);
 		hw->tx_queued++;
-		spin_unlock_irqrestore(&hw->spinlock, flags);
+		spin_unlock_irqrestore(&hw->lock, flags);
 	} else {
 		if (packet->packet_callback)
 			packet->packet_callback(packet->callback_data,
 					packet->length);
 		kfree(packet);
 	}
-
-	return 0;
 }
 
 static void ipw_setup_hardware(struct ipw_hardware *hw)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&hw->spinlock, flags);
+	spin_lock_irqsave(&hw->lock, flags);
 	if (hw->hw_version == HW_VERSION_1) {
 		/* Reset RX FIFO */
 		outw(DCR_RXRESET, hw->base_port + IODCR);
@@ -530,7 +540,7 @@
 		csr |= 1;
 		writew(csr, &hw->memregs_CCR->reg_config_and_status);
 	}
-	spin_unlock_irqrestore(&hw->spinlock, flags);
+	spin_unlock_irqrestore(&hw->lock, flags);
 }
 
 /*
@@ -549,28 +559,23 @@
 	if (!packet) {
 		unsigned long flags;
 
-		/*
-		 * If this is the first fragment, then we will need to fetch a
-		 * packet to put it in.
-		 */
-		spin_lock_irqsave(&hw->spinlock, flags);
-		/* If we have one in our pool, then pull it out. */
+		spin_lock_irqsave(&hw->lock, flags);
 		if (!list_empty(&hw->rx_pool)) {
 			packet = list_first_entry(&hw->rx_pool,
 					struct ipw_rx_packet, queue);
-			list_del(&packet->queue);
 			hw->rx_pool_size--;
-			spin_unlock_irqrestore(&hw->spinlock, flags);
+			spin_unlock_irqrestore(&hw->lock, flags);
+			list_del(&packet->queue);
 		} else {
-			/* Otherwise allocate a new one. */
-			static int min_capacity = 256;
+			const int min_capacity =
+				ipwireless_ppp_mru(hw->network + 2);
 			int new_capacity;
 
-			spin_unlock_irqrestore(&hw->spinlock, flags);
+			spin_unlock_irqrestore(&hw->lock, flags);
 			new_capacity =
-			    minimum_free_space > min_capacity
-			    ? minimum_free_space
-			    : min_capacity;
+				(minimum_free_space > min_capacity
+				 ? minimum_free_space
+				 : min_capacity);
 			packet = kmalloc(sizeof(struct ipw_rx_packet)
 					+ new_capacity, GFP_ATOMIC);
 			if (!packet)
@@ -580,10 +585,6 @@
 		packet->length = 0;
 	}
 
-	/*
-	 * If this packet does not have sufficient capacity for the data we
-	 * want to add, then make it bigger.
-	 */
 	if (packet->length + minimum_free_space > packet->capacity) {
 		struct ipw_rx_packet *old_packet = packet;
 
@@ -610,13 +611,15 @@
 		kfree(packet);
 	else {
 		hw->rx_pool_size++;
-		list_add_tail(&packet->queue, &hw->rx_pool);
+		list_add(&packet->queue, &hw->rx_pool);
 	}
 }
 
 static void queue_received_packet(struct ipw_hardware *hw,
-				  unsigned int protocol, unsigned int address,
-				  unsigned char *data, int length, int is_last)
+				  unsigned int protocol,
+				  unsigned int address,
+				  const unsigned char *data, int length,
+				  int is_last)
 {
 	unsigned int channel_idx = address - 1;
 	struct ipw_rx_packet *packet = NULL;
@@ -658,9 +661,9 @@
 			packet = *assem;
 			*assem = NULL;
 			/* Count queued DATA bytes only */
-			spin_lock_irqsave(&hw->spinlock, flags);
+			spin_lock_irqsave(&hw->lock, flags);
 			hw->rx_bytes_queued += packet->length;
-			spin_unlock_irqrestore(&hw->spinlock, flags);
+			spin_unlock_irqrestore(&hw->lock, flags);
 		}
 	} else {
 		/* If it's a CTRL packet, don't assemble, just queue it. */
@@ -682,13 +685,13 @@
 	 * network layer.
 	 */
 	if (packet) {
-		spin_lock_irqsave(&hw->spinlock, flags);
+		spin_lock_irqsave(&hw->lock, flags);
 		list_add_tail(&packet->queue, &hw->rx_queue);
 		/* Block reception of incoming packets if queue is full. */
 		hw->blocking_rx =
-			hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE;
+			(hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE);
 
-		spin_unlock_irqrestore(&hw->spinlock, flags);
+		spin_unlock_irqrestore(&hw->lock, flags);
 		schedule_work(&hw->work_rx);
 	}
 }
@@ -702,7 +705,7 @@
 	    container_of(work_rx, struct ipw_hardware, work_rx);
 	unsigned long flags;
 
-	spin_lock_irqsave(&hw->spinlock, flags);
+	spin_lock_irqsave(&hw->lock, flags);
 	while (!list_empty(&hw->rx_queue)) {
 		struct ipw_rx_packet *packet =
 			list_first_entry(&hw->rx_queue,
@@ -720,7 +723,7 @@
 		if (packet->protocol == TL_PROTOCOLID_COM_DATA) {
 			if (hw->network != NULL) {
 				/* If the network hasn't been disconnected. */
-				spin_unlock_irqrestore(&hw->spinlock, flags);
+				spin_unlock_irqrestore(&hw->lock, flags);
 				/*
 				 * This must run unlocked due to tty processing
 				 * and mutex locking
@@ -731,7 +734,7 @@
 						(unsigned char *)packet
 						+ sizeof(struct ipw_rx_packet),
 						packet->length);
-				spin_lock_irqsave(&hw->spinlock, flags);
+				spin_lock_irqsave(&hw->lock, flags);
 			}
 			/* Count queued DATA bytes only */
 			hw->rx_bytes_queued -= packet->length;
@@ -755,15 +758,15 @@
 		if (hw->shutting_down)
 			break;
 	}
-	spin_unlock_irqrestore(&hw->spinlock, flags);
+	spin_unlock_irqrestore(&hw->lock, flags);
 }
 
 static void handle_received_CTRL_packet(struct ipw_hardware *hw,
 					unsigned int channel_idx,
-					unsigned char *data, int len)
+					const unsigned char *data, int len)
 {
-	struct ipw_control_packet_body *body =
-		(struct ipw_control_packet_body *) data;
+	const struct ipw_control_packet_body *body =
+		(const struct ipw_control_packet_body *) data;
 	unsigned int changed_mask;
 
 	if (len != sizeof(struct ipw_control_packet_body)) {
@@ -805,13 +808,13 @@
 }
 
 static void handle_received_packet(struct ipw_hardware *hw,
-				   union nl_packet *packet,
+				   const union nl_packet *packet,
 				   unsigned short len)
 {
 	unsigned int protocol = packet->hdr.protocol;
 	unsigned int address = packet->hdr.address;
 	unsigned int header_length;
-	unsigned char *data;
+	const unsigned char *data;
 	unsigned int data_len;
 	int is_last = packet->hdr.packet_rank & NL_LAST_PACKET;
 
@@ -850,7 +853,7 @@
 static void do_receive_packet(struct ipw_hardware *hw)
 {
 	unsigned len;
-	unsigned int i;
+	unsigned i;
 	unsigned char pkt[LL_MTU_MAX];
 
 	start_timing();
@@ -859,8 +862,7 @@
 		len = inw(hw->base_port + IODRR);
 		if (len > hw->ll_mtu) {
 			printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-			       ": received a packet of %u bytes - "
-			       "longer than the MTU!\n", len);
+			       ": received a packet of %u bytes - longer than the MTU!\n", len);
 			outw(DCR_RXDONE | DCR_RXRESET, hw->base_port + IODCR);
 			return;
 		}
@@ -873,18 +875,17 @@
 			pkt[i + 1] = (unsigned char) (data >> 8);
 		}
 	} else {
-		len = inw(hw->base_port + IODMADPR);
+		len = inw(hw->base_port);
 		if (len > hw->ll_mtu) {
 			printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-			       ": received a packet of %u bytes - "
-			       "longer than the MTU!\n", len);
+			       ": received a packet of %u bytes - longer than the MTU!\n", len);
 			writew(MEMRX_PCINTACKK,
 				&hw->memory_info_regs->memreg_pc_interrupt_ack);
 			return;
 		}
 
 		for (i = 0; i < len; i += 2) {
-			__le16 raw_data = inw(hw->base_port + IODMADPR);
+			__le16 raw_data = inw(hw->base_port);
 			unsigned short data = le16_to_cpu(raw_data);
 
 			pkt[i] = (unsigned char) data;
@@ -892,13 +893,15 @@
 		}
 
 		while ((i & 3) != 2) {
-			inw(hw->base_port + IODMADPR);
+			inw(hw->base_port);
 			i += 2;
 		}
 	}
 
 	acknowledge_data_read(hw);
 
+	swap_packet_bitfield_from_le(pkt);
+
 	if (ipwireless_debug)
 		dump_data_bytes("recv", pkt, len);
 
@@ -916,8 +919,7 @@
 	 * until setup is complete.
 	 */
 	return (hw->to_setup || hw->initializing
-			? PRIO_SETUP + 1 :
-			NL_NUM_OF_PRIORITIES);
+			? PRIO_SETUP + 1 : NL_NUM_OF_PRIORITIES);
 }
 
 /*
@@ -928,17 +930,17 @@
 	int received = 0;
 	unsigned long flags;
 
-	spin_lock_irqsave(&hw->spinlock, flags);
+	spin_lock_irqsave(&hw->lock, flags);
 	while (hw->rx_ready && !hw->blocking_rx) {
 		received = 1;
 		hw->rx_ready--;
-		spin_unlock_irqrestore(&hw->spinlock, flags);
+		spin_unlock_irqrestore(&hw->lock, flags);
 
 		do_receive_packet(hw);
 
-		spin_lock_irqsave(&hw->spinlock, flags);
+		spin_lock_irqsave(&hw->lock, flags);
 	}
-	spin_unlock_irqrestore(&hw->spinlock, flags);
+	spin_unlock_irqrestore(&hw->lock, flags);
 
 	return received;
 }
@@ -954,7 +956,7 @@
 	int more_to_send = 0;
 	unsigned long flags;
 
-	spin_lock_irqsave(&hw->spinlock, flags);
+	spin_lock_irqsave(&hw->lock, flags);
 	if (hw->tx_queued && hw->tx_ready) {
 		int priority;
 		struct ipw_tx_packet *packet = NULL;
@@ -975,17 +977,17 @@
 		}
 		if (!packet) {
 			hw->tx_queued = 0;
-			spin_unlock_irqrestore(&hw->spinlock, flags);
+			spin_unlock_irqrestore(&hw->lock, flags);
 			return 0;
 		}
 
-		spin_unlock_irqrestore(&hw->spinlock, flags);
+		spin_unlock_irqrestore(&hw->lock, flags);
 
 		/* Send */
 		do_send_packet(hw, packet);
 
 		/* Check if more to send */
-		spin_lock_irqsave(&hw->spinlock, flags);
+		spin_lock_irqsave(&hw->lock, flags);
 		for (priority = 0; priority < priority_limit; priority++)
 			if (!list_empty(&hw->tx_queue[priority])) {
 				more_to_send = 1;
@@ -995,7 +997,7 @@
 		if (!more_to_send)
 			hw->tx_queued = 0;
 	}
-	spin_unlock_irqrestore(&hw->spinlock, flags);
+	spin_unlock_irqrestore(&hw->lock, flags);
 
 	return more_to_send;
 }
@@ -1008,9 +1010,9 @@
 	struct ipw_hardware *hw = (struct ipw_hardware *) hw_;
 	unsigned long flags;
 
-	spin_lock_irqsave(&hw->spinlock, flags);
+	spin_lock_irqsave(&hw->lock, flags);
 	if (hw->shutting_down) {
-		spin_unlock_irqrestore(&hw->spinlock, flags);
+		spin_unlock_irqrestore(&hw->lock, flags);
 		return;
 	}
 
@@ -1019,7 +1021,7 @@
 		 * Initial setup data sent to hardware
 		 */
 		hw->to_setup = 2;
-		spin_unlock_irqrestore(&hw->spinlock, flags);
+		spin_unlock_irqrestore(&hw->lock, flags);
 
 		ipw_setup_hardware(hw);
 		ipw_send_setup_packet(hw);
@@ -1030,7 +1032,7 @@
 		int priority_limit = get_current_packet_priority(hw);
 		int again;
 
-		spin_unlock_irqrestore(&hw->spinlock, flags);
+		spin_unlock_irqrestore(&hw->lock, flags);
 
 		do {
 			again = send_pending_packet(hw, priority_limit);
@@ -1068,16 +1070,16 @@
 		/* Transmit complete. */
 		if (irqn & IR_TXINTR) {
 			ack |= IR_TXINTR;
-			spin_lock_irqsave(&hw->spinlock, flags);
+			spin_lock_irqsave(&hw->lock, flags);
 			hw->tx_ready = 1;
-			spin_unlock_irqrestore(&hw->spinlock, flags);
+			spin_unlock_irqrestore(&hw->lock, flags);
 		}
 		/* Received data */
 		if (irqn & IR_RXINTR) {
 			ack |= IR_RXINTR;
-			spin_lock_irqsave(&hw->spinlock, flags);
+			spin_lock_irqsave(&hw->lock, flags);
 			hw->rx_ready++;
-			spin_unlock_irqrestore(&hw->spinlock, flags);
+			spin_unlock_irqrestore(&hw->lock, flags);
 		}
 		if (ack != 0) {
 			outw(ack, hw->base_port + IOIR);
@@ -1128,9 +1130,8 @@
 			} else {
 				return IRQ_NONE;
 			}
-		} else {
+		} else
 			return IRQ_NONE;
-		}
 	}
 
 	/*
@@ -1149,9 +1150,9 @@
 		if (hw->serial_number_detected) {
 			if (memtx_serial != hw->last_memtx_serial) {
 				hw->last_memtx_serial = memtx_serial;
-				spin_lock_irqsave(&hw->spinlock, flags);
+				spin_lock_irqsave(&hw->lock, flags);
 				hw->rx_ready++;
-				spin_unlock_irqrestore(&hw->spinlock, flags);
+				spin_unlock_irqrestore(&hw->lock, flags);
 				rx = 1;
 			} else
 				/* Ignore 'Timer Recovery' duplicates. */
@@ -1166,18 +1167,18 @@
 				printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
 					": memreg_tx serial num detected\n");
 
-				spin_lock_irqsave(&hw->spinlock, flags);
+				spin_lock_irqsave(&hw->lock, flags);
 				hw->rx_ready++;
-				spin_unlock_irqrestore(&hw->spinlock, flags);
+				spin_unlock_irqrestore(&hw->lock, flags);
 			}
 			rx = 1;
 		}
 	}
 	if (memrxdone & MEMRX_RX_DONE) {
 		writew(0, &hw->memory_info_regs->memreg_rx_done);
-		spin_lock_irqsave(&hw->spinlock, flags);
+		spin_lock_irqsave(&hw->lock, flags);
 		hw->tx_ready = 1;
-		spin_unlock_irqrestore(&hw->spinlock, flags);
+		spin_unlock_irqrestore(&hw->lock, flags);
 		tx = 1;
 	}
 	if (tx)
@@ -1195,8 +1196,7 @@
 					": spurious interrupt - new_tx mode\n");
 			else {
 				printk(KERN_WARNING IPWIRELESS_PCCARD_NAME
-					": no valid memreg_tx value - "
-					"switching to the old memreg_tx\n");
+					": no valid memreg_tx value - switching to the old memreg_tx\n");
 				hw->memreg_tx =
 					&hw->memory_info_regs->memreg_tx_old;
 				try_mem_tx_old = 1;
@@ -1211,7 +1211,7 @@
 	return IRQ_HANDLED;
 }
 
-irqreturn_t ipwireless_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t ipwireless_interrupt(int irq, void *dev_id)
 {
 	struct ipw_hardware *hw = dev_id;
 
@@ -1226,9 +1226,9 @@
 	int priority_limit;
 	unsigned long flags;
 
-	spin_lock_irqsave(&hw->spinlock, flags);
+	spin_lock_irqsave(&hw->lock, flags);
 	priority_limit = get_current_packet_priority(hw);
-	spin_unlock_irqrestore(&hw->spinlock, flags);
+	spin_unlock_irqrestore(&hw->lock, flags);
 
 	while (send_pending_packet(hw, priority_limit));
 }
@@ -1238,10 +1238,10 @@
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&hw->spinlock, flags);
+	spin_lock_irqsave(&hw->lock, flags);
 	list_add_tail(&packet->queue, &hw->tx_queue[priority]);
 	hw->tx_queued++;
-	spin_unlock_irqrestore(&hw->spinlock, flags);
+	spin_unlock_irqrestore(&hw->lock, flags);
 
 	flush_packets_to_hw(hw);
 }
@@ -1291,21 +1291,20 @@
 }
 
 int ipwireless_send_packet(struct ipw_hardware *hw, unsigned int channel_idx,
-			    unsigned char *data, unsigned int length,
+			    const unsigned char *data, unsigned int length,
 			    void (*callback) (void *cb, unsigned int length),
 			    void *callback_data)
 {
 	struct ipw_tx_packet *packet;
 
-	packet = alloc_data_packet(length,
-			       (unsigned char) (channel_idx + 1),
-			       TL_PROTOCOLID_COM_DATA);
+	packet = alloc_data_packet(length, (channel_idx + 1),
+			TL_PROTOCOLID_COM_DATA);
 	if (!packet)
 		return -ENOMEM;
 	packet->packet_callback = callback;
 	packet->callback_data = callback_data;
-	memcpy((unsigned char *) packet +
-			sizeof(struct ipw_tx_packet), data, length);
+	memcpy((unsigned char *) packet + sizeof(struct ipw_tx_packet), data,
+			length);
 
 	send_packet(hw, PRIO_DATA, packet);
 	return 0;
@@ -1321,12 +1320,11 @@
 		protocolid = TL_PROTOCOLID_SETUP;
 
 	packet = alloc_ctrl_packet(sizeof(struct ipw_control_packet),
-			(unsigned char) (channel_idx + 1),
-			protocolid, line);
+			(channel_idx + 1), protocolid, line);
 	if (!packet)
 		return -ENOMEM;
 	packet->header.length = sizeof(struct ipw_control_packet_body);
-	packet->body.value = (unsigned char) (state == 0 ? 0 : 1);
+	packet->body.value = (state == 0 ? 0 : 1);
 	send_packet(hw, prio, &packet->header);
 	return 0;
 }
@@ -1504,8 +1502,7 @@
 	if (vers_no == TL_SETUP_VERSION)
 		__handle_setup_get_version_rsp(hw);
 	else
-		printk(KERN_ERR
-				IPWIRELESS_PCCARD_NAME
+		printk(KERN_ERR IPWIRELESS_PCCARD_NAME
 				": invalid hardware version no %u\n",
 				(unsigned int) vers_no);
 }
@@ -1528,10 +1525,10 @@
 
 static void handle_received_SETUP_packet(struct ipw_hardware *hw,
 					 unsigned int address,
-					 unsigned char *data, int len,
+					 const unsigned char *data, int len,
 					 int is_last)
 {
-	union ipw_setup_rx_msg *rx_msg = (union ipw_setup_rx_msg *) data;
+	const union ipw_setup_rx_msg *rx_msg = (const union ipw_setup_rx_msg *) data;
 
 	if (address != ADDR_SETUP_PROT) {
 		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
@@ -1629,7 +1626,7 @@
 
 	INIT_LIST_HEAD(&hw->rx_queue);
 	INIT_LIST_HEAD(&hw->rx_pool);
-	spin_lock_init(&hw->spinlock);
+	spin_lock_init(&hw->lock);
 	tasklet_init(&hw->tasklet, ipwireless_do_tasklet, (unsigned long) hw);
 	INIT_WORK(&hw->work_rx, ipw_receive_data_work);
 	setup_timer(&hw->setup_timer, ipwireless_setup_timer,
@@ -1651,8 +1648,8 @@
 		enable_irq(hw->irq);
 	}
 	hw->base_port = base_port;
-	hw->hw_version = is_v2_card ? HW_VERSION_2 : HW_VERSION_1;
-	hw->ll_mtu = hw->hw_version == HW_VERSION_1 ? LL_MTU_V1 : LL_MTU_V2;
+	hw->hw_version = (is_v2_card ? HW_VERSION_2 : HW_VERSION_1);
+	hw->ll_mtu = (hw->hw_version == HW_VERSION_1 ? LL_MTU_V1 : LL_MTU_V2);
 	hw->memregs_CCR = (struct MEMCCR __iomem *)
 			((unsigned short __iomem *) attr_memory + 0x200);
 	hw->memory_info_regs = (struct MEMINFREG __iomem *) common_memory;
@@ -1695,10 +1692,10 @@
 		if (is_card_present(hw)) {
 			unsigned long flags;
 
-			spin_lock_irqsave(&hw->spinlock, flags);
+			spin_lock_irqsave(&hw->lock, flags);
 			hw->to_setup = 1;
 			hw->tx_ready = 1;
-			spin_unlock_irqrestore(&hw->spinlock, flags);
+			spin_unlock_irqrestore(&hw->lock, flags);
 			tasklet_schedule(&hw->tasklet);
 		}
 
diff --git a/drivers/char/pcmcia/ipwireless/hardware.h b/drivers/char/pcmcia/ipwireless/hardware.h
index 19ce5eb..90a8590 100644
--- a/drivers/char/pcmcia/ipwireless/hardware.h
+++ b/drivers/char/pcmcia/ipwireless/hardware.h
@@ -34,14 +34,14 @@
 
 struct ipw_hardware *ipwireless_hardware_create(void);
 void ipwireless_hardware_free(struct ipw_hardware *hw);
-irqreturn_t ipwireless_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t ipwireless_interrupt(int irq, void *dev_id);
 int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx,
 		int state);
 int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx,
 		int state);
 int ipwireless_send_packet(struct ipw_hardware *hw,
 			    unsigned int channel_idx,
-			    unsigned char *data,
+			    const unsigned char *data,
 			    unsigned int length,
 			    void (*packet_sent_callback) (void *cb,
 							  unsigned int length),
diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c
index cc7dcea..5eca7a9 100644
--- a/drivers/char/pcmcia/ipwireless/main.c
+++ b/drivers/char/pcmcia/ipwireless/main.c
@@ -49,7 +49,7 @@
 /* Debug mode: more verbose, print sent/recv bytes */
 int ipwireless_debug;
 int ipwireless_loopback;
-int ipwireless_out_queue = 1;
+int ipwireless_out_queue = 10;
 
 module_param_named(debug, ipwireless_debug, int, 0);
 module_param_named(loopback, ipwireless_loopback, int, 0);
@@ -57,7 +57,7 @@
 MODULE_PARM_DESC(debug, "switch on debug messages [0]");
 MODULE_PARM_DESC(loopback,
 		"debug: enable ras_raw channel [0]");
-MODULE_PARM_DESC(out_queue, "debug: set size of outgoing queue [1]");
+MODULE_PARM_DESC(out_queue, "debug: set size of outgoing PPP queue [10]");
 
 /* Executes in process context. */
 static void signalled_reboot_work(struct work_struct *work_reboot)
@@ -88,8 +88,6 @@
 	unsigned short buf[64];
 	cisparse_t parse;
 	unsigned short cor_value;
-	win_req_t request_attr_memory;
-	win_req_t request_common_memory;
 	memreq_t memreq_attr_memory;
 	memreq_t memreq_common_memory;
 
@@ -188,6 +186,9 @@
 		goto exit0;
 	}
 
+	request_region(link->io.BasePort1, link->io.NumPorts1,
+			IPWIRELESS_PCCARD_NAME);
+
 	/* memory settings */
 
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
@@ -214,16 +215,16 @@
 	}
 
 	if (parse.cftable_entry.mem.nwin > 0) {
-		request_common_memory.Attributes =
+		ipw->request_common_memory.Attributes =
 			WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE;
-		request_common_memory.Base =
+		ipw->request_common_memory.Base =
 			parse.cftable_entry.mem.win[0].host_addr;
-		request_common_memory.Size = parse.cftable_entry.mem.win[0].len;
-		if (request_common_memory.Size < 0x1000)
-			request_common_memory.Size = 0x1000;
-		request_common_memory.AccessSpeed = 0;
+		ipw->request_common_memory.Size = parse.cftable_entry.mem.win[0].len;
+		if (ipw->request_common_memory.Size < 0x1000)
+			ipw->request_common_memory.Size = 0x1000;
+		ipw->request_common_memory.AccessSpeed = 0;
 
-		ret = pcmcia_request_window(&link, &request_common_memory,
+		ret = pcmcia_request_window(&link, &ipw->request_common_memory,
 				&ipw->handle_common_memory);
 
 		if (ret != CS_SUCCESS) {
@@ -246,16 +247,18 @@
 		ipw->is_v2_card =
 			parse.cftable_entry.mem.win[0].len == 0x100;
 
-		ipw->common_memory = ioremap(request_common_memory.Base,
-				request_common_memory.Size);
+		ipw->common_memory = ioremap(ipw->request_common_memory.Base,
+				ipw->request_common_memory.Size);
+		request_mem_region(ipw->request_common_memory.Base,
+				ipw->request_common_memory.Size, IPWIRELESS_PCCARD_NAME);
 
-		request_attr_memory.Attributes =
+		ipw->request_attr_memory.Attributes =
 			WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE;
-		request_attr_memory.Base = 0;
-		request_attr_memory.Size = 0;	/* this used to be 0x1000 */
-		request_attr_memory.AccessSpeed = 0;
+		ipw->request_attr_memory.Base = 0;
+		ipw->request_attr_memory.Size = 0;	/* this used to be 0x1000 */
+		ipw->request_attr_memory.AccessSpeed = 0;
 
-		ret = pcmcia_request_window(&link, &request_attr_memory,
+		ret = pcmcia_request_window(&link, &ipw->request_attr_memory,
 				&ipw->handle_attr_memory);
 
 		if (ret != CS_SUCCESS) {
@@ -274,8 +277,10 @@
 			goto exit2;
 		}
 
-		ipw->attr_memory = ioremap(request_attr_memory.Base,
-				request_attr_memory.Size);
+		ipw->attr_memory = ioremap(ipw->request_attr_memory.Base,
+				ipw->request_attr_memory.Size);
+		request_mem_region(ipw->request_attr_memory.Base, ipw->request_attr_memory.Size,
+				IPWIRELESS_PCCARD_NAME);
 	}
 
 	INIT_WORK(&ipw->work_reboot, signalled_reboot_work);
@@ -311,14 +316,13 @@
 			(unsigned int) link->irq.AssignedIRQ);
 	if (ipw->attr_memory && ipw->common_memory)
 		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-				": attr memory 0x%08lx-0x%08lx, "
-				"common memory 0x%08lx-0x%08lx\n",
-				request_attr_memory.Base,
-				request_attr_memory.Base
-				+ request_attr_memory.Size - 1,
-				request_common_memory.Base,
-				request_common_memory.Base
-				+ request_common_memory.Size - 1);
+			": attr memory 0x%08lx-0x%08lx, common memory 0x%08lx-0x%08lx\n",
+			ipw->request_attr_memory.Base,
+			ipw->request_attr_memory.Base
+			+ ipw->request_attr_memory.Size - 1,
+			ipw->request_common_memory.Base,
+			ipw->request_common_memory.Base
+			+ ipw->request_common_memory.Size - 1);
 
 	ipw->network = ipwireless_network_create(ipw->hardware);
 	if (!ipw->network)
@@ -350,12 +354,16 @@
 	pcmcia_disable_device(link);
 exit3:
 	if (ipw->attr_memory) {
+		release_mem_region(ipw->request_attr_memory.Base,
+				ipw->request_attr_memory.Size);
 		iounmap(ipw->attr_memory);
 		pcmcia_release_window(ipw->handle_attr_memory);
 		pcmcia_disable_device(link);
 	}
 exit2:
 	if (ipw->common_memory) {
+		release_mem_region(ipw->request_common_memory.Base,
+				ipw->request_common_memory.Size);
 		iounmap(ipw->common_memory);
 		pcmcia_release_window(ipw->handle_common_memory);
 	}
@@ -367,19 +375,25 @@
 
 static void release_ipwireless(struct ipw_dev *ipw)
 {
-	struct pcmcia_device *link = ipw->link;
+	pcmcia_disable_device(ipw->link);
 
-	pcmcia_disable_device(link);
-
-	if (ipw->common_memory)
+	if (ipw->common_memory) {
+		release_mem_region(ipw->request_common_memory.Base,
+				ipw->request_common_memory.Size);
 		iounmap(ipw->common_memory);
-	if (ipw->attr_memory)
+	}
+	if (ipw->attr_memory) {
+		release_mem_region(ipw->request_attr_memory.Base,
+				ipw->request_attr_memory.Size);
 		iounmap(ipw->attr_memory);
+	}
 	if (ipw->common_memory)
 		pcmcia_release_window(ipw->handle_common_memory);
 	if (ipw->attr_memory)
 		pcmcia_release_window(ipw->handle_attr_memory);
-	pcmcia_disable_device(link);
+
+	/* Break the link with Card Services */
+	pcmcia_disable_device(ipw->link);
 }
 
 /*
@@ -437,10 +451,6 @@
 
 	release_ipwireless(ipw);
 
-	/* Break the link with Card Services */
-	if (link)
-		pcmcia_disable_device(link);
-
 	if (ipw->tty != NULL)
 		ipwireless_tty_free(ipw->tty);
 	if (ipw->network != NULL)
diff --git a/drivers/char/pcmcia/ipwireless/main.h b/drivers/char/pcmcia/ipwireless/main.h
index 1bfdcc8..0e0363a 100644
--- a/drivers/char/pcmcia/ipwireless/main.h
+++ b/drivers/char/pcmcia/ipwireless/main.h
@@ -45,10 +45,15 @@
 struct ipw_dev {
 	struct pcmcia_device *link;
 	int is_v2_card;
+
 	window_handle_t handle_attr_memory;
 	void __iomem *attr_memory;
+	win_req_t request_attr_memory;
+
 	window_handle_t handle_common_memory;
 	void __iomem *common_memory;
+	win_req_t request_common_memory;
+
 	dev_node_t nodes[2];
 	/* Reference to attribute memory, containing CIS data */
 	void *attribute_memory;
diff --git a/drivers/char/pcmcia/ipwireless/network.c b/drivers/char/pcmcia/ipwireless/network.c
index fe914d3..590762a 100644
--- a/drivers/char/pcmcia/ipwireless/network.c
+++ b/drivers/char/pcmcia/ipwireless/network.c
@@ -29,7 +29,6 @@
 #include "main.h"
 #include "tty.h"
 
-#define MAX_OUTGOING_PACKETS_QUEUED   ipwireless_out_queue
 #define MAX_ASSOCIATED_TTYS 2
 
 #define SC_RCV_BITS     (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
@@ -46,7 +45,7 @@
 	/* Number of packets queued up in hardware module. */
 	int outgoing_packets_queued;
 	/* Spinlock to avoid interrupts during shutdown */
-	spinlock_t spinlock;
+	spinlock_t lock;
 	struct mutex close_lock;
 
 	/* PPP ioctl data, not actually used anywere */
@@ -68,20 +67,20 @@
 	struct ipw_network *network = callback_data;
 	unsigned long flags;
 
-	spin_lock_irqsave(&network->spinlock, flags);
+	spin_lock_irqsave(&network->lock, flags);
 	network->outgoing_packets_queued--;
 	if (network->ppp_channel != NULL) {
 		if (network->ppp_blocked) {
 			network->ppp_blocked = 0;
-			spin_unlock_irqrestore(&network->spinlock, flags);
+			spin_unlock_irqrestore(&network->lock, flags);
 			ppp_output_wakeup(network->ppp_channel);
 			if (ipwireless_debug)
-				printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+				printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
 				       ": ppp unblocked\n");
 		} else
-			spin_unlock_irqrestore(&network->spinlock, flags);
+			spin_unlock_irqrestore(&network->lock, flags);
 	} else
-		spin_unlock_irqrestore(&network->spinlock, flags);
+		spin_unlock_irqrestore(&network->lock, flags);
 }
 
 /*
@@ -93,8 +92,8 @@
 	struct ipw_network *network = ppp_channel->private;
 	unsigned long flags;
 
-	spin_lock_irqsave(&network->spinlock, flags);
-	if (network->outgoing_packets_queued < MAX_OUTGOING_PACKETS_QUEUED) {
+	spin_lock_irqsave(&network->lock, flags);
+	if (network->outgoing_packets_queued < ipwireless_out_queue) {
 		unsigned char *buf;
 		static unsigned char header[] = {
 			PPP_ALLSTATIONS, /* 0xff */
@@ -103,7 +102,7 @@
 		int ret;
 
 		network->outgoing_packets_queued++;
-		spin_unlock_irqrestore(&network->spinlock, flags);
+		spin_unlock_irqrestore(&network->lock, flags);
 
 		/*
 		 * If we have the requested amount of headroom in the skb we
@@ -144,7 +143,9 @@
 		 * needs to be unblocked once we are ready to send.
 		 */
 		network->ppp_blocked = 1;
-		spin_unlock_irqrestore(&network->spinlock, flags);
+		spin_unlock_irqrestore(&network->lock, flags);
+		if (ipwireless_debug)
+			printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": ppp blocked\n");
 		return 0;
 	}
 }
@@ -249,11 +250,11 @@
 				work_go_online);
 	unsigned long flags;
 
-	spin_lock_irqsave(&network->spinlock, flags);
+	spin_lock_irqsave(&network->lock, flags);
 	if (!network->ppp_channel) {
 		struct ppp_channel *channel;
 
-		spin_unlock_irqrestore(&network->spinlock, flags);
+		spin_unlock_irqrestore(&network->lock, flags);
 		channel = kzalloc(sizeof(struct ppp_channel), GFP_KERNEL);
 		if (!channel) {
 			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
@@ -273,10 +274,10 @@
 		network->xaccm[3] = 0x60000000U;
 		network->raccm = ~0U;
 		ppp_register_channel(channel);
-		spin_lock_irqsave(&network->spinlock, flags);
+		spin_lock_irqsave(&network->lock, flags);
 		network->ppp_channel = channel;
 	}
-	spin_unlock_irqrestore(&network->spinlock, flags);
+	spin_unlock_irqrestore(&network->lock, flags);
 }
 
 static void do_go_offline(struct work_struct *work_go_offline)
@@ -287,16 +288,16 @@
 	unsigned long flags;
 
 	mutex_lock(&network->close_lock);
-	spin_lock_irqsave(&network->spinlock, flags);
+	spin_lock_irqsave(&network->lock, flags);
 	if (network->ppp_channel != NULL) {
 		struct ppp_channel *channel = network->ppp_channel;
 
 		network->ppp_channel = NULL;
-		spin_unlock_irqrestore(&network->spinlock, flags);
+		spin_unlock_irqrestore(&network->lock, flags);
 		mutex_unlock(&network->close_lock);
 		ppp_unregister_channel(channel);
 	} else {
-		spin_unlock_irqrestore(&network->spinlock, flags);
+		spin_unlock_irqrestore(&network->lock, flags);
 		mutex_unlock(&network->close_lock);
 	}
 }
@@ -381,18 +382,18 @@
 			 * the PPP layer.
 			 */
 			mutex_lock(&network->close_lock);
-			spin_lock_irqsave(&network->spinlock, flags);
+			spin_lock_irqsave(&network->lock, flags);
 			if (network->ppp_channel != NULL) {
 				struct sk_buff *skb;
 
-				spin_unlock_irqrestore(&network->spinlock,
+				spin_unlock_irqrestore(&network->lock,
 						flags);
 
 				/* Send the data to the ppp_generic module. */
 				skb = ipw_packet_received_skb(data, length);
 				ppp_input(network->ppp_channel, skb);
 			} else
-				spin_unlock_irqrestore(&network->spinlock,
+				spin_unlock_irqrestore(&network->lock,
 						flags);
 			mutex_unlock(&network->close_lock);
 		}
@@ -410,7 +411,7 @@
 	if (!network)
 		return NULL;
 
-	spin_lock_init(&network->spinlock);
+	spin_lock_init(&network->lock);
 	mutex_init(&network->close_lock);
 
 	network->hardware = hw;
@@ -478,10 +479,10 @@
 	int ret = -1;
 	unsigned long flags;
 
-	spin_lock_irqsave(&network->spinlock, flags);
+	spin_lock_irqsave(&network->lock, flags);
 	if (network->ppp_channel != NULL)
 		ret = ppp_channel_index(network->ppp_channel);
-	spin_unlock_irqrestore(&network->spinlock, flags);
+	spin_unlock_irqrestore(&network->lock, flags);
 
 	return ret;
 }
@@ -491,10 +492,15 @@
 	int ret = -1;
 	unsigned long flags;
 
-	spin_lock_irqsave(&network->spinlock, flags);
+	spin_lock_irqsave(&network->lock, flags);
 	if (network->ppp_channel != NULL)
 		ret = ppp_unit_number(network->ppp_channel);
-	spin_unlock_irqrestore(&network->spinlock, flags);
+	spin_unlock_irqrestore(&network->lock, flags);
 
 	return ret;
 }
+
+int ipwireless_ppp_mru(const struct ipw_network *network)
+{
+	return network->mru;
+}
diff --git a/drivers/char/pcmcia/ipwireless/network.h b/drivers/char/pcmcia/ipwireless/network.h
index ccacd26..561f765 100644
--- a/drivers/char/pcmcia/ipwireless/network.h
+++ b/drivers/char/pcmcia/ipwireless/network.h
@@ -48,5 +48,6 @@
 void ipwireless_ppp_close(struct ipw_network *net);
 int ipwireless_ppp_channel_index(struct ipw_network *net);
 int ipwireless_ppp_unit_number(struct ipw_network *net);
+int ipwireless_ppp_mru(const struct ipw_network *net);
 
 #endif
diff --git a/drivers/char/pcmcia/ipwireless/tty.c b/drivers/char/pcmcia/ipwireless/tty.c
index 42f3815..b141450 100644
--- a/drivers/char/pcmcia/ipwireless/tty.c
+++ b/drivers/char/pcmcia/ipwireless/tty.c
@@ -259,7 +259,7 @@
 	}
 
 	ret = ipwireless_send_packet(tty->hardware, IPW_CHANNEL_RAS,
-			       (unsigned char *) buf, count,
+			       buf, count,
 			       ipw_write_packet_sent_callback, tty);
 	if (ret == -1) {
 		mutex_unlock(&tty->ipw_tty_mutex);
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 5405769..5ce07b5 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -94,7 +94,7 @@
  */
 void cpuidle_uninstall_idle_handler(void)
 {
-	if (enabled_devices && (pm_idle != pm_idle_old)) {
+	if (enabled_devices && pm_idle_old && (pm_idle != pm_idle_old)) {
 		pm_idle = pm_idle_old;
 		cpuidle_kick_cpus();
 	}
diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c
index 48d084b..3c855ff 100644
--- a/drivers/i2c/busses/i2c-bfin-twi.c
+++ b/drivers/i2c/busses/i2c-bfin-twi.c
@@ -49,6 +49,8 @@
 	struct i2c_msg 		*pmsg;
 	int			msg_num;
 	int			cur_msg;
+	u16			saved_clkdiv;
+	u16			saved_control;
 	void __iomem		*regs_base;
 };
 
@@ -565,32 +567,43 @@
 	       I2C_FUNC_I2C;
 }
 
-
 static struct i2c_algorithm bfin_twi_algorithm = {
 	.master_xfer   = bfin_twi_master_xfer,
 	.smbus_xfer    = bfin_twi_smbus_xfer,
 	.functionality = bfin_twi_functionality,
 };
 
-
-static int i2c_bfin_twi_suspend(struct platform_device *dev, pm_message_t state)
+static int i2c_bfin_twi_suspend(struct platform_device *pdev, pm_message_t state)
 {
-	struct bfin_twi_iface *iface = platform_get_drvdata(dev);
+	struct bfin_twi_iface *iface = platform_get_drvdata(pdev);
+
+	iface->saved_clkdiv = read_CLKDIV(iface);
+	iface->saved_control = read_CONTROL(iface);
+
+	free_irq(iface->irq, iface);
 
 	/* Disable TWI */
-	write_CONTROL(iface, read_CONTROL(iface) & ~TWI_ENA);
-	SSYNC();
+	write_CONTROL(iface, iface->saved_control & ~TWI_ENA);
 
 	return 0;
 }
 
-static int i2c_bfin_twi_resume(struct platform_device *dev)
+static int i2c_bfin_twi_resume(struct platform_device *pdev)
 {
-	struct bfin_twi_iface *iface = platform_get_drvdata(dev);
+	struct bfin_twi_iface *iface = platform_get_drvdata(pdev);
 
-	/* Enable TWI */
-	write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA);
-	SSYNC();
+	int rc = request_irq(iface->irq, bfin_twi_interrupt_entry,
+		IRQF_DISABLED, pdev->name, iface);
+	if (rc) {
+		dev_err(&pdev->dev, "Can't get IRQ %d !\n", iface->irq);
+		return -ENODEV;
+	}
+
+	/* Resume TWI interface clock as specified */
+	write_CLKDIV(iface, iface->saved_clkdiv);
+
+	/* Resume TWI */
+	write_CONTROL(iface, iface->saved_control);
 
 	return 0;
 }
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
index 79b455a..32104ea 100644
--- a/drivers/i2c/busses/i2c-gpio.c
+++ b/drivers/i2c/busses/i2c-gpio.c
@@ -77,7 +77,7 @@
 	return gpio_get_value(pdata->scl_pin);
 }
 
-static int __init i2c_gpio_probe(struct platform_device *pdev)
+static int __devinit i2c_gpio_probe(struct platform_device *pdev)
 {
 	struct i2c_gpio_platform_data *pdata;
 	struct i2c_algo_bit_data *bit_data;
@@ -174,7 +174,7 @@
 	return ret;
 }
 
-static int __exit i2c_gpio_remove(struct platform_device *pdev)
+static int __devexit i2c_gpio_remove(struct platform_device *pdev)
 {
 	struct i2c_gpio_platform_data *pdata;
 	struct i2c_adapter *adap;
@@ -196,14 +196,15 @@
 		.name	= "i2c-gpio",
 		.owner	= THIS_MODULE,
 	},
-	.remove		= __exit_p(i2c_gpio_remove),
+	.probe		= i2c_gpio_probe,
+	.remove		= __devexit_p(i2c_gpio_remove),
 };
 
 static int __init i2c_gpio_init(void)
 {
 	int ret;
 
-	ret = platform_driver_probe(&i2c_gpio_driver, i2c_gpio_probe);
+	ret = platform_driver_register(&i2c_gpio_driver);
 	if (ret)
 		printk(KERN_ERR "i2c-gpio: probe failed: %d\n", ret);
 
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 007390a..4864723 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -33,6 +33,7 @@
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/cpufreq.h>
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
@@ -64,6 +65,7 @@
 	unsigned int		tx_setup;
 
 	enum s3c24xx_i2c_state	state;
+	unsigned long		clkrate;
 
 	void __iomem		*regs;
 	struct clk		*clk;
@@ -71,6 +73,10 @@
 	struct resource		*irq;
 	struct resource		*ioarea;
 	struct i2c_adapter	adap;
+
+#ifdef CONFIG_CPU_FREQ
+	struct notifier_block	freq_transition;
+#endif
 };
 
 /* default platform data to use if not supplied in the platform_device
@@ -501,6 +507,9 @@
 	unsigned long timeout;
 	int ret;
 
+	if (!readl(i2c->regs + S3C2410_IICCON) & S3C2410_IICCON_IRQEN)
+		return -EIO;
+
 	ret = s3c24xx_i2c_set_master(i2c);
 	if (ret != 0) {
 		dev_err(i2c->dev, "cannot get bus (error %d)\n", ret);
@@ -636,27 +645,28 @@
 	return (diff >= -2 && diff <= 2);
 }
 
-/* s3c24xx_i2c_getdivisor
+/* s3c24xx_i2c_clockrate
  *
  * work out a divisor for the user requested frequency setting,
  * either by the requested frequency, or scanning the acceptable
  * range of frequencies until something is found
 */
 
-static int s3c24xx_i2c_getdivisor(struct s3c24xx_i2c *i2c,
-				  struct s3c2410_platform_i2c *pdata,
-				  unsigned long *iicon,
-				  unsigned int *got)
+static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
 {
+	struct s3c2410_platform_i2c *pdata;
 	unsigned long clkin = clk_get_rate(i2c->clk);
-	
 	unsigned int divs, div1;
+	u32 iiccon;
 	int freq;
 	int start, end;
 
+	i2c->clkrate = clkin;
+
+	pdata = s3c24xx_i2c_get_platformdata(i2c->adap.dev.parent);
 	clkin /= 1000;		/* clkin now in KHz */
      
-	dev_dbg(i2c->dev,  "pdata %p, freq %lu %lu..%lu\n",
+	dev_dbg(i2c->dev, "pdata %p, freq %lu %lu..%lu\n",
 		 pdata, pdata->bus_freq, pdata->min_freq, pdata->max_freq);
 
 	if (pdata->bus_freq != 0) {
@@ -688,11 +698,79 @@
 
  found:
 	*got = freq;
-	*iicon |= (divs-1);
-	*iicon |= (div1 == 512) ? S3C2410_IICCON_TXDIV_512 : 0;
+
+	iiccon = readl(i2c->regs + S3C2410_IICCON);
+	iiccon &= ~(S3C2410_IICCON_SCALEMASK | S3C2410_IICCON_TXDIV_512);
+	iiccon |= (divs-1);
+
+	if (div1 == 512)
+		iiccon |= S3C2410_IICCON_TXDIV_512;
+
+	writel(iiccon, i2c->regs + S3C2410_IICCON);
+
 	return 0;
 }
 
+#ifdef CONFIG_CPU_FREQ
+
+#define freq_to_i2c(_n) container_of(_n, struct s3c24xx_i2c, freq_transition)
+
+static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb,
+					  unsigned long val, void *data)
+{
+	struct s3c24xx_i2c *i2c = freq_to_i2c(nb);
+	unsigned long flags;
+	unsigned int got;
+	int delta_f;
+	int ret;
+
+	delta_f = clk_get_rate(i2c->clk) - i2c->clkrate;
+
+	/* if we're post-change and the input clock has slowed down
+	 * or at pre-change and the clock is about to speed up, then
+	 * adjust our clock rate. <0 is slow, >0 speedup.
+	 */
+
+	if ((val == CPUFREQ_POSTCHANGE && delta_f < 0) ||
+	    (val == CPUFREQ_PRECHANGE && delta_f > 0)) {
+		spin_lock_irqsave(&i2c->lock, flags);
+		ret = s3c24xx_i2c_clockrate(i2c, &got);
+		spin_unlock_irqrestore(&i2c->lock, flags);
+
+		if (ret < 0)
+			dev_err(i2c->dev, "cannot find frequency\n");
+		else
+			dev_info(i2c->dev, "setting freq %d\n", got);
+	}
+
+	return 0;
+}
+
+static inline int s3c24xx_i2c_register_cpufreq(struct s3c24xx_i2c *i2c)
+{
+	i2c->freq_transition.notifier_call = s3c24xx_i2c_cpufreq_transition;
+
+	return cpufreq_register_notifier(&i2c->freq_transition,
+					 CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c)
+{
+	cpufreq_unregister_notifier(&i2c->freq_transition,
+				    CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+#else
+static inline int s3c24xx_i2c_register_cpufreq(struct s3c24xx_i2c *i2c)
+{
+	return 0;
+}
+
+static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c)
+{
+}
+#endif
+
 /* s3c24xx_i2c_init
  *
  * initialise the controller, set the IO lines and frequency 
@@ -719,9 +797,12 @@
 
 	dev_info(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr);
 
+	writel(iicon, i2c->regs + S3C2410_IICCON);
+
 	/* we need to work out the divisors for the clock... */
 
-	if (s3c24xx_i2c_getdivisor(i2c, pdata, &iicon, &freq) != 0) {
+	if (s3c24xx_i2c_clockrate(i2c, &freq) != 0) {
+		writel(0, i2c->regs + S3C2410_IICCON);
 		dev_err(i2c->dev, "cannot meet bus frequency required\n");
 		return -EINVAL;
 	}
@@ -730,8 +811,6 @@
 
 	dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq);
 	dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon);
-	
-	writel(iicon, i2c->regs + S3C2410_IICCON);
 
 	/* check for s3c2440 i2c controller  */
 
@@ -752,9 +831,12 @@
 static int s3c24xx_i2c_probe(struct platform_device *pdev)
 {
 	struct s3c24xx_i2c *i2c = &s3c24xx_i2c;
+	struct s3c2410_platform_i2c *pdata;
 	struct resource *res;
 	int ret;
 
+	pdata = s3c24xx_i2c_get_platformdata(&pdev->dev);
+
 	/* find the clock and enable it */
 
 	i2c->dev = &pdev->dev;
@@ -832,10 +914,24 @@
 	dev_dbg(&pdev->dev, "irq resource %p (%lu)\n", res,
 		(unsigned long)res->start);
 
-	ret = i2c_add_adapter(&i2c->adap);
+	ret = s3c24xx_i2c_register_cpufreq(i2c);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to register cpufreq notifier\n");
+		goto err_irq;
+	}
+
+	/* Note, previous versions of the driver used i2c_add_adapter()
+	 * to add the bus at any number. We now pass the bus number via
+	 * the platform data, so if unset it will now default to always
+	 * being bus 0.
+	 */
+
+	i2c->adap.nr = pdata->bus_num;
+
+	ret = i2c_add_numbered_adapter(&i2c->adap);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to add bus to i2c core\n");
-		goto err_irq;
+		goto err_cpufreq;
 	}
 
 	platform_set_drvdata(pdev, i2c);
@@ -843,6 +939,9 @@
 	dev_info(&pdev->dev, "%s: S3C I2C adapter\n", i2c->adap.dev.bus_id);
 	return 0;
 
+ err_cpufreq:
+	s3c24xx_i2c_deregister_cpufreq(i2c);
+
  err_irq:
 	free_irq(i2c->irq->start, i2c);
 
@@ -870,6 +969,8 @@
 {
 	struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
 
+	s3c24xx_i2c_deregister_cpufreq(i2c);
+
 	i2c_del_adapter(&i2c->adap);
 	free_irq(i2c->irq->start, i2c);
 
diff --git a/include/asm-arm/plat-s3c/iic.h b/include/asm-arm/plat-s3c/iic.h
index 71211c8..d08a1f2 100644
--- a/include/asm-arm/plat-s3c/iic.h
+++ b/include/asm-arm/plat-s3c/iic.h
@@ -21,6 +21,7 @@
 */
 
 struct s3c2410_platform_i2c {
+	int		bus_num;	/* bus number to use */
 	unsigned int	flags;
 	unsigned int	slave_addr;	/* slave address for controller */
 	unsigned long	bus_freq;	/* standard bus frequency */
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 743d85f..1c2e3ec 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -226,7 +226,7 @@
 
 extern void dccp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb);
 
-extern int  dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb);
+extern int  dccp_retransmit_skb(struct sock *sk);
 
 extern void dccp_send_ack(struct sock *sk);
 extern void dccp_reqsk_send_ack(struct sk_buff *sk, struct request_sock *rsk);
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index a835b88..882c5c4 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -196,8 +196,8 @@
 static void dccp_v4_err(struct sk_buff *skb, u32 info)
 {
 	const struct iphdr *iph = (struct iphdr *)skb->data;
-	const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data +
-							(iph->ihl << 2));
+	const u8 offset = iph->ihl << 2;
+	const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset);
 	struct dccp_sock *dp;
 	struct inet_sock *inet;
 	const int type = icmp_hdr(skb)->type;
@@ -207,7 +207,8 @@
 	int err;
 	struct net *net = dev_net(skb->dev);
 
-	if (skb->len < (iph->ihl << 2) + 8) {
+	if (skb->len < offset + sizeof(*dh) ||
+	    skb->len < offset + __dccp_basic_hdr_len(dh)) {
 		ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
 		return;
 	}
@@ -238,7 +239,7 @@
 	dp = dccp_sk(sk);
 	seq = dccp_hdr_seq(dh);
 	if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) &&
-	    !between48(seq, dp->dccps_swl, dp->dccps_swh)) {
+	    !between48(seq, dp->dccps_awl, dp->dccps_awh)) {
 		NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
 		goto out;
 	}
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index da50912..5e1ee0d 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -89,12 +89,19 @@
 {
 	struct ipv6hdr *hdr = (struct ipv6hdr *)skb->data;
 	const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset);
+	struct dccp_sock *dp;
 	struct ipv6_pinfo *np;
 	struct sock *sk;
 	int err;
 	__u64 seq;
 	struct net *net = dev_net(skb->dev);
 
+	if (skb->len < offset + sizeof(*dh) ||
+	    skb->len < offset + __dccp_basic_hdr_len(dh)) {
+		ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
+		return;
+	}
+
 	sk = inet6_lookup(net, &dccp_hashinfo,
 			&hdr->daddr, dh->dccph_dport,
 			&hdr->saddr, dh->dccph_sport, inet6_iif(skb));
@@ -116,6 +123,14 @@
 	if (sk->sk_state == DCCP_CLOSED)
 		goto out;
 
+	dp = dccp_sk(sk);
+	seq = dccp_hdr_seq(dh);
+	if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) &&
+	    !between48(seq, dp->dccps_awl, dp->dccps_awh)) {
+		NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
+		goto out;
+	}
+
 	np = inet6_sk(sk);
 
 	if (type == ICMPV6_PKT_TOOBIG) {
@@ -168,7 +183,6 @@
 
 	icmpv6_err_convert(type, code, &err);
 
-	seq = dccp_hdr_seq(dh);
 	/* Might be for an request_sock */
 	switch (sk->sk_state) {
 		struct request_sock *req, **prev;
diff --git a/net/dccp/output.c b/net/dccp/output.c
index fe20068..d06945c 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -53,8 +53,11 @@
 					  dccp_packet_hdr_len(dcb->dccpd_type);
 		int err, set_ack = 1;
 		u64 ackno = dp->dccps_gsr;
-
-		dccp_inc_seqno(&dp->dccps_gss);
+		/*
+		 * Increment GSS here already in case the option code needs it.
+		 * Update GSS for real only if option processing below succeeds.
+		 */
+		dcb->dccpd_seq = ADD48(dp->dccps_gss, 1);
 
 		switch (dcb->dccpd_type) {
 		case DCCP_PKT_DATA:
@@ -66,6 +69,9 @@
 
 		case DCCP_PKT_REQUEST:
 			set_ack = 0;
+			/* Use ISS on the first (non-retransmitted) Request. */
+			if (icsk->icsk_retransmits == 0)
+				dcb->dccpd_seq = dp->dccps_iss;
 			/* fall through */
 
 		case DCCP_PKT_SYNC:
@@ -84,8 +90,6 @@
 			break;
 		}
 
-		dcb->dccpd_seq = dp->dccps_gss;
-
 		if (dccp_insert_options(sk, skb)) {
 			kfree_skb(skb);
 			return -EPROTO;
@@ -103,7 +107,7 @@
 		/* XXX For now we're using only 48 bits sequence numbers */
 		dh->dccph_x	= 1;
 
-		dp->dccps_awh = dp->dccps_gss;
+		dccp_update_gss(sk, dcb->dccpd_seq);
 		dccp_hdr_set_seq(dh, dp->dccps_gss);
 		if (set_ack)
 			dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), ackno);
@@ -112,6 +116,11 @@
 		case DCCP_PKT_REQUEST:
 			dccp_hdr_request(skb)->dccph_req_service =
 							dp->dccps_service;
+			/*
+			 * Limit Ack window to ISS <= P.ackno <= GSS, so that
+			 * only Responses to Requests we sent are considered.
+			 */
+			dp->dccps_awl = dp->dccps_iss;
 			break;
 		case DCCP_PKT_RESET:
 			dccp_hdr_reset(skb)->dccph_reset_code =
@@ -284,14 +293,26 @@
 	}
 }
 
-int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
+/**
+ * dccp_retransmit_skb  -  Retransmit Request, Close, or CloseReq packets
+ * There are only four retransmittable packet types in DCCP:
+ * - Request  in client-REQUEST  state (sec. 8.1.1),
+ * - CloseReq in server-CLOSEREQ state (sec. 8.3),
+ * - Close    in   node-CLOSING  state (sec. 8.3),
+ * - Acks in client-PARTOPEN state (sec. 8.1.5, handled by dccp_delack_timer()).
+ * This function expects sk->sk_send_head to contain the original skb.
+ */
+int dccp_retransmit_skb(struct sock *sk)
 {
+	WARN_ON(sk->sk_send_head == NULL);
+
 	if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk) != 0)
 		return -EHOSTUNREACH; /* Routing failure or similar. */
 
-	return dccp_transmit_skb(sk, (skb_cloned(skb) ?
-				      pskb_copy(skb, GFP_ATOMIC):
-				      skb_clone(skb, GFP_ATOMIC)));
+	/* this count is used to distinguish original and retransmitted skb */
+	inet_csk(sk)->icsk_retransmits++;
+
+	return dccp_transmit_skb(sk, skb_clone(sk->sk_send_head, GFP_ATOMIC));
 }
 
 struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
@@ -437,19 +458,7 @@
 
 	dccp_sync_mss(sk, dst_mtu(dst));
 
-	/*
-	 * SWL and AWL are initially adjusted so that they are not less than
-	 * the initial Sequence Numbers received and sent, respectively:
-	 *	SWL := max(GSR + 1 - floor(W/4), ISR),
-	 *	AWL := max(GSS - W' + 1, ISS).
-	 * These adjustments MUST be applied only at the beginning of the
-	 * connection.
-	 */
-	dccp_update_gss(sk, dp->dccps_iss);
-	dccp_set_seqno(&dp->dccps_awl, max48(dp->dccps_awl, dp->dccps_iss));
-
-	/* S.GAR - greatest valid acknowledgement number received on a non-Sync;
-	 *         initialized to S.ISS (sec. 8.5)                            */
+	/* Initialise GAR as per 8.5; AWL/AWH are set in dccp_transmit_skb() */
 	dp->dccps_gar = dp->dccps_iss;
 
 	icsk->icsk_retransmits = 0;
diff --git a/net/dccp/timer.c b/net/dccp/timer.c
index 6a5b961..54b3c7e 100644
--- a/net/dccp/timer.c
+++ b/net/dccp/timer.c
@@ -99,21 +99,11 @@
 	}
 
 	/*
-	 * sk->sk_send_head has to have one skb with
-	 * DCCP_SKB_CB(skb)->dccpd_type set to one of the retransmittable DCCP
-	 * packet types. The only packets eligible for retransmission are:
-	 *	-- Requests in client-REQUEST  state (sec. 8.1.1)
-	 *	-- Acks     in client-PARTOPEN state (sec. 8.1.5)
-	 *	-- CloseReq in server-CLOSEREQ state (sec. 8.3)
-	 *	-- Close    in   node-CLOSING  state (sec. 8.3)                */
-	WARN_ON(sk->sk_send_head == NULL);
-
-	/*
 	 * More than than 4MSL (8 minutes) has passed, a RESET(aborted) was
 	 * sent, no need to retransmit, this sock is dead.
 	 */
 	if (dccp_write_timeout(sk))
-		goto out;
+		return;
 
 	/*
 	 * We want to know the number of packets retransmitted, not the
@@ -122,30 +112,28 @@
 	if (icsk->icsk_retransmits == 0)
 		DCCP_INC_STATS_BH(DCCP_MIB_TIMEOUTS);
 
-	if (dccp_retransmit_skb(sk, sk->sk_send_head) < 0) {
+	if (dccp_retransmit_skb(sk) != 0) {
 		/*
 		 * Retransmission failed because of local congestion,
 		 * do not backoff.
 		 */
-		if (icsk->icsk_retransmits == 0)
+		if (--icsk->icsk_retransmits == 0)
 			icsk->icsk_retransmits = 1;
 		inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
 					  min(icsk->icsk_rto,
 					      TCP_RESOURCE_PROBE_INTERVAL),
 					  DCCP_RTO_MAX);
-		goto out;
+		return;
 	}
 
 backoff:
 	icsk->icsk_backoff++;
-	icsk->icsk_retransmits++;
 
 	icsk->icsk_rto = min(icsk->icsk_rto << 1, DCCP_RTO_MAX);
 	inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto,
 				  DCCP_RTO_MAX);
 	if (icsk->icsk_retransmits > sysctl_dccp_retries1)
 		__sk_dst_reset(sk);
-out:;
 }
 
 static void dccp_write_timer(unsigned long data)
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index a42b64d..38ccb6d 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -104,9 +104,7 @@
 
 static int ipcomp4_init_state(struct xfrm_state *x)
 {
-	int err;
-	struct ipcomp_data *ipcd;
-	struct xfrm_algo_desc *calg_desc;
+	int err = -EINVAL;
 
 	x->props.header_len = 0;
 	switch (x->props.mode) {
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 0cfcea4..4545e43 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -134,9 +134,7 @@
 
 static int ipcomp6_init_state(struct xfrm_state *x)
 {
-	int err;
-	struct ipcomp_data *ipcd;
-	struct xfrm_algo_desc *calg_desc;
+	int err = -EINVAL;
 
 	x->props.header_len = 0;
 	switch (x->props.mode) {